Rearrange the file tree.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 2 Jun 2013 11:54:11 +0000 (12:54 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 22 Jun 2013 14:52:06 +0000 (15:52 +0100)
It's actually, like, a tree now.  Testing is a bit wobbly: you really do
have to make the library before the tests will build.  I don't like
this, but the pieces of the library are all rather intertwined.

One small piece of unintertwining: `strongprime.c' no longer includes
`rand.h', which detaches the mathematical code from the symmetric-crypto
build system disaster.

Test files have been moved into `t/' directories as is now established
practice.

Also take the opportunity to eradicate the CVS `$Id...$' droppings.

921 files changed:
.gitignore
.links
Makefile.am
arena.c [deleted file]
arena.h [deleted file]
base/Makefile.am [new file with mode: 0644]
base/arena.c [new file with mode: 0644]
base/arena.h [new file with mode: 0644]
base/ct.c [moved from ct.c with 100% similarity]
base/ct.h [moved from ct.h with 100% similarity]
base/keysz-conv.c [moved from keysz-conv.c with 100% similarity]
base/keysz.c [new file with mode: 0644]
base/keysz.h [moved from keysz.h with 100% similarity]
base/lmem.c [new file with mode: 0644]
base/lmem.h [new file with mode: 0644]
base/paranoia.h [new file with mode: 0644]
bbs-fetch.c [deleted file]
bbs-gen.c [deleted file]
bbs-jump.c [deleted file]
bbs-rand.c [deleted file]
bbs.h [deleted file]
bin-gentab.awk [deleted file]
bintab.h [deleted file]
bintab.in [deleted file]
bitops.h [deleted file]
bittest.c [deleted file]
blkc.h [deleted file]
blowfish-mktab.c [deleted file]
blowfish.c [deleted file]
blowfish.h [deleted file]
buf.c [deleted file]
buf.h [deleted file]
build-setup
calc/ec2.cal
calc/ecp.cal
calc/gfx-test.cal
calc/gfx.cal
cast-base.h [deleted file]
cast-s.c [deleted file]
cast-sk.c [deleted file]
cast-tab.h [deleted file]
cast128.c [deleted file]
cast128.h [deleted file]
cast256.c [deleted file]
cast256.h [deleted file]
catcrypt.c [deleted file]
catsign.c [deleted file]
cbc-def.h [deleted file]
cbc.h [deleted file]
cc-enc.c [deleted file]
cc-kem.c [deleted file]
cc-list.c [deleted file]
cc-sig.c [deleted file]
cc-subcmd.c [deleted file]
cc.h [deleted file]
cfb-def.h [deleted file]
cfb.h [deleted file]
configure.ac
cookie.c [deleted file]
counter-def.h [deleted file]
counter.h [deleted file]
crc32.c [deleted file]
crc32.h [deleted file]
daftstory.h [deleted file]
des-base.c [deleted file]
des-base.h [deleted file]
des-mktab.c [deleted file]
des.c [deleted file]
des.h [deleted file]
des3.c [deleted file]
des3.h [deleted file]
desx-tab.h [deleted file]
desx.c [deleted file]
desx.h [deleted file]
dh-check.c [deleted file]
dh-fetch.c [deleted file]
dh-gen.c [deleted file]
dh-kcdsa.c [deleted file]
dh-limlee.c [deleted file]
dh-param.c [deleted file]
dh.h [deleted file]
dsa-check.c [deleted file]
dsa-gen.c [deleted file]
dsa-sign.c [deleted file]
dsa-verify.c [deleted file]
dsa.h [deleted file]
dsarand.c [deleted file]
dsarand.h [deleted file]
dsig.c [deleted file]
ec-bin.c [deleted file]
ec-exp.c [deleted file]
ec-exp.h [deleted file]
ec-fetch.c [deleted file]
ec-gentab.awk [deleted file]
ec-guts.h [deleted file]
ec-info.c [deleted file]
ec-keys.h [deleted file]
ec-prime.c [deleted file]
ec-raw.c [deleted file]
ec-raw.h [deleted file]
ec-test.c [deleted file]
ec-test.h [deleted file]
ec.c [deleted file]
ec.h [deleted file]
ecb-def.h [deleted file]
ecb.h [deleted file]
ectab.h [deleted file]
ectab.in [deleted file]
exp.c [deleted file]
exp.h [deleted file]
f-binpoly.c [deleted file]
f-niceprime.c [deleted file]
f-prime.c [deleted file]
factorial.c [deleted file]
fibrand.c [deleted file]
fibrand.h [deleted file]
field-exp.c [deleted file]
field-exp.h [deleted file]
field-guts.h [deleted file]
field-parse.c [deleted file]
field.c [deleted file]
field.h [deleted file]
fipstest.c [deleted file]
fipstest.h [deleted file]
g-bin.c [deleted file]
g-ec.c [deleted file]
g-prime.c [deleted file]
gcipher.h [deleted file]
gdsa.c [deleted file]
gdsa.h [deleted file]
genlimits.c [deleted file]
genprimes.c [deleted file]
gf-arith.c [deleted file]
gf-exp.c [deleted file]
gf-exp.h [deleted file]
gf-gcd.c [deleted file]
gf.h [deleted file]
gfn.c [deleted file]
gfn.h [deleted file]
gfreduce-exp.h [deleted file]
gfreduce.c [deleted file]
gfreduce.h [deleted file]
gfshare-mktab.c [deleted file]
gfshare.c [deleted file]
gfshare.h [deleted file]
gfx-kmul.c [deleted file]
gfx-sqr-mktab.c [deleted file]
gfx-sqr.c [deleted file]
gfx.c [deleted file]
gfx.h [deleted file]
ghash-def.h [deleted file]
ghash.h [deleted file]
gkcdsa.c [deleted file]
gkcdsa.h [deleted file]
gmac.h [deleted file]
grand.c [deleted file]
grand.h [deleted file]
group-dstr.c [deleted file]
group-exp.c [deleted file]
group-exp.h [deleted file]
group-file.c [deleted file]
group-guts.h [deleted file]
group-parse.c [deleted file]
group-stdops.c [deleted file]
group-string.c [deleted file]
group-test.c [deleted file]
group.h [deleted file]
has160.c [deleted file]
has160.h [deleted file]
hash.h [deleted file]
hashsum.c [deleted file]
hmac-def.h [deleted file]
hmac.h [deleted file]
idea.c [deleted file]
idea.h [deleted file]
karatsuba.h [deleted file]
key-attr.c [deleted file]
key-binary.c [deleted file]
key-data.c [deleted file]
key-data.h [deleted file]
key-error.c [deleted file]
key-error.h [deleted file]
key-fetch.c [deleted file]
key-file.c [deleted file]
key-flags.c [deleted file]
key-io.c [deleted file]
key-misc.c [deleted file]
key-moan.c [deleted file]
key-pack.c [deleted file]
key-pass.c [deleted file]
key-text.c [deleted file]
key.h [deleted file]
key/Makefile.am [new file with mode: 0644]
key/key-attr.c [new file with mode: 0644]
key/key-binary.c [new file with mode: 0644]
key/key-data.c [new file with mode: 0644]
key/key-data.h [new file with mode: 0644]
key/key-error.c [new file with mode: 0644]
key/key-error.h [new file with mode: 0644]
key/key-fetch.c [new file with mode: 0644]
key/key-file.c [new file with mode: 0644]
key/key-flags.c [new file with mode: 0644]
key/key-io.c [new file with mode: 0644]
key/key-misc.c [new file with mode: 0644]
key/key-moan.c [new file with mode: 0644]
key/key-pack.c [new file with mode: 0644]
key/key-pass.c [new file with mode: 0644]
key/key-text.c [new file with mode: 0644]
key/key.h [new file with mode: 0644]
key/passphrase.c [new file with mode: 0644]
key/passphrase.h [new file with mode: 0644]
key/pixie-common.c [new file with mode: 0644]
key/pixie.h [new file with mode: 0644]
keycheck-mp.c [deleted file]
keycheck-report.c [deleted file]
keycheck.c [deleted file]
keycheck.h [deleted file]
keysz.c [deleted file]
keyutil.c [deleted file]
lcrand.c [deleted file]
lcrand.h [deleted file]
limlee.c [deleted file]
limlee.h [deleted file]
lmem.c [deleted file]
lmem.h [deleted file]
manual/catacomb.tex
mars-mktab.c [deleted file]
mars.c [deleted file]
mars.h [deleted file]
math/Makefile.am [new file with mode: 0644]
math/bin-gentab.awk [new file with mode: 0755]
math/bintab.h [new file with mode: 0644]
math/bintab.in [new file with mode: 0644]
math/bitops.h [new file with mode: 0644]
math/bittest.c [new file with mode: 0644]
math/buf.c [new file with mode: 0644]
math/buf.h [new file with mode: 0644]
math/ec-bin.c [new file with mode: 0644]
math/ec-exp.c [new file with mode: 0644]
math/ec-exp.h [new file with mode: 0644]
math/ec-fetch.c [new file with mode: 0644]
math/ec-gentab.awk [new file with mode: 0755]
math/ec-guts.h [new file with mode: 0644]
math/ec-info.c [new file with mode: 0644]
math/ec-keys.h [new file with mode: 0644]
math/ec-prime.c [new file with mode: 0644]
math/ec-raw.c [new file with mode: 0644]
math/ec-raw.h [new file with mode: 0644]
math/ec-test.c [new file with mode: 0644]
math/ec-test.h [new file with mode: 0644]
math/ec.c [new file with mode: 0644]
math/ec.h [new file with mode: 0644]
math/ectab.h [new file with mode: 0644]
math/ectab.in [new file with mode: 0644]
math/exp.c [new file with mode: 0644]
math/exp.h [new file with mode: 0644]
math/f-binpoly.c [new file with mode: 0644]
math/f-niceprime.c [new file with mode: 0644]
math/f-prime.c [new file with mode: 0644]
math/field-exp.c [new file with mode: 0644]
math/field-exp.h [new file with mode: 0644]
math/field-guts.h [new file with mode: 0644]
math/field-parse.c [new file with mode: 0644]
math/field.c [new file with mode: 0644]
math/field.h [new file with mode: 0644]
math/g-bin.c [new file with mode: 0644]
math/g-ec.c [new file with mode: 0644]
math/g-prime.c [new file with mode: 0644]
math/genlimits.c [new file with mode: 0644]
math/genprimes.c [new file with mode: 0644]
math/genwheel.c [moved from genwheel.c with 100% similarity]
math/gf-arith.c [new file with mode: 0644]
math/gf-exp.c [new file with mode: 0644]
math/gf-exp.h [new file with mode: 0644]
math/gf-gcd.c [new file with mode: 0644]
math/gf.h [new file with mode: 0644]
math/gfn.c [new file with mode: 0644]
math/gfn.h [new file with mode: 0644]
math/gfreduce-exp.h [new file with mode: 0644]
math/gfreduce.c [new file with mode: 0644]
math/gfreduce.h [new file with mode: 0644]
math/gfx-kmul.c [new file with mode: 0644]
math/gfx-sqr-mktab.c [new file with mode: 0644]
math/gfx-sqr.c [new file with mode: 0644]
math/gfx.c [new file with mode: 0644]
math/gfx.h [new file with mode: 0644]
math/group-dstr.c [new file with mode: 0644]
math/group-exp.c [new file with mode: 0644]
math/group-exp.h [new file with mode: 0644]
math/group-file.c [new file with mode: 0644]
math/group-guts.h [new file with mode: 0644]
math/group-parse.c [new file with mode: 0644]
math/group-stdops.c [new file with mode: 0644]
math/group-string.c [new file with mode: 0644]
math/group-test.c [new file with mode: 0644]
math/group.h [new file with mode: 0644]
math/karatsuba.h [new file with mode: 0644]
math/limlee.c [new file with mode: 0644]
math/limlee.h [new file with mode: 0644]
math/mp-arith.c [new file with mode: 0644]
math/mp-const.c [new file with mode: 0644]
math/mp-exp.c [new file with mode: 0644]
math/mp-exp.h [new file with mode: 0644]
math/mp-fibonacci.c [new file with mode: 0644]
math/mp-fibonacci.h [moved from mp-fibonacci.h with 100% similarity]
math/mp-gcd.c [new file with mode: 0644]
math/mp-io.c [new file with mode: 0644]
math/mp-jacobi.c [new file with mode: 0644]
math/mp-mem.c [new file with mode: 0644]
math/mp-misc.c [new file with mode: 0644]
math/mp-modexp.c [new file with mode: 0644]
math/mp-modsqrt.c [new file with mode: 0644]
math/mp-sqrt.c [new file with mode: 0644]
math/mp-test.c [new file with mode: 0644]
math/mp.h [new file with mode: 0644]
math/mparena.c [new file with mode: 0644]
math/mparena.h [new file with mode: 0644]
math/mpbarrett-exp.c [new file with mode: 0644]
math/mpbarrett-exp.h [new file with mode: 0644]
math/mpbarrett-mexp.c [new file with mode: 0644]
math/mpbarrett.c [new file with mode: 0644]
math/mpbarrett.h [new file with mode: 0644]
math/mpcrt.c [new file with mode: 0644]
math/mpcrt.h [new file with mode: 0644]
math/mpdump.c [new file with mode: 0644]
math/mpint.c [new file with mode: 0644]
math/mpint.h [new file with mode: 0644]
math/mpmont-exp.c [new file with mode: 0644]
math/mpmont-exp.h [new file with mode: 0644]
math/mpmont-mexp.c [new file with mode: 0644]
math/mpmont.c [new file with mode: 0644]
math/mpmont.h [new file with mode: 0644]
math/mpmul.c [new file with mode: 0644]
math/mpmul.h [new file with mode: 0644]
math/mprand.c [new file with mode: 0644]
math/mprand.h [new file with mode: 0644]
math/mpreduce-exp.h [new file with mode: 0644]
math/mpreduce.c [new file with mode: 0644]
math/mpreduce.h [new file with mode: 0644]
math/mpscan.c [new file with mode: 0644]
math/mpscan.h [new file with mode: 0644]
math/mptext-dstr.c [new file with mode: 0644]
math/mptext-file.c [new file with mode: 0644]
math/mptext-len.c [new file with mode: 0644]
math/mptext-string.c [new file with mode: 0644]
math/mptext.c [new file with mode: 0644]
math/mptext.h [new file with mode: 0644]
math/mptypes.c [new file with mode: 0644]
math/mpw.h [new file with mode: 0644]
math/mpx-kmul.c [new file with mode: 0644]
math/mpx-ksqr.c [new file with mode: 0644]
math/mpx.c [new file with mode: 0644]
math/mpx.h [new file with mode: 0644]
math/p-gentab.awk [new file with mode: 0755]
math/pfilt.c [new file with mode: 0644]
math/pfilt.h [new file with mode: 0644]
math/pgen-gcd.c [new file with mode: 0644]
math/pgen-simul.c [new file with mode: 0644]
math/pgen-stdev.c [new file with mode: 0644]
math/pgen.c [new file with mode: 0644]
math/pgen.h [new file with mode: 0644]
math/prim.c [new file with mode: 0644]
math/prim.h [new file with mode: 0644]
math/primeiter.c [new file with mode: 0644]
math/primeiter.h [moved from primeiter.h with 100% similarity]
math/ptab.h [new file with mode: 0644]
math/ptab.in [new file with mode: 0644]
math/qdparse.c [new file with mode: 0644]
math/qdparse.h [new file with mode: 0644]
math/rabin.c [new file with mode: 0644]
math/rabin.h [new file with mode: 0644]
math/rho.c [new file with mode: 0644]
math/rho.h [new file with mode: 0644]
math/strongprime.c [new file with mode: 0644]
math/strongprime.h [new file with mode: 0644]
math/t/ec [new file with mode: 0644]
math/t/gf [new file with mode: 0644]
math/t/gfn [new file with mode: 0644]
math/t/gfreduce [new file with mode: 0644]
math/t/gfx [new file with mode: 0644]
math/t/group [new file with mode: 0644]
math/t/mp [new file with mode: 0644]
math/t/mpbarrett [new file with mode: 0644]
math/t/mpcrt [new file with mode: 0644]
math/t/mpint [new file with mode: 0644]
math/t/mpmont [new file with mode: 0644]
math/t/mpreduce [new file with mode: 0644]
math/t/mptext [new file with mode: 0644]
math/t/mpx [new file with mode: 0644]
math/t/mpx-gen [new file with mode: 0755]
math/t/pgen [new file with mode: 0644]
maurer.c [deleted file]
maurer.h [deleted file]
md2-tab.h [deleted file]
md2.c [deleted file]
md2.h [deleted file]
md4.c [deleted file]
md4.h [deleted file]
md5.c [deleted file]
md5.h [deleted file]
mgf-def.h [deleted file]
mgf.h [deleted file]
misc/Makefile.am [new file with mode: 0644]
misc/gfshare-mktab.c [new file with mode: 0644]
misc/gfshare.c [new file with mode: 0644]
misc/gfshare.h [new file with mode: 0644]
misc/share.c [new file with mode: 0644]
misc/share.h [new file with mode: 0644]
mkpgroups [deleted file]
mkphrase.c [deleted file]
modes.am.in [deleted file]
mp-arith.c [deleted file]
mp-const.c [deleted file]
mp-exp.c [deleted file]
mp-exp.h [deleted file]
mp-fibonacci.c [deleted file]
mp-gcd.c [deleted file]
mp-io.c [deleted file]
mp-jacobi.c [deleted file]
mp-mem.c [deleted file]
mp-misc.c [deleted file]
mp-modexp.c [deleted file]
mp-modsqrt.c [deleted file]
mp-sqrt.c [deleted file]
mp-test.c [deleted file]
mp.h [deleted file]
mparena.c [deleted file]
mparena.h [deleted file]
mpbarrett-exp.c [deleted file]
mpbarrett-exp.h [deleted file]
mpbarrett-mexp.c [deleted file]
mpbarrett.c [deleted file]
mpbarrett.h [deleted file]
mpcrt.c [deleted file]
mpcrt.h [deleted file]
mpdump.c [deleted file]
mpint.c [deleted file]
mpint.h [deleted file]
mpmont-exp.c [deleted file]
mpmont-exp.h [deleted file]
mpmont-mexp.c [deleted file]
mpmont.c [deleted file]
mpmont.h [deleted file]
mpmul.c [deleted file]
mpmul.h [deleted file]
mprand.c [deleted file]
mprand.h [deleted file]
mpreduce-exp.h [deleted file]
mpreduce.c [deleted file]
mpreduce.h [deleted file]
mpscan.c [deleted file]
mpscan.h [deleted file]
mptext-dstr.c [deleted file]
mptext-file.c [deleted file]
mptext-len.c [deleted file]
mptext-string.c [deleted file]
mptext.c [deleted file]
mptext.h [deleted file]
mptypes.c [deleted file]
mpw.h [deleted file]
mpx-kmul.c [deleted file]
mpx-ksqr.c [deleted file]
mpx.c [deleted file]
mpx.h [deleted file]
noekeon.c [deleted file]
noekeon.h [deleted file]
noise.c [deleted file]
noise.h [deleted file]
oaep.c [deleted file]
ofb-def.h [deleted file]
ofb.h [deleted file]
p-gentab.awk [deleted file]
papers/rand.tex
paranoia.h [deleted file]
passphrase.c [deleted file]
passphrase.h [deleted file]
pcheck.pl [deleted file]
perftest.c [deleted file]
pfilt.c [deleted file]
pfilt.h [deleted file]
pgen-gcd.c [deleted file]
pgen-simul.c [deleted file]
pgen-stdev.c [deleted file]
pgen.c [deleted file]
pgen.h [deleted file]
pixie-common.c [deleted file]
pixie.c [deleted file]
pixie.h [deleted file]
pkcs1.c [deleted file]
prim.c [deleted file]
prim.h [deleted file]
primeiter.c [deleted file]
progs/Makefile.am [new file with mode: 0644]
progs/catcrypt.1 [moved from catcrypt.1 with 100% similarity]
progs/catcrypt.c [new file with mode: 0644]
progs/catsign.1 [moved from catsign.1 with 100% similarity]
progs/catsign.c [new file with mode: 0644]
progs/cc-enc.c [new file with mode: 0644]
progs/cc-hash.c [moved from cc-hash.c with 100% similarity]
progs/cc-kem.c [new file with mode: 0644]
progs/cc-list.c [new file with mode: 0644]
progs/cc-progress.c [moved from cc-progress.c with 100% similarity]
progs/cc-sig.c [new file with mode: 0644]
progs/cc-subcmd.c [new file with mode: 0644]
progs/cc.h [new file with mode: 0644]
progs/cookie.1 [moved from cookie.1 with 100% similarity]
progs/cookie.c [new file with mode: 0644]
progs/dsig.1 [moved from dsig.1 with 100% similarity]
progs/dsig.c [new file with mode: 0644]
progs/factorial.c [new file with mode: 0644]
progs/fibonacci.c [moved from fibonacci.c with 100% similarity]
progs/hashsum.1 [moved from hashsum.1 with 100% similarity]
progs/hashsum.c [new file with mode: 0644]
progs/key.1 [moved from key.1 with 100% similarity]
progs/key.c [new file with mode: 0644]
progs/keyring.5 [moved from keyring.5 with 100% similarity]
progs/mkphrase.1 [moved from mkphrase.1 with 100% similarity]
progs/mkphrase.c [new file with mode: 0644]
progs/perftest.c [new file with mode: 0644]
progs/pixie.1 [moved from pixie.1 with 100% similarity]
progs/pixie.c [new file with mode: 0644]
progs/rspit.c [new file with mode: 0644]
progs/xpixie [moved from xpixie with 100% similarity]
pss.c [deleted file]
ptab.h [deleted file]
ptab.in [deleted file]
pub/Makefile.am [new file with mode: 0644]
pub/bbs-fetch.c [new file with mode: 0644]
pub/bbs-gen.c [new file with mode: 0644]
pub/bbs-jump.c [new file with mode: 0644]
pub/bbs-rand.c [new file with mode: 0644]
pub/bbs.h [new file with mode: 0644]
pub/dh-check.c [new file with mode: 0644]
pub/dh-fetch.c [new file with mode: 0644]
pub/dh-gen.c [new file with mode: 0644]
pub/dh-kcdsa.c [new file with mode: 0644]
pub/dh-limlee.c [new file with mode: 0644]
pub/dh-param.c [new file with mode: 0644]
pub/dh.h [new file with mode: 0644]
pub/dsa-check.c [new file with mode: 0644]
pub/dsa-gen.c [new file with mode: 0644]
pub/dsa-misc.c [moved from dsa-misc.c with 100% similarity]
pub/dsa-sign.c [new file with mode: 0644]
pub/dsa-verify.c [new file with mode: 0644]
pub/dsa.h [new file with mode: 0644]
pub/gdsa.c [new file with mode: 0644]
pub/gdsa.h [new file with mode: 0644]
pub/gkcdsa.c [new file with mode: 0644]
pub/gkcdsa.h [new file with mode: 0644]
pub/keycheck-mp.c [new file with mode: 0644]
pub/keycheck-report.c [new file with mode: 0644]
pub/keycheck.c [new file with mode: 0644]
pub/keycheck.h [new file with mode: 0644]
pub/oaep.c [new file with mode: 0644]
pub/pkcs1.c [new file with mode: 0644]
pub/pss.c [new file with mode: 0644]
pub/rsa-fetch.c [new file with mode: 0644]
pub/rsa-gen.c [new file with mode: 0644]
pub/rsa-priv.c [new file with mode: 0644]
pub/rsa-pub.c [new file with mode: 0644]
pub/rsa-recover.c [new file with mode: 0644]
pub/rsa-test.c [new file with mode: 0644]
pub/rsa.h [new file with mode: 0644]
pub/t/bbs [new file with mode: 0644]
pub/t/dsa [new file with mode: 0644]
pub/t/gdsa [new file with mode: 0644]
pub/t/gkcdsa [new file with mode: 0644]
pub/t/rsa [new file with mode: 0644]
qdparse.c [deleted file]
qdparse.h [deleted file]
rabin.c [deleted file]
rabin.h [deleted file]
rand.c [deleted file]
rand.h [deleted file]
rand/Makefile.am [new file with mode: 0644]
rand/dsarand.c [new file with mode: 0644]
rand/dsarand.h [new file with mode: 0644]
rand/fibrand.c [new file with mode: 0644]
rand/fibrand.h [new file with mode: 0644]
rand/fipstest.c [new file with mode: 0644]
rand/fipstest.h [new file with mode: 0644]
rand/grand.c [new file with mode: 0644]
rand/grand.h [new file with mode: 0644]
rand/lcrand.c [new file with mode: 0644]
rand/lcrand.h [new file with mode: 0644]
rand/maurer.c [new file with mode: 0644]
rand/maurer.h [new file with mode: 0644]
rand/noise.c [new file with mode: 0644]
rand/noise.h [new file with mode: 0644]
rand/rand.c [new file with mode: 0644]
rand/rand.h [new file with mode: 0644]
rand/sslprf.c [new file with mode: 0644]
rand/sslprf.h [new file with mode: 0644]
rand/t/lcrand [new file with mode: 0644]
rand/t/sslprf [new file with mode: 0644]
rand/t/tlsprf [new file with mode: 0644]
rand/tlsprf.c [new file with mode: 0644]
rand/tlsprf.h [new file with mode: 0644]
rc2-tab.h [deleted file]
rc2.c [deleted file]
rc2.h [deleted file]
rc4.c [deleted file]
rc4.h [deleted file]
rc5.c [deleted file]
rc5.h [deleted file]
rho.c [deleted file]
rho.h [deleted file]
rijndael-base.c [deleted file]
rijndael-base.h [deleted file]
rijndael-mktab.c [deleted file]
rijndael.c [deleted file]
rijndael.h [deleted file]
rijndael192.c [deleted file]
rijndael192.h [deleted file]
rijndael256.c [deleted file]
rijndael256.h [deleted file]
rmd128.c [deleted file]
rmd128.h [deleted file]
rmd160.c [deleted file]
rmd160.h [deleted file]
rmd256.c [deleted file]
rmd256.h [deleted file]
rmd320.c [deleted file]
rmd320.h [deleted file]
rsa-fetch.c [deleted file]
rsa-gen.c [deleted file]
rsa-priv.c [deleted file]
rsa-pub.c [deleted file]
rsa-recover.c [deleted file]
rsa-test.c [deleted file]
rsa.h [deleted file]
rspit.c [deleted file]
safer-mktab.c [deleted file]
safer.c [deleted file]
safer.h [deleted file]
safersk.c [deleted file]
safersk.h [deleted file]
seal.c [deleted file]
seal.h [deleted file]
serpent-check.c [deleted file]
serpent-sbox.h [deleted file]
serpent.c [deleted file]
serpent.h [deleted file]
sha.c [deleted file]
sha.h [deleted file]
sha224.c [deleted file]
sha224.h [deleted file]
sha256.c [deleted file]
sha256.h [deleted file]
sha384.c [deleted file]
sha384.h [deleted file]
sha512.c [deleted file]
sha512.h [deleted file]
share.c [deleted file]
share.h [deleted file]
skipjack-tab.h [deleted file]
skipjack.c [deleted file]
skipjack.h [deleted file]
square-mktab.c [deleted file]
square.c [deleted file]
square.h [deleted file]
sslprf.c [deleted file]
sslprf.h [deleted file]
strongprime.c [deleted file]
strongprime.h [deleted file]
symm/Makefile.am [new file with mode: 0644]
symm/aes-trans [moved from tests/aes-trans with 100% similarity]
symm/blkc.h [new file with mode: 0644]
symm/blowfish-mktab.c [new file with mode: 0644]
symm/blowfish.c [new file with mode: 0644]
symm/blowfish.h [new file with mode: 0644]
symm/cast-base.h [new file with mode: 0644]
symm/cast-s.c [new file with mode: 0644]
symm/cast-sk.c [new file with mode: 0644]
symm/cast-tab.h [new file with mode: 0644]
symm/cast128.c [new file with mode: 0644]
symm/cast128.h [new file with mode: 0644]
symm/cast256.c [new file with mode: 0644]
symm/cast256.h [new file with mode: 0644]
symm/cbc-def.h [new file with mode: 0644]
symm/cbc.h [new file with mode: 0644]
symm/cfb-def.h [new file with mode: 0644]
symm/cfb.h [new file with mode: 0644]
symm/counter-def.h [new file with mode: 0644]
symm/counter.h [new file with mode: 0644]
symm/crc32.c [new file with mode: 0644]
symm/crc32.h [new file with mode: 0644]
symm/daftstory.h [new file with mode: 0644]
symm/des-base.c [new file with mode: 0644]
symm/des-base.h [new file with mode: 0644]
symm/des-mktab.c [new file with mode: 0644]
symm/des.c [new file with mode: 0644]
symm/des.h [new file with mode: 0644]
symm/des3.c [new file with mode: 0644]
symm/des3.h [new file with mode: 0644]
symm/desx-tab.h [new file with mode: 0644]
symm/desx.c [new file with mode: 0644]
symm/desx.h [new file with mode: 0644]
symm/ecb-def.h [new file with mode: 0644]
symm/ecb.h [new file with mode: 0644]
symm/gcipher.h [new file with mode: 0644]
symm/ghash-def.h [new file with mode: 0644]
symm/ghash.h [new file with mode: 0644]
symm/gmac.h [new file with mode: 0644]
symm/gthingtab.c.in [moved from gthingtab.c.in with 100% similarity]
symm/has160.c [new file with mode: 0644]
symm/has160.h [new file with mode: 0644]
symm/hash.h [new file with mode: 0644]
symm/hmac-def.h [new file with mode: 0644]
symm/hmac.h [new file with mode: 0644]
symm/idea.c [new file with mode: 0644]
symm/idea.h [new file with mode: 0644]
symm/mars-mktab.c [new file with mode: 0644]
symm/mars.c [new file with mode: 0644]
symm/mars.h [new file with mode: 0644]
symm/md2-tab.h [new file with mode: 0644]
symm/md2.c [new file with mode: 0644]
symm/md2.h [new file with mode: 0644]
symm/md4.c [new file with mode: 0644]
symm/md4.h [new file with mode: 0644]
symm/md5.c [new file with mode: 0644]
symm/md5.h [new file with mode: 0644]
symm/mgf-def.h [new file with mode: 0644]
symm/mgf.h [new file with mode: 0644]
symm/mode.c.in [moved from mode.c.in with 100% similarity]
symm/mode.h.in [moved from mode.h.in with 100% similarity]
symm/modes.am.in [new file with mode: 0644]
symm/multigen [moved from multigen with 100% similarity]
symm/noekeon.c [new file with mode: 0644]
symm/noekeon.h [new file with mode: 0644]
symm/ofb-def.h [new file with mode: 0644]
symm/ofb.h [new file with mode: 0644]
symm/rc2-tab.h [new file with mode: 0644]
symm/rc2.c [new file with mode: 0644]
symm/rc2.h [new file with mode: 0644]
symm/rc4.c [new file with mode: 0644]
symm/rc4.h [new file with mode: 0644]
symm/rc5.c [new file with mode: 0644]
symm/rc5.h [new file with mode: 0644]
symm/rijndael-base.c [new file with mode: 0644]
symm/rijndael-base.h [new file with mode: 0644]
symm/rijndael-mktab.c [new file with mode: 0644]
symm/rijndael.c [new file with mode: 0644]
symm/rijndael.h [new file with mode: 0644]
symm/rijndael192.c [new file with mode: 0644]
symm/rijndael192.h [new file with mode: 0644]
symm/rijndael256.c [new file with mode: 0644]
symm/rijndael256.h [new file with mode: 0644]
symm/rmd128.c [new file with mode: 0644]
symm/rmd128.h [new file with mode: 0644]
symm/rmd160.c [new file with mode: 0644]
symm/rmd160.h [new file with mode: 0644]
symm/rmd256.c [new file with mode: 0644]
symm/rmd256.h [new file with mode: 0644]
symm/rmd320.c [new file with mode: 0644]
symm/rmd320.h [new file with mode: 0644]
symm/safer-mktab.c [new file with mode: 0644]
symm/safer.c [new file with mode: 0644]
symm/safer.h [new file with mode: 0644]
symm/safersk.c [new file with mode: 0644]
symm/safersk.h [new file with mode: 0644]
symm/seal.c [new file with mode: 0644]
symm/seal.h [new file with mode: 0644]
symm/serpent-check.c [new file with mode: 0644]
symm/serpent-sbox.h [new file with mode: 0644]
symm/serpent.c [new file with mode: 0644]
symm/serpent.h [new file with mode: 0644]
symm/sha.c [new file with mode: 0644]
symm/sha.h [new file with mode: 0644]
symm/sha224.c [new file with mode: 0644]
symm/sha224.h [new file with mode: 0644]
symm/sha256.c [new file with mode: 0644]
symm/sha256.h [new file with mode: 0644]
symm/sha384.c [new file with mode: 0644]
symm/sha384.h [new file with mode: 0644]
symm/sha512.c [new file with mode: 0644]
symm/sha512.h [new file with mode: 0644]
symm/skipjack-tab.h [new file with mode: 0644]
symm/skipjack.c [new file with mode: 0644]
symm/skipjack.h [new file with mode: 0644]
symm/square-mktab.c [new file with mode: 0644]
symm/square.c [new file with mode: 0644]
symm/square.h [new file with mode: 0644]
symm/t/.gitignore [new file with mode: 0644]
symm/t/blowfish [new file with mode: 0644]
symm/t/cast128 [new file with mode: 0644]
symm/t/cast256.aes [moved from tests/cast256.aes with 100% similarity]
symm/t/des [new file with mode: 0644]
symm/t/des3 [new file with mode: 0644]
symm/t/desx [new file with mode: 0644]
symm/t/has160 [new file with mode: 0644]
symm/t/idea [new file with mode: 0644]
symm/t/mars.aes [moved from tests/mars.aes with 100% similarity]
symm/t/md2 [new file with mode: 0644]
symm/t/md4 [new file with mode: 0644]
symm/t/md5 [new file with mode: 0644]
symm/t/noekeon [new file with mode: 0644]
symm/t/rc2 [new file with mode: 0644]
symm/t/rc4 [new file with mode: 0644]
symm/t/rc5 [new file with mode: 0644]
symm/t/rijndael.aes [moved from tests/rijndael.aes with 100% similarity]
symm/t/rijndael192 [new file with mode: 0644]
symm/t/rijndael256 [new file with mode: 0644]
symm/t/rmd128 [new file with mode: 0644]
symm/t/rmd160 [new file with mode: 0644]
symm/t/rmd256 [new file with mode: 0644]
symm/t/rmd320 [new file with mode: 0644]
symm/t/safer [new file with mode: 0644]
symm/t/safersk [new file with mode: 0644]
symm/t/seal [new file with mode: 0644]
symm/t/serpent.aes [moved from tests/serpent.aes with 100% similarity]
symm/t/sha [new file with mode: 0644]
symm/t/sha224 [new file with mode: 0644]
symm/t/sha256 [new file with mode: 0644]
symm/t/sha384 [new file with mode: 0644]
symm/t/sha512 [new file with mode: 0644]
symm/t/skipjack [new file with mode: 0644]
symm/t/square [new file with mode: 0644]
symm/t/tea [new file with mode: 0644]
symm/t/tea-test.c [moved from tests/tea-test.c with 100% similarity]
symm/t/tiger [new file with mode: 0644]
symm/t/twofish.aes [moved from tests/twofish.aes with 100% similarity]
symm/t/whirlpool [new file with mode: 0644]
symm/t/whirlpool256 [new file with mode: 0644]
symm/t/xtea [new file with mode: 0644]
symm/t/xtea-test.c [moved from tests/xtea-test.c with 100% similarity]
symm/tea.c [new file with mode: 0644]
symm/tea.h [new file with mode: 0644]
symm/tiger-base.h [new file with mode: 0644]
symm/tiger-mktab.c [new file with mode: 0644]
symm/tiger.c [new file with mode: 0644]
symm/tiger.h [new file with mode: 0644]
symm/twofish-mktab.c [new file with mode: 0644]
symm/twofish.c [new file with mode: 0644]
symm/twofish.h [new file with mode: 0644]
symm/whirlpool-mktab.c [new file with mode: 0644]
symm/whirlpool.c [new file with mode: 0644]
symm/whirlpool.h [new file with mode: 0644]
symm/whirlpool256.c [new file with mode: 0644]
symm/whirlpool256.h [new file with mode: 0644]
symm/xtea.c [new file with mode: 0644]
symm/xtea.h [new file with mode: 0644]
tea.c [deleted file]
tea.h [deleted file]
tests/.gitignore [deleted file]
tests/bbs [deleted file]
tests/blowfish [deleted file]
tests/cast128 [deleted file]
tests/des [deleted file]
tests/des3 [deleted file]
tests/desx [deleted file]
tests/dsa [deleted file]
tests/ec [deleted file]
tests/gdsa [deleted file]
tests/gf [deleted file]
tests/gfn [deleted file]
tests/gfreduce [deleted file]
tests/gfx [deleted file]
tests/gkcdsa [deleted file]
tests/group [deleted file]
tests/has160 [deleted file]
tests/idea [deleted file]
tests/lcrand [deleted file]
tests/md2 [deleted file]
tests/md4 [deleted file]
tests/md5 [deleted file]
tests/mp [deleted file]
tests/mpbarrett [deleted file]
tests/mpcrt [deleted file]
tests/mpint [deleted file]
tests/mpmont [deleted file]
tests/mpreduce [deleted file]
tests/mptext [deleted file]
tests/mpx [deleted file]
tests/mpx-gen [deleted file]
tests/noekeon [deleted file]
tests/pgen [deleted file]
tests/rc2 [deleted file]
tests/rc4 [deleted file]
tests/rc5 [deleted file]
tests/rijndael192 [deleted file]
tests/rijndael256 [deleted file]
tests/rmd128 [deleted file]
tests/rmd160 [deleted file]
tests/rmd256 [deleted file]
tests/rmd320 [deleted file]
tests/rsa [deleted file]
tests/safer [deleted file]
tests/safersk [deleted file]
tests/seal [deleted file]
tests/sha [deleted file]
tests/sha224 [deleted file]
tests/sha256 [deleted file]
tests/sha384 [deleted file]
tests/sha512 [deleted file]
tests/skipjack [deleted file]
tests/square [deleted file]
tests/sslprf [deleted file]
tests/tea [deleted file]
tests/tiger [deleted file]
tests/tlsprf [deleted file]
tests/whirlpool [deleted file]
tests/whirlpool256 [deleted file]
tests/xtea [deleted file]
tiger-base.h [deleted file]
tiger-mktab.c [deleted file]
tiger.c [deleted file]
tiger.h [deleted file]
tlsprf.c [deleted file]
tlsprf.h [deleted file]
twofish-mktab.c [deleted file]
twofish.c [deleted file]
twofish.h [deleted file]
vars.am [new file with mode: 0644]
whirlpool-mktab.c [deleted file]
whirlpool.c [deleted file]
whirlpool.h [deleted file]
whirlpool256.c [deleted file]
whirlpool256.h [deleted file]
xtea.c [deleted file]
xtea.h [deleted file]

index 41bc25f..e849112 100644 (file)
@@ -1,17 +1,11 @@
-KEYRING
 Makefile.in
 aclocal.m4
 configure
 COPYING.LIB
 autom4te.cache
 config
-getdate.h
-getdate.y
-prof
-tinymp
-*.kr
-*.kr.old
-ylwrap
-modes.am
-auto-version
-confsubst
+progs/getdate.h
+progs/getdate.y
+symm/modes.am
+*.t
+*.to
diff --git a/.links b/.links
index 161dfb0..a6772a4 100644 (file)
--- a/.links
+++ b/.links
@@ -1,5 +1,5 @@
 COPYING.LIB
-getdate.y
-getdate.h
 config/auto-version
 config/confsubst
+progs/getdate.h
+progs/getdate.y
index 11251fa..4cacfbe 100644 (file)
 ### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 ### MA 02111-1307, USA.
 
-###--------------------------------------------------------------------------
-### Miscellaneous useful definitions.
-
-## Some convenient abbreviations for file suffixes.
-e                       = $(EXEEXT)
-o                       = $(OBJEXT)
-t                       = t$e
-
-## Installation directories.
-archincludedir          = $(pkglibdir)/include
-
-###--------------------------------------------------------------------------
-### Initial values of common variables.
+include $(top_srcdir)/vars.am
 
 SUBDIRS                         =
 
-EXTRA_DIST              =
-CLEANFILES              =
-DISTCLEANFILES          =
-MAINTAINERCLEANFILES    =
-SUFFIXES                =
-TESTS                   =
-BUILT_SOURCES           =
-
-bin_PROGRAMS            =
-noinst_PROGRAMS                 =
-lib_LTLIBRARIES                 =
-noinst_LTLIBRARIES      =
-pkginclude_HEADERS      =
-nodist_pkginclude_HEADERS =
-archinclude_HEADERS     =
-nodist_archinclude_HEADERS =
-dist_man_MANS           =
-
-###--------------------------------------------------------------------------
-### Standard configuration substitutions.
-
-## Substitute tags in files.
-confsubst = $(top_srcdir)/config/confsubst
-EXTRA_DIST             += config/confsubst
-
-SUBSTITUTIONS = \
-               prefix=$(prefix) exec_prefix=$(exec_prefix) \
-               libdir=$(libdir) includedir=$(includedir) \
-               PACKAGE=$(PACKAGE) VERSION=$(VERSION) \
-               CATACOMB_LIBS="$(CATACOMB_LIBS)"
-
-V_SUBST = $(V_SUBST_$(V))
-V_SUBST_ = $(V_SUBST_$(AM_DEFAULT_VERBOSITY))
-V_SUBST_0 = @echo "  SUBST  $@";
-SUBST = $(V_SUBST)$(confsubst)
-
 ###--------------------------------------------------------------------------
 ### The main library.
 
-lib_LTLIBRARIES                += libcatacomb.la
-libcatacomb_la_LIBADD   = $(CATACOMB_LIBS) $(mLib_LIBS)
+lib_LTLIBRARIES                 = libcatacomb.la
 libcatacomb_la_LDFLAGS  = -version-info $(LIBTOOL_VERSION_INFO)
+libcatacomb_la_LIBADD   = $(CATACOMB_LIBS) $(mLib_LIBS)
 libcatacomb_la_SOURCES  =
-nodist_libcatacomb_la_SOURCES =
-
-###--------------------------------------------------------------------------
-### Basic utilities.
-
-## The locked-memory arena.
-pkginclude_HEADERS     += arena.h
-libcatacomb_la_SOURCES += arena.c
-
-## Constant-type operations.
-pkginclude_HEADERS     += ct.h
-libcatacomb_la_SOURCES += ct.c
-
-## Acceptable key-size descriptions.
-pkginclude_HEADERS     += keysz.h
-libcatacomb_la_SOURCES += keysz.c keysz-conv.c
-
-## System-level memory locking.
-pkginclude_HEADERS     += lmem.h
-libcatacomb_la_SOURCES += lmem.c
-
-## Clearing secrets from memory.
-pkginclude_HEADERS     += paranoia.h
-
-###--------------------------------------------------------------------------
-### Main multiprecision integer library.
-
-## This library is unfortunately intertwined with some of the code generation
-## programs, so we must be rather careful.  The important bits of the maths
-## library needed by these programs is separated out into `libmpbase'.  There
-## is work going on to fix this unpleasant situation by generating the
-## relevant files from Python scripts rather than C programs, using
-## information gathered by `configure'.
-noinst_LTLIBRARIES     += libmpbase.la
-libcatacomb_la_LIBADD  += libmpbase.la
-libmpbase_la_LIBADD     = $(mLib_LIBS)
-libmpbase_la_SOURCES    =
-$(libmpbase_la_OBJECTS): mptypes.h
-
-## Additional buffer I/O functions for mathematical objects.
-pkginclude_HEADERS     += buf.h
-libcatacomb_la_SOURCES += buf.c
-
-## Infrastructure for fast exponentiation.
-pkginclude_HEADERS     += exp.h
-libcatacomb_la_SOURCES += exp.c
-
-## Main user-visible multiprecision arithmetic.
-pkginclude_HEADERS     += mp.h
-libmpbase_la_SOURCES   += mp-arith.c
-TESTS                  += mp-arith.$t
-libmpbase_la_SOURCES   += mp-const.c
-libcatacomb_la_SOURCES += mp-exp.c mp-exp.h
-libcatacomb_la_SOURCES += mp-gcd.c
-TESTS                  += mp-gcd.$t
-libmpbase_la_SOURCES   += mp-io.c
-libcatacomb_la_SOURCES += mp-jacobi.c
-TESTS                  += mp-jacobi.$t
-libmpbase_la_SOURCES   += mp-mem.c
-libmpbase_la_SOURCES   += mp-misc.c
-libcatacomb_la_SOURCES += mp-modexp.c
-TESTS                  += mp-modexp.$t
-libcatacomb_la_SOURCES += mp-modsqrt.c
-TESTS                  += mp-modsqrt.$t
-libcatacomb_la_SOURCES += mp-sqrt.c
-TESTS                  += mp-sqrt.$t
-libcatacomb_la_SOURCES += mp-test.c
-EXTRA_DIST             += tests/mp
-
-## Computing Fibonacci numbers.
-pkginclude_HEADERS     += mp-fibonacci.h
-libcatacomb_la_SOURCES += mp-fibonacci.c
-TESTS                  += mp-fibonacci.$t
-
-## Special memory allocation for multiprecision integers.
-pkginclude_HEADERS     += mparena.h
-libmpbase_la_SOURCES   += mparena.c
-
-## Barrett reduction, an efficient method for modular reduction.
-pkginclude_HEADERS     += mpbarrett.h
-libcatacomb_la_SOURCES += mpbarrett.c
-TESTS                  += mpbarrett.$t
-libcatacomb_la_SOURCES += mpbarrett-exp.c mpbarrett-mexp.c mpbarrett-exp.h
-TESTS                  += mpbarrett-exp.$t mpbarrett-mexp.$t
-EXTRA_DIST             += tests/mpbarrett
-
-## Solving congruences using the Chinese Remainder Theorem.
-pkginclude_HEADERS     += mpcrt.h
-libcatacomb_la_SOURCES += mpcrt.c
-TESTS                  += mpcrt.$t
-EXTRA_DIST             += tests/mpcrt
-
-## Conversions between machine-native and multiprecision integers.
-pkginclude_HEADERS     += mpint.h
-libcatacomb_la_SOURCES += mpint.c
-TESTS                  += mpint.$t
-EXTRA_DIST             += tests/mpint
-
-## Table of upper and lower limits of various types of machine integers, as
-## multiprecision integers.
-nodist_archinclude_HEADERS += mplimits.h
-nodist_libcatacomb_la_SOURCES += mplimits.c
-CLEANFILES             += mplimits.h mplimits.c
-noinst_PROGRAMS                += genlimits
-genlimits_LDADD                 = libmpbase.la
-mplimits.c: genlimits$e
-       $(AM_V_GEN)./genlimits c >mplimits.c.new && \
-               mv mplimits.c.new mplimits.c
-mplimits.h: genlimits$e
-       $(AM_V_GEN)./genlimits h >mplimits.h.new && \
-               mv mplimits.h.new mplimits.h
-$(genlimits_OBJECTS): mptypes.h
-mplimits.lo: mplimits.h
-
-## Montgomery reduction, a clever method for modular arithmetic.
-pkginclude_HEADERS     += mpmont.h
-libcatacomb_la_SOURCES += mpmont.c
-TESTS                  += mpmont.$t
-libcatacomb_la_SOURCES += mpmont-exp.c mpmont-mexp.c mpmont-exp.h
-TESTS                  += mpmont-exp.$t mpmont-mexp.$t
-EXTRA_DIST             += tests/mpmont
-
-## Efficient multiplication of many small numbers.
-pkginclude_HEADERS     += mpmul.h
-libcatacomb_la_SOURCES += mpmul.c
-TESTS                  += mpmul.$t
-
-## Generating random numbers.
-pkginclude_HEADERS     += mprand.h
-libcatacomb_la_SOURCES += mprand.c
-
-## Efficient reduction modulo numbers with conveninent binary
-## representations.
-pkginclude_HEADERS     += mpreduce.h
-libcatacomb_la_SOURCES += mpreduce.c mpreduce-exp.h
-TESTS                  += mpreduce.$t
-EXTRA_DIST             += tests/mpreduce
-
-## Iteratiion over the bianry representation of multiprecision integers.
-pkginclude_HEADERS     += mpscan.h
-libmpbase_la_SOURCES   += mpscan.c
-
-## Conversion between multiprecision integers and their textual
-## representations.
-pkginclude_HEADERS     += mptext.h
-libmpbase_la_SOURCES   += mptext.c
-TESTS                  += mptext.$t
-libcatacomb_la_SOURCES += mptext-dstr.c
-libcatacomb_la_SOURCES += mptext-file.c
-libcatacomb_la_SOURCES += mptext-len.c
-libmpbase_la_SOURCES   += mptext-string.c
-EXTRA_DIST             += tests/mptext
-
-## Basic types used in the representation of multiprecision integers.
-nodist_archinclude_HEADERS += mptypes.h
-BUILT_SOURCES          += mptypes.h
-CLEANFILES             += mptypes.h
-noinst_PROGRAMS                += mptypes
-mptypes.h: mptypes$e
-       $(AM_V_GEN)./mptypes >mptypes.h.new && mv mptypes.h.new mptypes.h
-
-## Low-level multiprecision arithmetic.
-pkginclude_HEADERS     += mpx.h bitops.h mpw.h
-libmpbase_la_SOURCES   += mpx.c
-TESTS                  += mpx.$t
-libmpbase_la_SOURCES   += karatsuba.h mpx-kmul.c mpx-ksqr.c
-TESTS                  += mpx-kmul.$t mpx-ksqr.$t
-noinst_PROGRAMS                += bittest
-TESTS                  += bittest
-EXTRA_DIST             += tests/mpx
-
-## A quick-and-dirty parser, used for parsing descriptions of groups, fields,
-## etc.
-pkginclude_HEADERS     += rho.h
-libcatacomb_la_SOURCES += rho.c
-TESTS                  += rho.$t
-
-## Pollard's `rho' algorithm for determining discrete logarithms.
-pkginclude_HEADERS     += qdparse.h
-libcatacomb_la_SOURCES += qdparse.c
-
-###--------------------------------------------------------------------------
-### Prime number checking, searching, and related jobs.
-
-## Generating Lim--Lee groups, i.e., unit groups of finite fields without
-## small subgroups (except for the obvious ones).
-pkginclude_HEADERS     += limlee.h
-libcatacomb_la_SOURCES += limlee.c
-
-## A table of small prime numbers.
-nodist_pkginclude_HEADERS += primetab.h
-nodist_libcatacomb_la_SOURCES += primetab.c
-CLEANFILES             += primetab.h primetab.c
-BUILT_SOURCES          += primetab.h primetab.c
-noinst_PROGRAMS                += genprimes
-genprimes_LDADD                 = $(mLib_LIBS)
-primetab.h: primetab.c
-primetab.c: genprimes$e
-       $(AM_V_GEN)./genprimes -hprimetab.h -cprimetab.c \
-               -sCATACOMB_PRIMETAB_H \
-               -n256 -t"unsigned short" -iprimetab
-
-## Filtering candidate prime numbers by checking for small factors
-## efficiently.
-pkginclude_HEADERS     += pfilt.h
-libcatacomb_la_SOURCES += pfilt.c
-
-## Generating prime numbers (and other kinds of numbers which need searching
-## for).
-pkginclude_HEADERS     += pgen.h
-libcatacomb_la_SOURCES += pgen.c
-libcatacomb_la_SOURCES += pgen-gcd.c
-libcatacomb_la_SOURCES += pgen-simul.c
-libcatacomb_la_SOURCES += pgen-stdev.c
-TESTS                  += pgen.$t
-EXTRA_DIST             += tests/pgen
-
-## Finding primitive elements in finite fields.
-pkginclude_HEADERS     += prim.h
-libcatacomb_la_SOURCES += prim.c
-
-## Iterating over all prime numbers from a given starting point.
-pkginclude_HEADERS     += primeiter.h
-libcatacomb_la_SOURCES += primeiter.c
-TESTS                  += primeiter.$t
-primeiter.lo: wheel.h
-
-## The Miller--Rabin primality test.
-pkginclude_HEADERS     += rabin.h
-libcatacomb_la_SOURCES += rabin.c
-
-## Finding `strong' primes, using Gordon's algorithm.  Once upon a time,
-## products of these kinds of numbers were harder to factor.
-pkginclude_HEADERS     += strongprime.h
-libcatacomb_la_SOURCES += strongprime.c
-
-## A `wheel', used by the prime iteration machinery.
-nodist_pkginclude_HEADERS += wheel.h
-nodist_libcatacomb_la_SOURCES += wheel.c
-CLEANFILES             += wheel.h wheel.c
-noinst_PROGRAMS                += genwheel
-genwheel_LDADD          = $(mLib_LIBS)
-wheel.h: wheel.c
-wheel.c: genwheel$e
-       $(AM_V_GEN)./genwheel -hwheel.h -cwheel.c \
-               -sCATACOMB_WHEEL_H \
-               -n5 -t"unsigned char" -iwheel
-
-###--------------------------------------------------------------------------
-### Binary polynomial arithmetic.
-
-## User-visible binary polynomial arithmetic.
-pkginclude_HEADERS     += gf.h
-libcatacomb_la_SOURCES += gf-arith.c
-TESTS                  += gf-arith.$t
-libcatacomb_la_SOURCES += gf-exp.c gf-exp.h
-libcatacomb_la_SOURCES += gf-gcd.c
-TESTS                  += gf-gcd.$t
-EXTRA_DIST             += tests/gf
-
-## Low-level binary polynomial arithmetic.
-pkginclude_HEADERS     += gfx.h
-libcatacomb_la_SOURCES += gfx.c
-TESTS                  += gfx.$t
-libcatacomb_la_SOURCES += gfx-kmul.c
-TESTS                  += gfx-kmul.$t
-libcatacomb_la_SOURCES += gfx-sqr.c
-gfx-sqr.lo: gfx-sqr-tab.h
-TESTS                  += gfx-sqr.$t
-CLEANFILES             += gfx-sqr-tab.h
-noinst_PROGRAMS                += gfx-sqr-mktab
-gfx-sqr-tab.h: gfx-sqr-mktab$e
-       $(AM_V_GEN)./gfx-sqr-mktab >gfx-sqr-tab.h.in && \
-               mv gfx-sqr-tab.h.in gfx-sqr-tab.h
-EXTRA_DIST             += tests/gfx
-
-## Conversions between normal and polynomial basis representations for binary
-## fields.
-pkginclude_HEADERS     += gfn.h
-libcatacomb_la_SOURCES += gfn.c
-TESTS                  += gfn.$t
-EXTRA_DIST             += tests/gfn
-
-## Efficient reduction modulo sparse polynomials.
-pkginclude_HEADERS     += gfreduce.h
-libcatacomb_la_SOURCES += gfreduce.c gfreduce-exp.h
-TESTS                  += gfreduce.$t
-EXTRA_DIST             += tests/gfreduce
-
-###--------------------------------------------------------------------------
-### Abstractions for various kinds of algebraic objects.
-
-## Abstract cyclic groups.
-pkginclude_HEADERS     += group.h group-guts.h
-libcatacomb_la_SOURCES += group-dstr.c
-libcatacomb_la_SOURCES += group-exp.c group-exp.h
-libcatacomb_la_SOURCES += group-file.c
-libcatacomb_la_SOURCES += group-parse.c
-libcatacomb_la_SOURCES += group-stdops.c
-libcatacomb_la_SOURCES += group-string.c
-libcatacomb_la_SOURCES += g-bin.c
-libcatacomb_la_SOURCES += g-prime.c
-libcatacomb_la_SOURCES += g-ec.c
-EXTRA_DIST             += group-test.c
-TESTS                  += group-test.$t
-EXTRA_DIST             += tests/group
-
-## Abstract finite fields.
-pkginclude_HEADERS     += field.h field-guts.h
-libcatacomb_la_SOURCES += field.c
-libcatacomb_la_SOURCES += field-exp.c field-exp.h
-libcatacomb_la_SOURCES += field-parse.c
-libcatacomb_la_SOURCES += f-binpoly.c
-libcatacomb_la_SOURCES += f-niceprime.c
-libcatacomb_la_SOURCES += f-prime.c
-
-## Table of built-in binary fields.
-pkginclude_HEADERS     += bintab.h
-libcatacomb_la_SOURCES += bintab.c
-CLEANFILES             += bintab.c
-EXTRA_DIST             += bintab.in bin-gentab.awk
-bintab.c: bintab.in bin-gentab.awk mpdump$e
-       $(AM_V_GEN)awk -f $(srcdir)/bin-gentab.awk \
-               <$(srcdir)/bintab.in >bintab.c.new && \
-       mv bintab.c.new bintab.c
-
-## Table of built-in prime fields.
-pkginclude_HEADERS     += ptab.h
-libcatacomb_la_SOURCES += ptab.c
-CLEANFILES             += ptab.c
-EXTRA_DIST             += ptab.in p-gentab.awk
-ptab.c: ptab.in p-gentab.awk mpdump$e
-       $(AM_V_GEN)awk -f $(srcdir)/p-gentab.awk \
-               <$(srcdir)/ptab.in >ptab.c.new && \
-       mv ptab.c.new ptab.c
-
-## A utility for building multiprecision integer constants.
-noinst_PROGRAMS                += mpdump
-mpdump_LDADD            = libmpbase.la
-$(mpdump_OBJECTS): mptypes.h
-
-###--------------------------------------------------------------------------
-### Elliptic curve arithmetic.
-
-## Basic elliptic curve arithmetic.
-pkginclude_HEADERS     += ec.h ec-guts.h
-libcatacomb_la_SOURCES += ec.c
-libcatacomb_la_SOURCES += ec-exp.c ec-exp.h
-libcatacomb_la_SOURCES += ec-info.c
-TESTS                  += ec-info.$t
-libcatacomb_la_SOURCES += ec-bin.c
-TESTS                  += ec-bin.$t
-libcatacomb_la_SOURCES += ec-prime.c
-TESTS                  += ec-prime.$t
-EXTRA_DIST             += tests/ec
-
-## The standard `raw' encoding (`EC2OSP') of elliptic curve points.
-pkginclude_HEADERS     += ec-raw.h
-libcatacomb_la_SOURCES += ec-raw.c
-
-## Test infrastructure for elliptic curves.
-pkginclude_HEADERS     += ec-test.h
-libcatacomb_la_SOURCES += ec-test.c
-TESTS                  += ec-test.$t
-
-## A table of built-in elliptic curves.
-pkginclude_HEADERS     += ectab.h
-libcatacomb_la_SOURCES += ectab.c
-CLEANFILES             += ectab.c
-EXTRA_DIST             += ectab.in ec-gentab.awk
-ectab.c: ectab.in ec-gentab.awk mpdump$e
-       $(AM_V_GEN)awk -f $(srcdir)/ec-gentab.awk \
-               <$(srcdir)/ectab.in >ectab.c.new && \
-       mv ectab.c.new ectab.c
-
-###--------------------------------------------------------------------------
-### Autogenerated lists.
-
-## Fancy template substitutions.
-multigen                = python $(srcdir)/multigen
-EXTRA_DIST             += multigen
-
-## The heart of this is an enormous cross-product of crypto primitives and
-## the corresponding modes of operation.  Rather than write it out longhand,
-## we generate it using `multigen'.  Unfortunately, this needs to be done
-## at the Automake level, which causes some interesting bootstrapping
-## problems.
-include modes.am
-
-EXTRA_DIST             += modes.am.in modes.am
-MAINTAINERCLEANFILES   += $(srcdir)/modes.am
-
-## Generate the lists.
-$(srcdir)/modes.am: modes.am.in
-       $(AM_V_GEN)$(multigen) -g $(srcdir)/modes.am.in $(srcdir)/modes.am \
-               blkc="$(BLKCS)" \
-                       blkcmode="$(BLKCMODES)" \
-                       blkcciphermode="$(BLKCCIPHERMODES)" \
-               hash="$(HASHES)" \
-                       hashmode="$(HASHMODES)" \
-                       hashciphermode="$(HASHCIPHERMODES)" \
-                       hashmacmode="$(HASHMACMODES)"
-
-## Initialize lists of known classes.
-ALL_CIPHERS             = $(CIPHER_MODES)
-ALL_HASHES              = $(HASHES)
-ALL_MACS                = $(MAC_MODES)
-
-###--------------------------------------------------------------------------
-### Block ciphers.
-
-BLKCS                   =
-BLKCMODES               =
-
-BLKCCIPHERMODES                 =
-BLKCMODES              += $(BLKCCIPHERMODES)
-
-## A tool for translating the AES-contest test vectors into a form our test
-## rigs understand.
-EXTRA_DIST             += tests/aes-trans
-
-## Block cipher utility macros, mainly used in mode implementations.
-pkginclude_HEADERS     += blkc.h
-
-## Source code and headers for the block ciphers.
-libcatacomb_la_SOURCES += $(BLKC_C)
-pkginclude_HEADERS     += $(BLKC_H)
-
-## Schneier's `Blowfish' block cipher.
-BLKCS                  += blowfish
-blowfish.lo: blowfish-tab.h
-CLEANFILES             += blowfish-tab.h
-noinst_PROGRAMS                += blowfish-mktab
-blowfish_mktab_CPPFLAGS         = $(AM_CPPFLAGS) -DQUIET
-blowfish-tab.h: blowfish-mktab$e
-       $(AM_V_GEN)./blowfish-mktab >blowfish-tab.h.new && \
-               mv blowfish-tab.h.new blowfish-tab.h
-
-## Adams and Tavares' `CAST' block ciphers.
-BLKCS                  += cast128 cast256
-libcatacomb_la_SOURCES += cast-s.c cast-sk.c cast-base.h cast-tab.h
-cast256.$t: tests/cast256
-EXTRA_DIST             += tests/cast256.aes
-MAINTAINERCLEANFILES   += $(srcdir)/tests/cast256
-tests/cast256: tests/cast256.aes
-       $(AM_V_GEN)$(srcdir)/tests/aes-trans CAST256 \
-               <$(srcdir)/tests/cast256.aes \
-               >$(srcdir)/tests/cast256.new && \
-       mv $(srcdir)/tests/cast256.new $(srcdir)/tests/cast256
-
-## IBM's `DES' block cipher, by Feistel, Coppersmith, and others.
-BLKCS                  += des des3
-libcatacomb_la_SOURCES += des-base.h des-base.c desx-tab.h
-des-base.lo: des-tab.h
-CLEANFILES             += des-tab.h
-noinst_PROGRAMS                += des-mktab
-des-tab.h: des-mktab$e
-       $(AM_V_GEN)./des-mktab >des-tab.h.new && \
-               mv des-tab.h.new des-tab.h
-
-## Rivest's `DESX' variant, with pre- and post-whitening.
-BLKCS                  += desx
-libcatacomb_la_SOURCES += desx-tab.h
-
-## Lai and Massey's IDEA.
-BLKCS                  += idea
-
-## IBM's `MARS' block cipher.
-BLKCS                  += mars
-mars.lo: mars-tab.h
-CLEANFILES             += mars-tab.h
-noinst_PROGRAMS                += mars-mktab
-mars-tab.h: mars-mktab$e
-       $(AM_V_GEN)./mars-mktab >mars-tab.h.new && \
-               mv mars-tab.h.new mars-tab.h
-mars.$t: tests/mars
-EXTRA_DIST             += tests/mars.aes
-MAINTAINERCLEANFILES   += $(srcdir)/tests/mars
-tests/mars: tests/mars.aes
-       $(AM_V_GEN)$(srcdir)/tests/aes-trans Mars \
-               <$(srcdir)/tests/mars.aes \
-               >$(srcdir)/tests/mars.new && \
-       mv $(srcdir)/tests/mars.new $(srcdir)/tests/mars
 
-## Daemen, Peeters, Van Assche and Rijmen's `Noekeon'.
-BLKCS                  += noekeon
+## Basic utilities.
+SUBDIRS                        += base
+libcatacomb_la_LIBADD  += base/libbase.la
 
-## Rivest's `RC2' block cipher.
-BLKCS                  += rc2
-libcatacomb_la_SOURCES += rc2-tab.h
+## Mathematical infrastructure.
+SUBDIRS                        += math
+libcatacomb_la_LIBADD  += math/libmath.la
 
-## Rivest's `RC5'.
-BLKCS                  += rc5
+## Symmetric cryptography.
+SUBDIRS                        += symm
+libcatacomb_la_LIBADD  += symm/libsymm.la
 
-## Daemen and Rijmen's `Rijndael' block cipher, selected as AES.
-BLKCS                  += rijndael rijndael192 rijndael256
-libcatacomb_la_SOURCES += rijndael-base.h rijndael-base.c
-rijndael-base.lo: rijndael-tab.h
-CLEANFILES             += rijndael-tab.h
-noinst_PROGRAMS                += rijndael-mktab
-rijndael-tab.h: rijndael-mktab$e
-       $(AM_V_GEN)./rijndael-mktab >rijndael-tab.h.new && \
-               mv rijndael-tab.h.new rijndael-tab.h
-rijndael.$t: tests/rijndael
-EXTRA_DIST             += tests/rijndael.aes
-MAINTAINERCLEANFILES   += $(srcdir)/tests/rijndael
-tests/rijndael: tests/rijndael.aes
-       $(AM_V_GEN)$(srcdir)/tests/aes-trans Rijndael \
-               <$(srcdir)/tests/rijndael.aes \
-               >$(srcdir)/tests/rijndael.new && \
-       mv $(srcdir)/tests/rijndael.new $(srcdir)/tests/rijndael
+## Key management.
+SUBDIRS                        += key
+libcatacomb_la_LIBADD  += key/libkey.la
 
-## Massey's `SAFER' block ciphers.
-BLKCS                  += safer safersk
-safer.lo: safer-tab.h
-CLEANFILES             += safer-tab.h
-noinst_PROGRAMS                += safer-mktab
-safer-tab.h: safer-mktab$e
-       $(AM_V_GEN)./safer-mktab >safer-tab.h.new && \
-               mv safer-tab.h.new safer-tab.h
+## Miscellaneous cryptography.
+SUBDIRS                        += misc
+libcatacomb_la_LIBADD  += misc/libmisc.la
 
-## Anderson, Biham and Knudsen's `Serpent' block cipher.
-BLKCS                  += serpent
-libcatacomb_la_SOURCES += serpent-sbox.h
-noinst_PROGRAMS                += serpent-check
-TESTS                  += serpent-check
-serpent.$t: tests/serpent
-EXTRA_DIST             += tests/serpent.aes
-MAINTAINERCLEANFILES   += $(srcdir)/tests/serpent
-tests/serpent: tests/serpent.aes
-       $(AM_V_GEN)$(srcdir)/tests/aes-trans Serpent -v rev=1 \
-               <$(srcdir)/tests/serpent.aes \
-               >$(srcdir)/tests/serpent.new && \
-       mv $(srcdir)/tests/serpent.new $(srcdir)/tests/serpent
+## Public-key cryptography.
+SUBDIRS                        += pub
+libcatacomb_la_LIBADD  += pub/libpub.la
 
-## The National Security Agency's `Skipjack' block cipher.  You don't want to
-## use this.
-BLKCS                  += skipjack
-libcatacomb_la_SOURCES += skipjack-tab.h
+## Random number generators and related functionality.
+SUBDIRS                        += rand
+libcatacomb_la_LIBADD  += rand/librand.la
 
-## Daemen and Rijmen's `Square' block cipher.
-BLKCS                  += square
-square.lo: square-tab.h
-CLEANFILES             += square-tab.h
-noinst_PROGRAMS                += square-mktab
-square-tab.h: square-mktab$e
-       $(AM_V_GEN)./square-mktab >square-tab.h.new && \
-               mv square-tab.h.new square-tab.h
-
-## Wheeler and Needham's `TEA' and `XTEA' block ciphers.
-BLKCS                  += tea xtea
-
-## Schneier, Kelsey, Whiting, Wagner, Hall and Ferguson's `Twofish' block
-## cipher.
-BLKCS                  += twofish
-twofish.lo: twofish-tab.h
-CLEANFILES             += twofish-tab.h
-noinst_PROGRAMS                += twofish-mktab
-twofish-tab.h: twofish-mktab$e
-       $(AM_V_GEN)./twofish-mktab >twofish-tab.h.new && \
-               mv twofish-tab.h.new twofish-tab.h
-twofish.$t: tests/twofish
-EXTRA_DIST             += tests/twofish.aes
-MAINTAINERCLEANFILES   += $(srcdir)/tests/twofish
-tests/twofish: tests/twofish.aes
-       $(AM_V_GEN)$(srcdir)/tests/aes-trans Twofish \
-               <$(srcdir)/tests/twofish.aes \
-               >$(srcdir)/tests/twofish.new && \
-       mv $(srcdir)/tests/twofish.new $(srcdir)/tests/twofish
-
-## The old NIST modes for DES.
-BLKCCIPHERMODES                += cbc cfb ecb ofb
-
-## Counter mode.
-BLKCCIPHERMODES                += counter
-
-###--------------------------------------------------------------------------
-### Hash functions.
-
-HASHES                  =
-HASHMODES               =
-
-HASHCIPHERMODES                 =
-HASHMODES              += $(HASHCIPHERMODES)
-
-HASHMACMODES            =
-HASHMODES              += $(HASHMACMODES)
-
-## Common definitions for hash functions.
-pkginclude_HEADERS     += hash.h
-
-## Source code and headers for the hash functions.
-libcatacomb_la_SOURCES += $(HASH_C)
-pkginclude_HEADERS     += $(HASH_H)
-
-## Lim and KISA's `HAS-160', recommended for use with KCDSA.
-HASHES                 += has160
-
-## Rivest's `MD' series of hash functions
-HASHES                 += md2 md4 md5
-libcatacomb_la_SOURCES += md2-tab.h
-
-## Dobbertin, Bosselaers and Preneel's `RIPEMD' suite.
-HASHES                 += rmd128 rmd160 rmd256 rmd320
-
-## The National Security Agency's `SHA-1' hash function.
-HASHES                 += sha
-
-## The National Security Agency's `SHA-2' suite.
-HASHES                 += sha224 sha256
-HASHES                 += sha384 sha512
-
-## Anderson and Biham's `Tiger' hash function.
-HASHES                 += tiger
-libcatacomb_la_SOURCES += tiger-base.h
-tiger.lo: tiger-tab.h
-CLEANFILES             += tiger-tab.h
-noinst_PROGRAMS                += tiger-mktab
-tiger-tab.h: tiger-mktab$e
-       $(AM_V_GEN)./tiger-mktab >tiger-tab.h.new && \
-               mv tiger-tab.h.new tiger-tab.h
-
-## Barreto and Rijmen's `Whirlpool' hash function.
-HASHES                 += whirlpool whirlpool256
-whirlpool.lo: whirlpool-tab.h
-CLEANFILES             += whirlpool-tab.h
-noinst_PROGRAMS                += whirlpool-mktab
-whirlpool-tab.h: whirlpool-mktab$e
-       $(AM_V_GEN)./whirlpool-mktab >whirlpool-tab.h.new && \
-               mv whirlpool-tab.h.new whirlpool-tab.h
-
-## Bellare, Canetti and Krawczyk's `HMAC' mode for message authentication.
-HASHMACMODES           += hmac
-
-## MGF1, used in OAEP and PSS.
-HASHCIPHERMODES                += mgf
-
-###--------------------------------------------------------------------------
-### Other symmetric primitives.
-
-## The CRC32 algorithm, which is useful, but has no worthwhile security.
-pkginclude_HEADERS     += crc32.h
-libcatacomb_la_SOURCES += crc32.c
-ALL_HASHES             += crc32=gcrc32
-
-## Rivest's `RC4' stream cipher.
-pkginclude_HEADERS     += rc4.h
-libcatacomb_la_SOURCES += rc4.c
-TESTS                  += rc4.$t
-EXTRA_DIST             += tests/rc4
-ALL_CIPHERS            += rc4
-
-## Coppersmith and Rogaway's `SEAL' pseudorandom function.
-pkginclude_HEADERS     += seal.h
-libcatacomb_la_SOURCES += seal.c
-TESTS                  += seal.$t
-EXTRA_DIST             += tests/seal
-ALL_CIPHERS            += seal
-###--------------------------------------------------------------------------
-### Autogenerated mode implementations.
-
-## The master stamp file, indicating that we generated all of the sources.
-CLEANFILES             += modes-gen-stamp
-EXTRA_DIST             += mode.h.in mode.c.in
-modes-gen-stamp:
-       $(AM_V_at)touch modes-gen-stamp
-       $(AM_V_GEN)$(multigen) -g $(srcdir)/mode.c.in \
-               @base-@mode.c \
-               base="$(BLKCS)" mode="$(BLKCMODES)"
-       $(AM_V_at)$(multigen) -g $(srcdir)/mode.c.in \
-               @base-@mode.c \
-               base="$(HASHES)" mode="$(HASHMODES)"
-       $(AM_V_at)$(multigen) -g $(srcdir)/mode.h.in \
-               @base-@mode.h \
-               base="$(BLKCS)" mode="$(BLKCMODES)"
-       $(AM_V_at)$(multigen) -g $(srcdir)/mode.h.in \
-               @base-@mode.h \
-               base="$(HASHES)" mode="$(HASHMODES)"
-       $(AM_V_at)touch modes-gen-stamp
-
-## The individual mode interfaces and implementations.
-pkginclude_HEADERS     += $(MODE_H)
-
-## Generated implementations.
-BUILT_SOURCES          += $(GENMODES_C)
-CLEANFILES             += $(GENMODES_C)
-nodist_libcatacomb_la_SOURCES += $(GENMODES_C)
-$(GENMODES_C): modes-gen-stamp
-
-## Generated interfaces.
-BUILT_SOURCES          += $(GENMODES_H)
-CLEANFILES             += $(GENMODES_H)
-nodist_pkginclude_HEADERS += $(GENMODES_H)
-$(GENMODES_H): modes-gen-stamp
-
-###--------------------------------------------------------------------------
-### Tables of classes for encryption, hashing, and message authentication.
-
-## The skeleton for the class tables.
-EXTRA_DIST             += gthingtab.c.in
-
-## Table of cipher classes.
-pkginclude_HEADERS     += gcipher.h
-CLEANFILES             += gciphertab.c
-nodist_libcatacomb_la_SOURCES += gciphertab.c
-gciphertab.c: gthingtab.c.in
-       $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gciphertab.c \
-               what=gcipher cls=gccipher thing="$(ALL_CIPHERS)"
-
-## Table of hash classes.
-pkginclude_HEADERS     += ghash.h ghash-def.h
-CLEANFILES             += ghashtab.c
-nodist_libcatacomb_la_SOURCES += ghashtab.c
-ghashtab.c: gthingtab.c.in
-       $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in ghashtab.c \
-               what=ghash cls=gchash thing="$(ALL_HASHES)"
-
-## Table of MAC classes.
-pkginclude_HEADERS     += gmac.h
-CLEANFILES             += gmactab.c
-nodist_libcatacomb_la_SOURCES += gmactab.c
-gmactab.c: gthingtab.c.in
-       $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gmactab.c \
-               what=gmac cls=gcmac thing="$(ALL_MACS)"
-
-###--------------------------------------------------------------------------
-### Testing for symmetric crypto things.
-
-## Run the test programs.
-TESTS                  += $(SYMM_TESTS)
-EXTRA_DIST             += $(SYMM_TEST_FILES)
-
-## A piece of sample text for round-trip testing encryption modes.
-EXTRA_DIST             += daftstory.h
-
-###--------------------------------------------------------------------------
-### Key management.
-
-## Assistance for elliptic-curve keys.
-pkginclude_HEADERS     += ec-keys.h
-libcatacomb_la_SOURCES += ec-fetch.c
-
-## Managing keys and keyring files.
-pkginclude_HEADERS     += key.h
-libcatacomb_la_SOURCES += key-attr.c
-libcatacomb_la_SOURCES += key-fetch.c
-libcatacomb_la_SOURCES += key-file.c
-libcatacomb_la_SOURCES += key-io.c
-libcatacomb_la_SOURCES += key-misc.c
-libcatacomb_la_SOURCES += key-moan.c
-
-## Managing key data.
-pkginclude_HEADERS     += key-data.h
-libcatacomb_la_SOURCES += key-binary.c
-libcatacomb_la_SOURCES += key-data.c
-libcatacomb_la_SOURCES += key-flags.c
-libcatacomb_la_SOURCES += key-pack.c
-libcatacomb_la_SOURCES += key-pass.c
-libcatacomb_la_SOURCES += key-text.c
-
-## Error reporting.
-pkginclude_HEADERS     += key-error.h
-libcatacomb_la_SOURCES += key-error.c
-
-## Reading passphrases.
-pkginclude_HEADERS     += passphrase.h
-libcatacomb_la_SOURCES += passphrase.c
-
-## Interfacing with the passphrase pixie.
-pkginclude_HEADERS     += pixie.h
-libcatacomb_la_SOURCES += pixie-common.c
-
-###--------------------------------------------------------------------------
-### Secret sharing.
-
-## Efficient sharing over GF(2^8).
-pkginclude_HEADERS     += gfshare.h
-libcatacomb_la_SOURCES += gfshare.c
-gfshare.lo: gfshare-tab.h
-CLEANFILES             += gfshare-tab.h
-noinst_PROGRAMS                += gfshare-mktab
-gfshare-tab.h: gfshare-mktab$e
-       $(AM_V_GEN)./gfshare-mktab >gfshare-tab.h.new && \
-               mv gfshare-tab.h.new gfshare-tab.h
-TESTS                  += gfshare.$t
-
-## Number-theoretic sharing over GF(p).
-pkginclude_HEADERS     += share.h
-libcatacomb_la_SOURCES += share.c
-TESTS                  += share.$t
-
-###--------------------------------------------------------------------------
-### Public-key cryptography.
-
-## The Blum--Blum--Shub random-bit generator.
-pkginclude_HEADERS     += bbs.h
-libcatacomb_la_SOURCES += bbs-fetch.c
-libcatacomb_la_SOURCES += bbs-gen.c
-libcatacomb_la_SOURCES += bbs-jump.c
-TESTS                  += bbs-jump.$t
-libcatacomb_la_SOURCES += bbs-rand.c
-TESTS                  += bbs-rand.$t
-EXTRA_DIST             += tests/bbs
-
-## Plain Diffie--Hellman, in Schorr groups.
-pkginclude_HEADERS     += dh.h
-libcatacomb_la_SOURCES += dh-check.c
-libcatacomb_la_SOURCES += dh-fetch.c
-libcatacomb_la_SOURCES += dh-gen.c
-libcatacomb_la_SOURCES += dh-kcdsa.c
-libcatacomb_la_SOURCES += dh-limlee.c
-libcatacomb_la_SOURCES += dh-param.c
-TESTS                  += dh-param.$t
-
-## The National Security Agency's Digital Signature Algorithm.
-pkginclude_HEADERS     += dsa.h
-libcatacomb_la_SOURCES += dsa-gen.c
-TESTS                  += dsa-gen.$t
-libcatacomb_la_SOURCES += dsa-misc.c
-libcatacomb_la_SOURCES += dsa-sign.c
-TESTS                  += dsa-sign.$t
-libcatacomb_la_SOURCES += dsa-verify.c
-TESTS                  += dsa-verify.$t
-libcatacomb_la_SOURCES += dsa-check.c
-EXTRA_DIST             += tests/dsa
-
-## Generalization of DSA to arbitrary cyclic groups.
-pkginclude_HEADERS     += gdsa.h
-libcatacomb_la_SOURCES += gdsa.c
-TESTS                  += gdsa.$t
-EXTRA_DIST             += tests/gdsa
-
-## KISA `KCDSA', generalized to arbitrary cyclic groups.
-pkginclude_HEADERS     += gkcdsa.h
-libcatacomb_la_SOURCES += gkcdsa.c
-TESTS                  += gkcdsa.$t
-EXTRA_DIST             += tests/gkcdsa
-
-## General key validity checking machinery.
-pkginclude_HEADERS     += keycheck.h
-libcatacomb_la_SOURCES += keycheck.c
-libcatacomb_la_SOURCES += keycheck-mp.c
-libcatacomb_la_SOURCES += keycheck-report.c
-
-## The Rivest--Shamir--Adleman trapdoor one-way function.
-pkginclude_HEADERS     += rsa.h
-libcatacomb_la_SOURCES += rsa-fetch.c
-libcatacomb_la_SOURCES += rsa-gen.c
-libcatacomb_la_SOURCES += rsa-priv.c
-libcatacomb_la_SOURCES += rsa-pub.c
-libcatacomb_la_SOURCES += rsa-recover.c
-libcatacomb_la_SOURCES += oaep.c
-libcatacomb_la_SOURCES += pkcs1.c
-libcatacomb_la_SOURCES += pss.c
-EXTRA_DIST             += rsa-test.c
-TESTS                  += rsa-test.$t
-EXTRA_DIST             += tests/rsa
+## At this point, we should construct the library.
+SUBDIRS                        += .
 
 ###--------------------------------------------------------------------------
-### Random number generators.
-
-## The FIPS186 generator used to generate DSA domain parameters.
-pkginclude_HEADERS     += dsarand.h
-libcatacomb_la_SOURCES += dsarand.c
-
-## Knuth's lagged-Fibonacci generator.
-pkginclude_HEADERS     += fibrand.h
-libcatacomb_la_SOURCES += fibrand.c
-
-## The FIPS 140--2 random number generator tests.
-pkginclude_HEADERS     += fipstest.h
-libcatacomb_la_SOURCES += fipstest.c
-
-## Interface for generic random number sources.
-pkginclude_HEADERS     += grand.h
-libcatacomb_la_SOURCES += grand.c
+### Ancillary programs.
 
-## A simple linear-congruential generator.
-pkginclude_HEADERS     += lcrand.h
-libcatacomb_la_SOURCES += lcrand.c
-TESTS                  += lcrand.$t
-EXTRA_DIST             += tests/lcrand
-
-## Maurer's universal statistical test.
-pkginclude_HEADERS     += maurer.h
-libcatacomb_la_SOURCES += maurer.c
-
-## System-specific noise acquisition.
-pkginclude_HEADERS     += noise.h
-libcatacomb_la_SOURCES += noise.c
-
-## Cryptographic laundering for true random data generation.
-pkginclude_HEADERS     += rand.h
-libcatacomb_la_SOURCES += rand.c
-
-## The SSL v3 pseudorandom function.
-pkginclude_HEADERS     += sslprf.h
-libcatacomb_la_SOURCES += sslprf.c
-TESTS                  += sslprf.$t
-EXTRA_DIST             += tests/sslprf
-
-## The TLS v1 pseudorandom function.
-pkginclude_HEADERS     += tlsprf.h
-libcatacomb_la_SOURCES += tlsprf.c
-TESTS                  += tlsprf.$t
-EXTRA_DIST             += tests/tlsprf
-
-###--------------------------------------------------------------------------
-### The `catcrypt' library.
-
-noinst_LTLIBRARIES     += libcatcrypt.la
-libcatcrypt_la_SOURCES  =
-
-## The main library.
-libcatcrypt_la_SOURCES += cc.h
-libcatcrypt_la_SOURCES += cc-enc.c
-libcatcrypt_la_SOURCES += cc-hash.c
-libcatcrypt_la_SOURCES += cc-kem.c
-libcatcrypt_la_SOURCES += cc-list.c
-libcatcrypt_la_SOURCES += cc-progress.c
-libcatcrypt_la_SOURCES += cc-sig.c
-libcatcrypt_la_SOURCES += cc-subcmd.c
-
-## Date parsing.
-libcatcrypt_la_SOURCES += getdate.h
-libcatcrypt_la_SOURCES += getdate.y
-
-###--------------------------------------------------------------------------
-### Utility programs.
-
-UTILS_LIBS              = libcatcrypt.la libcatacomb.la $(mLib_LIBS) $(LIBS)
-
-## Generate and verify datestamped cookies.
-bin_PROGRAMS           += cookie
-cookie_LDADD            = $(UTILS_LIBS)
-dist_man_MANS          += cookie.1
-
-## Asymmetric message encryption and decryption with deniable authentication.
-bin_PROGRAMS           += catcrypt
-catcrypt_LDADD          = $(UTILS_LIBS)
-dist_man_MANS          += catcrypt.1
-
-## Signing and verifying files.
-bin_PROGRAMS           += catsign
-catsign_LDADD           = $(UTILS_LIBS)
-dist_man_MANS          += catsign.1
-
-## Issue and verify signatures on directory trees.
-bin_PROGRAMS           += dsig
-dsig_LDADD              = $(UTILS_LIBS)
-dist_man_MANS          += dsig.1
-
-## Compute factorials to arbitrary precision.
-bin_PROGRAMS           += factorial
-factorial_LDADD                 = $(UTILS_LIBS)
-
-## Compute Fibonacci numbers to arbitrary precision.
-bin_PROGRAMS           += fibonacci
-fibonacci_LDADD                 = $(UTILS_LIBS)
-
-## Compute hashes of files.
-bin_PROGRAMS           += hashsum
-hashsum_LDADD           = $(UTILS_LIBS)
-dist_man_MANS          += hashsum.1
-
-## Key management utility.
-bin_PROGRAMS           += key
-key_SOURCES             = keyutil.c
-key_LDADD               = $(UTILS_LIBS)
-dist_man_MANS          += key.1 keyring.5
-
-## Generate passphrases with given entropy using wordlists and Markov models.
-bin_PROGRAMS           += mkphrase
-mkphrase_LDADD          = $(UTILS_LIBS)
-dist_man_MANS          += mkphrase.1
-
-## Performance testing.
-bin_PROGRAMS           += perftest
-perftest_LDADD          = $(UTILS_LIBS)
-
-## Remember passphrases for limited periods of time.
-bin_PROGRAMS           += pixie
-pixie_SOURCES           = pixie.c
-pixie_LDADD             = libcatacomb.la $(mLib_LIBS) $(PIXIE_LIBS)
-dist_man_MANS          += pixie.1
-EXTRA_DIST             += xpixie
-
-## Generate random data.
-bin_PROGRAMS           += rspit
-rspit_LDADD             = $(UTILS_LIBS)
-
-###--------------------------------------------------------------------------
-### Testing.
-
-SUFFIXES               += .c .$t .to
-.c.to:
-       $(AM_V_CC)$(COMPILE) -c -DTEST_RIG -DSRCDIR=\"$(srcdir)\" $< -o $@
-.to.$t: libcatacomb.la
-       $(AM_V_CCLD)$(LINK) $< libcatacomb.la $(mLib_LIBS) $(LIBS)
-.PRECIOUS: %.to
-CLEANFILES             += *.to *.$t
+SUBDIRS                        += progs
 
 ###--------------------------------------------------------------------------
 ### The pkg-config file.
@@ -1106,6 +93,7 @@ dist-hook::
 
 ## Additional build tools.
 EXTRA_DIST             += config/auto-version
+EXTRA_DIST             += config/confsubst
 
 ###--------------------------------------------------------------------------
 ### Debian.
diff --git a/arena.c b/arena.c
deleted file mode 100644 (file)
index dde8e84..0000000
--- a/arena.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*-c-*-
- *
- * $Id: arena.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Abstraction for memory allocation arenas
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/arena.h>
-#include <mLib/sub.h>
-
-#include "arena.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-arena *arena_secure = &arena_stdlib;
-subarena *arena_subsecure = &sub_global;
-
-/*----- Static variables --------------------------------------------------*/
-
-static subarena sub;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @arena_setsecure@ --- *
- *
- * Arguments:  @arena *a@ = arena to use for secure allocation
- *
- * Returns:    ---
- *
- * Use:                Call at the beginning of the program to set the arena for
- *             secure allocations.
- */
-
-void arena_setsecure(arena *a)
-{
-  arena_secure = a;
-  subarena_create(&sub, a);
-  arena_subsecure = &sub;
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/arena.h b/arena.h
deleted file mode 100644 (file)
index acae679..0000000
--- a/arena.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*-c-*-
- *
- * $Id: arena.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Abstraction for memory allocation arenas
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_ARENA_H
-#define CATACOMB_ARENA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/arena.h>
-#include <mLib/sub.h>
-
-/*----- Global variables --------------------------------------------------*/
-
-extern arena *arena_secure;
-extern subarena *arena_subsecure;
-
-/*----- Handy macros ------------------------------------------------------*/
-
-#define S_ALLOC(sz) A_ALLOC(arena_secure, sz)
-#define S_FREE(sz) A_FREE(arena_secure, sz)
-
-#define XS_ALLOC(sz) x_alloc(arena_secure, sz)
-#define XS_REALLOC(p, sz) x_realloc(arena_secure, p, sz)
-#define XS_FREE(p) x_free(arena_secure, p)
-
-#define S_CREATE(type) A_CREATE(arena_subsecure, type)
-#define S_DESTROY(p) A_DESTROY(arena_subsecure, p)
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @arena_setsecure@ --- *
- *
- * Arguments:  @arena *a@ = arena to use for secure allocation
- *
- * Returns:    ---
- *
- * Use:                Call at the beginning of the program to set the arena for
- *             secure allocations.
- */
-
-extern void arena_setsecure(arena */*a*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/base/Makefile.am b/base/Makefile.am
new file mode 100644 (file)
index 0000000..35c86ff
--- /dev/null
@@ -0,0 +1,54 @@
+### -*-makefile-*-
+###
+### Build script for basic utilities
+###
+### (c) 2013 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.
+
+include $(top_srcdir)/vars.am
+
+noinst_LTLIBRARIES      = libbase.la
+libbase_la_SOURCES      =
+
+###--------------------------------------------------------------------------
+### Component files.
+
+## The locked-memory arena.
+pkginclude_HEADERS     += arena.h
+libbase_la_SOURCES     += arena.c
+
+## Constant-type operations.
+pkginclude_HEADERS     += ct.h
+libbase_la_SOURCES     += ct.c
+
+## Acceptable key-size descriptions.
+pkginclude_HEADERS     += keysz.h
+libbase_la_SOURCES     += keysz.c keysz-conv.c
+
+## System-level memory locking.
+pkginclude_HEADERS     += lmem.h
+libbase_la_SOURCES     += lmem.c
+
+## Clearing secrets from memory.
+pkginclude_HEADERS     += paranoia.h
+
+###----- That's all, folks --------------------------------------------------
diff --git a/base/arena.c b/base/arena.c
new file mode 100644 (file)
index 0000000..93cbfa5
--- /dev/null
@@ -0,0 +1,63 @@
+/* -*-c-*-
+ *
+ * Abstraction for memory allocation arenas
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/arena.h>
+#include <mLib/sub.h>
+
+#include "arena.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+arena *arena_secure = &arena_stdlib;
+subarena *arena_subsecure = &sub_global;
+
+/*----- Static variables --------------------------------------------------*/
+
+static subarena sub;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @arena_setsecure@ --- *
+ *
+ * Arguments:  @arena *a@ = arena to use for secure allocation
+ *
+ * Returns:    ---
+ *
+ * Use:                Call at the beginning of the program to set the arena for
+ *             secure allocations.
+ */
+
+void arena_setsecure(arena *a)
+{
+  arena_secure = a;
+  subarena_create(&sub, a);
+  arena_subsecure = &sub;
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/base/arena.h b/base/arena.h
new file mode 100644 (file)
index 0000000..70952da
--- /dev/null
@@ -0,0 +1,77 @@
+/* -*-c-*-
+ *
+ * Abstraction for memory allocation arenas
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_ARENA_H
+#define CATACOMB_ARENA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/arena.h>
+#include <mLib/sub.h>
+
+/*----- Global variables --------------------------------------------------*/
+
+extern arena *arena_secure;
+extern subarena *arena_subsecure;
+
+/*----- Handy macros ------------------------------------------------------*/
+
+#define S_ALLOC(sz) A_ALLOC(arena_secure, sz)
+#define S_FREE(sz) A_FREE(arena_secure, sz)
+
+#define XS_ALLOC(sz) x_alloc(arena_secure, sz)
+#define XS_REALLOC(p, sz) x_realloc(arena_secure, p, sz)
+#define XS_FREE(p) x_free(arena_secure, p)
+
+#define S_CREATE(type) A_CREATE(arena_subsecure, type)
+#define S_DESTROY(p) A_DESTROY(arena_subsecure, p)
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @arena_setsecure@ --- *
+ *
+ * Arguments:  @arena *a@ = arena to use for secure allocation
+ *
+ * Returns:    ---
+ *
+ * Use:                Call at the beginning of the program to set the arena for
+ *             secure allocations.
+ */
+
+extern void arena_setsecure(arena */*a*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/ct.c b/base/ct.c
similarity index 100%
rename from ct.c
rename to base/ct.c
diff --git a/ct.h b/base/ct.h
similarity index 100%
rename from ct.h
rename to base/ct.h
similarity index 100%
rename from keysz-conv.c
rename to base/keysz-conv.c
diff --git a/base/keysz.c b/base/keysz.c
new file mode 100644 (file)
index 0000000..8291928
--- /dev/null
@@ -0,0 +1,81 @@
+/* -*-c-*-
+ *
+ * General block cipher utilities
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+
+#include "gcipher.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @keysz@ --- *
+ *
+ * Arguments:  @size_t sz@ = a proposed key size, or zero
+ *             @const octet *ksz@ = pointer to key size table
+ *
+ * Returns:    See below.
+ *
+ * Use:                Returns a sensible key size.  If @sz@ is nonzero, it is
+ *             interpreted as an amount (in bytes) of key material which the
+ *             caller has available, and the return value is either the
+ *             largest allowable key size less than or equal to the caller's
+ *             size, or zero if there is no valid key length small enough.
+ *             If @sz@ is zero, the function returns a `recommended' key
+ *             size.
+ */
+
+size_t keysz(size_t sz, const octet *ksz)
+{
+  if (sz == 0)
+    return (ksz[1]);
+  else switch (ksz[0]) {
+    case KSZ_ANY:
+      return (sz);
+    case KSZ_RANGE:
+      if (ksz[4])
+       sz -= sz % ksz[4];
+      if (sz < ksz[2])
+       return (0);
+      if (ksz[3] && sz > ksz[3])
+       return (ksz[3]);
+      return (sz);
+    case KSZ_SET: {
+      unsigned q = 0;
+      for (ksz++; *ksz; ksz++) {
+       if (sz >= *ksz && q < *ksz)
+         q = *ksz;
+      }
+      return (q);
+    }
+  }
+
+  assert(((void)"bad key size table", 0));
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from keysz.h
rename to base/keysz.h
diff --git a/base/lmem.c b/base/lmem.c
new file mode 100644 (file)
index 0000000..a613a54
--- /dev/null
@@ -0,0 +1,344 @@
+/* -*-c-*-
+ *
+ * Locked memory allocation (Unix-specific)
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef HAVE_MLOCK
+#  include <sys/mman.h>
+#endif
+
+#include <mLib/arena.h>
+#include <mLib/dstr.h>
+#include <mLib/sub.h>
+
+#include "lmem.h"
+
+/*----- Arena operations --------------------------------------------------*/
+
+static void *aalloc(arena *a, size_t sz) { return l_alloc((lmem *)a, sz); }
+static void afree(arena *a, void *p) { l_free((lmem *)a, p); }
+static void apurge(arena *a) { l_purge((lmem *)a); }
+
+static const arena_ops l_ops = { aalloc, arena_fakerealloc, afree, apurge };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @l_init@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *             @size_t sz@ = size of locked memory area requested
+ *
+ * Returns:    Zero if everything is fine, @+1@ if some insecure memory was
+ *             allocated, and @-1@ if everything went horribly wrong.
+ *
+ * Use:                Initializes the locked memory manager.  This function is safe
+ *             to call in a privileged program; privileges should usually be
+ *             dropped after allocating the locked memory block.
+ *
+ *             You must call @sub_init@ before allocating locked memory
+ *             buffers.
+ */
+
+int l_init(lmem *lm, size_t sz)
+{
+  char *p;
+  int rc = 0;
+  l_node *l;
+
+  /* --- Preliminaries --- */
+
+  lm->a.ops = &l_ops;
+  lm->err = 0;
+  lm->f = 0;
+
+  /* --- Try making a secure locked passphrase buffer --- *
+   *
+   * Drop privileges before emitting diagnostic messages.
+   */
+
+#ifdef HAVE_MLOCK
+
+  /* --- Memory-map a page from somewhere --- */
+
+#  ifdef MAP_ANON
+  p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#  else
+  {
+    int fd;
+    if ((fd = open("/dev/zero", O_RDWR)) >= 0) {
+      p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+      close(fd);
+    }
+  }
+#  endif
+
+  /* --- Lock the page in memory --- *
+   *
+   * Why does @mmap@ return such a stupid result if it fails?
+   */
+
+  if (p == 0 || p == MAP_FAILED) {
+    lm->emsg = "couldn't map locked memory area: %s";
+    lm->err = errno;
+    p = 0;
+  } else if (mlock(p, sz)) {
+    lm->emsg = "error locking memory area: %s";
+    lm->err = errno;
+    munmap(p, sz);
+    p = 0;
+  } else
+    lm->f |= LF_LOCKED;
+
+#endif
+
+  /* --- Make a standard passphrase buffer --- */
+
+#ifdef HAVE_MLOCK
+  if (!p)
+#else
+  lm->err = 0;
+  lm->emsg = "locked memory not available on this system";
+#endif
+  {
+    if ((p = malloc(sz)) == 0) {
+      lm->emsg = "not enough standard memory!";
+      lm->err = ENOMEM;
+      return (-1);
+    }
+    rc = +1;
+  }
+
+  /* --- Initialize the buffer --- */
+
+  lm->sz = lm->free = sz;
+  lm->p = p;
+
+  /* --- Initialize the free list --- */
+
+  l = CREATE(l_node);
+  l->next = 0;
+  l->p = p;
+  l->sz = sz;
+  l->f = 0;
+  lm->l = l;
+
+  /* --- Done --- */
+
+  return (rc);
+}
+
+/* --- @l_alloc@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *             @size_t sz@ = size requested
+ *
+ * Returns:    Pointer to allocated memory.
+ *
+ * Use:                Allocates @sz@ bytes of locked memory.
+ */
+
+void *l_alloc(lmem *lm, size_t sz)
+{
+  l_node *l;
+
+  sz = (sz + 3u) & ~3u;
+  for (l = lm->l; l; l = l->next) {
+    if (l->f & LF_ALLOC)
+      continue;
+    if (l->sz < sz)
+      continue;
+    l->f |= LF_ALLOC;
+    if (l->sz > sz) {
+      l_node *n = CREATE(l_node);
+      n->next = l->next;
+      n->p = l->p + sz;
+      n->sz = l->sz - sz;
+      l->sz = sz;
+      n->f = 0;
+      l->next = n;
+    }
+    assert(((void)"Locked buffer space has vanished", lm->free >= sz));
+    lm->free -= sz;
+    return (l->p);
+  }
+  return (0);
+}
+
+/* --- @l_free@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *             @void *p@ = pointer to block
+ *
+ * Returns:    ---
+ *
+ * Use:                Releases a block of locked memory.
+ */
+
+void l_free(lmem *lm, void *p)
+{
+  l_node *l;
+  l_node *ll = 0;
+
+  for (l = lm->l; l; l = l->next) {
+    size_t sz;
+
+    /* --- If this isn't the block, skip it --- */
+
+    if (l->p != p) {
+      ll = l;
+      continue;
+    }
+    assert(((void)"Block is already free", l->f & LF_ALLOC));
+
+    /* --- Coalesce with adjacent free blocks --- */
+
+    l->f &= ~LF_ALLOC;
+    sz = l->sz;
+    memset(p, 0, sz);
+
+    if (ll && !(ll->f & LF_ALLOC)) {
+      assert(((void)"Previous block doesn't fit", ll->p + ll->sz == p));
+      ll->sz += sz;
+      ll->next = l->next;
+      DESTROY(l);
+      l = ll;
+    }
+
+    ll = l->next;
+    if (ll && !(ll->f & LF_ALLOC)) {
+      assert(((void)"Next block doesn't fit", ll->p == l->p + l->sz));
+      l->sz += ll->sz;
+      l->next = ll->next;
+      DESTROY(ll);
+    }
+
+    lm->free += sz;
+    assert(((void)"Free lunch", lm->free <= lm->sz));
+    return;
+  }
+  assert(((void)"Not a locked block", 0));
+}
+
+/* --- @l_purge@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *
+ * Returns:    ---
+ *
+ * Use:                Purges all the free blocks in the buffer, and clears all of
+ *             the locked memory.  Memory is not freed back to the system.
+ */
+
+void l_purge(lmem *lm)
+{
+  l_node *l;
+
+  l = lm->l;
+  while (l) {
+    l_node *ll = l->next;
+    DESTROY(l);
+    l = ll;
+  }
+  memset(lm->p, 0, lm->sz);
+  l = CREATE(l_node);
+  l->next = 0;
+  l->p = lm->p;
+  l->sz = lm->sz;
+  l->f = 0;
+  lm->l = l;
+  lm->free = l->sz;
+}
+
+/* --- @l_destroy@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a locked memory arena permanently.
+ */
+
+void l_destroy(lmem *lm)
+{
+  l_node *l;
+
+  l = lm->l;
+  while (l) {
+    l_node *ll = l->next;
+    DESTROY(l);
+    l = ll;
+  }
+  memset(lm->p, 0, lm->sz);
+
+#ifdef HAVE_MLOCK
+  if (lm->f & LF_LOCKED)
+    munmap(lm->p, lm->sz);
+  else
+#endif
+    free(lm->p); /*sic*/
+}
+
+/* --- @l_report@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *             @dstr *d@ = string to write the error message on
+ *
+ * Returns:    Zero if the buffer is fine, @+1@ if there was a problem
+ *             getting locked memory but insecure stuff could be allocated,
+ *             and @-1@ if not even insecure memory could be found.
+ *
+ * Use:                Returns a user-digestable explanation for the state of a
+ *             locked memory buffer.  If the return code is zero, no message
+ *             is emitted to the string @d@.
+ */
+
+int l_report(lmem *lm, dstr *d)
+{
+  int rc;
+  if (lm->err)
+    dstr_putf(d, lm->emsg, strerror(lm->err));
+  if (!lm->p)
+    rc = -1;
+  else if (lm->err)
+    rc = +1;
+  else
+    rc = 0;
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/base/lmem.h b/base/lmem.h
new file mode 100644 (file)
index 0000000..88b0062
--- /dev/null
@@ -0,0 +1,164 @@
+/* -*-c-*-
+ *
+ * Locked memory allocation
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_LMEM_H
+#define CATACOMB_LMEM_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/arena.h>
+#include <mLib/dstr.h>
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- Block list --- *
+ *
+ * The block list is kept in normal memory, to avoid wasting precious locked
+ * memory.  Entries are sorted into ascending address order to make
+ * coalescing free blocks easier.  All blocks, free or not, are included in
+ * the list.
+ */
+
+typedef struct l_node {
+  struct l_node *next;                 /* Next free block in chain */
+  char *p;                             /* Pointer to the block */
+  size_t sz;                           /* Size of the block */
+  unsigned f;                          /* Various flags */
+} l_node;
+
+#define LF_ALLOC 1u
+
+/* --- Locked memory buffer state --- */
+
+typedef struct lmem {
+  arena a;                             /* Arena header block */
+  unsigned f;                          /* Various flags */
+  char *p;                             /* Pointer to locked buffer */
+  l_node *l;                           /* Pointer to block list */
+  size_t sz;                           /* Size of locked buffer */
+  size_t free;                         /* Size of free area */
+  int err; char *emsg;                 /* Error indicators */
+} lmem;
+
+#define LF_LOCKED 1u
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @l_init@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *             @size_t sz@ = size of locked memory area requested
+ *
+ * Returns:    Zero if everything is fine, @+1@ if some insecure memory was
+ *             allocated, and @-1@ if everything went horribly wrong.
+ *
+ * Use:                Initializes the locked memory manager.  This function is safe
+ *             to call in a privileged program; privileges should usually be
+ *             dropped after allocating the locked memory block.
+ *
+ *             You must call @sub_init@ before allocating locked memory
+ *             buffers.
+ */
+
+extern int l_init(lmem */*lm*/, size_t /*sz*/);
+
+/* --- @l_alloc@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *             @size_t sz@ = size requested
+ *
+ * Returns:    Pointer to allocated memory.
+ *
+ * Use:                Allocates @sz@ bytes of locked memory.
+ */
+
+extern void *l_alloc(lmem */*lm*/, size_t /*sz*/);
+
+/* --- @l_free@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *             @void *p@ = pointer to block
+ *
+ * Returns:    ---
+ *
+ * Use:                Releases a block of locked memory.
+ */
+
+extern void l_free(lmem */*lm*/, void */*p*/);
+
+/* --- @l_purge@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *
+ * Returns:    ---
+ *
+ * Use:                Purges all the free blocks in the buffer, and clears all of
+ *             the locked memory.  Memory is not freed back to the system.
+ */
+
+extern void l_purge(lmem */*lm*/);
+
+/* --- @l_destroy@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a locked memory arena permanently.
+ */
+
+extern void l_destroy(lmem */*lm*/);
+
+/* --- @l_report@ --- *
+ *
+ * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
+ *             @dstr *d@ = string to write the error message on
+ *
+ * Returns:    Zero if the buffer is fine, @+1@ if there was a problem
+ *             getting locked memory but insecure stuff could be allocated,
+ *             and @-1@ if not even insecure memory could be found.
+ *
+ * Use:                Returns a user-digestable explanation for the state of a
+ *             locked memory buffer.  If the return code is zero, no message
+ *             is emitted to the string @d@.
+ */
+
+extern int l_report(lmem */*lm*/, dstr */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/base/paranoia.h b/base/paranoia.h
new file mode 100644 (file)
index 0000000..368667c
--- /dev/null
@@ -0,0 +1,49 @@
+/* -*-c-*-
+ *
+ * Macros and functions for cryptographic paranoia
+ *
+ * (c) 1998 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.
+ */
+
+#ifndef CATACOMB_PARANOIA_H
+#define CATACOMB_PARANOIA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define BURN(x) (memset(&(x), 0, sizeof(x)))
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/bbs-fetch.c b/bbs-fetch.c
deleted file mode 100644 (file)
index 96c21d0..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*-c-*-
- *
- * $Id: bbs-fetch.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Key fetching for BBS public and private keys
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "bbs.h"
-#include "key.h"
-
-/*----- Key fetching ------------------------------------------------------*/
-
-const key_fetchdef bbs_pubfetch[] = {
-  { "n",       offsetof(bbs_pub, n),           KENC_MP,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-static const key_fetchdef priv[] = {
-  { "p",       offsetof(bbs_priv, p),          KENC_MP,        0 },
-  { "q",       offsetof(bbs_priv, q),          KENC_MP,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-const key_fetchdef bbs_privfetch[] = {
-  { "n",       offsetof(bbs_priv, n),          KENC_MP,        0 },
-  { "private", 0,                              KENC_STRUCT,    priv },
-  { 0,         0,                              0,              0 }
-};
-
-/* --- @bbs_pubfree@, @bbs_privfree@ --- *
- *
- * Arguments:  @bbs_pub *bp@, @bbs_priv *bp@ = pointer to key block
- *
- * Returns:    ---
- *
- * Use:                Frees an RSA key block.
- */
-
-void bbs_pubfree(bbs_pub *bp)
-{
-  mp_drop(bp->n);
-}
-
-void bbs_privfree(bbs_priv *bp)
-{
-  mp_drop(bp->n);
-  mp_drop(bp->p);
-  mp_drop(bp->q);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/bbs-gen.c b/bbs-gen.c
deleted file mode 100644 (file)
index c668b21..0000000
--- a/bbs-gen.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* -*-c-*-
- *
- * $Id: bbs-gen.c,v 1.6 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate Blum integers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "bbs.h"
-#include "mp.h"
-#include "mprand.h"
-#include "pgen.h"
-#include "strongprime.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @bbs_gen@ --- *
- *
- * Arguments:  @bbs_priv *bp@ = pointer to parameter block
- *             @unsigned nbits@ = number of bits in the modulus
- *             @grand *r@ = pointer to random number source
- *             @unsigned n@ = number of attempts to make
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for event handler
- *
- * Returns:    If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@.
- *
- * Use:                Finds two prime numbers %$p'$% and %$q'$% such that both are
- *             congruent to %$3 \bmod 4$%, and  $(p - 1)/2$% and
- *             %$(q - 1)/2$% have no common factors.  The product %$n = pq$%
- *             is eminently suitable for use as a modulus in a Blum-Blum-
- *             Shub pseudorandom bit generator.
- */
-
-int bbs_gen(bbs_priv *bp, unsigned nbits, grand *r, unsigned n,
-           pgen_proc *event, void *ectx)
-{
-  rabin rb;
-  pfilt jp;
-  pgen_jumpctx j;
-  pgen_gcdstepctx g;
-  unsigned nb = nbits/2;
-  mp *x = MP_NEW;
-
-  /* --- Generate @p@ --- */
-
-again:
-  if ((x = strongprime_setup("p", x, &jp, nb, r, n, event, ectx)) == 0)
-    goto fail_x;
-  j.j = &jp;
-  bp->p = pgen("p", MP_NEW, x, event, ectx, n, pgen_jump, &j,
-              rabin_iters(nb), pgen_test, &rb);
-  pfilt_destroy(&jp);
-  if (!bp->p) {
-    if (n)
-      goto fail_p;
-    goto again;
-  }
-
-  /* --- Generate @q@ --- */
-
-  nb = nbits - nb;
-  if ((x = strongprime_setup("q", x, &g.jp, nb, r, n, event, ectx)) == 0)
-    goto fail_q;
-  if ((x->v[0] & 3) != 3)
-    x = mp_add(x, x, g.jp.m);
-  pfilt_muladd(&g.jp, &g.jp, 2, 0);
-  g.r = mp_lsr(MP_NEW, bp->p, 1);
-  g.g = MP_NEW;
-  g.max = MP_ONE;
-  bp->q = pgen("q", MP_NEW, x, event, ectx, n, pgen_gcdstep, &g,
-              rabin_iters(nb), pgen_test, &rb);
-  pfilt_destroy(&g.jp);
-  mp_drop(g.r);
-  mp_drop(g.g);
-  if (!bp->q) {
-    if (n)
-      goto fail_q;
-    mp_drop(bp->p);
-    goto again;
-  }
-
-  /* --- Compute @n@ --- */
-
-  bp->n = mp_mul(MP_NEW, bp->p, bp->q);
-  mp_drop(x);
-  return (PGEN_DONE);
-
-  /* --- Tidy up if things went wrong --- */
-
-fail_q:
-  mp_drop(bp->p);
-fail_p:
-  mp_drop(x);
-fail_x:
-  return (PGEN_ABORT);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/bbs-jump.c b/bbs-jump.c
deleted file mode 100644 (file)
index 7275bd9..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Jumping around a BBS sequence
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "bbs.h"
-#include "mp.h"
-#include "mpbarrett.h"
-#include "mpcrt.h"
-#include "mpint.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @jump@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator context
- *             @const bbs_priv *bp@ = pointer to BBS modulus factors
- *             @mp *n@ = number of steps to move
- *             @mp *px@ = exponent mod @p@ for a one-step jump
- *             @mp *qx@ = exponent mod @q@ for a one-step jump
- *
- * Returns:    ---
- *
- * Use:                Jumps a BBS context a certain number of places (assuming the
- *             arguments are right).
- *
- *             Let the BBS modulus be %$n = pq$% and the current residue be
- *             %$x$%.  Then the computations performed are:
- *
- *               * Calculate %$x_p = x \bmod p$% and %$x_q = x \bmod q$%.
- *
- *               * Determine %$e_p = px^n \bmod (p - 1)$% and similarly
- *                 %$e_q = qx^n \bmod (p - 1)$%.
- *
- *               * Calculate %$x_p' = x_p^{e_p} \bmod p$% and
- *                 %$x_q' = x_q^{e_q} \bmod q$%.
- *
- *               * Combine %$x_p'$% and %$x_q'$% using the Chinese Remainder
- *                 Theorem.
- *
- *             If you want to step the generator forwards, simply set
- *             %$px = qx = 2$%.  If you want to step backwards, make
- *             %$px = (p + 1)/4$% and %$qx = (q + 1)/4$%.  Note that, if
- *             %$x$% is a quadratic residue mod $%p$%, then
- *
- *             %$(x^2) ^ {(p + 1)/4}$%
- *               %${} = x^{(p + 1)/2}$%
- *               %${} = x \cdot x^{(p - 1)/2}$%
- *               %${} = x$%
- *
- *             Simple, no?  (Note that the division works because
- *             %$p \equiv 3 \pmod 4$%.)
- */
-
-static void jump(bbs *b, const bbs_priv *bp, mp *n,
-                mp *px, mp *qx)
-{
-  mp *ep, *eq;
-  mp *v[2] = { MP_NEW, MP_NEW };
-
-  /* --- First work out the exponents --- */
-
-  {
-    mpbarrett mb;
-    mp *m;
-
-    m = mp_sub(MP_NEW, bp->p, MP_ONE);
-    mpbarrett_create(&mb, m);
-    ep = mpbarrett_exp(&mb, MP_NEW, px, n);
-    mpbarrett_destroy(&mb);
-    if (qx == px)
-      eq = MP_COPY(ep);
-    else {
-      m = mp_sub(m, bp->q, MP_ONE);
-      mpbarrett_create(&mb, m);
-      eq = mpbarrett_exp(&mb, MP_NEW, qx, n);
-      mpbarrett_destroy(&mb);
-    }
-
-    mp_drop(m);
-  }
-
-  /* --- Now calculate the residues of @x@ --- */
-
-  mp_div(0, &v[0], b->x, bp->p);
-  mp_div(0, &v[1], b->x, bp->q);
-
-  /* --- Exponentiate --- */
-
-  {
-    mpbarrett mb;
-
-    mpbarrett_create(&mb, bp->p);
-    v[0] = mpbarrett_exp(&mb, v[0], v[0], ep);
-    mpbarrett_destroy(&mb);
-
-    mpbarrett_create(&mb, bp->q);
-    v[1] = mpbarrett_exp(&mb, v[1], v[1], eq);
-    mpbarrett_destroy(&mb);
-
-    mp_drop(ep);
-    mp_drop(eq);
-  }
-
-  /* --- Sort out the result using the Chinese Remainder Theorem --- */
-
-  {
-    mpcrt_mod mv[2];
-    mpcrt c;
-    int i;
-
-    mv[0].m = MP_COPY(bp->p);
-    mv[1].m = MP_COPY(bp->q);
-    for (i = 0; i < 2; i++)
-      mv[i].n = mv[i].ni = mv[i].nni = MP_NEW;
-    mpcrt_create(&c, mv, 2, b->mb.m);
-    b->x = mpcrt_solve(&c, b->x, v);
-    mpcrt_destroy(&c);
-  }
-
-  /* --- Tidy away --- */
-
-  mp_drop(v[0]);
-  mp_drop(v[1]);
-  b->r = b->x->v[0];
-  b->b = b->k;
-}
-
-/* --- @bbs_{ff,rew}{,n}@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to a BBS generator state
- *             @const bbs_priv *bp@ = pointer to BBS modulus factors
- *             @mp *n@, @unsigned long n@ = number of steps to make
- *
- * Returns:    ---
- *
- * Use:                `Fast-forwards' or rewinds a Blum-Blum-Shub generator by @n@
- *             steps.  The @...n@ versions take an @unsigned long@ argument;
- *             the non-@...n@ versions a multiprecision integer.  If @n@ is
- *             negative then the generator is stepped in the reverse
- *             direction.
- */
-
-static void ff(bbs *b, const bbs_priv *bp, mp *n)
-  { jump(b, bp, n, MP_TWO, MP_TWO); }
-
-static void rew(bbs *b, const bbs_priv *bp, mp *n)
-{
-  mp *px = mp_lsr(MP_NEW, bp->p, 2);
-  mp *qx = mp_lsr(MP_NEW, bp->q, 2);
-  px = mp_add(px, px, MP_ONE);
-  qx = mp_add(qx, qx, MP_ONE);
-  jump(b, bp, n, px, qx);
-  mp_drop(px);
-  mp_drop(qx);
-}
-
-void bbs_ff(bbs *b, const bbs_priv *bp, mp *n)
-{
-  if (!MP_NEGP(n))
-    ff(b, bp, n);
-  else {
-    n = mp_neg(MP_NEW, n);
-    rew(b, bp, n);
-    mp_drop(n);
-  }
-}
-
-void bbs_ffn(bbs *b, const bbs_priv *bp, unsigned long n)
-  { mp *nn = mp_fromulong(MP_NEW, n); ff(b, bp, nn); mp_drop(nn); }
-
-void bbs_rew(bbs *b, const bbs_priv *bp, mp *n)
-{
-  if (!MP_NEGP(n))
-    rew(b, bp, n);
-  else {
-    n = mp_neg(MP_NEW, n);
-    ff(b, bp, n);
-    mp_drop(n);
-  }
-}
-
-void bbs_rewn(bbs *b, const bbs_priv *bp, unsigned long n)
-  { mp *nn = mp_fromulong(MP_NEW, n); bbs_rew(b, bp, nn); mp_drop(nn); }
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int verify(dstr *v)
-{
-  bbs_priv bp;
-  bbs b;
-  mp *x;
-  unsigned long n;
-  int ok = 1;
-  uint32 p, q, r;
-  int i;
-
-  bp.p = *(mp **)v[0].buf;
-  bp.q = *(mp **)v[1].buf;
-  bp.n = mp_mul(MP_NEW, bp.p, bp.q);
-  x = *(mp **)v[2].buf;
-  n = *(unsigned long *)v[3].buf;
-
-  bbs_create(&b, bp.n, x);
-  p = bbs_bits(&b, 32);
-
-  bbs_seed(&b, x);
-  for (i = 0; i < n; i++)
-    bbs_step(&b);
-  q = bbs_bits(&b, 32);
-  bbs_wrap(&b);
-
-  bbs_rewn(&b, &bp, n + (32 + b.k - 1) / b.k);
-  r = bbs_bits(&b, 32);
-
-  if (r != p) {
-    fputs("\n*** bbs rewind failure\n", stderr);
-    fputs("p = ", stderr); mp_writefile(bp.p, stderr, 10); fputc('\n', stderr);
-    fputs("q = ", stderr); mp_writefile(bp.q, stderr, 10); fputc('\n', stderr);
-    fputs("n = ", stderr); mp_writefile(bp.n, stderr, 10); fputc('\n', stderr);
-    fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr);
-    fprintf(stderr, "stepped %lu back\n", n + (32 + b.k - 1) / b.k);
-    fprintf(stderr, "expected output = %08lx, found %08lx\n",
-           (unsigned long)p, (unsigned long)r);
-    ok = 0;
-  }
-
-  bbs_seed(&b, x);
-  bbs_ffn(&b, &bp, n);
-  r = bbs_bits(&b, 32);
-
-  if (q != r) {
-    fputs("\n*** bbs fastforward failure\n", stderr);
-    fputs("p = ", stderr); mp_writefile(bp.p, stderr, 10); fputc('\n', stderr);
-    fputs("q = ", stderr); mp_writefile(bp.q, stderr, 10); fputc('\n', stderr);
-    fputs("n = ", stderr); mp_writefile(bp.n, stderr, 10); fputc('\n', stderr);
-    fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr);
-    fprintf(stderr, "stepped %lu back\n", n + (32 + b.k - 1) / b.k);
-    fprintf(stderr, "expected output = %08lx, found %08lx\n",
-           (unsigned long)q, (unsigned long)r);
-    ok = 0;
-  }
-
-  bbs_destroy(&b);
-  mp_drop(bp.p);
-  mp_drop(bp.q);
-  mp_drop(bp.n);
-  mp_drop(x);
-
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "bbs-jump", verify, { &type_mp, &type_mp, &type_mp, &type_ulong, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/bbs");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/bbs-rand.c b/bbs-rand.c
deleted file mode 100644 (file)
index 20d9c7a..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Blum-Blum-Shub secure random number generator
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#include "arena.h"
-#include "bbs.h"
-#include "grand.h"
-#include "mp.h"
-#include "mpbarrett.h"
-#include "mpint.h"
-#include "mprand.h"
-#include "paranoia.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @bbs_create@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state to initialize
- *             @mp *m@ = modulus (must be a Blum integer)
- *             @mp *x@ = initial seed for generator
- *
- * Returns:    ---
- *
- * Use:                Initializes a BBS generator.  The generator is stepped once
- *             after initialization, as for @bbs_seed@.
- */
-
-void bbs_create(bbs *b, mp *m, mp *x)
-{
-  mpw kw;
-  mp k;
-
-  mpbarrett_create(&b->mb, m);
-  kw = mp_bits(m) - 1;
-  mp_build(&k, &kw, &kw + 1);
-  b->k = mp_bits(&k) - 1;
-  b->x = 0;
-  bbs_seed(b, x);
-}
-
-/* --- @bbs_destroy@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *
- * Returns:    ---
- *
- * Use:                Destroys a generator state when it's no longer wanted.
- */
-
-void bbs_destroy(bbs *b)
-{
-  mp_drop(b->x);
-  mpbarrett_destroy(&b->mb);
-}
-
-/* --- @bbs_step@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *
- * Returns:    ---
- *
- * Use:                Steps the generator once.  This isn't too useful in client
- *             code.
- */
-
-void bbs_step(bbs *b)
-{
-  mp *x = b->x;
-  x = mp_sqr(x, x);
-  x = mpbarrett_reduce(&b->mb, x, x);
-  b->x = x;
-  b->b = b->k;
-  b->r = b->x->v[0];
-}
-
-/* --- @bbs_set@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *             @mp *x@ = new residue to set
- *
- * Returns:    ---
- *
- * Use:                Sets a new quadratic residue.  The generator is stepped once.
- */
-
-void bbs_set(bbs *b, mp *x)
-{
-  mp_drop(b->x);
-  b->x = MP_COPY(x);
-  bbs_step(b);
-}
-
-/* --- @bbs_seed@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *             @mp *x@ = new seed to set
- *
- * Returns     ---
- *
- * Use:                Sets a new seed.  The generator is stepped until the residue
- *             has clearly wrapped around.
- */
-
-void bbs_seed(bbs *b, mp *x)
-{
-  mp *y;
-  x = MP_COPY(x);
-  for (;;) {
-    y = mp_sqr(MP_NEW, x);
-    y = mpbarrett_reduce(&b->mb, y, y);
-    if (MP_CMP(y, <, x))
-      break;
-    mp_drop(x);
-    x = y;
-  }
-  mp_drop(x);
-  bbs_set(b, y);
-  mp_drop(y);
-}
-
-/* --- @bbs_bits@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *             @unsigned bits@ = number of bits wanted
- *
- * Returns:    Bits extracted from the BBS generator.
- *
- * Use:                Extracts a requested number of bits from the BBS generator.
- */
-
-uint32 bbs_bits(bbs *b, unsigned bits)
-{
-  uint32 x = 0;
-  mpw m;
-
-  /* --- Keep turning the handle until there's enough in the reservoir --- */
-
-  while (bits >= b->b) {
-    bits -= b->b;
-    m = (1 << b->b) - 1;
-    x |= (b->r & m) << bits;
-    bbs_step(b);
-  }
-
-  /* --- Extract the last few bits needed --- */
-
-  if (bits) {
-    m = (1 << bits) - 1;
-    b->b -= bits;
-    x |= (b->r >> b->b) & m;
-  }
-
-  /* --- Done --- */
-
-  return (x);
-}
-
-/* --- @bbs_wrap@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *
- * Returns:    ---
- *
- * Use:                Steps the generator if any of the reservoir bits are used.
- *             This can be used to `wrap up' after a Blum-Goldwasser
- *             encryption, for example, producing the final value to be sent
- *             along with the ciphertext.
- *
- *             If a generator is seeded, %$b$% bits are extracted, and then
- *             @bbs_wrap@ is called, the generator will have been stepped
- *             %$\lceil b/k \rceil$% times.
- */
-
-void bbs_wrap(bbs *b)
-{
-  if (b->b < b->k)
-    bbs_step(b);
-}
-
-/*----- Generic random number generator interface -------------------------*/
-
-typedef struct gctx {
-  grand r;
-  bbs b;
-} gctx;
-
-static void gdestroy(grand *r)
-{
-  gctx *g = (gctx *)r;
-  bbs_destroy(&g->b);
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static int gmisc(grand *r, unsigned op, ...)
-{
-  gctx *g = (gctx *)r;
-  va_list ap;
-  int rc = 0;
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDMP:
-       case GRAND_SEEDRAND:
-       case BBS_SET:
-       case BBS_STEP:
-       case BBS_STEPSZ:
-       case BBS_BITS:
-       case BBS_WRAP:
-       case BBS_FF:
-       case BBS_FFN:
-       case BBS_REW:
-       case BBS_REWN:
-       case BBS_MOD:
-       case BBS_STATE:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT: {
-      mp *x = mp_fromuint(MP_NEW, va_arg(ap, unsigned));
-      bbs_seed(&g->b, x);
-      mp_drop(x);
-    } break;
-    case GRAND_SEEDUINT32: {
-      mp *x = mp_fromuint32(MP_NEW, va_arg(ap, uint32));
-      bbs_seed(&g->b, x);
-      mp_drop(x);
-    } break;
-    case GRAND_SEEDMP:
-      bbs_seed(&g->b, va_arg(ap, mp *));
-      break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      mp *m = mprand(MP_NEW, mp_bits(g->b.mb.m) - 1, rr, 0);
-      bbs_seed(&g->b, m);
-      mp_drop(m);
-    } break;
-    case BBS_SET:
-      bbs_set(&g->b, va_arg(ap, mp *));
-      break;
-    case BBS_STEP:
-      bbs_step(&g->b);
-      break;
-    case BBS_STEPSZ:
-      rc = g->b.k;
-      break;
-    case BBS_BITS: {
-      unsigned nb = va_arg(ap, unsigned);
-      uint32 *w = va_arg(ap, uint32 *);
-      *w = bbs_bits(&g->b, nb);
-    } break;
-    case BBS_WRAP:
-      bbs_wrap(&g->b);
-      break;
-    case BBS_FF: {
-      const bbs_priv *bp = va_arg(ap, const bbs_priv *);
-      mp *n = va_arg(ap, mp *);
-      bbs_ff(&g->b, bp, n);
-    } break;
-    case BBS_FFN: {
-      const bbs_priv *bp = va_arg(ap, const bbs_priv *);
-      unsigned long n = va_arg(ap, unsigned long);
-      bbs_ffn(&g->b, bp, n);
-    } break;
-    case BBS_REW: {
-      const bbs_priv *bp = va_arg(ap, const bbs_priv *);
-      mp *n = va_arg(ap, mp *);
-      bbs_rew(&g->b, bp, n);
-    } break;
-    case BBS_REWN: {
-      const bbs_priv *bp = va_arg(ap, const bbs_priv *);
-      unsigned long n = va_arg(ap, unsigned long);
-      bbs_rewn(&g->b, bp, n);
-    } break;
-    case BBS_MOD: {
-      mp **n = va_arg(ap, mp **);
-      if (*n) MP_DROP(*n);
-      *n = MP_COPY(g->b.mb.m);
-    } break;
-    case BBS_STATE: {
-      mp **n = va_arg(ap, mp **);
-      if (*n) MP_DROP(*n);
-      *n = MP_COPY(g->b.x);
-    } break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static octet gbyte(grand *r)
-{
-  gctx *g = (gctx *)r;
-  return (bbs_bits(&g->b, 8));
-}
-
-static uint32 gword(grand *r)
-{
-  gctx *g = (gctx *)r;
-  return (bbs_bits(&g->b, 32));
-}
-
-static const grand_ops gops = {
-  "bbs",
-  GRAND_CRYPTO, 0,
-  gmisc, gdestroy,
-  gword, gbyte, gword, grand_range, grand_fill
-};
-
-/* --- @bbs_rand@ --- *
- *
- * Arguments:  @mp *m@ = modulus
- *             @mp *x@ = initial seed
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a
- *             Blum-Blum-Shub generator.
- */
-
-grand *bbs_rand(mp *m, mp *x)
-{
-  gctx *g = S_CREATE(gctx);
-  g->r.ops = &gops;
-  bbs_create(&g->b, m, x);
-  return (&g->r);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int verify(dstr *v)
-{
-  mp *n = *(mp **)v[0].buf;
-  mp *x = *(mp **)v[1].buf;
-  grand *b = bbs_rand(n, x);
-  dstr d = DSTR_INIT;
-  int ok = 1;
-
-  dstr_ensure(&d, v[2].len);
-  b->ops->fill(b, d.buf, v[2].len);
-  d.len = v[2].len;
-  if (memcmp(d.buf, v[2].buf, v[2].len) != 0) {
-    fputs("\n*** bbs failure\n", stderr);
-    fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr);
-    fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr);
-    fputs("expected = ", stderr); type_hex.dump(&v[2], stderr);
-    fputc('\n', stderr);
-    fputs("   found = ", stderr); type_hex.dump(&d, stderr);
-    fputc('\n', stderr);
-    fprintf(stderr, "k = %u\n", ((gctx *)b)->b.k);
-    ok = 0;
-  }
-  b->ops->destroy(b);
-  mp_drop(x);
-  mp_drop(n);
-  dstr_destroy(&d);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "bbs", verify, { &type_mp, &type_mp, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/bbs");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/bbs.h b/bbs.h
deleted file mode 100644 (file)
index 30fb474..0000000
--- a/bbs.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * The Blum-Blum-Shub random bit generator
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on the BBS generator ----------------------------------------*
- *
- * The Blum-Blum-Shub generator takes the least significant bits from the
- * sequence %$x_i = x_{i - 1}^2 \bmod n$%, where %$n = pq$% is the product of
- * two primes %$p$% and %$q$%, each of which are congruent to %$3 \bmod 4$%.
- * For maximum period of the generator, %$(p - 1)/2$% and %$(q - 1)/1$%
- * should be coprime.  It is safe to use the least significant
- * %$\log \log n$% bits of each step in the sequence -- an adversary must
- * factor the modulus before being able to work forwards or backwards.  The
- * output of the generator cannot be distinguished from a (uniform,
- * independent) random sequence of bits using any polynomial-time test.  This
- * is by far the strongest pseudorandom number generator provided in
- * Catacomb, and by far the slowest too.  For normal use, the standard
- * Catacomb @rand@ generator should be more than adequate.
- */
-
-#ifndef CATACOMB_BBS_H
-#define CATACOMB_BBS_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_KEY_H
-#  include "key.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_MPBARRETT_H
-#  include "mpbarrett.h"
-#endif
-
-#ifndef CATACOMB_PGEN_H
-#  include "pgen.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- Basic generator state --- */
-
-typedef struct bbs {
-  mpbarrett mb;                                /* Barrett reduction context */
-  mp *x;                               /* Current quadratic residue */
-  unsigned k;                          /* Number of bits from each step */
-  unsigned b;                          /* Number of bits in reservoir */
-  mpw r;                               /* Reservoir of output bits */
-} bbs;
-
-/* --- Parameters --- */
-
-typedef struct bbs_pub {
-  mp *n;
-} bbs_pub;
-
-typedef struct bbs_priv {
-  mp *p, *q;                           /* Prime factors (3 mod 4) */
-  mp *n;                               /* Product @pq@ -- a Blum integer */
-} bbs_priv;
-
-/*----- Key fetching ------------------------------------------------------*/
-
-extern const key_fetchdef bbs_pubfetch[];
-#define BBS_PUBFETCHSZ 3
-
-extern const key_fetchdef bbs_privfetch[];
-#define BBS_PRIVFETCHSZ 7
-
-/* --- @bbs_pubfree@, @bbs_privfree@ --- *
- *
- * Arguments:  @bbs_pub *bp@, @bbs_priv *bp@ = pointer to key block
- *
- * Returns:    ---
- *
- * Use:                Frees a BBS key block.
- */
-
-extern void bbs_pubfree(bbs_pub */*bp*/);
-extern void bbs_privfree(bbs_priv */*bp*/);
-
-/*----- The basic generator -----------------------------------------------*/
-
-/* --- @bbs_create@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state to initialize
- *             @mp *m@ = modulus (must be a Blum integer)
- *             @mp *x@ = initial seed for generator
- *
- * Returns:    ---
- *
- * Use:                Initializes a BBS generator.  The generator is stepped once
- *             after initialization, as for @bbs_seed@.
- */
-
-extern void bbs_create(bbs */*b*/, mp */*m*/, mp */*x*/);
-
-/* --- @bbs_destroy@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *
- * Returns:    ---
- *
- * Use:                Destroys a generator state when it's no longer wanted.
- */
-
-extern void bbs_destroy(bbs */*b*/);
-
-/* --- @bbs_step@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *
- * Returns:    ---
- *
- * Use:                Steps the generator once.  This isn't too useful in client
- *             code.
- */
-
-extern void bbs_step(bbs */*b*/);
-
-/* --- @bbs_set@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *             @mp *x@ = new residue to set
- *
- * Returns:    ---
- *
- * Use:                Sets a new quadratic residue.  The generator is stepped once.
- */
-
-extern void bbs_set(bbs */*b*/, mp */*x*/);
-
-/* --- @bbs_seed@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *             @mp *x@ = new seed to set
- *
- * Returns     ---
- *
- * Use:                Sets a new seed.  The generator is stepped until the residue
- *             has clearly wrapped around.
- */
-
-extern void bbs_seed(bbs */*b*/, mp */*x*/);
-
-/* --- @bbs_bits@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *             @unsigned bits@ = number of bits wanted
- *
- * Returns:    Bits extracted from the BBS generator.
- *
- * Use:                Extracts a requested number of bits from the BBS generator.
- */
-
-extern uint32 bbs_bits(bbs */*b*/, unsigned /*bits*/);
-
-/* --- @bbs_wrap@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to BBS generator state
- *
- * Returns:    ---
- *
- * Use:                Steps the generator if any of the reservoir bits are used.
- *             This can be used to `wrap up' after a Blum-Goldwasser
- *             encryption, for example, producing the final value to be sent
- *             along with the ciphertext.
- *
- *             If a generator is seeded, %$b$% bits are extracted, and then
- *             @bbs_wrap@ is called, the generator will have been stepped
- *             %$\lceil b/k \rceil$% times.
- */
-
-extern void bbs_wrap(bbs */*b*/);
-
-/*----- Large forwards and backwards jumps --------------------------------*/
-
-/* --- @bbs_{ff,rew}{,n}@ --- *
- *
- * Arguments:  @bbs *b@ = pointer to a BBS generator state
- *             @const bbs_priv *bp@ = pointer to BBS modulus factors
- *             @mp *n@, @unsigned long n@ = number of steps to make
- *
- * Returns:    ---
- *
- * Use:                `Fast-forwards' or rewinds a Blum-Blum-Shub generator by @n@
- *             steps.  The @...n@ versions take an @unsigned long@ argument;
- *             the non-@...n@ versions a multiprecision integer.  If @n@ is
- *             negative then the generator is stepped in the reverse
- *             direction.
- */
-
-extern void bbs_ff(bbs */*b*/, const bbs_priv */*bp*/, mp */*n*/);
-extern void bbs_ffn(bbs */*b*/, const bbs_priv */*bp*/, unsigned long /*n*/);
-extern void bbs_rew(bbs */*b*/, const bbs_priv */*bp*/, mp */*n*/);
-extern void bbs_rewn(bbs */*b*/, const bbs_priv */*bp*/, unsigned long /*n*/);
-
-/*----- Parameter generation ----------------------------------------------*/
-
-/* --- @bbs_gen@ --- *
- *
- * Arguments:  @bbs_priv *bp@ = pointer to parameter block
- *             @unsigned nbits@ = number of bits in the modulus
- *             @grand *r@ = pointer to random number source
- *             @unsigned n@ = number of attempts to make
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for event handler
- *
- * Returns:    If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@.
- *
- * Use:                Finds two prime numbers %$p'$% and %$q'$% such that both are
- *             congruent to %$3 \bmod 4$%, and  $(p - 1)/2$% and
- *             %$(q - 1)/2$% have no common factors.  The product %$n = pq$%
- *             is eminently suitable for use as a modulus in a Blum-Blum-
- *             Shub pseudorandom bit generator.
- */
-
-extern int bbs_gen(bbs_priv */*bp*/, unsigned /*nbits*/, grand */*r*/,
-                  unsigned /*n*/, pgen_proc */*event*/, void */*ectx*/);
-
-/*----- Generic random number generator interface -------------------------*/
-
-/* --- @bbs_rand@ --- *
- *
- * Arguments:  @mp *m@ = modulus
- *             @mp *x@ = initial seed
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a
- *             Blum-Blum-Shub generator.
- */
-
-extern grand *bbs_rand(mp */*m*/, mp */*x*/);
-
-/* --- Blum-Blum-Shub-specific misc op codes --- */
-
-enum {
-  BBS_SET = GRAND_SPECIFIC('B'),       /* @mp *x@ */
-  BBS_STEP,                            /* @void@ */
-  BBS_STEPSZ,                          /* @void@ */
-  BBS_BITS,                            /* @unsigned bits, uint32 *w@ */
-  BBS_WRAP,                            /* @void@ */
-  BBS_FF,                              /* @bbs_priv *p, mp *n@ */
-  BBS_FFN,                             /* @bbs_priv *p, unsigned long n@ */
-  BBS_REW,                             /* @bbs_priv *p, mp *n@ */
-  BBS_REWN,                            /* @bbs_priv *p, unsigned long n@ */
-  BBS_MOD,                             /* @mp **n@ */
-  BBS_STATE                            /* @mp **x@ */
-};
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/bin-gentab.awk b/bin-gentab.awk
deleted file mode 100755 (executable)
index fb8630e..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-#! /usr/bin/awk -f
-#
-# $Id: p-gentab.awk 2187 2004-09-04 07:50:08Z mdw $
-
-function banner(name,  s, i)
-{
-  s = "/*----- " name " ";
-  while (length(s) < 75) s = s "-";
-  return (s "*/");
-}
-
-function fix(name)
-{
-  gsub(/[^0-9A-Za-z_]+/, "_", name);
-  return (name);
-}
-
-BEGIN {
-  print "/* -*-c-*-";
-  print " *";
-  print " * Table of binary groups [generated]";
-  print " */";
-  print "";
-  print "#include \"bintab.h\"";
-  print "";
-  print "#define N(x) (sizeof(x)/sizeof(*x))";
-  print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }";
-  print "#define NOMP { 0, 0, 0, 0, 0 }";
-  print "";
-  print banner("Binary group data");
-  print "";
-
-  d_i = 0;
-  name = "";
-}
-
-function putmp(x,  d)
-{
-  if (!(x in data)) {
-    print "group " name ": missing " x >"/dev/stderr";
-    exit 1;
-  }
-  d = data[x];
-  if (!(d in cache)) {
-    n = "p_" fix(name) "_" x;
-    print "static mpw " n "[] = {";
-    system("./mpdump " d);
-    print "};";
-    print "";
-    cache[d] = n;
-  }
-  mp[x] = cache[d];
-}
-
-function flush()
-{
-  if (name == "") return;
-  print "/* --- Group " name " --- */";
-  delete mp;
-  print "";
-  putmp("p");
-  putmp("q");
-  putmp("g");
-  print "static bindata bin_" fix(name) " = {";
-  print "  MP(" mp["p"] "),"
-  print "  MP(" mp["q"] "),"
-  print "  MP(" mp["g"] ")"
-  print "};";
-  print "";
-  dname[d_i++] = name;
-  d[name] = name;
-  r[name] = "bin_" fix(name);
-  name = "";
-}
-
-/^[ \t]*(#|$)/ { next; }
-
-$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; }
-
-$1 == "group" { flush(); delete data; name = $2; next; }
-
-{ data[$1] = $2; next; }
-
-END {
-  flush();
-  print banner("Main table");
-  print "";
-  print "const binentry bintab[] = {";
-  for (i = 0; i < d_i; i++) {
-    name = dname[i];
-    rname = d[name];
-    if (!rname in r) {
-      print "group " rname " not found (alias from " name ")" >"/dev/stderr";
-      exit 1;
-    }
-    print "  { \"" name "\", &" r[rname] " },";
-  }
-  print "  { 0, 0 }";
-  print "};"
-  print "";
-  print banner("That's all, folks");
-}
diff --git a/bintab.h b/bintab.h
deleted file mode 100644 (file)
index 221d749..0000000
--- a/bintab.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Table of standard (ish) binary groups
- *
- * (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.
- */
-
-#ifndef CATACOMB_BINTAB_H
-#define CATACOMB_BINTAB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "ptab.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef pdata bindata;
-typedef pentry binentry;
-
-/*----- Global variables --------------------------------------------------*/
-
-extern const binentry bintab[];
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/bintab.in b/bintab.in
deleted file mode 100644 (file)
index debe112..0000000
--- a/bintab.in
+++ /dev/null
@@ -1,37 +0,0 @@
-# $Id$
-#
-# Standard binary groups
-
-#----- From P1363 annex A ---------------------------------------------------
-
-group p1363-40
-  p 0x200000000000000000000000000000000000000000000065
-  q 0xabbcb671934086d21ff5f7
-  g 0x66704fca38d7962439e5f9bdab4d9ac6f0dd745c72f822e
-
-group p1363-56
-  p 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100d
-  q 0x5538ed0653399777d80d50e508fd01
-  g 0x44e2fd3317b4a1968ce65b7e72f8d64262987d0a818a5a5189a6d588b67317c9ee05a38e3e5691e34933e3e050543d8b
-
-group p1363-64
-  p 0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800001
-  q 0x84b73a6a902299c1aeeb8b537f1ea87c1
-  g 0xce10e3ae38cacb7c1076723b80be855c629c03abef26d2a5ca898f75d2bd794daa9e21781f063ab2785a8c402f976d73e5c8d66072cd950dee1ea722bb8f3d
-
-group p1363-80
-  p 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080043
-  q 0x519f0cb14cf36cfcda7d08fab2b578314c9542801
-  g 0xd0f0d0046d995f82b1599c7bceb20010b2ec0d27748d113c532657584c9ea11ab6be6b7236cfafc2a087503e1ad108e559206d559e7c30f4a516da71fa3e08fc50e03084f18af4a59e9c6835beb67dfd2b47ef8d0ea30d8f65e378e9ba82819ffc0ade685fa6cb346dcecca7134893db0a6950c2beab89ee38508f03f2f1f186
-
-group p1363-112
-  p 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040481
-  q 0x399ac734bd00a6f622bdd00c5f930dcf2ae5d7c521755f7b664f104e423bddd
-  g 0x40154611e5cd5d4826382b23d4ba28fa9d050bb4db5e81b90816fa2823b62328798b70c061734b327e7e3221002a08554e4902f26c476a152380f49e7e2624066de81ef26ddabf4b2c4cc9374f60189e4e5446e04c39d1de05947c54eb6d8c63e498a83d5025ea9fcf2ff3195fb76d76cc2df73918268b72f693a28a01c14622351cc53546bdaacfc95ad19aee16d3d88fbb5fe8143a8a3dcf3d48525be95bef28921edcee081b5269d0b5307ed97f55e5d0218dd17a39f393e017fcfe999626f1fc6ae9a485395a62a3e969d2e0cce55755cc0e22c4356741313d762505c9a2594af3e94d8f913798d92ccf6a73d2447c474ed2924a29856c5c2feeb178a35b15545
-
-group p1363-128
-  p 0x1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002441
-  q 0xa5c52c0d53fc1f43b2cbfd7447d53d55c37004338502dfda0f31b7df76bde74081
-  g 0x9447bb7ca087a37a5268c9e4cd3b9c3eb752272af39657d616181d28f18634368ba972a26b93b2980b391e23d7a9313785a5a17adfd9f810a3677cc20342965e09afc81b8413c5b3054c3adffec6411f088942d5877eef220b2a01cd7c48e8bae8f394b2a0893eb293f6355fc3ea962e503ae1d6fd0c3d718de374100cf89cb9c72e125fac9f930abb9959d03ef18354dd16f3a51e42e2c43ef100a8c3ca9523e6decbdf1f67db454df5781d16d55e94663f9633985d2f76b71a9bb10a985a8c6e8cb4190bef038798e9f402ea8027698e9d28a4ee14f0a6724f38dab82578a0e9600fa5717f40d8f107cb148c896c3061945318b25436c04f84a1b0fa043417bf7904915fa6afaed5fd24c73a5a1328973f39e8bc930ccc3099d7f715f8738b13d0b113899200b2293cdba34a46d22c0fab4d8ed33a71c691ba90687000030ad2fe05b5668520e24edb37edcf43827d9cf0b96ff776f88a2041eadd6902e12428716b46533d765d
-
-#----- That's all, folks ----------------------------------------------------
diff --git a/bitops.h b/bitops.h
deleted file mode 100644 (file)
index 02f9a34..0000000
--- a/bitops.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*-c-*-
- *
- * $Id: bitops.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Bit operations by truth table
- *
- * (c) 2002 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.
- */
-
-#ifndef CATACOMB_BITOPS_H
-#define CATACOMB_BITOPS_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-#define B0000(x, y) (0u)
-#define B0001(x, y) ((x) & (y))
-#define B0010(x, y) ((x) & ~(y))
-#define B0011(x, y) (x)
-#define B0100(x, y) (~(x) & (y))
-#define B0101(x, y) (y)
-#define B0110(x, y) ((x) ^ (y))
-#define B0111(x, y) ((x) | (y))
-#define B1000(x, y) (~((x) | (y)))
-#define B1001(x, y) (~((x) ^ (y)))
-#define B1010(x, y) (~(y))
-#define B1011(x, y) ((x) | ~(y))
-#define B1100(x, y) (~(x))
-#define B1101(x, y) (~(x) | (y))
-#define B1110(x, y) (~((x) & (y)))
-#define B1111(x, y) (~0u)
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/bittest.c b/bittest.c
deleted file mode 100644 (file)
index f13d358..0000000
--- a/bittest.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*-c-*-
- *
- * $Id: bittest.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Check the bit operations work
- *
- * (c) 2002 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <string.h>
-#include "bitops.h"
-#include "mpx.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-int main(void)
-{
-  int rc = 0;
-#define CHECK(string) do {                                             \
-  const char *ref = #string;                                           \
-  char buf[5];                                                         \
-  buf[0] = B##string(0u, 0u) & 1u? '1' : '0';                          \
-  buf[1] = B##string(0u, 1u) & 1u? '1' : '0';                          \
-  buf[2] = B##string(1u, 0u) & 1u? '1' : '0';                          \
-  buf[3] = B##string(1u, 1u) & 1u? '1' : '0';                          \
-  buf[4] = 0;                                                          \
-  if (strcmp(buf, ref) != 0) {                                         \
-    fprintf(stderr, "mismatch ref `%s' != buf `%s'\n", ref, buf);      \
-    rc = 1;                                                            \
-  }                                                                    \
-} while (0);
-  MPX_DOBIN(CHECK)
-  return (rc);
-}
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/blkc.h b/blkc.h
deleted file mode 100644 (file)
index d95c4f9..0000000
--- a/blkc.h
+++ /dev/null
@@ -1,347 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Common definitions for block ciphers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_BLKC_H
-#define CATACOMB_BLKC_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-
-#include <mLib/bits.h>
-
-/*----- Theory of operation -----------------------------------------------*
- *
- * A block cipher has associated with it a triple, called PRE_CLASS, of the
- * form `(TYPE, ENDIAN, BITS)', where TYPE is either `N' (representing an
- * implemented bit size) or `X' (representing an unimplemented bit size,
- * causing loops to be compiled rather than unrolled code), ENDIAN is `B'
- * (big) or `L' (little), and BITS is the block size of the cipher in bits.
- */
-
-/*----- Data movement macros ----------------------------------------------*/
-
-/*
- * `The C preprocessor.  You will never find a more wretched hive of bogus
- * hackery.  We must be cautious.'
- */
-
-/* --- General dispatch macros --- */
-
-#define BLKC_DOGLUE(x, y) x ## y
-#define BLKC_GLUE(x, y) BLKC_DOGLUE(x, y)
-#define BLKC_APPLY(f, x) f x
-#define BLKC_FIRST(x, y, z) x
-#define BLKC_SECOND(x, y, z) y
-#define BLKC_THIRD(x, y, z) z
-#define BLKC_TYPE(PRE) BLKC_APPLY(BLKC_FIRST, PRE##_CLASS)
-#define BLKC_ENDIAN(PRE) BLKC_APPLY(BLKC_SECOND, PRE##_CLASS)
-#define BLKC_BITS(PRE) BLKC_APPLY(BLKC_THIRD, PRE##_CLASS)
-
-#define BLKC_STORE_E(PRE) BLKC_GLUE(STORE32_, BLKC_ENDIAN(PRE))
-#define BLKC_LOAD_E(PRE) BLKC_GLUE(LOAD32_, BLKC_ENDIAN(PRE))
-
-/* --- Interface macros --- */
-
-#define BLKC_STORE(PRE, b, w)                                          \
-  BLKC_GLUE(BLKC_STORE_, BLKC_TYPE(PRE))                               \
-    (PRE, b, w, BLKC_STORE_E(PRE), BLKC_BITS(PRE))
-
-#define BLKC_XSTORE(PRE, b, w, wx)                                     \
-  BLKC_GLUE(BLKC_XSTORE_, BLKC_TYPE(PRE))                              \
-    (PRE, b, w, wx, BLKC_STORE_E(PRE), BLKC_BITS(PRE))
-
-#define BLKC_LOAD(PRE, w, b)                                           \
-  BLKC_GLUE(BLKC_LOAD_, BLKC_TYPE(PRE))                                        \
-    (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE))
-
-#define BLKC_XLOAD(PRE, w, b)                                          \
-  BLKC_GLUE(BLKC_XLOAD_, BLKC_TYPE(PRE))                               \
-    (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE))
-
-#define BLKC_MOVE(PRE, w, wx)                                          \
-  BLKC_GLUE(BLKC_MOVE_, BLKC_TYPE(PRE))                                        \
-    (PRE, w, wx, BLKC_BITS(PRE))
-
-#define BLKC_XMOVE(PRE, w, wx)                                         \
-  BLKC_GLUE(BLKC_XMOVE_, BLKC_TYPE(PRE))                               \
-    (PRE, w, wx, BLKC_BITS(PRE))
-
-#define BLKC_STEP(PRE, w)                                              \
-  BLKC_GLUE(BLKC_STEP_X_, BLKC_ENDIAN(PRE))                            \
-    (PRE, w)
-
-#define BLKC_ZERO(PRE, w)                                              \
-  BLKC_GLUE(BLKC_ZERO_, BLKC_TYPE(PRE))                                        \
-    (PRE, w, BLKC_BITS(PRE))
-
-#define BLKC_SET(PRE, w, x)                                            \
-  BLKC_GLUE(BLKC_SET_X_, BLKC_ENDIAN(PRE))                             \
-    (PRE, w, x)
-
-#define BLKC_SHOW(PRE, tag, w) do {                                    \
-  fputs(tag ": ", stdout);                                             \
-  BLKC_SKEL_X(PRE, BLKC_W(w);, printf("%08x ", *_w++););               \
-  fputc('\n', stdout);                                                 \
-} while (0)
-
-/* --- General implementation skeleton --- */
-
-#define BLKC_SKEL(PRE, decl, guts) do {                                        \
-  decl                                                                 \
-  guts                                                                 \
-} while (0)
-
-#define BLKC_P(p) register octet *_p = (octet *)(p)
-#define BLKC_W(w) register uint32 *_w = (w)
-#define BLKC_WX(wx) register uint32 *_wx = (wx)
-
-/* --- Implementation for unusual block sizes --- */
-
-#define BLKC_SKEL_X(PRE, decl, guts)                                   \
-  BLKC_SKEL(PRE, unsigned _i; decl,                                    \
-           for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) {                  \
-             guts                                                      \
-           })
-
-#define BLKC_STORE_X(PRE, b, w, op, n)                                 \
-  BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w);,                                \
-             op(_p, *_w); _p += 4; _w++; )
-
-#define BLKC_XSTORE_X(PRE, b, w, wx, op, n)                            \
-  BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);,     \
-             op(_p, *_w ^ *_wx); _p += 4; _w++; _wx++; )
-
-#define BLKC_LOAD_X(PRE, w, b, op, n)                                  \
-  BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);,                                \
-             *_w = op(_p); _p += 4; _w++; )
-
-#define BLKC_XLOAD_X(PRE, w, b, op, n)                                 \
-  BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);,                                \
-             *_w ^= op(_p); _p += 4; _w++; )
-
-#define BLKC_MOVE_X(PRE, w, wx, n)                                     \
-  BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);,                      \
-             *_w = *_wx; _w++; _wx++; )                                \
-
-#define BLKC_XMOVE_X(PRE, w, wx, n)                                    \
-  BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);,                      \
-             *_w ^= *_wx; _w++; _wx++; )                               \
-
-#define BLKC_ZERO_X(PRE, w, n)                                         \
-  BLKC_SKEL_X(PRE, BLKC_W(w);, *_w++ = 0;)
-
-#define BLKC_STEP_X_B(PRE, w) do {                                     \
-  unsigned _i = PRE##_BLKSZ / 4; BLKC_W(w); uint32 _x = 0;             \
-  while (_i && !_x) { _i--; _w[_i] = _x = U32(_w[_i] + 1); }           \
-} while (0)
-
-#define BLKC_STEP_X_L(PRE, w) do {                                     \
-  unsigned _i = 0; BLKC_W(w); uint32 _x = 0;                           \
-  while (_i < PRE##_BLKSZ / 4 && !_x)                                  \
-    { _w[_i] = _x = U32(_w[_i] + 1); _i++; }                           \
-} while (0)
-
-#define BLKC_SET_X_B(PRE, w, x) do {                                   \
-  unsigned _i; BLKC_W(w); unsigned long _x = x;                                \
-  for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) {                           \
-    *_w++ = U32(_x);                                                   \
-    _x = ((_x & ~MASK32) >> 16) >> 16;                                 \
-  }                                                                    \
-} while (0)
-
-#define BLKC_SET_X_L(PRE, w, x) do {                                   \
-  unsigned _i; BLKC_W(w); unsigned long _x = x;        _w += PRE##_BLKSZ / 4;  \
-  for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) {                           \
-    *--_w = U32(_x);                                                   \
-    _x = ((_x & ~MASK32) >> 16) >> 16;                                 \
-  }                                                                    \
-} while (0)
-
-/* --- Implementation for known block sizes --- */
-
-#define BLKC_SKEL_64(PRE, decl, op, guts)                              \
-  BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1);)
-
-#define BLKC_SKEL_96(PRE, decl, op, guts)                              \
-  BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2);)
-
-#define BLKC_SKEL_128(PRE, decl, op, guts)                             \
-  BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);)
-
-#define BLKC_SKEL_192(PRE, decl, op, guts)                             \
-  BLKC_SKEL(PRE, decl,                                                 \
-           guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);         \
-           guts(op, 4); guts(op, 5);)
-
-#define BLKC_SKEL_256(PRE, decl, op, guts)                             \
-  BLKC_SKEL(PRE, decl,                                                 \
-           guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);         \
-           guts(op, 4); guts(op, 5); guts(op, 6); guts(op, 7);)
-
-#define BLKC_STORE_GUTS(op, i) op(_p + 4 * i, _w[i])
-#define BLKC_XSTORE_GUTS(op, i) op(_p + 4 * i, _w[i] ^ _wx[i])
-#define BLKC_LOAD_GUTS(op, i) _w[i] = op(_p + 4 * i)
-#define BLKC_XLOAD_GUTS(op, i) _w[i] ^= op(_p + 4 * i)
-#define BLKC_MOVE_GUTS(op, i) _w[i] = _wx[i]
-#define BLKC_XMOVE_GUTS(op, i) _w[i] ^= _wx[i]
-#define BLKC_ZERO_GUTS(op, i) _w[i] = 0
-
-#define BLKC_STORE_N(PRE, b, w, op, n)                                 \
-  BLKC_GLUE(BLKC_SKEL_, n)                                             \
-    (PRE, BLKC_P(b); const BLKC_W(w);, op, BLKC_STORE_GUTS)
-
-#define BLKC_XSTORE_N(PRE, b, w, wx, op, n)                            \
-  BLKC_GLUE(BLKC_SKEL_, n)                                             \
-    (PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);,              \
-     op, BLKC_XSTORE_GUTS)
-
-#define BLKC_LOAD_N(PRE, w, b, op, n)                                  \
-  BLKC_GLUE(BLKC_SKEL_, n)                                             \
-    (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_LOAD_GUTS)
-
-#define BLKC_XLOAD_N(PRE, w, b, op, n)                                 \
-  BLKC_GLUE(BLKC_SKEL_, n)                                             \
-    (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_XLOAD_GUTS)
-
-#define BLKC_MOVE_N(PRE, w, wx, n)                                     \
-  BLKC_GLUE(BLKC_SKEL_, n)                                             \
-    (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_MOVE_GUTS)
-
-#define BLKC_ZERO_N(PRE, w, n)                                         \
-  BLKC_GLUE(BLKC_SKEL_, n)                                             \
-    (PRE, BLKC_W(w); , op, BLKC_ZERO_GUTS)
-
-#define BLKC_XMOVE_N(PRE, w, wx, n)                                    \
-  BLKC_GLUE(BLKC_SKEL_, n)                                             \
-    (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_XMOVE_GUTS)
-
-/*----- Test rig for block ciphers ----------------------------------------*/
-
-/* --- @BLKC_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for cipher-specific definitions
- *
- * Use:                Standard test rig for block ciphers.
- */
-
-#ifdef TEST_RIG
-
-#include <string.h>
-
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#define BLKC_VERIFY(PRE, pre)                                          \
-                                                                       \
-static int pre##_verify(dstr *v)                                       \
-{                                                                      \
-  pre##_ctx k;                                                         \
-  uint32 p[PRE##_BLKSZ / 4];                                           \
-  uint32 c[PRE##_BLKSZ / 4];                                           \
-  uint32 d[PRE##_BLKSZ / 4];                                           \
-  dstr b = DSTR_INIT;                                                  \
-  int ok = 1;                                                          \
-                                                                       \
-  /* --- Initialize the key buffer --- */                              \
-                                                                       \
-  dstr_ensure(&b, PRE##_BLKSZ);                                                \
-  b.len = PRE##_BLKSZ;                                                 \
-  pre##_init(&k, v[0].buf, v[0].len);                                  \
-  BLKC_LOAD(PRE, p, v[1].buf);                                         \
-  BLKC_LOAD(PRE, c, v[2].buf);                                         \
-                                                                       \
-  /* --- Test encryption --- */                                                \
-                                                                       \
-  BLKC_MOVE(PRE, d, p);                                                        \
-  pre##_eblk(&k, d, d);                                                        \
-  BLKC_STORE(PRE, b.buf, d);                                           \
-  if (memcmp(b.buf, v[2].buf, PRE##_BLKSZ)) {                          \
-    ok = 0;                                                            \
-    printf("\nfail encryption:"                                                \
-          "\n\tkey        = ");                                        \
-    type_hex.dump(&v[0], stdout);                                      \
-    printf("\n\tplaintext  = "); type_hex.dump(&v[1], stdout);         \
-    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);         \
-    printf("\n\tcalculated = "); type_hex.dump(&b, stdout);            \
-    putchar('\n');                                                     \
-  }                                                                    \
-                                                                       \
-  /* --- Test decryption --- */                                                \
-                                                                       \
-  BLKC_MOVE(PRE, d, c);                                                        \
-  pre##_dblk(&k, d, d);                                                        \
-  BLKC_STORE(PRE, b.buf, d);                                           \
-  if (memcmp(b.buf, v[1].buf, PRE##_BLKSZ)) {                          \
-    ok = 0;                                                            \
-    printf("\nfail decryption:"                                                \
-          "\n\tkey        = ");                                        \
-    type_hex.dump(&v[0], stdout);                                      \
-    printf("\n\tciphertext = "); type_hex.dump(&v[2], stdout);         \
-    printf("\n\texpected   = "); type_hex.dump(&v[1], stdout);         \
-    printf("\n\tcalculated = "); type_hex.dump(&b, stdout);            \
-    putchar('\n');                                                     \
-  }                                                                    \
-                                                                       \
-  /* --- Return --- */                                                 \
-                                                                       \
-  return (ok);                                                         \
-}
-
-#define BLKC_TEST(PRE, pre)                                            \
-                                                                       \
-BLKC_VERIFY(PRE, pre)                                                  \
-                                                                       \
-static const test_chunk defs[] = {                                     \
-  { #pre, pre##_verify, { &type_hex, &type_hex, &type_hex, 0 } },      \
-  { 0, 0, { 0 } }                                                      \
-};                                                                     \
-                                                                       \
-int main(int argc, char *argv[])                                       \
-{                                                                      \
-  test_run(argc, argv, defs, SRCDIR"/tests/" #pre);                    \
-  return (0);                                                          \
-}
-
-#else
-#  define BLKC_VERIFY(PRE, pre)
-#  define BLKC_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/blowfish-mktab.c b/blowfish-mktab.c
deleted file mode 100644 (file)
index 9d6fcb2..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/* -*-c-*-
- *
- * $Id: blowfish-mktab.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Build Blowfish key table
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/bits.h>
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @spigot@ --- *
- *
- * Arguments:  @uint32 *buf@ = pointer to the output buffer
- *             @size_t n@ = number of output digits wanted
- *
- * Returns:    ---
- *
- * Use:                Writes digits of %$\pi$% to the given array.  The algorithm
- *             is based on the Spigot algorithm by Stanley Rabinowitz and
- *             Stan Wagon, published in Amer.Math.Monthly, March 1995, with
- *             bug fixes by C. Haenel.  I then bodged it to output hex
- *             digits rather than decimal ones, and to leave off the initial
- *             `3'.
- *
- *             I've not analysed the algorithm very much.
- */
-
-#define SPIGOT_WORDS (18 + 4 * 256ul)
-#define SPIGOT_BITS 8
-#define SPIGOT_RADIX (1ul << SPIGOT_BITS)
-#define SPIGOT_BUFLEN (SPIGOT_WORDS * 32)
-
-#ifdef QUIET
-#  define Q(x)
-#else
-#  define Q(x) x
-#endif
-
-static void spigot(uint32 *buf, size_t n)
-{
-  uint32 acc = 0;
-  int b = -1;
-  unsigned a[SPIGOT_BUFLEN] = { 0 };
-  uint32 p = 0;
-  unsigned f = 0;
-  unsigned max = 32 * n;
-  Q( size_t step = n / 60; )
-
-  Q( fputs("[                                                         ]\r[",
-          stderr); )
-
-#define EMIT(z) do {                                                   \
-  if (b == -1)                                                         \
-    b = 0;                                                             \
-  else {                                                               \
-    acc = (acc << SPIGOT_BITS) | (z);                                  \
-    b += SPIGOT_BITS;                                                  \
-    if (b == 32) {                                                     \
-      *buf++ = acc;                                                    \
-      acc = 0;                                                         \
-      b = 0;                                                           \
-      n--;                                                             \
-      if (!n)                                                          \
-       goto done;                                                      \
-      Q( if (n % step == 0)                                            \
-          fputc('.', stderr); )                                        \
-    }                                                                  \
-  }                                                                    \
-} while (0)
-
-  while (n) {
-    uint32 q = 0;
-    uint32 i;
-    uint32 x = 0;
-    uint32 k = max * 2 - 1;
-
-    for (i = max; i; i--) {
-      x = (b == -1 ? SPIGOT_RADIX * 2 : a[i - 1] << SPIGOT_BITS) + q * i;
-      q = x / k;
-      a[i - 1] = x - q * k;
-      k -= 2;
-    }
-
-    k = x & (SPIGOT_RADIX - 1);
-    if (k == SPIGOT_RADIX - 1)
-      f++;
-    else {
-      EMIT(p + (x >> SPIGOT_BITS));
-      if (f) {
-       unsigned d = (x >= SPIGOT_RADIX ? 0 : SPIGOT_RADIX - 1);
-       while (f) {
-         EMIT(d);
-         f--;
-       }
-      }
-      p = k;
-    }
-  }
-
-done:;
-  Q( fputc('\n', stderr); )
-
-#undef EMIT
-}
-
-/* --- @main@ --- */
-
-int main(void)
-{
-  uint32 dbuf[SPIGOT_WORDS];
-  int i, j;
-  uint32 *d = dbuf;
-
-  spigot(d, SPIGOT_WORDS);
-
-  fputs("\
-/* -*-c-*-\n\
- *\n\
- * Blowfish initial key table [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_BLOWFISH_TAB_H\n\
-#define CATACOMB_BLOWFISH_TAB_H\n\
-\n\
-#define BLOWFISH_IKEY {                                                        \\\n\
-  { ", stdout);
-
-  for (i = 0; i < 18; i++) {
-    printf("0x%08x", *d++);
-    if (i == 17)
-      fputs(" },                                               \\\n\
-                                                                       \\\n\
-  { ", stdout);
-    else if (i % 4 == 3)
-      fputs(",                 \\\n    ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-    printf("0x%08x", *d++);
-    if (i == 255) {
-      if (j == 3)
-       fputs(" }                       \\\n}\n\n#endif\n", stdout);
-      else
-       fputs(" },                      \\\n\
-                                                                       \\\n\
-  { ", stdout);
-    } else if (i % 4 == 3)
-      fputs(",                 \\\n    ", stdout);
-    else
-      fputs(", ", stdout);
-    }
-  }
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/blowfish.c b/blowfish.c
deleted file mode 100644 (file)
index 2750cfb..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/* -*-c-*-
- *
- * $Id: blowfish.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The Blowfish block cipher
- *
- * (c) 1998 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "blowfish.h"
-#include "blowfish-tab.h"
-#include "blkc.h"
-#include "gcipher.h"
-#include "paranoia.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-static const blowfish_ctx ikey = BLOWFISH_IKEY;
-
-const octet blowfish_keysz[] = { KSZ_RANGE, BLOWFISH_KEYSZ, 1, 56, 1 };
-
-/*----- Macros ------------------------------------------------------------*/
-
-#define ROUND(k, x, y, r) do {                                         \
-  x ^= *r;                                                             \
-  y ^= ((k->s0[U8(x >> 24)] +                                          \
-        k->s1[U8(x >> 16)]) ^                                          \
-        k->s2[U8(x >>  8)]) +                                          \
-        k->s3[U8(x >>  0)];                                            \
-} while (0)
-
-#define EBLK(k, a, b, c, d) do {                                       \
-  const uint32 *_r = k->p;                                             \
-  uint32 _x = a;                                                       \
-  uint32 _y = b;                                                       \
-  ROUND(k, _x, _y, _r++);                                              \
-  ROUND(k, _y, _x, _r++);                                              \
-  ROUND(k, _x, _y, _r++);                                              \
-  ROUND(k, _y, _x, _r++);                                              \
-  ROUND(k, _x, _y, _r++);                                              \
-  ROUND(k, _y, _x, _r++);                                              \
-  ROUND(k, _x, _y, _r++);                                              \
-  ROUND(k, _y, _x, _r++);                                              \
-  ROUND(k, _x, _y, _r++);                                              \
-  ROUND(k, _y, _x, _r++);                                              \
-  ROUND(k, _x, _y, _r++);                                              \
-  ROUND(k, _y, _x, _r++);                                              \
-  ROUND(k, _x, _y, _r++);                                              \
-  ROUND(k, _y, _x, _r++);                                              \
-  ROUND(k, _x, _y, _r++);                                              \
-  ROUND(k, _y, _x, _r++);                                              \
-  c = _y ^ k->p[17];                                                   \
-  d = _x ^ k->p[16];                                                   \
-} while (0)
-
-#define DBLK(k, a, b, c, d) do {                                       \
-  const uint32 *_r = k->p + 18;                                                \
-  uint32 _x = a;                                                       \
-  uint32 _y = b;                                                       \
-  ROUND(k, _x, _y, --_r);                                              \
-  ROUND(k, _y, _x, --_r);                                              \
-  ROUND(k, _x, _y, --_r);                                              \
-  ROUND(k, _y, _x, --_r);                                              \
-  ROUND(k, _x, _y, --_r);                                              \
-  ROUND(k, _y, _x, --_r);                                              \
-  ROUND(k, _x, _y, --_r);                                              \
-  ROUND(k, _y, _x, --_r);                                              \
-  ROUND(k, _x, _y, --_r);                                              \
-  ROUND(k, _y, _x, --_r);                                              \
-  ROUND(k, _x, _y, --_r);                                              \
-  ROUND(k, _y, _x, --_r);                                              \
-  ROUND(k, _x, _y, --_r);                                              \
-  ROUND(k, _y, _x, --_r);                                              \
-  ROUND(k, _x, _y, --_r);                                              \
-  ROUND(k, _y, _x, --_r);                                              \
-  c = _y ^ k->p[0];                                                    \
-  d = _x ^ k->p[1];                                                    \
-} while (0)
-
-/*----- Low-level encryption interface ------------------------------------*/
-
-/* --- @blowfish_init@ --- *
- *
- * Arguments:  @blowfish_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Blowfish key buffer.  Blowfish accepts
- *             a more-or-less arbitrary size key.
- */
-
-void blowfish_init(blowfish_ctx *k, const void *buf, size_t sz)
-{
-  KSZ_ASSERT(blowfish, sz);
-
-  /* --- Copy the initial value over --- */
-
-  memcpy(k, &ikey, sizeof(ikey));
-
-  /* --- Initialize the %$P$% array --- */
-
-  {
-    const octet *p = buf;
-    const octet *q = p + sz;
-    int i = 0, j = 0;
-    uint32 x = 0;
-
-    while (i < 18) {
-      x = (x << 8) | U8(*p++);
-      if (p >= q)
-       p = buf;
-      if (++j >= 4) {
-       k->p[i++] ^= x;
-       x = 0;
-       j = 0;
-      }
-    }
-
-    x = 0;
-  }
-
-  /* --- Now mangle the complete array of keys --- */
-
-  {
-    uint32 b[2];
-    int i;
-
-    b[0] = b[1] = 0;
-
-    for (i = 0; i < 18; i += 2) {
-      blowfish_eblk(k, b, b);
-      k->p[i] = b[0]; k->p[i + 1] = b[1];
-    }
-
-    for (i = 0; i < 256; i += 2) {
-      blowfish_eblk(k, b, b);
-      k->s0[i] = b[0]; k->s0[i + 1] = b[1];
-    }
-
-    for (i = 0; i < 256; i += 2) {
-      blowfish_eblk(k, b, b);
-      k->s1[i] = b[0]; k->s1[i + 1] = b[1];
-    }
-
-    for (i = 0; i < 256; i += 2) {
-      blowfish_eblk(k, b, b);
-      k->s2[i] = b[0]; k->s2[i + 1] = b[1];
-    }
-
-    for (i = 0; i < 256; i += 2) {
-      blowfish_eblk(k, b, b);
-      k->s3[i] = b[0]; k->s3[i + 1] = b[1];
-    }
-
-    BURN(b);
-  }
-}
-
-/* --- @blowfish_eblk@, @blowfish_dblk@ --- *
- *
- * Arguments:  @const blowfish_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-void blowfish_eblk(const blowfish_ctx *k, const uint32 *s, uint32 *d)
-{
-  EBLK(k, s[0], s[1], d[0], d[1]);
-}
-
-void blowfish_dblk(const blowfish_ctx *k, const uint32 *s, uint32 *d)
-{
-  DBLK(k, s[0], s[1], d[0], d[1]);
-}
-
-BLKC_TEST(BLOWFISH, blowfish)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/blowfish.h b/blowfish.h
deleted file mode 100644 (file)
index a9ece5e..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* -*-c-*-
- *
- * $Id: blowfish.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The Blowfish block cipher
- *
- * (c) 1998 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.
- */
-
-/*----- Notes on the Blowfish block cipher --------------------------------*
- *
- * Blowfish was invented by Bruce Schneier.  The algorithm is unpatented and
- * free for anyone to use.  It's fast, simple, offers a big key, and is
- * looking relatively bulletproof.  It's also this author's block cipher of
- * choice, for what little that's worth.  The disadvantage is that Blowfish
- * has a particularly heavyweight key schedule.
- */
-
-#ifndef CATACOMB_BLOWFISH_H
-#define CATACOMB_BLOWFISH_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define BLOWFISH_BLKSZ 8
-#define BLOWFISH_KEYSZ 32
-#define BLOWFISH_CLASS (N, B, 64)
-
-extern const octet blowfish_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct blowfish_ctx {
-  uint32 p[18];
-  uint32 s0[256], s1[256], s2[256], s3[256];
-} blowfish_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @blowfish_init@ --- *
- *
- * Arguments:  @blowfish_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Blowfish key buffer.  Blowfish accepts
- *             a more-or-less arbitrary size key.
- */
-
-extern void blowfish_init(blowfish_ctx */*k*/,
-                         const void */*buf*/, size_t /*sz*/);
-
-/* --- @blowfish_eblk@, @blowfish_dblk@ --- *
- *
- * Arguments:  @const blowfish_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void blowfish_eblk(const blowfish_ctx */*k*/,
-                         const uint32 */*s*/, uint32 */*d*/);
-
-extern void blowfish_dblk(const blowfish_ctx */*k*/,
-                         const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/buf.c b/buf.c
deleted file mode 100644 (file)
index 0cf2cf0..0000000
--- a/buf.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Buffer handling
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include "mp.h"
-#include "ec.h"
-#include "buf.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @buf_getmp@ --- *
- *
- * Arguments:  @buf *b@ = pointer to a buffer block
- *
- * Returns:    A multiprecision integer, or null if there wasn't one there.
- *
- * Use:                Gets a multiprecision integer from a buffer.
- */
-
-mp *buf_getmp(buf *b)
-{
-  uint16 sz;
-  size_t n;
-  mp *m;
-  if (buf_getu16(b, &sz) || buf_ensure(b, sz))
-    return (0);
-  m = mp_loadb(MP_NEW, BCUR(b), sz);
-  n = mp_octets(m);
-  if (n != sz && n != 0 && sz != 1) {
-    mp_drop(m);
-    return (0);
-  }
-  BSTEP(b, sz);
-  return (m);
-}
-
-/* --- @buf_putmp@ --- *
- *
- * Arguments:  @buf *b@ = pointer to a buffer block
- *             @mp *m@ = a multiprecision integer
- *
- * Returns:    Zero if it worked, nonzero if there wasn't enough space.
- *
- * Use:                Puts a multiprecision integer to a buffer.
- */
-
-int buf_putmp(buf *b, mp *m)
-{
-  size_t sz = mp_octets(m);
-  assert(sz < MASK16);
-  if (!sz) sz = 1;
-  if (buf_putu16(b, sz) || buf_ensure(b, sz))
-    return (-1);
-  mp_storeb(m, BCUR(b), sz);
-  BSTEP(b, sz);
-  return (0);
-}
-
-/* --- @buf_getec@ --- *
- *
- * Arguments:  @buf *b@ = pointer to a buffer block
- *             @ec *p@ = where to put the point
- *
- * Returns:    Zero if it worked, nonzero if it failed.
- *
- * Use:                Gets a multiprecision integer from a buffer.  The point must
- *             be initialized.
- */
-
-int buf_getec(buf *b, ec *p)
-{
-  mp *x = 0, *y = 0;
-  uint16 n;
-  if (buf_ensure(b, 2)) return (-1);
-  n = LOAD16(BCUR(b)); if (!n) { BSTEP(b, 2); EC_SETINF(p); return (0); }
-  if ((x = buf_getmp(b)) == 0 || (y = buf_getmp(b)) == 0) {
-    mp_drop(x); mp_drop(y); return (-1);
-  }
-  EC_DESTROY(p); p->x = x; p->y = y; p->z = 0;
-  return (0);
-}
-
-/* --- @buf_putec@ --- *
- *
- * Arguments:  @buf *b@ = pointer to a buffer block
- *             @ec *p@ = an elliptic curve point
- *
- * Returns:    Zero if it worked, nonzero if there wasn't enough space.
- *
- * Use:                Puts an elliptic curve point to a buffer.
- */
-
-int buf_putec(buf *b, ec *p)
-{
-  if (EC_ATINF(p)) return (buf_putu16(b, 0));
-  if (buf_putmp(b, p->x) || buf_putmp(b, p->y)) return (-1);
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/buf.h b/buf.h
deleted file mode 100644 (file)
index 065db07..0000000
--- a/buf.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Reading and writing packet buffers
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_BUF_H
-#define CATACOMB_BUF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-#include <mLib/buf.h>
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_EC_H
-#  include "ec.h"
-#endif
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @buf_getmp@ --- *
- *
- * Arguments:  @buf *b@ = pointer to a buffer block
- *
- * Returns:    A multiprecision integer, or null if there wasn't one there.
- *
- * Use:                Gets a multiprecision integer from a buffer.
- */
-
-extern mp *buf_getmp(buf */*b*/);
-
-/* --- @buf_putmp@ --- *
- *
- * Arguments:  @buf *b@ = pointer to a buffer block
- *             @mp *m@ = a multiprecision integer
- *
- * Returns:    Zero if it worked, nonzero if there wasn't enough space.
- *
- * Use:                Puts a multiprecision integer to a buffer.
- */
-
-extern int buf_putmp(buf */*b*/, mp */*m*/);
-
-/* --- @buf_getec@ --- *
- *
- * Arguments:  @buf *b@ = pointer to a buffer block
- *             @ec *p@ = where to put the point
- *
- * Returns:    Zero if it worked, nonzero if it failed.
- *
- * Use:                Gets a multiprecision integer from a buffer.  The point must
- *             be initialized.
- */
-
-extern int buf_getec(buf */*b*/, ec */*p*/);
-
-/* --- @buf_putec@ --- *
- *
- * Arguments:  @buf *b@ = pointer to a buffer block
- *             @ec *p@ = an elliptic curve point
- *
- * Returns:    Zero if it worked, nonzero if there wasn't enough space.
- *
- * Use:                Puts an elliptic curve point to a buffer.
- */
-
-extern int buf_putec(buf */*b*/, ec */*p*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
index 50aabee..77af12e 100755 (executable)
@@ -1,2 +1,2 @@
 #! /bin/sh -ex
-if [ ! -r modes.am ]; then touch -t197001010000.00 modes.am; fi
+if [ ! -r symm/modes.am ]; then touch -t197001010000.00 symm/modes.am; fi
index e43c61b..3a37330 100644 (file)
@@ -1,7 +1,5 @@
 /* -*-apcalc-*-
  *
- * $Id: ec2.cal,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
  * Testbed for elliptic curve arithmetic over binary fields
  *
  * (c) 2004 Straylight/Edgeware
index 4fedccf..700b18f 100644 (file)
@@ -1,7 +1,5 @@
 /* -*-apcalc-*-
  *
- * $Id: ecp.cal,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
  * Testbed for elliptic curve arithmetic over prime fields
  *
  * (c) 2000 Straylight/Edgeware
index 3a5804f..1c2d4c6 100644 (file)
@@ -1,7 +1,5 @@
 /* -*-apcalc-*-
  *
- * $Id: gfx-test.cal,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
  * Generate test cases for %$\gf{2}[x]$% arithmetic
  *
  * (c) 2000 Straylight/Edgeware
index 01d5c10..f898c45 100644 (file)
@@ -1,7 +1,5 @@
 /* -*-apcalc-*-
  *
- * $Id: gfx.cal,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
  * Testbed for %$\gf{2}$% poltnomial arithmetic
  *
  * (c) 2000 Straylight/Edgeware
diff --git a/cast-base.h b/cast-base.h
deleted file mode 100644 (file)
index 36cd42b..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cast-base.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Basic macros and definitions for CAST-128 and CAST-256
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_CAST_BASE_H
-#define CATACOMB_CAST_BASE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Round functions ---------------------------------------------------*/
-
-#define CAST_R_guts(km, kr, xx, yy, aop, bop, cop) do {                        \
-  uint32 i = km aop yy;                                                        \
-  unsigned _r = kr;                                                    \
-  i = ROL32(i, _r);                                                    \
-  xx ^= ((cast_s[0][U8(i >> 24)] bop                                   \
-         cast_s[1][U8(i >> 16)]) cop                                   \
-         cast_s[2][U8(i >>  8)]) aop                                   \
-         cast_s[3][U8(i >>  0)];                                       \
-} while (0)
-
-#define CAST_R1(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, +, ^, -)
-#define CAST_R2(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, ^, -, +)
-#define CAST_R3(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, -, +, ^)
-
-/*----- Global variables --------------------------------------------------*/
-
-extern const uint32 cast_s[4][256], cast_sk[4][256];
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/cast-s.c b/cast-s.c
deleted file mode 100644 (file)
index e9b1e6a..0000000
--- a/cast-s.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cast-s.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Basic S-boxes for CAST-128 and CAST-256
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "cast-base.h"
-#include "cast-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const uint32 cast_s[4][256] = CAST_S;
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cast-sk.c b/cast-sk.c
deleted file mode 100644 (file)
index 25210b7..0000000
--- a/cast-sk.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cast-sk.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Key-schedule S-boxes for CAST-128
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "cast-base.h"
-#include "cast-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const uint32 cast_sk[4][256] = CAST_SK;
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cast-tab.h b/cast-tab.h
deleted file mode 100644 (file)
index 6155f92..0000000
+++ /dev/null
@@ -1,569 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cast-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * S-boxes for CAST-128 and CAST-256
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_CAST_TAB_H
-#define CATACOMB_CAST_TAB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- S-box tables ------------------------------------------------------*/
-
-#define CAST_S {                                                       \
-  { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a,                    \
-    0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,                    \
-    0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675,                    \
-    0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,                    \
-    0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2,                    \
-    0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,                    \
-    0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f,                    \
-    0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,                    \
-    0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de,                    \
-    0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,                    \
-    0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f,                    \
-    0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,                    \
-    0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d,                    \
-    0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,                    \
-    0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165,                    \
-    0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,                    \
-    0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272,                    \
-    0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,                    \
-    0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d,                    \
-    0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,                    \
-    0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a,                    \
-    0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,                    \
-    0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f,                    \
-    0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,                    \
-    0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9,                    \
-    0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,                    \
-    0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6,                    \
-    0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,                    \
-    0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9,                    \
-    0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,                    \
-    0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e,                    \
-    0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,                    \
-    0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e,                    \
-    0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,                    \
-    0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82,                    \
-    0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,                    \
-    0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac,                    \
-    0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,                    \
-    0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f,                    \
-    0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,                    \
-    0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491,                    \
-    0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,                    \
-    0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de,                    \
-    0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,                    \
-    0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a,                    \
-    0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,                    \
-    0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79,                    \
-    0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,                    \
-    0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779,                    \
-    0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,                    \
-    0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755,                    \
-    0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,                    \
-    0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb,                    \
-    0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,                    \
-    0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0,                    \
-    0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,                    \
-    0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79,                    \
-    0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,                    \
-    0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298,                    \
-    0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,                    \
-    0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571,                    \
-    0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,                    \
-    0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d,                    \
-    0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf },                  \
-                                                                       \
-  { 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380,                    \
-    0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,                    \
-    0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba,                    \
-    0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,                    \
-    0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909,                    \
-    0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,                    \
-    0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b,                    \
-    0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,                    \
-    0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4,                    \
-    0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,                    \
-    0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f,                    \
-    0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,                    \
-    0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21,                    \
-    0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,                    \
-    0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d,                    \
-    0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,                    \
-    0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f,                    \
-    0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,                    \
-    0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d,                    \
-    0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,                    \
-    0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4,                    \
-    0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,                    \
-    0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801,                    \
-    0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,                    \
-    0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755,                    \
-    0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,                    \
-    0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709,                    \
-    0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,                    \
-    0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b,                    \
-    0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,                    \
-    0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c,                    \
-    0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,                    \
-    0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9,                    \
-    0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,                    \
-    0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3,                    \
-    0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,                    \
-    0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9,                    \
-    0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,                    \
-    0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab,                    \
-    0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,                    \
-    0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4,                    \
-    0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,                    \
-    0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43,                    \
-    0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,                    \
-    0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8,                    \
-    0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,                    \
-    0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171,                    \
-    0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,                    \
-    0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89,                    \
-    0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,                    \
-    0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b,                    \
-    0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,                    \
-    0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb,                    \
-    0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,                    \
-    0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e,                    \
-    0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,                    \
-    0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea,                    \
-    0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,                    \
-    0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea,                    \
-    0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,                    \
-    0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd,                    \
-    0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,                    \
-    0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef,                    \
-    0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 },                  \
-                                                                       \
-  { 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907,                    \
-    0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,                    \
-    0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae,                    \
-    0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,                    \
-    0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e,                    \
-    0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,                    \
-    0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc,                    \
-    0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,                    \
-    0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e,                    \
-    0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,                    \
-    0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f,                    \
-    0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,                    \
-    0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99,                    \
-    0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,                    \
-    0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f,                    \
-    0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,                    \
-    0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380,                    \
-    0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,                    \
-    0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8,                    \
-    0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,                    \
-    0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504,                    \
-    0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,                    \
-    0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6,                    \
-    0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,                    \
-    0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e,                    \
-    0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,                    \
-    0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d,                    \
-    0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,                    \
-    0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1,                    \
-    0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,                    \
-    0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c,                    \
-    0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,                    \
-    0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15,                    \
-    0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,                    \
-    0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4,                    \
-    0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,                    \
-    0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b,                    \
-    0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,                    \
-    0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392,                    \
-    0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,                    \
-    0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231,                    \
-    0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,                    \
-    0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889,                    \
-    0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,                    \
-    0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67,                    \
-    0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,                    \
-    0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49,                    \
-    0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,                    \
-    0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d,                    \
-    0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,                    \
-    0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d,                    \
-    0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,                    \
-    0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e,                    \
-    0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,                    \
-    0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767,                    \
-    0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,                    \
-    0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce,                    \
-    0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,                    \
-    0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24,                    \
-    0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,                    \
-    0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0,                    \
-    0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,                    \
-    0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5,                    \
-    0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 },                  \
-                                                                       \
-  { 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298,                    \
-    0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,                    \
-    0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120,                    \
-    0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,                    \
-    0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220,                    \
-    0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,                    \
-    0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe,                    \
-    0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,                    \
-    0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701,                    \
-    0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,                    \
-    0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b,                    \
-    0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,                    \
-    0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93,                    \
-    0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,                    \
-    0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746,                    \
-    0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,                    \
-    0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9,                    \
-    0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,                    \
-    0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb,                    \
-    0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,                    \
-    0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c,                    \
-    0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,                    \
-    0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7,                    \
-    0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,                    \
-    0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340,                    \
-    0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,                    \
-    0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327,                    \
-    0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,                    \
-    0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec,                    \
-    0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,                    \
-    0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205,                    \
-    0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,                    \
-    0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031,                    \
-    0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,                    \
-    0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5,                    \
-    0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,                    \
-    0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c,                    \
-    0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,                    \
-    0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69,                    \
-    0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,                    \
-    0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9,                    \
-    0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,                    \
-    0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff,                    \
-    0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,                    \
-    0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3,                    \
-    0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,                    \
-    0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2,                    \
-    0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,                    \
-    0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff,                    \
-    0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,                    \
-    0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091,                    \
-    0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,                    \
-    0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df,                    \
-    0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,                    \
-    0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf,                    \
-    0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,                    \
-    0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367,                    \
-    0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,                    \
-    0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c,                    \
-    0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,                    \
-    0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43,                    \
-    0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,                    \
-    0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e,                    \
-    0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 }                   \
-}
-
-#define CAST_SK {                                                      \
-  { 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911,                    \
-    0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,                    \
-    0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00,                    \
-    0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,                    \
-    0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180,                    \
-    0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,                    \
-    0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2,                    \
-    0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,                    \
-    0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725,                    \
-    0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,                    \
-    0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b,                    \
-    0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,                    \
-    0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571,                    \
-    0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,                    \
-    0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec,                    \
-    0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,                    \
-    0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea,                    \
-    0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,                    \
-    0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263,                    \
-    0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,                    \
-    0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468,                    \
-    0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,                    \
-    0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b,                    \
-    0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,                    \
-    0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284,                    \
-    0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,                    \
-    0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4,                    \
-    0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,                    \
-    0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7,                    \
-    0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,                    \
-    0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce,                    \
-    0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,                    \
-    0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6,                    \
-    0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,                    \
-    0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4,                    \
-    0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,                    \
-    0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561,                    \
-    0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,                    \
-    0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6,                    \
-    0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,                    \
-    0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406,                    \
-    0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,                    \
-    0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472,                    \
-    0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,                    \
-    0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487,                    \
-    0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,                    \
-    0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288,                    \
-    0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,                    \
-    0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2,                    \
-    0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,                    \
-    0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78,                    \
-    0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,                    \
-    0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76,                    \
-    0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,                    \
-    0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0,                    \
-    0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,                    \
-    0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58,                    \
-    0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,                    \
-    0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2,                    \
-    0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,                    \
-    0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be,                    \
-    0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,                    \
-    0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55,                    \
-    0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 },                  \
-                                                                       \
-  { 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c,                    \
-    0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,                    \
-    0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9,                    \
-    0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,                    \
-    0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e,                    \
-    0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,                    \
-    0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866,                    \
-    0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,                    \
-    0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c,                    \
-    0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,                    \
-    0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd,                    \
-    0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,                    \
-    0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53,                    \
-    0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,                    \
-    0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d,                    \
-    0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,                    \
-    0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf,                    \
-    0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,                    \
-    0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807,                    \
-    0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,                    \
-    0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a,                    \
-    0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,                    \
-    0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563,                    \
-    0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,                    \
-    0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0,                    \
-    0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,                    \
-    0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be,                    \
-    0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,                    \
-    0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0,                    \
-    0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,                    \
-    0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2,                    \
-    0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,                    \
-    0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853,                    \
-    0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,                    \
-    0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa,                    \
-    0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,                    \
-    0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9,                    \
-    0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,                    \
-    0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751,                    \
-    0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,                    \
-    0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358,                    \
-    0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,                    \
-    0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397,                    \
-    0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,                    \
-    0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459,                    \
-    0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,                    \
-    0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4,                    \
-    0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,                    \
-    0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f,                    \
-    0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,                    \
-    0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb,                    \
-    0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,                    \
-    0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2,                    \
-    0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,                    \
-    0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab,                    \
-    0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,                    \
-    0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b,                    \
-    0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,                    \
-    0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b,                    \
-    0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,                    \
-    0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855,                    \
-    0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,                    \
-    0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454,                    \
-    0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f },                  \
-                                                                       \
-  { 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693,                    \
-    0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,                    \
-    0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82,                    \
-    0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,                    \
-    0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd,                    \
-    0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,                    \
-    0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f,                    \
-    0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,                    \
-    0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9,                    \
-    0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,                    \
-    0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e,                    \
-    0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,                    \
-    0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83,                    \
-    0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,                    \
-    0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e,                    \
-    0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,                    \
-    0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a,                    \
-    0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,                    \
-    0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f,                    \
-    0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,                    \
-    0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b,                    \
-    0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,                    \
-    0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78,                    \
-    0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,                    \
-    0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d,                    \
-    0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,                    \
-    0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802,                    \
-    0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,                    \
-    0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9,                    \
-    0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,                    \
-    0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302,                    \
-    0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,                    \
-    0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858,                    \
-    0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,                    \
-    0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a,                    \
-    0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,                    \
-    0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4,                    \
-    0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,                    \
-    0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df,                    \
-    0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,                    \
-    0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9,                    \
-    0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,                    \
-    0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c,                    \
-    0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,                    \
-    0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07,                    \
-    0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,                    \
-    0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939,                    \
-    0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,                    \
-    0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e,                    \
-    0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,                    \
-    0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378,                    \
-    0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,                    \
-    0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd,                    \
-    0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,                    \
-    0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567,                    \
-    0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,                    \
-    0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2,                    \
-    0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,                    \
-    0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf,                    \
-    0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,                    \
-    0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2,                    \
-    0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,                    \
-    0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada,                    \
-    0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 },                  \
-                                                                       \
-  { 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095,                    \
-    0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,                    \
-    0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174,                    \
-    0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,                    \
-    0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940,                    \
-    0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,                    \
-    0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42,                    \
-    0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,                    \
-    0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164,                    \
-    0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,                    \
-    0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4,                    \
-    0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,                    \
-    0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0,                    \
-    0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,                    \
-    0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6,                    \
-    0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,                    \
-    0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491,                    \
-    0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,                    \
-    0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b,                    \
-    0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,                    \
-    0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8,                    \
-    0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,                    \
-    0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006,                    \
-    0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,                    \
-    0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564,                    \
-    0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,                    \
-    0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab,                    \
-    0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,                    \
-    0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc,                    \
-    0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,                    \
-    0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8,                    \
-    0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,                    \
-    0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441,                    \
-    0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,                    \
-    0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f,                    \
-    0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,                    \
-    0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504,                    \
-    0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,                    \
-    0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c,                    \
-    0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,                    \
-    0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6,                    \
-    0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,                    \
-    0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd,                    \
-    0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,                    \
-    0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4,                    \
-    0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,                    \
-    0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc,                    \
-    0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,                    \
-    0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba,                    \
-    0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,                    \
-    0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf,                    \
-    0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,                    \
-    0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603,                    \
-    0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,                    \
-    0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37,                    \
-    0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,                    \
-    0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819,                    \
-    0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,                    \
-    0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d,                    \
-    0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,                    \
-    0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347,                    \
-    0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,                    \
-    0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d,                    \
-    0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e }                   \
-}
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/cast128.c b/cast128.c
deleted file mode 100644 (file)
index 5f13614..0000000
--- a/cast128.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cast128.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The CAST-128 block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "cast-base.h"
-#include "cast128.h"
-#include "gcipher.h"
-#include "paranoia.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet cast128_keysz[] = { KSZ_RANGE, CAST128_KEYSZ, 0, 16, 1 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @cast128_init@ --- *
- *
- * Arguments:  @cast128_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a CAST-128 key buffer.  CAST-128 accepts
- *             128-bit keys or shorter.
- */
-
-void cast128_init(cast128_ctx *k, const void *buf, size_t sz)
-{
-  const octet *p = buf;
-  uint32 kk[4];
-  unsigned i;
-  uint32 a, b, c, d,  aa, bb, cc, dd;
-
-  /* --- Fiddle with the key size a bit --- */
-
-  KSZ_ASSERT(cast128, sz);
-
-  if (sz > 10)
-    k->r = 16;
-  else
-    k->r = 12;
-
-  /* --- Read the key into the array --- */
-
-  i = 0;
-  b = 32; aa = 0;
-  for (;;) {
-    if (!sz)
-      break;
-    b -= 8;
-    aa |= ((uint32)*p++ << b);
-    sz--;
-    if (b == 0) {
-      kk[i++] = aa;
-      if (i == 4)
-       break;
-      aa = 0;
-      b = 32;
-    }
-  }
-
-  for (; i < 4; i++) {
-    kk[i] = aa;
-    aa = 0;
-  }
-
-  /* --- Read the key words out --- */
-
-  a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3];
-
-#define X_0123 a
-#define X_4567 b
-#define X_89ab c
-#define X_cdef d
-
-#define X_0 U8(X_0123 >> 24)
-#define X_1 U8(X_0123 >> 16)
-#define X_2 U8(X_0123 >>  8)
-#define X_3 U8(X_0123 >>  0)
-#define X_4 U8(X_4567 >> 24)
-#define X_5 U8(X_4567 >> 16)
-#define X_6 U8(X_4567 >>  8)
-#define X_7 U8(X_4567 >>  0)
-#define X_8 U8(X_89ab >> 24)
-#define X_9 U8(X_89ab >> 16)
-#define X_a U8(X_89ab >>  8)
-#define X_b U8(X_89ab >>  0)
-#define X_c U8(X_cdef >> 24)
-#define X_d U8(X_cdef >> 16)
-#define X_e U8(X_cdef >>  8)
-#define X_f U8(X_cdef >>  0)
-
-#define Z_0123 aa
-#define Z_4567 bb
-#define Z_89ab cc
-#define Z_cdef dd
-
-#define Z_0 U8(Z_0123 >> 24)
-#define Z_1 U8(Z_0123 >> 16)
-#define Z_2 U8(Z_0123 >>  8)
-#define Z_3 U8(Z_0123 >>  0)
-#define Z_4 U8(Z_4567 >> 24)
-#define Z_5 U8(Z_4567 >> 16)
-#define Z_6 U8(Z_4567 >>  8)
-#define Z_7 U8(Z_4567 >>  0)
-#define Z_8 U8(Z_89ab >> 24)
-#define Z_9 U8(Z_89ab >> 16)
-#define Z_a U8(Z_89ab >>  8)
-#define Z_b U8(Z_89ab >>  0)
-#define Z_c U8(Z_cdef >> 24)
-#define Z_d U8(Z_cdef >> 16)
-#define Z_e U8(Z_cdef >>  8)
-#define Z_f U8(Z_cdef >>  0)
-
-#define SK(w, x, y, z)                                                 \
-  cast_sk[0][w] ^ cast_sk[1][x] ^ cast_sk[2][y] ^ cast_sk[3][z]
-
-  i = 0;
-  Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8];
-  Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a];
-  Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9];
-  Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b];
-  k->km[i++] = SK(Z_8, Z_9, Z_7, Z_6) ^ cast_sk[0][Z_2];
-  k->km[i++] = SK(Z_a, Z_b, Z_5, Z_4) ^ cast_sk[1][Z_6];
-  k->km[i++] = SK(Z_c, Z_d, Z_3, Z_2) ^ cast_sk[2][Z_9];
-  k->km[i++] = SK(Z_e, Z_f, Z_1, Z_0) ^ cast_sk[3][Z_c];
-  X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0];
-  X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2];
-  X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1];
-  X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3];
-  k->km[i++] = SK(X_3, X_2, X_c, X_d) ^ cast_sk[0][X_8];
-  k->km[i++] = SK(X_1, X_0, X_e, X_f) ^ cast_sk[1][X_d];
-  k->km[i++] = SK(X_7, X_6, X_8, X_9) ^ cast_sk[2][X_3];
-  k->km[i++] = SK(X_5, X_4, X_a, X_b) ^ cast_sk[3][X_7];
-  Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8];
-  Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a];
-  Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9];
-  Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b];
-  k->km[i++] = SK(Z_3, Z_2, Z_c, Z_d) ^ cast_sk[0][Z_9];
-  k->km[i++] = SK(Z_1, Z_0, Z_e, Z_f) ^ cast_sk[1][Z_c];
-  k->km[i++] = SK(Z_7, Z_6, Z_8, Z_9) ^ cast_sk[2][Z_2];
-  k->km[i++] = SK(Z_5, Z_4, Z_a, Z_b) ^ cast_sk[3][Z_6];
-  X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0];
-  X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2];
-  X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1];
-  X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3];
-  k->km[i++] = SK(X_8, X_9, X_7, X_6) ^ cast_sk[0][X_3];
-  k->km[i++] = SK(X_a, X_b, X_5, X_4) ^ cast_sk[1][X_7];
-  k->km[i++] = SK(X_c, X_d, X_3, X_2) ^ cast_sk[2][X_8];
-  k->km[i++] = SK(X_e, X_f, X_1, X_0) ^ cast_sk[3][X_d];
-
-  i = 0;
-  Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8];
-  Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a];
-  Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9];
-  Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b];
-  k->kr[i++] = (SK(Z_8, Z_9, Z_7, Z_6) ^ cast_sk[0][Z_2]) & 0x1f;
-  k->kr[i++] = (SK(Z_a, Z_b, Z_5, Z_4) ^ cast_sk[1][Z_6]) & 0x1f;
-  k->kr[i++] = (SK(Z_c, Z_d, Z_3, Z_2) ^ cast_sk[2][Z_9]) & 0x1f;
-  k->kr[i++] = (SK(Z_e, Z_f, Z_1, Z_0) ^ cast_sk[3][Z_c]) & 0x1f;
-  X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0];
-  X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2];
-  X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1];
-  X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3];
-  k->kr[i++] = (SK(X_3, X_2, X_c, X_d) ^ cast_sk[0][X_8]) & 0x1f;
-  k->kr[i++] = (SK(X_1, X_0, X_e, X_f) ^ cast_sk[1][X_d]) & 0x1f;
-  k->kr[i++] = (SK(X_7, X_6, X_8, X_9) ^ cast_sk[2][X_3]) & 0x1f;
-  k->kr[i++] = (SK(X_5, X_4, X_a, X_b) ^ cast_sk[3][X_7]) & 0x1f;
-  Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8];
-  Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a];
-  Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9];
-  Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b];
-  k->kr[i++] = (SK(Z_3, Z_2, Z_c, Z_d) ^ cast_sk[0][Z_9]) & 0x1f;
-  k->kr[i++] = (SK(Z_1, Z_0, Z_e, Z_f) ^ cast_sk[1][Z_c]) & 0x1f;
-  k->kr[i++] = (SK(Z_7, Z_6, Z_8, Z_9) ^ cast_sk[2][Z_2]) & 0x1f;
-  k->kr[i++] = (SK(Z_5, Z_4, Z_a, Z_b) ^ cast_sk[3][Z_6]) & 0x1f;
-  X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0];
-  X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2];
-  X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1];
-  X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3];
-  k->kr[i++] = (SK(X_8, X_9, X_7, X_6) ^ cast_sk[0][X_3]) & 0x1f;
-  k->kr[i++] = (SK(X_a, X_b, X_5, X_4) ^ cast_sk[1][X_7]) & 0x1f;
-  k->kr[i++] = (SK(X_c, X_d, X_3, X_2) ^ cast_sk[2][X_8]) & 0x1f;
-  k->kr[i++] = (SK(X_e, X_f, X_1, X_0) ^ cast_sk[3][X_d]) & 0x1f;
-
-  BURN(kk);
-}
-
-/* --- @cast128_eblk@, @cast128_dblk@ --- *
- *
- * Arguments:  @const cast128_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-void cast128_eblk(const cast128_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 a = s[0], b = s[1];
-  const uint32 *km = k->km;
-  const octet *kr = k->kr;
-
-  switch (k->r) {
-    default:
-      CAST_R1(*km++, *kr++, a, b);
-      CAST_R2(*km++, *kr++, b, a);
-      CAST_R3(*km++, *kr++, a, b);
-      CAST_R1(*km++, *kr++, b, a);
-      CAST_R2(*km++, *kr++, a, b);
-      CAST_R3(*km++, *kr++, b, a);
-      CAST_R1(*km++, *kr++, a, b);
-      CAST_R2(*km++, *kr++, b, a);
-      CAST_R3(*km++, *kr++, a, b);
-      CAST_R1(*km++, *kr++, b, a);
-      CAST_R2(*km++, *kr++, a, b);
-      CAST_R3(*km++, *kr++, b, a);
-      if (k->r == 12)
-       break;
-      CAST_R1(*km++, *kr++, a, b);
-      CAST_R2(*km++, *kr++, b, a);
-      CAST_R3(*km++, *kr++, a, b);
-      CAST_R1(*km++, *kr++, b, a);
-      break;
-  }
-
-  d[0] = b; d[1] = a;
-}
-
-void cast128_dblk(const cast128_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 a = s[0], b = s[1];
-  const uint32 *km = k->km + k->r;
-  const octet *kr = k->kr + k->r;
-
-  switch (k->r) {
-    case 16:
-    default:
-      CAST_R1(*--km, *--kr, a, b);
-      CAST_R3(*--km, *--kr, b, a);
-      CAST_R2(*--km, *--kr, a, b);
-      CAST_R1(*--km, *--kr, b, a);
-    case 12:
-      CAST_R3(*--km, *--kr, a, b);
-      CAST_R2(*--km, *--kr, b, a);
-      CAST_R1(*--km, *--kr, a, b);
-      CAST_R3(*--km, *--kr, b, a);
-      CAST_R2(*--km, *--kr, a, b);
-      CAST_R1(*--km, *--kr, b, a);
-      CAST_R3(*--km, *--kr, a, b);
-      CAST_R2(*--km, *--kr, b, a);
-      CAST_R1(*--km, *--kr, a, b);
-      CAST_R3(*--km, *--kr, b, a);
-      CAST_R2(*--km, *--kr, a, b);
-      CAST_R1(*--km, *--kr, b, a);
-      break;
-  }
-
-  d[0] = b; d[1] = a;
-}
-
-BLKC_TEST(CAST128, cast128)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cast128.h b/cast128.h
deleted file mode 100644 (file)
index fb51416..0000000
--- a/cast128.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cast128.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The CAST-128 block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the CAST-128 block cipher --------------------------------*
- *
- * CAST, designed by Carlisle Adams and Stafford Tavares, is a method for
- * designing block ciphers, based around the concept of `bent functions'.  It
- * is described in the paper `Constructing Symmetric Ciphers using the CAST
- * Design Procedure' by Carlisle Adams.
- *
- * CAST-128, defined in RFC2144, is a particular instance of the CAST design
- * procedure, The cipher seems strong and fairly quick.  The design procedure
- * itself is patented, although the cipher CAST-128 is free to use.
- *
- * Although CAST ciphers are resistant to differential and linear
- * cryptanalysis, some instances have been broken by more advanced techniques
- * -- the CAST procedure does not guarantee a strong cipher.  However,
- * CAST-128 has so far resisted all attacks against it, and has now been
- * accepted by the Canadian government for protection of all `Designated'
- * material.
- */
-
-#ifndef CATACOMB_CAST128_H
-#define CATACOMB_CAST128_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define CAST128_BLKSZ 8
-#define CAST128_KEYSZ 16
-#define CAST128_CLASS (N, B, 64)
-
-extern const octet cast128_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct cast128_ctx {
-  unsigned r;
-  uint32 km[16];
-  octet kr[16];
-} cast128_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @cast128_init@ --- *
- *
- * Arguments:  @cast128_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a CAST-128 key buffer.  CAST-128 accepts
- *             128-bit keys or shorter.
- */
-
-extern void cast128_init(cast128_ctx */*k*/,
-                        const void */*buf*/, size_t /*sz*/);
-
-/* --- @cast128_eblk@, @cast128_dblk@ --- *
- *
- * Arguments:  @const cast128_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void cast128_eblk(const cast128_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*d*/);
-
-extern void cast128_dblk(const cast128_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/cast256.c b/cast256.c
deleted file mode 100644 (file)
index 36546b0..0000000
--- a/cast256.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cast256.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The CAST-256 block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "cast-base.h"
-#include "cast256.h"
-#include "gcipher.h"
-#include "paranoia.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet cast256_keysz[] = { KSZ_RANGE, CAST256_KEYSZ, 0, 32, 1 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @cast256_init@ --- *
- *
- * Arguments:  @cast128_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a CAST-256 key buffer.  CAST-256 accepts
- *             256-bit keys or shorter.
- */
-
-void cast256_init(cast256_ctx *k, const void *buf, size_t sz)
-{
-  const octet *p = buf;
-  uint32 kk[8];
-  uint32 *km;
-  octet *kr;
-  unsigned i, j;
-  uint32 a, b, c, d, e, f, g, h;
-  uint32 m;
-  unsigned r;
-
-  /* --- Fiddle with the key size --- */
-
-  KSZ_ASSERT(cast256, sz);
-
-  /* --- Read the key into the array --- */
-
-  i = 0;
-  b = 32; a = 0;
-  for (;;) {
-    if (!sz)
-      break;
-    b -= 8;
-    a |= ((uint32)*p++ << b);
-    sz--;
-    if (b == 0) {
-      kk[i++] = a;
-      if (i == 8)
-       break;
-      a = 0;
-      b = 32;
-    }
-  }
-
-  for (; i < 8; i++) {
-    kk[i] = a;
-    a = 0;
-  }
-
-  /* --- Read the key words out --- */
-
-  a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3];
-  e = kk[4]; f = kk[5]; g = kk[6]; h = kk[7];
-
-#define ROOT2 0x5a827999
-#define ROOT3 0x6ed9eba1
-
-  m = ROOT2;
-  r = 19;
-
-  km = k->km;
-  kr = k->kr;
-  for (i = 0; i < 12; i++) {
-    for (j = 0; j < 2; j++) {
-      CAST_R1(m, r, g, h); m += ROOT3; r = (r + 17) & 0x1f;
-      CAST_R2(m, r, f, g); m += ROOT3; r = (r + 17) & 0x1f;
-      CAST_R3(m, r, e, f); m += ROOT3; r = (r + 17) & 0x1f;
-      CAST_R1(m, r, d, e); m += ROOT3; r = (r + 17) & 0x1f;
-      CAST_R2(m, r, c, d); m += ROOT3; r = (r + 17) & 0x1f;
-      CAST_R3(m, r, b, c); m += ROOT3; r = (r + 17) & 0x1f;
-      CAST_R1(m, r, a, b); m += ROOT3; r = (r + 17) & 0x1f;
-      CAST_R2(m, r, h, a); m += ROOT3; r = (r + 17) & 0x1f;
-    }
-    km[0] = h; km[1] = f; km[2] = d; km[3] = b;
-    kr[0] = a & 0x1f; kr[1] = c & 0x1f; kr[2] = e & 0x1f; kr[3] = g & 0x1f;
-    km += 4; kr += 4;
-  }
-}
-
-/* --- @cast256_eblk@, @cast256_dblk@ --- *
- *
- * Arguments:  @const cast256_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define Q0(k, r, a, b, c, d) do {                                      \
-  CAST_R1(k[0], r[0], c, d);                                           \
-  CAST_R2(k[1], r[1], b, c);                                           \
-  CAST_R3(k[2], r[2], a, b);                                           \
-  CAST_R1(k[3], r[3], d, a);                                           \
-} while (0)
-
-#define Q1(k, r, a, b, c, d) do {                                      \
-  CAST_R1(k[3], r[3], d, a);                                           \
-  CAST_R3(k[2], r[2], a, b);                                           \
-  CAST_R2(k[1], r[1], b, c);                                           \
-  CAST_R1(k[0], r[0], c, d);                                           \
-} while (0)
-
-void cast256_eblk(const cast256_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
-  const uint32 *km = k->km;
-  const octet *kr = k->kr;
-
-  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-
-  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
-
-  d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
-}
-
-void cast256_dblk(const cast256_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
-  const uint32 *km = k->km + 48;
-  const octet *kr = k->kr + 48;
-
-  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
-
-  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
-  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
-
-  d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
-}
-
-BLKC_TEST(CAST256, cast256)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cast256.h b/cast256.h
deleted file mode 100644 (file)
index 7e65a83..0000000
--- a/cast256.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cast256.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The CAST-128 block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the CAST-256 block cipher --------------------------------*
- *
- * CAST, designed by Carlisle Adams and Stafford Tavares, is a method for
- * designing block ciphers, based around the concept of `bent functions'.  It
- * is described in the paper `Constructing Symmetric Ciphers using the CAST
- * Design Procedure' by Carlisle Adams.
- *
- * CAST-256, defined in RFC2612, is a particular instance of the CAST design
- * procedure.  It is an `incomplete' Feistel network.  It uses the same
- * S-boxes and round functions as CAST-128.
- *
- * CAST-256 was submitted to the AES contest, but was not selected as one of
- * the five `finalist' algorithms.
- */
-
-#ifndef CATACOMB_CAST256_H
-#define CATACOMB_CAST256_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define CAST256_BLKSZ 16
-#define CAST256_KEYSZ 32
-#define CAST256_CLASS (N, B, 128)
-
-extern const octet cast256_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct cast256_ctx {
-  uint32 km[48];
-  octet kr[48];
-} cast256_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @cast256_init@ --- *
- *
- * Arguments:  @cast256_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a CAST-256 key buffer.  CAST-256 accepts
- *             256-bit keys or shorter.
- */
-
-extern void cast256_init(cast256_ctx */*k*/,
-                        const void */*buf*/, size_t /*sz*/);
-
-/* --- @cast256_eblk@, @cast256_dblk@ --- *
- *
- * Arguments:  @const cast256_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void cast256_eblk(const cast256_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*d*/);
-
-extern void cast256_dblk(const cast256_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/catcrypt.c b/catcrypt.c
deleted file mode 100644 (file)
index 08fb7e0..0000000
+++ /dev/null
@@ -1,771 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Command-line encryption tool
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include "config.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/base64.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include "buf.h"
-#include "rand.h"
-#include "noise.h"
-#include "mprand.h"
-#include "key.h"
-#include "cc.h"
-
-#include "ectab.h"
-#include "ptab.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static const char *keyring = "keyring";
-
-/*----- Data format -------------------------------------------------------*/
-
-/* --- Overview --- *
- *
- * The encrypted message is divided into chunks, each preceded by a two-octet
- * length.  The chunks don't need to be large -- the idea is that we can
- * stream the chunks in and out.
- *
- * The first chunk is a header.  It contains the decryption key-id, and maybe
- * the verification key-id if the message is signed.
- *
- * Next comes the key-encapsulation chunk.  This is decrypted in some
- * KEM-specific way to yield a secret hash.  The hash is expanded using an
- * MGF (or similar) to make a symmetric encryption and MAC key.
- *
- * If the message is signed, there comes a signature chunk.  The signature is
- * on the header and key-encapsulation chunks, and further output of the MGF.
- * This means that the recipient can modify the message and still have a
- * valid signature, so it's not useful for proving things to other people;
- * but it also means that the recipient knows that the message is from
- * someone who knows the hash, which limits the possiblities to (a) whoever
- * encrypted the message (good!) and (b) whoever knows the recipient's
- * private key.
- *
- * Then come message chunks.  Each one begins with a MAC over an implicit
- * sequence number and the ciphertext.  The final chunk's ciphertext is
- * empty; no other chunk is empty.  Thus can the correct end-of-file be
- * discerned.
- */
-
-/*----- Chunk I/O ---------------------------------------------------------*/
-
-static void chunk_write(enc *e, buf *b)
-{
-  octet l[2];
-  size_t n = BLEN(b);
-  assert(n <= MASK16);
-  STORE16(l, n);
-  if (e->ops->write(e, l, 2) ||
-      e->ops->write(e, BBASE(b), BLEN(b)))
-    die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
-}
-
-static void chunk_read(enc *e, dstr *d, buf *b)
-{
-  octet l[2];
-  size_t n;
-
-  dstr_reset(d);
-  errno = 0;
-  if (e->ops->read(e, l, 2) != 2)
-    goto err;
-  n = LOAD16(l);
-  dstr_ensure(d, n);
-  if (e->ops->read(e, d->buf, n) != n)
-    goto err;
-  d->len = n;
-  buf_init(b, d->buf, d->len);
-  return;
-
-err:
-  if (!errno) die(EXIT_FAILURE, "unexpected end-of-file on input");
-  else die(EXIT_FAILURE, "error reading input: %s", strerror(errno));
-}
-
-/*----- Encryption --------------------------------------------------------*/
-
-static int encrypt(int argc, char *argv[])
-{
-  const char *fn, *of = 0, *kn = "ccrypt", *skn = 0;
-  FILE *ofp = 0;
-  FILE *fp = 0;
-  const char *ef = "binary";
-  fprogress ff;
-  const char *err;
-  int i;
-  int en;
-  size_t n, chsz;
-  dstr d = DSTR_INIT;
-  octet *tag, *ct;
-  buf b;
-  size_t seq;
-  char bb[65536];
-  unsigned f = 0;
-  key_file kf;
-  key *k;
-  key *sk = 0;
-  kem *km;
-  sig *s = 0;
-  gcipher *cx, *c;
-  gmac *m;
-  ghash *h;
-  const encops *eo;
-  enc *e;
-
-#define f_bogus 1u
-#define f_nocheck 2u
-#define f_progress 4u
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "key",         OPTF_ARGREQ,    0,      'k' },
-      { "sign-key",    OPTF_ARGREQ,    0,      's' },
-      { "armour",      0,              0,      'a' },
-      { "armor",       0,              0,      'a' },
-      { "format",      OPTF_ARGREQ,    0,      'f' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
-      { "progress",    0,              0,      'p' },
-      { "nocheck",     0,              0,      'C' },
-      { 0,             0,              0,      0 }
-    };
-    i = mdwopt(argc, argv, "k:s:af:o:pC", opt, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'k': kn = optarg; break;
-      case 's': skn = optarg; break;
-      case 'a': ef = "pem"; break;
-      case 'f': ef = optarg; break;
-      case 'o': of = optarg; break;
-      case 'p': f |= f_progress; break;
-      case 'C': f |= f_nocheck; break;
-      default: f |= f_bogus; break;
-    }
-  }
-  if (argc - optind > 1 || (f & f_bogus))
-    die(EXIT_FAILURE, "Usage: encrypt [-OPTIONS] [FILE]");
-
-  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
-    die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
-  if ((k = key_bytag(&kf, kn)) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", kn);
-  if (skn && (sk = key_bytag(&kf, skn)) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", skn);
-
-  if ((eo = getenc(ef)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", ef);
-
-  fn = optind < argc ? argv[optind++] : "-";
-  if (strcmp(fn, "-") == 0)
-    fp = stdin;
-  else if ((fp = fopen(fn, "rb")) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s': %s",
-       fn, strerror(errno));
-  }
-
-  if (!of || strcmp(of, "-") == 0)
-    ofp = stdout;
-  else if ((ofp = fopen(of, eo->wmode)) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-       ofp, strerror(errno));
-  }
-
-  dstr_reset(&d);
-  key_fulltag(k, &d);
-  e = initenc(eo, ofp, "CATCRYPT ENCRYPTED MESSAGE");
-  km = getkem(k, "cckem", 0);
-  if (!(f & f_nocheck) && (err = km->ops->check(km)) != 0)
-    moan("key %s fails check: %s", d.buf, err);
-  if (sk) {
-    dstr_reset(&d);
-    key_fulltag(sk, &d);
-    s = getsig(sk, "ccsig", 1);
-    if ((err = s->ops->check(s)) != 0)
-      moan("key %s fails check: %s", d.buf, err);
-  }
-
-  /* --- Build the header chunk --- */
-
-  dstr_reset(&d);
-  dstr_ensure(&d, 256);
-  buf_init(&b, d.buf, 256);
-  buf_putu32(&b, k->id);
-  if (sk) buf_putu32(&b, sk->id);
-  assert(BOK(&b));
-  if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b));
-  chunk_write(e, &b);
-
-  /* --- Build the KEM chunk --- */
-
-  dstr_reset(&d);
-  if (setupkem(km, &d, &cx, &c, &m))
-    die(EXIT_FAILURE, "failed to encapsulate key");
-  buf_init(&b, d.buf, d.len);
-  BSTEP(&b, d.len);
-  if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b));
-  chunk_write(e, &b);
-
-  /* --- Write the signature chunk --- */
-
-  if (s) {
-    GC_ENCRYPT(cx, 0, bb, 1024);
-    GH_HASH(s->h, bb, 1024);
-    dstr_reset(&d);
-    if ((en = s->ops->doit(s, &d)) != 0)
-      die(EXIT_FAILURE, "error creating signature: %s", key_strerror(en));
-    buf_init(&b, d.buf, d.len);
-    BSTEP(&b, d.len);
-    chunk_write(e, &b);
-  }
-
-  /* --- Now do the main crypto --- */
-
-  if (f & f_progress) {
-    if (fprogress_init(&ff, fn, fp)) {
-      die(EXIT_FAILURE, "failed to initialize progress display: %s",
-         strerror(errno));
-    }
-  }
-
-  assert(GC_CLASS(c)->blksz <= sizeof(bb));
-  dstr_ensure(&d, sizeof(bb) + GM_CLASS(m)->hashsz);
-  seq = 0;
-  chsz = MASK16 - GM_CLASS(m)->hashsz;
-  for (;;) {
-    h = GM_INIT(m);
-    GH_HASHU32(h, seq);
-    seq++;
-    if (GC_CLASS(c)->blksz) {
-      GC_ENCRYPT(cx, 0, bb, GC_CLASS(c)->blksz);
-      GC_SETIV(c, bb);
-    }
-    n = fread(bb, 1, chsz, fp);
-    if (!n) break;
-    if (f & f_progress) fprogress_update(&ff, n);
-    buf_init(&b, d.buf, d.sz);
-    tag = buf_get(&b, GM_CLASS(m)->hashsz);
-    ct = buf_get(&b, n);
-    assert(tag); assert(ct);
-    GC_ENCRYPT(c, bb, ct, n);
-    GH_HASH(h, ct, n);
-    GH_DONE(h, tag);
-    GH_DESTROY(h);
-    chunk_write(e, &b);
-  }
-
-  /* --- Final terminator packet --- */
-
-  buf_init(&b, d.buf, d.sz);
-  tag = buf_get(&b, GM_CLASS(m)->hashsz);
-  assert(tag);
-  GH_DONE(h, tag);
-  GH_DESTROY(h);
-  chunk_write(e, &b);
-
-  /* --- All done --- */
-
-  if (f & f_progress) fprogress_done(&ff);
-  e->ops->encdone(e);
-  GM_DESTROY(m);
-  GC_DESTROY(c);
-  GC_DESTROY(cx);
-  freeenc(e);
-  if (s) freesig(s);
-  freekem(km);
-  if (fp != stdin) fclose(fp);
-  if (of) fclose(ofp);
-  key_close(&kf);
-  dstr_destroy(&d);
-  return (0);
-
-#undef f_bogus
-#undef f_nocheck
-#undef f_progress
-}
-
-/*---- Decryption ---------------------------------------------------------*/
-
-static int decrypt(int argc, char *argv[])
-{
-  const char *fn, *of = 0;
-  FILE *ofp = 0, *rfp = 0;
-  FILE *fp = 0;
-  const char *ef = "binary";
-  fprogress ff;
-  int i;
-  size_t n;
-  dstr d = DSTR_INIT;
-  buf b;
-  key_file kf;
-  size_t seq;
-  uint32 id;
-  key *k;
-  key *sk = 0;
-  kem *km;
-  sig *s = 0;
-  gcipher *cx;
-  gcipher *c;
-  ghash *h;
-  gmac *m;
-  octet *tag;
-  unsigned f = 0;
-  const encops *eo;
-  const char *err;
-  int verb = 1;
-  enc *e;
-
-#define f_bogus 1u
-#define f_buffer 2u
-#define f_nocheck 4u
-#define f_progress 8u
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "armour",      0,              0,      'a' },
-      { "armor",       0,              0,      'a' },
-      { "buffer",      0,              0,      'b' },
-      { "verbose",     0,              0,      'v' },
-      { "quiet",       0,              0,      'q' },
-      { "nocheck",     0,              0,      'C' },
-      { "format",      OPTF_ARGREQ,    0,      'f' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
-      { "progress",    0,              0,      'p' },
-      { 0,             0,              0,      0 }
-    };
-    i = mdwopt(argc, argv, "abf:o:pqvC", opt, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'a': ef = "pem"; break;
-      case 'b': f |= f_buffer; break;
-      case 'v': verb++; break;
-      case 'q': if (verb) verb--; break;
-      case 'C': f |= f_nocheck; break;
-      case 'f': ef = optarg; break;
-      case 'o': of = optarg; break;
-      case 'p': f |= f_progress; break;
-      default: f |= f_bogus; break;
-    }
-  }
-  if (argc - optind > 1 || (f & f_bogus))
-    die(EXIT_FAILURE, "Usage: decrypt [-OPTIONS] [FILE]");
-
-  if ((eo = getenc(ef)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", ef);
-
-  fn = optind < argc ? argv[optind++] : "-";
-  if (strcmp(fn, "-") == 0)
-    fp = stdin;
-  else if ((fp = fopen(fn, eo->rmode)) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s': %s",
-       fn, strerror(errno));
-  }
-
-  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
-    die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
-
-  e = initdec(eo, fp, checkbdry, "CATCRYPT ENCRYPTED MESSAGE");
-
-  if (f & f_progress) {
-    if (fprogress_init(&ff, fn, fp)) {
-      die(EXIT_FAILURE, "failed to initialize progress display: %s",
-         strerror(errno));
-    }
-  }
-
-  /* --- Read the header chunk --- */
-
-  chunk_read(e, &d, &b);
-  if (f & f_progress)
-    fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
-  if (buf_getu32(&b, &id)) {
-    if (f & f_progress) fprogress_done(&ff);
-    if (verb) printf("FAIL malformed header: missing keyid\n");
-    exit(EXIT_FAILURE);
-  }
-  if ((k = key_byid(&kf, id)) == 0) {
-    if (f & f_progress) fprogress_done(&ff);
-    if (verb) printf("FAIL key id %08lx not found\n", (unsigned long)id);
-    exit(EXIT_FAILURE);
-  }
-  if (BLEFT(&b)) {
-    if (buf_getu32(&b, &id)) {
-      if (f & f_progress) fprogress_done(&ff);
-      if (verb) printf("FAIL malformed header: missing signature keyid\n");
-      exit(EXIT_FAILURE);
-    }
-    if ((sk = key_byid(&kf, id)) == 0) {
-      if (f & f_progress) fprogress_done(&ff);
-      if (verb) printf("FAIL key id %08lx not found\n", (unsigned long)id);
-      exit(EXIT_FAILURE);
-    }
-  }
-  if (BLEFT(&b)) {
-    if (f & f_progress) fprogress_done(&ff);
-    if (verb) printf("FAIL malformed header: junk at end\n");
-    exit(EXIT_FAILURE);
-  }
-  if (sk) {
-    s = getsig(sk, "ccsig", 0);
-    if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0) {
-      dstr_reset(&d);
-      key_fulltag(sk, &d);
-      printf("WARN verification key %s fails check: %s\n", d.buf, err);
-    }
-    GH_HASHBUF16(s->h, BBASE(&b), BSZ(&b));
-  }
-
-  /* --- Find the key --- */
-
-  km = getkem(k, "cckem", 1);
-
-  /* --- Read the KEM chunk --- */
-
-  chunk_read(e, &d, &b);
-  if (f & f_progress)
-    fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
-  if (setupkem(km, &d, &cx, &c, &m)) {
-    if (f & f_progress) fprogress_done(&ff);
-    if (verb) printf("FAIL failed to decapsulate key\n");
-    exit(EXIT_FAILURE);
-  }
-  if (s) GH_HASHBUF16(s->h, d.buf, d.len);
-
-  /* --- Verify the signature, if there is one --- */
-
-  if (sk) {
-    dstr_reset(&d);
-    dstr_ensure(&d, 1024);
-    GC_ENCRYPT(cx, 0, d.buf, 1024);
-    GH_HASH(s->h, d.buf, 1024);
-    chunk_read(e, &d, &b);
-    if (f & f_progress)
-      fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
-    if (s->ops->doit(s, &d)) {
-      if (f & f_progress) fprogress_done(&ff);
-      if (verb) printf("FAIL signature verification failed\n");
-      exit(EXIT_FAILURE);
-    }
-    if (verb) {
-      dstr_reset(&d);
-      key_fulltag(sk, &d);
-      if (f & f_progress) fprogress_clear(&ff);
-      printf("INFO good-signature %s\n", d.buf);
-    }
-    freesig(s);
-  } else if (verb) {
-    if (f & f_progress) fprogress_clear(&ff);
-    printf("INFO no-signature\n");
-  }
-
-  /* --- Now decrypt the main body --- */
-
-  if (!of || strcmp(of, "-") == 0) {
-    ofp = stdout;
-    f |= f_buffer;
-  }
-  if (!(f & f_buffer)) {
-    if ((ofp = fopen(of, "wb")) == 0) {
-      if (f & f_progress) fprogress_done(&ff);
-      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-         ofp, strerror(errno));
-    }
-    rfp = ofp;
-  } else if ((rfp = tmpfile()) == 0) {
-    if (f & f_progress) fprogress_done(&ff);
-    die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno));
-  }
-
-  seq = 0;
-  dstr_ensure(&d, GC_CLASS(c)->blksz);
-  dstr_ensure(&d, 4);
-  for (;;) {
-    if (GC_CLASS(c)->blksz) {
-      GC_ENCRYPT(cx, 0, d.buf, GC_CLASS(c)->blksz);
-      GC_SETIV(c, d.buf);
-    }
-    h = GM_INIT(m);
-    GH_HASHU32(h, seq);
-    seq++;
-    chunk_read(e, &d, &b);
-    if (f & f_progress)
-      fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
-    if ((tag = buf_get(&b, GM_CLASS(m)->hashsz)) == 0) {
-      if (f & f_progress) fprogress_done(&ff);
-      if (verb) printf("FAIL bad ciphertext chunk: no tag\n");
-      exit(EXIT_FAILURE);
-    }
-    GH_HASH(h, BCUR(&b), BLEFT(&b));
-    if (memcmp(tag, GH_DONE(h, 0), GM_CLASS(m)->hashsz) != 0) {
-      if (f & f_progress) fprogress_done(&ff);
-      if (verb)
-       printf("FAIL bad ciphertext chunk: authentication failure\n");
-      exit(EXIT_FAILURE);
-    }
-    GH_DESTROY(h);
-    if (!BLEFT(&b))
-      break;
-    GC_DECRYPT(c, BCUR(&b), BCUR(&b), BLEFT(&b));
-    if (fwrite(BCUR(&b), 1, BLEFT(&b), rfp) != BLEFT(&b)) {
-      if (f & f_progress) fprogress_done(&ff);
-      if (verb) printf("FAIL error writing output: %s\n", strerror(errno));
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  if (f & f_progress) fprogress_done(&ff);
-  if (fflush(rfp) || ferror(rfp)) {
-    if (verb) printf("FAIL error writing output: %s\n", strerror(errno));
-    exit(EXIT_FAILURE);
-  }
-  if (f & f_buffer) {
-    if (!ofp && (ofp = fopen(of, "wb")) == 0) {
-      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-         of, strerror(errno));
-    }
-    rewind(rfp);
-    if (f & f_progress) fprogress_init(&ff, "copying buffer", rfp);
-    dstr_reset(&d);
-    dstr_ensure(&d, 65536);
-    if (verb && ofp == stdout) printf("DATA\n");
-    for (;;) {
-      n = fread(d.buf, 1, d.sz, rfp);
-      if (!n) break;
-      if (f & f_progress) fprogress_update(&ff, n);
-      if (fwrite(d.buf, 1, n, ofp) < n) {
-       if (f & f_progress) fprogress_done(&ff);
-       die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
-      }
-    }
-    if (f & f_progress) fprogress_done(&ff);
-    if (ferror(rfp) || fclose(rfp))
-      die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno));
-  }
-
-  e->ops->decdone(e);
-  if (verb && ofp != stdout)
-    printf("OK decrypted successfully\n");
-  if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
-      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
-  freeenc(e);
-  GC_DESTROY(c);
-  GC_DESTROY(cx);
-  GM_DESTROY(m);
-  freekem(km);
-  if (fp != stdin) fclose(fp);
-  key_close(&kf);
-  dstr_destroy(&d);
-  return (0);
-
-#undef f_bogus
-#undef f_buffer
-#undef f_nocheck
-#undef f_progress
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-#define LISTS(LI)                                                      \
-  LI("Lists", list,                                                    \
-     listtab[i].name, listtab[i].name)                                 \
-  LI("Key-encapsulation mechanisms", kem,                              \
-     kemtab[i].name, kemtab[i].name)                                   \
-  LI("Signature schemes", sig,                                         \
-     sigtab[i].name, sigtab[i].name)                                   \
-  LI("Encodings", enc,                                                 \
-     enctab[i].name, enctab[i].name)                                   \
-  LI("Symmetric encryption algorithms", cipher,                                \
-     gciphertab[i], gciphertab[i]->name)                               \
-  LI("Hash functions", hash,                                           \
-     ghashtab[i], ghashtab[i]->name)                                   \
-  LI("Message authentication codes", mac,                              \
-     gmactab[i], gmactab[i]->name)
-
-MAKELISTTAB(listtab, LISTS)
-
-int cmd_show(int argc, char *argv[])
-{
-  return (displaylists(listtab, argv + 1));
-}
-
-static int cmd_help(int, char **);
-
-static cmd cmdtab[] = {
-  { "help", cmd_help, "help [COMMAND...]" },
-  { "show", cmd_show, "show [ITEM...]" },
-  CMD_ENCODE,
-  CMD_DECODE,
-  { "encrypt", encrypt,
-    "encrypt [-apC] [-k TAG] [-s TAG] [-f FORMAT]\n\t\
-[-o OUTPUT] [FILE]", "\
-Options:\n\
-\n\
--a, --armour           Same as `-f pem'.\n\
--f, --format=FORMAT    Encode as FORMAT.\n\
--k, --key=TAG          Use public encryption key named by TAG.\n\
--s, --sign-key=TAG     Use private signature key named by TAG.\n\
--o, --output=FILE      Write output to FILE.\n\
--p, --progress         Show progress on large files.\n\
--C, --nocheck          Don't check the public key.\n\
-" },
-  { "decrypt", decrypt,
-    "decrypt [-abpqvC] [-f FORMAT] [-o OUTPUT] [FILE]", "\
-Options:\n\
-\n\
--a, --armour           Same as `-f pem'.\n\
--b, --buffer           Buffer output until we're sure we have it all.\n\
--f, --format=FORMAT    Decode as FORMAT.\n\
--o, --output=FILE      Write output to FILE.\n\
--p, --progress         Show progress on large files.\n\
--q, --quiet            Produce fewer messages.\n\
--v, --verbose          Produce more verbose messages.\n\
--C, --nocheck          Don't check the private key.\n\
-" },
-  { 0, 0, 0 }
-};
-
-static int cmd_help(int argc, char **argv)
-{
-  sc_help(cmdtab, stdout, argv + 1);
-  return (0);
-}
-
-void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n");
-}
-
-void help_global(FILE *fp)
-{
-  usage(fp);
-  fputs("\n\
-Encrypt and decrypt files.\n\
-\n\
-Global command-line options:\n\
-\n\
--h, --help [COMMAND...]        Show this help message, or help for COMMANDs.\n\
--v, --version          Show program version number.\n\
--u, --usage            Show a terse usage message.\n\
-\n\
--k, --keyring=FILE     Read keys from FILE.\n",
-       fp);
-}
-
-/* --- @main@ --- *
- *
- * Arguments:  @int argc@ = number of command line arguments
- *             @char *argv[]@ = vector of command line arguments
- *
- * Returns:    Zero if successful, nonzero otherwise.
- *
- * Use:                Encrypts or decrypts files.
- */
-
-int main(int argc, char *argv[])
-{
-  unsigned f = 0;
-
-#define f_bogus 1u
-
-  /* --- Initialize the library --- */
-
-  ego(argv[0]);
-  sub_init();
-  rand_noisesrc(RAND_GLOBAL, &noise_source);
-  rand_seed(RAND_GLOBAL, 160);
-
-  /* --- Parse options --- */
-
-  for (;;) {
-    static struct option opts[] = {
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'v' },
-      { "usage",       0,              0,      'u' },
-      { "keyring",     OPTF_ARGREQ,    0,      'k' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'h':
-       sc_help(cmdtab, stdout, argv + optind);
-       exit(0);
-       break;
-      case 'v':
-       version(stdout);
-       exit(0);
-       break;
-      case 'u':
-       usage(stdout);
-       exit(0);
-      case 'k':
-       keyring = optarg;
-       break;
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-
-  argc -= optind;
-  argv += optind;
-  optind = 0;
-  if (f & f_bogus || argc < 1) {
-    usage(stderr);
-    exit(EXIT_FAILURE);
-  }
-
-  /* --- Dispatch to the correct subcommand handler --- */
-
-  return (findcmd(cmdtab, argv[0])->cmd(argc, argv));
-
-#undef f_bogus
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/catsign.c b/catsign.c
deleted file mode 100644 (file)
index 3bbd7b2..0000000
--- a/catsign.c
+++ /dev/null
@@ -1,1276 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Sign files
- *
- * (c) 2005 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include "config.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <mLib/base64.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include "buf.h"
-#include "rand.h"
-#include "noise.h"
-#include "mprand.h"
-#include "key.h"
-#include "getdate.h"
-#include "cc.h"
-
-#include "ectab.h"
-#include "ptab.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static const char *keyring = "keyring";
-
-/*----- Data formats ------------------------------------------------------*
- *
- * Our crypto stuff is split into three parts: a header describing the key,
- * the message itself, and the signature.  In a detached signature, the
- * message is separate, and the header and signature are combined into one
- * encoded chunk.  In an attached signature, the message is included.  There
- * are two forms of message: binary and text.  Binary messages are divided
- * into chunks, each preceded by a 2-octet length, and terminated by a
- * zero-length chunk.  Text messages are byte-stuffed, as for RFC821, and
- * trailing whitespace before a newline is ignored.
- */
-
-typedef struct sigmsg {
-  unsigned f;                          /* Flags */
-#define F_DETACH 1u
-#define F_BINARY 2u
-#define F_SIGMASK 3u
-#define F_HASHMASK (F_BINARY)
-  uint32 keyid;                                /* Key identifier */
-  time_t t;                            /* When the signature was made */
-  dstr kh;                             /* Key fingerprint (sanity check) */
-  dstr sig;                            /* Signature */
-  sig *s;                              /* Signature algorithm */
-} sigmsg;
-
-#define F_MIDLINE 16u
-#define F_EOF 32u
-#define F_NOCLOSE 64u
-#define F_BOGUS 128u
-#define F_BUFFER 256u
-#define F_UTC 512u
-#define F_NOCHECK 1024u
-#define F_PROGRESS 2048u
-
-/*----- Chunk I/O ---------------------------------------------------------*/
-
-static void chunk_write(enc *e, const void *p, size_t n)
-{
-  octet b[2];
-
-  assert(n <= 0xffff);
-  STORE16(b, n);
-  if (e->ops->write(e, b, 2) || e->ops->write(e, p, n))
-    die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
-}
-
-static size_t chunk_read(enc *e, void *p)
-{
-  octet b[2];
-  size_t n;
-
-  if (e->ops->read(e, b, 2) != 2)
-    goto err;
-  n = LOAD16(b);
-  if (n && e->ops->read(e, p, n) != n)
-    goto err;
-  return (n);
-
-err:
-  if (!errno) die(EXIT_FAILURE, "unexpected end-of-file on input");
-  else die(EXIT_FAILURE, "error reading input: %s", strerror(errno));
-  return (0);
-}
-
-/*----- Message canonification --------------------------------------------*/
-
-#define MSGBUFSZ 65536
-#define MSGBUFTHRESH 32768
-
-typedef struct msgcanon {
-  unsigned f;
-  FILE *fp;
-  enc *e;
-  fprogress ff;
-  size_t (*read)(struct msgcanon *, void *);
-  void (*write)(struct msgcanon *, const void *, size_t);
-  void (*close)(struct msgcanon *);
-} msgcanon;
-
-#define MC_INIT { 0 }
-
-static size_t textread(msgcanon *m, void *bp)
-{
-  size_t n = 0, nsp = 0;
-  int ch;
-  char *b = bp;
-  unsigned f = m->f;
-
-  if (f & F_EOF) return (0);
-  for (;;) {
-    if ((ch = getc(m->fp)) == EOF) goto eof;
-    if (!(f & (F_DETACH | F_MIDLINE)) && ch == '.') {
-      ch = getc(m->fp);
-      if (ch == '\n') goto eof;
-    }
-    if (ch == '\n') {
-      n -= nsp; nsp = 0;
-      if (n >= MSGBUFTHRESH) goto full;
-      b[n++] = ch;
-      f &= ~F_MIDLINE;
-    } else if (isspace(ch)) {
-      f |= F_MIDLINE;
-      if (n >= MSGBUFSZ) goto full;
-      b[n++] = ch; nsp++;
-    } else {
-      f |= F_MIDLINE;
-      nsp = 0;
-      if (n >= MSGBUFTHRESH) goto full;
-      b[n++] = ch;
-    }
-  }
-eof:
-  f |= F_EOF;
-  goto done;
-full:
-  ungetc(ch, m->fp);
-done:
-  m->f = f;
-  if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
-  return (n);
-}
-
-static void textwrite(msgcanon *m, const void *bp, size_t n)
-{
-  const char *p = bp, *l = p + n;
-  unsigned f = m->f;
-
-  while (p < l) {
-    if (!(f & (F_MIDLINE | F_DETACH)) &&
-       (*p == '.' || *p == '-'))
-      putc('.', m->fp);
-    if (*p == '\n') f &= ~F_MIDLINE;
-    else f |= F_MIDLINE;
-    putc(*p, m->fp);
-    p++;
-  }
-  m->f = f;
-}
-
-static size_t binreadembed(msgcanon *m, void *bp)
-{
-  size_t n = chunk_read(m->e, bp);
-  if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
-  return (n);
-}
-
-static size_t binreaddetach(msgcanon *m, void *bp)
-{
-  size_t n = fread(bp, 1, MSGBUFSZ - 1, m->fp);
-  if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
-  return (n);
-}
-
-static void binwriteembed(msgcanon *m, const void *bp, size_t n)
-  { chunk_write(m->e, bp, n); }
-
-static void nullwrite(msgcanon *m, const void *bp, size_t n) { ; }
-
-static void mcsetup_readfile(msgcanon *m, unsigned f, const char *fn)
-{
-  m->f = F_DETACH | (f & (F_BINARY | F_PROGRESS));
-  if (!fn || strcmp(fn, "-") == 0) {
-    m->fp = stdin;
-    m->f |= F_NOCLOSE;
-  } else if ((m->fp = fopen(fn, (f & F_BINARY) ? "rb" : "r")) == 0)
-    die(EXIT_FAILURE, "couldn't open file `%s': %s", fn, strerror(errno));
-  if (m->f & F_PROGRESS) {
-    if (fprogress_init(&m->ff, fn, m->fp)) {
-      die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
-         strerror(errno));
-    }
-  }
-  m->read = (f & F_BINARY) ? binreaddetach : textread;
-}
-
-static void mcsetup_writenull(msgcanon *m) { m->write = nullwrite; }
-
-static void mcsetup_read(msgcanon *m, unsigned f, enc **ee,
-                        const char *fn, const char *dfn)
-{
-  enc *e = *ee;
-
-  m->f = f | F_NOCLOSE;
-
-  if (dfn && !(f & F_DETACH)) die(EXIT_FAILURE, "signature is not detached");
-  if (f & F_BINARY) {
-    if (!(f & F_DETACH)) {
-      m->e = e;
-      *ee = 0;
-      m->fp = e->fp;
-      m->read = binreadembed;
-      if (m->f & F_PROGRESS) {
-       if (fprogress_init(&m->ff, fn, m->fp)) {
-         die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
-             strerror(errno));
-       }
-      }
-    } else {
-      m->read = binreaddetach;
-      if (!dfn || strcmp(dfn, "-") == 0)
-       m->fp = stdin;
-      else if ((m->fp = fopen(dfn, "rb")) == 0)
-       die(EXIT_FAILURE, "can't open `%s': %s", dfn, strerror(errno));
-      else
-       m->f &= ~F_NOCLOSE;
-      if (m->f & F_PROGRESS) {
-       if (fprogress_init(&m->ff, dfn, m->fp)) {
-         die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
-             strerror(errno));
-       }
-      }
-    }
-  } else {
-    m->read = textread;
-    if (!(f & F_DETACH)) {
-      if (e->ops->decdone(e) || ferror(e->fp))
-       die(EXIT_FAILURE, "error at end of signature header");
-      m->fp = e->fp;
-      e->ops->destroy(e);
-      *ee = 0;
-      if (m->f & F_PROGRESS) {
-       if (fprogress_init(&m->ff, fn, m->fp)) {
-         die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
-             strerror(errno));
-       }
-      }
-    } else {
-      if (!dfn || strcmp(dfn, "-") == 0)
-       m->fp = stdin;
-      else if ((m->fp = fopen(dfn, "r")) == 0)
-       die(EXIT_FAILURE, "can't read file `%s': %s", dfn, strerror(errno));
-      else
-       m->f &= ~F_NOCLOSE;
-      if (m->f & F_PROGRESS) {
-       if (fprogress_init(&m->ff, dfn, m->fp)) {
-         die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
-             strerror(errno));
-       }
-      }
-    }
-  }
-}
-
-static void mcsetup_write(msgcanon *m, unsigned f, enc **ee)
-{
-  enc *e = *ee;
-
-  m->f = f | F_NOCLOSE;
-
-  if (f & F_DETACH)
-    m->write = nullwrite;
-  else if (f & F_BINARY) {
-    m->e = e;
-    *ee = 0;
-    m->fp = e->fp;
-    m->write = binwriteembed;
-  } else {
-    if (e->ops->encdone(e) || ferror(e->fp))
-      die(EXIT_FAILURE, "error at end of signature header");
-    m->fp = e->fp;
-    e->ops->destroy(e);
-    *ee = 0;
-    m->write = textwrite;
-  }
-}
-
-static void mc_endread(msgcanon *m, const encops *eops, enc **ee)
-{
-  if (!(m->f & F_DETACH)) {
-    if (m->f & F_BINARY)
-      *ee = m->e;
-    else
-      *ee = initdec(eops, m->fp, checkbdry, "CATSIGN SIGNATURE");
-  }
-  if (m->fp && !(m->f & F_NOCLOSE)) {
-    if (ferror(m->fp) || fclose(m->fp))
-      die(EXIT_FAILURE, "error closing message file: %s", strerror(errno));
-  }
-  if (m->f & F_PROGRESS) fprogress_done(&m->ff);
-}
-
-static void mc_endwrite(msgcanon *m, const encops *eops, enc **ee)
-{
-  if (!(m->f & F_BINARY)) {
-    if (m->f & F_MIDLINE) putc('\n', m->fp);
-    if (!(m->f & F_DETACH)) {
-      putc('.', m->fp); putc('\n', m->fp);
-      *ee = initenc(eops, m->fp, "CATSIGN SIGNATURE");
-    }
-  } else if (!(m->f & F_DETACH)) {
-    chunk_write(m->e, 0, 0);
-    *ee = m->e;
-  }
-  if (m->fp && !(m->f & F_NOCLOSE)) {
-    if (fflush(m->fp) || ferror(m->fp) || fclose(m->fp))
-      die(EXIT_FAILURE, "error closing message file: %s", strerror(errno));
-  }
-}
-
-/*----- Signature reading and writing -------------------------------------*/
-
-static void sig_init(sigmsg *s, unsigned f, uint32 keyid)
-{
-  s->f = f & F_SIGMASK;
-  s->keyid = keyid;
-  time(&s->t);
-  s->s = 0;
-  dstr_create(&s->kh);
-  dstr_create(&s->sig);
-}
-
-static void sig_destroy(sigmsg *s)
-{
-  dstr_destroy(&s->kh);
-  dstr_destroy(&s->sig);
-  if (s->s) freesig(s->s);
-}
-
-static void sigtobuffer(sigmsg *s, buf *b, int hashp)
-{
-  kludge64 t;
-
-  ASSIGN64(t, s->t);
-  if (hashp) buf_putu16(b, s->f & F_HASHMASK);
-  else buf_putu16(b, s->f & F_SIGMASK);
-  buf_putu32(b, s->keyid);
-  buf_putu32(b, HI64(t));
-  buf_putu32(b, LO64(t));
-  buf_putdstr16(b, &s->kh);
-  assert(BOK(b));
-}
-
-static void dohash(ghash *h, const void *p, size_t n)
-{
-/*   trace_block(1, "hashing", p, n); */
-  GH_HASH(h, p, n);
-}
-
-static void sig_hash(sigmsg *s)
-{
-  octet bb[16384];
-  buf b;
-
-  buf_init(&b, bb, sizeof(bb));
-  sigtobuffer(s, &b, 1);
-  dohash(s->s->h, BBASE(&b), BLEN(&b));
-}
-
-static void keyhash(key *k, sig *s, dstr *d)
-{
-  ghash *h;
-  key_filter kf;
-
-  h = GH_INIT(s->ch);
-  kf.f = KCAT_PUB;
-  kf.m = KF_CATMASK;
-  key_fingerprint(k, h, &kf);
-  dstr_ensure(d, GH_CLASS(h)->hashsz);
-  GH_DONE(h, d->buf + d->len);
-  d->len += GH_CLASS(h)->hashsz;
-  GH_DESTROY(h);
-}
-
-static void sig_writeheader(enc *e, sigmsg *s)
-{
-  octet bb[16384];
-  buf b;
-
-  buf_init(&b, bb, sizeof(bb));
-  sigtobuffer(s, &b, 0);
-  chunk_write(e, BBASE(&b), BLEN(&b));
-}
-
-static void sig_writesig(enc *e, sigmsg *s)
-  { chunk_write(e, s->sig.buf, s->sig.len); }
-
-static void diechoke(const char *m, void *p)
-  { die(EXIT_FAILURE, "%s%s%s", p, p ? ": " : "", m); }
-
-static void sig_readheader(enc *e, sigmsg *s,
-                          void (*choke)(const char *, void *), void *p)
-{
-  uint16 f;
-  octet bb[MSGBUFSZ];
-  uint32 x, y;
-  kludge64 t;
-  buf b;
-  size_t n;
-
-  n = chunk_read(e, bb);
-  buf_init(&b, bb, n);
-  if (buf_getu16(&b, &f)) choke("missing flags", p);
-  if (buf_getu32(&b, &x)) choke("missing keyid", p);
-  sig_init(s, f, x);
-  if (buf_getu32(&b, &x) || buf_getu32(&b, &y))
-    choke("missing datestamp", p);
-  SET64(t, x, y); s->t = GET64(time_t, t);
-  if (buf_getdstr16(&b, &s->kh))
-    choke("missing key hash", p);
-  if (BLEFT(&b))
-    choke("junk at end", p);
-}
-
-static void sig_readsig(enc *e, sigmsg *s)
-{
-  octet bb[MSGBUFSZ];
-  size_t n;
-
-  n = chunk_read(e, bb);
-  dstr_putm(&s->sig, bb, n);
-}
-
-/*----- Signing -----------------------------------------------------------*/
-
-static int sign(int argc, char *argv[])
-{
-  const char *ef = "binary", *fn = 0, *of = 0, *kn = "ccsig", *err;
-  unsigned f = 0;
-  key_file kf;
-  key *k;
-  sigmsg s;
-  FILE *ofp = 0;
-  int i;
-  char bb[MSGBUFSZ];
-  size_t n;
-  dstr d = DSTR_INIT;
-  const encops *eo;
-  msgcanon mc_in = MC_INIT, mc_out = MC_INIT;
-  enc *e;
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "armour",      0,              0,      'a' },
-      { "armor",       0,              0,      'a' },
-      { "binary",      0,              0,      'b' },
-      { "detach",      0,              0,      'd' },
-      { "key",         OPTF_ARGREQ,    0,      'k' },
-      { "format",      OPTF_ARGREQ,    0,      'f' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
-      { "progress",    0,              0,      'p' },
-      { "text",                0,              0,      't' },
-      { "nocheck",     0,              0,      'C' },
-      { 0,             0,              0,      0 }
-    };
-    i = mdwopt(argc, argv, "k:f:o:abdptC", opt, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'k': kn = optarg; break;
-      case 'f': ef = optarg; break;
-      case 'o': of = optarg; break;
-      case 'a': ef = "pem"; break;
-      case 't': f &= ~F_BINARY; break;
-      case 'b': f |= F_BINARY; break;
-      case 'd': f |= F_DETACH; break;
-      case 'C': f |= F_NOCHECK; break;
-      case 'p': f |= F_PROGRESS; break;
-      default: f |= F_BOGUS; break;
-    }
-  }
-  if (argc - optind > 1 || (f & F_BOGUS))
-    die(EXIT_FAILURE, "Usage: sign [-OPTIONS] [FILE]");
-
-  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
-    die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
-  if ((k = key_bytag(&kf, kn)) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", kn);
-
-  if ((eo = getenc(ef)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", ef);
-
-  fn = (optind >= argc) ? 0 : argv[optind++];
-
-  if (!of || strcmp(of, "-") == 0)
-    ofp = stdout;
-  else if ((ofp = fopen(of, eo->wmode)) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-       ofp, strerror(errno));
-  }
-
-  /* --- Start the work --- */
-
-  sig_init(&s, f, k->id);
-  dstr_reset(&d);
-  key_fulltag(k, &d);
-  s.s = getsig(k, "ccsig", 1);
-  if (!(f & F_NOCHECK) && (err = s.s->ops->check(s.s)) != 0)
-    moan("key %s fails check: %s", d.buf, err);
-  keyhash(k, s.s, &s.kh);
-  e = initenc(eo, ofp,
-             (f & F_DETACH) ? "CATSIGN SIGNATURE" :
-             (f & F_BINARY) ? "CATSIGN MESSAGE" :
-             "CATSIGN MESSAGE HEADER");
-  sig_writeheader(e, &s);
-
-  /* --- Hash the message --- */
-
-  mcsetup_readfile(&mc_in, f, fn);
-  mcsetup_write(&mc_out, f, &e);
-  sig_hash(&s);
-  for (;;) {
-    n = mc_in.read(&mc_in, bb);
-    if (!n) break;
-    dohash(s.s->h, bb, n);
-    mc_out.write(&mc_out, bb, n);
-  }
-  mc_endread(&mc_in, 0, 0);
-  mc_endwrite(&mc_out, eo, &e);
-
-  /* --- Write the signature --- */
-
-  if (s.s->ops->doit(s.s, &s.sig))
-    die(EXIT_FAILURE, "signature failed");
-  sig_writesig(e, &s);
-  e->ops->encdone(e);
-  if (fflush(ofp) || ferror(ofp) || fclose(ofp))
-    die(EXIT_FAILURE, "error writing signature: %s", strerror(errno));
-
-  /* --- All done --- */
-
-  freeenc(e);
-  key_close(&kf);
-  sig_destroy(&s);
-  dstr_destroy(&d);
-  return (0);
-}
-
-/*----- Verifying ---------------------------------------------------------*/
-
-typedef struct vrfctx {
-  unsigned f, m;
-  int verb;
-  const char *what;
-} vrfctx;
-
-static int vrfbdry(const char *b, void *p)
-{
-  vrfctx *v = p;
-
-  if (strcmp(b, "CATSIGN MESSAGE") == 0) {
-    v->f |= F_BINARY;
-    v->m |= F_BINARY | F_DETACH;
-    return (1);
-  } else if (strcmp(b, "CATSIGN MESSAGE HEADER") == 0) {
-    v->m |= F_BINARY | F_DETACH;
-    return (1);
-  } else if (strcmp(b, "CATSIGN SIGNATURE") == 0) {
-    v->f |= F_DETACH;
-    v->m |= F_DETACH;
-    return (1);
-  } else
-    return (0);
-}
-
-static void vrfchoke(const char *m, void *p)
-{
-  vrfctx *v = p;
-  if (v->verb) printf("FAIL %s: %s\n", v->what, m);
-  exit(EXIT_FAILURE);
-}
-
-static int verify(int argc, char *argv[])
-{
-  const char *ef = "binary", *of = 0, *fn, *dfn = 0, *kn = 0, *err;
-  vrfctx v = { 0, 0, 1 };
-  key_file kf;
-  key *k, *kk = 0;
-  sigmsg s;
-  FILE *fp, *ofp = 0, *rfp = 0;
-  fprogress ff;
-  struct tm *tm;
-  int i;
-  char bb[MSGBUFSZ];
-  size_t n;
-  time_t t_fresh = 0;
-  dstr d = DSTR_INIT, dd = DSTR_INIT;
-  const encops *eo;
-  msgcanon mc_in = MC_INIT;
-  enc *e;
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "armour",      0,              0,      'a' },
-      { "armor",       0,              0,      'a' },
-      { "buffer",      0,              0,      'b' },
-      { "key",         OPTF_ARGREQ,    0,      'k' },
-      { "format",      OPTF_ARGREQ,    0,      'f' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
-      { "progress",    0,              0,      'p' },
-      { "quiet",       0,              0,      'q' },
-      { "utc",         0,              0,      'u' },
-      { "fresh-time",  0,              0,      't' },
-      { "gmt",         0,              0,      'u' },
-      { "verbose",     0,              0,      'v' },
-      { "nocheck",     0,              0,      'C' },
-      { 0,             0,              0,      0 }
-    };
-    i = mdwopt(argc, argv, "k:f:o:abpqt:uvC", opt, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'a': ef = "pem"; break;
-      case 'b': v.f |= F_BUFFER; break;
-      case 'k': kn = optarg; break;
-      case 'f': ef = optarg; break;
-      case 'o': of = optarg; break;
-      case 'u': v.f |= F_UTC; break;
-      case 'C': v.f |= F_NOCHECK; break;
-      case 't':
-       if (strcmp(optarg, "always") == 0) t_fresh = 0;
-       else if ((t_fresh = get_date(optarg, 0)) < 0)
-         die(EXIT_FAILURE, "bad freshness time");
-       break;
-      case 'q': if (v.verb > 0) v.verb--; break;
-      case 'v': if (v.verb < 10) v.verb++; break;
-      case 'p': v.f |= F_PROGRESS; break;
-      default: v.f |= F_BOGUS; break;
-    }
-  }
-  if (argc - optind > 2 || (v.f & F_BOGUS))
-    die(EXIT_FAILURE, "Usage: verify [-OPTIONS] [FILE [MESSAGE]]");
-
-  if ((eo = getenc(ef)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", ef);
-
-  fn = optind < argc ? argv[optind++] : "-";
-  if (strcmp(fn, "-") == 0)
-    fp = stdin;
-  else if ((fp = fopen(fn, eo->rmode)) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s': %s",
-       fn, strerror(errno));
-  }
-
-  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
-    die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
-  if (kn && (kk = key_bytag(&kf, kn)) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", kn);
-
-  e = initdec(eo, fp, vrfbdry, &v);
-
-  /* --- Read the header chunk --- */
-
-  v.what = "malformed header";
-  sig_readheader(e, &s, vrfchoke, &v);
-
-  if (((s.f ^ v.f) & v.m) != 0) {
-    if (v.verb) printf("FAIL boundary string inconsistent with contents\n");
-    exit(EXIT_FAILURE);
-  }
-  v.f |= s.f;
-
-  if ((k = key_byid(&kf, s.keyid)) == 0) {
-    if (v.verb) printf("FAIL key id %08lx not found\n",
-                      (unsigned long)s.keyid);
-    exit(EXIT_FAILURE);
-  }
-  if (kk && k->id != kk->id) {
-    if (v.verb) {
-      dstr_reset(&d); key_fulltag(k, &d);
-      dstr_reset(&dd); key_fulltag(kk, &dd);
-      printf("FAIL signing key is %s; expected key %s\n", d.buf, dd.buf);
-    }
-    exit(EXIT_FAILURE);
-  }
-
-  s.s = getsig(k, "ccsig", 0);
-  dstr_reset(&d); key_fulltag(k, &d);
-  if (!(v.f & F_NOCHECK) && v.verb && (err = s.s->ops->check(s.s)) != 0)
-    printf("WARN verification key %s fails check: %s\n", d.buf, err);
-
-  dstr_reset(&dd); keyhash(k, s.s, &dd);
-  if (dd.len != s.kh.len || memcmp(dd.buf, s.kh.buf, dd.len) != 0) {
-    if (v.verb) printf("FAIL key hash mismatch\n");
-    exit(EXIT_FAILURE);
-  }
-
-  /* --- Now a merry dance --- */
-
-  if (v.f & F_DETACH)
-    sig_readsig(e, &s);
-  if (optind < argc)
-    dfn = argv[optind++];
-  mcsetup_read(&mc_in, v.f, &e, fn, dfn);
-
-  if (!of && (v.f & F_DETACH)) {
-    rfp = ofp = 0;
-    v.f &= ~F_BUFFER;
-  } else if (!of || strcmp(of, "-") == 0) {
-    v.f |= F_BUFFER;
-    ofp = stdout;
-  }
-  if (of && !(v.f & F_BUFFER)) {
-    if ((ofp = fopen(of, (v.f & F_BINARY) ? "wb" : "w")) == 0) {
-      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-         of, strerror(errno));
-    }
-    rfp = ofp;
-  } else if ((rfp = tmpfile()) == 0)
-    die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno));
-
-  /* --- Read the message and verify the signature --- */
-
-  sig_hash(&s);
-  for (;;) {
-    n = mc_in.read(&mc_in, bb);
-    if (!n) break;
-    dohash(s.s->h, bb, n);
-    if (rfp) fwrite(bb, 1, n, rfp);
-  }
-  mc_endread(&mc_in, eo, &e);
-  if (!(v.f & F_DETACH))
-    sig_readsig(e, &s);
-  if (rfp && (ferror(rfp) || fflush(rfp))) {
-    if (v.verb) printf("FAIL error writing message: %s\n", strerror(errno));
-    exit(EXIT_FAILURE);
-  }
-
-  /* --- Check the signature --- */
-
-  if (s.s->ops->doit(s.s, &s.sig)) {
-    if (v.verb) printf("FAIL signature verification failed\n");
-    exit(EXIT_FAILURE);
-  }
-  if (t_fresh && s.t < t_fresh) {
-    if (v.verb) printf("FAIL signature is stale\n");
-    exit(EXIT_FAILURE);
-  }
-  if (s.t > time(0)) {
-    if (v.verb) printf("FAIL signature timestamp in the future\n");
-    exit(EXIT_FAILURE);
-  }
-  if (v.verb) {
-    tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t);
-    strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm);
-    printf("INFO good-signature %s\n", d.buf);
-    printf("INFO date %s\n", bb);
-  }
-
-  /* --- Unbuffer buffered input --- */
-
-  if (v.f & F_BUFFER) {
-    if (!ofp && (ofp = fopen(of, "wb")) == 0) {
-      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-         of, strerror(errno));
-    }
-    rewind(rfp);
-    if (v.f & F_PROGRESS) fprogress_init(&ff, "copying buffer", rfp);
-    if (v.verb && ofp == stdout) printf("DATA\n");
-    for (;;) {
-      n = fread(bb, 1, sizeof(bb), rfp);
-      if (!n) break;
-      if (v.f & F_PROGRESS) fprogress_update(&ff, n);
-      if (fwrite(bb, 1, n, ofp) < n) {
-       if (v.f & F_PROGRESS) fprogress_done(&ff);
-       die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
-      }
-    }
-    if (v.f & F_PROGRESS) fprogress_done(&ff);
-    if (ferror(rfp) || fclose(rfp))
-      die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno));
-  }
-  if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
-      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
-
-  /* --- Tidy up --- */
-
-  e->ops->decdone(e);
-  if (v.verb && ofp != stdout)
-    printf("OK verified successfully\n");
-  freeenc(e);
-  key_close(&kf);
-  sig_destroy(&s);
-  dstr_destroy(&d);
-  dstr_destroy(&dd);
-  return (0);
-}
-
-/*----- Reformatting ------------------------------------------------------*/
-
-static int format(int argc, char *argv[])
-{
-  const char *ief = "binary", *oef = "binary";
-  const char *fn, *dfn = 0, *of = 0, *mf = 0;
-  sigmsg s;
-  FILE *fp, *ofp = 0, *mfp = 0;
-  int i;
-  size_t n;
-  msgcanon mc_in = MC_INIT, mc_out = MC_INIT;
-  char bb[MSGBUFSZ];
-  vrfctx v = { 0, 0, 1 };
-  unsigned f = 0, fm = ~F_SIGMASK, sf;
-  const encops *ieo, *oeo;
-  enc *ie, *oe;
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "armour-in",   0,              0,      'a' },
-      { "armor-in",    0,              0,      'a' },
-      { "armour-out",  0,              0,      'A' },
-      { "armor-out",   0,              0,      'A' },
-      { "detach",      0,              0,      'D' },
-      { "embed",       0,              0,      'E' },
-      { "format-in",   OPTF_ARGREQ,    0,      'f' },
-      { "format-out",  OPTF_ARGREQ,    0,      'F' },
-      { "message",     OPTF_ARGREQ,    0,      'm' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
-      { "progress",    0,              0,      'p' },
-      { 0,             0,              0,      0 }
-    };
-    i = mdwopt(argc, argv, "f:F:m:o:apADE", opt, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'a': ief = "pem"; break;
-      case 'A': oef = "pem"; break;
-      case 'f': ief = optarg; break;
-      case 'F': oef = optarg; break;
-      case 'D': f |= F_DETACH; fm |= F_DETACH; break;
-      case 'E': f &= ~F_DETACH; fm |= F_DETACH; break;
-      case 'm': mf = optarg; break;
-      case 'o': of = optarg; break;
-      case 'p': f |= F_PROGRESS; break;
-      default: f |= F_BOGUS; break;
-    }
-  }
-
-  if (argc - optind > 2 || (f & F_BOGUS))
-    die(EXIT_FAILURE, "Usage: format [-OPTIONS] [FILE [MESSAGE]]");
-
-  if ((ieo = getenc(ief)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", ief);
-  if ((oeo = getenc(oef)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", oef);
-
-  fn = optind < argc ? argv[optind++] : "-";
-  if (strcmp(fn, "-") == 0)
-    fp = stdin;
-  else if ((fp = fopen(fn, ieo->rmode)) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s': %s",
-       fn, strerror(errno));
-  }
-
-  if (optind < argc)
-    dfn = argv[optind++];
-
-  ie = initdec(ieo, fp, vrfbdry, &v);
-
-  /* --- Read the header chunk --- */
-
-  sig_readheader(ie, &s, diechoke, "malformed header");
-
-  if (((s.f ^ v.f) & v.m) != 0)
-    moan("boundary string inconsistent with contents (ignoring)");
-
-  mcsetup_read(&mc_in, s.f, &ie, fn, dfn);
-
-  /* --- Prepare the output stuff --- */
-
-  if (!of && !mf) of = "-";
-  sf = s.f;
-  f = (f & fm) | (s.f & ~fm);
-  s.f = f & F_SIGMASK;
-
-  if (sf & F_DETACH)
-    sig_readsig(ie, &s);
-
-  if (!of)
-    mcsetup_writenull(&mc_out);
-  else {
-    if (strcmp(of, "-") == 0)
-      ofp = stdout;
-    else if ((ofp = fopen(of, oeo->wmode)) == 0) {
-      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-         of, strerror(errno));
-    }
-    oe = initenc(oeo, ofp,
-                (f & F_DETACH) ? "CATSIGN SIGNATURE" :
-                (f & F_BINARY) ? "CATSIGN MESSAGE" :
-                "CATSIGN MESSAGE HEADER");
-    sig_writeheader(oe, &s);
-    mcsetup_write(&mc_out, f, &oe);
-  }
-
-  if (mf) {
-    if (strcmp(mf, "-") == 0)
-      mfp = stdout;
-    else if ((mfp = fopen(mf, (f & F_BINARY) ? "wb" : "w")) == 0) {
-      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-         mf, strerror(errno));
-    }
-  }
-
-  /* --- Wade through the message body --- */
-
-  for (;;) {
-    n = mc_in.read(&mc_in, bb);
-    if (!n) break;
-    mc_out.write(&mc_out, bb, n);
-    if (mfp) fwrite(bb, 1, n, mfp);
-  }
-  mc_endread(&mc_in, ieo, &ie);
-  if (of) mc_endwrite(&mc_out, oeo, &oe);
-
-  /* --- Write the signature --- */
-
-  if (!(sf & F_DETACH))
-    sig_readsig(ie, &s);
-  if (of) {
-    sig_writesig(oe, &s);
-    oe->ops->encdone(oe);
-  }
-
-  /* --- All done --- */
-
-  ie->ops->decdone(ie);
-  if (ferror(fp) || fclose(fp))
-    die(EXIT_FAILURE, "error reading input signature: %s", strerror(errno));
-  if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
-    die(EXIT_FAILURE, "error writing output signature: %s", strerror(errno));
-  if (mfp && (fflush(mfp) || ferror(mfp) || fclose(mfp)))
-    die(EXIT_FAILURE, "error writing output message: %s", strerror(errno));
-  freeenc(ie);
-  if (of) freeenc(oe);
-  sig_destroy(&s);
-  return (0);
-}
-
-static void infochoke(const char *m, void *p)
-{
-  vrfctx *v = p;
-  printf("BAD %s: %s\n", v->what, m);
-  exit(EXIT_FAILURE);
-}
-
-static void infokeyreport(const char *file, int line,
-                         const char *err, void *p)
-{ /*whatever*/; }
-
-static int info(int argc, char *argv[])
-{
-  const char *ef = "binary";
-  vrfctx v = { 0, 0, 1 };
-  key_file kf;
-  key *k;
-  sigmsg s;
-  FILE *fp;
-  int i;
-  struct tm *tm;
-  char bb[256];
-  dstr d = DSTR_INIT;
-  const encops *eo;
-  enc *e;
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "armour",      0,              0,      'a' },
-      { "armor",       0,              0,      'a' },
-      { "format",      OPTF_ARGREQ,    0,      'f' },
-      { "gmt",         0,              0,      'u' },
-      { "utc",         0,              0,      'u' },
-      { 0,             0,              0,      0 }
-    };
-    i = mdwopt(argc, argv, "f:au", opt, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'a': ef = "pem"; break;
-      case 'f': ef = optarg; break;
-      case 'u': v.f |= F_UTC; break;
-      default: v.f |= F_BOGUS; break;
-    }
-  }
-  if (argc - optind > 1 || (v.f & F_BOGUS))
-    die(EXIT_FAILURE, "Usage: info [-OPTIONS] [FILE]");
-
-  if ((eo = getenc(ef)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", ef);
-
-  if (optind >= argc)
-    fp = stdin;
-  else if (strcmp(argv[optind], "-") == 0) {
-    fp = stdin;
-    optind++;
-  } else if ((fp = fopen(argv[optind], eo->rmode)) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s': %s",
-       argv[optind], strerror(errno));
-  } else
-    optind++;
-
-  if (key_open(&kf, keyring, KOPEN_READ, infokeyreport, 0)) {
-    printf("NOTE can't open keyring `%s'\n", keyring);
-    keyring = 0;
-  }
-  e = initdec(eo, fp, vrfbdry, &v);
-
-  v.what = "malformed header";
-  sig_readheader(e, &s, infochoke, &v);
-
-  printf("INFO flags %sdetach %sbinary\n",
-        (s.f & F_DETACH) ? "" : "!",
-        (s.f & F_BINARY) ? "" : "!");
-
-  if (((s.f ^ v.f) & v.m) != 0) {
-    printf("WARN boundary string inconsistent with contents\n");
-    printf("INFO expected-flags");
-    if (v.m & F_DETACH) printf(" %sdetach", (v.f & F_DETACH) ? "" : "!");
-    if (v.m & F_BINARY) printf(" %sbinary", (v.f & F_BINARY) ? "" : "!");
-    putchar('\n');
-  }
-  v.f |= s.f;
-
-  tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t);
-  strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm);
-  printf("INFO date %s\n", bb);
-
-  if (keyring && (k = key_byid(&kf, s.keyid)) != 0) {
-    dstr_reset(&d); key_fulltag(k, &d);
-    printf("INFO key %s\n", d.buf);
-  } else
-    printf("INFO unknown-key %08lx\n", (unsigned long)s.keyid);
-
-  if (keyring) key_close(&kf);
-  dstr_destroy(&d);
-  sig_destroy(&s);
-  return (0);
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-#define LISTS(LI)                                                      \
-  LI("Lists", list,                                                    \
-     listtab[i].name, listtab[i].name)                                 \
-  LI("Signature schemes", sig,                                         \
-     sigtab[i].name, sigtab[i].name)                                   \
-  LI("Encodings", enc,                                                 \
-     enctab[i].name, enctab[i].name)                                   \
-  LI("Hash functions", hash,                                           \
-     ghashtab[i], ghashtab[i]->name)
-
-MAKELISTTAB(listtab, LISTS)
-
-int cmd_show(int argc, char *argv[])
-{
-  return (displaylists(listtab, argv + 1));
-}
-
-static int cmd_help(int, char **);
-
-static cmd cmdtab[] = {
-  { "help", cmd_help, "help [COMMAND...]" },
-  { "show", cmd_show, "show [ITEM...]" },
-  CMD_ENCODE,
-  CMD_DECODE,
-  { "sign", sign,
-    "sign [-adptC] [-k TAG] [-f FORMAT] [-o OUTPUT] [FILE]", "\
-Options:\n\
-\n\
--a, --armour           Same as `-f pem'.\n\
--b, --binary           Treat the input message as binary data.\n\
--d, --detach           Produce a detached signature.\n\
--f, --format=FORMAT    Encode as FORMAT.\n\
--k, --key=TAG          Use public encryption key named by TAG.\n\
--o, --output=FILE      Write output to FILE.\n\
--p, --progress         Show progress on large files.\n\
--t, --text             Canonify input message as a text file.\n\
--C, --nocheck          Don't check the private key.\n\
-" },
-  { "verify", verify,
-    "verify [-abpquvC] [-f FORMAT] [-k TAG] [-o OUTPUT]\n\t\
-[FILE [MESSAGE]]", "\
-Options:\n\
-\n\
--a, --armour           Same as `-f pem'.\n\
--b, --buffer           Buffer message until signature is verified.\n\
--f, --format=FORMAT    Decode as FORMAT.\n\
--k, --key=TAG          Require that the message be signed by key TAG.\n\
--o, --output=FILE      Write message to FILE.\n\
--p, --progress         Show progress on large files.\n\
--q, --quiet            Produce fewer messages.\n\
--t, --freshtime=TIME   Only accept signatures made after this time.\n\
--u, --utc              Show dates in UTC rather than local time.\n\
--v, --verbose          Produce more verbose messages.\n\
--C, --nocheck          Don't check the public key.\n\
-" },
-  { "info", info,
-    "info [-au] [-f FORMAT] [FILE]", "\
-Options:\n\
-\n\
--a, --armour           Same as `-f pem'.\n\
--f, --format=FORMAT    Decode as FORMAT.\n\
--u, --utc              Show dates in UTC rather than local time.\n\
-"},
-  { "format", format,
-    "format [-apuADE] [-f FORMAT] [-F format] [-m FILE] [-o FILE]\n\t\
-[FILE [MESSAGE]]", "\
-Options:\n\
-\n\
--a, --armour-in                Same as `-f pem'.\n\
--A, --armour-out       Same as `-F pem'.\n\
--D, --detach           Create detached signature.\n\
--E, --embed            Create signature with embedded message.\n\
--f, --format-in=FORMAT Decode input as FORMAT.\n\
--F, --format-out=FORMAT        Encode output as FORMAT.\n\
--m, --message=FILE     Write message to FILE.\n\
--o, --output=FILE      Write new signature to FILE.\n\
--p, --progress         Show progress on large files.\n\
-"},
-  { 0, 0, 0 }
-}; /* " Emacs seems confused. */
-
-static int cmd_help(int argc, char **argv)
-{
-  sc_help(cmdtab, stdout, argv + 1);
-  return (0);
-}
-
-void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n");
-}
-
-void help_global(FILE *fp)
-{
-  usage(fp);
-  fputs("\n\
-Sign and verify data.\n\
-\n\
-Global command-line options:\n\
-\n\
--h, --help [COMMAND...]        Show this help message, or help for COMMANDs.\n\
--v, --version          Show program version number.\n\
--u, --usage            Show a terse usage message.\n\
-\n\
--k, --keyring=FILE     Read keys from FILE.\n",
-       fp);
-}
-
-/* --- @main@ --- *
- *
- * Arguments:  @int argc@ = number of command line arguments
- *             @char *argv[]@ = vector of command line arguments
- *
- * Returns:    Zero if successful, nonzero otherwise.
- *
- * Use:                Encrypts or decrypts files.
- */
-
-int main(int argc, char *argv[])
-{
-  unsigned f = 0;
-
-#define f_bogus 1u
-
-  /* --- Initialize the library --- */
-
-  ego(argv[0]);
-  sub_init();
-  rand_noisesrc(RAND_GLOBAL, &noise_source);
-  rand_seed(RAND_GLOBAL, 160);
-/*   trace_on(stderr, 1); */
-
-  /* --- Parse options --- */
-
-  for (;;) {
-    static struct option opts[] = {
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'v' },
-      { "usage",       0,              0,      'u' },
-      { "keyring",     OPTF_ARGREQ,    0,      'k' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'h':
-       sc_help(cmdtab, stdout, argv + optind);
-       exit(0);
-       break;
-      case 'v':
-       version(stdout);
-       exit(0);
-       break;
-      case 'u':
-       usage(stdout);
-       exit(0);
-      case 'k':
-       keyring = optarg;
-       break;
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-
-  argc -= optind;
-  argv += optind;
-  optind = 0;
-  if (f & f_bogus || argc < 1) {
-    usage(stderr);
-    exit(EXIT_FAILURE);
-  }
-
-  /* --- Dispatch to the correct subcommand handler --- */
-
-  return (findcmd(cmdtab, argv[0])->cmd(argc, argv));
-
-#undef f_bogus
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cbc-def.h b/cbc-def.h
deleted file mode 100644 (file)
index d14c952..0000000
--- a/cbc-def.h
+++ /dev/null
@@ -1,549 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cbc-def.h,v 1.6 2004/04/17 09:58:36 mdw Exp $
- *
- * Definitions for cipher block chaining mode
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_CBC_DEF_H
-#define CATACOMB_CBC_DEF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_BLKC_H
-#  include "blkc.h"
-#endif
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @CBC_DEF@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use:                Creates an implementation for CBC stealing mode.
- */
-
-#define CBC_DEF(PRE, pre)                                              \
-                                                                       \
-/* --- @pre_cbcgetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @const pre_cbcctx *ctx@ = pointer to CBC context block  \
- *             @void *iv@ = pointer to output data block               \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Reads the currently set IV.  Reading and setting an IV  \
- *             is transparent to the CBC encryption or decryption      \
- *             process.                                                \
- */                                                                    \
-                                                                       \
-void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv)                 \
-{                                                                      \
-  BLKC_STORE(PRE, iv, ctx->iv);                                                \
-}                                                                      \
-                                                                       \
-/* --- @pre_cbcsetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
- *             @cnost void *iv@ = pointer to IV to set                 \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the IV to use for subsequent encryption.           \
- */                                                                    \
-                                                                       \
-void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv)                 \
-{                                                                      \
-  BLKC_LOAD(PRE, ctx->iv, iv);                                         \
-}                                                                      \
-                                                                       \
-/* --- @pre_cbcsetkey@ --- *                                           \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the CBC context to use a different cipher key.     \
- */                                                                    \
-                                                                       \
-void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k)            \
-{                                                                      \
-  ctx->ctx = *k;                                                       \
-}                                                                      \
-                                                                       \
-/* --- @pre_cbcinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to cipher context           \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a CBC context ready for use.  The @iv@      \
- *             argument may be passed as a null pointer to set a zero  \
- *             IV.  Apart from that, this call is equivalent to calls  \
- *             to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@.      \
- */                                                                    \
-                                                                       \
-void pre##_cbcinit(pre##_cbcctx *ctx,                                  \
-                    const void *key, size_t sz,                        \
-                    const void *iv)                                    \
-{                                                                      \
-  static const octet zero[PRE##_BLKSZ] = { 0 };                                \
-  pre##_init(&ctx->ctx, key, sz);                                      \
-  BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero);                             \
-}                                                                      \
-                                                                       \
-/* --- @pre_cbcencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts a block with a block cipher in CBC mode, with  \
- *             ciphertext stealing and other clever tricks.            \
- *             Essentially, data can be encrypted in arbitrary sized   \
- *             chunks, although decryption must use the same chunks.   \
- */                                                                    \
-                                                                       \
-void pre##_cbcencrypt(pre##_cbcctx *ctx,                               \
-                       const void *src, void *dest,                    \
-                       size_t sz)                                      \
-{                                                                      \
-  const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz)                                                             \
-    return;                                                            \
-                                                                       \
-  /* --- Extra magical case for a short block --- *                    \
-   *                                                                   \
-   * Encrypt the IV, then exclusive-or the plaintext with the octets   \
-   * of the encrypted IV, shifting ciphertext octets in instead.  This \
-   * basically switches over to CFB.                                   \
-   */                                                                  \
-                                                                       \
-  if (sz < PRE##_BLKSZ) {                                              \
-    octet b[PRE##_BLKSZ];                                              \
-    unsigned i;                                                                \
-                                                                       \
-    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
-    BLKC_STORE(PRE, b, ctx->iv);                                       \
-    if (d) {                                                           \
-      for (i = 0; i < sz; i++)                                         \
-       d[i] = b[i] ^ (s ? s[i] : 0);                                   \
-    }                                                                  \
-    memmove(b, b + sz, PRE##_BLKSZ - sz);                              \
-    memcpy(b + PRE##_BLKSZ - sz, d, sz);                               \
-    BLKC_LOAD(PRE, ctx->iv, b);                                                \
-    return;                                                            \
-  }                                                                    \
-                                                                       \
-  /* --- Do the main chunk of encryption --- *                         \
-   *                                                                   \
-   * This will do the whole lot if it's a whole number of blocks.  For \
-   * each block, XOR it with the previous ciphertext in @iv@, encrypt, \
-   * and keep a copy of the ciphertext for the next block.             \
-   */                                                                  \
-                                                                       \
-  while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                 \
-    if (s) {                                                           \
-      BLKC_XLOAD(PRE, ctx->iv, s);                                     \
-      s += PRE##_BLKSZ;                                                        \
-    }                                                                  \
-    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
-    if (d) {                                                           \
-      BLKC_STORE(PRE, d, ctx->iv);                                     \
-      d += PRE##_BLKSZ;                                                        \
-    }                                                                  \
-    sz -= PRE##_BLKSZ;                                                 \
-  }                                                                    \
-                                                                       \
-  /* --- Do the tail-end block and bit-left-over --- *                 \
-   *                                                                   \
-   * This isn't very efficient.  That shouldn't matter much.           \
-   */                                                                  \
-                                                                       \
-  if (sz) {                                                            \
-    octet b[PRE##_BLKSZ];                                              \
-    unsigned i;                                                                \
-                                                                       \
-    /* --- Let @sz@ be the size of the partial block --- */            \
-                                                                       \
-    sz -= PRE##_BLKSZ;                                                 \
-                                                                       \
-    /* --- First stage --- *                                           \
-     *                                                                 \
-     * XOR the complete block with the current IV, and encrypt it.  The        \
-     * first part of the result is the partial ciphertext block.  Don't        \
-     * write that out yet, because I've not read the partial plaintext \
-     * block.                                                          \
-     */                                                                        \
-                                                                       \
-    if (s) BLKC_XLOAD(PRE, ctx->iv, s);                                        \
-    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
-    BLKC_STORE(PRE, b, ctx->iv);                                       \
-                                                                       \
-    /* --- Second stage --- *                                          \
-     *                                                                 \
-     * Now XOR in the partial plaintext block, writing out the         \
-     * ciphertext as I go.  Then encrypt, and write the complete       \
-     * ciphertext block.                                               \
-     */                                                                        \
-                                                                       \
-    if (s) s += PRE##_BLKSZ;                                           \
-    if (d) d += PRE##_BLKSZ;                                           \
-    for (i = 0; i < sz; i++) {                                         \
-      register octet x = b[i];                                         \
-      if (s) b[i] ^= s[i];                                             \
-      if (d) d[i] = x;                                                 \
-    }                                                                  \
-    BLKC_LOAD(PRE, ctx->iv, b);                                                \
-    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
-    if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv);                  \
-  }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  return;                                                              \
-}                                                                      \
-                                                                       \
-/* --- @pre_cbcdecrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Decrypts a block with a block cipher in CBC mode, with  \
- *             ciphertext stealing and other clever tricks.            \
- *             Essentially, data can be encrypted in arbitrary sized   \
- *             chunks, although decryption must use the same chunks.   \
- */                                                                    \
-                                                                       \
-void pre##_cbcdecrypt(pre##_cbcctx *ctx,                               \
-                       const void *src, void *dest,                    \
-                       size_t sz)                                      \
-{                                                                      \
-  const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz)                                                             \
-    return;                                                            \
-                                                                       \
-  /* --- Extra magical case for a short block --- *                    \
-   *                                                                   \
-   * Encrypt the IV, then exclusive-or the ciphertext with the octets  \
-   * of the encrypted IV, shifting ciphertext octets in instead.  This \
-   * basically switches over to CFB.                                   \
-   */                                                                  \
-                                                                       \
-  if (sz < PRE##_BLKSZ) {                                              \
-    octet b[PRE##_BLKSZ], c[PRE##_BLKSZ];                              \
-    unsigned i;                                                                \
-                                                                       \
-    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
-    BLKC_STORE(PRE, b, ctx->iv);                                       \
-    for (i = 0; i < sz; i++) {                                         \
-      register octet x = s[i];                                         \
-      d[i] = b[i] ^ x;                                                 \
-      c[i] = x;                                                                \
-    }                                                                  \
-    memmove(b, b + sz, PRE##_BLKSZ - sz);                              \
-    memcpy(b + PRE##_BLKSZ - sz, c, sz);                               \
-    BLKC_LOAD(PRE, ctx->iv, b);                                                \
-    return;                                                            \
-  }                                                                    \
-                                                                       \
-  /* --- Do the main chunk of decryption --- *                         \
-   *                                                                   \
-   * This will do the whole lot if it's a whole number of blocks.  For \
-   * each block, decrypt, XOR it with the previous ciphertext in @iv@, \
-   * and keep a copy of the ciphertext for the next block.             \
-   */                                                                  \
-                                                                       \
-  while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                 \
-    uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4];                   \
-    BLKC_LOAD(PRE, niv, s);                                            \
-    pre##_dblk(&ctx->ctx, niv, b);                                     \
-    BLKC_XSTORE(PRE, d, b, ctx->iv);                                   \
-    BLKC_MOVE(PRE, ctx->iv, niv);                                      \
-    s += PRE##_BLKSZ;                                                  \
-    d += PRE##_BLKSZ;                                                  \
-    sz -= PRE##_BLKSZ;                                                 \
-  }                                                                    \
-                                                                       \
-  /* --- Do the tail-end block and bit-left-over --- *                 \
-   *                                                                   \
-   * This isn't very efficient.  That shouldn't matter much.           \
-   */                                                                  \
-                                                                       \
-  if (sz) {                                                            \
-    octet b[PRE##_BLKSZ];                                              \
-    uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4];                  \
-    unsigned i;                                                                \
-                                                                       \
-    /* --- Let @sz@ be the size of the partial block --- */            \
-                                                                       \
-    sz -= PRE##_BLKSZ;                                                 \
-                                                                       \
-    /* --- First stage --- *                                           \
-     *                                                                 \
-     * Take the complete ciphertext block, and decrypt it.  This block \
-     * is carried over for the next encryption operation.              \
-     */                                                                        \
-                                                                       \
-    BLKC_LOAD(PRE, niv, s);                                            \
-    pre##_dblk(&ctx->ctx, niv, bk);                                    \
-                                                                       \
-    /* --- Second stage --- *                                          \
-     *                                                                 \
-     * XORing the first few bytes of this with the partial ciphertext  \
-     * block recovers the partial plaintext block.  At the same time,  \
-     * write the partial ciphertext block's contents in ready for stage        \
-     * three.                                                          \
-     */                                                                        \
-                                                                       \
-    BLKC_STORE(PRE, b, bk);                                            \
-    s += PRE##_BLKSZ;                                                  \
-    d += PRE##_BLKSZ;                                                  \
-    for (i = 0; i < sz; i++) {                                         \
-      register octet x = s[i];                                         \
-      d[i] = b[i] ^ x;                                                 \
-      b[i] = x;                                                                \
-    }                                                                  \
-                                                                       \
-    /* --- Third stage --- *                                           \
-     *                                                                 \
-     * Decrypt the block we've got left, and XOR with the initial IV to        \
-     * recover the complete plaintext block.                           \
-     */                                                                        \
-                                                                       \
-    BLKC_LOAD(PRE, bk, b);                                             \
-    pre##_dblk(&ctx->ctx, bk, bk);                                     \
-    BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv);                    \
-    BLKC_MOVE(PRE, ctx->iv, niv);                                      \
-  }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  return;                                                              \
-}                                                                      \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-static const gcipher_ops gops;                                         \
-                                                                       \
-typedef struct gctx {                                                  \
-  gcipher c;                                                           \
-  pre##_cbcctx k;                                                      \
-} gctx;                                                                        \
-                                                                       \
-static gcipher *ginit(const void *k, size_t sz)                                \
-{                                                                      \
-  gctx *g = S_CREATE(gctx);                                            \
-  g->c.ops = &gops;                                                    \
-  pre##_cbcinit(&g->k, k, sz, 0);                                      \
-  return (&g->c);                                                      \
-}                                                                      \
-                                                                       \
-static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cbcencrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
-                                                                       \
-static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cbcdecrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
-                                                                       \
-static void gdestroy(gcipher *c)                                       \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static void gsetiv(gcipher *c, const void *iv)                         \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cbcsetiv(&g->k, iv);                                           \
-}                                                                      \
-                                                                       \
-static const gcipher_ops gops = {                                      \
-  &pre##_cbc,                                                          \
-  gencrypt, gdecrypt, gdestroy, gsetiv, 0                              \
-};                                                                     \
-                                                                       \
-const gccipher pre##_cbc = {                                           \
-  #pre "-cbc", pre##_keysz, PRE##_BLKSZ,                               \
-  ginit                                                                        \
-};                                                                     \
-                                                                       \
-CBC_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @CBC_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use:                Standard test rig for CBC functions.
- */
-
-#define CBC_TEST(PRE, pre)                                             \
-                                                                       \
-/* --- Initial plaintext for the test --- */                           \
-                                                                       \
-static const octet text[] = TEXT;                                      \
-                                                                       \
-/* --- Key and IV to use --- */                                                \
-                                                                       \
-static const octet key[] = KEY;                                                \
-static const octet iv[] = IV;                                          \
-                                                                       \
-/* --- Buffers for encryption and decryption output --- */             \
-                                                                       \
-static octet ct[sizeof(text)];                                         \
-static octet pt[sizeof(text)];                                         \
-                                                                       \
-static void hexdump(const octet *p, size_t sz)                         \
-{                                                                      \
-  const octet *q = p + sz;                                             \
-  for (sz = 0; p < q; p++, sz++) {                                     \
-    printf("%02x", *p);                                                        \
-    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
-      putchar(':');                                                    \
-  }                                                                    \
-}                                                                      \
-                                                                       \
-int main(void)                                                         \
-{                                                                      \
-  size_t sz = 0, rest;                                                 \
-  pre##_cbcctx ctx;                                                    \
-  pre##_ctx k;                                                         \
-  int status = 0;                                                      \
-  int done = 0;                                                                \
-                                                                       \
-  size_t keysz = PRE##_KEYSZ ?                                         \
-    PRE##_KEYSZ : strlen((const char *)key);                           \
-                                                                       \
-  fputs(#pre "-cbc: ", stdout);                                                \
-                                                                       \
-  pre##_init(&k, key, keysz);                                          \
-  pre##_cbcsetkey(&ctx, &k);                                           \
-                                                                       \
-  while (sz <= sizeof(text)) {                                         \
-    rest = sizeof(text) - sz;                                          \
-    memcpy(ct, text, sizeof(text));                                    \
-    pre##_cbcsetiv(&ctx, iv);                                          \
-    pre##_cbcencrypt(&ctx, ct, ct, sz);                                        \
-    pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest);                    \
-    memcpy(pt, ct, sizeof(text));                                      \
-    pre##_cbcsetiv(&ctx, iv);                                          \
-    pre##_cbcdecrypt(&ctx, pt, pt, sz);                                        \
-    pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest);                    \
-    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
-      done++;                                                          \
-      if (sizeof(text) < 40 || done % 8 == 0)                          \
-       fputc('.', stdout);                                             \
-      if (done % 480 == 0)                                             \
-       fputs("\n\t", stdout);                                          \
-      fflush(stdout);                                                  \
-    } else {                                                           \
-      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
-      status = 1;                                                      \
-      printf("\tplaintext      = "); hexdump(text, sz);                        \
-       printf(", "); hexdump(text + sz, rest);                         \
-       fputc('\n', stdout);                                            \
-      printf("\tciphertext     = "); hexdump(ct, sz);                  \
-       printf(", "); hexdump(ct + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      printf("\trecovered text = "); hexdump(pt, sz);                  \
-       printf(", "); hexdump(pt + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      fputc('\n', stdout);                                             \
-    }                                                                  \
-    if (sz < 63)                                                       \
-      sz++;                                                            \
-    else                                                               \
-      sz += 9;                                                         \
-  }                                                                    \
-                                                                       \
-  fputs(status ? " failed\n" : " ok\n", stdout);                       \
-  return (status);                                                     \
-}
-
-#else
-#  define CBC_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/cbc.h b/cbc.h
deleted file mode 100644 (file)
index 651df8a..0000000
--- a/cbc.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cbc.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Ciphertext block chaining for block ciphers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_CBC_H
-#define CATACOMB_CBC_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @CBC_DECL@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use:                Creates declarations for CBC stealing mode.
- */
-
-#define CBC_DECL(PRE, pre)                                             \
-                                                                       \
-/* --- Cipher block chaining context --- */                            \
-                                                                       \
-typedef struct pre##_cbcctx {                                          \
-  pre##_ctx ctx;                       /* Underlying cipher context */ \
-  uint32 iv[PRE##_BLKSZ / 4];          /* Previous ciphertext or IV */ \
-} pre##_cbcctx;                                                                \
-                                                                       \
-/* --- @pre_cbcgetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @const pre_cbcctx *ctx@ = pointer to CBC context block  \
- *             @void *iv@ = pointer to output data block               \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Reads the currently set IV.  Reading and setting an IV  \
- *             is transparent to the CBC encryption or decryption      \
- *             process.                                                \
- */                                                                    \
-                                                                       \
-extern void pre##_cbcgetiv(const pre##_cbcctx */*ctx*/,                        \
-                          void */*iv*/);                               \
-                                                                       \
-/* --- @pre_cbcsetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
- *             @cnost void *iv@ = pointer to IV to set                 \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the IV to use for subsequent encryption.           \
- */                                                                    \
-                                                                       \
-extern void pre##_cbcsetiv(pre##_cbcctx */*ctx*/,                      \
-                          const void */*iv*/);                         \
-                                                                       \
-/* --- @pre_cbcsetkey@ --- *                                           \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the CBC context to use a different cipher key.     \
- */                                                                    \
-                                                                       \
-extern void pre##_cbcsetkey(pre##_cbcctx */*ctx*/,                     \
-                           const pre##_ctx */*k*/);                    \
-                                                                       \
-/* --- @pre_cbcinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to cipher context           \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a CBC context ready for use.  The @iv@      \
- *             argument may be passed as a null pointer to set a zero  \
- *             IV.  Apart from that, this call is equivalent to calls  \
- *             to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@.      \
- */                                                                    \
-                                                                       \
-extern void pre##_cbcinit(pre##_cbcctx */*ctx*/,                       \
-                         const void */*key*/, size_t /*sz*/,           \
-                         const void */*iv*/);                          \
-                                                                       \
-/* --- @pre_cbcencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts a block with a block cipher in CBC mode, with  \
- *             ciphertext stealing and other clever tricks.            \
- *             Essentially, data can be encrypted in arbitrary sized   \
- *             chunks, although decryption must use the same chunks.   \
- */                                                                    \
-                                                                       \
-extern void pre##_cbcencrypt(pre##_cbcctx */*ctx*/,                    \
-                            const void */*src*/, void */*dest*/,       \
-                            size_t /*sz*/);                            \
-                                                                       \
-/* --- @pre_cbcdecrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Decrypts a block with a block cipher in CBC mode, with  \
- *             ciphertext stealing and other clever tricks.            \
- *             Essentially, data can be encrypted in arbitrary sized   \
- *             chunks, although decryption must use the same chunks.   \
- */                                                                    \
-                                                                       \
-extern void pre##_cbcdecrypt(pre##_cbcctx */*ctx*/,                    \
-                            const void */*src*/, void */*dest*/,       \
-                            size_t /*sz*/);                            \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-extern const gccipher pre##_cbc;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/cc-enc.c b/cc-enc.c
deleted file mode 100644 (file)
index 2b8b0fd..0000000
--- a/cc-enc.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Catcrypt data encoding
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include <errno.h>
-#include <stdio.h>
-
-#include <mLib/alloc.h>
-#include <mLib/base64.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include "cc.h"
-
-typedef int encbdryp(const char *, void *);
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Binary --- */
-
-static enc *bin_encinit(FILE *fp, const char *msg)
-  { enc *e = CREATE(enc); return (e); }
-static enc *bin_decinit(FILE *fp, encbdryp *func, void *p)
-  { enc *e = CREATE(enc); return (e); }
-
-static int bin_read(enc *e, void *p, size_t sz)
-{
-  size_t n;
-
-  if (!sz) return (0);
-  n = fread(p, 1, sz, e->fp);
-  if (!n || ferror(e->fp)) return (-1);
-  return (n);
-}
-
-static int bin_write(enc *e, const void *p, size_t sz)
-  { if (sz && fwrite(p, 1, sz, e->fp) < sz) return (-1); return (0); }
-
-static int bin_done(enc *e) { return (0); }
-
-static void bin_destroy(enc *e) { DESTROY(e); }
-
-/* --- PEM --- */
-
-typedef struct pem_encctx {
-  enc e;
-  char *msg;
-  unsigned f;
-  base64_ctx b;
-  dstr d;
-  size_t n;
-#define PEMF_NL 1u
-#define PEMF_EOF 2u
-} pem_encctx;
-
-static enc *pem_encinit(FILE *fp, const char *msg)
-{
-  pem_encctx *pe = CREATE(pem_encctx);
-  base64_init(&pe->b);
-  fprintf(fp, "-----BEGIN %s-----\n", msg);
-  pe->msg = xstrdup(msg);
-  dstr_create(&pe->d);
-  pe->n = 0;
-  pe->f = 0;
-  return (&pe->e);
-}
-
-int checkbdry(const char *b, void *p) { return (!p || strcmp(b, p) == 0); }
-
-static enc *pem_decinit(FILE *fp, encbdryp *func, void *p)
-{
-  char buf[128];
-  int i, d;
-  pem_encctx *pe;
-  int ch;
-
-  /* --- Go until I find a newline and `-----' --- */
-
-top:
-  d = 0;
-  for (;;) {
-    if ((ch = getc(fp)) == EOF) goto fail;
-    switch (ch) {
-      case '\n': d = 0; break;
-      case '-': if (d >= 0) { d++; if (d == 5) goto banner; }; break;
-      default: d = -1; break;
-    }
-  }
-
-  /* --- See what the banner looks like --- */
-
-banner:
-  i = d = 0;
-  for (;;) {
-    if ((ch = getc(fp)) == EOF) goto fail;
-    if (ch == '-') { d++; continue; }
-    if (ch == '\n') break;
-    if (i + d + 1 >= sizeof(buf)) goto top;
-    while (d) { buf[i++] = '-'; d--; }
-    buf[i++] = ch;
-  }
-  buf[i] = 0;
-
-  /* --- Check we have the right framing --- */
-
-  if (d != 5) goto top;
-  if (strncmp(buf, "BEGIN ", 6) != 0 || (func && !func(buf + 6, p)))
-    goto top;
-
-  /* --- Ready --- */
-
-  pe = CREATE(pem_encctx);
-  base64_init(&pe->b);
-  pe->msg = xstrdup(buf + 6);
-  dstr_create(&pe->d);
-  pe->n = 0;
-  pe->f = PEMF_NL;
-  return (&pe->e);
-
-  /* --- Failed --- */
-
-fail:
-  die(EXIT_FAILURE, "initial encapsulation boundary not found");
-  return (0);
-}
-
-#define PEM_CHUNKSZ 4096
-
-static int pem_read(enc *e, void *p, size_t sz)
-{
-  pem_encctx *pe = (pem_encctx *)e;
-  char buf[PEM_CHUNKSZ];
-  char *pp = p;
-  int ch;
-  size_t n;
-  int rc = 0;
-
-  for (;;) {
-    n = pe->d.len - pe->n;
-    if (n > sz) n = sz;
-    memcpy(pp, pe->d.buf + pe->n, n);
-    pe->n += n;
-    pp += n;
-    rc += n;
-    sz -= n;
-    if (!sz) break;
-    if (pe->f & PEMF_EOF) return (rc ? rc : -1);
-    dstr_reset(&pe->d);
-    n = 0;
-    for (;;) {
-      if ((ch = getc(pe->e.fp)) == EOF) return (-1);
-      if ((pe->f & PEMF_NL) && ch == '-') {
-       ungetc(ch, pe->e.fp);
-       pe->f |= PEMF_EOF;
-       break;
-      }
-      if (ch == '\n') { pe->f |= PEMF_NL; continue; }
-      pe->f &= ~PEMF_NL;
-      buf[n++] = ch;
-      if (n >= PEM_CHUNKSZ) break;
-    }
-    if (n)
-      base64_decode(&pe->b, buf, n, &pe->d);
-    if (pe->f & PEMF_EOF)
-      base64_decode(&pe->b, 0, 0, &pe->d);
-    pe->n = 0;
-  }
-  return (rc);
-}
-
-static int pem_write(enc *e, const void *p, size_t sz)
-{
-  pem_encctx *pe = (pem_encctx *)e;
-  const char *pp = p;
-  size_t n;
-
-  while (sz) {
-    n = PEM_CHUNKSZ;
-    if (n > sz) n = sz;
-    dstr_reset(&pe->d);
-    base64_encode(&pe->b, pp, n, &pe->d);
-    if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len)
-      return (-1);
-    pp += n;
-    sz -= n;
-  }
-  return (0);
-}
-
-static int pem_encdone(enc *e)
-{
-  pem_encctx *pe = (pem_encctx *)e;
-  dstr_reset(&pe->d);
-  base64_encode(&pe->b, 0, 0, &pe->d);
-  if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len)
-    return (-1);
-  if (pe->b.lnlen) fputc('\n', pe->e.fp);
-  fprintf(pe->e.fp, "-----END %s-----\n", pe->msg);
-  return (0);
-}
-
-static int pem_decdone(enc *e)
-{
-  pem_encctx *pe = (pem_encctx *)e;
-  char buf[128];
-  int i, d;
-  int ch;
-
-  for (d = 0; d < 5; d++)
-    if ((ch = getc(pe->e.fp)) != '-') goto fail;
-  i = d = 0;
-  for (;;) {
-    if ((ch = getc(pe->e.fp)) == EOF) goto fail;
-    if (ch == '-') { d++; continue; }
-    if (ch == '\n') break;
-    if (i + d + 1 >= sizeof(buf)) goto fail;
-    while (d) { buf[i++] = '-'; d--; }
-    buf[i++] = ch;
-  }
-  if (d != 5) goto fail;
-  buf[i] = 0;
-  if (strncmp(buf, "END ", 4) != 0 || strcmp(buf + 4, pe->msg) != 0)
-    goto fail;
-  return (0);
-
-fail:
-  die(EXIT_FAILURE, "final encapsulation boundary not found");
-  return (-1);
-}
-
-static void pem_destroy(enc *e)
-{
-  pem_encctx *pe = (pem_encctx *)e;
-  dstr_destroy(&pe->d);
-  xfree(pe->msg);
-  DESTROY(pe);
-}
-
-/* --- Encoder table --- */
-
-const encops enctab[] = {
-  { "binary", "rb", "wb", 1, 1,
-    bin_encinit, bin_decinit,
-    bin_read, bin_write,
-    bin_done, bin_done,
-    bin_destroy },
-  { "pem", "r", "w", 3, 4,
-    pem_encinit, pem_decinit,
-    pem_read, pem_write,
-    pem_encdone, pem_decdone,
-    pem_destroy },
-  { 0 }
-};
-
-/* --- @getenc@ --- *
- *
- * Arguments:  @const char *enc@ = name of wanted encoding
- *
- * Returns:    Pointer to encoder operations.
- *
- * Use:                Finds a named encoder or decoder.
- */
-
-const encops *getenc(const char *enc)
-{
-  const encops *eo;
-
-  for (eo = enctab; eo->name; eo++) {
-    if (strcmp(eo->name, enc) == 0)
-      goto e_found;
-  }
-  die(EXIT_FAILURE, "couldn't find encoding `%s'", enc);
-e_found:
-  return (eo);
-}
-
-/* --- @initenc@ --- *
- *
- * Arguments:  @const encops *eo@ = operations (from @getenc@)
- *             @FILE *fp@ = file handle to attach
- *             @const char *msg@ = banner message
- *
- * Returns:    The encoder object.
- *
- * Use:                Initializes an encoder.
- */
-
-enc *initenc(const encops *eo, FILE *fp, const char *msg)
-{
-  enc *e = eo->initenc(fp, msg);
-  e->ops = eo;
-  e->fp = fp;
-  return (e);
-}
-
-/* --- @initdec@ --- *
- *
- * Arguments:  @const encops *eo@ = operations (from @getenc@)
- *             @FILE *fp@ = file handle to attach
- *             @int (*func)(const char *, void *)@ = banner check function
- *             @void *p@ = argument for @func@
- *
- * Returns:    The encoder object.
- *
- * Use:                Initializes an encoder.
- */
-
-enc *initdec(const encops *eo, FILE *fp,
-            int (*func)(const char *, void *), void *p)
-{
-  enc *e = eo->initdec(fp, func, p);
-  e->ops = eo;
-  e->fp = fp;
-  return (e);
-}
-
-/* --- @freeenc@ --- *
- *
- * Arguments:  @enc *e@ = encoder object
- *
- * Returns:    ---
- *
- * Use:                Frees an encoder object.
- */
-
-void freeenc(enc *e) { e->ops->destroy(e); }
-
-/*----- Encoding and decoding commands ------------------------------------*/
-
-int cmd_encode(int argc, char *argv[])
-{
-  const char *fn, *of = 0;
-  FILE *ofp = 0;
-  FILE *fp = 0;
-  const char *ef = "binary";
-  const char *bd = "MESSAGE";
-  fprogress ff;
-  int i;
-  size_t n;
-  char buf[4096];
-  unsigned f = 0;
-  const encops *eo;
-  enc *e;
-
-#define f_bogus 1u
-#define f_progress 2u
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "format",      OPTF_ARGREQ,    0,      'f' },
-      { "boundary",    OPTF_ARGREQ,    0,      'b' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
-      { "progress",    0,              0,      'p' },
-      { 0,             0,              0,      0 }
-    };
-    i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'f': ef = optarg; break;
-      case 'b': bd = optarg; break;
-      case 'o': of = optarg; break;
-      case 'p': f |= f_progress; break;
-      default: f |= f_bogus; break;
-    }
-  }
-  if (argc - optind > 1 || (f & f_bogus))
-    die(EXIT_FAILURE, "Usage: encode [-OPTIONS] [FILE]");
-
-  if ((eo = getenc(ef)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", ef);
-
-  fn = optind < argc ? argv[optind++] : "-";
-  if (strcmp(fn, "-") == 0)
-    fp = stdin;
-  else if ((fp = fopen(fn, "rb")) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s': %s",
-       fn, strerror(errno));
-  }
-
-  if (!of || strcmp(of, "-") == 0)
-    ofp = stdout;
-  else if ((ofp = fopen(of, eo->wmode)) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-       ofp, strerror(errno));
-  }
-
-  e = initenc(eo, ofp, bd);
-
-  if (f & f_progress) {
-    if (fprogress_init(&ff, fn, fp)) {
-      die(EXIT_FAILURE, "failed to initialize progress display: %s",
-         strerror(errno));
-    }
-  }
-
-  do {
-    n = fread(buf, 1, sizeof(buf), fp);
-    if (f & f_progress) fprogress_update(&ff, n);
-    if (e->ops->write(e, buf, n)) {
-      if (f & f_progress) fprogress_done(&ff);
-      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
-    }
-  } while (n == sizeof(buf));
-  if (f & f_progress) fprogress_done(&ff);
-  e->ops->encdone(e);
-  freeenc(e);
-  return (0);
-
-#undef f_bogus
-#undef f_progress
-}
-
-int cmd_decode(int argc, char *argv[])
-{
-  const char *fn, *of = 0;
-  FILE *ofp = 0;
-  FILE *fp = 0;
-  const char *ef = "binary";
-  const char *bd = 0;
-  fprogress ff;
-  int i;
-  char buf[4096];
-  unsigned f = 0;
-  const encops *eo;
-  enc *e;
-
-#define f_bogus 1u
-#define f_progress 2u
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "format",      OPTF_ARGREQ,    0,      'f' },
-      { "boundary",    OPTF_ARGREQ,    0,      'b' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
-      { "progress",    0,              0,      'p' },
-      { 0,             0,              0,      0 }
-    };
-    i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'f': ef = optarg; break;
-      case 'b': bd = optarg; break;
-      case 'o': of = optarg; break;
-      case 'p': f |= f_progress; break;
-      default: f |= f_bogus; break;
-    }
-  }
-  if (argc - optind > 1 || (f & f_bogus))
-    die(EXIT_FAILURE, "Usage: decode [-OPTIONS] [FILE]");
-
-  if ((eo = getenc(ef)) == 0)
-    die(EXIT_FAILURE, "encoding `%s' not found", ef);
-
-  fn = optind < argc ? argv[optind++] : "-";
-  if (strcmp(fn, "-") == 0)
-    fp = stdin;
-  else if ((fp = fopen(fn, eo->rmode)) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s': %s",
-       fn, strerror(errno));
-  }
-
-  if (!of || strcmp(of, "-") == 0)
-    ofp = stdout;
-  else if ((ofp = fopen(of, "wb")) == 0) {
-    die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
-       ofp, strerror(errno));
-  }
-
-  e = initdec(eo, fp, checkbdry, (/*unconst*/ void *)bd);
-
-  if (f & f_progress) {
-    if (fprogress_init(&ff, fn, fp)) {
-      die(EXIT_FAILURE, "failed to initialize progress display: %s",
-         strerror(errno));
-    }
-  }
-
-  do {
-    if ((i = e->ops->read(e, buf, sizeof(buf))) < 0) {
-      if (f & f_progress) fprogress_done(&ff);
-      die(EXIT_FAILURE, "error reading input: %s", strerror(errno));
-    }
-    if (f & f_progress)
-      fprogress_update(&ff, i*e->ops->ncook/e->ops->nraw);
-    if (fwrite(buf, 1, i, ofp) < i) {
-      if (f & f_progress) fprogress_done(&ff);
-      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
-    }
-  } while (i == sizeof(buf));
-  e->ops->decdone(e);
-  if (f & f_progress) fprogress_done(&ff);
-  freeenc(e);
-  return (0);
-
-#undef f_bogus
-#undef f_progress
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cc-kem.c b/cc-kem.c
deleted file mode 100644 (file)
index 63199fc..0000000
--- a/cc-kem.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Catcrypt key-encapsulation
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include <stdlib.h>
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include "mprand.h"
-#include "rand.h"
-
-#include "ec.h"
-#include "ec-keys.h"
-#include "dh.h"
-#include "rsa.h"
-
-#include "rmd160.h"
-#include "blowfish-cbc.h"
-
-#include "cc.h"
-
-/*----- Key encapsulation -------------------------------------------------*/
-
-/* --- RSA --- */
-
-typedef struct rsa_encctx {
-  kem k;
-  rsa_pubctx rp;
-} rsa_encctx;
-
-static kem *rsa_encinit(key *k, void *kd)
-{
-  rsa_encctx *re = CREATE(rsa_encctx);
-  rsa_pubcreate(&re->rp, kd);
-  return (&re->k);
-}
-
-static int rsa_encdoit(kem *k, dstr *d, ghash *h)
-{
-  rsa_encctx *re = (rsa_encctx *)k;
-  mp *x = mprand_range(MP_NEW, re->rp.rp->n, &rand_global, 0);
-  mp *y = rsa_pubop(&re->rp, MP_NEW, x);
-  size_t n = mp_octets(re->rp.rp->n);
-  dstr_ensure(d, n);
-  mp_storeb(x, d->buf, n);
-  GH_HASH(h, d->buf, n);
-  mp_storeb(y, d->buf, n);
-  d->len += n;
-  mp_drop(x);
-  mp_drop(y);
-  return (0);
-}
-
-static const char *rsa_lengthcheck(mp *n)
-{
-  if (mp_bits(n) < 1020) return ("key too short");
-  return (0);
-}
-
-static const char *rsa_enccheck(kem *k)
-{
-  rsa_encctx *re = (rsa_encctx *)k;
-  const char *e;
-  if ((e = rsa_lengthcheck(re->rp.rp->n)) != 0) return (e);
-  return (0);
-}
-
-static void rsa_encdestroy(kem *k)
-{
-  rsa_encctx *re = (rsa_encctx *)k;
-  rsa_pubdestroy(&re->rp);
-  DESTROY(re);
-}
-
-static const kemops rsa_encops = {
-  rsa_pubfetch, sizeof(rsa_pub),
-  rsa_encinit, rsa_encdoit, rsa_enccheck, rsa_encdestroy
-};
-
-typedef struct rsa_decctx {
-  kem k;
-  rsa_privctx rp;
-} rsa_decctx;
-
-static kem *rsa_decinit(key *k, void *kd)
-{
-  rsa_decctx *rd = CREATE(rsa_decctx);
-  rsa_privcreate(&rd->rp, kd, &rand_global);
-  return (&rd->k);
-}
-
-static int rsa_decdoit(kem *k, dstr *d, ghash *h)
-{
-  rsa_decctx *rd = (rsa_decctx *)k;
-  mp *x = mp_loadb(MP_NEW, d->buf, d->len);
-  size_t n;
-  char *p;
-
-  if (MP_CMP(x, >=, rd->rp.rp->n)) {
-    mp_drop(x);
-    return (-1);
-  }
-  n = mp_octets(rd->rp.rp->n);
-  p = xmalloc(n);
-  x = rsa_privop(&rd->rp, x, x);
-  mp_storeb(x, p, n);
-  GH_HASH(h, p, n);
-  mp_drop(x);
-  xfree(p);
-  return (0);
-}
-
-static const char *rsa_deccheck(kem *k)
-{
-  rsa_decctx *rd = (rsa_decctx *)k;
-  const char *e;
-  if ((e = rsa_lengthcheck(rd->rp.rp->n)) != 0) return (e);
-  return (0);
-}
-
-static void rsa_decdestroy(kem *k)
-{
-  rsa_decctx *rd = (rsa_decctx *)k;
-  rsa_privdestroy(&rd->rp);
-  DESTROY(rd);
-}
-
-static const kemops rsa_decops = {
-  rsa_privfetch, sizeof(rsa_priv),
-  rsa_decinit, rsa_decdoit, rsa_deccheck, rsa_decdestroy
-};
-
-/* --- DH and EC --- */
-
-typedef struct dh_encctx {
-  kem k;
-  group *g;
-  mp *x;
-  ge *y;
-} dh_encctx;
-
-static dh_encctx *dh_doinit(key *k, const gprime_param *gp, mp *y,
-                           group *(*makegroup)(const gprime_param *),
-                           const char *what)
-{
-  dh_encctx *de = CREATE(dh_encctx);
-  dstr t = DSTR_INIT;
-
-  key_fulltag(k, &t);
-  if ((de->g = makegroup(gp)) == 0)
-    die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf);
-  de->x = MP_NEW;
-  de->y = G_CREATE(de->g);
-  if (G_FROMINT(de->g, de->y, y))
-    die(EXIT_FAILURE, "bad public key `%s'", t.buf);
-  dstr_destroy(&t);
-  return (de);
-}
-
-static dh_encctx *ec_doinit(key *k, const char *cstr, const ec *y)
-{
-  dh_encctx *de = CREATE(dh_encctx);
-  ec_info ei;
-  const char *e;
-  dstr t = DSTR_INIT;
-
-  key_fulltag(k, &t);
-  if ((e = ec_getinfo(&ei, cstr)) != 0 ||
-      (de->g = group_ec(&ei)) == 0)
-    die(EXIT_FAILURE, "bad elliptic curve spec in key `%s': %s", t.buf, e);
-  de->x = MP_NEW;
-  de->y = G_CREATE(de->g);
-  if (G_FROMEC(de->g, de->y, y))
-    die(EXIT_FAILURE, "bad public curve point `%s'", t.buf);
-  dstr_destroy(&t);
-  return (de);
-}
-
-static kem *dh_encinit(key *k, void *kd)
-{
-  dh_pub *dp = kd;
-  dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime");
-  return (&de->k);
-}
-
-static kem *bindh_encinit(key *k, void *kd)
-{
-  dh_pub *dp = kd;
-  dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary");
-  return (&de->k);
-}
-
-static kem *ec_encinit(key *k, void *kd)
-{
-  ec_pub *ep = kd;
-  dh_encctx *de = ec_doinit(k, ep->cstr, &ep->p);
-  return (&de->k);
-}
-
-static int dh_encdoit(kem *k, dstr *d, ghash *h)
-{
-  dh_encctx *de = (dh_encctx *)k;
-  mp *r = mprand_range(MP_NEW, de->g->r, &rand_global, 0);
-  ge *x = G_CREATE(de->g);
-  ge *y = G_CREATE(de->g);
-  size_t n = de->g->noctets;
-  buf b;
-
-  G_EXP(de->g, x, de->g->g, r);
-  G_EXP(de->g, y, de->y, r);
-  dstr_ensure(d, n);
-  buf_init(&b, d->buf, n);
-  G_TORAW(de->g, &b, y);
-  GH_HASH(h, BBASE(&b), BLEN(&b));
-  buf_init(&b, d->buf, n);
-  G_TORAW(de->g, &b, x);
-  GH_HASH(h, BBASE(&b), BLEN(&b));
-  d->len += BLEN(&b);
-  mp_drop(r);
-  G_DESTROY(de->g, x);
-  G_DESTROY(de->g, y);
-  return (0);
-}
-
-static const char *dh_enccheck(kem *k)
-{
-  dh_encctx *de = (dh_encctx *)k;
-  const char *e;
-  if ((e = G_CHECK(de->g, &rand_global)) != 0)
-    return (0);
-  if (group_check(de->g, de->y))
-    return ("public key not in subgroup");
-  return (0);
-}
-
-static void dh_encdestroy(kem *k)
-{
-  dh_encctx *de = (dh_encctx *)k;
-  G_DESTROY(de->g, de->y);
-  mp_drop(de->x);
-  G_DESTROYGROUP(de->g);
-  DESTROY(de);
-}
-
-static const kemops dh_encops = {
-  dh_pubfetch, sizeof(dh_pub),
-  dh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy
-};
-
-static const kemops bindh_encops = {
-  dh_pubfetch, sizeof(dh_pub),
-  bindh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy
-};
-
-static const kemops ec_encops = {
-  ec_pubfetch, sizeof(ec_pub),
-  ec_encinit, dh_encdoit, dh_enccheck, dh_encdestroy
-};
-
-static kem *dh_decinit(key *k, void *kd)
-{
-  dh_priv *dp = kd;
-  dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime");
-  de->x = MP_COPY(dp->x);
-  return (&de->k);
-}
-
-static kem *bindh_decinit(key *k, void *kd)
-{
-  dh_priv *dp = kd;
-  dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary");
-  de->x = MP_COPY(dp->x);
-  return (&de->k);
-}
-
-static kem *ec_decinit(key *k, void *kd)
-{
-  ec_priv *ep = kd;
-  dh_encctx *de = ec_doinit(k, ep->cstr, &ep->p);
-  de->x = MP_COPY(ep->x);
-  return (&de->k);
-}
-
-static int dh_decdoit(kem *k, dstr *d, ghash *h)
-{
-  dh_encctx *de = (dh_encctx *)k;
-  ge *x = G_CREATE(de->g);
-  size_t n = de->g->noctets;
-  void *p = xmalloc(n);
-  buf b;
-  int rc = -1;
-
-  buf_init(&b, d->buf, d->len);
-  if (G_FROMRAW(de->g, &b, x) || group_check(de->g, x))
-    goto done;
-  G_EXP(de->g, x, x, de->x);
-  buf_init(&b, p, n);
-  G_TORAW(de->g, &b, x);
-  GH_HASH(h, BBASE(&b), BLEN(&b));
-  GH_HASH(h, d->buf, d->len);
-  rc = 0;
-done:
-  G_DESTROY(de->g, x);
-  xfree(p);
-  return (rc);
-}
-
-static const kemops dh_decops = {
-  dh_privfetch, sizeof(dh_priv),
-  dh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy
-};
-
-static const kemops bindh_decops = {
-  dh_privfetch, sizeof(dh_priv),
-  bindh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy
-};
-
-static const kemops ec_decops = {
-  ec_privfetch, sizeof(ec_priv),
-  ec_decinit, dh_decdoit, dh_enccheck, dh_encdestroy
-};
-
-/* --- Symmetric --- */
-
-typedef struct symm_ctx {
-  kem k;
-  key_packdef kp;
-  key_bin kb;
-} symm_ctx;
-
-static kem *symm_init(key *k, void *kd)
-{
-  symm_ctx *s;
-  dstr d = DSTR_INIT;
-  int err;
-
-  s = CREATE(symm_ctx);
-
-  key_fulltag(k, &d);
-  s->kp.e = KENC_BINARY;
-  s->kp.p = &s->kb;
-  s->kp.kd = 0;
-
-  if ((err = key_unpack(&s->kp, kd, &d)) != 0) {
-    die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s",
-       d.buf, key_strerror(err));
-  }
-  dstr_destroy(&d);
-  return (&s->k);
-}
-
-static int symm_decdoit(kem *k, dstr *d, ghash *h)
-{
-  symm_ctx *s = (symm_ctx *)k;
-
-  GH_HASH(h, s->kb.k, s->kb.sz);
-  GH_HASH(h, d->buf, d->len);
-  return (0);
-}
-
-static int symm_encdoit(kem *k, dstr *d, ghash *h)
-{
-  dstr_ensure(d, h->ops->c->hashsz);
-  d->len += h->ops->c->hashsz;
-  rand_get(RAND_GLOBAL, d->buf, d->len);
-  return (symm_decdoit(k, d, h));
-}
-
-static const char *symm_check(kem *k) { return (0); }
-
-static void symm_destroy(kem *k)
-  { symm_ctx *s = (symm_ctx *)k; key_unpackdone(&s->kp); }
-
-static const kemops symm_encops = {
-  0, 0,
-  symm_init, symm_encdoit, symm_check, symm_destroy
-};
-
-static const kemops symm_decops = {
-  0, 0,
-  symm_init, symm_decdoit, symm_check, symm_destroy
-};
-
-/* --- The switch table --- */
-
-const struct kemtab kemtab[] = {
-  { "rsa",     &rsa_encops,    &rsa_decops },
-  { "dh",      &dh_encops,     &dh_decops },
-  { "bindh",   &bindh_encops,  &bindh_decops },
-  { "ec",      &ec_encops,     &ec_decops },
-  { "symm",    &symm_encops,   &symm_decops },
-  { 0,         0,              0 }
-};
-
-/* --- @getkem@ --- *
- *
- * Arguments:  @key *k@ = the key to load
- *             @const char *app@ = application name
- *             @int wantpriv@ = nonzero if we want to decrypt
- *
- * Returns:    A key-encapsulating thing.
- *
- * Use:                Loads a key.
- */
-
-kem *getkem(key *k, const char *app, int wantpriv)
-{
-  const char *kalg, *halg = 0, *calg = 0;
-  dstr d = DSTR_INIT;
-  dstr t = DSTR_INIT;
-  size_t n;
-  char *p = 0;
-  const char *q;
-  kem *kk;
-  const struct kemtab *kt;
-  const kemops *ko;
-  void *kd;
-  int e;
-  key_packdef *kp;
-
-  /* --- Setup stuff --- */
-
-  key_fulltag(k, &t);
-
-  /* --- Get the KEM name --- *
-   *
-   * Take the attribute if it's there; otherwise use the key type.
-   */
-
-  n = strlen(app);
-  if ((q = key_getattr(0, k, "kem")) != 0) {
-    dstr_puts(&d, q);
-    p = d.buf;
-  } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') {
-    dstr_puts(&d, k->type);
-    p = d.buf + n + 1;
-  } else
-    die(EXIT_FAILURE, "no KEM for key `%s'", t.buf);
-  kalg = p;
-
-  /* --- Grab the encryption scheme --- *
-   *
-   * Grab it from the KEM if it's there, but override it from the attribute.
-   */
-
-  if (p && (p = strchr(p, '/')) != 0) {
-    *p++ = 0;
-    calg = p;
-  }
-  if ((q = key_getattr(0, k, "cipher")) != 0)
-    calg = q;
-
-  /* --- Grab the hash function --- */
-
-  if (p && (p = strchr(p, '/')) != 0) {
-    *p++ = 0;
-    halg = p;
-  }
-  if ((q = key_getattr(0, k, "hash")) != 0)
-    halg = q;
-
-  /* --- Instantiate the KEM --- */
-
-  for (kt = kemtab; kt->name; kt++) {
-    if (strcmp(kt->name, kalg) == 0)
-      goto k_found;
-  }
-  die(EXIT_FAILURE, "key encapsulation mechanism `%s' not found in key `%s'",
-      kalg, t.buf);
-k_found:;
-  ko = wantpriv ? kt->decops : kt->encops;
-  if (!ko->kf) {
-    kd = k->k;
-    key_incref(kd);
-    kp = 0;
-  } else {
-    kd = xmalloc(ko->kdsz);
-    kp = key_fetchinit(ko->kf, 0, kd);
-    if ((e = key_fetch(kp, k)) != 0) {
-      die(EXIT_FAILURE, "error fetching key `%s': %s",
-         t.buf, key_strerror(e));
-    }
-  }
-  kk = ko->init(k, kd);
-  kk->kp = kp;
-  kk->ops = ko;
-  kk->kd = kd;
-
-  /* --- Set up the algorithms --- */
-
-  if (!halg)
-    kk->h = &rmd160;
-  else if ((kk->h = ghash_byname(halg)) == 0) {
-    die(EXIT_FAILURE, "hash algorithm `%s' not found in key `%s'",
-       halg, t.buf);
-  }
-
-  if (!calg)
-    kk->c = &blowfish_cbc;
-  else if ((kk->c = gcipher_byname(calg)) == 0) {
-    die(EXIT_FAILURE, "encryption scheme `%s' not found in key `%s'",
-       calg, t.buf);
-  }
-
-  dstr_reset(&d);
-  if ((q = key_getattr(0, k, "kdf")) == 0) {
-    dstr_putf(&d, "%s-mgf", kk->h->name);
-    q = d.buf;
-  }
-  if ((kk->cx = gcipher_byname(q)) == 0) {
-    die(EXIT_FAILURE, "encryption scheme (KDF) `%s' not found in key `%s'",
-       q, t.buf);
-  }
-
-  dstr_reset(&d);
-  if ((q = key_getattr(0, k, "mac")) == 0) {
-    dstr_putf(&d, "%s-hmac", kk->h->name);
-    q = d.buf;
-  }
-  if ((kk->m = gmac_byname(q)) == 0) {
-    die(EXIT_FAILURE,
-       "message authentication code `%s' not found in key `%s'",
-       q, t.buf);
-  }
-
-  /* --- Tidy up --- */
-
-  dstr_destroy(&d);
-  dstr_destroy(&t);
-  return (kk);
-}
-
-/* --- @setupkem@ --- *
- *
- * Arguments:  @kem *k@ = key-encapsulation thing
- *             @dstr *d@ = key-encapsulation data
- *             @gcipher **cx@ = key-expansion function (for IVs)
- *             @gcipher **c@ = where to put initialized encryption scheme
- *             @gmac **m@ = where to put initialized MAC
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Initializes all the various symmetric things from a KEM.
- */
-
-int setupkem(kem *k, dstr *d, gcipher **cx, gcipher **c, gmac **m)
-{
-  octet *kd;
-  size_t n, cn, mn;
-  ghash *h;
-  int rc = -1;
-
-  h = GH_INIT(k->h);
-  if (k->ops->doit(k, d, h))
-    goto done;
-  n = keysz(GH_CLASS(h)->hashsz, k->cx->keysz);
-  if (!n)
-    goto done;
-  kd = GH_DONE(h, 0);
-  *cx = GC_INIT(k->cx, kd, n);
-
-  cn = keysz(0, k->c->keysz); n = cn;
-  mn = keysz(0, k->m->keysz); if (mn > n) n = mn;
-  kd = xmalloc(n);
-  GC_ENCRYPT(*cx, 0, kd, cn);
-  *c = GC_INIT(k->c, kd, cn);
-  GC_ENCRYPT(*cx, 0, kd, mn);
-  *m = GM_KEY(k->m, kd, mn);
-  xfree(kd);
-
-  rc = 0;
-done:
-  GH_DESTROY(h);
-  return (rc);
-}
-
-/* --- @freekem@ --- *
- *
- * Arguments:  @kem *k@ = key-encapsulation thing
- *
- * Returns:    ---
- *
- * Use:                Frees up a key-encapsulation thing.
- */
-
-void freekem(kem *k)
-{
-  if (!k->ops->kf)
-    key_drop(k->kd);
-  else {
-    key_fetchdone(k->kp);
-    xfree(k->kd);
-  }
-  k->ops->destroy(k);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cc-list.c b/cc-list.c
deleted file mode 100644 (file)
index b182ba4..0000000
--- a/cc-list.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Emit lists of things in tables
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include <mLib/report.h>
-
-#include "cc.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @displaylists@ --- *
- *
- * Arguments:  @const struct listent *listtab@ = table of lists to show
- *             @char *const argv[]@ = list of lists to show
- *
- * Returns:    Nonzero if anything failed.
- *
- * Use:                Dumps the named lists, or all of them.
- */
-
-int displaylists(const struct listent *listtab, char *const argv[])
-{
-  const struct listent *li;
-  int i;
-  int rc = 0;
-
-  if (!argv || !*argv) {
-    for (li = listtab; li->name; li++)
-      li->list();
-  } else {
-    for (i = 0; argv[i]; i++) {
-      for (li = listtab; li->name; li++) {
-       if (strcmp(li->name, argv[i]) == 0) {
-         li->list();
-         goto cool;
-       }
-      }
-      moan("unknown list `%s'", argv[i]);
-      rc = 1;
-    cool:;
-    }
-  }
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cc-sig.c b/cc-sig.c
deleted file mode 100644 (file)
index 54b58f3..0000000
--- a/cc-sig.c
+++ /dev/null
@@ -1,806 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Catcrypt signatures
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include <stdlib.h>
-
-#include <mLib/report.h>
-
-#include "rand.h"
-#include "sha.h"
-#include "has160.h"
-
-#include "ec.h"
-#include "ec-keys.h"
-#include "dh.h"
-#include "gdsa.h"
-#include "gkcdsa.h"
-#include "rsa.h"
-
-#include "cc.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- RSA PKCS1 --- */
-
-typedef struct rsap1_sigctx {
-  sig s;
-  rsa_privctx rp;
-  pkcs1 p1;
-} rsap1_sigctx;
-
-static sig *rsap1_siginit(key *k, void *kd, const gchash *hc)
-{
-  rsap1_sigctx *rs = CREATE(rsap1_sigctx);
-  rsa_privcreate(&rs->rp, kd, &rand_global);
-  rs->p1.r = &rand_global;
-  rs->p1.ep = hc->name;
-  rs->p1.epsz = strlen(hc->name) + 1;
-  rs->s.h = 0;
-  return (&rs->s);
-}
-
-static int rsap1_sigdoit(sig *s, dstr *d)
-{
-  rsap1_sigctx *rs = (rsap1_sigctx *)s;
-  size_t n;
-  mp *m = rsa_sign(&rs->rp, MP_NEW,
-                  GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
-                  pkcs1_sigencode, &rs->p1);
-  if (!m) return (-1);
-  n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n);
-  d->len += n; mp_drop(m);
-  return (0);
-}
-
-static const char *rsa_lengthcheck(mp *n)
-{
-  if (mp_bits(n) < 1024) return ("key too short");
-  return (0);
-}
-
-static const char *rsap1_sigcheck(sig *s)
-{
-  rsap1_sigctx *rs = (rsap1_sigctx *)s;
-  const char *e;
-  if ((e = rsa_lengthcheck(rs->rp.rp->n)) != 0) return (e);
-  return (0);
-}
-
-static void rsap1_sigdestroy(sig *s)
-{
-  rsap1_sigctx *rs = (rsap1_sigctx *)s;
-  rsa_privdestroy(&rs->rp);
-  DESTROY(rs);
-}
-
-static const sigops rsap1_sig = {
-  rsa_privfetch, sizeof(rsa_priv),
-  rsap1_siginit, rsap1_sigdoit, rsap1_sigcheck, rsap1_sigdestroy
-};
-
-typedef struct rsap1_vrfctx {
-  sig s;
-  rsa_pubctx rp;
-  pkcs1 p1;
-} rsap1_vrfctx;
-
-static sig *rsap1_vrfinit(key *k, void *kd, const gchash *hc)
-{
-  rsap1_vrfctx *rv = CREATE(rsap1_vrfctx);
-  rsa_pubcreate(&rv->rp, kd);
-  rv->p1.r = &rand_global;
-  rv->p1.ep = hc->name;
-  rv->p1.epsz = strlen(hc->name) + 1;
-  rv->s.h = 0;
-  return (&rv->s);
-}
-
-static int rsap1_vrfdoit(sig *s, dstr *d)
-{
-  rsap1_vrfctx *rv = (rsap1_vrfctx *)s;
-  mp *m = mp_loadb(MP_NEW, d->buf, d->len);
-  int rc = rsa_verify(&rv->rp, m,
-                     GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
-                     0, pkcs1_sigdecode, &rv->p1);
-  mp_drop(m);
-  return (rc);
-}
-
-static const char *rsap1_vrfcheck(sig *s)
-{
-  rsap1_vrfctx *rv = (rsap1_vrfctx *)s;
-  const char *e;
-  if ((e = rsa_lengthcheck(rv->rp.rp->n)) != 0) return (e);
-  return (0);
-}
-
-static void rsap1_vrfdestroy(sig *s)
-{
-  rsap1_vrfctx *rv = (rsap1_vrfctx *)s;
-  rsa_pubdestroy(&rv->rp);
-  DESTROY(rv);
-}
-
-static const sigops rsap1_vrf = {
-  rsa_pubfetch, sizeof(rsa_pub),
-  rsap1_vrfinit, rsap1_vrfdoit, rsap1_vrfcheck, rsap1_vrfdestroy
-};
-
-/* --- RSA PSS --- */
-
-static const gccipher *getmgf(key *k, const gchash *hc)
-{
-  dstr d = DSTR_INIT;
-  const gccipher *gc;
-  const char *mm;
-
-  if ((mm = key_getattr(0, k, "mgf")) == 0) {
-    dstr_putf(&d, "%s-mgf", hc->name);
-    mm = d.buf;
-  }
-  if ((gc = gcipher_byname(mm)) == 0)
-    die(EXIT_FAILURE, "unknown encryption scheme `%s'", mm);
-  dstr_destroy(&d);
-  return (gc);
-}
-
-typedef struct rsapss_sigctx {
-  sig s;
-  rsa_privctx rp;
-  pss p;
-} rsapss_sigctx;
-
-static sig *rsapss_siginit(key *k, void *kd, const gchash *hc)
-{
-  rsapss_sigctx *rs = CREATE(rsapss_sigctx);
-  rsa_privcreate(&rs->rp, kd, &rand_global);
-  rs->p.r = &rand_global;
-  rs->p.cc = getmgf(k, hc);
-  rs->p.ch = hc;
-  rs->p.ssz = hc->hashsz;
-  rsa_privdestroy(&rs->rp);
-  return (&rs->s);
-}
-
-static int rsapss_sigdoit(sig *s, dstr *d)
-{
-  rsapss_sigctx *rs = (rsapss_sigctx *)s;
-  size_t n;
-  mp *m = rsa_sign(&rs->rp, MP_NEW,
-                  GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
-                  pss_encode, &rs->p);
-  if (!m) return (-1);
-  n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n);
-  d->len += n; mp_drop(m);
-  return (0);
-}
-
-static const char *rsapss_sigcheck(sig *s)
-{
-  rsapss_sigctx *rs = (rsapss_sigctx *)s;
-  const char *e;
-  if ((e = rsa_lengthcheck(rs->rp.rp->n)) != 0) return (e);
-  return (0);
-}
-
-static void rsapss_sigdestroy(sig *s)
-{
-  rsapss_sigctx *rs = (rsapss_sigctx *)s;
-  rsa_privdestroy(&rs->rp);
-  DESTROY(rs);
-}
-
-static const sigops rsapss_sig = {
-  rsa_privfetch, sizeof(rsa_priv),
-  rsapss_siginit, rsapss_sigdoit, rsapss_sigcheck, rsapss_sigdestroy
-};
-
-typedef struct rsapss_vrfctx {
-  sig s;
-  rsa_pubctx rp;
-  pss p;
-} rsapss_vrfctx;
-
-static sig *rsapss_vrfinit(key *k, void *kd, const gchash *hc)
-{
-  rsapss_vrfctx *rv = CREATE(rsapss_vrfctx);
-  rsa_pubcreate(&rv->rp, kd);
-  rv->p.r = &rand_global;
-  rv->p.cc = getmgf(k, hc);
-  rv->p.ch = hc;
-  rv->p.ssz = hc->hashsz;
-  return (&rv->s);
-}
-
-static int rsapss_vrfdoit(sig *s, dstr *d)
-{
-  rsapss_vrfctx *rv = (rsapss_vrfctx *)s;
-  mp *m = mp_loadb(MP_NEW, d->buf, d->len);
-  int rc = rsa_verify(&rv->rp, m,
-                     GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
-                     0, pss_decode, &rv->p);
-  mp_drop(m);
-  return (rc);
-}
-
-static const char *rsapss_vrfcheck(sig *s)
-{
-  rsapss_vrfctx *rv = (rsapss_vrfctx *)s;
-  const char *e;
-  if ((e = rsa_lengthcheck(rv->rp.rp->n)) != 0) return (e);
-  return (0);
-}
-
-static void rsapss_vrfdestroy(sig *s)
-{
-  rsapss_vrfctx *rv = (rsapss_vrfctx *)s;
-  rsa_pubdestroy(&rv->rp);
-  DESTROY(rv);
-}
-
-static const sigops rsapss_vrf = {
-  rsa_pubfetch, sizeof(rsa_pub),
-  rsapss_vrfinit, rsapss_vrfdoit, rsapss_vrfcheck, rsapss_vrfdestroy
-};
-
-/* --- DSA and ECDSA --- */
-
-typedef struct dsa_sigctx {
-  sig s;
-  gdsa g;
-} dsa_sigctx;
-
-static void dsa_initcommon(dsa_sigctx *ds, const gchash *hc,
-                          const char *ktag)
-{
-  ds->g.r = &rand_global;
-  ds->g.h = hc;
-  ds->g.u = MP_NEW;
-  ds->s.h = 0;
-}
-
-static dsa_sigctx *dsa_doinit(key *k, const gprime_param *gp,
-                             mp *y, const gchash *hc,
-                             group *(*makegroup)(const gprime_param *),
-                             const char *what)
-{
-  dsa_sigctx *ds = CREATE(dsa_sigctx);
-  dstr t = DSTR_INIT;
-
-  key_fulltag(k, &t);
-  if ((ds->g.g = makegroup(gp)) == 0)
-    die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf);
-  ds->g.p = G_CREATE(ds->g.g);
-  if (G_FROMINT(ds->g.g, ds->g.p, y))
-    die(EXIT_FAILURE, "bad public key in key `%s'", t.buf);
-  dsa_initcommon(ds, hc, t.buf);
-  dstr_destroy(&t);
-  return (ds);
-}
-
-static dsa_sigctx *ecdsa_doinit(key *k, const char *cstr,
-                               ec *y, const gchash *hc)
-{
-  dsa_sigctx *ds = CREATE(dsa_sigctx);
-  ec_info ei;
-  const char *e;
-  dstr t = DSTR_INIT;
-
-  key_fulltag(k, &t);
-  if ((e = ec_getinfo(&ei, cstr)) != 0)
-    die(EXIT_FAILURE, "bad curve in key `%s': %s", t.buf, e);
-  ds->g.g = group_ec(&ei);
-  ds->g.p = G_CREATE(ds->g.g);
-  if (G_FROMEC(ds->g.g, ds->g.p, y))
-    die(EXIT_FAILURE, "bad public key in key `%s'", t.buf);
-  dsa_initcommon(ds, hc, t.buf);
-  dstr_destroy(&t);
-  return (ds);
-}
-
-static sig *dsa_siginit(key *k, void *kd, const gchash *hc)
-{
-  dh_priv *dp = kd;
-  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime");
-  ds->g.u = MP_COPY(dp->x);
-  return (&ds->s);
-}
-
-static sig *bindsa_siginit(key *k, void *kd, const gchash *hc)
-{
-  dh_priv *dp = kd;
-  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary");
-  ds->g.u = MP_COPY(dp->x);
-  return (&ds->s);
-}
-
-static sig *ecdsa_siginit(key *k, void *kd, const gchash *hc)
-{
-  ec_priv *ep = kd;
-  dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc);
-  ds->g.u = MP_COPY(ep->x);
-  return (&ds->s);
-}
-
-static int dsa_sigdoit(sig *s, dstr *d)
-{
-  dsa_sigctx *ds = (dsa_sigctx *)s;
-  gdsa_sig ss = GDSA_SIG_INIT;
-  size_t n = mp_octets(ds->g.g->r);
-
-  gdsa_sign(&ds->g, &ss, GH_DONE(ds->s.h, 0), 0);
-  dstr_ensure(d, 2 * n);
-  mp_storeb(ss.r, d->buf, n);
-  mp_storeb(ss.s, d->buf + n, n);
-  d->len += 2 * n;
-  mp_drop(ss.r); mp_drop(ss.s);
-  return (0);
-}
-
-static const char *dsa_sigcheck(sig *s)
-{
-  dsa_sigctx *ds = (dsa_sigctx *)s;
-  const char *e;
-  if ((e = G_CHECK(ds->g.g, &rand_global)) != 0)
-    return (0);
-  if (group_check(ds->g.g, ds->g.p))
-    return ("public key not in subgroup");
-  return (0);
-}
-
-static void dsa_sigdestroy(sig *s)
-{
-  dsa_sigctx *ds = (dsa_sigctx *)s;
-  G_DESTROY(ds->g.g, ds->g.p);
-  mp_drop(ds->g.u);
-  G_DESTROYGROUP(ds->g.g);
-  DESTROY(ds);
-}
-
-static const sigops dsa_sig = {
-  dh_privfetch, sizeof(dh_priv),
-  dsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static const sigops bindsa_sig = {
-  dh_privfetch, sizeof(dh_priv),
-  bindsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static const sigops ecdsa_sig = {
-  ec_privfetch, sizeof(ec_priv),
-  ecdsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static sig *dsa_vrfinit(key *k, void *kd, const gchash *hc)
-{
-  dh_pub *dp = kd;
-  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime");
-  return (&ds->s);
-}
-
-static sig *bindsa_vrfinit(key *k, void *kd, const gchash *hc)
-{
-  dh_pub *dp = kd;
-  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary");
-  return (&ds->s);
-}
-
-static sig *ecdsa_vrfinit(key *k, void *kd, const gchash *hc)
-{
-  ec_pub *ep = kd;
-  dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc);
-  return (&ds->s);
-}
-
-static int dsa_vrfdoit(sig *s, dstr *d)
-{
-  dsa_sigctx *ds = (dsa_sigctx *)s;
-  gdsa_sig ss;
-  size_t n = d->len/2;
-  int rc;
-
-  ss.r = mp_loadb(MP_NEW, d->buf, n);
-  ss.s = mp_loadb(MP_NEW, d->buf + n, d->len - n);
-  rc = gdsa_verify(&ds->g, &ss, GH_DONE(ds->s.h, 0));
-  mp_drop(ss.r); mp_drop(ss.s);
-  return (rc);
-}
-
-static const sigops dsa_vrf = {
-  dh_pubfetch, sizeof(dh_pub),
-  dsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static const sigops bindsa_vrf = {
-  dh_pubfetch, sizeof(dh_pub),
-  bindsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static const sigops ecdsa_vrf = {
-  ec_pubfetch, sizeof(ec_pub),
-  ecdsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-/* --- KCDSA and ECKCDSA --- */
-
-static void kcdsa_privkey(dsa_sigctx *ds, mp *x)
-  { ds->g.u = mp_modinv(MP_NEW, x, ds->g.g->r); }
-
-static void kcdsa_sethash(dsa_sigctx *ds, const gchash *hc)
-  { ds->s.h = gkcdsa_beginhash(&ds->g); }
-
-static sig *kcdsa_siginit(key *k, void *kd, const gchash *hc)
-{
-  dh_priv *dp = kd;
-  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime");
-  kcdsa_privkey(ds, dp->x);
-  kcdsa_sethash(ds, hc);
-  return (&ds->s);
-}
-
-static sig *binkcdsa_siginit(key *k, void *kd, const gchash *hc)
-{
-  dh_priv *dp = kd;
-  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary");
-  kcdsa_privkey(ds, dp->x);
-  kcdsa_sethash(ds, hc);
-  return (&ds->s);
-}
-
-static sig *eckcdsa_siginit(key *k, void *kd, const gchash *hc)
-{
-  ec_priv *ep = kd;
-  dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc);
-  kcdsa_privkey(ds, ep->x);
-  kcdsa_sethash(ds, hc);
-  return (&ds->s);
-}
-
-static int kcdsa_sigdoit(sig *s, dstr *d)
-{
-  dsa_sigctx *ds = (dsa_sigctx *)s;
-  gkcdsa_sig ss = GKCDSA_SIG_INIT;
-  size_t hsz = ds->g.h->hashsz, n = mp_octets(ds->g.g->r);
-
-  gkcdsa_sign(&ds->g, &ss, GH_DONE(ds->s.h, 0), 0);
-  dstr_ensure(d, hsz + n);
-  memcpy(d->buf, ss.r, hsz);
-  mp_storeb(ss.s, d->buf + hsz, n);
-  d->len += hsz + n;
-  xfree(ss.r); mp_drop(ss.s);
-  return (0);
-}
-
-static const sigops kcdsa_sig = {
-  dh_privfetch, sizeof(dh_priv),
-  kcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static const sigops binkcdsa_sig = {
-  dh_privfetch, sizeof(dh_priv),
-  binkcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static const sigops eckcdsa_sig = {
-  ec_privfetch, sizeof(ec_priv),
-  eckcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static sig *kcdsa_vrfinit(key *k, void *kd, const gchash *hc)
-{
-  dh_pub *dp = kd;
-  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime");
-  kcdsa_sethash(ds, hc);
-  return (&ds->s);
-}
-
-static sig *binkcdsa_vrfinit(key *k, void *kd, const gchash *hc)
-{
-  dh_pub *dp = kd;
-  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary");
-  kcdsa_sethash(ds, hc);
-  return (&ds->s);
-}
-
-static sig *eckcdsa_vrfinit(key *k, void *kd, const gchash *hc)
-{
-  ec_pub *ep = kd;
-  dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc);
-  kcdsa_sethash(ds, hc);
-  return (&ds->s);
-}
-
-static int kcdsa_vrfdoit(sig *s, dstr *d)
-{
-  dsa_sigctx *ds = (dsa_sigctx *)s;
-  gkcdsa_sig ss;
-  size_t hsz = ds->g.h->hashsz, n = d->len - hsz;
-  int rc;
-
-  if (d->len < hsz)
-    return (-1);
-  ss.r = (octet *)d->buf;
-  ss.s = mp_loadb(MP_NEW, d->buf + hsz, n);
-  rc = gkcdsa_verify(&ds->g, &ss, GH_DONE(ds->s.h, 0));
-  mp_drop(ss.s);
-  return (rc);
-}
-
-static const sigops kcdsa_vrf = {
-  dh_pubfetch, sizeof(dh_pub),
-  kcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static const sigops binkcdsa_vrf = {
-  dh_pubfetch, sizeof(dh_pub),
-  binkcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-static const sigops eckcdsa_vrf = {
-  ec_pubfetch, sizeof(ec_pub),
-  eckcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
-};
-
-/* --- Symmetric message authentication --- */
-
-typedef struct mac_ctx {
-  sig s;
-  const gcmac *mc;
-  gmac *m;
-  key_packdef kp;
-  key_bin kb;
-} mac_ctx;
-
-static sig *mac_init(key *k, void *kd, const gchash *hc)
-{
-  mac_ctx *m;
-  dstr d = DSTR_INIT;
-  int err;
-  const char *mm;
-
-  m = CREATE(mac_ctx);
-
-  key_fulltag(k, &d);
-  m->kp.e = KENC_BINARY;
-  m->kp.p = &m->kb;
-  m->kp.kd = 0;
-
-  if ((mm = key_getattr(0 /*yik*/, k, "mac")) == 0) {
-    dstr_putf(&d, "%s-hmac", hc->name);
-    mm = d.buf;
-  }
-  if ((m->mc = gmac_byname(mm)) == 0)
-    die(EXIT_FAILURE, "unknown message authentication scheme `%s'", mm);
-  dstr_reset(&d);
-
-  if ((err = key_unpack(&m->kp, kd, &d)) != 0) {
-    die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s",
-       d.buf, key_strerror(err));
-  }
-  dstr_destroy(&d);
-
-  if (keysz(m->kb.sz, m->mc->keysz) != m->kb.sz) {
-    die(EXIT_FAILURE, "bad key size %lu for `%s'",
-       (unsigned long)m->kb.sz, m->mc->name);
-  }
-  m->m = GM_KEY(m->mc, m->kb.k, m->kb.sz);
-  m->s.h = GM_INIT(m->m);
-  return (&m->s);
-}
-
-static int mac_sigdoit(sig *s, dstr *d)
-{
-  mac_ctx *m = (mac_ctx *)s;
-
-  dstr_ensure(d, m->mc->hashsz);
-  GH_DONE(m->s.h, d->buf);
-  d->len += m->mc->hashsz;
-  return (0);
-}
-
-static int mac_vrfdoit(sig *s, dstr *d)
-{
-  mac_ctx *m = (mac_ctx *)s;
-  const octet *t;
-
-  t = GH_DONE(m->s.h, 0);
-  if (d->len != m->mc->hashsz || memcmp(d->buf, t, d->len) != 0)
-    return (-1);
-  return (0);
-}
-
-static const char *mac_check(sig *s) { return (0); }
-
-static void mac_destroy(sig *s)
-{
-  mac_ctx *m = (mac_ctx *)s;
-  GM_DESTROY(m->m);
-  key_unpackdone(&m->kp);
-}
-
-static const sigops mac_sig = {
-  0, 0,
-  mac_init, mac_sigdoit, mac_check, mac_destroy
-};
-
-static const sigops mac_vrf = {
-  0, 0,
-  mac_init, mac_vrfdoit, mac_check, mac_destroy
-};
-
-/* --- The switch table --- */
-
-const struct sigtab sigtab[] = {
-  { "rsapkcs1",        &rsap1_sig,     &rsap1_vrf,     &sha },
-  { "rsapss",  &rsapss_sig,    &rsapss_vrf,    &sha },
-  { "dsa",     &dsa_sig,       &dsa_vrf,       &sha },
-  { "bindsa",  &bindsa_sig,    &bindsa_vrf,    &sha },
-  { "ecdsa",   &ecdsa_sig,     &ecdsa_vrf,     &sha },
-  { "kcdsa",   &kcdsa_sig,     &kcdsa_vrf,     &has160 },
-  { "binkcdsa",        &binkcdsa_sig,  &binkcdsa_vrf,  &has160 },
-  { "eckcdsa", &eckcdsa_sig,   &eckcdsa_vrf,   &has160 },
-  { "mac",     &mac_sig,       &mac_vrf,       &rmd160 },
-  { 0,         0,              0 }
-};
-
-/* --- @getsig@ --- *
- *
- * Arguments:  @key *k@ = the key to load
- *             @const char *app@ = application name
- *             @int wantpriv@ = nonzero if we want to sign
- *
- * Returns:    A signature-making thing.
- *
- * Use:                Loads a key and starts hashing.
- */
-
-sig *getsig(key *k, const char *app, int wantpriv)
-{
-  const char *salg, *halg = 0;
-  dstr d = DSTR_INIT;
-  dstr t = DSTR_INIT;
-  char *p = 0;
-  const char *q;
-  sig *s;
-  size_t n;
-  const struct sigtab *st;
-  const sigops *so;
-  const gchash *ch;
-  void *kd;
-  int e;
-  key_packdef *kp;
-
-  /* --- Setup stuff --- */
-
-  key_fulltag(k, &t);
-
-  /* --- Get the signature algorithm --- *
-   *
-   * Take the attribute if it's there; otherwise use the key type.
-   */
-
-  n = strlen(app);
-  if ((q = key_getattr(0, k, "sig")) != 0) {
-    dstr_puts(&d, q);
-    p = d.buf;
-  } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') {
-    dstr_puts(&d, k->type);
-    p = d.buf + n + 1;
-  } else
-    die(EXIT_FAILURE, "no signature algorithm for key `%s'", t.buf);
-
-  /* --- Grab the hash algorithm --- *
-   *
-   * Grab it from the signature algorithm if it's there.  But override that
-   * from the attribute.
-   */
-
-  salg = p;
-  if ((p = strchr(p, '/')) != 0) {
-    *p++ = 0;
-    halg = p;
-  }
-  if ((q = key_getattr(0, k, "hash")) != 0)
-    halg = q;
-
-  /* --- Look up the algorithms in the table --- */
-
-  for (st = sigtab; st->name; st++) {
-    if (strcmp(st->name, salg) == 0)
-      goto s_found;
-  }
-  die(EXIT_FAILURE, "signature algorithm `%s' not found in key `%s'",
-      salg, t.buf);
-s_found:;
-  if (!halg)
-    ch = st->ch;
-  else {
-    if ((ch = ghash_byname(halg)) == 0) {
-      die(EXIT_FAILURE, "hash algorithm `%s' not found in key `%s'",
-         halg, t.buf);
-    }
-  }
-  so = wantpriv ? st->signops : st->verifyops;
-
-  /* --- Load the key --- */
-
-  if (!so->kf) {
-    kd = k->k;
-    key_incref(kd);
-    kp = 0;
-  } else {
-    kd = xmalloc(so->kdsz);
-    kp = key_fetchinit(so->kf, 0, kd);
-    if ((e = key_fetch(kp, k)) != 0) {
-      die(EXIT_FAILURE, "error fetching key `%s': %s",
-         t.buf, key_strerror(e));
-    }
-  }
-  s = so->init(k, kd, ch);
-  if (!s->h)
-    s->h = GH_INIT(ch);
-  s->kp = kp;
-  s->ops = so;
-  s->kd = kd;
-  s->ch = ch;
-
-  /* --- Free stuff up --- */
-
-  dstr_destroy(&d);
-  dstr_destroy(&t);
-  return (s);
-}
-
-/* --- @freesig@ --- *
- *
- * Arguments:  @sig *s@ = signature-making thing
- *
- * Returns:    ---
- *
- * Use:                Frees up a signature-making thing
- */
-
-void freesig(sig *s)
-{
-  GH_DESTROY(s->h);
-  if (!s->ops->kf)
-    key_drop(s->kd);
-  else {
-    key_fetchdone(s->kp);
-    xfree(s->kd);
-  }
-  s->ops->destroy(s);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cc-subcmd.c b/cc-subcmd.c
deleted file mode 100644 (file)
index c8f8b51..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Subcommand infrastructure
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include <mLib/quis.h>
-#include <mLib/report.h>
-
-#include "cc.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @findcmd@ --- *
- *
- * Arguments:  @const cmd *cmds@ = pointer to command table
- *             @const char *name@ = a command name
- *
- * Returns:    Pointer to the command structure.
- *
- * Use:                Looks up a command by name.  If the command isn't found, an
- *             error is reported and the program is terminated.
- */
-
-const cmd *findcmd(const cmd *cmds, const char *name)
-{
-  const cmd *c, *chosen = 0;
-  size_t sz = strlen(name);
-
-  for (c = cmds; c->name; c++) {
-    if (strncmp(name, c->name, sz) == 0) {
-      if (c->name[sz] == 0) {
-       chosen = c;
-       break;
-      } else if (chosen)
-       die(EXIT_FAILURE, "ambiguous command name `%s'", name);
-      else
-       chosen = c;
-    }
-  }
-  if (!chosen)
-    die(EXIT_FAILURE, "unknown command name `%s'", name);
-  return (chosen);
-}
-
-/* --- @sc_help@ --- *
- *
- * Arguments:  @const cmd *cmds@ = pointer to command table
- *             @FILE *fp@ = output file handle
- *             @char *const *argv@ = remaining arguments
- *
- * Returns:    ---
- *
- * Use:                Prints a help message, maybe with help about subcommands.
- */
-
-void sc_help(const cmd *cmds, FILE *fp, char *const *argv)
-{
-  const cmd *c;
-
-  version(fp);
-  fputc('\n', fp);
-  if (!*argv) {
-    help_global(fp);
-    fputs("\n\
-The following commands are understood:\n\n",
-         fp);
-    for (c = cmds; c->name; c++)
-      fprintf(fp, "%s\n", c->usage);
-  } else {
-    while (*argv) {
-      c = findcmd(cmds, *argv);
-      fprintf(fp, "Usage: %s [-OPTIONS] %s\n", QUIS, c->usage);
-      if (c->help) {
-       fputc('\n', fp);
-       pquis(fp, c->help);
-      }
-      argv++;
-      if (*argv) fputc('\n', fp);
-    }
-  }
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/cc.h b/cc.h
deleted file mode 100644 (file)
index f3a03f3..0000000
--- a/cc.h
+++ /dev/null
@@ -1,659 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Catcrypt common stuff
- *
- * (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.
- */
-
-#ifndef CATACOMB_CC_H
-#define CATACOMB_CC_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#if _FILE_OFFSET_BITS != 64
-#  error "Must set _FILE_OFFSET_BITS to 64."
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <mLib/dstr.h>
-
-#include "key.h"
-#include "gcipher.h"
-#include "ghash.h"
-#include "gmac.h"
-
-/*----- Cryptographic object tables ---------------------------------------*/
-
-/* --- Key encapsulation --- */
-
-typedef struct kem {
-  const struct kemops *ops;
-  key_packdef *kp;
-  void *kd;
-  const gchash *h;
-  const gccipher *c, *cx;
-  const gcmac *m;
-} kem;
-
-typedef struct kemops {
-  const key_fetchdef *kf;              /* Key fetching structure */
-  size_t kdsz;                         /* Size of the key-data structure */
-  kem *(*init)(key */*k*/, void */*kd*/);
-  int (*doit)(kem */*k*/, dstr */*d*/, ghash */*h*/);
-  const char *(*check)(kem */*k*/);
-  void (*destroy)(kem */*k*/);
-} kemops;
-
-struct kemtab {
-  const char *name;
-  const kemops *encops;
-  const kemops *decops;
-};
-
-extern const struct kemtab kemtab[];
-
-/* --- @getkem@ --- *
- *
- * Arguments:  @key *k@ = the key to load
- *             @const char *app@ = application name
- *             @int wantpriv@ = nonzero if we want to decrypt
- *
- * Returns:    A key-encapsulating thing.
- *
- * Use:                Loads a key.
- */
-
-extern kem *getkem(key */*k*/, const char */*app*/, int /*wantpriv*/);
-
-/* --- @setupkem@ --- *
- *
- * Arguments:  @kem *k@ = key-encapsulation thing
- *             @dstr *d@ = key-encapsulation data
- *             @gcipher **cx@ = key-expansion function (for IVs)
- *             @gcipher **c@ = where to put initialized encryption scheme
- *             @gmac **m@ = where to put initialized MAC
- *
- * Returns:    Zero for success, nonzero on faliure.
- *
- * Use:                Initializes all the various symmetric things from a KEM.
- */
-
-extern int setupkem(kem */*k*/, dstr */*d*/,
-                   gcipher **/*cx*/, gcipher **/*c*/, gmac **/*m*/);
-
-/* --- @freekem@ --- *
- *
- * Arguments:  @kem *k@ = key-encapsulation thing
- *
- * Returns:    ---
- *
- * Use:                Frees up a key-encapsulation thing.
- */
-
-extern void freekem(kem */*k*/);
-
-/* --- Signing --- */
-
-typedef struct sig {
-  const struct sigops *ops;
-  key_packdef *kp;
-  void *kd;
-  const gchash *ch;
-  ghash *h;
-} sig;
-
-typedef struct sigops {
-  const key_fetchdef *kf;              /* Key fetching structure */
-  size_t kdsz;                         /* Size of the key-data structure */
-  sig *(*init)(key */*k*/, void */*kd*/, const gchash */*hc*/);
-  int (*doit)(sig */*s*/, dstr */*d*/);
-  const char *(*check)(sig */*s*/);
-  void (*destroy)(sig */*s*/);
-} sigops;
-
-struct sigtab {
-  const char *name;
-  const sigops *signops;
-  const sigops *verifyops;
-  const gchash *ch;
-};
-
-extern const struct sigtab sigtab[];
-
-/* --- @getsig@ --- *
- *
- * Arguments:  @key *k@ = the key to load
- *             @const char *app@ = application name
- *             @int wantpriv@ = nonzero if we want to sign
- *
- * Returns:    A signature-making thing.
- *
- * Use:                Loads a key and starts hashing.
- */
-
-extern sig *getsig(key */*k*/, const char */*app*/, int /*wantpriv*/);
-
-/* --- @freesig@ --- *
- *
- * Arguments:  @sig *s@ = signature-making thing
- *
- * Returns:    ---
- *
- * Use:                Frees up a signature-making thing
- */
-
-extern void freesig(sig */*s*/);
-
-/*----- File encodings ----------------------------------------------------*/
-
-/* --- Data encoding --- */
-
-typedef struct enc {
-  const struct encops *ops;
-  FILE *fp;
-} enc;
-
-typedef struct encops {
-  const char *name;
-  const char *rmode, *wmode;
-  int nraw, ncook;
-  enc *(*initenc)(FILE */*fp*/, const char */*msg*/);
-  enc *(*initdec)(FILE */*fp*/,
-                 int (*/*func*/)(const char *, void *), void */*p*/);
-  int (*read)(enc */*e*/, void */*p*/, size_t /*sz*/);
-  int (*write)(enc */*e*/, const void */*p*/, size_t /*sz*/);
-  int (*encdone)(enc */*e*/);
-  int (*decdone)(enc */*e*/);
-  void (*destroy)(enc */*e*/);
-} encops;
-
-extern const encops enctab[];
-
-/* --- @getenc@ --- *
- *
- * Arguments:  @const char *enc@ = name of wanted encoding
- *
- * Returns:    Pointer to encoder operations.
- *
- * Use:                Finds a named encoder or decoder.
- */
-
-extern const encops *getenc(const char */*enc*/);
-
-/* --- @checkbdry@ --- *
- *
- * Arguments:  @const char *b@ = boundary string found
- *             @void *p@ = boundary string wanted
- *
- * Returns:    Nonzero if the boundary string is the one we wanted.
- *
- * Use:                Pass as @func@ to @initdec@ if you just want a simple life.
- */
-
-extern int checkbdry(const char */*b*/, void */*p*/);
-
-/* --- @initenc@ --- *
- *
- * Arguments:  @const encops *eo@ = operations (from @getenc@)
- *             @FILE *fp@ = file handle to attach
- *             @const char *msg@ = banner message
- *
- * Returns:    The encoder object.
- *
- * Use:                Initializes an encoder.
- */
-
-extern enc *initenc(const encops */*eo*/, FILE */*fp*/, const char */*msg*/);
-
-/* --- @initdec@ --- *
- *
- * Arguments:  @const encops *eo@ = operations (from @getenc@)
- *             @FILE *fp@ = file handle to attach
- *             @int (*func)(const char *, void *)@ = banner check function
- *             @void *p@ = argument for @func@
- *
- * Returns:    The encoder object.
- *
- * Use:                Initializes an encoder.
- */
-
-extern enc *initdec(const encops */*eo*/, FILE */*fp*/,
-                   int (*/*func*/)(const char *, void *), void */*p*/);
-
-/* --- @freeenc@ --- *
- *
- * Arguments:  @enc *e@ = encoder object
- *
- * Returns:    ---
- *
- * Use:                Frees an encoder object.
- */
-
-extern void freeenc(enc */*e*/);
-
-/* --- @cmd_encode@, @cmd_decode@ --- */
-
-#define CMD_ENCODE {                                                   \
-  "encode", cmd_encode,                                                        \
-    "encode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]",           \
-    "\
-Options:\n\
-\n\
--f, --format=FORMAT    Encode to FORMAT.\n\
--b, --boundary=LABEL   PEM boundary is LABEL.\n\
--o, --output=FILE      Write output to FILE.\n\
--p, --progress         Show progress on large files.\n\
-" }
-
-#define CMD_DECODE {                                                   \
-  "decode", cmd_decode,                                                        \
-    "decode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]",           \
-    "\
-Options:\n\
-\n\
--f, --format=FORMAT    Decode from FORMAT.\n\
--b, --boundary=LABEL   PEM boundary is LABEL.\n\
--o, --output=FILE      Write output to FILE.\n\
--p, --progress         Show progress on large files.\n\
-" }
-
-extern int cmd_encode(int /*argc*/, char */*argv*/[]);
-extern int cmd_decode(int /*argc*/, char */*argv*/[]);
-
-/*----- Hash encoding functions -------------------------------------------*/
-
-/* --- Table --- */
-
-#define ENCODINGS(_)                                                   \
-  _(HEX, hex)                                                          \
-  _(BASE64, base64)                                                    \
-  _(BASE32, base32)
-
-enum {
-#define ENUM(tag, name) ENC_##tag,
-  ENCODINGS(ENUM)
-#undef ENUM
-  ENC_LIMIT
-};
-
-typedef struct encodeops {
-  const char *name;
-  void (*put)(const octet *, size_t, FILE *);
-  size_t (*get)(const char *, octet *, size_t, char **);
-} encodeops;
-
-extern const encodeops encodingtab[];
-
-/* --- @getencoding@ --- *
- *
- * Arguments:  @const char *ename@ = encoding name
- *
- * Returns:    Pointer to encoding table entry, or null.
- *
- * Use:                Finds an encoding entry given its name.
- */
-
-extern const encodeops *getencoding(const char */*ename*/);
-
-/*----- File hashing ------------------------------------------------------*/
-
-typedef struct fhashstate {
-  const gchash *gch;
-  unsigned f;
-  struct fhent *ents;
-} fhashstate;
-
-#define FHF_BINARY 0x100u
-#define FHF_PROGRESS 0x200u
-#define FHF_JUNK 0x400u
-
-#define FHF_MASK 0xff00u
-
-/* --- @gethash@ --- *
- *
- * Arguments:  @const char *name@ = pointer to name string
- *
- * Returns:    Pointer to appropriate hash class.
- *
- * Use:                Chooses a hash function by name.
- */
-
-extern const gchash *gethash(const char */*name*/);
-
-/* --- @describefile@ --- *
- *
- * Arguments:  @const struct stat *st@ = pointer to file state
- *
- * Returns:    A snappy one-word description of the file.
- */
-
-extern const char *describefile(const struct stat */*st*/);
-
-/* --- @fhash_init@ ---*
- *
- * Arguments:  @fhashstate *fh@ = pointer to fhash state to initialize
- *             @const gchash *gch@ = hash class to set
- *             @unsigned f@ initial flags to set
- *
- * Returns:    ---
- *
- * Use:                Initializes an @fhashstate@ structure.
- */
-
-extern void fhash_init(fhashstate */*fh*/,
-                      const gchash */*gch*/, unsigned /*f*/);
-
-/* --- @fhash_free@ --- *
- *
- * Arguments:  @fhashstate *fh@ = pointer to fhash state to free
- *
- * Returns:    ---
- *
- * Use:                Frees an fhash state.
- */
-
-extern void fhash_free(fhashstate */*fh*/);
-
-/* --- @fhash@ --- *
- *
- * Arguments:  @fhashstate *fh@ = pointer to fhash state
- *             @const char *file@ = file name to be hashed (null for stdin)
- *             @void *buf@ = pointer to hash output buffer
- *
- * Returns:    Zero if it worked, nonzero on error.
- *
- * Use:                Hashes a file.
- */
-
-extern int fhash(fhashstate */*fh*/, const char */*file*/, void */*buf*/);
-
-/* --- @fhash_junk@ --- *
- *
- * Arguments:  @fhashstate *fh@ = pointer to fhash state
- *             @void (*func)(const char *, const struct stat *, void *)@
- *             @void *p@ = pointer to pass to function
- *
- * Returns:    Positive if any junk was found, negative on error, zero if
- *             everything was fine.
- *
- * Use:                Reports junk files in any directories covered by the hash
- *             state.
- */
-
-extern int fhash_junk(fhashstate */*fh*/,
-                     int (*/*func*/)(const char *,
-                                     const struct stat *,
-                                     void *),
-                     void */*p*/);
-
-/* --- @hfparse@ --- *
- *
- * Arguments:  @hfpctx *hfp@ = pointer to the context structure
- *
- * Returns:    A code indicating what happened.
- *
- * Use:                Parses a line from the input file.
- */
-
-enum {                                 /* Meaning and members set */
-  HF_FILE,                             /* File hash: @dline@ and @hbuf@ */
-  HF_ENC,                              /* Encoding: @ee@ */
-  HF_HASH,                             /* Hash function: @gch@ */
-  HF_ESC,                              /* Name escape: @f@ */
-  HF_EOF,                              /* End of file */
-  HF_BAD                               /* Unrecognized line */
-};
-
-typedef struct hfpctx {
-  unsigned f;                          /* Flags to read */
-#define HFF_ESCAPE 1u                  /*   File names are escaped */
-  FILE *fp;                            /* Input file to read */
-  dstr *dline;                         /* Line contents, corrupted */
-  const gchash *gch;                   /* Hash function to use */
-  const encodeops *ee;                 /* Encoding to apply to hashes */
-  dstr *dfile;                         /* File name for @HF_FILE@ lines */
-  octet *hbuf;                         /* Output buffer for hash data */
-} hfpctx;
-
-extern int hfparse(hfpctx */*hfp*/);
-
-/*----- String I/O --------------------------------------------------------*/
-
-#define GSF_RAW 4096u
-#define GSF_FILE 0u
-#define GSF_STRING 8192u
-
-#define GSF_MASK 61440u
-
-/* --- @getstring@ --- *
- *
- * Arguments:  @void *in@ = input source
- *             @dstr *d@ = destination string
- *             @unsigned f@ = input flags
- *
- * Returns:    Zero if OK, nonzero on end-of-file.
- *
- * Use:                Reads a filename (or something similar) from a stream.
- */
-
-extern int getstring(void */*in*/, dstr */*d*/, unsigned /*f*/);
-
-/* --- @putstring@ --- *
- *
- * Arguments:  @FILE *fp@ = stream to write on
- *             @const char *p@ = pointer to text
- *             @unsigned f@ = output flags
- *
- * Returns:    ---
- *
- * Use:                Emits a string to a stream.
- */
-
-extern void putstring(FILE */*fp*/, const char */*p*/, unsigned /*f*/);
-
-/*----- Lists of things ---------------------------------------------------*/
-
-/* --- @LIST(STRING, FP, END-TEST, NAME-EXPR)@ --- *
- *
- * Produce list of things.  Requires @i@ and @w@ variables in scope.
- * END-TEST and NAME-EXPR are in terms of @i@.
- */
-
-#define LIST(what, fp, end, name) do {                                 \
-  fputs(what ":\n  ", fp);                                             \
-  w = 2;                                                               \
-  for (i = 0; end; i++) {                                              \
-    if (w == 2)                                                                \
-      w += strlen(name);                                               \
-    else {                                                             \
-      if (strlen(name) + w > 76) {                                     \
-       fputs("\n  ", fp);                                              \
-       w = 2 + strlen(name);                                           \
-      } else {                                                         \
-       fputc(' ', fp);                                                 \
-       w += strlen(name) + 1;                                          \
-      }                                                                        \
-    }                                                                  \
-    fputs(name, fp);                                                   \
-  }                                                                    \
-  fputc('\n', fp);                                                     \
-} while (0)
-
-#define STDLISTS(LI)                                                   \
-  LI("Hash functions", hash,                                           \
-     ghashtab[i], ghashtab[i]->name)                                   \
-  LI("Encryption schemes", enc,                                                \
-     gciphertab[i], gciphertab[i]->name)                               \
-  LI("Message authentication schemes", mac,                            \
-     gmactab[i], gmactab[i]->name)                                     \
-  LI("Elliptic curves", ec,                                            \
-     ectab[i].name, ectab[i].name)                                     \
-  LI("Diffie-Hellman groups", dh,                                      \
-     ptab[i].name, ptab[i].name)
-
-#define LIDECL(text, tag, test, name)                                  \
-  static void show_##tag(void);
-
-#define LIDEF(text, tag, test, name)                                   \
-  static void show_##tag(void)                                         \
-  {                                                                    \
-    unsigned i, w;                                                     \
-    LIST(text, stdout, test, name);                                    \
-  }
-
-#define LIENT(text, tag, test, name)                                   \
-  { #tag, show_##tag },
-
-struct listent {
-  const char *name;
-  void (*list)(void);
-};
-
-#define MAKELISTTAB(listtab, LISTS)                                    \
-  LISTS(LIDECL)                                                                \
-  static const struct listent listtab[] = {                            \
-    LISTS(LIENT)                                                       \
-    { 0, 0 }                                                           \
-  };                                                                   \
-  LISTS(LIDEF)
-
-extern int displaylists(const struct listent */*listtab*/,
-                       char *const /*argv*/[]);
-
-/*----- Progress indicators -----------------------------------------------*/
-
-typedef struct fprogress {
-  const char *bp;
-  off_t o, sz, olast;
-  time_t start, last;
-  char name[24];
-} fprogress;
-
-/* --- @fprogress_init@ --- *
- *
- * Arguments:  @fprogress *f@ = progress context to be initialized
- *             @const char *name@ = file name string to show
- *             @FILE *fp@ = file we're reading from
- *
- * Returns:    Zero on success, nonzero if the file's state is now broken.
- *
- * Use:                Initializes a progress context.  Nothing is actually
- *             displayed yet.
- */
-
-extern int fprogress_init(fprogress */*f*/,
-                         const char */*name*/, FILE */*fp*/);
-
-/* --- @fprogress_update@ --- *
- *
- * Arguments:  @fprogress *f@ = progress context
- *             @size_t n@ = how much progress has been made
- *
- * Returns:    ---
- *
- * Use:                Maybe updates the display to show that some progress has been
- *             made.
- */
-
-extern void fprogress_update(fprogress */*f*/, size_t /*n*/);
-
-/* --- @fprogress_clear@ --- *
- *
- * Arguments:  @fprogress *f@ = progress context
- *
- * Returns:    ---
- *
- * Use:                Clears the progress display from the screen.
- */
-
-extern void fprogress_clear(fprogress */*f*/);
-
-/* --- @fprogress_done@ --- *
- *
- * Arguments:  @fprogress *f@ = progress context
- *
- * Returns:    ---
- *
- * Use:                Clear up the progress context and removes any display.
- */
-
-extern void fprogress_done(fprogress */*f*/);
-
-/*----- Subcommand dispatch -----------------------------------------------*/
-
-typedef struct cmd {
-  const char *name;
-  int (*cmd)(int /*argc*/, char */*argv*/[]);
-  const char *usage;
-  const char *help;
-} cmd;
-
-extern void version(FILE */*fp*/);
-extern void help_global(FILE */*fp*/);
-
-/* --- @findcmd@ --- *
- *
- * Arguments:  @const cmd *cmds@ = pointer to command table
- *             @const char *name@ = a command name
- *
- * Returns:    Pointer to the command structure.
- *
- * Use:                Looks up a command by name.  If the command isn't found, an
- *             error is reported and the program is terminated.
- */
-
-const cmd *findcmd(const cmd */*cmds*/, const char */*name*/);
-
-/* --- @sc_help@ --- *
- *
- * Arguments:  @const cmd *cmds@ = pointer to command table
- *             @FILE *fp@ = output file handle
- *             @char *const *argv@ = remaining arguments
- *
- * Returns:    ---
- *
- * Use:                Prints a help message, maybe with help about subcommands.
- */
-
-extern void sc_help(const cmd */*cmds*/, FILE */*fp*/,
-                   char *const */*argv*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/cfb-def.h b/cfb-def.h
deleted file mode 100644 (file)
index 357bb95..0000000
--- a/cfb-def.h
+++ /dev/null
@@ -1,508 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cfb-def.h,v 1.6 2004/04/17 09:58:37 mdw Exp $
- *
- * Definitions for ciphertext feedback mode
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_CFB_DEF_H
-#define CATACOMB_CFB_DEF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_BLKC_H
-#  include "blkc.h"
-#endif
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @CFB_DEF@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use:                Creates an implementation for CFB mode.
- */
-
-#define CFB_DEF(PRE, pre)                                              \
-                                                                       \
-/* --- @pre_cfbgetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @const pre_cfbctx *ctx@ = pointer to CFB context block  \
- *             @void *iv@ = pointer to output data block               \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Reads the currently set IV.  Reading and setting an IV  \
- *             is not transparent to the cipher.  It will add a `step' \
- *             which must be matched by a similar operation during     \
- *             decryption.                                             \
- */                                                                    \
-                                                                       \
-void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv)                 \
-{                                                                      \
-  octet *p = iv;                                                       \
-  unsigned off = ctx->off;                                             \
-  unsigned rest = PRE##_BLKSZ - off;                                   \
-  memcpy(p, ctx->iv + off, rest);                                      \
-  memcpy(p + rest, ctx->iv, off);                                      \
-}                                                                      \
-                                                                       \
-/* --- @pre_cfbsetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *             @cnost void *iv@ = pointer to IV to set                 \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the IV to use for subsequent encryption.           \
- */                                                                    \
-                                                                       \
-void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv)                 \
-{                                                                      \
-  memcpy(ctx->iv, iv, PRE##_BLKSZ);                                    \
-  ctx->off = PRE##_BLKSZ;                                              \
-}                                                                      \
-                                                                       \
-/* --- @pre_cfbbdry@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Inserts a boundary during encryption.  Successful       \
- *             decryption must place a similar boundary.               \
- */                                                                    \
-                                                                       \
-void pre##_cfbbdry(pre##_cfbctx *ctx)                                  \
-{                                                                      \
-  uint32 niv[PRE##_BLKSZ / 4];                                         \
-  BLKC_LOAD(PRE, niv, ctx->iv);                                                \
-  pre##_eblk(&ctx->ctx, niv, niv);                                     \
-  BLKC_STORE(PRE, ctx->iv, niv);                                       \
-  ctx->off = PRE##_BLKSZ;                                              \
-  BURN(niv);                                                           \
-}                                                                      \
-                                                                       \
-/* --- @pre_cfbsetkey@ --- *                                           \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the CFB context to use a different cipher key.     \
- */                                                                    \
-                                                                       \
-void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k)            \
-{                                                                      \
-  ctx->ctx = *k;                                                       \
-  ctx->off = PRE##_BLKSZ;                                              \
-}                                                                      \
-                                                                       \
-/* --- @pre_cfbinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to cipher context           \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a CFB context ready for use.  You should    \
- *             ensure that the IV chosen is unique: reusing an IV will \
- *             compromise the security of at least the first block     \
- *             encrypted.  This is equivalent to calls to @pre_init@,  \
- *             @pre_cfbsetkey@ and @pre_cfbsetiv@.                     \
- */                                                                    \
-                                                                       \
-void pre##_cfbinit(pre##_cfbctx *ctx,                                  \
-                    const void *key, size_t sz,                        \
-                    const void *iv)                                    \
-{                                                                      \
-  static const octet zero[PRE##_BLKSZ] = { 0 };                                \
-  pre##_init(&ctx->ctx, key, sz);                                      \
-  pre##_cfbsetiv(ctx, iv ? iv : zero);                                 \
-}                                                                      \
-                                                                       \
-/* --- @pre_cfbencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts a block with a block cipher in CFB mode.  The  \
- *             input block may be arbitrary in size.  CFB mode is not  \
- *             sensitive to block boundaries.                          \
- */                                                                    \
-                                                                       \
-void pre##_cfbencrypt(pre##_cfbctx *ctx,                               \
-                       const void *src, void *dest,                    \
-                       size_t sz)                                      \
-{                                                                      \
-  const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz)                                                             \
-    return;                                                            \
-                                                                       \
-  /* --- If I can deal with the block from my buffer, do that --- */   \
-                                                                       \
-  if (sz < PRE##_BLKSZ - off)                                          \
-    goto small;                                                                \
-                                                                       \
-  /* --- Finish off what's left in my buffer --- */                    \
-                                                                       \
-  while (off < PRE##_BLKSZ) {                                          \
-    register octet x = *s++;                                           \
-    ctx->iv[off] ^= x;                                                 \
-    if (d) *d++ = ctx->iv[off];                                                \
-    off++;                                                             \
-    sz--;                                                              \
-  }                                                                    \
-                                                                       \
-  /* --- Main encryption loop --- */                                   \
-                                                                       \
-  {                                                                    \
-    uint32 iv[PRE##_BLKSZ / 4];                                                \
-    BLKC_LOAD(PRE, iv, ctx->iv);                                       \
-                                                                       \
-    for (;;) {                                                         \
-      pre##_eblk(&ctx->ctx, iv, iv);                                   \
-      if (sz < PRE##_BLKSZ)                                            \
-       break;                                                          \
-      if (s) {                                                         \
-       BLKC_XLOAD(PRE, iv, s);                                         \
-       s += PRE##_BLKSZ;                                               \
-      }                                                                        \
-      if (d) {                                                         \
-       BLKC_STORE(PRE, d, iv);                                         \
-       d += PRE##_BLKSZ;                                               \
-      }                                                                        \
-      sz -= PRE##_BLKSZ;                                               \
-    }                                                                  \
-    off = 0;                                                           \
-    BLKC_STORE(PRE, ctx->iv, iv);                                      \
-  }                                                                    \
-                                                                       \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    do {                                                               \
-      register octet x = *s++;                                         \
-      ctx->iv[off] ^= x;                                               \
-      if (d) *d++ = ctx->iv[off];                                      \
-      off++;                                                           \
-      sz--;                                                            \
-    } while (sz);                                                      \
-  }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
-}                                                                      \
-                                                                       \
-/* --- @pre_cfbdecrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Decrypts a block with a block cipher in CFB mode.  The  \
- *             input block may be arbitrary in size.  CFB mode is not  \
- *             sensitive to block boundaries.                          \
- */                                                                    \
-                                                                       \
-void pre##_cfbdecrypt(pre##_cfbctx *ctx,                               \
-                       const void *src, void *dest,                    \
-                       size_t sz)                                      \
-{                                                                      \
-  const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz)                                                             \
-    return;                                                            \
-                                                                       \
-  /* --- If I can deal with the block from my buffer, do that --- */   \
-                                                                       \
-  if (sz < PRE##_BLKSZ - off)                                          \
-    goto small;                                                                \
-                                                                       \
-  /* --- Finish off what's left in my buffer --- */                    \
-                                                                       \
-  while (off < PRE##_BLKSZ) {                                          \
-    register octet x = *s++;                                           \
-    *d++ = ctx->iv[off] ^ x;                                           \
-    ctx->iv[off++] = x;                                                        \
-    sz--;                                                              \
-  }                                                                    \
-                                                                       \
-  /* --- Main encryption loop --- */                                   \
-                                                                       \
-  {                                                                    \
-    uint32 iv[PRE##_BLKSZ / 4];                                                \
-    BLKC_LOAD(PRE, iv, ctx->iv);                                       \
-                                                                       \
-    for (;;) {                                                         \
-      uint32 x[PRE##_BLKSZ / 4];                                       \
-      pre##_eblk(&ctx->ctx, iv, iv);                                   \
-      if (sz < PRE##_BLKSZ)                                            \
-       break;                                                          \
-      BLKC_LOAD(PRE, x, s);                                            \
-      BLKC_XSTORE(PRE, d, iv, x);                                      \
-      BLKC_MOVE(PRE, iv, x);                                           \
-      s += PRE##_BLKSZ;                                                        \
-      d += PRE##_BLKSZ;                                                        \
-      sz -= PRE##_BLKSZ;                                               \
-    }                                                                  \
-    off = 0;                                                           \
-    BLKC_STORE(PRE, ctx->iv, iv);                                      \
-  }                                                                    \
-                                                                       \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    do {                                                               \
-      register octet x = *s++;                                         \
-      *d++ = ctx->iv[off] ^ x;                                         \
-      ctx->iv[off++] = x;                                              \
-      sz--;                                                            \
-    } while (sz);                                                      \
-  }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
-}                                                                      \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-static const gcipher_ops gops;                                         \
-                                                                       \
-typedef struct gctx {                                                  \
-  gcipher c;                                                           \
-  pre##_cfbctx k;                                                      \
-} gctx;                                                                        \
-                                                                       \
-static gcipher *ginit(const void *k, size_t sz)                                \
-{                                                                      \
-  gctx *g = S_CREATE(gctx);                                            \
-  g->c.ops = &gops;                                                    \
-  pre##_cfbinit(&g->k, k, sz, 0);                                      \
-  return (&g->c);                                                      \
-}                                                                      \
-                                                                       \
-static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cfbencrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
-                                                                       \
-static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cfbdecrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
-                                                                       \
-static void gdestroy(gcipher *c)                                       \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static void gsetiv(gcipher *c, const void *iv)                         \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cfbsetiv(&g->k, iv);                                           \
-}                                                                      \
-                                                                       \
-static void gbdry(gcipher *c)                                          \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cfbbdry(&g->k);                                                        \
-}                                                                      \
-                                                                       \
-static const gcipher_ops gops = {                                      \
-  &pre##_cfb,                                                          \
-  gencrypt, gdecrypt, gdestroy, gsetiv, gbdry                          \
-};                                                                     \
-                                                                       \
-const gccipher pre##_cfb = {                                           \
-  #pre "-cfb", pre##_keysz, PRE##_BLKSZ,                               \
-  ginit                                                                        \
-};                                                                     \
-                                                                       \
-CFB_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @CFB_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use:                Standard test rig for CFB functions.
- */
-
-#define CFB_TEST(PRE, pre)                                             \
-                                                                       \
-/* --- Initial plaintext for the test --- */                           \
-                                                                       \
-static const octet text[] = TEXT;                                      \
-                                                                       \
-/* --- Key and IV to use --- */                                                \
-                                                                       \
-static const octet key[] = KEY;                                                \
-static const octet iv[] = IV;                                          \
-                                                                       \
-/* --- Buffers for encryption and decryption output --- */             \
-                                                                       \
-static octet ct[sizeof(text)];                                         \
-static octet pt[sizeof(text)];                                         \
-                                                                       \
-static void hexdump(const octet *p, size_t sz)                         \
-{                                                                      \
-  const octet *q = p + sz;                                             \
-  for (sz = 0; p < q; p++, sz++) {                                     \
-    printf("%02x", *p);                                                        \
-    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
-      putchar(':');                                                    \
-  }                                                                    \
-}                                                                      \
-                                                                       \
-int main(void)                                                         \
-{                                                                      \
-  size_t sz = 0, rest;                                                 \
-  pre##_cfbctx ctx;                                                    \
-  int status = 0;                                                      \
-  int done = 0;                                                                \
-  pre##_ctx k;                                                         \
-                                                                       \
-  size_t keysz = PRE##_KEYSZ ?                                         \
-    PRE##_KEYSZ : strlen((const char *)key);                           \
-                                                                       \
-  fputs(#pre "-cfb: ", stdout);                                                \
-                                                                       \
-  pre##_init(&k, key, keysz);                                          \
-  pre##_cfbsetkey(&ctx, &k);                                           \
-                                                                       \
-  while (sz <= sizeof(text)) {                                         \
-    rest = sizeof(text) - sz;                                          \
-    memcpy(ct, text, sizeof(text));                                    \
-    pre##_cfbsetiv(&ctx, iv);                                          \
-    pre##_cfbencrypt(&ctx, ct, ct, sz);                                        \
-    pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest);                    \
-    memcpy(pt, ct, sizeof(text));                                      \
-    pre##_cfbsetiv(&ctx, iv);                                          \
-    pre##_cfbdecrypt(&ctx, pt, pt, rest);                              \
-    pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz);                  \
-    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
-      done++;                                                          \
-      if (sizeof(text) < 40 || done % 8 == 0)                          \
-       fputc('.', stdout);                                             \
-      if (done % 480 == 0)                                             \
-       fputs("\n\t", stdout);                                          \
-      fflush(stdout);                                                  \
-    } else {                                                           \
-      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
-      status = 1;                                                      \
-      printf("\tplaintext      = "); hexdump(text, sz);                        \
-       printf(", "); hexdump(text + sz, rest);                         \
-       fputc('\n', stdout);                                            \
-      printf("\tciphertext     = "); hexdump(ct, sz);                  \
-       printf(", "); hexdump(ct + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      printf("\trecovered text = "); hexdump(pt, sz);                  \
-       printf(", "); hexdump(pt + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      fputc('\n', stdout);                                             \
-    }                                                                  \
-    if (sz < 63)                                                       \
-      sz++;                                                            \
-    else                                                               \
-      sz += 9;                                                         \
-  }                                                                    \
-                                                                       \
-  fputs(status ? " failed\n" : " ok\n", stdout);                       \
-  return (status);                                                     \
-}
-
-#else
-#  define CFB_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/cfb.h b/cfb.h
deleted file mode 100644 (file)
index e2082a1..0000000
--- a/cfb.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* -*-c-*-
- *
- * $Id: cfb.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Ciphertext feedback for block ciphers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_CFB_H
-#define CATACOMB_CFB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- @CFB_DECL@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use:                Creates declarations for CFB mode.
- */
-
-#define CFB_DECL(PRE, pre)                                             \
-                                                                       \
-/* --- Ciphertext feedback context --- */                              \
-                                                                       \
-typedef struct pre##_cfbctx {                                          \
-  pre##_ctx ctx;                       /* Underlying cipher context */ \
-  unsigned off;                                /* Offset into @iv@ buffer */   \
-  octet iv[PRE##_BLKSZ];               /* Previous ciphertext or IV */ \
-} pre##_cfbctx;                                                                \
-                                                                       \
-/* --- @pre_cfbgetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @const pre_cfbctx *ctx@ = pointer to CFB context block  \
- *             @void *iv@ = pointer to output data block               \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Reads the currently set IV.  Reading and setting an IV  \
- *             is not transparent to the cipher.  It will add a `step' \
- *             which must be matched by a similar operation during     \
- *             decryption.                                             \
- */                                                                    \
-                                                                       \
-extern void pre##_cfbgetiv(const pre##_cfbctx */*ctx*/,                        \
-                          void */*iv*/);                               \
-                                                                       \
-/* --- @pre_cfbsetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *             @cnost void *iv@ = pointer to IV to set                 \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the IV to use for subsequent encryption.           \
- */                                                                    \
-                                                                       \
-extern void pre##_cfbsetiv(pre##_cfbctx */*ctx*/,                      \
-                          const void */*iv*/);                         \
-                                                                       \
-/* --- @pre_cfbbdry@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Inserts a boundary during encryption.  Successful       \
- *             decryption must place a similar boundary.               \
- */                                                                    \
-                                                                       \
-extern void pre##_cfbbdry(pre##_cfbctx */*ctx*/);                      \
-                                                                       \
-/* --- @pre_cfbsetkey@ --- *                                           \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the CFB context to use a different cipher key.     \
- */                                                                    \
-                                                                       \
-extern void pre##_cfbsetkey(pre##_cfbctx */*ctx*/,                     \
-                           const pre##_ctx */*k*/);                    \
-                                                                       \
-/* --- @pre_cfbinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to cipher context           \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a CFB context ready for use.  You should    \
- *             ensure that the IV chosen is unique: reusing an IV will \
- *             compromise the security of at least the first block     \
- *             encrypted.  This is equivalent to calls to @pre_init@,  \
- *             @pre_cfbsetkey@ and @pre_cfbsetiv@.                     \
- */                                                                    \
-                                                                       \
-extern void pre##_cfbinit(pre##_cfbctx */*ctx*/,                       \
-                         const void */*key*/, size_t /*sz*/,           \
-                         const void */*iv*/);                          \
-                                                                       \
-/* --- @pre_cfbencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts a block with a block cipher in CFB mode.  The  \
- *             input block may be arbitrary in size.  CFB mode is not  \
- *             sensitive to block boundaries.                          \
- */                                                                    \
-                                                                       \
-extern void pre##_cfbencrypt(pre##_cfbctx */*ctx*/,                    \
-                            const void */*src*/, void */*dest*/,       \
-                            size_t /*sz*/);                            \
-                                                                       \
-/* --- @pre_cfbencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Decrypts a block with a block cipher in CFB mode.  The  \
- *             input block may be arbitrary in size.  CFB mode is not  \
- *             sensitive to block boundaries.                          \
- */                                                                    \
-                                                                       \
-extern void pre##_cfbdecrypt(pre##_cfbctx */*ctx*/,                    \
-                            const void */*src*/, void */*dest*/,       \
-                            size_t /*sz*/);                            \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-extern const gccipher pre##_cfb;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
index 9aff84a..aca24fe 100644 (file)
@@ -46,6 +46,9 @@ AC_SUBST(AM_CFLAGS)
 dnl--------------------------------------------------------------------------
 dnl C programming environment.
 
+dnl Find out if we're cross-compiling.
+AM_CONDITIONAL([CROSS_COMPILING], [test "$cross_compiling" = yes])
+
 dnl Various standard types.
 AC_CHECK_TYPE([pid_t], [int])
 AC_TYPE_UID_T
@@ -119,7 +122,15 @@ dnl Produce output.
 AC_CONFIG_HEADER([config/config.h])
 
 AC_CONFIG_FILES(
-  [Makefile])
+  [Makefile]
+  [base/Makefile]
+  [key/Makefile]
+  [math/Makefile]
+  [misc/Makefile]
+  [pub/Makefile]
+  [rand/Makefile]
+  [symm/Makefile]
+  [progs/Makefile])
 AC_OUTPUT
 
 dnl----- That's all, folks --------------------------------------------------
diff --git a/cookie.c b/cookie.c
deleted file mode 100644 (file)
index 8fa07da..0000000
--- a/cookie.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generate and validate cryptographic cookies
- *
- * (c) 1999 Mark Wooding
- */
-
-/*----- 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 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 General Public License for more details.
- *
- * You should have received a copy of the GNU 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include "config.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <mLib/base64.h>
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include "cc.h"
-#include "key.h"
-#include "gmac.h"
-#include "getdate.h"
-
-/*----- Handy global state ------------------------------------------------*/
-
-static const char *keyfile = "keyring";
-
-/*----- Cookie format -----------------------------------------------------*/
-
-/* --- Cookie header structure (unpacked) --- */
-
-typedef struct cookie {
-  uint32 k;
-  time_t exp;
-} cookie;
-
-/* --- Size of a cookie header (packed) --- */
-
-#define COOKIE_SZ (4 + 8)
-
-/* --- @COOKIE_PACK@ --- *
- *
- * Arguments:  @p@ = pointer to destination buffer
- *             @c@ = pointer to source cookie header block
- *
- * Use:                Packs a cookie header into an octet buffer in a machine-
- *             independent way.
- */
-
-#define COOKIE_PACK(p, c) do {                                         \
-  octet *_p = (octet *)(p);                                            \
-  const cookie *_c = (c);                                              \
-  STORE32(_p + 0, _c->k);                                              \
-  STORE32(_p + 4, ((_c->exp & ~MASK32) >> 16) >> 16);                  \
-  STORE32(_p + 8, _c->exp);                                            \
-} while (0)
-
-/* --- @COOKIE_UNPACK@ --- *
- *
- * Arguments:  @c@ = pointer to destination cookie header
- *             @p@ = pointer to source buffer
- *
- * Use:                Unpacks a cookie header from an octet buffer into a
- *             machine-specific but comprehensible structure.
- */
-
-#define COOKIE_UNPACK(c, p) do {                                       \
-  cookie *_c = (c);                                                    \
-  const octet *_p = (const octet *)(p);                                        \
-  _c->k = LOAD32(_p + 0);                                              \
-  _c->exp = ((time_t)(((LOAD32(_p + 4) << 16) << 16) & ~MASK32) |      \
-            (time_t)LOAD32(_p + 8));                                   \
-} while (0)
-
-/*----- Useful shared functions -------------------------------------------*/
-
-/* --- @doopen@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *             @unsigned how@ = method to open file with
- *
- * Returns:    ---
- *
- * Use:                Opens a key file and handles errors by panicking
- *             appropriately.
- */
-
-static void doopen(key_file *f, unsigned how)
-{
-  if (key_open(f, keyfile, how, key_moan, 0)) {
-    die(EXIT_FAILURE, "couldn't open file `%s': %s",
-       keyfile, strerror(errno));
-  }
-}
-
-/* --- @doclose@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *
- * Returns:    ---
- *
- * Use:                Closes a key file and handles errors by panicking
- *             appropriately.
- */
-
-static void doclose(key_file *f)
-{
-  switch (key_close(f)) {
-    case KWRITE_FAIL:
-      die(EXIT_FAILURE, "couldn't write file `%s': %s",
-         keyfile, strerror(errno));
-    case KWRITE_BROKEN:
-      die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)",
-         keyfile, strerror(errno));
-  }
-}
-
-/* --- @getmac@ --- *
- *
- * Arguments:  @key *k@ = key to use
- *             @const char *app@ = application name
- *
- * Returns:    The MAC to use.
- *
- * Use:                Finds the right MAC for the given key.
- */
-
-static gmac *getmac(key *k, const char *app)
-{
-  dstr t = DSTR_INIT;
-  dstr d = DSTR_INIT;
-  char *p = 0;
-  const char *q;
-  size_t n;
-  key_bin kb;
-  key_packdef kp;
-  const gcmac *cm;
-  int e;
-  gmac *m;
-
-  /* --- Set up --- */
-
-  key_fulltag(k, &t);
-
-  /* --- Pick out the right MAC --- */
-
-  n = strlen(app);
-  if ((q = key_getattr(0, k, "mac")) != 0) {
-    dstr_puts(&d, q);
-    p = d.buf;
-  } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') {
-    dstr_puts(&d, k->type);
-    p = d.buf + n + 1;
-  } else
-    die(EXIT_FAILURE, "no MAC algorithm for key `%s'", t.buf);
-  if ((cm = gmac_byname(p)) == 0) {
-    die(EXIT_FAILURE, "MAC algorithm `%s' not found in key `%s'",
-       p, t.buf);
-  }
-
-  /* --- Unlock the key --- */
-
-  kp.e = KENC_BINARY;
-  kp.p = &kb;
-  if ((e = key_unpack(&kp, k->k, &t)) != 0) {
-    die(EXIT_FAILURE, "error unpacking key `%s': %s",
-       t.buf, key_strerror(e));
-  }
-
-  /* --- Make the MAC object --- */
-
-  if (keysz(kb.sz, cm->keysz) != kb.sz)
-    die(EXIT_FAILURE, "key %s has bad length (%lu) for MAC %s",
-       t.buf, (unsigned long)kb.sz, cm->name);
-  m = cm->key(kb.k, kb.sz);
-  key_unpackdone(&kp);
-  return (m);
-}
-
-/*----- Command implementation --------------------------------------------*/
-
-/* --- @cmd_gen@ --- */
-
-static int cmd_gen(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  gmac *m;
-  ghash *h;
-  const char *tag = "cookie";
-  int err;
-  cookie c = { 0, KEXP_EXPIRE };
-  unsigned fl = 0;
-  int bits = 32;
-  const octet *t;
-  dstr d = DSTR_INIT;
-  octet buf[COOKIE_SZ];
-  base64_ctx b;
-
-  /* --- Various useful flag bits --- */
-
-#define f_bogus 1u
-
-  /* --- Parse options for the subcommand --- */
-
-  for (;;) {
-    static struct option opt[] = {
-      { "bits",                OPTF_ARGREQ,    0,      'b' },
-      { "expire",      OPTF_ARGREQ,    0,      'e' },
-      { "key",         OPTF_ARGREQ,    0,      'k' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+b:e:i:t:", opt, 0, 0, 0);
-    if (i < 0)
-      break;
-
-    /* --- Handle the various options --- */
-
-    switch (i) {
-
-      /* --- Fetch a size in bits --- */
-
-      case 'b':
-       if (!(bits = atoi(optarg)) || bits % 8)
-         die(EXIT_FAILURE, "bad number of bits: `%s'", optarg);
-       break;
-
-      /* --- Fetch an expiry time --- */
-
-      case 'e':
-       if (strcmp(optarg, "forever") == 0)
-         c.exp = KEXP_FOREVER;
-       else if ((c.exp = get_date(optarg, 0)) == -1)
-         die(EXIT_FAILURE, "bad expiry date: `%s'", optarg);
-       break;
-
-      /* --- Fetch a key type --- */
-
-      case 'k':
-       tag = optarg;
-       break;
-
-      /* --- Other things are bogus --- */
-
-      default:
-       fl |= f_bogus;
-       break;
-    }
-  }
-
-  /* --- Various sorts of bogosity --- */
-
-  if (fl & f_bogus || optind + 1 < argc)
-    die(EXIT_FAILURE,
-       "Usage: generate [-b BITS] [-e TIME] [-k TAG] [DATA]");
-
-  /* --- Choose a default expiry time --- */
-
-  if (c.exp == KEXP_EXPIRE)
-    c.exp = time(0) + 7 * 24 * 60 * 60;
-
-  /* --- Open the key file and get the key --- */
-
-  doopen(&f, KOPEN_WRITE);
-  if ((k = key_bytag(&f, tag)) == 0) {
-    die(EXIT_FAILURE, "no key with tag `%s' in keyring `%s'",
-       tag, keyfile);
-  }
-
-  c.k = k->id;
-  if ((err = key_used(&f, k, c.exp)) != 0)
-    die(EXIT_FAILURE, "can't generate cookie: %s", key_strerror(err));
-  m = getmac(k, "cookie");
-  if (bits/8 > GM_CLASS(m)->hashsz) {
-    die(EXIT_FAILURE, "inapproriate bit length for `%s' MACs",
-       GM_CLASS(m)->name);
-  }
-
-  /* --- Store and MAC the cookie --- */
-
-  COOKIE_PACK(buf, &c);
-
-  h = GM_INIT(m);
-  GH_HASH(h, buf, sizeof(buf));
-  if (argv[optind])
-    GH_HASH(h, argv[optind], strlen(argv[optind]));
-  t = GH_DONE(h, 0);
-
-  /* --- Encode and emit the finished cookie --- */
-
-  base64_init(&b);
-  b.indent = "";
-  base64_encode(&b, buf, sizeof(buf), &d);
-  base64_encode(&b, t, bits/8, &d);
-  base64_encode(&b, 0, 0, &d);
-  DWRITE(&d, stdout);
-  fputc('\n', stdout);
-  DDESTROY(&d);
-  GH_DESTROY(h);
-  GM_DESTROY(m);
-
-  doclose(&f);
-  return (0);
-
-#undef f_bogus
-}
-
-/* --- @cmd_verify@ --- */
-
-static int cmd_verify(int argc, char *argv[])
-{
-  key_file f;
-  dstr d = DSTR_INIT;
-  unsigned fl = 0;
-  int bits = -1, minbits = 32;
-  int v = 1;
-  base64_ctx b;
-  gmac *m;
-  ghash *h;
-  cookie c;
-  key *k;
-  int cbits;
-  const octet *t;
-  time_t now = time(0);
-
-  /* --- Various useful flag bits --- */
-
-#define f_bogus 1u
-#define f_forever 2u
-#define f_utc 4u
-
-  /* --- Parse options for the subcommand --- */
-
-  for (;;) {
-    static struct option opt[] = {
-      { "bits",                OPTF_ARGREQ,    0,      'b' },
-      { "min-bits",    OPTF_ARGREQ,    0,      'm' },
-      { "forever",     0,              0,      'f' },
-      { "quiet",       0,              0,      'q' },
-      { "verbose",     0,              0,      'v' },
-      { "utc",         0,              0,      'u' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+b:m:fqvu", opt, 0, 0, 0);
-    if (i < 0)
-      break;
-
-    /* --- Handle the various options --- */
-
-    switch (i) {
-
-      /* --- Fetch a size in bits --- */
-
-      case 'b':
-       if (!(bits = atoi(optarg)) || bits % 8)
-         die(EXIT_FAILURE, "bad number of bits: `%s'", optarg);
-       break;
-      case 'm':
-       if (!(minbits = atoi(optarg)) || minbits % 8)
-         die(EXIT_FAILURE, "bad number of bits: `%s'", optarg);
-       break;
-
-      /* --- Miscellaneous flags --- */
-
-      case 'f':
-       fl |= f_forever;
-       break;
-      case 'u':
-       fl |= f_utc;
-       break;
-      case 'q':
-       if (v > 0) v--;
-       break;
-      case 'v':
-       v++;
-       break;
-
-      /* --- Other things are bogus --- */
-
-      default:
-       fl |= f_bogus;
-       break;
-    }
-  }
-
-  /* --- Various sorts of bogosity --- */
-
-  if (fl & f_bogus || optind == argc || optind + 2 < argc) {
-    die(EXIT_FAILURE,
-       "Usage: verify [-fuqv] [-b BITS] [-m BITS] COOKIE [DATA]");
-  }
-  doopen(&f, KOPEN_READ);
-
-  /* --- Decode the base64 wrapping --- */
-
-  base64_init(&b);
-  base64_decode(&b, argv[optind], strlen(argv[optind]), &d);
-  base64_decode(&b, 0, 0, &d);
-
-  if (d.len < COOKIE_SZ + 1) {
-    if (v) printf("FAIL cookie too small\n");
-    goto fail;
-  }
-
-  /* --- Extract the relevant details --- */
-
-  COOKIE_UNPACK(&c, d.buf);
-
-  if (v > 1) {
-    char buf[64];
-    if (c.exp == KEXP_FOREVER)
-      strcpy(buf, "forever");
-    else {
-      struct tm *tm;
-      const char *fmt;
-
-      if (fl & f_utc) {
-       tm = gmtime(&c.exp);
-       fmt = "%Y-%m-%d %H:%M:%S UTC";
-      } else {
-       tm = localtime(&c.exp);
-       fmt = "%Y-%m-%d %H:%M:%S %Z";
-      }
-      strftime(buf, sizeof(buf), fmt, tm);
-    }
-    printf("INFO keyid = %08lx; expiry = %s\n", (unsigned long)c.k, buf);
-  }
-
-  /* --- Check the authentication token width --- */
-
-  cbits = (d.len - COOKIE_SZ) * 8;
-  if (v > 2) printf("INFO authentication token width = %i bits\n", cbits);
-  if (bits == -1) {
-    if (cbits < minbits) {
-      if (v) printf("FAIL authentication token too narrow\n");
-      goto fail;
-    }
-  } else {
-    if (cbits != bits) {
-      if (v) printf("FAIL authentication token width doesn't match\n");
-      goto fail;
-    }
-  }
-  /* --- Get the key --- */
-
-  if ((k = key_byid(&f, c.k)) == 0) {
-    if (v) printf("FAIL keyid %08lx unavailable\n", (unsigned long)c.k);
-    goto fail;
-  }
-
-  /* --- Check that the cookie authenticates OK --- */
-
-  m = getmac(k, "cookie");
-  h = GM_INIT(m);
-  GH_HASH(h, d.buf, COOKIE_SZ);
-  if (argv[optind + 1])
-    GH_HASH(h, argv[optind + 1], strlen(argv[optind + 1]));
-  t = GH_DONE(h, 0);
-
-  if (memcmp(t, d.buf + COOKIE_SZ, cbits / 8) != 0) {
-    if (v) printf("FAIL bad authentication token\n");
-    goto fail;
-  }
-
-  /* --- See whether the cookie has expired --- */
-
-  if (c.exp == KEXP_FOREVER) {
-    if (!(fl & f_forever)) {
-      if (v) printf("FAIL forever cookies not allowed\n");
-      goto fail;
-    }
-    if (k->exp != KEXP_FOREVER) {
-      if (v) printf("FAIL cookie lasts forever but key will expire\n");
-      goto fail;
-    }
-  } else if (c.exp < now) {
-    if (v) printf("FAIL cookie has expired\n");
-    goto fail;
-  }
-
-  if (v) printf("OK\n");
-  key_close(&f);
-  GM_DESTROY(m);
-  GH_DESTROY(h);
-  dstr_destroy(&d);
-  return (0);
-
-fail:
-  key_close(&f);
-  dstr_destroy(&d);
-  return (1);
-
-#undef f_bogus
-#undef f_forever
-#undef f_utc
-}
-
-/*----- Main command table ------------------------------------------------*/
-
-static int cmd_help(int, char **);
-
-#define LISTS(LI)                                                      \
-  LI("Lists", list,                                                    \
-     listtab[i].name, listtab[i].name)                                 \
-  LI("Message authentication algorithms", mac,                         \
-     gmactab[i], gmactab[i]->name)
-
-MAKELISTTAB(listtab, LISTS)
-
-static int cmd_show(int argc, char *argv[])
-{
-  return (displaylists(listtab, argv + 1));
-}
-
-static cmd cmds[] = {
-  { "help", cmd_help, "help [COMMAND...]" },
-  { "show", cmd_show, "show [ITEM...]" },
-  { "generate", cmd_gen,
-    "generate [-b BITS] [-e TIME] [-k TAG] [DATA]", "\
-Options:\n\
-\n\
--b, --bits=N           Use an N-bit token in the cookie.\n\
--e, --expire=TIME      Make the cookie expire after TIME.\n\
--k, --key=TAG          Use key TAG to create the token.\n\
-" },
-  { "verify", cmd_verify,
-    "verify [-fuqv] [-b BITS] [-m BITS] COOKIE [DATA]", "\
-Options:\n\
-\n\
--b, --bits=N           Accept tokens exactly N bits long only.\n\
--m, --min-bits=N       Accept tokens N bits long or more.\n\
--f, --forever          Accept cookies which never expire.\n\
--u, --utc              Output cookie expiry dates in UTC.\n\
--q, --quiet            Produce less output while checking cookies.\n\
--v, --verbose          Produce more output while checking cookies.\n\
-" },
-  { 0, 0, 0 }
-};
-
-static int cmd_help(int argc, char *argv[])
-{
-  sc_help(cmds, stdout, argv + 1);
-  return (0);
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Helpful GNUy functions --- */
-
-static void usage(FILE *fp)
-{
-  fprintf(fp, "Usage: %s [-k KEYRING] COMMAND [ARGS]\n", QUIS);
-}
-
-void version(FILE *fp)
-{
-  fprintf(fp, "%s, Catacomb version " VERSION "\n", QUIS);
-}
-
-void help_global(FILE *fp)
-{
-  usage(fp);
-  fputs("\n\
-Generates and validates cryptographic cookies.  Command line options\n\
-recognized are:\n\
-\n\
--h, --help [COMMAND]   Display this help text (or help for COMMAND).\n\
--v, --version          Display version number.\n\
--u, --usage            Display short usage summary.\n\
-\n\
--k, --key-file=FILE    Read and write keys in FILE.\n",
-       fp);
-}
-
-/* --- @main@ --- *
- *
- * Arguments:  @int argc@ = number of command line arguments
- *             @char *argv[]@ = array of arguments
- *
- * Returns:    Zero if OK, nonzero if not.
- *
- * Use:                Generates and validates cryptographic cookies.
- */
-
-int main(int argc, char *argv[])
-{
-  unsigned f = 0;
-
-#define f_bogus 1u
-#define f_forever 2u
-
-  /* --- Initialize the library --- */
-
-  ego(argv[0]);
-  sub_init();
-
-  /* --- Options parsing --- */
-
-  for (;;) {
-    static struct option opt[] = {
-
-      /* --- Standard GNUy help options --- */
-
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'v' },
-      { "usage",       0,              0,      'u' },
-
-      /* --- Actual relevant options --- */
-
-      { "keyring",     OPTF_ARGREQ,    0,      'k' },
-
-      /* --- Magic terminator --- */
-
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+hvu k:", opt, 0, 0, 0);
-
-    if (i < 0)
-      break;
-    switch (i) {
-
-      /* --- Helpful GNUs --- */
-
-      case 'u':
-       usage(stdout);
-       exit(0);
-      case 'v':
-       version(stdout);
-       exit(0);
-      case 'h':
-       sc_help(cmds, stdout, argv + optind);
-       exit(0);
-
-      /* --- Real genuine useful options --- */
-
-      case 'k':
-       keyfile = optarg;
-       break;
-
-      /* --- Bogus things --- */
-
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-
-  if ((f & f_bogus) || optind == argc) {
-    usage(stderr);
-    exit(EXIT_FAILURE);
-  }
-
-  /* --- Dispatch to appropriate command handler --- */
-
-  argc -= optind;
-  argv += optind;
-  optind = 0;
-  return (findcmd(cmds, argv[0])->cmd(argc, argv));
-
-#undef f_bogus
-#undef f_forever
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/counter-def.h b/counter-def.h
deleted file mode 100644 (file)
index 129efd9..0000000
+++ /dev/null
@@ -1,535 +0,0 @@
-/* -*-c-*-
- *
- * $Id: counter-def.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Block cipher counter mode (or long cycle mode)
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_COUNTER_DEF_H
-#define CATACOMB_COUNTER_DEF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_BLKC_H
-#  include "blkc.h"
-#endif
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @COUNTER_DEF@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use:                Creates definitions for counter mode.
- */
-
-#define COUNTER_DEF(PRE, pre)                                          \
-                                                                       \
-/* --- @pre_countergetiv@ --- *                                                \
- *                                                                     \
- * Arguments:  @const pre_counterctx *ctx@ = pointer to counter        \
- *                     context                                         \
- *             @void *iv@ = pointer to output data block               \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Reads the currently set IV.  Reading and setting an IV  \
- *             is not transparent to the cipher.  It will add a `step' \
- *             which must be matched by a similar operation during     \
- *             decryption.                                             \
- */                                                                    \
-                                                                       \
-void pre##_countergetiv(const pre##_counterctx *ctx, void *iv)         \
-{                                                                      \
-  BLKC_STORE(PRE, iv, ctx->n);                                         \
-}                                                                      \
-                                                                       \
-/* --- @pre_countersetiv@ --- *                                                \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
- *             @cnost void *iv@ = pointer to IV to set                 \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the IV to use for subsequent encryption.           \
- */                                                                    \
-                                                                       \
-void pre##_countersetiv(pre##_counterctx *ctx, const void *iv)         \
-{                                                                      \
-  BLKC_LOAD(PRE, ctx->n, iv);                                          \
-  ctx->off = PRE##_BLKSZ;                                              \
-}                                                                      \
-                                                                       \
-/* --- @pre_counterbdry@ --- *                                         \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Inserts a boundary during encryption.  Successful       \
- *             decryption must place a similar boundary.               \
- */                                                                    \
-                                                                       \
-void pre##_counterbdry(pre##_counterctx *ctx)                          \
-{                                                                      \
-  BLKC_STEP(PRE, ctx->n);                                              \
-  ctx->off = PRE##_BLKSZ;                                              \
-}                                                                      \
-                                                                       \
-/* --- @pre_countersetkey@ --- *                                       \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the counter context to use a different cipher key. \
- */                                                                    \
-                                                                       \
-void pre##_countersetkey(pre##_counterctx *ctx, const pre##_ctx *k)    \
-{                                                                      \
-  ctx->ctx = *k;                                                       \
-}                                                                      \
-                                                                       \
-/* --- @pre_counterinit@ --- *                                         \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to cipher context       \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a counter context ready for use.  You       \
- *             should ensure that the IV chosen is unique: reusing an  \
- *             IV will compromise the security of the entire           \
- *             plaintext.  This is equivalent to calls to @pre_init@,  \
- *             @pre_countersetkey@ and @pre_countersetiv@.             \
- */                                                                    \
-                                                                       \
-void pre##_counterinit(pre##_counterctx *ctx,                          \
-                      const void *key, size_t sz,                      \
-                      const void *iv)                                  \
-{                                                                      \
-  static const octet zero[PRE##_BLKSZ] = { 0 };                                \
-  pre##_init(&ctx->ctx, key, sz);                                      \
-  pre##_countersetiv(ctx, iv ? iv : zero);                             \
-}                                                                      \
-                                                                       \
-/* --- @pre_counterencrypt@ --- *                                      \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts or decrypts a block with a block cipher in     \
- *             counter mode: encryption and decryption are the same in \
- *             counter.  The destination may be null to just churn the \
- *             feedback round for a bit.  The source may be null to    \
- *             use the cipher as a random data generator.              \
- */                                                                    \
-                                                                       \
-void pre##_counterencrypt(pre##_counterctx *ctx,                       \
-                         const void *src, void *dest,                  \
-                         size_t sz)                                    \
-{                                                                      \
-  const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz)                                                             \
-    return;                                                            \
-                                                                       \
-  /* --- If I can deal with the block from my buffer, do that --- */   \
-                                                                       \
-  if (sz < PRE##_BLKSZ - off)                                          \
-    goto small;                                                                \
-                                                                       \
-  /* --- Finish off what's left in my buffer --- */                    \
-                                                                       \
-  if (!d)                                                              \
-    sz -= PRE##_BLKSZ - off;                                           \
-  else {                                                               \
-    while (off < PRE##_BLKSZ) {                                                \
-      register octet x = s ? *s++ : 0;                                 \
-      *d++ = ctx->buf[off++] ^ x;                                      \
-      sz--;                                                            \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  /* --- Main encryption loop --- */                                   \
-                                                                       \
-  {                                                                    \
-    uint32 n[PRE##_BLKSZ / 4];                                         \
-                                                                       \
-    for (;;) {                                                         \
-      pre##_eblk(&ctx->ctx, ctx->n, n);                                        \
-      BLKC_STEP(PRE, ctx->n);                                          \
-      if (sz < PRE##_BLKSZ)                                            \
-       break;                                                          \
-      if (d) {                                                         \
-       if (!s)                                                         \
-         BLKC_STORE(PRE, d, n);                                        \
-       else {                                                          \
-         uint32 x[PRE##_BLKSZ / 4];                                    \
-         BLKC_LOAD(PRE, x, s);                                         \
-         BLKC_XSTORE(PRE, d, n, x);                                    \
-         s += PRE##_BLKSZ;                                             \
-       }                                                               \
-       d += PRE##_BLKSZ;                                               \
-      }                                                                        \
-      sz -= PRE##_BLKSZ;                                               \
-    }                                                                  \
-                                                                       \
-    BLKC_STORE(PRE, ctx->buf, n);                                      \
-    off = 0;                                                           \
-  }                                                                    \
-                                                                       \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    if (!d)                                                            \
-      off += sz;                                                       \
-    else do {                                                          \
-      register octet x = s ? *s++ : 0;                                 \
-      *d++ = ctx->buf[off++] ^ x;                                      \
-      sz--;                                                            \
-    } while (sz);                                                      \
-  }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
-}                                                                      \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-static const gcipher_ops gops;                                         \
-                                                                       \
-typedef struct gctx {                                                  \
-  gcipher c;                                                           \
-  pre##_counterctx k;                                                  \
-} gctx;                                                                        \
-                                                                       \
-static gcipher *ginit(const void *k, size_t sz)                                \
-{                                                                      \
-  gctx *g = S_CREATE(gctx);                                            \
-  g->c.ops = &gops;                                                    \
-  pre##_counterinit(&g->k, k, sz, 0);                                  \
-  return (&g->c);                                                      \
-}                                                                      \
-                                                                       \
-static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_counterencrypt(&g->k, s, t, sz);                               \
-}                                                                      \
-                                                                       \
-static void gdestroy(gcipher *c)                                       \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static void gsetiv(gcipher *c, const void *iv)                         \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_countersetiv(&g->k, iv);                                       \
-}                                                                      \
-                                                                       \
-static void gbdry(gcipher *c)                                          \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_counterbdry(&g->k);                                            \
-}                                                                      \
-                                                                       \
-static const gcipher_ops gops = {                                      \
-  &pre##_counter,                                                      \
-  gencrypt, gencrypt, gdestroy, gsetiv, gbdry                          \
-};                                                                     \
-                                                                       \
-const gccipher pre##_counter = {                                       \
-  #pre "-counter", pre##_keysz, PRE##_BLKSZ,                           \
-  ginit                                                                        \
-};                                                                     \
-                                                                       \
-/* --- Generic random number generator interface --- */                        \
-                                                                       \
-typedef struct grctx {                                                 \
-  grand r;                                                             \
-  pre##_counterctx k;                                                  \
-} grctx;                                                               \
-                                                                       \
-static void grdestroy(grand *r)                                                \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static int grmisc(grand *r, unsigned op, ...)                          \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  va_list ap;                                                          \
-  int rc = 0;                                                          \
-  octet buf[PRE##_BLKSZ];                                              \
-  va_start(ap, op);                                                    \
-                                                                       \
-  switch (op) {                                                                \
-    case GRAND_CHECK:                                                  \
-      switch (va_arg(ap, unsigned)) {                                  \
-       case GRAND_CHECK:                                               \
-       case GRAND_SEEDINT:                                             \
-       case GRAND_SEEDUINT32:                                          \
-       case GRAND_SEEDBLOCK:                                           \
-       case GRAND_SEEDRAND:                                            \
-         rc = 1;                                                       \
-         break;                                                        \
-       default:                                                        \
-         rc = 0;                                                       \
-         break;                                                        \
-      }                                                                        \
-      break;                                                           \
-    case GRAND_SEEDINT:                                                        \
-      BLKC_SET(PRE, g->k.n, va_arg(ap, unsigned));                     \
-      g->k.off = PRE##_BLKSZ;                                          \
-      break;                                                           \
-    case GRAND_SEEDUINT32:                                             \
-      BLKC_SET(PRE, g->k.n, va_arg(ap, uint32));                       \
-      g->k.off = PRE##_BLKSZ;                                          \
-      break;                                                           \
-    case GRAND_SEEDBLOCK: {                                            \
-      const void *p = va_arg(ap, const void *);                                \
-      size_t sz = va_arg(ap, size_t);                                  \
-      if (sz < sizeof(buf)) {                                          \
-       memset(buf, 0, sizeof(buf));                                    \
-       memcpy(buf, p, sz);                                             \
-       p = buf;                                                        \
-      }                                                                        \
-      pre##_countersetiv(&g->k, p);                                    \
-    } break;                                                           \
-    case GRAND_SEEDRAND: {                                             \
-      grand *rr = va_arg(ap, grand *);                                 \
-      rr->ops->fill(rr, buf, sizeof(buf));                             \
-      pre##_countersetiv(&g->k, buf);                                  \
-    } break;                                                           \
-    default:                                                           \
-      GRAND_BADOP;                                                     \
-      break;                                                           \
-  }                                                                    \
-                                                                       \
-  va_end(ap);                                                          \
-  return (rc);                                                         \
-}                                                                      \
-                                                                       \
-static octet grbyte(grand *r)                                          \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  octet o;                                                             \
-  pre##_counterencrypt(&g->k, 0, &o, 1);                               \
-  return (o);                                                          \
-}                                                                      \
-                                                                       \
-static uint32 grword(grand *r)                                         \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  octet b[4];                                                          \
-  pre##_counterencrypt(&g->k, 0, b, sizeof(b));                                \
-  return (LOAD32(b));                                                  \
-}                                                                      \
-                                                                       \
-static void grfill(grand *r, void *p, size_t sz)                       \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  pre##_counterencrypt(&g->k, 0, p, sz);                               \
-}                                                                      \
-                                                                       \
-static const grand_ops grops = {                                       \
-  #pre "-counter",                                                     \
-  GRAND_CRYPTO, 0,                                                     \
-  grmisc, grdestroy,                                                   \
-  grword, grbyte, grword, grand_range, grfill                          \
-};                                                                     \
-                                                                       \
-/* --- @pre_counterrand@ --- *                                         \
- *                                                                     \
- * Arguments:  @const void *k@ = pointer to key material               \
- *             @size_t sz@ = size of key material                      \
- *                                                                     \
- * Returns:    Pointer to generic random number generator interface.   \
- *                                                                     \
- * Use:                Creates a random number interface wrapper around an     \
- *             counter-mode block cipher.                              \
- */                                                                    \
-                                                                       \
-grand *pre##_counterrand(const void *k, size_t sz)                     \
-{                                                                      \
-  grctx *g = S_CREATE(grctx);                                          \
-  g->r.ops = &grops;                                                   \
-  pre##_counterinit(&g->k, k, sz, 0);                                  \
-  return (&g->r);                                                      \
-}                                                                      \
-                                                                       \
-COUNTER_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @COUNTER_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use:                Standard test rig for counter functions.
- */
-
-#define COUNTER_TEST(PRE, pre)                                         \
-                                                                       \
-/* --- Initial plaintext for the test --- */                           \
-                                                                       \
-static const octet text[] = TEXT;                                      \
-                                                                       \
-/* --- Key and IV to use --- */                                                \
-                                                                       \
-static const octet key[] = KEY;                                                \
-static const octet iv[] = IV;                                          \
-                                                                       \
-/* --- Buffers for encryption and decryption output --- */             \
-                                                                       \
-static octet ct[sizeof(text)];                                         \
-static octet pt[sizeof(text)];                                         \
-                                                                       \
-static void hexdump(const octet *p, size_t sz)                         \
-{                                                                      \
-  const octet *q = p + sz;                                             \
-  for (sz = 0; p < q; p++, sz++) {                                     \
-    printf("%02x", *p);                                                        \
-    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
-      putchar(':');                                                    \
-  }                                                                    \
-}                                                                      \
-                                                                       \
-int main(void)                                                         \
-{                                                                      \
-  size_t sz = 0, rest;                                                 \
-  pre##_counterctx ctx;                                                        \
-  int status = 0;                                                      \
-  int done = 0;                                                                \
-  pre##_ctx k;                                                         \
-                                                                       \
-  size_t keysz = PRE##_KEYSZ ?                                         \
-    PRE##_KEYSZ : strlen((const char *)key);                           \
-                                                                       \
-  fputs(#pre "-counter: ", stdout);                                    \
-                                                                       \
-  pre##_init(&k, key, keysz);                                          \
-  pre##_countersetkey(&ctx, &k);                                       \
-                                                                       \
-  while (sz <= sizeof(text)) {                                         \
-    rest = sizeof(text) - sz;                                          \
-    memcpy(ct, text, sizeof(text));                                    \
-    pre##_countersetiv(&ctx, iv);                                      \
-    pre##_counterencrypt(&ctx, ct, ct, sz);                            \
-    pre##_counterencrypt(&ctx, ct + sz, ct + sz, rest);                        \
-    memcpy(pt, ct, sizeof(text));                                      \
-    pre##_countersetiv(&ctx, iv);                                      \
-    pre##_counterencrypt(&ctx, pt, pt, rest);                          \
-    pre##_counterencrypt(&ctx, pt + rest, pt + rest, sz);              \
-    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
-      done++;                                                          \
-      if (sizeof(text) < 40 || done % 8 == 0)                          \
-       fputc('.', stdout);                                             \
-      if (done % 480 == 0)                                             \
-       fputs("\n\t", stdout);                                          \
-      fflush(stdout);                                                  \
-    } else {                                                           \
-      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
-      status = 1;                                                      \
-      printf("\tplaintext      = "); hexdump(text, sz);                        \
-       printf(", "); hexdump(text + sz, rest);                         \
-       fputc('\n', stdout);                                            \
-      printf("\tciphertext     = "); hexdump(ct, sz);                  \
-       printf(", "); hexdump(ct + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      printf("\trecovered text = "); hexdump(pt, sz);                  \
-       printf(", "); hexdump(pt + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      fputc('\n', stdout);                                             \
-    }                                                                  \
-    if (sz < 63)                                                       \
-      sz++;                                                            \
-    else                                                               \
-      sz += 9;                                                         \
-  }                                                                    \
-                                                                       \
-  fputs(status ? " failed\n" : " ok\n", stdout);                       \
-  return (status);                                                     \
-}
-
-#else
-#  define COUNTER_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/counter.h b/counter.h
deleted file mode 100644 (file)
index 0cfaa72..0000000
--- a/counter.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/* -*-c-*-
- *
- * $Id: counter.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Block cipher counter mode (or long cycle mode)
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_COUNTER_H
-#define CATACOMB_COUNTER_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @COUNTER_DECL@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use:                Makes declarations for counter mode.
- */
-
-#define COUNTER_DECL(PRE, pre)                                         \
-                                                                       \
-/* --- Counter mode context --- */                                     \
-                                                                       \
-typedef struct pre##_counterctx {                                      \
-  pre##_ctx ctx;                       /* Underlying cipher context */ \
-  unsigned off;                                /* Current offset in buffer */  \
-  octet buf[PRE##_BLKSZ];              /* Output buffer */             \
-  uint32 n[PRE##_BLKSZ / 4];           /* Counter */                   \
-} pre##_counterctx;                                                    \
-                                                                       \
-/* --- @pre_countergetiv@ --- *                                                \
- *                                                                     \
- * Arguments:  @const pre_counterctx *ctx@ = pointer to counter        \
- *                     context                                         \
- *             @void *iv@ = pointer to output data block               \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Reads the currently set IV.  Reading and setting an IV  \
- *             is not transparent to the cipher.  It will add a `step' \
- *             which must be matched by a similar operation during     \
- *             decryption.                                             \
- */                                                                    \
-                                                                       \
-extern void pre##_countergetiv(const pre##_counterctx */*ctx*/,                \
-                              void */*iv*/);                           \
-                                                                       \
-/* --- @pre_countersetiv@ --- *                                                \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
- *             @cnost void *iv@ = pointer to IV to set                 \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the IV to use for subsequent encryption.           \
- */                                                                    \
-                                                                       \
-extern void pre##_countersetiv(pre##_counterctx */*ctx*/,              \
-                              const void */*iv*/);                     \
-                                                                       \
-/* --- @pre_counterbdry@ --- *                                         \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Inserts a boundary during encryption.  Successful       \
- *             decryption must place a similar boundary.               \
- */                                                                    \
-                                                                       \
-extern void pre##_counterbdry(pre##_counterctx */*ctx*/);              \
-                                                                       \
-/* --- @pre_countersetkey@ --- *                                       \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the counter context to use a different cipher key. \
- */                                                                    \
-                                                                       \
-extern void pre##_countersetkey(pre##_counterctx */*ctx*/,             \
-                               const pre##_ctx */*k*/);                \
-                                                                       \
-/* --- @pre_counterinit@ --- *                                         \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to cipher context       \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a counter context ready for use.  You       \
- *             should ensure that the IV chosen is unique: reusing an  \
- *             IV will compromise the security of the entire           \
- *             plaintext.  This is equivalent to calls to @pre_init@,  \
- *             @pre_countersetkey@ and @pre_countersetiv@.             \
- */                                                                    \
-                                                                       \
-extern void pre##_counterinit(pre##_counterctx */*ctx*/,               \
-                             const void */*key*/, size_t /*sz*/,       \
-                             const void */*iv*/);                      \
-                                                                       \
-/* --- @pre_counterencrypt@ --- *                                      \
- *                                                                     \
- * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts or decrypts a block with a block cipher in     \
- *             counter mode: encryption and decryption are the same in \
- *             counter.  The destination may be null to just churn the \
- *             feedback round for a bit.  The source may be null to    \
- *             use the cipher as a random data generator.              \
- */                                                                    \
-                                                                       \
-extern void pre##_counterencrypt(pre##_counterctx */*ctx*/,            \
-                                const void */*src*/, void */*dest*/,   \
-                                size_t /*sz*/);                        \
-                                                                       \
-/* --- @pre_counterrand@ --- *                                         \
- *                                                                     \
- * Arguments:  @const void *k@ = pointer to key material               \
- *             @size_t sz@ = size of key material                      \
- *                                                                     \
- * Returns:    Pointer to generic random number generator interface.   \
- *                                                                     \
- * Use:                Creates a random number interface wrapper around an     \
- *             counter-mode block cipher.                              \
- */                                                                    \
-                                                                       \
-extern grand *pre##_counterrand(const void */*k*/, size_t /*sz*/);     \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-extern const gccipher pre##_counter;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/crc32.c b/crc32.c
deleted file mode 100644 (file)
index 3bccfa3..0000000
--- a/crc32.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*-c-*-
- *
- * $Id: crc32.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Generic hash wrapper for CRC32
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/crc32.h>
-#include <mLib/sub.h>
-
-#include "arena.h"
-#include "crc32.h"
-#include "ghash.h"
-#include "paranoia.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-typedef struct gctx {
-  ghash h;
-  uint32 c;
-  octet buf[4];
-} gctx;
-
-static const ghash_ops gops;
-
-static ghash *ghinit(void)
-{
-  gctx *g = S_CREATE(gctx);
-  g->h.ops = &gops;
-  g->c = 0;
-  return (&g->h);
-}
-
-static void ghhash(ghash *h, const void *p, size_t sz)
-{
-  gctx *g = (gctx *)h;
-  CRC32(g->c, g->c, p, sz);
-}
-
-static octet *ghdone(ghash *h, void *buf)
-{
-  gctx *g = (gctx *)h;
-  if (!buf)
-    buf = g->buf;
-  STORE32(buf, g->c);
-  return (buf);
-}
-
-static void ghdestroy(ghash *h)
-{
-  gctx *g = (gctx *)h;
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static ghash *ghcopy(ghash *h)
-{
-  gctx *g = (gctx *)h;
-  gctx *gg = S_CREATE(gctx);
-  memcpy(gg, g, sizeof(gctx));
-  return (&gg->h);
-}
-
-static const ghash_ops gops = { &gcrc32, ghhash, ghdone, ghdestroy, ghcopy };
-const gchash gcrc32 = { "crc32", 4, ghinit };
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/crc32.h b/crc32.h
deleted file mode 100644 (file)
index 1cf164f..0000000
--- a/crc32.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*-c-*-
- *
- * $Id: crc32.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Generic hash wrapper for CRC32
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_CRC32_H
-#define CATACOMB_CRC32_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/crc32.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Generic interface -------------------------------------------------*/
-
-extern const gchash gcrc32;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/daftstory.h b/daftstory.h
deleted file mode 100644 (file)
index 30313a4..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*-c-*-
- *
- * $Id: daftstory.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Daft story for use in test encryptions
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_DAFTSTORY_H
-#define CATACOMB_DAFTSTORY_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- Don't ask --- */
-
-#ifdef SMALL_TEST
-#  define TEXT "A small piece of text for testing encryption."
-#else
-#  define STORY "\
-Once upon a time there were a beautiful princess, a slightly nutty wizard,\n\
-and a watermelon.  Now, the watermelon had decided that it probably wasn't\n\
-going to get very far with the princess unless it did something pretty\n\
-drastic.  So it asked the wizard to turn it into a handsome prince.\n\
-\n\
-At least, this is the way that the wizard viewed the situation.  He might\n\
-have just hallucinated it all; those mushrooms had looked ever so nice.\n\
-\n\
-Back to the point.  The watermelon had expressed its desire not to be a\n\
-watermelon any more.  And the wizard was probably tripping something quite\n\
-powerful.  He hunted around a bit for his staff, and mumbled something\n\
-that film directors would think of as sounding appropriately arcane and\n\
-mystical (but was, in fact, just the ingredients list for an ancient\n\
-remedy for athlete's foot) and *pop*.  Cooked watermelon.  Yuk.\n\
-\n\
-Later in the year, the princess tripped over the hem of her dress, fell\n\
-down a spiral staircase, and died.  The king ordered dressmakers to attach\n\
-safety warnings to long dresses.\n\
-\n\
-And the wizard?         Who cares?\n\
-"
-#  define TEXT STORY STORY
-#endif
-
-#define KEY "Penguins rule OK, rhubarb cauliflower"
-#define IV "EdgewareCatacomb, parsley, sage, rosemary and thyme"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/des-base.c b/des-base.c
deleted file mode 100644 (file)
index 1003cb6..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*-c-*-
- *
- * $Id: des-base.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Common features for DES implementation
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "des-base.h"
-#include "des-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const uint32 des_sp[8][64] = DES_SP;
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/des-base.h b/des-base.h
deleted file mode 100644 (file)
index 709877b..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* -*-c-*-
- *
- * $Id: des-base.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Common features for DES implementation
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_DES_BASE_H
-#define CATACOMB_DES_BASE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- External data -----------------------------------------------------*/
-
-extern const uint32 des_sp[8][64];
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @DES_ROUND@ --- *
- *
- * This is the basic DES round function.  The inputs are the two subkey
- * halves, and the left and right block halves.  Note that the block halves
- * are rotated left one place at this point.  This wraps what's meant to be
- * the top bit around to the bottom, so I get a clear run at the S-boxes.
- */
-
-#define DES_ROUND(ka, kb, x, y) do {                                   \
-  uint32 _t = (y) ^ (ka);                                              \
-  (x) ^= des_sp[7][(_t >>  0) & 0x3f] ^                                        \
-        des_sp[5][(_t >>  8) & 0x3f] ^                                 \
-        des_sp[3][(_t >> 16) & 0x3f] ^                                 \
-        des_sp[1][(_t >> 24) & 0x3f];                                  \
-  _t = ROR32((y), 4) ^ (kb);                                           \
-  (x) ^= des_sp[6][(_t >>  0) & 0x3f] ^                                        \
-        des_sp[4][(_t >>  8) & 0x3f] ^                                 \
-        des_sp[2][(_t >> 16) & 0x3f] ^                                 \
-        des_sp[0][(_t >> 24) & 0x3f];                                  \
-} while (0)
-
-/* --- @DES_IP@, @DES_IPINV@ --- *
- *
- * The cryptographically useless initial and final permutations.  The initial
- * permutation also rotates the two block halves left by one place.  This is
- * undone by the inverse permutation at the end.
- */
-
-#define DES_IP(x, y) do {                                              \
-  uint32 _t;                                                           \
-  _t = (y ^ (x >> 4)) & 0x0f0f0f0f; y ^= _t; x ^= _t << 4;             \
-  _t = (x ^ (x >> 18)) & 0x00003333; x ^= _t; x ^= _t << 18;           \
-  _t = (y ^ (y >> 18)) & 0x00003333; y ^= _t; y ^= _t << 18;           \
-  _t = (x ^ (x >> 9)) & 0x00550055; x ^= _t; x ^= _t << 9;             \
-  _t = (y ^ (y >> 9)) & 0x00550055; y ^= _t; y ^= _t << 9;             \
-  _t = (x ^ (x >> 24)) & 0x000000ff; x ^= _t; x ^= _t << 24;           \
-  _t = (y ^ (y >> 24)) & 0x000000ff; y ^= _t; y ^= _t << 24;           \
-  _t = (y ^ (x >> 16)) & 0x0000ffff; y ^= _t; x ^= _t << 16;           \
-  x = ROL32(x, 1); y = ROL32(y, 1);                                    \
-} while (0)
-
-#define DES_IPINV(x, y) do {                                           \
-  uint32 _t;                                                           \
-  x = ROR32(x, 1); y = ROR32(y, 1);                                    \
-  _t = (y ^ (x >> 16)) & 0x0000ffff; y ^= _t; x ^= _t << 16;           \
-  _t = (x ^ (x >> 24)) & 0x000000ff; x ^= _t; x ^= _t << 24;           \
-  _t = (y ^ (y >> 24)) & 0x000000ff; y ^= _t; y ^= _t << 24;           \
-  _t = (y ^ (x >> 4)) & 0x0f0f0f0f; y ^= _t; x ^= _t << 4;             \
-  _t = (x ^ (x >> 18)) & 0x00003333; x ^= _t; x ^= _t << 18;           \
-  _t = (y ^ (y >> 18)) & 0x00003333; y ^= _t; y ^= _t << 18;           \
-  _t = (x ^ (x >> 9)) & 0x00550055; x ^= _t; x ^= _t << 9;             \
-  _t = (y ^ (y >> 9)) & 0x00550055; y ^= _t; y ^= _t << 9;             \
-} while (0)
-
-/* --- @DES_EBLK@, @DES_DBLK@ --- *
- *
- * Whole block encryption and decryption.
- */
-
-#define DES_EBLK(k, a, b, c, d) do {                                   \
-  const uint32 *_k = (k);                                              \
-  uint32 _x = (a), _y = (b);                                           \
-  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
-  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
-  (c) = _y;                                                            \
-  (d) = _x;                                                            \
-} while (0)
-
-#define DES_DBLK(k, a, b, c, d) do {                                   \
-  const uint32 *_k = (k) + 32;                                         \
-  uint32 _x = (a), _y = (b);                                           \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
-  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
-  (c) = _y;                                                            \
-  (d) = _x;                                                            \
-} while (0)
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/des-mktab.c b/des-mktab.c
deleted file mode 100644 (file)
index 9f27e62..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/* -*-c-*-
- *
- * $Id: des-mktab.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Build combined S-P tables for DES
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-/*----- Static variables --------------------------------------------------*/
-
-/* --- S boxes --- */
-
-static const char s[8][4][16] = {
-
-  /* --- S1 --- */
-
-  { { 14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7 },
-    {  0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8 },
-    {  4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0 },
-    { 15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13 } },
-
-  /* --- S2 --- */
-
-  { { 15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10 },
-    {  3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5 },
-    {  0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15 },
-    { 13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9 } },
-
-  /* --- S3 --- */
-
-  { { 10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8 },
-    { 13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1 },
-    { 13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7 },
-    {  1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12 } },
-
-  /* --- S4 --- */
-
-  { {  7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15 },
-    { 13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9 },
-    { 10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4 },
-    {  3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14 } },
-
-  /* --- S5 --- */
-
-  { {  2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9 },
-    { 14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6 },
-    {  4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14 },
-    { 11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3 } },
-
-  /* --- S6 --- */
-
-  { { 12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11 },
-    { 10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8 },
-    {  9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6 },
-    {  4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13 } },
-
-  /* --- S7 --- */
-
-  { {  4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1 },
-    { 13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6 },
-    {  1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2 },
-    {  6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12 } },
-
-  /* --- S8 --- */
-
-  { { 13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7 },
-    {  1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2 },
-    {  7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8 },
-    {  2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11 } }
-};
-
-/* --- P table --- */
-
-static char p[32] = {
-  16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
-   2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
-};
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @unique@ --- *
- *
- * Arguments:  @const char *t@ = pointer to table
- *             @int base@ = base of the data
- *             @int sz@ = number of elements
- *             @const char *name@ = name of this table
- *             @...@ = things to fill in
- *
- * Returns:    Zero if it failed, nonzero if it didn't.
- *
- * Use:                Validates a table.  All the elements must be in range and
- *             unique.
- */
-
-static int unique(const char *t, int base, int sz, const char *name, ...)
-{
-  char u[32];
-  char nbuf[128];
-  int i;
-  int ok = 1;
-
-  {
-    va_list ap;
-    va_start(ap, name);
-    vsprintf(nbuf, name, ap);
-    va_end(ap);
-  }
-
-  if (sz > sizeof(u)) {
-    fprintf(stderr, "internal error: table `%s' too large\n", nbuf);
-    exit(EXIT_FAILURE);
-  }
-  memset(u, 0, sizeof(u));
-  for (i = 0; i < sz; i++) {
-    int x = t[i] - base;
-    if (x >= sz) {
-      fprintf(stderr, "validation error: %i too big (index %i) in %s\n",
-             x + base, i, nbuf);
-      ok = 0;
-    } else if (u[x]) {
-      fprintf(stderr, "validation error: duplicate %i (index %i) in %s\n",
-             x + base, i, nbuf);
-      ok = 0;
-    }
-    u[x] = 1;
-  }
-  for (i = 0; i < sz; i++) {
-    if (!u[i]) {
-      fprintf(stderr, "validation error: missing %i in %s\n",
-             i + base, nbuf);
-      ok = 0;
-    }
-  }
-
-  return (ok);
-}
-
-/* --- @validate@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    Only if everything's OK.
- *
- * Use:                Validates the tables.  A bit.  Not much at all...
- */
-
-static void validate(void)
-{
-  int i, j;
-  int ok = 1;
-
-  for (i = 0; i < 8; i++) for (j = 0; j < 4; j++)
-    if (!unique(s[i][j], 0, 16, "sbox %i, row %i", i, j)) ok = 0;
-  if (!unique(p, 1, 32, "p")) ok = 0;
-  if (!ok)
-    exit(EXIT_FAILURE);
-}
-
-/* --- @permute@ --- *
- *
- * Arguments:  @unsigned long x@ = value to permute
- *
- * Returns:    Permuted version of @x@.
- *
- * Use:                Permutes a number.  The result is the input value after
- *             having been spewed through the @P@ permutation, and then
- *             (and this is important) rotated left one place.
- */
-
-static unsigned long permute(unsigned long x)
-{
-  unsigned long y = 0;
-  unsigned i;
-
-  for (i = 0; i < 32; i++) {
-    if (x & (1 << (32 - p[i])))
-      y |= (1 << (31 - i));
-  }
-  return (ROL32(y, 1));
-}
-
-/* --- @mangle@ --- *
- *
- * Arguments:  @const char s[4][16]@ = an s-box
- *             @unsigned long ss[64]@ = output buffer
- *             @int bitoff@ = bit offset to use
- *
- * Returns:    ---
- *
- * Use:                Mangles the s-box.  Specifically, the bizarre indexing is
- *             transformed into something sensible, and the result is
- *             permuted according to the @p@ table.
- */
-
-static void mangle(const char s[4][16], unsigned long *ss, int bitoff)
-{
-  unsigned i;
-  for (i = 0; i < 64; i++) {
-    unsigned row = ((i & 0x20) >> 4) | (i & 0x01);
-    unsigned col = (i & 0x1e) >> 1;
-    ss[i] = permute(s[row][col] << bitoff);
-  }
-}
-
-/* --- @main@ --- */
-
-int main(void)
-{
-  int i, j;
-  unsigned long ss[64];
-  const char *sep;
-
-  validate();
-
-  fputs("\
-/* -*-c-*-\n\
- *\n\
- * DES tables [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_DES_TAB_H\n\
-#define CATACOMB_DES_TAB_H\n\
-\n\
-#define DES_SP {                                                       \\\n\
-", stdout);
-  for (i = 0; i < 8; i++) {
-    mangle(s[i], ss, 28 - 4 * i);
-    printf("\
-                                                                       \\\n\
-  /* --- SP[%i] --- */                                                 \\\n\
-                                                                       \\\n\
-", i);
-    sep = "  { ";
-    for (j = 0; j < 64; j++) {
-      printf("%s0x%08lx", sep, ss[j]);
-      if (j % 4 == 3)
-       sep = ",                        \\\n    ";
-      else
-       sep = ", ";
-    }
-    printf(" }%s                       \\\n", i == 7 ? "" : ",");
-  }
-  fputs("\
-}\n\
-\n\
-#endif\n\
-", stdout);
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/des.c b/des.c
deleted file mode 100644 (file)
index e2f0761..0000000
--- a/des.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * The Data Encryption Standard
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "des-base.h"
-#include "des.h"
-#include "gcipher.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet des_keysz[] = { KSZ_SET, 7, 8, 0 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @permute@ --- *
- *
- * Arguments:  @const char *p@ = pointer to permutation table
- *             @uint32 a, b@ = source value to permute
- *             @uint32 *d@ = destination for value
- *
- * Returns:    ---
- *
- * Use:                Performs a 64-bit permutation.  The table is given in the
- *             normal (but bizarre) DES bit numbering system.  That's not to
- *             say that the tables in this source file are like the normal
- *             DES tables, because they're not.
- */
-
-static void permute(const char *p, uint32 a, uint32 b, uint32 *d)
-{
-  uint32 x = 0, y = 0;
-  int i;
-
-  for (i = 0; i < 32; i++) {
-    int q = p[i];
-    uint32 t;
-    if (!q)
-      continue;
-    else if (q <= 32)
-      t = a;
-    else {
-      t = b;
-      q -= 32;
-    }
-    if (t & (1 << (32 - q)))
-      x |= (1 << (31 - i));
-  }
-
-  p += 32;
-
-  for (i = 0; i < 32; i++) {
-    int q = p[i];
-    uint32 t;
-    if (!q)
-      continue;
-    else if (q <= 32)
-      t = a;
-    else {
-      t = b;
-      q -= 32;
-    }
-    if (t & (1 << (32 - q)))
-      y |= (1 << (31 - i));
-  }
-
-  d[0] = x;
-  d[1] = y;
-}
-
-/* --- @des_expand@ --- *
- *
- * Arguments:  @const octet *k@ = pointer to key material
- *             @size_t n@ = number of octets of key material (7 or 8)
- *             @uint32 *xx, *yy@ = where to put the results
- *
- * Returns:    ---
- *
- * Use:                Extracts 64 bits of key material from the given buffer,
- *             possibly expanding it from 56 to 64 bits on the way.
- *             Parity is set correctly if the key is expanded.
- */
-
-void des_expand(const octet *k, size_t n, uint32 *xx, uint32 *yy)
-{
-  uint32 x, y, z;
-
-  if (n == 8) {
-    x = LOAD32(k + 0);
-    y = LOAD32(k + 4);
-  } else {
-    x = LOAD32(k + 0);
-    x = (x & 0xfe000000) | ((x & 0x01fffff0) >> 1);
-    x = (x & 0xfffe0000) | ((x & 0x0001fff8) >> 1);
-    x = (x & 0xfffffe00) | ((x & 0x000001fc) >> 1);
-    z = x; z ^= z >> 4; z ^= z >> 2; z ^= z >> 1;
-    x |= (z & 0x01010101) ^ 0x01010101;
-    y = LOAD32(k + 3) << 1; /* Note: misaligned */
-    y = (y & 0x000000fe) | ((y & 0x1fffff00) << 1);
-    y = (y & 0x0000fefe) | ((y & 0x3fff0000) << 1);
-    y = (y & 0x00fefefe) | ((y & 0x7f000000) << 1);
-    z = y; z ^= z >> 4; z ^= z >> 2; z ^= z >> 1;
-    y |= (z & 0x01010101) ^ 0x01010101;
-  }
-  *xx = x; *yy = y;
-}
-
-/* --- @des_init@ --- *
- *
- * Arguments:  @des_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a DES key buffer.  The key buffer may be either 7
- *             or 8 bytes long.  If it's 8 bytes, the key is assumed to be
- *             padded with parity bits in the low order bit of each octet.
- *             These are stripped out without checking prior to the actual
- *             key scheduling.
- */
-
-void des_init(des_ctx *k, const void *buf, size_t sz)
-{
-  uint32 x, y;
-  uint32 *kp = k->k;
-  uint32 ka[2];
-  int i;
-
-  /* --- @pc1@ --- *
-   *
-   * This cryptographically useless permutation is used to mangle the key
-   * before it's subjected to the key schedule proper.  I've not actually
-   * messed it about much except for inserting padding at the beginning of
-   * the two halves of the key.
-   */
-
-  static const char pc1[] = {
-     0,         0,  0,  0,
-    57, 49, 41, 33, 25, 17,  9,
-     1, 58, 50, 42, 34, 26, 18,
-    10,         2, 59, 51, 43, 35, 27,
-    19, 11,  3, 60, 52, 44, 36,
-     0,         0,  0,  0,
-    63, 55, 47, 39, 31, 23, 15,
-     7, 62, 54, 46, 38, 30, 22,
-    14,         6, 61, 53, 45, 37, 29,
-    21, 13,  5, 28, 20, 12,  4
-  };
-
-  /* --- @pc2@ --- *
-   *
-   * This irritating but necessary permutation mangles the key between the
-   * simple rotation-based schedule and the actual XOR with which it modifies
-   * the behaviour of the cipher.
-   *
-   * This version of the table doesn't look much like the original.  This is
-   * because some parts of the world have been permuted in order to make
-   * things simpler for the round function.  In particular, everything is
-   * rotated left one place to avoid problems with the wraparound of the
-   * expansion permutation, and the key is split between odd and even S-boxes
-   * rather than high and low ones.  That's without the complication of the
-   * padding bits in the representation of the 56-bit proto-key.
-   */
-
-  static const char pc2[] = {
-     0,         0,  3 + 4, 28 + 4, 15 + 4,  6 + 4, 21 + 4, 10 + 4, /* S-box 2 */
-     0,         0, 16 + 4,  7 + 4, 27 + 4, 20 + 4, 13 + 4,  2 + 4, /* S-box 4 */
-     0,         0, 30 + 8, 40 + 8, 51 + 8, 45 + 8, 33 + 8, 48 + 8, /* S-box 6 */
-     0,         0, 46 + 8, 42 + 8, 50 + 8, 36 + 8, 29 + 8, 32 + 8, /* S-box 8 */
-     0,         0, 14 + 4, 17 + 4, 11 + 4, 24 + 4,  1 + 4,  5 + 4, /* S-box 1 */
-     0,         0, 23 + 4, 19 + 4, 12 + 4,  4 + 4, 26 + 4,  8 + 4, /* S-box 3 */
-     0,         0, 41 + 8, 52 + 8, 31 + 8, 37 + 8, 47 + 8, 55 + 8, /* S-box 5 */
-     0,         0, 44 + 8, 49 + 8, 39 + 8, 56 + 8, 34 + 8, 53 + 8  /* S-box 7 */
-  };
-
-  /* --- @v@ --- *
-   *
-   * Contains the rotation amounts for the key halves.
-   */
-
-  static const char v[] = {
-    1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
-  };
-
-  /* --- Extract the key into my registers --- *
-   *
-   * The 7 byte case is rather horrible.  It expands the key to the 8 byte
-   * case before going any further.  It could probably do with its own @pc1@
-   * table.
-   */
-
-  KSZ_ASSERT(des, sz);
-  des_expand(buf, sz, &x, &y);
-
-  /* --- Permute using the pointless PC1 --- */
-
-  permute(pc1, x, y, ka);
-  x = ka[0]; y = ka[1];
-
-  /* --- Now for the key schedule proper --- */
-
-  for (i = 0; i < 16; i++) {
-    if (v[i] == 1) {
-      x = ((x << 1) | (x >> 27)) & 0x0fffffff;
-      y = ((y << 1) | (y >> 27)) & 0x0fffffff;
-    } else {
-      x = ((x << 2) | (x >> 26)) & 0x0fffffff;
-      y = ((y << 2) | (y >> 26)) & 0x0fffffff;
-    }
-    permute(pc2, x, y, kp);
-    kp += 2;
-  }
-}
-
-/* --- @des_eblk@, @des_dblk@ --- *
- *
- * Arguments:  @const des_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-void des_eblk(const des_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 x = s[0], y = s[1];
-  DES_IP(x, y);
-  DES_EBLK(k->k, x, y, x, y);
-  DES_IPINV(x, y);
-  d[0] = x, d[1] = y;
-}
-
-void des_dblk(const des_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 x = s[0], y = s[1];
-  DES_IP(x, y);
-  DES_DBLK(k->k, x, y, x, y);
-  DES_IPINV(x, y);
-  d[0] = x, d[1] = y;
-}
-
-BLKC_TEST(DES, des)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/des.h b/des.h
deleted file mode 100644 (file)
index f3fe91c..0000000
--- a/des.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * The Data Encryption Standard
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on the Data Encryption Standard -----------------------------*
- *
- * Almost twenty years after it was first accepted, DES is still the standard
- * block cipher.  It's showing its age in its small key size and poor
- * optimiziation for software implementations, but it's not really been badly
- * dented by the intensive analysis thrown at it.
- *
- * This interface is here for compatibility with existing protocols, and
- * because it's a trivial veneer over the base DES code which is used by the
- * @des3@ interface which implements proper strong triple-DES.
- */
-
-#ifndef CATACOMB_DES_H
-#define CATACOMB_DES_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define DES_BLKSZ 8
-#define DES_KEYSZ 7
-#define DES_CLASS (N, B, 64)
-
-extern const octet des_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct des_ctx {
-  uint32 k[32];
-} des_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @des_expand@ --- *
- *
- * Arguments:  @const octet *k@ = pointer to key material
- *             @size_t n@ = number of octets of key material (7 or 8)
- *             @uint32 *xx, *yy@ = where to put the results
- *
- * Returns:    ---
- *
- * Use:                Extracts 64 bits of key material from the given buffer,
- *             possibly expanding it from 56 to 64 bits on the way.
- *             Parity is set correctly if the key is expanded.
- */
-
-extern void des_expand(const octet */*k*/, size_t /*n*/,
-                      uint32 */*xx*/, uint32 */*yy*/);
-
-/* --- @des_init@ --- *
- *
- * Arguments:  @des_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a DES key buffer.  The key buffer may be either 7
- *             or 8 bytes long.  If it's 8 bytes, the key is assumed to be
- *             padded with parity bits in the low order bit of each octet.
- *             These are stripped out without checking prior to the actual
- *             key scheduling.
- */
-
-extern void des_init(des_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @des_eblk@, @des_dblk@ --- *
- *
- * Arguments:  @const des_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void des_eblk(const des_ctx */*k*/,
-                    const uint32 */*s*/, uint32 */*d*/);
-extern void des_dblk(const des_ctx */*k*/,
-                    const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/des3.c b/des3.c
deleted file mode 100644 (file)
index 66f8243..0000000
--- a/des3.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/* -*-c-*-
- *
- * $Id: des3.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of double- and triple-DES
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "des-base.h"
-#include "des.h"
-#include "des3.h"
-#include "gcipher.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet des3_keysz[] = { KSZ_SET, 21, 7, 8, 14, 16, 24, 0 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @des3_init@ --- *
- *
- * Arguments:  @des3_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a DES key buffer.  The key buffer may have length
- *             7, 8, 14, 16, 21, or 24.  These correspond to one, two or
- *             three DES keys, either packed or unpacked (i.e., still
- *             containing parity bits).
- */
-
-void des3_init(des3_ctx *k, const void *buf, size_t sz)
-{
-  size_t step;
-  const octet *p = buf;
-
-  KSZ_ASSERT(des3, sz);
-
-  if (sz % 7 == 0)
-    step = 7;
-  else
-    step = 8;
-
-  des_init(&k->a, p, step);
-  if (sz > 8) p += step;
-  des_init(&k->b, p, step);
-  if (sz > 16) p += step; else p = buf;
-  des_init(&k->c, p, step);
-}
-
-/* --- @des3_eblk@, @des3_dblk@ --- *
- *
- * Arguments:  @const des3_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-void des3_eblk(const des3_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 x = s[0], y = s[1];
-  DES_IP(x, y);
-  DES_EBLK(k->a.k, x, y, x, y);
-  DES_DBLK(k->b.k, x, y, x, y);
-  DES_EBLK(k->c.k, x, y, x, y);
-  DES_IPINV(x, y);
-  d[0] = x, d[1] = y;
-}
-
-void des3_dblk(const des3_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 x = s[0], y = s[1];
-  DES_IP(x, y);
-  DES_DBLK(k->c.k, x, y, x, y);
-  DES_EBLK(k->b.k, x, y, x, y);
-  DES_DBLK(k->a.k, x, y, x, y);
-  DES_IPINV(x, y);
-  d[0] = x, d[1] = y;
-}
-
-BLKC_TEST(DES3, des3)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/des3.h b/des3.h
deleted file mode 100644 (file)
index f4f3311..0000000
--- a/des3.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -*-c-*-
- *
- * $Id: des3.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of double- and triple-DES
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_DES3_H
-#define CATACOMB_DES3_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Notes on double- and triple-DES -----------------------------------*
- *
- * The normal recommendation for using DES now is `triple DES'.
- * Conventionally, this involves an encrypt-decrypt-encrypt sequence,
- * although whether the first and last operations use the same key is
- * unfortunately not agreed upon.  This interface handles both cases (and the
- * single-key one too, although the simple @des@ calls are quicker for that).
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_DES_H
-#  include "des.h"
-#endif
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define DES3_BLKSZ 8
-#define DES3_KEYSZ 21
-#define DES3_CLASS (N, B, 64)
-
-extern const octet des3_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct des3_ctx {
-  des_ctx a, b, c;
-} des3_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @des3_init@ --- *
- *
- * Arguments:  @des3_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a DES key buffer.  The key buffer may have length
- *             7, 8, 14, 16, 21, or 24.  These correspond to one, two or
- *             three DES keys, either packed or unpacked (i.e., still
- *             containing parity bits).
- */
-
-extern void des3_init(des3_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @des3_eblk@, @des_dblk@ --- *
- *
- * Arguments:  @const des3_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void des3_eblk(const des3_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-extern void des3_dblk(const des3_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/desx-tab.h b/desx-tab.h
deleted file mode 100644 (file)
index 7c892e5..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*-c-*-
- *
- * $Id: desx-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Tables for DESX
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_DESX_TAB_H
-#define CATACOMB_DESX_TAB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- S-box table -------------------------------------------------------*/
-
-#define DESX_S {                                                       \
-  0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a,                      \
-  0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0,                      \
-  0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b,                      \
-  0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a,                      \
-  0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda,                      \
-  0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36,                      \
-  0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8,                      \
-  0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c,                      \
-  0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17,                      \
-  0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60,                      \
-  0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72,                      \
-  0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa,                      \
-  0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd,                      \
-  0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e,                      \
-  0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b,                      \
-  0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf,                      \
-  0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77,                      \
-  0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6,                      \
-  0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3,                      \
-  0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3,                      \
-  0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e,                      \
-  0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c,                      \
-  0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d,                      \
-  0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2,                      \
-  0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46,                      \
-  0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5,                      \
-  0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97,                      \
-  0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5,                      \
-  0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef,                      \
-  0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,                      \
-  0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf,                      \
-  0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab,                      \
-}
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/desx.c b/desx.c
deleted file mode 100644 (file)
index d779482..0000000
--- a/desx.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Implementation of DESX
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "des-base.h"
-#include "des.h"
-#include "desx.h"
-#include "desx-tab.h"
-#include "gcipher.h"
-
-/*----- Tables ------------------------------------------------------------*/
-
-static const octet s[256] = DESX_S;
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet desx_keysz[] = { KSZ_SET, 23, 7, 8, 15, 16, 24, 0 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @desx_init@ --- *
- *
- * Arguments:  @desx_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a DESX key buffer.  The key buffer contains, in
- *             order, a single-DES key (either 7 or 8 bytes), an optional
- *             8-byte pre-whitening key, and an optional 8-byte
- *             port-whitening key.  If no whitening keys are specified, the
- *             algorithm becomes the same as single-DES.
- */
-
-static void mangle(octet *b, const octet *p)
-{
-  unsigned i;
-
-  for (i = 0; i < 8; i++)
-    b[i] = *p++ ^ s[b[i] ^ b[(i + 1) & 7u]];
-}
-
-void desx_init(desx_ctx *k, const void *buf, size_t sz)
-{
-  const octet *p = buf, *kk = buf;
-  size_t n;
-
-  KSZ_ASSERT(desx, sz);
-
-  n = sz % 8 == 7 ? 7 : 8;
-  des_init(&k->k, p, n);
-  p += n;
-  sz -= n;
-  if (!sz)
-    k->prea = k->preb = k->posta = k->postb = 0;
-  else {
-    const octet *q = p;
-    k->prea = LOAD32(q + 0);
-    k->preb = LOAD32(q + 4);
-    p += 8;
-    sz -= 8;
-    if (sz) {
-      k->posta = LOAD32(p + 0);
-      k->postb = LOAD32(p + 4);
-    } else {
-      octet b[16];
-      uint32 x, y;
-
-      des_expand(kk, n, &x, &y);
-      STORE32(b + 8, x); STORE32(b + 12, y);
-      memset(b, 0, 8);
-      mangle(b, b + 8);
-      mangle(b, q);
-      k->posta = LOAD32(b + 0);
-      k->postb = LOAD32(b + 4);
-    }
-  }
-}
-
-/* --- @desx_eblk@, @desx_dblk@ --- *
- *
- * Arguments:  @const desx_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-void desx_eblk(const desx_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 x = s[0], y = s[1];
-  x ^= k->prea; y ^= k->preb;
-  DES_IP(x, y);
-  DES_EBLK(k->k.k, x, y, x, y);
-  DES_IPINV(x, y);
-  x ^= k->posta; y ^= k->postb;
-  d[0] = x, d[1] = y;
-}
-
-void desx_dblk(const desx_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 x = s[0], y = s[1];
-  x ^= k->posta; y ^= k->postb;
-  DES_IP(x, y);
-  DES_DBLK(k->k.k, x, y, x, y);
-  DES_IPINV(x, y);
-  x ^= k->prea; y ^= k->preb;
-  d[0] = x, d[1] = y;
-}
-
-BLKC_TEST(DESX, desx)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/desx.h b/desx.h
deleted file mode 100644 (file)
index bee363e..0000000
--- a/desx.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*-c-*-
- *
- * $Id: desx.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The DESX algorithm
- *
- * (c) 2001 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.
- */
-
-/*----- Notes on DESX -----------------------------------------------------*
- *
- * DESX was designed by Ron Rivest in 1986 as a simple and cheap way to
- * strengthen DES against exhaustive search.  It also increases the
- * difficulty of differential and linear attacks.
- */
-
-#ifndef CATACOMB_DESX_H
-#define CATACOMB_DESX_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_DES_H
-#  include "des.h"
-#endif
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define DESX_BLKSZ 8
-#define DESX_KEYSZ 23
-#define DESX_CLASS (N, B, 64)
-
-extern const octet desx_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct desx_ctx {
-  des_ctx k;
-  uint32 prea, preb;
-  uint32 posta, postb;
-} desx_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @desx_init@ --- *
- *
- * Arguments:  @desx_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a DESX key buffer.  The key buffer contains, in
- *             order, an optional 8-byte pre-whitening key, a single-DES key
- *             (either 7 or 8 bytes), and an optional 8-byte port-whitening
- *             key.  If no whitening keys are specified, the algorithm
- *             becomes the same as single-DES.
- */
-
-extern void desx_init(desx_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @desx_eblk@, @desx_dblk@ --- *
- *
- * Arguments:  @const desx_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void desx_eblk(const desx_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-extern void desx_dblk(const desx_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/dh-check.c b/dh-check.c
deleted file mode 100644 (file)
index ef07e66..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dh-check.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Checks Diffie-Hellman group parameters
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#include "dh.h"
-#include "keycheck.h"
-#include "mp.h"
-#include "mpmont.h"
-#include "mpmul.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @dh_checkparam@ --- *
- *
- * Arguments:  @keycheck *kc@ = keycheck state
- *             @const dh_param *dp@ = pointer to the parameter set
- *             @mp **v@ = optional vector of factors
- *             @size_t n@ = size of vector
- *
- * Returns:    Zero if all OK, or return status from function.
- *
- * Use:                Checks a set of Diffie-Hellman parameters for consistency and
- *             security.
- */
-
-int dh_checkparam(keycheck *kc, const dh_param *dp, mp **v, size_t n)
-{
-  int rc = 0;
-  mpmont mm;
-  mp *pm1 = MP_NEW;
-  mp *q = MP_NEW;
-  mp *x;
-  mpmul mu;
-  size_t i;
-
-  /* --- Check that the numbers which are supposed to be prime are --- */
-
-  if ((!v && keycheck_prime(kc, KCSEV_WARN, dp->q, "q")) ||
-      keycheck_prime(kc, KCSEV_ERR, dp->p, "p"))
-    goto fail;
-
-  /* --- Ensure that %$q$% is a sensible choice of number --- */
-
-  pm1 = mp_sub(pm1, dp->p, MP_ONE);
-  mp_div(0, &q, pm1, dp->q);
-  if (!mp_eq(q, MP_ZERO) &&
-      keycheck_report(kc, KCSEV_ERR, "q not a factor of p - 1"))
-    goto fail;
-
-  /* --- Check that %$g$% is actually right --- *
-   *
-   * This isn't perfect.  If %$q$% is composite and we don't have the factors
-   * of %$p - 1$% then the order of %$g$% may be some factor of %$q$% which
-   * we can't find.  (If we do have the factors, we check them all lower
-   * down.)  We do strip out powers of two from %$q$% before testing, though.
-   */
-
-  if ((mp_eq(dp->g, MP_ONE) || mp_eq(dp->g, pm1)) &&
-      keycheck_report(kc, KCSEV_ERR, "g is degenerate (+/-1 mod p)"))
-    goto fail;
-  q = mp_odd(q, dp->q, &i);
-  mpmont_create(&mm, dp->p);
-  x = mpmont_mul(&mm, MP_NEW, dp->g, mm.r2);
-  q = mpmont_expr(&mm, q, x, q);
-  mp_drop(x);
-  do {
-    if (mp_eq(q, mm.r) != !i) {
-      if (keycheck_report(kc, KCSEV_ERR, "order of g != q")) {
-       mpmont_destroy(&mm);
-       goto fail;
-      }
-      break;
-    }
-    if (i) {
-      q = mp_sqr(q, q);
-      q = mpmont_reduce(&mm, q, q);
-    }
-  } while (i--);
-
-  /* --- Check Lim-Lee primes more carefully --- *
-   *
-   * In this case, we really can be sure whether the order of %$g$% is
-   * actually %$q$% as advertised.  Also ensure that the individual primes
-   * are really prime, and that their product is correct.
-   */
-
-  if (!v)
-    mpmont_destroy(&mm);
-  else {
-    dstr d = DSTR_INIT;
-    mp *r = MP_NEW;
-
-    mpmul_init(&mu);
-    for (i = 0; i < n; i++) {
-      DRESET(&d);
-      dstr_putf(&d, "factor f_%lu of p", (unsigned long)i);
-      if ((rc = keycheck_prime(kc, KCSEV_ERR, v[i], d.buf)) != 0)
-       break;
-      mp_div(&q, &r, dp->q, v[i]);
-      if (mp_eq(r, MP_ZERO) && !mp_eq(q, MP_ONE)) {
-       q = mpmont_exp(&mm, q, dp->g, q);
-       if (mp_eq(q, MP_ONE) &&
-           (rc = keycheck_report(kc, KCSEV_ERR,
-                                 "order of g is proper divisor of q")) != 0)
-         break;
-      }
-      mpmul_add(&mu, v[i]);
-    }
-    mp_drop(q);
-    mp_drop(r);
-    q = mpmul_done(&mu);
-    mpmont_destroy(&mm);
-    dstr_destroy(&d);
-    if (rc)
-      goto fail;
-    q = mp_lsl(q, q, 1);
-    if (!mp_eq(q, pm1) &&
-       keycheck_report(kc, KCSEV_ERR, "product of f_i != (p - 1)/2"))
-      goto fail;
-  }
-
-  /* --- Finally, check the key sizes --- */
-
-  if ((mp_bits(dp->p) < 1024 &&
-       keycheck_report(kc, KCSEV_WARN,
-                      "p too small to resist index calculus attacks")) ||
-      (mp_bits(dp->q) < 160 &&
-       keycheck_report(kc, KCSEV_WARN,
-                      "q too small to resist collision-finding attacks")))
-    goto fail;
-
-  /* --- Done --- */
-
-tidy:
-  mp_drop(q);
-  mp_drop(pm1);
-  return (rc);
-fail:
-  rc = -1;
-  goto tidy;
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dh-fetch.c b/dh-fetch.c
deleted file mode 100644 (file)
index 57439d2..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dh-fetch.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Key fetching for Diffie-Hellman public and private keys
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "dh.h"
-#include "key.h"
-
-/*----- Key fetching ------------------------------------------------------*/
-
-const key_fetchdef dh_paramfetch[] = {
-  { "p",       offsetof(dh_param, p),          KENC_MP,        0 },
-  { "q",       offsetof(dh_param, q),          KENC_MP,        0 },
-  { "g",       offsetof(dh_param, g),          KENC_MP,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-const key_fetchdef dh_pubfetch[] = {
-  { "p",       offsetof(dh_pub, dp.p),         KENC_MP,        0 },
-  { "q",       offsetof(dh_pub, dp.q),         KENC_MP,        0 },
-  { "g",       offsetof(dh_pub, dp.g),         KENC_MP,        0 },
-  { "y",       offsetof(dh_pub, y),            KENC_MP,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-static const key_fetchdef priv[] = {
-  { "x",       offsetof(dh_priv, x),           KENC_MP,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-const key_fetchdef dh_privfetch[] = {
-  { "p",       offsetof(dh_priv, dp.p),        KENC_MP,        0 },
-  { "q",       offsetof(dh_priv, dp.q),        KENC_MP,        0 },
-  { "g",       offsetof(dh_priv, dp.g),        KENC_MP,        0 },
-  { "y",       offsetof(dh_priv, y),           KENC_MP,        0 },
-  { "private", 0,                              KENC_STRUCT,    priv },
-  { 0,         0,                              0,              0 }
-};
-
-/* --- @dh_paramfree@, @dh_pubfree@, @dh_privfree@ --- *
- *
- * Arguments:  @dh_param *dp@, @dh_pub *dp@, @dh_priv *dp@ = pointer
- *                     to key block to free
- *
- * Returns:    ---
- *
- * Use:                Frees a Diffie-Hellman key block.
- */
-
-void dh_paramfree(dh_param *dp)
-{
-  mp_drop(dp->p);
-  mp_drop(dp->q);
-  mp_drop(dp->g);
-}
-
-void dh_pubfree(dh_pub *dp)
-{
-  mp_drop(dp->dp.p);
-  mp_drop(dp->dp.q);
-  mp_drop(dp->dp.g);
-  mp_drop(dp->y);
-}
-
-void dh_privfree(dh_priv *dp)
-{
-  mp_drop(dp->dp.p);
-  mp_drop(dp->dp.q);
-  mp_drop(dp->dp.g);
-  mp_drop(dp->y);
-  mp_drop(dp->x);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dh-gen.c b/dh-gen.c
deleted file mode 100644 (file)
index a1b61a1..0000000
--- a/dh-gen.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dh-gen.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate Diffie-Hellman parameters
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/macros.h>
-
-#include "dh.h"
-#include "grand.h"
-#include "mp.h"
-#include "mpmont.h"
-#include "mprand.h"
-#include "pfilt.h"
-#include "pgen.h"
-#include "prim.h"
-#include "rabin.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @dh_gen@ --- *
- *
- * Arguments:  @dh_param *dp@ = pointer to output parameter block
- *             @unsigned ql@ = length of %$q$% in bits, or zero
- *             @unsigned pl@ = length of %$p$% in bits
- *             @unsigned steps@ = number of steps to go
- *             @grand *r@ = random number source
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for the event handler
- *
- * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't.
- *
- * Use:                Generates Diffie-Hellman parameters.
- *
- *             The parameters are a prime %$q$%, relatively small, and a
- *             large prime %$p = kq + 1$% for some %$k$%, together with a
- *             generator %$g$% of the cyclic subgroup of order %$q$%.  These
- *             are actually the same as the DSA parameter set, but the
- *             generation algorithm is different.  Also, if @ql@ is zero,
- *             this algorithm forces %$k = 2$%, and chooses %$g = 4$%.  Make
- *             sure you have something interesting to do if you choose this
- *             option.
- */
-
-int dh_gen(dh_param *dp, unsigned ql, unsigned pl, unsigned steps, grand *r,
-          pgen_proc *event, void *ectx)
-{
-  /* --- If @ql@ is zero, do the time consuming safe-prime thing --- */
-
-  if (!ql) {
-    pgen_simulprime sp[2];
-    pgen_simulctx ss;
-
-    mp *m = mprand(MP_NEW, pl - 1, r, 1);
-    ss.step = MP_TWO;
-    sp[0].mul = MP_ONE; sp[0].add = MP_ZERO; sp[0].f = 0;
-    sp[1].mul = MP_TWO; sp[1].add = MP_ONE; sp[1].f = PGENF_KEEP;
-    ss.v = sp; ss.n = N(sp);
-    dp->q = pgen("p", MP_NEW, m, event, ectx, steps, pgen_simulstep, &ss,
-                rabin_iters(pl), pgen_simultest, &ss);
-    mp_drop(m);
-    if (!dp->q) {
-      mp_drop(sp[1].u.x);
-      return (PGEN_ABORT);
-    }
-    dp->p = sp[1].u.x;
-    dp->g = MP_FOUR;
-    return (PGEN_DONE);
-  }
-
-  /* --- Otherwise the job is much simpler --- *
-   *
-   * But doesn't look it...
-   */
-
-  else {
-    pgen_filterctx c;
-    pgen_jumpctx j;
-    rabin rb;
-    prim_ctx p;
-    int i;
-    mp *m = MP_NEW;
-    mp *x, *y;
-
-    /* --- Generate @q@ first --- */
-
-    c.step = 2;
-    m = mprand(MP_NEW, ql, r, 1);
-    dp->q = pgen("q", MP_NEW, m, event, ectx, steps, pgen_filter, &c,
-                rabin_iters(ql), pgen_test, &rb);
-    if (!dp->q)
-      goto fail_q;
-
-    /* --- Now pick a suitable @p@ --- */
-
-    m = mp_lsl(m, dp->q, 1);
-    x = mprand(MP_NEW, pl, r, 0);
-    y = MP_NEW; mp_div(0, &y, x, m);
-    x = mp_sub(x, x, y);
-    x = mp_add(x, x, MP_ONE);
-    mp_drop(y);
-    pfilt_create(&c.f, m);
-    j.j = &c.f;
-    dp->p = pgen("p", MP_NEW, x, event, ectx, steps, pgen_jump, &j,
-                rabin_iters(pl), pgen_test, &rb);
-    pfilt_destroy(&c.f);
-    mp_drop(x);
-    if (!dp->p)
-      goto fail_p;
-
-    /* --- And finally a suitable @g@ --- */
-
-    mpmont_create(&p.mm, dp->p);
-    mp_div(&m, 0, dp->p, dp->q);
-    i = 0;
-    p.exp = m;
-    p.n = 0;
-    dp->g = pgen("g", MP_NEW, MP_NEW, event, ectx, 0, prim_step, &i,
-                1, prim_test, &p);
-    mpmont_destroy(&p.mm);
-    if (!dp->g)
-      goto fail_g;
-    mp_drop(m);
-    return (PGEN_DONE);
-
-    /* --- Tidy up --- */
-
-  fail_g:
-    mp_drop(dp->q);
-  fail_q:
-    mp_drop(dp->p);
-  fail_p:
-    mp_drop(m);
-    return (PGEN_ABORT);
-  }
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dh-kcdsa.c b/dh-kcdsa.c
deleted file mode 100644 (file)
index b503a5b..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generate KCDSA prime groups
- *
- * (c) 2006 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/macros.h>
-
-#include "dh.h"
-#include "mprand.h"
-#include "pgen.h"
-#include "prim.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @dh_kcdsagen@ --- *
- *
- * Arguments:  @dh_param *dp@ = pointer to output parameter block
- *             @unsigned ql@ = size of small factor of %$(p - 1)/2$%
- *             @unsigned pl@ = size of %$p$% in bits
- *             @unsigned flags@ = other generation flags
- *             @unsigned steps@ = number of steps to go
- *             @grand *r@ = random number source
- *             @pgen_proc *ev@ = event handler function
- *             @void *ec@ = context for the event handler
- *
- * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed.
- *
- * Use:                Generates a KCDSA prime group.  That is, it chooses a prime
- *             %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and
- *             %$v$%.  The actual group of interest is the subgroup of order
- *             %$q$%.
- */
-
-int dh_kcdsagen(dh_param *dp, unsigned ql, unsigned pl,
-               unsigned flags, unsigned steps, grand *r,
-               pgen_proc *ev, void *ec)
-{
-  pgen_filterctx pf;
-  pgen_simulprime sp[2];
-  pgen_simulctx ss;
-  prim_ctx pc;
-  rabin rb;
-  int rc = PGEN_ABORT;
-  int i;
-  mp *x;
-
-  /* --- First trick: find %$q$% --- */
-
-  pf.step = 2;
-  x = mprand(MP_NEW, pl - ql, r, 1);
-  x = pgen("v", x, x, ev, ec,
-          steps, pgen_filter, &pf,
-          rabin_iters(pl - ql), pgen_test, &rb);
-  if (!x)
-    goto fail_0;
-
-  /* --- Second trick: find %$p$% and %$v$% --- */
-
-  x = mp_lsl(x, x, 1);
-  sp[0].add = MP_ZERO; sp[0].mul = MP_ONE; sp[0].f = 0;
-  sp[1].add = MP_ONE; sp[1].mul = x; sp[1].f = PGENF_KEEP;
-  ss.step = MP_TWO; ss.v = sp; ss.n = N(sp);
-  x = mprand(MP_NEW, ql, r, 1);
-  dp->q = pgen("p", MP_NEW, x, ev, ec,
-              steps, pgen_simulstep, &ss,
-              rabin_iters(ql), pgen_simultest, &ss);
-  mp_drop(sp[0].mul);
-  if (!dp->q)
-    goto fail_1;
-  dp->p = sp[1].u.x;
-
-  /* --- Third trick: find a generator --- */
-
-  mpmont_create(&pc.mm, dp->p);
-  mp_div(&x, 0, dp->p, dp->q);
-  i = 0;
-  pc.exp = x;
-  pc.n = 0;
-  dp->g = pgen("g", MP_NEW, MP_NEW, ev, ec,
-              0, prim_step, &i, 1, prim_test, &pc);
-  mpmont_destroy(&pc.mm);
-  if (!dp->g)
-    goto fail_2;
-
-  rc = PGEN_DONE;
-  goto done;
-
-  /* --- Tidying up and going home --- */
-
-fail_2:
-  mp_drop(dp->p);
-fail_1:
-fail_0:
-done:
-  mp_drop(x);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dh-limlee.c b/dh-limlee.c
deleted file mode 100644 (file)
index 26666a3..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dh-limlee.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate Diffie-Hellman parameters from Lim-Lee primes
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "dh.h"
-#include "limlee.h"
-#include "mpmont.h"
-#include "prim.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @dh_limlee@ --- *
- *
- * Arguments:  @dh_param *dp@ = pointer to output parameter block
- *             @unsigned ql@ = length of smallest factor of %$(p - 1)/2$%
- *             @unsigned pl@ = length of %$p$% in bits
- *             @unsigned flags@ = other generation flags
- *             @unsigned steps@ = number of steps to go
- *             @grand *r@ = random number source
- *             @pgen_proc *oev@ = outer event handler function
- *             @void *oec@ = argument for the outer event handler
- *             @pgen_proc *iev@ = inner event handler function
- *             @void *iec@ = argument for the inner event handler
- *             @size_t *nf@, @mp ***f@ = output array for factors
- *
- * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't.
- *
- * Use:                Generates Diffie-Hellman parameters based on a Lim-Lee prime.
- *
- *             The modulus is a large prime %$p = 2 \prod q_i + 1$%, @pl@
- *             bits long, where the %$q_i$% are smaller primes each at least
- *             @ql@ bits long.  It is safe to set @nf@ and @f@ to zero if
- *             you're not interested in the factor values.
- *
- *             The returned %$g$% generates a subgroup of order %$q_0$% (the
- *             first factor, returned as @f[0]@), if the flag @DH_SUBGROUP@
- *             is set on entry; otherwise %$g$% will have order
- *             %$(p - 1)/2$%.
- */
-
-int dh_limlee(dh_param *dp, unsigned ql, unsigned pl,
-             unsigned flags, unsigned steps, grand *r,
-             pgen_proc *oev, void *oec, pgen_proc *iev,
-             void *iec, size_t *nf, mp ***f)
-{
-  mp **ff;
-  size_t nff;
-  prim_ctx pc;
-  size_t i;
-  int j;
-  mp *pp;
-
-  /* --- Generate the Lim-Lee prime --- */
-
-  if ((dp->p = limlee("p", MP_NEW, MP_NEW, ql, pl,
-                     r, steps, oev, oec, iev, iec, &nff, &ff)) == 0)
-    return (PGEN_ABORT);
-
-  /* --- Now find a primitive element --- */
-
-  mpmont_create(&pc.mm, dp->p);
-  pp = mp_sub(MP_NEW, dp->p, MP_ONE);
-  if (flags & DH_SUBGROUP) {
-    dp->q = mp_copy(ff[0]);
-    pc.exp = MP_NEW;
-    mp_div(&pc.exp, 0, pp, dp->q);
-    pc.n = 0;
-    pc.f = 0;
-  } else {
-    dp->q = mp_lsr(MP_NEW, dp->p, 1);
-    pc.exp = MP_TWO;
-    pc.n = nff;
-    pc.f = xmalloc(nff * sizeof(mp *));
-    for (i = 0; i < nff; i++) {
-      pc.f[i] = MP_NEW;
-      mp_div(&pc.f[i], 0, pp, ff[i]);
-    }
-  }
-
-  j = 0;
-  dp->g = pgen("g", MP_NEW, MP_NEW, oev, oec,
-              0, prim_step, &j, 1, prim_test, &pc);
-
-  mp_drop(pp);
-  if (pc.f) {
-    for (i = 0; i < pc.n; i++)
-      mp_drop(pc.f[i]);
-    xfree(pc.f);
-  }
-  mpmont_destroy(&pc.mm);
-
-  /* --- Do something sensible with the list of primes --- */
-
-  if (dp->g && f) {
-    *f = ff;
-    *nf = nff;
-  } else {
-    for (i = 0; i < nff; i++)
-      mp_drop(ff[i]);
-    xfree(ff);
-  }
-
-  /* --- Tidy up and return --- */
-
-  if (!dp->g) {
-    mp_drop(dp->p);
-    mp_drop(dp->q);
-    return (PGEN_ABORT);
-  }
-  return (PGEN_DONE);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dh-param.c b/dh-param.c
deleted file mode 100644 (file)
index e1e5374..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Reading Diffie-Hellman parameters
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "dh.h"
-#include "ptab.h"
-#include "bintab.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* ---- @dh_infofromdata@ --- *
- *
- * Arguments:  @dh_param *dp@ = parameters to fill in
- *             @pdata *pd@ = packed data structure
- *
- * Returns:    ---
- *
- * Use:                Fills in a parameters structure from a packed data block.
- */
-
-void dh_infofromdata(dh_param *dp, pdata *pd)
-  { dp->p = &pd->p; dp->q = &pd->q; dp->g = &pd->g; }
-
-/* --- @dh_parse@, @dhbin_parse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *             @dh_param *dp@ = parameters to fill in
- *
- * Returns:    Zero if OK, nonzero on error.
- *
- * Use:                Parses a prime group string.  This is either one of the
- *             standard group strings, or a %$p$%, %$q$%, %$g$% triple
- *             separated by commas.
- */
-
-static int parse(qd_parse *qd, gprime_param *dp)
-{
-  mp *p = MP_NEW, *q = MP_NEW, *g = MP_NEW;
-
-  if ((p = qd_getmp(qd)) == 0) goto fail;
-  qd_delim(qd, ','); if ((q = qd_getmp(qd)) == 0) goto fail;
-  qd_delim(qd, ','); if ((g = qd_getmp(qd)) == 0) goto fail;
-  dp->p = p; dp->q = q; dp->g = g;
-  return (0);
-fail:
-  mp_drop(p); mp_drop(q); mp_drop(g);
-  return (-1);
-}
-
-int dh_parse(qd_parse *qd, dh_param *dp)
-{
-  const pentry *pe;
-
-  for (pe = ptab; pe->name; pe++) {
-    if (qd_enum(qd, pe->name) >= 0) {
-      dh_infofromdata(dp, pe->data);
-      goto found;
-    }
-  }
-  if (parse(qd, dp))
-    return (-1);
-found:
-  return (0);
-}
-
-int dhbin_parse(qd_parse *qd, gbin_param *gb)
-{
-  const binentry *be;
-
-  for (be = bintab; be->name; be++) {
-    if (qd_enum(qd, be->name) >= 0) {
-      dh_infofromdata(gb, be->data);
-      goto found;
-    }
-  }
-  if (parse(qd, gb))
-    return (-1);
-found:
-  return (0);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include "fibrand.h"
-
-int main(int argc, char *argv[])
-{
-  const pentry *pe;
-  const binentry *be;
-  const char *e;
-  int ok = 1, aok = 1;
-  grand *gr;
-
-  gr = fibrand_create(0);
-  fputs("checking standard prime groups:", stdout);
-  fflush(stdout);
-  for (pe = ptab; pe->name; pe++) {
-    dh_param dp;
-    group *g;
-    dh_infofromdata(&dp, pe->data);
-    g = group_prime(&dp);
-    if (mp_bits(dp.p) > 2048 &&
-       (!argv[1] || strcmp(argv[1], "keen") != 0)) {
-      printf(" [%s skipped]", pe->name);
-      fflush(stdout);
-      continue;
-    }
-    e = G_CHECK(g, gr);
-    G_DESTROYGROUP(g);
-    dh_paramfree(&dp);
-    if (e) {
-      printf(" [%s failed: %s]", pe->name, e);
-      ok = aok = 0;
-    } else
-      printf(" %s", pe->name);
-    fflush(stdout);
-  }
-  fputs(ok ? " ok\n" : " failed\n", stdout);
-  ok = 1;
-  fputs("checking standard binary groups:", stdout);
-  for (be = bintab; be->name; be++) {
-    gbin_param gb;
-    group *g;
-    dh_infofromdata(&gb, be->data);
-    g = group_binary(&gb);
-    e = G_CHECK(g, gr);
-    G_DESTROYGROUP(g);
-    dh_paramfree(&gb);
-    if (e) {
-      printf(" [%s failed: %s]", be->name, e);
-      ok = aok = 0;
-    } else
-      printf(" %s", be->name);
-    fflush(stdout);
-  }
-  fputs(ok ? " ok\n" : " failed\n", stdout);
-  gr->ops->destroy(gr);
-  return (!aok);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dh.h b/dh.h
deleted file mode 100644 (file)
index 04b526e..0000000
--- a/dh.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Diffie-Hellman and related public-key systems
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_DH_H
-#define CATACOMB_DH_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GROUP_H
-#  include "group.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_KEY_H
-#  include "key.h"
-#endif
-
-#ifndef CATACOMB_KEYCHECK_H
-#  include "keycheck.h"
-#endif
-
-#ifndef CATACOMB_PGEN_H
-#  include "pgen.h"
-#endif
-
-#ifndef CATACOMB_QDPARSE_H
-#  include "qdparse.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef gprime_param dh_param;         /* Group parameters */
-
-typedef struct dh_pub {
-  dh_param dp;                         /* Shared parameters */
-  mp *y;                               /* Public key */
-} dh_pub;
-
-typedef struct dh_priv {
-  dh_param dp;                         /* Shared parameters */
-  mp *x;                               /* Private key */
-  mp *y;                               /* %$y \equiv g^x \pmod{p}$% */
-} dh_priv;
-
-/*----- Key fetching ------------------------------------------------------*/
-
-extern const key_fetchdef dh_paramfetch[];
-#define DH_PARAMFETCHSZ 5
-
-extern const key_fetchdef dh_pubfetch[];
-#define DH_PUBFETCHSZ 6
-
-extern const key_fetchdef dh_privfetch[];
-#define DH_PRIVFETCHSZ 9
-
-/* --- @dh_paramfree@, @dh_pubfree@, @dh_privfree@ --- *
- *
- * Arguments:  @dh_param *dp@, @dh_pub *dp@, @dh_priv *dp@ = pointer to
- *                     key block to free
- *
- * Returns:    ---
- *
- * Use:                Frees a Diffie-Hellman key block.
- */
-
-extern void dh_paramfree(dh_param */*dp*/);
-extern void dh_pubfree(dh_pub */*dp*/);
-extern void dh_privfree(dh_priv */*dp*/);
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @dh_gen@ --- *
- *
- * Arguments:  @dh_param *dp@ = pointer to output parameter block
- *             @unsigned ql@ = length of %$q$% in bits, or zero
- *             @unsigned pl@ = length of %$p$% in bits
- *             @unsigned steps@ = number of steps to go
- *             @grand *r@ = random number source
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for the event handler
- *
- * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't.
- *
- * Use:                Generates Diffie-Hellman parameters.
- *
- *             The parameters are a prime %$q$%, relatively small, and a
- *             large prime %$p = kq + 1$% for some %$k$%, together with a
- *             generator %$g$% of the cyclic subgroup of order %$q$%.  These
- *             are actually the same as the DSA parameter set, but the
- *             generation algorithm is different.  Also, if @ql@ is zero,
- *             this algorithm forces %$k = 2$%, and chooses %$g = 4$%.  Make
- *             sure you have something interesting to do if you choose this
- *             option.
- */
-
-extern int dh_gen(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/,
-                 unsigned /*steps*/, grand */*r*/, pgen_proc */*event*/,
-                 void */*ectx*/);
-
-/* --- @dh_limlee@ --- *
- *
- * Arguments:  @dh_param *dp@ = pointer to output parameter block
- *             @unsigned ql@ = length of smallest factor of %$(p - 1)/2$%
- *             @unsigned pl@ = length of %$p$% in bits
- *             @unsigned flags@ = other generation flags
- *             @unsigned steps@ = number of steps to go
- *             @grand *r@ = random number source
- *             @pgen_proc *oev@ = outer event handler function
- *             @void *oec@ = argument for the outer event handler
- *             @pgen_proc *iev@ = inner event handler function
- *             @void *iec@ = argument for the inner event handler
- *             @size_t *nf@, @mp ***f@ = output array for factors
- *
- * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't.
- *
- * Use:                Generates Diffie-Hellman parameters based on a Lim-Lee prime.
- *
- *             The modulus is a large prime %$p = 2 \prod q_i + 1$%, @pl@
- *             bits long, where the %$q_i$% are smaller primes each at least
- *             @ql@ bits long.  It is safe to set @nf@ and @f@ to zero if
- *             you're not interested in the factor values.
- *
- *             The returned %$g$% generates a subgroup of order %$q_0$% (the
- *             first factor, returned as @f[0]@), if the flag @DH_SUBGROUP@
- *             is set on entry; otherwise %$g$% will have order
- *             %$(p - 1)/2$%.
- */
-
-#define DH_SUBGROUP 1u
-
-extern int dh_limlee(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/,
-                    unsigned /*flags*/, unsigned /*steps*/, grand */*r*/,
-                    pgen_proc */*oev*/, void */*oec*/, pgen_proc */*iev*/,
-                    void */*iec*/, size_t */*nf*/, mp ***/*f*/);
-
-/* --- @dh_kcdsagen@ --- *
- *
- * Arguments:  @dh_param *dp@ = pointer to output parameter block
- *             @unsigned ql@ = size of small factor of %$(p - 1)/2$%
- *             @unsigned pl@ = size of %$p$% in bits
- *             @unsigned flags@ = other generation flags (none defined)
- *             @unsigned steps@ = number of steps to go
- *             @grand *r@ = random number source
- *             @pgen_proc *ev@ = event handler function
- *             @void *ec@ = context for the event handler
- *
- * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed.
- *
- * Use:                Generates a KCDSA prime group.  That is, it chooses a prime
- *             %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and
- *             %$v$%.  The actual group of interest is the subgroup of order
- *             %$q$%.
- */
-
-extern int dh_kcdsagen(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/,
-                      unsigned /*flags*/, unsigned /*steps*/, grand */*r*/,
-                      pgen_proc */*ev*/, void */*ec*/);
-
-/* --- @dh_checkparam@ --- *
- *
- * Arguments:  @keycheck *kc@ = keycheck state
- *             @const dh_param *dp@ = pointer to the parameter set
- *             @mp **v@ = optional vector of factors
- *             @size_t n@ = size of vector
- *
- * Returns:    Zero if all OK, or return status from function.
- *
- * Use:                Checks a set of Diffie-Hellman parameters for consistency and
- *             security.
- */
-
-extern int dh_checkparam(keycheck */*kc*/, const dh_param */*dp*/,
-                        mp **/*v*/, size_t /*n*/);
-
-/* ---- @dh_infofromdata@ --- *
- *
- * Arguments:  @dh_param *dp@ = parameters to fill in
- *             @pdata *pd@ = packed data structure
- *
- * Returns:    ---
- *
- * Use:                Fills in a parameters structure from a packed data block.
- */
-
-struct pdata;
-extern void dh_infofromdata(dh_param */*dp*/, struct pdata */*pd*/);
-
-/* --- @dh_parse@, @dhbin_parse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *             @dh_param *dp@ = parameters to fill in
- *
- * Returns:    Zero if OK, nonzero on error.
- *
- * Use:                Parses a prime/binary group string.  This is either one of
- *             the standard group strings, or a %$p$%, %$q$%, %$g$% triple
- *             separated by commas.
- */
-
-extern int dh_parse(qd_parse */*qd*/, dh_param */*dp*/);
-extern int dhbin_parse(qd_parse */*qd*/, gbin_param */*gb*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/dsa-check.c b/dsa-check.c
deleted file mode 100644 (file)
index a99cd0e..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dsa-check.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Consistency checking for DSA keys
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "dh.h"
-#include "dsa.h"
-#include "dsarand.h"
-#include "grand.h"
-#include "keycheck.h"
-#include "mp.h"
-#include "mprand.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @dsa_checkparam@ --- *
- *
- * Arguments:  @keycheck *kc@ = keycheck state
- *             @const dsa_param *dp@ = pointer to the parameter set
- *             @const dsa_seed *ds@ = pointer to seed information
- *
- * Returns:    Zero if all OK, or return status from function.
- *
- * Use:                Checks a set of DSA parameters for consistency and security.
- */
-
-int dsa_checkparam(keycheck *kc, const dsa_param *dp, const dsa_seed *ds)
-{
-  if (ds) {
-    grand *r = dsarand_create(ds->p, ds->sz);
-    mp *p = MP_NEW, *q = MP_NEW;
-    int rc = 0;
-    unsigned i;
-    unsigned long n;
-
-    r->ops->misc(r, DSARAND_PASSES, 2);
-    q = mprand(q, mp_bits(dp->q), r, 1);
-    if (!mp_eq(q, dp->q) &&
-       keycheck_report(kc, KCSEV_ERR, "q doesn't match seed provided"))
-      rc = -1;
-    else {
-      n = mp_bits(dp->p);
-      r->ops->misc(r, DSARAND_PASSES, 1);
-      for (i = 0; i <= ds->count; i++)
-       p = mprand(p, n, r, 0);
-      q = mp_lsl(q, q, 1);
-      mp_div(0, &q, p, q);
-      p = mp_sub(p, p, q);
-      p->v[0] |= 1;
-      if (!mp_eq(p, dp->p) &&
-         keycheck_report(kc, KCSEV_ERR, "p doesn't match seed provided"))
-       rc = -1;
-    }
-    mp_drop(p);
-    mp_drop(q);
-    r->ops->destroy(r);
-    if (rc)
-      return (rc);
-  }
-  return (dh_checkparam(kc, dp, 0, 0));
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dsa-gen.c b/dsa-gen.c
deleted file mode 100644 (file)
index adb8d9a..0000000
--- a/dsa-gen.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dsa-gen.c,v 1.10 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate DSA shared parameters
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "dsa.h"
-#include "dsarand.h"
-#include "fibrand.h"
-#include "mp.h"
-#include "mprand.h"
-#include "pgen.h"
-#include "prim.h"
-#include "sha.h"
-
-/*----- The DSA stepper ---------------------------------------------------*/
-
-/* --- @next@ --- *
- *
- * Arguments:  @pgen_event *ev@ = pointer to event block
- *             @dsa_stepctx *d@ = pointer to stepping context
- *
- * Returns:    A @PGEN@ result code.
- *
- * Use:                Steps the generator once, reads the result, and tests it.
- */
-
-static int next(pgen_event *ev, dsa_stepctx *d)
-{
-  mp *m;
-  int rc;
-
-  /* --- Load the new candidate --- */
-
-  if (d->seedbuf)
-    d->r->ops->misc(d->r, DSARAND_GETSEED, d->seedbuf);
-  m = mprand(ev->m, d->bits, d->r, 0);
-
-  /* --- Force to be a multiple of @q@ --- */
-
-  if (d->q) {
-    mp *r = MP_NEW;
-    mp_div(0, &r, m, d->q);
-    m = mp_sub(m, m, r);
-    mp_drop(r);
-  }
-  m->v[0] |= d->or;
-  ev->m = m;
-
-  /* --- Do the trial division --- */
-
-  rc = pfilt_smallfactor(m);
-  d->count++;
-
-  /* --- Return the result --- */
-
-  return (rc);
-}
-
-/* --- @dsa_step@ --- */
-
-int dsa_step(int rq, pgen_event *ev, void *p)
-{
-  dsa_stepctx *d = p;
-
-  switch (rq) {
-    case PGEN_BEGIN:
-    case PGEN_TRY:
-      return (next(ev, d));
-    case PGEN_DONE:
-      return (PGEN_DONE);
-  }
-  return (PGEN_ABORT);
-}
-
-/*----- Glue code ---------------------------------------------------------*/
-
-/* --- @dsa_gen@ --- *
- *
- * Arguments:  @dsa_param *dp@ = where to store parameters
- *             @unsigned ql@ = length of @q@ in bits
- *             @unsigned pl@ = length of @p@ in bits
- *             @unsigned steps@ = number of steps to find @q@
- *             @const void *k@ = pointer to key material
- *             @size_t sz@ = size of key material
- *             @dsa_seed *ds@ = optional pointer for output seed information
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for event handler
- *
- * Returns:    @PGEN_DONE@ if everything worked ok; @PGEN_ABORT@ otherwise.
- *
- * Use:                Generates the DSA shared parameters from a given seed value.
- *
- *             The parameters are a prime %$q$%, relatively small, and a
- *             large prime %$p = kq + 1$% for some %$k$%, together with a
- *             generator %$g$% of the cyclic subgroup of order %$q$%.  These
- *             are actually the same as the Diffie-Hellman parameter set,
- *             but the generation algorithm is different.
- *
- *             The algorithm used is a compatible extension of the method
- *             described in the DSA standard, FIPS 186.  The standard
- *             requires that %$q$% be 160 bits in size (i.e., @ql == 160@)
- *             and that the length of %$p$% be %$L = 512 + 64l$% for some
- *             %$l$%.  Neither limitation applies to this implementation.
- */
-
-int dsa_gen(dsa_param *dp, unsigned ql, unsigned pl, unsigned steps,
-           const void *k, size_t sz, dsa_seed *ds,
-           pgen_proc *event, void *ectx)
-{
-  dsa_stepctx s;
-  prim_ctx p;
-  int i;
-  rabin r;
-  mp *qc;
-
-  /* --- Initialize the stepping context --- */
-
-  s.r = dsarand_create(k, sz);
-
-  /* --- Find @q@ --- */
-
-  s.q = 0;
-  s.r->ops->misc(s.r, DSARAND_PASSES, 2);
-  s.bits = ql;
-  s.count = 0;
-  s.or = 1;
-  if (!ds)
-    s.seedbuf = 0;
-  else {
-    ds->sz = sz;
-    ds->p = s.seedbuf = xmalloc(sz);
-  }
-  if ((dp->q = pgen("q", MP_NEW, MP_NEW, event, ectx, steps, dsa_step, &s,
-                   rabin_iters(ql), pgen_test, &r)) == 0)
-    goto fail_q;
-
-  /* --- Find @p@ --- */
-
-  s.count = ~0;
-  s.q = mp_lsl(MP_NEW, dp->q, 1);
-  s.r->ops->misc(s.r, DSARAND_PASSES, 1);
-  s.bits = pl;
-  s.seedbuf = 0;
-  if ((dp->p = pgen("p", MP_NEW, MP_NEW, event, ectx, 4096, dsa_step, &s,
-                   rabin_iters(pl), pgen_test, &r)) == 0)
-    goto fail_p;
-  mp_drop(s.q);
-  if (ds)
-    ds->count = s.count;
-
-  /* --- Find @g@ --- *
-   *
-   * The division returns remainder 1.  This doesn't matter.
-   */
-
-  mpmont_create(&p.mm, dp->p);
-  qc = MP_NEW; mp_div(&qc, 0, dp->p, dp->q);
-  i = 0;
-  p.exp = qc;
-  p.n = 0;
-  if ((dp->g = pgen("g", MP_NEW, MP_NEW, event, ectx, 0, prim_step, &i,
-                   1, prim_test, &p)) == 0)
-    goto fail_g;
-
-  /* --- Done --- */
-
-  mp_drop(qc);
-  mpmont_destroy(&p.mm);
-  s.r->ops->destroy(s.r);
-  return (PGEN_DONE);
-
-  /* --- Tidy up when things go wrong --- */
-
-fail_g:
-  mp_drop(qc);
-  mpmont_destroy(&p.mm);
-fail_p:
-  mp_drop(dp->q);
-  mp_drop(s.q);
-fail_q:
-  s.r->ops->destroy(s.r);
-  if (ds)
-    xfree(ds->p);
-  return (PGEN_ABORT);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int verify(dstr *v)
-{
-  mp *q = *(mp **)v[4].buf;
-  mp *p = *(mp **)v[5].buf;
-  mp *g = *(mp **)v[6].buf;
-  dsa_param dp;
-  dsa_seed ds;
-  unsigned long l = *(unsigned long *)v[1].buf;
-  unsigned long n = *(unsigned long *)v[3].buf;
-  int ok = 1;
-  int rc;
-  keycheck kc;
-  keycheck_reportctx kcr;
-
-  rc = dsa_gen(&dp, 160, l, 16, v[0].buf, v[0].len, &ds, pgen_evspin, 0);
-  if (rc || ds.count != n || ds.sz != v[2].len ||
-      memcmp(ds.p, v[2].buf, v[2].len) != 0 ||
-      !MP_EQ(q, dp.q) || !MP_EQ(p, dp.p) || !MP_EQ(g, dp.g)) {
-    fputs("\n*** gen failed", stderr);
-    fputs("\nseed_in = ", stderr); type_hex.dump(&v[0], stderr);
-    fprintf(stderr, "\nl = %lu", l);
-    fputs("\nseed_out = ", stderr); type_hex.dump(&v[2], stderr);
-    fprintf(stderr, "\ncount = %lu", n);
-    fputs("\n  q = ", stderr); mp_writefile(q, stderr, 16);
-    fputs("\n  p = ", stderr); mp_writefile(p, stderr, 16);
-    fputs("\n  g = ", stderr); mp_writefile(g, stderr, 16);
-    if (!rc) {
-      dstr d;
-      d.buf = ds.p; d.len = ds.sz;
-      fputs("\nds.seed = ", stderr); type_hex.dump(&d, stderr);
-      fprintf(stderr, "\nds.count = %u", ds.count);
-      fputs("\ndp.q = ", stderr); mp_writefile(dp.q, stderr, 16);
-      fputs("\ndp.p = ", stderr); mp_writefile(dp.p, stderr, 16);
-      fputs("\ndp.g = ", stderr); mp_writefile(dp.g, stderr, 16);
-    }
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  kcr.fp = stderr;
-  kcr.sev = KCSEV_ERR;
-  keycheck_init(&kc, keycheck_stdreport, &kcr);
-  if (!rc)
-    dsa_checkparam(&kc, &dp, &ds);
-  if (!keycheck_allclear(&kc, KCSEV_ERR)) {
-    fputs("\n*** gen failed check", stderr);
-    fputs("\nseed_in = ", stderr); type_hex.dump(&v[0], stderr);
-    fprintf(stderr, "\nl = %lu", l);
-    fputs("\nseed_out = ", stderr); type_hex.dump(&v[2], stderr);
-    fprintf(stderr, "\ncount = %lu", n);
-    fputs("\n  q = ", stderr); mp_writefile(q, stderr, 16);
-    fputs("\n  p = ", stderr); mp_writefile(p, stderr, 16);
-    fputs("\n  g = ", stderr); mp_writefile(g, stderr, 16);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(q); mp_drop(p); mp_drop(g);
-  if (!rc) {
-    mp_drop(dp.q); mp_drop(dp.p); mp_drop(dp.g); xfree(ds.p);
-  }
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "gen", verify,
-    { &type_hex, &type_ulong, &type_hex, &type_ulong,
-      &type_mp, &type_mp, &type_mp, 0 }         },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/dsa");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dsa-sign.c b/dsa-sign.c
deleted file mode 100644 (file)
index 9d30dd9..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dsa-sign.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * DSA signing operation
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "dsa.h"
-#include "mp.h"
-#include "mpbarrett.h"
-#include "mpmont.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @dsa_mksig@ --- *
- *
- * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
- *             @mp *a@ = secret signing key
- *             @mp *m@ = message to be signed
- *             @mp *k@ = random data
- *             @mp **rr, **ss@ = where to put output parameters
- *
- * Returns:    ---
- *
- * Use:                Computes a DSA signature of a message.
- */
-
-void dsa_mksig(const dsa_param *dp, mp *a, mp *m, mp *k, mp **rr, mp **ss)
-{
-  mpmont pm;
-  mpbarrett qb;
-  mp *k1, *r;
-  mp *ar;
-
-  /* --- Compute %$r = (g^k \bmod p) \bmod q$% --- */
-
-  mpmont_create(&pm, dp->p);
-  r = mpmont_exp(&pm, MP_NEW, dp->g, k);
-  mpmont_destroy(&pm);
-  mp_div(0, &r, r, dp->q);
-
-  /* --- Compute %$k^{-1} \bmod q$% --- */
-
-  k1 = mp_modinv(MP_NEW, k, dp->q);
-
-  /* --- Now for %$k^{-1}(m + ar)$% --- */
-
-  mpbarrett_create(&qb, dp->q);
-  ar = mp_mul(MP_NEW, a, r);
-  ar = mp_add(ar, ar, m);
-  ar = mpbarrett_reduce(&qb, ar, ar);
-  ar = mp_mul(ar, ar, k1);
-  ar = mpbarrett_reduce(&qb, ar, ar);
-  mpbarrett_destroy(&qb);
-  MP_DROP(k1);
-  if (*rr) MP_DROP(*rr);
-  if (*ss) MP_DROP(*ss);
-  *rr = r;
-  *ss = ar;
-}
-
-/* --- @dsa_sign@ --- *
- *
- * Arguments:  @dsa_param *dp@ = pointer to DSA parameters
- *             @mp *a@ = pointer to secret signing key
- *             @const void *m@ = pointer to message
- *             @size_t msz@ = size of the message
- *             @const void *k@ = secret random data for securing signature
- *             @size_t ksz@ = size of secret data
- *             @void *r@ = pointer to output space for @r@
- *             @size_t rsz@ = size of output space for @r@
- *             @void *s@ = pointer to output space for @s@
- *             @size_t ssz@ = size of output space for @s@
- *
- * Returns:    ---
- *
- * Use:                Signs a message, storing the results in a big-endian binary
- *             form.
- */
-
-void dsa_sign(dsa_param *dp, mp *a,
-             const void *m, size_t msz, const void *k, size_t ksz,
-             void *r, size_t rsz, void *s, size_t ssz)
-{
-  mp *mm = dsa_h2n(MP_NEW, dp->q, m, msz);
-  mp *km = mp_loadb(MP_NEW, k, ksz);
-  mp *rm = MP_NEW, *sm = MP_NEW;
-  dsa_mksig(dp, a, mm, km, &rm, &sm);
-  mp_storeb(rm, r, rsz);
-  mp_storeb(sm, s, ssz);
-  mp_drop(mm); mp_drop(km);
-  mp_drop(rm); mp_drop(sm);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-#include "sha.h"
-
-static int verify(dstr *v)
-{
-  dsa_param dp;
-  mp *x;
-  sha_ctx c;
-  octet hash[SHA_HASHSZ];
-  dsa_sig s;
-  int ok = 1;
-
-  dp.q = *(mp **)v[0].buf;
-  dp.p = *(mp **)v[1].buf;
-  dp.g = *(mp **)v[2].buf;
-  x = *(mp **)v[3].buf;
-
-  sha_init(&c);
-  sha_hash(&c, v[4].buf, v[4].len);
-  sha_done(&c, hash);
-
-  dsa_sign(&dp, x, hash, sizeof(hash), v[5].buf, v[5].len,
-          s.r, sizeof(s.r), s.s, sizeof(s.s));
-
-  if (v[6].len != sizeof(s.r) || v[7].len != sizeof(s.s) ||
-      memcmp(s.r, v[6].buf, sizeof(s.r)) != 0 ||
-      memcmp(s.s, v[7].buf, sizeof(s.s)) != 0) {
-    fputs("\n*** signature failed", stderr);
-    fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16);
-    fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16);
-    fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16);
-    fputs("\nx = ", stderr); mp_writefile(x, stderr, 16);
-    fprintf(stderr, "\nmessage = `%s'", v[4].buf);
-    fputs("\nk = ", stderr); type_hex.dump(&v[5], stderr);
-    fputs("\nR = ", stderr); type_hex.dump(&v[6], stderr);
-    fputs("\nS = ", stderr); type_hex.dump(&v[7], stderr);
-
-    {
-      mp *m = MP_NEW;
-      m = mp_loadb(m, hash, sizeof(hash));
-      fputs("\nm = ", stderr); mp_writefile(m, stderr, 16);
-      m = mp_loadb(m, s.r, sizeof(s.r));
-      fputs("\nr = ", stderr); mp_writefile(m, stderr, 16);
-      m = mp_loadb(m, s.s, sizeof(s.s));
-      fputs("\ns = ", stderr); mp_writefile(m, stderr, 16);
-      mp_drop(m);
-    }
-
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(dp.p);
-  mp_drop(dp.q);
-  mp_drop(dp.g);
-  mp_drop(x);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "sign", verify,
-    { &type_mp, &type_mp, &type_mp, &type_mp,
-      &type_string, &type_hex, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/dsa");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dsa-verify.c b/dsa-verify.c
deleted file mode 100644 (file)
index 90895b4..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dsa-verify.c,v 1.7 2004/04/08 01:36:15 mdw Exp $
- *
- * DSA signature verification
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "dsa.h"
-#include "mp.h"
-#include "mpmont.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @dsa_vrfy@ --- *
- *
- * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
- *             @mp *y@ = public verification key
- *             @mp *m@ = message which was signed
- *             @mp *r, *s@ = the signature
- *
- * Returns:    Zero if the signature is a forgery, nonzero if it's valid.
- *
- * Use:                Verifies a DSA digital signature.
- */
-
-int dsa_vrfy(const dsa_param *dp, mp *y, mp *m, mp *r, mp *s)
-{
-  mpmont pm, qm;
-  mp *w;
-  mp_expfactor f[2];
-  int ok;
-
-  /* --- Ensure that all of the signature bits are in range --- */
-
-  if ((r->f | s->f) & MP_NEG)
-    return (0);
-  if (MP_CMP(r, >=, dp->q) || MP_CMP(s, >=, dp->q))
-    return (0);
-
-  /* --- Set up Montgomery contexts --- */
-
-  mpmont_create(&pm, dp->p);
-  mpmont_create(&qm, dp->q);
-
-  /* --- Compute %$w = s^{-1} \bmod q$% --- */
-
-  {
-    mp *z = mp_modinv(MP_NEW, s, dp->q);
-    w = mpmont_mul(&qm, MP_NEW, z, qm.r2);
-    mp_drop(z);
-  }
-
-  /* --- Compute %$wr$% and %$wm$% --- */
-
-  f[0].exp = mpmont_mul(&qm, MP_NEW, w, m);
-  f[1].exp = mpmont_mul(&qm, MP_NEW, w, r);
-  mp_drop(w);
-  mpmont_destroy(&qm);
-
-  /* --- Do the exponentiation and take residue mod @q@ --- */
-
-  f[0].base = dp->g;
-  f[1].base = y;
-  w = mpmont_mexp(&pm, MP_NEW, f, 2);
-  mp_div(0, &w, w, dp->q);
-  ok = MP_EQ(w, r);
-
-  /* --- Tidy up --- */
-
-  mp_drop(w);
-  mp_drop(f[0].exp);
-  mp_drop(f[1].exp);
-  mpmont_destroy(&pm);
-  return (ok);
-}
-
-/* --- @dsa_verify@ --- *
- *
- * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
- *             @mp *y@ = public verification key
- *             @const void *m@ = pointer to message block
- *             @size_t msz@ = size of message block
- *             @const void *r@ = pointer to @r@ signature half
- *             @size_t rsz@ = size of @r@
- *             @const void *s@ = pointer to @s@ signature half
- *             @size_t ssz@ = size of @s@
- *
- * Returns:    Zero if the signature is a forgery, nonzero if it's valid.
- *
- * Use:                Verifies a DSA digital signature.
- */
-
-int dsa_verify(const dsa_param *dp, mp *y,
-              const void *m, size_t msz,
-              const void *r, size_t rsz,
-              const void *s, size_t ssz)
-{
-  mp *mm = dsa_h2n(MP_NEW, dp->q, m, msz);
-  mp *rm = mp_loadb(MP_NEW, r, rsz);
-  mp *sm = mp_loadb(MP_NEW, s, ssz);
-  int ok = dsa_vrfy(dp, y, mm, rm, sm);
-  mp_drop(mm);
-  mp_drop(rm);
-  mp_drop(sm);
-  return (ok);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-#include "sha.h"
-
-static int verify(int good, dstr *v)
-{
-  dsa_param dp;
-  mp *y;
-  sha_ctx c;
-  octet hash[SHA_HASHSZ];
-  int ok = 1;
-  int rc;
-
-  dp.q = *(mp **)v[0].buf;
-  dp.p = *(mp **)v[1].buf;
-  dp.g = *(mp **)v[2].buf;
-  y = *(mp **)v[3].buf;
-
-  sha_init(&c);
-  sha_hash(&c, v[4].buf, v[4].len);
-  sha_done(&c, hash);
-
-  rc = dsa_verify(&dp, y, hash, sizeof(hash),
-                 v[5].buf, v[5].len, v[6].buf, v[6].len);
-
-  if (!rc != !good) {
-    if (good)
-      fputs("\n*** verification failed", stderr);
-    else
-      fputs("\n*** verification succeeded", stderr);
-    fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16);
-    fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16);
-    fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16);
-    fputs("\ny = ", stderr); mp_writefile(y, stderr, 16);
-    fprintf(stderr, "\nmessage = `%s'", v[4].buf);
-    fputs("\nr = ", stderr); type_hex.dump(&v[5], stderr);
-    fputs("\ns = ", stderr); type_hex.dump(&v[6], stderr);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(dp.p);
-  mp_drop(dp.q);
-  mp_drop(dp.g);
-  mp_drop(y);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vgood(dstr *v) { return verify(1, v); }
-static int vbad(dstr *v) { return verify(0, v); }
-
-static test_chunk tests[] = {
-  { "verify-good", vgood,
-    { &type_mp, &type_mp, &type_mp, &type_mp,
-      &type_string, &type_hex, &type_hex, 0 } },
-  { "verify-bad", vbad,
-    { &type_mp, &type_mp, &type_mp, &type_mp,
-      &type_string, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/dsa");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dsa.h b/dsa.h
deleted file mode 100644 (file)
index 43ff845..0000000
--- a/dsa.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dsa.h,v 1.9 2004/04/08 01:36:15 mdw Exp $
- *
- * Digital Signature Algorithm
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_DSA_H
-#define CATACOMB_DSA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Notes on the Digital Signature Algorithm --------------------------*
- *
- * The Digital Signature Algorithm was designed by the NSA for US Government
- * use.  It's defined in FIPS 186-1.  Whether it's covered by patents is
- * under dispute, although it looks relatively clear.  It produces compact
- * signatures, and is relatively easy to compute.  It seems strong, if
- * appropriate parameters are chosen.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_DH_H
-#  include "dh.h"
-#endif
-
-#ifndef CATACOMB_KEY_H
-#  include "key.h"
-#endif
-
-#ifndef CATACOMB_KEYCHECK_H
-#  include "keycheck.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_PGEN_H
-#  include "pgen.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- The parameters and keys are the same as for Diffie-Hellman --- */
-
-typedef dh_param dsa_param;
-typedef dh_pub dsa_pub;
-typedef dh_priv dsa_priv;
-
-/* --- DSA key seed structure --- */
-
-typedef struct dsa_seed {
-  void *p;                             /* Pointer to seed material */
-  size_t sz;                           /* Size of seed material */
-  unsigned count;                      /* Iterations to find @p@ */
-} dsa_seed;
-
-/* --- DSA signature structure --- *
- *
- * This is the recommended structure for a DSA signature.  The actual signing
- * function can cope with arbitrary-sized objects given appropriate
- * parameters, however.
- */
-
-#define DSA_SIGLEN 20
-
-typedef struct dsa_sig {
-  octet r[DSA_SIGLEN];                 /* 160-bit @r@ value */
-  octet s[DSA_SIGLEN];                 /* 160-bit @s@ value */
-} dsa_sig;
-
-/*----- Key fetching ------------------------------------------------------*/
-
-#define dsa_paramfetch dh_paramfetch
-#define dsa_pubfetch dh_pubfetch
-#define dsa_privfetch dh_privfetch
-
-#define DSA_PARAMFETCHSZ DH_PARAMFETCHSZ
-#define DSA_PUBFETCHSZ DH_PUBFETCHSZ
-#define DSA_PRIVFETCHSZ DH_PRIVFETCHSZ
-
-#define dsa_paramfree dh_paramfree
-#define dsa_pubfree dh_pubfree
-#define dsa_privfree dh_privfree
-
-/*----- DSA stepper -------------------------------------------------------*/
-
-typedef struct dsa_stepctx {
-
-  /* --- To be initialized by the client --- */
-
-  grand *r;                            /* Random number generator */
-  mp *q;                               /* Force @p@ to be a multiple */
-  size_t bits;                         /* Number of bits in the result */
-  unsigned or;                         /* OR mask for low order bits */
-  unsigned count;                      /* Counts the number of steps made */
-  void *seedbuf;                       /* Pointer to seed buffer */
-} dsa_stepctx;
-
-/* --- @dsa_step@ --- *
- *
- * The stepper chooses random integers, ensures that they are a multiple of
- * @q@ (if specified), sets the low-order bits, and then tests for
- * divisibility by small primes.
- */
-
-extern pgen_proc dsa_step;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @dsa_gen@ --- *
- *
- * Arguments:  @dsa_param *dp@ = where to store parameters
- *             @unsigned ql@ = length of @q@ in bits
- *             @unsigned pl@ = length of @p@ in bits
- *             @unsigned steps@ = number of steps to find @q@
- *             @const void *k@ = pointer to key material
- *             @size_t sz@ = size of key material
- *             @dsa_seed *sd@ = optional pointer for output seed information
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for event handler
- *
- * Returns:    @PGEN_DONE@ if everything worked ok; @PGEN_ABORT@ otherwise.
- *
- * Use:                Generates the DSA shared parameters from a given seed value.
- *             This can take quite a long time.
- *
- *             The algorithm used is a compatible extension of the method
- *             described in the DSA standard, FIPS 186.  The standard
- *             requires that %$q$% be 160 bits in size (i.e., @ql == 160@)
- *             and that the length of %$p$% be %$L = 512 + 64l$% for some
- *             %$l$%.  Neither limitation applies to this implementation.
- */
-
-extern int dsa_gen(dsa_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/,
-                  unsigned /*steps*/, const void */*k*/, size_t /*sz*/,
-                  dsa_seed */*sd*/, pgen_proc */*event*/, void */*ectx*/);
-
-/* --- @dsa_checkparam@ --- *
- *
- * Arguments:  @keycheck *kc@ = keycheck state
- *             @const dsa_param *dp@ = pointer to the parameter set
- *             @const dsa_seed *ds@ = pointer to seed information
- *
- * Returns:    Zero if all OK, or return status from function.
- *
- * Use:                Checks a set of DSA parameters for consistency and security.
- */
-
-extern int dsa_checkparam(keycheck */*kc*/, const dsa_param */*dp*/,
-                         const dsa_seed */*ds*/);
-
-/* --- @dsa_h2n@ --- *
- *
- * Arguments:  @mp *d@ = destination integer
- *             @mp *r@ = order of the DSA group
- *             @const void *h@ = pointer to message hash
- *             @size_t hsz@ = size (in bytes) of the hash output
- *
- * Returns:    Resulting integer.
- *
- * Use:                Converts a hash to an integer in the demented way necessary
- *             for DSA/ECDSA.  This is, of course, completely insane, but
- *             there you go.
- */
-
-extern mp *dsa_h2n(mp */*d*/, mp */*r*/, const void */*h*/, size_t /*hsz*/);
-
-/* --- @dsa_mksig@ --- *
- *
- * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
- *             @mp *a@ = secret signing key
- *             @mp *m@ = message to be signed
- *             @mp *k@ = random data
- *             @mp **rr, **ss@ = where to put output parameters
- *
- * Returns:    ---
- *
- * Use:                Computes a DSA signature of a message.
- */
-
-extern void dsa_mksig(const dsa_param */*dp*/, mp */*a*/,
-                     mp */*m*/, mp */*k*/,
-                     mp **/*rr*/, mp **/*ss*/);
-
-/* --- @dsa_sign@ --- *
- *
- * Arguments:  @dsa_param *dp@ = pointer to DSA parameters
- *             @mp *a@ = pointer to secret signing key
- *             @const void *m@ = pointer to message
- *             @size_t msz@ = size of the message
- *             @const void *k@ = secret random data for securing signature
- *             @size_t ksz@ = size of secret data
- *             @void *r@ = pointer to output space for @r@
- *             @size_t rsz@ = size of output space for @r@
- *             @void *s@ = pointer to output space for @s@
- *             @size_t ssz@ = size of output space for @s@
- *
- * Returns:    ---
- *
- * Use:                Signs a message, storing the results in a big-endian binary
- *             form.
- */
-
-extern void dsa_sign(dsa_param */*dp*/, mp */*a*/,
-                    const void */*m*/, size_t /*msz*/,
-                    const void */*k*/, size_t /*ksz*/,
-                    void */*r*/, size_t /*rsz*/,
-                    void */*s*/, size_t /*ssz*/);
-
-/* --- @dsa_vrfy@ --- *
- *
- * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
- *             @mp *y@ = public verification key
- *             @mp *m@ = message which was signed
- *             @mp *r, *s@ = the signature
- *
- * Returns:    Zero if the signature is a forgery, nonzero if it's valid.
- *
- * Use:                Verifies a DSA digital signature.
- */
-
-extern int dsa_vrfy(const dsa_param */*dp*/, mp */*y*/,
-                   mp */*m*/, mp */*r*/, mp */*s*/);
-
-/* --- @dsa_verify@ --- *
- *
- * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
- *             @mp *y@ = public verification key
- *             @const void *m@ = pointer to message block
- *             @size_t msz@ = size of message block
- *             @const void *r@ = pointer to @r@ signature half
- *             @size_t rsz@ = size of @r@
- *             @const void *s@ = pointer to @s@ signature half
- *             @size_t ssz@ = size of @s@
- *
- * Returns:    Zero if the signature is a forgery, nonzero if it's valid.
- *
- * Use:                Verifies a DSA digital signature.
- */
-
-extern int dsa_verify(const dsa_param */*dp*/, mp */*y*/,
-                     const void */*m*/, size_t /*msz*/,
-                     const void */*r*/, size_t /*rsz*/,
-                     const void */*s*/, size_t /*ssz*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/dsarand.c b/dsarand.c
deleted file mode 100644 (file)
index 5372b3f..0000000
--- a/dsarand.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dsarand.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Random number generator for DSA
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#include "dsarand.h"
-#include "grand.h"
-#include "sha.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @STEP@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *
- * Use:                Increments the buffer by one, interpreting it as a big-endian
- *             integer.  Carries outside the integer are discarded.
- */
-
-#define STEP(d) do {                                                   \
-  dsarand *_d = (d);                                                   \
-  octet *_p = _d->p;                                                   \
-  octet *_q = _p + _d->sz;                                             \
-  unsigned _c = 1;                                                     \
-  while (_c && _q > _p) {                                              \
-    _c += *--_q;                                                       \
-    *_q = U8(_c);                                                      \
-    _c >>= 8;                                                          \
-  }                                                                    \
-} while (0)
-
-/* --- @dsarand_init@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *             @const void *p@ = pointer to seed buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    ---
- *
- * Use:                Initializes a DSA random number generator.
- */
-
-void dsarand_init(dsarand *d, const void *p, size_t sz)
-{
-  d->p = xmalloc(sz);
-  d->sz = sz;
-  d->passes = 1;
-  if (p)
-    memcpy(d->p, p, sz);
-}
-
-/* --- @dsarand_reseed@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *             @const void *p@ = pointer to seed buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    ---
- *
- * Use:                Initializes a DSA random number generator.
- */
-
-void dsarand_reseed(dsarand *d, const void *p, size_t sz)
-{
-  xfree(d->p);
-  d->p = xmalloc(sz);
-  d->sz = sz;
-  d->passes = 1;
-  if (p)
-    memcpy(d->p, p, sz);
-}
-
-/* --- @dsarand_destroy@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *
- * Returns:    ---
- *
- * Use:                Disposes of a DSA random number generation context.
- */
-
-void dsarand_destroy(dsarand *d)
-{
-  xfree(d->p);
-}
-
-/* --- @dsarand_fill@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *             @void *p@ = pointer to output buffer
- *             @size_t sz@ = size of output buffer
- *
- * Returns:    ---
- *
- * Use:                Fills an output buffer with pseudorandom data.
- *
- *             Let %$p$% be the numerical value of the input buffer, and let
- *             %$b$% be the number of bytes required.  Let
- *             %$z = \lceil b / 20 \rceil$% be the number of SHA outputs
- *             required.  Then the output of pass %$n$% is
- *
- *               %$P_n = \sum_{0 \le i < z} 2^{160i} SHA(p + nz + i)$%
- *                                                     %${} \bmod 2^{8b}$%
- *
- *             and the actual result in the output buffer is the XOR of all
- *             of the output passes.
- *
- *             The DSA procedure for choosing @q@ involves two passes with
- *             %$z = 1$%; the procedure for choosing @p@ involves one pass
- *             with larger %$z$%.  This generalization of the DSA generation
- *             procedure is my own invention but it seems relatively sound.
- */
-
-void dsarand_fill(dsarand *d, void *p, size_t sz)
-{
-  octet *q = p;
-  unsigned n = d->passes;
-
-  /* --- Write out the first pass --- *
-   *
-   * This can write directly to the output buffer, so it's done differently
-   * from the latter passes.
-   */
-
-  {
-    size_t o = sz;
-
-    while (o) {
-      sha_ctx h;
-
-      /* --- Hash the input buffer --- */
-
-      sha_init(&h);
-      sha_hash(&h, d->p, d->sz);
-
-      /* --- If enough space, extract the hash output directly --- */
-
-      if (o >= SHA_HASHSZ) {
-       o -= SHA_HASHSZ;
-       sha_done(&h, q + o);
-      }
-
-      /* --- Otherwise take the hash result out of line and copy it --- */
-
-      else {
-       octet hash[SHA_HASHSZ];
-       sha_done(&h, hash);
-       memcpy(q, hash + (SHA_HASHSZ - o), o);
-       o = 0;
-      }
-
-      /* --- Step the input buffer --- */
-
-      STEP(d);
-    }
-
-    /* --- Another pass has been done --- */
-
-    n--;
-  }
-
-  /* --- Write out subsequent passes --- *
-   *
-   * The hash output has to be done offline, so this is slightly easier.
-   */
-
-  while (n) {
-    size_t o = sz;
-
-    while (o) {
-      sha_ctx h;
-      octet hash[SHA_HASHSZ];
-      size_t n;
-      octet *pp, *qq;
-
-      /* --- Hash the input buffer --- */
-
-      sha_init(&h);
-      sha_hash(&h, d->p, d->sz);
-      sha_done(&h, hash);
-
-      /* --- Work out how much output is wanted --- */
-
-      n = SHA_HASHSZ;
-      if (n > o)
-       n = o;
-      o -= n;
-
-      /* --- XOR the data out --- */
-
-      for (pp = hash + (SHA_HASHSZ - n), qq = q + o;
-          pp < hash + SHA_HASHSZ; pp++, qq++)
-       *qq ^= *pp;
-
-      /* --- Step the input buffer --- */
-
-      STEP(d);
-    }
-
-    /* --- Another pass is done --- */
-
-    n--;
-  }
-}
-
-/*----- Generic pseudorandom-number generator interface -------------------*/
-
-static const grand_ops gops;
-
-typedef struct gctx {
-  grand r;
-  dsarand d;
-} gctx;
-
-static void gdestroy(grand *r)
-{
-  gctx *g = (gctx *)r;
-  dsarand_destroy(&g->d);
-  DESTROY(g);
-}
-
-static int gmisc(grand *r, unsigned op, ...)
-{
-  gctx *g = (gctx *)r;
-  va_list ap;
-  int rc = 0;
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDBLOCK:
-       case GRAND_SEEDRAND:
-       case DSARAND_PASSES:
-       case DSARAND_SEEDSZ:
-       case DSARAND_GETSEED:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDBLOCK: {
-      const void *p = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      dsarand_reseed(&g->d, p, sz);
-    } break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      rr->ops->fill(rr, g->d.p, g->d.sz);
-    } break;
-    case DSARAND_PASSES:
-      g->d.passes = va_arg(ap, unsigned);
-      break;
-    case DSARAND_SEEDSZ:
-      rc = g->d.sz;
-      break;
-    case DSARAND_GETSEED:
-      memcpy(va_arg(ap, void *), g->d.p, g->d.sz);
-      break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static void gfill(grand *r, void *p, size_t sz)
-{
-  gctx *g = (gctx *)r;
-  dsarand_fill(&g->d, p, sz);
-}
-
-static const grand_ops gops = {
-  "dsarand",
-  0, 0,
-  gmisc, gdestroy,
-  grand_word, grand_byte, grand_word, grand_range, gfill
-};
-
-/* --- @dsarand_create@ --- *
- *
- * Arguments:  @const void *p@ = pointer to seed buffer
- *             @size_t sz@ = size of seed buffer
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a Catacomb
- *             entropy pool generator.
- */
-
-grand *dsarand_create(const void *p, size_t sz)
-{
-  gctx *g = CREATE(gctx);
-  g->r.ops = &gops;
-  dsarand_init(&g->d, p, sz);
-  return (&g->r);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/dsarand.h b/dsarand.h
deleted file mode 100644 (file)
index bc5e700..0000000
--- a/dsarand.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* -*-c-*-
- *
- * $Id: dsarand.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Random number generator for DSA
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_DSARAND_H
-#define CATACOMB_DSARAND_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_SHA_H
-#  include "sha.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct dsarand {
-  octet *p;                            /* Pointer to seed (modified) */
-  size_t sz;                           /* Size of the seed buffer */
-  unsigned passes;                     /* Number of passes to make */
-} dsarand;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @dsarand_init@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *             @const void *p@ = pointer to seed buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    ---
- *
- * Use:                Initializes a DSA random number generator.
- */
-
-extern void dsarand_init(dsarand */*d*/, const void */*p*/, size_t /*sz*/);
-
-/* --- @dsarand_reseed@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *             @const void *p@ = pointer to seed buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    ---
- *
- * Use:                Initializes a DSA random number generator.
- */
-
-extern void dsarand_reseed(dsarand */*d*/, const void */*p*/, size_t /*sz*/);
-
-/* --- @dsarand_destroy@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *
- * Returns:    ---
- *
- * Use:                Disposes of a DSA random number generation context.
- */
-
-extern void dsarand_destroy(dsarand */*d*/);
-
-/* --- @dsarand_fill@ --- *
- *
- * Arguments:  @dsarand *d@ = pointer to context
- *             @void *p@ = pointer to output buffer
- *             @size_t sz@ = size of output buffer
- *
- * Returns:    ---
- *
- * Use:                Fills an output buffer with pseudorandom data.
- *
- *             Let %$p$% be the numerical value of the input buffer, and let
- *             %$b$% be the number of bytes required.  Let
- *             %$z = \lceil b / 20 \rceil$% be the number of SHA outputs
- *             required.  Then the output of pass %$n$% is
- *
- *               %$P_n = \sum_{0 \le i < z} 2^{160i} SHA(p + nz + i)$%
- *                                                     %${} \bmod 2^{8b}$%
- *
- *             and the actual result in the output buffer is the XOR of all
- *             of the output passes.
- *
- *             The DSA procedure for choosing @q@ involves two passes with
- *             %$z = 1$%; the procedure for choosing @p@ involves one pass
- *             with larger %$z$%.  This generalization of the DSA generation
- *             procedure is my own invention but it seems relatively sound.
- */
-
-extern void dsarand_fill(dsarand */*d*/, void */*p*/, size_t /*sz*/);
-
-/*----- Generic pseudorandom-number generator interface -------------------*/
-
-/* --- Miscellaneous operations --- */
-
-enum {
-  DSARAND_PASSES = GRAND_SPECIFIC('D'),        /* @unsigned n@ */
-  DSARAND_SEEDSZ,                      /* No args */
-  DSARAND_GETSEED                      /* @void *buf@ */
-};
-
-/* --- @dsarand_create@ --- *
- *
- * Arguments:  @const void *p@ = pointer to seed buffer
- *             @size_t sz@ = size of seed buffer
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface to a DSA generator.
- */
-
-extern grand *dsarand_create(const void */*p*/, size_t /*sz*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/dsig.c b/dsig.c
deleted file mode 100644 (file)
index a7fa5a9..0000000
--- a/dsig.c
+++ /dev/null
@@ -1,1126 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Verify signatures on distribuitions of files
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include "config.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/base64.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include "getdate.h"
-#include "rand.h"
-#include "ghash.h"
-#include "key.h"
-#include "key-data.h"
-#include "noise.h"
-#include "cc.h"
-
-/*----- Data formatting ---------------------------------------------------*/
-
-/* --- Binary data structure --- *
- *
- * The binary format, which is used for hashing and for the optional binary
- * output, consists of a sequence of tagged blocks.  The tag describes the
- * format and meaining of the following data.
- */
-
-enum {
-  /* --- Block tags --- */
-
-  T_IDENT = 0,                         /* An identifying marker */
-  T_KEYID,                             /* Key identifier */
-  T_BEGIN,                             /* Begin hashing here */
-  T_COMMENT = T_BEGIN,                 /* A textual comment */
-  T_DATE,                              /* Creation date of signature */
-  T_EXPIRE,                            /* Expiry date of signature */
-  T_FILE,                              /* File and corresponding hash */
-  T_SIGNATURE,                         /* Final signature block */
-
-  /* --- Error messages --- */
-
-  E_EOF = -1,
-  E_BIN = -2,
-  E_TAG = -3,
-  E_DATE = -4
-};
-
-/* --- Name translation table --- */
-
-static const char *tagtab[] = {
-  "ident:", "keyid:",
-  "comment:", "date:", "expires:", "file:",
-  "signature:",
-  0
-};
-
-static const char *errtab[] = {
-  "Off-by-one bug",
-  "Unexpected end-of-file",
-  "Binary object too large",
-  "Unrecognized tag",
-  "Bad date string"
-};
-
-/* --- Memory representation of block types --- */
-
-typedef struct block {
-  int tag;                             /* Type tag */
-  dstr d;                              /* String data */
-  dstr b;                              /* Binary data */
-  time_t t;                            /* Timestamp */
-  uint32 k;                            /* Keyid */
-} block;
-
-/* --- @timestring@ --- *
- *
- * Arguments:  @time_t t@ = a timestamp
- *             @dstr *d@ = a string to write on
- *
- * Returns:    ---
- *
- * Use:                Writes a textual representation of the timestamp to the
- *             string.
- */
-
-static void timestring(time_t t, dstr *d)
-{
-  if (t == KEXP_FOREVER)
-    DPUTS(d, "forever");
-  else {
-    struct tm *tm = localtime(&t);
-    DENSURE(d, 32);
-    d->len += strftime(d->buf + d->len, 32, "%Y-%m-%d %H:%M:%S %Z", tm);
-    DPUTZ(d);
-  }
-}
-
-/* --- @breset@ --- *
- *
- * Arguments:  @block *b@ = block to reset
- *
- * Returns:    ---
- *
- * Use:                Resets a block so that more stuff can be put in it.
- */
-
-static void breset(block *b)
-{
-  b->tag = 0;
-  DRESET(&b->d);
-  DRESET(&b->b);
-  b->k = 0;
-  b->t = KEXP_EXPIRE;
-}
-
-/* --- @binit@ --- *
- *
- * Arguments:  @block *b@ = block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a block as something to read into.
- */
-
-static void binit(block *b)
-{
-  dstr_create(&b->d);
-  dstr_create(&b->b);
-  breset(b);
-}
-
-/* --- @bdestroy@ --- *
- *
- * Arguments:  @block *b@ = block to destroy
- *
- * Returns:    ---
- *
- * Use:                Destroys a block's contents.
- */
-
-static void bdestroy(block *b)
-{
-  dstr_destroy(&b->d);
-  dstr_destroy(&b->b);
-}
-
-/* --- @bget@ --- *
- *
- * Arguments:  @block *b@ = pointer to block
- *             @FILE *fp@ = stream to read from
- *             @unsigned bin@ = binary switch
- *
- * Returns:    Tag of block, or an error tag.
- *
- * Use:                Reads a block from a stream.
- */
-
-static int bget(block *b, FILE *fp, unsigned bin)
-{
-  int tag;
-
-  /* --- Read the tag --- */
-
-  if (bin)
-    tag = getc(fp);
-  else {
-    dstr d = DSTR_INIT;
-    if (getstring(fp, &d, GSF_FILE))
-      return (E_EOF);
-    for (tag = 0; tagtab[tag]; tag++) {
-      if (strcmp(tagtab[tag], d.buf) == 0)
-       goto done;
-    }
-    return (E_TAG);
-  done:;
-  }
-
-  /* --- Decide what to do next --- */
-
-  breset(b);
-  b->tag = tag;
-  switch (tag) {
-
-    /* --- Reading of strings --- */
-
-    case T_IDENT:
-    case T_COMMENT:
-      if (getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0)))
-       return (E_EOF);
-      break;
-
-    /* --- Timestamps --- */
-
-    case T_DATE:
-    case T_EXPIRE:
-      if (bin) {
-       octet buf[8];
-       if (fread(buf, sizeof(buf), 1, fp) < 1)
-         return (E_EOF);
-       b->t = ((time_t)(((LOAD32(buf + 0) << 16) << 16) & ~MASK32) |
-               (time_t)LOAD32(buf + 4));
-      } else {
-       if (getstring(fp, &b->d, GSF_FILE))
-         return (E_EOF);
-       if (strcmp(b->d.buf, "forever") == 0)
-         b->t = KEXP_FOREVER;
-       else if ((b->t = get_date(b->d.buf, 0)) == -1)
-         return (E_DATE);
-      }
-      break;
-
-    /* --- Key ids --- */
-
-    case T_KEYID:
-      if (bin) {
-       octet buf[4];
-       if (fread(buf, sizeof(buf), 1, fp) < 1)
-         return (E_EOF);
-       b->k = LOAD32(buf);
-      } else {
-       if (getstring(fp, &b->d, GSF_FILE))
-         return (E_EOF);
-       b->k = strtoul(b->d.buf, 0, 16);
-      }
-      break;
-
-    /* --- Reading of binary data --- */
-
-    case T_FILE:
-    case T_SIGNATURE:
-      if (bin) {
-       octet buf[2];
-       uint32 sz;
-       if (fread(buf, sizeof(buf), 1, fp) < 1)
-         return (E_EOF);
-       sz = LOAD16(buf);
-       if (sz > 4096)
-         return (E_BIN);
-       DENSURE(&b->b, sz);
-       if (fread(b->b.buf + b->b.len, 1, sz, fp) < sz)
-         return (E_EOF);
-       b->b.len += sz;
-      } else {
-       base64_ctx b64;
-       if (getstring(fp, &b->d, GSF_FILE))
-         return (E_EOF);
-       base64_init(&b64);
-       base64_decode(&b64, b->d.buf, b->d.len, &b->b);
-       base64_decode(&b64, 0, 0, &b->b);
-       DRESET(&b->d);
-      }
-      if (tag == T_FILE &&
-         getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0)))
-       return (E_EOF);
-      break;
-
-      /* --- Anything else --- */
-
-    default:
-      return (E_TAG);
-  }
-
-  return (tag);
-}
-
-/* --- @blob@ --- *
- *
- * Arguments:  @block *b@ = pointer to block to emit
- *             @dstr *d@ = output buffer
- *
- * Returns:    ---
- *
- * Use:                Encodes a block in a binary format.
- */
-
-static void blob(block *b, dstr *d)
-{
-  DPUTC(d, b->tag);
-  switch (b->tag) {
-    case T_IDENT:
-    case T_COMMENT:
-      DPUTD(d, &b->d);
-      DPUTC(d, 0);
-      break;
-    case T_DATE:
-    case T_EXPIRE:
-      DENSURE(d, 8);
-      if (b->t == KEXP_FOREVER) {
-       STORE32(d->buf + d->len, 0xffffffff);
-       STORE32(d->buf + d->len + 4, 0xffffffff);
-      } else {
-       STORE32(d->buf + d->len, ((b->t & ~MASK32) >> 16) >> 16);
-       STORE32(d->buf + d->len + 4, b->t);
-      }
-      d->len += 8;
-      break;
-    case T_KEYID:
-      DENSURE(d, 4);
-      STORE32(d->buf + d->len, b->k);
-      d->len += 4;
-      break;
-    case T_FILE:
-    case T_SIGNATURE:
-      DENSURE(d, 2);
-      STORE16(d->buf + d->len, b->b.len);
-      d->len += 2;
-      DPUTD(d, &b->b);
-      if (b->tag == T_FILE) {
-       DPUTD(d, &b->d);
-       DPUTC(d, 0);
-      }
-      break;
-  }
-}
-
-/* --- @bwrite@ --- *
- *
- * Arguments:  @block *b@ = pointer to block to write
- *             @FILE *fp@ = stream to write on
- *
- * Returns:    ---
- *
- * Use:                Writes a block on a stream in a textual format.
- */
-
-static void bwrite(block *b, FILE *fp)
-{
-  fputs(tagtab[b->tag], fp);
-  putc(' ', fp);
-  switch (b->tag) {
-    case T_IDENT:
-    case T_COMMENT:
-      putstring(fp, b->d.buf, 0);
-      break;
-    case T_DATE:
-    case T_EXPIRE: {
-      dstr d = DSTR_INIT;
-      timestring(b->t, &d);
-      putstring(fp, d.buf, 0);
-      dstr_destroy(&d);
-    } break;
-    case T_KEYID:
-      fprintf(fp, "%08lx", (unsigned long)b->k);
-      break;
-    case T_FILE:
-    case T_SIGNATURE: {
-      dstr d = DSTR_INIT;
-      base64_ctx b64;
-      base64_init(&b64);
-      b64.maxline = 0;
-      base64_encode(&b64, b->b.buf, b->b.len, &d);
-      base64_encode(&b64, 0, 0, &d);
-      dstr_write(&d, fp);
-      if (b->tag == T_FILE) {
-       putc(' ', fp);
-       putstring(fp, b->d.buf, 0);
-      }
-    } break;
-  }
-  putc('\n', fp);
-}
-
-/* --- @bemit@ --- *
- *
- * Arguments:  @block *b@ = pointer to block to write
- *             @FILE *fp@ = file to write on
- *             @ghash *h@ = pointer to hash function
- *             @unsigned bin@ = binary/text flag
- *
- * Returns:    ---
- *
- * Use:                Spits out a block properly.
- */
-
-static void bemit(block *b, FILE *fp, ghash *h, unsigned bin)
-{
-  if (h || (fp && bin)) {
-    dstr d = DSTR_INIT;
-    blob(b, &d);
-    if (h)
-      GH_HASH(h, d.buf, d.len);
-    if (fp && bin)
-      fwrite(d.buf, d.len, 1, fp);
-  }
-  if (fp && !bin)
-    bwrite(b, fp);
-}
-
-/*----- Static variables --------------------------------------------------*/
-
-static const char *keyring = "keyring";
-
-/*----- Other shared functions --------------------------------------------*/
-
-/* --- @fhex@ --- *
- *
- * Arguments:  @FILE *fp@ = file to write on
- *             @const void *p@ = pointer to data to be written
- *             @size_t sz@ = size of the data to write
- *
- * Returns:    ---
- *
- * Use:                Emits a hex dump to a stream.
- */
-
-static void fhex(FILE *fp, const void *p, size_t sz)
-{
-  const octet *q = p;
-  if (!sz)
-    return;
-  for (;;) {
-    fprintf(fp, "%02x", *q++);
-    sz--;
-    if (!sz)
-      break;
-  }
-}
-
-/*----- Signature generation ----------------------------------------------*/
-
-static int sign(int argc, char *argv[])
-{
-#define f_bogus 1u
-#define f_bin 2u
-#define f_nocheck 4u
-
-  unsigned f = 0;
-  const char *ki = "dsig";
-  key_file kf;
-  key *k;
-  sig *s;
-  fhashstate fh;
-  time_t exp = KEXP_EXPIRE;
-  unsigned verb = 0;
-  const char *ifile = 0, *hfile = 0;
-  const char *ofile = 0;
-  const char *c = 0;
-  const char *err;
-  FILE *ifp, *ofp;
-  dstr d = DSTR_INIT;
-  hfpctx hfp;
-  block b;
-  int e, hf, n;
-
-  for (;;) {
-    static struct option opts[] = {
-      { "null",                0,              0,      '0' },
-      { "binary",      0,              0,      'b' },
-      { "verbose",     0,              0,      'v' },
-      { "progress",    0,              0,      'p' },
-      { "quiet",       0,              0,      'q' },
-      { "comment",     OPTF_ARGREQ,    0,      'c' },
-      { "file",                OPTF_ARGREQ,    0,      'f' },
-      { "hashes",      OPTF_ARGREQ,    0,      'h' },
-      { "output",      OPTF_ARGREQ,    0,      'o' },
-      { "key",         OPTF_ARGREQ,    0,      'k' },
-      { "expire",      OPTF_ARGREQ,    0,      'e' },
-      { "nocheck",     OPTF_ARGREQ,    0,      'C' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+0vpqbC" "c:" "f:h:o:" "k:e:",
-                  opts, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case '0':
-       f |= GSF_RAW;
-       break;
-      case 'b':
-       f |= f_bin;
-       break;
-      case 'v':
-       verb++;
-       break;
-      case 'p':
-       f |= FHF_PROGRESS;
-       break;
-      case 'q':
-       if (verb > 0)
-         verb--;
-       break;
-      case 'C':
-       f |= f_nocheck;
-       break;
-      case 'c':
-       c = optarg;
-       break;
-      case 'f':
-       ifile = optarg;
-       break;
-      case 'h':
-       hfile = optarg;
-       break;
-      case 'o':
-       ofile = optarg;
-       break;
-      case 'k':
-       ki = optarg;
-       break;
-      case 'e':
-       if (strcmp(optarg, "forever") == 0)
-         exp = KEXP_FOREVER;
-       else if ((exp = get_date(optarg, 0)) == -1)
-         die(EXIT_FAILURE, "bad expiry time");
-       break;
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-  if (optind != argc || (f & f_bogus))
-    die(EXIT_FAILURE, "Usage: sign [-OPTIONS]");
-  if (hfile && ifile)
-    die(EXIT_FAILURE, "Inconsistent options `-h' and `-f'");
-
-  /* --- Locate the signing key --- */
-
-  if (key_open(&kf, keyring, KOPEN_WRITE, key_moan, 0))
-    die(EXIT_FAILURE, "couldn't open keyring `%s'", keyring);
-  if ((k = key_bytag(&kf, ki)) == 0)
-    die(EXIT_FAILURE, "couldn't find key `%s'", ki);
-  key_fulltag(k, &d);
-  if (exp == KEXP_FOREVER && k->exp != KEXP_FOREVER) {
-    die(EXIT_FAILURE, "key `%s' expires: can't create nonexpiring signature",
-       d.buf);
-  }
-  s = getsig(k, "dsig", 1);
-
-  /* --- Check the key --- */
-
-  if (!(f & f_nocheck) && (err = s->ops->check(s)) != 0)
-    moan("key `%s' fails check: %s", d.buf, err);
-
-  /* --- Open files --- */
-
-  if (hfile) ifile = hfile;
-  if (!ifile || strcmp(ifile, "-") == 0)
-    ifp = stdin;
-  else if ((ifp = fopen(ifile, (f & f_bin) ? "rb" : "r")) == 0) {
-    die(EXIT_FAILURE, "couldn't open input file `%s': %s",
-       ifile, strerror(errno));
-  }
-
-  if (!ofile || strcmp(ofile, "-") == 0)
-    ofp = stdout;
-  else if ((ofp = fopen(ofile, (f & f_bin) ? "wb" : "w")) == 0) {
-    die(EXIT_FAILURE, "couldn't open output file `%s': %s",
-       ofile, strerror(errno));
-  }
-
-  /* --- Emit the start of the output --- */
-
-  binit(&b); b.tag = T_IDENT;
-  dstr_putf(&b.d, "%s, Catacomb version " VERSION, QUIS);
-  bemit(&b, ofp, 0, f & f_bin);
-
-  breset(&b); b.tag = T_KEYID; b.k = k->id;
-  bemit(&b, ofp, 0, f & f_bin);
-
-  /* --- Start hashing, and emit the datestamps and things --- */
-
-  {
-    time_t now = time(0);
-
-    breset(&b); b.tag = T_DATE; b.t = now; bemit(&b, ofp, s->h, f & f_bin);
-    if (exp == KEXP_EXPIRE)
-      exp = now + 86400 * 28;
-    breset(&b); b.tag = T_EXPIRE; b.t = exp; bemit(&b, ofp, s->h, f & f_bin);
-    if (c) {
-      breset(&b); b.tag = T_COMMENT; DPUTS(&b.d, c);
-      bemit(&b, ofp, s->h, f & f_bin);
-    }
-
-    if (!(f & f_bin))
-      putc('\n', ofp);
-  }
-
-  /* --- Now hash the various files --- */
-
-  if (hfile) {
-    hfp.f = f;
-    hfp.fp = ifp;
-    hfp.ee = &encodingtab[ENC_HEX];
-    hfp.gch = GH_CLASS(s->h);
-    hfp.dline = &d;
-    hfp.dfile = &b.d;
-
-    n = 0;
-    for (;;) {
-      breset(&b);
-      DENSURE(&b.b, hfp.gch->hashsz);
-      hfp.hbuf = (octet *)b.b.buf;
-      if (ferror(ofp)) { f |= f_bogus; break; }
-      if ((hf = hfparse(&hfp)) == HF_EOF) break;
-      n++;
-
-      switch (hf) {
-       case HF_HASH:
-         if (hfp.gch != GH_CLASS(s->h)) {
-           moan("%s:%d: incorrect hash function `%s' (should be `%s')",
-                hfile, n, hfp.gch->name, GH_CLASS(s->h)->name);
-           f |= f_bogus;
-         }
-         break;
-       case HF_BAD:
-         moan("%s:%d: invalid hash-file line", hfile, n);
-         f |= f_bogus;
-         break;
-       case HF_FILE:
-         b.tag = T_FILE;
-         b.b.len += hfp.gch->hashsz;
-         bemit(&b, ofp, s->h, f & f_bin);
-         break;
-      }
-    }
-  } else {
-    for (;;) {
-
-      /* --- Stop on an output error --- */
-
-      if (ferror(ofp)) {
-       f |= f_bogus;
-       break;
-      }
-
-      /* --- Read the next filename to hash --- */
-
-      fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY);
-      breset(&b);
-      if (getstring(ifp, &b.d, GSF_FILE | f))
-       break;
-      b.tag = T_FILE;
-      DENSURE(&b.b, GH_CLASS(s->h)->hashsz);
-      if (fhash(&fh, b.d.buf, b.b.buf)) {
-       moan("error reading `%s': %s", b.d.buf, strerror(errno));
-       f |= f_bogus;
-      } else {
-       b.b.len += GH_CLASS(s->h)->hashsz;
-       if (verb) {
-         fhex(stderr, b.b.buf, b.b.len);
-         fprintf(stderr, " %s\n", b.d.buf);
-       }
-       bemit(&b, ofp, s->h, f & f_bin);
-      }
-      fhash_free(&fh);
-    }
-  }
-
-  /* --- Create the signature --- */
-
-  if (!(f & f_bogus)) {
-    breset(&b);
-    b.tag = T_SIGNATURE;
-    if ((e = s->ops->doit(s, &b.b)) != 0) {
-      moan("error creating signature: %s", key_strerror(e));
-      f |= f_bogus;
-    }
-    if (!(f & f_bogus)) {
-      bemit(&b, ofp, 0, f & f_bin);
-      key_used(&kf, k, exp);
-    }
-  }
-
-  /* --- Tidy up at the end --- */
-
-  freesig(s);
-  bdestroy(&b);
-  if (ifile)
-    fclose(ifp);
-  if (ofile) {
-    if (fclose(ofp))
-      f |= f_bogus;
-  } else {
-    if (fflush(ofp))
-      f |= f_bogus;
-  }
-  if ((e = key_close(&kf)) != 0) {
-    switch (e) {
-      case KWRITE_FAIL:
-       die(EXIT_FAILURE, "couldn't write file `%s': %s",
-           keyring, strerror(errno));
-      case KWRITE_BROKEN:
-       die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)",
-           keyring, strerror(errno));
-    }
-  }
-  if (f & f_bogus)
-    die(EXIT_FAILURE, "error(s) occurred while creating signature");
-  return (EXIT_SUCCESS);
-
-#undef f_bin
-#undef f_bogus
-#undef f_nocheck
-}
-
-/*----- Signature verification --------------------------------------------*/
-
-static int checkjunk(const char *path, const struct stat *st, void *p)
-{
-  if (!st) printf("JUNK (error %s) %s\n", strerror(errno), path);
-  else printf("JUNK %s %s\n", describefile(st), path);
-  return (0);
-}
-
-static int verify(int argc, char *argv[])
-{
-#define f_bogus 1u
-#define f_bin 2u
-#define f_ok 4u
-#define f_nocheck 8u
-
-  unsigned f = 0;
-  unsigned verb = 1;
-  key_file kf;
-  key *k = 0;
-  sig *s;
-  dstr d = DSTR_INIT;
-  const char *err;
-  fhashstate fh;
-  FILE *fp;
-  block b;
-  int e;
-
-  /* --- Parse the options --- */
-
-  for (;;) {
-    static struct option opts[] = {
-      { "verbose",     0,              0,      'v' },
-      { "progress",    0,              0,      'p' },
-      { "quiet",       0,              0,      'q' },
-      { "nocheck",     0,              0,      'C' },
-      { "junk",                0,              0,      'j' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+vpqCj", opts, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'v':
-       verb++;
-       break;
-      case 'p':
-       f |= FHF_PROGRESS;
-       break;
-      case 'q':
-       if (verb)
-         verb--;
-       break;
-      case 'C':
-       f |= f_nocheck;
-       break;
-      case 'j':
-       f |= FHF_JUNK;
-       break;
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-  argc -= optind;
-  argv += optind;
-  if ((f & f_bogus) || argc > 1)
-    die(EXIT_FAILURE, "Usage: verify [-qvC] [FILE]");
-
-  /* --- Open the key file, and start reading the input file --- */
-
-  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
-    die(EXIT_FAILURE, "couldn't open keyring `%s'\n", keyring);
-  if (argc < 1)
-    fp = stdin;
-  else {
-    if ((fp = fopen(argv[0], "rb")) == 0) {
-      die(EXIT_FAILURE, "couldn't open file `%s': %s\n",
-             argv[0], strerror(errno));
-    }
-    if (getc(fp) == 0) {
-      ungetc(0, fp);
-      f |= f_bin;
-    } else {
-      fclose(fp);
-      if ((fp = fopen(argv[0], "r")) == 0) {
-       die(EXIT_FAILURE, "couldn't open file `%s': %s\n",
-               argv[0], strerror(errno));
-      }
-    }
-  }
-
-  /* --- Read the introductory matter --- */
-
-  binit(&b);
-  for (;;) {
-    breset(&b);
-    e = bget(&b, fp, f & f_bin);
-    if (e < 0)
-      die(EXIT_FAILURE, "error reading packet: %s", errtab[-e]);
-    if (e >= T_BEGIN)
-      break;
-    switch (e) {
-      case T_IDENT:
-       if (verb > 2)
-         printf("INFO ident: `%s'\n", b.d.buf);
-       break;
-      case T_KEYID:
-       if ((k = key_byid(&kf, b.k)) == 0) {
-         if (verb)
-           printf("FAIL key %08lx not found\n", (unsigned long)b.k);
-         exit(EXIT_FAILURE);
-       }
-       if (verb > 2) {
-         DRESET(&b.d);
-         key_fulltag(k, &b.d);
-         printf("INFO key: %s\n", b.d.buf);
-       }
-       break;
-      default:
-       die(EXIT_FAILURE, "(internal) unknown packet type\n");
-       break;
-    }
-  }
-
-  /* --- Initialize the hash function and start reading hashed packets --- */
-
-  if (!k) {
-    if (verb)
-      puts("FAIL no keyid packet found");
-    exit(EXIT_FAILURE);
-  }
-
-  s = getsig(k, "dsig", 0);
-  if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0)
-    printf("WARN public key fails check: %s", err);
-
-  fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY);
-  for (;;) {
-    switch (e) {
-      case T_COMMENT:
-       if (verb > 1)
-         printf("INFO comment: `%s'\n", b.d.buf);
-       bemit(&b, 0, s->h, 0);
-       break;
-      case T_DATE:
-       if (verb > 2) {
-         DRESET(&b.d);
-         timestring(b.t, &b.d);
-         printf("INFO date: %s\n", b.d.buf);
-       }
-       bemit(&b, 0, s->h, 0);
-       break;
-      case T_EXPIRE: {
-       time_t now = time(0);
-       if (b.t != KEXP_FOREVER && b.t < now) {
-         if (verb > 1)
-           puts("BAD signature has expired");
-         f |= f_bogus;
-       }
-       if (verb > 2) {
-         DRESET(&b.d);
-         timestring(b.t, &b.d);
-         printf("INFO expires: %s\n", b.d.buf);
-       }
-       bemit(&b, 0, s->h, 0);
-      }        break;
-      case T_FILE:
-       DRESET(&d);
-       DENSURE(&d, GH_CLASS(s->h)->hashsz);
-       if (fhash(&fh, b.d.buf, d.buf)) {
-         if (verb > 1) {
-           printf("BAD error reading file `%s': %s\n",
-                   b.d.buf, strerror(errno));
-         }
-         f |= f_bogus;
-       } else if (b.b.len != GH_CLASS(s->h)->hashsz ||
-                  memcmp(d.buf, b.b.buf, b.b.len) != 0) {
-         if (verb > 1)
-           printf("BAD file `%s' has incorrect hash\n", b.d.buf);
-         f |= f_bogus;
-       } else if (verb > 3) {
-         fputs("INFO hash: ", stdout);
-         fhex(stdout, b.b.buf, b.b.len);
-         printf(" %s\n", b.d.buf);
-       }
-       bemit(&b, 0, s->h, 0);
-       break;
-      case T_SIGNATURE:
-       if (s->ops->doit(s, &b.b)) {
-         if (verb > 1)
-           puts("BAD bad signature");
-         f |= f_bogus;
-       } else if (verb > 2)
-         puts("INFO good signature");
-       goto done;
-      default:
-       if (verb)
-         printf("FAIL invalid packet type %i\n", e);
-       exit(EXIT_FAILURE);
-       break;
-    }
-    breset(&b);
-    e = bget(&b, fp, f & f_bin);
-    if (e < 0) {
-      if (verb)
-       printf("FAIL error reading packet: %s\n", errtab[-e]);
-      exit(EXIT_FAILURE);
-    }
-  }
-done:
-  if ((f & FHF_JUNK) && fhash_junk(&fh, checkjunk, 0))
-    f |= f_bogus;
-  fhash_free(&fh);
-  bdestroy(&b);
-  dstr_destroy(&d);
-  freesig(s);
-  key_close(&kf);
-  if (fp != stdin)
-    fclose(fp);
-  if (verb) {
-    if (f & f_bogus)
-      puts("FAIL signature invalid");
-    else
-      puts("OK signature verified");
-  }
-  return (f & f_bogus ? EXIT_FAILURE : EXIT_SUCCESS);
-
-#undef f_bogus
-#undef f_bin
-#undef f_ok
-#undef f_nocheck
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-#define LISTS(LI)                                                      \
-  LI("Lists", list,                                                    \
-     listtab[i].name, listtab[i].name)                                 \
-  LI("Signature schemes", sig,                                         \
-     sigtab[i].name, sigtab[i].name)                                   \
-  LI("Hash functions", hash,                                           \
-     ghashtab[i], ghashtab[i]->name)
-
-MAKELISTTAB(listtab, LISTS)
-
-int cmd_show(int argc, char *argv[])
-{
-  return (displaylists(listtab, argv + 1));
-}
-
-static int cmd_help(int, char **);
-
-static cmd cmdtab[] = {
-  { "help", cmd_help, "help [COMMAND...]" },
-  { "show", cmd_show, "show [ITEM...]" },
-  { "sign", sign,
-    "sign [-0bpqvC] [-c COMMENT] [-k TAG] [-e EXPIRE]\n\t\
-[-f FILE] [-h FILE] [-o OUTPUT]",
-    "\
-Options:\n\
-\n\
--0, --null             Read null-terminated filenames from stdin.\n\
--b, --binary           Produce a binary output file.\n\
--q, --quiet            Produce fewer messages while working.\n\
--v, --verbose          Produce more messages while working.\n\
--p, --progress         Show progress on large files.\n\
--C, --nocheck          Don't check the private key.\n\
--c, --comment=COMMENT  Include COMMENT in the output file.\n\
--f, --file=FILE                Read filenames to hash from FILE.\n\
--h, --hashes=FILE      Read precomputed hashes from FILE.\n\
--o, --output=FILE      Write the signed result to FILE.\n\
--k, --key=TAG          Use a key named by TAG.\n\
--e, --expire=TIME      The signature should expire after TIME.\n\
-" },
-  { "verify", verify,
-    "verify [-pqvC] [FILE]", "\
-Options:\n\
-\n\
--q, --quiet            Produce fewer messages while working.\n\
--v, --verbose          Produce more messages while working.\n\
--p, --progress         Show progress on large files.\n\
--C, --nocheck          Don't check the public key.\n\
-" },
-  { 0, 0, 0 }
-};
-
-static int cmd_help(int argc, char **argv)
-{
-  sc_help(cmdtab, stdout, argv + 1);
-  return (0);
-}
-
-void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n");
-}
-
-void help_global(FILE *fp)
-{
-  usage(fp);
-  fputs("\n\
-Create and verify signatures on lists of files.\n\
-\n\
-Global command-line options:\n\
-\n\
--h, --help [COMMAND...]        Show this help message, or help for COMMANDs.\n\
--v, --version          Show program version number.\n\
--u, --usage            Show a terse usage message.\n\
-\n\
--k, --keyring=FILE     Read keys from FILE.\n",
-       fp);
-}
-
-/* --- @main@ --- *
- *
- * Arguments:  @int argc@ = number of command line arguments
- *             @char *argv[]@ = vector of command line arguments
- *
- * Returns:    Zero if successful, nonzero otherwise.
- *
- * Use:                Signs or verifies signatures on lists of files.  Useful for
- *             ensuring that a distribution is unmolested.
- */
-
-int main(int argc, char *argv[])
-{
-  unsigned f = 0;
-
-#define f_bogus 1u
-
-  /* --- Initialize the library --- */
-
-  ego(argv[0]);
-  sub_init();
-  rand_noisesrc(RAND_GLOBAL, &noise_source);
-  rand_seed(RAND_GLOBAL, 160);
-
-  /* --- Parse options --- */
-
-  for (;;) {
-    static struct option opts[] = {
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'v' },
-      { "usage",       0,              0,      'u' },
-      { "keyring",     OPTF_ARGREQ,    0,      'k' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'h':
-       sc_help(cmdtab, stdout, argv + optind);
-       exit(0);
-       break;
-      case 'v':
-       version(stdout);
-       exit(0);
-       break;
-      case 'u':
-       usage(stdout);
-       exit(0);
-      case 'k':
-       keyring = optarg;
-       break;
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-
-  argc -= optind;
-  argv += optind;
-  optind = 0;
-  if (f & f_bogus || argc < 1) {
-    usage(stderr);
-    exit(EXIT_FAILURE);
-  }
-
-  /* --- Dispatch to the correct subcommand handler --- */
-
-  return (findcmd(cmdtab, argv[0])->cmd(argc, argv));
-
-#undef f_bogus
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-bin.c b/ec-bin.c
deleted file mode 100644 (file)
index 8ba7354..0000000
--- a/ec-bin.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Arithmetic for elliptic curves over binary fields
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/sub.h>
-
-#include "ec.h"
-#include "ec-guts.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-static const ec_ops ec_binops, ec_binprojops;
-
-static ec *ecneg(ec_curve *c, ec *d, const ec *p)
-{
-  EC_COPY(d, p);
-  if (d->x)
-    d->y = F_ADD(c->f, d->y, d->y, d->x);
-  return (d);
-}
-
-static ec *ecprojneg(ec_curve *c, ec *d, const ec *p)
-{
-  EC_COPY(d, p);
-  if (d->x) {
-    mp *t = F_MUL(c->f, MP_NEW, d->x, d->z);
-    d->y = F_ADD(c->f, d->y, d->y, t);
-    MP_DROP(t);
-  }
-  return (d);
-}
-
-static ec *ecfind(ec_curve *c, ec *d, mp *x)
-{
-  field *f = c->f;
-  mp *y, *u, *v;
-
-  if (F_ZEROP(f, x))
-    y = F_SQRT(f, MP_NEW, c->b);
-  else {
-    u = F_SQR(f, MP_NEW, x);           /* %$x^2$% */
-    y = F_MUL(f, MP_NEW, u, c->a);     /* %$a x^2$% */
-    y = F_ADD(f, y, y, c->b);          /* %$a x^2 + b$% */
-    v = F_MUL(f, MP_NEW, u, x);                /* %$x^3$% */
-    y = F_ADD(f, y, y, v);             /* %$A = x^3 + a x^2 + b$% */
-    if (!F_ZEROP(f, y)) {
-      u = F_INV(f, u, u);              /* %$x^{-2}$% */
-      v = F_MUL(f, v, u, y);       /* %$B = A x^{-2} = x + a + b x^{-2}$% */
-      y = F_QUADSOLVE(f, y, v);                /* %$z^2 + z = B$% */
-      if (y) y = F_MUL(f, y, y, x);    /* %$y = z x$% */
-    }
-    MP_DROP(u);
-    MP_DROP(v);
-  }
-  if (!y) return (0);
-  EC_DESTROY(d);
-  d->x = MP_COPY(x);
-  d->y = y;
-  d->z = MP_COPY(f->one);
-  return (d);
-}
-
-static ec *ecdbl(ec_curve *c, ec *d, const ec *a)
-{
-  if (EC_ATINF(a) || F_ZEROP(c->f, a->x))
-    EC_SETINF(d);
-  else {
-    field *f = c->f;
-    mp *lambda;
-    mp *dx, *dy;
-
-    dx = F_INV(f, MP_NEW, a->x);       /* %$x^{-1}$% */
-    dy = F_MUL(f, MP_NEW, dx, a->y);   /* %$y/x$% */
-    lambda = F_ADD(f, dy, dy, a->x);   /* %$\lambda = x + y/x$% */
-
-    dx = F_SQR(f, dx, lambda);         /* %$\lambda^2$% */
-    dx = F_ADD(f, dx, dx, lambda);     /* %$\lambda^2 + \lambda$% */
-    dx = F_ADD(f, dx, dx, c->a);       /* %$x' = a + \lambda^2 + \lambda$% */
-
-    dy = F_ADD(f, MP_NEW, a->x, dx);   /* %$ x + x' $% */
-    dy = F_MUL(f, dy, dy, lambda);     /* %$ (x + x') \lambda$% */
-    dy = F_ADD(f, dy, dy, a->y);       /* %$ (x + x') \lambda + y$% */
-    dy = F_ADD(f, dy, dy, dx);     /* %$ y' = (x + x') \lambda + y + x'$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = 0;
-    MP_DROP(lambda);
-  }
-  return (d);
-}
-
-static ec *ecprojdbl(ec_curve *c, ec *d, const ec *a)
-{
-  if (EC_ATINF(a) || F_ZEROP(c->f, a->x))
-    EC_SETINF(d);
-  else {
-    field *f = c->f;
-    ecctx_bin *cc = (ecctx_bin *)c;
-    mp *dx, *dy, *dz, *u, *v;
-
-    dy = F_SQR(f, MP_NEW, a->z);       /* %$z^2$% */
-    dx = F_MUL(f, MP_NEW, dy, cc->bb); /* %$c z^2$% */
-    dx = F_ADD(f, dx, dx, a->x);       /* %$x + c z^2$% */
-    dz = F_SQR(f, MP_NEW, dx);         /* %$(x + c z^2)^2$% */
-    dx = F_SQR(f, dx, dz);             /* %$x' = (x + c z^2)^4$% */
-
-    dz = F_MUL(f, dz, dy, a->x);       /* %$z' = x z^2$% */
-
-    dy = F_SQR(f, dy, a->x);           /* %$x^2$% */
-    u = F_MUL(f, MP_NEW, a->y, a->z);  /* %$y z$% */
-    u = F_ADD(f, u, u, dz);            /* %$z' + y z$% */
-    u = F_ADD(f, u, u, dy);            /* %$u = z' + x^2 + y z$% */
-
-    v = F_SQR(f, MP_NEW, dy);          /* %$x^4$% */
-    dy = F_MUL(f, dy, v, dz);          /* %$x^4 z'$% */
-    v = F_MUL(f, v, u, dx);            /* %$u x'$% */
-    dy = F_ADD(f, dy, dy, v);          /* %$y' = x^4 z' + u x'$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = dz;
-    MP_DROP(u);
-    MP_DROP(v);
-  }
-  return (d);
-}
-
-static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b)
-{
-  if (a == b)
-    ecdbl(c, d, a);
-  else if (EC_ATINF(a))
-    EC_COPY(d, b);
-  else if (EC_ATINF(b))
-    EC_COPY(d, a);
-  else {
-    field *f = c->f;
-    mp *lambda;
-    mp *dx, *dy;
-
-    if (!MP_EQ(a->x, b->x)) {
-      dx = F_ADD(f, MP_NEW, a->x, b->x); /* %$x_0 + x_1$% */
-      dy = F_INV(f, MP_NEW, dx);       /* %$(x_0 + x_1)^{-1}$% */
-      dx = F_ADD(f, dx, a->y, b->y);   /* %$y_0 + y_1$% */
-      lambda = F_MUL(f, MP_NEW, dy, dx);
-                                 /* %$\lambda = (y_0 + y_1)/(x_0 + x_1)$% */
-
-      dx = F_SQR(f, dx, lambda);       /* %$\lambda^2$% */
-      dx = F_ADD(f, dx, dx, lambda);   /* %$\lambda^2 + \lambda$% */
-      dx = F_ADD(f, dx, dx, c->a);     /* %$a + \lambda^2 + \lambda$% */
-      dx = F_ADD(f, dx, dx, a->x);    /* %$a + \lambda^2 + \lambda + x_0$% */
-      dx = F_ADD(f, dx, dx, b->x);
-                          /* %$x' = a + \lambda^2 + \lambda + x_0 + x_1$% */
-    } else if (!MP_EQ(a->y, b->y) || F_ZEROP(f, a->x)) {
-      EC_SETINF(d);
-      return (d);
-    } else {
-      dx = F_INV(f, MP_NEW, a->x);     /* %$x^{-1}$% */
-      dy = F_MUL(f, MP_NEW, dx, a->y); /* %$y/x$% */
-      lambda = F_ADD(f, dy, dy, a->x); /* %$\lambda = x + y/x$% */
-
-      dx = F_SQR(f, dx, lambda);       /* %$\lambda^2$% */
-      dx = F_ADD(f, dx, dx, lambda);   /* %$\lambda^2 + \lambda$% */
-      dx = F_ADD(f, dx, dx, c->a);    /* %$x' = a + \lambda^2 + \lambda$% */
-      dy = MP_NEW;
-    }
-
-    dy = F_ADD(f, dy, a->x, dx);       /* %$ x + x' $% */
-    dy = F_MUL(f, dy, dy, lambda);     /* %$ (x + x') \lambda$% */
-    dy = F_ADD(f, dy, dy, a->y);       /* %$ (x + x') \lambda + y$% */
-    dy = F_ADD(f, dy, dy, dx);     /* %$ y' = (x + x') \lambda + y + x'$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = 0;
-    MP_DROP(lambda);
-  }
-  return (d);
-}
-
-static ec *ecprojadd(ec_curve *c, ec *d, const ec *a, const ec *b)
-{
-  if (a == b)
-    c->ops->dbl(c, d, a);
-  else if (EC_ATINF(a))
-    EC_COPY(d, b);
-  else if (EC_ATINF(b))
-    EC_COPY(d, a);
-  else {
-    field *f = c->f;
-    mp *dx, *dy, *dz, *u, *uu, *v, *t, *s, *ss, *r, *w, *l;
-
-    dz = F_SQR(f, MP_NEW, b->z);       /* %$z_1^2$% */
-    u = F_MUL(f, MP_NEW, dz, a->x);    /* %$u_0 = x_0 z_1^2$% */
-    t = F_MUL(f, MP_NEW, dz, b->z);    /* %$z_1^3$% */
-    s = F_MUL(f, MP_NEW, t, a->y);     /* %$s_0 = y_0 z_1^3$% */
-
-    dz = F_SQR(f, dz, a->z);           /* %$z_0^2$% */
-    uu = F_MUL(f, MP_NEW, dz, b->x);   /* %$u_1 = x_1 z_0^2$% */
-    t = F_MUL(f, t, dz, a->z);         /* %$z_0^3$% */
-    ss = F_MUL(f, MP_NEW, t, b->y);    /* %$s_1 = y_1 z_0^3$% */
-
-    w = F_ADD(f, u, u, uu);            /* %$r = u_0 + u_1$% */
-    r = F_ADD(f, s, s, ss);            /* %$w = s_0 + s_1$% */
-    if (F_ZEROP(f, w)) {
-      MP_DROP(w);
-      MP_DROP(uu);
-      MP_DROP(ss);
-      MP_DROP(t);
-      MP_DROP(dz);
-      if (F_ZEROP(f, r)) {
-       MP_DROP(r);
-       return (c->ops->dbl(c, d, a));
-      } else {
-       MP_DROP(r);
-       EC_SETINF(d);
-       return (d);
-      }
-    }
-
-    l = F_MUL(f, t, a->z, w);          /* %$l = z_0 w$% */
-
-    dz = F_MUL(f, dz, l, b->z);                /* %$z' = l z_1$% */
-
-    ss = F_MUL(f, ss, r, b->x);                /* %$r x_1$% */
-    t = F_MUL(f, uu, l, b->y);         /* %$l y_1$% */
-    v = F_ADD(f, ss, ss, t);           /* %$v = r x_1 + l y_1$% */
-
-    t = F_ADD(f, t, r, dz);            /* %$t = r + z'$% */
-
-    uu = F_SQR(f, MP_NEW, dz);         /* %$z'^2$% */
-    dx = F_MUL(f, MP_NEW, uu, c->a);   /* %$a z'^2$% */
-    uu = F_MUL(f, uu, t, r);           /* %$t r$% */
-    dx = F_ADD(f, dx, dx, uu);         /* %$a z'^2 + t r$% */
-    r = F_SQR(f, r, w);                        /* %$w^2$% */
-    uu = F_MUL(f, uu, r, w);           /* %$w^3$% */
-    dx = F_ADD(f, dx, dx, uu);         /* %$x' = a z'^2 + t r + w^3$% */
-
-    r = F_SQR(f, r, l);                        /* %$l^2$% */
-    dy = F_MUL(f, uu, v, r);           /* %$v l^2$% */
-    l = F_MUL(f, l, t, dx);            /* %$t x'$% */
-    dy = F_ADD(f, dy, dy, l);          /* %$y' = t x' + v l^2$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = dz;
-    MP_DROP(l);
-    MP_DROP(r);
-    MP_DROP(w);
-    MP_DROP(t);
-    MP_DROP(v);
-  }
-  return (d);
-}
-
-static int eccheck(ec_curve *c, const ec *p)
-{
-  field *f = c->f;
-  int rc;
-  mp *u, *v;
-
-  if (EC_ATINF(p)) return (0);
-  v = F_SQR(f, MP_NEW, p->x);
-  u = F_MUL(f, MP_NEW, v, p->x);
-  v = F_MUL(f, v, v, c->a);
-  u = F_ADD(f, u, u, v);
-  u = F_ADD(f, u, u, c->b);
-  v = F_MUL(f, v, p->x, p->y);
-  u = F_ADD(f, u, u, v);
-  v = F_SQR(f, v, p->y);
-  u = F_ADD(f, u, u, v);
-  rc = F_ZEROP(f, u) ? 0 : -1;
-  mp_drop(u);
-  mp_drop(v);
-  return (rc);
-}
-
-static int ecprojcheck(ec_curve *c, const ec *p)
-{
-  ec t = EC_INIT;
-  int rc;
-
-  c->ops->fix(c, &t, p);
-  rc = eccheck(c, &t);
-  EC_DESTROY(&t);
-  return (rc);
-}
-
-static void ecdestroy(ec_curve *c)
-{
-  ecctx_bin *cc = (ecctx_bin *)c;
-  MP_DROP(cc->c.a);
-  MP_DROP(cc->c.b);
-  if (cc->bb) MP_DROP(cc->bb);
-  DESTROY(cc);
-}
-
-/* --- @ec_bin@, @ec_binproj@ --- *
- *
- * Arguments:  @field *f@ = the underlying field for this elliptic curve
- *             @mp *a, *b@ = the coefficients for this curve
- *
- * Returns:    A pointer to the curve, or null.
- *
- * Use:                Creates a curve structure for an elliptic curve defined over
- *             a binary field.  The @binproj@ variant uses projective
- *             coordinates, which can be a win.
- */
-
-ec_curve *ec_bin(field *f, mp *a, mp *b)
-{
-  ecctx_bin *cc = CREATE(ecctx_bin);
-  cc->c.ops = &ec_binops;
-  cc->c.f = f;
-  cc->c.a = F_IN(f, MP_NEW, a);
-  cc->c.b = F_IN(f, MP_NEW, b);
-  cc->bb = 0;
-  return (&cc->c);
-}
-
-ec_curve *ec_binproj(field *f, mp *a, mp *b)
-{
-  ecctx_bin *cc = CREATE(ecctx_bin);
-  int i;
-  mp *c, *d;
-
-  cc->c.ops = &ec_binprojops;
-  cc->c.f = f;
-  cc->c.a = F_IN(f, MP_NEW, a);
-  cc->c.b = F_IN(f, MP_NEW, b);
-
-  c = MP_COPY(cc->c.b);
-  for (i = 0; i < f->nbits - 2; i++)
-    c = F_SQR(f, c, c);
-  d = F_SQR(f, MP_NEW, c); d = F_SQR(f, d, d);
-  if (!MP_EQ(d, cc->c.b)) {
-    MP_DROP(c);
-    MP_DROP(d);
-    MP_DROP(cc->c.a);
-    MP_DROP(cc->c.b);
-    DESTROY(cc);
-    return (0);
-  }
-  cc->bb = c;
-  MP_DROP(d);
-  return (&cc->c);
-}
-
-static const ec_ops ec_binops = {
-  "bin",
-  ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix,
-  ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck
-};
-
-static const ec_ops ec_binprojops = {
-  "binproj",
-  ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix,
-  ecfind, ecprojneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck
-};
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
-
-int main(int argc, char *argv[])
-{
-  field *f;
-  ec_curve *c;
-  ec g = EC_INIT, d = EC_INIT;
-  mp *p, *a, *b, *r, *beta;
-  int i, n = argc == 1 ? 1 : atoi(argv[1]);
-
-  printf("ec-bin: ");
-  fflush(stdout);
-  a = MP(0x7ffffffffffffffffffffffffffffffffffffffff);
-  b = MP(0x6645f3cacf1638e139c6cd13ef61734fbc9e3d9fb);
-  p = MP(0x800000000000000000000000000000000000000c9);
-  beta = MP(0x715169c109c612e390d347c748342bcd3b02a0bef);
-  r = MP(0x040000000000000000000292fe77e70c12a4234c32);
-
-  f = field_binnorm(p, beta);
-  c = ec_binproj(f, a, b);
-  g.x = MP(0x0311103c17167564ace77ccb09c681f886ba54ee8);
-  g.y = MP(0x333ac13c6447f2e67613bf7009daf98c87bb50c7f);
-
-  for (i = 0; i < n; i++) {
-    ec_mul(c, &d, &g, r);
-    if (EC_ATINF(&d)) {
-      fprintf(stderr, "zero too early\n");
-      return (1);
-    }
-    ec_add(c, &d, &d, &g);
-    if (!EC_ATINF(&d)) {
-      fprintf(stderr, "didn't reach zero\n");
-      MP_EPRINTX("d.x", d.x);
-      MP_EPRINTX("d.y", d.y);
-      return (1);
-    }
-    ec_destroy(&d);
-  }
-
-  ec_destroy(&g);
-  ec_destroycurve(c);
-  F_DESTROY(f);
-  MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r); MP_DROP(beta);
-  assert(!mparena_count(&mparena_global));
-  printf("ok\n");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-exp.c b/ec-exp.c
deleted file mode 100644 (file)
index 2c9a800..0000000
--- a/ec-exp.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Point multiplication for elliptic curves
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "ec.h"
-#include "ec-exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @ec_imul@, @ec_mul@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p@ = pointer to the generator point
- *             @mp *n@ = integer multiplier
- *
- * Returns:    The destination @d@.
- *
- * Use:                Multiplies a point by a scalar, returning %$n p$%.  The
- *             @imul@ variant uses internal representations for argument
- *             and result.
- */
-
-ec *ec_imul(ec_curve *c, ec *d, const ec *p, mp *n)
-{
-  ec t = EC_INIT;
-
-  EC_COPY(&t, p);
-  if (t.x && (n->f & MP_BURN))
-    t.x->f |= MP_BURN;
-  MP_SHRINK(n);
-  EC_SETINF(d);
-  if (MP_ZEROP(n))
-    ;
-  else {
-    if (MP_NEGP(n))
-      EC_NEG(c, &t, &t);
-    if (MP_LEN(n) < EXP_THRESH)
-      EXP_SIMPLE(*d, t, n);
-    else
-      EXP_WINDOW(*d, t, n);
-  }
-  EC_DESTROY(&t);
-  return (d);
-}
-
-ec *ec_mul(ec_curve *c, ec *d, const ec *p, mp *n)
-{
-  EC_IN(c, d, p);
-  ec_imul(c, d, d, n);
-  return (EC_OUT(c, d, d));
-}
-
-/* --- @ec_mmul@, @ec_immul@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec_mulfactor *f@ = pointer to vector of factors
- *             @size_t n@ = number of factors
- *
- * Returns:    The destination @d@.
- *
- * Use:                Does simultaneous point multiplication.  The @immul@ variant
- *             uses internal representations for arguments and result.
- */
-
-#undef EXP_WINSZ
-#define EXP_WINSZ 3
-
-static ec *immul(ec_curve *c, ec *d, ec_mulfactor *f, size_t n)
-{
-  size_t i;
-
-  for (i = 0; i < n; i++) {
-    MP_SHRINK(f[i].exp);
-    if (MP_NEGP(f[i].exp))
-      EC_NEG(c, &f[i].base, &f[i].base);
-    if (f[i].base.x && f[i].exp->f & MP_BURN)
-      f[i].base.x->f |= MP_BURN;
-  }
-  EC_SETINF(d);
-  EXP_SIMUL(*d, f, n);
-  for (i = 0; i < n; i++)
-    EC_DESTROY(&f[i].base);
-  xfree(f);
-  return (d);
-}
-
-ec *ec_immul(ec_curve *c, ec *d, const ec_mulfactor *f, size_t n)
-{
-  ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
-  size_t i;
-
-  for (i = 0; i < n; i++) {
-    EC_CREATE(&ff[i].base);
-    EC_COPY(&ff[i].base, &f[i].base);
-    ff[i].exp = f[i].exp;
-  }
-  return (immul(c, d, ff, n));
-}
-
-ec *ec_mmul(ec_curve *c, ec *d, const ec_mulfactor *f, size_t n)
-{
-  ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
-  size_t i;
-
-  for (i = 0; i < n; i++) {
-    EC_CREATE(&ff[i].base);
-    EC_IN(c, &ff[i].base, &f[i].base);
-    ff[i].exp = f[i].exp;
-  }
-  immul(c, d, ff, n);
-  return (EC_OUT(c, d, d));
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-exp.h b/ec-exp.h
deleted file mode 100644 (file)
index 8ee3154..0000000
--- a/ec-exp.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ec-exp.h,v 1.6 2004/04/08 01:36:15 mdw Exp $
- *
- * Exponentiation operations for elliptic curves
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_EC_EXP_H
-#define CATACOMB_EC_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentation definitions -----------------------------------------*/
-
-#define EXP_TYPE ec
-
-#define EXP_COPY(d, p) do {                                            \
-  (d).x = MP_COPY((p).x);                                              \
-  (d).y = MP_COPY((p).y);                                              \
-  (d).z = (p).z ? MP_COPY((p).z) : MP_NEW;                             \
-} while (0)
-#define EXP_DROP(x) EC_DESTROY(&(x))
-
-#define EXP_MUL(a, x) EC_ADD(c, &(a), &(a), &(x))
-#define EXP_SQR(a) EC_DBL(c, &(a), &(a))
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) do {                                       \
-  EC_CREATE(&(d));                                                     \
-  EC_ADD(c, &(d), &(x), &(y));                                         \
-} while (0)
-#define EXP_SETSQR(d, x) do {                                          \
-  EC_CREATE(&(d));                                                     \
-  EC_DBL(c, &(d), &(x));                                               \
-} while (0)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ec-fetch.c b/ec-fetch.c
deleted file mode 100644 (file)
index 81bfb6c..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ec-fetch.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Key fetching for elliptic curve public and private keys
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "ec-keys.h"
-#include "key.h"
-
-/*----- Key fetching ------------------------------------------------------*/
-
-const key_fetchdef ec_paramfetch[] = {
-  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
-  { 0,         0,                              0,              0 }
-};
-
-const key_fetchdef ec_pubfetch[] = {
-  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
-  { "p",       offsetof(ec_pub, p),            KENC_EC,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-static const key_fetchdef priv[] = {
-  { "x",       offsetof(ec_priv, x),           KENC_MP,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-const key_fetchdef ec_privfetch[] = {
-  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
-  { "p",       offsetof(ec_pub, p),            KENC_EC,        0 },
-  { "private", 0,                              KENC_STRUCT,    priv },
-  { 0,         0,                              0,              0 }
-};
-
-/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- *
- *
- * Arguments:  @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to
- *                     key block to free
- *
- * Returns:    ---
- *
- * Use:                Frees an elliptic curve key block
- */
-
-void ec_paramfree(ec_param *ep)
-{
-  if (ep->ei.c) ec_freeinfo(&ep->ei);
-  xfree(ep->cstr);
-}
-
-void ec_pubfree(ec_pub *ep)
-{
-  if (ep->ei.c) ec_freeinfo(&ep->ei);
-  xfree(ep->cstr);
-  EC_DESTROY(&ep->p);
-}
-
-void ec_privfree(ec_priv *ep)
-{
-  if (ep->ei.c) ec_freeinfo(&ep->ei);
-  xfree(ep->cstr);
-  EC_DESTROY(&ep->p);
-  mp_drop(ep->x);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-gentab.awk b/ec-gentab.awk
deleted file mode 100755 (executable)
index b00300c..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#! /usr/bin/awk -f
-#
-# $Id: ec-gentab.awk,v 1.1 2004/04/01 21:28:41 mdw Exp $
-
-function banner(name,  s, i)
-{
-  s = "/*----- " name " ";
-  while (length(s) < 75) s = s "-";
-  return (s "*/");
-}
-
-function fix(name)
-{
-  gsub(/[^0-9A-Za-z_]+/, "_", name);
-  return (name);
-}
-
-BEGIN {
-  print "/* -*-c-*-";
-  print " *";
-  print " * Table of elliptic curves [generated]";
-  print " */";
-  print "";
-  print "#include \"ectab.h\"";
-  print "";
-  print "#define N(x) (sizeof(x)/sizeof(*x))";
-  print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }";
-  print "#define NOMP { 0, 0, 0, 0, 0 }";
-  print "";
-  print banner("Curve data");
-  print "";
-
-  d_i = 0;
-  name = "";
-}
-
-function putmp(x,  d)
-{
-  if (!(x in data)) {
-    print "curve " name ": missing " x >"/dev/stderr";
-    exit 1;
-  }
-  d = data[x];
-  if (!(d in cache)) {
-    n = "c_" fix(name) "_" x;
-    print "static mpw " n "[] = {";
-    system("./mpdump " d);
-    print "};";
-    print "";
-    cache[d] = n;
-  }
-  mp[x] = cache[d];
-}
-
-function flush()
-{
-  if (name == "") return;
-  print "/* --- Curve " name " --- */";
-  delete mp;
-  print "";
-  putmp("p");
-  if (type == "binnorm") putmp("beta");
-  putmp("a");
-  putmp("b");
-  putmp("r");
-  putmp("h");
-  putmp("gx");
-  putmp("gy");
-  print "static ecdata c_" fix(name) " = {";
-  print "  FTAG_" toupper(type) ",";
-  print "  MP(" mp["p"] "),"
-  if (type == "binnorm")
-    print "  MP(" mp["beta"] "),";
-  else
-    print "  NOMP,";
-  print "  MP(" mp["a"] "),"
-  print "  MP(" mp["b"] "),"
-  print "  MP(" mp["r"] "),"
-  print "  MP(" mp["h"] "),"
-  print "  MP(" mp["gx"] "),"
-  print "  MP(" mp["gy"] ")"
-  print "};";
-  print "";
-  dname[d_i++] = name;
-  d[name] = name;
-  r[name] = "c_" fix(name);
-  name = "";
-}
-
-/^[ \t]*(#|$)/ { next; }
-
-$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; }
-
-$1 == "curve" { flush(); delete data; name = $2; type = $3; next; }
-
-{ data[$1] = $2; next; }
-
-END {
-  flush();
-  print banner("Main table");
-  print "";
-  print "const ecentry ectab[] = {";
-  for (i = 0; i < d_i; i++) {
-    name = dname[i];
-    rname = d[name];
-    if (!rname in r) {
-      print "curve " rname " not found (alias from " name ")" >"/dev/stderr";
-      exit 1;
-    }
-    print "  { \"" name "\", &" r[rname] " },";
-  }
-  print "  { 0, 0 }";
-  print "};"
-  print "";
-  print banner("That's all, folks");
-}
diff --git a/ec-guts.h b/ec-guts.h
deleted file mode 100644 (file)
index fb2b306..0000000
--- a/ec-guts.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Internal structures for built-in elliptic curve types
- *
- * (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.
- */
-
-#ifndef CATACOMB_EC_GUTS_H
-#define CATACOMB_EC_GUTS_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_EC_H
-#  include "ec.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct ecctx_bin {
-  ec_curve c;
-  mp *bb;
-} ecctx_bin;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ec-info.c b/ec-info.c
deleted file mode 100644 (file)
index 6fcef88..0000000
--- a/ec-info.c
+++ /dev/null
@@ -1,781 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Elliptic curve information management
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/darray.h>
-
-#include "ec.h"
-#include "ectab.h"
-#include "gf.h"
-#include "keysz.h"
-#include "mpbarrett.h"
-#include "pgen.h"
-#include "primeiter.h"
-#include "mprand.h"
-#include "mpint.h"
-#include "rabin.h"
-
-/*----- Embedding degree checking -----------------------------------------*
- *
- * Let %$q = p^m$% be a prime power, and let %$E$% be an elliptic curve over
- * %$\gf{q}$% with %$n = \#E(\gf{q}) = r h$% where %$r$% is prime.  Then the
- * Weil and Tate pairings can be used to map %$r$%-torsion points on
- * %$E(\gf{q})$% onto the %$r$%-th roots of unity (i.e., the order-%$r$%
- * subgroup) in an extension field %$\gf{p^k}$% of %$\gf{p}$% (%%\emph{not}%%
- * of %$\gf{q}$% -- see [Hitt]).  We call the smallest such %$k$% the
- * %%\emph{embedding degree}%% of the curve %$E$%.  The
- * Menezes-Okamoto-Vanstone (MOV) attack solves the discrete log problem in
- * %$E(\gf{q})$% by using the pairing and then applying index calculus to
- * extract a discrete log in %$\gf{p^k}$%; obviously this only works if %$k$%
- * is small enough.
- *
- * The usual check, suggested in, e.g., [P1363] or [SEC1], only covers
- * extension fields %$\gf{q^\ell}$% of %$\gf{q}$%, which is fine when %$q$%
- * is prime, but when we're dealing with binary fields it works less well.
- * Indeed, as [Hitt] demonstrates, the embedding field can actually be
- * %%\emph{smaller}%% than %$\gf{q}$%, and choosing %$m$% prime doesn't help
- * (even though I previously thought it did).
- *
- * Define the %%\emph{embedding degree bound}%% %$B$% to be the smallest
- * %$i$% such that discrete logs in %$\gf{p^i}$% are about as hard as in
- * %$E(\gf{q})$%.
- *
- * The embedding group is a subgroup of the multiplicative group
- * %$\gf{p^k}^*$% which contains %$p^k - 1$% elements; therefore we must have
- * %$r \mid p^k - 1$%, or, equivalently, %$p^k \equiv 1 \pmod{r}$%.
- *
- * The recommended checking procedure, e.g., in [P1363], is just to check
- * %$q^i \not\equiv 1 \pmod{r}$% for each %$0 < i < B$%.  This is fast when
- * you only consider extension fields of %$\gf{q}$%, since %$B$% is at most
- * about 27.  However, as noted above, this is inadequate when %$q$% is a
- * prime power, and we must check all the extension fields of %$p$%.  Now
- * %$B$% can be about 15000, which is rather scarier -- we need a better
- * algorithm.
- *
- * As noted, we must have %$p^k \equiv 1 \pmod{r}$%; but by minimality of
- * %$k$%, we must have %$p^i \not\equiv 1 \pmod{r}$% for %$0 < i < k$%.
- * Therefore %$p$% generates an order-%$k$% subgroup in %$\gf{r}^*$%, so we
- * must have %$k \mid r - 1$%.
- *
- * Of course, factoring %$r - 1$% is a mug's game; but we're not interested
- * in the complete factorization -- just the %$B$%-smooth portion.  An
- * algorithm suggests itself:
- *
- *   1. Extract the factors of %$r - 1$% which are less than %$B$%.
- *
- *   2. For each divisor %$d$% of %$r - 1$% less than %$B$% (which we can
- *     construct using this factorization), make sure that
- *      %$p^d \not\equiv 1 \pmod{r}$%.
- *
- * This takes a little while but not ever-so long.
- *
- * This is enough for cryptosystems based on the computational Diffie-
- * Hellman problem to be secure.  However, it's %%\emph{not}%% enough for the
- * %%\emph{decisional}%% Diffie-Hellman problem to be hard; it appears we
- * also need to hope that there aren't any suitable distortion maps with
- * which one can solve the DDH problem.  I don't know how to check for those
- * at the moment.
- *
- * We'll take the subgroup order as indicative of the security level actually
- * wanted.  Then, to ensure security against the MOV attack, we must ensure
- * that the embedding degree is sufficiently large that discrete logs in
- * %$\gf{q^m}$% are at least as hard as discrete logs over the curve.
- *
- * We actually allow a small amount of slop in the conversions, in order to
- * let people pick nice round numbers for their key lengths.
- *
- * References:
- *
- * [Hitt]  L. Hitt, On an improved definition of embedding degree;
- *         http://eprint.iacr.org/2006/415
- *
- * [P1363] IEEE 1363-2000: Standard Specifications for Public Key
- *         Cryptography; http://grouper.ieee.org/groups/1363/P1363/index.html
- *
- * [SEC1]  SEC 1: Elliptic Curve Cryptography;
- *         http://www.secg.org/download/aid-385/sec1_final.pdf
- */
-
-/* --- @movcheck@ --- *
- *
- * Arguments:  @mp *r@ = curve subgroup order
- *             @mp *p@ = field characteristic
- *             @unsigned long B@ = embedding degree bound
- *
- * Returns:    Zero if OK, nonzero if an embedding was found.
- *
- * Use:                Checks a curve for embeddings with degree less than the
- *             stated bound %$B$%.  See above for explanation and a
- *             description of the algorithm.
- */
-
-static int movcheck(mp *r, mp *p, unsigned long B)
-{
-  mpmont mm;
-  mp *r1, *pp = MP_NEW, *t = MP_NEW, *u = MP_NEW, *v = MP_NEW, *tt;
-  struct factor {
-    unsigned long f;
-    unsigned c, e;
-  };
-  DA_DECL(factor_v, struct factor);
-  factor_v fv = DA_INIT;
-  size_t nf;
-  struct factor *ff;
-  primeiter pi;
-  mp *BB;
-  unsigned long d, f;
-  unsigned i, j;
-  int rc = 0;
-
-  /* --- Special case --- *
-   *
-   * If %$r = 2$% then (a) Montgomery reduction won't work, and (b) we have
-   * no security worth checking anyway.  Otherwise we're guaranteed that
-   * %$r$% is a prime, so it must be odd.
-   */
-
-  if (MP_EQ(r, MP_TWO))
-    return (0);
-
-  /* --- First factor the %$B%-smooth portion of %$r - 1$% --- *
-   *
-   * We can generate prime numbers up to %$B$% efficiently, so trial division
-   * it is.
-   */
-
-  BB = mp_fromulong(MP_NEW, B);
-  r1 = mp_sub(MP_NEW, r, MP_ONE);
-  primeiter_create(&pi, 0);
-  for (;;) {
-    pp = primeiter_next(&pi, pp);
-    if (MP_CMP(pp, >, BB))
-      break;
-    mp_div(&u, &v, r1, pp);
-    if (!MP_ZEROP(v))
-      continue;
-    i = 0;
-    do {
-      tt = r1; r1 = u; u = tt; i++;
-      mp_div(&u, &v, r1, pp);
-    } while (MP_ZEROP(v));
-    DA_ENSURE(&fv, 1);
-    DA_UNSAFE_EXTEND(&fv, 1);
-    DA_LAST(&fv).f = mp_toulong(pp);
-    DA_LAST(&fv).e = i;
-    DA_LAST(&fv).c = 0;
-  }
-  MP_DROP(BB); MP_DROP(pp); primeiter_destroy(&pi);
-  nf = DA_LEN(&fv); ff = DA(&fv);
-
-  /* --- Now generate divisors of %$r - 1$% less than %$B$% --- *
-   *
-   * For each divisor %$d$%, check whether %$p^d \equiv 1 \pmod{r}$%.
-   */
-
-  mpmont_create(&mm, r);
-  u = mpmont_mul(&mm, u, p, mm.r2);
-  for (;;) {
-
-    /* --- Construct the divisor --- */
-
-    d = 1;
-    for (i = 0; i < nf; i++) {
-      f = ff[i].f; j = ff[i].c; if (!j) continue;
-      for (;;) {
-       if (f >= (B + d - 1)/d) goto toobig;
-       if (j & 1) d *= f;
-       j >>= 1; if (!j) break;
-       f *= f;
-      }
-    }
-    v = mp_fromulong(v, d);
-
-    /* --- Compute %$p^k \bmod r$% and check --- */
-
-    t = mpmont_expr(&mm, t, u, v);
-    if (MP_EQ(t, mm.r)) {
-      rc = -1;
-      break;
-    }
-
-    /* --- Step the divisors along --- */
-
-  toobig:
-    for (i = 0; i < nf; i++) {
-      if (ff[i].c < ff[i].e) {
-       ff[i].c++;
-       goto more;
-      }
-      ff[i].c = 0;
-    }
-    break;
-  more:;
-  }
-
-  /* --- Clear away the debris --- */
-
-  mpmont_destroy(&mm);
-  MP_DROP(t); MP_DROP(u); MP_DROP(v); MP_DROP(r1);
-  DA_DESTROY(&fv);
-  return (rc);
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @ec_curveparse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *
- * Returns:    Elliptic curve pointer if OK, or null.
- *
- * Use:                Parses an elliptic curve description, which has the form
- *
- *               * a field description
- *               * an optional `;'
- *               * `prime', `primeproj', `bin', or `binproj'
- *               * an optional `:'
- *               * the %$a$% parameter
- *               * an optional `,'
- *               * the %$b$% parameter
- */
-
-ec_curve *ec_curveparse(qd_parse *qd)
-{
-  mp *a = MP_NEW, *b = MP_NEW;
-  ec_curve *c;
-  field *f;
-
-  if ((f = field_parse(qd)) == 0) goto fail;
-  qd_delim(qd, ';');
-  switch (qd_enum(qd, "prime,primeproj,bin,binproj")) {
-    case 0:
-      if (F_TYPE(f) != FTY_PRIME) {
-       qd->e = "field not prime";
-       goto fail;
-      }
-      qd_delim(qd, ':');
-      if ((a = qd_getmp(qd)) == 0) goto fail;
-      qd_delim(qd, ',');
-      if ((b = qd_getmp(qd)) == 0) goto fail;
-      c = ec_prime(f, a, b);
-      break;
-    case 1:
-      if (F_TYPE(f) != FTY_PRIME) {
-       qd->e = "field not prime";
-       goto fail;
-      }
-      qd_delim(qd, ':');
-      if ((a = qd_getmp(qd)) == 0) goto fail;
-      qd_delim(qd, ',');
-      if ((b = qd_getmp(qd)) == 0) goto fail;
-      c = ec_primeproj(f, a, b);
-      break;
-    case 2:
-      if (F_TYPE(f) != FTY_BINARY) {
-       qd->e = "field not binary";
-       goto fail;
-      }
-      qd_delim(qd, ':');
-      if ((a = qd_getmp(qd)) == 0) goto fail;
-      qd_delim(qd, ',');
-      if ((b = qd_getmp(qd)) == 0) goto fail;
-      c = ec_bin(f, a, b);
-      break;
-    case 3:
-      if (F_TYPE(f) != FTY_BINARY) {
-       qd->e = "field not binary";
-       goto fail;
-      }
-      qd_delim(qd, ':');
-      if ((a = qd_getmp(qd)) == 0) goto fail;
-      qd_delim(qd, ',');
-      if ((b = qd_getmp(qd)) == 0) goto fail;
-      c = ec_binproj(f, a, b);
-      break;
-    default:
-      goto fail;
-  }
-  if (!c) {
-    qd->e = "bad curve parameters";
-    goto fail;
-  }
-  if (a) MP_DROP(a);
-  if (b) MP_DROP(b);
-  return (c);
-
-fail:
-  if (f) F_DESTROY(f);
-  if (a) MP_DROP(a);
-  if (b) MP_DROP(b);
-  return (0);
-}
-
-/* --- @ec_ptparse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *             @ec *p@ = where to put the point
- *
- * Returns:    The point address, or null.
- *
- * Use:                Parses an elliptic curve point.  This has the form
- *
- *               * %$x$%-coordinate
- *               * optional `,'
- *               * %$y$%-coordinate
- */
-
-ec *ec_ptparse(qd_parse *qd, ec *p)
-{
-  mp *x = MP_NEW, *y = MP_NEW;
-
-  if (qd_enum(qd, "inf") >= 0) {
-    EC_SETINF(p);
-    return (p);
-  }
-  if ((x = qd_getmp(qd)) == 0) goto fail;
-  qd_delim(qd, ',');
-  if ((y = qd_getmp(qd)) == 0) goto fail;
-  EC_DESTROY(p);
-  p->x = x;
-  p->y = y;
-  p->z = 0;
-  return (p);
-
-fail:
-  if (x) MP_DROP(x);
-  if (y) MP_DROP(y);
-  return (0);
-}
-
-/* --- @ec_infofromdata@ --- *
- *
- * Arguments:  @ec_info *ei@ = where to write the information
- *             @ecdata *ed@ = raw data
- *
- * Returns:    ---
- *
- * Use:                Loads elliptic curve information about one of the standard
- *             curves.
- */
-
-void ec_infofromdata(ec_info *ei, ecdata *ed)
-{
-  field *f;
-
-  switch (ed->ftag) {
-    case FTAG_PRIME:
-      f = field_prime(&ed->p);
-      ei->c = ec_primeproj(f, &ed->a, &ed->b);
-      break;
-    case FTAG_NICEPRIME:
-      f = field_niceprime(&ed->p);
-      ei->c = ec_primeproj(f, &ed->a, &ed->b);
-      break;
-    case FTAG_BINPOLY:
-      f = field_binpoly(&ed->p);
-      ei->c = ec_binproj(f, &ed->a, &ed->b);
-      break;
-    case FTAG_BINNORM:
-      f = field_binnorm(&ed->p, &ed->beta);
-      ei->c = ec_binproj(f, &ed->a, &ed->b);
-      break;
-    default:
-      abort();
-  }
-
-  assert(f); assert(ei->c);
-  EC_CREATE(&ei->g); ei->g.x = &ed->gx; ei->g.y = &ed->gy; ei->g.z = 0;
-  ei->r = &ed->r; ei->h = &ed->h;
-}
-
-/* --- @ec_infoparse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *             @ec_info *ei@ = curve information block, currently
- *                     uninitialized
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Parses an elliptic curve information string, and stores the
- *             information in @ei@.  This is either the name of a standard
- *             curve, or it has the form
- *
- *               * elliptic curve description
- *               * optional `;'
- *               * common point
- *               * optional `:'
- *               * group order
- *               * optional `*'
- *               * cofactor
- */
-
-int ec_infoparse(qd_parse *qd, ec_info *ei)
-{
-  ec_curve *c = 0;
-  field *f;
-  ec g = EC_INIT;
-  const ecentry *ee;
-  mp *r = MP_NEW, *h = MP_NEW;
-
-  for (ee = ectab; ee->name; ee++) {
-    if (qd_enum(qd, ee->name) >= 0) {
-      ec_infofromdata(ei, ee->data);
-      goto found;
-    }
-  }
-
-  if ((c = ec_curveparse(qd)) == 0) goto fail;
-  qd_delim(qd, ';'); if (!ec_ptparse(qd, &g)) goto fail;
-  qd_delim(qd, ':'); if ((r = qd_getmp(qd)) == 0) goto fail;
-  qd_delim(qd, '*'); if ((h = qd_getmp(qd)) == 0) goto fail;
-  ei->c = c; ei->g = g; ei->r = r; ei->h = h;
-
-found:
-  return (0);
-
-fail:
-  EC_DESTROY(&g);
-  if (r) MP_DROP(r);
-  if (h) MP_DROP(h);
-  if (c) { f = c->f; ec_destroycurve(c); F_DESTROY(f); }
-  return (-1);
-}
-
-/* --- @ec_getinfo@ --- *
- *
- * Arguments:  @ec_info *ei@ = where to write the information
- *             @const char *p@ = string describing a curve
- *
- * Returns:    Null on success, or a pointer to an error message.
- *
- * Use:                Parses out information about a curve.  The string is either a
- *             standard curve name, or a curve info string.
- */
-
-const char *ec_getinfo(ec_info *ei, const char *p)
-{
-  qd_parse qd;
-
-  qd.p = p;
-  qd.e = 0;
-  if (ec_infoparse(&qd, ei))
-    return (qd.e);
-  if (!qd_eofp(&qd)) {
-    ec_freeinfo(ei);
-    return ("junk found at end of string");
-  }
-  return (0);
-}
-
-/* --- @ec_sameinfop@ --- *
- *
- * Arguments:  @ec_info *ei, *ej@ = two elliptic curve parameter sets
- *
- * Returns:    Nonzero if the curves are identical (not just isomorphic).
- *
- * Use:                Checks for sameness of curve parameters.
- */
-
-int ec_sameinfop(ec_info *ei, ec_info *ej)
-{
-  return (ec_samep(ei->c, ej->c) &&
-         MP_EQ(ei->r, ej->r) && MP_EQ(ei->h, ej->h) &&
-         EC_EQ(&ei->g, &ej->g));
-}
-
-/* --- @ec_freeinfo@ --- *
- *
- * Arguments:  @ec_info *ei@ = elliptic curve information block to free
- *
- * Returns:    ---
- *
- * Use:                Frees the information block.
- */
-
-void ec_freeinfo(ec_info *ei)
-{
-  field *f;
-
-  EC_DESTROY(&ei->g);
-  MP_DROP(ei->r);
-  MP_DROP(ei->h);
-  f = ei->c->f; ec_destroycurve(ei->c); F_DESTROY(f);
-}
-
-/* --- @ec_checkinfo@ --- *
- *
- * Arguments:  @const ec_info *ei@ = elliptic curve information block
- *
- * Returns:    Null if OK, or pointer to error message.
- *
- * Use:                Checks an elliptic curve according to the rules in SEC1.
- */
-
-static const char *gencheck(const ec_info *ei, grand *gr, mp *q, mp *ch)
-{
-  ec_curve *c = ei->c;
-  unsigned long qmbits, rbits, cbits, B;
-  mp *qq;
-  mp *nn;
-  mp *x, *y;
-  ec p;
-  int rc;
-
-  /* --- Check curve isn't anomalous --- */
-
-  if (MP_EQ(ei->r, q)) return ("curve is anomalous");
-
-  /* --- Check %$G \in E \setminus \{ 0 \}$% --- */
-
-  if (EC_ATINF(&ei->g)) return ("generator at infinity");
-  if (ec_check(c, &ei->g)) return ("generator not on curve");
-
-  /* --- Check %$r$% is prime --- */
-
-  if (!pgen_primep(ei->r, gr)) return ("generator order not prime");
-
-  /* --- Check that the cofactor is correct --- *
-   *
-   * Let %$q$% be the size of the field, and let %$n = h r = \#E(\gf{q})$% be
-   * the number of %$\gf{q}$%-rational points on our curve.  Hasse's theorem
-   * tells us that
-   *
-   *   %$|q + 1 - n| \le 2\sqrt{q}$%
-   *
-   * or, if we square both sides,
-   *
-   *   %$(q + 1 - n)^2 \le 4 q$%.
-   *
-   * We'd like the cofactor to be uniquely determined by this equation, which
-   * is possible as long as it's not too big.  (If it is, we have to mess
-   * about with Weil pairings, which is no fun.)  For this, we need the
-   * following inequalities:
-   *
-   *   * %$A = (q + 1 - n)^2 \le 4 q$% (both lower and upper bounds from
-   *    Hasse's theorem);
-   *
-   *   * %$B = (q + 1 - n - r)^2 > 4 q$% (check %$h - 1$% isn't possible);
-   *    and
-   *
-   *   * %$C = (q + 1 - n + r)^2 > 4 q$% (check %$h + 1$% isn't possible).
-   */
-
-  rc = 1;
-  qq = mp_add(MP_NEW, q, MP_ONE);
-  nn = mp_mul(MP_NEW, ei->r, ei->h);
-  nn = mp_sub(nn, qq, nn);
-  qq = mp_lsl(qq, q, 2);
-
-  y = mp_sqr(MP_NEW, nn);
-  if (MP_CMP(y, >, qq)) rc = 0;
-
-  x = mp_sub(MP_NEW, nn, ei->r);
-  y = mp_sqr(y, x);
-  if (MP_CMP(y, <=, qq)) rc = 0;
-
-  x = mp_add(x, nn, ei->r);
-  y = mp_sqr(y, x);
-  if (MP_CMP(y, <=, qq)) rc = 0;
-
-  MP_DROP(x);
-  MP_DROP(y);
-  MP_DROP(nn);
-  MP_DROP(qq);
-  if (!rc) return ("incorrect or ambiguous cofactor");
-
-  /* --- Check %$n G = 0$% --- */
-
-  EC_CREATE(&p);
-  ec_mul(c, &p, &ei->g, ei->r);
-  rc = EC_ATINF(&p);
-  EC_DESTROY(&p);
-  if (!rc) return ("incorrect group order");
-
-  /* --- Check the embedding degree --- */
-
-  rbits = mp_bits(ei->r);
-  cbits = mp_bits(ch);
-  qmbits = keysz_todl(keysz_fromec(rbits * 7/8));
-  B = (qmbits + cbits - 1)/cbits;
-  if (movcheck(ei->r, ch, B))
-    return("curve embedding degree too low");
-
-  /* --- Done --- */
-
-  return (0);
-}
-
-static int primeeltp(mp *x, field *f)
-  { return (!MP_NEGP(x) && MP_CMP(x, <, f->m)); }
-
-static const char *primecheck(const ec_info *ei, grand *gr)
-{
-  ec_curve *c = ei->c;
-  field *f = c->f;
-  mp *x, *y;
-  int rc;
-  const char *err;
-
-  /* --- Check %$p$% is an odd prime --- */
-
-  if (!pgen_primep(f->m, gr)) return ("p not prime");
-
-  /* --- Check %$a$%, %$b$%, %$G_x$% and %$G_y$% are in %$[0, p)$% --- */
-
-  if (!primeeltp(c->a, f)) return ("a out of range");
-  if (!primeeltp(c->b, f)) return ("b out of range");
-  if (!primeeltp(ei->g.x, f)) return ("G_x out of range");
-  if (!primeeltp(ei->g.x, f)) return ("G_y out of range");
-
-  /* --- Check %$4 a^3 + 27 b^2 \not\equiv 0 \pmod{p}$% --- */
-
-  x = F_SQR(f, MP_NEW, c->a);
-  x = F_MUL(f, x, x, c->a);
-  x = F_QDL(f, x, x);
-  y = F_SQR(f, MP_NEW, c->b);
-  y = F_TPL(f, y, y);
-  y = F_TPL(f, y, y);
-  y = F_TPL(f, y, y);
-  x = F_ADD(f, x, x, y);
-  rc = F_ZEROP(f, x);
-  MP_DROP(x);
-  MP_DROP(y);
-  if (rc) return ("not an elliptic curve");
-
-  /* --- Now do the general checks --- */
-
-  err = gencheck(ei, gr, f->m, f->m);
-  return (err);
-}
-
-static const char *bincheck(const ec_info *ei, grand *gr)
-{
-  ec_curve *c = ei->c;
-  field *f = c->f;
-  mp *x;
-  int rc;
-  const char *err;
-
-  /* --- Check that %$m$% is prime --- */
-
-  x = mp_fromuint(MP_NEW, f->nbits);
-  rc = pfilt_smallfactor(x);
-  mp_drop(x);
-  if (rc != PGEN_DONE) return ("degree not prime");
-
-  /* --- Check that %$p$% is irreducible --- */
-
-  if (!gf_irreduciblep(f->m)) return ("p not irreducible");
-
-  /* --- Check that %$a, b, G_x, G_y$% have degree less than %$p$% --- */
-
-  if (mp_bits(c->a) > f->nbits) return ("a out of range");
-  if (mp_bits(c->b) > f->nbits) return ("a out of range");
-  if (mp_bits(ei->g.x) > f->nbits) return ("G_x out of range");
-  if (mp_bits(ei->g.y) > f->nbits) return ("G_y out of range");
-
-  /* --- Check that %$b \ne 0$% --- */
-
-  if (F_ZEROP(f, c->b)) return ("b is zero");
-
-  /* --- Now do the general checks --- */
-
-  x = mp_lsl(MP_NEW, MP_ONE, f->nbits);
-  err = gencheck(ei, gr, x, MP_TWO);
-  mp_drop(x);
-  return (err);
-}
-
-const char *ec_checkinfo(const ec_info *ei, grand *gr)
-{
-  switch (F_TYPE(ei->c->f)) {
-    case FTY_PRIME: return (primecheck(ei, gr)); break;
-    case FTY_BINARY: return (bincheck(ei, gr)); break;
-  }
-  return ("unknown curve type");
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include "fibrand.h"
-
-int main(int argc, char *argv[])
-{
-  const ecentry *ee;
-  const char *e;
-  int ok = 1;
-  int i;
-  grand *gr;
-
-  gr = fibrand_create(0);
-  if (argc > 1) {
-    for (i = 1; i < argc; i++) {
-      ec_info ei;
-      if ((e = ec_getinfo(&ei, argv[i])) != 0)
-       fprintf(stderr, "bad curve spec `%s': %s\n", argv[i], e);
-      else {
-       e = ec_checkinfo(&ei, gr);
-       ec_freeinfo(&ei);
-       if (!e)
-         printf("OK %s\n", argv[i]);
-       else {
-         printf("BAD %s: %s\n", argv[i], e);
-         ok = 0;
-       }
-      }
-      assert(mparena_count(MPARENA_GLOBAL) == 0);
-    }
-  } else {
-    fputs("checking standard curves:", stdout);
-    fflush(stdout);
-    for (ee = ectab; ee->name; ee++) {
-      ec_info ei;
-      ec_infofromdata(&ei, ee->data);
-      e = ec_checkinfo(&ei, gr);
-      ec_freeinfo(&ei);
-      if (e) {
-       printf(" [%s fails: %s]", ee->name, e);
-       ok = 0;
-      } else
-       printf(" %s", ee->name);
-      fflush(stdout);
-      assert(mparena_count(MPARENA_GLOBAL) == 0);
-    }
-    fputs(ok ? " ok\n" : " failed\n", stdout);
-  }
-  gr->ops->destroy(gr);
-  return (!ok);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-keys.h b/ec-keys.h
deleted file mode 100644 (file)
index 60db9ff..0000000
--- a/ec-keys.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ec-keys.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Elliptic curve key-fetching
- *
- * (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.
- */
-
-#ifndef CATACOMB_EC_KEYS_H
-#define CATACOMB_EC_KEYS_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_EC_H
-#  include "ec.h"
-#endif
-
-#ifndef CATACOMB_KEY_H
-#  include "key.h"
-#endif
-
-/*----- Key structures ----------------------------------------------------*/
-
-typedef struct ec_param {
-  ec_info ei;                          /* Curve information */
-  char *cstr;                          /* Curve definition string */
-} ec_param;
-
-typedef struct ec_pub {
-  ec_info ei;                          /* Curve information */
-  char *cstr;                          /* Curve definition string */
-  ec p;                                        /* Public point */
-} ec_pub;
-
-typedef struct ec_priv {
-  ec_info ei;                          /* Curve information */
-  char *cstr;                          /* Curve definition string */
-  ec p;                                        /* Public point */
-  mp *x;                               /* Secret exponent */
-} ec_priv;
-
-extern const key_fetchdef ec_paramfetch[];
-#define EC_PARAMFETCHSZ 3
-
-extern const key_fetchdef ec_pubfetch[];
-#define EC_PUBFETCHSZ 4
-
-extern const key_fetchdef ec_privfetch[];
-#define EC_PRIVFETCHSZ 7
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- *
- *
- * Arguments:  @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to
- *                     key block to free
- *
- * Returns:    ---
- *
- * Use:                Frees an elliptic curve key block
- */
-
-extern void ec_paramfree(ec_param */*ep*/);
-extern void ec_pubfree(ec_pub */*ep*/);
-extern void ec_privfree(ec_priv */*ep*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ec-prime.c b/ec-prime.c
deleted file mode 100644 (file)
index 52815e4..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Elliptic curves over prime fields
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/sub.h>
-
-#include "ec.h"
-
-/*----- Simple prime curves -----------------------------------------------*/
-
-static const ec_ops ec_primeops, ec_primeprojops, ec_primeprojxops;
-
-static ec *ecneg(ec_curve *c, ec *d, const ec *p)
-{
-  EC_COPY(d, p);
-  if (d->y)
-    d->y = F_NEG(c->f, d->y, d->y);
-  return (d);
-}
-
-static ec *ecfind(ec_curve *c, ec *d, mp *x)
-{
-  mp *p, *q;
-  field *f = c->f;
-
-  q = F_SQR(f, MP_NEW, x);
-  p = F_MUL(f, MP_NEW, x, q);
-  q = F_MUL(f, q, x, c->a);
-  p = F_ADD(f, p, p, q);
-  p = F_ADD(f, p, p, c->b);
-  MP_DROP(q);
-  p = F_SQRT(f, p, p);
-  if (!p)
-    return (0);
-  EC_DESTROY(d);
-  d->x = MP_COPY(x);
-  d->y = p;
-  d->z = MP_COPY(f->one);
-  return (d);
-}
-
-static ec *ecdbl(ec_curve *c, ec *d, const ec *a)
-{
-  if (EC_ATINF(a) || F_ZEROP(c->f, a->y))
-    EC_SETINF(d);
-  else {
-    field *f = c->f;
-    mp *lambda;
-    mp *dy, *dx;
-
-    dx = F_SQR(f, MP_NEW, a->x);       /* %$x^2$% */
-    dy = F_DBL(f, MP_NEW, a->y);       /* %$2 y$% */
-    dx = F_TPL(f, dx, dx);             /* %$3 x^2$% */
-    dx = F_ADD(f, dx, dx, c->a);       /* %$3 x^2 + A$% */
-    dy = F_INV(f, dy, dy);             /* %$(2 y)^{-1}$% */
-    lambda = F_MUL(f, MP_NEW, dx, dy); /* %$\lambda = (3 x^2 + A)/(2 y)$% */
-
-    dx = F_SQR(f, dx, lambda);         /* %$\lambda^2$% */
-    dy = F_DBL(f, dy, a->x);           /* %$2 x$% */
-    dx = F_SUB(f, dx, dx, dy);         /* %$x' = \lambda^2 - 2 x */
-    dy = F_SUB(f, dy, a->x, dx);       /* %$x - x'$% */
-    dy = F_MUL(f, dy, lambda, dy);     /* %$\lambda (x - x')$% */
-    dy = F_SUB(f, dy, dy, a->y);       /* %$y' = \lambda (x - x') - y$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = 0;
-    MP_DROP(lambda);
-  }
-  return (d);
-}
-
-static ec *ecprojdbl(ec_curve *c, ec *d, const ec *a)
-{
-  if (EC_ATINF(a) || F_ZEROP(c->f, a->y))
-    EC_SETINF(d);
-  else {
-    field *f = c->f;
-    mp *p, *q, *m, *s, *dx, *dy, *dz;
-
-    p = F_SQR(f, MP_NEW, a->z);                /* %$z^2$% */
-    q = F_SQR(f, MP_NEW, p);           /* %$z^4$% */
-    p = F_MUL(f, p, q, c->a);          /* %$A z^4$% */
-    m = F_SQR(f, MP_NEW, a->x);                /* %$x^2$% */
-    m = F_TPL(f, m, m);                        /* %$3 x^2$% */
-    m = F_ADD(f, m, m, p);             /* %$m = 3 x^2 + A z^4$% */
-
-    q = F_DBL(f, q, a->y);             /* %$2 y$% */
-    dz = F_MUL(f, MP_NEW, q, a->z);    /* %$z' = 2 y z$% */
-
-    p = F_SQR(f, p, q);                        /* %$4 y^2$% */
-    s = F_MUL(f, MP_NEW, p, a->x);     /* %$s = 4 x y^2$% */
-    q = F_SQR(f, q, p);                        /* %$16 y^4$% */
-    q = F_HLV(f, q, q);                        /* %$t = 8 y^4$% */
-
-    p = F_DBL(f, p, s);                        /* %$2 s$% */
-    dx = F_SQR(f, MP_NEW, m);          /* %$m^2$% */
-    dx = F_SUB(f, dx, dx, p);          /* %$x' = m^2 - 2 s$% */
-
-    s = F_SUB(f, s, s, dx);            /* %$s - x'$% */
-    dy = F_MUL(f, p, m, s);            /* %$m (s - x')$% */
-    dy = F_SUB(f, dy, dy, q);          /* %$y' = m (s - x') - t$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = dz;
-    MP_DROP(m);
-    MP_DROP(q);
-    MP_DROP(s);
-  }
-  return (d);
-}
-
-static ec *ecprojxdbl(ec_curve *c, ec *d, const ec *a)
-{
-  if (EC_ATINF(a) || F_ZEROP(c->f, a->y))
-    EC_SETINF(d);
-  else {
-    field *f = c->f;
-    mp *p, *q, *m, *s, *dx, *dy, *dz;
-
-    m = F_SQR(f, MP_NEW, a->z);                /* %$z^2$% */
-    p = F_SUB(f, MP_NEW, a->x, m);     /* %$x - z^2$% */
-    q = F_ADD(f, MP_NEW, a->x, m);     /* %$x + z^2$% */
-    m = F_MUL(f, m, p, q);             /* %$x^2 - z^4$% */
-    m = F_TPL(f, m, m);                        /* %$m = 3 x^2 - 3 z^4$% */
-
-    q = F_DBL(f, q, a->y);             /* %$2 y$% */
-    dz = F_MUL(f, MP_NEW, q, a->z);    /* %$z' = 2 y z$% */
-
-    p = F_SQR(f, p, q);                        /* %$4 y^2$% */
-    s = F_MUL(f, MP_NEW, p, a->x);     /* %$s = 4 x y^2$% */
-    q = F_SQR(f, q, p);                        /* %$16 y^4$% */
-    q = F_HLV(f, q, q);                        /* %$t = 8 y^4$% */
-
-    p = F_DBL(f, p, s);                        /* %$2 s$% */
-    dx = F_SQR(f, MP_NEW, m);          /* %$m^2$% */
-    dx = F_SUB(f, dx, dx, p);          /* %$x' = m^2 - 2 s$% */
-
-    s = F_SUB(f, s, s, dx);            /* %$s - x'$% */
-    dy = F_MUL(f, p, m, s);            /* %$m (s - x')$% */
-    dy = F_SUB(f, dy, dy, q);          /* %$y' = m (s - x') - t$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = dz;
-    MP_DROP(m);
-    MP_DROP(q);
-    MP_DROP(s);
-  }
-  return (d);
-}
-
-static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b)
-{
-  if (a == b)
-    ecdbl(c, d, a);
-  else if (EC_ATINF(a))
-    EC_COPY(d, b);
-  else if (EC_ATINF(b))
-    EC_COPY(d, a);
-  else {
-    field *f = c->f;
-    mp *lambda;
-    mp *dy, *dx;
-
-    if (!MP_EQ(a->x, b->x)) {
-      dy = F_SUB(f, MP_NEW, a->y, b->y); /* %$y_0 - y_1$% */
-      dx = F_SUB(f, MP_NEW, a->x, b->x); /* %$x_0 - x_1$% */
-      dx = F_INV(f, dx, dx);           /* %$(x_0 - x_1)^{-1}$% */
-      lambda = F_MUL(f, MP_NEW, dy, dx);
-                                  /* %$\lambda = (y_0 - y1)/(x_0 - x_1)$% */
-    } else if (F_ZEROP(c->f, a->y) || !MP_EQ(a->y, b->y)) {
-      EC_SETINF(d);
-      return (d);
-    } else {
-      dx = F_SQR(f, MP_NEW, a->x);     /* %$x_0^2$% */
-      dx = F_TPL(f, dx, dx);           /* %$3 x_0^2$% */
-      dx = F_ADD(f, dx, dx, c->a);     /* %$3 x_0^2 + A$% */
-      dy = F_DBL(f, MP_NEW, a->y);     /* %$2 y_0$% */
-      dy = F_INV(f, dy, dy);           /* %$(2 y_0)^{-1}$% */
-      lambda = F_MUL(f, MP_NEW, dx, dy);
-                                   /* %$\lambda = (3 x_0^2 + A)/(2 y_0)$% */
-    }
-
-    dx = F_SQR(f, dx, lambda);         /* %$\lambda^2$% */
-    dx = F_SUB(f, dx, dx, a->x);       /* %$\lambda^2 - x_0$% */
-    dx = F_SUB(f, dx, dx, b->x);       /* %$x' = \lambda^2 - x_0 - x_1$% */
-    dy = F_SUB(f, dy, b->x, dx);       /* %$x_1 - x'$% */
-    dy = F_MUL(f, dy, lambda, dy);     /* %$\lambda (x_1 - x')$% */
-    dy = F_SUB(f, dy, dy, b->y);      /* %$y' = \lambda (x_1 - x') - y_1$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = 0;
-    MP_DROP(lambda);
-  }
-  return (d);
-}
-
-static ec *ecprojadd(ec_curve *c, ec *d, const ec *a, const ec *b)
-{
-  if (a == b)
-    c->ops->dbl(c, d, a);
-  else if (EC_ATINF(a))
-    EC_COPY(d, b);
-  else if (EC_ATINF(b))
-    EC_COPY(d, a);
-  else {
-    field *f = c->f;
-    mp *p, *q, *r, *w, *u, *uu, *s, *ss, *dx, *dy, *dz;
-
-    q = F_SQR(f, MP_NEW, a->z);                /* %$z_0^2$% */
-    u = F_MUL(f, MP_NEW, q, b->x);     /* %$u = x_1 z_0^2$% */
-    p = F_MUL(f, MP_NEW, q, b->y);     /* %$y_1 z_0^2$% */
-    s = F_MUL(f, q, p, a->z);          /* %$s = y_1 z_0^3$% */
-
-    q = F_SQR(f, MP_NEW, b->z);                /* %$z_1^2$% */
-    uu = F_MUL(f, MP_NEW, q, a->x);    /* %$uu = x_0 z_1^2$%*/
-    p = F_MUL(f, p, q, a->y);          /* %$y_0 z_1^2$% */
-    ss = F_MUL(f, q, p, b->z);         /* %$ss = y_0 z_1^3$% */
-
-    w = F_SUB(f, p, uu, u);            /* %$w = uu - u$% */
-    r = F_SUB(f, MP_NEW, ss, s);       /* %$r = ss - s$% */
-    if (F_ZEROP(f, w)) {
-      MP_DROP(w);
-      MP_DROP(u);
-      MP_DROP(s);
-      MP_DROP(uu);
-      MP_DROP(ss);
-      if (F_ZEROP(f, r)) {
-       MP_DROP(r);
-       return (c->ops->dbl(c, d, a));
-      } else {
-       MP_DROP(r);
-       EC_SETINF(d);
-       return (d);
-      }
-    }
-    u = F_ADD(f, u, u, uu);            /* %$t = uu + u$% */
-    s = F_ADD(f, s, s, ss);            /* %$m = ss + r$% */
-
-    uu = F_MUL(f, uu, a->z, w);                /* %$z_0 w$% */
-    dz = F_MUL(f, ss, uu, b->z);       /* %$z' = z_0 z_1 w$% */
-
-    p = F_SQR(f, uu, w);               /* %$w^2$% */
-    q = F_MUL(f, MP_NEW, p, u);                /* %$t w^2$% */
-    u = F_MUL(f, u, p, w);             /* %$w^3$% */
-    p = F_MUL(f, p, u, s);             /* %$m w^3$% */
-
-    dx = F_SQR(f, u, r);               /* %$r^2$% */
-    dx = F_SUB(f, dx, dx, q);          /* %$x' = r^2 - t w^2$% */
-
-    s = F_DBL(f, s, dx);               /* %$2 x'$% */
-    q = F_SUB(f, q, q, s);             /* %$v = t w^2 - 2 x'$% */
-    dy = F_MUL(f, s, q, r);            /* %$v r$% */
-    dy = F_SUB(f, dy, dy, p);          /* %$v r - m w^3$% */
-    dy = F_HLV(f, dy, dy);             /* %$y' = (v r - m w^3)/2$% */
-
-    EC_DESTROY(d);
-    d->x = dx;
-    d->y = dy;
-    d->z = dz;
-    MP_DROP(p);
-    MP_DROP(q);
-    MP_DROP(r);
-    MP_DROP(w);
-  }
-  return (d);
-}
-
-static int eccheck(ec_curve *c, const ec *p)
-{
-  field *f = c->f;
-  mp *l, *x, *r;
-  int rc;
-  if (EC_ATINF(p)) return (0);
-  l = F_SQR(f, MP_NEW, p->y);
-  x = F_SQR(f, MP_NEW, p->x);
-  r = F_MUL(f, MP_NEW, x, p->x);
-  x = F_MUL(f, x, c->a, p->x);
-  r = F_ADD(f, r, r, x);
-  r = F_ADD(f, r, r, c->b);
-  rc = MP_EQ(l, r) ? 0 : -1;
-  mp_drop(l);
-  mp_drop(x);
-  mp_drop(r);
-  return (rc);
-}
-
-static int ecprojcheck(ec_curve *c, const ec *p)
-{
-  ec t = EC_INIT;
-  int rc;
-
-  c->ops->fix(c, &t, p);
-  rc = eccheck(c, &t);
-  EC_DESTROY(&t);
-  return (rc);
-}
-
-static void ecdestroy(ec_curve *c)
-{
-  MP_DROP(c->a);
-  MP_DROP(c->b);
-  DESTROY(c);
-}
-
-/* --- @ec_prime@, @ec_primeproj@ --- *
- *
- * Arguments:  @field *f@ = the underlying field for this elliptic curve
- *             @mp *a, *b@ = the coefficients for this curve
- *
- * Returns:    A pointer to the curve, or null.
- *
- * Use:                Creates a curve structure for an elliptic curve defined over
- *             a prime field.  The @primeproj@ variant uses projective
- *             coordinates, which can be a win.
- */
-
-extern ec_curve *ec_prime(field *f, mp *a, mp *b)
-{
-  ec_curve *c = CREATE(ec_curve);
-  c->ops = &ec_primeops;
-  c->f = f;
-  c->a = F_IN(f, MP_NEW, a);
-  c->b = F_IN(f, MP_NEW, b);
-  return (c);
-}
-
-extern ec_curve *ec_primeproj(field *f, mp *a, mp *b)
-{
-  ec_curve *c = CREATE(ec_curve);
-  mp *ax;
-
-  ax = mp_add(MP_NEW, a, MP_THREE);
-  ax = F_IN(f, ax, ax);
-  if (F_ZEROP(f, ax))
-    c->ops = &ec_primeprojxops;
-  else
-    c->ops = &ec_primeprojops;
-  MP_DROP(ax);
-  c->f = f;
-  c->a = F_IN(f, MP_NEW, a);
-  c->b = F_IN(f, MP_NEW, b);
-  return (c);
-}
-
-static const ec_ops ec_primeops = {
-  "prime",
-  ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix,
-  ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck
-};
-
-static const ec_ops ec_primeprojops = {
-  "primeproj",
-  ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix,
-  ecfind, ecneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck
-};
-
-static const ec_ops ec_primeprojxops = {
-  "primeproj",
-  ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix,
-  ecfind, ecneg, ecprojadd, ec_stdsub, ecprojxdbl, ecprojcheck
-};
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
-
-int main(int argc, char *argv[])
-{
-  field *f;
-  ec_curve *c;
-  ec g = EC_INIT, d = EC_INIT;
-  mp *p, *a, *b, *r;
-  int i, n = argc == 1 ? 1 : atoi(argv[1]);
-
-  printf("ec-prime: ");
-  fflush(stdout);
-  a = MP(-3);
-  b = MP(0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef);
-  p = MP(39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319);
-  r = MP(39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942642);
-
-  f = field_niceprime(p);
-  c = ec_primeproj(f, a, b);
-
-  g.x = MP(0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7);
-  g.y = MP(0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f);
-
-  for (i = 0; i < n; i++) {
-    ec_mul(c, &d, &g, r);
-    if (EC_ATINF(&d)) {
-      fprintf(stderr, "zero too early\n");
-      return (1);
-    }
-    ec_add(c, &d, &d, &g);
-    if (!EC_ATINF(&d)) {
-      fprintf(stderr, "didn't reach zero\n");
-      MP_EPRINT("d.x", d.x);
-      MP_EPRINT("d.y", d.y);
-      return (1);
-    }
-    ec_destroy(&d);
-  }
-  ec_destroy(&g);
-  ec_destroycurve(c);
-  F_DESTROY(f);
-  MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r);
-  assert(!mparena_count(&mparena_global));
-  printf("ok\n");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-raw.c b/ec-raw.c
deleted file mode 100644 (file)
index 738827f..0000000
--- a/ec-raw.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ec-raw.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Raw formatting of elliptic curve points
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "ec.h"
-#include "ec-raw.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @ec_putraw@ --- *
- *
- * Arguments:  @ec_curve *c@ = elliptic curve
- *             @buf *b@ = pointer to a buffer
- *             @const ec *p@ = an elliptic curve point
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Puts an elliptic curve point to the given buffer using the
- *             standard uncompressed format described in P1383 and SEC1.
- *             This requires at most @1 + 2 * c->f->noctets@ space in the
- *             buffer.  We don't do point compression.
- */
-
-int ec_putraw(ec_curve *c, buf *b, const ec *p)
-{
-  octet *q;
-  size_t n;
-
-  if (EC_ATINF(p)) return (buf_putbyte(b, 0));
-  buf_putbyte(b, 4);
-  n = c->f->noctets;
-  if ((q = buf_get(b, n * 2)) == 0) return (-1);
-  mp_storeb(p->x, q, n);
-  mp_storeb(p->y, q + n, n);
-  return (0);
-}
-
-/* --- @ec_getraw@ --- *
- *
- * Arguments:  @ec_curve *c@ = elliptic curve
- *             @buf *b@ = pointer to a buffer
- *             @ec *d@ = an elliptic curve point
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Reads an elliptic curve point from the given buffer using the
- *             standard uncompressed format described in P1383 and SEC1.
- *             We don't do point compression.
- */
-
-int ec_getraw(ec_curve *c, buf *b, ec *d)
-{
-  const octet *q;
-  size_t n;
-  int u;
-
-  if ((u = buf_getbyte(b)) < 0) return (-1);
-  if (!u) { EC_SETINF(d); return (0); }
-  if (!(u & 4)) return (-1);
-  n = c->f->noctets;
-  if ((q = buf_get(b, n * 2)) == 0) return (-1);
-  EC_DESTROY(d);
-  d->x = mp_loadb(MP_NEW, q, n);
-  d->y = mp_loadb(MP_NEW, q + n, n);
-  d->z = 0;
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-raw.h b/ec-raw.h
deleted file mode 100644 (file)
index 083ca93..0000000
--- a/ec-raw.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ec-raw.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Raw formatting of elliptic curve points
- *
- * (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.
- */
-
-#ifndef CATACOMB_EC_RAW_H
-#define CATACOMB_EC_RAW_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_BUF_H
-#  include "buf.h"
-#endif
-
-#ifndef CATACOMB_EC_H
-#  include "ec.h"
-#endif
-
-/*----- Data formatting ---------------------------------------------------*/
-
-/* --- @ec_putraw@ --- *
- *
- * Arguments:  @ec_curve *c@ = elliptic curve
- *             @buf *b@ = pointer to a buffer
- *             @const ec *p@ = an elliptic curve point
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Puts an elliptic curve point to the given buffer using the
- *             standard uncompressed format described in P1383 and SEC1.
- *             We don't do point compression.
- */
-
-extern int ec_putraw(ec_curve */*c*/, buf */*b*/, const ec */*p*/);
-
-/* --- @ec_getraw@ --- *
- *
- * Arguments:  @ec_curve *c@ = elliptic curve
- *             @buf *b@ = pointer to a buffer
- *             @ec *d@ = an elliptic curve point
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Reads an elliptic curve point from the given buffer using the
- *             standard uncompressed format described in P1383 and SEC1.
- *             We don't do point compression.
- */
-
-extern int ec_getraw(ec_curve */*c*/, buf */*b*/, ec */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ec-test.c b/ec-test.c
deleted file mode 100644 (file)
index ad2af90..0000000
--- a/ec-test.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Code for testing elliptic-curve stuff
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/testrig.h>
-#include <mLib/sub.h>
-
-#include "ec.h"
-#include "ec-test.h"
-
-/*----- Cardboard cut-out elliptic curve ----------------------------------*/
-
-typedef struct ecctx {
-  ec_curve c;
-  unsigned long magic;
-  char *name;
-  ec_curve *real;
-} ecctx;
-
-#define MAGIC 0x3a1f0b07
-
-static void ecDESTROY(ec_curve *cc)
-{
-  ecctx *c = (ecctx *)cc;
-  xfree(c->name);
-  ec_destroycurve(c->real);
-  DESTROY(c);
-}
-
-#define UNOP(OP)                                                       \
-  static ec *ec##OP(ec_curve *cc, ec *d, const ec *p) {                        \
-    ecctx *c = (ecctx *)cc;                                            \
-    return (EC_##OP(c->real, d, p));                                   \
-  }
-
-#define BINOP(OP)                                                      \
-  static ec *ec##OP(ec_curve *cc, ec *d, const ec *p, const ec *q) {   \
-    ecctx *c = (ecctx *)cc;                                            \
-    return (EC_##OP(c->real, d, p, q));                                        \
-  }
-
-UNOP(IN)
-UNOP(OUT)
-UNOP(FIX)
-UNOP(NEG)
-UNOP(DBL)
-BINOP(ADD)
-BINOP(SUB)
-
-#undef UNOP
-#undef BINOP
-
-static ec *ecFIND(ec_curve *cc, ec *d, mp *x)
-{
-  ecctx *c = (ecctx *)cc;
-  return (EC_FIND(c->real, d, x));
-}
-
-static int ecCHECK(ec_curve *cc, const ec *p)
-{
-  ecctx *c = (ecctx *)cc;
-  return (EC_CHECK(c->real, p));
-}
-
-static int ecSAMEP(ec_curve *cc, ec_curve *dd)
-{
-  ecctx *c = (ecctx *)cc, *d = (ecctx *)dd;
-  return (ec_samep(c->real, d->real));
-}
-
-static const ec_ops ecops = {
-  "cardboard",
-  ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX,
-  ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK
-};
-
-static ec_curve *ec_cutout(ec_curve *real, const char *name)
-{
-  ecctx *c = CREATE(ecctx);
-  c->c.f = real->f;
-  c->c.ops = &ecops;
-  c->c.a = real->a;
-  c->c.b = real->b;
-  c->magic = MAGIC;
-  c->name = xstrdup(name);
-  c->real = real;
-  return (&c->c);
-}
-
-static const char *ec_name(ec_curve *cc)
-{
-  ecctx *c = (ecctx *)cc;
-  assert(c->magic == MAGIC);
-  return (c->name);
-}
-
-/*----- Test field types --------------------------------------------------*/
-
-static void ecvcvt(const char *buf, dstr *d)
-{
-  ec_curve *v;
-  qd_parse qd;
-
-  qd.p = buf;
-  qd.e = 0;
-  if ((v = ec_curveparse(&qd)) == 0) {
-    fprintf(stderr, "bad curve `%.*s|%s': %s\n",
-           qd.p - buf, buf, qd.p, qd.e);
-    exit(1);
-  }
-  dstr_ensure(d, sizeof(v));
-  *(ec_curve **)d->buf = ec_cutout(v, buf);
-  d->len += sizeof(v);
-}
-
-static void ecvdump(dstr *d, FILE *fp)
-{
-  ec_curve *v = *(ec_curve **)d->buf;
-  fprintf(fp, "%s", ec_name(v));
-}
-
-const test_type type_ecurve = { ecvcvt, ecvdump };
-
-static void eccvt(const char *p, dstr *d)
-{
-  ec *a;
-  qd_parse qd;
-
-  qd.p = p;
-  qd.e = 0;
-  dstr_ensure(d, sizeof(ec));
-  a = (ec *)d->buf;
-  d->len += sizeof(ec);
-  ec_create(a);
-  if (!ec_ptparse(&qd, a)) {
-    fprintf(stderr, "bad point `%.*s|%s': %s\n", qd.p - p, p, qd.p, qd.e);
-    exit(1);
-  }
-}
-
-static void ecdodump(ec *a, FILE *fp)
-{
-  if (EC_ATINF(a))
-    fputs("inf", fp);
-  else {
-    fputs("0x", fp);
-    mp_writefile(a->x, fp, 16);
-    fputs(", 0x", fp);
-    mp_writefile(a->y, fp, 16);
-  }
-}
-
-static void ecdump(dstr *d, FILE *fp)
-{
-  ec *a = (ec *)d->buf;
-  ecdodump(a, fp);
-}
-
-const test_type type_ec = { eccvt, ecdump };
-
-/*----- Testing elliptic curve functionality ------------------------------*/
-
-#ifdef TEST_RIG
-
-static void ecdestroy(ec_curve *c)
-{
-  field *f = c->f;
-  ec_destroycurve(c);
-  F_DESTROY(f);
-}
-
-#define UNOP(op)                                                       \
-  static int v##op(dstr v[])                                           \
-  {                                                                    \
-    ec_curve *e = *(ec_curve **)v[0].buf;                              \
-    ec *a = (ec *)v[1].buf;                                            \
-    ec *r = (ec *)v[2].buf;                                            \
-    ec c = EC_INIT;                                                    \
-    int ok = 1;                                                                \
-    ec_##op(e, &c, a);                                                 \
-    if (!EC_EQ(r, &c)) {                                               \
-      fprintf(stderr, #op "failed");                                   \
-      fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);      \
-      fprintf(stderr, "\n    a = "); ecdodump(a, stderr);              \
-      fprintf(stderr, "\n    r = "); ecdodump(r, stderr);              \
-      fprintf(stderr, "\n    c = "); ecdodump(&c, stderr);             \
-      fprintf(stderr, "\n");                                           \
-      ok = 0;                                                          \
-    }                                                                  \
-    EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c);                      \
-    ecdestroy(e);                                                      \
-    return (ok);                                                       \
-  }
-
-#define BINOP(op)                                                      \
-  static int v##op(dstr v[])                                           \
-  {                                                                    \
-    ec_curve *e = *(ec_curve **)v[0].buf;                              \
-    ec *a = (ec *)v[1].buf;                                            \
-    ec *b = (ec *)v[2].buf;                                            \
-    ec *r = (ec *)v[3].buf;                                            \
-    ec c = EC_INIT;                                                    \
-    int ok = 1;                                                                \
-    ec_##op(e, &c, a, b);                                              \
-    if (!EC_EQ(r, &c)) {                                               \
-      fprintf(stderr, #op "failed");                                   \
-      fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);      \
-      fprintf(stderr, "\n    a = "); ecdodump(a, stderr);              \
-      fprintf(stderr, "\n    b = "); ecdodump(b, stderr);              \
-      fprintf(stderr, "\n    r = "); ecdodump(r, stderr);              \
-      fprintf(stderr, "\n    c = "); ecdodump(&c, stderr);             \
-      fprintf(stderr, "\n");                                           \
-      ok = 0;                                                          \
-    }                                                                  \
-    EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c);       \
-    ecdestroy(e);                                                      \
-    return (ok);                                                       \
-  }
-
-UNOP(neg)
-UNOP(dbl)
-BINOP(add)
-BINOP(sub)
-
-static int vcheck(dstr v[])
-{
-  ec_curve *e = *(ec_curve **)v[0].buf;
-  ec *a = (ec *)v[1].buf;
-  int r = *(int *)v[2].buf;
-  int c;
-  int ok = 1;
-  c = ec_check(e, a);
-  if (r != c) {
-    fprintf(stderr, "check failed");
-    fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
-    fprintf(stderr, "\n           a = "); ecdodump(a, stderr);
-    fprintf(stderr, "\n           r = %d", r);
-    fprintf(stderr, "\n           c = %d", c);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  EC_DESTROY(a);
-  ecdestroy(e);
-  return (ok);
-}
-
-static int vmul(dstr v[])
-{
-  ec_curve *e = *(ec_curve **)v[0].buf;
-  ec *a = (ec *)v[1].buf;
-  mp *n = *(mp **)v[2].buf;
-  ec *r = (ec *)v[3].buf;
-  ec c = EC_INIT;
-  int ok = 1;
-  ec_mul(e, &c, a, n);
-  if (!EC_EQ(r, &c)) {
-    fprintf(stderr, "mul failed");
-    fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
-    fprintf(stderr, "\n           a = "); ecdodump(a, stderr);
-    fprintf(stderr, "\n           n = "); mp_writefile(n, stderr, 10);
-    fprintf(stderr, "\n           r = "); ecdodump(r, stderr);
-    fprintf(stderr, "\n           c = "); ecdodump(&c, stderr);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); MP_DROP(n);
-  ecdestroy(e);
-  return (ok);
-}
-
-static int vfind(dstr v[])
-{
-  ec_curve *e = *(ec_curve **)v[0].buf;
-  mp *x = *(mp **)v[1].buf;
-  ec *r = (ec *)v[2].buf;
-  ec c = EC_INIT;
-  int ok = 1;
-  if (!ec_find(e, &c, x)) EC_SETINF(&c);
-  if (!EC_EQ(r, &c)) {
-    fprintf(stderr, "find failed");
-    fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
-    fprintf(stderr, "\n           x = "); mp_writefile(x, stderr, 16);
-    fprintf(stderr, "\n           r = "); ecdodump(r, stderr);
-    fprintf(stderr, "\n           c = "); ecdodump(&c, stderr);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  MP_DROP(x); EC_DESTROY(r); EC_DESTROY(&c);
-  ecdestroy(e);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "neg", vneg, { &type_ecurve, &type_ec, &type_ec } },
-  { "dbl", vdbl, { &type_ecurve, &type_ec, &type_ec } },
-  { "add", vadd, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
-  { "sub", vsub, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
-  { "mul", vmul, { &type_ecurve, &type_ec, &type_mp, &type_ec } },
-  { "check", vcheck, { &type_ecurve, &type_ec, &type_int } },
-  { "find", vfind, { &type_ecurve, &type_mp, &type_ec } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/ec");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec-test.h b/ec-test.h
deleted file mode 100644 (file)
index 18e4b25..0000000
--- a/ec-test.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ec-test.h,v 1.3 2004/04/08 16:17:32 mdw Exp $
- *
- * Elliptic curve test functions
- *
- * (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.
- */
-
-#ifndef CATACOMB_EC_TEST_H
-#define CATACOMB_EC_TEST_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/testrig.h>
-
-#ifndef CATACOMB_EC_H
-#  include "ec.h"
-#endif
-
-/*----- Test vector types -------------------------------------------------*/
-
-extern const test_type type_ecurve, type_ec;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ec.c b/ec.c
deleted file mode 100644 (file)
index cad7a56..0000000
--- a/ec.c
+++ /dev/null
@@ -1,424 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Elliptic curve definitions
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "ec.h"
-
-/*----- Trivial wrappers --------------------------------------------------*/
-
-/* --- @ec_samep@ --- *
- *
- * Arguments:  @ec_curve *c, *d@ = two elliptic curves
- *
- * Returns:    Nonzero if the curves are identical (not just isomorphic).
- *
- * Use:                Checks for sameness of curves.  This function does the full
- *             check, not just the curve-type-specific check done by the
- *             @sampep@ field operation.
- */
-
-int ec_samep(ec_curve *c, ec_curve *d)
-{
-  return (c == d || (field_samep(c->f, d->f) &&
-                    c->ops == d->ops && EC_SAMEP(c, d)));
-}
-
-/* --- @ec_create@ --- *
- *
- * Arguments:  @ec *p@ = pointer to an elliptic-curve point
- *
- * Returns:    The argument @p@.
- *
- * Use:                Initializes a new point.  The initial value is the additive
- *             identity (which is universal for all curves).
- */
-
-ec *ec_create(ec *p) { EC_CREATE(p); return (p); }
-
-/* --- @ec_destroy@ --- *
- *
- * Arguments:  @ec *p@ = pointer to an elliptic-curve point
- *
- * Returns:    ---
- *
- * Use:                Destroys a point, making it invalid.
- */
-
-void ec_destroy(ec *p) { EC_DESTROY(p); }
-
-/* --- @ec_atinf@ --- *
- *
- * Arguments:  @const ec *p@ = pointer to a point
- *
- * Returns:    Nonzero if %$p = O$% is the point at infinity, zero
- *             otherwise.
- */
-
-int ec_atinf(const ec *p) { return (EC_ATINF(p)); }
-
-/* --- @ec_setinf@ --- *
- *
- * Arguments:  @ec *p@ = pointer to a point
- *
- * Returns:    The argument @p@.
- *
- * Use:                Sets the given point to be the point %$O$% at infinity.
- */
-
-ec *ec_setinf(ec *p) { EC_SETINF(p); return (p); }
-
-/* --- @ec_copy@ --- *
- *
- * Arguments:  @ec *d@ = pointer to destination point
- *             @const ec *p@ = pointer to source point
- *
- * Returns:    The destination @d@.
- *
- * Use:                Creates a copy of an elliptic curve point.
- */
-
-ec *ec_copy(ec *d, const ec *p) { EC_COPY(d, p); return (d); }
-
-/* --- @ec_eq@ --- *
- *
- * Arguments:  @const ec *p, *q@ = two points
- *
- * Returns:    Nonzero if the points are equal.  Compares external-format
- *             points.
- */
-
-int ec_eq(const ec *p, const ec *q) { return (EC_EQ(p, q)); }
-
-/*----- Standard curve operations -----------------------------------------*/
-
-/* --- @ec_stdsamep@ --- *
- *
- * Arguments:  @ec_curve *c, *d@ = two elliptic curves
- *
- * Returns:    Nonzero if the curves are identical (not just isomorphic).
- *
- * Use:                Simple sameness check on @a@ and @b@ curve members.
- */
-
-int ec_stdsamep(ec_curve *c, ec_curve *d)
-  { return (MP_EQ(c->a, d->a) && MP_EQ(c->b, d->b)); }
-
-/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination
- *             @const ec *p@ = pointer to a source point
- *
- * Returns:    The destination @d@.
- *
- * Use:                An identity operation if your curve has no internal
- *             representation.  (The field internal representation is still
- *             used.)
- */
-
-ec *ec_idin(ec_curve *c, ec *d, const ec *p)
-{
-  if (EC_ATINF(p))
-    EC_SETINF(d);
-  else {
-    field *f = c->f;
-    d->x = F_IN(f, d->x, p->x);
-    d->y = F_IN(f, d->y, p->y);
-    mp_drop(d->z); d->z = 0;
-  }
-  return (d);
-}
-
-ec *ec_idout(ec_curve *c, ec *d, const ec *p)
-{
-  if (EC_ATINF(p))
-    EC_SETINF(d);
-  else {
-    field *f = c->f;
-    d->x = F_OUT(f, d->x, p->x);
-    d->y = F_OUT(f, d->y, p->y);
-    mp_drop(d->z); d->z = 0;
-  }
-  return (d);
-}
-
-ec *ec_idfix(ec_curve *c, ec *d, const ec *p)
-  { EC_COPY(d, p); return (d); }
-
-/* --- @ec_projin@, @ec_projout@, @ec_projfix@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination
- *             @const ec *p@ = pointer to a source point
- *
- * Returns:    The destination @d@.
- *
- * Use:                Conversion functions if your curve operations use a
- *             projective representation.
- */
-
-ec *ec_projin(ec_curve *c, ec *d, const ec *p)
-{
-  if (EC_ATINF(p))
-    EC_SETINF(d);
-  else {
-    field *f = c->f;
-    d->x = F_IN(f, d->x, p->x);
-    d->y = F_IN(f, d->y, p->y);
-    mp_drop(d->z); d->z = MP_COPY(f->one);
-  }
-  return (d);
-}
-
-ec *ec_projout(ec_curve *c, ec *d, const ec *p)
-{
-  if (EC_ATINF(p))
-    EC_SETINF(d);
-  else {
-    mp *x, *y, *z, *zz;
-    field *f = c->f;
-    if (p->z == f->one) {
-      d->x = F_OUT(f, d->x, p->x);
-      d->y = F_OUT(f, d->y, p->y);
-    } else {
-      z = F_INV(f, MP_NEW, p->z);
-      zz = F_SQR(f, MP_NEW, z);
-      z = F_MUL(f, z, zz, z);
-      x = F_MUL(f, d->x, p->x, zz);
-      y = F_MUL(f, d->y, p->y, z);
-      mp_drop(z);
-      mp_drop(zz);
-      d->x = F_OUT(f, x, x);
-      d->y = F_OUT(f, y, y);
-    }
-    mp_drop(d->z);
-    d->z = 0;
-  }
-  return (d);
-}
-
-ec *ec_projfix(ec_curve *c, ec *d, const ec *p)
-{
-  if (EC_ATINF(p))
-    EC_SETINF(d);
-  else if (p->z == c->f->one)
-    EC_COPY(d, p);
-  else {
-    mp *z, *zz;
-    field *f = c->f;
-    z = F_INV(f, MP_NEW, p->z);
-    zz = F_SQR(f, MP_NEW, z);
-    z = F_MUL(f, z, zz, z);
-    d->x = F_MUL(f, d->x, p->x, zz);
-    d->y = F_MUL(f, d->y, p->y, z);
-    mp_drop(z);
-    mp_drop(zz);
-    mp_drop(d->z);
-    d->z = MP_COPY(f->one);
-  }
-  return (d);
-}
-
-/* --- @ec_stdsub@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination
- *             @const ec *p, *q@ = the operand points
- *
- * Returns:    The destination @d@.
- *
- * Use:                Standard point subtraction operation, in terms of negation
- *             and addition.  This isn't as efficient as a ready-made
- *             subtraction operator.
- */
-
-ec *ec_stdsub(ec_curve *c, ec *d, const ec *p, const ec *q)
-{
-  ec t = EC_INIT;
-  EC_NEG(c, &t, q);
-  EC_FIX(c, &t, &t);
-  EC_ADD(c, d, p, &t);
-  EC_DESTROY(&t);
-  return (d);
-}
-
-/*----- Creating curves ---------------------------------------------------*/
-
-/* --- @ec_destroycurve@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an ellptic curve
- *
- * Returns:    ---
- *
- * Use:                Destroys a description of an elliptic curve.
- */
-
-void ec_destroycurve(ec_curve *c) { c->ops->destroy(c); }
-
-/*----- Real arithmetic ---------------------------------------------------*/
-
-/* --- @ec_find@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @mp *x@ = a possible x-coordinate
- *
- * Returns:    Zero if OK, nonzero if there isn't a point there.
- *
- * Use:                Finds a point on an elliptic curve with a given x-coordinate.
- */
-
-ec *ec_find(ec_curve *c, ec *d, mp *x)
-{
-  x = F_IN(c->f, MP_NEW, x);
-  if ((d = EC_FIND(c, d, x)) != 0)
-    EC_OUT(c, d, d);
-  MP_DROP(x);
-  return (d);
-}
-
-/* --- @ec_neg@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p@ = pointer to the operand point
- *
- * Returns:    The destination point.
- *
- * Use:                Computes the negation of the given point.
- */
-
-ec *ec_neg(ec_curve *c, ec *d, const ec *p)
-  { EC_IN(c, d, p); EC_NEG(c, d, d); return (EC_OUT(c, d, d)); }
-
-/* --- @ec_add@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p, *q@ = pointers to the operand points
- *
- * Returns:    ---
- *
- * Use:                Adds two points on an elliptic curve.
- */
-
-ec *ec_add(ec_curve *c, ec *d, const ec *p, const ec *q)
-{
-  ec pp = EC_INIT, qq = EC_INIT;
-  EC_IN(c, &pp, p);
-  EC_IN(c, &qq, q);
-  EC_ADD(c, d, &pp, &qq);
-  EC_OUT(c, d, d);
-  EC_DESTROY(&pp);
-  EC_DESTROY(&qq);
-  return (d);
-}
-
-/* --- @ec_sub@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p, *q@ = pointers to the operand points
- *
- * Returns:    The destination @d@.
- *
- * Use:                Subtracts one point from another on an elliptic curve.
- */
-
-ec *ec_sub(ec_curve *c, ec *d, const ec *p, const ec *q)
-{
-  ec pp = EC_INIT, qq = EC_INIT;
-  EC_IN(c, &pp, p);
-  EC_IN(c, &qq, q);
-  EC_SUB(c, d, &pp, &qq);
-  EC_OUT(c, d, d);
-  EC_DESTROY(&pp);
-  EC_DESTROY(&qq);
-  return (d);
-}
-
-/* --- @ec_dbl@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p@ = pointer to the operand point
- *
- * Returns:    ---
- *
- * Use:                Doubles a point on an elliptic curve.
- */
-
-ec *ec_dbl(ec_curve *c, ec *d, const ec *p)
-  { EC_IN(c, d, p); EC_DBL(c, d, d); return (EC_OUT(c, d, d)); }
-
-/* --- @ec_check@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @const ec *p@ = pointer to the point
- *
- * Returns:    Zero if OK, nonzero if this is an invalid point.
- *
- * Use:                Checks that a point is actually on an elliptic curve.
- */
-
-int ec_check(ec_curve *c, const ec *p)
-{
-  ec t = EC_INIT;
-  int rc;
-
-  if (EC_ATINF(p))
-    return (0);
-  EC_IN(c, &t, p);
-  rc = EC_CHECK(c, &t);
-  EC_DESTROY(&t);
-  return (rc);
-}
-
-/* --- @ec_rand@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @grand *r@ = random number source
- *
- * Returns:    The destination @d@.
- *
- * Use:                Finds a random point on the given curve.
- */
-
-ec *ec_rand(ec_curve *c, ec *d, grand *r)
-{
-  mp *x = MP_NEW;
-  do x = F_RAND(c->f, x, r); while (!EC_FIND(c, d, x));
-  mp_drop(x);
-  if (grand_range(r, 2)) EC_NEG(c, d, d);
-  return (EC_OUT(c, d, d));
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ec.h b/ec.h
deleted file mode 100644 (file)
index ac0b8fc..0000000
--- a/ec.h
+++ /dev/null
@@ -1,618 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Elliptic curve definitions
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_EC_H
-#define CATACOMB_EC_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_FIELD_H
-#  include "field.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_QDPARSE_H
-#  include "qdparse.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- An elliptic curve representation --- */
-
-typedef struct ec_curve {
-  const struct ec_ops *ops;            /* Curve operations */
-  field *f;                            /* Underlying field structure */
-  mp *a, *b;                           /* Standard params (internal form) */
-} ec_curve;
-
-/* --- An elliptic curve point --- */
-
-typedef struct ec {
-  mp *x, *y;                           /* Point coordinates */
-  mp *z;                               /* Common denominator (or null) */
-} ec;
-
-/* --- A factor for simultaneous multiplication --- */
-
-typedef struct ec_mulfactor {
-  ec base;                             /* The point */
-  mp *exp;                             /* The exponent */
-} ec_mulfactor;
-
-/* --- Elliptic curve operations --- *
- *
- * All operations (apart from @destroy@ and @in@) are guaranteed to be
- * performed on internal representations of points.
- *
- * (Historical note.  We used to guarantee that the second to @add@ and @mul@
- * was the output of @in@ or @fix@, but this canonification turned out to
- * make the precomputation in @ec_exp@ too slow.  Projective implementations
- * must therefore cope with a pair of arbitrary points.)
- */
-
-typedef struct ec_ops {
-  const char *name;
-  void (*destroy)(ec_curve */*c*/);
-  int (*samep)(ec_curve */*c*/, ec_curve */*d*/);
-  ec *(*in)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-  ec *(*out)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-  ec *(*fix)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-  ec *(*find)(ec_curve */*c*/, ec */*d*/, mp */*x*/);
-  ec *(*neg)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-  ec *(*add)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/);
-  ec *(*sub)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/);
-  ec *(*dbl)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-  int (*check)(ec_curve */*c*/, const ec */*p*/);
-} ec_ops;
-
-#define EC_NAME(c)             (c)->ops->name
-
-#define EC_SAMEP(c, d)         (c)->ops->samep((c), (d))
-#define EC_IN(c, d, p)         (c)->ops->in((c), (d), (p))
-#define EC_OUT(c, d, p)                (c)->ops->out((c), (d), (p))
-#define EC_FIX(c, d, p)                (c)->ops->fix((c), (d), (p))
-
-#define EC_FIND(c, d, x)       (c)->ops->find((c), (d), (x))
-#define EC_NEG(c, d, x)                (c)->ops->neg((c), (d), (x))
-#define EC_ADD(c, d, p, q)     (c)->ops->add((c), (d), (p), (q))
-#define EC_SUB(c, d, p, q)     (c)->ops->sub((c), (d), (p), (q))
-#define EC_DBL(c, d, p)                (c)->ops->dbl((c), (d), (p))
-#define EC_CHECK(c, p)         (c)->ops->check((c), (p))
-
-/* --- Elliptic curve parameters --- */
-
-typedef struct ec_info {
-  ec_curve *c;                         /* The actual curve */
-  ec g;                                        /* The common point */
-  mp *r;                               /* Order of %$g$% */
-  mp *h;                               /* Cofactor %$h = \#E/r$% */
-} ec_info;
-
-/*----- Simple memory management things -----------------------------------*/
-
-/* --- @ec_create@ --- *
- *
- * Arguments:  @ec *p@ = pointer to an elliptic-curve point
- *
- * Returns:    The argument @p@.
- *
- * Use:                Initializes a new point.  The initial value is the additive
- *             identity (which is universal for all curves).
- */
-
-#define EC_INIT { MP_NEW, MP_NEW, MP_NEW }
-
-#define EC_CREATE(p) do {                                              \
-  ec *_p = (p);                                                                \
-  _p->x = _p->y = _p->z = MP_NEW;                                      \
-} while (0)
-
-extern ec *ec_create(ec */*p*/);
-
-/* --- @ec_destroy@ --- *
- *
- * Arguments:  @ec *p@ = pointer to an elliptic-curve point
- *
- * Returns:    ---
- *
- * Use:                Destroys a point, making it invalid.
- */
-
-#define EC_DESTROY(p) do {                                             \
-  ec *_p = (p);                                                                \
-  if (!EC_ATINF(_p)) {                                                 \
-    MP_DROP(_p->x);                                                    \
-    MP_DROP(_p->y);                                                    \
-    if (_p->z) MP_DROP(_p->z);                                         \
-  }                                                                    \
-} while (0)
-
-extern void ec_destroy(ec */*p*/);
-
-/* --- @ec_atinf@ --- *
- *
- * Arguments:  @const ec *p@ = pointer to a point
- *
- * Returns:    Nonzero if %$p = O$% is the point at infinity, zero
- *             otherwise.
- */
-
-#define EC_ATINF(p) ((p)->x == MP_NEW || (p)->x == MP_NEWSEC)
-
-extern int ec_atinf(const ec */*p*/);
-
-/* --- @ec_setinf@ --- *
- *
- * Arguments:  @ec *p@ = pointer to a point
- *
- * Returns:    The argument @p@.
- *
- * Use:                Sets the given point to be the point %$O$% at infinity.
- */
-
-#define EC_SETINF(p) do {                                              \
-  ec *_p = (p);                                                                \
-  if (!EC_ATINF(_p)) {                                                 \
-    MP_DROP(_p->x);                                                    \
-    MP_DROP(_p->y);                                                    \
-    if (_p->z) MP_DROP(_p->z);                                         \
-    _p->x = _p->y = _p->z = MP_NEW;                                    \
-    _p->y = MP_NEW;                                                    \
-    _p->z = MP_NEW;                                                    \
-  }                                                                    \
-} while (0)
-
-extern ec *ec_setinf(ec */*p*/);
-
-/* --- @ec_copy@ --- *
- *
- * Arguments:  @ec *d@ = pointer to destination point
- *             @const ec *p@ = pointer to source point
- *
- * Returns:    The destination @d@.
- *
- * Use:                Creates a copy of an elliptic curve point.
- */
-
-#define EC_COPY(d, p) do {                                             \
-  ec *_d = (d);                                                                \
-  const ec *_p = (p);                                                  \
-  if (d != p) {                                                                \
-    EC_DESTROY(d);                                                     \
-    if (EC_ATINF(p))                                                   \
-      _d->x = _d->y = _d->z = MP_NEW;                                  \
-    else {                                                             \
-      _d->x = MP_COPY(_p->x);                                          \
-      _d->y = MP_COPY(_p->y);                                          \
-      _d->z = _p->z ? MP_COPY(_p->z) : MP_NEW;                         \
-    }                                                                  \
-  }                                                                    \
-} while (0)
-
-extern ec *ec_copy(ec */*d*/, const ec */*p*/);
-
-/* --- @ec_eq@ --- *
- *
- * Arguments:  @const ec *p, *q@ = two points
- *
- * Returns:    Nonzero if the points are equal.  Compares external-format
- *             points.
- */
-
-#define EC_EQ(p, q)                                                    \
-    ((EC_ATINF(p) && EC_ATINF(q)) ||                                   \
-     (!EC_ATINF(p) && !EC_ATINF(q) &&                                  \
-      MP_EQ((p)->x, (q)->x) &&                                         \
-      MP_EQ((p)->y, (q)->y)))
-
-extern int ec_eq(const ec *p, const ec *q);
-
-/*----- Interesting arithmetic --------------------------------------------*/
-
-/* --- @ec_samep@ --- *
- *
- * Arguments:  @ec_curve *c, *d@ = two elliptic curves
- *
- * Returns:    Nonzero if the curves are identical (not just isomorphic).
- *
- * Use:                Checks for sameness of curves.  This function does the full
- *             check, not just the curve-type-specific check done by the
- *             @sampep@ field operation.
- */
-
-extern int ec_samep(ec_curve */*c*/, ec_curve */*d*/);
-
-/* --- @ec_find@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @mp *x@ = a possible x-coordinate
- *
- * Returns:    The destination if OK, or null if no point was found.
- *
- * Use:                Finds a point on an elliptic curve with a given
- *             x-coordinate.  If there is no point with the given
- *             %$x$%-coordinate, a null pointer is returned and the
- *             destination is left invalid.
- */
-
-extern ec *ec_find(ec_curve */*c*/, ec */*d*/, mp */*x*/);
-
-/* --- @ec_rand@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @grand *r@ = random number source
- *
- * Returns:    The destination @d@.
- *
- * Use:                Finds a random point on the given curve.
- */
-
-extern ec *ec_rand(ec_curve */*c*/, ec */*d*/, grand */*r*/);
-
-/* --- @ec_neg@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p@ = pointer to the operand point
- *
- * Returns:    The destination point.
- *
- * Use:                Computes the negation of the given point.
- */
-
-extern ec *ec_neg(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-
-/* --- @ec_add@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p, *q@ = pointers to the operand points
- *
- * Returns:    The destination @d@.
- *
- * Use:                Adds two points on an elliptic curve.
- */
-
-extern ec *ec_add(ec_curve */*c*/, ec */*d*/,
-                 const ec */*p*/, const ec */*q*/);
-
-/* --- @ec_sub@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p, *q@ = pointers to the operand points
- *
- * Returns:    The destination @d@.
- *
- * Use:                Subtracts one point from another on an elliptic curve.
- */
-
-extern ec *ec_sub(ec_curve */*c*/, ec */*d*/,
-                 const ec */*p*/, const ec */*q*/);
-
-/* --- @ec_dbl@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p@ = pointer to the operand point
- *
- * Returns:    The destination @d@.
- *
- * Use:                Doubles a point on an elliptic curve.
- */
-
-extern ec *ec_dbl(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-
-/* --- @ec_check@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @const ec *p@ = pointer to the point
- *
- * Returns:    Zero if OK, nonzero if this is an invalid point.
- *
- * Use:                Checks that a point is actually on an elliptic curve.
- */
-
-extern int ec_check(ec_curve */*c*/, const ec */*p*/);
-
-/* --- @ec_mul@, @ec_imul@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec *p@ = pointer to the generator point
- *             @mp *n@ = integer multiplier
- *
- * Returns:    The destination @d@.
- *
- * Use:                Multiplies a point by a scalar, returning %$n p$%.  The
- *             @imul@ variant uses internal representations for argument
- *             and result.
- */
-
-extern ec *ec_mul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/);
-extern ec *ec_imul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/);
-
-/* --- @ec_mmul@, @ec_immul@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination point
- *             @const ec_mulfactor *f@ = pointer to vector of factors
- *             @size_t n@ = number of factors
- *
- * Returns:    The destination @d@.
- *
- * Use:                Does simultaneous point multiplication.  The @immul@ variant
- *             uses internal representations for arguments and result.
- */
-
-extern ec *ec_mmul(ec_curve */*c*/, ec */*d*/,
-                  const ec_mulfactor */*f*/, size_t /*n*/);
-extern ec *ec_immul(ec_curve */*c*/, ec */*d*/,
-                   const ec_mulfactor */*f*/, size_t /*n*/);
-
-/*----- Standard curve operations -----------------------------------------*/
-
-/* --- @ec_stdsamep@ --- *
- *
- * Arguments:  @ec_curve *c, *d@ = two elliptic curves
- *
- * Returns:    Nonzero if the curves are identical (not just isomorphic).
- *
- * Use:                Simple sameness check on @a@ and @b@ curve members.
- */
-
-extern int ec_stdsamep(ec_curve */*c*/, ec_curve */*d*/);
-
-/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination
- *             @const ec *p@ = pointer to a source point
- *
- * Returns:    The destination @d@.
- *
- * Use:                An identity operation if your curve has no internal
- *             representation.  (The field internal representation is still
- *             used.)
- */
-
-extern ec *ec_idin(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-extern ec *ec_idout(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-extern ec *ec_idfix(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-
-/* --- @ec_projin@, @ec_projout@, @ec_projfix@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination
- *             @const ec *p@ = pointer to a source point
- *
- * Returns:    The destination @d@.
- *
- * Use:                Conversion functions if your curve operations use a
- *             projective representation.
- */
-
-extern ec *ec_projin(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-extern ec *ec_projout(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-extern ec *ec_projfix(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
-
-/* --- @ec_stdsub@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
- *             @ec *d@ = pointer to the destination
- *             @const ec *p, *q@ = the operand points
- *
- * Returns:    The destination @d@.
- *
- * Use:                Standard point subtraction operation, in terms of negation
- *             and addition.  This isn't as efficient as a ready-made
- *             subtraction operator.
- */
-
-extern ec *ec_stdsub(ec_curve */*c*/, ec */*d*/,
-                    const ec */*p*/, const ec */*q*/);
-
-/*----- Creating curves ---------------------------------------------------*/
-
-/* --- @ec_destroycurve@ --- *
- *
- * Arguments:  @ec_curve *c@ = pointer to an ellptic curve
- *
- * Returns:    ---
- *
- * Use:                Destroys a description of an elliptic curve.
- */
-
-extern void ec_destroycurve(ec_curve */*c*/);
-
-/* --- @ec_prime@, @ec_primeproj@ --- *
- *
- * Arguments:  @field *f@ = the underlying field for this elliptic curve
- *             @mp *a, *b@ = the coefficients for this curve
- *
- * Returns:    A pointer to the curve, or null.
- *
- * Use:                Creates a curve structure for an elliptic curve defined over
- *             a prime field.  The @primeproj@ variant uses projective
- *             coordinates, which can be a win.
- */
-
-extern ec_curve *ec_prime(field */*f*/, mp */*a*/, mp */*b*/);
-extern ec_curve *ec_primeproj(field */*f*/, mp */*a*/, mp */*b*/);
-
-/* --- @ec_bin@, @ec_binproj@ --- *
- *
- * Arguments:  @field *f@ = the underlying field for this elliptic curve
- *             @mp *a, *b@ = the coefficients for this curve
- *
- * Returns:    A pointer to the curve, or null.
- *
- * Use:                Creates a curve structure for an elliptic curve defined over
- *             a binary field.  The @binproj@ variant uses projective
- *             coordinates, which can be a win.
- */
-
-extern ec_curve *ec_bin(field */*f*/, mp */*a*/, mp */*b*/);
-extern ec_curve *ec_binproj(field */*f*/, mp */*a*/, mp */*b*/);
-
-/*----- Curve parameter sets ----------------------------------------------*/
-
-/* --- @ec_curveparse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *
- * Returns:    Elliptic curve pointer if OK, or null.
- *
- * Use:                Parses an elliptic curve description, which has the form
- *
- *               * a field description
- *               * an optional `;'
- *               * `prime', `primeproj', `bin', or `binproj'
- *               * an optional `:'
- *               * the %$a$% parameter
- *               * an optional `,'
- *               * the %$b$% parameter
- */
-
-extern ec_curve *ec_curveparse(qd_parse */*qd*/);
-
-/* --- @ec_ptparse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *             @ec *p@ = where to put the point
- *
- * Returns:    The point address, or null.
- *
- * Use:                Parses an elliptic curve point.  This has the form
- *
- *               * %$x$%-coordinate
- *               * optional `,'
- *               * %$y$%-coordinate
- */
-
-extern ec *ec_ptparse(qd_parse */*qd*/, ec */*p*/);
-
-/* --- @ec_infoparse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *             @ec_info *ei@ = curve information block, currently
- *                     uninitialized
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Parses an elliptic curve information string, and stores the
- *             information in @ei@.  This has the form
- *
- *               * elliptic curve description
- *               * optional `;'
- *               * common point
- *               * optional `:'
- *               * group order
- *               * optional `*'
- *               * cofactor
- */
-
-extern int ec_infoparse(qd_parse */*qd*/, ec_info */*ei*/);
-
-/* --- @ec_infofromdata@ --- *
- *
- * Arguments:  @ec_info *ei@ = where to write the information
- *             @ecdata *ed@ = raw data
- *
- * Returns:    ---
- *
- * Use:                Loads elliptic curve information about one of the standard
- *             curves.
- */
-
-struct ecdata;
-extern void ec_infofromdata(ec_info */*ei*/, struct ecdata */*ed*/);
-
-/* --- @ec_getinfo@ --- *
- *
- * Arguments:  @ec_info *ei@ = where to write the information
- *             @const char *p@ = string describing a curve
- *
- * Returns:    Null on success, or a pointer to an error message.
- *
- * Use:                Parses out information about a curve.  The string is either a
- *             standard curve name, or a curve info string.
- */
-
-extern const char *ec_getinfo(ec_info */*ei*/, const char */*p*/);
-
-/* --- @ec_sameinfop@ --- *
- *
- * Arguments:  @ec_info *ei, *ej@ = two elliptic curve parameter sets
- *
- * Returns:    Nonzero if the curves are identical (not just isomorphic).
- *
- * Use:                Checks for sameness of curve parameters.
- */
-
-extern int ec_sameinfop(ec_info */*ei*/, ec_info */*ej*/);
-
-/* --- @ec_freeinfo@ --- *
- *
- * Arguments:  @ec_info *ei@ = elliptic curve information block to free
- *
- * Returns:    ---
- *
- * Use:                Frees the information block.
- */
-
-extern void ec_freeinfo(ec_info */*ei*/);
-
-/* --- @ec_checkinfo@ --- *
- *
- * Arguments:  @const ec_info *ei@ = elliptic curve information block
- *
- * Returns:    Null if OK, or pointer to error message.
- *
- * Use:                Checks an elliptic curve according to the rules in SEC1.
- */
-
-extern const char *ec_checkinfo(const ec_info */*ei*/, grand */*gr*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ecb-def.h b/ecb-def.h
deleted file mode 100644 (file)
index 08a25f6..0000000
--- a/ecb-def.h
+++ /dev/null
@@ -1,473 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ecb-def.h,v 1.4 2004/04/17 09:58:37 mdw Exp $
- *
- * Definitions electronic code book mode
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_ECB_DEF_H
-#define CATACOMB_ECB_DEF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_BLKC_H
-#  include "blkc.h"
-#endif
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @ECB_DEF@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use:                Creates an implementation for ECB stealing mode.
- */
-
-#define ECB_DEF(PRE, pre)                                              \
-                                                                       \
-/* --- @pre_ecbsetkey@ --- *                                           \
- *                                                                     \
- * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the ECB context to use a different cipher key.     \
- */                                                                    \
-                                                                       \
-void pre##_ecbsetkey(pre##_ecbctx *ctx, const pre##_ctx *k)            \
-{                                                                      \
-  ctx->ctx = *k;                                                       \
-}                                                                      \
-                                                                       \
-/* --- @pre_ecbinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_ecbctx *ctx@ = pointer to cipher context           \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes an ECB context ready for use.  This is      \
- *             equivalent to calls to @pre_init@ and @pre_setkey@.     \
- */                                                                    \
-                                                                       \
-void pre##_ecbinit(pre##_ecbctx *ctx,                                  \
-                    const void *key, size_t sz,                        \
-                    const void *iv)                                    \
-{                                                                      \
-  pre##_init(&ctx->ctx, key, sz);                                      \
-}                                                                      \
-                                                                       \
-/* --- @pre_ecbencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts a block with a block cipher in ECB mode, with  \
- *             ciphertext stealing and other clever tricks.            \
- *             Essentially, data can be encrypted in arbitrary sized   \
- *             chunks, although decryption must use the same chunks.   \
- */                                                                    \
-                                                                       \
-void pre##_ecbencrypt(pre##_ecbctx *ctx,                               \
-                       const void *src, void *dest,                    \
-                       size_t sz)                                      \
-{                                                                      \
-  const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz)                                                             \
-    return;                                                            \
-                                                                       \
-  /* --- Short blocks aren't allowed in ECB --- *                      \
-   *                                                                   \
-   * There's absolutely nothing secure I can do with them.             \
-   */                                                                  \
-                                                                       \
-  assert(((void)"ECB must have at least one whole block to work with", \
-         sz >= PRE##_BLKSZ));                                          \
-                                                                       \
-  /* --- Do the main chunk of encryption --- *                         \
-   *                                                                   \
-   * This will do the whole lot if it's a whole number of blocks.  Just        \
-   * give each block to the cipher in turn.  This is trivial.          \
-   * Hopefully...                                                      \
-   */                                                                  \
-                                                                       \
-  while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                 \
-    uint32 x[PRE##_BLKSZ / 4];                                         \
-    if (!s)                                                            \
-      BLKC_ZERO(PRE, x);                                               \
-    else {                                                             \
-      BLKC_LOAD(PRE, x, s);                                            \
-      s += PRE##_BLKSZ;                                                        \
-    }                                                                  \
-    pre##_eblk(&ctx->ctx, x, x);                                       \
-    if (d) {                                                           \
-      BLKC_STORE(PRE, d, x);                                           \
-      d += PRE##_BLKSZ;                                                        \
-    }                                                                  \
-    sz -= PRE##_BLKSZ;                                                 \
-  }                                                                    \
-                                                                       \
-  /* --- Do the tail-end block and bit-left-over --- *                 \
-   *                                                                   \
-   * This isn't very efficient.  That shouldn't matter much.           \
-   */                                                                  \
-                                                                       \
-  if (sz) {                                                            \
-    uint32 x[PRE##_BLKSZ / 4];                                         \
-    octet b[PRE##_BLKSZ];                                              \
-    unsigned i;                                                                \
-                                                                       \
-    /* --- Let @sz@ be the size of the partial block --- */            \
-                                                                       \
-    sz -= PRE##_BLKSZ;                                                 \
-                                                                       \
-    /* --- First stage --- *                                           \
-     *                                                                 \
-     * Read in the current block, and encrypt it.  The first part of   \
-     * the result is the partial ciphertext block.  Don't write that   \
-     * out yet, because I've not read the partial plaintext block.     \
-     */                                                                        \
-                                                                       \
-    if (!s)                                                            \
-      BLKC_ZERO(PRE, x);                                               \
-    else {                                                             \
-      BLKC_LOAD(PRE, x, s);                                            \
-      s += PRE##_BLKSZ;                                                        \
-    }                                                                  \
-    pre##_eblk(&ctx->ctx, x, x);                                       \
-    BLKC_STORE(PRE, b, x);                                             \
-                                                                       \
-    /* --- Second stage --- *                                          \
-     *                                                                 \
-     * Now move in the partial plaintext block, writing out the                \
-     * ciphertext as I go.  Then encrypt, and write the complete       \
-     * ciphertext block.                                               \
-     */                                                                        \
-                                                                       \
-    if (d) d += PRE##_BLKSZ;                                           \
-    for (i = 0; i < sz; i++) {                                         \
-      register octet y = b[i];                                         \
-      b[i] = s[i];                                                     \
-      if (d) d[i] = y;                                                 \
-    }                                                                  \
-    BLKC_LOAD(PRE, x, b);                                              \
-    pre##_eblk(&ctx->ctx, x, x);                                       \
-    if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, x);                                \
-  }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  return;                                                              \
-}                                                                      \
-                                                                       \
-/* --- @pre_ecbdecrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Decrypts a block with a block cipher in ECB mode, with  \
- *             ciphertext stealing and other clever tricks.            \
- *             Essentially, data can be encrypted in arbitrary sized   \
- *             chunks, although decryption must use the same chunks.   \
- */                                                                    \
-                                                                       \
-void pre##_ecbdecrypt(pre##_ecbctx *ctx,                               \
-                       const void *src, void *dest,                    \
-                       size_t sz)                                      \
-{                                                                      \
-  const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz)                                                             \
-    return;                                                            \
-                                                                       \
-  /* --- Short blocks aren't allowed in ECB --- *                      \
-   *                                                                   \
-   * There's absolutely nothing secure I can do with them.             \
-   */                                                                  \
-                                                                       \
-  assert(((void)"ECB must have at least one whole block to work with", \
-         sz >= PRE##_BLKSZ));                                          \
-                                                                       \
-  /* --- Do the main chunk of decryption --- *                         \
-   *                                                                   \
-   * This will do the whole lot if it's a whole number of blocks.      \
-   * Each block is just handed to the block cipher in turn.            \
-   */                                                                  \
-                                                                       \
-  while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                 \
-    uint32 x[PRE##_BLKSZ / 4];                                         \
-    BLKC_LOAD(PRE, x, s);                                              \
-    pre##_dblk(&ctx->ctx, x, x);                                       \
-    BLKC_STORE(PRE, d, x);                                             \
-    s += PRE##_BLKSZ;                                                  \
-    d += PRE##_BLKSZ;                                                  \
-    sz -= PRE##_BLKSZ;                                                 \
-  }                                                                    \
-                                                                       \
-  /* --- Do the tail-end block and bit-left-over --- *                 \
-   *                                                                   \
-   * This isn't very efficient.  That shouldn't matter much.           \
-   */                                                                  \
-                                                                       \
-  if (sz) {                                                            \
-    uint32 x[PRE##_BLKSZ / 4];                                         \
-    octet b[PRE##_BLKSZ];                                              \
-    unsigned i;                                                                \
-                                                                       \
-    /* --- Let @sz@ be the size of the partial block --- */            \
-                                                                       \
-    sz -= PRE##_BLKSZ;                                                 \
-                                                                       \
-    /* --- First stage --- *                                           \
-     *                                                                 \
-     * Take the complete ciphertext block, and decrypt it.  This block \
-     * is carried over for the next encryption operation.              \
-     */                                                                        \
-                                                                       \
-    BLKC_LOAD(PRE, x, s);                                              \
-    pre##_dblk(&ctx->ctx, x, x);                                       \
-    BLKC_STORE(PRE, b, x);                                             \
-                                                                       \
-    /* --- Second stage --- *                                          \
-     *                                                                 \
-     * The first few bytes are the partial plaintext block.  Write that        \
-     * and replace with the partial ciphertext block.  Then decrypt    \
-     * what's left as the complete plaintext.                          \
-     */                                                                        \
-                                                                       \
-    s += PRE##_BLKSZ;                                                  \
-    d += PRE##_BLKSZ;                                                  \
-    for (i = 0; i < sz; i++) {                                         \
-      register octet y = s[i];                                         \
-      d[i] = b[i];                                                     \
-      b[i] = y;                                                                \
-    }                                                                  \
-    BLKC_LOAD(PRE, x, b);                                              \
-    pre##_dblk(&ctx->ctx, x, x);                                       \
-    BLKC_STORE(PRE, d - PRE##_BLKSZ, x);                               \
-  }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  return;                                                              \
-}                                                                      \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-static const gcipher_ops gops;                                         \
-                                                                       \
-typedef struct gctx {                                                  \
-  gcipher c;                                                           \
-  pre##_ecbctx k;                                                      \
-} gctx;                                                                        \
-                                                                       \
-static gcipher *ginit(const void *k, size_t sz)                                \
-{                                                                      \
-  gctx *g = S_CREATE(gctx);                                            \
-  g->c.ops = &gops;                                                    \
-  pre##_ecbinit(&g->k, k, sz, 0);                                      \
-  return (&g->c);                                                      \
-}                                                                      \
-                                                                       \
-static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_ecbencrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
-                                                                       \
-static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_ecbdecrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
-                                                                       \
-static void gdestroy(gcipher *c)                                       \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static const gcipher_ops gops = {                                      \
-  &pre##_ecb,                                                          \
-  gencrypt, gdecrypt, gdestroy, 0, 0                                   \
-};                                                                     \
-                                                                       \
-const gccipher pre##_ecb = {                                           \
-  #pre "-ecb", pre##_keysz, PRE##_BLKSZ,                               \
-  ginit                                                                        \
-};                                                                     \
-                                                                       \
-ECB_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @ECB_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use:                Standard test rig for ECB functions.
- */
-
-#define ECB_TEST(PRE, pre)                                             \
-                                                                       \
-/* --- Initial plaintext for the test --- */                           \
-                                                                       \
-static const octet text[] = TEXT;                                      \
-                                                                       \
-/* --- Key and IV to use --- */                                                \
-                                                                       \
-static const octet key[] = KEY;                                                \
-static const octet iv[] = IV;                                          \
-                                                                       \
-/* --- Buffers for encryption and decryption output --- */             \
-                                                                       \
-static octet ct[sizeof(text)];                                         \
-static octet pt[sizeof(text)];                                         \
-                                                                       \
-static void hexdump(const octet *p, size_t sz)                         \
-{                                                                      \
-  const octet *q = p + sz;                                             \
-  for (sz = 0; p < q; p++, sz++) {                                     \
-    printf("%02x", *p);                                                        \
-    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
-      putchar(':');                                                    \
-  }                                                                    \
-}                                                                      \
-                                                                       \
-int main(void)                                                         \
-{                                                                      \
-  size_t sz = 0, rest;                                                 \
-  pre##_ecbctx ctx;                                                    \
-  int status = 0;                                                      \
-  int done = 0;                                                                \
-                                                                       \
-  size_t keysz = PRE##_KEYSZ ?                                         \
-    PRE##_KEYSZ : strlen((const char *)key);                           \
-                                                                       \
-  fputs(#pre "-ecb: ", stdout);                                                \
-                                                                       \
-  pre##_ecbinit(&ctx, key, keysz, iv);                                 \
-                                                                       \
-  while (sz <= sizeof(text)) {                                         \
-    rest = sizeof(text) - sz;                                          \
-    if ((sz != 0 && sz < PRE##_BLKSZ) ||                               \
-       (rest != 0 && rest < PRE##_BLKSZ))                              \
-      goto next;                                                       \
-    memcpy(ct, text, sizeof(text));                                    \
-    pre##_ecbencrypt(&ctx, ct, ct, sz);                                        \
-    pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest);                    \
-    memcpy(pt, ct, sizeof(text));                                      \
-    pre##_ecbdecrypt(&ctx, pt, pt, sz);                                        \
-    pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest);                    \
-    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
-      done++;                                                          \
-      if (sizeof(text) < 40 || done % 8 == 0)                          \
-       fputc('.', stdout);                                             \
-      if (done % 480 == 0)                                             \
-       fputs("\n\t", stdout);                                          \
-      fflush(stdout);                                                  \
-    } else {                                                           \
-      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
-      status = 1;                                                      \
-      printf("\tplaintext      = "); hexdump(text, sz);                        \
-       printf(", "); hexdump(text + sz, rest);                         \
-       fputc('\n', stdout);                                            \
-      printf("\tciphertext     = "); hexdump(ct, sz);                  \
-       printf(", "); hexdump(ct + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      printf("\trecovered text = "); hexdump(pt, sz);                  \
-       printf(", "); hexdump(pt + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      fputc('\n', stdout);                                             \
-    }                                                                  \
-  next:                                                                        \
-    if (sz < 63)                                                       \
-      sz++;                                                            \
-    else                                                               \
-      sz += 9;                                                         \
-  }                                                                    \
-                                                                       \
-  fputs(status ? " failed\n" : " ok\n", stdout);                       \
-  return (status);                                                     \
-}
-
-#else
-#  define ECB_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ecb.h b/ecb.h
deleted file mode 100644 (file)
index ed39310..0000000
--- a/ecb.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ecb.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Electronic code book for block ciphers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_ECB_H
-#define CATACOMB_ECB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @ECB_DECL@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use:                Creates declarations for ECB stealing mode.
- */
-
-#define ECB_DECL(PRE, pre)                                             \
-                                                                       \
-/* --- Electronic codebook context --- */                              \
-                                                                       \
-typedef struct pre##_ecbctx {                                          \
-  pre##_ctx ctx;                       /* Underlying cipher context */ \
-} pre##_ecbctx;                                                                \
-                                                                       \
-/* --- @pre_ecbsetkey@ --- *                                           \
- *                                                                     \
- * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the ECB context to use a different cipher key.     \
- */                                                                    \
-                                                                       \
-extern void pre##_ecbsetkey(pre##_ecbctx */*ctx*/,                     \
-                           const pre##_ctx */*k*/);                    \
-                                                                       \
-/* --- @pre_ecbinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_ecbctx *ctx@ = pointer to cipher context           \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes an ECB context ready for use.  This is      \
- *             equivalent to calls to @pre_init@ and @pre_setkey@.     \
- */                                                                    \
-                                                                       \
-extern void pre##_ecbinit(pre##_ecbctx */*ctx*/,                       \
-                         const void */*key*/, size_t /*sz*/,           \
-                         const void */*iv*/);                          \
-                                                                       \
-/* --- @pre_ecbencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts a block with a block cipher in ECB mode, with  \
- *             ciphertext stealing and other clever tricks.            \
- *             Essentially, data can be encrypted in arbitrary sized   \
- *             chunks, although decryption must use the same chunks.   \
- */                                                                    \
-                                                                       \
-extern void pre##_ecbencrypt(pre##_ecbctx */*ctx*/,                    \
-                            const void */*src*/, void */*dest*/,       \
-                            size_t /*sz*/);                            \
-                                                                       \
-/* --- @pre_ecbdecrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Decrypts a block with a block cipher in ECB mode, with  \
- *             ciphertext stealing and other clever tricks.            \
- *             Essentially, data can be encrypted in arbitrary sized   \
- *             chunks, although decryption must use the same chunks.   \
- */                                                                    \
-                                                                       \
-extern void pre##_ecbdecrypt(pre##_ecbctx */*ctx*/,                    \
-                            const void */*src*/, void */*dest*/,       \
-                            size_t /*sz*/);                            \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-extern const gccipher pre##_ecb;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ectab.h b/ectab.h
deleted file mode 100644 (file)
index 7e6161c..0000000
--- a/ectab.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ectab.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Table of standard elliptic curves
- *
- * (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.
- */
-
-#ifndef CATACOMB_ECTAB_H
-#define CATACOMB_ECTAB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "ec.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct ecdata {
-  unsigned ftag;                       /* The kind of curve this is */
-  mp p, beta;                          /* Modulus, and conversion magic */
-  mp a, b;                             /* Elliptic curve parameters */
-  mp r;                                        /* Order of common point %$g$% */
-  mp h;                                        /* Cofactor %$h = \#E/r$% */
-  mp gx, gy;                           /* Common point */
-} ecdata;
-
-enum {
-  FTAG_PRIME,                          /* Prime but not nice */
-  FTAG_NICEPRIME,                      /* Nice prime field */
-  FTAG_BINPOLY,                                /* Binary field, poly basis */
-  FTAG_BINNORM                         /* Binary field, normal basis */
-};
-
-typedef struct ecentry {
-  const char *name;
-  ecdata *data;
-} ecentry;
-
-/*----- Global variables --------------------------------------------------*/
-
-extern const ecentry ectab[];
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ectab.in b/ectab.in
deleted file mode 100644 (file)
index 238accb..0000000
--- a/ectab.in
+++ /dev/null
@@ -1,636 +0,0 @@
-# $Id$
-#
-# Standard ellipic curves
-
-#----- Curves from SEC2 -----------------------------------------------------
-
-curve secp112r1 prime
-  p 0xdb7c2abf62e35e668076bead208b
-  a 0xdb7c2abf62e35e668076bead2088
-  b 0x659ef8ba043916eede8911702b22
-  r 0xdb7c2abf62e35e7628dfac6561c5
-  h 1
-  gx 0x09487239995a5ee76b55f9c2f098
-  gy 0xa89ce5af8724c0a23e0e0ff77500
-curve secp112r2 prime
-  p 0xdb7c2abf62e35e668076bead208b
-  a 0x6127c24c05f38a0aaaf65c0ef02c
-  b 0x51def1815db5ed74fcc34c85d709
-  r 0x36df0aafd8b8d7597ca10520d04b
-  h 4
-  gx 0x4ba30ab5e892b4e1649dd0928643
-  gy 0xadcd46f5882e3747def36e956e97
-
-curve secp128r1 niceprime
-  p 0xfffffffdffffffffffffffffffffffff
-  a 0xfffffffdfffffffffffffffffffffffc
-  b 0xe87579c11079f43dd824993c2cee5ed3
-  r 0xfffffffe0000000075a30d1b9038a115
-  h 1
-  gx 0x161ff7528b899b2d0c28607ca52c5b86
-  gy 0xcf5ac8395bafeb13c02da292dded7a83
-curve secp128r2 niceprime
-  p 0xfffffffdffffffffffffffffffffffff
-  a 0xd6031998d1b3bbfebf59cc9bbff9aee1
-  b 0x5eeefca380d02919dc2c6558bb6d8a5d
-  r 0x3fffffff7fffffffbe0024720613b5a3
-  h 4
-  gx 0x7b6aa5d85e572983e6fb32a7cdebc140
-  gy 0x27b6916a894d3aee7106fe805fc34b44
-
-curve secp160k1 niceprime
-  p 0xfffffffffffffffffffffffffffffffeffffac73
-  a 0
-  b 7
-  r 0x0100000000000000000001b8fa16dfab9aca16b6b3
-  h 1
-  gx 0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebb
-  gy 0x938cf935318fdced6bc28286531733c3f03c4fee
-curve secp160r1 niceprime
-  p 0xffffffffffffffffffffffffffffffff7fffffff
-  a 0xffffffffffffffffffffffffffffffff7ffffffc
-  b 0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45
-  r 0x0100000000000000000001f4c8f927aed3ca752257
-  h 1
-  gx 0x4a96b5688ef573284664698968c38bb913cbfc82
-  gy 0x23a628553168947d59dcc912042351377ac5fb32
-curve secp160r2 niceprime
-  p 0xfffffffffffffffffffffffffffffffeffffac73
-  a 0xfffffffffffffffffffffffffffffffeffffac70
-  b 0xb4e134d3fb59eb8bab57274904664d5af50388ba
-  r 0x0100000000000000000000351ee786a818f3a1a16b
-  h 1
-  gx 0x52dcb034293a117e1f4ff11b30f7199d3144ce6d
-  gy 0xfeaffef2e331f296e071fa0df9982cfea7d43f2e
-
-curve secp192k1 niceprime
-  p 0xfffffffffffffffffffffffffffffffffffffffeffffee37
-  a 0
-  b 3
-  r 0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d
-  h 1
-  gx 0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d
-  gy 0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d
-curve secp192r1 niceprime
-  p 0xfffffffffffffffffffffffffffffffeffffffffffffffff
-  a 0xfffffffffffffffffffffffffffffffefffffffffffffffc
-  b 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1
-  r 0xffffffffffffffffffffffff99def836146bc9b1b4d22831
-  h 1
-  gx 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
-  gy 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811
-
-curve secp224k1 niceprime
-  p 0xfffffffffffffffffffffffffffffffffffffffffffffffeffffe56d
-  a 0
-  b 5
-  r 0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7
-  h 1
-  gx 0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c
-  gy 0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5
-curve secp224r1 niceprime
-  p 0xffffffffffffffffffffffffffffffff000000000000000000000001
-  a 0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe
-  b 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
-  r 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
-  h 1
-  gx 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
-  gy 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34
-
-curve secp256k1 niceprime
-  p 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
-  a 0
-  b 7
-  r 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
-  h 1
-  gx 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
-  gy 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
-curve secp256r1 niceprime
-  p 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
-  a 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc
-  b 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
-  r 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
-  h 1
-  gx 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
-  gy 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
-
-curve secp384r1 niceprime
-  p 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff
-  a 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc
-  b 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef
-  r 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973
-  h 1
-  gx 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7
-  gy 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f
-
-curve secp521r1 niceprime
-  p 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  a 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc
-  b 0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00
-  r 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409
-  h 1
-  gx 0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66
-  gy 0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650
-
-curve sect113r1 binpoly
-  p 0x20000000000000000000000000201
-  a 0x003088250ca6e7c7fe649ce85820f7
-  b 0x00e8bee4d3e2260744188be0e9c723
-  r 0x0100000000000000d9ccec8a39e56f
-  h 2
-  gx 0x009d73616f35f4ab1407d73562c10f
-  gy 0x00a52830277958ee84d1315ed31886
-curve sect113r2 binpoly
-  p 0x20000000000000000000000000201
-  a 0x00689918dbec7e5a0dd6dfc0aa55c7
-  b 0x0095e9a9ec9b297bd4bf36e059184f
-  r 0x010000000000000108789b2496af93
-  h 2
-  gx 0x01a57a6a7b26ca5ef52fcdb8164797
-  gy 0x00b3adc94ed1fe674c06e695baba1d
-
-curve sect131r1 binpoly
-  p 0x80000000000000000000000000000010d
-  a 0x07a11b09a76b562144418ff3ff8c2570b8
-  b 0x0217c05610884b63b9c6c7291678f9d341
-  r 0x0400000000000000023123953a9464b54d
-  h 2
-  gx 0x0081baf91fdf9833c40f9c181343638399
-  gy 0x078c6e7ea38c001f73c8134b1b4ef9e150
-curve sect131r2 binpoly
-  p 0x80000000000000000000000000000010d
-  a 0x03e5a88919d7cafcbf415f07c2176573b2
-  b 0x04b8266a46c55657ac734ce38f018f2192
-  r 0x0400000000000000016954a233049ba98f
-  h 2
-  gx 0x0356dcd8f2f95031ad652d23951bb366a8
-  gy 0x0648f06d867940a5366d9e265de9eb240f
-
-curve sect163k1 binpoly
-  p 0x800000000000000000000000000000000000000c9
-  a 1
-  b 1
-  r 0x04000000000000000000020108a2e0cc0d99f8a5ef
-  h 2
-  gx 0x02fe13c0537bbc11acaa07d793de4e6d5e5c94eee8
-  gy 0x0289070fb05d38ff58321f2e800536d538ccdaa3d9
-curve sect163r1 binpoly
-  p 0x800000000000000000000000000000000000000c9
-  a 0x07b6882caaefa84f9554ff8428bd88e246d2782ae2
-  b 0x0713612dcddcb40aab946bda29ca91f73af958afd9
-  r 0x03ffffffffffffffffffff48aab689c29ca710279b
-  h 2
-  gx 0x0369979697ab43897789566789567f787a7876a654
-  gy 0x00435edb42efafb2989d51fefce3c80988f41ff883
-curve sect163r2 binpoly
-  p 0x800000000000000000000000000000000000000c9
-  a 1
-  b 0x020a601907b8c953ca1481eb10512f78744a3205fd
-  r 0x040000000000000000000292fe77e70c12a4234c33
-  h 2
-  gx 0x03f0eba16286a2d57ea0991168d4994637e8343e36
-  gy 0x00d51fbc6c71a0094fa2cdd545b11c5c0c797324f1
-
-curve sect193r1 binpoly
-  p 0x2000000000000000000000000000000000000000000008001
-  a 0x0017858feb7a98975169e171f77b4087de098ac8a911df7b01
-  b 0x00fdfb49bfe6c3a89facadaa7a1e5bbc7cc1c2e5d831478814
-  r 0x01000000000000000000000000c7f34a778f443acc920eba49
-  h 2
-  gx 0x01f481bc5f0ff84a74ad6cdf6fdef4bf6179625372d8c0c5e1
-  gy 0x0025e399f2903712ccf3ea9e3a1ad17fb0b3201b6af7ce1b05
-curve sect193r2 binpoly
-  p 0x2000000000000000000000000000000000000000000008001
-  a 0x0163f35a5137c2ce3ea6ed8667190b0bc43ecd69977702709b
-  b 0x00c9bb9e8927d4d64c377e2ab2856a5b16e3efb7f61d4316ae
-  r 0x010000000000000000000000015aab561b005413ccd4ee99d5
-  h 2
-  gx 0x00d9b67d192e0367c803f39e1a7e82ca14a651350aae617e8f
-  gy 0x01ce94335607c304ac29e7defbd9ca01f596f927224cdecf6c
-
-curve sect233k1 binpoly
-  p 0x20000000000000000000000000000000000000004000000000000000001
-  a 0
-  b 1
-  r 0x8000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf
-  h 4
-  gx 0x017232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126
-  gy 0x01db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3
-curve sect233r1 binpoly
-  p 0x20000000000000000000000000000000000000004000000000000000001
-  a 1
-  b 0x0066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad
-  r 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7
-  h 2
-  gx 0x00fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b
-  gy 0x01006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052
-
-curve sect239k1 binpoly
-  p 0x800000000000000000004000000000000000000000000000000000000001
-  a 0
-  b 1
-  r 0x2000000000000000000000000000005a79fec67cb6e91f1c1da800e478a5
-  h 4
-  gx 0x29a0b6a887a983e9730988a68727a8b2d126c44cc2cc7b2a6555193035dc
-  gy 0x76310804f12e549bdb011c103089e73510acb275fc312a5dc6b76553f0ca
-
-curve sect283k1 binpoly
-  p 0x800000000000000000000000000000000000000000000000000000000000000000010a1
-  a 0
-  b 1
-  r 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61
-  h 4
-  gx 0x0503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836
-  gy 0x01ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259
-curve sect283r1 binpoly
-  p 0x800000000000000000000000000000000000000000000000000000000000000000010a1
-  a 1
-  b 0x027b680ac8b8596da5a4af8a19a0303fca97fd7645309fa2a581485af6263e313b79a2f5
-  r 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307
-  h 2
-  gx 0x05f939258db7dd90e1934f8c70b0dfec2eed25b8557eac9c80e2e198f8cdbecd86b12053
-  gy 0x03676854fe24141cb98fe6d4b20d02b4516ff702350eddb0826779c813f0df45be8112f4
-
-curve sect409k1 binpoly
-  p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
-  a 0
-  b 1
-  r 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf
-  h 4
-  gx 0x0060f05f658f49c1ad3ab1890f7184210efd0987e307c84c27accfb8f9f67cc2c460189eb5aaaa62ee222eb1b35540cfe9023746
-  gy 0x01e369050b7c4e42acba1dacbf04299c3460782f918ea427e6325165e9ea10e3da5f6c42e9c55215aa9ca27a5863ec48d8e0286b
-curve sect409r1 binpoly
-  p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
-  a 1
-  b 0x0021a5c2c8ee9feb5c4b9a753b7b476b7fd6422ef1f3dd674761fa99d6ac27c8a9a197b272822f6cd57a55aa4f50ae317b13545f
-  r 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173
-  h 2
-  gx 0x015d4860d088ddb3496b0c6064756260441cde4af1771d4db01ffe5b34e59703dc255a868a1180515603aeab60794e54bb7996a7
-  gy 0x0061b1cfab6be5f32bbfa78324ed106a7636b9c5a7bd198d0158aa4f5488d08f38514f1fdf4b4f40d2181b3681c364ba0273c706
-
-curve sect571k1 binpoly
-  p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
-  a 0
-  b 1
-  r 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001
-  h 4
-  gx 0x026eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972
-  gy 0x0349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3
-curve sect571r1 binpoly
-  p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
-  a 1
-  b 0x02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a
-  r 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47
-  h 2
-  gx 0x0303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19
-  gy 0x037bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b
-
-#----- Curves from ANSI X9.62 -----------------------------------------------
-#
-# The conversion factors for the normal basis representations were generated
-# because none were given in the document.
-
-curve ansi-c2pnb163v1 binpoly
-  p 0x080000000000000000000000000000000000000107
-  a 0x072546b5435234a422e0789675f432c89435de5242
-  b 0x00c9517d06d5240d3cff38c74b20b6cd4d6f9dd4d9
-  r 0x0400000000000000000001e60fc8821cc74daeafc1
-  h 2
-  gx 0x07af69989546103d79329fcc3d74880f33bbe803cb
-  gy 0x01ec23211b5966adea1d3f87f7ea5848aef0b7ca9f
-curve ansi-c2pnb163v2 binpoly
-  p 0x080000000000000000000000000000000000000107
-  a 0x0108b39e77c4b108bed981ed0e890e117c511cf072
-  b 0x0667aceb38af4e488c407433ffae4f1c811638df20
-  r 0x03fffffffffffffffffffdf64de1151adbb78f10a7
-  h 2
-  gx 0x0024266e4eb5106d0a964d92c4860e2671db9b6cc5
-  gy 0x079f684ddf6684c5cd258b3890021b2386dfd19fc5
-curve ansi-c2pnb163v3 binpoly
-  p 0x080000000000000000000000000000000000000107
-  a 0x07a526c63d3e25a256a007699f5447e32ae456b50e
-  b 0x03f7061798eb99e238fd6f1bf95b48feeb4854252b
-  r 0x03fffffffffffffffffffe1aee140f110aff961309
-  h 2
-  gx 0x02f9f87b7c574d0bdecf8a22e6524775f98cdebdcb
-  gy 0x05b935590c155e17ea48eb3ff3718b893df59a05d0
-
-curve ansi-c2tnb191v1 binpoly
-  p 0x800000000000000000000000000000000000000000000201
-  a 0x2866537b676752636a68f56554e12640276b649ef7526267
-  b 0x2e45ef571f00786f67b0081b9495a3d95462f5de0aa185ec
-  r 0x40000000000000000000000004a20e90c39067c893bbb9a5
-  h 2
-  gx 0x36b3daf8a23206f9c4f299d7b21a9c369137f2c84ae1aa0d
-  gy 0x765be73433b3f95e332932e70ea245ca2418ea0ef98018fb
-curve ansi-c2tnb191v2 binpoly
-  p 0x800000000000000000000000000000000000000000000201
-  a 0x401028774d7777c7b7666d1366ea432071274f89ff01e718
-  b 0x0620048d28bcbd03b6249c99182b7c8cd19700c362c46a01
-  r 0x20000000000000000000000050508cb89f652824e06b8173
-  h 4
-  gx 0x3809b2b7cc1b28cc5a87926aad83fd28789e81e2c9e3bf10
-  gy 0x17434386626d14f3dbf01760d9213a3e1cf37aec437d668a
-curve ansi-c2tnb191v3 binpoly
-  p 0x800000000000000000000000000000000000000000000201
-  a 0x6c01074756099122221056911c77d77e77a777e7e7e77fcb
-  b 0x71fe1af926cf847989efef8db459f66394d90f32ad3f15e8
-  r 0x155555555555555555555555610c0b196812bfb6288a3ea3
-  h 6
-  gx 0x375d4ce24fde434489de8746e71786015009e66e38a926dd
-  gy 0x545a39176196575d985999366e6ad34ce0a77cd7127b06be
-curve ansi-c2onb191v1 binnorm
-  p 0x800000000000000000000000000000000000000000000201
-  beta 0x19c409a7f85383bf0ef72b097a5c7398013a2dba6269292d
-  a 0x65903e04e1e4924253e26a3c9ac28c758bd8184a3fb680e8
-  b 0x54678621b190cfce282ade219d5b3a065e3f4b3ffdebb29b
-  r 0x4000000000000000000000009cf2d6e3901dac4c32eec65d
-  h 2
-  gx 0x5a2c69a32e8638e51ccefaad05350a978457cb5fb6df994a
-  gy 0x0f32fe0fa0e902f19b17d363c269f4f5cfe8087618569954
-curve ansi-c2onb191v2 binnorm
-  p 0x800000000000000000000000000000000000000000000201
-  beta 0x19c409a7f85383bf0ef72b097a5c7398013a2dba6269292d
-  a 0x25f8d06c97c822536d469cd5170cdd7bb9f500bd6db110fb
-  b 0x75ff570e35ca94fb3780c2619d081c17aa59fbd5e591c1c4
-  r 0x0fffffffffffffffffffffffeeb354b7270b2992b7818627
-  h 8
-  gx 0x2a16910e8f6c4b199be24213857abc9c992edfb2471f3c68
-  gy 0x1592dbfebeb81a7c071b744d5e2f9e242ea65b81138a3468  
-
-curve ansi-c2tnb239v1 binpoly
-  p 0x800000000000000000000000000000000000000000000000001000000001
-  a 0x32010857077c5431123a46b808906756f543423e8d27877578125778ac76
-  b 0x790408f2eedaf392b012edefb3392f30f4327c0ca3f31fc383c422aa8c16
-  r 0x2000000000000000000000000000000f4d42ffe1492a4993f1cad666e447
-  h 4
-  gx 0x57927098fa932e7c0a96d3fd5b706ef7e5f5c156e16b7e7c86038552e91d
-  gy 0x61d8ee5077c33fecf6f1a16b268de469c3c7744ea9a971649fc7a9616305
-curve ansi-c2tnb239v2 binpoly
-  p 0x800000000000000000000000000000000000000000000000001000000001
-  a 0x4230017757a767fae42398569b746325d45313af0766266479b75654e65f
-  b 0x5037ea654196cff0cd82b2c14a2fcf2e3ff8775285b545722f03eacdb74b
-  r 0x1555555555555555555555555555553c6f2885259c31e3fcdf154624522d
-  h 6
-  gx 0x28f9d04e900069c8dc47a08534fe76d2b900b7d7ef31f5709f200c4ca205
-  gy 0x5667334c45aff3b5a03bad9dd75e2c71a99362567d5453f7fa6e227ec833
-curve ansi-c2tnb239v3 binpoly
-  p 0x800000000000000000000000000000000000000000000000001000000001
-  a 0x01238774666a67766d6676f778e676b66999176666e687666d8766c66a9f
-  b 0x6a941977ba9f6a435199acfc51067ed587f519c5ecb541b8e44111de1d40
-  r 0x0cccccccccccccccccccccccccccccac4912d2d9df903ef9888b8a0e4cff
-  h 10
-  gx 0x70f6e9d04d289c4e89913ce3530bfde903977d42b146d539bf1bde4e9c92
-  gy 0x2e5a0eaf6e5e1305b9004dce5c0ed7fe59a35608f33837c816d80b79f461
-curve ansi-c2onb239v1 binnorm
-  p 0x800000000000000000000000000000000000000000000000001000000001
-  beta 0x3b5ce9846911b248f9347018a7ac8cce3662cee952ba45becd02d4b903ec
-  a 0x182dd45f5d470239b8983fea47b8b292641c57f9bf84baecde8bb3adce30
-  b 0x147a9c1d4c2ce9be5d34ec02797f76667ebad5a3f93fa2a524bfde91ef28
-  r 0x200000000000000000000000000000474f7e69f42fe430931d0b455aae8b
-  h 4
-  gx 0x4912ad657f1d1c6b32edb9942c95e226b06fb012cd40fdea0d72197c8104
-  gy 0x01f1fbc3d21168fd3f66c441c2b5c6cfdcd9ed3e13646b7a4db9a3b0c286
-curve ansi-c2onb239v2 binnorm
-  p 0x800000000000000000000000000000000000000000000000001000000001
-  beta 0x3b5ce9846911b248f9347018a7ac8cce3662cee952ba45becd02d4b903ec
-  a 0x1ecf1b9d28d8017505e17475d3df2982e243ca5cb5e9f94a3f36124a486e
-  b 0x3ee257250d1a2e66cef23aa0f25b12388de8a10ff9554f90afbaa9a08b6d
-  r 0x1555555555555555555555555555558cf77a5d0589d2a9340d963b7ad703
-  h 6
-  gx 0x5f949ccb694f26b96d191e8925205a719929e93c37174cb6c7f659a37b85
-  gy 0x2d788d605ac81069e9964fd6edbae8bbf582a5c409a1078cf487a147ceb2
-  ## The spec seems bogus: the suggested base point G isn't in the
-  ## subgroup!  The point above is h G.
-  ##gx 0x193279fc543e9f5f7119189785b9c60b249be4820baf6c24bdfa2813f8b8
-  ##gy 0x5da021e5af77604051fc5c38da8293c1eeeaa00f046eeb93b6c8b774bb9b
-
-curve ansi-c2tnb359v1 binpoly
-  p 0x800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001
-  a 0x5667676a654b20754f356ea92017d946567c46675556f19556a04616b567d223a5e05656fb549016a96656a557
-  b 0x2472e2d0197c49363f1fe7f5b6db075d52b6947d135d8ca445805d39bc345626089687742b6329e70680231988
-  r 0x01af286bca1af286bca1af286bca1af286bca1af286bc9fb8f6b85c556892c20a7eb964fe7719e74f490758d3b
-  h 76
-  gx 0x3c258ef3047767e7ede0f1fdaa79daee3841366a132e163aced4ed2401df9c6bdcde98e8e707c07a2239b1b097
-  gy 0x53d7e08529547048121e9c95f3791dd804963948f34fae7bf44ea82365dc7868fe57e4ae2de211305a407104bd
-
-curve ansi-c2tnb431v1 binpoly
-  p 0x800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001
-  a 0x1a827ef00dd6fc0e234caf046c6a5d8a85395b236cc4ad2cf32a0cadbdc9ddf620b0eb9906d0957f6c6feacd615468df104de296cd8f
-  b 0x10d9b4a3d9047d8b154359abfb1b7f5485b04ceb868237ddc9deda982a679a5a919b626d4e50a8dd731b107a9962381fb5d807bf2618
-  r 0x000340340340340340340340340340340340340340340340340340340323c313fab50589703b5ec68d3587fec60d161cc149c1ad4a91
-  h 10080
-  gx 0x120fc05d3c67a99de161d2f4092622feca701be4f50f4758714e8a87bbf2a658ef8c21e7c5efe965361f6c2999c0c247b0dbd70ce6b7
-  gy 0x20d0af8903a96f8d5fa2c255745d3c451b302c9346d9b7e485e7bce41f6b591f3e8f6addcbb0bc4c2f947a7de1a89b625d6a598b3760
-
-# These curves aren't included because their degree isn't prime (so they
-# may be vulnerable to Weil descent)
-# ansi-c2pnb176w1 is bad: 176 isn't prime
-# ansi-c2pnb208v1 is bad: 208 isn't prime
-# ansi-c2pnb272w1 is bad: 272 isn't prime
-# ansi-c2pnb304w1 is bad: 304 isn't prime
-# ansi-c2pnb368w1 is bad: 368 isn't prime
-
-alias ansi-prime192v1 secp192r1
-curve ansi-prime192v2 niceprime
-  p 0xfffffffffffffffffffffffffffffffeffffffffffffffff
-  a 0xfffffffffffffffffffffffffffffffefffffffffffffffc
-  b 0xcc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953
-  r 0xfffffffffffffffffffffffe5fb1a724dc80418648d8dd31
-  h 1
-  gx 0xeea2bae7e1497842f2de7769cfe9c989c072ad696f48034a
-  gy 0x6574d11d69b6ec7a672bb82a083df2f2b0847de970b2de15
-curve ansi-prime192v3 niceprime
-  p 0xfffffffffffffffffffffffffffffffeffffffffffffffff
-  a 0xfffffffffffffffffffffffffffffffefffffffffffffffc
-  b 0x22123dc2395a05caa7423daeccc94760a7d462256bd56916
-  r 0xffffffffffffffffffffffff7a62d031c83f4294f640ec13
-  h 1
-  gx 0x7d29778100c65a1da1783716588dce2b8b4aee8e228f1896
-  gy 0x38a90f22637337334b49dcb66a6dc8f9978aca7648a943b0
-
-curve ansi-prime239v1 niceprime
-  p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff
-  a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc
-  b 0x6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a
-  r 0x7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b
-  h 1
-  gx 0x0ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf
-  gy 0x7debe8e4e90a5dae6e4054ca530ba04654b36818ce226b39fccb7b02f1ae
-curve ansi-prime239v2 niceprime
-  p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff
-  a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc
-  b 0x617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c
-  r 0x7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063
-  h 1
-  gx 0x38af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7
-  gy 0x5b0125e4dbea0ec7206da0fc01d9b081329fb555de6ef460237dff8be4ba
-curve ansi-prime239v3 niceprime
-  p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff
-  a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc
-  b 0x255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e
-  r 0x7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551
-  h 1
-  gx 0x6768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a
-  gy 0x1607e6898f390c06bc1d552bad226f3b6fcfe48b6e818499af18e3ed6cf3
-
-alias ansi-prime256v1 secp256r1
-
-#----- Curves from ANSI X9.63 -----------------------------------------------
-#
-# These are just duplicates of the SEC curves.
-
-alias ansit163k1 sect163k1
-alias ansit163r1 sect163r1
-alias ansit163r2 sect163r2
-alias ansit193r1 sect193r1
-alias ansit193r2 sect193r2
-alias ansit233k1 sect233k1
-alias ansit233r1 sect233r1
-alias ansit239k1 sect239k1
-alias ansit283k1 sect283k1
-alias ansit283r1 sect283r1
-alias ansit409k1 sect409k1
-alias ansit409r1 sect409r1
-alias ansit571k1 sect571k1
-alias ansit571r1 sect571r1
-
-alias ansip160k1 secp160k1
-alias ansip160r1 secp160r1
-alias ansip160r2 secp160r2
-alias ansip192k1 secp192k1
-alias ansip192r1 secp192r1
-alias ansip224k1 secp224k1
-alias ansip224r1 secp224r1
-alias ansip256k1 secp256k1
-alias ansip256r1 secp256r1
-alias ansip384r1 secp384r1
-alias ansip521r1 secp521r1
-
-#----- Curves from RFC2414 (Oakley) -----------------------------------------
-#
-# The Oakley curves are not good:
-#   oakley155 has too large a cofactor
-#   oakley185's field has composite degree
-# Hence, we include neither here.
-
-#----- NIST curves from FIPS186-2 -------------------------------------------
-#
-# These are duplicates of SEC2 curves.  However, the normal basis
-# representations aren't in SEC, so we give them here.  (Conversion factors
-# from FIPS186-2.
-
-alias nist-p192 secp192r1
-alias nist-p224 secp224r1
-alias nist-p256 secp256r1
-alias nist-p384 secp384r1
-alias nist-p521 secp521r1
-
-alias nist-k163 sect163k1
-alias nist-k233 sect233k1
-alias nist-k283 sect283k1
-alias nist-k409 sect409k1
-alias nist-k571 sect571k1
-
-alias nist-b163 sect163r2
-alias nist-b233 sect233r1
-alias nist-b283 sect283r1
-alias nist-b409 sect409r1
-alias nist-b571 sect571r1
-
-curve nist-k163n binnorm
-  p 0x800000000000000000000000000000000000000c9
-  beta 0x715169c109c612e390d347c748342bcd3b02a0bef
-  a 0x7ffffffffffffffffffffffffffffffffffffffff
-  b 0x7ffffffffffffffffffffffffffffffffffffffff
-  r 0x04000000000000000000020108a2e0cc0d99f8a5ef
-  h 2
-  gx 0x05679b353caa46825fea2d3713ba450da0c2a4541
-  gy 0x235b7c6710050689906bac3d9dec76a835591edb2
-curve nist-b163n binnorm
-  p 0x800000000000000000000000000000000000000c9
-  beta 0x715169c109c612e390d347c748342bcd3b02a0bef
-  a 0x7ffffffffffffffffffffffffffffffffffffffff
-  b 0x6645f3cacf1638e139c6cd13ef61734fbc9e3d9fb
-  r 0x040000000000000000000292fe77e70c12a4234c33
-  h 2
-  gx 0x0311103c17167564ace77ccb09c681f886ba54ee8
-  gy 0x333ac13c6447f2e67613bf7009daf98c87bb50c7f
-
-curve nist-k233n binnorm
-  p 0x20000000000000000000000000000000000000004000000000000000001
-  beta 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
-  a 0
-  b 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  r 0x8000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf
-  h 4
-  gx 0x0fde76d9dcd26e643ac26f1aa901aa129784b71fc0722b2d05614d650b3
-  gy 0x0643e317633155c9e0447ba8020a3c43177450ee036d633501434cac978
-curve nist-b233n binnorm
-  p 0x20000000000000000000000000000000000000004000000000000000001
-  beta 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
-  a 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  b 0x1a003e0962d4f9a8e407c904a9538163adb825212600c7752ad52233279
-  r 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7
-  h 2
-  gx 0x18b863524b3cdfefb94f2784e0b116faac54404bc9162a363bab84a14c5
-  gy 0x04925df77bd8b8ff1a5ff519417822bfedf2bbd752644292c98c7af6e02
-
-curve nist-k283n binnorm
-  p 0x800000000000000000000000000000000000000000000000000000000000000000010a1
-  beta 0x31e0ed791c3282dc5624a720818049d053e8c7ab8663792bc1d792eba9867fc7b317a99
-  a 0
-  b 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  r 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61
-  h 4
-  gx 0x3ab9593f8db09fc188f1d7c4ac9fcc3e57fcd3bdb15024b212c70229de5fcd92eb0ea60
-  gy 0x2118c4755e7345cd8f603ef93b98b106fe8854ffeb9a3b304634cc83a0e759f0c2686b1
-curve nist-b283n binnorm
-  p 0x800000000000000000000000000000000000000000000000000000000000000000010a1
-  beta 0x31e0ed791c3282dc5624a720818049d053e8c7ab8663792bc1d792eba9867fc7b317a99
-  a 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  b 0x157261b894739fb5a13503f55f0b3f10c5601166633102201138cc180c0206bdafbc951
-  r 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307
-  h 2
-  gx 0x749468e464ee468634b21f7f61cb700701817e6bc36a2364cb8906e940948eaa463c35d
-  gy 0x62968bd3b489ac5c9b859da68475c315bafcdc4ccd0dc905b70f62446f49c052f49c08c
-
-curve nist-k409n binnorm
-  p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
-  beta 0x0dfa06be206aa97b7a41fffb9b0c55f8f048062fbe8381b4248adf92912ccc8e3f91a24e1cfb3950532b988971c23042e85708d
-  a 0
-  b 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  r 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf
-  h 4
-  gx 0x1b559c7cba2422e3affe13343e808b55e012d726ca0b7e6a63aeafbc1e3a98e10ca0fcf98350c3b7f89a9754a8e1dc0713cec4a
-  gy 0x16d8c42052f07e7713e7490eff318ba1abd6fef8a5433c894b24f5c817aeb79852496fbee803a47bc8a203878ebf1c499afd7d6
-curve nist-b409n binnorm
-  p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
-  beta 0x0dfa06be206aa97b7a41fffb9b0c55f8f048062fbe8381b4248adf92912ccc8e3f91a24e1cfb3950532b988971c23042e85708d
-  a 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  b 0x124d0651c3d3772f7f5a1fe6e715559e2129bdfa04d52f7b6ac7c532cf0ed06f610072d88ad2fdcc50c6fde72843670f8b3742a
-  r 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173
-  h 2
-  gx 0x0ceacbc9f475767d8e69f3b5dfab39813685262bcacf22b84c7b6dd981899e7318c96f0761f77c602c016ced7c548de830d708f
-  gy 0x199d64ba8f089c6db0e0b61e80bb95934afd0caf2e8be76d1c5e9affc7476df49142691ad30390288aa09bcc59c1573aa3c009a
-
-curve nist-k571n binnorm
-  p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
-  beta 0x452186bbf5840a0bcf8c9f02a54efa04e813b43c3d4149606c4d27b487bf107393c8907f79d9778beb35ee87467d3288274caebda6ce05aeb4ca5cf3c3044bd4372232f2c1a27c4
-  a 0
-  b 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  r 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001
-  h 4
-  gx 0x04bb2dba418d0db107adae003427e5d7cc139acb465e5934f0bea2ab2f3622bc29b3d5b9aa7a1fdfd5d8be66057c1008e71e484bcd98f22bf8476423767367429ef2ec5bc3ebcf7
-  gy 0x44cbb57de20788d2c952d7b56cf39bd3e89b18984bd124e751ceff4369dd8dac6a59e6e745df44d8220ce22aa2c852cfcbbef49ebaa98bd2483e33180e04286feaa253050caff60
-curve nist-b571n binnorm
-  p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
-  beta 0x452186bbf5840a0bcf8c9f02a54efa04e813b43c3d4149606c4d27b487bf107393c8907f79d9778beb35ee87467d3288274caebda6ce05aeb4ca5cf3c3044bd4372232f2c1a27c4
-  a 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  b 0x3762d0d47116006179da35688eeaccf591a5cdea75000118d9608c59132d43426101a1dfb3774115f586623f75f00001ce611983c1275fa31f5bc9f4be1a0f467f01ca885c74777
-  r 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47
-  h 2
-  gx 0x0735e035def5925cc33173eb2a8ce7767522b466d278b650a2916127dfea9d2d361089f0a7a0247a184e1c70d417866e0fe0feb0ff8f2f3f9176418f97d117e624e2015df1662a8
-  gy 0x04a36420572616cdf7e606fccadaecfc3b76dab0eb1248dd03fbdfc9cd3242c4726be579855e812de7ec5c500b4576a24628048b6a72d880062eed0dd34b1096d3acbb6b01a4a97
-
-#----- That's all, folks-----------------------------------------------------
diff --git a/exp.c b/exp.c
deleted file mode 100644 (file)
index 4327129..0000000
--- a/exp.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*-c-*-
- *
- * $Id: exp.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Generalized exponentiation
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define EXP_TYPE /* Hack */
-#include "exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @exp_simulnext@ --- *
- *
- * Arguments:  @exp_simul *e@ = pointer to state structure
- *             @size_t x@ = a current accumulator
- *
- * Returns:    The next column of bits.
- *
- * Use:                Scans the next column of bits for a simultaneous
- *             exponentiation.
- */
-
-size_t exp_simulnext(exp_simul *e, size_t x)
-{
-  size_t i;
-
-  /* --- Move to the next word along --- */
-
-  if (!e->b) {
-    e->o--;
-    for (i = 0; i < e->n; i++)
-      e->s[i].w = e->o < e->s[i].len ? e->s[i].v[e->o] : 0;
-    e->b = MPW_BITS;
-  }
-
-  /* --- Scan out a column of bits --- */
-
-  for (i = 0; i < e->n; i++) {
-    x = (x << 1) | ((e->s[i].w >> (MPW_BITS - 1)) & 1u);
-    e->s[i].w <<= 1;
-  }
-  e->b--;
-  return (x);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/exp.h b/exp.h
deleted file mode 100644 (file)
index 9ff6a24..0000000
--- a/exp.h
+++ /dev/null
@@ -1,422 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generalized exponentiation
- *
- * (c) 2001 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.
- */
-
-#ifdef CATACOMB_EXP_H
-#  error "Multiple inclusion of <catacomb/exp.h>"
-#endif
-
-#define CATACOMB_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/alloc.h>
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct exp_simulscan {
-  mpw w;
-  size_t len;
-  const mpw *v;
-} exp_simulscan;
-
-typedef struct exp_simul {
-  unsigned b;
-  size_t o, n;
-  exp_simulscan *s;
-} exp_simul;
-
-/*----- Macros provided ---------------------------------------------------*/
-
-/* --- Parameters --- */
-
-#ifndef EXP_WINSZ                      /* Sliding window size */
-#  define EXP_WINSZ 4                  /* Predefine if you need to */
-#endif
-
-/* --- These are determined from the window size --- *
- *
- * Given a %$k$%-bit exponent, I expect to do %$k/2$% multiplies if I use the
- * simple way.  If I use an n-bit sliding window, then I do %$2^n$%
- * multiplies up front, but I only do %$(2^n - 1)/2^n k/n$% multiplies for
- * the exponentiation.  This is a win when
- *
- *   %$k \ge \frac{n 2^{n+1}}{n - 2}$%
- */
-
-#define EXP_TABSZ (1 << EXP_WINSZ)
-#define EXP_THRESH                                                     \
-    ((EXP_WINSZ * (2 << EXP_WINSZ))/((EXP_WINSZ - 2) * MPW_BITS))
-
-/* --- Required operations --- *
- *
- * The macros here are independent of the underlying group elements.  You
- * must provide the necessary group operations and other definitions.  The
- * group operation is assumed to be written multiplicatively.
- *
- * @EXP_TYPE@                  The type of a group element, e.g., @mp *@.
- *
- * @EXP_COPY(d, x)@            Makes @d@ be a copy of @x@.
- *
- * @EXP_DROP(x)@               Discards the element @x@, reclaiming any
- *                             memory it used.
- *
- * @EXP_MUL(a, x)@             Multiplies @a@ by @x@ (writing the result
- *                             back to @a@).
- *
- * @EXP_FIX(x)@                        Makes @x@ be a canonical representation of
- *                             its value.  All multiplications have the
- *                             right argument canonical.
- *
- * @EXP_SQR(a)@                        Multiplies @a@ by itself.
- *
- * @EXP_SETMUL(d, x, y)@       Sets @d@ to be the product of @x@ and @y@.
- *                             The value @d@ has not been initialized.
- *
- * @EXP_SETSQR(d, x)@          Sets @d@ to be the square of @x@.
- *
- * Only @EXP_TYPE@, @EXP_MUL@ and @EXP_SQR@ are required for simple
- * exponentation.  Sliding window and simultaneous exponentation require all
- * of the operations.
- */
-
-#ifndef EXP_TYPE
-#  error "EXP_TYPE not defined for <catacomb/exp.h>"
-#endif
-
-/* --- @EXP_SIMPLE@ --- *
- *
- * Arguments:  @a@ = the result object, initially a multiplicative identity
- *             @g@ = the object to exponentiate
- *             @x@ = the exponent, as a multiprecision integer
- *
- * Use:                Performs a simple left-to-right exponentiation.  At the end
- *             of the code, the answer is left in @a@; @g@ and @x@ are
- *             unchanged.
- */
-
-#define EXP_SIMPLE(a, g, x) do {                                       \
-  mpscan sc;                                                           \
-  unsigned sq = 0;                                                     \
-                                                                       \
-  /* --- Begin scanning --- */                                         \
-                                                                       \
-  mp_rscan(&sc, x);                                                    \
-  if (!MP_RSTEP(&sc))                                                  \
-    goto exp_simple_exit;                                              \
-  while (!MP_RBIT(&sc))                                                        \
-    MP_RSTEP(&sc);                                                     \
-                                                                       \
-  /* --- Do the main body of the work --- */                           \
-                                                                       \
-  EXP_FIX(g);                                                          \
-  for (;;) {                                                           \
-    EXP_MUL(a, g);                                                     \
-    sq = 0;                                                            \
-    for (;;) {                                                         \
-      if (!MP_RSTEP(&sc))                                              \
-       goto exp_simple_done;                                           \
-      sq++;                                                            \
-      if (MP_RBIT(&sc))                                                        \
-       break;                                                          \
-    }                                                                  \
-    while (sq--) EXP_SQR(a);                                           \
-  }                                                                    \
-                                                                       \
-  /* --- Do a final round of squaring --- */                           \
-                                                                       \
-exp_simple_done:                                                       \
-  while (sq--) EXP_SQR(a);                                             \
-exp_simple_exit:;                                                      \
-} while (0)
-
-/* --- @EXP_WINDOW@ --- *
- *
- * Arguments:  @a@ = the result object, initially a multiplicative identity
- *             @g@ = the object to exponentiate
- *             @x@ = the exponent, as a multiprecision integer
- *
- * Use:                Performs a sliding-window exponentiation.  At the end of the
- *             code, the answer is left in @a@; @g@ and @x@ are unchanged.
- */
-
-#define EXP_WINDOW(a, g, x) do {                                       \
-  EXP_TYPE *v;                                                         \
-  EXP_TYPE g2;                                                         \
-  unsigned i, sq = 0;                                                  \
-  mpscan sc;                                                           \
-                                                                       \
-  /* --- Get going --- */                                              \
-                                                                       \
-  mp_rscan(&sc, x);                                                    \
-  if (!MP_RSTEP(&sc))                                                  \
-    goto exp_window_exit;                                              \
-                                                                       \
-  /* --- Do the precomputation --- */                                  \
-                                                                       \
-  EXP_FIX(g);                                                          \
-  EXP_SETSQR(g2, g);                                                   \
-  EXP_FIX(g2);                                                         \
-  v = xmalloc(EXP_TABSZ * sizeof(EXP_TYPE));                           \
-  EXP_COPY(v[0], g);                                                   \
-  for (i = 1; i < EXP_TABSZ; i++) {                                    \
-    EXP_SETMUL(v[i], v[i - 1], g2);                                    \
-    EXP_FIX(v[i]);                                                     \
-  }                                                                    \
-  EXP_DROP(g2);                                                                \
-                                                                       \
-  /* --- Skip top-end zero bits --- *                                  \
-   *                                                                   \
-   * If the initial step worked, there must be a set bit somewhere, so \
-   * keep stepping until I find it.                                    \
-   */                                                                  \
-                                                                       \
-  while (!MP_RBIT(&sc))                                                        \
-    MP_RSTEP(&sc);                                                     \
-                                                                       \
-  /* --- Now for the main work --- */                                  \
-                                                                       \
-  for (;;) {                                                           \
-    unsigned l = 1;                                                    \
-    unsigned z = 0;                                                    \
-                                                                       \
-    /* --- The next bit is set, so read a window index --- *           \
-     *                                                                 \
-     * Reset @i@ to zero and increment @sq@.  Then, until either I read        \
-     * @WINSZ@ bits or I run out of bits, scan in a bit: if it's clear,        \
-     * bump the @z@ counter; if it's set, push a set bit into @i@,     \
-     * shift it over by @z@ bits, bump @sq@ by @z + 1@ and clear @z@.  \
-     * By the end of this palaver, @i@ is an index to the precomputed  \
-     * value in @v@.                                                   \
-     */                                                                        \
-                                                                       \
-    i = 0;                                                             \
-    sq++;                                                              \
-    while (l < EXP_WINSZ && MP_RSTEP(&sc)) {                           \
-      l++;                                                             \
-      if (!MP_RBIT(&sc))                                               \
-       z++;                                                            \
-      else {                                                           \
-       i = ((i << 1) | 1) << z;                                        \
-       sq += z + 1;                                                    \
-       z = 0;                                                          \
-      }                                                                        \
-    }                                                                  \
-                                                                       \
-    /* --- Do the squaring --- *                                       \
-     *                                                                 \
-     * Remember that @sq@ carries over from the zero-skipping stuff    \
-     * below.                                                          \
-     */                                                                        \
-                                                                       \
-    while (sq--) EXP_SQR(a);                                           \
-                                                                       \
-    /* --- Do the multiply --- */                                      \
-                                                                       \
-    EXP_MUL(a, v[i]);                                                  \
-                                                                       \
-    /* --- Now grind along through the rest of the bits --- */         \
-                                                                       \
-    sq = z;                                                            \
-    for (;;) {                                                         \
-      if (!MP_RSTEP(&sc))                                              \
-       goto exp_window_done;                                           \
-      if (MP_RBIT(&sc))                                                        \
-       break;                                                          \
-      sq++;                                                            \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  /* --- Do a final round of squaring --- */                           \
-                                                                       \
-exp_window_done:                                                       \
-  while (sq--) EXP_SQR(a);                                             \
-  for (i = 0; i < EXP_TABSZ; i++)                                      \
-    EXP_DROP(v[i]);                                                    \
-  xfree(v);                                                            \
-exp_window_exit:;                                                      \
-} while (0)
-
-/* --- @EXP_SIMUL@ --- *
- *
- * Arguments:  @a@ = the result object, initially a multiplicative identity
- *             @f@ = pointer to a vector of base/exp pairs
- *             @n@ = the number of base/exp pairs
- *
- * Use:                Performs a simultaneous sliding-window exponentiation.  The
- *             @f@ table is an array of structures containing members @base@
- *             of type @EXP_TYPE@, and @exp@ of type @mp *@.
- */
-
-#define EXP_SIMUL(a, f, n) do {                                                \
-  size_t i, j, jj, k;                                                  \
-  size_t vn = 1 << (EXP_WINSZ * n), m = (1 << n) - 1;                  \
-  EXP_TYPE *v = xmalloc(vn * sizeof(EXP_TYPE));                                \
-  exp_simul e;                                                         \
-  unsigned sq = 0;                                                     \
-                                                                       \
-  /* --- Fill in the precomputed table --- */                          \
-                                                                       \
-  j = 1;                                                               \
-  for (i = 0; i < n; i++) {                                            \
-    EXP_COPY(v[j], f[n - 1 - i].base);                                 \
-    EXP_FIX(v[j]);                                                     \
-    j <<= 1;                                                           \
-  }                                                                    \
-  k = n * EXP_WINSZ;                                                   \
-  jj = 1;                                                              \
-  for (; i < k; i++) {                                                 \
-    EXP_SETSQR(v[j], v[jj]);                                           \
-    EXP_FIX(v[j]);                                                     \
-    j <<= 1; jj <<= 1;                                                 \
-  }                                                                    \
-  for (i = 1; i < vn; i <<= 1) {                                       \
-    for (j = 1; j < i; j++) {                                          \
-      EXP_SETMUL(v[j + i], v[j], v[i]);                                        \
-      EXP_FIX(v[j + i]);                                               \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  /* --- Set up the bitscanners --- *                                  \
-   *                                                                   \
-   * Got to use custom scanners, to keep them all in sync.             \
-   */                                                                  \
-                                                                       \
-  e.n = n;                                                             \
-  e.b = 0;                                                             \
-  e.s = xmalloc(n * sizeof(*e.s));                                     \
-  e.o = 0;                                                             \
-  for (i = 0; i < n; i++) {                                            \
-    MP_SHRINK(f[i].exp);                                               \
-    e.s[i].len = MP_LEN(f[i].exp);                                     \
-    e.s[i].v = f[i].exp->v;                                            \
-    if (e.s[i].len > e.o)                                              \
-      e.o = e.s[i].len;                                                        \
-  }                                                                    \
-                                                                       \
-  /* --- Skip as far as a nonzero column in the exponent matrix --- */ \
-                                                                       \
-  do {                                                                 \
-    if (!e.o && !e.b)                                                  \
-      goto exp_simul_done;                                             \
-    i = exp_simulnext(&e, 0);                                          \
-  } while (!(i & m));                                                  \
-                                                                       \
-  /* --- Now for the main work --- */                                  \
-                                                                       \
-  for (;;) {                                                           \
-    unsigned l = 1;                                                    \
-    unsigned z = 0;                                                    \
-                                                                       \
-    /* --- Just read a nonzero column, so read a window index --- *    \
-     *                                                                 \
-     * Clear high bits of @i@ and increment @sq@.  Then, until either I        \
-     * read @WINSZ@ columns or I run out, scan in a column and append  \
-     * it to @i@.  If it's zero, bump the @z@ counter; if it's nonzero,        \
-     * bump @sq@ by @z + 1@ and clear @z@.  By the end of this palaver,        \
-     * @i@ is an index to the precomputed value in @v@, followed by    \
-     * @n * z@ zero bits.                                              \
-     */                                                                        \
-                                                                       \
-    sq++;                                                              \
-    while (l < EXP_WINSZ && (e.o || e.b)) {                            \
-      l++;                                                             \
-      i = exp_simulnext(&e, i);                                                \
-      if (!(i & m))                                                    \
-       z++;                                                            \
-      else {                                                           \
-       sq += z + 1;                                                    \
-       z = 0;                                                          \
-      }                                                                        \
-    }                                                                  \
-                                                                       \
-    /* --- Do the squaring --- *                                       \
-     *                                                                 \
-     * Remember that @sq@ carries over from the zero-skipping stuff    \
-     * below.                                                          \
-     */                                                                        \
-                                                                       \
-    while (sq--) EXP_SQR(a);                                           \
-                                                                       \
-    /* --- Do the multiply --- */                                      \
-                                                                       \
-    i >>= (z * n);                                                     \
-    EXP_MUL(a, v[i]);                                                  \
-                                                                       \
-    /* --- Now grind along through the rest of the bits --- */         \
-                                                                       \
-    sq = z;                                                            \
-    for (;;) {                                                         \
-      if (!e.o && !e.b)                                                        \
-       goto exp_simul_done;                                            \
-      if ((i = exp_simulnext(&e, 0)) != 0)                             \
-       break;                                                          \
-      sq++;                                                            \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  /* --- Do a final round of squaring --- */                           \
-                                                                       \
-exp_simul_done:                                                                \
-  while (sq--) EXP_SQR(a);                                             \
-  for (i = 1; i < vn; i++)                                             \
-    EXP_DROP(v[i]);                                                    \
-  xfree(v);                                                            \
-  xfree(e.s);                                                          \
-} while (0)
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @exp_simulnext@ --- *
- *
- * Arguments:  @exp_simul *e@ = pointer to state structure
- *             @size_t x@ = a current accumulator
- *
- * Returns:    The next column of bits.
- *
- * Use:                Scans the next column of bits for a simultaneous
- *             exponentiation.
- */
-
-extern size_t exp_simulnext(exp_simul */*e*/, size_t /*x*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
diff --git a/f-binpoly.c b/f-binpoly.c
deleted file mode 100644 (file)
index 5f6a527..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Binary fields with polynomial basis representation
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/sub.h>
-
-#include "field.h"
-#include "field-guts.h"
-#include "mprand.h"
-
-/*----- Polynomial basis --------------------------------------------------*/
-
-/* --- Field operations --- */
-
-static void fdestroy(field *ff) {
-  fctx_binpoly *f = (fctx_binpoly *)ff;
-  gfreduce_destroy(&f->r); MP_DROP(f->f.q);
-  DESTROY(f);
-}
-
-static mp *frand(field *f, mp *d, grand *r) {
-  return (mprand(d, f->nbits, r, 0));
-}
-
-static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); }
-
-static mp *fadd(field *ff, mp *d, mp *x, mp *y) { return (gf_add(d, x, y)); }
-
-static mp *fmul(field *ff, mp *d, mp *x, mp *y) {
-  fctx_binpoly *f = (fctx_binpoly *)ff; d = gf_mul(d, x, y);
-  return (gfreduce_do(&f->r, d, d));
-}
-
-static mp *fsqr(field *ff, mp *d, mp *x) {
-  fctx_binpoly *f = (fctx_binpoly *)ff; d = gf_sqr(d, x);
-  return (gfreduce_do(&f->r, d, d));
-}
-
-static mp *finv(field *ff, mp *d, mp *x) {
-  fctx_binpoly *f = (fctx_binpoly *)ff;
-  d = gf_modinv(d, x, f->r.p);
-  return (d);
-}
-
-static mp *freduce(field *ff, mp *d, mp *x) {
-  fctx_binpoly *f = (fctx_binpoly *)ff;
-  return (gfreduce_do(&f->r, d, x));
-}
-
-static mp *fsqrt(field *ff, mp *d, mp *x) {
-  fctx_binpoly *f = (fctx_binpoly *)ff;
-  return (gfreduce_sqrt(&f->r, d, x));
-}
-
-static mp *fquadsolve(field *ff, mp *d, mp *x) {
-  fctx_binpoly *f = (fctx_binpoly *)ff;
-  return (gfreduce_quadsolve(&f->r, d, x));
-}
-
-/* --- Field operations table --- */
-
-static const field_ops fops = {
-  FTY_BINARY, "binpoly",
-  fdestroy, frand, field_stdsamep,
-  freduce, field_id,
-  fzerop, field_id, fadd, fadd, fmul, fsqr, finv, freduce, fsqrt,
-  fquadsolve,
-  0, 0, 0, 0
-};
-
-/* --- @field_binpoly@ --- *
- *
- * Arguments:  @mp *p@ = the reduction polynomial
- *
- * Returns:    A pointer to the field.
- *
- * Use:                Creates a field structure for a binary field mod @p@.
- */
-
-field *field_binpoly(mp *p)
-{
-  fctx_binpoly *f = CREATE(fctx_binpoly);
-  f->f.ops = &fops;
-  f->f.zero = MP_ZERO;
-  f->f.one = MP_ONE;
-  f->f.nbits = mp_bits(p) - 1;
-  f->f.noctets = (f->f.nbits + 7) >> 3;
-  gfreduce_create(&f->r, p);
-  f->f.m = f->r.p;
-  f->f.q = mp_lsl(MP_NEW, MP_ONE, f->f.nbits);
-  return (&f->f);
-}
-
-/*----- Normal basis ------------------------------------------------------*/
-
-/* --- Field operations --- */
-
-static void fndestroy(field *ff) {
-  fctx_binnorm *f = (fctx_binnorm *)ff; gfreduce_destroy(&f->f.r);
-  gfn_destroy(&f->ntop); gfn_destroy(&f->pton); MP_DROP(f->f.f.q);
-  DESTROY(f);
-}
-
-static int fnsamep(field *ff, field *gg) {
-  fctx_binnorm *f = (fctx_binnorm *)ff, *g = (fctx_binnorm *)gg;
-  return (MP_EQ(f->ntop.r[0], g->ntop.r[0]) && field_stdsamep(ff, gg));
-}
-
-static mp *fnin(field *ff, mp *d, mp *x) {
-  fctx_binnorm *f = (fctx_binnorm *)ff;
-  return (gfn_transform(&f->ntop, d, x));
-}
-
-static mp *fnout(field *ff, mp *d, mp *x) {
-  fctx_binnorm *f = (fctx_binnorm *)ff;
-  return (gfn_transform(&f->pton, d, x));
-}
-
-/* --- Field operations table --- */
-
-static const field_ops fnops = {
-  FTY_BINARY, "binnorm",
-  fndestroy, frand, fnsamep,
-  fnin, fnout,
-  fzerop, field_id, fadd, fadd, fmul, fsqr, finv, freduce, fsqrt,
-  fquadsolve,
-  0, 0, 0, 0
-};
-
-/* --- @field_binnorm@ --- *
- *
- * Arguments:  @mp *p@ = the reduction polynomial
- *             @mp *beta@ = representation of normal point
- *
- * Returns:    A pointer to the field.
- *
- * Use:                Creates a field structure for a binary field mod @p@ which
- *             uses a normal basis representation externally.  Computations
- *             are still done on a polynomial-basis representation.
- */
-
-field *field_binnorm(mp *p, mp *beta)
-{
-  fctx_binnorm *f = CREATE(fctx_binnorm);
-  f->f.f.ops = &fnops;
-  f->f.f.zero = MP_ZERO;
-  f->f.f.one = MP_ONE;
-  f->f.f.nbits = mp_bits(p) - 1;
-  f->f.f.noctets = (f->f.f.nbits + 7) >> 3;
-  gfreduce_create(&f->f.r, p);
-  f->f.f.m = f->f.r.p;
-  f->f.f.q = mp_lsl(MP_NEW, MP_ONE, f->f.f.nbits);
-  gfn_create(p, beta, &f->ntop, &f->pton);
-  return (&f->f.f);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/f-niceprime.c b/f-niceprime.c
deleted file mode 100644 (file)
index 83b9ca5..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Prime fields with efficient reduction for special-form primes
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/sub.h>
-
-#include "field.h"
-#include "field-guts.h"
-#include "mprand.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Field operations --- */
-
-static void fdestroy(field *ff) {
-  fctx_niceprime *f = (fctx_niceprime *)ff;
-  mpreduce_destroy(&f->r);
-  DESTROY(f);
-}
-
-static mp *frand(field *ff, mp *d, grand *r) {
-  fctx_niceprime *f = (fctx_niceprime *)ff;
-  return (mprand_range(d, f->r.p, r, 0));
-}
-
-static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); }
-
-static mp *fneg(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff;
-  return (mp_sub(d, f->r.p, x));
-}
-
-static mp *fadd(field *ff, mp *d, mp *x, mp *y) {
-  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_add(d, x, y);
-  if (MP_NEGP(d)) d = mp_add(d, d, f->r.p);
-  else if (MP_CMP(d, >, f->r.p)) d = mp_sub(d, d, f->r.p);
-  return (d);
-}
-
-static mp *fsub(field *ff, mp *d, mp *x, mp *y) {
-  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_sub(d, x, y);
-  if (MP_NEGP(d)) d = mp_add(d, d, f->r.p);
-  else if (MP_CMP(d, >, f->r.p)) d = mp_sub(d, d, f->r.p);
-  return (d);
-}
-
-static mp *fmul(field *ff, mp *d, mp *x, mp *y) {
-  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_mul(d, x, y);
-  return (mpreduce_do(&f->r, d, d));
-}
-
-static mp *fsqr(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_sqr(d, x);
-  return (mpreduce_do(&f->r, d, d));
-}
-
-static mp *finv(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff;
-  d = mp_modinv(d, x, f->r.p);
-  return (d);
-}
-
-static mp *freduce(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff;
-  return (mpreduce_do(&f->r, d, x));
-}
-
-static mp *fsqrt(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff;
-  return (mp_modsqrt(d, x, f->r.p));
-}
-
-static mp *fdbl(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_lsl(d, x, 1);
-  if (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p);
-  return (d);
-}
-
-static mp *ftpl(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff; MP_DEST(d, MP_LEN(x) + 1, x->f);
-  MPX_UMULN(d->v, d->vl, x->v, x->vl, 3); d->f &= ~MP_UNDEF;
-  while (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p);
-  return (d);
-}
-
-static mp *fqdl(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_lsl(d, x, 2);
-  while (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p);
-  return (d);
-}
-
-static mp *fhlv(field *ff, mp *d, mp *x) {
-  fctx_niceprime *f = (fctx_niceprime *)ff;
-  if (MP_ZEROP(x)) { MP_COPY(x); MP_DROP(d); return (x); }
-  if (x->v[0] & 1) { d = mp_add(d, x, f->r.p); x = d; }
-  return (mp_lsr(d, x, 1));
-}
-
-/* --- Field operations table --- */
-
-static const field_ops fops = {
-  FTY_PRIME, "niceprime",
-  fdestroy, frand, field_stdsamep,
-  freduce, field_id,
-  fzerop, fneg, fadd, fsub, fmul, fsqr, finv, freduce, fsqrt,
-  0,
-  fdbl, ftpl, fqdl, fhlv
-};
-
-/* --- @field_niceprime@ --- *
- *
- * Arguments:  @mp *p@ = the characteristic of the field
- *
- * Returns:    A pointer to the field, or null.
- *
- * Use:                Creates a field structure for a prime field of size %$p$%,
- *             using efficient reduction for nice primes.
- */
-
-field *field_niceprime(mp *p)
-{
-  fctx_niceprime *f = CREATE(fctx_niceprime);
-  f->f.ops = &fops;
-  f->f.zero = MP_ZERO;
-  f->f.one = MP_ONE;
-  f->f.nbits = mp_bits(p);
-  f->f.noctets = (f->f.nbits + 7) >> 3;
-  if (mpreduce_create(&f->r, p)) {
-    DESTROY(f);
-    return (0);
-  }
-  f->f.m = f->r.p;
-  f->f.q = f->r.p;
-  return (&f->f);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/f-prime.c b/f-prime.c
deleted file mode 100644 (file)
index 31638f5..0000000
--- a/f-prime.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Prime fields with Montgomery arithmetic
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/sub.h>
-
-#include "field.h"
-#include "mprand.h"
-#include "field-guts.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Field operations --- */
-
-static void fdestroy(field *ff) {
-  fctx_prime *f = (fctx_prime *)ff;
-  mpmont_destroy(&f->mm);
-  DESTROY(f);
-}
-
-static mp *frand(field *ff, mp *d, grand *r) {
-  fctx_prime *f = (fctx_prime *)ff;
-  return (mprand_range(d, f->mm.m, r, 0));
-}
-
-static mp *fin(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff;
-  mp_div(0, &d, x, f->mm.m);
-  return (mpmont_mul(&f->mm, d, d, f->mm.r2));
-}
-
-static mp *fout(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff;
-  return (mpmont_reduce(&f->mm, d, x));
-}
-
-static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); }
-
-static mp *fneg(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff;
-  return (mp_sub(d, f->mm.m, x));
-}
-
-static mp *fadd(field *ff, mp *d, mp *x, mp *y) {
-  fctx_prime *f = (fctx_prime *)ff; d = mp_add(d, x, y);
-  if (MP_NEGP(d)) d = mp_add(d, d, f->mm.m);
-  else if (MP_CMP(d, >, f->mm.m)) d = mp_sub(d, d, f->mm.m);
-  return (d);
-}
-
-static mp *fsub(field *ff, mp *d, mp *x, mp *y) {
-  fctx_prime *f = (fctx_prime *)ff; d = mp_sub(d, x, y);
-  if (MP_NEGP(d)) d = mp_add(d, d, f->mm.m);
-  else if (MP_CMP(d, >, f->mm.m)) d = mp_sub(d, d, f->mm.m);
-  return (d);
-}
-
-static mp *fmul(field *ff, mp *d, mp *x, mp *y) {
-  fctx_prime *f = (fctx_prime *)ff;
-  return (mpmont_mul(&f->mm, d, x, y));
-}
-
-static mp *fsqr(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff; d = mp_sqr(d, x);
-  return (mpmont_reduce(&f->mm, d, d));
-}
-
-static mp *finv(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff; d = mpmont_reduce(&f->mm, d, x);
-  d = mp_modinv(d, d, f->mm.m); return (mpmont_mul(&f->mm, d, d, f->mm.r2));
-}
-
-static mp *freduce(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff;
-  mp_div(0, &d, x, f->mm.m);
-  return (d);
-}
-
-static mp *fsqrt(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff; d = mpmont_reduce(&f->mm, d, x);
-  d = mp_modsqrt(d, d, f->mm.m); if (!d) return (d);
-  return (mpmont_mul(&f->mm, d, d, f->mm.r2));
-}
-
-static mp *fdbl(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff; d = mp_lsl(d, x, 1);
-  if (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m);
-  return (d);
-}
-
-static mp *ftpl(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff; MP_DEST(d, MP_LEN(x) + 1, x->f);
-  MPX_UMULN(d->v, d->vl, x->v, x->vl, 3); d->f &= ~MP_UNDEF;
-  while (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m);
-  return (d);
-}
-
-static mp *fqdl(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff; d = mp_lsl(d, x, 2);
-  while (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m);
-  return (d);
-}
-
-static mp *fhlv(field *ff, mp *d, mp *x) {
-  fctx_prime *f = (fctx_prime *)ff;
-  if (MP_ZEROP(x)) { MP_COPY(x); MP_DROP(d); return (x); }
-  if (x->v[0] & 1) { d = mp_add(d, x, f->mm.m); x = d; }
-  return (mp_lsr(d, x, 1));
-}
-
-/* --- Field operations table --- */
-
-static const field_ops fops = {
-  FTY_PRIME, "prime",
-  fdestroy, frand, field_stdsamep,
-  fin, fout,
-  fzerop, fneg, fadd, fsub, fmul, fsqr, finv, freduce, fsqrt,
-  0,
-  fdbl, ftpl, fqdl, fhlv
-};
-
-/* --- @field_prime@ --- *
- *
- * Arguments:  @mp *p@ = the characteristic of the field
- *
- * Returns:    A pointer to the field or null.
- *
- * Use:                Creates a field structure for a prime field of size %$p$%,
- *             using Montgomery reduction for arithmetic.
- */
-
-field *field_prime(mp *p)
-{
-  fctx_prime *f;
-
-  f = CREATE(fctx_prime);
-  f->f.ops = &fops;
-  if (mpmont_create(&f->mm, p)) {
-    DESTROY(f);
-    return (0);
-  }
-  f->f.zero = MP_ZERO;
-  f->f.one = f->mm.r;
-  f->f.m = f->mm.m;
-  f->f.nbits = mp_bits(p);
-  f->f.noctets = (f->f.nbits + 7) >> 3;
-  f->f.q = f->mm.m;
-  return (&f->f);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/factorial.c b/factorial.c
deleted file mode 100644 (file)
index 31316a7..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/* -*-c-*-
- *
- * $Id: factorial.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Example factorial computation
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "config.h"
-
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-
-#include "mpint.h"
-#include "mpmul.h"
-#include "mptext.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "Usage: $ [-r RADIX] INTEGER\n");
-}
-
-static void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-static void help(FILE *fp)
-{
-  version(fp);
-  putc('\n', fp);
-  usage(fp);
-  fputs("\n\
-Prints the factorial of the given integer on its output.  Input may be\n\
-in decimal (the default), octal with preceding zero, hex with preceding\n\
-`0x', or any base N between 2 and 62 inclusive with preceding `N_'.\n\
-Output may be in any base between 2 and 62; the default is base 10.  For\n\
-bases between 11 and 36 inclusive, lowercase letters of either case are\n\
-used as additional digits with values 10 upwards; lowercase is always\n\
-used for output.  For bases between 37 and 62 inclusive, lowercase letters\n\
-have lower value than uppercase; hence `a' has the value 10, while `A' has\n\
-the value 36.\n\
-\n\
-Options provided:\n\
-\n\
--h, --help             Display this help message.\n\
--v, --version          Display the version number.\n\
--u, --usage            Display a usage message.\n\
-\n\
--r, --radix=N          Write output in base N.\n\
-", fp);
-}
-
-int main(int argc, char *argv[])
-{
-  unsigned long x;
-  int r = 10;
-  char *p;
-  mp *f, *ulmax, *xx;
-  unsigned fl = 0;
-
-#define f_bogus 1u
-
-  ego(argv[0]);
-
-  for (;;) {
-    static const struct option opt[] = {
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'v' },
-      { "usage",       0,              0,      'u' },
-      { "radix",       OPTF_ARGREQ,    0,      'r' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "hvur:", opt, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'h':
-       help(stdout);
-       exit(0);
-      case 'v':
-       version(stdout);
-       exit(0);
-      case 'u':
-       usage(stdout);
-       exit(0);
-      case 'r':
-       r = atoi(optarg);
-       if (r < 2 || r > 62)
-         die(EXIT_FAILURE, "bad radix `%s'", optarg);
-       break;
-      default:
-       fl |= f_bogus;
-       break;
-    }
-  }
-
-  if (optind + 1 != argc || (fl & f_bogus)) {
-    usage(stderr);
-    exit(EXIT_FAILURE);
-  }
-  ulmax = mp_fromulong(MP_NEW, ULONG_MAX);
-  p = argv[optind];
-  while (isspace((unsigned char)*p))
-    p++;
-  xx = mp_readstring(MP_NEW, argv[optind], &p, 0);
-  while (isspace((unsigned char)*p))
-    p++;
-  if (!xx || *p || MP_CMP(xx, >, ulmax))
-    die(EXIT_FAILURE, "bad integer `%s'", argv[optind]);
-  x = mp_toulong(xx);
-  mp_drop(xx);
-  mp_drop(ulmax);
-  f = mp_factorial(x);
-  mp_writefile(f, stdout, r);
-  fputc('\n', stdout);
-  mp_drop(f);
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/fibrand.c b/fibrand.c
deleted file mode 100644 (file)
index c926a1a..0000000
--- a/fibrand.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/* -*-c-*-
- *
- * $Id: fibrand.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Fibonacci generator
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#include "fibrand.h"
-#include "grand.h"
-#include "lcrand.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @fibrand_step@ --- *
- *
- * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
- *
- * Returns:    Next output from generator.
- *
- * Use:                Steps the generator.  Returns
- *             %$x_{i - 24} + x_{i - 55} \bmod 2^{32}$%.
- */
-
-uint32 fibrand_step(fibrand *f)
-{
-  unsigned i = f->i;
-  unsigned j = i + (FIB_SZ - FIB_TAP);
-  uint32 x;
-  if (j >= FIB_SZ)
-    j -= FIB_SZ;
-  x = f->x[i] = U32(f->x[i] + f->x[j]);
-  i++;
-  if (i >= FIB_SZ)
-    i = 0;
-  f->i = i;
-  return (x);
-}
-
-/* --- @fibrand_seed@ --- *
- *
- * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
- *             @grand *r@ = random number generator to extract words from
- *
- * Returns:    ---
- *
- * Use:                Initializes a Fibonacci generator using word outputs from the
- *             given random number source @r@.
- */
-
-void fibrand_seed(fibrand *f, grand *r)
-{
-  int i;
-  unsigned p = 0;
-
-  for (i = 0; i < FIB_SZ; i++)
-    p |= f->x[i] = r->ops->word(r);
-  if (!(p & 1)) {
-    i = r->ops->range(r, FIB_SZ);
-    f->x[i] |= 1;
-  }
-  f->i = 0;
-}
-
-/* --- @fibrand_lcseed@ --- *
- *
- * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
- *             @uint32 seed@ = seed value
- *
- * Returns:    ---
- *
- * Use:                Initializes a Fibonacci generator using outputs from the
- *             @lcrand@ generator seeded from @seed@.  This is faster than
- *             using a generic @lcrand@-based generator and @fibrand_rseed@
- *             because it uses raw outputs rather than uniformly distributed
- *             32-bit words.
- */
-
-void fibrand_lcseed(fibrand *f, uint32 seed)
-{
-  int i;
-  unsigned p = 0;
-
-  for (i = 0; i < FIB_SZ; i++)
-    p |= f->x[i] = seed = lcrand(seed);
-  if (!(p & 1)) {
-    i = lcrand_range(&seed, FIB_SZ);
-    f->x[i] |= 1;
-  }
-  f->i = 0;
-}
-
-/* --- @fibrand_range@ --- *
- *
- * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
- *             @uint32 m@ = limit
- *
- * Returns:    A uniformly distributed pseudorandom integer in the interval
- *             %$[0, m)$%.
- */
-
-uint32 fibrand_range(fibrand *f, uint32 m)
-{
-  uint32 r = 0xffffffff - (0xffffffff % m);
-  uint32 x;
-
-  /* --- Now generate numbers until a good one comes along --- */
-
-  do x = fibrand_step(f); while (x >= r);
-  return (x % m);
-}
-
-/*----- Generic interface -------------------------------------------------*/
-
-typedef struct gctx {
-  grand r;
-  fibrand f;
-} gctx;
-
-static void gdestroy(grand *r)
-{
-  gctx *g = (gctx *)r;
-  DESTROY(g);
-}
-
-static int gmisc(grand *r, unsigned op, ...)
-{
-  gctx *g = (gctx *)r;
-  va_list ap;
-  int rc = 0;
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDRAND:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT:
-      fibrand_lcseed(&g->f, va_arg(ap, unsigned));
-      break;
-    case GRAND_SEEDUINT32:
-      fibrand_lcseed(&g->f, va_arg(ap, uint32));
-      break;
-    case GRAND_SEEDRAND:
-      fibrand_seed(&g->f, va_arg(ap, grand *));
-      break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static octet gbyte(grand *r)
-{
-  gctx *g = (gctx *)r;
-  return (U8(fibrand_step(&g->f)));
-}
-
-static uint32 gword(grand *r)
-{
-  gctx *g = (gctx *)r;
-  return (fibrand_step(&g->f));
-}
-
-static uint32 grange(grand *r, uint32 l)
-{
-  gctx *g = (gctx *)r;
-  return (fibrand_range(&g->f, l));
-}
-
-static void gfill(grand *r, void *p, size_t sz)
-{
-  gctx *g = (gctx *)r;
-  octet *q = p;
-  while (sz) {
-    *q++ = U8(fibrand_step(&g->f));
-    sz--;
-  }
-}
-
-static const grand_ops gops = {
-  "fibrand",
-  0, 0,
-  gmisc, gdestroy,
-  gword, gbyte, gword, grange, gfill
-};
-
-/* --- @fibrand_create@ --- *
- *
- * Arguments:  @uint32 seed@ = initial seed
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a Fibonacci
- *             generator.  The generator is seeded using @fibrand_lcseed@.
- */
-
-grand *fibrand_create(uint32 seed)
-{
-  gctx *g = CREATE(gctx);
-  g->r.ops = &gops;
-  fibrand_lcseed(&g->f, seed);
-  return (&g->r);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/fibrand.h b/fibrand.h
deleted file mode 100644 (file)
index 14d2aec..0000000
--- a/fibrand.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* -*-c-*-
- *
- * $Id: fibrand.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Fibonacci generator
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on the Fibonacci generator ----------------------------------*
- *
- * The generator was originally suggested by G. J. Mitchell and D. P. Moore
- * in 1957, and publicized by D. E. Knuth as Algorithm 3.2.2A in volume 2 of
- * his work `The Art of Computer Programming'.  The generator is simple: at
- * each stage it emits %$x_n = (x_{n - 55} + x_{n - 24}) \bmod 2^{32}$%.  The
- * period is proven to be greater than %$2^{55}$%, and statistical properties
- * appear to be good.
- */
-
-#ifndef CATACOMB_FIBRAND_H
-#define CATACOMB_FIBRAND_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Magic constants ---------------------------------------------------*/
-
-#define FIB_SZ 55
-#define FIB_TAP 24
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct fibrand {
-  unsigned i;
-  uint32 x[FIB_SZ];
-} fibrand;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @fibrand_step@ --- *
- *
- * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
- *
- * Returns:    Next output from generator.
- *
- * Use:                Steps the generator.  Returns
- *             %$x_{i - 24} + x_{i - 55} \bmod 2^{32}$%.
- */
-
-extern uint32 fibrand_step(fibrand */*f*/);
-
-/* --- @fibrand_seed@ --- *
- *
- * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
- *             @grand *r@ = random number generator to extract words from
- *
- * Returns:    ---
- *
- * Use:                Initializes a Fibonacci generator using word outputs from the
- *             given random number source @r@.
- */
-
-extern void fibrand_seed(fibrand */*f*/, grand */*r*/);
-
-/* --- @fibrand_lcseed@ --- *
- *
- * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
- *             @uint32 seed@ = seed value
- *
- * Returns:    ---
- *
- * Use:                Initializes a Fibonacci generator using outputs from the
- *             @lcrand@ generator seeded from @seed@.  This is faster than
- *             using a generic @lcrand@-based generator and @fibrand_rseed@
- *             because it uses raw outputs rather than uniformly distributed
- *             32-bit words.
- */
-
-extern void fibrand_lcseed(fibrand */*f*/, uint32 /*seed*/);
-
-/* --- @fibrand_range@ --- *
- *
- * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
- *             @uint32 m@ = limit
- *
- * Returns:    A uniformly distributed pseudorandom integer in the interval
- *             %$[0, m)$%.
- */
-
-extern uint32 fibrand_range(fibrand */*f*/, uint32 /*m*/);
-
-/* --- @fibrand_create@ --- *
- *
- * Arguments:  @uint32 seed@ = initial seed
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a Fibonacci
- *             generator.  The generator is seeded using @fibrand_lcseed@.
- */
-
-extern grand *fibrand_create(uint32 /*seed*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/field-exp.c b/field-exp.c
deleted file mode 100644 (file)
index 628fa49..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Exponentiation in finite fields
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "field.h"
-#include "field-exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @field_exp@ --- *
- *
- * Arguments:  @field *f@ = pointer to field
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e$%.
- *
- * Use:                Exponentiation in a finite field.  Note that all quantities
- *             are in internal format.
- */
-
-mp *field_exp(field *f, mp *d, mp *a, mp *e)
-{
-  mp *x = MP_COPY(f->one);
-  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
-
-  MP_COPY(a);
-  MP_SHRINK(e);
-  if (MP_ZEROP(e))
-    ;
-  else {
-    if (MP_NEGP(e))
-      a = F_INV(f, a, a);
-    if (MP_LEN(e) < EXP_THRESH)
-      EXP_SIMPLE(x, a, e);
-    else
-      EXP_WINDOW(x, a, e);
-  }
-  mp_drop(d);
-  mp_drop(spare);
-  mp_drop(a);
-  return (x);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/field-exp.h b/field-exp.h
deleted file mode 100644 (file)
index 928a893..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Exponentiation in finite fields
- *
- * (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.
- */
-
-#ifndef CATACOMB_FIELD_EXP_H
-#define CATACOMB_FIELD_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentiation definitions ----------------------------------------*/
-
-#define EXP_TYPE mp *
-
-#define EXP_COPY(d, x) d = MP_COPY(x)
-#define EXP_DROP(x) MP_DROP(x)
-
-#define EXP_MUL(a, x) a = F_MUL(f, a, a, x)
-#define EXP_SQR(a) a = F_SQR(f, a, a)
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) d = F_MUL(f, MP_NEW, x, y)
-#define EXP_SETSQR(d, x) d = F_SQR(f, MP_NEW, x)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/field-guts.h b/field-guts.h
deleted file mode 100644 (file)
index fc7ce50..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Internal structures for built-in fields
- *
- * (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.
- */
-
-#ifndef CATACOMB_FIELD_GUTS_H
-#define CATACOMB_FIELD_GUTS_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_EC_H
-#  include "ec.h"
-#endif
-
-#ifndef CATACOMB_MPMONT_H
-#  include "mpmont.h"
-#endif
-
-#ifndef CATACOMB_MPREDUCE_H
-#  include "mpreduce.h"
-#endif
-
-#ifndef CATACOMB_GF_H
-#  include "gf.h"
-#endif
-
-#ifndef CATACOMB_GFN_H
-#  include "gfn.h"
-#endif
-
-#ifndef CATACOMB_GFREDUCE_H
-#  include "gfreduce.h"
-#endif
-
-#ifndef CATACOMB_FIELD_H
-#  include "field.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct fctx_prime {
-  field f;
-  mpmont mm;
-} fctx_prime;
-
-typedef struct fctx_niceprime {
-  field f;
-  mpreduce r;
-} fctx_niceprime;
-
-typedef struct fctx_binpoly {
-  field f;
-  gfreduce r;
-} fctx_binpoly;
-
-typedef struct fctx_binnorm {
-  fctx_binpoly f;
-  gfn ntop, pton;
-} fctx_binnorm;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/field-parse.c b/field-parse.c
deleted file mode 100644 (file)
index cbbd246..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*-c-*-
- *
- * $Id: field-parse.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Parse field descriptions
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "field.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @field_parse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *
- * Returns:    Field pointer if OK, or null.
- *
- * Use:                Parses a field description, which has the form
- *
- *               * `prime', `niceprime' or `binpoly'
- *               * an optional `:'
- *               * the field modulus
- */
-
-field *field_parse(qd_parse *qd)
-{
-  field *f = 0;
-  mp *m = MP_NEW, *b = MP_NEW;
-
-  switch (qd_enum(qd, "prime,niceprime,binpoly,binnorm")) {
-    case 0:
-      qd_delim(qd, ':');
-      if ((m = qd_getmp(qd)) == 0) goto done;
-      f = field_prime(m);
-      break;
-    case 1:
-      qd_delim(qd, ':');
-      if ((m = qd_getmp(qd)) == 0) goto done;
-      f = field_niceprime(m);
-      break;
-    case 2:
-      qd_delim(qd, ':');
-      if ((m = qd_getmp(qd)) == 0) goto done;
-      f = field_binpoly(m);
-      break;
-    case 3:
-      qd_delim(qd, ':');
-      if ((m = qd_getmp(qd)) == 0) goto done;
-      qd_delim(qd, ',');
-      if ((b = qd_getmp(qd)) == 0) goto done;
-      f = field_binnorm(m, b);
-      break;
-    default:
-      goto done;
-  }
-  if (!f) qd->e = "bad field parameters";
-done:
-  mp_drop(m);
-  mp_drop(b);
-  return (f);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/field.c b/field.c
deleted file mode 100644 (file)
index 8fb1ad6..0000000
--- a/field.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Abstract field operations
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "field.h"
-#include "mp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @field_id@ --- *
- *
- * Arguments:  @field *f@ = pointer to a field
- *             @mp *d@ = a destination element
- *             @mp *x@ = a source element
- *
- * Returns:    The result element.
- *
- * Use:                An identity operation which can be used if your field has no
- *             internal representation.
- */
-
-mp *field_id(field *f, mp *d, mp *x)
-  { x = MP_COPY(x); if (d) MP_DROP(d); return (x); }
-
-/* --- @field_samep@ --- *
- *
- * Arguments:  @field *f, *g@ = two fields
- *
- * Returns:    Nonzero if the fields are identical (not just isomorphic).
- *
- * Use:                Checks for sameness of fields.  This function does the full
- *             check, not just the field-type-specific check done by the
- *             @sampep@ field operation.
- */
-
-int field_samep(field *f, field *g)
-  { return (f == g || (f->ops == g->ops && F_SAMEP(f, g))); }
-
-/* --- @field_stdsamep@ --- *
- *
- * Arguments:  @field *f, *g@ = two fields
- *
- * Returns:    Nonzero if the fields are identical (not just isomorphic).
- *
- * Use:                Standard sameness check, based on equality of the @m@
- *             member.
- */
-
-int field_stdsamep(field *f, field *g) { return (MP_EQ(f->m, g->m)); }
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/field.h b/field.h
deleted file mode 100644 (file)
index 6085716..0000000
--- a/field.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Definitions for field arithmetic
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_FIELD_H
-#define CATACOMB_FIELD_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_QDPARSE_H
-#  include "qdparse.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct field {
-  const struct field_ops *ops;         /* Field operations */
-  mp *zero, *one;                      /* Identities in the field */
-  mp *m;                               /* Modulus (prime and binary) */
-  unsigned long nbits;                 /* Length of field element in bits */
-  size_t noctets;                      /* Length of element in octets */
-  mp *q;                               /* Number of elements in field */
-} field;
-
-enum {
-  FTY_PRIME,
-  FTY_BINARY
-};
-
-typedef struct field_ops {
-
-  /* --- General information --- */
-
-  unsigned ty;                         /* What kind of field this is */
-  const char *name;                    /* Human-readable name string */
-
-  /* --- Universal operations --- */
-
-  void (*destroy)(field */*f*/);
-  mp *(*rand)(field */*f*/, mp */*d*/, grand */*r*/);
-  int (*samep)(field */*f*/, field */*g*/);
-
-  mp *(*in)(field */*f*/, mp */*d*/, mp */*x*/);
-  mp *(*out)(field */*f*/, mp */*d*/, mp */*x*/);
-
-  int (*zerop)(field */*f*/, mp */*x*/);
-  mp *(*neg)(field */*f*/, mp */*d*/, mp */*x*/);
-  mp *(*add)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
-  mp *(*sub)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
-  mp *(*mul)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
-  mp *(*sqr)(field */*f*/, mp */*d*/, mp */*x*/);
-  mp *(*inv)(field */*f*/, mp */*d*/, mp */*x*/);
-  mp *(*reduce)(field */*f*/, mp */*d*/, mp */*x*/);
-  mp *(*sqrt)(field */*f*/, mp */*d*/, mp */*x*/);
-
-  /* --- Operations for binary fields only --- */
-
-  mp *(*quadsolve)(field */*f*/, mp */*d*/, mp */*x*/);
-
-  /* --- Operations for prime fields only --- */
-
-  mp *(*dbl)(field */*f*/, mp */*d*/, mp */*x*/);
-  mp *(*tpl)(field */*f*/, mp */*d*/, mp */*x*/);
-  mp *(*qdl)(field */*f*/, mp */*d*/, mp */*x*/);
-  mp *(*hlv)(field */*f*/, mp */*d*/, mp */*x*/);
-
-} field_ops;
-
-#define F_TYPE(f)              (f)->ops->ty
-#define F_NAME(f)              (f)->ops->name
-
-#define F_DESTROY(f)           (f)->ops->destroy((f))
-#define F_RAND(f, d, r)                (f)->ops->rand((f), (d), (r))
-#define F_SAMEP(f, g)          (f)->ops->samep((f), (g))
-
-#define F_IN(f, d, x)          (f)->ops->in((f), (d), (x))
-#define F_OUT(f, d, x)         (f)->ops->out((f), (d), (x))
-
-#define F_ZEROP(f, x)          (f)->ops->zerop((f), (x))
-#define F_NEG(f, d, x)         (f)->ops->neg((f), (d), (x))
-#define F_ADD(f, d, x, y)      (f)->ops->add((f), (d), (x), (y))
-#define F_SUB(f, d, x, y)      (f)->ops->sub((f), (d), (x), (y))
-#define F_MUL(f, d, x, y)      (f)->ops->mul((f), (d), (x), (y))
-#define F_SQR(f, d, x)         (f)->ops->sqr((f), (d), (x))
-#define F_INV(f, d, x)         (f)->ops->inv((f), (d), (x))
-#define F_REDUCE(f, d, x)      (f)->ops->reduce((f), (d), (x))
-#define F_SQRT(f, d, x)                (f)->ops->sqrt((f), (d), (x))
-
-#define F_QUADSOLVE(f, d, x)   (f)->ops->quadsolve((f), (d), (x))
-
-#define F_DBL(f, d, x)         (f)->ops->dbl((f), (d), (x))
-#define F_TPL(f, d, x)         (f)->ops->tpl((f), (d), (x))
-#define F_QDL(f, d, x)         (f)->ops->qdl((f), (d), (x))
-#define F_HLV(f, d, x)         (f)->ops->hlv((f), (d), (x))
-
-/*----- Helpful field operations ------------------------------------------*/
-
-/* --- @field_id@ --- *
- *
- * Arguments:  @field *f@ = pointer to a field
- *             @mp *d@ = a destination element
- *             @mp *x@ = a source element
- *
- * Returns:    The result element.
- *
- * Use:                An identity operation which can be used if your field has no
- *             internal representation.
- */
-
-extern mp *field_id(field */*f*/, mp */*d*/, mp */*x*/);
-
-/* --- @field_samep@ --- *
- *
- * Arguments:  @field *f, *g@ = two fields
- *
- * Returns:    Nonzero if the fields are identical (not just isomorphic).
- *
- * Use:                Checks for sameness of fields.  This function does the full
- *             check, not just the field-type-specific check done by the
- *             @sampep@ field operation.
- */
-
-extern int field_samep(field */*f*/, field */*g*/);
-
-/* --- @field_stdsamep@ --- *
- *
- * Arguments:  @field *f, *g@ = two fields
- *
- * Returns:    Nonzero if the fields are identical (not just isomorphic).
- *
- * Use:                Standard sameness check, based on equality of the @m@
- *             member.
- */
-
-extern int field_stdsamep(field */*f*/, field */*g*/);
-
-/*----- Arithmetic --------------------------------------------------------*/
-
-/* --- @field_exp@ --- *
- *
- * Arguments:  @field *f@ = pointer to field
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e$%.
- *
- * Use:                Exponentiation in a finite field.  Note that all quantities
- *             are in internal format.  This is a generic implementation
- *             suitable for use with all fields and is not intended to be
- *             optimal.
- */
-
-extern mp *field_exp(field */*f*/, mp */*d*/, mp */*a*/, mp */*e*/);
-
-/*----- Creating fields ---------------------------------------------------*/
-
-/* --- @field_prime@ --- *
- *
- * Arguments:  @mp *p@ = the characteristic of the field
- *
- * Returns:    A pointer to the field.
- *
- * Use:                Creates a field structure for a prime field of size %$p$%,
- *             using Montgomery reduction for arithmetic.
- */
-
-extern field *field_prime(mp */*p*/);
-
-/* --- @field_niceprime@ --- *
- *
- * Arguments:  @mp *p@ = the characteristic of the field
- *
- * Returns:    A pointer to the field, or null.
- *
- * Use:                Creates a field structure for a prime field of size %$p$%,
- *             using efficient reduction for nice primes.
- */
-
-extern field *field_niceprime(mp */*p*/);
-
-/* --- @field_binpoly@ --- *
- *
- * Arguments:  @mp *p@ = an irreducible polynomial over %$\gf{2}$%
- *
- * Returns:    A pointer to the field.
- *
- * Use:                Creates a field structure for a binary field using naive
- *             arithmetic.
- */
-
-extern field *field_binpoly(mp */*p*/);
-
-/* --- @field_binnorm@ --- *
- *
- * Arguments:  @mp *p@ = the reduction polynomial
- *             @mp *beta@ = representation of normal point
- *
- * Returns:    A pointer to the field.
- *
- * Use:                Creates a field structure for a binary field mod @p@ which
- *             uses a normal basis representation externally.  Computations
- *             are still done on a polynomial-basis representation.
- */
-
-extern field *field_binnorm(mp */*p*/, mp */*beta*/);
-
-/* --- @field_parse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = parser context
- *
- * Returns:    Field pointer if OK, or null.
- *
- * Use:                Parses a field description, which has the form
- *
- *               * `prime', `niceprime', `binpoly', or `binnorm'
- *               * an optional `:'
- *               * the field modulus
- *               * for `binnorm', an optional `,' and the beta value
- */
-
-extern field *field_parse(qd_parse */*qd*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/fipstest.c b/fipstest.c
deleted file mode 100644 (file)
index 4563882..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* -*-c-*-
- *
- * $Id: fipstest.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * FIPS140 randomness tests
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "fipstest.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @monobit@ --- *
- *
- * Arguments:  @const octet *p@ = pointer to buffer
- *
- * Returns:    Zero if OK, @FIPSTEST_MONOBIT@ on failure.
- *
- * Use:                Performs the monobit test on a buffer of data.  If %$n_1$% is
- *             the number of 1 bits in the buffer, then the monobit test is
- *             passed when %$9654 < n_1 < 10346$%.
- */
-
-static unsigned monobit(const octet *p)
-{
-  unsigned n1 = 0;
-  unsigned i, j;
-
-  for (i = 0; i < FIPSTEST_BUFSZ; i++) {
-    octet x = p[i];
-    for (j = 0; j < 8; j++) {
-      if (x & 1)
-       n1++;
-      x >>= 1;
-    }
-  }
-
-  if (9725 >= n1 || n1 >= 10275)
-    return (FIPSTEST_MONOBIT);
-  return (0);
-}
-
-/* --- @poker@ --- *
- *
- * Arguments:  @const octet *p@ = pointer to buffer
- *
- * Returns:    Zero if OK, @FIPSTEST_POKER@ on failure.
- *
- * Use:                Performs the poker test on a buffer of data.  The buffer is
- *             divided into 4-bit nibbles %$x_i$%.  If
- *             %$f(x) = \sum_{x_i = x} 1$% is the frequency of each nibble,
- *             then the test is passed if
- *             %$2.16 < 16/5000 \sum_i f(i)^2 - 5000 < 46.17$%.
- */
-
-static unsigned poker(const octet *p)
-{
-  unsigned long f[16] = { 0 };
-  unsigned i;
-  unsigned long q = 0;
-
-  /* --- Compute the frequencies --- */
-
-  for (i = 0; i < FIPSTEST_BUFSZ; i++) {
-    octet x = p[i];
-    f[x & 0xf]++;
-    f[(x >> 4) & 0xf]++;
-  }
-
-  /* --- Now do the comparison --- *
-   *
-   * This can be simplified.  Multiply through the inequality by 5000 and
-   * we get %$5150 < 16 \sum_i f(i)^2 - 5000^2 < 287000$%.
-   */
-
-  for (i = 0; i < 16; i++)
-    q += f[i] * f[i];
-  q <<= 4;
-  q -= 5000ul * 5000ul;
-
-  if (10800 >= q || q >= 230850)
-    return (FIPSTEST_POKER);
-  return (0);
-}
-
-/* --- @runs@ --- *
- *
- * Arguments:  @const octet *p@ = pointer to buffer
- *
- * Returns:    Zero for success, @FIPSTEST_RUNS@ or @FIPSTEST_LONGRUNS@ on
- *             failure.
- *
- * Use:                Performs the runs and long runs tests.  The frequency of each
- *             `run', or sequence of equal bits, is counted and tested.
- */
-
-static unsigned runs(const octet *p)
-{
-  unsigned rc = 0;
-  unsigned i, j;
-  unsigned r = 0;
-  unsigned bb = 0;
-  unsigned f[2][6] = { { 0 } };
-
-  /* --- Count the run lengths --- */
-
-  for (i = 0; i < FIPSTEST_BUFSZ; i++) {
-    octet x = p[i];
-    for (j = 0; j < 8; j++) {
-      unsigned b = x & 1;
-      x >>= 1;
-      if (b == bb)
-       r++;
-      else {
-       if (r) {
-         if (r >= 34)
-           rc |= FIPSTEST_LONGRUNS;
-         if (r > 6)
-           r = 6;
-         f[bb][r - 1]++;
-       }
-       r = 1;
-       bb = b;
-      }
-    }
-  }
-
-  if (r >= 26)
-    rc |= FIPSTEST_LONGRUNS;
-  if (r > 6)
-    r = 6;
-  f[bb][r - 1]++;
-
-  /* --- Check the results --- */
-
-  if (2343 > f[0][0] || f[0][0] > 2657 || 2343 > f[1][0] || f[1][0] > 2657 ||
-      1135 > f[0][1] || f[0][1] > 1365 || 1135 > f[1][1] || f[1][1] > 1365 ||
-       542 > f[0][2] || f[0][2] >  708 ||  542 > f[1][2] || f[1][2] >  708 ||
-       251 > f[0][3] || f[0][3] >  373 ||  251 > f[1][3] || f[1][3] >  373 ||
-       111 > f[0][4] || f[0][4] >  201 ||  111 > f[1][4] || f[1][4] >  201 ||
-       111 > f[0][5] || f[0][5] >  201 ||  111 > f[1][5] || f[1][5] >  201)
-    rc |= FIPSTEST_RUNS;
-
-  return (rc);
-}
-
-/* --- @fipstest@ --- *
- *
- * Arguments:  @const octet *p@ = pointer to a buffer of @FIPSTEST_BUFSZ@
- *                     bytes
- *
- * Returns:    Zero if OK, or a bitmask of failed tests.
- *
- * Use:                Performs the FIPS140 randomness tests on a block of data.
- */
-
-unsigned fipstest(const octet *p)
-{
-  unsigned rc = 0;
-  rc |= monobit(p);
-  rc |= poker(p);
-  rc |= runs(p);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/fipstest.h b/fipstest.h
deleted file mode 100644 (file)
index 1db305c..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*-c-*-
- *
- * $Id: fipstest.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * FIPS140 randomness tests
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_FIPSTEST_H
-#define CATACOMB_FIPSTEST_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define FIPSTEST_BUFSZ 2500
-
-#define FIPSTEST_OK 0u
-#define FIPSTEST_MONOBIT 1u
-#define FIPSTEST_POKER 2u
-#define FIPSTEST_RUNS 4u
-#define FIPSTEST_LONGRUNS 8u
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @fipstest@ --- *
- *
- * Arguments:  @const octet *p@ = pointer to a buffer of @FIPSTEST_BUFSZ@
- *                     bytes
- *
- * Returns:    Zero if OK, or a bitmask of failed tests.
- *
- * Use:                Performs the FIPS140 randomness tests on a block of data.
- */
-
-extern unsigned fipstest(const octet */*p*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/g-bin.c b/g-bin.c
deleted file mode 100644 (file)
index bdae80a..0000000
--- a/g-bin.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Abstraction for prime groups
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/sub.h>
-
-#include "mpmont.h"
-#include "pgen.h"
-
-#define ge mp *
-#include "group.h"
-#include "group-guts.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Group operations --- */
-
-static void gdestroygroup(group *gg) {
-  gctx_bin *g = (gctx_bin *)gg;
-  mp_drop(g->gen); mp_drop(g->g.r); mp_drop(g->g.h);
-  gfreduce_destroy(&g->r);
-  DESTROY(g);
-}
-
-static mp **gcreate(group *gg)
-  { mp **x = CREATE(mp *); *x = MP_COPY(*gg->i); return (x); }
-
-static void gcopy(group *gg, mp **d, mp **x)
-  { mp *t = MP_COPY(*x); MP_DROP(*d); *d = t; }
-
-static void gburn(group *gg, mp **x) { (*x)->f |= MP_BURN; }
-
-static void gdestroy(group *gg, mp **x) { MP_DROP(*x); DESTROY(x); }
-
-static int gsamep(group *gg, group *hh) {
-  gctx_bin *g = (gctx_bin *)gg, *h = (gctx_bin *)hh;
-  return (MP_EQ(g->r.p, h->r.p));
-}
-
-static int geq(group *gg, mp **x, mp **y) { return (MP_EQ(*x, *y)); }
-
-static const char *gcheck(group *gg, grand *gr) {
-  gctx_bin *g = (gctx_bin *)gg; int rc; mp *t, *tt;
-  if (!gf_irreduciblep(g->r.p)) return ("p is not irreducible");
-  t = mp_mul(MP_NEW, g->g.r, g->g.h); t = mp_add(t, t, MP_ONE);
-  tt = mp_lsl(MP_NEW, MP_ONE, g->g.nbits);
-  rc = MP_EQ(t, tt); MP_DROP(t); MP_DROP(tt);
-  if (!rc) return ("not a subgroup");
-  return (group_stdcheck(gg, gr));
-}
-
-static void gmul(group *gg, mp **d, mp **x, mp **y) {
-  gctx_bin *g = (gctx_bin *)gg; mp *r = gf_mul(*d, *x, *y);
-  *d = gfreduce_do(&g->r, r, r);
-}
-
-static void gsqr(group *gg, mp **d, mp **x) {
-  gctx_bin *g = (gctx_bin *)gg; mp *r = gf_sqr(*d, *x);
-  *d = gfreduce_do(&g->r, r, r);
-}
-
-static void ginv(group *gg, mp **d, mp **x)
-  { gctx_bin *g = (gctx_bin *)gg; *d = gf_modinv(*d, *x, g->r.p); }
-
-static void gexp(group *gg, mp **d, mp **x, mp *n)
-  { gctx_bin *g = (gctx_bin *)gg; *d = gfreduce_exp(&g->r, *d, *x, n); }
-
-static int gread(group *gg, mp **d, const mptext_ops *ops, void *p) {
-  mp *t; if ((t = mp_read(MP_NEW, 0, ops, p)) == 0) return (-1);
-  mp_drop(*d); *d = t; return (0);
-}
-
-static int gwrite(group *gg, mp **x, const mptext_ops *ops, void *p) {
-  int rc = -1;
-  if (!ops->put("0x", 2, p) && !mp_write(*x, 16, ops, p)) rc = 0;
-  return (rc);
-}
-
-static mp *gtoint(group *gg, mp *d, mp **x) { return MP_COPY(*x); }
-
-static int gfromint(group *gg, mp **d, mp *x) { *d = MP_COPY(x); return 0; }
-
-static int gtobuf(group *gg, buf *b, mp **x)
-  { int rc = buf_putmp(b, *x); return (rc); }
-
-static int gfrombuf(group *gg, buf *b, mp **d) {
-  gctx_bin *g = (gctx_bin *)gg; mp *x;
-  if ((x = buf_getmp(b)) == 0) return (-1);
-  MP_DROP(*d); *d = gfreduce_do(&g->r, x, x);
-  return (0);
-}
-
-static int gtoraw(group *gg, buf *b, mp **x) {
-  gctx_bin * g = (gctx_bin *)gg; octet *q;
-  if ((q = buf_get(b, g->g.noctets)) == 0) return (-1);
-  mp_storeb(*x, q, g->g.noctets); return (0);
-}
-
-static int gfromraw(group *gg, buf *b, mp **d) {
-  gctx_bin * g = (gctx_bin *)gg; mp *x; octet *q;
-  if ((q = buf_get(b, g->g.noctets)) == 0) return (-1);
-  x = mp_loadb(MP_NEW, q, g->g.noctets);
-  MP_DROP(*d); *d = gfreduce_do(&g->r, x, x);
-  return (0);
-}
-
-/* --- @group_binary@ --- *
- *
- * Arguments:  @const gbin_param *gb@ = group parameters
- *
- * Returns:    A pointer to the group, or null.
- *
- * Use:                Constructs an abstract group interface for a subgroup of a
- *             prime field.  Group elements are @mp *@ pointers.
- */
-
-static const group_ops gops = {
-  GTY_BINARY, "bin",
-  gdestroygroup, gcreate, gcopy, gburn, gdestroy,
-  gsamep, geq, group_stdidentp,
-  gcheck,
-  gmul, gsqr, ginv, group_stddiv, gexp, group_stdmexp,
-  gread, gwrite,
-  gtoint, gfromint, group_stdtoec, group_stdfromec, gtobuf, gfrombuf,
-  gtoraw, gfromraw
-};
-
-group *group_binary(const gbin_param *gb)
-{
-  gctx_bin *g;
-  mp *t;
-
-  if (!MP_POSP(gb->p))
-    return (0);
-  g = CREATE(gctx_bin);
-  g->g.ops = &gops;
-  g->g.nbits = mp_bits(gb->p) - 1;
-  g->g.noctets = (g->g.nbits + 7) >> 3;
-  gfreduce_create(&g->r, gb->p);
-  g->one = MP_ONE;
-  g->g.i = &g->one;
-  g->gen = MP_COPY(gb->g);
-  g->g.g = &g->gen;
-  g->g.r = MP_COPY(gb->q);
-  t = mp_lsl(MP_NEW, MP_ONE, g->g.nbits);
-  t = mp_sub(t, t, MP_ONE);
-  g->g.h = MP_NEW; mp_div(&g->g.h, 0, t, gb->q);
-  MP_DROP(t);
-  return (&g->g);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/g-ec.c b/g-ec.c
deleted file mode 100644 (file)
index 4679742..0000000
--- a/g-ec.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Abstraction for elliptic curve groups
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <ctype.h>
-
-#include <mLib/sub.h>
-
-#define ge ec
-#include "group.h"
-#include "ec-raw.h"
-#include "group-guts.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Group operations --- */
-
-static void gdestroygroup(group *gg) {
-  gctx_ec *g = (gctx_ec *)gg;
-  EC_DESTROY(&g->gen);
-  ec_freeinfo(&g->ei);
-  DESTROY(g);
-}
-
-static ec *gcreate(group *gg)
-  { ec *x = CREATE(ec); EC_CREATE(x); return (x); }
-
-static void gcopy(group *gg, ec *d, ec *x) { EC_COPY(d, x); }
-
-static void gburn(group *gg, ec *x) { if (x->x) (x->x)->f |= MP_BURN; }
-
-static void gdestroy(group *gg, ec *x) { EC_DESTROY(x); DESTROY(x); }
-
-static int gsamep(group *gg, group *hh) {
-  gctx_ec *g = (gctx_ec *)gg, *h = (gctx_ec *)hh;
-  return (ec_sameinfop(&g->ei, &h->ei));
-}
-
-static int geq(group *gg, ec *x, ec *y) {
-  gctx_ec *g = (gctx_ec *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y);
-  return (EC_EQ(x, y));
-}
-
-static int gidentp(group *gg, ec *x) { return (EC_ATINF(x)); }
-
-static const char *gcheck(group *gg, grand *gr)
-  { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); }
-
-static void gmul(group *gg, ec *d, ec *x, ec *y)
-  { gctx_ec *g = (gctx_ec *)gg; EC_ADD(g->ei.c, d, x, y); }
-
-static void gsqr(group *gg, ec *d, ec *x)
-  { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); }
-
-static void ginv(group *gg, ec *d, ec *x)
-  { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); }
-
-static void gdiv(group *gg, ec *d, ec *x, ec *y)
-  { gctx_ec *g = (gctx_ec *)gg; EC_SUB(g->ei.c, d, x, y); }
-
-static void gexp(group *gg, ec *d, ec *x, mp *n)
-  { gctx_ec *g = (gctx_ec *)gg; ec_imul(g->ei.c, d, x, n); }
-
-static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) {
-  gctx_ec *g = (gctx_ec *)gg; size_t i;
-  ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
-  for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; }
-  ec_immul(g->ei.c, d, ff, n); xfree(ff);
-}
-
-static int gread(group *gg, ec *d, const mptext_ops *ops, void *p) {
-  gctx_ec *g = (gctx_ec *)gg;
-  ec t = EC_INIT;
-  int rc = -1;
-  int ch;
-
-  ch = ops->get(p);
-  if (tolower(ch) == 'i') {
-    if (tolower(ops->get(p)) != 'n' || tolower(ops->get(p)) != 'f')
-      return (-1);
-    EC_SETINF(d);
-    return (0);
-  }
-  ops->unget(ch, p);
-  if ((t.x = mp_read(MP_NEW, 0, ops, p)) == 0) goto done;
-  do ch = ops->get(p); while (ch == ',' || isspace(ch)); ops->unget(ch, p);
-  if ((t.y = mp_read(MP_NEW, 0, ops, p)) == 0) goto done;
-  EC_IN(g->ei.c, &t, &t);
-  if (EC_CHECK(g->ei.c, &t)) goto done;
-  EC_COPY(d, &t); rc = 0;
-  EC_DESTROY(&t);
-done:
-  return (rc);
-}
-
-static int gwrite(group *gg, ec *x, const mptext_ops *ops, void *p) {
-  gctx_ec *g = (gctx_ec *)gg; int rc = -1; ec t = EC_INIT;
-  EC_OUT(g->ei.c, &t, x); if (EC_ATINF(&t)) rc = ops->put("inf", 3, p);
-  else if (!ops->put("0x", 2, p) && !mp_write(t.x, 16, ops, p) &&
-          !ops->put(", 0x", 4, p) && !mp_write(t.y, 16, ops, p)) rc = 0;
-  EC_DESTROY(&t); return (rc);
-}
-
-static mp *gtoint(group *gg, mp *d, ec *x) {
-  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0;
-  else { EC_OUT(g->ei.c, &t, x); i = MP_COPY(t.x); EC_DESTROY(&t); }
-  mp_drop(d); return (i);
-}
-
-static int gfromint(group *gg, ec *d, mp *x) {
-  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT;
-  if (!ec_find(g->ei.c, &t, x)) return (-1);
-  EC_IN(g->ei.c, d, &t); EC_DESTROY(&t); return (0);
-}
-
-static int gtoec(group *gg, ec *d, ec *x)
-  { gctx_ec *g = (gctx_ec *)gg; EC_OUT(g->ei.c, d, x); return (0); }
-
-static int gfromec(group *gg, ec *d, const ec *x) {
-  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x);
-  rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t);
-  return (rc);
-}
-
-static int gtobuf(group *gg, buf *b, ec *x) {
-  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
-  EC_OUT(g->ei.c, &t, x); rc = buf_putec(b, &t); EC_DESTROY(&t); return (rc);
-}
-
-static int gfrombuf(group *gg, buf *b, ec *d) {
-  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
-  if (buf_getec(b, &t)) return (-1);
-  EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t);
-  if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc);
-}
-
-static int gtoraw(group *gg, buf *b, ec *x) {
-  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
-  EC_OUT(g->ei.c, &t, x); rc = ec_putraw(g->ei.c, b, &t);
-  EC_DESTROY(&t); return (rc);
-}
-
-static int gfromraw(group *gg, buf *b, ec *d) {
-  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
-  if (ec_getraw(g->ei.c, b, &t)) return (-1);
-  EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t);
-  if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc);
-}
-
-/* --- @group_ec@ --- *
- *
- * Arguments:  @const ec_info *ei@ = elliptic curve parameters
- *
- * Returns:    A pointer to the group.
- *
- * Use:                Constructs an abstract group interface for an elliptic curve
- *             group.  Group elements are @ec@ structures.  The contents of
- *             the @ec_info@ structure becomes the property of the @group@
- *             object; you can (and should) free the structure itself, but
- *             calling @ec_freeinfo@ on it is not allowed.
- */
-
-static const group_ops gops = {
-  GTY_EC, "ec",
-  gdestroygroup, gcreate, gcopy, gburn, gdestroy,
-  gsamep, geq, gidentp,
-  gcheck,
-  gmul, gsqr, ginv, gdiv, gexp, gmexp,
-  gread, gwrite,
-  gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw
-};
-
-group *group_ec(const ec_info *ei)
-{
-  gctx_ec *g = CREATE(gctx_ec);
-
-  g->g.ops = &gops;
-  g->g.nbits = ei->c->f->nbits * 2;
-  g->g.noctets = ei->c->f->noctets * 2 + 1;
-  g->ei = *ei;
-  EC_CREATE(&g->id);
-  g->g.i = &g->id;
-  EC_CREATE(&g->gen);
-  g->g.g = &g->gen;
-  EC_IN(g->ei.c, &g->gen, &ei->g);
-  g->g.r = ei->r;
-  g->g.h = ei->h;
-  return (&g->g);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/g-prime.c b/g-prime.c
deleted file mode 100644 (file)
index 5230111..0000000
--- a/g-prime.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Abstraction for prime groups
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/sub.h>
-
-#include "mpmont.h"
-#include "pgen.h"
-
-#define ge mp *
-#include "group.h"
-#include "group-guts.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Group operations --- */
-
-static void gdestroygroup(group *gg) {
-  gctx_prime *g = (gctx_prime *)gg;
-  mp_drop(g->gen); mp_drop(g->g.r); mp_drop(g->g.h);
-  mpmont_destroy(&g->mm);
-  DESTROY(g);
-}
-
-static mp **gcreate(group *gg)
-  { mp **x = CREATE(mp *); *x = MP_COPY(*gg->i); return (x); }
-
-static void gcopy(group *gg, mp **d, mp **x)
-  { mp *t = MP_COPY(*x); MP_DROP(*d); *d = t; }
-
-static void gburn(group *gg, mp **x) { (*x)->f |= MP_BURN; }
-
-static void gdestroy(group *gg, mp **x) { MP_DROP(*x); DESTROY(x); }
-
-static int gsamep(group *gg, group *hh) {
-  gctx_prime *g = (gctx_prime *)gg, *h = (gctx_prime *)hh;
-  return (MP_EQ(g->mm.m, h->mm.m));
-}
-
-static int geq(group *gg, mp **x, mp **y) { return (MP_EQ(*x, *y)); }
-
-static const char *gcheck(group *gg, grand *gr) {
-  gctx_prime *g = (gctx_prime *)gg; int rc; mp *t;
-  if (!pgen_primep(g->mm.m, gr)) return ("p is not prime");
-  t = mp_mul(MP_NEW, g->g.r, g->g.h); t = mp_add(t, t, MP_ONE);
-  rc = MP_EQ(t, g->mm.m); MP_DROP(t); if (!rc) return ("not a subgroup");
-  return (group_stdcheck(gg, gr));
-}
-
-static void gmul(group *gg, mp **d, mp **x, mp **y)
-  { gctx_prime *g = (gctx_prime *)gg; *d = mpmont_mul(&g->mm, *d, *x, *y); }
-
-static void gsqr(group *gg, mp **d, mp **x) {
-  gctx_prime *g = (gctx_prime *)gg; mp *r = mp_sqr(*d, *x);
-  *d = mpmont_reduce(&g->mm, r, r);
-}
-
-static void ginv(group *gg, mp **d, mp **x) {
-  gctx_prime *g = (gctx_prime *)gg; mp *r = mpmont_reduce(&g->mm, *d, *x);
-  r = mp_modinv(r, r, g->mm.m); *d = mpmont_mul(&g->mm, r, r, g->mm.r2);
-}
-
-static void gexp(group *gg, mp **d, mp **x, mp *n)
-  { gctx_prime *g = (gctx_prime *)gg; *d = mpmont_expr(&g->mm, *d, *x, n); }
-
-static void gmexp(group *gg, mp **d, const group_expfactor *f, size_t n) {
-  gctx_prime *g = (gctx_prime *)gg; size_t i;
-  mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor));
-  for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; }
-  *d = mpmont_mexpr(&g->mm, *d, ff, n); xfree(ff);
-}
-
-static int gread(group *gg, mp **d, const mptext_ops *ops, void *p) {
-  gctx_prime *g = (gctx_prime *)gg; mp *t;
-  if ((t = mp_read(MP_NEW, 0, ops, p)) == 0) return (-1);
-  mp_drop(*d); *d = mpmont_mul(&g->mm, t, t, g->mm.r2); return (0);
-}
-
-static int gwrite(group *gg, mp **x, const mptext_ops *ops, void *p) {
-  gctx_prime *g = (gctx_prime *)gg;
-  mp *t = mpmont_reduce(&g->mm, MP_NEW, *x);
-  int rc = mp_write(t, 10, ops, p); MP_DROP(t); return (rc);
-}
-
-static mp *gtoint(group *gg, mp *d, mp **x) {
-  gctx_prime *g = (gctx_prime *)gg;
-  return (mpmont_reduce(&g->mm, d, *x));
-}
-
-static int gfromint(group *gg, mp **d, mp *x) {
-  gctx_prime *g = (gctx_prime *)gg; mp_div(0, d, x, g->mm.m);
-  *d = mpmont_mul(&g->mm, *d, *d, g->mm.r2); return (0);
-}
-
-static int gtobuf(group *gg, buf *b, mp **x) {
-  gctx_prime *g = (gctx_prime *)gg;
-  mp *t = mpmont_reduce(&g->mm, MP_NEW, *x);
-  int rc = buf_putmp(b, t); MP_DROP(t); return (rc);
-}
-
-static int gfrombuf(group *gg, buf *b, mp **d) {
-  gctx_prime * g = (gctx_prime *)gg; mp *x;
-  if ((x = buf_getmp(b)) == 0) return (-1);
-  mp_div(0, &x, x, g->mm.m); mp_drop(*d);
-  *d = mpmont_mul(&g->mm, x, x, g->mm.r2); return(0);
-}
-
-static int gtoraw(group *gg, buf *b, mp **x) {
-  gctx_prime *g = (gctx_prime *)gg; octet *q;
-  mp *t = mpmont_reduce(&g->mm, MP_NEW, *x);
-  if ((q = buf_get(b, g->g.noctets)) == 0) { MP_DROP(t); return (-1); }
-  mp_storeb(t, q, g->g.noctets); MP_DROP(t); return (0);
-}
-
-static int gfromraw(group *gg, buf *b, mp **d) {
-  gctx_prime * g = (gctx_prime *)gg; mp *x; octet *q;
-  if ((q = buf_get(b, g->g.noctets)) == 0) return (-1);
-  x = mp_loadb(MP_NEW, q, g->g.noctets);
-  mp_div(0, &x, x, g->mm.m); mp_drop(*d);
-  *d = mpmont_mul(&g->mm, x, x, g->mm.r2); return(0);
-}
-
-/* --- @group_prime@ --- *
- *
- * Arguments:  @const gprime_param *gp@ = group parameters
- *
- * Returns:    A pointer to the group, or null.
- *
- * Use:                Constructs an abstract group interface for a subgroup of a
- *             prime field.  Group elements are @mp *@ pointers.
- */
-
-static const group_ops gops = {
-  GTY_PRIME, "prime",
-  gdestroygroup, gcreate, gcopy, gburn, gdestroy,
-  gsamep, geq, group_stdidentp,
-  gcheck,
-  gmul, gsqr, ginv, group_stddiv, gexp, gmexp,
-  gread, gwrite,
-  gtoint, gfromint, group_stdtoec, group_stdfromec, gtobuf, gfrombuf,
-  gtoraw, gfromraw
-};
-
-group *group_prime(const gprime_param *gp)
-{
-  gctx_prime *g;
-
-  if (!MP_POSP(gp->p) || !MP_ODDP(gp->p))
-    return (0);
-  g = CREATE(gctx_prime);
-  g->g.ops = &gops;
-  g->g.nbits = mp_bits(gp->p);
-  g->g.noctets = (g->g.nbits + 7) >> 3;
-  mpmont_create(&g->mm, gp->p);
-  g->g.i = &g->mm.r;
-  g->gen = mpmont_mul(&g->mm, MP_NEW, gp->g, g->mm.r2);
-  g->g.g = &g->gen;
-  g->g.r = MP_COPY(gp->q);
-  g->g.h = MP_NEW; mp_div(&g->g.h, 0, gp->p, gp->q);
-  return (&g->g);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gcipher.h b/gcipher.h
deleted file mode 100644 (file)
index 5682738..0000000
--- a/gcipher.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gcipher.h,v 1.5 2004/04/21 00:37:32 mdw Exp $
- *
- * Generic symmetric cipher interface
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_GCIPHER_H
-#define CATACOMB_GCIPHER_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_KEYSZ_H
-#  include "keysz.h"
-#endif
-
-/*----- Generic symmetric cipher interface --------------------------------*/
-
-typedef struct gcipher {
-  const struct gcipher_ops *ops;       /* Pointer to cipher operations */
-} gcipher;
-
-typedef struct gcipher_ops {
-  const struct gccipher *c;            /* Pointer to cipher class */
-  void (*encrypt)(gcipher */*c*/, const void */*s*/,
-                 void */*t*/, size_t /*sz*/);
-  void (*decrypt)(gcipher */*c*/, const void */*s*/,
-                 void */*t*/, size_t /*sz*/);
-  void (*destroy)(gcipher */*c*/);
-  void (*setiv)(gcipher */*c*/, const void */*iv*/);
-  void (*bdry)(gcipher */*c*/);
-} gcipher_ops;
-
-typedef struct gccipher {
-  const char *name;                    /* Cipher name */
-  const octet *keysz;                  /* Preferred key size table */
-  size_t blksz;                                /* Block size or zero if none */
-  gcipher *(*init)(const void */*k*/, size_t /*sz*/);
-} gccipher;
-
-#define GC_INIT(cc, k, sz)     (cc)->init((k), (sz))
-#define GC_CLASS(cc)           (cc)->ops->c
-#define GC_ENCRYPT(c, s, t, sz)        (c)->ops->encrypt((c), (s), (t), (sz))
-#define GC_DECRYPT(c, s, t, sz)        (c)->ops->decrypt((c), (s), (t), (sz))
-#define GC_DESTROY(c)          (c)->ops->destroy((c))
-#define GC_SETIV(c, iv)                (c)->ops->setiv((c), (iv))
-#define GC_BDRY(c)             (c)->ops->bdry((c))
-
-/*----- Tables ------------------------------------------------------------*/
-
-extern const gccipher *const gciphertab[];
-
-/* --- @gcipher_byname@ --- *
- *
- * Arguments:  @const char *p@ = pointer to name string
- *
- * Returns:    The named cipher class, or null.
- */
-
-extern const gccipher *gcipher_byname(const char */*p*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/gdsa.c b/gdsa.c
deleted file mode 100644 (file)
index 1f5dac7..0000000
--- a/gdsa.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "dsa.h"
-#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(const 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 = dsa_h2n(MP_NEW, g->r, 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_ZEROP(k)) goto new_k;
-  G_EXP(g, z, g->g, k);
-  sr = G_TOINT(g, sr, z); assert(sr);
-  if (MP_ZEROP(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);
-  k = mp_modinv(k, k, g->r);
-  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, *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); h = mp_modinv(MP_NEW, s->s, g->r);
-  e[0].base = g->g; e[1].base = c->p;
-  t = dsa_h2n(MP_NEW, g->r, 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
deleted file mode 100644 (file)
index f673b70..0000000
--- a/gdsa.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * 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.
- */
-
-#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(const 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
diff --git a/genlimits.c b/genlimits.c
deleted file mode 100644 (file)
index 6bd0e98..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generate limit MPs for C types
- *
- * (c) 2006 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _GNU_SOURCE
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#if __STDC_VERSION__ >= 199900l
-#  include <stdint.h>
-#  include <inttypes.h>
-#endif
-
-#include "mp.h"
-#include "mpint.h"
-
-/*----- Data types --------------------------------------------------------*/
-
-/* --- Hack for GCC --- *
- *
- * WG14 in their infinite wisdom decided not to use the GCC constant name.
- */
-
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)
-#  define EXT __extension__
-#else
-#  define EXT
-#endif
-
-#if defined(LONG_LONG_MIN) && !defined(LLONG_MIN)
-#  define LLONG_MIN EXT LONG_LONG_MIN
-#endif
-
-#if defined(LONG_LONG_MAX) && !defined(LLONG_MAX)
-#  define LLONG_MAX EXT LONG_LONG_MAX
-#endif
-
-#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
-#  define ULLONG_MAX EXT ULONG_LONG_MAX
-#endif
-
-/* --- Choose the largest integer type --- */
-
-#if defined(INTMAX_MAX)
-  typedef intmax_t imax;
-#elif defined(LLONG_MAX)
-  EXT typedef long long imax;
-#else
-  typedef long imax;
-#endif
-
-#if defined(UINTMAX_MAX)
-  typedef uintmax_t umax;
-#elif defined(ULLONG_MAX)
-  EXT typedef unsigned long long umax;
-#else
-  typedef unsigned long umax;
-#endif
-
-/*----- Main code ---------------------------------------------------------*/
-
-#define TABSZ 64
-
-enum { NEG, POS, NSIGN };
-
-umax cmap[TABSZ];
-int gmap[TABSZ][NSIGN];
-struct { int g, s; } qmap[TABSZ];
-int dumpp = 0;
-
-static int n, q;
-
-static void dump(mp *x)
-{
-  int i, w, n;
-
-  fputs("  ", stdout);
-  w = (MPW_BITS + 3)/4;
-  n = 1;
-  while (2 + 2 * n * (4 + w) < 72) n <<= 1;
-  i = 0;
-  for (;;) {
-    printf("0x%0*x", w, x->v[i]);
-    i++;
-    if (i >= MP_LEN(x)) break;
-    fputs(",", stdout);
-    if (i % n) fputs(" ", stdout); else fputs("\n  ", stdout);
-  }
-  fputs("\n", stdout);
-}
-
-static void doemit(umax c, int s, int *gg, int *qq)
-{
-  int i;
-  mp *x = MP_NEW;
-
-  for (i = 0; i < n; i++) {
-    if (cmap[i] == c)
-      goto found;
-  }
-
-  assert(i < TABSZ);
-  n = i + 1;
-  cmap[i] = c;
-  gmap[i][POS] = gmap[i][NEG] = -1;
-  if (dumpp) {
-    MP_FROMINT(x, umax, c);
-    printf("static mpw guts_%d[] = {\n", q);
-    dump(x);
-    fputs("};\n\n", stdout);
-    MP_DROP(x);
-  }
-
-found:
-  *gg = i;
-  if (gmap[i][s] < 0) {
-    assert(q < TABSZ);
-    gmap[i][s] = q;
-    qmap[q].g = i;
-    qmap[q].s = s;
-    q++;
-  }
-  *qq = gmap[i][s];
-}
-
-static void emit(imax c, int *gg, int *qq)
-{
-  umax uc;
-  int s;
-
-  if (c >= 0) { uc = c; s = POS; }
-  else { uc = -c; s = NEG; }
-  doemit(uc, s, gg, qq);
-}
-
-static void uemit(umax c, int *gg, int *qq) { doemit(c, POS, gg, qq); }
-
-struct {
-  const char *name;
-  imax min;
-  umax max;
-  int gmin, gmax;
-  int qmin, qmax;
-} tab[] = {
-  { "SCHAR",   SCHAR_MIN,      SCHAR_MAX },
-  { "CHAR",    CHAR_MIN,       CHAR_MAX },
-  { "UCHAR",   0,              UCHAR_MAX },
-  { "UINT8",   0,              0xff },
-  { "SHRT",    SHRT_MIN,       SHRT_MAX },
-  { "USHRT",   0,              USHRT_MAX },
-  { "UINT16",  0,              0xffff },
-  { "INT",     INT_MIN,        INT_MAX },
-  { "UINT",    0,              UINT_MAX },
-  { "LONG",    LONG_MIN,       LONG_MAX },
-  { "ULONG",   0,              ULONG_MAX },
-  { "UINT32",  0,              0xffffffff },
-#ifdef LLONG_MAX
-  { "LLONG",   LLONG_MIN,      LLONG_MAX },
-  { "ULLONG",  0,              ULLONG_MAX },
-#endif
-  { "SIZET",   0,              ~(size_t)0 },
-  { 0 }
-};
-
-static void dogen(void)
-{
-  int i;
-
-  for (i = 0; tab[i].name; i++) {
-    if (tab[i].min)
-      emit(tab[i].min, &tab[i].gmin, &tab[i].qmin);
-    uemit(tab[i].max, &tab[i].gmax, &tab[i].qmax);
-  }
-}
-
-static void cgen(void)
-{
-  int i;
-
-  fputs("\
-/* -*-c-*-\n\
- *\n\
- * C integer limits [generated]\n\
- */\n\
-\n\
-#include \"mplimits.h\"\n\
-\n\
-#define N(x) (sizeof(x)/sizeof(*x))\n\
-#define MPpos(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }\n\
-#define MPneg(x) { x, x + N(x), N(x), 0, MP_CONST|MP_NEG, 0 }\n\
-\n",
-       stdout);
-  dumpp = 1;
-  dogen();
-
-  fputs("mp mp_limits[] = {\n", stdout);
-  for (i = 0; i < q; i++)
-    printf("  MP%s(guts_%d),\n", qmap[i].s ? "pos" : "neg", qmap[i].g);
-  fputs("};\n", stdout);
-}
-
-static void hgen(void)
-{
-  int i;
-
-  fputs("\
-/* -*-c-*-\n\
- *\n\
- * C integer limits [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_MPLIMITS_H\n\
-#define CATACOMB_MPLIMITS_H\n\
-\n\
-#ifndef CATACOMB_MP_H\n\
-#  include \"mp.h\"\n\
-#endif\n\
-\n\
-extern mp mp_limits[];\n\
-\n",
-       stdout);
-  dogen();
-
-  for (i = 0; tab[i].name; i++) {
-    if (tab[i].min) {
-      printf("#define MP_%s_MIN (&mp_limits[%d])\n",
-            tab[i].name, gmap[tab[i].qmin][NEG]);
-    }
-    printf("#define MP_%s_MAX (&mp_limits[%d])\n",
-          tab[i].name, gmap[tab[i].qmax][POS]);
-  }
-  fputs("\n#endif\n", stdout);
-}
-
-int main(int argc, char *argv[])
-{
-  const char *what = argc == 2 ? argv[1] : "<bogus>";
-
-  switch (what[0]) {
-    case 'c': cgen(); break;
-    case 'h': hgen(); break;
-    default:
-      fprintf(stderr, "unknown action `%s'\n", what);
-      exit(1);
-  }
-  if (fflush(stdout) || fclose(stdout)) {
-    fprintf(stderr, "error writing output: %s\n", strerror(errno));
-    exit(1);
-  }
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/genprimes.c b/genprimes.c
deleted file mode 100644 (file)
index 2d80d07..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/* -*-c-*-
- *
- * $Id: genprimes.c,v 1.7 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate prime number table
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/darray.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-
-/*----- Data structures ---------------------------------------------------*/
-
-DA_DECL(intv, int);
-
-/*----- Main code ---------------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
-  int p_max = 0, p_n = 0;
-  char *type = "unsigned int";
-  char *header = "primetab.h";
-  char *source = "primetab.c";
-  char *name = "primetab";
-  char *sym = 0;
-  intv p = DA_INIT;
-  int i;
-
-  ego(argv[0]);
-
-  for (;;) {
-    int i = getopt(argc, argv, "h:c:i:n:m:t:s:");
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'h':
-       header = optarg;
-       break;
-      case 'c':
-       source = optarg;
-       break;
-      case 'i':
-       name = optarg;
-       break;
-      case 'n':
-       p_max = 0;
-       p_n = atoi(optarg);
-       break;
-      case 'm':
-       p_n = 0;
-       p_max = atoi(optarg);
-       break;
-      case 't':
-       type = optarg;
-       break;
-      case 's':
-       sym = optarg;
-       break;
-      default:
-       pquis(stderr, "Usage: $ [-n nprimes] [-m maxprime] [-t type]\n");
-       exit(EXIT_FAILURE);
-    }
-  }
-
-  if (!p_max && !p_n)
-    die(EXIT_FAILURE, "bad arguments to `-n' or `-m'");
-
-  if (p_n || p_max >= 2)
-    DA_PUSH(&p, 2);
-  for (i = 3; (!p_max && !p_n) ||
-             (p_n && DA_LEN(&p) < p_n) ||
-             (p_max && i <= p_max);
-       i += 2) {
-    int j;
-    for (j = 0; j < DA_LEN(&p); j++) {
-      if (i % DA(&p)[j] == 0)
-       goto composite;
-    }
-    DA_PUSH(&p, i);
-  composite:;
-  }
-
-  {
-    FILE *fp = fopen(header, "w");
-    dstr d = DSTR_INIT;
-    char *q;
-    if (!fp)
-      die(EXIT_FAILURE, "couldn't write `%s': %s", header, strerror(errno));
-    if (!sym) {
-      for (q = header; *q; q++) {
-       int ch = (unsigned char)*q;
-       if (isalnum(ch))
-         ch = toupper(ch);
-       else
-         ch = '_';
-       DPUTC(&d, ch);
-      }
-      DPUTZ(&d);
-      sym = d.buf;
-    }
-    fprintf(fp, "\
-/* -*-c-*-\n\
- *\n\
- * Table of small prime numbers [generated]\n\
- */\n\
-\n\
-#ifndef %s\n\
-#define %s\n\
-\n\
-#define NPRIME %luu\n\
-#define MAXPRIME %uu\n\
-\n\
-typedef %s smallprime;\n\
-extern const smallprime %s[];\n\
-\n\
-#endif\n\
-",
-           sym, sym,
-           (unsigned long)DA_LEN(&p),
-           DA_LAST(&p),
-           type, name);
-    dstr_destroy(&d);
-    if (fclose(fp) == EOF) {
-      remove(header);
-      die(EXIT_FAILURE, "error writing `%s': %s", header, strerror(errno));
-    }
-  }
-
-  {
-    FILE *fp = fopen(source, "w");
-    int i;
-    if (!fp)
-      die(EXIT_FAILURE, "couldn't write `%s': %s", source, strerror(errno));
-    fprintf(fp, "\
-/* -*-c-*-\n\
- *\n\
- * Table of small prime numbers [generated]\n\
- */\n\
-\n\
-#include \"%s\"\n\
-\n\
-const %s %s[] = {",
-           header, type, name);
-    for (i = 0; i < DA_LEN(&p); i++) {
-      if (i % 8 == 0)
-       fputs("\n  ", fp);
-      fprintf(fp, "%5i, ", DA(&p)[i]);
-    }
-    fputs("\n\
-};\n\
-", fp);
-    if (fclose(fp) == EOF) {
-      remove(source);
-      die(EXIT_FAILURE, "error writing `%s': %s", source, strerror(errno));
-    }
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gf-arith.c b/gf-arith.c
deleted file mode 100644 (file)
index 5a7b3f2..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Basic arithmetic on binary polynomials
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "gf.h"
-
-/*----- Macros ------------------------------------------------------------*/
-
-#define MAX(x, y) ((x) >= (y) ? (x) : (y))
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gf_add@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ added to @b@.
- */
-
-mp *gf_add(mp *d, mp *a, mp *b)
-{
-  MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & MP_BURN);
-  gfx_add(d->v, d->vl, a->v, a->vl, b->v, b->vl);
-  d->f = (a->f | b->f) & MP_BURN;
-  MP_SHRINK(d);
-  return (d);
-}
-
-/* --- @gf_mul@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ multiplied by @b@.
- */
-
-mp *gf_mul(mp *d, mp *a, mp *b)
-{
-  a = MP_COPY(a);
-  b = MP_COPY(b);
-
-  if (MP_LEN(a) <= MPK_THRESH || MP_LEN(b) <= GFK_THRESH) {
-    MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF);
-    gfx_mul(d->v, d->vl, a->v, a->vl, b->v, b->vl);
-  } else {
-    size_t m = MAX(MP_LEN(a), MP_LEN(b));
-    mpw *s;
-    MP_DEST(d, 2 * m, a->f | b->f | MP_UNDEF);
-    s = mpalloc(d->a, 3 * m);
-    gfx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + 3 * m);
-    mpfree(d->a, s);
-  }
-
-  d->f = (a->f | b->f) & MP_BURN;
-  MP_SHRINK(d);
-  MP_DROP(a);
-  MP_DROP(b);
-  return (d);
-}
-
-/* --- @gf_sqr@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    Result, @a@ squared.
- */
-
-mp *gf_sqr(mp *d, mp *a)
-{
-  MP_COPY(a);
-  MP_DEST(d, 2 * MP_LEN(a), a->f & MP_BURN);
-  gfx_sqr(d->v, d->vl, a->v, a->vl);
-  d->f = a->f & MP_BURN;
-  MP_SHRINK(d);
-  MP_DROP(a);
-  return (d);
-}
-
-/* --- @gf_div@ --- *
- *
- * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
- *             @mp *a, *b@ = sources
- *
- * Use:                Calculates the quotient and remainder when @a@ is divided by
- *             @b@.  The destinations @*qq@ and @*rr@ must be distinct.
- *             Either of @qq@ or @rr@ may be null to indicate that the
- *             result is irrelevant.  (Discarding both results is silly.)
- *             There is a performance advantage if @a == *rr@.
- */
-
-void gf_div(mp **qq, mp **rr, mp *a, mp *b)
- {
-  mp *r = rr ? *rr : MP_NEW;
-  mp *q = qq ? *qq : MP_NEW;
-
-  /* --- Set the remainder up right --- */
-
-  b = MP_COPY(b);
-  a = MP_COPY(a);
-  if (r)
-    MP_DROP(r);
-  r = a;
-  MP_DEST(r, MP_LEN(b) + 2, a->f | b->f);
-
-  /* --- Fix up the quotient too --- */
-
-  r = MP_COPY(r);
-  MP_DEST(q, MP_LEN(r), r->f | MP_UNDEF);
-  MP_DROP(r);
-
-  /* --- Perform the calculation --- */
-
-  gfx_div(q->v, q->vl, r->v, r->vl, b->v, b->vl);
-
-  /* --- Sort out the sign of the results --- *
-   *
-   * If the signs of the arguments differ, and the remainder is nonzero, I
-   * must add one to the absolute value of the quotient and subtract the
-   * remainder from @b@.
-   */
-
-  q->f = (r->f | b->f) & MP_BURN;
-  r->f = (r->f | b->f) & MP_BURN;
-
-  /* --- Store the return values --- */
-
-  MP_DROP(b);
-
-  if (!qq)
-    MP_DROP(q);
-  else {
-    MP_SHRINK(q);
-    *qq = q;
-  }
-
-  if (!rr)
-    MP_DROP(r);
-  else {
-    MP_SHRINK(r);
-    *rr = r;
-  }
-}
-
-/* --- @gf_irreduciblep@ --- *
- *
- * Arguments:  @mp *f@ = a polynomial
- *
- * Returns:    Nonzero if the polynomial is irreducible; otherwise zero.
- */
-
-int gf_irreduciblep(mp *f)
-{
-  unsigned long m;
-  mp *u = MP_TWO;
-  mp *v = MP_NEW;
-
-  if (MP_ZEROP(f))
-    return (0);
-  else if (MP_LEN(f) == 1) {
-    if (f->v[0] < 2) return (0);
-    if (f->v[0] < 4) return (1);
-  }
-  m = (mp_bits(f) - 1)/2;
-  while (m) {
-    u = gf_sqr(u, u);
-    gf_div(0, &u, u, f);
-    v = gf_add(v, u, MP_TWO);
-    gf_gcd(&v, 0, 0, v, f);
-    if (!MP_EQ(v, MP_ONE)) break;
-    m--;
-  }
-  MP_DROP(u);
-  MP_DROP(v);
-  return (!m);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b)
-{
-  if (!MP_EQ(expect, result)) {
-    fprintf(stderr, "\n*** %s failed", op);
-    fputs("\n*** a     = ", stderr); mp_writefile(a, stderr, 16);
-    fputs("\n*** b     = ", stderr); mp_writefile(b, stderr, 16);
-    fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 16);
-    fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 16);
-    fputc('\n', stderr);
-    return (0);
-  }
-  return (1);
-}
-
-#define RIG(name, op)                                                  \
-  static int t##name(dstr *v)                                          \
-  {                                                                    \
-    mp *a = *(mp **)v[0].buf;                                          \
-    mp *b = *(mp **)v[1].buf;                                          \
-    mp *r = *(mp **)v[2].buf;                                          \
-    mp *c = op(MP_NEW, a, b);                                          \
-    int ok = verify(#name, r, c, a, b);                                        \
-    mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(r);                    \
-    assert(mparena_count(MPARENA_GLOBAL) == 0);                                \
-    return (ok);                                                       \
-  }
-
-RIG(add, gf_add)
-RIG(mul, gf_mul)
-RIG(exp, gf_exp)
-
-#undef RIG
-
-static int tsqr(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  mp *r = *(mp **)v[1].buf;
-  mp *c = MP_NEW;
-  int ok = 1;
-  c = gf_sqr(MP_NEW, a);
-  ok &= verify("sqr", r, c, a, MP_ZERO);
-  mp_drop(a); mp_drop(r); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tdiv(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  mp *b = *(mp **)v[1].buf;
-  mp *q = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *c = MP_NEW, *d = MP_NEW;
-  int ok = 1;
-  gf_div(&c, &d, a, b);
-  ok &= verify("div(quotient)", q, c, a, b);
-  ok &= verify("div(remainder)", r, d, a, b);
-  mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(d); mp_drop(r); mp_drop(q);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tirred(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  int r = *(int *)v[1].buf;
-  int c = gf_irreduciblep(a);
-  int ok = 1;
-  if (r != c) {
-    ok = 0;
-    fprintf(stderr, "\n*** irred failed");
-    fputs("\n*** a     = ", stderr); mp_writefile(a, stderr, 16);
-    fprintf(stderr, "\n*** r     = %d\n", r);
-    fprintf(stderr, "*** c     = %d\n", c);
-  }
-  mp_drop(a);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "add", tadd, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "sqr", tsqr, { &type_mp, &type_mp, 0 } },
-  { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "irred", tirred, { &type_mp, &type_int, 0 } },
-  { 0, 0, { 0 } },
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/gf");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gf-exp.c b/gf-exp.c
deleted file mode 100644 (file)
index 92c151f..0000000
--- a/gf-exp.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Exponentiation for binary polynomials
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-
-#include "gf.h"
-#include "gf-exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gf_exp@ --- *
- *
- * Arguments:  @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e$%.
- */
-
-mp *gf_exp(mp *d, mp *a, mp *e)
-{
-  mp *x = MP_ONE;
-  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
-  assert(!MP_NEGP(e));
-
-  MP_COPY(a);
-  if (MP_ZEROP(e))
-    ;
-  else if (MP_LEN(e) < EXP_THRESH)
-    EXP_SIMPLE(x, a, e);
-  else
-    EXP_WINDOW(x, a, e);
-  mp_drop(d);
-  mp_drop(spare);
-  mp_drop(a);
-  return (x);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gf-exp.h b/gf-exp.h
deleted file mode 100644 (file)
index 85090c7..0000000
--- a/gf-exp.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Exponentiation for binary polynomials
- *
- * (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.
- */
-
-#ifndef CATACOMB_GF_EXP_H
-#define CATACOMB_GF_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentiation ----------------------------------------------------*/
-
-#define EXP_TYPE mp *
-
-#define EXP_COPY(d, x) d = MP_COPY(x)
-#define EXP_DROP(x) MP_DROP(x)
-
-#define EXP_MUL(a, x) do {                                             \
-  mp *t = gf_mul(spare, a, x);                                         \
-  spare = a;                                                           \
-  a = t;                                                               \
-} while (0)
-
-#define EXP_SQR(a) do {                                                        \
-  mp *t = gf_sqr(spare, a);                                            \
-  spare = a;                                                           \
-  a = t;                                                               \
-} while (0)
-
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) d = gf_mul(MP_NEW, x, y)
-#define EXP_SETSQR(d, x) d = gf_sqr(MP_NEW, x)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/gf-gcd.c b/gf-gcd.c
deleted file mode 100644 (file)
index 03cee47..0000000
--- a/gf-gcd.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Euclidian algorithm on binary polynomials
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "gf.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gf_gcd@ --- *
- *
- * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
- *             @mp *a, *b@ = sources (must be nonzero)
- *
- *
- * Returns:    ---
- *
- * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
- *             @ax + by = gcd(a, b)@.  This is useful for computing modular
- *             inverses.
- */
-
-void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b)
-{
-  mp *x = MP_ONE, *X = MP_ZERO;
-  mp *y = MP_ZERO, *Y = MP_ONE;
-  mp *u, *v;
-  mp *q = MP_NEW, *t, *spare = MP_NEW;
-  unsigned f = 0;
-
-#define f_swap 1u
-#define f_ext 2u
-
-  /* --- Sort out some initial flags --- */
-
-  if (xx || yy)
-    f |= f_ext;
-
-  /* --- Ensure that @a@ is larger than @b@ --- *
-   *
-   * If they're the same length we don't care which order they're in, so this
-   * unsigned comparison is fine.
-   */
-
-  if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) {
-    t = a; a = b; b = t;
-    f |= f_swap;
-  }
-
-  /* --- Check for zeroness --- */
-
-  if (MP_EQ(b, MP_ZERO)) {
-
-    /* --- Store %$|a|$% as the GCD --- */
-
-    if (gcd) {
-      if (*gcd) MP_DROP(*gcd);
-      a = MP_COPY(a);
-      *gcd = a;
-    }
-
-    /* --- Store %$1$% and %$0$% in the appropriate bins --- */
-
-    if (f & f_ext) {
-      if (f & f_swap) {
-       mp **t = xx; xx = yy; yy = t;
-      }
-      if (xx) {
-       if (*xx) MP_DROP(*xx);
-       if (MP_EQ(a, MP_ZERO))
-         *xx = MP_ZERO;
-       else
-         *xx = MP_ONE;
-      }
-      if (yy) {
-       if (*yy) MP_DROP(*yy);
-       *yy = MP_ZERO;
-      }
-    }
-    return;
-  }
-
-  /* --- Main extended Euclidean algorithm --- */
-
-  u = MP_COPY(a);
-  v = MP_COPY(b);
-
-  while (!MP_ZEROP(v)) {
-    gf_div(&q, &u, u, v);
-    if (f & f_ext) {
-      t = gf_mul(spare, X, q);
-      t = gf_add(t, t, x);
-      spare = x; x = X; X = t;
-      t = gf_mul(spare, Y, q);
-      t = gf_add(t, t, y);
-      spare = y; y = Y; Y = t;
-    }
-    t = u; u = v; v = t;
-  }
-
-  MP_DROP(q); if (spare) MP_DROP(spare);
-  if (!gcd)
-    MP_DROP(u);
-  else {
-    if (*gcd) MP_DROP(*gcd);
-    u->f &= ~MP_NEG;
-    *gcd = u;
-  }
-
-  /* --- Perform a little normalization --- */
-
-  if (f & f_ext) {
-
-    /* --- If @a@ and @b@ got swapped, swap the coefficients back --- */
-
-    if (f & f_swap) {
-      t = x; x = y; y = t;
-      t = a; a = b; b = t;
-    }
-
-    /* --- Store the results --- */
-
-    if (!xx)
-      MP_DROP(x);
-    else {
-      if (*xx) MP_DROP(*xx);
-      *xx = x;
-    }
-
-    if (!yy)
-      MP_DROP(y);
-    else {
-      if (*yy) MP_DROP(*yy);
-      *yy = y;
-    }
-  }
-
-  MP_DROP(v);
-  MP_DROP(X); MP_DROP(Y);
-}
-
-/* -- @gf_modinv@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *x@ = argument
- *             @mp *p@ = modulus
- *
- * Returns:    The inverse %$x^{-1} \bmod p$%.
- *
- * Use:                Computes a modular inverse, the catch being that the
- *             arguments and results are binary polynomials.  An assertion
- *             fails if %$p$% has no inverse.
- */
-
-mp *gf_modinv(mp *d, mp *x, mp *p)
-{
-  mp *g = MP_NEW;
-  gf_gcd(&g, 0, &d, p, x);
-  assert(MP_EQ(g, MP_ONE));
-  mp_drop(g);
-  return (d);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int gcd(dstr *v)
-{
-  int ok = 1;
-  mp *a = *(mp **)v[0].buf;
-  mp *b = *(mp **)v[1].buf;
-  mp *g = *(mp **)v[2].buf;
-  mp *x = *(mp **)v[3].buf;
-  mp *y = *(mp **)v[4].buf;
-
-  mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW;
-  gf_gcd(&gg, &xx, &yy, a, b);
-  if (!MP_EQ(x, xx)) {
-    fputs("\n*** gf_gcd(x) failed", stderr);
-    fputs("\na     = ", stderr); mp_writefile(a, stderr, 16);
-    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 16);
-    fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 16);
-    fputs("\nresult = ", stderr); mp_writefile(xx, stderr, 16);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-  if (!MP_EQ(y, yy)) {
-    fputs("\n*** gf_gcd(y) failed", stderr);
-    fputs("\na     = ", stderr); mp_writefile(a, stderr, 16);
-    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 16);
-    fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 16);
-    fputs("\nresult = ", stderr); mp_writefile(yy, stderr, 16);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  if (!ok) {
-    mp *ax = gf_mul(MP_NEW, a, xx);
-    mp *by = gf_mul(MP_NEW, b, yy);
-    ax = gf_add(ax, ax, by);
-    if (MP_EQ(ax, gg))
-      fputs("\n*** (Alternative result found.)\n", stderr);
-    MP_DROP(ax);
-    MP_DROP(by);
-  }
-
-  if (!MP_EQ(g, gg)) {
-    fputs("\n*** gf_gcd(gcd) failed", stderr);
-    fputs("\na     = ", stderr); mp_writefile(a, stderr, 16);
-    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 16);
-    fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 16);
-    fputs("\nresult = ", stderr); mp_writefile(gg, stderr, 16);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-  MP_DROP(a); MP_DROP(b); MP_DROP(g); MP_DROP(x); MP_DROP(y);
-  MP_DROP(gg); MP_DROP(xx); MP_DROP(yy);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "gcd", gcd, { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/gf");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gf.h b/gf.h
deleted file mode 100644 (file)
index 8de8231..0000000
--- a/gf.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Arithmetic on binary polynomials
- *
- * (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.
- */
-
-#ifndef CATACOMB_GF_H
-#define CATACOMB_GF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_GFX_H
-#  include "gfx.h"
-#endif
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @gf_add@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ added to @b@.
- */
-
-extern mp *gf_add(mp */*d*/, mp */*a*/, mp */*b*/);
-#define gf_sub gf_add
-
-/* --- @gf_mul@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ multiplied by @b@.
- */
-
-extern mp *gf_mul(mp */*d*/, mp */*a*/, mp */*b*/);
-
-/* --- @gf_sqr@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    Result, @a@ squared.
- */
-
-extern mp *gf_sqr(mp */*d*/, mp */*a*/);
-
-/* --- @gf_div@ --- *
- *
- * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
- *             @mp *a, *b@ = sources
- *
- * Use:                Calculates the quotient and remainder when @a@ is divided by
- *             @b@.  The destinations @*qq@ and @*rr@ must be distinct.
- *             Either of @qq@ or @rr@ may be null to indicate that the
- *             result is irrelevant.  (Discarding both results is silly.)
- *             There is a performance advantage if @a == *rr@.
- */
-
-extern void gf_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/);
-
-/* --- @gf_exp@ --- *
- *
- * Arguments:  @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e$%.
- */
-
-extern mp *gf_exp(mp */*d*/, mp */*a*/, mp */*e*/);
-
-/* --- @gf_irreduciblep@ --- *
- *
- * Arguments:  @mp *f@ = a polynomial
- *
- * Returns:    Nonzero if the polynomial is irreducible; otherwise zero.
- */
-
-extern int gf_irreduciblep(mp */*f*/);
-
-/* --- @gf_gcd@ --- *
- *
- * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
- *             @mp *a, *b@ = sources (must be nonzero)
- *
- *
- * Returns:    ---
- *
- * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
- *             @ax + by = gcd(a, b)@.  This is useful for computing modular
- *             inverses.
- */
-
-extern void gf_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/,
-                  mp */*a*/, mp */*b*/);
-
-/* -- @gf_modinv@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *x@ = argument
- *             @mp *p@ = modulus
- *
- * Returns:    The inverse %$x^{-1} \bmod p$%.
- *
- * Use:                Computes a modular inverse, the catch being that the
- *             arguments and results are binary polynomials.  An assertion
- *             fails if %$p$% has no inverse.
- */
-
-extern mp *gf_modinv(mp */*d*/, mp */*x*/, mp */*p*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/gfn.c b/gfn.c
deleted file mode 100644 (file)
index 8bfc441..0000000
--- a/gfn.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gfn.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Normal-basis translation for binary fields
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "gfreduce.h"
-#include "gfn.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gfn_copy@ --- *
- *
- * Arguments:  @gfn *d@ = where to put the copy
- *             @const gfn *s@ = where the source is
- *
- * Returns:    ---
- *
- * Use:                Makes a copy of a translation matrix.
- */
-
-void gfn_copy(gfn *d, const gfn *s)
-{
-  size_t i;
-
-  d->n = s->n;
-  d->r = xmalloc(s->n * sizeof(mp *));
-  for (i = 0; i < s->n; i++)
-    d->r[i] = MP_COPY(s->r[i]);
-}
-
-/* --- @gfn_destroy@ --- *
- *
- * Arguments:  @gfn *m@ = a transformation matrix to free
- *
- * Returns:    ---
- *
- * Use:                Frees up a transformation matrix when it's no longer wanted.
- */
-
-void gfn_destroy(gfn *m)
-  { size_t i; for (i = 0; i < m->n; i++) MP_DROP(m->r[i]); xfree(m->r); }
-
-/* --- @gfn_identity@ --- *
- *
- * Arguments:  @gfn *m@ = where to put the matrix
- *             @size_t n@ = size of the matrix
- *
- * Returns:    ---
- *
- * Use:                Fills @m@ with an identity matrix.
- */
-
-void gfn_identity(gfn *m, size_t n)
-{
-  size_t i;
-
-  m->n = n;
-  m->r = xmalloc(n * sizeof(mp *));
-  m->r[0] = MP_ONE;
-  for (i = 1; i < n; i++)
-    m->r[i] = mp_lsl(MP_NEW, m->r[i - 1], 1);
-}
-
-/* --- @gfn_invert@ --- *
- *
- * Arguments:  @gfn *m@ = a transformation matrix
- *
- * Returns:    Zero if successful, nonzero if the matrix was singular.
- *
- * Use:                Inverts a transformation matrix.
- */
-
-int gfn_invert(gfn *m)
-{
-  size_t i, j;
-  gfn mm;
-  mp *t;
-  int rc = -1;
-
-  mm = *m;
-  gfn_identity(m, mm.n);
-  for (i = 0; i < mm.n; i++) {
-    if (!mp_testbit(mm.r[i], i)) {
-      for (j = i + 1; j < mm.n; j++) {
-       if (mp_testbit(mm.r[j], i))
-         goto found_set;
-      }
-      goto fail;
-    found_set:
-      t = mm.r[i]; mm.r[i] = mm.r[j]; mm.r[j] = t;
-      t = m->r[i]; m->r[i] = m->r[j]; m->r[j] = t;
-    }
-    for (j = 0; j < mm.n; j++) {
-      if (j == i) continue;
-      if (mp_testbit(mm.r[j], i)) {
-       mm.r[j] = mp_xor(mm.r[j], mm.r[j], mm.r[i]);
-       m->r[j] = mp_xor(m->r[j], m->r[j], m->r[i]);
-      }
-    }
-  }
-  rc = 0;
-fail:
-  gfn_destroy(&mm);
-  return (rc);
-}
-
-/* --- @gfn_transform@ --- *
- *
- * Arguments:  @gfn *m@ = conversion matrix to apply
- *             @mp *d@ = destination pointer
- *             @mp *x@ = input value
- *
- * Returns:    The transformed element.
- *
- * Use:                Transforms a field element according to the given matrix.
- */
-
-mp *gfn_transform(gfn *m, mp *d, mp *x)
-{
-  mp *y = MP_ZERO;
-  size_t i;
-  mpscan sc;
-
-  for (i = 0, mp_scan(&sc, x); i < m->n && mp_step(&sc); i++)
-    if (mp_bit(&sc)) y = mp_xor(y, y, m->r[i]);
-  mp_drop(d);
-  return (y);
-}
-
-/* --- @gfn_create@ --- *
- *
- * Arguments:  @mp *p@ = modulus for polynomial basis
- *             @mp *beta@ = the generator of the normal basis, expressed
- *                     relative to the polynomial basis
- *             @gfn *ntop@ = output normal-to-polynomail conversion matrix
- *             @gfn *pton@ = output polynomial-to-normal conversion matrix
- *
- * Returns:    Zero if it worked, nonzero otherwise (e.g., if %$\beta$%
- *             doesn't generate a proper basis).
- *
- * Use:                Constructs conversion matrices between polynomial and normal
- *             basis representations of binary field elements.
- */
-
-int gfn_create(mp *p, mp *beta, gfn *ntop, gfn *pton)
-{
-  size_t m = mp_bits(p) - 1;
-  size_t i;
-  gfreduce gr;
-  gfn *np, tmp;
-
-  /* --- We start by building the the @ntop@ matrix --- *
-   *
-   * For mad reasons, the string representation of normal-basis elements is
-   * backwards.
-   */
-
-  gfreduce_create(&gr, p);
-  np = ntop ? ntop : &tmp;
-  np->n = m;
-  np->r = xmalloc(m * sizeof(mp *));
-  np->r[m - 1] = MP_COPY(beta);
-  for (i = m - 1; i--; ) {
-    mp *x = gf_sqr(MP_NEW, np->r[i + 1]);
-    np->r[i] = gfreduce_do(&gr, x, x);
-  }
-  gfreduce_destroy(&gr);
-
-  /* --- That was easy -- now invert it --- */
-
-  if (pton) {
-    if (ntop) gfn_copy(pton, np); else *pton = *np;
-    if (gfn_invert(pton)) {
-      gfn_destroy(pton);
-      if (ntop) gfn_destroy(ntop);
-      return (-1);
-    }
-  }
-
-  /* --- And we're done --- */
-
-  return (0);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int check(dstr *v)
-{
-  mp *p = *(mp **)v[0].buf;
-  mp *beta = *(mp **)v[1].buf;
-  mp *xp = *(mp **)v[2].buf;
-  mp *xn = *(mp **)v[3].buf;
-  mp *y = MP_NEW;
-  gfn pton, ntop, ii;
-  size_t i;
-  int ok = 1;
-
-  gfn_create(p, beta, &ntop, &pton);
-  gfn_identity(&ii, pton.n);
-  for (i = 0; i < pton.n; i++) {
-    y = gfn_transform(&ntop, y, pton.r[i]);
-    if (!MP_EQ(y, ii.r[i])) {
-      ok = 0;
-      fprintf(stderr, "*** inverse pton->ntop check failed (row %lu)\n",
-             (unsigned long)i);
-      MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta);
-      MP_EPRINTX("*** computed", y);
-    }
-  }
-  gfn_destroy(&ii);
-  y = gfn_transform(&pton, y, xp);
-  if (!MP_EQ(y, xn)) {
-    ok = 0;
-    fprintf(stderr, "*** pton failed\n");
-    MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta);
-    MP_EPRINTX("*** xp", xp); MP_EPRINTX("*** xn", xn);
-    MP_EPRINTX("*** computed", y);
-  }
-  y = gfn_transform(&ntop, y, xn);
-  if (!MP_EQ(y, xp)) {
-    ok = 0;
-    fprintf(stderr, "*** ntop failed\n");
-    MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta);
-    MP_EPRINTX("*** xp", xp); MP_EPRINTX("*** xn", xn);
-    MP_EPRINTX("*** computed", y);
-  }
-  gfn_destroy(&pton); gfn_destroy(&ntop);
-  mp_drop(p); mp_drop(beta); mp_drop(xp); mp_drop(xn); mp_drop(y);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "gfn", check, { &type_mp, &type_mp, &type_mp, &type_mp } },
-  { 0 }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, tests, SRCDIR "/tests/gfn");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gfn.h b/gfn.h
deleted file mode 100644 (file)
index dcb0db0..0000000
--- a/gfn.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gfn.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Normal-basis translation for binary fields
- *
- * (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.
- */
-
-#ifndef CATACOMB_GFN_H
-#define CATACOMB_GFN_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "gf.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct gfn {
-  size_t n;                            /* Number of rows */
-  mp **r;                              /* Array of the rows */
-} gfn;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @gfn_copy@ --- *
- *
- * Arguments:  @gfn *d@ = where to put the copy
- *             @const gfn *s@ = where the source is
- *
- * Returns:    ---
- *
- * Use:                Makes a copy of a translation matrix.
- */
-
-extern void gfn_copy(gfn */*d*/, const gfn */*s*/);
-
-/* --- @gfn_destroy@ --- *
- *
- * Arguments:  @gfn *m@ = a transformation matrix to free
- *
- * Returns:    ---
- *
- * Use:                Frees up a transformation matrix when it's no longer wanted.
- */
-
-extern void gfn_destroy(gfn */*m*/);
-
-/* --- @gfn_identity@ --- *
- *
- * Arguments:  @gfn *m@ = where to put the matrix
- *             @size_t n@ = size of the matrix
- *
- * Returns:    ---
- *
- * Use:                Fills @m@ with an identity matrix.
- */
-
-extern void gfn_identity(gfn */*m*/, size_t /*n*/);
-
-/* --- @gfn_invert@ --- *
- *
- * Arguments:  @gfn *m@ = a transformation matrix
- *
- * Returns:    Zero if successful, nonzero if the matrix was singular.
- *
- * Use:                Inverts a transformation matrix.
- */
-
-extern int gfn_invert(gfn */*m*/);
-
-/* --- @gfn_transform@ --- *
- *
- * Arguments:  @gfn *m@ = conversion matrix to apply
- *             @mp *d@ = destination pointer
- *             @mp *x@ = input value
- *
- * Returns:    The transformed element.
- *
- * Use:                Transforms a field element according to the given matrix.
- */
-
-extern mp *gfn_transform(gfn */*m*/, mp */*d*/, mp */*x*/);
-
-/* --- @gfn_create@ --- *
- *
- * Arguments:  @mp *p@ = modulus for polynomial basis
- *             @mp *beta@ = the generator of the normal basis, expressed
- *                     relative to the polynomial basis
- *             @gfn *ntop@ = output normal-to-polynomail conversion matrix
- *             @gfn *pton@ = output polynomial-to-normal conversion matrix
- *
- * Returns:    Zero if it worked, nonzero otherwise (e.g., if %$\beta$%
- *             doesn't generate a proper basis).
- *
- * Use:                Constructs conversion matrices between polynomial and normal
- *             basis representations of binary field elements.
- */
-
-extern int gfn_create(mp */*p*/, mp */*beta*/, gfn */*ntop*/, gfn */*pton*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/gfreduce-exp.h b/gfreduce-exp.h
deleted file mode 100644 (file)
index d4aaf0a..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gfreduce-exp.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Exponentiation operations for binary field reduction
- *
- * (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.
- */
-
-#ifndef CATACOMB_GFREDUCE_EXP_H
-#define CATACOMB_GFREDUCE_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentiation definitions ----------------------------------------*/
-
-#define EXP_TYPE mp *
-
-#define EXP_COPY(d, x) d = MP_COPY(x)
-#define EXP_DROP(x) MP_DROP(x)
-
-#define EXP_MUL(a, x) do {                                             \
-  mp *t = gf_mul(spare, a, x);                                         \
-  spare = a;                                                           \
-  a = gfreduce_do(gr, t, t);                                           \
-} while (0)
-
-#define EXP_SQR(a) do {                                                        \
-  mp *t = gf_sqr(spare, a);                                            \
-  spare = a;                                                           \
-  a = gfreduce_do(gr, t, t);                                           \
-} while (0)
-
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) do {                                       \
-  d = gf_mul(MP_NEW, x, y);                                            \
-  d = gfreduce_do(gr, d, d);                                           \
-} while (0)
-
-#define EXP_SETSQR(d, x) do {                                          \
-  d = gf_sqr(MP_NEW, x);                                               \
-  d = gfreduce_do(gr, d, d);                                           \
-} while (0)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/gfreduce.c b/gfreduce.c
deleted file mode 100644 (file)
index f9b92c8..0000000
+++ /dev/null
@@ -1,652 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Efficient reduction modulo sparse binary polynomials
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/alloc.h>
-#include <mLib/darray.h>
-#include <mLib/macros.h>
-
-#include "gf.h"
-#include "gfreduce.h"
-#include "gfreduce-exp.h"
-#include "fibrand.h"
-#include "mprand.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-DA_DECL(instr_v, gfreduce_instr);
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- What's going on here? --- *
- *
- * Let's face it, @gfx_div@ sucks.  It works (I hope), but it's not in any
- * sense fast.  Here, we do efficient reduction modulo sparse polynomials.
- *
- * Suppose we have a polynomial @X@ we're trying to reduce mod @P@.  If we
- * take the topmost nonzero word of @X@, call it @w@, then we can eliminate
- * it by subtracting off @w P x^{k}@ for an appropriate value of @k@.  The
- * trick is in observing that if @P@ is sparse we can do this multiplication
- * and subtraction efficiently, just by XORing appropriate shifts of @w@ into
- * @X@.
- *
- * The first tricky bit is in working out when to stop.  I'll use eight-bit
- * words to demonstrate what I'm talking about.
- *
- *  xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
- *                 001ppppp pppppppp pppppppp pppppppp
- *                   |<rp>|
- *                   |<------------ bp ------------->|
- *                 |<------------ nw --------------->|
- *
- * The trick of taking whole words off of @X@ stops working when there are
- * only @nw@ words left.  Then we have to mask off the bottom bits of @w@
- * before continuing.
- */
-
-/* --- @gfreduce_create@ --- *
- *
- * Arguments:  @gfreduce *r@ = structure to fill in
- *             @mp *x@ = a (hopefully sparse) polynomial
- *
- * Returns:    ---
- *
- * Use:                Initializes a context structure for reduction.
- */
-
-void gfreduce_create(gfreduce *r, mp *p)
-{
-  instr_v iv = DA_INIT;
-  unsigned long d;
-  unsigned dw;
-  mpscan sc;
-  unsigned long i;
-  gfreduce_instr *ip;
-  unsigned f = 0;
-  size_t w, ww, wi, wl, ll, bb;
-
-  /* --- Sort out the easy stuff --- */
-
-  d = mp_bits(p); assert(d); d--;
-  r->lim = d/MPW_BITS;
-  dw = d%MPW_BITS;
-  if (!dw)
-    r->mask = 0;
-  else {
-    r->mask = MPW(((mpw)-1) << dw);
-    r->lim++;
-  }
-  r->p = mp_copy(p);
-
-  /* --- Stash a new instruction --- */
-
-#define INSTR(op_, arg_) do {                                          \
-  DA_ENSURE(&iv, 1);                                                   \
-  DA(&iv)[DA_LEN(&iv)].op = (op_);                                     \
-  DA(&iv)[DA_LEN(&iv)].arg = (arg_);                                   \
-  DA_EXTEND(&iv, 1);                                                   \
-} while (0)
-
-#define f_lsr 1u
-
-  w = (d + MPW_BITS - 1)/MPW_BITS;
-  INSTR(GFRI_LOAD, w);
-  wi = DA_LEN(&iv);
-  f = 0;
-  ll = 0;
-  bb = MPW_BITS - dw;
-  for (i = 0, mp_scan(&sc, p); mp_step(&sc) && i < d; i++) {
-    if (!mp_bit(&sc))
-      continue;
-    ww = (d - i + MPW_BITS - 1)/MPW_BITS;
-    if (ww != w) {
-      wl = DA_LEN(&iv);
-      INSTR(GFRI_STORE, w);
-      if (!ll)
-       ll = DA_LEN(&iv);
-      if (!(f & f_lsr))
-       INSTR(GFRI_LOAD, ww);
-      else {
-       INSTR(GFRI_LOAD, w - 1);
-       for (; wi < wl; wi++) {
-         ip = &DA(&iv)[wi];
-         assert(ip->op == GFRI_LSL);
-         if (ip->arg)
-           INSTR(GFRI_LSR, MPW_BITS - ip->arg);
-       }
-       if (w - 1 != ww) {
-         INSTR(GFRI_STORE, w - 1);
-         INSTR(GFRI_LOAD, ww);
-       }
-       f &= ~f_lsr;
-      }
-      w = ww;
-      wi = DA_LEN(&iv);
-    }
-    INSTR(GFRI_LSL, (bb + i)%MPW_BITS);
-    if ((bb + i)%MPW_BITS)
-      f |= f_lsr;
-  }
-  wl = DA_LEN(&iv);
-  INSTR(GFRI_STORE, w);
-  if (!ll)
-    ll = DA_LEN(&iv);
-  if (f & f_lsr) {
-    INSTR(GFRI_LOAD, w - 1);
-    for (; wi < wl; wi++) {
-      ip = &DA(&iv)[wi];
-      assert(ip->op == GFRI_LSL);
-      if (ip->arg)
-       INSTR(GFRI_LSR, MPW_BITS - ip->arg);
-    }
-    INSTR(GFRI_STORE, w - 1);
-  }
-
-#undef INSTR
-
-  r->in = DA_LEN(&iv);
-  r->iv = xmalloc(r->in * sizeof(gfreduce_instr));
-  r->liv = r->iv + ll;
-  memcpy(r->iv, DA(&iv), r->in * sizeof(gfreduce_instr));
-  DA_DESTROY(&iv);
-}
-
-/* --- @gfreduce_destroy@ --- *
- *
- * Arguments:  @gfreduce *r@ = structure to free
- *
- * Returns:    ---
- *
- * Use:                Reclaims the resources from a reduction context.
- */
-
-void gfreduce_destroy(gfreduce *r)
-{
-  mp_drop(r->p);
-  xfree(r->iv);
-}
-
-/* --- @gfreduce_dump@ --- *
- *
- * Arguments:  @gfreduce *r@ = structure to dump
- *             @FILE *fp@ = file to dump on
- *
- * Returns:    ---
- *
- * Use:                Dumps a reduction context.
- */
-
-void gfreduce_dump(gfreduce *r, FILE *fp)
-{
-  size_t i;
-
-  fprintf(fp, "poly = "); mp_writefile(r->p, fp, 16);
-  fprintf(fp, "\n  lim = %lu; mask = %lx\n",
-         (unsigned long)r->lim, (unsigned long)r->mask);
-  for (i = 0; i < r->in; i++) {
-    static const char *opname[] = { "load", "lsl", "lsr", "store" };
-    assert(r->iv[i].op < N(opname));
-    fprintf(fp, "  %s %lu\n",
-           opname[r->iv[i].op],
-           (unsigned long)r->iv[i].arg);
-  }
-}
-
-/* --- @gfreduce_do@ --- *
- *
- * Arguments:  @gfreduce *r@ = reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = source
- *
- * Returns:    Destination, @x@ reduced modulo the reduction poly.
- */
-
-static void run(const gfreduce_instr *i, const gfreduce_instr *il,
-               mpw *v, mpw z)
-{
-  mpw w = 0;
-
-  for (; i < il; i++) {
-    switch (i->op) {
-      case GFRI_LOAD: w = *(v - i->arg); break;
-      case GFRI_LSL: w ^= z << i->arg; break;
-      case GFRI_LSR: w ^= z >> i->arg; break;
-      case GFRI_STORE: *(v - i->arg) = MPW(w); break;
-      default: abort();
-    }
-  }
-}
-
-mp *gfreduce_do(gfreduce *r, mp *d, mp *x)
-{
-  mpw *v, *vl;
-  const gfreduce_instr *il;
-  mpw z;
-
-  /* --- Try to reuse the source's space --- */
-
-  MP_COPY(x);
-  if (d) MP_DROP(d);
-  MP_DEST(x, MP_LEN(x), x->f);
-
-  /* --- Do the reduction --- */
-
-  il = r->iv + r->in;
-  if (MP_LEN(x) >= r->lim) {
-    v = x->v + r->lim;
-    vl = x->vl;
-    while (vl-- > v) {
-      while (*vl) {
-       z = *vl;
-       *vl = 0;
-       run(r->iv, il, vl, z);
-      }
-    }
-    if (r->mask) {
-      while (*vl & r->mask) {
-       z = *vl & r->mask;
-       *vl &= ~r->mask;
-       run(r->iv, il, vl, z);
-      }
-    }
-  }
-
-  /* --- Done --- */
-
-  MP_SHRINK(x);
-  return (x);
-}
-
-/* --- @gfreduce_sqrt@ --- *
- *
- * Arguments:  @gfreduce *r@ = pointer to reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = some polynomial
- *
- * Returns:    The square root of @x@ modulo @r->p@, or null.
- */
-
-mp *gfreduce_sqrt(gfreduce *r, mp *d, mp *x)
-{
-  mp *y = MP_COPY(x);
-  mp *z, *spare = MP_NEW;
-  unsigned long m = mp_bits(r->p) - 1;
-  unsigned long i;
-
-  for (i = 0; i < m - 1; i++) {
-    mp *t = gf_sqr(spare, y);
-    spare = y;
-    y = gfreduce_do(r, t, t);
-  }
-  z = gf_sqr(spare, y);
-  z = gfreduce_do(r, z, z);
-  if (!MP_EQ(x, z)) {
-    mp_drop(y);
-    y = 0;
-  }
-  mp_drop(z);
-  mp_drop(d);
-  return (y);
-}
-
-/* --- @gfreduce_trace@ --- *
- *
- * Arguments:  @gfreduce *r@ = pointer to reduction context
- *             @mp *x@ = some polynomial
- *
- * Returns:    The trace of @x@. (%$\Tr(x)=x + x^2 + \cdots + x^{2^{m-1}}$%
- *             if %$x \in \gf{2^m}$%).
- */
-
-int gfreduce_trace(gfreduce *r, mp *x)
-{
-  mp *y = MP_COPY(x);
-  mp *spare = MP_NEW;
-  unsigned long m = mp_bits(r->p) - 1;
-  unsigned long i;
-  int rc;
-
-  for (i = 0; i < m - 1; i++) {
-    mp *t = gf_sqr(spare, y);
-    spare = y;
-    y = gfreduce_do(r, t, t);
-    y = gf_add(y, y, x);
-  }
-  rc = !MP_ZEROP(y);
-  mp_drop(spare);
-  mp_drop(y);
-  return (rc);
-}
-
-/* --- @gfreduce_halftrace@ --- *
- *
- * Arguments:  @gfreduce *r@ = pointer to reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = some polynomial
- *
- * Returns:    The half-trace of @x@.
- *             (%$\HfTr(x)= x + x^{2^2} + \cdots + x^{2^{m-1}}$%
- *             if %$x \in \gf{2^m}$% with %$m$% odd).
- */
-
-mp *gfreduce_halftrace(gfreduce *r, mp *d, mp *x)
-{
-  mp *y = MP_COPY(x);
-  mp *spare = MP_NEW;
-  unsigned long m = mp_bits(r->p) - 1;
-  unsigned long i;
-
-  mp_drop(d);
-  for (i = 0; i < m - 1; i += 2) {
-    mp *t = gf_sqr(spare, y);
-    spare = y;
-    y = gfreduce_do(r, t, t);
-    t = gf_sqr(spare, y);
-    spare = y;
-    y = gfreduce_do(r, t, t);
-    y = gf_add(y, y, x);
-  }
-  mp_drop(spare);
-  return (y);
-}
-
-/* --- @gfreduce_quadsolve@ --- *
- *
- * Arguments:  @gfreduce *r@ = pointer to reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = some polynomial
- *
- * Returns:    A polynomial @y@ such that %$y^2 + y = x$%, or null.
- */
-
-mp *gfreduce_quadsolve(gfreduce *r, mp *d, mp *x)
-{
-  unsigned long m = mp_bits(r->p) - 1;
-  mp *t;
-
-  MP_COPY(x);
-  if (m & 1)
-    d = gfreduce_halftrace(r, d, x);
-  else {
-    mp *z, *w, *rho = MP_NEW;
-    mp *spare = MP_NEW;
-    grand *fr = fibrand_create(0);
-    unsigned long i;
-
-    for (;;) {
-      rho = mprand(rho, m, fr, 0);
-      z = MP_ZERO;
-      w = MP_COPY(rho);
-      for (i = 0; i < m - 1; i++) {
-       t = gf_sqr(spare, z); spare = z; z = gfreduce_do(r, t, t);
-       t = gf_sqr(spare, w); spare = w; w = gfreduce_do(r, t, t);
-       t = gf_mul(spare, w, x); t = gfreduce_do(r, t, t); spare = t;
-       z = gf_add(z, z, t);
-       w = gf_add(w, w, rho);
-      }
-      if (!MP_ZEROP(w))
-       break;
-      MP_DROP(z);
-      MP_DROP(w);
-    }
-    if (d) MP_DROP(d);
-    MP_DROP(w);
-    MP_DROP(spare);
-    MP_DROP(rho);
-    fr->ops->destroy(fr);
-    d = z;
-  }
-
-  t = gf_sqr(MP_NEW, d); t = gfreduce_do(r, t, t); t = gf_add(t, t, d);
-  if (!MP_EQ(t, x)) {
-    MP_DROP(d);
-    d = 0;
-  }
-  MP_DROP(t);
-  MP_DROP(x);
-  if (d) d->v[0] &= ~(mpw)1;
-  return (d);
-}
-
-/* --- @gfreduce_exp@ --- *
- *
- * Arguments:  @gfreduce *gr@ = pointer to reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e \bmod m$%.
- */
-
-mp *gfreduce_exp(gfreduce *gr, mp *d, mp *a, mp *e)
-{
-  mp *x = MP_ONE;
-  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
-
-  MP_SHRINK(e);
-  MP_COPY(a);
-  if (MP_ZEROP(e))
-    ;
-  else {
-    if (MP_NEGP(e))
-      a = gf_modinv(a, a, gr->p);
-    if (MP_LEN(e) < EXP_THRESH)
-      EXP_SIMPLE(x, a, e);
-    else
-      EXP_WINDOW(x, a, e);
-  }
-  mp_drop(d);
-  mp_drop(a);
-  mp_drop(spare);
-  return (x);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
-
-static int vreduce(dstr *v)
-{
-  mp *d = *(mp **)v[0].buf;
-  mp *n = *(mp **)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *c;
-  int ok = 1;
-  gfreduce rr;
-
-  gfreduce_create(&rr, d);
-  c = gfreduce_do(&rr, MP_NEW, n);
-  if (!MP_EQ(c, r)) {
-    fprintf(stderr, "\n*** reduction failed\n*** ");
-    gfreduce_dump(&rr, stderr);
-    fprintf(stderr, "\n*** n = "); mp_writefile(n, stderr, 16);
-    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
-    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  gfreduce_destroy(&rr);
-  mp_drop(n); mp_drop(d); mp_drop(r); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vmodexp(dstr *v)
-{
-  mp *p = *(mp **)v[0].buf;
-  mp *g = *(mp **)v[1].buf;
-  mp *x = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *c;
-  int ok = 1;
-  gfreduce rr;
-
-  gfreduce_create(&rr, p);
-  c = gfreduce_exp(&rr, MP_NEW, g, x);
-  if (!MP_EQ(c, r)) {
-    fprintf(stderr, "\n*** modexp failed\n*** ");
-    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
-    fprintf(stderr, "\n*** g = "); mp_writefile(g, stderr, 16);
-    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
-    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
-    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  gfreduce_destroy(&rr);
-  mp_drop(p); mp_drop(g); mp_drop(r); mp_drop(x); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vsqrt(dstr *v)
-{
-  mp *p = *(mp **)v[0].buf;
-  mp *x = *(mp **)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *c;
-  int ok = 1;
-  gfreduce rr;
-
-  gfreduce_create(&rr, p);
-  c = gfreduce_sqrt(&rr, MP_NEW, x);
-  if (!MP_EQ(c, r)) {
-    fprintf(stderr, "\n*** sqrt failed\n*** ");
-    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
-    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
-    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
-    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  gfreduce_destroy(&rr);
-  mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vtr(dstr *v)
-{
-  mp *p = *(mp **)v[0].buf;
-  mp *x = *(mp **)v[1].buf;
-  int r = *(int *)v[2].buf, c;
-  int ok = 1;
-  gfreduce rr;
-
-  gfreduce_create(&rr, p);
-  c = gfreduce_trace(&rr, x);
-  if (c != r) {
-    fprintf(stderr, "\n*** trace failed\n*** ");
-    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
-    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
-    fprintf(stderr, "\n*** c = %d", c);
-    fprintf(stderr, "\n*** r = %d", r);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  gfreduce_destroy(&rr);
-  mp_drop(p); mp_drop(x);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vhftr(dstr *v)
-{
-  mp *p = *(mp **)v[0].buf;
-  mp *x = *(mp **)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *c;
-  int ok = 1;
-  gfreduce rr;
-
-  gfreduce_create(&rr, p);
-  c = gfreduce_halftrace(&rr, MP_NEW, x);
-  if (!MP_EQ(c, r)) {
-    fprintf(stderr, "\n*** halftrace failed\n*** ");
-    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
-    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
-    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
-    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  gfreduce_destroy(&rr);
-  mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vquad(dstr *v)
-{
-  mp *p = *(mp **)v[0].buf;
-  mp *x = *(mp **)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *c;
-  int ok = 1;
-  gfreduce rr;
-
-  gfreduce_create(&rr, p);
-  c = gfreduce_quadsolve(&rr, MP_NEW, x);
-  if (!MP_EQ(c, r)) {
-    fprintf(stderr, "\n*** quadsolve failed\n*** ");
-    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
-    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
-    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
-    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  gfreduce_destroy(&rr);
-  mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "reduce", vreduce, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "modexp", vmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { "sqrt", vsqrt, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "trace", vtr, { &type_mp, &type_mp, &type_int, 0 } },
-  { "halftrace", vhftr, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "quadsolve", vquad, { &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/gfreduce");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gfreduce.h b/gfreduce.h
deleted file mode 100644 (file)
index 1a5685c..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gfreduce.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Reduction modulo sparse binary polynomials
- *
- * (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.
- */
-
-#ifndef CATACOMB_GFREDUCE_H
-#define CATACOMB_GFREDUCE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GF_H
-#  include "gf.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct gfreduce_instr {
-  unsigned op;                         /* Instruction opcode */
-  size_t arg;                          /* Immediate argument */
-} gfreduce_instr;
-
-enum {
-  GFRI_LOAD,                           /* Load @p[arg]@ */
-  GFRI_LSL,                            /* XOR with @w << arg@ */
-  GFRI_LSR,                            /* XOR with @w >> arg@ */
-  GFRI_STORE,                          /* Store @p[arg]@ */
-  GFRI_MAX
-};
-
-typedef struct gfreduce {
-  size_t lim;                          /* Word of degree bit */
-  mpw mask;                            /* Mask for degree word */
-  mp *p;                               /* Copy of the polynomial */
-  size_t in;                           /* Number of instruction words */
-  gfreduce_instr *iv, *liv;            /* Vector of instructions */
-} gfreduce;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @gfreduce_create@ --- *
- *
- * Arguments:  @gfreduce *r@ = structure to fill in
- *             @mp *x@ = a (hopefully sparse) polynomial
- *
- * Returns:    ---
- *
- * Use:                Initializes a context structure for reduction.
- */
-
-extern void gfreduce_create(gfreduce */*r*/, mp */*p*/);
-
-/* --- @gfreduce_destroy@ --- *
- *
- * Arguments:  @gfreduce *r@ = structure to free
- *
- * Returns:    ---
- *
- * Use:                Reclaims the resources from a reduction context.
- */
-
-extern void gfreduce_destroy(gfreduce */*r*/);
-
-/* --- @gfreduce_dump@ --- *
- *
- * Arguments:  @gfreduce *r@ = structure to dump
- *             @FILE *fp@ = file to dump on
- *
- * Returns:    ---
- *
- * Use:                Dumps a reduction context.
- */
-
-extern void gfreduce_dump(gfreduce */*r*/, FILE */*fp*/);
-
-/* --- @gfreduce_do@ --- *
- *
- * Arguments:  @gfreduce *r@ = reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = source
- *
- * Returns:    Destination, @x@ reduced modulo the reduction poly.
- */
-
-extern mp *gfreduce_do(gfreduce */*r*/, mp */*d*/, mp */*x*/);
-
-/* --- @gfreduce_sqrt@ --- *
- *
- * Arguments:  @gfreduce *r@ = pointer to reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = some polynomial
- *
- * Returns:    The square root of @x@ modulo @r->p@, or null.
- */
-
-extern mp *gfreduce_sqrt(gfreduce */*r*/, mp */*d*/, mp */*x*/);
-
-/* --- @gfreduce_trace@ --- *
- *
- * Arguments:  @gfreduce *r@ = pointer to reduction context
- *             @mp *x@ = some polynomial
- *
- * Returns:    The trace of @x@. (%$\Tr(x)=x + x^2 + \cdots + x^{2^{m-1}}$%
- *             if %$x \in \gf{2^m}$%).
- */
-
-extern int gfreduce_trace(gfreduce */*r*/, mp */*x*/);
-
-/* --- @gfreduce_halftrace@ --- *
- *
- * Arguments:  @gfreduce *r@ = pointer to reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = some polynomial
- *
- * Returns:    The half-trace of @x@.
- *             (%$\HfTr(x)= x + x^{2^2} + \cdots + x^{2^{m-1}}$%
- *             if %$x \in \gf{2^m}$% with %$m$% odd).
- */
-
-extern mp *gfreduce_halftrace(gfreduce */*r*/, mp */*d*/, mp */*x*/);
-
-/* --- @gfreduce_quadsolve@ --- *
- *
- * Arguments:  @gfreduce *r@ = pointer to reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = some polynomial
- *
- * Returns:    A polynomial @y@ such that %$y^2 + y = x$%, or null.
- */
-
-extern mp *gfreduce_quadsolve(gfreduce */*r*/, mp */*d*/, mp */*x*/);
-
-/* --- @gfreduce_exp@ --- *
- *
- * Arguments:  @gfreduce *gr@ = pointer to reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e \bmod m$%.
- */
-
-extern mp *gfreduce_exp(gfreduce */*gr*/, mp */*d*/, mp */*a*/, mp */*e*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/gfshare-mktab.c b/gfshare-mktab.c
deleted file mode 100644 (file)
index 4cf5727..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gfshare-mktab.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate tables for %$\gf{2^8}$% multiplication
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/bits.h>
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define MOD 0x11d
-
-/*----- Main code ---------------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
-  octet log[256], alog[256];
-  unsigned x;
-  unsigned i;
-
-  x = 1;
-  for (i = 0; i < 255; i++) {
-    alog[i] = x;
-    log[x] = i;
-    x <<= 1;
-    if (x & 0x100)
-      x ^= MOD;
-  }
-  log[0] = 0;
-  alog[255] = 1;
-
-  fputs("\
-/* -*-c-*-\n\
- *\n\
- * Log tables for secret sharing in %$\\gf{2^8}$% [generated]\n\
- */\n\
-\n\
-#ifndef GFSHARE_TAB_H\n\
-#define GFSHARE_TAB_H\n\
-\n\
-#define GFSHARE_LOG {                                                  \\\n\
-  ", stdout);
-
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", log[i]);
-    if (i == 255)
-      puts("                   \\\n}\n");
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  fputs("\
-#define GFSHARE_EXP {                                                  \\\n\
-  ", stdout);
-
-  for (i = 0; i < 510; i++) {
-    printf("0x%02x", alog[i % 255]);
-    if (i == 509)
-      puts("                                   \\\n}\n");
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  /* --- Done --- */
-
-  fputs("#endif\n", stdout);
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gfshare.c b/gfshare.c
deleted file mode 100644 (file)
index 99b1223..0000000
--- a/gfshare.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Secret sharing over %$\gf{2^8}$%
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-
-#include "arena.h"
-#include "gfshare.h"
-#include "gfshare-tab.h"
-#include "grand.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static const octet gflog[] = GFSHARE_LOG, gfexp[] = GFSHARE_EXP;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gfshare_create@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share context to initialize
- *             @unsigned t@ = threshold for the system
- *             @size_t sz@ = size of the secret
- *
- * Returns:    ---
- *
- * Use:                Initializes a sharing context.
- */
-
-void gfshare_create(gfshare *s, unsigned t, size_t sz)
-{
-  s->t = t;
-  s->i = 0;
-  s->sz = sz;
-  s->v = 0;
-}
-
-/* --- @gfshare_destroy@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share context to destroy
- *
- * Returns:    ---
- *
- * Use:                Disposes of a sharing context.  The allocations for the
- *             individual shares and the vector @v@ are freed; the secret is
- *             left alone.
- */
-
-void gfshare_destroy(gfshare *s)
-{
-  if (s->v)
-    XS_FREE(s->v);
-}
-
-/* --- @gfshare_mkshares@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share context to fill in
- *             @grand *r@ = pointer to random number source
- *             @const void *buf@ = pointer to the secret to share
- *
- * Returns:    ---
- *
- * Use:                Initializes a sharing context to be able to create shares.
- *             The context structure is expected to be mostly filled in.  In
- *             particular, @t@ must be initialized.  If @v@ is zero, a
- *             vector of appropriate size is allocated.  You should use the
- *             macro @GFSHARE_INIT@ or @gfshare_create@ to construct sharing
- *             contexts.
- */
-
-void gfshare_mkshares(gfshare *s, grand *r, const void *buf)
-{
-  s->v = XS_ALLOC(s->sz * s->t);
-  r->ops->fill(r, s->v, s->sz * (s->t - 1));
-  memcpy(s->v + s->sz * (s->t - 1), buf, s->sz);
-}
-
-/* --- @gfshare_get@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share conext
- *             @unsigned x@ = share index to fetch
- *             @void *buf@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Extracts a share from the system.  You may extract up to 255
- *             shares from the system.  Shares are indexed from 0.
- */
-
-void gfshare_get(gfshare *s, unsigned x, void *buf)
-{
-  unsigned i;
-  const octet *p = s->v;
-  unsigned ilog = gflog[x + 1];
-
-  /* --- Evaluate the polynomial at %$x = i + 1$% --- */
-
-  memcpy(buf, p, s->sz);
-  p += s->sz;
-
-  for (i = 1; i < s->t; i++) {
-    octet *q = buf;
-    unsigned k;
-    for (k = 0; k < s->sz; k++) {
-      unsigned qq = *q;
-      if (qq)
-       qq = gfexp[ilog + gflog[qq]];
-      *q++ = qq ^ *p++;
-    }
-  }
-}
-
-/* --- @gfshare_addedp@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to sharing context
- *             @unsigned x@ = which share number to check
- *
- * Returns:    Nonzero if share @x@ has been added already, zero if it
- *             hasn't.
- */
-
-int gfshare_addedp(gfshare *s, unsigned x)
-{
-  unsigned i;
-
-  for (i = 0; i < s->i; i++) {
-    if (GFSHARE_INDEX(s, i) == x + 1)
-      return (1);
-  }
-  return (0);
-}
-
-/* --- @gfshare_add@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to sharing context
- *             @unsigned x@ = which share number this is
- *             @const void *y@ = the share value
- *
- * Returns:    Number of shares required before recovery may be performed.
- *
- * Use:                Adds a share to the context.  The context must have been
- *             initialized with the correct threshold @t@.
- */
-
-unsigned gfshare_add(gfshare *s, unsigned x, const void *y)
-{
-  octet *p;
-
-  assert(((void)"Share context is full", s->i < s->t));
-  assert(((void)"Share already present", !gfshare_addedp(s, x)));
-
-  /* --- If no vector has been allocated, create one --- */
-
-  if (!s->v) {
-    s->v = XS_ALLOC(s->t * (s->sz + 1));
-    s->i = 0;
-  }
-
-  /* --- Store the share in the vector --- */
-
-  p = &GFSHARE_INDEX(s, s->i);
-  *p++ = x + 1;
-  memcpy(p, y, s->sz);
-  s->i++;
-
-  /* --- Done --- */
-
-  return (s->t - s->i);
-}
-
-/* --- @gfshare_combine@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share context
- *             @void *buf@ = pointer to output buffer for the secret
- *
- * Returns:    ---
- *
- * Use:                Reconstructs a secret, given enough shares.
- */
-
-void gfshare_combine(gfshare *s, void *buf)
-{
-  unsigned i, j;
-  unsigned xi, xj;
-
-  /* --- Sanity checking --- */
-
-  assert(((void)"Not enough shares yet", s->i == s->t));
-
-  /* --- Grind through the shares --- */
-
-  memset(buf, 0, s->sz);
-
-  for (i = 0; i < s->t; i++) {
-    octet *p = buf;
-    octet *q = &GFSHARE_INDEX(s, i);
-    unsigned c = 0, ci = 0;
-
-    /* --- Compute the magic coefficient --- */
-
-    xi = *q++;
-    for (j = 0; j < s->t; j++) {
-      if (i == j)
-       continue;
-      xj = GFSHARE_INDEX(s, j);
-      c += gflog[xj];
-      if (c >= 0xff)
-       c -= 0xff;
-      ci += gflog[xi ^ xj];
-      if (ci >= 0xff)
-       ci -= 0xff;
-    }
-    if (ci > c)
-      c += 0xff;
-    c -= ci;
-
-    /* --- Work out another layer of the secret --- */
-
-    p = buf;
-    for (j = 0; j < s->sz; j++) {
-      if (*q)
-       *p ^= gfexp[c + gflog[*q]];
-      p++, q++;
-    }
-  }
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include "fibrand.h"
-
-static int verify(grand *r)
-{
-  unsigned n = r->ops->range(r, 16) + 8;
-  unsigned t = r->ops->range(r, n - 1) + 1;
-  unsigned len = r->ops->range(r, 32) + 1;
-
-  octet *v = xmalloc(t * len);
-  unsigned *p = xmalloc(n * sizeof(unsigned));
-  octet *sec = xmalloc(len), *sbuf = xmalloc(len);
-  gfshare s;
-  unsigned i;
-
-  int ok = 1;
-
-  for (i = 0; i < n; i++)
-    p[i] = i;
-  for (i = 0; i < t; i++) {
-    unsigned long j = r->ops->range(r, n - i);
-    unsigned x = p[i];
-    p[i] = p[i + j];
-    p[i + j] = x;
-  }
-
-  r->ops->fill(r, sec, len);
-
-  gfshare_create(&s, t, len);
-
-  gfshare_mkshares(&s, r, sec);
-  for (i = 0; i < t; i++)
-    gfshare_get(&s, p[i], v + (i * len));
-  gfshare_destroy(&s);
-
-  gfshare_create(&s, t, len);
-  for (i = 0; i < t; i++)
-    gfshare_add(&s, p[i], v + (i * len));
-  gfshare_combine(&s, sbuf);
-  gfshare_destroy(&s);
-
-  if (memcmp(sec, sbuf, len) != 0) {
-    ok = 0;
-    fprintf(stderr, "\nbad recombination of shares\n");
-  };
-
-  xfree(sec);
-  xfree(sbuf);
-
-  xfree(v);
-  xfree(p);
-
-  return (ok);
-}
-
-int main(void)
-{
-  grand *r = fibrand_create(0);
-  unsigned i;
-  int ok = 1;
-
-  fputs("gfshare: ", stdout);
-  for (i = 0; i < 40; i++) {
-    if (!verify(r))
-      ok = 0;
-    fputc('.', stdout);
-    fflush(stdout);
-  }
-
-  if (ok)
-    fputs(" ok\n", stdout);
-  else
-    fputs(" failed\n", stdout);
-  return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gfshare.h b/gfshare.h
deleted file mode 100644 (file)
index 9826758..0000000
--- a/gfshare.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Secret sharing over %$\gf{2^8}$%
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the system -----------------------------------------------*
- *
- * This uses a variant of Shamir's secret sharing system.  Shamir's original
- * system used polynomials modulo a large prime.  This implementation instead
- * uses the field %$\gf{2^8}$%, represented by
- *
- *   %$\gf{2}[x]/(x^8 + x^4 + x^3 + x^2 + 1)$%
- *
- * and shares each byte of the secret independently.  It is therefore limited
- * to 255 players, although this probably isn't a serious limitation in
- * practice.
- *
- * Share creation and reconstruction is extremely efficient.  Contrast the
- * performance of the straightforward implementation based on multiprecision
- * arithmetic.
- */
-
-#ifndef CATACOMB_GFSHARE_H
-#define CATACOMB_GFSHARE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- A secret sharing context --- */
-
-typedef struct gfshare {
-  unsigned t;                          /* Threshold */
-  unsigned i;                          /* Next free slot in vector */
-  size_t sz;                           /* Size of the secret and shares */
-  octet *v;                            /* Vector of share information */
-} gfshare;
-
-#define GFSHARE_INIT(t, sz) { t, 0, sz, 0 }
-
-#define GFSHARE_INDEX(s, i) ((s)->v[(i) * ((s)->sz + 1)])
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @gfshare_create@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share context to initialize
- *             @unsigned t@ = threshold for the system
- *             @size_t sz@ = size of the secret
- *
- * Returns:    ---
- *
- * Use:                Initializes a sharing context.
- */
-
-extern void gfshare_create(gfshare */*s*/, unsigned /*t*/, size_t /*sz*/);
-
-/* --- @gfshare_destroy@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share context to destroy
- *
- * Returns:    ---
- *
- * Use:                Disposes of a sharing context.  The allocations for the
- *             individual shares and the vector @v@ are freed; the secret is
- *             left alone.
- */
-
-extern void gfshare_destroy(gfshare */*s*/);
-
-/* --- @gfshare_mkshares@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share context to fill in
- *             @grand *r@ = pointer to random number source
- *             @const void *buf@ = pointer to the secret to share
- *
- * Returns:    ---
- *
- * Use:                Initializes a sharing context to be able to create shares.
- *             The context structure is expected to be mostly filled in.  In
- *             particular, @t@ must be initialized.  If @v@ is zero, a
- *             vector of appropriate size is allocated.  You should use the
- *             macro @GFSHARE_INIT@ or @gfshare_create@ to construct sharing
- *             contexts.
- */
-
-extern void gfshare_mkshares(gfshare */*s*/, grand */*r*/,
-                            const void */*buf*/);
-
-/* --- @gfshare_get@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share conext
- *             @unsigned x@ = share index to fetch
- *             @void *buf@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Extracts a share from the system.  You may extract up to 255
- *             shares from the system.  Shares are indexed from 0.
- */
-
-extern void gfshare_get(gfshare */*s*/, unsigned /*x*/, void */*buf*/);
-
-/* --- @gfshare_addedp@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to sharing context
- *             @unsigned x@ = which share number to check
- *
- * Returns:    Nonzero if share @x@ has been added already, zero if it
- *             hasn't.
- */
-
-extern int gfshare_addedp(gfshare */*s*/, unsigned /*x*/);
-
-/* --- @gfshare_add@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to sharing context
- *             @unsigned x@ = which share number this is
- *             @const void *y@ = the share value
- *
- * Returns:    Number of shares required before recovery may be performed.
- *
- * Use:                Adds a share to the context.  The context must have been
- *             initialized with the correct threshold @t@.
- */
-
-extern unsigned gfshare_add(gfshare */*s*/,
-                           unsigned /*x*/, const void */*y*/);
-
-/* --- @gfshare_combine@ --- *
- *
- * Arguments:  @gfshare *s@ = pointer to share context
- *             @void *buf@ = pointer to output buffer for the secret
- *
- * Returns:    ---
- *
- * Use:                Reconstructs a secret, given enough shares.
- */
-
-extern void gfshare_combine(gfshare */*s*/, void */*buf*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/gfx-kmul.c b/gfx-kmul.c
deleted file mode 100644 (file)
index ec2bd6d..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Karatsuba's multiplication algorithm on binary polynomials
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include "gfx.h"
-#include "karatsuba.h"
-
-/*----- Tweakables --------------------------------------------------------*/
-
-#ifdef TEST_RIG
-#  undef GFK_THRESH
-#  define GFK_THRESH 1
-#endif
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gfx_kmul@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
- *             @const mpw *av, *avl@ = pointer to first argument
- *             @const mpw *bv, *bvl@ = pointer to second argument
- *             @mpw *sv, *svl@ = pointer to scratch workspace
- *
- * Returns:    ---
- *
- * Use:                Multiplies two binary polynomials using Karatsuba's
- *             algorithm.  This is rather faster than traditional long
- *             multiplication (e.g., @gfx_umul@) on polynomials with large
- *             degree, although more expensive on small ones.
- *
- *             The destination must be twice as large as the larger
- *             argument.  The scratch space must be twice as large as the
- *             larger argument.
- */
-
-void gfx_kmul(mpw *dv, mpw *dvl,
-             const mpw *av, const mpw *avl,
-             const mpw *bv, const mpw *bvl,
-             mpw *sv, mpw *svl)
-{
-  const mpw *avm, *bvm;
-  size_t m;
-
-  /* --- Dispose of easy cases to @mpx_umul@ --- *
-   *
-   * Karatsuba is only a win on large numbers, because of all the
-   * recursiveness and bookkeeping.  The recursive calls make a quick check
-   * to see whether to bottom out to @gfx_umul@ which should help quite a
-   * lot, but sometimes the only way to know is to make sure...
-   */
-
-  MPX_SHRINK(av, avl);
-  MPX_SHRINK(bv, bvl);
-
-  if (avl - av <= GFK_THRESH || bvl - bv <= GFK_THRESH) {
-    gfx_mul(dv, dvl, av, avl, bv, bvl);
-    return;
-  }
-
-  /* --- How the algorithm works --- *
-   *
-   * Let %$A = xb + y$% and %$B = ub + v$%.  Then, simply by expanding,
-   * %$AB = x u b^2 + b(x v + y u) + y v$%.  That's not helped any, because
-   * I've got four multiplications, each four times easier than the one I
-   * started with.  However, note that I can rewrite the coefficient of %$b$%
-   * as %$xv + yu = (x + y)(u + v) - xu - yv$%.  The terms %$xu$% and %$yv$%
-   * I've already calculated, and that leaves only one more multiplication to
-   * do.  So now I have three multiplications, each four times easier, and
-   * that's a win.
-   */
-
-  /* --- First things --- *
-   *
-   * Sort out where to break the factors in half.  I'll choose the midpoint
-   * of the larger one, since this minimizes the amount of work I have to do
-   * most effectively.
-   */
-
-  if (avl - av > bvl - bv) {
-    m = (avl - av + 1) >> 1;
-    avm = av + m;
-    if (bvl - bv > m)
-      bvm = bv + m;
-    else
-      bvm = bvl;
-  } else {
-    m = (bvl - bv + 1) >> 1;
-    bvm = bv + m;
-    if (avl - av > m)
-      avm = av + m;
-    else
-      avm = avl;
-  }
-
-  /* --- Sort out the middle term --- */
-
-  {
-    mpw *bsv = sv + m, *ssv = bsv + m;
-    mpw *rdv = dv + m, *rdvl = rdv + 2 * m;
-
-    assert(rdvl <= dvl);
-    assert(ssv <= svl);
-    UXOR2(sv, bsv, av, avm, avm, avl);
-    UXOR2(bsv, ssv, bv, bvm, bvm, bvl);
-    if (m > GFK_THRESH)
-      gfx_kmul(rdv, rdvl, sv, bsv, bsv, ssv, ssv, svl);
-    else
-      gfx_mul(rdv, rdvl, sv, bsv, bsv, ssv);
-  }
-
-  /* --- Sort out the other two terms --- */
-
-  {
-    mpw *svm = sv + m, *ssv = svm + m;
-    mpw *tdv = dv + m;
-    mpw *rdv = tdv + m;
-
-    if (avl == avm || bvl == bvm)
-      MPX_ZERO(rdv + m, dvl);
-    else {
-      if (m > GFK_THRESH)
-       gfx_kmul(sv, ssv, avm, avl, bvm, bvl, ssv, svl);
-      else
-       gfx_mul(sv, ssv, avm, avl, bvm, bvl);
-      MPX_COPY(rdv + m, dvl, svm, ssv);
-      UXOR(rdv, sv, svm);
-      UXOR(tdv, sv, ssv);
-    }
-
-    if (m > GFK_THRESH)
-      gfx_kmul(sv, ssv, av, avm, bv, bvm, ssv, svl);
-    else
-      gfx_mul(sv, ssv, av, avm, bv, bvm);
-    MPX_COPY(dv, tdv, sv, svm);
-    UXOR(tdv, sv, ssv);
-    UXOR(tdv, svm, ssv);
-  }
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/alloc.h>
-#include <mLib/testrig.h>
-
-#define ALLOC(v, vl, sz) do {                                          \
-  size_t _sz = (sz);                                                   \
-  mpw *_vv = xmalloc(MPWS(_sz));                                       \
-  mpw *_vvl = _vv + _sz;                                               \
-  (v) = _vv;                                                           \
-  (vl) = _vvl;                                                         \
-} while (0)
-
-#define LOAD(v, vl, d) do {                                            \
-  const dstr *_d = (d);                                                        \
-  mpw *_v, *_vl;                                                       \
-  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
-  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
-  (v) = _v;                                                            \
-  (vl) = _vl;                                                          \
-} while (0)
-
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-
-static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
-{
-  fputs(msg, stderr);
-  MPX_SHRINK(v, vl);
-  while (v < vl)
-    fprintf(stderr, " %08lx", (unsigned long)*--vl);
-  fputc('\n', stderr);
-}
-
-static int mul(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  mpw *s, *sl;
-  size_t m;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(b, bl, &v[1]);
-  LOAD(c, cl, &v[2]);
-  m = MAX(al - a, bl - b) + 1;
-  ALLOC(d, dl, 2 * m);
-  ALLOC(s, sl, 2 * m);
-
-  gfx_kmul(d, dl, a, al, b, bl, s, sl);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** mul failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("      b", b, bl);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(c); xfree(d); xfree(s);
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "mul", mul, { &type_hex, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/gfx");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gfx-sqr-mktab.c b/gfx-sqr-mktab.c
deleted file mode 100644 (file)
index c0a0b36..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gfx-sqr-mktab.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Build table for squaring of binary polynomials
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/bits.h>
-
-/*----- Main code ---------------------------------------------------------*/
-
-static void mktab(uint16 *t)
-{
-  unsigned i, j, x;
-
-  for (i = 0; i < 256; i++) {
-    x = 0;
-    for (j = 0; j < 8; j++) {
-      if (i & (1 << j))
-       x |= 1 << (2 * j);
-    }
-    t[i] = x;
-  }
-}
-
-int main(void)
-{
-  uint16 t[256];
-  unsigned i;
-
-  mktab(t);
-fputs("\
-/* -*-c-*-\n\
- *\n\
- * Bit spacing table for binary polynomial squaring\n\
- */\n\
-\n\
-#ifndef GFX_SQR_TAB_H\n\
-#define GFX_SQR_TAB_H\n\
-\n\
-#define GFX_SQRTAB {                                                   \\\n\
-  ", stdout);
-
-  for (i = 0; i < 256; i++) {
-    printf("0x%04x", t[i]);
-    if (i == 255)
-      puts("   \\\n}\n");
-    else if (i % 8 == 7)
-      fputs(", \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  fputs("#endif\n", stdout);
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gfx-sqr.c b/gfx-sqr.c
deleted file mode 100644 (file)
index ef54cf1..0000000
--- a/gfx-sqr.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Sqaring binary polynomials
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mpx.h"
-#include "gfx.h"
-#include "gfx-sqr-tab.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static const uint16 tab[256] = GFX_SQRTAB;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gfx_sqr@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = argument vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs squaring of binary polynomials.
- */
-
-void gfx_sqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl)
-{
-  mpd a = 0, aa = 0;
-  unsigned b = 0, bb = 0;
-
-  /* --- Simple stuff --- */
-
-  if (dv >= dvl)
-    return;
-  MPX_SHRINK(av, avl);
-
-  /* --- The main algorithm --- *
-   *
-   * Our method depends on the fact that, in a field of characteristic 2, we
-   * have that %$(a + b)^2 = a^2 + b^2$%.  Thus, to square a polynomial, it's
-   * sufficient just to put a zero bit between each of the bits of the
-   * original argument.  We use a precomputed table for this, and work on
-   * entire octets at a time.  Life is more complicated because we've got to
-   * be careful of bizarre architectures which don't have words with a
-   * multiple of 8 bits in them.
-   */
-
-  for (;;) {
-
-    /* --- Input buffering --- */
-
-    if (b < 8) {
-      if (av >= avl)
-       break;
-      a |= *av++ << b;
-      b += MPW_BITS;
-    }
-
-    /* --- Do the work in the middle --- */
-
-    aa |= (mpd)(tab[U8(a)]) << bb;
-    bb += 16;
-    a >>= 8;
-    b -= 8;
-
-    /* --- Output buffering --- */
-
-    if (bb >= MPW_BITS) {
-      *dv++ = MPW(aa);
-      if (dv >= dvl)
-       return;
-      aa >>= MPW_BITS;
-      bb -= MPW_BITS;
-    }
-  }
-
-  /* --- Flush the input buffer --- */
-
-  if (b) for (;;) {
-    aa |= (mpd)(tab[U8(a)]) << bb;
-    bb += 16;
-    if (bb > MPW_BITS) {
-      *dv++ = MPW(aa);
-      if (dv >= dvl)
-       return;
-      aa >>= MPW_BITS;
-      bb -= MPW_BITS;
-    }
-    a >>= 8;
-    if (b <= 8)
-      break;
-    else
-      b -= 8;
-  }
-
-  /* --- Flush the output buffer --- */
-
-  if (bb) for (;;) {
-    *dv++ = MPW(aa);
-    if (dv >= dvl)
-      return;
-    aa >>= MPW_BITS;
-    if (bb <= MPW_BITS)
-      break;
-    else
-      bb -= MPW_BITS;
-  }
-
-  /* --- Zero the rest of everything --- */
-
-  MPX_ZERO(dv, dvl);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#define ALLOC(v, vl, sz) do {                                          \
-  size_t _sz = (sz);                                                   \
-  mpw *_vv = xmalloc(MPWS(_sz));                                       \
-  mpw *_vvl = _vv + _sz;                                               \
-  (v) = _vv;                                                           \
-  (vl) = _vvl;                                                         \
-} while (0)
-
-#define LOAD(v, vl, d) do {                                            \
-  const dstr *_d = (d);                                                        \
-  mpw *_v, *_vl;                                                       \
-  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
-  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
-  (v) = _v;                                                            \
-  (vl) = _vl;                                                          \
-} while (0)
-
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-
-static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
-{
-  fputs(msg, stderr);
-  MPX_SHRINK(v, vl);
-  while (v < vl)
-    fprintf(stderr, " %08lx", (unsigned long)*--vl);
-  fputc('\n', stderr);
-}
-
-static int vsqr(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(b, bl, &v[1]);
-  ALLOC(d, dl, 2 * (al - a));
-
-  gfx_sqr(d, dl, a, al);
-  if (!mpx_ueq(d, dl, b, bl)) {
-    fprintf(stderr, "\n*** vsqr failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("expected", b, bl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(d);
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "sqr", vsqr, { &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/gfx");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gfx.c b/gfx.c
deleted file mode 100644 (file)
index b1bdd51..0000000
--- a/gfx.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Low-level arithmetic on binary polynomials
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-
-#include "mpx.h"
-#include "mpscan.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gfx_add@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = first addend vector base and limit
- *             @const mpw *bv, *bvl@ = second addend vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Adds two %$\gf{2}$% polynomials.  This is the same as
- *             subtraction.
- */
-
-void gfx_add(mpw *dv, mpw *dvl,
-            const mpw *av, const mpw *avl,
-            const mpw *bv, const mpw *bvl)
-{
-  MPX_SHRINK(av, avl);
-  MPX_SHRINK(bv, bvl);
-
-  while (av < avl || bv < bvl) {
-    mpw a, b;
-    if (dv >= dvl)
-      return;
-    a = (av < avl) ? *av++ : 0;
-    b = (bv < bvl) ? *bv++ : 0;
-    *dv++ = a ^ b;
-  }
-  if (dv < dvl)
-    MPX_ZERO(dv, dvl);
-}
-
-/* --- @gfx_acc@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = addend vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Adds the addend into the destination.  This is considerably
- *             faster than the three-address add call.
- */
-
-void gfx_acc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl)
-{
-  size_t dlen, alen;
-
-  MPX_SHRINK(av, avl);
-  dlen = dvl - dv;
-  alen = avl - av;
-  if (dlen < alen)
-    avl = av + dlen;
-  while (av < avl)
-    *dv++ ^= *av++;
-}
-
-/* --- @gfx_accshift@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = addend vector base and limit
- *             @size_t n@ = number of bits to shift
- *
- * Returns:    ---
- *
- * Use:                Shifts the argument left by %$n$% places and adds it to the
- *             destination.  This is a primitive used by multiplication and
- *             division.
- */
-
-void gfx_accshift(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
-{
-  size_t c = n / MPW_BITS;
-  mpw x = 0, y;
-  size_t dlen, alen;
-
-  /* --- Sort out the shift amounts --- */
-
-  if (dvl - dv < c)
-    return;
-  dv += c;
-  n %= MPW_BITS;
-  if (!n) {
-    gfx_acc(dv, dvl, av, avl);
-    return;
-  }
-  c = MPW_BITS - n;
-
-  /* --- Sort out vector lengths --- */
-
-  MPX_SHRINK(av, avl);
-  dlen = dvl - dv;
-  alen = avl - av;
-  if (dlen < alen)
-    avl = av + dlen;
-
-  /* --- Now do the hard work --- */
-
-  while (av < avl) {
-    y = *av++;
-    *dv++ ^= MPW((y << n) | (x >> c));
-    x = y;
-  }
-  if (dv < dvl)
-    *dv++ ^= x >> c;
-}
-
-/* --- @gfx_mul@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = first argument vector base and limit
- *             @const mpw *bv, *bvl@ = second argument vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Does multiplication of polynomials over %$\gf{2}$%.
- */
-
-void gfx_mul(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,
-            const mpw *bv, const mpw *bvl)
-{
-  mpscan sc;
-  const mpw *v;
-  mpw *vv;
-  mpw z;
-  mpd x, y;
-
-  MPX_SHRINK(av, avl);
-  MPX_SHRINK(bv, bvl);
-  MPSCAN_INITX(&sc, av, avl);
-  MPX_ZERO(dv, dvl);
-
-  while (bv < bvl && dv < dvl) {
-    x = 0;
-    for (v = av, vv = dv++; v < avl && vv < dvl; v++) {
-      z = *bv; y = *v;
-      while (z) {
-       if (z & 1u) x ^= y;
-       z >>= 1; y <<= 1;
-      }
-      *vv++ ^= MPW(x);
-      x >>= MPW_BITS;
-    }
-    if (vv < dvl)
-      *vv++ = MPW(x);
-    bv++;
-  }
-}
-
-/* --- @gfx_div@ --- *
- *
- * Arguments:  @mpw *qv, *qvl@ = quotient vector base and limit
- *             @mpw *rv, *rvl@ = dividend/remainder vector base and limit
- *             @const mpw *dv, *dvl@ = divisor vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs division on polynomials over %$\gf{2}$%.
- */
-
-void gfx_div(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl,
-            const mpw *dv, const mpw *dvl)
-{
-  size_t dlen, rlen, qlen;
-  size_t dbits;
-  mpw *rvv, *rvd;
-  unsigned rvm, n, qi;
-  mpw q;
-
-  MPX_SHRINK(rv, rvl);
-  MPX_SHRINK(dv, dvl);
-  assert(((void)"division by zero in gfx_div", dv < dvl));
-  MPX_BITS(dbits, dv, dvl);
-  dlen = dvl - dv;
-  rlen = rvl - rv;
-  qlen = qvl - qv;
-
-  MPX_ZERO(qv, qvl);
-  if (dlen > rlen)
-    return;
-  rvd = rvl - dlen;
-  rvv = rvl - 1;
-  rvm = 1 << (MPW_BITS - 1);
-  n = MPW_BITS - (dbits % MPW_BITS);
-  if (n == MPW_BITS)
-    n = 0;
-  q = 0;
-  qi = rvd - rv;
-
-  for (;;) {
-    q <<= 1;
-    if (*rvv & rvm) {
-      q |= 1;
-      gfx_accshift(rvd, rvl, dv, dvl, n);
-    }
-    rvm >>= 1;
-    if (!rvm) {
-      rvm = 1 << (MPW_BITS - 1);
-      rvv--;
-    }
-    if (n)
-      n--;
-    else {
-      if (qi < qlen)
-       qv[qi] = q;
-      q = 0;
-      qi--;
-      if (rvd == rv)
-       break;
-      n = MPW_BITS - 1;
-      rvd--;
-    }
-  }
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#define ALLOC(v, vl, sz) do {                                          \
-  size_t _sz = (sz);                                                   \
-  mpw *_vv = xmalloc(MPWS(_sz));                                       \
-  mpw *_vvl = _vv + _sz;                                               \
-  (v) = _vv;                                                           \
-  (vl) = _vvl;                                                         \
-} while (0)
-
-#define LOAD(v, vl, d) do {                                            \
-  const dstr *_d = (d);                                                        \
-  mpw *_v, *_vl;                                                       \
-  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
-  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
-  (v) = _v;                                                            \
-  (vl) = _vl;                                                          \
-} while (0)
-
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-
-static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
-{
-  fputs(msg, stderr);
-  MPX_SHRINK(v, vl);
-  while (v < vl)
-    fprintf(stderr, " %08lx", (unsigned long)*--vl);
-  fputc('\n', stderr);
-}
-
-static int vadd(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(b, bl, &v[1]);
-  LOAD(c, cl, &v[2]);
-  ALLOC(d, dl, MAX(al - a, bl - b) + 1);
-
-  gfx_add(d, dl, a, al, b, bl);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** vadd failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("      b", b, bl);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int vmul(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(b, bl, &v[1]);
-  LOAD(c, cl, &v[2]);
-  ALLOC(d, dl, (al - a) + (bl - b));
-
-  gfx_mul(d, dl, a, al, b, bl);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** vmul failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("      b", b, bl);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int vdiv(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *q, *ql;
-  mpw *r, *rl;
-  mpw *qq, *qql;
-  int ok = 1;
-
-  ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len);
-  LOAD(b, bl, &v[1]);
-  LOAD(q, ql, &v[2]);
-  LOAD(r, rl, &v[3]);
-  ALLOC(qq, qql, al - a);
-
-  gfx_div(qq, qql, a, al, b, bl);
-  if (!mpx_ueq(qq, qql, q, ql) ||
-      !mpx_ueq(a, al, r, rl)) {
-    fprintf(stderr, "\n*** vdiv failed\n");
-    dumpmp(" divisor", b, bl);
-    dumpmp("expect r", r, rl);
-    dumpmp("result r", a, al);
-    dumpmp("expect q", q, ql);
-    dumpmp("result q", qq, qql);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(r); xfree(q); xfree(qq);
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "add", vadd, { &type_hex, &type_hex, &type_hex, 0 } },
-  { "mul", vmul, { &type_hex, &type_hex, &type_hex, 0 } },
-  { "div", vdiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/gfx");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/gfx.h b/gfx.h
deleted file mode 100644 (file)
index 91ea226..0000000
--- a/gfx.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gfx.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Low-level arithmetic on binary polynomials
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_GFX_H
-#define CATACOMB_GFX_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MPX_H
-#  include "mpx.h"
-#endif
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @gfx_add@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = first addend vector base and limit
- *             @const mpw *bv, *bvl@ = second addend vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Adds two %$\gf{2}$% polynomials.  This is the same as
- *             subtraction.
- */
-
-extern void gfx_add(mpw */*dv*/, mpw */*dvl*/,
-                   const mpw */*av*/, const mpw */*avl*/,
-                   const mpw */*bv*/, const mpw */*bvl*/);
-
-/* --- @gfx_acc@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = addend vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Adds the addend into the destination.  This is considerably
- *             faster than the three-address add call.
- */
-
-extern void gfx_acc(mpw */*dv*/, mpw */*dvl*/,
-                   const mpw */*av*/, const mpw */*avl*/);
-
-/* --- @gfx_accshift@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = addend vector base and limit
- *             @size_t n@ = number of bits to shift
- *
- * Returns:    ---
- *
- * Use:                Shifts the argument left by %$n$% places and adds it to the
- *             destination.  This is a primitive used by multiplication and
- *             division.
- */
-
-extern void gfx_accshift(mpw */*dv*/, mpw */*dvl*/,
-                        const mpw */*av*/, const mpw */*avl*/,
-                        size_t /*n*/);
-
-/* --- @gfx_mul@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = first argument vector base and limit
- *             @const mpw *bv, *bvl@ = second argument vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Does multiplication of polynomials over %$\gf{2}$%.
- */
-
-extern void gfx_mul(mpw */*dv*/, mpw */*dvl*/,
-                   const mpw */*av*/, const mpw */*avl*/,
-                   const mpw */*bv*/, const mpw */*bvl*/);
-
-/* --- @gfx_sqr@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = argument vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs squaring of binary polynomials.
- */
-
-extern void gfx_sqr(mpw */*dv*/, mpw */*dvl*/,
-                   const mpw */*av*/, const mpw */*avl*/);
-
-/* --- @gfx_div@ --- *
- *
- * Arguments:  @mpw *qv, *qvl@ = quotient vector base and limit
- *             @mpw *rv, *rvl@ = dividend/remainder vector base and limit
- *             @const mpw *dv, *dvl@ = divisor vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs division on polynomials over %$\gf{2}$%.
- */
-
-extern void gfx_div(mpw */*qv*/, mpw */*qvl*/, mpw */*rv*/, mpw */*rvl*/,
-                   const mpw */*dv*/, const mpw */*dvl*/);
-
-/*----- Karatsuba multiplication algorithms -------------------------------*/
-
-/* --- @GFK_THRESH@ --- *
- *
- * This is the limiting length for using Karatsuba algorithms.  It's best to
- * use the simpler classical multiplication method on numbers smaller than
- * this.
- */
-
-#define GFK_THRESH 2
-
-/* --- @gfx_kmul@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
- *             @const mpw *av, *avl@ = pointer to first argument
- *             @const mpw *bv, *bvl@ = pointer to second argument
- *             @mpw *sv, *svl@ = pointer to scratch workspace
- *
- * Returns:    ---
- *
- * Use:                Multiplies two binary polynomials using Karatsuba's
- *             algorithm.  This is rather faster than traditional long
- *             multiplication (e.g., @gfx_umul@) on polynomials with large
- *             degree, although more expensive on small ones.
- *
- *             The destination must be twice as large as the larger
- *             argument.  The scratch space must be twice as large as the
- *             larger argument.
- */
-
-extern void gfx_kmul(mpw */*dv*/, mpw */*dvl*/,
-                    const mpw */*av*/, const mpw */*avl*/,
-                    const mpw */*bv*/, const mpw */*bvl*/,
-                    mpw */*sv*/, mpw */*svl*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ghash-def.h b/ghash-def.h
deleted file mode 100644 (file)
index 6d20e5b..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ghash-def.h,v 1.7 2004/04/08 01:36:15 mdw Exp $
- *
- * Definitions for generic hash interface
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_GHASH_DEF_H
-#define CATACOMB_GHASH_DEF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-/*----- Generic hash function interface -----------------------------------*/
-
-/* --- @GHASH_DEF@ --- *
- *
- * Arguments:  @PRE, pre@ = prefixes for hash function
- *
- * Use:                Defines the generic hash instance.
- */
-
-#define GHASH_DEF(PRE, pre)                                            \
-                                                                       \
-static const ghash_ops gops;                                           \
-                                                                       \
-typedef struct gctx {                                                  \
-  ghash h;                                                             \
-  pre##_ctx c;                                                         \
-  octet buf[PRE##_HASHSZ];                                             \
-} gctx;                                                                        \
-                                                                       \
-static ghash *ghinit(void)                                             \
-{                                                                      \
-  gctx *g = S_CREATE(gctx);                                            \
-  g->h.ops = &gops;                                                    \
-  pre##_init(&g->c);                                                   \
-  return (&g->h);                                                      \
-}                                                                      \
-                                                                       \
-static void ghhash(ghash *h, const void *p, size_t sz)                 \
-{                                                                      \
-  gctx *g = (gctx *)h;                                                 \
-  pre##_hash(&g->c, p, sz);                                            \
-}                                                                      \
-                                                                       \
-static octet *ghdone(ghash *h, void *buf)                              \
-{                                                                      \
-  gctx *g = (gctx *)h;                                                 \
-  if (!buf)                                                            \
-    buf = g->buf;                                                      \
-  pre##_done(&g->c, buf);                                              \
-  return (buf);                                                                \
-}                                                                      \
-                                                                       \
-static void ghdestroy(ghash *h)                                                \
-{                                                                      \
-  gctx *g = (gctx *)h;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static ghash *ghcopy(ghash *h)                                         \
-{                                                                      \
-  gctx *g = (gctx *)h;                                                 \
-  gctx *gg = S_CREATE(gctx);                                           \
-  memcpy(gg, g, sizeof(gctx));                                         \
-  return (&gg->h);                                                     \
-}                                                                      \
-                                                                       \
-static const ghash_ops gops =                                          \
-  { &pre, ghhash, ghdone, ghdestroy, ghcopy };                         \
-const gchash pre = { #pre, PRE##_HASHSZ, ghinit, PRE##_BUFSZ };
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ghash.h b/ghash.h
deleted file mode 100644 (file)
index d20aff4..0000000
--- a/ghash.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generic hash function interface
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_GHASH_H
-#define CATACOMB_GHASH_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Generic hash function interface -----------------------------------*/
-
-typedef struct ghash {
-  const struct ghash_ops *ops;         /* Pointer to hash operations */
-} ghash;
-
-typedef struct ghash_ops {
-  const struct gchash *c;              /* Pointer to hash class */
-  void (*hash)(ghash */*h*/, const void */*p*/, size_t /*sz*/); /* Hash */
-  octet *(*done)(ghash */*h*/, void */*buf*/); /* Write result */
-  void (*destroy)(ghash */*h*/);       /* Destroy hash block */
-  ghash *(*copy)(ghash */*h*/);                /* Make a copy of the hash context */
-} ghash_ops;
-
-#define GH_INIT(ch)            (ch)->init()
-#define GH_CLASS(h)            (h)->ops->c
-#define GH_HASH(h, p, sz)      (h)->ops->hash((h), (p), (sz))
-#define GH_DONE(h, buf)                (h)->ops->done((h), (buf))
-#define GH_DESTROY(h)          (h)->ops->destroy((h))
-#define GH_COPY(h)             (h)->ops->copy((h))
-
-#define GH_HASHU_(h, n, W)  do {                                       \
-  TY_U##W n_ = (n); octet b_[SZ_##W];                                  \
-  STORE##W(b_, n_); GH_HASH((h), b_, SZ_##W);                          \
-} while (0)
-#define GH_HASHU8(h, n)         GH_HASHU_((h), (n), 8)
-#define GH_HASHU16(h, n) GH_HASHU_((h), (n), 16)
-#define GH_HASHU16_B(h, n) GH_HASHU_((h), (n), 16_B)
-#define GH_HASHU16_L(h, n) GH_HASHU_((h), (n), 16_L)
-#define GH_HASHU24(h, n) GH_HASHU_((h), (n), 24)
-#define GH_HASHU24_B(h, n) GH_HASHU_((h), (n), 24_B)
-#define GH_HASHU24_L(h, n) GH_HASHU_((h), (n), 24_L)
-#define GH_HASHU32(h, n) GH_HASHU_((h), (n), 32)
-#define GH_HASHU32_B(h, n) GH_HASHU_((h), (n), 32_B)
-#define GH_HASHU32_L(h, n) GH_HASHU_((h), (n), 32_L)
-#ifdef HAVE_UINT64
-#  define GH_HASHU64(h, n) GH_HASHU_((h), (n), 64)
-#  define GH_HASHU64_B(h, n) GH_HASHU_((h), (n), 64_B)
-#  define GH_HASHU64_L(h, n) GH_HASHU_((h), (n), 64_L)
-#endif
-
-#define GH_HASHBUF_(h, p, sz, W) do {                                  \
-  size_t sz_ = (sz); assert(sz_ <= MASK##W);                           \
-  GH_HASHU_(h, sz_, W); GH_HASH(h, (p), sz_);                          \
-} while (0)
-#define GH_HASHBUF8(h, p, sz) GH_HASHBUF_((h), (p), (sz), 8)
-#define GH_HASHBUF16(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16)
-#define GH_HASHBUF16_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16_L)
-#define GH_HASHBUF16_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16_B)
-#define GH_HASHBUF24(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24)
-#define GH_HASHBUF24_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24_L)
-#define GH_HASHBUF24_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24_B)
-#define GH_HASHBUF32(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32)
-#define GH_HASHBUF32_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32_L)
-#define GH_HASHBUF32_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32_B)
-#ifdef HAVE_UINT64
-#  define GH_HASHBUF64(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64)
-#  define GH_HASHBUF64_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64_L)
-#  define GH_HASHBUF64_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64_B)
-#endif
-
-#define GH_HASHSTR_(h, p, W) do {                                      \
-  const char *p_ = (p); GH_HASHBUF_((h), p_, strlen(p_), W);           \
-} while (0)
-#define GH_HASHSTR8(h, p) GH_HASHSTR_((h), (p), 8)
-#define GH_HASHSTR16(h, p) GH_HASHSTR_((h), (p), 16)
-#define GH_HASHSTR16_L(h, p) GH_HASHSTR_((h), (p), 16_L)
-#define GH_HASHSTR16_B(h, p) GH_HASHSTR_((h), (p), 16_B)
-#define GH_HASHSTR24(h, p) GH_HASHSTR_((h), (p), 24)
-#define GH_HASHSTR24_L(h, p) GH_HASHSTR_((h), (p), 24_L)
-#define GH_HASHSTR24_B(h, p) GH_HASHSTR_((h), (p), 24_B)
-#define GH_HASHSTR32(h, p) GH_HASHSTR_((h), (p), 32)
-#define GH_HASHSTR32_L(h, p) GH_HASHSTR_((h), (p), 32_L)
-#define GH_HASHSTR32_B(h, p) GH_HASHSTR_((h), (p), 32_B)
-#ifdef HAVE_UINT64
-#  define GH_HASHSTR64(h, p) GH_HASHSTR_((h), (p), 64)
-#  define GH_HASHSTR64_L(h, p) GH_HASHSTR_((h), (p), 64_L)
-#  define GH_HASHSTR64_B(h, p) GH_HASHSTR_((h), (p), 64_B)
-#endif
-
-#define GH_HASHSTRZ(h, p) do {                                         \
-  const char *p_ = (p); GH_HASH((h), p_, strlen(p_) + 1);              \
-} while (0)
-#define GH_HASHSTR(h, p) do {                                          \
-  const char *p_ = (p); GH_HASH((h), p_, strlen(p_));                  \
-} while (0)
-
-typedef struct gchash {
-  const char *name;                    /* Name of the hash function */
-  size_t hashsz;                       /* Size of output hash */
-  ghash *(*init)(void);                        /* Create a new hash instance */
-  size_t bufsz;                                /* Buffer size, or zero */
-} gchash;
-
-/*----- Tables ------------------------------------------------------------*/
-
-extern const gchash *const ghashtab[];
-
-/* --- @ghash_byname@ --- *
- *
- * Arguments:  @const char *p@ = pointer to name string
- *
- * Returns:    The named cipher class, or null.
- */
-
-extern const gchash *ghash_byname(const char */*p*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/gkcdsa.c b/gkcdsa.c
deleted file mode 100644 (file)
index ed2b37d..0000000
--- a/gkcdsa.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "gkcdsa.h"
-#include "group.h"
-#include "ghash.h"
-#include "mpbarrett.h"
-#include "mprand.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gkcdsa_beginhash@ --- *
- *
- * Arguments:  @const gkcdsa *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(const 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_ZEROP(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_modinv(MP_NEW, c.u, c.g->r);
-  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
deleted file mode 100644 (file)
index 9dc893e..0000000
--- a/gkcdsa.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * 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.
- */
-
-#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 ------------------------------------------------*/
-
-/* --- @gkcdsa_beginhash@ --- *
- *
- * Arguments:  @const gkcdsa *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(const 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/gmac.h b/gmac.h
deleted file mode 100644 (file)
index 096c36d..0000000
--- a/gmac.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* -*-c-*-
- *
- * $Id: gmac.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Generic MAC function interface
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_GMAC_H
-#define CATACOMB_GMAC_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Generic MAC function interface ------------------------------------*/
-
-typedef struct gmac {
-  const struct gmac_ops *ops;          /* Pointer to MAC operations */
-} gmac;
-
-typedef struct gmac_ops {
-  const struct gcmac *c;               /* Pointer to MAC class */
-  ghash *(*init)(gmac */*m*/);         /* Create keyed hash instance */
-  void (*destroy)(gmac */*m*/);                /* Destroy MAC key block */
-} gmac_ops;
-
-typedef struct gcmac {
-  const char *name;                    /* Name of the MAC function */
-  size_t hashsz;                       /* Size of output hash */
-  const octet *keysz;                  /* Key size options */
-  gmac *(*key)(const void */*k*/, size_t /*sz*/); /* Create key */
-} gcmac;
-
-#define GM_KEY(cm, k, ksz)     (cm)->key((k), (ksz))
-#define GM_CLASS(km)           (km)->ops->c
-#define GM_INIT(km)            (km)->ops->init((km))
-#define GM_DESTROY(km)         (km)->ops->destroy((km))
-
-/*----- Tables ------------------------------------------------------------*/
-
-extern const gcmac *const gmactab[];
-
-/* --- @gmac_byname@ --- *
- *
- * Arguments:  @const char *p@ = pointer to name string
- *
- * Returns:    The named cipher class, or null.
- */
-
-extern const gcmac *gmac_byname(const char */*p*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/grand.c b/grand.c
deleted file mode 100644 (file)
index 0fa4e16..0000000
--- a/grand.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* -*-c-*-
- *
- * $Id: grand.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Generic interface to random number generators
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#include "grand.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @grand_byte@ --- *
- *
- * Arguments:  @grand *r@ = pointet to generic generator
- *
- * Returns:    A uniformly-distributed pseudorandom integer in the interval
- *             %$[0, 256)$%.
- */
-
-octet grand_byte(grand *r)
-{
-  if (r->ops->byte != grand_byte)
-    return (r->ops->byte(r));
-  else if (r->ops->word != grand_word)
-    return (r->ops->word(r) & 0xff);
-  else if (r->ops->fill != grand_fill) {
-    octet o;
-    r->ops->fill(r, &o, 1);
-    return (o);
-  } else
-    return (grand_range(r, 256));
-}
-
-/* --- @grand_word@ --- *
- *
- * Arguments:  @grand *r@ = pointet to generic generator
- *
- * Returns:    A uniformly-distributed pseudorandom integer in the interval
- *             %$[0, 2^{32})$%.
- */
-
-uint32 grand_word(grand *r)
-{
-  if (r->ops->word != grand_word)
-    return (r->ops->word(r));
-  else {
-    octet b[4];
-    grand_fill(r, b, sizeof(b));
-    return (LOAD32(b));
-  }
-}
-
-/* --- @grand_range@ --- *
- *
- * Arguments:  @grand *r@ = pointet to generic generator
- *             @uint32 l@ = limit for acceptable results
- *
- * Returns:    A uniformly-distributed pseudorandom integer in the interval
- *             %$[0, l)$%.
- */
-
-uint32 grand_range(grand *r, uint32 l)
-{
-  if (r->ops->range != grand_range)
-    return (r->ops->range(r, l));
-  else {
-    uint32 m, z;
-    uint32 (*w)(grand */*r*/);
-    uint32 x;
-
-    /* --- Decide where to get data from --- *
-     *
-     * The choice of %$2^{32} - 1$% as a limit when using @grand_word@ isn't
-     * wonderful, but working with %$2^{32}$% is awkward and the loss of a
-     * few return values isn't significant.  The algorithm below still
-     * successfully returns uniformly distributed results.
-     */
-
-    if (r->ops->max) {
-      w = r->ops->raw;
-      m = r->ops->max;
-    } else {
-      w = grand_word;
-      m = 0xffffffff;
-    }
-
-    /* --- Work out maximum acceptable return value --- *
-     *
-     * This will be the highest multiple of @l@ less than @m@.
-     */
-
-    z = m - (m % l);
-
-    /* --- Generate numbers until something acceptable is found --- *
-     *
-     * This will require an expected number of attempts less than 2.
-     */
-
-    do x = w(r); while (x >= z);
-    return (x % l);
-  }
-}
-
-/* --- @grand_fill@ --- *
- *
- * Arguments:  @grand *r@ = pointet to generic generator
- *             @void *p@ = pointer to a buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    ---
- *
- * Use:                Fills a buffer with uniformly distributed pseudorandom bytes
- *             (see @grand_byte@).
- */
-
-void grand_fill(grand *r, void *p, size_t sz)
-{
-  if (r->ops->fill != grand_fill)
-    r->ops->fill(r, p, sz);
-  else {
-    octet *q = p;
-    while (sz) {
-      *q++ = r->ops->byte(r);
-      sz--;
-    }
-  }
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/grand.h b/grand.h
deleted file mode 100644 (file)
index 49ac3b4..0000000
--- a/grand.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/* -*-c-*-
- *
- * $Id: grand.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Generic interface to random number generators
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_GRAND_H
-#define CATACOMB_GRAND_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Generic random number generator interface -------------------------*/
-
-typedef struct grand {
-  const struct grand_ops *ops;
-} grand;
-
-typedef struct grand_ops {
-
-  /* --- Various important properties --- */
-
-  const char *name;                    /* Generator's name */
-  unsigned f;                          /* Various flags */
-  uint32 max;                          /* Maximum raw output */
-
-  /* --- Maintenance methods --- */
-
-  int (*misc)(grand */*r*/, unsigned /*op*/, ...); /* Miscellaneous ops */
-  void (*destroy)(grand */*r*/);       /* Destroy generator context */
-
-  /* --- Output methods --- *
-   *
-   * Only one of these operations need actually be implemented.  All the
-   * other operations may be synthesized.  Of course, performance is improved
-   * if more are provided.
-   */
-
-  uint32 (*raw)(grand */*r*/);         /* Uniform over %$[0, max)$% */
-  octet (*byte)(grand */*r*/);         /* Uniform over %$[0, 256)$% */
-  uint32 (*word)(grand */*r*/);                /* Uniform over %$[0, 2^{32})$% */
-  uint32 (*range)(grand */*r*/, uint32 /*l*/); /* Uniform over %$[0, l)$% */
-  void (*fill)(grand */*r*/, void */*p*/, size_t /*sz*/); /* Fill buffer */
-} grand_ops;
-
-#define GR_DESTROY(r)          (r)->ops->destroy((r))
-#define GR_RAW(r)              (r)->ops->raw((r))
-#define GR_WORD(r)             (r)->ops->word((r))
-#define GR_RANGE(r, l)         (r)->ops->range((r), (l))
-#define GR_FILL(r, p, sz)      (r)->ops->fill((r), (p), (sz))
-
-/* --- Flag types --- */
-
-#define GRAND_CRYPTO 1u                        /* Cryptographically strong */
-
-/* --- Operation types --- */
-
-enum {
-
-  /* --- Required operations --- */
-
-  GRAND_CHECK,                         /* @unsigned op2@ */
-
-  /* --- Standard seeding operations --- */
-
-  GRAND_SEEDINT,                       /* @int i@ */
-  GRAND_SEEDUINT32,                    /* @uint32 i@ */
-  GRAND_SEEDBLOCK,                     /* @const void *p, size_t sz@ */
-  GRAND_SEEDMP,                                /* @mp *m@ */
-  GRAND_SEEDRAND                       /* @grand *g@ */
-
-  /* --- Generator-specific operations --- */
-
-#define GRAND_SPECIFIC(ch) ((unsigned)(ch) << 8)
-};
-
-#define GRAND_BADOP assert(((void)"bad grand_misc op", 0))
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @grand_byte@ --- *
- *
- * Arguments:  @grand *r@ = pointet to generic generator
- *
- * Returns:    A uniformly-distributed pseudorandom integer in the interval
- *             %$[0, 256)$%.
- */
-
-extern octet grand_byte(grand */*r*/);
-
-/* --- @grand_word@ --- *
- *
- * Arguments:  @grand *r@ = pointet to generic generator
- *
- * Returns:    A uniformly-distributed pseudorandom integer in the interval
- *             %$[0, 2^{32})$%.
- */
-
-extern uint32 grand_word(grand */*r*/);
-
-/* --- @grand_range@ --- *
- *
- * Arguments:  @grand *r@ = pointet to generic generator
- *             @uint32 l@ = limit for acceptable results
- *
- * Returns:    A uniformly-distributed pseudorandom integer in the interval
- *             %$[0, l)$%.
- */
-
-extern uint32 grand_range(grand */*r*/, uint32 /*l*/);
-
-/* --- @grand_fill@ --- *
- *
- * Arguments:  @grand *r@ = pointet to generic generator
- *             @void *p@ = pointer to a buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    ---
- *
- * Use:                Fills a buffer with uniformly distributed pseudorandom bytes
- *             (see @grand_byte@).
- */
-
-extern void grand_fill(grand */*r*/, void */*p*/, size_t /*sz*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/group-dstr.c b/group-dstr.c
deleted file mode 100644 (file)
index f41b978..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*-c-*-
- *
- * $Id: group-dstr.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Dynamic string I/O for group elements
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "group.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @group_readdstr@ --- *
- *
- * Arguments:  @group *g@ = an abstract group
- *             @ge *d@ = destination group element
- *             @dstr *dd@ = string to read from
- *             @size_t *off@ = offset to start at (updated)
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Parses a group element from a dynamic string.
- */
-
-int group_readdstr(group *g, ge *d, dstr *dd, size_t *off)
-{
-  mptext_dstrctx md;
-
-  md.d = dd;
-  md.i = off ? *off : 0;
-  if (G_READ(g, d, &mptext_dstrops, &md))
-    return (-1);
-  if (off) *off = md.i;
-  return (0);
-}
-
-/* --- @group_writedstr@ --- *
- *
- * Arguments:  @group *g@ = an abstract group
- *             @ge *x@ = a group element
- *             @dstr *d@ = string to write to
- *             @size_t sz@ = how long the buffer is
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Writes a group element to a dstr buffer.
- */
-
-int group_writedstr(group *g, ge *x, dstr *d)
-{
-  mptext_dstrctx md;
-
-  md.d = d;
-  if (G_WRITE(g, x, &mptext_dstrops, &md))
-    return (-1);
-  DPUTZ(d);
-  return (0);
-}
-
-
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/group-exp.c b/group-exp.c
deleted file mode 100644 (file)
index a706125..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Exponentiation for abstract groups
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "group.h"
-#include "group-exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @group_stdexp@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @ge *x@ = base element
- *             @mp *n@ = exponent
- *
- * Returns:    ---
- *
- * Use:                Computes %$d = x^n$% efficiently.
- */
-
-void group_stdexp(group *gg, ge *d, ge *x, mp *n)
-{
-  ge *t = G_CREATE(gg);
-
-  G_COPY(gg, t, x);
-  MP_SHRINK(n);
-  G_COPY(gg, d, gg->i);
-  if (n->f & MP_BURN)
-    G_BURN(gg, t);
-  if (MP_ZEROP(n))
-    ;
-  else {
-    if (MP_NEGP(n))
-      G_INV(gg, t, t);
-    if (MP_LEN(n) < EXP_THRESH)
-      EXP_SIMPLE(d, t, n);
-    else
-      EXP_WINDOW(d, t, n);
-  }
-  G_DESTROY(gg, t);
-}
-
-/* --- @group_stdmexp@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @const group_expfactor *f@ = vector of factors
- *             @size_t n@ = number of factors
- *
- * Returns:    ---
- *
- * Use:                Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently.
- */
-
-#undef EXP_WINSZ
-#define EXP_WINSZ 3
-
-void group_stdmexp(group *gg, ge *d, const group_expfactor *f, size_t n)
-{
-  group_expfactor *ff = xmalloc(n * sizeof(group_expfactor));
-  size_t i;
-
-  for (i = 0; i < n; i++) {
-    ff[i].base = G_CREATE(gg);
-    MP_SHRINK(f[i].exp);
-    if (MP_NEGP(f[i].exp))
-      G_INV(gg, ff[i].base, f[i].base);
-    else
-      G_COPY(gg, ff[i].base, f[i].base);
-    if (f[i].exp->f & MP_BURN)
-      G_BURN(gg, ff[i].base);
-    ff[i].exp = f[i].exp;
-  }
-  G_COPY(gg, d, gg->i);
-  EXP_SIMUL(d, ff, n);
-  for (i = 0; i < n; i++)
-    G_DESTROY(gg, ff[i].base);
-  xfree(ff);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/group-exp.h b/group-exp.h
deleted file mode 100644 (file)
index 6f1c1c5..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*-c-*-
- *
- * $Id: group-exp.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Exponentiation operations for abstract groups
- *
- * (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.
- */
-
-#ifndef CATACOMB_GROUP_EXP_H
-#define CATACOMB_GROUP_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentation definitions -----------------------------------------*/
-
-#define EXP_TYPE ge *
-
-#define EXP_COPY(d, p) do {                                            \
-  (d) = G_CREATE(gg);                                                  \
-  G_COPY(gg, (d), (p));                                                        \
-} while (0)
-#define EXP_DROP(x) G_DESTROY(gg, (x))
-
-#define EXP_MUL(a, x) G_MUL(gg, (a), (a), (x))
-#define EXP_SQR(a) G_SQR(gg, (a), (a));
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) do {                                       \
-  (d) = G_CREATE(gg);                                                  \
-  G_MUL(gg, (d), (x), (y));                                            \
-} while (0)
-#define EXP_SETSQR(d, x) do {                                          \
-  (d) = G_CREATE(gg);                                                  \
-  G_SQR(gg, (d), (x));                                                 \
-} while (0)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/group-file.c b/group-file.c
deleted file mode 100644 (file)
index 212e26e..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*-c-*-
- *
- * $Id: group-file.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * File I/O for group elements
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "group.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @group_readfile@ --- *
- *
- * Arguments:  @group *g@ = an abstract group
- *             @ge *d@ = destination group element
- *             @FILE *fp@ = the file to read from
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Parses a group element from a file.
- */
-
-int group_readfile(group *g, ge *d, FILE *fp)
-  { return (G_READ(g, d, &mptext_fileops, fp)); }
-
-/* --- @group_writefile@ --- *
- *
- * Arguments:  @group *g@ = an abstract group
- *             @ge *x@ = a group element
- *             @FILE *fp@ = the file to write on
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Writes a group element to a file.
- */
-
-int group_writefile(group *g, ge *x, FILE *fp)
-  { return (G_WRITE(g, x, &mptext_fileops, fp)); }
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/group-guts.h b/group-guts.h
deleted file mode 100644 (file)
index 42ab20d..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Internal structures for built-in groups
- *
- * (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.
- */
-
-#ifndef CATACOMB_GROUP_GUTS_H
-#define CATACOMB_GROUP_GUTS_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_EC_H
-#  include "ec.h"
-#endif
-
-#ifndef CATACOMB_MPMONT_H
-#  include "mpmont.h"
-#endif
-
-#ifndef CATACOMB_GFREDUCE_H
-#  include "gfreduce.h"
-#endif
-
-#ifndef CATACOMB_GROUP_H
-#  include "group.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct gctx_prime {
-  group g;
-  mp *gen;
-  mpmont mm;
-} gctx_prime;
-
-typedef struct gctx_ec {
-  group g;
-  ec id, gen;
-  ec_info ei;
-} gctx_ec;
-
-typedef struct gctx_bin {
-  group g;
-  mp *gen;
-  mp *one;
-  gfreduce r;
-} gctx_bin;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/group-parse.c b/group-parse.c
deleted file mode 100644 (file)
index 7711952..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* -*-c-*-
- *
- * $Id: group-parse.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Parse group description strings
- *
- * (c) 2004 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of Trivial IP Encryption (TrIPE).
- *
- * TrIPE is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * TrIPE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with TrIPE; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "group.h"
-#include "dh.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @group_parse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = quick-and-dirty parser
- *
- * Returns:    Group pointer, or null for failure.
- *
- * Use:                Parses a group description and returns the group.  This has
- *             the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and
- *             SPEC is the appropriate kind of group specification of the
- *             given type.
- */
-
-group *group_parse(qd_parse *qd)
-{
-  group *g = 0;
-
-  switch (qd_enum(qd, "prime,ec")) {
-    case 0: {
-      dh_param dp;
-      qd_delim(qd, '{');
-      if (dh_parse(qd, &dp)) goto ouch;
-      qd_delim(qd, '}');
-      g = group_prime(&dp);
-      dh_paramfree(&dp);
-    } break;
-    case 1: {
-      ec_info ei;
-      qd_delim(qd, '{');
-      if (ec_infoparse(qd, &ei)) goto ouch;
-      qd_delim(qd, '}');
-      g = group_ec(&ei);
-    } break;
-  }
-  if (!g) qd->e = "bad group parameters";
-ouch:
-  return (g);
-}
-
-/* --- @group_fromstring@ --- *
- *
- * Arguments:  @const char *p@ = pointer to string to read
- *             @group **gg@ = where to put the group pointer
- *
- * Returns:    Null if OK, or an error string.
- *
- * Use:                Parses a group spec from a string, and returns the group.
- */
-
-const char *group_fromstring(const char *p, group **gg)
-{
-  group *g;
-  qd_parse qd;
-
-  qd.p = p;
-  qd.e = 0;
-  if ((g = group_parse(&qd)) == 0) return (qd.e);
-  if (!qd_eofp(&qd)) { G_DESTROYGROUP(g); return ("junk at end of string"); }
-  *gg = g;
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/group-stdops.c b/group-stdops.c
deleted file mode 100644 (file)
index 77f48f7..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Standard group operations
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "group.h"
-#include "pgen.h"
-
-/*----- Handy functions ---------------------------------------------------*/
-
-/* --- @group_check@ --- *
- *
- * Arguments:  @group *g@ = an abstract group
- *             @ge *x@ = a group element
- *
- * Returns:    Zero on success, nonzero for failure.
- *
- * Use:                Checks that @x@ is a valid group element.  This may take a
- *             while, since it checks that %$x \ne 1$% and %$x^r = 1$%.
- */
-
-int group_check(group *g, ge *x)
-{
-  ge *d = G_CREATE(g);
-  int rc;
-
-  G_EXP(g, d, x, g->r);
-  rc = (G_IDENTP(g, d) && !G_IDENTP(g, x));
-  G_DESTROY(g, d);
-  if (!rc) return (-1);
-  return (0);
-}
-
-/* --- @group_samep@ --- *
- *
- * Arguments:  @group *g, *h@ = two abstract groups
- *
- * Returns:    Nonzero if the groups are in fact identical (not just
- *             isomorphic).
- *
- * Use:                Checks to see whether two groups are actually the same.  This
- *             function does the full check: the group operatrion @samep@
- *             just does the group-specific details.
- */
-
-int group_samep(group *g, group *h)
-{
-  return (g == h || (g->ops == h->ops &&
-                    MP_EQ(g->r, h->r) && MP_EQ(g->h, h->h) &&
-                    G_EQ(g, g->i, h->i) && G_EQ(g, g->g, h->g) &&
-                    G_SAMEP(g, h)));
-}
-
-/*----- Standard implementations ------------------------------------------*/
-
-/* --- @group_stdidentp@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *x@ = group element
- *
- * Returns:    Nonzero if %$x$% is the group identity.
- */
-
-int group_stdidentp(group *g, ge *x) { return (G_EQ(g, x, g->i)); }
-
-/* --- @group_stdsqr@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @ge *x@ = group element
- *
- * Returns:    ---
- *
- * Use:                Computes %$d = x^2$% as %$d = x x$%.
- */
-
-void group_stdsqr(group *g, ge *d, ge *x) { G_MUL(g, d, x, x); }
-
-/* --- @group_stddiv@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @ge *x@ = dividend
- *             @ge *y@ = divisor
- *
- * Returns:    ---
- *
- * Use:                Computes %$d = x/y$% as %$d = x y^{-1}$%.
- */
-
-void group_stddiv(group *g, ge *d, ge *x, ge *y)
-  { G_INV(g, d, y); G_MUL(g, d, x, d); }
-
-/* --- @group_stdtoec@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ec *d@ = destination point
- *             @ge *x@ = group element
- *
- * Returns:    @-1@, indicating failure.
- *
- * Use:                Fails to convert a group element to an elliptic curve point.
- */
-
-int group_stdtoec(group *g, ec *d, ge *x) { return (-1); }
-
-/* --- @group_stdfromec@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @const ec *p@ = elliptic curve point
- *
- * Returns:    Zero for success, @-1@ on failure.
- *
- * Use:                Converts %$p$% to a group element by converting its %$x$%-
- *             coordinate.
- */
-
-int group_stdfromec(group *g, ge *d, const ec *p)
-  { if (EC_ATINF(p)) return (-1); return (G_FROMINT(g, d, p->x)); }
-
-/* --- @group_stdcheck@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @grand *gr@ = random number source.
- *
- * Returns:    Null on success, or a pointer to an error message.
- */
-
-const char *group_stdcheck(group *g, grand *gr)
-{
-  ge *t;
-  int rc;
-
-  if (!pgen_primep(g->r, gr)) return ("group order not prime");
-  t = G_CREATE(g); G_EXP(g, t, g->g, g->r);
-  rc = G_IDENTP(g, t); G_DESTROY(g, t);
-  if (!rc) return ("generator not in the group");
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/group-string.c b/group-string.c
deleted file mode 100644 (file)
index 7753d97..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*-c-*-
- *
- * $Id: group-string.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * String I/O for group elements
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "group.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @group_readstring@ --- *
- *
- * Arguments:  @group *g@ = an abstract group
- *             @ge *d@ = destination group element
- *             @const char *p@ = where the string is
- *             @char **end@ = where to put the end pointer
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Parses a group element from a string.
- */
-
-int group_readstring(group *g, ge *d, const char *p, char **end)
-{
-  mptext_stringctx ms;
-
-  ms.buf = (/*unconst*/ char *)p;
-  ms.lim = (/*unconst*/ char *)p + strlen(p);
-  if (G_READ(g, d, &mptext_stringops, &ms))
-    return (-1);
-  if (end) *end = ms.buf;
-  return (0);
-}
-
-/* --- @group_writestring@ --- *
- *
- * Arguments:  @group *g@ = an abstract group
- *             @ge *x@ = a group element
- *             @char *p@ = where the string should go
- *             @size_t sz@ = how long the buffer is
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Writes a group element to a string buffer.
- */
-
-int group_writestring(group *g, ge *x, char *p, size_t sz)
-{
-  mptext_stringctx ms;
-
-  ms.buf = p;
-  ms.lim = p + sz - 1;
-  if (G_WRITE(g, x, &mptext_stringops, &ms))
-    return (-1);
-  *ms.buf = 0;
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/group-test.c b/group-test.c
deleted file mode 100644 (file)
index 5608ec0..0000000
+++ /dev/null
@@ -1,563 +0,0 @@
-/* -*-c-*-
- *
- * $Id: group-test.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Testing group operations
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-
-#include <mLib/testrig.h>
-
-#include "group.h"
-#include "fibrand.h"
-#include "ec.h"
-#include "ec-test.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-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 show(group *g, const char *p, ge *x) {
-  fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr);
-  putc('\n', stderr);
-}
-
-static void showec(const char *p, ec *q) {
-  fprintf(stderr, "*** %s = ", p);
-  if (EC_ATINF(q)) fprintf(stderr, "inf\n");
-  else {
-    mp_writefile(q->x, stderr, 16); fputs(", ", stderr);
-    mp_writefile(q->x, stderr, 16); putchar('\n');
-  }
-}
-
-static void showmp(const char *p, mp *x, int r) {
-  fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r);
-  putc('\n', stderr);
-}
-
-static int check(const char *op, const char *gd, group *g,
-                ge *r, ge *c, ...) {
-  va_list ap;
-
-  if (G_EQ(g, r, c)) return (1);
-  fprintf(stderr, "\n*** %s failed\n", op);
-  fprintf(stderr, "*** group: %s\n", gd);
-  va_start(ap, c);
-  for (;;) {
-    const char *p; ge *x;
-    p = va_arg(ap, const char *); if (!p) break;
-    x = va_arg(ap, ge *); show(g, p, x);
-  }
-  show(g, "expected", r);
-  show(g, "computed", c);
-  return (0);
-}
-
-/*----- Actual tests ------------------------------------------------------*/
-
-static int vcheck(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  grand *gr = fibrand_create(0);
-  const char *e = G_CHECK(g, gr);
-  int ok = 1;
-  gr->ops->destroy(gr);
-  if (!e) e = "ok";
-  G_DESTROYGROUP(g);
-  if (strcmp(e, v[1].buf)) {
-    ok = 0;
-    fprintf(stderr, "*** check failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    fprintf(stderr, "*** expected: %s\n", v[1].buf);
-    fprintf(stderr, "*** returned: %s\n", e);
-  }
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vcheckelt(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  int ir = *(int *)v[2].buf;
-  int ic = group_check(g, x);
-  int ok = 1;
-  if (ir != ic) {
-    ok = 0;
-    fprintf(stderr, "*** check failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    show(g, "x", x);
-    fprintf(stderr, "*** expected %s\n", ir ? "failure" : "success");
-  }
-  G_DESTROY(g, x);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vmul(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  ge *y = getge(g, v[2].buf);
-  ge *r = getge(g, v[3].buf);
-  ge *c = G_CREATE(g);
-  int ok = 1;
-  G_MUL(g, c, x, y);
-  ok &= check("mul", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
-  G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vsqr(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  ge *r = getge(g, v[2].buf);
-  ge *c = G_CREATE(g);
-  int ok = 1;
-  G_SQR(g, c, x);
-  ok &= check("sqr", v[0].buf, g, r, c, "x", x, (char *)0);
-  G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vinv(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  ge *r = getge(g, v[2].buf);
-  ge *c = G_CREATE(g);
-  int ok = 1;
-  G_INV(g, c, x);
-  ok &= check("inv", v[0].buf, g, r, c, "x", x, (char *)0);
-  G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vdiv(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  ge *y = getge(g, v[2].buf);
-  ge *r = getge(g, v[3].buf);
-  ge *c = G_CREATE(g);
-  int ok = 1;
-  G_DIV(g, c, x, y);
-  ok &= check("div", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
-  group_stddiv(g, c, x, y);
-  ok &= check("stddiv", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
-  G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vexp(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  mp *n = *(mp **)v[2].buf;
-  ge *r = getge(g, v[3].buf);
-  ge *c = G_CREATE(g);
-  int ok = 1;
-  G_EXP(g, c, x, n);
-  if (!G_EQ(g, r, c)) {
-    ok = 0;
-    fprintf(stderr, "\n*** exp failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    show(g, "x", x); showmp("n", n, 10);
-    show(g, "expected", r); show(g, "computed", c);
-  }
-  group_stdexp(g, c, x, n);
-  if (!G_EQ(g, r, c)) {
-    ok = 0;
-    fprintf(stderr, "\n*** stdexp failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    show(g, "x", x); showmp("n", n, 10);
-    show(g, "expected", r); show(g, "computed", c);
-  }
-  G_DESTROY(g, x); MP_DROP(n); G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vmexp(size_t n, dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *c, *r;
-  group_expfactor *f = xmalloc(n * sizeof(group_expfactor));
-  int ok = 1;
-  size_t i;
-  for (i = 0; i < n; i++) {
-    f[i].base = getge(g, v[1 + 2 * i].buf);
-    f[i].exp = *(mp **)v[2 + 2 * i].buf;
-  }
-  r = getge(g, v[1 + 2 * n].buf);
-  c = G_CREATE(g);
-  G_MEXP(g, c, f, n);
-  if (!G_EQ(g, r, c)) {
-    ok = 0;
-    fprintf(stderr, "\n*** mexp failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    for (i = 0; i < n; i++) {
-      show(g, "base", f[i].base);
-      showmp("exp", f[i].exp, 10);
-    }
-    show(g, "expected", r); show(g, "computed", c);
-  }
-  group_stdmexp(g, c, f, n);
-  if (!G_EQ(g, r, c)) {
-    ok = 0;
-    fprintf(stderr, "\n*** stdmexp failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    for (i = 0; i < n; i++) {
-      show(g, "base", f[i].base);
-      showmp("exp", f[i].exp, 10);
-    }
-    show(g, "expected", r); show(g, "computed", c);
-  }
-  for (i = 0; i < n; i++) { G_DESTROY(g, f[i].base); MP_DROP(f[i].exp); }
-  G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vmexp1(dstr *v) { return vmexp(1, v); }
-static int vmexp2(dstr *v) { return vmexp(2, v); }
-static int vmexp3(dstr *v) { return vmexp(3, v); }
-static int vmexp4(dstr *v) { return vmexp(4, v); }
-
-static int vtoint(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  int ir = *(int *)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *c;
-  int ic;
-  int ok = 1;
-  c = G_TOINT(g, MP_NEW, x);
-  ic = c ? 0 : -1;
-  if (ir != ic || (!ic && !MP_EQ(r, c))) {
-    ok = 0;
-    fprintf(stderr, "\n*** toint failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    if (ir) fprintf(stderr, "*** expected failure\n");
-    else { show(g, "x", x); showmp("expected", r, 16);
-    showmp("computed", c, 16); }
-  }
-  G_DESTROY(g, x); mp_drop(r); mp_drop(c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vfromint(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  mp *x = *(mp **)v[1].buf;
-  int ir = *(int *)v[2].buf;
-  ge *r = getge(g, v[3].buf);
-  int ic;
-  ge *c = G_CREATE(g);
-  int ok = 1;
-  ic = G_FROMINT(g, c, x);
-  if (ir != ic || (!ic && !G_EQ(g, r, c))) {
-    ok = 0;
-    fprintf(stderr, "\n*** fromint failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    showmp("x", x, 16); if (ir) fprintf(stderr, "*** should have failed\n");
-    else { show(g, "expected", r); show(g, "computed", c); }
-  }
-  MP_DROP(x); G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vtoec(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  int ir = *(int *)v[2].buf;
-  ec *r = (ec *)v[3].buf;
-  int ic;
-  ec c = EC_INIT;
-  int ok = 1;
-  ic = G_TOEC(g, &c, x);
-  if (ir != ic || (!ic && !EC_EQ(r, &c))) {
-    ok = 0;
-    fprintf(stderr, "\n*** toec failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    show(g, "x", x);
-    if (ir) fprintf(stderr, "*** should have failed\n");
-    else { showec("expected", r); showec("computed", &c); }
-  }
-  G_DESTROY(g, x); EC_DESTROY(&c); EC_DESTROY(r);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vfromec(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ec *p = (ec *)v[1].buf;
-  int ir = *(int *)v[2].buf;
-  ge *r = getge(g, v[3].buf);
-  int ic;
-  ge *c = G_CREATE(g);
-  int ok = 1;
-  ic = G_FROMEC(g, c, p);
-  if (ir != ic || (!ic && !G_EQ(g, r, c))) {
-    ok = 0;
-    fprintf(stderr, "\n*** fromec failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    showec("p", p); if (ir) fprintf(stderr, "*** should have failed\n");
-    else { show(g, "expected", r); show(g, "computed", c); }
-  }
-  EC_DESTROY(p); G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vtobuf(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  int ir = *(int *)v[2].buf;
-  dstr c = DSTR_INIT;
-  int ic;
-  buf b;
-  int ok = 1;
-
-  dstr_ensure(&c, v[3].len);
-  buf_init(&b, c.buf, v[3].len);
-  ic = G_TOBUF(g, &b, x);
-  c.len = BLEN(&b);
-  if (ic != ir || (!ic && (c.len != v[3].len ||
-                          memcmp(c.buf, v[3].buf, c.len)))) {
-    ok = 0;
-    fprintf(stderr, "*** tobuf failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    show(g, "x", x);
-    if (ir) fprintf(stderr, "*** expected failure\n");
-    else {
-      fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
-      fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
-      fputc('\n', stderr);
-    }
-  }
-  G_DESTROY(g, x); dstr_destroy(&c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vfrombuf(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  int ir = *(int *)v[2].buf;
-  ge *r = getge(g, v[3].buf);
-  int ic;
-  ge *c = G_CREATE(g);
-  buf b;
-  int ok = 1;
-
-  buf_init(&b, v[1].buf, v[1].len);
-  ic = G_FROMBUF(g, &b, c);
-  if ((ic < 0) != (ir < 0) || (ir >= 0 &&
-                              (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
-    ok = 0;
-    fprintf(stderr, "*** frombuf failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
-    fputc('\n', stderr);
-    if (ir < 0) fprintf(stderr, "*** expected failure\n");
-    else {
-      show(g, "expected", r); show(g, "computed", c);
-      fprintf(stderr, "*** expected used = %d\n", ir);
-      fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
-    }
-  }
-  G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vtoraw(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  ge *x = getge(g, v[1].buf);
-  int ir = *(int *)v[2].buf;
-  dstr c = DSTR_INIT;
-  int ic;
-  buf b;
-  int ok = 1;
-
-  dstr_ensure(&c, v[3].len);
-  buf_init(&b, c.buf, v[3].len);
-  ic = G_TORAW(g, &b, x);
-  c.len = BLEN(&b);
-  if (ic != ir || (!ic && (c.len != v[3].len ||
-                          memcmp(c.buf, v[3].buf, c.len)))) {
-    ok = 0;
-    fprintf(stderr, "*** toraw failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    show(g, "x", x);
-    if (ir) fprintf(stderr, "*** expected failure\n");
-    else {
-      fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
-      fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
-      fputc('\n', stderr);
-    }
-  }
-  G_DESTROY(g, x); dstr_destroy(&c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vfromraw(dstr *v)
-{
-  group *g = getgroup(v[0].buf);
-  int ir = *(int *)v[2].buf;
-  ge *r = getge(g, v[3].buf);
-  int ic;
-  ge *c = G_CREATE(g);
-  buf b;
-  int ok = 1;
-
-  buf_init(&b, v[1].buf, v[1].len);
-  ic = G_FROMRAW(g, &b, c);
-  if ((ic < 0) != (ir < 0) || (ir >= 0 &&
-                              (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
-    ok = 0;
-    fprintf(stderr, "*** fromraw failed\n");
-    fprintf(stderr, "*** group: %s\n", v[0].buf);
-    fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
-    fputc('\n', stderr);
-    if (ir < 0) fprintf(stderr, "*** expected failure\n");
-    else {
-      show(g, "expected", r); show(g, "computed", c);
-      fprintf(stderr, "*** expected used = %d\n", ir);
-      fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
-    }
-  }
-  G_DESTROY(g, r); G_DESTROY(g, c);
-  G_DESTROYGROUP(g);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static const test_chunk tests[] = {
-  { "check",   vcheck,         { &type_string, &type_string } },
-  { "checkelt",        vcheckelt,      { &type_string, &type_string, &type_int } },
-  { "mul",     vmul,           { &type_string, &type_string,
-                                 &type_string, &type_string } },
-  { "sqr",     vsqr,           { &type_string, &type_string,
-                                 &type_string } },
-  { "inv",     vinv,           { &type_string, &type_string,
-                                 &type_string } },
-  { "div",     vdiv,           { &type_string, &type_string,
-                                 &type_string, &type_string } },
-  { "exp",     vexp,           { &type_string, &type_string,
-                                 &type_mp, &type_string } },
-  { "mexp-1",  vmexp1,         { &type_string,
-                                 &type_string, &type_mp,
-                                 &type_string } },
-  { "mexp-2",  vmexp2,         { &type_string,
-                                 &type_string, &type_mp,
-                                 &type_string, &type_mp,
-                                 &type_string } },
-  { "mexp-3",  vmexp3,         { &type_string,
-                                 &type_string, &type_mp,
-                                 &type_string, &type_mp,
-                                 &type_string, &type_mp,
-                                 &type_string } },
-  { "mexp-4",  vmexp4,         { &type_string,
-                                 &type_string, &type_mp,
-                                 &type_string, &type_mp,
-                                 &type_string, &type_mp,
-                                 &type_string, &type_mp,
-                                 &type_string } },
-  { "toint",   vtoint,         { &type_string, &type_string,
-                                 &type_int, &type_mp } },
-  { "fromint", vfromint,       { &type_string, &type_mp,
-                                 &type_int, &type_string } },
-  { "toec",    vtoec,          { &type_string, &type_string,
-                                 &type_int, &type_ec } },
-  { "fromec",  vfromec,        { &type_string, &type_ec,
-                                 &type_int, &type_string } },
-  { "tobuf",   vtobuf,         { &type_string, &type_string,
-                                 &type_int, &type_hex } },
-  { "frombuf", vfrombuf,       { &type_string, &type_hex,
-                                 &type_int, &type_string } },
-  { "toraw",   vtoraw,         { &type_string, &type_string,
-                                 &type_int, &type_hex } },
-  { "fromraw", vfromraw,       { &type_string, &type_hex,
-                                 &type_int, &type_string } },
-  { 0 }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/group");
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/group.h b/group.h
deleted file mode 100644 (file)
index a144706..0000000
--- a/group.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * General cyclic group abstraction
- *
- * (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.
- */
-
-#ifndef CATACOMB_GROUP_H
-#define CATACOMB_GROUP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#ifndef CATACOMB_BUF_H
-#  include "buf.h"
-#endif
-
-#ifndef CATACOMB_DH_H
-#  include "ec.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_QDPARSE_H
-#  include "qdparse.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-#ifndef ge
-  typedef struct ge ge;                        /* Group element (abstract type) */
-#endif
-
-typedef struct group_ {
-  const struct group_ops *ops;         /* Operations table */
-  size_t nbits;                                /* Size of an element in bits */
-  size_t noctets;                      /* Size of raw element in octets */
-  ge *i;                               /* Identity element */
-  ge *g;                               /* Generator element */
-  mp *r;                               /* Order of the generator */
-  mp *h;                               /* Cofactor */
-} group;
-
-typedef struct group_expfactor {
-  ge *base;                            /* The base */
-  mp *exp;                             /* The exponent */
-} group_expfactor;
-
-typedef struct group_ops {
-
-  /* --- General information --- */
-
-  unsigned ty;                         /* Type of this group */
-  const char *name;                    /* Textual name string */
-
-  /* --- Memory management --- */
-
-  void (*destroygroup)(group */*g*/);
-  ge *(*create)(group */*g*/);
-  void (*copy)(group */*g*/, ge */*d*/, ge */*x*/);
-  void (*burn)(group */*g*/, ge */*x*/);
-  void (*destroy)(group */*g*/, ge */*e*/);
-
-  /* --- Comparisons --- */
-
-  int (*samep)(group */*g*/, group */*h*/);
-  int (*eq)(group */*g*/, ge */*x*/, ge */*y*/);
-  int (*identp)(group */*g*/, ge */*x*/);
-
-  /* --- Other stuff --- */
-
-  const char *(*check)(group */*g*/, grand */*gr*/);
-
-  /* --- Arithmetic --- */
-
-  void (*mul)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
-  void (*sqr)(group */*g*/, ge */*d*/, ge */*x*/);
-  void (*inv)(group */*g*/, ge */*d*/, ge */*x*/);
-  void (*div)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
-  void (*exp)(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/);
-  void (*mexp)(group */*g*/, ge */*d*/,
-              const group_expfactor */*f*/, size_t /*n*/);
-
-  /* --- Debugging --- */
-
-  int (*read)(group */*g*/, ge */*d*/,
-             const mptext_ops */*ops*/, void */*p*/);
-  int (*write)(group */*g*/, ge */*x*/,
-              const mptext_ops */*ops*/, void */*p*/);
-
-  /* --- Conversions --- */
-
-  mp *(*toint)(group */*g*/, mp */*d*/, ge */*x*/);
-  int (*fromint)(group */*g*/, ge */*d*/, mp */*x*/);
-  int (*toec)(group */*g*/, ec */*d*/, ge */*x*/);
-  int (*fromec)(group */*g*/, ge */*d*/, const ec */*p*/);
-  int (*tobuf)(group */*h*/, buf */*b*/, ge */*x*/);
-  int (*frombuf)(group */*h*/, buf */*b*/, ge */*d*/);
-  int (*toraw)(group */*h*/, buf */*b*/, ge */*x*/);
-  int (*fromraw)(group */*h*/, buf */*b*/, ge */*d*/);
-
-} group_ops;
-
-enum {
-  GTY_PRIME,                           /* Prime field subgroup */
-  GTY_BINARY,                          /* Binary feld subgroup */
-  GTY_EC                               /* Elliptic curve group */
-};
-
-#define G_NAME(g)              (g)->ops->name
-#define G_TYPE(g)              (g)->ops->ty
-
-#define G_DESTROYGROUP(g)      (g)->ops->destroygroup((g))
-#define G_CREATE(g)            (g)->ops->create((g))
-#define G_COPY(g, d, x)                (g)->ops->copy((g), (d), (x))
-#define G_BURN(g, x)           (g)->ops->burn((g), (x))
-#define G_DESTROY(g, x)                (g)->ops->destroy((g), (x))
-
-#define G_SAMEP(g, h)          (g)->ops->samep((g), (h))
-#define G_EQ(g, x, y)          (g)->ops->eq((g), (x), (y))
-#define G_IDENTP(g, x)         (g)->ops->identp((g), (x))
-
-#define G_CHECK(g, gr)         (g)->ops->check((g), (gr))
-
-#define G_MUL(g, d, x, y)      (g)->ops->mul((g), (d), (x), (y))
-#define G_SQR(g, d, x)         (g)->ops->sqr((g), (d), (x))
-#define G_INV(g, d, x)         (g)->ops->inv((g), (d), (x))
-#define G_DIV(g, d, x, y)      (g)->ops->div((g), (d), (x), (y))
-#define G_EXP(g, d, x, n)      (g)->ops->exp((g), (d), (x), (n))
-#define G_MEXP(g, d, f, n)     (g)->ops->mexp((g), (d), (f), (n))
-
-#define G_READ(g, d, o, p)     (g)->ops->read((g), (d), (o), (p))
-#define G_WRITE(g, x, o, p)    (g)->ops->write((g), (x), (o), (p))
-
-#define G_TOINT(g, d, x)       (g)->ops->toint((g), (d), (x))
-#define G_FROMINT(g, d, x)     (g)->ops->fromint((g), (d), (x))
-#define G_TOEC(g, d, x)                (g)->ops->toec((g), (d), (x))
-#define G_FROMEC(g, d, p)      (g)->ops->fromec((g), (d), (p))
-#define G_TOBUF(g, b, x)       (g)->ops->tobuf((g), (b), (x))
-#define G_FROMBUF(g, b, d)     (g)->ops->frombuf((g), (b), (d))
-#define G_TORAW(g, b, x)       (g)->ops->toraw((g), (b), (x))
-#define G_FROMRAW(g, b, d)     (g)->ops->fromraw((g), (b), (d))
-
-/*----- Handy functions ---------------------------------------------------*/
-
-/* --- @group_check@ --- *
- *
- * Arguments:  @group *g@ = an abstract group
- *             @ge *x@ = a group element
- *
- * Returns:    Zero on success, nonzero for failure.
- *
- * Use:                Checks that @x@ is a valid group element.  This may take a
- *             while, since it checks that %$x^h \ne 1$%.
- */
-
-extern int group_check(group */*g*/, ge */*x*/);
-
-/* --- @group_samep@ --- *
- *
- * Arguments:  @group *g, *h@ = two abstract groups
- *
- * Returns:    Nonzero if the groups are in fact identical (not just
- *             isomorphic).
- *
- * Use:                Checks to see whether two groups are actually the same.  This
- *             function does the full check: the group operatrion @samep@
- *             just does the group-specific details.
- */
-
-extern int group_samep(group */*g*/, group */*h*/);
-
-/*----- Textual I/O on group elements -------------------------------------*/
-
-extern int group_readstring(group */*g*/, ge */*d*/,
-                           const char */*p*/, char **/*end*/);
-extern int group_writestring(group */*g*/, ge */*d*/,
-                            char */*p*/, size_t /*sz*/);
-
-extern int group_readfile(group */*g*/, ge */*d*/, FILE */*fp*/);
-extern int group_writefile(group */*g*/, ge */*x*/, FILE */*fp*/);
-
-extern int group_readdstr(group */*g*/, ge */*d*/,
-                         dstr */*dd*/, size_t */*off*/);
-extern int group_writedstr(group */*g*/, ge */*x*/, dstr */*d*/);
-
-/*----- Standard implementations ------------------------------------------*/
-
-/* --- @group_stdidentp@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *x@ = group element
- *
- * Returns:    Nonzero if %$x$% is the group identity.
- */
-
-extern int group_stdidentp(group */*g*/, ge */*x*/);
-
-/* --- @group_stdcheck@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @grand *gr@ = random number source.
- *
- * Returns:    Null on success, or a pointer to an error message.
- */
-
-extern const char *group_stdcheck(group */*g*/, grand */*gr*/);
-
-/* --- @group_stdsqr@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @ge *x@ = group element
- *
- * Returns:    ---
- *
- * Use:                Computes %$d = x^2$% as %$d = x x$%.
- */
-
-extern void group_stdsqr(group */*g*/, ge */*d*/, ge */*x*/);
-
-/* --- @group_stddiv@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @ge *x@ = dividend
- *             @ge *y@ = divisor
- *
- * Returns:    ---
- *
- * Use:                Computes %$d = x/y$% as %$d = x y^{-1}$%.
- */
-
-extern void group_stddiv(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
-
-/* --- @group_stdexp@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @ge *x@ = base element
- *             @mp *n@ = exponent
- *
- * Returns:    ---
- *
- * Use:                Computes %$d = x^n$% efficiently.
- */
-
-extern void group_stdexp(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/);
-
-/* --- @group_stdmexp@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @const group_expfactor *f@ = vector of factors
- *             @size_t n@ = number of factors
- *
- * Returns:    ---
- *
- * Use:                Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently.
- */
-
-extern void group_stdmexp(group */*g*/, ge */*d*/,
-                         const group_expfactor */*f*/, size_t /*n*/);
-
-/* --- @group_stdtoec@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ec *d@ = destination point
- *             @ge *x@ = group element
- *
- * Returns:    @-1@, indicating failure.
- *
- * Use:                Fails to convert a group element to an elliptic curve point.
- */
-
-extern int group_stdtoec(group */*g*/, ec */*d*/, ge */*x*/);
-
-/* --- @group_stdfromec@ --- *
- *
- * Arguments:  @group *g@ = abstract group
- *             @ge *d@ = destination pointer
- *             @const ec *p@ = elliptic curve point
- *
- * Returns:    Zero for success, @-1@ on failure.
- *
- * Use:                Converts %$p$% to a group element by converting its %$x$%-
- *             coordinate.
- */
-
-extern int group_stdfromec(group */*g*/, ge */*d*/, const ec */*p*/);
-
-/*----- Prime field subgroups ---------------------------------------------*/
-
-typedef struct gprime_param {
-  mp *p, *q;                           /* Prime numbers %$p$% and %$q$% */
-  mp *g;                               /* Generates order-%$q$% subgroup */
-} gprime_param;
-
-/* --- @group_prime@ --- *
- *
- * Arguments:  @const gprime_param *gp@ = group parameters
- *
- * Returns:    A pointer to the group, or null.
- *
- * Use:                Constructs an abstract group interface for a subgroup of a
- *             prime field.  Group elements are @mp *@ pointers.
- */
-
-group *group_prime(const gprime_param */*gp*/);
-
-/*----- Binary field subgroups --------------------------------------------*/
-
-typedef gprime_param gbin_param;
-
-/* --- @group_binary@ --- *
- *
- * Arguments:  @const gbin_param *gb@ = group parameters
- *
- * Returns:    A pointer to the group, or null.
- *
- * Use:                Constructs an abstract group interface for a subgroup of a
- *             prime field.  Group elements are @mp *@ pointers.
- */
-
-group *group_binary(const gbin_param */*gp*/);
-
-/*----- Elliptic curve groups ---------------------------------------------*/
-
-/* --- @group_ec@ --- *
- *
- * Arguments:  @const ec_info *ei@ = elliptic curve parameters
- *
- * Returns:    A pointer to the group, or null.
- *
- * Use:                Constructs an abstract group interface for an elliptic curve
- *             group.  Group elements are @ec@ structures.  The contents of
- *             the @ec_info@ structure becomes the property of the @group@
- *             object; you can (and should) free the structure itself, but
- *             calling @ec_freeinfo@ on it is not allowed.
- */
-
-group *group_ec(const ec_info */*ei*/);
-
-/*----- General group initialization --------------------------------------*/
-
-/* --- @group_parse@ --- *
- *
- * Arguments:  @qd_parse *qd@ = quick-and-dirty parser
- *
- * Returns:    Group pointer, or null for failure.
- *
- * Use:                Parses a group description and returns the group.  This has
- *             the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and
- *             SPEC is the appropriate kind of group specification of the
- *             given type.
- */
-
-extern group *group_parse(qd_parse */*qd*/);
-
-/* --- @group_fromstring@ --- *
- *
- * Arguments:  @const char *p@ = pointer to string to read
- *             @group **gg@ = where to put the group pointer
- *
- * Returns:    Null if OK, or an error string.
- *
- * Use:                Parses a group spec from a string, and returns the group.
- */
-
-extern const char *group_fromstring(const char */*p*/, group **/*gg*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/has160.c b/has160.c
deleted file mode 100644 (file)
index 76c63aa..0000000
--- a/has160.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* -*-c-*-
- *
- * $Id: has160.c,v 1.2 2004/04/08 01:36:15 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.
- */
-
-/*----- 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
deleted file mode 100644 (file)
index 699260a..0000000
--- a/has160.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*-c-*-
- *
- * $Id: has160.h,v 1.2 2004/04/08 01:36:15 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.
- */
-
-/*----- 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
diff --git a/hash.h b/hash.h
deleted file mode 100644 (file)
index c2c10d0..0000000
--- a/hash.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generic handling for message digest functions
- *
- * (c) 1998 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.
- */
-
-#ifndef CATACOMB_HASH_H
-#define CATACOMB_HASH_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include <mLib/bits.h>
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @HASH_BUFFER@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for hash-specific definitions
- *             @ictx@ = pointer to context block for the hash
- *             @ibuf@ = pointer to input data to hash
- *             @isz@ = size of buffer
- *
- * Use:                Handles buffering of input data to a hash function.  The
- *             hash's compression function is called when the buffer is
- *             full.  Note that the compression function can be called on
- *             data which is at odd alignments; it is expected to cope
- *             gracefully with this (possibly by copying the data into its
- *             internal buffer before starting).
- */
-
-#define HASH_BUFFER(PRE, pre, ictx, ibuf, isz) do {                    \
-  pre##_ctx *_bctx = (ictx);                                           \
-  size_t _bsz = (isz);                                                 \
-  const octet *_bbuf = (octet *)(ibuf);                                        \
-                                                                       \
-  /* --- Add on the size done so far --- *                             \
-   *                                                                   \
-   * Messy, because trapping overflow is difficult when you don't know \
-   * how many bits you've actually got.                                        \
-   */                                                                  \
-                                                                       \
-  {                                                                    \
-    uint32 _l = U32(_bsz);                                             \
-    uint32 _h = ((_bsz & ~MASK32) >> 16) >> 16;                                \
-    _bctx->nh += _h;                                                   \
-    _bctx->nl += _l;                                                   \
-    if (_bctx->nl < _l || _bctx->nl & ~MASK32)                         \
-      _bctx->nh++;                                                     \
-  }                                                                    \
-                                                                       \
-  /* --- Handle very small contributions --- */                                \
-                                                                       \
-  if (_bctx->off + _bsz < PRE##_BUFSZ) {                               \
-    memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz);                      \
-    _bctx->off += _bsz;                                                        \
-  } else {                                                             \
-                                                                       \
-    /* --- Handle an initial partial buffer --- */                     \
-                                                                       \
-    if (_bctx->off) {                                                  \
-      size_t s = PRE##_BUFSZ - _bctx->off;                             \
-      memcpy(_bctx->buf + _bctx->off, _bbuf, s);                       \
-      pre##_compress(_bctx, _bctx->buf);                               \
-      _bsz -= s; _bbuf += s;                                           \
-    }                                                                  \
-                                                                       \
-    /* --- Do whole buffers while we can --- */                                \
-                                                                       \
-    while (_bsz >= PRE##_BUFSZ) {                                      \
-      pre##_compress(_bctx, _bbuf);                                    \
-      _bsz -= PRE##_BUFSZ; _bbuf += PRE##_BUFSZ;                       \
-    }                                                                  \
-                                                                       \
-    /* --- And wrap up at the end --- */                               \
-                                                                       \
-    if (_bsz)                                                          \
-      memcpy(_bctx->buf, _bbuf, _bsz);                                 \
-    _bctx->off = _bsz;                                                 \
-  }                                                                    \
-} while (0)
-
-/* --- @HASH_PAD@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for hash-specific definitions
- *             @ictx@ = pointer to context block for the hash
- *             @term@ = terminator character to write following the data
- *             @pad@ = pad character to fill with
- *             @diff@ = size of space to leave at the end of the last block
- *
- * Use:                Does padding for message digest functions.
- */
-
-#define HASH_PAD(PRE, pre, ictx, term, pad, diff) do {                 \
-  pre##_ctx *_pctx = (ictx);                                           \
-                                                                       \
-  _pctx->buf[_pctx->off] = term;                                       \
-  _pctx->off++;                                                                \
-  if (_pctx->off > PRE##_BUFSZ - diff) {                               \
-    if (_pctx->off < PRE##_BUFSZ)                                      \
-      memset(_pctx->buf + _pctx->off, pad, PRE##_BUFSZ - _pctx->off);  \
-    pre##_compress(_pctx, _pctx->buf);                                 \
-    memset(_pctx->buf, pad, PRE##_BUFSZ - diff);                       \
-  } else                                                               \
-    memset(_pctx->buf + _pctx->off, pad,                               \
-          PRE##_BUFSZ - _pctx->off - diff);                            \
-} while (0)
-
-/* --- @HASH_MD5STRENGTH@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for hash-specific definitions
- *             @ictx@ = pointer to context block for the hash
- *
- * Use:                Does MD5-style MD strengthening.  The data is terminated
- *             by a single set bit, padded with zero bits, and then a 64-
- *             bit length is written, little-end first.
- */
-
-#define HASH_MD5STRENGTH(PRE, pre, ictx) do {                          \
-  pre##_ctx *_mctx = (ictx);                                           \
-  HASH_PAD(PRE, pre, _mctx, 0x80u, 0, 8);                              \
-  STORE32_L(_mctx->buf + PRE##_BUFSZ - 8, _mctx->nl << 3);             \
-  STORE32_L(_mctx->buf + PRE##_BUFSZ - 4,                              \
-           (_mctx->nl >> 29) | (_mctx->nh << 3));                      \
-  pre##_compress(_mctx, _mctx->buf);                                   \
-} while (0)
-
-/* --- @HASH_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for hash-specfic definitions
- *
- * Use:                Standard test rig for hash functions.
- */
-
-#ifdef TEST_RIG
-
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#define HASH_BUFLEN 100000
-
-#define HASH_TEST(PRE, pre)                                            \
-                                                                       \
-static int verify(dstr *v)                                             \
-{                                                                      \
-  pre##_ctx ctx;                                                       \
-  int ok = 1;                                                          \
-  int i;                                                               \
-  octet *p;                                                            \
-  int szs[] = { 1, 7, 192, -1, 0 }, *ip;                               \
-  size_t sz;                                                           \
-  dstr d;                                                              \
-                                                                       \
-  dstr_create(&d);                                                     \
-  dstr_ensure(&d, PRE##_HASHSZ);                                       \
-  d.len = PRE##_HASHSZ;                                                        \
-                                                                       \
-  for (ip = szs; *ip; ip++) {                                          \
-    i = *ip;                                                           \
-    sz = v[0].len;                                                     \
-    if (i == -1)                                                       \
-      i = sz;                                                          \
-    if (i > sz)                                                                \
-      continue;                                                                \
-    p = (octet *)v[0].buf;                                             \
-    pre##_init(&ctx);                                                  \
-    while (sz) {                                                       \
-      if (i > sz)                                                      \
-       i = sz;                                                         \
-      pre##_hash(&ctx, p, i);                                          \
-      p += i;                                                          \
-      sz -= i;                                                         \
-    }                                                                  \
-    pre##_done(&ctx, d.buf);                                           \
-    if (memcmp(d.buf, v[1].buf, PRE##_HASHSZ) != 0) {                  \
-      printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\texpected = ",    \
-            *ip, v[0].buf);                                            \
-      type_hex.dump(&v[1], stdout);                                    \
-      fputs("\n\tcomputed = ", stdout);                                        \
-      type_hex.dump(&d, stdout);                                       \
-      putchar('\n');                                                   \
-      ok = 0;                                                          \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  dstr_destroy(&d);                                                    \
-  return (ok);                                                         \
-}                                                                      \
-                                                                       \
-static int verifyrep(dstr *v)                                          \
-{                                                                      \
-  pre##_ctx ctx;                                                       \
-  size_t len = v[0].len;                                               \
-  int n = *(int *)v[1].buf;                                            \
-  int nd = 0;                                                          \
-  int nn = len;                                                                \
-  int ok = 1;                                                          \
-  octet *p, *q;                                                                \
-  dstr d = DSTR_INIT;                                                  \
-                                                                       \
-  while (nn < HASH_BUFLEN && (n & 1) == 0) { nd++; nn <<= 1; n >>= 1; }        \
-  p = xmalloc(nn);                                                     \
-  memcpy(p, v[0].buf, len);                                            \
-  q = p + len;                                                         \
-  while (nd--) { memcpy(q, p, len); q += len; len <<= 1; }             \
-                                                                       \
-  dstr_ensure(&d, PRE##_HASHSZ);                                       \
-  d.len = PRE##_HASHSZ;                                                        \
-  pre##_init(&ctx);                                                    \
-  while (n--) pre##_hash(&ctx, p, len);                                        \
-  pre##_done(&ctx, d.buf);                                             \
-                                                                       \
-  if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) {                    \
-    printf("\nfail:\n\tinput = `%s'\n\treps = `%i'\n\texpected = ",    \
-            v[0].buf, *(int *)v[1].buf);                               \
-    type_hex.dump(&v[2], stdout);                                      \
-    fputs("\n\tcomputed = ", stdout);                                  \
-    type_hex.dump(&d, stdout);                                         \
-    putchar('\n');                                                     \
-    ok = 0;                                                            \
-  }                                                                    \
-  xfree(p);                                                            \
-  dstr_destroy(&d);                                                    \
-  return (ok);                                                         \
-}                                                                      \
-                                                                       \
-static test_chunk defs[] = {                                           \
-  { #pre, verify, { &type_string, &type_hex, 0 } },                    \
-  { #pre "-rep", verifyrep,                                            \
-    { &type_string, &type_int, &type_hex, 0 } },                       \
-  { 0, 0, { 0 } }                                                      \
-};                                                                     \
-                                                                       \
-int main(int argc, char *argv[])                                       \
-{                                                                      \
-  ego(argv[0]);                                                                \
-  test_run(argc, argv, defs, SRCDIR"/tests/" #pre);                    \
-  return (0);                                                          \
-}
-
-#else
-#  define HASH_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/hashsum.c b/hashsum.c
deleted file mode 100644 (file)
index 290641b..0000000
--- a/hashsum.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Hash files using some secure hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include "ghash.h"
-#include "cc.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-#define f_bogus 1u
-#define f_verbose 2u
-#define f_check 4u
-#define f_files 8u
-#define f_oddhash 16u
-#define f_escape 32u
-#define f_oddenc 64u
-
-/*----- Guts --------------------------------------------------------------*/
-
-static int checkjunk(const char *path, const struct stat *st, void *p)
-{
-  const char *what;
-  fhashstate *fh = p;
-
-  if (!st) {
-    if (fh->f & f_verbose)
-      fprintf(stderr, "JUNK (error %s) %s\n", strerror(errno), path);
-    else
-      moan("couldn't stat junk file `%s': %s", path, strerror(errno));
-  } else {
-    what = describefile(st);
-    if (fh->f & f_verbose)
-      fprintf(stderr, "JUNK %s %s\n", what, path);
-    else
-      moan("found junk %s `%s'", what, path);
-  }
-  return (0);
-}
-
-static int warnjunk(const char *path, const struct stat *st, void *p)
-{
-  if (st)
-    moan("unexpected %s `%s'", describefile(st), path);
-  else
-    moan("couldn't stat unexpected file `%s': %s", path, strerror(errno));
-  return (0);
-}
-
-static int checkhash(fhashstate *fh, const char *file, const encodeops *e)
-{
-  int rc;
-  hfpctx hfp;
-  dstr dl = DSTR_INIT;
-  dstr df = DSTR_INIT;
-  unsigned long n = 0, nfail = 0;
-  int hf;
-
-  if (!file || strcmp(file, "-") == 0)
-    hfp.fp = stdin;
-  else if ((hfp.fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) {
-    moan("couldn't open `%s': %s", file, strerror(errno));
-    return (EXIT_FAILURE);
-  }
-
-  hfp.dline = &dl;
-  hfp.dfile = &df;
-  hfp.hbuf = xmalloc(2 * fh->gch->hashsz);
-  hfp.gch = fh->gch;
-  hfp.ee = e;
-  hfp.f = fh->f;
-
-  while ((hf = hfparse(&hfp)) != HF_EOF) {
-    switch (hf) {
-      case HF_HASH:
-       xfree(hfp.hbuf);
-       hfp.hbuf = xmalloc(2 * hfp.gch->hashsz);
-       break;
-      case HF_FILE:
-       if (fhash(fh, df.buf, hfp.hbuf + hfp.gch->hashsz)) {
-         moan("couldn't read `%s': %s", df.buf, strerror(errno));
-         rc = EXIT_FAILURE;
-         continue;
-       }
-       if (memcmp(hfp.hbuf, hfp.hbuf + hfp.gch->hashsz,
-                  hfp.gch->hashsz) != 0) {
-         if (hfp.f & f_verbose)
-           fprintf(stderr, "FAIL %s\n", df.buf);
-         else
-           moan("%s check failed for `%s'", hfp.gch->name, df.buf);
-         nfail++;
-         rc = EXIT_FAILURE;
-       } else {
-         if (hfp.f & f_verbose)
-           fprintf(stderr, "OK %s\n", df.buf);
-       }
-       n++;
-    }
-  }
-
-  if (ferror(hfp.fp)) {
-    moan("error reading input `%s': %s",
-        file ? file : "<stdin>", strerror(errno));
-    rc = EXIT_FAILURE;
-  }
-  dstr_destroy(&dl);
-  dstr_destroy(&df);
-  xfree(hfp.hbuf);
-  if ((fh->f & f_verbose) && nfail)
-    moan("%lu of %lu file(s) failed %s check", nfail, n, hfp.gch->name);
-  else if (!n)
-    moan("no files checked");
-  return (rc);
-}
-
-static int dohash(fhashstate *fh, const char *file, const encodeops *e)
-{
-  int rc = 0;
-  octet *p = xmalloc(fh->gch->hashsz);
-
-  if (fhash(fh, file, p)) {
-    moan("couldn't read `%s': %s", file ? file : "<stdin>", strerror(errno));
-    rc = EXIT_FAILURE;
-  } else {
-    e->put(p, fh->gch->hashsz, stdout);
-    if (file) {
-      fputc(' ', stdout);
-      fputc(fh->f & FHF_BINARY ? '*' : ' ', stdout);
-      if (fh->f & f_escape)
-       putstring(stdout, file, 0);
-      else
-       fputs(file, stdout);
-    }
-    fputc('\n', stdout);
-  }
-
-  xfree(p);
-  return (rc);
-}
-
-static int dofile(fhashstate *fh, const char *file, const encodeops *e)
-  { return (fh->f & f_check ? checkhash : dohash)(fh, file, e); }
-
-static int hashfiles(fhashstate *fh, const char *file, const encodeops *e)
-{
-  FILE *fp;
-  dstr d = DSTR_INIT;
-  int rc = 0;
-  int rrc;
-
-  if (!file || strcmp(file, "-") == 0)
-    fp = stdin;
-  else if ((fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) {
-    moan("couldn't open `%s': %s", file, strerror(errno));
-    return (EXIT_FAILURE);
-  }
-
-  for (;;) {
-    DRESET(&d);
-    if (getstring(fp, &d, GSF_FILE | fh->f))
-      break;
-    if ((rrc = dofile(fh, d.buf, e)) != 0)
-      rc = rrc;
-  }
-
-  return (rc);
-}
-
-static int hashsum(fhashstate *fh, const char *file, const encodeops *e)
-  { return (fh->f & f_files ? hashfiles : dofile)(fh, file, e); }
-
-/*----- Main driver -------------------------------------------------------*/
-
-void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "Usage: $ [-f0ebcv] [-a ALGORITHM] [-E ENC] [FILES...]\n");
-}
-
-static void help(FILE *fp, const gchash *gch)
-{
-  version(fp);
-  fputc('\n', fp);
-  usage(fp);
-  pquis(fp, "\n\
-Generates or checks message digests on files.  Options available:\n\
-\n\
--h, --help             Display this help message.\n\
--V, --version          Display program's version number.\n\
--u, --usage            Display a terse usage message.\n\
--l, --list [ITEM...]   Show known hash functions and/or encodings.\n\
-\n\
--a, --algorithm=ALG    Use the message digest algorithm ALG.\n\
--E, --encoding=ENC     Represent hashes using encoding ENC.\n\
-\n\
--f, --files            Read a list of file names from standard input.\n\
--0, --null             File names are null terminated, not plain text.\n\
-\n\
--e, --escape           Escape funny characters in filenames.\n\
--c, --check            Check message digests rather than emitting them.\n\
--b, --binary           When reading files, treat them as binary.\n\
--p, --progress         Show a progress indicator for large files.\n\
--v, --verbose          Be verbose when checking digests.\n\
-\n\
-For a list of hashing algorithms and encodings, type `$ --list'.\n\
-");
-  if (gch)
-    fprintf(fp, "The default message digest algorithm is %s.\n", gch->name);
-}
-
-#define LISTS(LI)                                                      \
-  LI("Lists", list, listtab[i].name, listtab[i].name)                  \
-  LI("Hash functions", hash, ghashtab[i], ghashtab[i]->name)           \
-  LI("Encodings", enc, encodingtab[i].name, encodingtab[i].name)
-
-MAKELISTTAB(listtab, LISTS)
-
-int main(int argc, char *argv[])
-{
-  fhashstate fh;
-  const encodeops *e = &encodingtab[ENC_HEX];
-  int rc;
-
-  /* --- Initialization --- */
-
-  ego(argv[0]);
-  sub_init();
-  fhash_init(&fh, 0, 0);
-
-  /* --- Choose a hash function from the name --- */
-
-  {
-    char *q = xstrdup(QUIS);
-    size_t len = strlen(q);
-    if (len > 3 && strcmp(q + len - 3, "sum") == 0) {
-      q[len - 3] = 0;
-      fh.gch = gethash(q);
-    }
-    if (!fh.gch)
-      fh.gch = gethash("md5");
-    xfree(q);
-  }
-
-  /* --- Read options --- */
-
-  for (;;) {
-    static struct option opts[] = {
-      { "help",                0,              0,      'h' },
-      { "verbose",     0,              0,      'V' },
-      { "usage",       0,              0,      'u' },
-
-      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
-      { "hash",                OPTF_ARGREQ,    0,      'a' },
-      { "encoding",    OPTF_ARGREQ,    0,      'E' },
-      { "list",                0,              0,      'l' },
-
-      { "files",       0,              0,      'f' },
-      { "find",                0,              0,      'f' },
-      { "null",                0,              0,      '0' },
-
-      { "escape",      0,              0,      'e' },
-      { "check",       0,              0,      'c' },
-      { "junk",                0,              0,      'j' },
-      { "binary",      0,              0,      'b' },
-      { "verbose",     0,              0,      'v' },
-      { "progress",    0,              0,      'p' },
-
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "hVu a:E:l f0 ecjbvp", opts, 0, 0, 0);
-    if (i < 0)
-      break;
-
-    switch (i) {
-      case 'h':
-       help(stdout, fh.gch);
-       exit(0);
-      case 'V':
-       version(stdout);
-       exit(0);
-      case 'u':
-       usage(stdout);
-       exit(0);
-      case 'l':
-       exit(displaylists(listtab, argv + optind));
-      case 'a':
-       if ((fh.gch = gethash(optarg)) == 0)
-         die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg);
-       fh.f |= f_oddhash;
-       break;
-      case 'E':
-       if ((e = getencoding(optarg)) == 0)
-         die(EXIT_FAILURE, "unknown encoding `%s'", optarg);
-       fh.f |= f_oddenc;
-       break;
-      case 'f':
-       fh.f |= f_files;
-       break;
-      case '0':
-       fh.f |= GSF_RAW;
-       break;
-      case 'e':
-       fh.f |= f_escape;
-       break;
-      case 'c':
-       fh.f |= f_check;
-       break;
-      case 'j':
-       fh.f |= FHF_JUNK;
-       break;
-      case 'b':
-       fh.f |= FHF_BINARY;
-       break;
-      case 'v':
-       fh.f |= f_verbose;
-       break;
-      case 'p':
-       fh.f |= FHF_PROGRESS;
-       break;
-      default:
-       fh.f |= f_bogus;
-       break;
-    }
-  }
-
-  if (fh.f & f_bogus) {
-    usage(stderr);
-    exit(EXIT_FAILURE);
-  }
-  argv += optind;
-  argc -= optind;
-
-  /* --- Generate output --- */
-
-  if (!(fh.f & f_check) && (argc || (fh.f & f_files))) {
-    if (fh.f & f_oddhash) printf("#hash %s\n", fh.gch->name);
-    if (fh.f & f_oddenc) printf("#encoding %s\n", e->name);
-    if (fh.f & f_escape) fputs("#escape\n", stdout);
-  }
-  if (!argc)
-    rc = hashsum(&fh, 0, e);
-  else {
-    int i;
-    int rrc;
-
-    rc = 0;
-    for (i = 0; i < argc; i++) {
-      if ((rrc = hashsum(&fh, argv[i], e)) != 0)
-       rc = rrc;
-    }
-  }
-
-  if (fh.f & FHF_JUNK) {
-    if (fh.f & f_check) {
-      if (fhash_junk(&fh, checkjunk, &fh)) rc = EXIT_FAILURE;
-    } else {
-      if (fhash_junk(&fh, warnjunk, 0) < 0) rc = EXIT_FAILURE;
-    }
-  }
-  fhash_free(&fh);
-
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/hmac-def.h b/hmac-def.h
deleted file mode 100644 (file)
index 8b6b4f5..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-/* -*-c-*-
- *
- * $Id: hmac-def.h,v 1.8 2004/04/08 01:36:15 mdw Exp $
- *
- * Definitions for HMAC and NMAC
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_HMAC_DEF_H
-#define CATACOMB_HMAC_DEF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_GMAC_H
-#  include "gmac.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @HMAC_DEF@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying hash function
- *
- * Use:                Creates implementations for the HMAC and NMAC functions.
- */
-
-#define HMAC_DEF(PRE, pre)                                             \
-                                                                       \
-/* --- Useful constants --- */                                         \
-                                                                       \
-const octet pre##_hmackeysz[] = { KSZ_ANY, PRE##_STATESZ };            \
-const octet pre##_sslmackeysz[] = { KSZ_ANY, PRE##_STATESZ };          \
-const octet pre##_nmackeysz[] = { KSZ_SET, 2 * PRE##_STATESZ, 0 };     \
-                                                                       \
-/* --- @pre_nmacinit@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_macctx *key@ = pointer to a MAC key object         \
- *             @const void *ok@ = pointer to outer hash init vector    \
- *             @const void *ik@ = pointer to inner hash init vector    \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a MAC key for doing NMAC hashing.           \
- */                                                                    \
-                                                                       \
-void pre##_nmacinit(pre##_mackey *key, const void *ok, const void *ik) \
-{                                                                      \
-  memcpy(key->ochain, ok, PRE##_STATESZ);                              \
-  memcpy(key->ichain, ik, PRE##_STATESZ);                              \
-  key->ocount = key->icount = 0;                                       \
-}                                                                      \
-                                                                       \
-/* --- @pre_hmacinit@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_mackey *key@ = pointer to MAC key object           \
- *             @const void *k@ = pointer to key to use                 \
- *             @size_t sz@ = size of key data                          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a MAC key for doing HMAC hashing.  Keys     \
- *             longer than the hash function's output size aren't very \
- *             useful, but are accepted.  Keys longer than the hash's  \
- *             block size are also accepted; they are hashed before    \
- *             use, as specified in RFC2104.                           \
- */                                                                    \
-                                                                       \
-void pre##_hmacinit(pre##_mackey *key, const void *k, size_t sz)       \
-{                                                                      \
-  int i;                                                               \
-  const octet *kbuf = k;                                               \
-  pre##_ctx ctx;                                                       \
-  octet buf[PRE##_HASHSZ];                                             \
-                                                                       \
-  if (sz > PRE##_BUFSZ)        {                                               \
-    pre##_init(&ctx);                                                  \
-    pre##_hash(&ctx, k, sz);                                           \
-    pre##_done(&ctx, buf);                                             \
-    kbuf = buf;                                                                \
-    sz = PRE##_HASHSZ;                                                 \
-  }                                                                    \
-                                                                       \
-  pre##_init(&ctx);                                                    \
-  memset(ctx.buf, 0x5c, PRE##_BUFSZ);                                  \
-  for (i = 0; i < sz; i++)                                             \
-    ctx.buf[i] ^= kbuf[i];                                             \
-  pre##_compress(&ctx, ctx.buf);                                       \
-  pre##_state(&ctx, key->ochain);                                      \
-                                                                       \
-  pre##_init(&ctx);                                                    \
-  memset(ctx.buf, 0x36, PRE##_BUFSZ);                                  \
-  for (i = 0; i < sz; i++)                                             \
-    ctx.buf[i] ^= kbuf[i];                                             \
-  pre##_compress(&ctx, ctx.buf);                                       \
-  pre##_state(&ctx, key->ichain);                                      \
-                                                                       \
-  key->ocount = key->icount = PRE##_BUFSZ;                             \
-  BURN(ctx);                                                           \
-}                                                                      \
-                                                                       \
-/* --- @pre_sslmacinit@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_mackey *key@ = pointer to MAC key object           \
- *             @const void *k@ = pointer to key to use                 \
- *             @size_t sz@ = size of key data                          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a MAC key for doing hasing using the SSL3   \
- *             variant of HMAC.                                        \
- */                                                                    \
-                                                                       \
-void pre##_sslmacinit(pre##_mackey *key, const void *k, size_t sz)     \
-{                                                                      \
-  const octet *kbuf = k;                                               \
-  pre##_ctx ctx;                                                       \
-  octet buf[PRE##_HASHSZ];                                             \
-                                                                       \
-  if (sz > PRE##_BUFSZ)        {                                               \
-    pre##_init(&ctx);                                                  \
-    pre##_hash(&ctx, k, sz);                                           \
-    pre##_done(&ctx, buf);                                             \
-    kbuf = buf;                                                                \
-    sz = PRE##_HASHSZ;                                                 \
-  }                                                                    \
-                                                                       \
-  pre##_init(&ctx);                                                    \
-  memcpy(ctx.buf, kbuf, sz);                                           \
-  memset(ctx.buf + sz, 0x5c, PRE##_BUFSZ - sz);                                \
-  pre##_compress(&ctx, ctx.buf);                                       \
-  pre##_state(&ctx, key->ochain);                                      \
-                                                                       \
-  pre##_init(&ctx);                                                    \
-  memcpy(ctx.buf, kbuf, sz);                                           \
-  memset(ctx.buf + sz, 0x36, PRE##_BUFSZ - sz);                                \
-  pre##_compress(&ctx, ctx.buf);                                       \
-  pre##_state(&ctx, key->ichain);                                      \
-                                                                       \
-  key->ocount = key->icount = PRE##_BUFSZ;                             \
-  BURN(ctx);                                                           \
-}                                                                      \
-                                                                       \
-/* --- @pre_macinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
- *             @const pre_mackey *key@ = pointer to MAC key block      \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Instantiates a MAC context from a key block.            \
- */                                                                    \
-                                                                       \
-void pre##_macinit(pre##_macctx *ctx, const pre##_mackey *key)         \
-{                                                                      \
-  memcpy(ctx->chain, key->ochain, PRE##_STATESZ);                      \
-  ctx->count = key->ocount;                                            \
-  pre##_set(&ctx->ctx, key->ichain, key->icount);                      \
-}                                                                      \
-                                                                       \
-/* --- @pre_machash@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
- *             @const void *buf@ = pointer to buffer                   \
- *             @size_t sz@ = size of the buffer                        \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Hashes a buffer.                                        \
- */                                                                    \
-                                                                       \
-void pre##_machash(pre##_macctx *ctx, const void *buf, size_t sz)      \
-{                                                                      \
-  pre##_hash(&ctx->ctx, buf, sz);                                      \
-}                                                                      \
-                                                                       \
-/* --- @pre_macdone@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
- *             @void *mac@ = pointer to buffer to receive MAC          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Returns the result of a MAC computation.                \
- */                                                                    \
-                                                                       \
-void pre##_macdone(pre##_macctx *ctx, void *mac)                       \
-{                                                                      \
-  pre##_done(&ctx->ctx, mac);                                          \
-  pre##_set(&ctx->ctx, ctx->chain, ctx->count);                                \
-  pre##_hash(&ctx->ctx, mac, PRE##_HASHSZ);                            \
-  pre##_done(&ctx->ctx, mac);                                          \
-}                                                                      \
-                                                                       \
-/* --- Generic MAC interface --- */                                    \
-                                                                       \
-static const gmac_ops gkops;                                           \
-static const ghash_ops gops, gnops, gsslops;                           \
-                                                                       \
-typedef struct gkctx {                                                 \
-  gmac m;                                                              \
-  const ghash_ops *gops;                                               \
-  pre##_mackey k;                                                      \
-} gkctx;                                                               \
-                                                                       \
-typedef struct gctx {                                                  \
-  ghash h;                                                             \
-  pre##_macctx c;                                                      \
-  octet buf[PRE##_HASHSZ];                                             \
-} gctx;                                                                        \
-                                                                       \
-static ghash *gkinit(gmac *m)                                          \
-{                                                                      \
-  gkctx *gk = (gkctx *)m;                                              \
-  gctx *g = S_CREATE(gctx);                                            \
-  g->h.ops = gk->gops;                                                 \
-  pre##_macinit(&g->c, &gk->k);                                                \
-  return (&g->h);                                                      \
-}                                                                      \
-                                                                       \
-static gmac *gkey(const void *k, size_t sz)                            \
-{                                                                      \
-  gkctx *gk = S_CREATE(gkctx);                                         \
-  gk->m.ops = &gkops;                                                  \
-  gk->gops = &gops;                                                    \
-  pre##_hmacinit(&gk->k, k, sz);                                       \
-  return (&gk->m);                                                     \
-}                                                                      \
-                                                                       \
-static gmac *gnkey(const void *k, size_t sz)                           \
-{                                                                      \
-  gkctx *gk = S_CREATE(gkctx);                                         \
-  const octet *kk = k;                                                 \
-  assert(keysz(sz, pre##_nmackeysz) == sz);                            \
-  gk->m.ops = &gkops;                                                  \
-  gk->gops = &gnops;                                                   \
-  pre##_nmacinit(&gk->k, kk, kk + PRE##_STATESZ);                      \
-  return (&gk->m);                                                     \
-}                                                                      \
-                                                                       \
-static gmac *gsslkey(const void *k, size_t sz)                         \
-{                                                                      \
-  gkctx *gk = S_CREATE(gkctx);                                         \
-  gk->m.ops = &gkops;                                                  \
-  gk->gops = &gsslops;                                                 \
-  pre##_sslmacinit(&gk->k, k, sz);                                     \
-  return (&gk->m);                                                     \
-}                                                                      \
-                                                                       \
-static void ghhash(ghash *h, const void *p, size_t sz)                 \
-{                                                                      \
-  gctx *g = (gctx *)h;                                                 \
-  pre##_machash(&g->c, p, sz);                                         \
-}                                                                      \
-                                                                       \
-static octet *ghdone(ghash *h, void *buf)                              \
-{                                                                      \
-  gctx *g = (gctx *)h;                                                 \
-  if (!buf)                                                            \
-    buf = g->buf;                                                      \
-  pre##_macdone(&g->c, buf);                                           \
-  return (buf);                                                                \
-}                                                                      \
-                                                                       \
-static ghash *ghcopy(ghash *h)                                         \
-{                                                                      \
-  gctx *g = (gctx *)h;                                                 \
-  gctx *gg = S_CREATE(gctx);                                           \
-  memcpy(gg, g, sizeof(gctx));                                         \
-  return (&gg->h);                                                     \
-}                                                                      \
-                                                                       \
-static void ghdestroy(ghash *h)                                                \
-{                                                                      \
-  gctx *g = (gctx *)h;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static void gkdestroy(gmac *m)                                         \
-{                                                                      \
-  gkctx *gk = (gkctx *)m;                                              \
-  BURN(*gk);                                                           \
-  S_DESTROY(gk);                                                       \
-}                                                                      \
-                                                                       \
-static ghash *ghinit(void)                                             \
-{                                                                      \
-  assert(((void)"Attempt to instantiate an unkeyed MAC", 0));          \
-  return (0);                                                          \
-}                                                                      \
-                                                                       \
-const gcmac pre##_nmac =                                               \
-  { #pre "-nmac", PRE##_HASHSZ, pre##_nmackeysz, gnkey };              \
-const gcmac pre##_hmac =                                               \
-  { #pre "-hmac", PRE##_HASHSZ, pre##_hmackeysz, gkey };               \
-const gcmac pre##_sslmac =                                             \
-  { #pre "-sslmac", PRE##_HASHSZ, pre##_sslmackeysz, gsslkey };                \
-static const gmac_ops gkops = { &pre##_hmac, gkinit, gkdestroy };      \
-static const gmac_ops gnkops = { &pre##_nmac, gkinit, gkdestroy };     \
-static const gmac_ops gsslkops = { &pre##_sslmac, gkinit, gkdestroy }; \
-static const gchash gch = { #pre "-hmac", PRE##_HASHSZ, ghinit };      \
-static const ghash_ops gops =                                          \
-  { &gch, ghhash, ghdone, ghdestroy, ghcopy };                         \
-static const gchash gnch = { #pre "-nmac", PRE##_HASHSZ, ghinit };     \
-static const ghash_ops gnops =                                         \
-  { &gch, ghhash, ghdone, ghdestroy, ghcopy };                         \
-static const gchash gsslch = { #pre "-sslmac", PRE##_HASHSZ, ghinit }; \
-static const ghash_ops gsslops =                                       \
-  { &gch, ghhash, ghdone, ghdestroy, ghcopy };                         \
-                                                                       \
-HMAC_TEST(PRE, pre)
-
-/* --- @HMAC_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for hash-specfic definitions
- *
- * Use:                Standard test rig for MAC functions.
- */
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include <mLib/dstr.h>
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#define HMAC_TEST(PRE, pre)                                            \
-                                                                       \
-static int macverify(dstr *v)                                          \
-{                                                                      \
-  pre##_macctx cctx;                                                   \
-  pre##_mackey ckey;                                                   \
-  int ok = 1;                                                          \
-  int i;                                                               \
-  octet *p;                                                            \
-  int szs[] = { 1, 7, 192, -1, 0 }, *ip;                               \
-  size_t csz;                                                          \
-  dstr d;                                                              \
-                                                                       \
-  dstr_create(&d);                                                     \
-  dstr_ensure(&d, PRE##_HASHSZ);                                       \
-  d.len = PRE##_HASHSZ;                                                        \
-                                                                       \
-  pre##_hmacinit(&ckey, v[1].buf, v[1].len);                           \
-                                                                       \
-  for (ip = szs; *ip; ip++) {                                          \
-    i = *ip;                                                           \
-    csz = v[0].len;                                                    \
-    if (i == -1)                                                       \
-      i = csz;                                                         \
-    if (i > csz)                                                       \
-      continue;                                                                \
-    p = (octet *)v[0].buf;                                             \
-    pre##_macinit(&cctx, &ckey);                                       \
-    while (csz) {                                                      \
-      if (i > csz)                                                     \
-       i = csz;                                                        \
-      pre##_machash(&cctx, p, i);                                      \
-      p += i;                                                          \
-      csz -= i;                                                                \
-    }                                                                  \
-    pre##_macdone(&cctx, d.buf);                                       \
-    if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) {                  \
-      printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\tkey = ",         \
-            *ip, v[0].buf);                                            \
-      type_hex.dump(&v[1], stdout);                                    \
-      fputs("\n\texpected = ", stdout);                                        \
-      type_hex.dump(&v[2], stdout);                                    \
-      fputs("\n\tcomputed = ", stdout);                                        \
-      type_hex.dump(&d, stdout);                                       \
-      putchar('\n');                                                   \
-      ok = 0;                                                          \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  dstr_destroy(&d);                                                    \
-  return (ok);                                                         \
-}                                                                      \
-                                                                       \
-static test_chunk macdefs[] = {                                                \
-  { #pre "-hmac", macverify,                                           \
-    { &type_string, &type_hex, &type_hex, 0 } },                       \
-  { 0, 0, { 0 } }                                                      \
-};                                                                     \
-                                                                       \
-int main(int argc, char *argv[])                                       \
-{                                                                      \
-  ego(argv[0]);                                                                \
-  test_run(argc, argv, macdefs, SRCDIR"/tests/" #pre);                 \
-  return (0);                                                          \
-}
-
-#else
-#  define HMAC_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/hmac.h b/hmac.h
deleted file mode 100644 (file)
index fffb093..0000000
--- a/hmac.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/* -*-c-*-
- *
- * $Id: hmac.h,v 1.7 2004/04/08 01:36:15 mdw Exp $
- *
- * Generic code for HMAC and NMAC
- *
- * (c) 1998 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.
- */
-
-/*----- Notes on the HMAC and NMAC constructions --------------------------*
- *
- * Designed by Mihir Bellare, Ran Canetti and Hugo Krawczyk, NMAC is a method
- * for constructing keyed message authentication algorithms from unkeyed hash
- * functions.  It has been proven to provide useful security given reasonable
- * assumptions about the underlying hash function.  HMAC is an alternative
- * formulation which doesn't require low-level access to the hash function's
- * implementation.  NMAC was designed to allow MD5 has a suitable underlying
- * hash function, even though doubts were already being raised about its
- * collision resistance.
- */
-
-#ifndef CATACOMB_HMAC_H
-#define CATACOMB_HMAC_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GMAC_H
-#  include "gmac.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @HMAC_DECL@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying hash function
- *
- * Use:                Creates declarations for the HMAC and NMAC functions.
- */
-
-#define HMAC_DECL(PRE, pre)                                            \
-                                                                       \
-/* --- An HMAC or NMAC key --- */                                      \
-                                                                       \
-typedef struct pre##_mackey {                                          \
-  octet ochain[PRE##_STATESZ];         /* Chaining for outer hash */   \
-  unsigned ocount;                     /* Byte count for outer hash */ \
-  octet ichain[PRE##_STATESZ];         /* Chaining for inner hash */   \
-  unsigned icount;                     /* Byte count for inner hash */ \
-} pre##_mackey;                                                                \
-                                                                       \
-/* --- An HMAC or NMAC hashing context --- */                          \
-                                                                       \
-typedef struct pre##_macctx {                                          \
-  pre##_ctx ctx;                       /* Context for main hashing */  \
-  octet chain[PRE##_STATESZ];          /* Chaining for outer hash */   \
-  unsigned count;                      /* Byte count for outer hash */ \
-} pre##_macctx;                                                                \
-                                                                       \
-/* --- Other useful constants --- */                                   \
-                                                                       \
-extern const octet pre##_hmackeysz[];                                  \
-extern const octet pre##_nmackeysz[];                                  \
-extern const octet pre##_sslmackeysz[];                                        \
-                                                                       \
-/* --- @pre_nmacinit@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_macctx *key@ = pointer to a MAC key object         \
- *             @const void *ok@ = pointer to outer hash init vector    \
- *             @const void *ik@ = pointer to inner hash init vector    \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a MAC key for doing NMAC hashing.           \
- */                                                                    \
-                                                                       \
-extern void pre##_nmacinit(pre##_mackey */*key*/,                      \
-                          const void */*ok*/, const void */*ik*/);     \
-                                                                       \
-/* --- @pre_hmacinit@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_mackey *key@ = pointer to MAC key object           \
- *             @const void *k@ = pointer to key to use                 \
- *             @size_t sz@ = size of key data                          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a MAC key for doing HMAC hashing.  Keys     \
- *             longer than the hash function's output size aren't very \
- *             useful, but are accepted.  Keys longer than the hash's  \
- *             block size are also accepted; they are hashed before    \
- *             use, as specified in RFC2104.                           \
- */                                                                    \
-                                                                       \
-extern void pre##_hmacinit(pre##_mackey */*key*/,                      \
-                          const void */*k*/, size_t /*sz*/);           \
-                                                                       \
-/* --- @pre_sslmacinit@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_mackey *key@ = pointer to MAC key object           \
- *             @const void *k@ = pointer to key to use                 \
- *             @size_t sz@ = size of key data                          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a MAC key for doing hasing using the SSL3   \
- *             variant of HMAC.                                        \
- */                                                                    \
-                                                                       \
-extern void pre##_sslmacinit(pre##_mackey */*key*/,                    \
-                            const void */*k*/, size_t /*sz*/);         \
-                                                                       \
-/* --- @pre_macinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
- *             @const pre_mackey *key@ = pointer to MAC key block      \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Instantiates a MAC context from a key block.            \
- */                                                                    \
-                                                                       \
-extern void pre##_macinit(pre##_macctx */*ctx*/,                       \
-                         const pre##_mackey */*key*/);                 \
-                                                                       \
-/* --- @pre_machash@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
- *             @const void *buf@ = pointer to buffer                   \
- *             @size_t sz@ = size of the buffer                        \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Hashes a buffer.                                        \
- */                                                                    \
-                                                                       \
-extern void pre##_machash(pre##_macctx */*ctx*/,                       \
-                         const void */*buf*/, size_t /*sz*/);          \
-                                                                       \
-/* --- @pre_macdone@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
- *             @void *mac@ = pointer to buffer to receive MAC          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Returns the result of a MAC computation.                \
- */                                                                    \
-                                                                       \
-extern void pre##_macdone(pre##_macctx */*ctx*/, void */*mac*/);       \
-                                                                       \
-/* --- Generic MAC interface --- */                                    \
-                                                                       \
-extern const gcmac pre##_hmac;                                         \
-extern const gcmac pre##_nmac;                                         \
-extern const gcmac pre##_sslmac;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/idea.c b/idea.c
deleted file mode 100644 (file)
index c0f7fe7..0000000
--- a/idea.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/* -*-c-*-
- *
- * $Id: idea.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of the IDEA cipher
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "idea.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet idea_keysz[] = { KSZ_SET, IDEA_KEYSZ };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @inv@ --- *
- *
- * Arguments:  @uint16 n@ = number to invert
- *
- * Returns:    Multiplicative inverse of @n@ %$\pmod{2^{16} + 1}$%.
- *
- * Use:                Computes multiplicative inverses.  This is handy for the
- *             decryption key scheduling.
- */
-
-static uint16 inv(uint16 n)
-{
-  uint32 m = 0x10001;
-  uint32 a = 1, b = 0;
-  uint32 nn = n;
-
-  if (!nn)
-    nn = 0x10000;
-  for (;;) {
-    uint32 q, r, t;
-    if (!(r = m % nn))
-      break;
-    q = m / nn;
-    m = nn; nn = r;
-    t = a; a = b - q * a; b = t;
-  }
-  if (a > MASK16)
-    a += 1;
-  return (U16(a));
-}
-
-/* --- @MUL@ --- *
- *
- * Arguments @x@ and @y@ are two 32-bit values to multiply.  On exit, @x@ is
- * the product of the two arguments.  The result is not normalized back to 16
- * bits; the arguments are not expected to be normalized.
- *
- * This code is from `Side Channel Attack Hardening of the IDEA Cipher',
- * published by Ascom Tech.
- */
-
-#define MUL(x, y) do {                                                 \
-  unsigned _t;                                                         \
-  uint32 _tt;                                                          \
-                                                                       \
-  x = U16(x - 1);                                                      \
-  _t = U16(y - 1);                                                     \
-  _tt = (uint32)x * (uint32)_t + (uint32)x + (uint32)_t + 1;           \
-  x = U16(_tt);                                                                \
-  _t = U16(_tt >> 16);                                                 \
-  x = x - _t + (x <= _t);                                              \
-} while (0)
-
-/* --- @idea_init@ --- *
- *
- * Arguments:  @idea_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes an IDEA key buffer.  The buffer must be exactly
- *             16 bytes in size, because IDEA is only defined with a key
- *             size of 128 bits.
- */
-
-void idea_init(idea_ctx *k, const void *buf, size_t sz)
-{
-  KSZ_ASSERT(idea, sz);
-
-  /* --- Unpack the encryption key --- */
-
-  {
-    const octet *p = buf;
-    uint16 *q = k->e;
-    uint32 a = LOAD32(p +  0);
-    uint32 b = LOAD32(p +  4);
-    uint32 c = LOAD32(p +  8);
-    uint32 d = LOAD32(p + 12);
-    int i;
-
-    /* --- Main unpacking loop --- */
-
-    for (i = 0; i < 6; i++) {
-
-      /* --- Spit out the next 8 subkeys --- */
-
-      q[0] = U16(a >> 16);
-      q[1] = U16(a >>  0);
-      q[2] = U16(b >> 16);
-      q[3] = U16(b >>  0);
-      q[4] = U16(c >> 16);
-      q[5] = U16(c >>  0);
-      q[6] = U16(d >> 16);
-      q[7] = U16(d >>  0);
-      q += 8;
-
-      /* --- Rotate and permute the subkeys --- */
-
-      {
-       uint32 t = a;
-       a = U32((a << 25) | (b >> 7));
-       b = U32((b << 25) | (c >> 7));
-       c = U32((c << 25) | (d >> 7));
-       d = U32((d << 25) | (t >> 7));
-      }
-    }
-
-    /* --- Write out the tail-enders --- */
-
-    q[0] = U16(a >> 16);
-    q[1] = U16(a >>  0);
-    q[2] = U16(b >> 16);
-    q[3] = U16(b >>  0);
-  }
-
-  /* --- Convert this into the decryption key --- */
-
-  {
-    uint16 *p = k->e + 52;
-    uint16 *q = k->d;
-    int i;
-
-    /* --- Translate the main round keys --- */
-
-    for (i = 0; i < 8; i++) {
-      p -= 6;
-      q[4] = p[0];
-      q[5] = p[1];
-      q[0] = inv(p[2]);
-      q[3] = inv(p[5]);
-      if (i) {
-       q[1] = 0x10000 - p[4];
-       q[2] = 0x10000 - p[3];
-      } else {
-       q[1] = 0x10000 - p[3];
-       q[2] = 0x10000 - p[4];
-      }
-      q += 6;
-    }
-
-    /* --- Translate the tail-enders --- */
-
-    p -= 4;
-    q[0] = inv(p[0]);
-    q[1] = 0x10000 - p[1];
-    q[2] = 0x10000 - p[2];
-    q[3] = inv(p[3]);
-  }
-}
-
-/* --- @ROUND@ --- */
-
-#define MIX(k, a, b, c, d) do {                                                \
-  MUL(a, k[0]);                                                                \
-  b += k[1];                                                           \
-  c += k[2];                                                           \
-  MUL(d, k[3]);                                                                \
-} while (0)
-
-#define MA(k, a, b, c, d) do {                                         \
-  unsigned _u = a ^ c;                                                 \
-  unsigned _v = b ^ d;                                                 \
-  MUL(_u, k[4]);                                                       \
-  _v += _u;                                                            \
-  MUL(_v, k[5]);                                                       \
-  _u += _v;                                                            \
-  a ^= _v;                                                             \
-  b ^= _u;                                                             \
-  c ^= _v;                                                             \
-  d ^= _u;                                                             \
-} while (0);
-
-#define ROUND(k, a, b, c, d) do {                                      \
-  MIX(k, a, b, c, d);                                                  \
-  MA(k, a, b, c, d);                                                   \
-  (k) += 6;                                                            \
-} while (0)
-
-/* --- Encryption --- */
-
-#define EBLK(k, a, b, c, d) do {                                       \
-  unsigned _a = U16(a >> 16);                                          \
-  unsigned _b = U16(a >>  0);                                          \
-  unsigned _c = U16(b >> 16);                                          \
-  unsigned _d = U16(b >>  0);                                          \
-  const uint16 *_k = (k);                                              \
-                                                                       \
-  ROUND(_k, _a, _b, _c, _d);                                           \
-  ROUND(_k, _a, _c, _b, _d);                                           \
-  ROUND(_k, _a, _b, _c, _d);                                           \
-  ROUND(_k, _a, _c, _b, _d);                                           \
-  ROUND(_k, _a, _b, _c, _d);                                           \
-  ROUND(_k, _a, _c, _b, _d);                                           \
-  ROUND(_k, _a, _b, _c, _d);                                           \
-  ROUND(_k, _a, _c, _b, _d);                                           \
-  MIX  (_k, _a, _c, _b, _d);                                           \
-  c = ((uint32)U16(_a) << 16) | (uint32)U16(_c);                       \
-  d = ((uint32)U16(_b) << 16) | (uint32)U16(_d);                       \
-} while (0)
-
-#define DBLK(k, a, b) EBLK((k), (a), (b))
-
-/* --- @idea_eblk@, @idea_dblk@ --- *
- *
- * Arguments:  @const idea_ctx *k@ = pointer to a key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-void idea_eblk(const idea_ctx *k, const uint32 *s, uint32 *d)
-{
-  EBLK(k->e, s[0], s[1], d[0], d[1]);
-}
-
-void idea_dblk(const idea_ctx *k, const uint32 *s, uint32 *d)
-{
-  EBLK(k->d, s[0], s[1], d[0], d[1]);
-}
-
-BLKC_TEST(IDEA, idea)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/idea.h b/idea.h
deleted file mode 100644 (file)
index b049d74..0000000
--- a/idea.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*-c-*-
- *
- * $Id: idea.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of the IDEA cipher
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on the IDEA block cipher ------------------------------------*
- *
- * IDEA was invented by James Massey and Xuejia Lai.  The fundamental idea
- * underlying the cipher is combining incompatible group operations.  The
- * algorithm's main claim to fame is that it is the symmetric cipher in PGP
- * version 2.
- *
- * The IDEA algorithm is allegedly patented by Ascom Tech A.G., even in the
- * UK and Europe.  Ascom are willing to grant licences for use in software
- * which forbids commercial use, but this is not compatible with Free
- * Software Foundation ideology.  The author recommends against the use of
- * the IDEA cipher entirely.  Blowfish is conceptually simpler, appears more
- * concervative, offers a larger keyspace, runs faster, and is in the public
- * domain.
- */
-
-#ifndef CATACOMB_IDEA_H
-#define CATACOMB_IDEA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define IDEA_BLKSZ 8
-#define IDEA_KEYSZ 16
-#define IDEA_CLASS (N, B, 64)
-
-extern const octet idea_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct idea_ctx {
-  uint16 e[52];
-  uint16 d[52];
-} idea_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @idea_init@ --- *
- *
- * Arguments:  @idea_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes an IDEA key buffer.  The buffer must be exactly
- *             16 bytes in size, because IDEA is only defined with a key
- *             size of 128 bits.
- */
-
-extern void idea_init(idea_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @idea_eblk@, @idea_dblk@ --- *
- *
- * Arguments:  @const idea_ctx *k@ = pointer to a key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void idea_eblk(const idea_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-extern void idea_dblk(const idea_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/karatsuba.h b/karatsuba.h
deleted file mode 100644 (file)
index d0b81fc..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/* -*-c-*-
- *
- * $Id: karatsuba.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Macros for Karatsuba functions
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_KARATSUBA_H
-#define CATACOMB_KARATSUBA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MPW_H
-#  include "mpw.h"
-#endif
-
-/*----- Normal arithmetic macros ------------------------------------------*/
-
-#define UADD(dv, av, avl) do {                                         \
-  mpw *_dv = (dv);                                                     \
-  const mpw *_av = (av), *_avl = (avl);                                        \
-  mpw _c = 0;                                                          \
-                                                                       \
-  while (_av < _avl) {                                                 \
-    mpw _a, _b;                                                                \
-    mpd _x;                                                            \
-    _a = *_av++;                                                       \
-    _b = *_dv;                                                         \
-    _x = (mpd)_a + (mpd)_b + _c;                                       \
-    *_dv++ = MPW(_x);                                                  \
-    _c = _x >> MPW_BITS;                                               \
-  }                                                                    \
-  while (_c) {                                                         \
-    mpd _x = (mpd)*_dv + (mpd)_c;                                      \
-    *_dv++ = MPW(_x);                                                  \
-    _c = _x >> MPW_BITS;                                               \
-  }                                                                    \
-} while (0)
-
-#define UADD2(dv, dvl, av, avl, bv, bvl) do {                          \
-  mpw *_dv = (dv), *_dvl = (dvl);                                      \
-  const mpw *_av = (av), *_avl = (avl);                                        \
-  const mpw *_bv = (bv), *_bvl = (bvl);                                        \
-  mpw _c = 0;                                                          \
-                                                                       \
-  while (_av < _avl || _bv < _bvl) {                                   \
-    mpw _a, _b;                                                                \
-    mpd _x;                                                            \
-    _a = (_av < _avl) ? *_av++ : 0;                                    \
-    _b = (_bv < _bvl) ? *_bv++ : 0;                                    \
-    _x = (mpd)_a + (mpd)_b + _c;                                       \
-    *_dv++ = MPW(_x);                                                  \
-    _c = _x >> MPW_BITS;                                               \
-  }                                                                    \
-  *_dv++ = _c;                                                         \
-  while (_dv < _dvl)                                                   \
-    *_dv++ = 0;                                                                \
-} while (0)
-
-#define USUB(dv, av, avl) do {                                         \
-  mpw *_dv = (dv);                                                     \
-  const mpw *_av = (av), *_avl = (avl);                                        \
-  mpw _c = 0;                                                          \
-                                                                       \
-  while (_av < _avl) {                                                 \
-    mpw _a, _b;                                                                \
-    mpd _x;                                                            \
-    _a = *_av++;                                                       \
-    _b = *_dv;                                                         \
-    _x = (mpd)_b - (mpd)_a - _c;                                       \
-    *_dv++ = MPW(_x);                                                  \
-    if (_x >> MPW_BITS)                                                        \
-      _c = 1;                                                          \
-    else                                                               \
-      _c = 0;                                                          \
-  }                                                                    \
-  while (_c) {                                                         \
-    mpd _x = (mpd)*_dv - (mpd)_c;                                      \
-    *_dv++ = MPW(_x);                                                  \
-    if (_x >> MPW_BITS)                                                        \
-      _c = 1;                                                          \
-    else                                                               \
-      _c = 0;                                                          \
-  }                                                                    \
-} while (0)
-
-/*----- Binary polynomial arithmetic macros -------------------------------*/
-
-#define UXOR(dv, av, avl) do {                                         \
-  mpw *_dv = (dv);                                                     \
-  const mpw *_av = (av), *_avl = (avl);                                        \
-                                                                       \
-  while (_av < _avl)                                                   \
-    *_dv++ ^= *_av++;                                                  \
-} while (0)
-
-#define UXOR2(dv, dvl, av, avl, bv, bvl) do {                          \
-  mpw *_dv = (dv), *_dvl = (dvl);                                      \
-  const mpw *_av = (av), *_avl = (avl);                                        \
-  const mpw *_bv = (bv), *_bvl = (bvl);                                        \
-                                                                       \
-  while (_av < _avl || _bv < _bvl) {                                   \
-    mpw _a, _b;                                                                \
-    _a = (_av < _avl) ? *_av++ : 0;                                    \
-    _b = (_bv < _bvl) ? *_bv++ : 0;                                    \
-    *_dv++ = _a ^ _b;                                                  \
-  }                                                                    \
-  while (_dv < _dvl)                                                   \
-    *_dv++ = 0;                                                                \
-} while (0)
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/key-attr.c b/key-attr.c
deleted file mode 100644 (file)
index b6a3616..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Key attribute manipulation
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <mLib/dstr.h>
-#include <mLib/sym.h>
-
-#include "key.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @key_chkident@ --- *
- *
- * Arguments:  @const char *p@ = pointer to a type string
- *
- * Returns:    Zero if OK, -1 on error.
- *
- * Use:                Checks whether an identification component string is OK.
- */
-
-int key_chkident(const char *p)
-{
-  if (!p || !*p || strlen(p) > 255)
-    return (-1);
-  while (*p) {
-    if (*p == ':' || *p == '.' || isspace((unsigned char)*p))
-      return (-1);
-    p++;
-  }
-  return (0);
-}
-
-/* --- @key_chkcomment@ --- *
- *
- * Arguments:  @const char *p@ = pointer to a comment string
- *
- * Returns:    Zero if OK, -1 on error.
- *
- * Use:                Checks whether a comment string is OK.
- */
-
-int key_chkcomment(const char *p)
-{
-  if (!p)
-    return (0);
-  if (!*p)
-    return (-1);
-  while (*p) {
-    if (*p == '\n')
-      return (-1);
-    p++;
-  }
-  return (0);
-}
-
-/* --- @key_mkattriter@ --- *
- *
- * Arguments:  @key_attriter *i@ = pointer to attribute iterator
- *             @key *k@ = pointer to key
- *
- * Returns:    ---
- *
- * Use:                Initializes an attribute iterator.  The attributes are
- *             returned by @key_nextattr@.
- */
-
-void key_mkattriter(key_attriter *i, key *k)
-{
-  sym_mkiter(&i->i, &k->a);
-}
-
-/* --- @key_nextattr@ --- *
- *
- * Arguments:  @key_attriter *i@ = pointer to attribute iterator
- *             @const char **n, **v@ = pointers to name and value
- *
- * Returns:    Zero if no attribute available, or nonzero if returned OK.
- *
- * Use:                Returns the next attribute.
- */
-
-int key_nextattr(key_attriter *i, const char **n, const char **v)
-{
-  key_attr *a = sym_next(&i->i);
-  if (!a)
-    return (0);
-  if (n) *n = SYM_NAME(a);
-  if (v) *v = a->p;
-  return (1);
-}
-
-/* --- @key_getattr@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file
- *             @key *k@ = pointer to key
- *             @const char *n@ = pointer to attribute name
- *
- * Returns:    Pointer to attribute value, or null if not found.
- *
- * Use:                Returns the value of a key attribute.
- */
-
-const char *key_getattr(key_file *f, key *k, const char *n)
-{
-  key_attr *a;
-  if ((a = sym_find(&k->a, n, -1, 0, 0)) == 0)
-    return (0);
-  return (a->p);
-}
-
-/* --- @key_putattr@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file
- *             @key *k@ = pointer to key
- *             @const char *n@ = pointer to attribute name
- *             @const char *v@ = pointer to attribute value or null
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Inserts an attribute on a key.  If an attribute with the same
- *             name already exists, it is deleted.  Setting a null value
- *             removes the attribute.
- */
-
-int key_putattr(key_file *f, key *k, const char *n, const char *v)
-{
-  key_attr *a;
-  unsigned found;
-
-  if (!(f->f & KF_WRITE))
-    return (KERR_READONLY);
-  if (strlen(n) > 255)
-    return (KERR_BADATTR);
-
-  if (v) {
-    a = sym_find(&k->a, n, -1, sizeof(*a), &found);
-    if (found)
-      xfree(a->p);
-    a->p = xstrdup(v);
-  } else if ((a = sym_find(&k->a, n, -1, 0, 0)) != 0) {
-    xfree(a->p);
-    sym_remove(&k->a, a);
-  }
-
-  f->f |= KF_MODIFIED;
-  return (0);
-}
-
-/* --- @key_setkeydata@ --- *
- *
- * Arguments:  @key_file *kf@ = pointer to key file
- *             @key *k@ = pointer to key
- *             @key_data *kd@ = new key data
- *
- * Returns:    Zero on success, or a @KERR_@ error code on failure.
- *
- * Use:                Sets the key data for a key.
- */
-
-int key_setkeydata(key_file *kf, key *k, key_data *kd)
-{
-  if (!(kf->f & KF_WRITE))
-    return (KERR_READONLY);
-  key_incref(kd);
-  key_drop(k->k);
-  k->k = kd;
-  kf->f |= KF_MODIFIED;
-  return (0);
-}
-
-/* --- @key_setcomment@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *             @key *k@ = pointer to key block
- *             @const char *c@ = pointer to comment to set, or zero
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Replaces the key's current comment with a new one.
- */
-
-int key_setcomment(key_file *f, key *k, const char *c)
-{
-  if (!(f->f & KF_WRITE))
-    return (KERR_READONLY);
-  if (key_chkcomment(c))
-    return (KERR_BADCOMMENT);
-  if (k->c)
-    xfree(k->c);
-  if (c)
-    k->c = xstrdup(c);
-  else
-    k->c = 0;
-  f->f |= KF_MODIFIED;
-  return (0);
-}
-
-/* --- @key_settag@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *             @key *k@ = pointer to key block
- *             @const char *tag@ = pointer to comment to set, or zero
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Replaces the key's current tag with a new one.
- */
-
-int key_settag(key_file *f, key *k, const char *tag)
-{
-  key_ref *kr;
-  unsigned found;
-
-  if (!(f->f & KF_WRITE))
-    return (KERR_READONLY);
-
-  /* --- Make sure the tag is OK --- */
-
-  if (tag && key_chkident(tag))
-    return (KERR_BADTAG);
-
-  /* --- See if the new tag is the same as the old one --- */
-
-  if ((!tag && !k->tag) ||
-      (tag && k->tag && strcmp(tag, k->tag) == 0))
-    return (0);
-
-  /* --- Allocate an entry for the new tag --- */
-
-  if (tag) {
-    kr = sym_find(&f->bytag, tag, -1, sizeof(*kr), &found);
-    if (found && !KEY_EXPIRED(time(0), kr->k->del))
-      return (KERR_DUPTAG);
-    kr->k = k;
-  }
-
-  /* --- Remove any existing tag --- */
-
-  if (k->tag) {
-    kr = sym_find(&f->bytag, k->tag, -1, 0, 0);
-    assert(((void)"No bytag link", kr));
-    sym_remove(&f->bytag, kr);
-    xfree(k->tag);
-  }
-
-  /* --- Done --- */
-
-  f->f |= KF_MODIFIED;
-  if (tag)
-    k->tag = xstrdup(tag);
-  else
-    k->tag = 0;
-  return (0);
-}
-
-/* --- @key_fulltag@ --- *
- *
- * Arguments:  @key *k@ = pointer to key
- *             @dstr *d@ = pointer to destination string
- *
- * Returns:    ---
- *
- * Use:                Emits the key's full tag, which has the form
- *             `ID:TYPE[:TAG]'.  This is used in the textual file format,
- *             and to identify passphrases for locked keys.
- */
-
-void key_fulltag(key *k, dstr *d)
-{
-  dstr_putf(d, "%08lx:%s", (unsigned long)k->id, k->type);
-  if (k->tag)
-    dstr_putf(d, ":%s", k->tag);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-binary.c b/key-binary.c
deleted file mode 100644 (file)
index c1ef53b..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Key binary encoding
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-#include <mLib/sub.h>
-#include <mLib/sym.h>
-
-#include "key-data.h"
-#include "mp.h"
-#include "mptext.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @key_decode@ --- *
- *
- * Arguments:  @const void *p@ = pointer to buffer to read
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    The newly-read key data, or null if it failed.
- *
- * Use:                Decodes a binary representation of a key.
- */
-
-key_data *key_decode(const void *p, size_t sz)
-{
-  const octet *q = p;
-  size_t psz;
-  key_data *kd;
-  unsigned e;
-
-  /* --- Parse the header information --- *
-   *
-   * Make sure the size matches external reality.  Security holes have been
-   * known to creep in without this sort of check.  (No, this isn't an after-
-   * the-fact patch-up.)
-   */
-
-  e = LOAD16(q);
-  psz = LOAD16(q + 2);
-  if (psz + 4 > sz)
-    return (0);
-
-  /* --- Now decide what to do --- */
-
-  switch (e & KF_ENCMASK) {
-
-    /* --- Plain binary data --- */
-
-    case KENC_BINARY:
-    case KENC_ENCRYPT:
-      kd = key_newbinary(e, q + 4, psz);
-      break;
-
-    /* --- Multiprecision integer data --- */
-
-    case KENC_MP:
-      kd = key_newmp(e, mp_loadb(e & KF_BURN ? MP_NEWSEC : MP_NEW,
-                                q + 4, psz));
-      break;
-
-    /* --- String data --- */
-
-    case KENC_STRING:
-      kd = key_newraw(e);
-      kd->u.p = xmalloc(sz + 1);
-      memcpy(kd->u.p, q + 4, sz);
-      kd->u.p[sz] = 0;
-      break;
-
-    /* --- Elliptic curve point data --- */
-
-    case KENC_EC: {
-      size_t xsz, ysz;
-      kd = key_newraw(e);
-      EC_CREATE(&kd->u.e);
-      if (!sz) break;
-      if (sz < 2) return (0);
-      xsz = LOAD16(q + 4);
-      if (sz < xsz + 4) return (0);
-      ysz = LOAD16(q + 6 + xsz);
-      if (sz < xsz + ysz + 4) return (0);
-      kd->u.e.x = mp_loadb(MP_NEW, q + 6, xsz);
-      kd->u.e.y = mp_loadb(MP_NEW, q + 8 + xsz, ysz);
-    } break;
-
-    /* --- Structured key data --- */
-
-    case KENC_STRUCT: {
-      dstr d = DSTR_INIT;
-      key_data *nkd;
-
-      if ((e & ~KF_ENCMASK) || (psz & 3))
-       return (0);
-      q += 4;
-      kd = key_newstruct();
-
-      while (psz) {
-
-       /* --- Read the tag string --- */
-
-       DRESET(&d);
-       sz = LOAD8(q);
-       if (sz >= psz)
-         goto fail;
-       DPUTM(&d, q + 1, sz);
-       DPUTZ(&d);
-       sz = (sz + 4) & ~3;
-       q += sz; psz -= sz;
-
-       /* --- Read the encoding and size --- */
-
-       sz = (LOAD16(q + 2) + 7) & ~3;
-       if (sz > psz)
-         goto fail;
-
-       /* --- Create a table node and fill it in --- */
-
-       if ((nkd = key_decode(q, sz)) == 0)
-         goto fail;
-       key_structsteal(kd, d.buf, nkd);
-       psz -= sz;
-       q += sz;
-      }
-      dstr_destroy(&d);
-      break;
-
-      /* --- Tidy up after a failure --- */
-
-    fail:
-      dstr_destroy(&d);
-      key_drop(kd);
-      return (0);
-    } break;
-
-    /* --- Everything else --- */
-
-    default:
-      return (0);
-  }
-
-  /* --- OK, that was good --- */
-
-  kd->e = e;
-  return (kd);
-}
-
-/* --- @key_encode@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @dstr *d@ = pointer to destination string
- *             @const key_filter *kf@ = pointer to key selection block
- *
- * Returns:    Nonzero if an item was actually written.
- *
- * Use:                Encodes a key block as binary data.
- */
-
-static int ksbyname(const void *a, const void *b) {
-  key_struct *const *x = a, *const *y = b;
-  return (strcmp(SYM_NAME(*x), SYM_NAME(*y)));
-}
-
-int key_encode(key_data *k, dstr *d, const key_filter *kf)
-{
-  int rc = 0;
-  if (!KEY_MATCH(k, kf))
-    return (0);
-  switch (k->e & KF_ENCMASK) {
-    case KENC_BINARY:
-    case KENC_ENCRYPT: {
-      char *p;
-
-      DENSURE(d, (k->u.k.sz + 7) & ~3);
-      p = d->buf + d->len;
-      STORE16(p, k->e);
-      STORE16(p + 2, k->u.k.sz);
-      d->len += 4;
-      DPUTM(d, k->u.k.k, k->u.k.sz);
-      rc = 1;
-    } break;
-
-    case KENC_MP: {
-      char *p;
-      size_t sz = mp_octets(k->u.m);
-
-      DENSURE(d, (sz + 7) & ~3);
-      p = d->buf + d->len;
-      STORE16(p, k->e);
-      STORE16(p + 2, sz);
-      mp_storeb(k->u.m, p + 4, sz);
-      d->len += sz + 4;
-      rc = 1;
-    } break;
-
-    case KENC_STRING: {
-      char *p;
-      size_t sz = strlen(k->u.p);
-
-      DENSURE(d, (sz + 7) & ~3);
-      p = d->buf + d->len;
-      STORE16(p, k->e);
-      STORE16(p + 2, sz);
-      memcpy(p + 4, k->u.p, sz);
-      d->len += sz + 4;
-      rc = 1;
-    } break;
-
-    case KENC_EC: {
-      char *p;
-      size_t xsz = 0, ysz = 0;
-      size_t sz;
-
-      if (EC_ATINF(&k->u.e))
-       sz = 0;
-      else {
-       xsz = mp_octets(k->u.e.x);
-       ysz = mp_octets(k->u.e.y);
-       sz = xsz + ysz + 4;
-      }
-      DENSURE(d, (sz + 7) & ~3);
-      p = d->buf + d->len;
-      STORE16(p, k->e);
-      STORE16(p + 2, sz);
-      if (!EC_ATINF(&k->u.e)) {
-       STORE16(p + 4, xsz);
-       mp_storeb(k->u.e.x, p + 6, xsz);
-       STORE16(p + 6 + xsz, ysz);
-       mp_storeb(k->u.e.y, p + 8 + xsz, ysz);
-      }
-      d->len += sz + 4;
-      rc = 1;
-    } break;
-
-    case KENC_STRUCT: {
-      size_t n;
-      char *p;
-      key_struct *ks, **ksv;
-      size_t nks, j;
-      sym_iter i;
-
-      n = d->len;
-      DENSURE(d, 4);
-      p = d->buf + n;
-      STORE16(p, k->e & KF_ENCMASK);
-      d->len += 4;
-
-      for (nks = 0, sym_mkiter(&i, &k->u.s);
-          (ks = sym_next(&i)) != 0;
-          nks++);
-      if (nks) {
-       ksv = xmalloc(nks * sizeof(*ksv));
-       for (j = 0, sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; j++)
-         ksv[j] = ks;
-       qsort(ksv, nks, sizeof(*ksv), ksbyname);
-       for (j = 0; j < nks; j++) {
-         size_t o = d->len;
-         ks = ksv[j];
-         DENSURE(d, 1);
-         *(octet *)(d->buf + d->len++) = strlen(SYM_NAME(ks));
-         DPUTS(d, SYM_NAME(ks));
-         while (d->len & 3)
-           DPUTC(d, 0);
-         if (key_encode(ks->k, d, kf))
-           rc = 1;
-         else
-           d->len = o;
-       }
-       xfree(ksv);
-      }
-      if (!rc)
-       d->len = n;
-      else {
-       p = d->buf + n + 2;
-       n = d->len - n - 4;
-       STORE16(p,  n);
-      }
-    } break;
-  }
-  while (d->len & 3)
-    DPUTC(d, 0);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-data.c b/key-data.c
deleted file mode 100644 (file)
index 69795fe..0000000
+++ /dev/null
@@ -1,469 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Encoding and decoding of key data
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/base64.h>
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-#include <mLib/sub.h>
-#include <mLib/sym.h>
-
-#include "key-data.h"
-#include "mp.h"
-#include "mptext.h"
-
-/*----- Reference counting stuff ------------------------------------------*/
-
-/* --- @key_incref@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data
- *
- * Returns:    ---
- *
- * Use:                Increments the refcount on a key data block.
- */
-
-void key_incref(key_data *k) { KEY_INCREF(k); }
-
-/* --- @key_destroy@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data to destroy
- *
- * Returns:    ---
- *
- * Use:                Destroys a block of key data, regardless of reference count.
- *             Don't use this unless you know what you're doing.
- */
-
-void key_destroy(key_data *k)
-{
-  switch (k->e & KF_ENCMASK) {
-    case KENC_BINARY:
-    case KENC_ENCRYPT:
-      if (k->u.k.k) {
-       if (k->e & KF_BURN)
-         memset(k->u.k.k, 0, k->u.k.sz);
-       sub_free(k->u.k.k, k->u.k.sz);
-      }
-      break;
-    case KENC_MP:
-      mp_drop(k->u.m);
-      break;
-    case KENC_STRING:
-      xfree(k->u.p);
-      break;
-    case KENC_EC:
-      EC_DESTROY(&k->u.e);
-      break;
-    case KENC_STRUCT: {
-      key_data *kd;
-      key_subkeyiter i;
-
-      for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &kd); )
-       KEY_DROP(kd);
-      sym_destroy(&k->u.s);
-    } break;
-    default:
-      abort();
-  }
-  DESTROY(k);
-}
-
-/* --- @key_drop@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data to destroy
- *
- * Returns:    ---
- *
- * Use:                Drops a reference to key data, destroying it if necessary.
- */
-
-void key_drop(key_data *k) { KEY_DROP(k); }
-
-/* --- @key_split@ --- *
- *
- * Arguments:  @key_data **kk@ = address of pointer to key data block
- *
- * Returns:    ---
- *
- * Use:                Replaces @*kk@ with a pointer to the same key data, but with
- *             just one reference.
- */
-
-void key_split(key_data **kk)
-{
-  key_data *k = *kk;
-
-  if (k->ref == 1)
-    return;
-  switch (k->e & KF_ENCMASK) {
-    case KENC_BINARY:
-      *kk = key_newbinary(k->e, k->u.k.k, k->u.k.sz);
-      break;
-    case KENC_ENCRYPT:
-      *kk = key_newencrypted(k->e, k->u.k.k, k->u.k.sz);
-      break;
-    case KENC_MP:
-      *kk = key_newmp(k->e, k->u.m);
-      break;
-    case KENC_STRING:
-      *kk = key_newstring(k->e, k->u.p);
-      break;
-    case KENC_EC:
-      *kk = key_newec(k->e, &k->u.e);
-      break;
-    case KENC_STRUCT: {
-      key_subkeyiter i;
-      const char *tag;
-      key_data *kd;
-
-      *kk = key_newstruct();
-      for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); )
-       key_structset(*kk, tag, kd);
-    } break;
-    default:
-      abort();
-  }
-}
-
-/*----- Setting new values ------------------------------------------------*/
-
-/* --- @key_newraw@ --- *
- *
- * Arguments:  @unsigned e@ = encoding type to set
- *
- * Returns:    New key block, not filled in.
- */
-
-key_data *key_newraw(unsigned e)
-{
-  key_data *k = CREATE(key_data);
-  k->e = e;
-  k->ref = 1;
-  return (k);
-}
-
-/* --- @key_newbinary@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @const void *p@ = pointer to key data
- *             @size_t sz@ = size of the key data
- *
- * Returns:    New key data object.
- */
-
-key_data *key_newbinary(unsigned e, const void *p, size_t sz)
-{
-  key_data *k = key_newraw(KENC_BINARY | e);
-  k->u.k.k = sub_alloc(sz);
-  memcpy(k->u.k.k, p, sz);
-  k->u.k.sz = sz;
-  return (k);
-}
-
-/* --- @key_newencrypted@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @const void *p@ = pointer to key data
- *             @size_t sz@ = size of the key data
- *
- * Returns:    New key data object.
- */
-
-key_data *key_newencrypted(unsigned e, const void *p, size_t sz)
-{
-  key_data *k = key_newraw(KENC_ENCRYPT | e);
-  k->u.k.k = sub_alloc(sz);
-  memcpy(k->u.k.k, p, sz);
-  k->u.k.sz = sz;
-  return (k);
-}
-
-/* --- @key_newmp@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @mp *m@ = pointer to the value to set
- *
- * Returns:    New key data object.
- */
-
-key_data *key_newmp(unsigned e, mp *m)
-{
-  key_data *k = key_newraw(KENC_MP | e);
-  k->u.m = MP_COPY(m);
-  return (k);
-}
-
-/* --- @key_newstring@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @const char *p@ = pointer to the value to set
- *
- * Returns:    New key data object.
- */
-
-key_data *key_newstring(unsigned e, const char *p)
-{
-  key_data *k = key_newraw(KENC_STRING | e);
-  k->u.p = xstrdup(p);
-  return (k);
-}
-
-/* --- @key_newec@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @const ec *pt@ = pointer to the value to set
- *
- * Returns:    New key data object.
- */
-
-key_data *key_newec(unsigned e, const ec *pt)
-{
-  key_data *k = key_newraw(KENC_EC | e);
-  EC_CREATE(&k->u.e);
-  EC_COPY(&k->u.e, pt);
-  return (k);
-}
-
-/* --- @key_newstruct@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    New key data object.
- */
-
-key_data *key_newstruct(void)
-{
-  key_data *k = key_newraw(KENC_STRUCT);
-  sym_create(&k->u.s);
-  return (k);
-}
-
-/* --- @key_structfind@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const char *tag@ = pointer to tag string
- *
- * Returns:    Pointer to key data block, or null.
- *
- * Use:                Looks up the tag in a structured key.
- */
-
-key_data *key_structfind(key_data *k, const char *tag)
-{
-  key_struct *ks;
-  assert(((void)"Key is not structured",
-         (k->e & KF_ENCMASK) == KENC_STRUCT));
-  ks = sym_find(&k->u.s, tag, -1, 0, 0);
-  if (!ks)
-    return (0);
-  return (ks->k);
-}
-
-/* --- @key_mksubkeyiter@ --- *
- *
- * Arguments:  @key_subkeyiter *i@ = pointer to iterator block
- *             @key_data *k@ = pointer to key data block
- *
- * Returns:    ---
- *
- * Use:                Initializes a subkey iterator.
- */
-
-void key_mksubkeyiter(key_subkeyiter *i, key_data *k)
-{
-  assert(((void)"Key is not structured",
-         (k->e & KF_ENCMASK) == KENC_STRUCT));
-  sym_mkiter(&i->i, &k->u.s);
-}
-
-/* --- @key_nextsubkey@ --- *
- *
- * Arguments:  @key_structiter *i@ = pointer to iterator block
- *             @const char **tag@ = where to put the tag pointer, or null
- *             @key_data **kd@ = where to put the key data pointer, or null
- *
- * Returns:    Nonzero if there was another item, zero if we hit the
- *             end-stop.
- *
- * Use:                Collects the next subkey of a structured key.
- */
-
-int key_nextsubkey(key_subkeyiter *i, const char **tag, key_data **kd)
-{
-  key_struct *ks;
-
-  if ((ks = sym_next(&i->i)) == 0)
-    return (0);
-  if (tag) *tag = SYM_NAME(ks);
-  if (kd) *kd = ks->k;
-  return (1);
-}
-
-/* --- @key_structset@, @key_structsteal@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const char *tag@ = pointer to tag string
- *             @key_data *kd@ = new key data to store
- *
- * Returns:    ---
- *
- * Use:                Creates a new subkey.  Stealing doesn't affect @kd@'s
- *             refcount.  If @kd@ is null, the subkey is deleted.
- */
-
-static void structset(key_data *k, int stealp,
-                     const char *tag, key_data *kd)
-{
-  key_struct *ks;
-  unsigned f;
-
-  assert(((void)"Key is not structured", k->e == KENC_STRUCT));
-  assert(((void)"Key has multiple references", k->ref == 1));
-  if (!kd) {
-    ks = sym_find(&k->u.s, tag, -1, 0, 0);
-    if (ks) sym_remove(&k->u.s, ks);
-  } else {
-    ks = sym_find(&k->u.s, tag, -1, sizeof(*ks), &f);
-    if (f)
-      key_drop(ks->k);
-    if (!stealp) KEY_INCREF(kd);
-    ks->k = kd;
-  }
-}
-
-void key_structset(key_data *k, const char *tag, key_data *kd)
-  { structset(k, 0, tag, kd); }
-void key_structsteal(key_data *k, const char *tag, key_data *kd)
-  { structset(k, 1, tag, kd); }
-
-/*----- Miscellaneous operations ------------------------------------------*/
-
-/* --- @key_do@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const key_filter *kf@ = pointer to filter block
- *             @dstr *d@ = pointer to base string
- *             @int (*func)(key_data *kd, dstr *d, void *p@ = function
- *             @void *p@ = argument to function
- *
- * Returns:    Nonzero return code from function, or zero.
- *
- * Use:                Runs a function over all the leaves of a key.
- */
-
-int key_do(key_data *k, const key_filter *kf, dstr *d,
-          int (*func)(key_data */*kd*/, dstr */*d*/, void */*p*/),
-          void *p)
-{
-  if (!KEY_MATCH(k, kf))
-    return (0);
-  if ((k->e & KF_ENCMASK) != KENC_STRUCT)
-    return (func(k, d, p));
-  else {
-    key_subkeyiter i;
-    const char *tag;
-    size_t n = 0;
-    int rc;
-
-    if (d)
-      n = d->len;
-    for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
-      if (d) {
-       d->len = n;
-       dstr_putf(d, ".%s", tag);
-      }
-      if ((rc = key_do(k, kf, d, func, p)) != 0)
-       return (rc);
-    }
-    return (0);
-  }
-}
-
-/* --- @key_copydata@ --- *
- *
- * Arguments:  @key_data *k@ = key data to copy
- *             @const key_filter *kf@ = pointer to filter block
- *
- * Returns:    Pointer to a copy of the data, or null if the root subkey
- *             didn't match the filter.
- *
- * Use:                Copies a chunk of key data.  Subkeys, whether they're
- *             structured or leaves, which don't match the filter aren't
- *             copied.  The copy may or may not have structure in common
- *             with the original.
- */
-
-static int structmatchp(key_data *k, const key_filter *kf)
-{
-  key_subkeyiter i;
-
-  if (!KEY_MATCH(k, kf)) return (0);
-  else if ((k->e & KF_ENCMASK) == KENC_STRUCT) return (1);
-  else {
-    for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &k); )
-      if (!structmatchp(k, kf)) return (0);
-    return (1);
-  }
-}
-
-key_data *key_copydata(key_data *k, const key_filter *kf)
-{
-  key_subkeyiter i;
-  const char *tag;
-  key_data *kd, *kkd;
-
-  /* --- Trivial cases --- */
-
-  if (!KEY_MATCH(k, kf))
-    return (0);
-  else if (structmatchp(k, kf)) {
-    key_incref(k);
-    return (k);
-  }
-
-  /* --- Copy a structured key recursively --- */
-
-  kkd = key_newstruct();
-  for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
-    if ((kd = key_copydata(kd, kf)) != 0)
-      key_structsteal(kkd, tag, kd);
-  }
-
-  /* --- Done --- */
-
-  return (kkd);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-data.h b/key-data.h
deleted file mode 100644 (file)
index d6a5636..0000000
+++ /dev/null
@@ -1,594 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Manipulating key data
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_KEY_DATA_H
-#define CATACOMB_KEY_DATA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-#include <mLib/sym.h>
-
-#ifndef CATACOMB_KEY_ERROR_H
-#  include "key-error.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_EC_H
-#  include "ec.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- Key binary data --- */
-
-typedef struct key_bin {
-  octet *k;                            /* Pointer to key data */
-  size_t sz;                           /* Size of the key data (in bytes) */
-} key_bin;
-
-/* --- Key data structure --- */
-
-typedef struct key_data {
-  unsigned e;                          /* Encoding type for key data */
-  unsigned ref;                                /* Reference counter */
-  union {
-    key_bin k;                         /* Binary key data */
-    mp *m;                             /* Multiprecision integer */
-    sym_table s;                       /* Structured key data */
-    char *p;                           /* String pointer */
-    ec e;                              /* Elliptic curve point */
-  } u;
-} key_data;
-
-typedef struct key_struct {
-  sym_base _b;
-  key_data *k;
-} key_struct;
-
-typedef struct key_subkeyiter { sym_iter i; } key_subkeyiter;
-
-/* --- Packing and unpacking --- */
-
-typedef struct key_packdef {
-  unsigned e;                          /* Key data encoding type */
-  void *p;                             /* Pointer to the destination */
-  key_data *kd;                                /* Key data block */
-} key_packdef;
-
-typedef struct key_packstruct {
-  char *name;                          /* Pointer to name string */
-  key_packdef kp;                      /* Packing structure */
-} key_packstruct;
-
-/* --- Key binary encoding --- *
- *
- * The binary encoding consists of a header containing a 16-bit encoding type
- * and a 16-bit length, followed immediately by the key data, followed by
- * between zero and three zero bytes to make the total length a multiple of
- * four.  The format of the following data depends on the encoding type:
- *
- * @KENC_BINARY@       Binary data.
- *
- * @KENC_MP@           Octet array interpreted in big-endian byte order.
- *
- * @KENC_STRUCT@       An array of pairs, each containing a string (8-bit
- *                     length followed by data and zero-padding to 4-byte
- *                     boundary) and key binary encodings.
- *
- * @KENC_ENCRYPT@      Binary data, format
- */
-
-/* --- Key encoding methods and other flags--- */
-
-enum {
-
-  /* --- Bottom two bits are the encoding type --- */
-
-  KF_ENCMASK   = 0x83,                 /* Encoding mask */
-  KENC_BINARY  = 0x00,                 /* Plain binary key (@k@) */
-  KENC_MP      = 0x01,                 /* Multiprecision integer (@i@) */
-  KENC_STRUCT  = 0x02,                 /* Structured key data (@s@) */
-  KENC_ENCRYPT = 0x03,                 /* Encrypted key type (@k@) */
-  KENC_STRING  = 0x80,                 /* ASCII string (@p@) */
-  KENC_EC      = 0x81,                 /* Elliptic curve point (@e@) */
-
-  /* --- Key category bits --- */
-
-  KF_CATMASK   = 0x0c,                 /* Category mask */
-  KCAT_SYMM    = 0x00,                 /* Symmetric encryption key */
-  KCAT_PRIV    = 0x04,                 /* Private (asymmetric) key */
-  KCAT_PUB     = 0x08,                 /* Public (asymmetric) key */
-  KCAT_SHARE   = 0x0c,                 /* Shared (asymmetric) key */
-  KF_NONSECRET = 0x08,                 /* Bit flag for non-secret keys */
-
-  /* --- Other flags --- */
-
-  KF_BURN      = 0x10,                 /* Burn key after use */
-  KF_OPT       = 0x20,                 /* Optional key (for @key_unpack@) */
-
-  /* --- Tag end --- */
-
-  KENC_MAX                             /* Dummy limit constant */
-};
-
-/* --- Key locking return codes --- */
-
-#define KL_OK 0                                /* All good */
-#define KL_IOERR -1                    /* I/O problem (e.g., getting pp) */
-#define KL_KEYERR -2                   /* Wrong key supplied */
-#define KL_DATAERR -3                  /* Data format error */
-
-/* --- Key flag filtering --- */
-
-typedef struct key_filter {
-  unsigned f;
-  unsigned m;
-} key_filter;
-
-/* --- Matching aginst key selection --- */
-
-#define KEY_MATCH(kd, kf)                                              \
-  (!(kf) ||                                                            \
-   ((kd)->e & KF_ENCMASK) == KENC_STRUCT ||                            \
-   ((kd)->e & (kf)->m) == (kf)->f)
-
-/*----- Key flags and filtering -------------------------------------------*/
-
-/* --- @key_readflags@ --- *
- *
- * Arguments:  @const char *p@ = pointer to string to read
- *             @char **pp@ = where to store the end pointer
- *             @unsigned *ff@ = where to store the flags
- *             @unsigned *mm@ = where to store the mask
- *
- * Returns:    Zero if all went well, nonzero if there was an error.
- *
- * Use:                Reads a flag string.
- */
-
-extern int key_readflags(const char */*p*/, char **/*pp*/,
-                        unsigned */*ff*/, unsigned */*mm*/);
-
-/* --- @key_writeflags@ --- *
- *
- * Arguments:  @unsigned f@ = flags to write
- *             @dstr *d@ = pointer to destination string
- *
- * Returns:    ---
- *
- * Use:                Emits a flags word as a string representation.
- */
-
-extern void key_writeflags(unsigned /*f*/, dstr */*d*/);
-
-/* --- @key_match@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const key_filter *kf@ = pointer to filter block
- *
- * Returns:    Nonzero if the key matches the filter.
- *
- * Use:                Checks whether a key matches a filter.
- */
-
-extern int key_match(key_data */*k*/, const key_filter */*kf*/);
-
-/*----- Setting new key data ----------------------------------------------*/
-
-/* --- @key_newraw@ --- *
- *
- * Arguments:  @unsigned e@ = encoding type to set
- *
- * Returns:    New key block, not filled in.
- */
-
-extern key_data *key_newraw(unsigned /*e*/);
-
-/* --- @key_newbinary@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @const void *p@ = pointer to key data
- *             @size_t sz@ = size of the key data
- *
- * Returns:    New key data object.
- */
-
-extern key_data *key_newbinary(unsigned /*e*/,
-                              const void */*p*/, size_t /*sz*/);
-
-/* --- @key_newencrypted@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @const void *p@ = pointer to key data
- *             @size_t sz@ = size of the key data
- *
- * Returns:    New key data object.
- */
-
-extern key_data *key_newencrypted(unsigned /*e*/,
-                                 const void */*p*/, size_t /*sz*/);
-
-/* --- @key_newmp@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @mp *m@ = pointer to the value to set
- *
- * Returns:    New key data object.
- */
-
-extern key_data *key_newmp(unsigned /*e*/, mp */*m*/);
-
-/* --- @key_newstring@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @const char *p@ = pointer to the value to set
- *
- * Returns:    New key data object.
- */
-
-extern key_data *key_newstring(unsigned /*e*/, const char */*p*/);
-
-/* --- @key_newec@ --- *
- *
- * Arguments:  @unsigned e@ = other encoding flags
- *             @const ec *pt@ = pointer to the value to set
- *
- * Returns:    New key data object.
- */
-
-extern key_data *key_newec(unsigned /*e*/, const ec */*pt*/);
-
-/* --- @key_newstruct@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    New key data object.
- */
-
-extern key_data *key_newstruct(void);
-
-/* --- @key_structfind@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const char *tag@ = pointer to tag string
- *
- * Returns:    Pointer to key data block, or null.
- *
- * Use:                Looks up the tag in a structured key.
- */
-
-extern key_data *key_structfind(key_data */*k*/, const char */*tag*/);
-
-/* --- @key_mksubkeyiter@ --- *
- *
- * Arguments:  @key_subkeyiter *i@ = pointer to iterator block
- *             @key_data *k@ = pointer to key data block
- *
- * Returns:    ---
- *
- * Use:                Initializes a subkey iterator.
- */
-
-extern void key_mksubkeyiter(key_subkeyiter */*i*/, key_data */*k*/);
-
-/* --- @key_nextsubkey@ --- *
- *
- * Arguments:  @key_structiter *i@ = pointer to iterator block
- *             @const char **tag@ = where to put the tag pointer, or null
- *             @key_data **kd@ = where to put the key data pointer, or null
- *
- * Returns:    Nonzero if there was another item, zero if we hit the
- *             end-stop.
- *
- * Use:                Collects the next subkey of a structured key.
- */
-
-extern int key_nextsubkey(key_subkeyiter */*i*/,
-                         const char **/*tag*/, key_data **/*kd*/);
-
-/* --- @key_structset@, @key_structsteal@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const char *tag@ = pointer to tag string
- *             @key_data *kd@ = new key data to store
- *
- * Returns:    ---
- *
- * Use:                Creates a new subkey.  Stealing doesn't affect @kd@'s
- *             refcount.  If @kd@ is null, the subkey is deleted.
- */
-
-extern void key_structset(key_data */*k*/,
-                         const char */*tag*/, key_data */*kd*/);
-extern void key_structsteal(key_data */*k*/,
-                           const char */*tag*/, key_data */*kd*/);
-
-/* --- @key_split@ --- *
- *
- * Arguments:  @key_data **kk@ = address of pointer to key data block
- *
- * Returns:    ---
- *
- * Use:                Replaces @*kk@ with a pointer to the same key data, but with
- *             just one reference.
- */
-
-extern void key_split(key_data **/*kk*/);
-
-/*----- Miscellaneous operations ------------------------------------------*/
-
-/* --- @key_incref@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data
- *
- * Returns:    ---
- *
- * Use:                Increments the refcount on a key data block.
- */
-
-#define KEY_INCREF(k) ((k)->ref++)
-extern void key_incref(key_data */*k*/);
-
-/* --- @key_destroy@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data to destroy
- *
- * Returns:    ---
- *
- * Use:                Destroys a block of key data, regardless of reference count.
- *             Don't use this unless you know what you're doing.
- */
-
-extern void key_destroy(key_data */*k*/);
-
-/* --- @key_drop@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data to destroy
- *
- * Returns:    ---
- *
- * Use:                Drops a reference to key data, destroying it if necessary.
- */
-
-#define KEY_DROP(k) do {                                               \
-  key_data *_k = k;                                                    \
-  _k->ref--;                                                           \
-  if (_k->ref == 0)                                                    \
-    key_destroy(_k);                                                   \
-} while (0)
-
-extern void key_drop(key_data */*k*/);
-
-/* --- @key_do@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const key_filter *kf@ = pointer to filter block
- *             @dstr *d@ = pointer to base string
- *             @int (*func)(key_data *kd, dstr *d, void *p@ = function
- *             @void *p@ = argument to function
- *
- * Returns:    Nonzero return code from function, or zero.
- *
- * Use:                Runs a function over all the leaves of a key.
- */
-
-extern int key_do(key_data */*k*/, const key_filter */*kf*/, dstr */*d*/,
-                 int (*/*func*/)(key_data */*kd*/,
-                                 dstr */*d*/, void */*p*/),
-                 void */*p*/);
-
-/* --- @key_copydata@ --- *
- *
- * Arguments:  @key_data *k@ = key data to copy
- *             @const key_filter *kf@ = pointer to filter block
- *
- * Returns:    Pointer to a copy of the data, or null if the root subkey
- *             didn't match the filter.
- *
- * Use:                Copies a chunk of key data.  Subkeys, whether they're
- *             structured or leaves, which don't match the filter aren't
- *             copied.  The copy may or may not have structure in common
- *             with the original.
- */
-
-extern key_data *key_copydata(key_data */*k*/, const key_filter */*kf*/);
-
-/*----- Textual encoding --------------------------------------------------*/
-
-/* --- @key_read@ --- *
- *
- * Arguments:  @const char *p@ = pointer to textual key representation
- *             @char **pp@ = where to store the end pointer
- *
- * Returns:    The newly-read key data, or null if it failed.
- *
- * Use:                Parses a textual key description.
- */
-
-extern key_data *key_read(const char */*p*/, char **/*pp*/);
-
-/* --- @key_write@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data
- *             @dstr *d@ = destination string to write on
- *             @const key_filter *kf@ = pointer to key selection block
- *
- * Returns:    Nonzero if any items were actually written.
- *
- * Use:                Writes a key in a textual encoding.
- */
-
-extern int key_write(key_data */*k*/, dstr */*d*/, const key_filter */*kf*/);
-
-/*----- Key binary encoding -----------------------------------------------*/
-
-/* --- @key_decode@ --- *
- *
- * Arguments:  @const void *p@ = pointer to buffer to read
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    The newly-read key data, or null if it failed.
- *
- * Use:                Decodes a binary representation of a key.
- */
-
-extern key_data *key_decode(const void */*p*/, size_t /*sz*/);
-
-/* --- @key_encode@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @dstr *d@ = pointer to destination string
- *             @const key_filter *kf@ = pointer to key selection block
- *
- * Returns:    Nonzero if any items were actually written.
- *
- * Use:                Encodes a key block as binary data.
- */
-
-extern int key_encode(key_data */*k*/, dstr */*d*/,
-                     const key_filter */*kf*/);
-
-/*----- Packing and unpacking keys ----------------------------------------*/
-
-/* --- @key_pack@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *             @key_data **kd@ = where to put the key data pointer
- *             @dstr *d@ = pointer to tag string for the key data
- *
- * Returns:    Error code, or zero.
- *
- * Use:                Packs a key from a data structure.
- */
-
-extern int key_pack(key_packdef */*kp*/, key_data **/*kd*/, dstr */*d*/);
-
-/* --- @key_unpack@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *             @key_data *kd@ = pointer to source key data
- *             @dstr *d@ = pointer to tag string for the key data
- *
- * Returns:    Error code, or zero.
- *
- * Use:                Unpacks a key into an appropriate data structure.
- */
-
-extern int key_unpack(key_packdef */*kp*/, key_data */*kd*/, dstr */*d*/);
-
-/* --- @key_unpackdone@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing definition
- *
- * Returns:    ---
- *
- * Use:                Frees the key components contained within a packing
- *             definition, created during key unpacking.
- */
-
-extern void key_unpackdone(key_packdef */*kp*/);
-
-/*----- Key encryption ----------------------------------------------------*/
-
-/* --- @key_lock@ --- *
- *
- * Arguments:  @key_data **kt@ = where to store the destination pointer
- *             @key_data *k@ = source key data block or null to use @*kt@
- *             @const void *e@ = secret to encrypt key with
- *             @size_t esz@ = size of the secret
- *
- * Returns:    ---
- *
- * Use:                Encrypts a key data block using a secret.
- */
-
-extern void key_lock(key_data **/*kt*/, key_data */*k*/,
-                    const void */*e*/, size_t /*esz*/);
-
-/* --- @key_unlock@ --- *
- *
- * Arguments:  @key_data **kt@ = where to store the destination pointer
- *             @key_data *k@ = source key data block or null to use @*kt@
- *             @const void *e@ = secret to decrypt the block with
- *             @size_t esz@ = size of the secret
- *
- * Returns:    Zero for success, or a @KERR_@ error code.
- *
- * Use:                Unlocks a key using a secret.
- */
-
-extern int key_unlock(key_data **/*kt*/, key_data */*k*/,
-                     const void */*e*/, size_t /*esz*/);
-
-/* --- @key_plock@ --- *
- *
- * Arguments:  @key_data **kt@ = where to store the destination pointer
- *             @key_data *k@ = source key data block or null to use @*kt@
- *             @const char *tag@ = tag to use for passphrase
- *
- * Returns:    Zero if successful, a @KERR@ error code on failure.
- *
- * Use:                Locks a key by encrypting it with a passphrase.
- */
-
-extern int key_plock(key_data **/*kt*/, key_data */*k*/,
-                    const char */*tag*/);
-
-/* --- @key_punlock@ --- *
- *
- * Arguments:  @key_data **kt@ = where to store the destination pointer
- *             @key_data *k@ = source key data block or null to use @*kt@
- *             @const char *tag@ = tag to use for passphrase
- *
- * Returns:    Zero if successful, a @KERR@ error code on failure.
- *
- * Use:                Unlocks a passphrase-locked key.
- */
-
-extern int key_punlock(key_data **/*kt*/, key_data */*k*/,
-                      const char */*tag*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/key-error.c b/key-error.c
deleted file mode 100644 (file)
index cd7d386..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Translating key error codes into strings
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/macros.h>
-#include "key-error.h"
-
-/*----- Error reporting ---------------------------------------------------*/
-
-/* --- @key_strerror@ --- *
- *
- * Arguments:  @int err@ = error code from @key_new@
- *
- * Returns:    Pointer to error string.
- *
- * Use:                Translates a @KERR@ error code into a human-readable
- *             string.
- */
-
-const char *key_strerror(int err)
-{
-  static const char *const tab[] = {
-#define ENTRY(tag, num, str) str,
-    KEY_ERRORS(ENTRY)
-#undef ENTRY
-    "Unknown error code"
-  };
-
-  unsigned e = -err;
-  if (e >= N(tab))
-    e = N(tab) - 1;
- return (tab[e]);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-error.h b/key-error.h
deleted file mode 100644 (file)
index 2029a2b..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Key management error codes
- *
- * (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.
- */
-
-#ifndef CATACOMB_KEY_ERROR_H
-#define CATACOMB_KEY_ERROR_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Error codes -------------------------------------------------------*/
-
-#define KEY_ERRORS(_)                                                  \
-  _(OK,                  0, "No error")                                        \
-  _(BADTAG,     -1, "Bad tag string")                                  \
-  _(BADTYPE,    -2, "Bad type string")                                 \
-  _(BADCOMMENT,         -3, "Bad comment string")                              \
-  _(DUPID,      -4, "Key id already exists")                           \
-  _(DUPTAG,     -5, "Key tag already exists")                          \
-  _(READONLY,   -6, "Key file is read-only")                           \
-  _(WILLEXPIRE,         -7, "Key will eventually expire")                      \
-  _(EXPIRED,    -8, "Key has expired")                                 \
-  _(BADFLAGS,   -9, "Bad key flags string")                            \
-  _(BADPASS,   -10, "Failed to unlock key")                            \
-  _(WRONGTYPE, -11, "Unexpected key encoding type")                    \
-  _(NOTFOUND,  -12, "Key not found")                                   \
-  _(BADATTR,   -13, "Bad attribute name")                              \
-  _(MALFORMED, -14, "Malformed key data")                              \
-  _(IO,                -15, "I/O error")                                       \
-
-enum {
-#define ENTRY(tag, num, str) KERR_##tag = num,
-  KEY_ERRORS(ENTRY)
-#undef ENTRY
-  KERR__dummy
-};
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @key_strerror@ --- *
- *
- * Arguments:  @int err@ = error code from @key_new@
- *
- * Returns:    Pointer to error string.
- *
- * Use:                Translates a @KERR@ error code into a human-readable string.
- */
-
-extern const char *key_strerror(int /*err*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/key-fetch.c b/key-fetch.c
deleted file mode 100644 (file)
index 08a800b..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Higher-level key unpacking
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#include "key.h"
-#include "key-data.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @key_fetchinit@ --- *
- *
- * Arguments:  @const key_fetchdef *kf@ = pointer to base definition
- *             @key_packstruct *kps@ = pointer to destination packing def
- *             @void *p@ = pointer to destination block
- *
- * Returns:    Pointer to packing definition.
- *
- * Use:                Initializes a packing definition (@key_packdef@ structure).
- *             If @kps@ is null on entry, an appropriately sized block is
- *             allocated automatically.  Otherwise it must be large enough.
- */
-
-static size_t kfcount(const key_fetchdef *kf)
-{
-  size_t n = 1;
-  while (kf->name) {
-    n++;
-    if (kf->kf)
-      n += kfcount(kf->kf);
-    kf++;
-  }
-  return (n);
-}
-
-key_packdef *key_fetchinit(const key_fetchdef *kf,
-                          key_packstruct *kp, void *p)
-{
-  size_t n = 1 + kfcount(kf);
-  key_packdef *kpd;
-  key_packstruct *kps;
-  char *cp = p;
-
-  /* --- If @kps@ is null, count the entries and allocate --- */
-
-  if (kp)
-    kp->name = 0;
-  else {
-    kp = xmalloc(n * sizeof(*kp));
-    kp->name = (char *)kp;
-  }
-
-  /* --- Fill in the top part --- */
-
-  kp->kp.e = KENC_STRUCT;
-  kp->kp.p = &kp[1];
-  kp->kp.kd = 0;
-  kpd = &kp->kp;
-
-  /* --- Initialize for the main loop --- */
-
-  kps = kp + n;
-  n = 0;
-  kp++;
-
-  /* --- Iterate over the entries in the table --- *
-   *
-   * The end of the target block is used as a stack to record where
-   * substructure is meant to occur.  The integer @n@ is the depth of the
-   * stack; @kps@ is a full descending stack pointer.  The @kp.p@ member of a
-   * stack element points back to an entry with substructure, the @kp.p@
-   * member of which refers to the @kf@ table for the substructure.
-   *
-   * This should all be about as clear as mud.
-   */
-
-  for (;;) {
-
-    /* --- Blat out a level's worth --- */
-
-    while (kf->name) {
-      kp->name = kf->name;
-      kp->kp.e = kf->e;
-      kp->kp.kd = 0;
-      if ((kf->e & KF_ENCMASK) != KENC_STRUCT)
-       kp->kp.p = cp + kf->off;
-      else {
-       (--kps)->kp.p = kp;
-       kp->kp.p = (void *)kf->kf;
-       n++;
-      }
-      kf++;
-      kp++;
-    }
-    (kp++)->name = 0;
-    if (!n)
-      break;
-
-    /* --- Pop an entry from the stack --- */
-
-    {
-      key_packstruct *kkp = (kps++)->kp.p;
-      kf = kkp->kp.p;
-      kkp->kp.p = kp;
-      n--;
-    }
-  }
-
-  /* --- We're done --- */
-
-  return (kpd);
-}
-
-/* --- @key_fetch@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *             @key *k@ = key file containing desired key
- *
- * Returns:    Error code, or zero.
- *
- * Use:                Fetches an unpacked key from a packed one.
- */
-
-int key_fetch(key_packdef *kp, key *k)
-{
-  dstr d = DSTR_INIT;
-  int e;
-
-  key_fulltag(k, &d);
-  e = key_unpack(kp, k->k, &d);
-  dstr_destroy(&d);
-  return (e);
-}
-
-/* --- @key_fetchbyname@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *             @key_file *kf@ = key file containing desired key
- *             @const char *tag@ = user's tag describing the key
- *
- * Returns:    Error code, or zero.
- *
- * Use:                Fetches a named key from a key file and unpacks it
- *             conveniently.
- */
-
-int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag)
-{
-  dstr d = DSTR_INIT;
-  key_data **kd;
-  int e;
-
-  if (key_qtag(kf, tag, &d, 0, &kd))
-    e = KERR_NOTFOUND;
-  else
-    e = key_unpack(kp, *kd, &d);
-  dstr_destroy(&d);
-  return (e);
-}
-
-/* --- @key_fetchdone@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *
- * Returns:    ---
- *
- * Use:                Frees a packing structure.  If the structure was allocated by
- *             @key_fetchinit@ then it is freed.
- */
-
-void key_fetchdone(key_packdef *kp)
-{
-  key_packstruct *kps =
-    (key_packstruct *)(((char *)kp) - offsetof(key_packstruct, kp));
-  key_unpackdone(kp);
-  if (kps->name)
-    xfree(kps);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-file.c b/key-file.c
deleted file mode 100644 (file)
index 3245b93..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * System-dependent key filing operations
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <mLib/dstr.h>
-#include <mLib/lock.h>
-
-#include "key.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @fdcopy@ --- *
- *
- * Arguments:  @int source@ = source file descriptor
- *             @int dest@ = destination file descriptor
- *
- * Returns:    Zero if OK, nonzero otherwise.
- *
- * Use:                Copies data from one file descriptor to another.
- */
-
-static int fdcopy(int source, int dest)
-{
-  char buf[4096];
-  char *p;
-
-  if (lseek(source, 0, SEEK_SET) < 0||
-      lseek(dest, 0, SEEK_SET) < 0 ||
-      ftruncate(dest, 0) < 0)
-    return (-1);
-  for (;;) {
-    int n = read(source, buf, sizeof(buf));
-    if (n < 0)
-      return (-1);
-    else if (n == 0)
-      break;
-    p = buf;
-    while (n) {
-      int nn = write(dest, p, n);
-      if (nn < 0)
-       return (-1);
-      p += nn;
-      n -= nn;
-    }
-  }
-  return (0);
-}
-
-/* --- @key_save@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *
- * Returns:    A @KWRITE_@ code indicating how well it worked.
- *
- * Use:                Writes a key file's data back to the actual file.  This code
- *             is extremely careful about error handling.  It should usually
- *             be able to back out somewhere sensible, but it can tell when
- *             it's got itself into a real pickle and starts leaving well
- *             alone.
- *
- *             Callers, please make sure that you ring alarm bells when this
- *             function returns @KWRITE_BROKEN@.
- */
-
-int key_save(key_file *f)
-{
-  dstr n_older = DSTR_INIT, n_old = DSTR_INIT, n_new = DSTR_INIT;
-  int rc = KWRITE_FAIL;
-
-  if (!(f->f & KF_MODIFIED))
-    return (KWRITE_OK);
-  if (!f->fp)
-    return (KWRITE_FAIL);
-
-  /* --- Write a new key file out --- *
-   *
-   * Check for an error after each key line.  This ought to be enough.
-   * Checking after each individual byte write and @fprintf@ isn't much fun.
-   */
-
-  dstr_putf(&n_new, "%s.new", f->name);
-
-  {
-    key *k;
-    key_iter i;
-    FILE *fp;
-
-    if ((fp = fopen(n_new.buf, "w")) == 0)
-      goto fail_open;
-
-    for (key_mkiter(&i, f); (k = key_next(&i)) != 0; ) {
-      if (key_extract(f, k, fp, 0)) {
-       fclose(fp);
-       goto fail_write;
-      }
-    }
-
-    if (fclose(fp))
-      goto fail_write;
-  }
-
-  /* --- Set up the other filenames --- */
-
-  dstr_putf(&n_older, "%s.older", f->name);
-  dstr_putf(&n_old, "%s.old", f->name);
-
-  /* --- Move the current backup on one --- *
-   *
-   * If the `older' file exists, then we're in need of attention.
-   */
-
-  {
-    struct stat st;
-    if (stat(n_older.buf, &st) == 0 || errno != ENOENT) {
-      errno = EEXIST;
-      rc = KWRITE_BROKEN;
-      goto fail_shift;
-    }
-    if (rename(n_old.buf, n_older.buf) && errno != ENOENT)
-      goto fail_shift;
-  }
-
-  /* --- Copy the current file to the backup --- */
-
-  {
-    int fd;
-    if ((fd = open(n_old.buf, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0)
-      goto fail_backup;
-    if (fdcopy(fileno(f->fp), fd)) {
-      close(fd);
-      goto fail_backup;
-    }
-    if (close(fd))
-      goto fail_backup;
-  }
-
-  /* --- Copy the newly created file to the current one --- *
-   *
-   * This is the dangerous bit.
-   */
-
-  {
-    int fd;
-    if ((fd = open(n_new.buf, O_RDONLY)) < 0)
-      goto fail_update;
-    if (fdcopy(fd, fileno(f->fp))) {
-      close(fd);
-      goto fail_update;
-    }
-    close(fd);
-    if (fsync(fileno(f->fp)))
-      goto fail_update;
-  }
-
-  /* --- Clean up --- *
-   *
-   * Remove the `new' file and the `older' backup.  Then we're done.
-   */
-
-  unlink(n_new.buf);
-  unlink(n_older.buf);
-  dstr_destroy(&n_new);
-  dstr_destroy(&n_old);
-  dstr_destroy(&n_older);
-  return (KWRITE_OK);
-
-  /* --- Failure while writing the new key file --- *
-   *
-   * I need to copy the backup back.  If that fails then I'm really stuffed.
-   * If not, then I might as well try to get the backups sorted back out
-   * again.
-   */
-
-fail_update:
-  {
-    int fd;
-    int e = errno;
-
-    if ((fd = open(n_old.buf, O_RDONLY)) < 0)
-      rc = KWRITE_BROKEN;
-    else if (fdcopy(fd, fileno(f->fp))) {
-      close(fd);
-      rc = KWRITE_BROKEN;
-    } else {
-      close(fd);
-      if (fsync(fileno(f->fp)))
-       rc = KWRITE_BROKEN;
-    }
-
-    errno = e;
-    if (rc == KWRITE_BROKEN)
-      goto fail_shift;
-  }
-  /* Now drop through */
-
-  /* --- Failure while writing the new backup --- *
-   *
-   * The new backup isn't any use.  Try to recover the old one.
-   */
-
-fail_backup:
-  {
-    int e = errno;
-    unlink(n_old.buf);
-    if (rename(n_older.buf, n_old.buf) && errno != ENOENT)
-      rc = KWRITE_BROKEN;
-    errno = e;
-  }
-  /* Now drop through */
-
-  /* --- Failure while demoting the current backup --- *
-   *
-   * Leave the completed output file there for the operator in case he wants
-   * to clean up.
-   */
-
-fail_shift:
-  dstr_destroy(&n_new);
-  dstr_destroy(&n_old);
-  dstr_destroy(&n_older);
-  return (rc);
-
-  /* --- Failure during write of new data --- *
-   *
-   * Clean up the new file and return.  These errors can never cause
-   * breakage.
-   */
-
-fail_write:
-  unlink(n_new.buf);
-fail_open:
-  dstr_destroy(&n_new);
-  return (rc);
-}
-
-/* --- @key_lockfile@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure to initialize
- *             @const char *file@ = pointer to the file name
- *             @unsigned how@ = opening options (@KOPEN_*@).
- *
- * Returns:    Zero if it worked, nonzero otherwise.
- *
- * Use:                Opens a keyfile and stores the information needed for
- *             continued access in the structure.
- *
- *             If the file is opened with @KOPEN_WRITE@, it's created if
- *             necessary with read and write permissions for owner only, and
- *             locked for update while it's open.
- *
- *             This is a system-dependent routine, and only really intended
- *             for the private use of @key_open@.
- */
-
-int key_lockfile(key_file *f, const char *file, unsigned how)
-{
-  int of, lf;
-  const char *ff;
-  int fd;
-
-  /* --- Handle the magic no-file option --- */
-
-  if (how & KOPEN_NOFILE) {
-    f->fp = 0;
-    return (0);
-  }
-
-  /* --- Lots of things depend on whether we're writing --- */
-
-  switch (how & KOPEN_MASK) {
-    case KOPEN_READ:
-      of = O_RDONLY;
-      lf = LOCK_NONEXCL;
-      ff = "r";
-      break;
-    case KOPEN_WRITE:
-      of = O_RDWR | O_CREAT;
-      lf = LOCK_EXCL;
-      ff = "r+";
-      break;
-    default:
-      errno = EINVAL;
-      return (-1);
-  }
-
-  /* --- Open and lock the file --- */
-
-  if ((fd = open(file, of, 0600)) < 0)
-    return (-1);
-  if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 ||
-      lock_file(fd, lf) < 0 ||
-      (f->fp = fdopen(fd, ff)) == 0) {
-    close(fd);
-    return (-1);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-flags.c b/key-flags.c
deleted file mode 100644 (file)
index a547898..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Reading and writing key flag strings
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-
-#include "key-data.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct key_flags {
-  unsigned f;
-  unsigned m;
-} key_flags;
-
-/*----- Flags table -------------------------------------------------------*/
-
-typedef struct flagent {
-  const char *name;
-  unsigned f;
-  unsigned m;
-} flagent;
-
-static const flagent flagtab[] = {
-
-  /* --- Encoding types --- */
-
-  { "binary",          KENC_BINARY,    KF_ENCMASK },
-  { "integer",         KENC_MP,        KF_ENCMASK },
-  { "struct",          KENC_STRUCT,    KF_ENCMASK },
-  { "encrypt",         KENC_ENCRYPT,   KF_ENCMASK },
-  { "string",          KENC_STRING,    KF_ENCMASK },
-  { "ec",              KENC_EC,        KF_ENCMASK },
-
-  /* --- Classes of keys --- */
-
-  { "shared",          KCAT_SHARE,     KF_CATMASK },
-  { "public",          KCAT_PUB,       KF_CATMASK },
-  { "private",         KCAT_PRIV,      KF_CATMASK },
-  { "symmetric",       KCAT_SYMM,      KF_CATMASK },
-  { "secret",          0,              KF_NONSECRET },
-  { "-secret",         KF_NONSECRET,   KF_NONSECRET },
-
-  /* --- Other flags --- */
-
-  { "burn",            KF_BURN,        KF_BURN },
-  { "-burn",           0,              KF_BURN },
-
-  /* --- End marker --- */
-
-  { 0,                 0,              0 }
-};
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @key_readflags@ --- *
- *
- * Arguments:  @const char *p@ = pointer to string to read
- *             @char **pp@ = where to store the end pointer
- *             @unsigned *ff@ = where to store the flags
- *             @unsigned *mm@ = where to store the mask
- *
- * Returns:    Zero if all went well, nonzero if there was an error.
- *
- * Use:                Reads a flag string.
- */
-
-int key_readflags(const char *p, char **pp, unsigned *ff, unsigned *mm)
-{
-  unsigned f = 0, m = 0;
-
-  for (;;) {
-    size_t sz = strcspn(p, ",:");
-    const flagent *e, *ee = 0;
-
-    /* --- Look up the string in the flags table --- */
-
-    if (sz == 4 && strncmp(p, "none", 4) == 0)
-      goto next;
-    for (e = flagtab; e->name; e++) {
-      if (strncmp(e->name, p, sz) == 0) {
-       if (e->name[sz] == 0) {
-         ee = e;
-         break;
-       } else if (ee)
-         return (KERR_BADFLAGS);
-       else
-         ee = e;
-      }
-    }
-    if (!ee)
-      return (KERR_BADFLAGS);
-
-    /* --- Adjust the flag words --- *
-     *
-     * Ensure that the flags set are disjoint.
-     */
-
-    if (m & ee->m)
-      return (KERR_BADFLAGS);
-    m |= ee->m;
-    f |= ee->f;
-  next:
-    p += sz;
-    if (*p == 0 || *p == ':')
-      break;
-    p++;
-  }
-
-  /* --- Report the results --- */
-
-  if (ff) *ff = f;
-  if (mm) *mm = m;
-  if (pp) *pp = (char *)p;
-  return (0);
-}
-
-/* --- @key_writeflags@ --- *
- *
- * Arguments:  @unsigned f@ = flags to write
- *             @dstr *d@ = pointer to destination string
- *
- * Returns:    ---
- *
- * Use:                Emits a flags word as a string representation.
- */
-
-void key_writeflags(unsigned f, dstr *d)
-{
-  int del = 0;
-  const flagent *e;
-  unsigned m = 0;
-
-  for (e = flagtab; e->name; e++) {
-    if (m & e->m || e->name[0] == '-' || (f & e->m) != e->f)
-      continue;
-    if (del)
-      DPUTC(d, ',');
-    DPUTS(d, e->name);
-    m |= e->m;
-    del = 1;
-  }
-}
-
-/* --- @key_match@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const key_filter *kf@ = pointer to filter block
- *
- * Returns:    Nonzero if the key matches the filter.
- *
- * Use:                Checks whether a key matches a filter.
- */
-
-int key_match(key_data *k, const key_filter *kf)
-{
-  key_subkeyiter i;
-  const char *tag;
-  key_data *kd;
-
-  if (!kf)
-    return (1);
-  if ((k->e & KF_ENCMASK) != KENC_STRUCT)
-    return ((k->e & kf->m) == kf->f);
-
-  for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
-    if (key_match(kd, kf))
-      return (1);
-  }
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-io.c b/key-io.c
deleted file mode 100644 (file)
index 5c70909..0000000
--- a/key-io.c
+++ /dev/null
@@ -1,571 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Adding new keys to a key file
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <mLib/bits.h>
-#include <mLib/crc32.h>
-#include <mLib/dstr.h>
-#include <mLib/hash.h>
-#include <mLib/str.h>
-#include <mLib/sub.h>
-#include <mLib/sym.h>
-#include <mLib/url.h>
-
-#include "key.h"
-
-/*----- Tweakable macros --------------------------------------------------*/
-
-#define KEY_INITSZ 16
-
-/*----- Low-level functions -----------------------------------------------*/
-
-/* --- @insert@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure
- *             @key *k@ = pointer to key block to insert
- *
- * Returns:    Error code (one of the @KERR@ code).
- *
- * Use:                Links a new key block into the complicated data structure
- *             which is a keyring file.
- */
-
-static int insert(key_file *f, key *k)
-{
-  key_ref *kr = 0;
-  unsigned found;
-
-  /* --- Sanity preservatives --- */
-
-  if (key_chkident(k->type))
-    return (KERR_BADTYPE);
-  else if (k->tag && key_chkident(k->tag))
-    return (KERR_BADTAG);
-
-  /* --- Insert into the tag table --- */
-
-  if (k->tag) {
-    kr = sym_find(&f->bytag, k->tag, -1, sizeof(*kr), &found);
-    if (found)
-      return (KERR_DUPTAG);
-    kr->k = k;
-  }
-
-  /* --- Insert into the id table --- */
-
-  {
-    hash_base **bin, *b;
-
-    bin = HASH_BIN(&f->byid, k->id);
-    for (b = *bin; b; b = b->next) {
-      if (b->hash == k->id) {
-       if (kr)
-         sym_remove(&f->bytag, kr);
-       return (KERR_DUPID);
-      }
-    }
-
-    k->_b.next = *bin;
-    *bin = &k->_b;
-    k->_b.hash = k->id;
-  }
-
-  /* --- Extend the table --- */
-
-  if (f->idload > 0)
-    f->idload--;
-  else if (hash_extend(&f->byid))
-    f->idload = SYM_LIMIT(f->byid.mask / 2);
-
-  /* --- Insert into the type table --- */
-
-  kr = sym_find(&f->bytype, k->type, -1, sizeof(*kr), &found);
-  if (!found) {
-    kr->k = k;
-    k->next = 0;
-  } else {
-    key **p = &kr->k;
-    if (k->exp != KEXP_FOREVER) {
-      while (*p && (*p)->exp != KEXP_EXPIRE && (*p)->exp > k->exp)
-       p = &(*p)->next;
-    }
-    k->next = *p;
-    *p = k;
-  }
-
-  return (KERR_OK);
-}
-
-/*----- Reading and writing keys ------------------------------------------*/
-
-/* --- @exptime@ --- *
- *
- * Arguments:  @const char *p@ = pointer to string
- *
- * Returns:    Time value.
- *
- * Use:                Translates an expiry or deletion time.
- */
-
-time_t exptime(const char *p)
-{
-  size_t sz = strlen(p);
-  if (strncmp(p, "expired", sz) == 0)
-    return (KEXP_EXPIRE);
-  else if (strncmp(p, "forever", sz) == 0)
-    return (KEXP_FOREVER);
-  else
-    return (atol(p));
-}
-
-/* --- @key_merge@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure
- *             @const char *file@ = name of file (for error messages)
- *             @FILE *fp@ = file handle to read from
- *             @key_reporter *rep@ = error reporting function
- *             @void *arg@ = argument for function
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Reads keys from a file, and inserts them into the file.
- */
-
-int key_merge(key_file *f, const char *file, FILE *fp,
-             key_reporter *rep, void *arg)
-{
-  int line = 0;
-  dstr l = DSTR_INIT;
-  dstr n = DSTR_INIT, v = DSTR_INIT;
-
-  if (!(f->f & KF_WRITE))
-    return (KERR_READONLY);
-
-  for (; dstr_putline(&l, fp) != EOF; DRESET(&l)) {
-    char *vf[6];
-    char *p = l.buf;
-    key *k;
-
-    /* --- Skip blank lines and comments --- *
-     *
-     * Quite what they're doing in what ought to be an automatically-
-     * maintained file I don't know.
-     */
-
-    line++;
-    while (isspace((unsigned char)*p))
-      p++;
-    if (!*p || *p == '#')
-      continue;
-
-    /* --- Break the line into fields --- *
-     *
-     * There are currently six fields of interest:
-     *
-     *  * The key's identification (id, tag and type).
-     *  * The actual key data itself.
-     *  * The key expiry time.
-     *  * The key deletion time.
-     *  * The attributes field.
-     *  * Any further comments.
-     *
-     * All but the last field can contain no spaces.
-     */
-
-    {
-      int n = str_split(p, vf, 5, &vf[5]);
-      if (n < 4) {
-       if (rep)
-         rep(file, line, "too few fields", arg);
-       goto skip_0;
-      }
-    }
-
-    /* --- Allocate a new key block --- */
-
-    k = CREATE(key);
-
-    /* --- Extract the key data into the block --- */
-
-    if ((k->k = key_read(vf[1], 0)) == 0) {
-      if (rep)
-       rep(file, line, "bad key data", arg);
-      goto skip_1;
-    }
-
-    /* --- Decode the identification field --- *
-     *
-     * For compatibility, derive a keyid from the key data.  This can only be
-     * done if the key encoding is binary (and presumably old-encoding binary
-     * at that).
-     */
-
-    {
-      char *q = strchr(vf[0], ':');
-      char *qq;
-
-      if (!q) {
-       if (k->k->e != KENC_BINARY) {
-         if (rep)
-           rep(file, line, "new-style key encoding but no keyid", arg);
-         goto skip_2;
-       }
-       k->id = crc32(0, k->k->u.k.k, k->k->u.k.sz);
-       k->type = xstrdup(vf[0]);
-       k->tag = 0;
-      } else {
-       *q++ = 0;
-       k->id = strtoul(p, 0, 16);
-       if ((qq = strchr(q, ':')) == 0 || !qq[1]) {
-         if (qq)
-           *qq = 0;
-         k->tag = 0;
-       } else {
-         *qq++ = 0;
-         k->tag = xstrdup(qq);
-       }
-       k->type = xstrdup(q);
-      }
-    }
-
-    /* --- Get a key block for the new key --- */
-
-    k->exp = exptime(vf[2]);
-    k->del = exptime(vf[3]);
-
-    /* --- Insert the key block into the table --- */
-
-    {
-      int err;
-
-    again:
-      if ((err = insert(f, k)) < 0) {
-       if (err == KERR_DUPTAG) {
-         if (rep)
-           rep(file, line, "duplicate key tag stripped", arg);
-         xfree(k->tag);
-         k->tag = 0;
-         goto again;
-       }
-       if (rep)
-         rep(file, line, key_strerror(err), arg);
-       goto skip_3;
-      }
-    }
-
-    /* --- Parse up the attributes, if specified --- */
-
-    sym_create(&k->a);
-    if (vf[4] && strcmp(vf[4], "-") != 0) {
-      url_dctx uc;
-      for (url_initdec(&uc, vf[4]); url_dec(&uc, &n, &v); ) {
-       key_putattr(f, k, n.buf, v.buf);
-       DRESET(&n); DRESET(&v);
-      }
-    }
-
-    /* --- Insert the comment --- */
-
-    if (vf[5])
-      k->c = xstrdup(vf[5]);
-    else
-      k->c = 0;
-    continue;
-
-    /* --- Tidy up after something going wrong --- */
-
-  skip_3:
-    if (k->tag)
-      xfree(k->tag);
-    xfree(k->type);
-  skip_2:
-    key_drop(k->k);
-  skip_1:
-    DESTROY(k);
-  skip_0:;
-  }
-
-  /* --- Extensive tidying up now required --- */
-
-  dstr_destroy(&l);
-  dstr_destroy(&n);
-  dstr_destroy(&v);
-  f->f |= KF_MODIFIED;
-  return (0);
-}
-
-/* --- @key_extract@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure
- *             @key *k@ = key to extract
- *             @FILE *fp@ = file to write on
- *             @const key_filter *kf@ = pointer to key selection block
- *
- * Returns:    Zero if OK, EOF on error.
- *
- * Use:                Extracts a key to an ouptut file.
- */
-
-int key_extract(key_file *f, key *k, FILE *fp, const key_filter *kf)
-{
-  dstr d = DSTR_INIT;
-  time_t t = time(0);
-
-  /* --- Skip the key if it's deleted or unselected--- */
-
-  if (KEY_EXPIRED(t, k->del) || !key_match(k->k, kf))
-    return (0);
-
-  /* --- Encode the key and write the easy stuff --- */
-
-  key_fulltag(k, &d);
-  DPUTC(&d, ' ');
-  key_write(k->k, &d, kf);
-  DPUTC(&d, ' ');
-  dstr_write(&d, fp);
-  DRESET(&d);
-
-  /* --- Write out the expiry and deletion times --- */
-
-  if (KEY_EXPIRED(t, k->exp))
-    fputs("expired ", fp);
-  else if (k->exp == KEXP_FOREVER)
-    fputs("forever ", fp);
-  else
-    fprintf(fp, "%li ", (long)k->exp);
-
-  if (k->del == KEXP_FOREVER)
-    fputs("forever ", fp);
-  else
-    fprintf(fp, "%li ", (long)k->del);
-
-  /* --- Output the attributes --- */
-
-  {
-    int none = 1;
-    sym_iter i;
-    key_attr *a;
-    url_ectx uc;
-
-    url_initenc(&uc);
-    for (sym_mkiter(&i, &k->a); (a = sym_next(&i)) != 0; ) {
-      none = 0;
-      url_enc(&uc, &d, SYM_NAME(a), a->p);
-    }
-    if (none)
-      DPUTS(&d, "-");
-    DWRITE(&d, fp);
-  }
-
-  dstr_destroy(&d);
-  if (k->c) {
-    putc(' ', fp);
-    fputs(k->c, fp);
-  }
-  putc('\n', fp);
-  return (ferror(fp) ? EOF : 0);
-}
-
-/*----- Opening and closing files -----------------------------------------*/
-
-/* --- @key_open@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure to initialize
- *             @const char *file@ = pointer to the file name
- *             @unsigned how@ = opening options (@KOPEN_*@).
- *             @key_reporter *rep@ = error reporting function
- *             @void *arg@ = argument for function
- *
- * Returns:    Zero if it worked, nonzero otherwise.
- *
- * Use:                Opens a key file, reads its contents, and stores them in a
- *             structure.  The file is locked appropriately until closed
- *             using @key_close@.  On an error, everything is cleared away
- *             tidily.  If the file is opened with @KOPEN_WRITE@, it's
- *             created if necessary, with read and write permissions for its
- *             owner only.
- */
-
-int key_open(key_file *f, const char *file, unsigned how,
-            key_reporter *rep, void *arg)
-{
-  if (key_lockfile(f, file, how)) {
-    rep(file, 0, strerror(errno), arg);
-    return (-1);
-  }
-  f->f = 0;
-  f->name = xstrdup(file);
-
-  hash_create(&f->byid, KEY_INITSZ);
-  f->idload = SYM_LIMIT(KEY_INITSZ);
-  sym_create(&f->bytype);
-  sym_create(&f->bytag);
-  f->f |= KF_WRITE;
-  if (f->fp)
-    key_merge(f, file, f->fp, rep, arg);
-  f->f &= ~KF_MODIFIED;
-
-  if ((how & KOPEN_MASK) == KOPEN_READ) {
-    f->f &= ~KF_WRITE;
-    fclose(f->fp);
-    f->fp = 0;
-  }
-
-  return (0);
-}
-
-/* --- @key_discard@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *
- * Returns:    ---
- *
- * Use:                Frees all the key data, without writing changes.
- */
-
-void key_discard(key_file *f)
-{
-  hash_base *b;
-  hash_iter i;
-
-  /* --- Free all the individual keys --- */
-
-  for (hash_mkiter(&i, &f->byid); (b = hash_next(&i)) != 0; ) {
-    sym_iter j;
-    key_attr *a;
-    key *k = (key *)b;
-
-    if (k->k) key_drop(k->k);
-    xfree(k->type);
-    xfree(k->tag);
-    if (k->c)
-      xfree(k->c);
-    for (sym_mkiter(&j, &k->a); (a = sym_next(&j)) != 0; )
-      xfree(a->p);
-    sym_destroy(&k->a);
-    DESTROY(k);
-  }
-  hash_destroy(&f->byid);
-  sym_destroy(&f->bytype);
-  sym_destroy(&f->bytag);
-
-  if (f->fp)
-    fclose(f->fp);
-  xfree(f->name);
-}
-
-/* --- @key_close@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *
- * Returns:    A @KWRITE_@ code indicating how it went.
- *
- * Use:                Frees all the key data, writes any changes.  Make sure that
- *             all hell breaks loose if this returns @KWRITE_BROKEN@.
- */
-
-int key_close(key_file *f)
-{
-  int e;
-
-  if (f->fp && (e = key_save(f)) != KWRITE_OK)
-    return (e);
-  key_discard(f);
-  return (KWRITE_OK);
-}
-
-/* --- @key_new@ ---
- *
- * Arguments:  @key_file *f@ = pointer to key file
- *             @uint32 id@ = keyid to set
- *             @const char *type@ = the type of this key
- *             @time_t exp@ = when the key expires
- *             @key *kk@ = where to put the key pointer
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Attaches a new key to a key file.  You must have a writable
- *             key file for this to work.
- *
- *             The type is a key type string.  This interface doesn't care
- *             about how type strings are formatted: it just treats them as
- *             opaque gobs of text.  Clients are advised to choose some
- *             standard for representing key types, though.
- *
- *             The expiry time should either be a time in the future, or the
- *             magic value @KEXP_FOREVER@ which means `never expire this
- *             key'.  Be careful with `forever' keys.  If I were you, I'd
- *             use a more sophisticated key management system than this for
- *             them.
- */
-
-int key_new(key_file *f, uint32 id, const char *type, time_t exp, key **kk)
-{
-  key *k = 0;
-  time_t t = time(0);
-  int e = KERR_OK;
-
-  /* --- Make sure the file is writable --- */
-
-  if (!(f->f & KF_WRITE))
-    e = KERR_READONLY;
-  else if (KEY_EXPIRED(t, exp))
-    e = KERR_EXPIRED;
-  else if (key_chkident(type))
-    e = KERR_BADTYPE;
-  else {
-    k = CREATE(key);
-    k->id = id;
-    k->tag = 0;
-    k->exp = k->del = exp;
-    k->c = 0;
-    k->type = (char *)type; /* temporarily */
-    sym_create(&k->a);
-    if ((e = insert(f, k)) != 0)
-      DESTROY(k);
-    else {
-      k->k = key_newstring(KCAT_SHARE, "<unset>");
-      k->type = xstrdup(type);
-      *kk = k;
-      f->f |= KF_MODIFIED;
-    }
-  }
-
-  return (e);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-misc.c b/key-misc.c
deleted file mode 100644 (file)
index 5ff7078..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Simple key management
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <mLib/bits.h>
-#include <mLib/hash.h>
-#include <mLib/sub.h>
-#include <mLib/sym.h>
-
-#include "key.h"
-
-/*----- Useful macros -----------------------------------------------------*/
-
-#define KEY_WRITE(f) do {                                              \
-     if (!(f)->f & KF_WRITE)                                           \
-       return (KERR_READONLY);                                         \
-   } while (0)
-
-#define KEY_MODIFY(f) do { (f)->f |= KF_MODIFIED; } while (0)
-
-#define KEY_LOAD(n) ((n) * 2)
-
-/*----- Iteration and iterators -------------------------------------------*/
-
-/* --- @key_mkiter@ --- *
- *
- * Arguments:  @key_iter *i@ = pointer to iterator object
- *             @key_file *f@ = pointer to file structure
- *
- * Returns:    ---
- *
- * Use:                Initializes a key iterator.  The keys are returned by
- *             @key_next@.
- */
-
-void key_mkiter(key_iter *i, key_file *f)
-{
-  HASH_MKITER(&i->i, &f->byid);
-  i->t = time(0);
-}
-
-/* --- @key_next@ --- *
- *
- * Arguments:  @key_iter *i@ = pointer to iterator object
- *
- * Returns:    Pointer to next key, or null.
- *
- * Use:                Returns the next key in some arbitrary sequence.
- */
-
-key *key_next(key_iter *i)
-{
-  hash_base *b;
-  key *k;
-  do {
-    HASH_NEXT(&i->i, b);
-    k = (key *)b;
-  } while (k && KEY_EXPIRED(i->t, k->exp) && KEY_EXPIRED(i->t, k->del));
-  return (k);
-}
-
-/*----- Lookup ------------------------------------------------------------*/
-
-/* --- @key_bytype@ --- *
- *
- * Arguments:  @key_file *f@ = key file we want a key from
- *             @const char *type@ = type string for desired key
- *
- * Returns:    Pointer to the best key to use, or null.
- *
- * Use:                Looks up a key by its type.  Returns the key with the latest
- *             expiry time.  This function will not return an expired key.
- */
-
-key *key_bytype(key_file *f, const char *type)
-{
-  time_t now = time(0);
-  key *k;
-  key_ref *kr;
-
-  if ((kr = sym_find(&f->bytype, type, -1, 0, 0)) == 0)
-    return (0);
-  for (k = kr->k; k && KEY_EXPIRED(now, k->exp); k = k->next)
-    ;
-  return (k);
-}
-
-/* --- @key_byid@ --- *
- *
- * Arguments:  @key_file *f@ = key file to find a key from
- *             @uint32 id@ = id to look for
- *
- * Returns:    Key with matching id.
- *
- * Use:                Returns a key given its id.  This function will return an
- *             expired key, but not a deleted one.
- */
-
-key *key_byid(key_file *f, uint32 id)
-{
-  time_t t = time(0);
-  hash_base **bin, *b;
-
-  bin = HASH_BIN(&f->byid, id);
-  for (b = *bin; b; b = b->next) {
-    if (b->hash == id) {
-      key *k = (key *)b;
-      if (KEY_EXPIRED(t, k->exp) && KEY_EXPIRED(t, k->del))
-       return (0);
-      return (k);
-    }
-  }
-  return (0);
-}
-
-/* --- @key_bytag@ --- *
- *
- * Arguments:  @key_file *f@ = key file to find a key from
- *             @const char *tag@ = pointer to tag string
- *
- * Returns:    Key with matching id or tag.
- *
- * Use:                Returns a key given its tag or id.  This function will return
- *             an expired key, but not a deleted one.
- */
-
-key *key_bytag(key_file *f, const char *tag)
-{
-  time_t t = time(0);
-  char *p;
-  uint32 id;
-  key_ref *kr = sym_find(&f->bytag, tag, -1, 0, 0);
-
-  if (kr && !(KEY_EXPIRED(t, kr->k->exp) && KEY_EXPIRED(t, kr->k->del)))
-    return (kr->k);
-  id = strtoul(tag, &p, 16);
-  if (!*p)
-    return (key_byid(f, id));
-  return (key_bytype(f, tag));
-}
-
-/* --- @key_qtag@ --- *
- *
- * Arguments:  @key_file *f@ = key file to find a key from
- *             @const char *tag@ = pointer to tag string
- *             @dstr *d@ = pointer to string for full tag name
- *             @key **k@ = where to store the key pointer
- *             @key_data ***kd@ = where to store the key data pointer
- *
- * Returns:    Zero if OK, nonzero if it failed.
- *
- * Use:                Performs a full lookup on a qualified tag name.  The tag is
- *             qualified by the names of subkeys, separated by dots.  Hence,
- *             a qualified tag is ID|TAG[.TAG...].  The various result
- *             pointers can be null to indicate that the result isn't
- *             interesting.
- */
-
-int key_qtag(key_file *f, const char *tag, dstr *d, key **k, key_data ***kd)
-{
-  dstr dd = DSTR_INIT;
-  const char *q;
-  key *kk;
-  key_data **kkd;
-
-  /* --- Find the end of the base tag --- */
-
-  if ((q = strchr(tag, '.')) == 0)
-    DPUTS(&dd, tag);
-  else {
-    DPUTM(&dd, tag, q - tag);
-    DPUTZ(&dd);
-    q++;
-  }
-
-  /* --- Look up the key tag --- */
-
-  if ((kk = key_bytag(f, dd.buf)) == 0) {
-    dstr_destroy(&dd);
-    return (-1);
-  }
-
-  /* --- Set the various initial bits of result up --- */
-
-  if (d)
-    key_fulltag(kk, d);
-  if (k)
-    *k = kk;
-  kkd = &kk->k;
-
-  /* --- Now dig through the rest of the tag --- */
-
-  if (q) {
-    while (*q) {
-      key_struct *ks;
-
-      /* --- Stick on the next bit of the fullqtag --- */
-
-      DRESET(&dd);
-      while (*q && *q != '.') {
-       DPUTC(&dd, *q);
-       q++;
-      }
-      DPUTZ(&dd);
-      if (d) {
-       DPUTC(d, '.');
-       DPUTD(d, &dd);
-      }
-
-      /* --- Look up the subkey --- */
-
-      if ((*kkd)->e != KENC_STRUCT) {
-       kkd = 0;
-       break;
-      }
-      if ((ks = sym_find(&(*kkd)->u.s, dd.buf, -1, 0, 0)) == 0) {
-       kkd = 0;
-       break;
-      }
-      kkd = &ks->k;
-    }
-  }
-
-  /* --- Return the results --- */
-
-  dstr_destroy(&dd);
-  if (!kkd)
-    return (-1);
-  if (kd)
-    *kd = kkd;
-  return (0);
-}
-
-/*----- Miscellaneous functions -------------------------------------------*/
-
-/* --- @key_delete@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file block
- *             @key *k@ = key to delete
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Removes the given key from the list.  The key file must be
- *             writable.  (Due to the horridness of the data structures,
- *             deleted keys aren't actually removed, just marked so that
- *             they can't be looked up or iterated over.  One upshot of
- *             this is that they don't get written back to the file when
- *             it's closed.)
- */
-
-int key_delete(key_file *f, key *k)
-{
-  KEY_WRITE(f);
-  k->exp = KEXP_EXPIRE;
-  k->del = KEXP_EXPIRE;
-  KEY_MODIFY(f);
-  return (0);
-}
-
-/* --- @key_expired@ --- *
- *
- * Arguments:  @key *k@ = pointer to key block
- *
- * Returns:    Zero if the key is OK, nonzero if it's expired.
- */
-
-int key_expired(key *k)
-{
-  time_t now = time(0);
-  return (KEY_EXPIRED(now, k->exp) || KEY_EXPIRED(now, k->del));
-}
-
-/* --- @key_expire@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file block
- *             @key *k@ = pointer to key block
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Immediately marks the key as expired.  It may be removed
- *             immediately, if it is no longer required, and will be removed
- *             by a tidy operation when it is no longer required.  The key
- *             file must be writable.
- */
-
-int key_expire(key_file *f, key *k)
-{
-  KEY_WRITE(f);
-  k->exp = KEXP_EXPIRE;
-  if (k->del == KEXP_FOREVER)
-    k->del = KEXP_EXPIRE;
-  KEY_MODIFY(f);
-  return (0);
-}
-
-/* --- @key_used@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file
- *             @key *k@ = pointer to key block
- *             @time_t t@ = when key can be removed
- *
- * Returns:    Zero if OK, nonzero on failure.
- *
- * Use:                Marks a key as being required until a given time.  Even
- *             though the key may expire before then (and won't be returned
- *             by type after that time), it will still be available when
- *             requested explicitly by id.  The key file must be writable.
- *
- *             The only (current) reason for failure is attempting to use
- *             a key which can expire for something which can't.
- */
-
-int key_used(key_file *f, key *k, time_t t)
-{
-  KEY_WRITE(f);
-  if (t == KEXP_FOREVER) {
-    if (k->exp != KEXP_FOREVER)
-      return (KERR_WILLEXPIRE);
-  } else if (k->del >= t)
-    return (0);
-
-  k->del = t;
-  KEY_MODIFY(f);
-  return (0);
-}
-
-/* --- @key_fingerprint@ --- *
- *
- * Arguments:  @key *k@ = the key to fingerprint
- *             @ghash *h@ = the hash to use
- *             @const key_filter *kf@ = filter to apply
- *
- * Returns:    Nonzero if the key slightly matched the filter.
- *
- * Use:                Updates the hash context with the key contents.
- */
-
-static int abyname(const void *a, const void *b) {
-  key_attr *const *x = a, *const *y = b;
-  return (strcmp(SYM_NAME(*x), SYM_NAME(*y)));
-}
-
-int key_fingerprint(key *k, ghash *h, const key_filter *kf)
-{
-  dstr d = DSTR_INIT;
-  int rc = 0;
-  key_attr *a, **v;
-  size_t n, i;
-  sym_iter ai;
-
-  if (!key_encode(k->k, &d, kf))
-    goto done;
-  rc = 1;
-  GH_HASHSTR(h, "catacomb-key-fingerprint:");
-  GH_HASHU32(h, k->id);
-  GH_HASHSTR8(h, k->type);
-  GH_HASH(h, d.buf, d.len);
-  for (n = 0, sym_mkiter(&ai, &k->a); (a = sym_next(&ai)) != 0; n++);
-  if (n) {
-    v = xmalloc(n * sizeof(*v));
-    for (i = 0, sym_mkiter(&ai, &k->a); (a = sym_next(&ai)) != 0; i++)
-      v[i] = a;
-    qsort(v, n, sizeof(*v), abyname);
-    for (i = 0; i < n; i++) {
-      GH_HASHSTR8(h, SYM_NAME(v[i]));
-      GH_HASHSTR16(h, v[i]->p);
-    }
-    xfree(v);
-  }
-done:
-  dstr_destroy(&d);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-moan.c b/key-moan.c
deleted file mode 100644 (file)
index ebefe02..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*-c-*-
- *
- * $Id: key-moan.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Standard error handling function for key loading
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/report.h>
-
-#include "key.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @key_moan@ --- *
- *
- * Arguments:  @const char *file@ = name of the file
- *             @int line@ = line number in file
- *             @const char *msg@ = error message
- *             @void *p@ = argument pointer
- *
- * Returns:    ---
- *
- * Use:                Reports an error message about loading a key file.
- */
-
-void key_moan(const char *file, int line, const char *msg, void *p)
-{
-  moan("%s:%i: error: %s", file, line, msg);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-pack.c b/key-pack.c
deleted file mode 100644 (file)
index 7f79800..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Packing and unpacking key data
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#include "key-data.h"
-
-/*----- Generic packing and unpacking -------------------------------------*/
-
-/* --- @key_pack@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *             @key_data **kd@ = where to put the key data pointer
- *             @dstr *d@ = pointer to tag string for the key data
- *
- * Returns:    Error code, or zero.
- *
- * Use:                Packs a key from a data structure.
- */
-
-int key_pack(key_packdef *kp, key_data **kd, dstr *d)
-{
-  switch (kp->e & KF_ENCMASK) {
-
-    /* --- Binary and integer keys are easy --- */
-
-    case KENC_BINARY: {
-      key_bin *b = kp->p;
-      *kd = key_newbinary(kp->e, b->k, b->sz);
-      return (0);
-    }
-    case KENC_MP:
-      *kd = key_newmp(kp->e, *(mp **)kp->p);
-      return (0);
-    case KENC_STRING:
-      *kd = key_newstring(kp->e, *(char **)kp->p);
-      return (0);
-    case KENC_EC:
-      *kd = key_newec(kp->e, (ec *)kp->p);
-      return (0);
-
-    /* --- Encrypted keys are a little tricky --- *
-     *
-     * This works rather differently to unpacking.
-     */
-
-    case KENC_ENCRYPT: {
-      key_data *kkd;
-      int err = key_pack(kp->p, &kkd, d);
-      if (!err) {
-       err = key_plock(kd, kkd, d->buf);
-       key_drop(kkd);
-      }
-      return (err);
-    }
-
-    /* --- Structured keys, as ever, are a nuisance --- */
-
-    case KENC_STRUCT: {
-      int err;
-      key_packstruct *p;
-      size_t l = d->len;
-
-      *kd = key_newstruct();
-      DPUTC(d, '.');
-      for (p = kp->p; p->name; p++) {
-       key_data *kkd;
-       d->len = l + 1;
-       DPUTS(d, p->name);
-       if ((err = key_pack(&p->kp, &kkd, d)) != 0) {
-         key_drop(*kd);
-         return (err);
-       }
-       key_structsteal(*kd, p->name, kkd);
-      }
-      d->len = l;
-      d->buf[l] = 0;
-      return (0);
-    }
-    default:
-      abort();
-  }
-}
-
-/* --- @key_unpack@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *             @key_data *kd@ = pointer to source key data
- *             @dstr *d@ = pointer to tag string for the key data
- *
- * Returns:    Error code, or zero.
- *
- * Use:                Unpacks a key into an appropriate data structure.
- */
-
-int key_unpack(key_packdef *kp, key_data *kd, dstr *d)
-{
-  unsigned e = kp->e & KF_ENCMASK;
-  int err;
-
-  /* --- Decrypt the encrypted key --- */
-
-  if ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) {
-    if ((err = key_punlock(&kp->kd, kd, d->buf)) != 0)
-      goto fail;
-    kd = kp->kd;
-  }
-
-  /* --- Ensure that the key has the right type --- */
-
-  if ((kd->e & KF_ENCMASK) != e) {
-    err = KERR_WRONGTYPE;
-    goto fail;
-  }
-
-  /* --- Unpack the key --- *
-   *
-   * Only three possibilities left now.
-   */
-
-  switch (e) {
-
-    /* --- Binary and integer keys are easy --- */
-
-    case KENC_BINARY:
-      *(key_bin *)kp->p = kd->u.k;
-      break;
-    case KENC_MP:
-      *(mp **)kp->p = kd->u.m;
-      break;
-    case KENC_STRING:
-      *(char **)kp->p = kd->u.p;
-      break;
-    case KENC_EC:
-      *(ec *)kp->p = kd->u.e;
-      break;
-
-    /* --- Structured keys take a little care --- */
-
-    case KENC_STRUCT: {
-      key_packstruct *p, *q;
-      size_t l = d->len;
-
-      /* --- Iterate over the requested subparts --- */
-
-      DPUTC(d, '.');
-      for (p = kp->p; p->name; p++) {
-       key_data *kkd;
-
-       /* --- Build the name --- */
-
-       d->len = l + 1;
-       DPUTS(d, p->name);
-
-       /* --- Find and unpack the subkey --- */
-
-       if ((kkd = key_structfind(kd, p->name)) == 0) {
-         if (!(p->kp.e & KF_OPT)) {
-           err = KERR_NOTFOUND;
-           goto tidy;
-         }
-       } else if ((err = key_unpack(&p->kp, kkd, d)) != 0) {
-         p++;
-         goto tidy;
-       }
-      }
-
-      /* --- Done --- */
-
-      d->len = l;
-      d->buf[l] = 0;
-      break;
-
-      /* --- Tidy up if something went wrong --- */
-
-    tidy:
-      for (q = kp->p; q < p; q++)
-       key_unpackdone(&q->kp);
-      goto fail;
-    }
-
-    default:
-      abort();
-  }
-
-  return (0);
-
-  /* --- Something went wrong --- */
-
-fail:
-  if (kp->kd) {
-    key_drop(kp->kd);
-    kp->kd = 0;
-  }
-  return (err);
-}
-
-/* --- @key_unpackdone@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing definition
- *
- * Returns:    ---
- *
- * Use:                Frees the key components contained within a packing
- *             definition, created during key unpacking.
- */
-
-void key_unpackdone(key_packdef *kp)
-{
-  if (kp->kd) {
-    key_drop(kp->kd);
-    kp->kd = 0;
-  }
-  if ((kp->e & KF_ENCMASK) == KENC_STRUCT) {
-    key_packstruct *p;
-    for (p = kp->p; p->name; p++)
-      key_unpackdone(&p->kp);
-  }
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-pass.c b/key-pass.c
deleted file mode 100644 (file)
index f303245..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Encrypting keys with passphrases
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#include "key-data.h"
-#include "paranoia.h"
-#include "passphrase.h"
-#include "rand.h"
-
-#include "blowfish-cbc.h"
-#include "rmd160.h"
-#include "rmd160-mgf.h"
-#include "rmd160-hmac.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Format --- *
- *
- * Choose a random 160-bit string %$R$%.  Take the passphrase %$P$%, and
- * the message %$m$%.  Now, compute %$K_E \cat K_T = H(R \cat P)$%,
- * %$y_0 = E_{K_E}(m)$% and %$\tau = T_{K_T}(y_0)$%.  The ciphertext is
- * %$y = N \cat \tau \cat y_0$%.
- *
- * This is not the original format.  The original format was insecure, and
- * has been replaced incompatibly.
- */
-
-/* --- @key_lock@ --- *
- *
- * Arguments:  @key_data **kt@ = where to store the destination pointer
- *             @key_data *k@ = source key data block or null to use @*kt@
- *             @const void *e@ = secret to encrypt key with
- *             @size_t esz@ = size of the secret
- *
- * Returns:    ---
- *
- * Use:                Encrypts a key data block using a secret.
- */
-
-void key_lock(key_data **kt, key_data *k, const void *e, size_t esz)
-{
-  dstr d = DSTR_INIT;
-  octet b[RMD160_HASHSZ * 2];
-  octet *m;
-  size_t msz;
-  rmd160_mgfctx r;
-  blowfish_cbcctx c;
-  rmd160_mackey mk;
-  rmd160_macctx mc;
-
-  /* --- Sanity check --- */
-
-  if (k) key_incref(k); else k = *kt;
-  assert(((void)"Key data is already encrypted",
-         (k->e & KF_ENCMASK) != KENC_ENCRYPT));
-
-  /* --- Format the stuff in the buffer --- */
-
-  DENSURE(&d, RMD160_HASHSZ * 2);
-  rand_get(RAND_GLOBAL, d.buf, RMD160_HASHSZ);
-  d.len += RMD160_HASHSZ * 2;
-  key_encode(k, &d, 0);
-  m = (octet *)d.buf + RMD160_HASHSZ * 2;
-  msz = d.len - RMD160_HASHSZ * 2;
-
-  /* --- Hash the passphrase to make a key --- */
-
-  rmd160_mgfkeybegin(&r);
-  rmd160_mgfkeyadd(&r, d.buf, RMD160_HASHSZ);
-  rmd160_mgfkeyadd(&r, e, esz);
-  rmd160_mgfencrypt(&r, 0, b, sizeof(b));
-  BURN(r);
-
-  /* --- Encrypt the plaintext --- */
-
-  blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0);
-  blowfish_cbcencrypt(&c, m, m, msz);
-  BURN(c);
-
-  /* --- MAC the ciphertext --- */
-
-  rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
-  rmd160_macinit(&mc, &mk);
-  rmd160_machash(&mc, m, msz);
-  rmd160_macdone(&mc, d.buf + RMD160_HASHSZ);
-  BURN(mk);
-  BURN(mc);
-
-  /* --- Done --- */
-
-  BURN(b);
-  *kt = key_newencrypted(0, d.buf, d.len);
-  key_drop(k);
-  dstr_destroy(&d);
-}
-
-/* --- @key_unlock@ --- *
- *
- * Arguments:  @key_data **kt@ = where to store the destination pointer
- *             @key_data *k@ = source key data block or null to use @*kt@
- *             @const void *e@ = secret to decrypt the block with
- *             @size_t esz@ = size of the secret
- *
- * Returns:    Zero for success, or a @KERR_@ error code.
- *
- * Use:                Unlocks a key using a secret.
- */
-
-int key_unlock(key_data **kt, key_data *k, const void *e, size_t esz)
-{
-  octet b[RMD160_HASHSZ * 2];
-  octet *p = 0;
-  int rc;
-  int drop = 0;
-  key_data *kd;
-  rmd160_mgfctx r;
-  blowfish_cbcctx c;
-  rmd160_mackey mk;
-  rmd160_macctx mc;
-  size_t sz;
-
-  /* --- Sanity check --- */
-
-  if (!k) { k = *kt; drop = 1; }
-  assert(((void)"Key data isn't encrypted",
-         (k->e & KF_ENCMASK) == KENC_ENCRYPT));
-
-  /* --- Check the size --- */
-
-  if (k->u.k.sz < RMD160_HASHSZ * 2)
-    return (KERR_MALFORMED);
-  sz = k->u.k.sz - RMD160_HASHSZ * 2;
-
-  /* --- Hash the passphrase to make a key --- */
-
-  rmd160_mgfkeybegin(&r);
-  rmd160_mgfkeyadd(&r, k->u.k.k, RMD160_HASHSZ);
-  rmd160_mgfkeyadd(&r, e, esz);
-  rmd160_mgfencrypt(&r, 0, b, sizeof(b));
-  BURN(r);
-
-  /* --- Verify the MAC --- */
-
-  rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
-  rmd160_macinit(&mc, &mk);
-  rmd160_machash(&mc, k->u.k.k + RMD160_HASHSZ * 2, sz);
-  rmd160_macdone(&mc, b + RMD160_HASHSZ);
-  if (memcmp(b + RMD160_HASHSZ, k->u.k.k + RMD160_HASHSZ,
-            RMD160_HASHSZ) != 0) {
-    rc = KERR_BADPASS;
-    goto fail;
-  }
-  BURN(mk);
-  BURN(mc);
-
-  /* --- Allocate a destination buffer --- */
-
-  p = xmalloc(sz);
-
-  /* --- Decrypt the key data --- */
-
-  blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0);
-  blowfish_cbcdecrypt(&c, k->u.k.k + RMD160_HASHSZ * 2, p, sz);
-  BURN(c);
-
-  /* --- Decode the key data into the destination buffer --- */
-
-  if ((kd = key_decode(p, sz)) == 0) {
-    rc = KERR_MALFORMED;
-    goto fail;
-  }
-  *kt = kd;
-
-  /* --- Done --- */
-
-  xfree(p);
-  if (drop) key_drop(k);
-  return (0);
-
-  /* --- Tidy up if things went wrong --- */
-
-fail:
-  BURN(b);
-  xfree(p);
-  return (rc);
-}
-
-/* --- @key_plock@ --- *
- *
- * Arguments:  @key_data **kt@ = where to store the destination pointer
- *             @key_data *k@ = source key data block or null to use @*kt@
- *             @const char *tag@ = tag to use for passphrase
- *
- * Returns:    Zero if successful, a @KERR@ error code on failure.
- *
- * Use:                Locks a key by encrypting it with a passphrase.
- */
-
-int key_plock(key_data **kt, key_data *k, const char *tag)
-{
-  char buf[256];
-
-  if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf)))
-    return (KERR_IO);
-  key_lock(kt, k, buf, strlen(buf));
-  BURN(buf);
-  return (0);
-}
-
-/* --- @key_punlock@ --- *
- *
- * Arguments:  @key_data **kt@ = where to store the destination pointer
- *             @key_data *k@ = source key data block or null to use @*kt@
- *             @const char *tag@ = tag to use for passphrase
- *
- * Returns:    Zero if it worked, a @KERR_@ error code on failure.
- *
- * Use:                Unlocks a passphrase-locked key.
- */
-
-int key_punlock(key_data **kt, key_data *k, const char *tag)
-{
-  char buf[256];
-  int rc;
-
-  if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
-    return (KERR_IO);
-  rc = key_unlock(kt, k, buf, strlen(buf));
-  BURN(buf);
-  if (rc == KERR_BADPASS || !k)
-    passphrase_cancel(tag);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key-text.c b/key-text.c
deleted file mode 100644 (file)
index ff9e705..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Key textual encoding
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/base64.h>
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-#include <mLib/sub.h>
-#include <mLib/sym.h>
-#include <mLib/url.h>
-
-#include "key-data.h"
-#include "mp.h"
-#include "mptext.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @key_read@ --- *
- *
- * Arguments:  @const char *p@ = pointer to textual key representation
- *             @char **pp@ = where to store the end pointer
- *
- * Returns:    The newly-read key data, or null if it failed.
- *
- * Use:                Parses a textual key description.
- */
-
-key_data *key_read(const char *p, char **pp)
-{
-  unsigned e;
-  key_data *kd;
-
-  /* --- Read the encoding type --- *
-   *
-   * The key format is `[FLAGS:]DATA'.  If there is no encoding type
-   * named, assume that it's `binary' for backwards compatibility.
-   */
-
-  if (strchr(p, ':') == 0)
-    e = 0;
-  else {
-    char *q;
-    if (key_readflags(p, &q, &e, 0))
-      return (0);
-    p = q + 1;
-  }
-
-  /* --- Now scan the data based on the encoding type --- */
-
-  switch (e & KF_ENCMASK) {
-
-    /* --- Binary encoding --- *
-     *
-     * Simply read out the Base64-encoded data.  Since `,' and `]' are our
-     * delimeter characters, and they can't appear in Base64-encoded data, I
-     * can just do a simple search to find the end of the encoded data.
-     */
-
-    case KENC_BINARY:
-    case KENC_ENCRYPT: {
-      dstr d = DSTR_INIT;
-      base64_ctx b;
-      size_t sz = strcspn(p, ",]");
-
-      base64_init(&b);
-      base64_decode(&b, p, sz, &d);
-      base64_decode(&b, 0, 0, &d);
-      kd = key_newbinary(e, d.buf, d.len);
-      dstr_destroy(&d);
-      p += sz;
-    } break;
-
-    /* --- Multiprecision integer encoding --- *
-     *
-     * Multiprecision integers have a convenient reading function.
-     */
-
-    case KENC_MP: {
-      char *q;
-      mp *m = mp_readstring(e & KF_BURN ? MP_NEWSEC : MP_NEW, p, &q, 0);
-      if (!m)
-       return (0);
-      kd = key_newmp(e, m);
-      MP_DROP(m);
-      p = q;
-    } break;
-
-    /* --- String encoding --- *
-     *
-     * We use form-urlencoding to ensure that evil characters don't get out.
-     */
-
-    case KENC_STRING: {
-      dstr d = DSTR_INIT;
-      size_t sz = strcspn(p, ",]");
-      const char *l = p + sz;
-      unsigned int ch;
-      int x, n;
-
-      while (p < l) {
-       switch (*p) {
-         case '+':
-           DPUTC(&d, ' '); break;
-         case '%':
-           x = sscanf(p + 1, "%2x%n", &ch, &n);
-           if (x == 1) { DPUTC(&d, ch); p += n; break; }
-         default:
-           DPUTC(&d, *p); break;
-       }
-       p++;
-      }
-      DPUTZ(&d);
-      kd = key_newstring(e, d.buf);
-      dstr_destroy(&d);
-    } break;
-
-    /* --- Elliptic curve encoding --- *
-     *
-     * Again, we have a convenient function.  Assume for now that points
-     * aren't secret.  (Reasonably safe.)
-     */
-
-    case KENC_EC: {
-      ec pt = EC_INIT;
-      qd_parse qd;
-      qd.p = p;
-      qd.e = 0;
-      if (!ec_ptparse(&qd, &pt))
-       return (0);
-      kd = key_newec(e, &pt);
-      EC_DESTROY(&pt);
-      p = qd.p;
-    } break;
-
-    /* --- Structured information encoding --- *
-     *
-     * The format for structured key data is `[NAME=KEY,...]', where the
-     * brackets are part of the syntax.  Structured keys have no flags apart
-     * from the encoding.
-     *
-     * The binary encoding only allows names up to 255 bytes long.  Check for
-     * this here.
-     */
-
-    case KENC_STRUCT: {
-      dstr d = DSTR_INIT;
-      key_data *nkd;
-      char *q;
-
-      /* --- Read the opening bracket --- */
-
-      kd = key_newstruct();
-      if (*p != '[')
-       return (0);
-      p++;
-
-      /* --- Read named key subparts --- */
-
-      for (;;) {
-       size_t sz;
-
-       /* --- Stop if there's a close-bracket --- *
-        *
-        * This allows `[]' to be an empty structured key, which is good.  It
-        * also makes `[foo=enc:bar,]' legal, and that's less good but I can
-        * live with it.
-        */
-
-       if (*p == ']')
-         break;
-
-       /* --- Read the name out and check the length --- */
-
-       if ((q = strchr(p, '=')) == 0)
-         goto fail;
-       sz = q - p;
-       if (sz >= 256)
-         goto fail;
-       DRESET(&d);
-       DPUTM(&d, p, sz);
-       DPUTZ(&d);
-
-       /* --- Read the key data for the subkey --- */
-
-       if ((nkd = key_read(q + 1, &q)) == 0)
-         goto fail;
-       key_structsteal(kd, d.buf, nkd);
-       p = q;
-
-       /* --- Read the comma or close-bracket --- */
-
-       if (*p == ']')
-         break;
-       else if (*p == ',')
-         p++;
-       else
-         goto fail;
-      }
-
-      /* --- Step past the close bracket --- */
-
-      p++;
-      dstr_destroy(&d);
-      break;
-
-      /* --- Tidy up after a failure --- */
-
-    fail:
-      dstr_destroy(&d);
-      return (0);
-    } break;
-
-    /* --- Anything else is unknown --- */
-
-    default:
-      return (0);
-  }
-
-  /* --- Return the end pointer --- */
-
-  kd->e = e;
-  if (pp)
-    *pp = (char *)p;
-  return (kd);
-}
-
-/* --- @key_write@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data
- *             @dstr *d@ = destination string to write on
- *             @const key_filter *kf@ = pointer to key selection block
- *
- * Returns:    Nonzero if an item was actually written.
- *
- * Use:                Writes a key in a textual encoding.
- */
-
-int key_write(key_data *k, dstr *d, const key_filter *kf)
-{
-  int rc = 0;
-  if (!KEY_MATCH(k, kf))
-    return (0);
-  switch (k->e & KF_ENCMASK) {
-    case KENC_BINARY:
-    case KENC_ENCRYPT: {
-      base64_ctx b;
-
-      if ((k->e & KF_ENCMASK) == KENC_BINARY)
-       key_writeflags(k->e, d);
-      else
-       DPUTS(d, "encrypt,secret");
-      DPUTC(d, ':');
-      base64_init(&b);
-      b.indent = "";
-      b.maxline = 0;
-      base64_encode(&b, k->u.k.k, k->u.k.sz, d);
-      base64_encode(&b, 0, 0, d);
-      rc = 1;
-    } break;
-    case KENC_MP:
-      key_writeflags(k->e, d);
-      DPUTC(d, ':');
-      mp_writedstr(k->u.m, d, 10);
-      rc = 1;
-      break;
-    case KENC_STRING: {
-      const char *p = k->u.p;
-      key_writeflags(k->e, d);
-      DPUTC(d, ':');
-      while (*p) {
-       if (*p == ' ') DPUTC(d, '+');
-       else if (!isalnum((unsigned char)*p)) dstr_putf(d, "%%%02x", *p);
-       else DPUTC(d, *p);
-       p++;
-      }
-      rc = 1;
-    } break;
-    case KENC_EC:
-      key_writeflags(k->e, d);
-      DPUTS(d, ":0x"); mp_writedstr(k->u.e.x, d, 16);
-      DPUTS(d, ",0x"); mp_writedstr(k->u.e.y, d, 16);
-      rc = 1;
-      break;
-    case KENC_STRUCT: {
-      key_subkeyiter i;
-      const char *tag;
-      char del = 0;
-      size_t n = d->len;
-
-      DPUTS(d, "struct:[");
-      for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
-       size_t o = d->len;
-       if (del)
-         DPUTC(d, del);
-       DPUTS(d, tag);
-       DPUTC(d, '=');
-       if (!key_write(k, d, kf))
-         d->len = o;
-       else {
-         del = ',';
-         rc = 1;
-       }
-      }
-      if (!rc)
-       d->len = n;
-      else
-       DPUTC(d, ']');
-    } break;
-  }
-  DPUTZ(d);
-
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/key.h b/key.h
deleted file mode 100644 (file)
index dffd0eb..0000000
--- a/key.h
+++ /dev/null
@@ -1,702 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Simple key management
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_KEY_H
-#define CATACOMB_KEY_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <time.h>
-
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-#include <mLib/hash.h>
-#include <mLib/sym.h>
-
-#ifndef CATACOMB_KEY_ERROR_H
-#  include "key-error.h"
-#endif
-
-#ifndef CATACOMB_KEY_DATA_H
-#  include "key-data.h"
-#endif
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- Key attributes --- *
- *
- * Each attribute is stored as a symbol in a symbol table.  The value is
- * the plain (not url-encoded) text to be written to the the file.  If the
- * value is binary data, then by this point it's base-64 encoded.
- */
-
-typedef struct key_attr {
-  sym_base _b;                         /* Symbol table data */
-  char *p;                             /* Pointer to attribute value */
-} key_attr;
-
-/* --- Main key structure --- *
- *
- * Each key is stored in two symbol tables, one indexed by keyid, and the
- * other indexed by type.  Because many keys can have the same type, the type
- * table contains a list of keys, sorted in descending order of expiry.
- */
-
-typedef struct key {
-
-  /* --- Hashtable management --- */
-
-  hash_base _b;                                /* Symbol table data */
-  struct key *next;                    /* Next key of the same type */
-
-  /* --- Basic key attributes --- */
-
-  uint32 id;                           /* Key id used to name it */
-  char *tag;                           /* Textual tag name */
-  char *type;                          /* Textual key type */
-  time_t exp, del;                     /* Expiry times for keys */
-
-  /* --- The key data itself --- */
-
-  key_data *k;                         /* The actual key data */
-
-  /* --- Other attributes and commentary --- */
-
-  sym_table a;                         /* Hashtable of key attributes */
-  char *c;                             /* Any additional comments */
-} key;
-
-/* --- The keys-by-type entries --- */
-
-typedef struct key_ref {
-  sym_base _b;                         /* Symbol table data */
-  key *k;                              /* Pointer to first key in list */
-} key_ref;
-
-/* --- A key file --- */
-
-typedef struct key_file {
-  FILE *fp;                            /* File pointer open on file */
-  char *name;                          /* Filename used to create it */
-  unsigned f;                          /* Various useful flags */
-  hash_table byid;                     /* Table of keys by keyid */
-  sym_table bytype;                    /* Table of keys by type */
-  sym_table bytag;                     /* Table of keys by tag */
-  size_t idload;                       /* Loading on id table */
-} key_file;
-
-/* --- Key file flags --- */
-
-#define KF_WRITE 1u                    /* File opened for writing */
-#define KF_MODIFIED 2u                 /* File has been modified */
-
-/* --- Iterating over keys --- *
- *
- * Both of these are simple symbol table iterators, but they're made distinct
- * types for the dubious benefits that type safety brings.
- */
-
-typedef struct { hash_iter i; time_t t; } key_iter;
-typedef struct { sym_iter i; } key_attriter;
-
-/* --- Key fetching --- */
-
-typedef struct key_fetchdef {
-  char *name;                          /* Name of item */
-  size_t off;                          /* Offset into target structure */
-  unsigned e;                          /* Flags for the item */
-  const struct key_fetchdef *kf;       /* Substructure pointer */
-} key_fetchdef;
-
-/* --- File opening options --- */
-
-#define KOPEN_READ 0u
-#define KOPEN_WRITE 1u
-#define KOPEN_MASK 0xff
-#define KOPEN_NOFILE 0x100
-
-/* --- Various other magic numbers --- */
-
-#define KEXP_FOREVER ((time_t)-1)      /* Never expire this key */
-#define KEXP_EXPIRE ((time_t)-2)       /* Expire this key when unused */
-
-/* --- Write error codes --- */
-
-enum {
-  KWRITE_OK,                           /* Everything went fine */
-  KWRITE_FAIL = -1,                    /* Close attempt failed */
-  KWRITE_BROKEN        = -2                    /* Key ring needs manual fixing */
-};
-
-/* --- Error reporting functions for @key_merge@ and @key_open@ --- */
-
-typedef void key_reporter(const char */*file*/, int /*line*/,
-                         const char */*err*/, void */*p*/);
-
-/* --- Macros for testing expiry --- */
-
-#define KEY_EXPIRED(now, exp)                                          \
-  ((exp) == KEXP_EXPIRE || ((exp) != KEXP_FOREVER && (exp) < (now)))
-
-/*----- Reading and writing keys and files --------------------------------*/
-
-/* --- @key_merge@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure
- *             @const char *file@ = name of file (for error messages)
- *             @FILE *fp@ = file handle to read from
- *             @key_reporter *rep@ = error reporting function
- *             @void *arg@ = argument for function
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Reads keys from a file, and inserts them into the file.
- */
-
-extern int key_merge(key_file */*f*/, const char */*file*/, FILE */*fp*/,
-                    key_reporter */*rep*/, void */*arg*/);
-
-/* --- @key_extract@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure
- *             @key *k@ = key to extract
- *             @FILE *fp@ = file to write on
- *             @const key_filter *kf@ = pointer to key selection block
- *
- * Returns:    Zero if OK, EOF on error.
- *
- * Use:                Extracts a key to an ouptut file.
- */
-
-extern int key_extract(key_file */*f*/, key */*k*/, FILE */*fp*/,
-                      const key_filter */*kf*/);
-
-/* --- @key_open@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure to initialize
- *             @const char *file@ = pointer to the file name
- *             @unsigned how@ = opening options (@KOPEN_*@).
- *             @key_reporter *rep@ = error reporting function
- *             @void *arg@ = argument for function
- *
- * Returns:    Zero if it worked, nonzero otherwise.
- *
- * Use:                Opens a key file, reads its contents, and stores them in a
- *             structure.  The file is locked appropriately until closed
- *             using @key_close@.  On an error, everything is cleared away
- *             tidily.  If the file is opened with @KOPEN_WRITE@, it's
- *             created if necessary, with read and write permissions for its
- *             owner only.
- */
-
-extern int key_open(key_file */*f*/, const char */*file*/, unsigned /*how*/,
-                   key_reporter */*rep*/, void */*arg*/);
-
-/* --- @key_discard@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *
- * Returns:    ---
- *
- * Use:                Frees all the key data, without writing changes.
- */
-
-extern void key_discard(key_file */*f*/);
-
-/* --- @key_close@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *
- * Returns:    A @KWRITE_@ code indicating how it went.
- *
- * Use:                Frees all the key data, writes any changes.  Make sure that
- *             all hell breaks loose if this returns @KWRITE_BROKEN@.
- */
-
-extern int key_close(key_file */*f*/);
-
-/* --- @key_save@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *
- * Returns:    A @KWRITE_@ code indicating how well it worked.
- *
- * Use:                Writes a key file's data back to the actual file.  This code
- *             is extremely careful about error handling.  It should usually
- *             be able to back out somewhere sensible, but it can tell when
- *             it's got itself into a real pickle and starts leaving well
- *             alone.
- *
- *             Callers, please make sure that you ring alarm bells when this
- *             function returns @KWRITE_BROKEN@.
- */
-
-extern int key_save(key_file */*f*/);
-
-/* --- @key_lockfile@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file structure to initialize
- *             @const char *file@ = pointer to the file name
- *             @unsigned how@ = opening options (@KOPEN_*@).
- *
- * Returns:    Zero if it worked, nonzero otherwise.
- *
- * Use:                Opens a keyfile and stores the information needed for
- *             continued access in the structure.
- *
- *             If the file is opened with @KOPEN_WRITE@, it's created if
- *             necessary with read and write permissions for owner only, and
- *             locked for update while it's open.
- *
- *             This is a system-dependent routine, and only really intended
- *             for the private use of @key_open@.
- */
-
-extern int key_lockfile(key_file */*f*/, const char */*file*/,
-                       unsigned /*how*/);
-
-/*----- Creating and manipulating keys ------------------------------------*/
-
-/* --- @key_new@ ---
- *
- * Arguments:  @key_file *f@ = pointer to key file
- *             @uint32 id@ = keyid to set
- *             @const char *type@ = the type of this key
- *             @time_t exp@ = when the key expires
- *             @key *kk@ = where to put the key pointer
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Attaches a new key to a key file.  You must have a writable
- *             key file for this to work.
- *
- *             The type is a key type string.  This interface doesn't care
- *             about how type strings are formatted: it just treats them as
- *             opaque gobs of text.  Clients are advised to choose some
- *             standard for representing key types, though.
- *
- *             The expiry time should either be a time in the future, or the
- *             magic value @KEXP_FOREVER@ which means `never expire this
- *             key'.  Be careful with `forever' keys.  If I were you, I'd
- *             use a more sophisticated key management system than this for
- *             them.
- *
- *             You have to set the actual key yourself.
- */
-
-extern int key_new(key_file */*f*/, uint32 /*id*/, const char */*type*/,
-                  time_t /*exp*/, key **/*kk*/);
-
-/* --- @key_delete@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file block
- *             @key *k@ = key to delete
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Removes the given key from the list.  The key file must be
- *             writable.  (Due to the horridness of the data structures,
- *             deleted keys aren't actually removed, just marked so that
- *             they can't be looked up or iterated over.  One upshot of
- *             this is that they don't get written back to the file when
- *             it's closed.)
- */
-
-extern int key_delete(key_file */*f*/, key */*k*/);
-
-/* --- @key_expired@ --- *
- *
- * Arguments:  @key *k@ = pointer to key block
- *
- * Returns:    Zero if the key is OK, nonzero if it's expired.
- */
-
-int key_expired(key */*k*/);
-
-/* --- @key_expire@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file block
- *             @key *k@ = pointer to key block
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Immediately marks the key as expired.  It may be removed
- *             immediately, if it is no longer required, and will be removed
- *             by a tidy operation when it is no longer required.  The key
- *             file must be writable.
- */
-
-extern int key_expire(key_file */*f*/, key */*k*/);
-
-/* --- @key_used@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file
- *             @key *k@ = pointer to key block
- *             @time_t t@ = when key can be removed
- *
- * Returns:    Zero if OK, nonzero on failure.
- *
- * Use:                Marks a key as being required until a given time.  Even
- *             though the key may expire before then (and won't be returned
- *             by type after that time), it will still be available when
- *             requested explicitly by id.  The key file must be writable.
- *
- *             The only (current) reason for failure is attempting to use
- *             a key which can expire for something which can't.
- */
-
-extern int key_used(key_file */*f*/, key */*k*/, time_t /*t*/);
-
-/* --- @key_fingerprint@ --- *
- *
- * Arguments:  @key *k@ = the key to fingerprint
- *             @ghash *h@ = the hash to use
- *             @const key_filter *kf@ = filter to apply
- *
- * Returns:    Nonzero if the key slightly matched the filter.
- *
- * Use:                Updates the hash context with the key contents.
- */
-
-extern int key_fingerprint(key */*k*/, ghash */*h*/,
-                          const key_filter */*kf*/);
-
-/*----- Setting and reading attributes ------------------------------------*/
-
-/* --- @key_chkident@ --- *
- *
- * Arguments:  @const char *p@ = pointer to a type string
- *
- * Returns:    Zero if OK, -1 on error.
- *
- * Use:                Checks whether an identification component string is OK.
- */
-
-extern int key_chkident(const char */*p*/);
-
-/* --- @key_chkcomment@ --- *
- *
- * Arguments:  @const char *p@ = pointer to a comment string
- *
- * Returns:    Zero if OK, -1 on error.
- *
- * Use:                Checks whether a comment string is OK.
- */
-
-extern int key_chkcomment(const char */*p*/);
-
-/* --- @key_setcomment@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *             @key *k@ = pointer to key block
- *             @const char *c@ = pointer to comment to set, or zero
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Replaces the key's current comment with a new one.
- */
-
-extern int key_setcomment(key_file */*f*/, key */*k*/, const char */*c*/);
-
-/* --- @key_settag@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *             @key *k@ = pointer to key block
- *             @const char *tag@ = pointer to comment to set, or zero
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Replaces the key's current tag with a new one.
- */
-
-extern int key_settag(key_file */*f*/, key */*k*/, const char */*tag*/);
-
-/* --- @key_setkeydata@ --- *
- *
- * Arguments:  @key_file *kf@ = pointer to key file
- *             @key *k@ = pointer to key
- *             @key_data *kd@ = new key data
- *
- * Returns:    Zero on success, or a @KERR_@ error code on failure.
- *
- * Use:                Sets the key data for a key.
- */
-
-extern int key_setkeydata(key_file */*kf*/, key */*k*/, key_data */*kd*/);
-
-/* --- @key_fulltag@ --- *
- *
- * Arguments:  @key *k@ = pointer to key
- *             @dstr *d@ = pointer to destination string
- *
- * Returns:    ---
- *
- * Use:                Emits the key's full tag, which has the form
- *             `ID:TYPE[:TAG]'.  This is used in the textual file format,
- *             and to identify passphrases for locked keys.
- */
-
-extern void key_fulltag(key */*k*/, dstr */*d*/);
-
-/* --- @key_qtag@ --- *
- *
- * Arguments:  @key_file *f@ = key file to find a key from
- *             @const char *tag@ = pointer to tag string
- *             @dstr *d@ = pointer to string for full tag name
- *             @key **k@ = where to store the key pointer
- *             @key_data ***kd@ = where to store the key data pointer
- *
- * Returns:    Zero if OK, nonzero if it failed.
- *
- * Use:                Performs a full lookup on a qualified tag name.  The tag is
- *             qualified by the names of subkeys, separated by dots.  Hence,
- *             a qualified tag is ID|TAG[.TAG...].  The various result
- *             pointers can be null to indicate that the result isn't
- *             interesting.
- */
-
-extern int key_qtag(key_file */*f*/, const char */*tag*/,
-                   dstr */*d*/, key **/*k*/, key_data ***/*kd*/);
-
-/* --- @key_getattr@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file
- *             @key *k@ = pointer to key
- *             @const char *n@ = pointer to attribute name
- *
- * Returns:    Pointer to attribute value, or null if not found.
- *
- * Use:                Returns the value of a key attribute.
- */
-
-extern const char *key_getattr(key_file */*f*/, key */*k*/,
-                              const char */*n*/);
-
-/* --- @key_putattr@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to file
- *             @key *k@ = pointer to key
- *             @const char *n@ = pointer to attribute name
- *             @const char *v@ = pointer to attribute value or null
- *
- * Returns:    Error code (one of the @KERR@ constants).
- *
- * Use:                Inserts an attribute on a key.  If an attribute with the same
- *             name already exists, it is deleted.  Setting a null value
- *             removes the attribute.
- */
-
-extern int key_putattr(key_file */*f*/, key */*k*/,
-                      const char */*n*/, const char */*v*/);
-
-/* --- @key_mkattriter@ --- *
- *
- * Arguments:  @key_attriter *i@ = pointer to attribute iterator
- *             @key *k@ = pointer to key
- *
- * Returns:    ---
- *
- * Use:                Initializes an attribute iterator.  The attributes are
- *             returned by @key_nextattr@.
- */
-
-extern void key_mkattriter(key_attriter */*i*/, key */*k*/);
-
-/* --- @key_nextattr@ --- *
- *
- * Arguments:  @key_attriter *i@ = pointer to attribute iterator
- *             @const char **n, **v@ = pointers to name and value
- *
- * Returns:    Zero if no attribute available, or nonzero if returned OK.
- *
- * Use:                Returns the next attribute.
- */
-
-extern int key_nextattr(key_attriter */*i*/,
-                       const char **/*n*/, const char **/*v*/);
-
-/*----- Searching and iterating -------------------------------------------*/
-
-/* --- @key_bytype@ --- *
- *
- * Arguments:  @key_file *f@ = key file we want a key from
- *             @const char *type@ = type string for desired key
- *
- * Returns:    Pointer to the best key to use, or null.
- *
- * Use:                Looks up a key by its type.  Returns the key with the latest
- *             expiry time.  This function will not return an expired key.
- */
-
-extern key *key_bytype(key_file */*f*/, const char */*type*/);
-
-/* --- @key_byid@ --- *
- *
- * Arguments:  @key_file *f@ = key file to find a key from
- *             @uint32 id@ = id to look for
- *
- * Returns:    Key with matching id.
- *
- * Use:                Returns a key given its id.  This function will return an
- *             expired key, but not a deleted one.
- */
-
-extern key *key_byid(key_file */*f*/, uint32 /*id*/);
-
-/* --- @key_bytag@ --- *
- *
- * Arguments:  @key_file *f@ = key file to find a key from
- *             @const char *tag@ = pointer to tag string
- *
- * Returns:    Key with matching id or tag.
- *
- * Use:                Returns a key given its tag or id.  This function will return
- *             an expired key, but not a deleted one.
- */
-
-extern key *key_bytag(key_file */*f*/, const char */*tag*/);
-
-/* --- @key_mkiter@ --- *
- *
- * Arguments:  @key_iter *i@ = pointer to iterator object
- *             @key_file *f@ = pointer to file structure
- *
- * Returns:    ---
- *
- * Use:                Initializes a key iterator.  The keys are returned by
- *             @key_next@.
- */
-
-extern void key_mkiter(key_iter */*i*/, key_file */*f*/);
-
-/* --- @key_next@ --- *
- *
- * Arguments:  @key_iter *i@ = pointer to iterator object
- *
- * Returns:    Pointer to next key, or null.
- *
- * Use:                Returns the next key in some arbitrary sequence.
- */
-
-extern key *key_next(key_iter */*i*/);
-
-/*----- Fetching key data conveniently ------------------------------------*/
-
-/* --- @key_fetchinit@ --- *
- *
- * Arguments:  @const key_fetchdef *kf@ = pointer to base definition
- *             @key_packstruct *kps@ = pointer to destination packing def
- *             @void *p@ = pointer to destination block
- *
- * Returns:    Pointer to packing definition.
- *
- * Use:                Initializes a packing definition (@key_packdef@ structure).
- *             If @kps@ is null on entry, an appropriately sized block is
- *             allocated automatically.  Otherwise it must be large enough.
- */
-
-extern key_packdef *key_fetchinit(const key_fetchdef */*kf*/,
-                                 key_packstruct */*kp*/, void */*p*/);
-
-/* --- @key_fetch@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *             @key *k@ = key file containing desired key
- *
- * Returns:    Error code, or zero.
- *
- * Use:                Fetches an unpacked key from a packed one.
- */
-
-extern int key_fetch(key_packdef */*kp*/, key */*k*/);
-
-/* --- @key_fetchbyname@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *             @key_file *kf@ = key file containing desired key
- *             @const char *tag@ = user's tag describing the key
- *
- * Returns:    Error code, or zero.
- *
- * Use:                Fetches a named key from a key file and unpacks it
- *             conveniently.
- */
-
-extern int key_fetchbyname(key_packdef */*kp*/,
-                          key_file */*kf*/, const char */*tag*/);
-
-/* --- @key_fetchdone@ --- *
- *
- * Arguments:  @key_packdef *kp@ = pointer to packing structure
- *
- * Returns:    ---
- *
- * Use:                Frees a packing structure.  If the structure was allocated by
- *             @key_fetchinit@ then it is freed.
- */
-
-extern void key_fetchdone(key_packdef */*kp*/);
-
-/*----- Other functions ---------------------------------------------------*/
-
-/* --- @key_moan@ --- *
- *
- * Arguments:  @const char *file@ = name of the file
- *             @int line@ = line number in file
- *             @const char *msg@ = error message
- *             @void *p@ = argument pointer
- *
- * Returns:    ---
- *
- * Use:                Reports an error message about loading a key file.
- */
-
-extern void key_moan(const char */*file*/, int /*line*/,
-                    const char */*msg*/, void */*p*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/key/Makefile.am b/key/Makefile.am
new file mode 100644 (file)
index 0000000..b73aad8
--- /dev/null
@@ -0,0 +1,65 @@
+### -*-makefile-*-
+###
+### Build script for key management
+###
+### (c) 2013 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.
+
+include $(top_srcdir)/vars.am
+
+noinst_LTLIBRARIES      = libkey.la
+libkey_la_SOURCES       =
+
+###--------------------------------------------------------------------------
+### Component files.
+
+## Managing keys and keyring files.
+pkginclude_HEADERS     += key.h
+libkey_la_SOURCES      += key-attr.c
+libkey_la_SOURCES      += key-fetch.c
+libkey_la_SOURCES      += key-file.c
+libkey_la_SOURCES      += key-io.c
+libkey_la_SOURCES      += key-misc.c
+libkey_la_SOURCES      += key-moan.c
+
+## Managing key data.
+pkginclude_HEADERS     += key-data.h
+libkey_la_SOURCES      += key-binary.c
+libkey_la_SOURCES      += key-data.c
+libkey_la_SOURCES      += key-flags.c
+libkey_la_SOURCES      += key-pack.c
+libkey_la_SOURCES      += key-pass.c
+libkey_la_SOURCES      += key-text.c
+
+## Error reporting.
+pkginclude_HEADERS     += key-error.h
+libkey_la_SOURCES      += key-error.c
+
+## Reading passphrases.
+pkginclude_HEADERS     += passphrase.h
+libkey_la_SOURCES      += passphrase.c
+
+## Interfacing with the passphrase pixie.
+pkginclude_HEADERS     += pixie.h
+libkey_la_SOURCES      += pixie-common.c
+
+###----- That's all, folks --------------------------------------------------
diff --git a/key/key-attr.c b/key/key-attr.c
new file mode 100644 (file)
index 0000000..e884d69
--- /dev/null
@@ -0,0 +1,306 @@
+/* -*-c-*-
+ *
+ * Key attribute manipulation
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <mLib/dstr.h>
+#include <mLib/sym.h>
+
+#include "key.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_chkident@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to a type string
+ *
+ * Returns:    Zero if OK, -1 on error.
+ *
+ * Use:                Checks whether an identification component string is OK.
+ */
+
+int key_chkident(const char *p)
+{
+  if (!p || !*p || strlen(p) > 255)
+    return (-1);
+  while (*p) {
+    if (*p == ':' || *p == '.' || isspace((unsigned char)*p))
+      return (-1);
+    p++;
+  }
+  return (0);
+}
+
+/* --- @key_chkcomment@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to a comment string
+ *
+ * Returns:    Zero if OK, -1 on error.
+ *
+ * Use:                Checks whether a comment string is OK.
+ */
+
+int key_chkcomment(const char *p)
+{
+  if (!p)
+    return (0);
+  if (!*p)
+    return (-1);
+  while (*p) {
+    if (*p == '\n')
+      return (-1);
+    p++;
+  }
+  return (0);
+}
+
+/* --- @key_mkattriter@ --- *
+ *
+ * Arguments:  @key_attriter *i@ = pointer to attribute iterator
+ *             @key *k@ = pointer to key
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an attribute iterator.  The attributes are
+ *             returned by @key_nextattr@.
+ */
+
+void key_mkattriter(key_attriter *i, key *k)
+{
+  sym_mkiter(&i->i, &k->a);
+}
+
+/* --- @key_nextattr@ --- *
+ *
+ * Arguments:  @key_attriter *i@ = pointer to attribute iterator
+ *             @const char **n, **v@ = pointers to name and value
+ *
+ * Returns:    Zero if no attribute available, or nonzero if returned OK.
+ *
+ * Use:                Returns the next attribute.
+ */
+
+int key_nextattr(key_attriter *i, const char **n, const char **v)
+{
+  key_attr *a = sym_next(&i->i);
+  if (!a)
+    return (0);
+  if (n) *n = SYM_NAME(a);
+  if (v) *v = a->p;
+  return (1);
+}
+
+/* --- @key_getattr@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file
+ *             @key *k@ = pointer to key
+ *             @const char *n@ = pointer to attribute name
+ *
+ * Returns:    Pointer to attribute value, or null if not found.
+ *
+ * Use:                Returns the value of a key attribute.
+ */
+
+const char *key_getattr(key_file *f, key *k, const char *n)
+{
+  key_attr *a;
+  if ((a = sym_find(&k->a, n, -1, 0, 0)) == 0)
+    return (0);
+  return (a->p);
+}
+
+/* --- @key_putattr@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file
+ *             @key *k@ = pointer to key
+ *             @const char *n@ = pointer to attribute name
+ *             @const char *v@ = pointer to attribute value or null
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Inserts an attribute on a key.  If an attribute with the same
+ *             name already exists, it is deleted.  Setting a null value
+ *             removes the attribute.
+ */
+
+int key_putattr(key_file *f, key *k, const char *n, const char *v)
+{
+  key_attr *a;
+  unsigned found;
+
+  if (!(f->f & KF_WRITE))
+    return (KERR_READONLY);
+  if (strlen(n) > 255)
+    return (KERR_BADATTR);
+
+  if (v) {
+    a = sym_find(&k->a, n, -1, sizeof(*a), &found);
+    if (found)
+      xfree(a->p);
+    a->p = xstrdup(v);
+  } else if ((a = sym_find(&k->a, n, -1, 0, 0)) != 0) {
+    xfree(a->p);
+    sym_remove(&k->a, a);
+  }
+
+  f->f |= KF_MODIFIED;
+  return (0);
+}
+
+/* --- @key_setkeydata@ --- *
+ *
+ * Arguments:  @key_file *kf@ = pointer to key file
+ *             @key *k@ = pointer to key
+ *             @key_data *kd@ = new key data
+ *
+ * Returns:    Zero on success, or a @KERR_@ error code on failure.
+ *
+ * Use:                Sets the key data for a key.
+ */
+
+int key_setkeydata(key_file *kf, key *k, key_data *kd)
+{
+  if (!(kf->f & KF_WRITE))
+    return (KERR_READONLY);
+  key_incref(kd);
+  key_drop(k->k);
+  k->k = kd;
+  kf->f |= KF_MODIFIED;
+  return (0);
+}
+
+/* --- @key_setcomment@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *             @key *k@ = pointer to key block
+ *             @const char *c@ = pointer to comment to set, or zero
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Replaces the key's current comment with a new one.
+ */
+
+int key_setcomment(key_file *f, key *k, const char *c)
+{
+  if (!(f->f & KF_WRITE))
+    return (KERR_READONLY);
+  if (key_chkcomment(c))
+    return (KERR_BADCOMMENT);
+  if (k->c)
+    xfree(k->c);
+  if (c)
+    k->c = xstrdup(c);
+  else
+    k->c = 0;
+  f->f |= KF_MODIFIED;
+  return (0);
+}
+
+/* --- @key_settag@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *             @key *k@ = pointer to key block
+ *             @const char *tag@ = pointer to comment to set, or zero
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Replaces the key's current tag with a new one.
+ */
+
+int key_settag(key_file *f, key *k, const char *tag)
+{
+  key_ref *kr;
+  unsigned found;
+
+  if (!(f->f & KF_WRITE))
+    return (KERR_READONLY);
+
+  /* --- Make sure the tag is OK --- */
+
+  if (tag && key_chkident(tag))
+    return (KERR_BADTAG);
+
+  /* --- See if the new tag is the same as the old one --- */
+
+  if ((!tag && !k->tag) ||
+      (tag && k->tag && strcmp(tag, k->tag) == 0))
+    return (0);
+
+  /* --- Allocate an entry for the new tag --- */
+
+  if (tag) {
+    kr = sym_find(&f->bytag, tag, -1, sizeof(*kr), &found);
+    if (found && !KEY_EXPIRED(time(0), kr->k->del))
+      return (KERR_DUPTAG);
+    kr->k = k;
+  }
+
+  /* --- Remove any existing tag --- */
+
+  if (k->tag) {
+    kr = sym_find(&f->bytag, k->tag, -1, 0, 0);
+    assert(((void)"No bytag link", kr));
+    sym_remove(&f->bytag, kr);
+    xfree(k->tag);
+  }
+
+  /* --- Done --- */
+
+  f->f |= KF_MODIFIED;
+  if (tag)
+    k->tag = xstrdup(tag);
+  else
+    k->tag = 0;
+  return (0);
+}
+
+/* --- @key_fulltag@ --- *
+ *
+ * Arguments:  @key *k@ = pointer to key
+ *             @dstr *d@ = pointer to destination string
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits the key's full tag, which has the form
+ *             `ID:TYPE[:TAG]'.  This is used in the textual file format,
+ *             and to identify passphrases for locked keys.
+ */
+
+void key_fulltag(key *k, dstr *d)
+{
+  dstr_putf(d, "%08lx:%s", (unsigned long)k->id, k->type);
+  if (k->tag)
+    dstr_putf(d, ":%s", k->tag);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-binary.c b/key/key-binary.c
new file mode 100644 (file)
index 0000000..046819a
--- /dev/null
@@ -0,0 +1,314 @@
+/* -*-c-*-
+ *
+ * Key binary encoding
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+#include <mLib/sub.h>
+#include <mLib/sym.h>
+
+#include "key-data.h"
+#include "mp.h"
+#include "mptext.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_decode@ --- *
+ *
+ * Arguments:  @const void *p@ = pointer to buffer to read
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    The newly-read key data, or null if it failed.
+ *
+ * Use:                Decodes a binary representation of a key.
+ */
+
+key_data *key_decode(const void *p, size_t sz)
+{
+  const octet *q = p;
+  size_t psz;
+  key_data *kd;
+  unsigned e;
+
+  /* --- Parse the header information --- *
+   *
+   * Make sure the size matches external reality.  Security holes have been
+   * known to creep in without this sort of check.  (No, this isn't an after-
+   * the-fact patch-up.)
+   */
+
+  e = LOAD16(q);
+  psz = LOAD16(q + 2);
+  if (psz + 4 > sz)
+    return (0);
+
+  /* --- Now decide what to do --- */
+
+  switch (e & KF_ENCMASK) {
+
+    /* --- Plain binary data --- */
+
+    case KENC_BINARY:
+    case KENC_ENCRYPT:
+      kd = key_newbinary(e, q + 4, psz);
+      break;
+
+    /* --- Multiprecision integer data --- */
+
+    case KENC_MP:
+      kd = key_newmp(e, mp_loadb(e & KF_BURN ? MP_NEWSEC : MP_NEW,
+                                q + 4, psz));
+      break;
+
+    /* --- String data --- */
+
+    case KENC_STRING:
+      kd = key_newraw(e);
+      kd->u.p = xmalloc(sz + 1);
+      memcpy(kd->u.p, q + 4, sz);
+      kd->u.p[sz] = 0;
+      break;
+
+    /* --- Elliptic curve point data --- */
+
+    case KENC_EC: {
+      size_t xsz, ysz;
+      kd = key_newraw(e);
+      EC_CREATE(&kd->u.e);
+      if (!sz) break;
+      if (sz < 2) return (0);
+      xsz = LOAD16(q + 4);
+      if (sz < xsz + 4) return (0);
+      ysz = LOAD16(q + 6 + xsz);
+      if (sz < xsz + ysz + 4) return (0);
+      kd->u.e.x = mp_loadb(MP_NEW, q + 6, xsz);
+      kd->u.e.y = mp_loadb(MP_NEW, q + 8 + xsz, ysz);
+    } break;
+
+    /* --- Structured key data --- */
+
+    case KENC_STRUCT: {
+      dstr d = DSTR_INIT;
+      key_data *nkd;
+
+      if ((e & ~KF_ENCMASK) || (psz & 3))
+       return (0);
+      q += 4;
+      kd = key_newstruct();
+
+      while (psz) {
+
+       /* --- Read the tag string --- */
+
+       DRESET(&d);
+       sz = LOAD8(q);
+       if (sz >= psz)
+         goto fail;
+       DPUTM(&d, q + 1, sz);
+       DPUTZ(&d);
+       sz = (sz + 4) & ~3;
+       q += sz; psz -= sz;
+
+       /* --- Read the encoding and size --- */
+
+       sz = (LOAD16(q + 2) + 7) & ~3;
+       if (sz > psz)
+         goto fail;
+
+       /* --- Create a table node and fill it in --- */
+
+       if ((nkd = key_decode(q, sz)) == 0)
+         goto fail;
+       key_structsteal(kd, d.buf, nkd);
+       psz -= sz;
+       q += sz;
+      }
+      dstr_destroy(&d);
+      break;
+
+      /* --- Tidy up after a failure --- */
+
+    fail:
+      dstr_destroy(&d);
+      key_drop(kd);
+      return (0);
+    } break;
+
+    /* --- Everything else --- */
+
+    default:
+      return (0);
+  }
+
+  /* --- OK, that was good --- */
+
+  kd->e = e;
+  return (kd);
+}
+
+/* --- @key_encode@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @dstr *d@ = pointer to destination string
+ *             @const key_filter *kf@ = pointer to key selection block
+ *
+ * Returns:    Nonzero if an item was actually written.
+ *
+ * Use:                Encodes a key block as binary data.
+ */
+
+static int ksbyname(const void *a, const void *b) {
+  key_struct *const *x = a, *const *y = b;
+  return (strcmp(SYM_NAME(*x), SYM_NAME(*y)));
+}
+
+int key_encode(key_data *k, dstr *d, const key_filter *kf)
+{
+  int rc = 0;
+  if (!KEY_MATCH(k, kf))
+    return (0);
+  switch (k->e & KF_ENCMASK) {
+    case KENC_BINARY:
+    case KENC_ENCRYPT: {
+      char *p;
+
+      DENSURE(d, (k->u.k.sz + 7) & ~3);
+      p = d->buf + d->len;
+      STORE16(p, k->e);
+      STORE16(p + 2, k->u.k.sz);
+      d->len += 4;
+      DPUTM(d, k->u.k.k, k->u.k.sz);
+      rc = 1;
+    } break;
+
+    case KENC_MP: {
+      char *p;
+      size_t sz = mp_octets(k->u.m);
+
+      DENSURE(d, (sz + 7) & ~3);
+      p = d->buf + d->len;
+      STORE16(p, k->e);
+      STORE16(p + 2, sz);
+      mp_storeb(k->u.m, p + 4, sz);
+      d->len += sz + 4;
+      rc = 1;
+    } break;
+
+    case KENC_STRING: {
+      char *p;
+      size_t sz = strlen(k->u.p);
+
+      DENSURE(d, (sz + 7) & ~3);
+      p = d->buf + d->len;
+      STORE16(p, k->e);
+      STORE16(p + 2, sz);
+      memcpy(p + 4, k->u.p, sz);
+      d->len += sz + 4;
+      rc = 1;
+    } break;
+
+    case KENC_EC: {
+      char *p;
+      size_t xsz = 0, ysz = 0;
+      size_t sz;
+
+      if (EC_ATINF(&k->u.e))
+       sz = 0;
+      else {
+       xsz = mp_octets(k->u.e.x);
+       ysz = mp_octets(k->u.e.y);
+       sz = xsz + ysz + 4;
+      }
+      DENSURE(d, (sz + 7) & ~3);
+      p = d->buf + d->len;
+      STORE16(p, k->e);
+      STORE16(p + 2, sz);
+      if (!EC_ATINF(&k->u.e)) {
+       STORE16(p + 4, xsz);
+       mp_storeb(k->u.e.x, p + 6, xsz);
+       STORE16(p + 6 + xsz, ysz);
+       mp_storeb(k->u.e.y, p + 8 + xsz, ysz);
+      }
+      d->len += sz + 4;
+      rc = 1;
+    } break;
+
+    case KENC_STRUCT: {
+      size_t n;
+      char *p;
+      key_struct *ks, **ksv;
+      size_t nks, j;
+      sym_iter i;
+
+      n = d->len;
+      DENSURE(d, 4);
+      p = d->buf + n;
+      STORE16(p, k->e & KF_ENCMASK);
+      d->len += 4;
+
+      for (nks = 0, sym_mkiter(&i, &k->u.s);
+          (ks = sym_next(&i)) != 0;
+          nks++);
+      if (nks) {
+       ksv = xmalloc(nks * sizeof(*ksv));
+       for (j = 0, sym_mkiter(&i, &k->u.s); (ks = sym_next(&i)) != 0; j++)
+         ksv[j] = ks;
+       qsort(ksv, nks, sizeof(*ksv), ksbyname);
+       for (j = 0; j < nks; j++) {
+         size_t o = d->len;
+         ks = ksv[j];
+         DENSURE(d, 1);
+         *(octet *)(d->buf + d->len++) = strlen(SYM_NAME(ks));
+         DPUTS(d, SYM_NAME(ks));
+         while (d->len & 3)
+           DPUTC(d, 0);
+         if (key_encode(ks->k, d, kf))
+           rc = 1;
+         else
+           d->len = o;
+       }
+       xfree(ksv);
+      }
+      if (!rc)
+       d->len = n;
+      else {
+       p = d->buf + n + 2;
+       n = d->len - n - 4;
+       STORE16(p,  n);
+      }
+    } break;
+  }
+  while (d->len & 3)
+    DPUTC(d, 0);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-data.c b/key/key-data.c
new file mode 100644 (file)
index 0000000..8b01d72
--- /dev/null
@@ -0,0 +1,467 @@
+/* -*-c-*-
+ *
+ * Encoding and decoding of key data
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/base64.h>
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+#include <mLib/sub.h>
+#include <mLib/sym.h>
+
+#include "key-data.h"
+#include "mp.h"
+#include "mptext.h"
+
+/*----- Reference counting stuff ------------------------------------------*/
+
+/* --- @key_incref@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data
+ *
+ * Returns:    ---
+ *
+ * Use:                Increments the refcount on a key data block.
+ */
+
+void key_incref(key_data *k) { KEY_INCREF(k); }
+
+/* --- @key_destroy@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a block of key data, regardless of reference count.
+ *             Don't use this unless you know what you're doing.
+ */
+
+void key_destroy(key_data *k)
+{
+  switch (k->e & KF_ENCMASK) {
+    case KENC_BINARY:
+    case KENC_ENCRYPT:
+      if (k->u.k.k) {
+       if (k->e & KF_BURN)
+         memset(k->u.k.k, 0, k->u.k.sz);
+       sub_free(k->u.k.k, k->u.k.sz);
+      }
+      break;
+    case KENC_MP:
+      mp_drop(k->u.m);
+      break;
+    case KENC_STRING:
+      xfree(k->u.p);
+      break;
+    case KENC_EC:
+      EC_DESTROY(&k->u.e);
+      break;
+    case KENC_STRUCT: {
+      key_data *kd;
+      key_subkeyiter i;
+
+      for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &kd); )
+       KEY_DROP(kd);
+      sym_destroy(&k->u.s);
+    } break;
+    default:
+      abort();
+  }
+  DESTROY(k);
+}
+
+/* --- @key_drop@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Drops a reference to key data, destroying it if necessary.
+ */
+
+void key_drop(key_data *k) { KEY_DROP(k); }
+
+/* --- @key_split@ --- *
+ *
+ * Arguments:  @key_data **kk@ = address of pointer to key data block
+ *
+ * Returns:    ---
+ *
+ * Use:                Replaces @*kk@ with a pointer to the same key data, but with
+ *             just one reference.
+ */
+
+void key_split(key_data **kk)
+{
+  key_data *k = *kk;
+
+  if (k->ref == 1)
+    return;
+  switch (k->e & KF_ENCMASK) {
+    case KENC_BINARY:
+      *kk = key_newbinary(k->e, k->u.k.k, k->u.k.sz);
+      break;
+    case KENC_ENCRYPT:
+      *kk = key_newencrypted(k->e, k->u.k.k, k->u.k.sz);
+      break;
+    case KENC_MP:
+      *kk = key_newmp(k->e, k->u.m);
+      break;
+    case KENC_STRING:
+      *kk = key_newstring(k->e, k->u.p);
+      break;
+    case KENC_EC:
+      *kk = key_newec(k->e, &k->u.e);
+      break;
+    case KENC_STRUCT: {
+      key_subkeyiter i;
+      const char *tag;
+      key_data *kd;
+
+      *kk = key_newstruct();
+      for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); )
+       key_structset(*kk, tag, kd);
+    } break;
+    default:
+      abort();
+  }
+}
+
+/*----- Setting new values ------------------------------------------------*/
+
+/* --- @key_newraw@ --- *
+ *
+ * Arguments:  @unsigned e@ = encoding type to set
+ *
+ * Returns:    New key block, not filled in.
+ */
+
+key_data *key_newraw(unsigned e)
+{
+  key_data *k = CREATE(key_data);
+  k->e = e;
+  k->ref = 1;
+  return (k);
+}
+
+/* --- @key_newbinary@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @const void *p@ = pointer to key data
+ *             @size_t sz@ = size of the key data
+ *
+ * Returns:    New key data object.
+ */
+
+key_data *key_newbinary(unsigned e, const void *p, size_t sz)
+{
+  key_data *k = key_newraw(KENC_BINARY | e);
+  k->u.k.k = sub_alloc(sz);
+  memcpy(k->u.k.k, p, sz);
+  k->u.k.sz = sz;
+  return (k);
+}
+
+/* --- @key_newencrypted@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @const void *p@ = pointer to key data
+ *             @size_t sz@ = size of the key data
+ *
+ * Returns:    New key data object.
+ */
+
+key_data *key_newencrypted(unsigned e, const void *p, size_t sz)
+{
+  key_data *k = key_newraw(KENC_ENCRYPT | e);
+  k->u.k.k = sub_alloc(sz);
+  memcpy(k->u.k.k, p, sz);
+  k->u.k.sz = sz;
+  return (k);
+}
+
+/* --- @key_newmp@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @mp *m@ = pointer to the value to set
+ *
+ * Returns:    New key data object.
+ */
+
+key_data *key_newmp(unsigned e, mp *m)
+{
+  key_data *k = key_newraw(KENC_MP | e);
+  k->u.m = MP_COPY(m);
+  return (k);
+}
+
+/* --- @key_newstring@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @const char *p@ = pointer to the value to set
+ *
+ * Returns:    New key data object.
+ */
+
+key_data *key_newstring(unsigned e, const char *p)
+{
+  key_data *k = key_newraw(KENC_STRING | e);
+  k->u.p = xstrdup(p);
+  return (k);
+}
+
+/* --- @key_newec@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @const ec *pt@ = pointer to the value to set
+ *
+ * Returns:    New key data object.
+ */
+
+key_data *key_newec(unsigned e, const ec *pt)
+{
+  key_data *k = key_newraw(KENC_EC | e);
+  EC_CREATE(&k->u.e);
+  EC_COPY(&k->u.e, pt);
+  return (k);
+}
+
+/* --- @key_newstruct@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    New key data object.
+ */
+
+key_data *key_newstruct(void)
+{
+  key_data *k = key_newraw(KENC_STRUCT);
+  sym_create(&k->u.s);
+  return (k);
+}
+
+/* --- @key_structfind@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const char *tag@ = pointer to tag string
+ *
+ * Returns:    Pointer to key data block, or null.
+ *
+ * Use:                Looks up the tag in a structured key.
+ */
+
+key_data *key_structfind(key_data *k, const char *tag)
+{
+  key_struct *ks;
+  assert(((void)"Key is not structured",
+         (k->e & KF_ENCMASK) == KENC_STRUCT));
+  ks = sym_find(&k->u.s, tag, -1, 0, 0);
+  if (!ks)
+    return (0);
+  return (ks->k);
+}
+
+/* --- @key_mksubkeyiter@ --- *
+ *
+ * Arguments:  @key_subkeyiter *i@ = pointer to iterator block
+ *             @key_data *k@ = pointer to key data block
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a subkey iterator.
+ */
+
+void key_mksubkeyiter(key_subkeyiter *i, key_data *k)
+{
+  assert(((void)"Key is not structured",
+         (k->e & KF_ENCMASK) == KENC_STRUCT));
+  sym_mkiter(&i->i, &k->u.s);
+}
+
+/* --- @key_nextsubkey@ --- *
+ *
+ * Arguments:  @key_structiter *i@ = pointer to iterator block
+ *             @const char **tag@ = where to put the tag pointer, or null
+ *             @key_data **kd@ = where to put the key data pointer, or null
+ *
+ * Returns:    Nonzero if there was another item, zero if we hit the
+ *             end-stop.
+ *
+ * Use:                Collects the next subkey of a structured key.
+ */
+
+int key_nextsubkey(key_subkeyiter *i, const char **tag, key_data **kd)
+{
+  key_struct *ks;
+
+  if ((ks = sym_next(&i->i)) == 0)
+    return (0);
+  if (tag) *tag = SYM_NAME(ks);
+  if (kd) *kd = ks->k;
+  return (1);
+}
+
+/* --- @key_structset@, @key_structsteal@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const char *tag@ = pointer to tag string
+ *             @key_data *kd@ = new key data to store
+ *
+ * Returns:    ---
+ *
+ * Use:                Creates a new subkey.  Stealing doesn't affect @kd@'s
+ *             refcount.  If @kd@ is null, the subkey is deleted.
+ */
+
+static void structset(key_data *k, int stealp,
+                     const char *tag, key_data *kd)
+{
+  key_struct *ks;
+  unsigned f;
+
+  assert(((void)"Key is not structured", k->e == KENC_STRUCT));
+  assert(((void)"Key has multiple references", k->ref == 1));
+  if (!kd) {
+    ks = sym_find(&k->u.s, tag, -1, 0, 0);
+    if (ks) sym_remove(&k->u.s, ks);
+  } else {
+    ks = sym_find(&k->u.s, tag, -1, sizeof(*ks), &f);
+    if (f)
+      key_drop(ks->k);
+    if (!stealp) KEY_INCREF(kd);
+    ks->k = kd;
+  }
+}
+
+void key_structset(key_data *k, const char *tag, key_data *kd)
+  { structset(k, 0, tag, kd); }
+void key_structsteal(key_data *k, const char *tag, key_data *kd)
+  { structset(k, 1, tag, kd); }
+
+/*----- Miscellaneous operations ------------------------------------------*/
+
+/* --- @key_do@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const key_filter *kf@ = pointer to filter block
+ *             @dstr *d@ = pointer to base string
+ *             @int (*func)(key_data *kd, dstr *d, void *p@ = function
+ *             @void *p@ = argument to function
+ *
+ * Returns:    Nonzero return code from function, or zero.
+ *
+ * Use:                Runs a function over all the leaves of a key.
+ */
+
+int key_do(key_data *k, const key_filter *kf, dstr *d,
+          int (*func)(key_data */*kd*/, dstr */*d*/, void */*p*/),
+          void *p)
+{
+  if (!KEY_MATCH(k, kf))
+    return (0);
+  if ((k->e & KF_ENCMASK) != KENC_STRUCT)
+    return (func(k, d, p));
+  else {
+    key_subkeyiter i;
+    const char *tag;
+    size_t n = 0;
+    int rc;
+
+    if (d)
+      n = d->len;
+    for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
+      if (d) {
+       d->len = n;
+       dstr_putf(d, ".%s", tag);
+      }
+      if ((rc = key_do(k, kf, d, func, p)) != 0)
+       return (rc);
+    }
+    return (0);
+  }
+}
+
+/* --- @key_copydata@ --- *
+ *
+ * Arguments:  @key_data *k@ = key data to copy
+ *             @const key_filter *kf@ = pointer to filter block
+ *
+ * Returns:    Pointer to a copy of the data, or null if the root subkey
+ *             didn't match the filter.
+ *
+ * Use:                Copies a chunk of key data.  Subkeys, whether they're
+ *             structured or leaves, which don't match the filter aren't
+ *             copied.  The copy may or may not have structure in common
+ *             with the original.
+ */
+
+static int structmatchp(key_data *k, const key_filter *kf)
+{
+  key_subkeyiter i;
+
+  if (!KEY_MATCH(k, kf)) return (0);
+  else if ((k->e & KF_ENCMASK) == KENC_STRUCT) return (1);
+  else {
+    for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &k); )
+      if (!structmatchp(k, kf)) return (0);
+    return (1);
+  }
+}
+
+key_data *key_copydata(key_data *k, const key_filter *kf)
+{
+  key_subkeyiter i;
+  const char *tag;
+  key_data *kd, *kkd;
+
+  /* --- Trivial cases --- */
+
+  if (!KEY_MATCH(k, kf))
+    return (0);
+  else if (structmatchp(k, kf)) {
+    key_incref(k);
+    return (k);
+  }
+
+  /* --- Copy a structured key recursively --- */
+
+  kkd = key_newstruct();
+  for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
+    if ((kd = key_copydata(kd, kf)) != 0)
+      key_structsteal(kkd, tag, kd);
+  }
+
+  /* --- Done --- */
+
+  return (kkd);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-data.h b/key/key-data.h
new file mode 100644 (file)
index 0000000..9c00908
--- /dev/null
@@ -0,0 +1,592 @@
+/* -*-c-*-
+ *
+ * Manipulating key data
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_KEY_DATA_H
+#define CATACOMB_KEY_DATA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+#include <mLib/sym.h>
+
+#ifndef CATACOMB_KEY_ERROR_H
+#  include "key-error.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- Key binary data --- */
+
+typedef struct key_bin {
+  octet *k;                            /* Pointer to key data */
+  size_t sz;                           /* Size of the key data (in bytes) */
+} key_bin;
+
+/* --- Key data structure --- */
+
+typedef struct key_data {
+  unsigned e;                          /* Encoding type for key data */
+  unsigned ref;                                /* Reference counter */
+  union {
+    key_bin k;                         /* Binary key data */
+    mp *m;                             /* Multiprecision integer */
+    sym_table s;                       /* Structured key data */
+    char *p;                           /* String pointer */
+    ec e;                              /* Elliptic curve point */
+  } u;
+} key_data;
+
+typedef struct key_struct {
+  sym_base _b;
+  key_data *k;
+} key_struct;
+
+typedef struct key_subkeyiter { sym_iter i; } key_subkeyiter;
+
+/* --- Packing and unpacking --- */
+
+typedef struct key_packdef {
+  unsigned e;                          /* Key data encoding type */
+  void *p;                             /* Pointer to the destination */
+  key_data *kd;                                /* Key data block */
+} key_packdef;
+
+typedef struct key_packstruct {
+  char *name;                          /* Pointer to name string */
+  key_packdef kp;                      /* Packing structure */
+} key_packstruct;
+
+/* --- Key binary encoding --- *
+ *
+ * The binary encoding consists of a header containing a 16-bit encoding type
+ * and a 16-bit length, followed immediately by the key data, followed by
+ * between zero and three zero bytes to make the total length a multiple of
+ * four.  The format of the following data depends on the encoding type:
+ *
+ * @KENC_BINARY@       Binary data.
+ *
+ * @KENC_MP@           Octet array interpreted in big-endian byte order.
+ *
+ * @KENC_STRUCT@       An array of pairs, each containing a string (8-bit
+ *                     length followed by data and zero-padding to 4-byte
+ *                     boundary) and key binary encodings.
+ *
+ * @KENC_ENCRYPT@      Binary data, format
+ */
+
+/* --- Key encoding methods and other flags--- */
+
+enum {
+
+  /* --- Bottom two bits are the encoding type --- */
+
+  KF_ENCMASK   = 0x83,                 /* Encoding mask */
+  KENC_BINARY  = 0x00,                 /* Plain binary key (@k@) */
+  KENC_MP      = 0x01,                 /* Multiprecision integer (@i@) */
+  KENC_STRUCT  = 0x02,                 /* Structured key data (@s@) */
+  KENC_ENCRYPT = 0x03,                 /* Encrypted key type (@k@) */
+  KENC_STRING  = 0x80,                 /* ASCII string (@p@) */
+  KENC_EC      = 0x81,                 /* Elliptic curve point (@e@) */
+
+  /* --- Key category bits --- */
+
+  KF_CATMASK   = 0x0c,                 /* Category mask */
+  KCAT_SYMM    = 0x00,                 /* Symmetric encryption key */
+  KCAT_PRIV    = 0x04,                 /* Private (asymmetric) key */
+  KCAT_PUB     = 0x08,                 /* Public (asymmetric) key */
+  KCAT_SHARE   = 0x0c,                 /* Shared (asymmetric) key */
+  KF_NONSECRET = 0x08,                 /* Bit flag for non-secret keys */
+
+  /* --- Other flags --- */
+
+  KF_BURN      = 0x10,                 /* Burn key after use */
+  KF_OPT       = 0x20,                 /* Optional key (for @key_unpack@) */
+
+  /* --- Tag end --- */
+
+  KENC_MAX                             /* Dummy limit constant */
+};
+
+/* --- Key locking return codes --- */
+
+#define KL_OK 0                                /* All good */
+#define KL_IOERR -1                    /* I/O problem (e.g., getting pp) */
+#define KL_KEYERR -2                   /* Wrong key supplied */
+#define KL_DATAERR -3                  /* Data format error */
+
+/* --- Key flag filtering --- */
+
+typedef struct key_filter {
+  unsigned f;
+  unsigned m;
+} key_filter;
+
+/* --- Matching aginst key selection --- */
+
+#define KEY_MATCH(kd, kf)                                              \
+  (!(kf) ||                                                            \
+   ((kd)->e & KF_ENCMASK) == KENC_STRUCT ||                            \
+   ((kd)->e & (kf)->m) == (kf)->f)
+
+/*----- Key flags and filtering -------------------------------------------*/
+
+/* --- @key_readflags@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to string to read
+ *             @char **pp@ = where to store the end pointer
+ *             @unsigned *ff@ = where to store the flags
+ *             @unsigned *mm@ = where to store the mask
+ *
+ * Returns:    Zero if all went well, nonzero if there was an error.
+ *
+ * Use:                Reads a flag string.
+ */
+
+extern int key_readflags(const char */*p*/, char **/*pp*/,
+                        unsigned */*ff*/, unsigned */*mm*/);
+
+/* --- @key_writeflags@ --- *
+ *
+ * Arguments:  @unsigned f@ = flags to write
+ *             @dstr *d@ = pointer to destination string
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits a flags word as a string representation.
+ */
+
+extern void key_writeflags(unsigned /*f*/, dstr */*d*/);
+
+/* --- @key_match@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const key_filter *kf@ = pointer to filter block
+ *
+ * Returns:    Nonzero if the key matches the filter.
+ *
+ * Use:                Checks whether a key matches a filter.
+ */
+
+extern int key_match(key_data */*k*/, const key_filter */*kf*/);
+
+/*----- Setting new key data ----------------------------------------------*/
+
+/* --- @key_newraw@ --- *
+ *
+ * Arguments:  @unsigned e@ = encoding type to set
+ *
+ * Returns:    New key block, not filled in.
+ */
+
+extern key_data *key_newraw(unsigned /*e*/);
+
+/* --- @key_newbinary@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @const void *p@ = pointer to key data
+ *             @size_t sz@ = size of the key data
+ *
+ * Returns:    New key data object.
+ */
+
+extern key_data *key_newbinary(unsigned /*e*/,
+                              const void */*p*/, size_t /*sz*/);
+
+/* --- @key_newencrypted@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @const void *p@ = pointer to key data
+ *             @size_t sz@ = size of the key data
+ *
+ * Returns:    New key data object.
+ */
+
+extern key_data *key_newencrypted(unsigned /*e*/,
+                                 const void */*p*/, size_t /*sz*/);
+
+/* --- @key_newmp@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @mp *m@ = pointer to the value to set
+ *
+ * Returns:    New key data object.
+ */
+
+extern key_data *key_newmp(unsigned /*e*/, mp */*m*/);
+
+/* --- @key_newstring@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @const char *p@ = pointer to the value to set
+ *
+ * Returns:    New key data object.
+ */
+
+extern key_data *key_newstring(unsigned /*e*/, const char */*p*/);
+
+/* --- @key_newec@ --- *
+ *
+ * Arguments:  @unsigned e@ = other encoding flags
+ *             @const ec *pt@ = pointer to the value to set
+ *
+ * Returns:    New key data object.
+ */
+
+extern key_data *key_newec(unsigned /*e*/, const ec */*pt*/);
+
+/* --- @key_newstruct@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    New key data object.
+ */
+
+extern key_data *key_newstruct(void);
+
+/* --- @key_structfind@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const char *tag@ = pointer to tag string
+ *
+ * Returns:    Pointer to key data block, or null.
+ *
+ * Use:                Looks up the tag in a structured key.
+ */
+
+extern key_data *key_structfind(key_data */*k*/, const char */*tag*/);
+
+/* --- @key_mksubkeyiter@ --- *
+ *
+ * Arguments:  @key_subkeyiter *i@ = pointer to iterator block
+ *             @key_data *k@ = pointer to key data block
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a subkey iterator.
+ */
+
+extern void key_mksubkeyiter(key_subkeyiter */*i*/, key_data */*k*/);
+
+/* --- @key_nextsubkey@ --- *
+ *
+ * Arguments:  @key_structiter *i@ = pointer to iterator block
+ *             @const char **tag@ = where to put the tag pointer, or null
+ *             @key_data **kd@ = where to put the key data pointer, or null
+ *
+ * Returns:    Nonzero if there was another item, zero if we hit the
+ *             end-stop.
+ *
+ * Use:                Collects the next subkey of a structured key.
+ */
+
+extern int key_nextsubkey(key_subkeyiter */*i*/,
+                         const char **/*tag*/, key_data **/*kd*/);
+
+/* --- @key_structset@, @key_structsteal@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const char *tag@ = pointer to tag string
+ *             @key_data *kd@ = new key data to store
+ *
+ * Returns:    ---
+ *
+ * Use:                Creates a new subkey.  Stealing doesn't affect @kd@'s
+ *             refcount.  If @kd@ is null, the subkey is deleted.
+ */
+
+extern void key_structset(key_data */*k*/,
+                         const char */*tag*/, key_data */*kd*/);
+extern void key_structsteal(key_data */*k*/,
+                           const char */*tag*/, key_data */*kd*/);
+
+/* --- @key_split@ --- *
+ *
+ * Arguments:  @key_data **kk@ = address of pointer to key data block
+ *
+ * Returns:    ---
+ *
+ * Use:                Replaces @*kk@ with a pointer to the same key data, but with
+ *             just one reference.
+ */
+
+extern void key_split(key_data **/*kk*/);
+
+/*----- Miscellaneous operations ------------------------------------------*/
+
+/* --- @key_incref@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data
+ *
+ * Returns:    ---
+ *
+ * Use:                Increments the refcount on a key data block.
+ */
+
+#define KEY_INCREF(k) ((k)->ref++)
+extern void key_incref(key_data */*k*/);
+
+/* --- @key_destroy@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a block of key data, regardless of reference count.
+ *             Don't use this unless you know what you're doing.
+ */
+
+extern void key_destroy(key_data */*k*/);
+
+/* --- @key_drop@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Drops a reference to key data, destroying it if necessary.
+ */
+
+#define KEY_DROP(k) do {                                               \
+  key_data *_k = k;                                                    \
+  _k->ref--;                                                           \
+  if (_k->ref == 0)                                                    \
+    key_destroy(_k);                                                   \
+} while (0)
+
+extern void key_drop(key_data */*k*/);
+
+/* --- @key_do@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const key_filter *kf@ = pointer to filter block
+ *             @dstr *d@ = pointer to base string
+ *             @int (*func)(key_data *kd, dstr *d, void *p@ = function
+ *             @void *p@ = argument to function
+ *
+ * Returns:    Nonzero return code from function, or zero.
+ *
+ * Use:                Runs a function over all the leaves of a key.
+ */
+
+extern int key_do(key_data */*k*/, const key_filter */*kf*/, dstr */*d*/,
+                 int (*/*func*/)(key_data */*kd*/,
+                                 dstr */*d*/, void */*p*/),
+                 void */*p*/);
+
+/* --- @key_copydata@ --- *
+ *
+ * Arguments:  @key_data *k@ = key data to copy
+ *             @const key_filter *kf@ = pointer to filter block
+ *
+ * Returns:    Pointer to a copy of the data, or null if the root subkey
+ *             didn't match the filter.
+ *
+ * Use:                Copies a chunk of key data.  Subkeys, whether they're
+ *             structured or leaves, which don't match the filter aren't
+ *             copied.  The copy may or may not have structure in common
+ *             with the original.
+ */
+
+extern key_data *key_copydata(key_data */*k*/, const key_filter */*kf*/);
+
+/*----- Textual encoding --------------------------------------------------*/
+
+/* --- @key_read@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to textual key representation
+ *             @char **pp@ = where to store the end pointer
+ *
+ * Returns:    The newly-read key data, or null if it failed.
+ *
+ * Use:                Parses a textual key description.
+ */
+
+extern key_data *key_read(const char */*p*/, char **/*pp*/);
+
+/* --- @key_write@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data
+ *             @dstr *d@ = destination string to write on
+ *             @const key_filter *kf@ = pointer to key selection block
+ *
+ * Returns:    Nonzero if any items were actually written.
+ *
+ * Use:                Writes a key in a textual encoding.
+ */
+
+extern int key_write(key_data */*k*/, dstr */*d*/, const key_filter */*kf*/);
+
+/*----- Key binary encoding -----------------------------------------------*/
+
+/* --- @key_decode@ --- *
+ *
+ * Arguments:  @const void *p@ = pointer to buffer to read
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    The newly-read key data, or null if it failed.
+ *
+ * Use:                Decodes a binary representation of a key.
+ */
+
+extern key_data *key_decode(const void */*p*/, size_t /*sz*/);
+
+/* --- @key_encode@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @dstr *d@ = pointer to destination string
+ *             @const key_filter *kf@ = pointer to key selection block
+ *
+ * Returns:    Nonzero if any items were actually written.
+ *
+ * Use:                Encodes a key block as binary data.
+ */
+
+extern int key_encode(key_data */*k*/, dstr */*d*/,
+                     const key_filter */*kf*/);
+
+/*----- Packing and unpacking keys ----------------------------------------*/
+
+/* --- @key_pack@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_data **kd@ = where to put the key data pointer
+ *             @dstr *d@ = pointer to tag string for the key data
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Packs a key from a data structure.
+ */
+
+extern int key_pack(key_packdef */*kp*/, key_data **/*kd*/, dstr */*d*/);
+
+/* --- @key_unpack@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_data *kd@ = pointer to source key data
+ *             @dstr *d@ = pointer to tag string for the key data
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Unpacks a key into an appropriate data structure.
+ */
+
+extern int key_unpack(key_packdef */*kp*/, key_data */*kd*/, dstr */*d*/);
+
+/* --- @key_unpackdone@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing definition
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees the key components contained within a packing
+ *             definition, created during key unpacking.
+ */
+
+extern void key_unpackdone(key_packdef */*kp*/);
+
+/*----- Key encryption ----------------------------------------------------*/
+
+/* --- @key_lock@ --- *
+ *
+ * Arguments:  @key_data **kt@ = where to store the destination pointer
+ *             @key_data *k@ = source key data block or null to use @*kt@
+ *             @const void *e@ = secret to encrypt key with
+ *             @size_t esz@ = size of the secret
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts a key data block using a secret.
+ */
+
+extern void key_lock(key_data **/*kt*/, key_data */*k*/,
+                    const void */*e*/, size_t /*esz*/);
+
+/* --- @key_unlock@ --- *
+ *
+ * Arguments:  @key_data **kt@ = where to store the destination pointer
+ *             @key_data *k@ = source key data block or null to use @*kt@
+ *             @const void *e@ = secret to decrypt the block with
+ *             @size_t esz@ = size of the secret
+ *
+ * Returns:    Zero for success, or a @KERR_@ error code.
+ *
+ * Use:                Unlocks a key using a secret.
+ */
+
+extern int key_unlock(key_data **/*kt*/, key_data */*k*/,
+                     const void */*e*/, size_t /*esz*/);
+
+/* --- @key_plock@ --- *
+ *
+ * Arguments:  @key_data **kt@ = where to store the destination pointer
+ *             @key_data *k@ = source key data block or null to use @*kt@
+ *             @const char *tag@ = tag to use for passphrase
+ *
+ * Returns:    Zero if successful, a @KERR@ error code on failure.
+ *
+ * Use:                Locks a key by encrypting it with a passphrase.
+ */
+
+extern int key_plock(key_data **/*kt*/, key_data */*k*/,
+                    const char */*tag*/);
+
+/* --- @key_punlock@ --- *
+ *
+ * Arguments:  @key_data **kt@ = where to store the destination pointer
+ *             @key_data *k@ = source key data block or null to use @*kt@
+ *             @const char *tag@ = tag to use for passphrase
+ *
+ * Returns:    Zero if successful, a @KERR@ error code on failure.
+ *
+ * Use:                Unlocks a passphrase-locked key.
+ */
+
+extern int key_punlock(key_data **/*kt*/, key_data */*k*/,
+                      const char */*tag*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/key/key-error.c b/key/key-error.c
new file mode 100644 (file)
index 0000000..a091997
--- /dev/null
@@ -0,0 +1,60 @@
+/* -*-c-*-
+ *
+ * Translating key error codes into strings
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/macros.h>
+#include "key-error.h"
+
+/*----- Error reporting ---------------------------------------------------*/
+
+/* --- @key_strerror@ --- *
+ *
+ * Arguments:  @int err@ = error code from @key_new@
+ *
+ * Returns:    Pointer to error string.
+ *
+ * Use:                Translates a @KERR@ error code into a human-readable
+ *             string.
+ */
+
+const char *key_strerror(int err)
+{
+  static const char *const tab[] = {
+#define ENTRY(tag, num, str) str,
+    KEY_ERRORS(ENTRY)
+#undef ENTRY
+    "Unknown error code"
+  };
+
+  unsigned e = -err;
+  if (e >= N(tab))
+    e = N(tab) - 1;
+ return (tab[e]);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-error.h b/key/key-error.h
new file mode 100644 (file)
index 0000000..6b3131c
--- /dev/null
@@ -0,0 +1,81 @@
+/* -*-c-*-
+ *
+ * Key management error codes
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_KEY_ERROR_H
+#define CATACOMB_KEY_ERROR_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Error codes -------------------------------------------------------*/
+
+#define KEY_ERRORS(_)                                                  \
+  _(OK,                  0, "No error")                                        \
+  _(BADTAG,     -1, "Bad tag string")                                  \
+  _(BADTYPE,    -2, "Bad type string")                                 \
+  _(BADCOMMENT,         -3, "Bad comment string")                              \
+  _(DUPID,      -4, "Key id already exists")                           \
+  _(DUPTAG,     -5, "Key tag already exists")                          \
+  _(READONLY,   -6, "Key file is read-only")                           \
+  _(WILLEXPIRE,         -7, "Key will eventually expire")                      \
+  _(EXPIRED,    -8, "Key has expired")                                 \
+  _(BADFLAGS,   -9, "Bad key flags string")                            \
+  _(BADPASS,   -10, "Failed to unlock key")                            \
+  _(WRONGTYPE, -11, "Unexpected key encoding type")                    \
+  _(NOTFOUND,  -12, "Key not found")                                   \
+  _(BADATTR,   -13, "Bad attribute name")                              \
+  _(MALFORMED, -14, "Malformed key data")                              \
+  _(IO,                -15, "I/O error")                                       \
+
+enum {
+#define ENTRY(tag, num, str) KERR_##tag = num,
+  KEY_ERRORS(ENTRY)
+#undef ENTRY
+  KERR__dummy
+};
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @key_strerror@ --- *
+ *
+ * Arguments:  @int err@ = error code from @key_new@
+ *
+ * Returns:    Pointer to error string.
+ *
+ * Use:                Translates a @KERR@ error code into a human-readable string.
+ */
+
+extern const char *key_strerror(int /*err*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/key/key-fetch.c b/key/key-fetch.c
new file mode 100644 (file)
index 0000000..d8d6da2
--- /dev/null
@@ -0,0 +1,206 @@
+/* -*-c-*-
+ *
+ * Higher-level key unpacking
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "key.h"
+#include "key-data.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_fetchinit@ --- *
+ *
+ * Arguments:  @const key_fetchdef *kf@ = pointer to base definition
+ *             @key_packstruct *kps@ = pointer to destination packing def
+ *             @void *p@ = pointer to destination block
+ *
+ * Returns:    Pointer to packing definition.
+ *
+ * Use:                Initializes a packing definition (@key_packdef@ structure).
+ *             If @kps@ is null on entry, an appropriately sized block is
+ *             allocated automatically.  Otherwise it must be large enough.
+ */
+
+static size_t kfcount(const key_fetchdef *kf)
+{
+  size_t n = 1;
+  while (kf->name) {
+    n++;
+    if (kf->kf)
+      n += kfcount(kf->kf);
+    kf++;
+  }
+  return (n);
+}
+
+key_packdef *key_fetchinit(const key_fetchdef *kf,
+                          key_packstruct *kp, void *p)
+{
+  size_t n = 1 + kfcount(kf);
+  key_packdef *kpd;
+  key_packstruct *kps;
+  char *cp = p;
+
+  /* --- If @kps@ is null, count the entries and allocate --- */
+
+  if (kp)
+    kp->name = 0;
+  else {
+    kp = xmalloc(n * sizeof(*kp));
+    kp->name = (char *)kp;
+  }
+
+  /* --- Fill in the top part --- */
+
+  kp->kp.e = KENC_STRUCT;
+  kp->kp.p = &kp[1];
+  kp->kp.kd = 0;
+  kpd = &kp->kp;
+
+  /* --- Initialize for the main loop --- */
+
+  kps = kp + n;
+  n = 0;
+  kp++;
+
+  /* --- Iterate over the entries in the table --- *
+   *
+   * The end of the target block is used as a stack to record where
+   * substructure is meant to occur.  The integer @n@ is the depth of the
+   * stack; @kps@ is a full descending stack pointer.  The @kp.p@ member of a
+   * stack element points back to an entry with substructure, the @kp.p@
+   * member of which refers to the @kf@ table for the substructure.
+   *
+   * This should all be about as clear as mud.
+   */
+
+  for (;;) {
+
+    /* --- Blat out a level's worth --- */
+
+    while (kf->name) {
+      kp->name = kf->name;
+      kp->kp.e = kf->e;
+      kp->kp.kd = 0;
+      if ((kf->e & KF_ENCMASK) != KENC_STRUCT)
+       kp->kp.p = cp + kf->off;
+      else {
+       (--kps)->kp.p = kp;
+       kp->kp.p = (void *)kf->kf;
+       n++;
+      }
+      kf++;
+      kp++;
+    }
+    (kp++)->name = 0;
+    if (!n)
+      break;
+
+    /* --- Pop an entry from the stack --- */
+
+    {
+      key_packstruct *kkp = (kps++)->kp.p;
+      kf = kkp->kp.p;
+      kkp->kp.p = kp;
+      n--;
+    }
+  }
+
+  /* --- We're done --- */
+
+  return (kpd);
+}
+
+/* --- @key_fetch@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key *k@ = key file containing desired key
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Fetches an unpacked key from a packed one.
+ */
+
+int key_fetch(key_packdef *kp, key *k)
+{
+  dstr d = DSTR_INIT;
+  int e;
+
+  key_fulltag(k, &d);
+  e = key_unpack(kp, k->k, &d);
+  dstr_destroy(&d);
+  return (e);
+}
+
+/* --- @key_fetchbyname@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_file *kf@ = key file containing desired key
+ *             @const char *tag@ = user's tag describing the key
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Fetches a named key from a key file and unpacks it
+ *             conveniently.
+ */
+
+int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag)
+{
+  dstr d = DSTR_INIT;
+  key_data **kd;
+  int e;
+
+  if (key_qtag(kf, tag, &d, 0, &kd))
+    e = KERR_NOTFOUND;
+  else
+    e = key_unpack(kp, *kd, &d);
+  dstr_destroy(&d);
+  return (e);
+}
+
+/* --- @key_fetchdone@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a packing structure.  If the structure was allocated by
+ *             @key_fetchinit@ then it is freed.
+ */
+
+void key_fetchdone(key_packdef *kp)
+{
+  key_packstruct *kps =
+    (key_packstruct *)(((char *)kp) - offsetof(key_packstruct, kp));
+  key_unpackdone(kp);
+  if (kps->name)
+    xfree(kps);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-file.c b/key/key-file.c
new file mode 100644 (file)
index 0000000..e7f4fdd
--- /dev/null
@@ -0,0 +1,336 @@
+/* -*-c-*-
+ *
+ * System-dependent key filing operations
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <mLib/dstr.h>
+#include <mLib/lock.h>
+
+#include "key.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @fdcopy@ --- *
+ *
+ * Arguments:  @int source@ = source file descriptor
+ *             @int dest@ = destination file descriptor
+ *
+ * Returns:    Zero if OK, nonzero otherwise.
+ *
+ * Use:                Copies data from one file descriptor to another.
+ */
+
+static int fdcopy(int source, int dest)
+{
+  char buf[4096];
+  char *p;
+
+  if (lseek(source, 0, SEEK_SET) < 0||
+      lseek(dest, 0, SEEK_SET) < 0 ||
+      ftruncate(dest, 0) < 0)
+    return (-1);
+  for (;;) {
+    int n = read(source, buf, sizeof(buf));
+    if (n < 0)
+      return (-1);
+    else if (n == 0)
+      break;
+    p = buf;
+    while (n) {
+      int nn = write(dest, p, n);
+      if (nn < 0)
+       return (-1);
+      p += nn;
+      n -= nn;
+    }
+  }
+  return (0);
+}
+
+/* --- @key_save@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *
+ * Returns:    A @KWRITE_@ code indicating how well it worked.
+ *
+ * Use:                Writes a key file's data back to the actual file.  This code
+ *             is extremely careful about error handling.  It should usually
+ *             be able to back out somewhere sensible, but it can tell when
+ *             it's got itself into a real pickle and starts leaving well
+ *             alone.
+ *
+ *             Callers, please make sure that you ring alarm bells when this
+ *             function returns @KWRITE_BROKEN@.
+ */
+
+int key_save(key_file *f)
+{
+  dstr n_older = DSTR_INIT, n_old = DSTR_INIT, n_new = DSTR_INIT;
+  int rc = KWRITE_FAIL;
+
+  if (!(f->f & KF_MODIFIED))
+    return (KWRITE_OK);
+  if (!f->fp)
+    return (KWRITE_FAIL);
+
+  /* --- Write a new key file out --- *
+   *
+   * Check for an error after each key line.  This ought to be enough.
+   * Checking after each individual byte write and @fprintf@ isn't much fun.
+   */
+
+  dstr_putf(&n_new, "%s.new", f->name);
+
+  {
+    key *k;
+    key_iter i;
+    FILE *fp;
+
+    if ((fp = fopen(n_new.buf, "w")) == 0)
+      goto fail_open;
+
+    for (key_mkiter(&i, f); (k = key_next(&i)) != 0; ) {
+      if (key_extract(f, k, fp, 0)) {
+       fclose(fp);
+       goto fail_write;
+      }
+    }
+
+    if (fclose(fp))
+      goto fail_write;
+  }
+
+  /* --- Set up the other filenames --- */
+
+  dstr_putf(&n_older, "%s.older", f->name);
+  dstr_putf(&n_old, "%s.old", f->name);
+
+  /* --- Move the current backup on one --- *
+   *
+   * If the `older' file exists, then we're in need of attention.
+   */
+
+  {
+    struct stat st;
+    if (stat(n_older.buf, &st) == 0 || errno != ENOENT) {
+      errno = EEXIST;
+      rc = KWRITE_BROKEN;
+      goto fail_shift;
+    }
+    if (rename(n_old.buf, n_older.buf) && errno != ENOENT)
+      goto fail_shift;
+  }
+
+  /* --- Copy the current file to the backup --- */
+
+  {
+    int fd;
+    if ((fd = open(n_old.buf, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0)
+      goto fail_backup;
+    if (fdcopy(fileno(f->fp), fd)) {
+      close(fd);
+      goto fail_backup;
+    }
+    if (close(fd))
+      goto fail_backup;
+  }
+
+  /* --- Copy the newly created file to the current one --- *
+   *
+   * This is the dangerous bit.
+   */
+
+  {
+    int fd;
+    if ((fd = open(n_new.buf, O_RDONLY)) < 0)
+      goto fail_update;
+    if (fdcopy(fd, fileno(f->fp))) {
+      close(fd);
+      goto fail_update;
+    }
+    close(fd);
+    if (fsync(fileno(f->fp)))
+      goto fail_update;
+  }
+
+  /* --- Clean up --- *
+   *
+   * Remove the `new' file and the `older' backup.  Then we're done.
+   */
+
+  unlink(n_new.buf);
+  unlink(n_older.buf);
+  dstr_destroy(&n_new);
+  dstr_destroy(&n_old);
+  dstr_destroy(&n_older);
+  return (KWRITE_OK);
+
+  /* --- Failure while writing the new key file --- *
+   *
+   * I need to copy the backup back.  If that fails then I'm really stuffed.
+   * If not, then I might as well try to get the backups sorted back out
+   * again.
+   */
+
+fail_update:
+  {
+    int fd;
+    int e = errno;
+
+    if ((fd = open(n_old.buf, O_RDONLY)) < 0)
+      rc = KWRITE_BROKEN;
+    else if (fdcopy(fd, fileno(f->fp))) {
+      close(fd);
+      rc = KWRITE_BROKEN;
+    } else {
+      close(fd);
+      if (fsync(fileno(f->fp)))
+       rc = KWRITE_BROKEN;
+    }
+
+    errno = e;
+    if (rc == KWRITE_BROKEN)
+      goto fail_shift;
+  }
+  /* Now drop through */
+
+  /* --- Failure while writing the new backup --- *
+   *
+   * The new backup isn't any use.  Try to recover the old one.
+   */
+
+fail_backup:
+  {
+    int e = errno;
+    unlink(n_old.buf);
+    if (rename(n_older.buf, n_old.buf) && errno != ENOENT)
+      rc = KWRITE_BROKEN;
+    errno = e;
+  }
+  /* Now drop through */
+
+  /* --- Failure while demoting the current backup --- *
+   *
+   * Leave the completed output file there for the operator in case he wants
+   * to clean up.
+   */
+
+fail_shift:
+  dstr_destroy(&n_new);
+  dstr_destroy(&n_old);
+  dstr_destroy(&n_older);
+  return (rc);
+
+  /* --- Failure during write of new data --- *
+   *
+   * Clean up the new file and return.  These errors can never cause
+   * breakage.
+   */
+
+fail_write:
+  unlink(n_new.buf);
+fail_open:
+  dstr_destroy(&n_new);
+  return (rc);
+}
+
+/* --- @key_lockfile@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure to initialize
+ *             @const char *file@ = pointer to the file name
+ *             @unsigned how@ = opening options (@KOPEN_*@).
+ *
+ * Returns:    Zero if it worked, nonzero otherwise.
+ *
+ * Use:                Opens a keyfile and stores the information needed for
+ *             continued access in the structure.
+ *
+ *             If the file is opened with @KOPEN_WRITE@, it's created if
+ *             necessary with read and write permissions for owner only, and
+ *             locked for update while it's open.
+ *
+ *             This is a system-dependent routine, and only really intended
+ *             for the private use of @key_open@.
+ */
+
+int key_lockfile(key_file *f, const char *file, unsigned how)
+{
+  int of, lf;
+  const char *ff;
+  int fd;
+
+  /* --- Handle the magic no-file option --- */
+
+  if (how & KOPEN_NOFILE) {
+    f->fp = 0;
+    return (0);
+  }
+
+  /* --- Lots of things depend on whether we're writing --- */
+
+  switch (how & KOPEN_MASK) {
+    case KOPEN_READ:
+      of = O_RDONLY;
+      lf = LOCK_NONEXCL;
+      ff = "r";
+      break;
+    case KOPEN_WRITE:
+      of = O_RDWR | O_CREAT;
+      lf = LOCK_EXCL;
+      ff = "r+";
+      break;
+    default:
+      errno = EINVAL;
+      return (-1);
+  }
+
+  /* --- Open and lock the file --- */
+
+  if ((fd = open(file, of, 0600)) < 0)
+    return (-1);
+  if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 ||
+      lock_file(fd, lf) < 0 ||
+      (f->fp = fdopen(fd, ff)) == 0) {
+    close(fd);
+    return (-1);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-flags.c b/key/key-flags.c
new file mode 100644 (file)
index 0000000..169de2c
--- /dev/null
@@ -0,0 +1,202 @@
+/* -*-c-*-
+ *
+ * Reading and writing key flag strings
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+
+#include "key-data.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct key_flags {
+  unsigned f;
+  unsigned m;
+} key_flags;
+
+/*----- Flags table -------------------------------------------------------*/
+
+typedef struct flagent {
+  const char *name;
+  unsigned f;
+  unsigned m;
+} flagent;
+
+static const flagent flagtab[] = {
+
+  /* --- Encoding types --- */
+
+  { "binary",          KENC_BINARY,    KF_ENCMASK },
+  { "integer",         KENC_MP,        KF_ENCMASK },
+  { "struct",          KENC_STRUCT,    KF_ENCMASK },
+  { "encrypt",         KENC_ENCRYPT,   KF_ENCMASK },
+  { "string",          KENC_STRING,    KF_ENCMASK },
+  { "ec",              KENC_EC,        KF_ENCMASK },
+
+  /* --- Classes of keys --- */
+
+  { "shared",          KCAT_SHARE,     KF_CATMASK },
+  { "public",          KCAT_PUB,       KF_CATMASK },
+  { "private",         KCAT_PRIV,      KF_CATMASK },
+  { "symmetric",       KCAT_SYMM,      KF_CATMASK },
+  { "secret",          0,              KF_NONSECRET },
+  { "-secret",         KF_NONSECRET,   KF_NONSECRET },
+
+  /* --- Other flags --- */
+
+  { "burn",            KF_BURN,        KF_BURN },
+  { "-burn",           0,              KF_BURN },
+
+  /* --- End marker --- */
+
+  { 0,                 0,              0 }
+};
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_readflags@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to string to read
+ *             @char **pp@ = where to store the end pointer
+ *             @unsigned *ff@ = where to store the flags
+ *             @unsigned *mm@ = where to store the mask
+ *
+ * Returns:    Zero if all went well, nonzero if there was an error.
+ *
+ * Use:                Reads a flag string.
+ */
+
+int key_readflags(const char *p, char **pp, unsigned *ff, unsigned *mm)
+{
+  unsigned f = 0, m = 0;
+
+  for (;;) {
+    size_t sz = strcspn(p, ",:");
+    const flagent *e, *ee = 0;
+
+    /* --- Look up the string in the flags table --- */
+
+    if (sz == 4 && strncmp(p, "none", 4) == 0)
+      goto next;
+    for (e = flagtab; e->name; e++) {
+      if (strncmp(e->name, p, sz) == 0) {
+       if (e->name[sz] == 0) {
+         ee = e;
+         break;
+       } else if (ee)
+         return (KERR_BADFLAGS);
+       else
+         ee = e;
+      }
+    }
+    if (!ee)
+      return (KERR_BADFLAGS);
+
+    /* --- Adjust the flag words --- *
+     *
+     * Ensure that the flags set are disjoint.
+     */
+
+    if (m & ee->m)
+      return (KERR_BADFLAGS);
+    m |= ee->m;
+    f |= ee->f;
+  next:
+    p += sz;
+    if (*p == 0 || *p == ':')
+      break;
+    p++;
+  }
+
+  /* --- Report the results --- */
+
+  if (ff) *ff = f;
+  if (mm) *mm = m;
+  if (pp) *pp = (char *)p;
+  return (0);
+}
+
+/* --- @key_writeflags@ --- *
+ *
+ * Arguments:  @unsigned f@ = flags to write
+ *             @dstr *d@ = pointer to destination string
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits a flags word as a string representation.
+ */
+
+void key_writeflags(unsigned f, dstr *d)
+{
+  int del = 0;
+  const flagent *e;
+  unsigned m = 0;
+
+  for (e = flagtab; e->name; e++) {
+    if (m & e->m || e->name[0] == '-' || (f & e->m) != e->f)
+      continue;
+    if (del)
+      DPUTC(d, ',');
+    DPUTS(d, e->name);
+    m |= e->m;
+    del = 1;
+  }
+}
+
+/* --- @key_match@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const key_filter *kf@ = pointer to filter block
+ *
+ * Returns:    Nonzero if the key matches the filter.
+ *
+ * Use:                Checks whether a key matches a filter.
+ */
+
+int key_match(key_data *k, const key_filter *kf)
+{
+  key_subkeyiter i;
+  const char *tag;
+  key_data *kd;
+
+  if (!kf)
+    return (1);
+  if ((k->e & KF_ENCMASK) != KENC_STRUCT)
+    return ((k->e & kf->m) == kf->f);
+
+  for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
+    if (key_match(kd, kf))
+      return (1);
+  }
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-io.c b/key/key-io.c
new file mode 100644 (file)
index 0000000..df7cd53
--- /dev/null
@@ -0,0 +1,569 @@
+/* -*-c-*-
+ *
+ * Adding new keys to a key file
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <mLib/bits.h>
+#include <mLib/crc32.h>
+#include <mLib/dstr.h>
+#include <mLib/hash.h>
+#include <mLib/str.h>
+#include <mLib/sub.h>
+#include <mLib/sym.h>
+#include <mLib/url.h>
+
+#include "key.h"
+
+/*----- Tweakable macros --------------------------------------------------*/
+
+#define KEY_INITSZ 16
+
+/*----- Low-level functions -----------------------------------------------*/
+
+/* --- @insert@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure
+ *             @key *k@ = pointer to key block to insert
+ *
+ * Returns:    Error code (one of the @KERR@ code).
+ *
+ * Use:                Links a new key block into the complicated data structure
+ *             which is a keyring file.
+ */
+
+static int insert(key_file *f, key *k)
+{
+  key_ref *kr = 0;
+  unsigned found;
+
+  /* --- Sanity preservatives --- */
+
+  if (key_chkident(k->type))
+    return (KERR_BADTYPE);
+  else if (k->tag && key_chkident(k->tag))
+    return (KERR_BADTAG);
+
+  /* --- Insert into the tag table --- */
+
+  if (k->tag) {
+    kr = sym_find(&f->bytag, k->tag, -1, sizeof(*kr), &found);
+    if (found)
+      return (KERR_DUPTAG);
+    kr->k = k;
+  }
+
+  /* --- Insert into the id table --- */
+
+  {
+    hash_base **bin, *b;
+
+    bin = HASH_BIN(&f->byid, k->id);
+    for (b = *bin; b; b = b->next) {
+      if (b->hash == k->id) {
+       if (kr)
+         sym_remove(&f->bytag, kr);
+       return (KERR_DUPID);
+      }
+    }
+
+    k->_b.next = *bin;
+    *bin = &k->_b;
+    k->_b.hash = k->id;
+  }
+
+  /* --- Extend the table --- */
+
+  if (f->idload > 0)
+    f->idload--;
+  else if (hash_extend(&f->byid))
+    f->idload = SYM_LIMIT(f->byid.mask / 2);
+
+  /* --- Insert into the type table --- */
+
+  kr = sym_find(&f->bytype, k->type, -1, sizeof(*kr), &found);
+  if (!found) {
+    kr->k = k;
+    k->next = 0;
+  } else {
+    key **p = &kr->k;
+    if (k->exp != KEXP_FOREVER) {
+      while (*p && (*p)->exp != KEXP_EXPIRE && (*p)->exp > k->exp)
+       p = &(*p)->next;
+    }
+    k->next = *p;
+    *p = k;
+  }
+
+  return (KERR_OK);
+}
+
+/*----- Reading and writing keys ------------------------------------------*/
+
+/* --- @exptime@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to string
+ *
+ * Returns:    Time value.
+ *
+ * Use:                Translates an expiry or deletion time.
+ */
+
+time_t exptime(const char *p)
+{
+  size_t sz = strlen(p);
+  if (strncmp(p, "expired", sz) == 0)
+    return (KEXP_EXPIRE);
+  else if (strncmp(p, "forever", sz) == 0)
+    return (KEXP_FOREVER);
+  else
+    return (atol(p));
+}
+
+/* --- @key_merge@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure
+ *             @const char *file@ = name of file (for error messages)
+ *             @FILE *fp@ = file handle to read from
+ *             @key_reporter *rep@ = error reporting function
+ *             @void *arg@ = argument for function
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Reads keys from a file, and inserts them into the file.
+ */
+
+int key_merge(key_file *f, const char *file, FILE *fp,
+             key_reporter *rep, void *arg)
+{
+  int line = 0;
+  dstr l = DSTR_INIT;
+  dstr n = DSTR_INIT, v = DSTR_INIT;
+
+  if (!(f->f & KF_WRITE))
+    return (KERR_READONLY);
+
+  for (; dstr_putline(&l, fp) != EOF; DRESET(&l)) {
+    char *vf[6];
+    char *p = l.buf;
+    key *k;
+
+    /* --- Skip blank lines and comments --- *
+     *
+     * Quite what they're doing in what ought to be an automatically-
+     * maintained file I don't know.
+     */
+
+    line++;
+    while (isspace((unsigned char)*p))
+      p++;
+    if (!*p || *p == '#')
+      continue;
+
+    /* --- Break the line into fields --- *
+     *
+     * There are currently six fields of interest:
+     *
+     *  * The key's identification (id, tag and type).
+     *  * The actual key data itself.
+     *  * The key expiry time.
+     *  * The key deletion time.
+     *  * The attributes field.
+     *  * Any further comments.
+     *
+     * All but the last field can contain no spaces.
+     */
+
+    {
+      int n = str_split(p, vf, 5, &vf[5]);
+      if (n < 4) {
+       if (rep)
+         rep(file, line, "too few fields", arg);
+       goto skip_0;
+      }
+    }
+
+    /* --- Allocate a new key block --- */
+
+    k = CREATE(key);
+
+    /* --- Extract the key data into the block --- */
+
+    if ((k->k = key_read(vf[1], 0)) == 0) {
+      if (rep)
+       rep(file, line, "bad key data", arg);
+      goto skip_1;
+    }
+
+    /* --- Decode the identification field --- *
+     *
+     * For compatibility, derive a keyid from the key data.  This can only be
+     * done if the key encoding is binary (and presumably old-encoding binary
+     * at that).
+     */
+
+    {
+      char *q = strchr(vf[0], ':');
+      char *qq;
+
+      if (!q) {
+       if (k->k->e != KENC_BINARY) {
+         if (rep)
+           rep(file, line, "new-style key encoding but no keyid", arg);
+         goto skip_2;
+       }
+       k->id = crc32(0, k->k->u.k.k, k->k->u.k.sz);
+       k->type = xstrdup(vf[0]);
+       k->tag = 0;
+      } else {
+       *q++ = 0;
+       k->id = strtoul(p, 0, 16);
+       if ((qq = strchr(q, ':')) == 0 || !qq[1]) {
+         if (qq)
+           *qq = 0;
+         k->tag = 0;
+       } else {
+         *qq++ = 0;
+         k->tag = xstrdup(qq);
+       }
+       k->type = xstrdup(q);
+      }
+    }
+
+    /* --- Get a key block for the new key --- */
+
+    k->exp = exptime(vf[2]);
+    k->del = exptime(vf[3]);
+
+    /* --- Insert the key block into the table --- */
+
+    {
+      int err;
+
+    again:
+      if ((err = insert(f, k)) < 0) {
+       if (err == KERR_DUPTAG) {
+         if (rep)
+           rep(file, line, "duplicate key tag stripped", arg);
+         xfree(k->tag);
+         k->tag = 0;
+         goto again;
+       }
+       if (rep)
+         rep(file, line, key_strerror(err), arg);
+       goto skip_3;
+      }
+    }
+
+    /* --- Parse up the attributes, if specified --- */
+
+    sym_create(&k->a);
+    if (vf[4] && strcmp(vf[4], "-") != 0) {
+      url_dctx uc;
+      for (url_initdec(&uc, vf[4]); url_dec(&uc, &n, &v); ) {
+       key_putattr(f, k, n.buf, v.buf);
+       DRESET(&n); DRESET(&v);
+      }
+    }
+
+    /* --- Insert the comment --- */
+
+    if (vf[5])
+      k->c = xstrdup(vf[5]);
+    else
+      k->c = 0;
+    continue;
+
+    /* --- Tidy up after something going wrong --- */
+
+  skip_3:
+    if (k->tag)
+      xfree(k->tag);
+    xfree(k->type);
+  skip_2:
+    key_drop(k->k);
+  skip_1:
+    DESTROY(k);
+  skip_0:;
+  }
+
+  /* --- Extensive tidying up now required --- */
+
+  dstr_destroy(&l);
+  dstr_destroy(&n);
+  dstr_destroy(&v);
+  f->f |= KF_MODIFIED;
+  return (0);
+}
+
+/* --- @key_extract@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure
+ *             @key *k@ = key to extract
+ *             @FILE *fp@ = file to write on
+ *             @const key_filter *kf@ = pointer to key selection block
+ *
+ * Returns:    Zero if OK, EOF on error.
+ *
+ * Use:                Extracts a key to an ouptut file.
+ */
+
+int key_extract(key_file *f, key *k, FILE *fp, const key_filter *kf)
+{
+  dstr d = DSTR_INIT;
+  time_t t = time(0);
+
+  /* --- Skip the key if it's deleted or unselected--- */
+
+  if (KEY_EXPIRED(t, k->del) || !key_match(k->k, kf))
+    return (0);
+
+  /* --- Encode the key and write the easy stuff --- */
+
+  key_fulltag(k, &d);
+  DPUTC(&d, ' ');
+  key_write(k->k, &d, kf);
+  DPUTC(&d, ' ');
+  dstr_write(&d, fp);
+  DRESET(&d);
+
+  /* --- Write out the expiry and deletion times --- */
+
+  if (KEY_EXPIRED(t, k->exp))
+    fputs("expired ", fp);
+  else if (k->exp == KEXP_FOREVER)
+    fputs("forever ", fp);
+  else
+    fprintf(fp, "%li ", (long)k->exp);
+
+  if (k->del == KEXP_FOREVER)
+    fputs("forever ", fp);
+  else
+    fprintf(fp, "%li ", (long)k->del);
+
+  /* --- Output the attributes --- */
+
+  {
+    int none = 1;
+    sym_iter i;
+    key_attr *a;
+    url_ectx uc;
+
+    url_initenc(&uc);
+    for (sym_mkiter(&i, &k->a); (a = sym_next(&i)) != 0; ) {
+      none = 0;
+      url_enc(&uc, &d, SYM_NAME(a), a->p);
+    }
+    if (none)
+      DPUTS(&d, "-");
+    DWRITE(&d, fp);
+  }
+
+  dstr_destroy(&d);
+  if (k->c) {
+    putc(' ', fp);
+    fputs(k->c, fp);
+  }
+  putc('\n', fp);
+  return (ferror(fp) ? EOF : 0);
+}
+
+/*----- Opening and closing files -----------------------------------------*/
+
+/* --- @key_open@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure to initialize
+ *             @const char *file@ = pointer to the file name
+ *             @unsigned how@ = opening options (@KOPEN_*@).
+ *             @key_reporter *rep@ = error reporting function
+ *             @void *arg@ = argument for function
+ *
+ * Returns:    Zero if it worked, nonzero otherwise.
+ *
+ * Use:                Opens a key file, reads its contents, and stores them in a
+ *             structure.  The file is locked appropriately until closed
+ *             using @key_close@.  On an error, everything is cleared away
+ *             tidily.  If the file is opened with @KOPEN_WRITE@, it's
+ *             created if necessary, with read and write permissions for its
+ *             owner only.
+ */
+
+int key_open(key_file *f, const char *file, unsigned how,
+            key_reporter *rep, void *arg)
+{
+  if (key_lockfile(f, file, how)) {
+    rep(file, 0, strerror(errno), arg);
+    return (-1);
+  }
+  f->f = 0;
+  f->name = xstrdup(file);
+
+  hash_create(&f->byid, KEY_INITSZ);
+  f->idload = SYM_LIMIT(KEY_INITSZ);
+  sym_create(&f->bytype);
+  sym_create(&f->bytag);
+  f->f |= KF_WRITE;
+  if (f->fp)
+    key_merge(f, file, f->fp, rep, arg);
+  f->f &= ~KF_MODIFIED;
+
+  if ((how & KOPEN_MASK) == KOPEN_READ) {
+    f->f &= ~KF_WRITE;
+    fclose(f->fp);
+    f->fp = 0;
+  }
+
+  return (0);
+}
+
+/* --- @key_discard@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees all the key data, without writing changes.
+ */
+
+void key_discard(key_file *f)
+{
+  hash_base *b;
+  hash_iter i;
+
+  /* --- Free all the individual keys --- */
+
+  for (hash_mkiter(&i, &f->byid); (b = hash_next(&i)) != 0; ) {
+    sym_iter j;
+    key_attr *a;
+    key *k = (key *)b;
+
+    if (k->k) key_drop(k->k);
+    xfree(k->type);
+    xfree(k->tag);
+    if (k->c)
+      xfree(k->c);
+    for (sym_mkiter(&j, &k->a); (a = sym_next(&j)) != 0; )
+      xfree(a->p);
+    sym_destroy(&k->a);
+    DESTROY(k);
+  }
+  hash_destroy(&f->byid);
+  sym_destroy(&f->bytype);
+  sym_destroy(&f->bytag);
+
+  if (f->fp)
+    fclose(f->fp);
+  xfree(f->name);
+}
+
+/* --- @key_close@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *
+ * Returns:    A @KWRITE_@ code indicating how it went.
+ *
+ * Use:                Frees all the key data, writes any changes.  Make sure that
+ *             all hell breaks loose if this returns @KWRITE_BROKEN@.
+ */
+
+int key_close(key_file *f)
+{
+  int e;
+
+  if (f->fp && (e = key_save(f)) != KWRITE_OK)
+    return (e);
+  key_discard(f);
+  return (KWRITE_OK);
+}
+
+/* --- @key_new@ ---
+ *
+ * Arguments:  @key_file *f@ = pointer to key file
+ *             @uint32 id@ = keyid to set
+ *             @const char *type@ = the type of this key
+ *             @time_t exp@ = when the key expires
+ *             @key *kk@ = where to put the key pointer
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Attaches a new key to a key file.  You must have a writable
+ *             key file for this to work.
+ *
+ *             The type is a key type string.  This interface doesn't care
+ *             about how type strings are formatted: it just treats them as
+ *             opaque gobs of text.  Clients are advised to choose some
+ *             standard for representing key types, though.
+ *
+ *             The expiry time should either be a time in the future, or the
+ *             magic value @KEXP_FOREVER@ which means `never expire this
+ *             key'.  Be careful with `forever' keys.  If I were you, I'd
+ *             use a more sophisticated key management system than this for
+ *             them.
+ */
+
+int key_new(key_file *f, uint32 id, const char *type, time_t exp, key **kk)
+{
+  key *k = 0;
+  time_t t = time(0);
+  int e = KERR_OK;
+
+  /* --- Make sure the file is writable --- */
+
+  if (!(f->f & KF_WRITE))
+    e = KERR_READONLY;
+  else if (KEY_EXPIRED(t, exp))
+    e = KERR_EXPIRED;
+  else if (key_chkident(type))
+    e = KERR_BADTYPE;
+  else {
+    k = CREATE(key);
+    k->id = id;
+    k->tag = 0;
+    k->exp = k->del = exp;
+    k->c = 0;
+    k->type = (char *)type; /* temporarily */
+    sym_create(&k->a);
+    if ((e = insert(f, k)) != 0)
+      DESTROY(k);
+    else {
+      k->k = key_newstring(KCAT_SHARE, "<unset>");
+      k->type = xstrdup(type);
+      *kk = k;
+      f->f |= KF_MODIFIED;
+    }
+  }
+
+  return (e);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-misc.c b/key/key-misc.c
new file mode 100644 (file)
index 0000000..80e9597
--- /dev/null
@@ -0,0 +1,405 @@
+/* -*-c-*-
+ *
+ * Simple key management
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <mLib/bits.h>
+#include <mLib/hash.h>
+#include <mLib/sub.h>
+#include <mLib/sym.h>
+
+#include "key.h"
+
+/*----- Useful macros -----------------------------------------------------*/
+
+#define KEY_WRITE(f) do {                                              \
+     if (!(f)->f & KF_WRITE)                                           \
+       return (KERR_READONLY);                                         \
+   } while (0)
+
+#define KEY_MODIFY(f) do { (f)->f |= KF_MODIFIED; } while (0)
+
+#define KEY_LOAD(n) ((n) * 2)
+
+/*----- Iteration and iterators -------------------------------------------*/
+
+/* --- @key_mkiter@ --- *
+ *
+ * Arguments:  @key_iter *i@ = pointer to iterator object
+ *             @key_file *f@ = pointer to file structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a key iterator.  The keys are returned by
+ *             @key_next@.
+ */
+
+void key_mkiter(key_iter *i, key_file *f)
+{
+  HASH_MKITER(&i->i, &f->byid);
+  i->t = time(0);
+}
+
+/* --- @key_next@ --- *
+ *
+ * Arguments:  @key_iter *i@ = pointer to iterator object
+ *
+ * Returns:    Pointer to next key, or null.
+ *
+ * Use:                Returns the next key in some arbitrary sequence.
+ */
+
+key *key_next(key_iter *i)
+{
+  hash_base *b;
+  key *k;
+  do {
+    HASH_NEXT(&i->i, b);
+    k = (key *)b;
+  } while (k && KEY_EXPIRED(i->t, k->exp) && KEY_EXPIRED(i->t, k->del));
+  return (k);
+}
+
+/*----- Lookup ------------------------------------------------------------*/
+
+/* --- @key_bytype@ --- *
+ *
+ * Arguments:  @key_file *f@ = key file we want a key from
+ *             @const char *type@ = type string for desired key
+ *
+ * Returns:    Pointer to the best key to use, or null.
+ *
+ * Use:                Looks up a key by its type.  Returns the key with the latest
+ *             expiry time.  This function will not return an expired key.
+ */
+
+key *key_bytype(key_file *f, const char *type)
+{
+  time_t now = time(0);
+  key *k;
+  key_ref *kr;
+
+  if ((kr = sym_find(&f->bytype, type, -1, 0, 0)) == 0)
+    return (0);
+  for (k = kr->k; k && KEY_EXPIRED(now, k->exp); k = k->next)
+    ;
+  return (k);
+}
+
+/* --- @key_byid@ --- *
+ *
+ * Arguments:  @key_file *f@ = key file to find a key from
+ *             @uint32 id@ = id to look for
+ *
+ * Returns:    Key with matching id.
+ *
+ * Use:                Returns a key given its id.  This function will return an
+ *             expired key, but not a deleted one.
+ */
+
+key *key_byid(key_file *f, uint32 id)
+{
+  time_t t = time(0);
+  hash_base **bin, *b;
+
+  bin = HASH_BIN(&f->byid, id);
+  for (b = *bin; b; b = b->next) {
+    if (b->hash == id) {
+      key *k = (key *)b;
+      if (KEY_EXPIRED(t, k->exp) && KEY_EXPIRED(t, k->del))
+       return (0);
+      return (k);
+    }
+  }
+  return (0);
+}
+
+/* --- @key_bytag@ --- *
+ *
+ * Arguments:  @key_file *f@ = key file to find a key from
+ *             @const char *tag@ = pointer to tag string
+ *
+ * Returns:    Key with matching id or tag.
+ *
+ * Use:                Returns a key given its tag or id.  This function will return
+ *             an expired key, but not a deleted one.
+ */
+
+key *key_bytag(key_file *f, const char *tag)
+{
+  time_t t = time(0);
+  char *p;
+  uint32 id;
+  key_ref *kr = sym_find(&f->bytag, tag, -1, 0, 0);
+
+  if (kr && !(KEY_EXPIRED(t, kr->k->exp) && KEY_EXPIRED(t, kr->k->del)))
+    return (kr->k);
+  id = strtoul(tag, &p, 16);
+  if (!*p)
+    return (key_byid(f, id));
+  return (key_bytype(f, tag));
+}
+
+/* --- @key_qtag@ --- *
+ *
+ * Arguments:  @key_file *f@ = key file to find a key from
+ *             @const char *tag@ = pointer to tag string
+ *             @dstr *d@ = pointer to string for full tag name
+ *             @key **k@ = where to store the key pointer
+ *             @key_data ***kd@ = where to store the key data pointer
+ *
+ * Returns:    Zero if OK, nonzero if it failed.
+ *
+ * Use:                Performs a full lookup on a qualified tag name.  The tag is
+ *             qualified by the names of subkeys, separated by dots.  Hence,
+ *             a qualified tag is ID|TAG[.TAG...].  The various result
+ *             pointers can be null to indicate that the result isn't
+ *             interesting.
+ */
+
+int key_qtag(key_file *f, const char *tag, dstr *d, key **k, key_data ***kd)
+{
+  dstr dd = DSTR_INIT;
+  const char *q;
+  key *kk;
+  key_data **kkd;
+
+  /* --- Find the end of the base tag --- */
+
+  if ((q = strchr(tag, '.')) == 0)
+    DPUTS(&dd, tag);
+  else {
+    DPUTM(&dd, tag, q - tag);
+    DPUTZ(&dd);
+    q++;
+  }
+
+  /* --- Look up the key tag --- */
+
+  if ((kk = key_bytag(f, dd.buf)) == 0) {
+    dstr_destroy(&dd);
+    return (-1);
+  }
+
+  /* --- Set the various initial bits of result up --- */
+
+  if (d)
+    key_fulltag(kk, d);
+  if (k)
+    *k = kk;
+  kkd = &kk->k;
+
+  /* --- Now dig through the rest of the tag --- */
+
+  if (q) {
+    while (*q) {
+      key_struct *ks;
+
+      /* --- Stick on the next bit of the fullqtag --- */
+
+      DRESET(&dd);
+      while (*q && *q != '.') {
+       DPUTC(&dd, *q);
+       q++;
+      }
+      DPUTZ(&dd);
+      if (d) {
+       DPUTC(d, '.');
+       DPUTD(d, &dd);
+      }
+
+      /* --- Look up the subkey --- */
+
+      if ((*kkd)->e != KENC_STRUCT) {
+       kkd = 0;
+       break;
+      }
+      if ((ks = sym_find(&(*kkd)->u.s, dd.buf, -1, 0, 0)) == 0) {
+       kkd = 0;
+       break;
+      }
+      kkd = &ks->k;
+    }
+  }
+
+  /* --- Return the results --- */
+
+  dstr_destroy(&dd);
+  if (!kkd)
+    return (-1);
+  if (kd)
+    *kd = kkd;
+  return (0);
+}
+
+/*----- Miscellaneous functions -------------------------------------------*/
+
+/* --- @key_delete@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file block
+ *             @key *k@ = key to delete
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Removes the given key from the list.  The key file must be
+ *             writable.  (Due to the horridness of the data structures,
+ *             deleted keys aren't actually removed, just marked so that
+ *             they can't be looked up or iterated over.  One upshot of
+ *             this is that they don't get written back to the file when
+ *             it's closed.)
+ */
+
+int key_delete(key_file *f, key *k)
+{
+  KEY_WRITE(f);
+  k->exp = KEXP_EXPIRE;
+  k->del = KEXP_EXPIRE;
+  KEY_MODIFY(f);
+  return (0);
+}
+
+/* --- @key_expired@ --- *
+ *
+ * Arguments:  @key *k@ = pointer to key block
+ *
+ * Returns:    Zero if the key is OK, nonzero if it's expired.
+ */
+
+int key_expired(key *k)
+{
+  time_t now = time(0);
+  return (KEY_EXPIRED(now, k->exp) || KEY_EXPIRED(now, k->del));
+}
+
+/* --- @key_expire@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file block
+ *             @key *k@ = pointer to key block
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Immediately marks the key as expired.  It may be removed
+ *             immediately, if it is no longer required, and will be removed
+ *             by a tidy operation when it is no longer required.  The key
+ *             file must be writable.
+ */
+
+int key_expire(key_file *f, key *k)
+{
+  KEY_WRITE(f);
+  k->exp = KEXP_EXPIRE;
+  if (k->del == KEXP_FOREVER)
+    k->del = KEXP_EXPIRE;
+  KEY_MODIFY(f);
+  return (0);
+}
+
+/* --- @key_used@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file
+ *             @key *k@ = pointer to key block
+ *             @time_t t@ = when key can be removed
+ *
+ * Returns:    Zero if OK, nonzero on failure.
+ *
+ * Use:                Marks a key as being required until a given time.  Even
+ *             though the key may expire before then (and won't be returned
+ *             by type after that time), it will still be available when
+ *             requested explicitly by id.  The key file must be writable.
+ *
+ *             The only (current) reason for failure is attempting to use
+ *             a key which can expire for something which can't.
+ */
+
+int key_used(key_file *f, key *k, time_t t)
+{
+  KEY_WRITE(f);
+  if (t == KEXP_FOREVER) {
+    if (k->exp != KEXP_FOREVER)
+      return (KERR_WILLEXPIRE);
+  } else if (k->del >= t)
+    return (0);
+
+  k->del = t;
+  KEY_MODIFY(f);
+  return (0);
+}
+
+/* --- @key_fingerprint@ --- *
+ *
+ * Arguments:  @key *k@ = the key to fingerprint
+ *             @ghash *h@ = the hash to use
+ *             @const key_filter *kf@ = filter to apply
+ *
+ * Returns:    Nonzero if the key slightly matched the filter.
+ *
+ * Use:                Updates the hash context with the key contents.
+ */
+
+static int abyname(const void *a, const void *b) {
+  key_attr *const *x = a, *const *y = b;
+  return (strcmp(SYM_NAME(*x), SYM_NAME(*y)));
+}
+
+int key_fingerprint(key *k, ghash *h, const key_filter *kf)
+{
+  dstr d = DSTR_INIT;
+  int rc = 0;
+  key_attr *a, **v;
+  size_t n, i;
+  sym_iter ai;
+
+  if (!key_encode(k->k, &d, kf))
+    goto done;
+  rc = 1;
+  GH_HASHSTR(h, "catacomb-key-fingerprint:");
+  GH_HASHU32(h, k->id);
+  GH_HASHSTR8(h, k->type);
+  GH_HASH(h, d.buf, d.len);
+  for (n = 0, sym_mkiter(&ai, &k->a); (a = sym_next(&ai)) != 0; n++);
+  if (n) {
+    v = xmalloc(n * sizeof(*v));
+    for (i = 0, sym_mkiter(&ai, &k->a); (a = sym_next(&ai)) != 0; i++)
+      v[i] = a;
+    qsort(v, n, sizeof(*v), abyname);
+    for (i = 0; i < n; i++) {
+      GH_HASHSTR8(h, SYM_NAME(v[i]));
+      GH_HASHSTR16(h, v[i]->p);
+    }
+    xfree(v);
+  }
+done:
+  dstr_destroy(&d);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-moan.c b/key/key-moan.c
new file mode 100644 (file)
index 0000000..cc44770
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*-c-*-
+ *
+ * Standard error handling function for key loading
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/report.h>
+
+#include "key.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_moan@ --- *
+ *
+ * Arguments:  @const char *file@ = name of the file
+ *             @int line@ = line number in file
+ *             @const char *msg@ = error message
+ *             @void *p@ = argument pointer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reports an error message about loading a key file.
+ */
+
+void key_moan(const char *file, int line, const char *msg, void *p)
+{
+  moan("%s:%i: error: %s", file, line, msg);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-pack.c b/key/key-pack.c
new file mode 100644 (file)
index 0000000..61495b9
--- /dev/null
@@ -0,0 +1,247 @@
+/* -*-c-*-
+ *
+ * Packing and unpacking key data
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "key-data.h"
+
+/*----- Generic packing and unpacking -------------------------------------*/
+
+/* --- @key_pack@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_data **kd@ = where to put the key data pointer
+ *             @dstr *d@ = pointer to tag string for the key data
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Packs a key from a data structure.
+ */
+
+int key_pack(key_packdef *kp, key_data **kd, dstr *d)
+{
+  switch (kp->e & KF_ENCMASK) {
+
+    /* --- Binary and integer keys are easy --- */
+
+    case KENC_BINARY: {
+      key_bin *b = kp->p;
+      *kd = key_newbinary(kp->e, b->k, b->sz);
+      return (0);
+    }
+    case KENC_MP:
+      *kd = key_newmp(kp->e, *(mp **)kp->p);
+      return (0);
+    case KENC_STRING:
+      *kd = key_newstring(kp->e, *(char **)kp->p);
+      return (0);
+    case KENC_EC:
+      *kd = key_newec(kp->e, (ec *)kp->p);
+      return (0);
+
+    /* --- Encrypted keys are a little tricky --- *
+     *
+     * This works rather differently to unpacking.
+     */
+
+    case KENC_ENCRYPT: {
+      key_data *kkd;
+      int err = key_pack(kp->p, &kkd, d);
+      if (!err) {
+       err = key_plock(kd, kkd, d->buf);
+       key_drop(kkd);
+      }
+      return (err);
+    }
+
+    /* --- Structured keys, as ever, are a nuisance --- */
+
+    case KENC_STRUCT: {
+      int err;
+      key_packstruct *p;
+      size_t l = d->len;
+
+      *kd = key_newstruct();
+      DPUTC(d, '.');
+      for (p = kp->p; p->name; p++) {
+       key_data *kkd;
+       d->len = l + 1;
+       DPUTS(d, p->name);
+       if ((err = key_pack(&p->kp, &kkd, d)) != 0) {
+         key_drop(*kd);
+         return (err);
+       }
+       key_structsteal(*kd, p->name, kkd);
+      }
+      d->len = l;
+      d->buf[l] = 0;
+      return (0);
+    }
+    default:
+      abort();
+  }
+}
+
+/* --- @key_unpack@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_data *kd@ = pointer to source key data
+ *             @dstr *d@ = pointer to tag string for the key data
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Unpacks a key into an appropriate data structure.
+ */
+
+int key_unpack(key_packdef *kp, key_data *kd, dstr *d)
+{
+  unsigned e = kp->e & KF_ENCMASK;
+  int err;
+
+  /* --- Decrypt the encrypted key --- */
+
+  if ((kd->e & KF_ENCMASK) == KENC_ENCRYPT) {
+    if ((err = key_punlock(&kp->kd, kd, d->buf)) != 0)
+      goto fail;
+    kd = kp->kd;
+  }
+
+  /* --- Ensure that the key has the right type --- */
+
+  if ((kd->e & KF_ENCMASK) != e) {
+    err = KERR_WRONGTYPE;
+    goto fail;
+  }
+
+  /* --- Unpack the key --- *
+   *
+   * Only three possibilities left now.
+   */
+
+  switch (e) {
+
+    /* --- Binary and integer keys are easy --- */
+
+    case KENC_BINARY:
+      *(key_bin *)kp->p = kd->u.k;
+      break;
+    case KENC_MP:
+      *(mp **)kp->p = kd->u.m;
+      break;
+    case KENC_STRING:
+      *(char **)kp->p = kd->u.p;
+      break;
+    case KENC_EC:
+      *(ec *)kp->p = kd->u.e;
+      break;
+
+    /* --- Structured keys take a little care --- */
+
+    case KENC_STRUCT: {
+      key_packstruct *p, *q;
+      size_t l = d->len;
+
+      /* --- Iterate over the requested subparts --- */
+
+      DPUTC(d, '.');
+      for (p = kp->p; p->name; p++) {
+       key_data *kkd;
+
+       /* --- Build the name --- */
+
+       d->len = l + 1;
+       DPUTS(d, p->name);
+
+       /* --- Find and unpack the subkey --- */
+
+       if ((kkd = key_structfind(kd, p->name)) == 0) {
+         if (!(p->kp.e & KF_OPT)) {
+           err = KERR_NOTFOUND;
+           goto tidy;
+         }
+       } else if ((err = key_unpack(&p->kp, kkd, d)) != 0) {
+         p++;
+         goto tidy;
+       }
+      }
+
+      /* --- Done --- */
+
+      d->len = l;
+      d->buf[l] = 0;
+      break;
+
+      /* --- Tidy up if something went wrong --- */
+
+    tidy:
+      for (q = kp->p; q < p; q++)
+       key_unpackdone(&q->kp);
+      goto fail;
+    }
+
+    default:
+      abort();
+  }
+
+  return (0);
+
+  /* --- Something went wrong --- */
+
+fail:
+  if (kp->kd) {
+    key_drop(kp->kd);
+    kp->kd = 0;
+  }
+  return (err);
+}
+
+/* --- @key_unpackdone@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing definition
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees the key components contained within a packing
+ *             definition, created during key unpacking.
+ */
+
+void key_unpackdone(key_packdef *kp)
+{
+  if (kp->kd) {
+    key_drop(kp->kd);
+    kp->kd = 0;
+  }
+  if ((kp->e & KF_ENCMASK) == KENC_STRUCT) {
+    key_packstruct *p;
+    for (p = kp->p; p->name; p++)
+      key_unpackdone(&p->kp);
+  }
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-pass.c b/key/key-pass.c
new file mode 100644 (file)
index 0000000..665030e
--- /dev/null
@@ -0,0 +1,262 @@
+/* -*-c-*-
+ *
+ * Encrypting keys with passphrases
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "key-data.h"
+#include "paranoia.h"
+#include "passphrase.h"
+#include "rand.h"
+
+#include "blowfish-cbc.h"
+#include "rmd160.h"
+#include "rmd160-mgf.h"
+#include "rmd160-hmac.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Format --- *
+ *
+ * Choose a random 160-bit string %$R$%.  Take the passphrase %$P$%, and
+ * the message %$m$%.  Now, compute %$K_E \cat K_T = H(R \cat P)$%,
+ * %$y_0 = E_{K_E}(m)$% and %$\tau = T_{K_T}(y_0)$%.  The ciphertext is
+ * %$y = N \cat \tau \cat y_0$%.
+ *
+ * This is not the original format.  The original format was insecure, and
+ * has been replaced incompatibly.
+ */
+
+/* --- @key_lock@ --- *
+ *
+ * Arguments:  @key_data **kt@ = where to store the destination pointer
+ *             @key_data *k@ = source key data block or null to use @*kt@
+ *             @const void *e@ = secret to encrypt key with
+ *             @size_t esz@ = size of the secret
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts a key data block using a secret.
+ */
+
+void key_lock(key_data **kt, key_data *k, const void *e, size_t esz)
+{
+  dstr d = DSTR_INIT;
+  octet b[RMD160_HASHSZ * 2];
+  octet *m;
+  size_t msz;
+  rmd160_mgfctx r;
+  blowfish_cbcctx c;
+  rmd160_mackey mk;
+  rmd160_macctx mc;
+
+  /* --- Sanity check --- */
+
+  if (k) key_incref(k); else k = *kt;
+  assert(((void)"Key data is already encrypted",
+         (k->e & KF_ENCMASK) != KENC_ENCRYPT));
+
+  /* --- Format the stuff in the buffer --- */
+
+  DENSURE(&d, RMD160_HASHSZ * 2);
+  rand_get(RAND_GLOBAL, d.buf, RMD160_HASHSZ);
+  d.len += RMD160_HASHSZ * 2;
+  key_encode(k, &d, 0);
+  m = (octet *)d.buf + RMD160_HASHSZ * 2;
+  msz = d.len - RMD160_HASHSZ * 2;
+
+  /* --- Hash the passphrase to make a key --- */
+
+  rmd160_mgfkeybegin(&r);
+  rmd160_mgfkeyadd(&r, d.buf, RMD160_HASHSZ);
+  rmd160_mgfkeyadd(&r, e, esz);
+  rmd160_mgfencrypt(&r, 0, b, sizeof(b));
+  BURN(r);
+
+  /* --- Encrypt the plaintext --- */
+
+  blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0);
+  blowfish_cbcencrypt(&c, m, m, msz);
+  BURN(c);
+
+  /* --- MAC the ciphertext --- */
+
+  rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
+  rmd160_macinit(&mc, &mk);
+  rmd160_machash(&mc, m, msz);
+  rmd160_macdone(&mc, d.buf + RMD160_HASHSZ);
+  BURN(mk);
+  BURN(mc);
+
+  /* --- Done --- */
+
+  BURN(b);
+  *kt = key_newencrypted(0, d.buf, d.len);
+  key_drop(k);
+  dstr_destroy(&d);
+}
+
+/* --- @key_unlock@ --- *
+ *
+ * Arguments:  @key_data **kt@ = where to store the destination pointer
+ *             @key_data *k@ = source key data block or null to use @*kt@
+ *             @const void *e@ = secret to decrypt the block with
+ *             @size_t esz@ = size of the secret
+ *
+ * Returns:    Zero for success, or a @KERR_@ error code.
+ *
+ * Use:                Unlocks a key using a secret.
+ */
+
+int key_unlock(key_data **kt, key_data *k, const void *e, size_t esz)
+{
+  octet b[RMD160_HASHSZ * 2];
+  octet *p = 0;
+  int rc;
+  int drop = 0;
+  key_data *kd;
+  rmd160_mgfctx r;
+  blowfish_cbcctx c;
+  rmd160_mackey mk;
+  rmd160_macctx mc;
+  size_t sz;
+
+  /* --- Sanity check --- */
+
+  if (!k) { k = *kt; drop = 1; }
+  assert(((void)"Key data isn't encrypted",
+         (k->e & KF_ENCMASK) == KENC_ENCRYPT));
+
+  /* --- Check the size --- */
+
+  if (k->u.k.sz < RMD160_HASHSZ * 2)
+    return (KERR_MALFORMED);
+  sz = k->u.k.sz - RMD160_HASHSZ * 2;
+
+  /* --- Hash the passphrase to make a key --- */
+
+  rmd160_mgfkeybegin(&r);
+  rmd160_mgfkeyadd(&r, k->u.k.k, RMD160_HASHSZ);
+  rmd160_mgfkeyadd(&r, e, esz);
+  rmd160_mgfencrypt(&r, 0, b, sizeof(b));
+  BURN(r);
+
+  /* --- Verify the MAC --- */
+
+  rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
+  rmd160_macinit(&mc, &mk);
+  rmd160_machash(&mc, k->u.k.k + RMD160_HASHSZ * 2, sz);
+  rmd160_macdone(&mc, b + RMD160_HASHSZ);
+  if (memcmp(b + RMD160_HASHSZ, k->u.k.k + RMD160_HASHSZ,
+            RMD160_HASHSZ) != 0) {
+    rc = KERR_BADPASS;
+    goto fail;
+  }
+  BURN(mk);
+  BURN(mc);
+
+  /* --- Allocate a destination buffer --- */
+
+  p = xmalloc(sz);
+
+  /* --- Decrypt the key data --- */
+
+  blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0);
+  blowfish_cbcdecrypt(&c, k->u.k.k + RMD160_HASHSZ * 2, p, sz);
+  BURN(c);
+
+  /* --- Decode the key data into the destination buffer --- */
+
+  if ((kd = key_decode(p, sz)) == 0) {
+    rc = KERR_MALFORMED;
+    goto fail;
+  }
+  *kt = kd;
+
+  /* --- Done --- */
+
+  xfree(p);
+  if (drop) key_drop(k);
+  return (0);
+
+  /* --- Tidy up if things went wrong --- */
+
+fail:
+  BURN(b);
+  xfree(p);
+  return (rc);
+}
+
+/* --- @key_plock@ --- *
+ *
+ * Arguments:  @key_data **kt@ = where to store the destination pointer
+ *             @key_data *k@ = source key data block or null to use @*kt@
+ *             @const char *tag@ = tag to use for passphrase
+ *
+ * Returns:    Zero if successful, a @KERR@ error code on failure.
+ *
+ * Use:                Locks a key by encrypting it with a passphrase.
+ */
+
+int key_plock(key_data **kt, key_data *k, const char *tag)
+{
+  char buf[256];
+
+  if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf)))
+    return (KERR_IO);
+  key_lock(kt, k, buf, strlen(buf));
+  BURN(buf);
+  return (0);
+}
+
+/* --- @key_punlock@ --- *
+ *
+ * Arguments:  @key_data **kt@ = where to store the destination pointer
+ *             @key_data *k@ = source key data block or null to use @*kt@
+ *             @const char *tag@ = tag to use for passphrase
+ *
+ * Returns:    Zero if it worked, a @KERR_@ error code on failure.
+ *
+ * Use:                Unlocks a passphrase-locked key.
+ */
+
+int key_punlock(key_data **kt, key_data *k, const char *tag)
+{
+  char buf[256];
+  int rc;
+
+  if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
+    return (KERR_IO);
+  rc = key_unlock(kt, k, buf, strlen(buf));
+  BURN(buf);
+  if (rc == KERR_BADPASS || !k)
+    passphrase_cancel(tag);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key-text.c b/key/key-text.c
new file mode 100644 (file)
index 0000000..98c1fba
--- /dev/null
@@ -0,0 +1,344 @@
+/* -*-c-*-
+ *
+ * Key textual encoding
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/base64.h>
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+#include <mLib/sub.h>
+#include <mLib/sym.h>
+#include <mLib/url.h>
+
+#include "key-data.h"
+#include "mp.h"
+#include "mptext.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_read@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to textual key representation
+ *             @char **pp@ = where to store the end pointer
+ *
+ * Returns:    The newly-read key data, or null if it failed.
+ *
+ * Use:                Parses a textual key description.
+ */
+
+key_data *key_read(const char *p, char **pp)
+{
+  unsigned e;
+  key_data *kd;
+
+  /* --- Read the encoding type --- *
+   *
+   * The key format is `[FLAGS:]DATA'.  If there is no encoding type
+   * named, assume that it's `binary' for backwards compatibility.
+   */
+
+  if (strchr(p, ':') == 0)
+    e = 0;
+  else {
+    char *q;
+    if (key_readflags(p, &q, &e, 0))
+      return (0);
+    p = q + 1;
+  }
+
+  /* --- Now scan the data based on the encoding type --- */
+
+  switch (e & KF_ENCMASK) {
+
+    /* --- Binary encoding --- *
+     *
+     * Simply read out the Base64-encoded data.  Since `,' and `]' are our
+     * delimeter characters, and they can't appear in Base64-encoded data, I
+     * can just do a simple search to find the end of the encoded data.
+     */
+
+    case KENC_BINARY:
+    case KENC_ENCRYPT: {
+      dstr d = DSTR_INIT;
+      base64_ctx b;
+      size_t sz = strcspn(p, ",]");
+
+      base64_init(&b);
+      base64_decode(&b, p, sz, &d);
+      base64_decode(&b, 0, 0, &d);
+      kd = key_newbinary(e, d.buf, d.len);
+      dstr_destroy(&d);
+      p += sz;
+    } break;
+
+    /* --- Multiprecision integer encoding --- *
+     *
+     * Multiprecision integers have a convenient reading function.
+     */
+
+    case KENC_MP: {
+      char *q;
+      mp *m = mp_readstring(e & KF_BURN ? MP_NEWSEC : MP_NEW, p, &q, 0);
+      if (!m)
+       return (0);
+      kd = key_newmp(e, m);
+      MP_DROP(m);
+      p = q;
+    } break;
+
+    /* --- String encoding --- *
+     *
+     * We use form-urlencoding to ensure that evil characters don't get out.
+     */
+
+    case KENC_STRING: {
+      dstr d = DSTR_INIT;
+      size_t sz = strcspn(p, ",]");
+      const char *l = p + sz;
+      unsigned int ch;
+      int x, n;
+
+      while (p < l) {
+       switch (*p) {
+         case '+':
+           DPUTC(&d, ' '); break;
+         case '%':
+           x = sscanf(p + 1, "%2x%n", &ch, &n);
+           if (x == 1) { DPUTC(&d, ch); p += n; break; }
+         default:
+           DPUTC(&d, *p); break;
+       }
+       p++;
+      }
+      DPUTZ(&d);
+      kd = key_newstring(e, d.buf);
+      dstr_destroy(&d);
+    } break;
+
+    /* --- Elliptic curve encoding --- *
+     *
+     * Again, we have a convenient function.  Assume for now that points
+     * aren't secret.  (Reasonably safe.)
+     */
+
+    case KENC_EC: {
+      ec pt = EC_INIT;
+      qd_parse qd;
+      qd.p = p;
+      qd.e = 0;
+      if (!ec_ptparse(&qd, &pt))
+       return (0);
+      kd = key_newec(e, &pt);
+      EC_DESTROY(&pt);
+      p = qd.p;
+    } break;
+
+    /* --- Structured information encoding --- *
+     *
+     * The format for structured key data is `[NAME=KEY,...]', where the
+     * brackets are part of the syntax.  Structured keys have no flags apart
+     * from the encoding.
+     *
+     * The binary encoding only allows names up to 255 bytes long.  Check for
+     * this here.
+     */
+
+    case KENC_STRUCT: {
+      dstr d = DSTR_INIT;
+      key_data *nkd;
+      char *q;
+
+      /* --- Read the opening bracket --- */
+
+      kd = key_newstruct();
+      if (*p != '[')
+       return (0);
+      p++;
+
+      /* --- Read named key subparts --- */
+
+      for (;;) {
+       size_t sz;
+
+       /* --- Stop if there's a close-bracket --- *
+        *
+        * This allows `[]' to be an empty structured key, which is good.  It
+        * also makes `[foo=enc:bar,]' legal, and that's less good but I can
+        * live with it.
+        */
+
+       if (*p == ']')
+         break;
+
+       /* --- Read the name out and check the length --- */
+
+       if ((q = strchr(p, '=')) == 0)
+         goto fail;
+       sz = q - p;
+       if (sz >= 256)
+         goto fail;
+       DRESET(&d);
+       DPUTM(&d, p, sz);
+       DPUTZ(&d);
+
+       /* --- Read the key data for the subkey --- */
+
+       if ((nkd = key_read(q + 1, &q)) == 0)
+         goto fail;
+       key_structsteal(kd, d.buf, nkd);
+       p = q;
+
+       /* --- Read the comma or close-bracket --- */
+
+       if (*p == ']')
+         break;
+       else if (*p == ',')
+         p++;
+       else
+         goto fail;
+      }
+
+      /* --- Step past the close bracket --- */
+
+      p++;
+      dstr_destroy(&d);
+      break;
+
+      /* --- Tidy up after a failure --- */
+
+    fail:
+      dstr_destroy(&d);
+      return (0);
+    } break;
+
+    /* --- Anything else is unknown --- */
+
+    default:
+      return (0);
+  }
+
+  /* --- Return the end pointer --- */
+
+  kd->e = e;
+  if (pp)
+    *pp = (char *)p;
+  return (kd);
+}
+
+/* --- @key_write@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data
+ *             @dstr *d@ = destination string to write on
+ *             @const key_filter *kf@ = pointer to key selection block
+ *
+ * Returns:    Nonzero if an item was actually written.
+ *
+ * Use:                Writes a key in a textual encoding.
+ */
+
+int key_write(key_data *k, dstr *d, const key_filter *kf)
+{
+  int rc = 0;
+  if (!KEY_MATCH(k, kf))
+    return (0);
+  switch (k->e & KF_ENCMASK) {
+    case KENC_BINARY:
+    case KENC_ENCRYPT: {
+      base64_ctx b;
+
+      if ((k->e & KF_ENCMASK) == KENC_BINARY)
+       key_writeflags(k->e, d);
+      else
+       DPUTS(d, "encrypt,secret");
+      DPUTC(d, ':');
+      base64_init(&b);
+      b.indent = "";
+      b.maxline = 0;
+      base64_encode(&b, k->u.k.k, k->u.k.sz, d);
+      base64_encode(&b, 0, 0, d);
+      rc = 1;
+    } break;
+    case KENC_MP:
+      key_writeflags(k->e, d);
+      DPUTC(d, ':');
+      mp_writedstr(k->u.m, d, 10);
+      rc = 1;
+      break;
+    case KENC_STRING: {
+      const char *p = k->u.p;
+      key_writeflags(k->e, d);
+      DPUTC(d, ':');
+      while (*p) {
+       if (*p == ' ') DPUTC(d, '+');
+       else if (!isalnum((unsigned char)*p)) dstr_putf(d, "%%%02x", *p);
+       else DPUTC(d, *p);
+       p++;
+      }
+      rc = 1;
+    } break;
+    case KENC_EC:
+      key_writeflags(k->e, d);
+      DPUTS(d, ":0x"); mp_writedstr(k->u.e.x, d, 16);
+      DPUTS(d, ",0x"); mp_writedstr(k->u.e.y, d, 16);
+      rc = 1;
+      break;
+    case KENC_STRUCT: {
+      key_subkeyiter i;
+      const char *tag;
+      char del = 0;
+      size_t n = d->len;
+
+      DPUTS(d, "struct:[");
+      for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
+       size_t o = d->len;
+       if (del)
+         DPUTC(d, del);
+       DPUTS(d, tag);
+       DPUTC(d, '=');
+       if (!key_write(k, d, kf))
+         d->len = o;
+       else {
+         del = ',';
+         rc = 1;
+       }
+      }
+      if (!rc)
+       d->len = n;
+      else
+       DPUTC(d, ']');
+    } break;
+  }
+  DPUTZ(d);
+
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/key.h b/key/key.h
new file mode 100644 (file)
index 0000000..bed3632
--- /dev/null
+++ b/key/key.h
@@ -0,0 +1,700 @@
+/* -*-c-*-
+ *
+ * Simple key management
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_KEY_H
+#define CATACOMB_KEY_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <time.h>
+
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+#include <mLib/hash.h>
+#include <mLib/sym.h>
+
+#ifndef CATACOMB_KEY_ERROR_H
+#  include "key-error.h"
+#endif
+
+#ifndef CATACOMB_KEY_DATA_H
+#  include "key-data.h"
+#endif
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- Key attributes --- *
+ *
+ * Each attribute is stored as a symbol in a symbol table.  The value is
+ * the plain (not url-encoded) text to be written to the the file.  If the
+ * value is binary data, then by this point it's base-64 encoded.
+ */
+
+typedef struct key_attr {
+  sym_base _b;                         /* Symbol table data */
+  char *p;                             /* Pointer to attribute value */
+} key_attr;
+
+/* --- Main key structure --- *
+ *
+ * Each key is stored in two symbol tables, one indexed by keyid, and the
+ * other indexed by type.  Because many keys can have the same type, the type
+ * table contains a list of keys, sorted in descending order of expiry.
+ */
+
+typedef struct key {
+
+  /* --- Hashtable management --- */
+
+  hash_base _b;                                /* Symbol table data */
+  struct key *next;                    /* Next key of the same type */
+
+  /* --- Basic key attributes --- */
+
+  uint32 id;                           /* Key id used to name it */
+  char *tag;                           /* Textual tag name */
+  char *type;                          /* Textual key type */
+  time_t exp, del;                     /* Expiry times for keys */
+
+  /* --- The key data itself --- */
+
+  key_data *k;                         /* The actual key data */
+
+  /* --- Other attributes and commentary --- */
+
+  sym_table a;                         /* Hashtable of key attributes */
+  char *c;                             /* Any additional comments */
+} key;
+
+/* --- The keys-by-type entries --- */
+
+typedef struct key_ref {
+  sym_base _b;                         /* Symbol table data */
+  key *k;                              /* Pointer to first key in list */
+} key_ref;
+
+/* --- A key file --- */
+
+typedef struct key_file {
+  FILE *fp;                            /* File pointer open on file */
+  char *name;                          /* Filename used to create it */
+  unsigned f;                          /* Various useful flags */
+  hash_table byid;                     /* Table of keys by keyid */
+  sym_table bytype;                    /* Table of keys by type */
+  sym_table bytag;                     /* Table of keys by tag */
+  size_t idload;                       /* Loading on id table */
+} key_file;
+
+/* --- Key file flags --- */
+
+#define KF_WRITE 1u                    /* File opened for writing */
+#define KF_MODIFIED 2u                 /* File has been modified */
+
+/* --- Iterating over keys --- *
+ *
+ * Both of these are simple symbol table iterators, but they're made distinct
+ * types for the dubious benefits that type safety brings.
+ */
+
+typedef struct { hash_iter i; time_t t; } key_iter;
+typedef struct { sym_iter i; } key_attriter;
+
+/* --- Key fetching --- */
+
+typedef struct key_fetchdef {
+  char *name;                          /* Name of item */
+  size_t off;                          /* Offset into target structure */
+  unsigned e;                          /* Flags for the item */
+  const struct key_fetchdef *kf;       /* Substructure pointer */
+} key_fetchdef;
+
+/* --- File opening options --- */
+
+#define KOPEN_READ 0u
+#define KOPEN_WRITE 1u
+#define KOPEN_MASK 0xff
+#define KOPEN_NOFILE 0x100
+
+/* --- Various other magic numbers --- */
+
+#define KEXP_FOREVER ((time_t)-1)      /* Never expire this key */
+#define KEXP_EXPIRE ((time_t)-2)       /* Expire this key when unused */
+
+/* --- Write error codes --- */
+
+enum {
+  KWRITE_OK,                           /* Everything went fine */
+  KWRITE_FAIL = -1,                    /* Close attempt failed */
+  KWRITE_BROKEN        = -2                    /* Key ring needs manual fixing */
+};
+
+/* --- Error reporting functions for @key_merge@ and @key_open@ --- */
+
+typedef void key_reporter(const char */*file*/, int /*line*/,
+                         const char */*err*/, void */*p*/);
+
+/* --- Macros for testing expiry --- */
+
+#define KEY_EXPIRED(now, exp)                                          \
+  ((exp) == KEXP_EXPIRE || ((exp) != KEXP_FOREVER && (exp) < (now)))
+
+/*----- Reading and writing keys and files --------------------------------*/
+
+/* --- @key_merge@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure
+ *             @const char *file@ = name of file (for error messages)
+ *             @FILE *fp@ = file handle to read from
+ *             @key_reporter *rep@ = error reporting function
+ *             @void *arg@ = argument for function
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Reads keys from a file, and inserts them into the file.
+ */
+
+extern int key_merge(key_file */*f*/, const char */*file*/, FILE */*fp*/,
+                    key_reporter */*rep*/, void */*arg*/);
+
+/* --- @key_extract@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure
+ *             @key *k@ = key to extract
+ *             @FILE *fp@ = file to write on
+ *             @const key_filter *kf@ = pointer to key selection block
+ *
+ * Returns:    Zero if OK, EOF on error.
+ *
+ * Use:                Extracts a key to an ouptut file.
+ */
+
+extern int key_extract(key_file */*f*/, key */*k*/, FILE */*fp*/,
+                      const key_filter */*kf*/);
+
+/* --- @key_open@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure to initialize
+ *             @const char *file@ = pointer to the file name
+ *             @unsigned how@ = opening options (@KOPEN_*@).
+ *             @key_reporter *rep@ = error reporting function
+ *             @void *arg@ = argument for function
+ *
+ * Returns:    Zero if it worked, nonzero otherwise.
+ *
+ * Use:                Opens a key file, reads its contents, and stores them in a
+ *             structure.  The file is locked appropriately until closed
+ *             using @key_close@.  On an error, everything is cleared away
+ *             tidily.  If the file is opened with @KOPEN_WRITE@, it's
+ *             created if necessary, with read and write permissions for its
+ *             owner only.
+ */
+
+extern int key_open(key_file */*f*/, const char */*file*/, unsigned /*how*/,
+                   key_reporter */*rep*/, void */*arg*/);
+
+/* --- @key_discard@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees all the key data, without writing changes.
+ */
+
+extern void key_discard(key_file */*f*/);
+
+/* --- @key_close@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *
+ * Returns:    A @KWRITE_@ code indicating how it went.
+ *
+ * Use:                Frees all the key data, writes any changes.  Make sure that
+ *             all hell breaks loose if this returns @KWRITE_BROKEN@.
+ */
+
+extern int key_close(key_file */*f*/);
+
+/* --- @key_save@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *
+ * Returns:    A @KWRITE_@ code indicating how well it worked.
+ *
+ * Use:                Writes a key file's data back to the actual file.  This code
+ *             is extremely careful about error handling.  It should usually
+ *             be able to back out somewhere sensible, but it can tell when
+ *             it's got itself into a real pickle and starts leaving well
+ *             alone.
+ *
+ *             Callers, please make sure that you ring alarm bells when this
+ *             function returns @KWRITE_BROKEN@.
+ */
+
+extern int key_save(key_file */*f*/);
+
+/* --- @key_lockfile@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file structure to initialize
+ *             @const char *file@ = pointer to the file name
+ *             @unsigned how@ = opening options (@KOPEN_*@).
+ *
+ * Returns:    Zero if it worked, nonzero otherwise.
+ *
+ * Use:                Opens a keyfile and stores the information needed for
+ *             continued access in the structure.
+ *
+ *             If the file is opened with @KOPEN_WRITE@, it's created if
+ *             necessary with read and write permissions for owner only, and
+ *             locked for update while it's open.
+ *
+ *             This is a system-dependent routine, and only really intended
+ *             for the private use of @key_open@.
+ */
+
+extern int key_lockfile(key_file */*f*/, const char */*file*/,
+                       unsigned /*how*/);
+
+/*----- Creating and manipulating keys ------------------------------------*/
+
+/* --- @key_new@ ---
+ *
+ * Arguments:  @key_file *f@ = pointer to key file
+ *             @uint32 id@ = keyid to set
+ *             @const char *type@ = the type of this key
+ *             @time_t exp@ = when the key expires
+ *             @key *kk@ = where to put the key pointer
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Attaches a new key to a key file.  You must have a writable
+ *             key file for this to work.
+ *
+ *             The type is a key type string.  This interface doesn't care
+ *             about how type strings are formatted: it just treats them as
+ *             opaque gobs of text.  Clients are advised to choose some
+ *             standard for representing key types, though.
+ *
+ *             The expiry time should either be a time in the future, or the
+ *             magic value @KEXP_FOREVER@ which means `never expire this
+ *             key'.  Be careful with `forever' keys.  If I were you, I'd
+ *             use a more sophisticated key management system than this for
+ *             them.
+ *
+ *             You have to set the actual key yourself.
+ */
+
+extern int key_new(key_file */*f*/, uint32 /*id*/, const char */*type*/,
+                  time_t /*exp*/, key **/*kk*/);
+
+/* --- @key_delete@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file block
+ *             @key *k@ = key to delete
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Removes the given key from the list.  The key file must be
+ *             writable.  (Due to the horridness of the data structures,
+ *             deleted keys aren't actually removed, just marked so that
+ *             they can't be looked up or iterated over.  One upshot of
+ *             this is that they don't get written back to the file when
+ *             it's closed.)
+ */
+
+extern int key_delete(key_file */*f*/, key */*k*/);
+
+/* --- @key_expired@ --- *
+ *
+ * Arguments:  @key *k@ = pointer to key block
+ *
+ * Returns:    Zero if the key is OK, nonzero if it's expired.
+ */
+
+int key_expired(key */*k*/);
+
+/* --- @key_expire@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file block
+ *             @key *k@ = pointer to key block
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Immediately marks the key as expired.  It may be removed
+ *             immediately, if it is no longer required, and will be removed
+ *             by a tidy operation when it is no longer required.  The key
+ *             file must be writable.
+ */
+
+extern int key_expire(key_file */*f*/, key */*k*/);
+
+/* --- @key_used@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file
+ *             @key *k@ = pointer to key block
+ *             @time_t t@ = when key can be removed
+ *
+ * Returns:    Zero if OK, nonzero on failure.
+ *
+ * Use:                Marks a key as being required until a given time.  Even
+ *             though the key may expire before then (and won't be returned
+ *             by type after that time), it will still be available when
+ *             requested explicitly by id.  The key file must be writable.
+ *
+ *             The only (current) reason for failure is attempting to use
+ *             a key which can expire for something which can't.
+ */
+
+extern int key_used(key_file */*f*/, key */*k*/, time_t /*t*/);
+
+/* --- @key_fingerprint@ --- *
+ *
+ * Arguments:  @key *k@ = the key to fingerprint
+ *             @ghash *h@ = the hash to use
+ *             @const key_filter *kf@ = filter to apply
+ *
+ * Returns:    Nonzero if the key slightly matched the filter.
+ *
+ * Use:                Updates the hash context with the key contents.
+ */
+
+extern int key_fingerprint(key */*k*/, ghash */*h*/,
+                          const key_filter */*kf*/);
+
+/*----- Setting and reading attributes ------------------------------------*/
+
+/* --- @key_chkident@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to a type string
+ *
+ * Returns:    Zero if OK, -1 on error.
+ *
+ * Use:                Checks whether an identification component string is OK.
+ */
+
+extern int key_chkident(const char */*p*/);
+
+/* --- @key_chkcomment@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to a comment string
+ *
+ * Returns:    Zero if OK, -1 on error.
+ *
+ * Use:                Checks whether a comment string is OK.
+ */
+
+extern int key_chkcomment(const char */*p*/);
+
+/* --- @key_setcomment@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *             @key *k@ = pointer to key block
+ *             @const char *c@ = pointer to comment to set, or zero
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Replaces the key's current comment with a new one.
+ */
+
+extern int key_setcomment(key_file */*f*/, key */*k*/, const char */*c*/);
+
+/* --- @key_settag@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *             @key *k@ = pointer to key block
+ *             @const char *tag@ = pointer to comment to set, or zero
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Replaces the key's current tag with a new one.
+ */
+
+extern int key_settag(key_file */*f*/, key */*k*/, const char */*tag*/);
+
+/* --- @key_setkeydata@ --- *
+ *
+ * Arguments:  @key_file *kf@ = pointer to key file
+ *             @key *k@ = pointer to key
+ *             @key_data *kd@ = new key data
+ *
+ * Returns:    Zero on success, or a @KERR_@ error code on failure.
+ *
+ * Use:                Sets the key data for a key.
+ */
+
+extern int key_setkeydata(key_file */*kf*/, key */*k*/, key_data */*kd*/);
+
+/* --- @key_fulltag@ --- *
+ *
+ * Arguments:  @key *k@ = pointer to key
+ *             @dstr *d@ = pointer to destination string
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits the key's full tag, which has the form
+ *             `ID:TYPE[:TAG]'.  This is used in the textual file format,
+ *             and to identify passphrases for locked keys.
+ */
+
+extern void key_fulltag(key */*k*/, dstr */*d*/);
+
+/* --- @key_qtag@ --- *
+ *
+ * Arguments:  @key_file *f@ = key file to find a key from
+ *             @const char *tag@ = pointer to tag string
+ *             @dstr *d@ = pointer to string for full tag name
+ *             @key **k@ = where to store the key pointer
+ *             @key_data ***kd@ = where to store the key data pointer
+ *
+ * Returns:    Zero if OK, nonzero if it failed.
+ *
+ * Use:                Performs a full lookup on a qualified tag name.  The tag is
+ *             qualified by the names of subkeys, separated by dots.  Hence,
+ *             a qualified tag is ID|TAG[.TAG...].  The various result
+ *             pointers can be null to indicate that the result isn't
+ *             interesting.
+ */
+
+extern int key_qtag(key_file */*f*/, const char */*tag*/,
+                   dstr */*d*/, key **/*k*/, key_data ***/*kd*/);
+
+/* --- @key_getattr@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file
+ *             @key *k@ = pointer to key
+ *             @const char *n@ = pointer to attribute name
+ *
+ * Returns:    Pointer to attribute value, or null if not found.
+ *
+ * Use:                Returns the value of a key attribute.
+ */
+
+extern const char *key_getattr(key_file */*f*/, key */*k*/,
+                              const char */*n*/);
+
+/* --- @key_putattr@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to file
+ *             @key *k@ = pointer to key
+ *             @const char *n@ = pointer to attribute name
+ *             @const char *v@ = pointer to attribute value or null
+ *
+ * Returns:    Error code (one of the @KERR@ constants).
+ *
+ * Use:                Inserts an attribute on a key.  If an attribute with the same
+ *             name already exists, it is deleted.  Setting a null value
+ *             removes the attribute.
+ */
+
+extern int key_putattr(key_file */*f*/, key */*k*/,
+                      const char */*n*/, const char */*v*/);
+
+/* --- @key_mkattriter@ --- *
+ *
+ * Arguments:  @key_attriter *i@ = pointer to attribute iterator
+ *             @key *k@ = pointer to key
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an attribute iterator.  The attributes are
+ *             returned by @key_nextattr@.
+ */
+
+extern void key_mkattriter(key_attriter */*i*/, key */*k*/);
+
+/* --- @key_nextattr@ --- *
+ *
+ * Arguments:  @key_attriter *i@ = pointer to attribute iterator
+ *             @const char **n, **v@ = pointers to name and value
+ *
+ * Returns:    Zero if no attribute available, or nonzero if returned OK.
+ *
+ * Use:                Returns the next attribute.
+ */
+
+extern int key_nextattr(key_attriter */*i*/,
+                       const char **/*n*/, const char **/*v*/);
+
+/*----- Searching and iterating -------------------------------------------*/
+
+/* --- @key_bytype@ --- *
+ *
+ * Arguments:  @key_file *f@ = key file we want a key from
+ *             @const char *type@ = type string for desired key
+ *
+ * Returns:    Pointer to the best key to use, or null.
+ *
+ * Use:                Looks up a key by its type.  Returns the key with the latest
+ *             expiry time.  This function will not return an expired key.
+ */
+
+extern key *key_bytype(key_file */*f*/, const char */*type*/);
+
+/* --- @key_byid@ --- *
+ *
+ * Arguments:  @key_file *f@ = key file to find a key from
+ *             @uint32 id@ = id to look for
+ *
+ * Returns:    Key with matching id.
+ *
+ * Use:                Returns a key given its id.  This function will return an
+ *             expired key, but not a deleted one.
+ */
+
+extern key *key_byid(key_file */*f*/, uint32 /*id*/);
+
+/* --- @key_bytag@ --- *
+ *
+ * Arguments:  @key_file *f@ = key file to find a key from
+ *             @const char *tag@ = pointer to tag string
+ *
+ * Returns:    Key with matching id or tag.
+ *
+ * Use:                Returns a key given its tag or id.  This function will return
+ *             an expired key, but not a deleted one.
+ */
+
+extern key *key_bytag(key_file */*f*/, const char */*tag*/);
+
+/* --- @key_mkiter@ --- *
+ *
+ * Arguments:  @key_iter *i@ = pointer to iterator object
+ *             @key_file *f@ = pointer to file structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a key iterator.  The keys are returned by
+ *             @key_next@.
+ */
+
+extern void key_mkiter(key_iter */*i*/, key_file */*f*/);
+
+/* --- @key_next@ --- *
+ *
+ * Arguments:  @key_iter *i@ = pointer to iterator object
+ *
+ * Returns:    Pointer to next key, or null.
+ *
+ * Use:                Returns the next key in some arbitrary sequence.
+ */
+
+extern key *key_next(key_iter */*i*/);
+
+/*----- Fetching key data conveniently ------------------------------------*/
+
+/* --- @key_fetchinit@ --- *
+ *
+ * Arguments:  @const key_fetchdef *kf@ = pointer to base definition
+ *             @key_packstruct *kps@ = pointer to destination packing def
+ *             @void *p@ = pointer to destination block
+ *
+ * Returns:    Pointer to packing definition.
+ *
+ * Use:                Initializes a packing definition (@key_packdef@ structure).
+ *             If @kps@ is null on entry, an appropriately sized block is
+ *             allocated automatically.  Otherwise it must be large enough.
+ */
+
+extern key_packdef *key_fetchinit(const key_fetchdef */*kf*/,
+                                 key_packstruct */*kp*/, void */*p*/);
+
+/* --- @key_fetch@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key *k@ = key file containing desired key
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Fetches an unpacked key from a packed one.
+ */
+
+extern int key_fetch(key_packdef */*kp*/, key */*k*/);
+
+/* --- @key_fetchbyname@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *             @key_file *kf@ = key file containing desired key
+ *             @const char *tag@ = user's tag describing the key
+ *
+ * Returns:    Error code, or zero.
+ *
+ * Use:                Fetches a named key from a key file and unpacks it
+ *             conveniently.
+ */
+
+extern int key_fetchbyname(key_packdef */*kp*/,
+                          key_file */*kf*/, const char */*tag*/);
+
+/* --- @key_fetchdone@ --- *
+ *
+ * Arguments:  @key_packdef *kp@ = pointer to packing structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a packing structure.  If the structure was allocated by
+ *             @key_fetchinit@ then it is freed.
+ */
+
+extern void key_fetchdone(key_packdef */*kp*/);
+
+/*----- Other functions ---------------------------------------------------*/
+
+/* --- @key_moan@ --- *
+ *
+ * Arguments:  @const char *file@ = name of the file
+ *             @int line@ = line number in file
+ *             @const char *msg@ = error message
+ *             @void *p@ = argument pointer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reports an error message about loading a key file.
+ */
+
+extern void key_moan(const char */*file*/, int /*line*/,
+                    const char */*msg*/, void */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/key/passphrase.c b/key/passphrase.c
new file mode 100644 (file)
index 0000000..6f0780f
--- /dev/null
@@ -0,0 +1,164 @@
+/* -*-c-*-
+ *
+ * Reading of passphrases (Unix-specific)
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#include <mLib/dstr.h>
+
+#include "passphrase.h"
+#include "pixie.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static int fd = -1;
+static unsigned flags = 0;
+
+#define f_fail 1u
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @passphrase_connect@ ---
+ *
+ * Arguments:  @const char *sock@ = socket name to connect to, or null for
+ *             default
+ *
+ * Returns:    Zero if OK, nonzero if it failed
+ *
+ * Use:                Attempts to connect to the passphrase pixie.
+ */
+
+int passphrase_connect(const char *sock)
+{
+  if (fd != -1)
+    close(fd);
+  if ((fd = pixie_open(sock)) < 0) {
+    flags |= f_fail;
+    return (-1);
+  }
+  flags &= ~f_fail;
+  return (0);
+}
+
+static int pconn(void)
+{
+  if (fd != -1)
+    return (0);
+  if (flags & f_fail)
+    return (-1);
+  return (passphrase_connect(0));
+}
+
+/* --- @passphrase_read@ --- *
+ *
+ * Arguments:  @const char *tag@ = pointer to passphrase tag string
+ *             @unsigned mode@ = reading mode
+ *             @char *buf@ = pointer to destination buffer
+ *             @size_t sz@ = size of destination buffer
+ *
+ * Returns:    Zero if successful, nonzero on failure.
+ *
+ * Use:                Reads a passphrase from the user, using some system-specific
+ *             secure mechanism.  The mechanism may keep a cache of
+ *             passphrases, so the user may not necessarily be prompted.
+ */
+
+int passphrase_read(const char *tag, unsigned mode, char *buf, size_t sz)
+{
+  dstr d = DSTR_INIT;
+  int rc = 1;
+
+  /* --- Try talking to the pixie --- */
+
+  if (!pconn()) {
+    rc = pixie_read(fd, tag, mode, buf, sz);
+    if (rc < 0) {
+      close(fd);
+      fd = -1;
+      return (-1);
+    }
+    if (rc == 0)
+      return (0);
+  }
+
+  /* --- Read from the terminal --- */
+
+  dstr_putf(&d, "%s %s: ",
+           mode == PMODE_READ ? "Passphrase" : "New passphrase",
+           tag);
+  if (pixie_getpass(d.buf, buf, sz))
+    goto fail;
+  if (mode == PMODE_VERIFY) {
+    char b[1024];
+    DRESET(&d);
+    dstr_putf(&d, "Verify passphrase %s: ", tag);
+    if (pixie_getpass(d.buf, b, sizeof(b)) || strcmp(b, buf) != 0) {
+      memset(b, 0, sizeof(b));
+      goto fail;
+    }
+  }
+  dstr_destroy(&d);
+
+  /* --- If the pixie is interested, tell it the new passphrase --- */
+
+  if (fd >= 0)
+    pixie_set(fd, tag, buf);
+  return (0);
+
+  /* --- Tidy up after a failure --- */
+
+fail:
+  dstr_destroy(&d);
+  memset(buf, 0, sz);
+  return (-1);
+}
+
+/* --- @passphrase_cancel@ --- *
+ *
+ * Arguments:  @const char *tag@ = pointer to passphrase tag string
+ *
+ * Returns:    ---
+ *
+ * Use:                Attempts to make the passphrase cache forget about a
+ *             particular passphrase.  This may be useful if the passphrase
+ *             turns out to be wrong, or if the user is attempting to change
+ *             the passphrase.
+ */
+
+void passphrase_cancel(const char *tag)
+{
+  if (!pconn())
+    pixie_cancel(fd, tag);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/key/passphrase.h b/key/passphrase.h
new file mode 100644 (file)
index 0000000..876df70
--- /dev/null
@@ -0,0 +1,103 @@
+/* -*-c-*-
+ *
+ * Reading passphrases
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_PASSPHRASE_H
+#define CATACOMB_PASSPHRASE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- Passphrase modes --- *
+ *
+ * @PMODE_VERIFY@ requests that the passphrase be repeated to make sure it's
+ * right.
+ */
+
+enum {
+  PMODE_READ,
+  PMODE_VERIFY
+};
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @passphrase_connect@ ---
+ *
+ * Arguments:  @const char *sock@ = socket name to connect to, or null for
+ *                     default
+ *
+ * Returns:    Zero if OK, nonzero if it failed
+ *
+ * Use:                Attempts to connect to the passphrase pixie.
+ */
+
+extern int passphrase_connect(const char */*sock*/);
+
+/* --- @passphrase_read@ --- *
+ *
+ * Arguments:  @const char *tag@ = pointer to passphrase tag string
+ *             @unsigned mode@ = reading mode
+ *             @char *buf@ = pointer to destination buffer
+ *             @size_t sz@ = size of destination buffer
+ *
+ * Returns:    Zero if successful, nonzero on failure.
+ *
+ * Use:                Reads a passphrase from the user, using some system-specific
+ *             secure mechanism.  The mechanism may keep a cache of
+ *             passphrases, so the user may not necessarily be prompted.
+ */
+
+extern int passphrase_read(const char */*tag*/, unsigned /*mode*/,
+                          char */*buf*/, size_t /*sz*/);
+
+/* --- @passphrase_cancel@ --- *
+ *
+ * Arguments:  @const char *tag@ = pointer to passphrase tag string
+ *
+ * Returns:    ---
+ *
+ * Use:                Attempts to make the passphrase cache forget about a
+ *             particular passphrase.  This may be useful if the passphrase
+ *             turns out to be wrong, or if the user is attempting to change
+ *             the passphrase.
+ */
+
+extern void passphrase_cancel(const char */*tag*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/key/pixie-common.c b/key/pixie-common.c
new file mode 100644 (file)
index 0000000..f24b576
--- /dev/null
@@ -0,0 +1,374 @@
+/* -*-c-*-
+ *
+ * Common code for Pixie client and server (Unix-specific)
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <pwd.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/str.h>
+
+#include "pixie.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @pixie_address@ --- *
+ *
+ * Arguments:  @const char *sock@ = pointer to socket name
+ *             @size_t *psz@ = where to write the address size
+ *
+ * Returns:    Pointer to filled-in Unix-domain socket address.
+ *
+ * Use:                Returns a Unix-domain socket address to use to find the
+ *             passphrase pixie.
+ */
+
+struct sockaddr_un *pixie_address(const char *sock, size_t *psz)
+{
+  dstr d = DSTR_INIT;
+
+  /* --- Get the default socket path if none specified --- */
+
+  if (!sock)
+    sock = getenv("CATACOMB_PIXIE_SOCKET");
+  if (!sock)
+    sock = "%h/.catacomb/pixie";
+
+  /* --- Substitute interesting sequences in the path --- */
+
+  {
+    const char *q, *qq;
+
+    q = sock;
+    for (;;) {
+      qq = strchr(q, '%');
+      if (!qq || !qq[1]) {
+       DPUTS(&d, q);
+       break;
+      }
+      DPUTM(&d, q, qq - q);
+      q = qq + 1;
+      switch (*q) {
+       case 'u':
+         qq = getenv("USER");
+         if (!qq)
+           qq = getenv("LOGNAME");
+         if (!qq) {
+           struct passwd *pw = getpwuid(getuid());
+           if (pw)
+             qq = pw->pw_name;
+           else
+             qq = "<unknown>";
+         }
+         DPUTS(&d, qq);
+         break;
+       case 'h':
+         qq = getenv("HOME");
+         if (!qq) {
+           struct passwd *pw = getpwuid(getuid());
+           if (pw)
+             qq = pw->pw_dir;
+           else
+             qq = "<unknown>";
+         }
+         DPUTS(&d, qq);
+         break;
+       default:
+         DPUTC(&d, '%');
+         DPUTC(&d, *q);
+         break;
+      }
+      q++;
+    }
+    DPUTZ(&d);
+  }
+
+  /* --- Allocate and initialize the socket address --- */
+
+  {
+    struct sockaddr_un *sun;
+    size_t bsz = offsetof(struct sockaddr_un, sun_path);
+    *psz = bsz + d.len + 1;
+    sun = xmalloc(bsz + d.len + 1);
+    memset(sun, 0, bsz);
+    sun->sun_family = AF_UNIX;
+    memcpy(sun->sun_path, d.buf, d.len + 1);
+    dstr_destroy(&d);
+    return (sun);
+  }
+}
+
+/* --- @pixie_fdline@ --- *
+ *
+ * Arguments:  @int fd@ = file descriptor to read from
+ *             @char *buf@ = pointer to buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reads a line from a file descriptor.  The read is done one
+ *             character at a time.  If the entire line won't fit, the end
+ *             is truncated.  The line is null terminated.
+ */
+
+void pixie_fdline(int fd, char *buf, size_t sz)
+{
+  char *p = buf;
+  char *q = p + sz - 1;
+
+  for (;;) {
+    char c;
+    if (read(fd, &c, 1) < 1)
+      break;
+    if (c == '\n')
+      break;
+    if (p < q)
+      *p++ = c;
+  }
+  *p = 0;
+}
+
+/* --- @pixie_getpass@ --- *
+ *
+ * Arguments:  @const char *prompt@ = pointer to prompt string
+ *             @char *buf@ = pointer to buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    Zero if it worked OK, nonzero otherwise.
+ *
+ * Use:                Reads a passphrase from the terminal or some other requested
+ *             source.
+ */
+
+int pixie_getpass(const char *prompt, char *buf, size_t sz)
+{
+  const char *pfd = getenv("CATACOMB_PASSPHRASE_FD");
+  int fd = 0;
+
+  /* --- See whether a terminal is what's wanted --- */
+
+  if (pfd) {
+    fd = atoi(pfd);
+    pixie_fdline(fd, buf, sz);
+  } else {
+    struct termios ta;
+    struct termios ota;
+    char nl = '\n';
+
+    if ((fd = open("/dev/tty", O_RDWR)) < 0)
+      goto fail_0;
+    if (tcgetattr(fd, &ta) < 0)
+      goto fail_1;
+    ota = ta;
+    ta.c_lflag &= ~(ECHO | ISIG);
+    if (tcsetattr(fd, TCSAFLUSH, &ta))
+      goto fail_1;
+    write(fd, prompt, strlen(prompt));
+    pixie_fdline(fd, buf, sz);
+    tcsetattr(fd, TCSAFLUSH, &ota);
+    write(fd, &nl, 1);
+    close(fd);
+  }
+  return (0);
+
+  /* --- Tidy up if things went wrong --- */
+
+fail_1:
+  close(fd);
+fail_0:
+  return (-1);
+}
+
+/* --- @pixie_open@ --- *
+ *
+ * Arguments:  @const char *sock@ = path to pixie socket
+ *
+ * Returns:    Less than zero if it failed, or file descriptor.
+ *
+ * Use:                Opens a connection to a passphrase pixie.
+ */
+
+int pixie_open(const char *sock)
+{
+  struct sockaddr_un *sun;
+  size_t sz;
+  int fd;
+
+  /* --- Open the connection --- */
+
+  if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+    goto fail_0;
+  sun = pixie_address(sock, &sz);
+  if (connect(fd, (struct sockaddr *)sun, sz))
+    goto fail_1;
+  xfree(sun);
+  return (fd);
+
+  /* --- Tidy up if things went wrong --- */
+
+fail_1:
+  xfree(sun);
+  close(fd);
+fail_0:
+  return (-1);
+}
+
+/* --- @pixie_read@ --- *
+ *
+ * Arguments:  @int fd@ = connection to passphrase pixie
+ *             @const char *tag@ = pointer to tag string
+ *             @unsigned mode@ = reading mode
+ *             @char *buf@ = pointer to destination buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    Zero if all went well, @-1@ if the read fails, @+1@ to
+ *             request the passphrase from the user.
+ *
+ * Use:                Reads a passphrase from the pixie.
+ */
+
+int pixie_read(int fd, const char *tag, unsigned mode, char *buf, size_t sz)
+{
+  dstr d = DSTR_INIT;
+  char *p, *q;
+
+  /* --- Send the request --- */
+
+  dstr_putf(&d, "%s %s\n", mode == PMODE_READ ? "PASS" : "VERIFY", tag);
+  write(fd, d.buf, d.len);
+  dstr_destroy(&d);
+
+  /* --- Sort out the result --- */
+
+again:
+  pixie_fdline(fd, buf, sz);
+  p = buf;
+  if ((q = str_getword(&p)) == 0)
+    return (-1);
+  if (strcmp(q, "INFO") == 0)
+    goto again;
+  else if (strcmp(q, "MISSING") == 0)
+    return (+1);
+  else if (strcmp(q, "OK") != 0)
+    return (-1);
+
+  /* --- Return the final answer --- */
+
+  if (p)
+    memmove(buf, p, strlen(p) + 1);
+  else
+    *buf = 0;
+  return (0);
+}
+
+/* --- @pixie_set@ --- *
+ *
+ * Arguments:  @int fd@ = pixie file descriptor
+ *             @const char *tag@ = pointer to tag string
+ *             @const char *phrase@ = pointer to passphrase string
+ *
+ * Returns:    ---
+ *
+ * Use:                Sends a passphrase to the passphrase pixie.
+ */
+
+void pixie_set(int fd, const char *tag, const char *phrase)
+{
+  dstr d = DSTR_INIT;
+  char buf[16];
+  size_t sz = strlen(phrase);
+  char nl = '\n';
+  char *p, *q;
+
+  /* --- Send the request --- *
+   *
+   * I didn't want to copy it out of the caller's buffer.  @writev@ may
+   * produce a copy, too, so I didn't do that either.
+   */
+
+  dstr_putf(&d, "SET %s -- ", tag);
+  write(fd, d.buf, d.len);
+  write(fd, phrase, sz);
+  write(fd, &nl, 1);
+  dstr_destroy(&d);
+
+  /* --- Pick up the pieces --- */
+
+again:
+  pixie_fdline(fd, buf, sizeof(buf));
+  p = buf;
+  if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0)
+    goto again;
+}
+
+/* --- @pixie_cancel@ --- *
+ *
+ * Arguments:  @int fd@ = pixie file descriptor
+ *             @const char *tag@ = pointer to tag string
+ *
+ * Returns:    ---
+ *
+ * Use:                Cancels a passphrase if it turns out to be bogus.
+ */
+
+void pixie_cancel(int fd, const char *tag)
+{
+  dstr d = DSTR_INIT;
+  char buf[16];
+  char *p, *q;
+
+  /* --- Send the request --- */
+
+  dstr_putf(&d, "FLUSH %s\n", tag);
+  write(fd, d.buf, d.len);
+  dstr_destroy(&d);
+
+  /* --- Sort out the result --- */
+
+again:
+  pixie_fdline(fd, buf, sizeof(buf));
+  p = buf;
+  if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0)
+    goto again;
+}
+
+/*----- That's all, folks -------------------------------------------------*/
+
diff --git a/key/pixie.h b/key/pixie.h
new file mode 100644 (file)
index 0000000..bfda993
--- /dev/null
@@ -0,0 +1,216 @@
+/* -*-c-*-
+ *
+ * Passphrase pixie definitions (Unix-specific)
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_PIXIE_H
+#define CATACOMB_PIXIE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef CATACOMB_PASSPHRASE_H
+#  include "passphrase.h"
+#endif
+
+/*----- Protocol definition -----------------------------------------------*
+ *
+ * The protocol is simple and text-based.  The client connects to the
+ * server's socket and sends `request lines', each of which elicits one or
+ * more `response lines' from the server.  Request and response lines contain
+ * whitespace-separated fields, and are terminated by a single linefeed.  The
+ * final field on a line may contain whitespace.  The first field describes
+ * the type of the line.  The type field is not case-sensitive, although
+ * writing them in uppercase is conventional.
+ *
+ * The requests are:
+ *
+ * HELP
+ *     Provide (very) brief help with the pixie protocol.
+ *
+ * LIST
+ *     Return a list of passphrases currently stored, together with expiry
+ *     information.
+ *
+ * PASS tag [expire]
+ *     Request the passphrase named `tag' from the pixie.
+ *
+ * VERIFY tag [expire]
+ *     Request a new passphrase, which therefore requires verification.
+ *
+ * SET tag [expire] -- phrase
+ *     Set the value of passphrase `tag'.  This will usually be a follow-up
+ *     to a MISSING response.
+ *
+ * FLUSH [tag]
+ *     Flush the passphrase named `tag', or all passphrases, from memory.
+ *
+ * QUIT
+ *     Requests that the pixie close down.
+ *
+ * Response lines are as follows:
+ *
+ * OK [phrase]
+ *     Request completed successfully.  If a passphrase was requested, it is
+ *     returned by the pixie.  This is the final response to a request.
+ *
+ * MISSING
+ *     The passphrase requested is not known, and no requester mechanism is
+ *     present.  The client should request the passphrase itself and pass it
+ *     back to the pixie.  This is the final response to a request.
+ *
+ * FAIL error
+ *     Reports an error.  The message given is intended to be
+ *     human-readable.  This is the final response to a request.
+ *
+ * INFO message
+ *     Reports a human-readable informational message.  Further responses
+ *     follow.
+ *
+ * ITEM tag expires
+ *     Reports a passphrase in response to a LIST request.  One ITEM
+ *     response is given for each passphrase currently in memory.  An OK or
+ *     FAIL response follows the last ITEM.
+ *
+ * Expiry times in requests may be given in any format acceptable to
+ * `getdate'.  Expiry times in responses are returned in ISO format
+ * (YYYY-MM-DD HH:MM:SS ZZZ) and are expressed relative to local time.
+ */
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @pixie_open@ --- *
+ *
+ * Arguments:  @const char *sock@ = path to pixie socket
+ *
+ * Returns:    Less than zero if it failed, or file descriptor.
+ *
+ * Use:                Opens a connection to a passphrase pixie.
+ */
+
+extern int pixie_open(const char */*sock*/);
+
+/* --- @pixie_read@ --- *
+ *
+ * Arguments:  @int fd@ = connection to passphrase pixie
+ *             @const char *tag@ = pointer to tag string
+ *             @unsigned mode@ = reading mode
+ *             @char *buf@ = pointer to destination buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    Zero if all went well, @-1@ if the read fails, @+1@ to
+ *             request the passphrase from the user.
+ *
+ * Use:                Reads a passphrase from the pixie.
+ */
+
+extern int pixie_read(int /*fd*/, const char */*tag*/, unsigned /*mode*/,
+                     char */*buf*/, size_t /*sz*/);
+
+/* --- @pixie_set@ --- *
+ *
+ * Arguments:  @int fd@ = pixie file descriptor
+ *             @const char *tag@ = pointer to tag string
+ *             @const char *phrase@ = pointer to passphrase string
+ *
+ * Returns:    ---
+ *
+ * Use:                Sends a passphrase to the passphrase pixie.
+ */
+
+extern void pixie_set(int /*fd*/, const char */*tag*/,
+                     const char */*phrase*/);
+
+/* --- @pixie_cancel@ --- *
+ *
+ * Arguments:  @int fd@ = pixie file descriptor
+ *             @const char *tag@ = pointer to tag string
+ *
+ * Returns:    ---
+ *
+ * Use:                Cancels a passphrase if it turns out to be bogus.
+ */
+
+extern void pixie_cancel(int /*fd*/, const char */*tag*/);
+
+/* --- @pixie_address@ --- *
+ *
+ * Arguments:  @const char *sock@ = pointer to socket name
+ *             @size_t *psz@ = where to write the address size
+ *
+ * Returns:    Pointer to filled-in Unix-domain socket address.
+ *
+ * Use:                Returns a Unix-domain socket address to use to find the
+ *             passphrase pixie.
+ */
+
+extern struct sockaddr_un *pixie_address(const char */*sock*/,
+                                        size_t */*psz*/);
+
+/* --- @pixie_fdline@ --- *
+ *
+ * Arguments:  @int fd@ = file descriptor to read from
+ *             @char *buf@ = pointer to buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reads a line from a file descriptor.  The read is done one
+ *             character at a time.  If the entire line won't fit, the end
+ *             is truncated.  The line is null terminated.
+ */
+
+extern void pixie_fdline(int /*fd*/, char */*buf*/, size_t /*sz*/);
+
+/* --- @pixie_getpass@ --- *
+ *
+ * Arguments:  @const char *prompt@ = pointer to prompt string
+ *             @char *buf@ = pointer to buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    Zero if it worked OK, nonzero otherwise.
+ *
+ * Use:                Reads a passphrase from the terminal or some other requested
+ *             source.
+ */
+
+extern int pixie_getpass(const char */*prompt*/,
+                        char */*buf*/, size_t /*sz*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/keycheck-mp.c b/keycheck-mp.c
deleted file mode 100644 (file)
index 580d608..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*-c-*-
- *
- * $Id: keycheck-mp.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Key consistency checking tools for large integers
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#include "fibrand.h"
-#include "grand.h"
-#include "keycheck.h"
-#include "mp.h"
-#include "mprand.h"
-#include "pfilt.h"
-#include "pgen.h"
-#include "rabin.h"
-#include "rand.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @keycheck_prime@ --- *
- *
- * Arguments:  @keycheck *kc@ = keycheck state
- *             @unsigned sev@ = severity if not prime
- *             @mp *m@ = a number to check for primality
- *             @const char *name@ = name of this number
- *
- * Returns:    Zero if OK, or return status from function.
- *
- * Use:                Checks that a number is prime.
- */
-
-int keycheck_prime(keycheck *kc, unsigned sev, mp *m, const char *name)
-{
-  int rc;
-
-  rc = pfilt_smallfactor(m);
-  if (rc == PGEN_TRY) {
-    rabin rn;
-    grand *r = fibrand_create(0);
-    unsigned n;
-    mp *x = MP_NEW;
-
-    r->ops->misc(r, GRAND_SEEDRAND, &rand_global);
-    n = rabin_iters(mp_bits(m));
-    rabin_create(&rn, m);
-    do {
-      x = mprand_range(x, m, r, 0);
-      rc = rabin_test(&rn, x);
-      n--;
-    } while (n && rc == PGEN_PASS);
-    rabin_destroy(&rn);
-    mp_drop(x);
-    r->ops->destroy(r);
-  }
-  if (rc != PGEN_FAIL)
-    rc = 0;
-  else
-    rc = keycheck_report(kc, sev, "%s not prime", name);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/keycheck-report.c b/keycheck-report.c
deleted file mode 100644 (file)
index c69a6ae..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*-c-*-
- *
- * $Id: keycheck-report.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * A standard reporter function
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-
-#include "keycheck.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @keycheck_stdreport@ --- *
- *
- * Arguments:  @unsigned sev@ = problem severity
- *             @const char *msg@ = message to report
- *             @void *p@ = an uninteresting pointer
- *
- * Returns:    Zero.
- *
- * Use:                Reports a message to stderr.
- */
-
-int keycheck_stdreport(unsigned sev, const char *msg, void *p)
-{
-  static const char *const sevtab[] = {
-    "informational", "warning", "error"
-  };
-  keycheck_reportctx *r = p;
-  if (r && sev < r->sev)
-    return (0);
-  fprintf(r ? r->fp : stderr, "keycheck: %s: %s\n", sevtab[sev], msg);
-  return (0);
-}
-
-/*----- that's all, folks -------------------------------------------------*/
diff --git a/keycheck.c b/keycheck.c
deleted file mode 100644 (file)
index 0025f98..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -*-c-*-
- *
- * $Id: keycheck.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Framework for checking consistency of keys
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-
-#include <mLib/dstr.h>
-
-#include "keycheck.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @keycheck_report@ --- *
- *
- * Arguments:  @keycheck *kc@ = keycheck state
- *             @unsigned sev@ = severity of this report
- *             @const char *msg@ = message to send along
- *             @...@ = things to fill the message in with
- *
- * Returns:    Zero to continue, or nonzero to stop and give up.
- *
- * Use:                Reports a message to the user function.
- */
-
-int keycheck_report(keycheck *kc, unsigned sev, const char *msg, ...)
-{
-  int rc;
-  va_list ap;
-  dstr d = DSTR_INIT;
-
-  kc->sev[sev]++;
-  va_start(ap, msg);
-  dstr_vputf(&d, msg, &ap);
-  va_end(ap);
-  rc = kc->func ? kc->func(sev, d.buf, kc->p) : 0;
-  dstr_destroy(&d);
-  return (rc);
-}
-
-/* --- @keycheck_init@ --- *
- *
- * Arguments:  @keycheck *kc@ = pointer to block to initialize
- *             @int (*func)(unsigned sev, const char *msg, void *p)@ =
- *                     handler function for problems
- *             @void *p@ = pointer to give to handler
- *
- * Returns:    ---
- *
- * Use:                Initializes a key checking context.
- */
-
-void keycheck_init(keycheck *kc,
-                  int (*func)(unsigned /*sev*/,
-                              const char */*msg*/,
-                              void */*p*/),
-                  void *p)
-{
-  unsigned i;
-  kc->func = func;
-  kc->p = p;
-  for (i = 0; i < KCSEV_MAX; i++)
-    kc->sev[i] = 0;
-}
-
-/* --- @keycheck_allclear@ --- *
- *
- * Arguments:  @keycheck *kc@ = pointer to keycheck context
- *             @unsigned sev@ = minimum severity to care about
- *
- * Returns:    Nonzero if no problems of @sev@ or above were noticed.
- */
-
-int keycheck_allclear(keycheck *kc, unsigned sev)
-{
-  while (sev < KCSEV_MAX) {
-    if (kc->sev[sev])
-      return (0);
-    sev++;
-  }
-  return (1);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/keycheck.h b/keycheck.h
deleted file mode 100644 (file)
index b80ceeb..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/* -*-c-*-
- *
- * $Id: keycheck.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Framework for checking consistency of keys
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_KEYCHECK_H
-#define CATACOMB_KEYCHECK_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-enum {
-  KCSEV_ALL,
-  KCSEV_INFO = KCSEV_ALL,
-  KCSEV_WARN,
-  KCSEV_ERR,
-  KCSEV_MAX
-};
-
-typedef struct keycheck {
-  unsigned sev[KCSEV_MAX];
-  int (*func)(unsigned /*sev*/, const char */*msg*/, void */*p*/);
-  void *p;
-} keycheck;
-
-typedef struct keycheck_reportctx {
-  FILE *fp;
-  unsigned sev;
-} keycheck_reportctx;
-
-/*----- Generic functions -------------------------------------------------*/
-
-/* --- @keycheck_report@ --- *
- *
- * Arguments:  @keycheck *kc@ = keycheck state
- *             @unsigned sev@ = severity of this report
- *             @const char *msg@ = message to send along
- *             @...@ = things to fill the message in with
- *
- * Returns:    Zero to continue, or nonzero to stop and give up.
- *
- * Use:                Reports a message to the user function.
- */
-
-extern int keycheck_report(keycheck */*kc*/, unsigned /*sev*/,
-                          const char */*msg*/, ...);
-
-/* --- @keycheck_init@ --- *
- *
- * Arguments:  @keycheck *kc@ = pointer to block to initialize
- *             @int (*func)(unsigned sev, const char *msg, void *p)@ =
- *                     handler function for problems
- *             @void *p@ = pointer to give to handler
- *
- * Returns:    ---
- *
- * Use:                Initializes a key checking context.
- */
-
-extern void keycheck_init(keycheck */*kc*/,
-                         int (*/*func*/)(unsigned /*sev*/,
-                                         const char */*msg*/,
-                                         void */*p*/),
-                         void */*p*/);
-
-/* --- @keycheck_allclear@ --- *
- *
- * Arguments:  @keycheck *kc@ = pointer to keycheck context
- *             @unsigned sev@ = minimum severity to care about
- *
- * Returns:    Nonzero if no problems of @sev@ or above were noticed.
- */
-
-extern int keycheck_allclear(keycheck */*kc*/, unsigned /*sev*/);
-
-/*----- A standard report function ----------------------------------------*/
-
-/* --- @keycheck_stdreport@ --- *
- *
- * Arguments:  @unsigned sev@ = problem severity
- *             @const char *msg@ = message to report
- *             @void *p@ = pointer to a @keycheck_reportctx@ structure
- *
- * Returns:    Zero.
- *
- * Use:                Reports a message to stderr.
- */
-
-extern int keycheck_stdreport(unsigned /*sev*/,
-                             const char */*msg*/, void */*p*/);
-
-/*----- Special support functions for large integers ----------------------*/
-
-/* --- @keycheck_prime@ --- *
- *
- * Arguments:  @keycheck *kc@ = keycheck state
- *             @unsigned sev@ = severity if not prime
- *             @mp *m@ = a number to check for primality
- *             @const char *name@ = name of this number
- *
- * Returns:    Zero if OK, or return status from function.
- *
- * Use:                Checks that a number is prime.
- */
-
-extern int keycheck_prime(keycheck */*kc*/, unsigned /*sev*/,
-                         mp */*m*/, const char */*name*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/keysz.c b/keysz.c
deleted file mode 100644 (file)
index ccc0769..0000000
--- a/keysz.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*-c-*-
- *
- * $Id: keysz.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * General block cipher utilities
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-
-#include "gcipher.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @keysz@ --- *
- *
- * Arguments:  @size_t sz@ = a proposed key size, or zero
- *             @const octet *ksz@ = pointer to key size table
- *
- * Returns:    See below.
- *
- * Use:                Returns a sensible key size.  If @sz@ is nonzero, it is
- *             interpreted as an amount (in bytes) of key material which the
- *             caller has available, and the return value is either the
- *             largest allowable key size less than or equal to the caller's
- *             size, or zero if there is no valid key length small enough.
- *             If @sz@ is zero, the function returns a `recommended' key
- *             size.
- */
-
-size_t keysz(size_t sz, const octet *ksz)
-{
-  if (sz == 0)
-    return (ksz[1]);
-  else switch (ksz[0]) {
-    case KSZ_ANY:
-      return (sz);
-    case KSZ_RANGE:
-      if (ksz[4])
-       sz -= sz % ksz[4];
-      if (sz < ksz[2])
-       return (0);
-      if (ksz[3] && sz > ksz[3])
-       return (ksz[3]);
-      return (sz);
-    case KSZ_SET: {
-      unsigned q = 0;
-      for (ksz++; *ksz; ksz++) {
-       if (sz >= *ksz && q < *ksz)
-         q = *ksz;
-      }
-      return (q);
-    }
-  }
-
-  assert(((void)"bad key size table", 0));
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/keyutil.c b/keyutil.c
deleted file mode 100644 (file)
index cca075f..0000000
--- a/keyutil.c
+++ /dev/null
@@ -1,2308 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Simple key manager program
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include "config.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <mLib/base64.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include <noise.h>
-#include <rand.h>
-
-#include "bintab.h"
-#include "bbs.h"
-#include "dh.h"
-#include "dsa.h"
-#include "dsarand.h"
-#include "ec.h"
-#include "ec-keys.h"
-#include "ectab.h"
-#include "fibrand.h"
-#include "getdate.h"
-#include "gfreduce.h"
-#include "key.h"
-#include "mp.h"
-#include "mpmont.h"
-#include "mprand.h"
-#include "mptext.h"
-#include "pgen.h"
-#include "ptab.h"
-#include "rsa.h"
-
-#include "cc.h"
-#include "sha-mgf.h"
-#include "sha256-mgf.h"
-#include "sha224-mgf.h"
-#include "sha384-mgf.h"
-#include "sha512-mgf.h"
-#include "tiger-mgf.h"
-#include "rmd128-mgf.h"
-#include "rmd160-mgf.h"
-#include "rmd256-mgf.h"
-#include "rmd320-mgf.h"
-#include "md5-mgf.h"
-#include "dsarand.h"
-
-/*----- Handy global state ------------------------------------------------*/
-
-static const char *keyfile = "keyring";
-
-/*----- Useful shared functions -------------------------------------------*/
-
-/* --- @doopen@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *             @unsigned how@ = method to open file with
- *
- * Returns:    ---
- *
- * Use:                Opens a key file and handles errors by panicking
- *             appropriately.
- */
-
-static void doopen(key_file *f, unsigned how)
-{
-  if (key_open(f, keyfile, how, key_moan, 0))
-    die(1, "couldn't open keyring `%s': %s", keyfile, strerror(errno));
-}
-
-/* --- @doclose@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *
- * Returns:    ---
- *
- * Use:                Closes a key file and handles errors by panicking
- *             appropriately.
- */
-
-static void doclose(key_file *f)
-{
-  switch (key_close(f)) {
-    case KWRITE_FAIL:
-      die(EXIT_FAILURE, "couldn't write file `%s': %s",
-         keyfile, strerror(errno));
-    case KWRITE_BROKEN:
-      die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)",
-         keyfile, strerror(errno));
-  }
-}
-
-/* --- @setattr@ --- *
- *
- * Arguments:  @key_file *f@ = pointer to key file block
- *             @key *k@ = pointer to key block
- *             @char *v[]@ = array of assignments (overwritten!)
- *
- * Returns:    ---
- *
- * Use:                Applies the attribute assignments to the key.
- */
-
-static void setattr(key_file *f, key *k, char *v[])
-{
-  while (*v) {
-    int err;
-    char *p = *v;
-    size_t eq = strcspn(p, "=");
-    if (!p[eq]) {
-      moan("invalid assignment: `%s' (ignored)", p);
-      v++;
-      continue;
-    }
-    p[eq] = 0;
-    p += eq + 1;
-    if ((err = key_putattr(f, k, *v, *p ? p : 0)) != 0)
-      die(EXIT_FAILURE, "couldn't set attributes: %s", key_strerror(err));
-    v++;
-  }
-}
-
-/*----- Seeding -----------------------------------------------------------*/
-
-const struct seedalg { const char *p; grand *(*gen)(const void *, size_t); }
-seedtab[] = {
-  { "dsarand", dsarand_create },
-  { "rmd128-mgf", rmd128_mgfrand },
-  { "rmd160-mgf", rmd160_mgfrand },
-  { "rmd256-mgf", rmd256_mgfrand },
-  { "rmd320-mgf", rmd320_mgfrand },
-  { "sha-mgf", sha_mgfrand },
-  { "sha224-mgf", sha224_mgfrand },
-  { "sha256-mgf", sha256_mgfrand },
-  { "sha384-mgf", sha384_mgfrand },
-  { "sha512-mgf", sha512_mgfrand },
-  { "tiger-mgf", tiger_mgfrand },
-  { 0, 0 }
-};
-
-#define SEEDALG_DEFAULT (seedtab + 2)
-
-/*----- Key generation ----------------------------------------------------*/
-
-/* --- Key generation parameters --- */
-
-typedef struct keyopts {
-  key_file *kf;                                /* Pointer to key file */
-  key *k;                              /* Pointer to the actual key */
-  dstr tag;                            /* Full tag name for the key */
-  unsigned f;                          /* Flags for the new key */
-  unsigned bits, qbits;                        /* Bit length for the new key */
-  const char *curve;                   /* Elliptic curve name/info */
-  grand *r;                            /* Random number source */
-  key *p;                              /* Parameters key-data */
-} keyopts;
-
-#define f_bogus 1u                     /* Error in parsing */
-#define f_lock 2u                      /* Passphrase-lock private key */
-#define f_quiet 4u                     /* Don't show a progress indicator */
-#define f_limlee 8u                    /* Generate Lim-Lee primes */
-#define f_subgroup 16u                 /* Generate a subgroup */
-#define f_retag 32u                    /* Remove any existing tag */
-#define f_kcdsa 64u                    /* Generate KCDSA primes */
-
-/* --- @dolock@ --- *
- *
- * Arguments:  @keyopts *k@ = key generation options
- *             @key_data **kd@ = pointer to key data to lock
- *             @const char *t@ = tag suffix or null
- *
- * Returns:    ---
- *
- * Use:                Does passphrase locking on new keys.
- */
-
-static void dolock(keyopts *k, key_data **kd, const char *t)
-{
-  if (!(k->f & f_lock))
-    return;
-  if (t)
-    dstr_putf(&k->tag, ".%s", t);
-  if (key_plock(kd, 0, k->tag.buf))
-    die(EXIT_FAILURE, "couldn't lock key");
-}
-
-/* --- @copyparam@ --- *
- *
- * Arguments:  @keyopts *k@ = pointer to key options
- *             @const char **pp@ = checklist of parameters
- *
- * Returns:    Nonzero if parameters copied; zero if you have to generate
- *             them.
- *
- * Use:                Copies parameters from a source key to the current one.
- */
-
-static int copyparam(keyopts *k, const char **pp)
-{
-  key_filter kf;
-  key_attriter i;
-  key_data *kd;
-  const char *n, *v;
-
-  kf.f = KCAT_SHARE;
-  kf.m = KF_CATMASK;
-
-  /* --- Quick check if no parameters supplied --- */
-
-  if (!k->p)
-    return (0);
-
-  /* --- Run through the checklist --- */
-
-  while (*pp) {
-    key_data *kd = key_structfind(k->p->k, *pp);
-    if (!kd)
-      die(EXIT_FAILURE, "bad parameter key: parameter `%s' not found", *pp);
-    if (!KEY_MATCH(kd, &kf))
-      die(EXIT_FAILURE, "bad parameter key: subkey `%s' is not shared", *pp);
-    pp++;
-  }
-
-  /* --- Copy over the parameters --- */
-
-  kd = key_copydata(k->p->k, &kf);
-  assert(kd);
-  key_setkeydata(k->kf, k->k, kd);
-  key_drop(kd);
-
-  /* --- Copy over attributes --- */
-
-  for (key_mkattriter(&i, k->p); key_nextattr(&i, &n, &v); )
-    key_putattr(k->kf, k->k, n, v);
-
-  /* --- Done --- */
-
-  return (1);
-}
-
-/* --- @getmp@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key data block
- *             @const char *tag@ = tag string to use
- *
- * Returns:    Pointer to multiprecision integer key item.
- *
- * Use:                Fetches an MP key component.
- */
-
-static mp *getmp(key_data *k, const char *tag)
-{
-  k = key_structfind(k, tag);
-  if (!k)
-    die(EXIT_FAILURE, "unexpected failure looking up subkey `%s'", tag);
-  if ((k->e & KF_ENCMASK) != KENC_MP)
-    die(EXIT_FAILURE, "subkey `%s' has an incompatible type");
-  return (k->u.m);
-}
-
-/* --- @keyrand@ --- *
- *
- * Arguments:  @key_file *kf@ = pointer to key file
- *             @const char *id@ = pointer to key id (or null)
- *
- * Returns:    ---
- *
- * Use:                Keys the random number generator.
- */
-
-static void keyrand(key_file *kf, const char *id)
-{
-  key *k;
-
-  /* --- Find the key --- */
-
-  if (id) {
-    if ((k = key_bytag(kf, id)) == 0)
-      die(EXIT_FAILURE, "key `%s' not found", id);
-  } else
-    k = key_bytype(kf, "catacomb-rand");
-
-  if (k) {
-    key_data *kd = k->k, *kkd;
-    key_incref(kd);
-
-  again:
-    switch (kd->e & KF_ENCMASK) {
-      case KENC_BINARY:
-       break;
-      case KENC_ENCRYPT: {
-       dstr d = DSTR_INIT;
-       key_fulltag(k, &d);
-       if (key_punlock(&kkd, kd, d.buf))
-         die(EXIT_FAILURE, "error unlocking key `%s'", d.buf);
-       dstr_destroy(&d);
-       key_drop(kd);
-       kd = kkd;
-      } goto again;
-      default: {
-       dstr d = DSTR_INIT;
-       key_fulltag(k, &d);
-       die(EXIT_FAILURE, "bad encoding type for key `%s'", d.buf);
-      } break;
-    }
-
-    /* --- Key the generator --- */
-
-    rand_key(RAND_GLOBAL, kd->u.k.k, kd->u.k.sz);
-    key_drop(kd);
-  }
-}
-
-/* --- Key generation algorithms --- */
-
-static void alg_binary(keyopts *k)
-{
-  unsigned sz;
-  unsigned m;
-  key_data *kd;
-  octet *p;
-
-  if (!k->bits)
-    k->bits = 128;
-  if (k->p)
-    die(EXIT_FAILURE, "no shared parameters for binary keys");
-
-  sz = (k->bits + 7) >> 3;
-  p = sub_alloc(sz);
-  m = (1 << (((k->bits - 1) & 7) + 1)) - 1;
-  k->r->ops->fill(k->r, p, sz);
-  *p &= m;
-  kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz);
-  memset(p, 0, sz);
-  dolock(k, &kd, 0);
-  key_setkeydata(k->kf, k->k, kd);
-  key_drop(kd);
-  sub_free(p, sz);
-}
-
-static void alg_des(keyopts *k)
-{
-  unsigned sz;
-  octet *p;
-  key_data *kd;
-  int i;
-
-  if (!k->bits)
-    k->bits = 168;
-  if (k->p)
-    die(EXIT_FAILURE, "no shared parameters for DES keys");
-  if (k->bits % 56 || k->bits > 168)
-    die(EXIT_FAILURE, "DES keys must be 56, 112 or 168 bits long");
-
-  sz = k->bits / 7;
-  p = sub_alloc(sz);
-  k->r->ops->fill(k->r, p, sz);
-  for (i = 0; i < sz; i++) {
-    octet x = p[i] | 0x01;
-    x = x ^ (x >> 4);
-    x = x ^ (x >> 2);
-    x = x ^ (x >> 1);
-    p[i] = (p[i] & 0xfe) | (x & 0x01);
-  }
-  kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz);
-  memset(p, 0, sz);
-  dolock(k, &kd, 0);
-  key_setkeydata(k->kf, k->k, kd);
-  key_drop(kd);
-  sub_free(p, sz);
-}
-
-static void alg_rsa(keyopts *k)
-{
-  rsa_priv rp;
-  key_data *kd, *kkd;
-
-  /* --- Sanity checking --- */
-
-  if (k->p)
-    die(EXIT_FAILURE, "no shared parameters for RSA keys");
-  if (!k->bits)
-    k->bits = 1024;
-
-  /* --- Generate the RSA parameters --- */
-
-  if (rsa_gen(&rp, k->bits, k->r, 0,
-             (k->f & f_quiet) ? 0 : pgen_ev, 0))
-    die(EXIT_FAILURE, "RSA key generation failed");
-
-  /* --- Run a test encryption --- */
-
-  {
-    grand *g = fibrand_create(k->r->ops->word(k->r));
-    rsa_pub rpp;
-    mp *m = mprand_range(MP_NEW, rp.n, g, 0);
-    mp *c;
-
-    rpp.n = rp.n;
-    rpp.e = rp.e;
-    c = rsa_qpubop(&rpp, MP_NEW, m);
-    c = rsa_qprivop(&rp, c, c, g);
-
-    if (!MP_EQ(c, m))
-      die(EXIT_FAILURE, "test encryption failed");
-    mp_drop(c);
-    mp_drop(m);
-    g->ops->destroy(g);
-  }
-
-  /* --- Allrighty then --- */
-
-  kd = key_newstruct();
-  key_structsteal(kd, "n", key_newmp(KCAT_PUB, rp.n));
-  key_structsteal(kd, "e", key_newmp(KCAT_PUB, rp.e));
-
-  kkd = key_newstruct();
-  key_structsteal(kkd, "d", key_newmp(KCAT_PRIV | KF_BURN, rp.d));
-  key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, rp.p));
-  key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, rp.q));
-  key_structsteal(kkd, "q-inv", key_newmp(KCAT_PRIV | KF_BURN, rp.q_inv));
-  key_structsteal(kkd, "d-mod-p", key_newmp(KCAT_PRIV | KF_BURN, rp.dp));
-  key_structsteal(kkd, "d-mod-q", key_newmp(KCAT_PRIV | KF_BURN, rp.dq));
-  dolock(k, &kkd, "private");
-  key_structsteal(kd, "private", kkd);
-  key_setkeydata(k->kf, k->k, kd);
-  key_drop(kd);
-  rsa_privfree(&rp);
-}
-
-static void alg_dsaparam(keyopts *k)
-{
-  static const char *pl[] = { "q", "p", "g", 0 };
-  if (!copyparam(k, pl)) {
-    dsa_param dp;
-    octet *p;
-    size_t sz;
-    dstr d = DSTR_INIT;
-    base64_ctx c;
-    key_data *kd;
-    dsa_seed ds;
-
-    /* --- Choose appropriate bit lengths if necessary --- */
-
-    if (!k->qbits)
-      k->qbits = 160;
-    if (!k->bits)
-      k->bits = 1024;
-
-    /* --- Allocate a seed block --- */
-
-    sz = (k->qbits + 7) >> 3;
-    p = sub_alloc(sz);
-    k->r->ops->fill(k->r, p, sz);
-
-    /* --- Allocate the parameters --- */
-
-    if (dsa_gen(&dp, k->qbits, k->bits, 0, p, sz, &ds,
-               (k->f & f_quiet) ? 0 : pgen_ev, 0))
-      die(EXIT_FAILURE, "DSA parameter generation failed");
-
-    /* --- Store the parameters --- */
-
-    kd = key_newstruct();
-    key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q));
-    key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p));
-    key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g));
-    mp_drop(dp.q);
-    mp_drop(dp.p);
-    mp_drop(dp.g);
-    key_setkeydata(k->kf, k->k, kd);
-    key_drop(kd);
-
-    /* --- Store the seed for future verification --- */
-
-    base64_init(&c);
-    c.maxline = 0;
-    c.indent = "";
-    base64_encode(&c, ds.p, ds.sz, &d);
-    base64_encode(&c, 0, 0, &d);
-    DPUTZ(&d);
-    key_putattr(k->kf, k->k, "seed", d.buf);
-    DRESET(&d);
-    dstr_putf(&d, "%u", ds.count);
-    key_putattr(k->kf, k->k, "count", d.buf);
-    xfree(ds.p);
-    sub_free(p, sz);
-    dstr_destroy(&d);
-  }
-}
-
-static void alg_dsa(keyopts *k)
-{
-  mp *q, *p, *g;
-  mp *x, *y;
-  mpmont mm;
-  key_data *kd, *kkd;
-
-  /* --- Get the shared parameters --- */
-
-  alg_dsaparam(k);
-  key_split(&k->k->k); kd = k->k->k;
-  q = getmp(kd, "q");
-  p = getmp(kd, "p");
-  g = getmp(kd, "g");
-
-  /* --- Choose a private key --- */
-
-  x = mprand_range(MP_NEWSEC, q, k->r, 0);
-  mpmont_create(&mm, p);
-  y = mpmont_exp(&mm, MP_NEW, g, x);
-
-  /* --- Store everything away --- */
-
-  key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
-
-  kkd = key_newstruct();
-  key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
-  dolock(k, &kkd, "private");
-  key_structsteal(kd, "private", kkd);
-
-  mp_drop(x); mp_drop(y);
-}
-
-static void alg_dhparam(keyopts *k)
-{
-  static const char *pl[] = { "p", "q", "g", 0 };
-  key_data *kd;
-  if (!copyparam(k, pl)) {
-    dh_param dp;
-    int rc;
-
-    if (k->curve) {
-      qd_parse qd;
-      group *g;
-      const char *e;
-
-      if (strcmp(k->curve, "list") == 0) {
-       unsigned i, w;
-       LIST("Built-in prime fields", stdout, ptab[i].name, ptab[i].name);
-       exit(0);
-      }
-      qd.p = k->curve;
-      if (dh_parse(&qd, &dp))
-       die(EXIT_FAILURE, "error in field spec: %s", qd.e);
-      if (!qd_eofp(&qd))
-       die(EXIT_FAILURE, "junk at end of field spec");
-      if ((g = group_prime(&dp)) == 0)
-       die(EXIT_FAILURE, "invalid prime field");
-      if (!(k->f & f_quiet) && (e = G_CHECK(g, &rand_global)) != 0)
-       moan("WARNING!  group check failed: %s", e);
-      G_DESTROYGROUP(g);
-      goto done;
-    }
-
-    if (!k->bits)
-      k->bits = 1024;
-
-    /* --- Choose a large safe prime number --- */
-
-    if (k->f & f_limlee) {
-      mp **f;
-      size_t nf;
-      if (!k->qbits)
-       k->qbits = 256;
-      rc = dh_limlee(&dp, k->qbits, k->bits,
-                    (k->f & f_subgroup) ? DH_SUBGROUP : 0,
-                    0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0,
-                    (k->f & f_quiet) ? 0 : pgen_evspin, 0, &nf, &f);
-      if (!rc) {
-       dstr d = DSTR_INIT;
-       size_t i;
-       for (i = 0; i < nf; i++) {
-         if (i)
-           dstr_puts(&d, ", ");
-         mp_writedstr(f[i], &d, 10);
-         mp_drop(f[i]);
-       }
-       key_putattr(k->kf, k->k, "factors", d.buf);
-       dstr_destroy(&d);
-      }
-    } else if (k->f & f_kcdsa) {
-      if (!k->qbits)
-       k->qbits = 256;
-      rc = dh_kcdsagen(&dp, k->qbits, k->bits, 0,
-                      0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0);
-      if (!rc) {
-       dstr d = DSTR_INIT;
-       mp *v = MP_NEW;
-
-       mp_writedstr(dp.q, &d, 10);
-       mp_div(&v, 0, dp.p, dp.q);
-       v = mp_lsr(v, v, 1);
-       dstr_puts(&d, ", ");
-       mp_writedstr(v, &d, 10);
-       mp_drop(v);
-       key_putattr(k->kf, k->k, "factors", d.buf);
-       dstr_destroy(&d);
-      }
-    } else
-      rc = dh_gen(&dp, k->qbits, k->bits, 0, k->r,
-                 (k->f & f_quiet) ? 0 : pgen_ev, 0);
-
-    if (rc)
-      die(EXIT_FAILURE, "Diffie-Hellman parameter generation failed");
-
-  done:
-    kd = key_newstruct();
-    key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p));
-    key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q));
-    key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g));
-    mp_drop(dp.q);
-    mp_drop(dp.p);
-    mp_drop(dp.g);
-    key_setkeydata(k->kf, k->k, kd);
-    key_drop(kd);
-  }
-}
-
-static void alg_dh(keyopts *k)
-{
-  mp *x, *y;
-  mp *p, *q, *g;
-  mpmont mm;
-  key_data *kd, *kkd;
-
-  /* --- Get the shared parameters --- */
-
-  alg_dhparam(k);
-  key_split(&k->k->k); kd = k->k->k;
-  p = getmp(kd, "p");
-  q = getmp(kd, "q");
-  g = getmp(kd, "g");
-
-  /* --- Choose a suitable private key --- *
-   *
-   * Since %$g$% has order %$q$%, choose %$x < q$%.
-   */
-
-  x = mprand_range(MP_NEWSEC, q, k->r, 0);
-
-  /* --- Compute the public key %$y = g^x \bmod p$% --- */
-
-  mpmont_create(&mm, p);
-  y = mpmont_exp(&mm, MP_NEW, g, x);
-  mpmont_destroy(&mm);
-
-  /* --- Store everything away --- */
-
-  key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
-
-  kkd = key_newstruct();
-  key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
-  dolock(k, &kkd, "private");
-  key_structsteal(kd, "private", kkd);
-
-  mp_drop(x); mp_drop(y);
-}
-
-static void alg_bbs(keyopts *k)
-{
-  bbs_priv bp;
-  key_data *kd, *kkd;
-
-  /* --- Sanity checking --- */
-
-  if (k->p)
-    die(EXIT_FAILURE, "no shared parameters for Blum-Blum-Shub keys");
-  if (!k->bits)
-    k->bits = 1024;
-
-  /* --- Generate the BBS parameters --- */
-
-  if (bbs_gen(&bp, k->bits, k->r, 0,
-             (k->f & f_quiet) ? 0 : pgen_ev, 0))
-    die(EXIT_FAILURE, "Blum-Blum-Shub key generation failed");
-
-  /* --- Allrighty then --- */
-
-  kd = key_newstruct();
-  key_structsteal(kd, "n", key_newmp(KCAT_PUB, bp.n));
-
-  kkd = key_newstruct();
-  key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, bp.p));
-  key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, bp.q));
-  dolock(k, &kkd, "private");
-  key_structsteal(kd, "private", kkd);
-  key_setkeydata(k->kf, k->k, kd);
-  key_drop(kd);
-
-  bbs_privfree(&bp);
-}
-
-static void alg_binparam(keyopts *k)
-{
-  static const char *pl[] = { "p", "q", "g", 0 };
-  if (!copyparam(k, pl)) {
-    gbin_param gb;
-    qd_parse qd;
-    group *g;
-    const char *e;
-    key_data *kd;
-
-    /* --- Decide on a field --- */
-
-    if (!k->bits) k->bits = 128;
-    if (k->curve && strcmp(k->curve, "list") == 0) {
-      unsigned i, w;
-      LIST("Built-in binary fields", stdout,
-          bintab[i].name, bintab[i].name);
-      exit(0);
-    }
-    if (!k->curve) {
-      if (k->bits <= 40) k->curve = "p1363-40";
-      else if (k->bits <= 56) k->curve = "p1363-56";
-      else if (k->bits <= 64) k->curve = "p1363-64";
-      else if (k->bits <= 80) k->curve = "p1363-80";
-      else if (k->bits <= 112) k->curve = "p1363-112";
-      else if (k->bits <= 128) k->curve = "p1363-128";
-      else {
-       die(EXIT_FAILURE,
-           "no built-in binary fields provide %u-bit security",
-           k->bits);
-      }
-    }
-
-    /* --- Check it --- */
-
-    qd.e = 0;
-    qd.p = k->curve;
-    if (dhbin_parse(&qd, &gb))
-      die(EXIT_FAILURE, "error in field spec: %s", qd.e);
-    if (!qd_eofp(&qd))
-      die(EXIT_FAILURE, "junk at end of field spec");
-    if ((g = group_binary(&gb)) == 0)
-      die(EXIT_FAILURE, "invalid binary field");
-    if (!(k->f & f_quiet) && (e = G_CHECK(g, &rand_global)) != 0)
-      moan("WARNING!  group check failed: %s", e);
-    G_DESTROYGROUP(g);
-
-    /* --- Write out the answer --- */
-
-    kd = key_newstruct();
-    key_structsteal(kd, "p", key_newmp(KCAT_SHARE, gb.p));
-    key_structsteal(kd, "q", key_newmp(KCAT_SHARE, gb.q));
-    key_structsteal(kd, "g", key_newmp(KCAT_SHARE, gb.g));
-    mp_drop(gb.q);
-    mp_drop(gb.p);
-    mp_drop(gb.g);
-    key_setkeydata(k->kf, k->k, kd);
-    key_drop(kd);
-  }
-}
-
-static void alg_bin(keyopts *k)
-{
-  mp *x, *y;
-  mp *p, *q, *g;
-  gfreduce r;
-  key_data *kd, *kkd;
-
-  /* --- Get the shared parameters --- */
-
-  alg_binparam(k);
-  key_split(&k->k->k); kd = k->k->k;
-  p = getmp(kd, "p");
-  q = getmp(kd, "q");
-  g = getmp(kd, "g");
-
-  /* --- Choose a suitable private key --- *
-   *
-   * Since %$g$% has order %$q$%, choose %$x < q$%.
-   */
-
-  x = mprand_range(MP_NEWSEC, q, k->r, 0);
-
-  /* --- Compute the public key %$y = g^x \bmod p$% --- */
-
-  gfreduce_create(&r, p);
-  y = gfreduce_exp(&r, MP_NEW, g, x);
-  gfreduce_destroy(&r);
-
-  /* --- Store everything away --- */
-
-  key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
-
-  kkd = key_newstruct();
-  key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
-  dolock(k, &kkd, "private");
-  key_structsteal(kd, "private", kkd);
-
-  mp_drop(x); mp_drop(y);
-}
-
-static void alg_ecparam(keyopts *k)
-{
-  static const char *pl[] = { "curve", 0 };
-  if (!copyparam(k, pl)) {
-    ec_info ei;
-    const char *e;
-    key_data *kd;
-
-    /* --- Decide on a curve --- */
-
-    if (!k->bits) k->bits = 256;
-    if (k->curve && strcmp(k->curve, "list") == 0) {
-      unsigned i, w;
-      LIST("Built-in elliptic curves", stdout,
-          ectab[i].name, ectab[i].name);
-      exit(0);
-    }
-    if (!k->curve) {
-      if (k->bits <= 56) k->curve = "secp112r1";
-      else if (k->bits <= 64) k->curve = "secp128r1";
-      else if (k->bits <= 80) k->curve = "secp160r1";
-      else if (k->bits <= 96) k->curve = "secp192r1";
-      else if (k->bits <= 112) k->curve = "secp224r1";
-      else if (k->bits <= 128) k->curve = "secp256r1";
-      else if (k->bits <= 192) k->curve = "secp384r1";
-      else if (k->bits <= 256) k->curve = "secp521r1";
-      else
-       die(EXIT_FAILURE, "no built-in curves provide %u-bit security",
-           k->bits);
-    }
-
-    /* --- Check it --- */
-
-    if ((e = ec_getinfo(&ei, k->curve)) != 0)
-      die(EXIT_FAILURE, "error in curve spec: %s", e);
-    if (!(k->f & f_quiet) && (e = ec_checkinfo(&ei, k->r)) != 0)
-      moan("WARNING!  curve check failed: %s", e);
-    ec_freeinfo(&ei);
-
-    /* --- Write out the answer --- */
-
-    kd = key_newstruct();
-    key_structsteal(kd, "curve", key_newstring(KCAT_SHARE, k->curve));
-    key_setkeydata(k->kf, k->k, kd);
-    key_drop(kd);
-  }
-}
-
-static void alg_ec(keyopts *k)
-{
-  key_data *kd;
-  key_data *kkd;
-  mp *x = MP_NEW;
-  ec p = EC_INIT;
-  const char *e;
-  ec_info ei;
-
-  /* --- Get the curve --- */
-
-  alg_ecparam(k);
-  key_split(&k->k->k); kd = k->k->k;
-  if ((kkd = key_structfind(kd, "curve")) == 0)
-    die(EXIT_FAILURE, "unexpected failure looking up subkey `curve')");
-  if ((kkd->e & KF_ENCMASK) != KENC_STRING)
-    die(EXIT_FAILURE, "subkey `curve' is not a string");
-  if ((e = ec_getinfo(&ei, kkd->u.p)) != 0)
-    die(EXIT_FAILURE, "error in curve spec: %s", e);
-
-  /* --- Invent a private exponent and compute the public key --- */
-
-  x = mprand_range(MP_NEWSEC, ei.r, k->r, 0);
-  ec_mul(ei.c, &p, &ei.g, x);
-
-  /* --- Store everything away --- */
-
-  key_structsteal(kd, "p", key_newec(KCAT_PUB, &p));
-
-  kkd = key_newstruct();
-  key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
-  dolock(k, &kkd, "private");
-  key_structsteal(kd, "private", kkd);
-
-  /* --- Done --- */
-
-  ec_freeinfo(&ei);
-  mp_drop(x);
-}
-
-/* --- The algorithm tables --- */
-
-typedef struct keyalg {
-  const char *name;
-  void (*proc)(keyopts *o);
-  const char *help;
-} keyalg;
-
-static keyalg algtab[] = {
-  { "binary",          alg_binary,     "Plain binary data" },
-  { "des",             alg_des,        "Binary with DES-style parity" },
-  { "rsa",             alg_rsa,        "RSA public-key encryption" },
-  { "bbs",             alg_bbs,        "Blum-Blum-Shub generator" },
-  { "dsa",             alg_dsa,        "DSA digital signatures" },
-  { "dsa-param",       alg_dsaparam,   "DSA shared parameters" },
-  { "dh",              alg_dh,         "Diffie-Hellman key exchange" },
-  { "dh-param",                alg_dhparam,    "Diffie-Hellman parameters" },
-  { "bindh",           alg_bin,        "DH over a binary field" },
-  { "bindh-param",     alg_binparam,   "Binary-field DH parameters" },
-  { "ec-param",                alg_ecparam,    "Elliptic curve parameters" },
-  { "ec",              alg_ec,         "Elliptic curve crypto" },
-  { 0,                 0 }
-};
-
-/* --- @cmd_add@ --- */
-
-static int cmd_add(int argc, char *argv[])
-{
-  key_file f;
-  time_t exp = KEXP_EXPIRE;
-  uint32 kid = rand_global.ops->word(&rand_global);
-  const char *tag = 0, *ptag = 0;
-  const char *c = 0;
-  keyalg *alg = algtab;
-  const char *rtag = 0;
-  const struct seedalg *sa = SEEDALG_DEFAULT;
-  keyopts k = { 0, 0, DSTR_INIT, 0, 0, 0, 0, 0 };
-  const char *seed = 0;
-  k.r = &rand_global;
-
-  /* --- Parse options for the subcommand --- */
-
-  for (;;) {
-    static struct option opt[] = {
-      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
-      { "bits",                OPTF_ARGREQ,    0,      'b' },
-      { "qbits",       OPTF_ARGREQ,    0,      'B' },
-      { "parameters",  OPTF_ARGREQ,    0,      'p' },
-      { "expire",      OPTF_ARGREQ,    0,      'e' },
-      { "comment",     OPTF_ARGREQ,    0,      'c' },
-      { "tag",         OPTF_ARGREQ,    0,      't' },
-      { "rand-id",     OPTF_ARGREQ,    0,      'R' },
-      { "key-id",      OPTF_ARGREQ,    0,      'I' },
-      { "curve",       OPTF_ARGREQ,    0,      'C' },
-      { "seedalg",     OPTF_ARGREQ,    0,      'A' },
-      { "seed",                OPTF_ARGREQ,    0,      's' },
-      { "newseed",     OPTF_ARGREQ,    0,      'n' },
-      { "lock",                0,              0,      'l' },
-      { "quiet",       0,              0,      'q' },
-      { "lim-lee",     0,              0,      'L' },
-      { "subgroup",    0,              0,      'S' },
-      { "kcdsa",       0,              0,      'K' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:I:C:A:s:n:lqrLKS",
-                  opt, 0, 0, 0);
-    if (i < 0)
-      break;
-
-    /* --- Handle the various options --- */
-
-    switch (i) {
-
-      /* --- Read an algorithm name --- */
-
-      case 'a': {
-       keyalg *a;
-       size_t sz = strlen(optarg);
-
-       if (strcmp(optarg, "list") == 0) {
-         for (a = algtab; a->name; a++)
-           printf("%-10s %s\n", a->name, a->help);
-         return (0);
-       }
-
-       alg = 0;
-       for (a = algtab; a->name; a++) {
-         if (strncmp(optarg, a->name, sz) == 0) {
-           if (a->name[sz] == 0) {
-             alg = a;
-             break;
-           } else if (alg)
-             die(EXIT_FAILURE, "ambiguous algorithm name `%s'", optarg);
-           else
-             alg = a;
-         }
-       }
-       if (!alg)
-         die(EXIT_FAILURE, "unknown algorithm name `%s'", optarg);
-      } break;
-
-      /* --- Bits must be nonzero and a multiple of 8 --- */
-
-      case 'b': {
-       char *p;
-       k.bits = strtoul(optarg, &p, 0);
-       if (k.bits == 0 || *p != 0)
-         die(EXIT_FAILURE, "bad bitlength `%s'", optarg);
-      } break;
-
-      case 'B': {
-       char *p;
-       k.qbits = strtoul(optarg, &p, 0);
-       if (k.qbits == 0 || *p != 0)
-         die(EXIT_FAILURE, "bad bitlength `%s'", optarg);
-      } break;
-
-      /* --- Parameter selection --- */
-
-      case 'p':
-       ptag = optarg;
-       break;
-
-      /* --- Expiry dates get passed to @get_date@ for parsing --- */
-
-      case 'e':
-       if (strcmp(optarg, "forever") == 0)
-         exp = KEXP_FOREVER;
-       else {
-         exp = get_date(optarg, 0);
-         if (exp == -1)
-           die(EXIT_FAILURE, "bad expiry date `%s'", optarg);
-       }
-       break;
-
-      /* --- Store comments without interpretation --- */
-
-      case 'c':
-       if (key_chkcomment(optarg))
-         die(EXIT_FAILURE, "bad comment string `%s'", optarg);
-       c = optarg;
-       break;
-
-      /* --- Elliptic curve parameters --- */
-
-      case 'C':
-       k.curve = optarg;
-       break;
-
-      /* --- Store tags --- */
-
-      case 't':
-       if (key_chkident(optarg))
-         die(EXIT_FAILURE, "bad tag string `%s'", optarg);
-       tag = optarg;
-       break;
-      case 'r':
-       k.f |= f_retag;
-       break;
-
-      /* --- Seeding --- */
-
-      case 'A': {
-       const struct seedalg *ss;
-       if (strcmp(optarg, "list") == 0) {
-         printf("Seed algorithms:\n");
-         for (ss = seedtab; ss->p; ss++)
-           printf("  %s\n", ss->p);
-         exit(0);
-       }
-       if (seed) die(EXIT_FAILURE, "seed already set -- put -A first");
-       sa = 0;
-       for (ss = seedtab; ss->p; ss++) {
-         if (strcmp(optarg, ss->p) == 0)
-           sa = ss;
-       }
-       if (!sa)
-         die(EXIT_FAILURE, "seed algorithm `%s' not known", optarg);
-      } break;
-
-      case 's': {
-       base64_ctx b;
-       dstr d = DSTR_INIT;
-       if (seed) die(EXIT_FAILURE, "seed already set");
-       base64_init(&b);
-       base64_decode(&b, optarg, strlen(optarg), &d);
-       base64_decode(&b, 0, 0, &d);
-       k.r = sa->gen(d.buf, d.len);
-       seed = optarg;
-       dstr_destroy(&d);
-      } break;
-
-      case 'n': {
-       base64_ctx b;
-       dstr d = DSTR_INIT;
-       char *p;
-       unsigned n = strtoul(optarg, &p, 0);
-       if (n == 0 || *p != 0 || n % 8 != 0)
-         die(EXIT_FAILURE, "bad seed length `%s'", optarg);
-       if (seed) die(EXIT_FAILURE, "seed already set");
-       n /= 8;
-       p = xmalloc(n);
-       rand_get(RAND_GLOBAL, p, n);
-       base64_init(&b);
-       base64_encode(&b, p, n, &d);
-       base64_encode(&b, 0, 0, &d);
-       seed = d.buf;
-       k.r = sa->gen(p, n);
-      } break;
-
-      /* --- Key id --- */
-
-      case 'I': {
-       char *p;
-       unsigned long id;
-
-       errno = 0;
-       id = strtoul(optarg, &p, 16);
-       if (errno || *p || id > MASK32)
-         die(EXIT_FAILURE, "bad key-id `%s'", optarg);
-       kid = id;
-      } break;
-
-      /* --- Other flags --- */
-
-      case 'R':
-       rtag = optarg;
-       break;
-      case 'l':
-       k.f |= f_lock;
-       break;
-      case 'q':
-       k.f |= f_quiet;
-       break;
-      case 'L':
-       k.f |= f_limlee;
-       break;
-      case 'K':
-       k.f |= f_kcdsa;
-       break;
-      case 'S':
-       k.f |= f_subgroup;
-       break;
-
-      /* --- Other things are bogus --- */
-
-      default:
-       k.f |= f_bogus;
-       break;
-    }
-  }
-
-  /* --- Various sorts of bogosity --- */
-
-  if ((k.f & f_bogus) || optind + 1 > argc) {
-    die(EXIT_FAILURE,
-       "Usage: add [OPTIONS] TYPE [ATTR...]");
-  }
-  if (key_chkident(argv[optind]))
-    die(EXIT_FAILURE, "bad key type `%s'", argv[optind]);
-
-  /* --- Set up various bits of the state --- */
-
-  if (exp == KEXP_EXPIRE)
-    exp = time(0) + 14 * 24 * 60 * 60;
-
-  /* --- Open the file and create the basic key block --- *
-   *
-   * Keep on generating keyids until one of them doesn't collide.
-   */
-
-  doopen(&f, KOPEN_WRITE);
-  k.kf = &f;
-
-  /* --- Key the generator --- */
-
-  keyrand(&f, rtag);
-
-  for (;;) {
-    int err;
-    if ((err = key_new(&f, kid, argv[optind], exp, &k.k)) == 0)
-      break;
-    else if (err != KERR_DUPID)
-      die(EXIT_FAILURE, "error adding new key: %s", key_strerror(err));
-  }
-
-  /* --- Set various simple attributes --- */
-
-  if (tag) {
-    int err;
-    key *kk;
-    if (k.f & f_retag) {
-      if ((kk = key_bytag(&f, tag)) != 0 &&
-         kk->tag &&
-         strcmp(kk->tag, tag) == 0)
-       key_settag(&f, kk, 0);
-    }
-    if ((err = key_settag(&f, k.k, tag)) != 0)
-      die(EXIT_FAILURE, "error setting key tag: %s", key_strerror(err));
-  }
-
-  if (c) {
-    int err = key_setcomment(&f, k.k, c);
-    if (err)
-      die(EXIT_FAILURE, "error setting key comment: %s", key_strerror(err));
-  }
-
-  setattr(&f, k.k, argv + optind + 1);
-  if (seed) {
-    key_putattr(&f, k.k, "genseed", seed);
-    key_putattr(&f, k.k, "seedalg", sa->p);
-  }
-
-  key_fulltag(k.k, &k.tag);
-
-  /* --- Find the parameter key --- */
-
-  if (ptag) {
-    if ((k.p = key_bytag(&f, ptag)) == 0)
-      die(EXIT_FAILURE, "parameter key `%s' not found", ptag);
-    if ((k.p->k->e & KF_ENCMASK) != KENC_STRUCT)
-      die(EXIT_FAILURE, "parameter key `%s' is not structured", ptag);
-  }
-
-  /* --- Now generate the actual key data --- */
-
-  alg->proc(&k);
-
-  /* --- Done --- */
-
-  dstr_destroy(&k.tag);
-  doclose(&f);
-  return (0);
-}
-
-/*----- Key listing -------------------------------------------------------*/
-
-/* --- Listing options --- */
-
-typedef struct listopts {
-  const char *tfmt;                    /* Date format (@strftime@-style) */
-  int v;                               /* Verbosity level */
-  unsigned f;                          /* Various flags */
-  time_t t;                            /* Time now (for key expiry) */
-  key_filter kf;                       /* Filter for matching keys */
-} listopts;
-
-/* --- Listing flags --- */
-
-#define f_newline 2u                   /* Write newline before next entry */
-#define f_attr 4u                      /* Written at least one attribute */
-#define f_utc 8u                       /* Emit UTC time, not local time */
-
-/* --- @showkeydata@ --- *
- *
- * Arguments:  @key_data *k@ = pointer to key to write
- *             @int ind@ = indentation level
- *             @listopts *o@ = listing options
- *             @dstr *d@ = tag string for this subkey
- *
- * Returns:    ---
- *
- * Use:                Emits a piece of key data in a human-readable format.
- */
-
-static void showkeydata(key_data *k, int ind, listopts *o, dstr *d)
-{
-#define INDENT(i) do {                                                 \
-  int _i;                                                              \
-  for (_i = 0; _i < (i); _i++) {                                       \
-    putchar(' ');                                                      \
-  }                                                                    \
-} while (0)
-
-  switch (k->e & KF_ENCMASK) {
-
-    /* --- Binary key data --- *
-     *
-     * Emit as a simple hex dump.
-     */
-
-    case KENC_BINARY: {
-      const octet *p = k->u.k.k;
-      const octet *l = p + k->u.k.sz;
-      size_t sz = 0;
-
-      fputs(" {", stdout);
-      while (p < l) {
-       if (sz % 16 == 0) {
-         putchar('\n');
-         INDENT(ind + 2);
-       } else if (sz % 8 == 0)
-         fputs("  ", stdout);
-       else
-         putc(' ', stdout);
-       printf("%02x", *p++);
-       sz++;
-      }
-      putchar('\n');
-      INDENT(ind);
-      fputs("}\n", stdout);
-    } break;
-
-    /* --- Encrypted data --- *
-     *
-     * If the user is sufficiently keen, ask for a passphrase and decrypt the
-     * key.  Otherwise just say that it's encrypted and move on.
-     */
-
-    case KENC_ENCRYPT:
-      if (o->v <= 3)
-       fputs(" encrypted\n", stdout);
-      else {
-       key_data *kd;
-       if (key_punlock(&kd, k, d->buf))
-         printf(" <failed to unlock %s>\n", d->buf);
-       else {
-         fputs(" encrypted", stdout);
-         showkeydata(kd, ind, o, d);
-         key_drop(kd);
-       }
-      }
-      break;
-
-    /* --- Integer keys --- *
-     *
-     * Emit as a large integer in decimal.  This makes using the key in
-     * `calc' or whatever easier.
-     */
-
-    case KENC_MP:
-      putchar(' ');
-      mp_writefile(k->u.m, stdout, 10);
-      putchar('\n');
-      break;
-
-    /* --- Strings --- */
-
-    case KENC_STRING:
-      printf(" `%s'\n", k->u.p);
-      break;
-
-    /* --- Elliptic curve points --- */
-
-    case KENC_EC:
-      if (EC_ATINF(&k->u.e))
-       fputs(" inf\n", stdout);
-      else {
-       fputs(" 0x", stdout); mp_writefile(k->u.e.x, stdout, 16);
-       fputs(", 0x", stdout); mp_writefile(k->u.e.y, stdout, 16);
-       putchar('\n');
-      }
-      break;
-
-    /* --- Structured keys --- *
-     *
-     * Just iterate over the subkeys.
-     */
-
-    case KENC_STRUCT: {
-      key_subkeyiter i;
-      const char *tag;
-      size_t n = d->len;
-
-      fputs(" {\n", stdout);
-      for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
-       if (!key_match(k, &o->kf))
-         continue;
-       INDENT(ind + 2);
-       printf("%s =", tag);
-       d->len = n;
-       dstr_putf(d, ".%s", tag);
-       showkeydata(k, ind + 2, o, d);
-      }
-      INDENT(ind);
-      fputs("}\n", stdout);
-    } break;
-  }
-
-#undef INDENT
-}
-
-/* --- @showkey@ --- *
- *
- * Arguments:  @key *k@ = pointer to key to show
- *             @listopts *o@ = pointer to listing options
- *
- * Returns:    ---
- *
- * Use:                Emits a listing of a particular key.
- */
-
-static void showkey(key *k, listopts *o)
-{
-  char ebuf[24], dbuf[24];
-  struct tm *tm;
-
-  /* --- Skip the key if the filter doesn't match --- */
-
-  if (!key_match(k->k, &o->kf))
-    return;
-
-  /* --- Sort out the expiry and deletion times --- */
-
-  if (KEY_EXPIRED(o->t, k->exp))
-    strcpy(ebuf, "expired");
-  else if (k->exp == KEXP_FOREVER)
-    strcpy(ebuf, "forever");
-  else {
-    tm = (o->f & f_utc) ? gmtime(&k->exp) : localtime(&k->exp);
-    strftime(ebuf, sizeof(ebuf), o->tfmt, tm);
-  }
-
-  if (KEY_EXPIRED(o->t, k->del))
-    strcpy(dbuf, "deleted");
-  else if (k->del == KEXP_FOREVER)
-    strcpy(dbuf, "forever");
-  else {
-    tm = (o->f & f_utc) ? gmtime(&k->del) : localtime(&k->del);
-    strftime(dbuf, sizeof(dbuf), o->tfmt, tm);
-  }
-
-  /* --- If in compact format, just display and quit --- */
-
-  if (!o->v) {
-    if (!(o->f & f_newline)) {
-      printf("%8s  %-20s  %-20s  %-10s  %s\n",
-            "Id", "Tag", "Type", "Expire", "Delete");
-    }
-    printf("%08lx  %-20s  %-20s  %-10s  %s\n",
-          (unsigned long)k->id, k->tag ? k->tag : "<none>",
-          k->type, ebuf, dbuf);
-    o->f |= f_newline;
-    return;
-  }
-
-  /* --- Display the standard header --- */
-
-  if (o->f & f_newline)
-    fputc('\n', stdout);
-  printf("keyid: %08lx\n", (unsigned long)k->id);
-  printf("tag: %s\n", k->tag ? k->tag : "<none>");
-  printf("type: %s\n", k->type);
-  printf("expiry: %s\n", ebuf);
-  printf("delete: %s\n", dbuf);
-  printf("comment: %s\n", k->c ? k->c : "<none>");
-
-  /* --- Display the attributes --- */
-
-  if (o->v > 1) {
-    key_attriter i;
-    const char *av, *an;
-
-    o->f &= ~f_attr;
-    printf("attributes:");
-    for (key_mkattriter(&i, k); key_nextattr(&i, &an, &av); ) {
-      printf("\n  %s = %s", an, av);
-      o->f |= f_attr;
-    }
-    if (o->f & f_attr)
-      fputc('\n', stdout);
-    else
-      puts(" <none>");
-  }
-
-  /* --- If dumping requested, dump the raw key data --- */
-
-  if (o->v > 2) {
-    dstr d = DSTR_INIT;
-    fputs("key:", stdout);
-    key_fulltag(k, &d);
-    showkeydata(k->k, 0, o, &d);
-    dstr_destroy(&d);
-  }
-
-  o->f |= f_newline;
-}
-
-/* --- @cmd_list@ --- */
-
-static int cmd_list(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  listopts o = { 0, 0, 0, 0, { 0, 0 } };
-
-  /* --- Parse subcommand options --- */
-
-  for (;;) {
-    static struct option opt[] = {
-      { "quiet",       0,              0,      'q' },
-      { "verbose",     0,              0,      'v' },
-      { "utc",         0,              0,      'u' },
-      { "filter",      OPTF_ARGREQ,    0,      'f' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+uqvf:", opt, 0, 0, 0);
-    if (i < 0)
-      break;
-
-    switch (i) {
-      case 'u':
-       o.f |= f_utc;
-       break;
-      case 'q':
-       if (o.v)
-         o.v--;
-       break;
-      case 'v':
-       o.v++;
-       break;
-      case 'f': {
-       char *p;
-       int e = key_readflags(optarg, &p, &o.kf.f, &o.kf.m);
-       if (e || *p)
-         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
-      } break;
-      default:
-       o.f |= f_bogus;
-       break;
-    }
-  }
-
-  if (o.f & f_bogus)
-    die(EXIT_FAILURE, "Usage: list [-uqv] [-f FILTER] [TAG...]");
-
-  /* --- Open the key file --- */
-
-  doopen(&f, KOPEN_READ);
-  o.t = time(0);
-
-  /* --- Set up the time format --- */
-
-  if (!o.v)
-    o.tfmt = "%Y-%m-%d";
-  else if (o.f & f_utc)
-    o.tfmt = "%Y-%m-%d %H:%M:%S UTC";
-  else
-    o.tfmt = "%Y-%m-%d %H:%M:%S %Z";
-
-  /* --- If specific keys were requested use them, otherwise do all --- *
-   *
-   * Some day, this might turn into a wildcard match.
-   */
-
-  if (optind < argc) {
-    do {
-      if ((k = key_bytag(&f, argv[optind])) != 0)
-       showkey(k, &o);
-      else {
-       moan("key `%s' not found", argv[optind]);
-       o.f |= f_bogus;
-      }
-      optind++;
-    } while (optind < argc);
-  } else {
-    key_iter i;
-    for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; )
-      showkey(k, &o);
-  }
-
-  /* --- Done --- */
-
-  doclose(&f);
-  if (o.f & f_bogus)
-    return (EXIT_FAILURE);
-  else
-    return (0);
-}
-
-/*----- Command implementation --------------------------------------------*/
-
-/* --- @cmd_expire@ --- */
-
-static int cmd_expire(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  int i;
-  int rc = 0;
-
-  if (argc < 2)
-    die(EXIT_FAILURE, "Usage: expire TAG...");
-  doopen(&f, KOPEN_WRITE);
-  for (i = 1; i < argc; i++) {
-    if ((k = key_bytag(&f, argv[i])) != 0)
-      key_expire(&f, k);
-    else {
-      moan("key `%s' not found", argv[i]);
-      rc = 1;
-    }
-  }
-  doclose(&f);
-  return (rc);
-}
-
-/* --- @cmd_delete@ --- */
-
-static int cmd_delete(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  int i;
-  int rc = 0;
-
-  if (argc < 2)
-    die(EXIT_FAILURE, "Usage: delete TAG...");
-  doopen(&f, KOPEN_WRITE);
-  for (i = 1; i < argc; i++) {
-    if ((k = key_bytag(&f, argv[i])) != 0)
-      key_delete(&f, k);
-    else {
-      moan("key `%s' not found", argv[i]);
-      rc = 1;
-    }
-  }
-  doclose(&f);
-  return (rc);
-}
-
-/* --- @cmd_setattr@ --- */
-
-static int cmd_setattr(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-
-  if (argc < 3)
-    die(EXIT_FAILURE, "Usage: setattr TAG ATTR...");
-  doopen(&f, KOPEN_WRITE);
-  if ((k = key_bytag(&f, argv[1])) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
-  setattr(&f, k, argv + 2);
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_getattr@ --- */
-
-static int cmd_getattr(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  dstr d = DSTR_INIT;
-  const char *p;
-
-  if (argc != 3)
-    die(EXIT_FAILURE, "Usage: getattr TAG ATTR");
-  doopen(&f, KOPEN_READ);
-  if ((k = key_bytag(&f, argv[1])) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
-  key_fulltag(k, &d);
-  if ((p = key_getattr(&f, k, argv[2])) == 0)
-    die(EXIT_FAILURE, "no attribute `%s' for key `%s'", argv[2], d.buf);
-  puts(p);
-  dstr_destroy(&d);
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_finger@ --- */
-
-static void fingerprint(key *k, const gchash *ch, const key_filter *kf)
-{
-  ghash *h;
-  dstr d = DSTR_INIT;
-  const octet *p;
-  size_t i;
-
-  h = GH_INIT(ch);
-  if (key_fingerprint(k, h, kf)) {
-    p = GH_DONE(h, 0);
-    key_fulltag(k, &d);
-    for (i = 0; i < ch->hashsz; i++) {
-      if (i && i % 4 == 0)
-       putchar('-');
-      printf("%02x", p[i]);
-    }
-    printf(" %s\n", d.buf);
-  }
-  dstr_destroy(&d);
-  GH_DESTROY(h);
-}
-
-static int cmd_finger(int argc, char *argv[])
-{
-  key_file f;
-  int rc = 0;
-  const gchash *ch = &rmd160;
-  key_filter kf = { KF_NONSECRET, KF_NONSECRET };
-
-  for (;;) {
-    static struct option opt[] = {
-      { "filter",      OPTF_ARGREQ,    0,      'f' },
-      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'f': {
-       char *p;
-       int err = key_readflags(optarg, &p, &kf.f, &kf.m);
-       if (err || *p)
-         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
-      } break;
-      case 'a':
-       if ((ch = ghash_byname(optarg)) == 0)
-         die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg);
-       break;
-      default:
-       rc = 1;
-       break;
-    }
-  }
-
-  argv += optind; argc -= optind;
-  if (rc)
-    die(EXIT_FAILURE, "Usage: fingerprint [-f FILTER] [TAG...]");
-
-  doopen(&f, KOPEN_READ);
-
-  if (argc) {
-    int i;
-    for (i = 0; i < argc; i++) {
-      key *k = key_bytag(&f, argv[i]);
-      if (k)
-       fingerprint(k, ch, &kf);
-      else {
-       rc = 1;
-       moan("key `%s' not found", argv[i]);
-      }
-    }
-  } else {
-    key_iter i;
-    key *k;
-    for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; )
-      fingerprint(k, ch, &kf);
-  }
-  return (rc);
-}
-
-/* --- @cmd_verify@ --- */
-
-static unsigned xdigit(char c)
-{
-  if ('A' <= c && c <= 'Z') return (c + 10 - 'A');
-  if ('a' <= c && c <= 'z') return (c + 10 - 'a');
-  if ('0' <= c && c <= '9') return (c - '0');
-  return (~0u);
-}
-
-static void unhexify(octet *q, char *p, size_t n)
-{
-  unsigned a = 0;
-  int i = 0;
-
-  for (;;) {
-    if (*p == '-' || *p == ':' || isspace((unsigned char)*p)) {
-      p++;
-      continue;
-    }
-    if (!n && !*p)
-      break;
-    if (!*p)
-      die(EXIT_FAILURE, "hex string too short");
-    if (!isxdigit((unsigned char)*p))
-      die(EXIT_FAILURE, "bad hex string");
-    if (!n)
-      die(EXIT_FAILURE, "hex string too long");
-    a = (a << 4) | xdigit(*p++);
-    i++;
-    if (i == 2) {
-      *q++ = U8(a);
-      a = 0;
-      i = 0;
-      n--;
-    }
-  }
-}
-
-static int cmd_verify(int argc, char *argv[])
-{
-  key_file f;
-  int rc = 0;
-  const gchash *ch = &rmd160;
-  ghash *h;
-  key *k;
-  octet *buf;
-  const octet *fpr;
-  key_filter kf = { KF_NONSECRET, KF_NONSECRET };
-
-  for (;;) {
-    static struct option opt[] = {
-      { "filter",      OPTF_ARGREQ,    0,      'f' },
-      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'f': {
-       char *p;
-       int err = key_readflags(optarg, &p, &kf.f, &kf.m);
-       if (err || *p)
-         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
-      } break;
-      case 'a':
-       if ((ch = ghash_byname(optarg)) == 0)
-         die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg);
-       break;
-      default:
-       rc = 1;
-       break;
-    }
-  }
-
-  argv += optind; argc -= optind;
-  if (rc || argc != 2)
-    die(EXIT_FAILURE, "Usage: verify [-f FILTER] TAG FINGERPRINT");
-
-  doopen(&f, KOPEN_READ);
-
-  if ((k = key_bytag(&f, argv[0])) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", argv[0]);
-  buf = xmalloc(ch->hashsz);
-  unhexify(buf, argv[1], ch->hashsz);
-  h = GH_INIT(ch);
-  if (!key_fingerprint(k, h, &kf))
-    die(EXIT_FAILURE, "key has no fingerprintable components (as filtered)");
-  fpr = GH_DONE(h, 0);
-  if (memcmp(fpr, buf, ch->hashsz) != 0)
-    die(EXIT_FAILURE, "key fingerprint mismatch");
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_comment@ --- */
-
-static int cmd_comment(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  int err;
-
-  if (argc < 2 || argc > 3)
-    die(EXIT_FAILURE, "Usage: comment TAG [COMMENT]");
-  doopen(&f, KOPEN_WRITE);
-  if ((k = key_bytag(&f, argv[1])) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
-  if ((err = key_setcomment(&f, k, argv[2])) != 0)
-    die(EXIT_FAILURE, "bad comment `%s': %s", argv[2], key_strerror(err));
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_tag@ --- */
-
-static int cmd_tag(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  int err;
-  unsigned flags = 0;
-  int rc = 0;
-
-  for (;;) {
-    static struct option opt[] = {
-      { "retag",       0,              0,      'r' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+r", opt, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'r':
-       flags |= f_retag;
-       break;
-      default:
-       rc = 1;
-       break;
-    }
-  }
-
-  argv += optind; argc -= optind;
-  if (argc < 1 || argc > 2 || rc)
-    die(EXIT_FAILURE, "Usage: tag [-r] TAG [NEW-TAG]");
-  doopen(&f, KOPEN_WRITE);
-  if (flags & f_retag) {
-    if ((k = key_bytag(&f, argv[1])) != 0 && strcmp(k->tag, argv[1]) == 0)
-      key_settag(&f, k, 0);
-  }
-  if ((k = key_bytag(&f, argv[0])) == 0)
-    die(EXIT_FAILURE, "key `%s' not found", argv[0]);
-  if ((err = key_settag(&f, k, argv[1])) != 0)
-    die(EXIT_FAILURE, "bad tag `%s': %s", argv[1], key_strerror(err));
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_lock@ --- */
-
-static int cmd_lock(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  key_data **kd;
-  dstr d = DSTR_INIT;
-
-  if (argc != 2)
-    die(EXIT_FAILURE, "Usage: lock QTAG");
-  doopen(&f, KOPEN_WRITE);
-  if (key_qtag(&f, argv[1], &d, &k, &kd))
-    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
-  if ((*kd)->e == KENC_ENCRYPT && key_punlock(kd, 0, d.buf))
-    die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf);
-  if (key_plock(kd, 0, d.buf))
-    die(EXIT_FAILURE, "failed to lock key `%s'", d.buf);
-  f.f |= KF_MODIFIED;
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_unlock@ --- */
-
-static int cmd_unlock(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  key_data **kd;
-  dstr d = DSTR_INIT;
-
-  if (argc != 2)
-    die(EXIT_FAILURE, "Usage: unlock QTAG");
-  doopen(&f, KOPEN_WRITE);
-  if (key_qtag(&f, argv[1], &d, &k, &kd))
-    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
-  if ((*kd)->e != KENC_ENCRYPT)
-    die(EXIT_FAILURE, "key `%s' is not encrypted", d.buf);
-  if (key_punlock(kd, 0, d.buf))
-    die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf);
-  f.f |= KF_MODIFIED;
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_extract@ --- */
-
-static int cmd_extract(int argc, char *argv[])
-{
-  key_file f;
-  key *k;
-  int i;
-  int rc = 0;
-  key_filter kf = { 0, 0 };
-  dstr d = DSTR_INIT;
-  const char *outfile = 0;
-  FILE *fp;
-
-  for (;;) {
-    static struct option opt[] = {
-      { "filter",      OPTF_ARGREQ,    0,      'f' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "f:", opt, 0, 0, 0);
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'f': {
-       char *p;
-       int err = key_readflags(optarg, &p, &kf.f, &kf.m);
-       if (err || *p)
-         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
-      } break;
-      default:
-       rc = 1;
-       break;
-    }
-  }
-
-  argv += optind; argc -= optind;
-  if (rc || argc < 1)
-    die(EXIT_FAILURE, "Usage: extract [-f FILTER] FILE [TAG...]");
-  if (strcmp(*argv, "-") == 0)
-    fp = stdout;
-  else {
-    outfile = *argv;
-    dstr_putf(&d, "%s.new", outfile);
-    if (!(fp = fopen(d.buf, "w"))) {
-      die(EXIT_FAILURE, "couldn't open `%s' for writing: %s",
-         d.buf, strerror(errno));
-    }
-  }
-
-  doopen(&f, KOPEN_READ);
-  if (argc < 2) {
-    key_iter i;
-    key *k;
-    for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; )
-      key_extract(&f, k, fp, &kf);
-  } else {
-    for (i = 1; i < argc; i++) {
-      if ((k = key_bytag(&f, argv[i])) != 0)
-       key_extract(&f, k, fp, &kf);
-      else {
-       moan("key `%s' not found", argv[i]);
-       rc = 1;
-      }
-    }
-  }
-  if (fclose(fp) || (outfile && rename(d.buf, outfile)))
-    die(EXIT_FAILURE, "error writing file: %s", strerror(errno));
-  dstr_destroy(&d);
-  doclose(&f);
-  return (rc);
-}
-
-/* --- @cmd_tidy@ --- */
-
-static int cmd_tidy(int argc, char *argv[])
-{
-  key_file f;
-  if (argc != 1)
-    die(EXIT_FAILURE, "Usage: tidy");
-  doopen(&f, KOPEN_WRITE);
-  f.f |= KF_MODIFIED; /* Nasty hack */
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_merge@ --- */
-
-static int cmd_merge(int argc, char *argv[])
-{
-  key_file f;
-  FILE *fp;
-
-  if (argc != 2)
-    die(EXIT_FAILURE, "Usage: merge FILE");
-  if (strcmp(argv[1], "-") == 0)
-    fp = stdin;
-  else if (!(fp = fopen(argv[1], "r"))) {
-    die(EXIT_FAILURE, "couldn't open `%s' for reading: %s",
-       argv[1], strerror(errno));
-  }
-
-  doopen(&f, KOPEN_WRITE);
-  key_merge(&f, argv[1], fp, key_moan, 0);
-  doclose(&f);
-  return (0);
-}
-
-/* --- @cmd_show@ --- */
-
-#define LISTS(LI)                                                      \
-  LI("Lists", list,                                                    \
-     listtab[i].name, listtab[i].name)                                 \
-  LI("Hash functions", hash,                                           \
-     ghashtab[i], ghashtab[i]->name)                                   \
-  LI("Elliptic curves", ec,                                            \
-     ectab[i].name, ectab[i].name)                                     \
-  LI("Prime Diffie-Hellman groups", dh,                                        \
-     ptab[i].name, ptab[i].name)                                       \
-  LI("Binary Diffie-Hellman groups", bindh,                            \
-     bintab[i].name, bintab[i].name)                                   \
-  LI("Key-generation algorithms", keygen,                              \
-     algtab[i].name, algtab[i].name)                                   \
-  LI("Random seeding algorithms", seed,                                        \
-     seedtab[i].p, seedtab[i].p)
-
-MAKELISTTAB(listtab, LISTS)
-
-static int cmd_show(int argc, char *argv[])
-{
-  return (displaylists(listtab, argv + 1));
-}
-
-/*----- Main command table ------------------------------------------------*/
-
-static int cmd_help(int argc, char *argv[]);
-
-static cmd cmds[] = {
-  { "help", cmd_help, "help [COMMAND...]" },
-  { "show", cmd_show, "show [ITEM...]" },
-  { "list", cmd_list, "list [-uqv] [-f FILTER] [TAG...]", "\
-Options:\n\
-\n\
--u, --utc              Display expiry times etc. in UTC, not local time.\n\
--q, --quiet            Show less information.\n\
--v, --verbose          Show more information.\n\
-" },
-  { "fingerprint", cmd_finger, "fingerprint [-f FILTER] [TAG...]", "\
-Options:\n\
-\n\
--f, --filter=FILT      Only hash key components matching FILT.\n\
--a, --algorithm=HASH   Use the named HASH algorithm.\n\
-                         ($ show hash for list.)\n\
-" },
-  { "verify", cmd_verify, "verify [-f FILTER] TAG FINGERPRINT", "\
-Options:\n\
-\n\
--f, --filter=FILT      Only hash key components matching FILT.\n\
--a, --algorithm=HASH   Use the named HASH algorithm.\n\
-                         ($ show hash for list.)\n\
-" },
-  { "extract", cmd_extract, "extract [-f FILTER] FILE [TAG...]", "\
-Options:\n\
-\n\
--f, --filter=FILT      Only extract key components matching FILT.\n\
-" },
-  { "merge", cmd_merge, "merge FILE" },
-  { "expire", cmd_expire, "expire TAG..." },
-  { "delete", cmd_delete, "delete TAG..." },
-  { "setattr", cmd_setattr, "setattr TAG ATTR..." },
-  { "getattr", cmd_getattr, "getattr TAG ATTR" },
-  { "comment", cmd_comment, "comment TAG [COMMENT]" },
-  { "lock", cmd_lock, "lock QTAG" },
-  { "unlock", cmd_unlock, "unlock QTAG" },
-  { "tag", cmd_tag, "tag [-r] TAG [NEW-TAG]", "\
-Options:\n\
-\n\
--r, --retag            Untag any key currently called new-tag.\n\
-" },
-  { "tidy", cmd_tidy, "tidy" },
-  { "add", cmd_add,
-    "add [-OPTIONS] TYPE [ATTR...]\n\
-       Options: [-lqrLKS] [-a ALG] [-bB BITS] [-p PARAM] [-R TAG]\n\
-                [-A SEEDALG] [-s SEED] [-n BITS] [-I KEYID]\n\
-                [-e EXPIRE] [-t TAG] [-c COMMENT]", "\
-Options:\n\
-\n\
--a, --algorithm=ALG    Generate keys suitable for ALG.\n\
-                         ($ show keygen for list.)\n\
--b, --bits=N           Generate an N-bit key.\n\
--B, --qbits=N          Use an N-bit subgroup or factors.\n\
--p, --parameters=TAG   Get group parameters from TAG.\n\
--C, --curve=NAME       Use elliptic curve or DH group NAME.\n\
-                         ($ show ec or $ show dh for list.)\n\
--A, --seedalg=ALG      Use pseudorandom generator ALG to generate key.\n\
-                         ($ show seed for list.)\n\
--s, --seed=BASE64      Use Base64-encoded string BASE64 as seed.\n\
--n, --newseed=COUNT    Generate new COUNT-bit seed.\n\
--e, --expire=TIME      Make the key expire after TIME.\n\
--c, --comment=STRING   Attach the command STRING to the key.\n\
--t, --tag=TAG          Tag the key with the name TAG.\n\
--r, --retag            Untag any key currently with that tag.\n\
--R, --rand-id=TAG      Use key named TAG for the random number generator.\n\
--I, --key-id=ID                Force the key-id for the new key.\n\
--l, --lock             Lock the generated key with a passphrase.\n\
--q, --quiet            Don't give progress indicators while working.\n\
--L, --lim-lee          Generate Lim-Lee primes for Diffie-Hellman groups.\n\
--K, --kcdsa            Generate KCDSA-style Lim-Lee primes for DH groups.\n\
--S, --subgroup         Use a prime-order subgroup for Diffie-Hellman.\n\
-" },
-  { 0, 0, 0 }
-};
-
-static int cmd_help(int argc, char *argv[])
-{
-  sc_help(cmds, stdout, argv + 1);
-  return (0);
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Helpful GNUy functions --- */
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n");
-}
-
-void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-void help_global(FILE *fp)
-{
-  usage(fp);
-  fputs("\n\
-Performs various simple key management operations.\n\
-\n\
-Global command line options:\n\
-\n\
--h, --help [COMMAND...]        Display this help text (or help for COMMANDs).\n\
--v, --version          Display version number.\n\
--u, --usage            Display short usage summary.\n\
-\n\
--k, --keyring=FILE     Read and write keys in FILE.\n",
-       fp);
-}
-
-/* --- @main@ --- *
- *
- * Arguments:  @int argc@ = number of command line arguments
- *             @char *argv[]@ = array of command line arguments
- *
- * Returns:    Nonzero on failure.
- *
- * Use:                Main program.  Performs simple key management functions.
- */
-
-int main(int argc, char *argv[])
-{
-  unsigned f = 0;
-
-#define f_bogus 1u
-
-  /* --- Initialization --- */
-
-  ego(argv[0]);
-  sub_init();
-
-  /* --- Parse command line options --- */
-
-  for (;;) {
-    static struct option opt[] = {
-
-      /* --- Standard GNUy help options --- */
-
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'v' },
-      { "usage",       0,              0,      'u' },
-
-      /* --- Real live useful options --- */
-
-      { "keyring",     OPTF_ARGREQ,    0,      'k' },
-
-      /* --- Magic terminator --- */
-
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "+hvu k:", opt, 0, 0, 0);
-
-    if (i < 0)
-      break;
-    switch (i) {
-
-      /* --- GNU help options --- */
-
-      case 'h':
-       sc_help(cmds, stdout, argv + optind);
-       exit(0);
-      case 'v':
-       version(stdout);
-       exit(0);
-      case 'u':
-       usage(stdout);
-       exit(0);
-
-      /* --- Real useful options --- */
-
-      case 'k':
-       keyfile = optarg;
-       break;
-
-      /* --- Bogosity --- */
-
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-
-  /* --- Complain about excessive bogons --- */
-
-  if (f & f_bogus || optind == argc) {
-    usage(stderr);
-    exit(1);
-  }
-
-  /* --- Initialize the Catacomb random number generator --- */
-
-  rand_noisesrc(RAND_GLOBAL, &noise_source);
-  rand_seed(RAND_GLOBAL, 160);
-
-  /* --- Dispatch to appropriate command handler --- */
-
-  argc -= optind;
-  argv += optind;
-  optind = 0;
-  return (findcmd(cmds, argv[0])->cmd(argc, argv));
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/lcrand.c b/lcrand.c
deleted file mode 100644 (file)
index a108f13..0000000
--- a/lcrand.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* -*-c-*-
- *
- * $Id: lcrand.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Simple linear congruential generator
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#include "grand.h"
-#include "lcrand.h"
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-/* --- The generator parameters --- */
-
-#define P LCRAND_P                     /* Modulus */
-#define A LCRAND_A                     /* Multiplier (primitive mod @p@) */
-#define C LCRAND_C                     /* Additive constant */
-
-/* --- Precomputed values for modular reduction --- */
-
-#define D 5                            /* %$p = 2^{32} - d$% */
-
-/* --- Other useful bits --- */
-
-#define P256 4294967040u               /* Highest multiple of 256 < %$p$% */
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @lcrand@ --- *
- *
- * Arguments:  @uint32 x@ = seed value
- *
- * Returns:    New state of the generator.
- *
- * Use:                Steps the generator.  Returns %$ax + c \bmod p$%.
- */
-
-uint32 lcrand(uint32 x)
-{
-  uint32 a[2], xx[2];
-  uint32 yy[2];
-
-  /* --- Unpack things into the arrays --- */
-
-  a[0] = U16(A); a[1] = U16(A >> 16);
-  xx[0] = U16(x); xx[1] = U16(x >> 16);
-
-  /* --- Multiply everything together --- *
-   *
-   * This is plain old long multiplication, although it looks a bit strange.
-   * I set up the top and bottom partial products directly where they're
-   * supposed to be.  The cross terms I add together, with the low 16 bits in
-   * @q@ and the high 32 bits in @p@.  These I then add into the product.
-   */
-
-  {
-    uint32 p, q;
-
-    yy[0] = a[0] * xx[0];
-    yy[1] = a[1] * xx[1];
-
-    p = a[0] * xx[1];
-    q = p + a[1] * xx[0];
-    p = ((q < p) << 16) + (q >> 16);
-    q = U16(q) << 16;
-
-    q += yy[0];
-    if (q < yy[0])
-      p++;
-    else
-      p += (q >> 16) >> 16;
-    yy[0] = q;
-
-    yy[1] += p;
-  }
-
-  /* --- Now reduce mod p --- *
-   *
-   * I'm using shifts and adds to do the multiply step here.  This needs to
-   * be changed if @D@ ever becomes something other than 5.
-   */
-
-#if D != 5
-#  error "Change shift sequence!"
-#endif
-
-  {
-    uint32 q;
-
-    q = yy[1];
-    x = yy[0];
-
-    while (q) {
-      uint32 y, z;
-      y = q >> 30;
-      z = q << 2;
-      z += q;
-      if (z < q)
-       y++;
-      else
-       y += (q >> 16) >> 16;
-      q = y;
-      x += z;
-      if (x < z || x > P)
-       x -= P;
-    }
-  }
-
-  /* --- Now add on the constant --- */
-
-  x += C;
-  if (x < C || x >= P)
-    x -= P;
-
-  /* --- Done --- */
-
-  return (x);
-}
-
-/* --- @lcrand_range@ --- *
- *
- * Arguments:  @uint32 *x@ = pointer to seed value (updated)
- *             @uint32 m@ = limit allowable
- *
- * Returns:    A uniformly distributed pseudorandom integer in the interval
- *             %$[0, m)$%.
- */
-
-uint32 lcrand_range(uint32 *x, uint32 m)
-{
-  uint32 xx = *x;
-  uint32 r = P - P % m;
-  do xx = lcrand(xx); while (xx >= r);
-  *x = xx;
-  return (xx % m);
-}
-
-/*----- Generic interface -------------------------------------------------*/
-
-typedef struct gctx {
-  grand r;
-  uint32 x;
-} gctx;
-
-static void gdestroy(grand *r)
-{
-  gctx *g = (gctx *)r;
-  DESTROY(g);
-}
-
-static int gmisc(grand *r, unsigned op, ...)
-{
-  gctx *g = (gctx *)r;
-  va_list ap;
-  int rc = 0;
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDRAND:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT:
-      g->x = va_arg(ap, unsigned);
-      break;
-    case GRAND_SEEDUINT32:
-      g->x = va_arg(ap, uint32);
-      break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      uint32 x;
-      do x = rr->ops->word(rr); while (x >= P || x == LCRAND_FIXEDPT);
-      g->x = x;
-    } break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static uint32 graw(grand *r)
-{
-  gctx *g = (gctx *)r;
-  g->x = lcrand(g->x);
-  return (g->x);
-}
-
-static octet gbyte(grand *r)
-{
-  gctx *g = (gctx *)r;
-  uint32 x = g->x;
-  do x = lcrand(x); while (x >= P256);
-  g->x = x;
-  return (x / (P256 / 256));
-}
-
-static uint32 grange(grand *r, uint32 l)
-{
-  gctx *g = (gctx *)r;
-  return (lcrand_range(&g->x, l));
-}
-
-static const grand_ops gops = {
-  "lcrand",
-  LCRAND_P, 0,
-  gmisc, gdestroy,
-  graw, gbyte, grand_word, grange, grand_fill
-};
-
-/* --- @lcrand_create@ --- *
- *
- * Arguments:  @uint32 x@ = initial seed
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a linear
- *             congruential generator.
- */
-
-grand *lcrand_create(uint32 x)
-{
-  gctx *g = CREATE(gctx);
-  g->r.ops = &gops;
-  g->x = x;
-  return (&g->r);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int verify(dstr *v)
-{
-  uint32 x = *(uint32 *)v[0].buf;
-  uint32 y = *(uint32 *)v[1].buf;
-  uint32 z = lcrand(x);
-  int ok = 1;
-  if (y != z) {
-    fprintf(stderr,
-           "\n*** lcrand failed.  lcrand(%lu) = %lu, expected %lu\n",
-           (unsigned long)x, (unsigned long)z, (unsigned long)y);
-    ok = 0;
-  }
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "lcrand", verify, { &type_uint32, &type_uint32, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, tests, SRCDIR"/tests/lcrand");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/lcrand.h b/lcrand.h
deleted file mode 100644 (file)
index 080370c..0000000
--- a/lcrand.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*-c-*-
- *
- * $Id: lcrand.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Simple linear congruential generator
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on the linear congruential generator ------------------------*
- *
- * This pseudorandom number generator is simple, but has absolutely no
- * cryptographic strength whatever.  It may be used whenever random numbers
- * are required but cryptographic strength is not, for example when
- * generating numbers for use in primality tests.  To be honest, it's not
- * even particularly fast, although a certain amount of effort has been
- * expended on making it better than awfully slow.  To put things in
- * perspective, it can't quite spit bytes out as fast as OFB DES.  (Then
- * again, bytes aren't its natural output format.)  Its main use is probably
- * seeding a Fibonacci generator.
- *
- * There exists a fixed-point input @LCRAND_FIXEDPT@ -- when fed to the
- * generator it comes straight back out again.  All other inputs less than
- * the modulus are part of the same sequence of period %$p - 1$%.
- *
- * The generator has been tested for its statistical properties.  George
- * Marsaglia's Diehard tests give it a reasonably clean bill of health.
- *
- * The modulus %$p$% is chosen as the largest prime number less than
- * %$2^{32}$%.  The multiplier %$a$% and additive constant %$c$% are based on
- * the decimal expansions of %$\pi$% and %$e$%, with the additional
- * restriction that the multiplier must be a primitive element modulo %$p$%.
- * The fixed point value is determined as %$c / (1 - a) \bmod p$%.
- */
-
-#ifndef CATACOMB_LCRAND_H
-#define CATACOMB_LCRAND_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Constants ---------------------------------------------------------*/
-
-#define LCRAND_P 4294967291u           /* Modulus for the generator */
-#define LCRAND_A 314159265u            /* Multiplier (primitive mod @p@) */
-#define LCRAND_C 271828183u            /* Additive constant */
-
-#define LCRAND_FIXEDPT 3223959250u     /* Fixed point (only bad input) */
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @lcrand@ --- *
- *
- * Arguments:  @uint32 x@ = seed value
- *
- * Returns:    New state of the generator.
- *
- * Use:                Steps the generator.  Returns %$ax + c \bmod p$%.
- */
-
-extern uint32 lcrand(uint32 /*x*/);
-
-/* --- @lcrand_range@ --- *
- *
- * Arguments:  @uint32 *x@ = pointer to seed value (updated)
- *             @uint32 m@ = limit allowable
- *
- * Returns:    A uniformly distributed pseudorandom integer in the interval
- *             %$[0, m)$%.
- */
-
-extern uint32 lcrand_range(uint32 */*x*/, uint32 /*m*/);
-
-/* --- @lcrand_create@ --- *
- *
- * Arguments:  @uint32 x@ = initial seed
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a linear
- *             congruential generator.
- */
-
-extern grand *lcrand_create(uint32 /*x*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/limlee.c b/limlee.c
deleted file mode 100644 (file)
index b6fc4d6..0000000
--- a/limlee.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/* -*-c-*-
- *
- * $Id: limlee.c,v 1.9 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate Lim-Lee primes
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-
-#include "limlee.h"
-#include "mpmul.h"
-#include "mprand.h"
-#include "pgen.h"
-#include "rabin.h"
-
-/*----- Stepping through combinations -------------------------------------*/
-
-/* --- @comb_init@ --- *
- *
- * Arguments:  @octet *c@ = pointer to byte-flag array
- *             @unsigned n@ = number of items in the array
- *             @unsigned r@ = number of desired items
- *
- * Returns:    ---
- *
- * Use:                Initializes a byte-flag array which, under the control of
- *             @comb_next@, will step through all combinations of @r@ chosen
- *             elements.
- */
-
-static void comb_init(octet *c, unsigned n, unsigned r)
-{
-  memset(c, 0, n - r);
-  memset(c + (n - r), 1, r);
-}
-
-/* --- @comb_next@ --- *
- *
- * Arguments:  @octet *c@ = pointer to byte-flag array
- *             @unsigned n@ = number of items in the array
- *             @unsigned r@ = number of desired items
- *
- * Returns:    Nonzero if another combination was returned, zero if we've
- *             reached the end.
- *
- * Use:                Steps on to the next combination in sequence.
- */
-
-static int comb_next(octet *c, unsigned n, unsigned r)
-{
-  unsigned g = 0;
-
-  /* --- How the algorithm works --- *
-   *
-   * Set bits start at the end and work their way towards the start.
-   * Excepting bits already at the start, we scan for the lowest set bit, and
-   * move it one place nearer the start.  A group of bits at the start are
-   * counted and reset just below the `moved' bit.  If there is no moved bit
-   * then we're done.
-   */
-
-  /* --- Count the group at the start --- */
-
-  for (; *c; c++) {
-    g++;
-    *c = 0;
-  }
-  if (g == r)
-    return (0);
-
-  /* --- Move the next bit down one --- *
-   *
-   * There must be one, because otherwise we'd have counted %$r$% bits
-   * earlier.
-   */
-
-  for (; !*c; c++)
-    ;
-  *c = 0;
-  g++;
-  for (; g; g--)
-    *--c = 1;
-  return (1);
-}
-
-/*----- Default prime generator -------------------------------------------*/
-
-static void llgen(limlee_factor *f, unsigned pl, limlee_stepctx *l)
-{
-  pgen_filterctx pf;
-  rabin r;
-  mp *p;
-
-again:
-  p = mprand(l->newp, pl, l->r, 1);
-  pf.step = 2;
-  p = pgen(l->d.buf, p, p, l->iev, l->iec, 0, pgen_filter, &pf,
-          rabin_iters(pl), pgen_test, &r);
-  if (!p)
-    goto again;
-  f->p = p;
-}
-
-static void llfree(limlee_factor *f, limlee_stepctx *l)
-{
-  mp_drop(f->p);
-}
-
-static const limlee_primeops primeops_simple = { llgen, llfree };
-
-/*----- Lim-Lee stepper ---------------------------------------------------*/
-
-/* --- @init@ --- *
- *
- * Arguments:  @pgen_event *ev@ = pointer to event block
- *             @limlee_stepctx *l@ = pointer to Lim-Lee context
- *
- * Returns:    A @PGEN@ result code.
- *
- * Use:                Initializes the stepper.
- */
-
-static int init(pgen_event *ev, limlee_stepctx *l)
-{
-  size_t i;
-  unsigned qql;
-
-  /* --- First of all, decide on a number of factors to make --- */
-
-  l->nf = l->pl / l->ql;
-  qql = l->pl % l->ql;
-  if (!l->nf)
-    return (PGEN_ABORT);
-  else if (qql && l->nf > 1) {
-    l->nf--;
-    qql += l->ql;
-  }
-
-  /* --- Now decide on how many primes I'll actually generate --- *
-   *
-   * The formula %$m = \max(3 n + 5, 25)$% comes from GPG's prime generation
-   * library.
-   */
-
-  l->poolsz = l->nf * 3 + 5;
-  if (l->poolsz < 25)
-    l->poolsz = 25;
-
-  /* --- Allocate and initialize the various tables --- */
-
-  l->c = xmalloc(l->poolsz);
-  l->v = xmalloc(l->poolsz * sizeof(limlee_factor));
-  comb_init(l->c, l->poolsz, l->nf);
-  for (i = 0; i < l->poolsz; i++)
-    l->v[i].p = 0;
-
-  /* --- Other bits of initialization --- */
-
-  l->seq = 0;
-  dstr_create(&l->d);
-  if (!l->pops) {
-    l->pops = &primeops_simple;
-    l->pc = 0;
-  }
-
-  /* --- Find a big prime --- */
-
-  if (!qql)
-    l->qq.p = 0;
-  else {
-    dstr_putf(&l->d, "%s*", ev->name);
-    l->pops->pgen(&l->qq, qql, l);
-  }
-
-  return (PGEN_TRY);
-}
-
-/* --- @next@ --- *
- *
- * Arguments:  @int rq@ = request which triggered this call
- *             @pgen_event *ev@ = pointer to event block
- *             @limlee_stepctx *l@ = pointer to Lim-Lee context
- *
- * Returns:    A @PGEN@ result code.
- *
- * Use:                Initializes the stepper.
- */
-
-static int next(int rq, pgen_event *ev, limlee_stepctx *l)
-{
-  mp *p;
-  int rc;
-
-  mp_drop(ev->m);
-
-  for (;;) {
-    size_t i;
-    mpmul mm = MPMUL_INIT;
-
-    /* --- Step on to next combination --- */
-
-    if (rq == PGEN_TRY && !comb_next(l->c, l->poolsz, l->nf)) {
-      for (i = 0; i < l->poolsz; i++) {
-       l->pops->pfree(&l->v[i], l);
-       l->v[i].p = 0;
-      }
-    }
-    rq = PGEN_TRY; /* For next time through */
-
-    /* --- Gather up some factors --- */
-
-    if (l->qq.p)
-      mpmul_add(&mm, l->qq.p);
-    for (i = 0; i < l->poolsz; i++) {
-      if (!l->c[i])
-       continue;
-      if (!l->v[i].p) {
-       DRESET(&l->d);
-       dstr_putf(&l->d, "%s_%lu", ev->name, l->seq++);
-       l->pops->pgen(&l->v[i], l->ql, l);
-      }
-      mpmul_add(&mm, l->v[i].p);
-    }
-
-    /* --- Check it for small factors --- */
-
-    p = mpmul_done(&mm);
-    p = mp_lsl(p, p, 1);
-    p->v[0] |= 1;
-    if ((rc = pfilt_smallfactor(p)) != PGEN_FAIL)
-      break;
-    mp_drop(p);
-  }
-
-  ev->m = p;
-  return (rc);
-}
-
-/* --- @done@ --- *
- *
- * Arguments:  @pgen_event *ev@ = pointer to event block
- *             @limlee_stepctx *l@ = pointer to Lim-Lee context
- *
- * Returns:    A @PGEN@ result code.
- *
- * Use:                Finalizes the stepper.  The output values in the context
- *             take on their final results; other resources are discarded.
- */
-
-static int done(pgen_event *ev, limlee_stepctx *l)
-{
-  size_t i, j;
-  limlee_factor *v;
-
-  /* --- If an output vector of factors is wanted, produce one --- */
-
-  if (!(l->f & LIMLEE_KEEPFACTORS))
-    v = 0;
-  else {
-    if (l->qq.p)
-      l->nf++;
-    v = xmalloc(l->nf * sizeof(limlee_factor));
-  }
-
-  for (i = 0, j = 0; i < l->poolsz; i++) {
-    if (v && l->c[i])
-      v[j++] = l->v[i];
-    else if (l->v[i].p)
-      l->pops->pfree(&l->v[i], l);
-  }
-
-  if (l->qq.p) {
-    if (v)
-      v[j++] = l->qq;
-    else
-      l->pops->pfree(&l->qq, l);
-  }
-
-  xfree(l->v);
-  l->v = v;
-
-  /* --- Free other resources --- */
-
-  xfree(l->c);
-  dstr_destroy(&l->d);
-
-  /* --- Done --- */
-
-  return (PGEN_DONE);
-}
-
-/* --- @limlee_step@ --- */
-
-int limlee_step(int rq, pgen_event *ev, void *p)
-{
-  limlee_stepctx *l = p;
-  int rc;
-
-  switch (rq) {
-    case PGEN_BEGIN:
-      if ((rc = init(ev, l)) != PGEN_TRY)
-       return (rc);
-    case PGEN_TRY:
-      return (next(rq, ev, l));
-    case PGEN_DONE:
-      return (done(ev, l));
-  }
-  return (PGEN_ABORT);
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @limlee@ --- *
- *
- * Arguments:  @const char *name@ = pointer to name root
- *             @mp *d@ = pointer to destination integer
- *             @mp *newp@ = how to generate factor primes
- *             @unsigned ql@ = size of individual factors
- *             @unsigned pl@ = size of large prime
- *             @grand *r@ = a random number source
- *             @unsigned on@ = number of outer attempts to make
- *             @pgen_proc *oev@ = outer event handler function
- *             @void *oec@ = argument for the outer event handler
- *             @pgen_proc *iev@ = inner event handler function
- *             @void *iec@ = argument for the inner event handler
- *             @size_t *nf@, @mp ***f@ = output array for factors
- *
- * Returns:    A Lim-Lee prime, or null if generation failed.
- *
- * Use:                Generates Lim-Lee primes.  A Lim-Lee prime %$p$% is one which
- *             satisfies %$p = 2 \prod_i q_i + 1$%, where all of the %$q_i$%
- *             are large enough to resist square-root discrete log
- *             algorithms.
- *
- *             If we succeed, and @f@ is non-null, we write the array of
- *             factors chosen to @f@ for the benefit of the caller.
- */
-
-mp *limlee(const char *name, mp *d, mp *newp,
-          unsigned ql, unsigned pl, grand *r,
-          unsigned on, pgen_proc *oev, void *oec,
-          pgen_proc *iev, void *iec,
-          size_t *nf, mp ***f)
-{
-  limlee_stepctx l;
-  rabin rr;
-
-  l.f = 0; if (f) l.f |= LIMLEE_KEEPFACTORS;
-  l.newp = newp;
-  l.pl = pl; l.ql = ql;
-  l.pops = 0;
-  l.iev = iev;
-  l.iec = iec;
-  l.r = r;
-
-  d = pgen(name, d, 0, oev, oec, on, limlee_step, &l,
-          rabin_iters(pl), pgen_test, &rr);
-
-  if (d && f) {
-    mp **v;
-    size_t i;
-    v = xmalloc(l.nf * sizeof(mp *));
-    for (i = 0; i < l.nf; i++)
-      v[i] = l.v[i].p;
-    xfree(l.v);
-    *f = v;
-    *nf = l.nf;
-  }
-
-  return (d);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/limlee.h b/limlee.h
deleted file mode 100644 (file)
index 8b03bc3..0000000
--- a/limlee.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*-c-*-
- *
- * $Id: limlee.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate Lim-Lee primes
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_LIMLEE_H
-#define CATACOMB_LIMLEE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_PGEN_H
-#  include "pgen.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct limlee_factor {
-  mp *p;                               /* The actual prime */
-  unsigned tag;                                /* A tag, usable by the generator */
-  void *more;                          /* Pointer to more data */
-} limlee_factor;
-
-typedef struct limlee_stepctx {
-
-  /* --- To be initialized by the caller --- */
-
-  unsigned f;                          /* Various useful flags */
-  mp *newp;                            /* Initial valid for new primes */
-  unsigned ql, pl;                     /* Size of factors and result */
-  const struct limlee_primeops *pops;  /* Pointer to generator ops */
-  void *pc;                            /* Context ptr for generator ops */
-  pgen_proc *iev;                      /* Event handler for inner @pgen@ */
-  void *iec;                           /* Context for inner @pgen@ */
-  grand *r;                            /* Random number generator */
-
-  /* --- Output values --- */
-
-  size_t nf;                           /* Number of factors wanted */
-  limlee_factor *v;                    /* Vector of factors */
-
-  /* --- Maintained internally --- */
-
-  octet *c;                            /* Combination byte-flag vector */
-  unsigned long seq;                   /* Sequence number for primes */
-  size_t poolsz;                       /* Size of the small-prime pool */
-  dstr d;                              /* String for subprime name */
-  limlee_factor qq;                    /* Big prime to pick up slack */
-
-} limlee_stepctx;
-
-typedef struct limlee_primeops {
-  void (*pgen)(limlee_factor */*f*/, unsigned /*pl*/, limlee_stepctx */*l*/);
-  void (*pfree)(limlee_factor */*f*/, limlee_stepctx */*l*/);
-} limlee_primeops;
-
-/* --- Flags --- */
-
-#define LIMLEE_KEEPFACTORS 1u
-
-/*----- The Lim-Lee stepper function --------------------------------------*/
-
-extern pgen_proc limlee_step;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @limlee@ --- *
- *
- * Arguments:  @const char *name@ = pointer to name root
- *             @mp *d@ = pointer to destination integer
- *             @mp *newp@ = how to generate factor primes
- *             @unsigned ql@ = size of individual factors
- *             @unsigned pl@ = size of large prime
- *             @grand *r@ = a random number source
- *             @unsigned on@ = number of outer attempts to make
- *             @pgen_proc *oev@ = outer event handler function
- *             @void *oec@ = argument for the outer event handler
- *             @pgen_proc *iev@ = inner event handler function
- *             @void *iec@ = argument for the inner event handler
- *             @size_t *nf@, @mp ***f@ = output array for factors
- *
- * Returns:    A Lim-Lee prime, or null if generation failed.
- *
- * Use:                Generates Lim-Lee primes.  A Lim-Lee prime %$p$% is one which
- *             satisfies %$p = 2 \prod_i q_i + 1$%, where all of the %$q_i$%
- *             are large enough to resist square-root discrete log
- *             algorithms.
- *
- *             If we succeed, and @f@ is non-null, we write the array of
- *             factors chosen to @f@ for the benefit of the caller.
- */
-
-extern mp *limlee(const char */*name*/, mp */*d*/, mp */*newp*/,
-                 unsigned /*ql*/, unsigned /*pl*/, grand */*r*/,
-                 unsigned /*on*/, pgen_proc */*oev*/, void */*oec*/,
-                 pgen_proc */*iev*/, void */*iec*/,
-                 size_t */*nf*/, mp ***/*f*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/lmem.c b/lmem.c
deleted file mode 100644 (file)
index a7033d0..0000000
--- a/lmem.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Locked memory allocation (Unix-specific)
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#ifdef HAVE_MLOCK
-#  include <sys/mman.h>
-#endif
-
-#include <mLib/arena.h>
-#include <mLib/dstr.h>
-#include <mLib/sub.h>
-
-#include "lmem.h"
-
-/*----- Arena operations --------------------------------------------------*/
-
-static void *aalloc(arena *a, size_t sz) { return l_alloc((lmem *)a, sz); }
-static void afree(arena *a, void *p) { l_free((lmem *)a, p); }
-static void apurge(arena *a) { l_purge((lmem *)a); }
-
-static const arena_ops l_ops = { aalloc, arena_fakerealloc, afree, apurge };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @l_init@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *             @size_t sz@ = size of locked memory area requested
- *
- * Returns:    Zero if everything is fine, @+1@ if some insecure memory was
- *             allocated, and @-1@ if everything went horribly wrong.
- *
- * Use:                Initializes the locked memory manager.  This function is safe
- *             to call in a privileged program; privileges should usually be
- *             dropped after allocating the locked memory block.
- *
- *             You must call @sub_init@ before allocating locked memory
- *             buffers.
- */
-
-int l_init(lmem *lm, size_t sz)
-{
-  char *p;
-  int rc = 0;
-  l_node *l;
-
-  /* --- Preliminaries --- */
-
-  lm->a.ops = &l_ops;
-  lm->err = 0;
-  lm->f = 0;
-
-  /* --- Try making a secure locked passphrase buffer --- *
-   *
-   * Drop privileges before emitting diagnostic messages.
-   */
-
-#ifdef HAVE_MLOCK
-
-  /* --- Memory-map a page from somewhere --- */
-
-#  ifdef MAP_ANON
-  p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
-#  else
-  {
-    int fd;
-    if ((fd = open("/dev/zero", O_RDWR)) >= 0) {
-      p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
-      close(fd);
-    }
-  }
-#  endif
-
-  /* --- Lock the page in memory --- *
-   *
-   * Why does @mmap@ return such a stupid result if it fails?
-   */
-
-  if (p == 0 || p == MAP_FAILED) {
-    lm->emsg = "couldn't map locked memory area: %s";
-    lm->err = errno;
-    p = 0;
-  } else if (mlock(p, sz)) {
-    lm->emsg = "error locking memory area: %s";
-    lm->err = errno;
-    munmap(p, sz);
-    p = 0;
-  } else
-    lm->f |= LF_LOCKED;
-
-#endif
-
-  /* --- Make a standard passphrase buffer --- */
-
-#ifdef HAVE_MLOCK
-  if (!p)
-#else
-  lm->err = 0;
-  lm->emsg = "locked memory not available on this system";
-#endif
-  {
-    if ((p = malloc(sz)) == 0) {
-      lm->emsg = "not enough standard memory!";
-      lm->err = ENOMEM;
-      return (-1);
-    }
-    rc = +1;
-  }
-
-  /* --- Initialize the buffer --- */
-
-  lm->sz = lm->free = sz;
-  lm->p = p;
-
-  /* --- Initialize the free list --- */
-
-  l = CREATE(l_node);
-  l->next = 0;
-  l->p = p;
-  l->sz = sz;
-  l->f = 0;
-  lm->l = l;
-
-  /* --- Done --- */
-
-  return (rc);
-}
-
-/* --- @l_alloc@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *             @size_t sz@ = size requested
- *
- * Returns:    Pointer to allocated memory.
- *
- * Use:                Allocates @sz@ bytes of locked memory.
- */
-
-void *l_alloc(lmem *lm, size_t sz)
-{
-  l_node *l;
-
-  sz = (sz + 3u) & ~3u;
-  for (l = lm->l; l; l = l->next) {
-    if (l->f & LF_ALLOC)
-      continue;
-    if (l->sz < sz)
-      continue;
-    l->f |= LF_ALLOC;
-    if (l->sz > sz) {
-      l_node *n = CREATE(l_node);
-      n->next = l->next;
-      n->p = l->p + sz;
-      n->sz = l->sz - sz;
-      l->sz = sz;
-      n->f = 0;
-      l->next = n;
-    }
-    assert(((void)"Locked buffer space has vanished", lm->free >= sz));
-    lm->free -= sz;
-    return (l->p);
-  }
-  return (0);
-}
-
-/* --- @l_free@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *             @void *p@ = pointer to block
- *
- * Returns:    ---
- *
- * Use:                Releases a block of locked memory.
- */
-
-void l_free(lmem *lm, void *p)
-{
-  l_node *l;
-  l_node *ll = 0;
-
-  for (l = lm->l; l; l = l->next) {
-    size_t sz;
-
-    /* --- If this isn't the block, skip it --- */
-
-    if (l->p != p) {
-      ll = l;
-      continue;
-    }
-    assert(((void)"Block is already free", l->f & LF_ALLOC));
-
-    /* --- Coalesce with adjacent free blocks --- */
-
-    l->f &= ~LF_ALLOC;
-    sz = l->sz;
-    memset(p, 0, sz);
-
-    if (ll && !(ll->f & LF_ALLOC)) {
-      assert(((void)"Previous block doesn't fit", ll->p + ll->sz == p));
-      ll->sz += sz;
-      ll->next = l->next;
-      DESTROY(l);
-      l = ll;
-    }
-
-    ll = l->next;
-    if (ll && !(ll->f & LF_ALLOC)) {
-      assert(((void)"Next block doesn't fit", ll->p == l->p + l->sz));
-      l->sz += ll->sz;
-      l->next = ll->next;
-      DESTROY(ll);
-    }
-
-    lm->free += sz;
-    assert(((void)"Free lunch", lm->free <= lm->sz));
-    return;
-  }
-  assert(((void)"Not a locked block", 0));
-}
-
-/* --- @l_purge@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *
- * Returns:    ---
- *
- * Use:                Purges all the free blocks in the buffer, and clears all of
- *             the locked memory.  Memory is not freed back to the system.
- */
-
-void l_purge(lmem *lm)
-{
-  l_node *l;
-
-  l = lm->l;
-  while (l) {
-    l_node *ll = l->next;
-    DESTROY(l);
-    l = ll;
-  }
-  memset(lm->p, 0, lm->sz);
-  l = CREATE(l_node);
-  l->next = 0;
-  l->p = lm->p;
-  l->sz = lm->sz;
-  l->f = 0;
-  lm->l = l;
-  lm->free = l->sz;
-}
-
-/* --- @l_destroy@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *
- * Returns:    ---
- *
- * Use:                Disposes of a locked memory arena permanently.
- */
-
-void l_destroy(lmem *lm)
-{
-  l_node *l;
-
-  l = lm->l;
-  while (l) {
-    l_node *ll = l->next;
-    DESTROY(l);
-    l = ll;
-  }
-  memset(lm->p, 0, lm->sz);
-
-#ifdef HAVE_MLOCK
-  if (lm->f & LF_LOCKED)
-    munmap(lm->p, lm->sz);
-  else
-#endif
-    free(lm->p); /*sic*/
-}
-
-/* --- @l_report@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *             @dstr *d@ = string to write the error message on
- *
- * Returns:    Zero if the buffer is fine, @+1@ if there was a problem
- *             getting locked memory but insecure stuff could be allocated,
- *             and @-1@ if not even insecure memory could be found.
- *
- * Use:                Returns a user-digestable explanation for the state of a
- *             locked memory buffer.  If the return code is zero, no message
- *             is emitted to the string @d@.
- */
-
-int l_report(lmem *lm, dstr *d)
-{
-  int rc;
-  if (lm->err)
-    dstr_putf(d, lm->emsg, strerror(lm->err));
-  if (!lm->p)
-    rc = -1;
-  else if (lm->err)
-    rc = +1;
-  else
-    rc = 0;
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/lmem.h b/lmem.h
deleted file mode 100644 (file)
index 65a31a8..0000000
--- a/lmem.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/* -*-c-*-
- *
- * $Id: lmem.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Locked memory allocation
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_LMEM_H
-#define CATACOMB_LMEM_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/arena.h>
-#include <mLib/dstr.h>
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- Block list --- *
- *
- * The block list is kept in normal memory, to avoid wasting precious locked
- * memory.  Entries are sorted into ascending address order to make
- * coalescing free blocks easier.  All blocks, free or not, are included in
- * the list.
- */
-
-typedef struct l_node {
-  struct l_node *next;                 /* Next free block in chain */
-  char *p;                             /* Pointer to the block */
-  size_t sz;                           /* Size of the block */
-  unsigned f;                          /* Various flags */
-} l_node;
-
-#define LF_ALLOC 1u
-
-/* --- Locked memory buffer state --- */
-
-typedef struct lmem {
-  arena a;                             /* Arena header block */
-  unsigned f;                          /* Various flags */
-  char *p;                             /* Pointer to locked buffer */
-  l_node *l;                           /* Pointer to block list */
-  size_t sz;                           /* Size of locked buffer */
-  size_t free;                         /* Size of free area */
-  int err; char *emsg;                 /* Error indicators */
-} lmem;
-
-#define LF_LOCKED 1u
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @l_init@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *             @size_t sz@ = size of locked memory area requested
- *
- * Returns:    Zero if everything is fine, @+1@ if some insecure memory was
- *             allocated, and @-1@ if everything went horribly wrong.
- *
- * Use:                Initializes the locked memory manager.  This function is safe
- *             to call in a privileged program; privileges should usually be
- *             dropped after allocating the locked memory block.
- *
- *             You must call @sub_init@ before allocating locked memory
- *             buffers.
- */
-
-extern int l_init(lmem */*lm*/, size_t /*sz*/);
-
-/* --- @l_alloc@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *             @size_t sz@ = size requested
- *
- * Returns:    Pointer to allocated memory.
- *
- * Use:                Allocates @sz@ bytes of locked memory.
- */
-
-extern void *l_alloc(lmem */*lm*/, size_t /*sz*/);
-
-/* --- @l_free@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *             @void *p@ = pointer to block
- *
- * Returns:    ---
- *
- * Use:                Releases a block of locked memory.
- */
-
-extern void l_free(lmem */*lm*/, void */*p*/);
-
-/* --- @l_purge@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *
- * Returns:    ---
- *
- * Use:                Purges all the free blocks in the buffer, and clears all of
- *             the locked memory.  Memory is not freed back to the system.
- */
-
-extern void l_purge(lmem */*lm*/);
-
-/* --- @l_destroy@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *
- * Returns:    ---
- *
- * Use:                Disposes of a locked memory arena permanently.
- */
-
-extern void l_destroy(lmem */*lm*/);
-
-/* --- @l_report@ --- *
- *
- * Arguments:  @lmem *lm@ = pointer to locked memory descriptor
- *             @dstr *d@ = string to write the error message on
- *
- * Returns:    Zero if the buffer is fine, @+1@ if there was a problem
- *             getting locked memory but insecure stuff could be allocated,
- *             and @-1@ if not even insecure memory could be found.
- *
- * Use:                Returns a user-digestable explanation for the state of a
- *             locked memory buffer.  If the return code is zero, no message
- *             is emitted to the string @d@.
- */
-
-extern int l_report(lmem */*lm*/, dstr */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
index f13c7c1..a811331 100644 (file)
@@ -1,7 +1,5 @@
 %%% -*-latex-*-
 %%%
-%%% $Id: catacomb.tex,v 1.3 2004/04/08 01:36:15 mdw Exp $
-%%%
 %%% Catacomb manual
 %%%
 %%% (c) 1999 Straylight/Edgeware
diff --git a/mars-mktab.c b/mars-mktab.c
deleted file mode 100644 (file)
index 9726ed9..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mars-mktab.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate the MARS S-box table
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "sha.h"
-
-/*----- SHA-1 (quick version) ---------------------------------------------*/
-
-/* --- @sha_compress@ --- *
- *
- * Arguments:  @sha_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                SHA-1 compression function.
- */
-
-void sha_compress(sha_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d, e;
-  uint32 buf[80];
-
-  /* --- Fetch the chaining variables --- */
-
-  a = ctx->a;
-  b = ctx->b;
-  c = ctx->c;
-  d = ctx->d;
-  e = ctx->e;
-
-  /* --- Fetch and expand the buffer contents --- */
-
-  {
-    int i;
-    const octet *p;
-
-    for (i = 0, p = sbuf; i < 16; i++, p += 4)
-      buf[i] = LOAD32(p);
-    for (i = 16; i < 80; i++) {
-      uint32 x = buf[i - 3] ^ buf[i - 8] ^ buf[i - 14] ^ buf[i - 16];
-      buf[i] = ROL32(x, 1);
-    }
-  }
-
-  /* --- 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) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-
-#define T(v, w, x, y, z, i, f, k) do {                                 \
-  uint32 _x;                                                           \
-  z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k;                       \
-  w = ROR32(w, 2);                                                     \
-  _x = v; v = z; z = y; y = x; x = w; w = _x;                          \
-} while (0)
-
-#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999)
-#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1)
-#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc)
-#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6)
-
-  /* --- The main compression function --- */
-
-  {
-    unsigned i;
-    for (i = 0; i < 20; i++)
-      FF(a, b, c, d, e, i);
-    for (i = 20; i < 40; i++)
-      GG(a, b, c, d, e, i);
-    for (i = 40; i < 60; i++)
-      HH(a, b, c, d, e, i);
-    for (i = 60; i < 80; i++)
-      II(a, b, c, d, e, i);
-  }
-
-  ctx->a += a;
-  ctx->b += b;
-  ctx->c += c;
-  ctx->d += d;
-  ctx->e += e;
-}
-
-/* --- @sha_init@ --- *
- *
- * Arguments:  @sha_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void sha_init(sha_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;
-}
-
-/* --- @sha_hash@ --- *
- *
- * Arguments:  @sha_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 sha_hash(sha_ctx *ctx, const void *buf, size_t sz)
-{
-  sha_ctx *_bctx = (ctx);
-  size_t _bsz = (sz);
-  const octet *_bbuf = (octet *) (buf);
-
-  {
-    uint32 _l = ((uint32) ((_bsz) & MASK32));
-    uint32 _h = ((_bsz & ~MASK32) >> 16) >> 16;
-    _bctx->nh += _h;
-    _bctx->nl += _l;
-    if (_bctx->nl < _l || _bctx->nl & ~MASK32)
-      _bctx->nh++;
-  }
-  if (_bctx->off + _bsz < SHA_BUFSZ) {
-    memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz);
-    _bctx->off += _bsz;
-  } else {
-    if (_bctx->off) {
-      size_t s = SHA_BUFSZ - _bctx->off;
-      memcpy(_bctx->buf + _bctx->off, _bbuf, s);
-      sha_compress(_bctx, _bctx->buf);
-      _bsz -= s;
-      _bbuf += s;
-    }
-    while (_bsz >= SHA_BUFSZ) {
-      sha_compress(_bctx, _bbuf);
-      _bsz -= SHA_BUFSZ;
-      _bbuf += SHA_BUFSZ;
-    }
-    if (_bsz)
-      memcpy(_bctx->buf, _bbuf, _bsz);
-    _bctx->off = _bsz;
-  }
-}
-
-/* --- @sha_done@ --- *
- *
- * Arguments:  @sha_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void sha_done(sha_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  {
-    sha_ctx *_pctx = (ctx);
-    _pctx->buf[_pctx->off] = 0x80;
-    _pctx->off++;
-    if (_pctx->off > SHA_BUFSZ - 8) {
-      if (_pctx->off < SHA_BUFSZ)
-       memset(_pctx->buf + _pctx->off, 0, SHA_BUFSZ - _pctx->off);
-      sha_compress(_pctx, _pctx->buf);
-      memset(_pctx->buf, 0, SHA_BUFSZ - 8);
-    } else
-      memset(_pctx->buf + _pctx->off, 0, SHA_BUFSZ - _pctx->off - 8);
-  }
-  STORE32(ctx->buf + SHA_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3));
-  STORE32(ctx->buf + SHA_BUFSZ - 4, ctx->nl << 3);
-  sha_compress(ctx, ctx->buf);
-  STORE32(p +  0, ctx->a);
-  STORE32(p +  4, ctx->b);
-  STORE32(p +  8, ctx->c);
-  STORE32(p + 12, ctx->d);
-  STORE32(p + 16, ctx->e);
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-static void mks(uint32 c3, uint32 *s)
-{
-  octet ibuf[16], obuf[20];
-  sha_ctx h;
-  unsigned i, j;
-
-  STORE32_L(ibuf +  4, 0xb7e15162);
-  STORE32_L(ibuf +  8, 0x243f6a88);
-  STORE32_L(ibuf + 12, c3);
-
-  for (i = 0; i < 510; i += 5) {
-    STORE32_L(ibuf, i);
-    sha_init(&h);
-    sha_hash(&h, ibuf, sizeof(ibuf));
-    sha_done(&h, obuf);
-    for (j = 0; j < 5; j++)
-      *s++ = LOAD32_L(obuf + (4 * j));
-  }
-  STORE32_L(ibuf, i);
-  sha_init(&h);
-  sha_hash(&h, ibuf, sizeof(ibuf));
-  sha_done(&h, obuf);
-  for (j = 0; i < 512; j++, i++)
-    *s++ = LOAD32_L(obuf + (4 * j));
-}
-
-static void fix(uint32 *s)
-{
-  unsigned i, j, n;
-  uint32 d;
-
-  for (i = 0; i < 512; i++) {
-    for (j = i & ~255u; j < ((i + 255) & ~255u); j++) {
-      if (i == j)
-       continue;
-      d = s[i] ^ s[j];
-      n = 0;
-      if (!(d & 0xff000000)) n++;
-      if (!(d & 0x00ff0000)) n++;
-      if (!(d & 0x0000ff00)) n++;
-      if (!(d & 0x000000ff)) n++;
-      if (n >= 2) {
-       s[i] = U32(s[i] * 3);
-       goto fixed;
-      }
-    }
-  fixed:;
-  }
-}
-
-int main(void)
-{
-  uint32 s[512];
-  unsigned i;
-
-  mks(0x02917d59, s);
-  fix(s);
-
-  puts("\
-/* -*-c-*-\n\
- *\n\
- * MARS tables [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_MARS_TAB_H\n\
-#define CATACOMB_MARS_TAB_H\n\
-");
-
-  fputs("\
-/* --- The S-box --- */\n\
-\n\
-#define MARS_S {                                                       \\\n\
-  ", stdout);
-  for (i = 0; i < 512; i++) {
-    printf("0x%08lx", (unsigned long)s[i]);
-    if (i == 511)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 4 == 3)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  puts("#endif");
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mars.c b/mars.c
deleted file mode 100644 (file)
index 9240083..0000000
--- a/mars.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mars.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The MARS block cipher
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "mars.h"
-#include "mars-tab.h"
-#include "paranoia.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet mars_keysz[] = { KSZ_RANGE, MARS_KEYSZ, 0, 56, 4 };
-
-/*----- Useful tables -----------------------------------------------------*/
-
-static const uint32 s[512] = MARS_S;
-#define s0 (s +          0)
-#define s1 (s + 256)
-#define bb (s + 265)
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mars_init@ --- *
- *
- * Arguments:  @mars_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a MARS key buffer.  MARS accepts key sizes
- *             between 128 and 448 bits which are a multiple of 32 bits.
- */
-
-void mars_init(mars_ctx *k, const void *buf, size_t sz)
-{
-  uint32 t[15];
-  uint32 *kk = k->k;
-  const octet *p;
-  unsigned i, j, ii;
-
-  KSZ_ASSERT(mars, sz);
-
-  /* --- Copy the key into the temporary buffer --- */
-
-  p = buf;
-  for (i = 0; i < sz/4; i++) {
-    t[i] = LOAD32_L(p);
-    p += 4;
-  }
-  t[i++] = sz/4;
-  for (; i < 15; i++)
-    t[i] = 0;
-
-  /* --- Now spit out the actual key material --- */
-
-  for (j = 0; j < 4; j++) {
-    uint32 x;
-
-    /* --- Do the linear mixing stage --- */
-
-    for (i = 0; i < 15; i++) {
-      x = t[(i + 8)%15] ^ t[(i + 13)%15];
-      t[i] ^= ROL32(x, 3) ^ ((i << 2) | j);
-    }
-
-    /* --- Now do the Feistel stirring stage --- */
-
-    x = t[14];
-    for (ii = 0; ii < 4; ii++) {
-      for (i = 0; i < 15; i++) {
-       x = t[i] + s[x & 511u];
-       t[i] = x = ROL32(x, 9);
-      }
-    }
-
-    /* --- And spit out the key material --- */
-
-    for (i = 0; i < 10; i++)
-      *kk++ = t[(4 * i)%15];
-  }
-
-  /* --- Finally, fix up the multiplicative entries --- */
-
-  for (i = 5; i < 37; i += 2) {
-    uint32 w, m, x;
-    j = k->k[i] & 3u;
-    w = k->k[i] | 3u;
-
-    /* --- Compute the magic mask value --- */
-
-    m = 0;
-    for (ii = 0; ii <= 22; ii++) {
-      x = w >> ii;
-      if ((x & 0x3ff) == 0x3ff || (x & 0x3ff) == 0)
-       m |= 0x3ff << ii;
-    }
-    m &= ~(((w ^ (w << 1)) | (w ^ (w >> 1))) | 0x80000003);
-
-    /* --- Add in the bias entry to fix up the key --- */
-
-    x = ROL32(bb[j], k->k[i - 1]);
-    k->k[i] = w ^ (x & m);
-  }
-}
-
-/* --- @mars_eblk@, @mars_dblk@ --- *
- *
- * Arguments:  @const mars_ctx *k@ = pointer to key block
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define KADD(k, a, b, c, d)  a += *k++, b += *k++, c += *k++, d += *k++
-#define KSUB(k, a, b, c, d)  a -= *k++, b -= *k++, c -= *k++, d -= *k++
-#define IKADD(k, a, b, c, d) d += *--k, c += *--k, b += *--k, a += *--k
-#define IKSUB(k, a, b, c, d) d -= *--k, c -= *--k, b -= *--k, a -= *--k
-
-#define MIX(a, b, c, d) do {                                           \
-  b ^= s0[(a >>         0) & 0xff];                                            \
-  b += s1[(a >>         8) & 0xff];                                            \
-  c += s0[(a >> 16) & 0xff];                                           \
-  d ^= s1[(a >> 24) & 0xff];                                           \
-  a = ROL32(a, 8);                                                     \
-} while (0)
-
-#define IMIX(a, b, c, d) do {                                          \
-  a = ROR32(a, 8);                                                     \
-  d ^= s1[(a >> 24) & 0xff];                                           \
-  c -= s0[(a >> 16) & 0xff];                                           \
-  b -= s1[(a >>         8) & 0xff];                                            \
-  b ^= s0[(a >>         0) & 0xff];                                            \
-} while (0)
-
-#define E(x, y, z, k, a) do {                                          \
-  uint32 kx = *k++, ky = *k++;                                         \
-  y = a + kx;                                                          \
-  a = ROL32(a, 13); z = a * ky; z = ROL32(z, 5);                       \
-  x = s[y & 511u] ^ z; y = ROL32(y, z);                                        \
-  z = ROL32(z, 5); x ^= z; x = ROL32(x, z);                            \
-} while (0)
-
-#define IE(x, y, z, k, a) do {                                         \
-  uint32 ky = *--k, kx = *--k;                                         \
-  z = a * ky;                                                          \
-  a = ROR32(a, 13); y = a + kx; z = ROL32(z, 5);                       \
-  x = s[y & 511u] ^ z; y = ROL32(y, z);                                        \
-  z = ROL32(z, 5); x ^= z; x = ROL32(x, z);                            \
-} while (0)
-
-#define ROUND(k, a, b, c, d) do {                                      \
-  uint32 x, y, z;                                                      \
-  E(x, y, z, k, a);                                                    \
-  b += x; c += y; d ^= z;                                              \
-} while (0)
-
-#define IROUND(k, a, b, c, d) do {                                     \
-  uint32 x, y, z;                                                      \
-  IE(x, y, z, k, a);                                                   \
-  b -= x; c -= y; d ^= z;                                              \
-} while (0)
-
-void mars_eblk(const mars_ctx *k, const uint32 *src, uint32 *dst)
-{
-  uint32 a, b, c, d;
-  const uint32 *kk = k->k;
-
-  a = src[0], b = src[1], c = src[2], d = src[3];
-  KADD(kk, a, b, c, d);
-
-  MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c;
-  MIX(c, d, a, b); MIX(d, a, b, c);
-  MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c;
-  MIX(c, d, a, b); MIX(d, a, b, c);
-
-  ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a);
-  ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c);
-  ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a);
-  ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c);
-
-  ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c);
-  ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a);
-  ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c);
-  ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a);
-
-  IMIX(a, d, c, b); IMIX(b, a, d, c);
-  c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a);
-  IMIX(a, d, c, b); IMIX(b, a, d, c);
-  c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a);
-
-  KSUB(kk, a, b, c, d);
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-}
-
-void mars_dblk(const mars_ctx *k, const uint32 *src, uint32 *dst)
-{
-  uint32 a, b, c, d;
-  const uint32 *kk = k->k + 40;
-
-  a = src[0], b = src[1], c = src[2], d = src[3];
-  IKADD(kk, a, b, c, d);
-
-  MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b;
-  MIX(b, a, d, c); MIX(a, d, c, b);
-  MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b;
-  MIX(b, a, d, c); MIX(a, d, c, b);
-
-  IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d);
-  IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b);
-  IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d);
-  IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b);
-
-  IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b);
-  IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d);
-  IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b);
-  IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d);
-
-  IMIX(d, a, b, c); IMIX(c, d, a, b);
-  b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d);
-  IMIX(d, a, b, c); IMIX(c, d, a, b);
-  b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d);
-
-  IKSUB(kk, a, b, c, d);
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-}
-
-BLKC_TEST(MARS, mars)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mars.h b/mars.h
deleted file mode 100644 (file)
index f32f9f4..0000000
--- a/mars.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mars.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The MARS block cipher
- *
- * (c) 2001 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.
- */
-
-/*----- Notes on the MARS block cipher ------------------------------------*
- *
- * MARS was IBM's submission to the AES contest.  It was designed by a number
- * of clever people at the T. J. Watson labs, and made it to the second round
- * of the contest.  Unfortunately, MARS is rather messy.  There are some
- * awkward corner cases in the key schedule algorithm, for example, that show
- * up very rarely.
- */
-
-#ifndef CATACOMB_MARS_H
-#define CATACOMB_MARS_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define MARS_BLKSZ 16
-#define MARS_KEYSZ 32
-#define MARS_CLASS (N, L, 128)
-
-extern const octet mars_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct mars_ctx {
-  uint32 k[40];
-} mars_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mars_init@ --- *
- *
- * Arguments:  @mars_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a MARS key buffer.  MARS accepts key sizes
- *             between 128 and 448 bits which are a multiple of 32 bits.
- */
-
-extern void mars_init(mars_ctx */*k*/,
-                     const void */*buf*/, size_t /*sz*/);
-
-/* --- @mars_eblk@, @mars_dblk@ --- *
- *
- * Arguments:  @const mars_ctx *k@ = pointer to key block
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void mars_eblk(const mars_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-
-extern void mars_dblk(const mars_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/math/Makefile.am b/math/Makefile.am
new file mode 100644 (file)
index 0000000..5bb546c
--- /dev/null
@@ -0,0 +1,392 @@
+### -*-makefile-*-
+###
+### Build script for mathematical infrastructure
+###
+### (c) 2013 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.
+
+include $(top_srcdir)/vars.am
+
+noinst_LTLIBRARIES      = libmath.la
+libmath_la_SOURCES      =
+nodist_libmath_la_SOURCES =
+libmath_la_LIBADD       =
+
+TEST_LIBS               = libmath.la
+
+###--------------------------------------------------------------------------
+### Main multiprecision integer library.
+
+## This library is unfortunately intertwined with some of the code generation
+## programs, so we must be rather careful.  The important bits of the maths
+## library needed by these programs is separated out into `libmpbase'.  There
+## is work going on to fix this unpleasant situation by generating the
+## relevant files from Python scripts rather than C programs, using
+## information gathered by `configure'.
+noinst_LTLIBRARIES     += libmpbase.la
+libmath_la_LIBADD      += libmpbase.la
+libmpbase_la_LIBADD     = $(mLib_LIBS)
+libmpbase_la_SOURCES    =
+$(libmpbase_la_OBJECTS): mptypes.h
+
+## Additional buffer I/O functions for mathematical objects.
+pkginclude_HEADERS     += buf.h
+libmath_la_SOURCES     += buf.c
+
+## Infrastructure for fast exponentiation.
+pkginclude_HEADERS     += exp.h
+libmath_la_SOURCES     += exp.c
+
+## Main user-visible multiprecision arithmetic.
+pkginclude_HEADERS     += mp.h
+libmpbase_la_SOURCES   += mp-arith.c
+TESTS                  += mp-arith.$t
+libmpbase_la_SOURCES   += mp-const.c
+libmath_la_SOURCES     += mp-exp.c mp-exp.h
+libmath_la_SOURCES     += mp-gcd.c
+TESTS                  += mp-gcd.$t
+libmpbase_la_SOURCES   += mp-io.c
+libmath_la_SOURCES     += mp-jacobi.c
+TESTS                  += mp-jacobi.$t
+libmpbase_la_SOURCES   += mp-mem.c
+libmpbase_la_SOURCES   += mp-misc.c
+libmath_la_SOURCES     += mp-modexp.c
+TESTS                  += mp-modexp.$t
+libmath_la_SOURCES     += mp-modsqrt.c
+TESTS                  += mp-modsqrt.$t
+libmath_la_SOURCES     += mp-sqrt.c
+TESTS                  += mp-sqrt.$t
+libmath_la_SOURCES     += mp-test.c
+EXTRA_DIST             += t/mp
+
+## Computing Fibonacci numbers.
+pkginclude_HEADERS     += mp-fibonacci.h
+libmath_la_SOURCES     += mp-fibonacci.c
+TESTS                  += mp-fibonacci.$t
+
+## Special memory allocation for multiprecision integers.
+pkginclude_HEADERS     += mparena.h
+libmpbase_la_SOURCES   += mparena.c
+
+## Barrett reduction, an efficient method for modular reduction.
+pkginclude_HEADERS     += mpbarrett.h
+libmath_la_SOURCES     += mpbarrett.c
+TESTS                  += mpbarrett.$t
+libmath_la_SOURCES     += mpbarrett-exp.c mpbarrett-mexp.c mpbarrett-exp.h
+TESTS                  += mpbarrett-exp.$t mpbarrett-mexp.$t
+TESTS                  += mpbarrett.$t
+EXTRA_DIST             += t/mpbarrett
+
+## Solving congruences using the Chinese Remainder Theorem.
+pkginclude_HEADERS     += mpcrt.h
+libmath_la_SOURCES     += mpcrt.c
+TESTS                  += mpcrt.$t
+EXTRA_DIST             += t/mpcrt
+
+## Conversions between machine-native and multiprecision integers.
+pkginclude_HEADERS     += mpint.h
+libmath_la_SOURCES     += mpint.c
+TESTS                  += mpint.$t
+EXTRA_DIST             += t/mpint
+
+## Table of upper and lower limits of various types of machine integers, as
+## multiprecision integers.
+nodist_archinclude_HEADERS += mplimits.h
+nodist_libmath_la_SOURCES += mplimits.c
+CLEANFILES             += mplimits.h mplimits.c
+noinst_PROGRAMS                += genlimits
+genlimits_LDADD                 = libmpbase.la
+mplimits.c: genlimits$e
+       $(AM_V_GEN)./genlimits c >mplimits.c.new && \
+               mv mplimits.c.new mplimits.c
+mplimits.h: genlimits$e
+       $(AM_V_GEN)./genlimits h >mplimits.h.new && \
+               mv mplimits.h.new mplimits.h
+$(genlimits_OBJECTS): mptypes.h
+mplimits.lo: mplimits.h
+
+## Montgomery reduction, a clever method for modular arithmetic.
+pkginclude_HEADERS     += mpmont.h
+libmath_la_SOURCES     += mpmont.c
+TESTS                  += mpmont.$t
+libmath_la_SOURCES     += mpmont-exp.c mpmont-mexp.c mpmont-exp.h
+TESTS                  += mpmont-exp.$t mpmont-mexp.$t
+EXTRA_DIST             += t/mpmont
+
+## Efficient multiplication of many small numbers.
+pkginclude_HEADERS     += mpmul.h
+libmath_la_SOURCES     += mpmul.c
+TESTS                  += mpmul.$t
+
+## Generating random numbers.
+pkginclude_HEADERS     += mprand.h
+libmath_la_SOURCES     += mprand.c
+
+## Efficient reduction modulo numbers with conveninent binary
+## representations.
+pkginclude_HEADERS     += mpreduce.h
+libmath_la_SOURCES     += mpreduce.c mpreduce-exp.h
+TESTS                  += mpreduce.$t
+EXTRA_DIST             += t/mpreduce
+
+## Iteratiion over the bianry representation of multiprecision integers.
+pkginclude_HEADERS     += mpscan.h
+libmpbase_la_SOURCES   += mpscan.c
+
+## Conversion between multiprecision integers and their textual
+## representations.
+pkginclude_HEADERS     += mptext.h
+libmpbase_la_SOURCES   += mptext.c
+TESTS                  += mptext.$t
+libmath_la_SOURCES     += mptext-dstr.c
+libmath_la_SOURCES     += mptext-file.c
+libmath_la_SOURCES     += mptext-len.c
+libmpbase_la_SOURCES   += mptext-string.c
+EXTRA_DIST             += t/mptext
+
+## Basic types used in the representation of multiprecision integers.
+nodist_archinclude_HEADERS += mptypes.h
+BUILT_SOURCES          += mptypes.h
+CLEANFILES             += mptypes.h
+noinst_PROGRAMS                += mptypes
+mptypes.h: mptypes$e
+       $(AM_V_GEN)./mptypes >mptypes.h.new && mv mptypes.h.new mptypes.h
+
+## Low-level multiprecision arithmetic.
+pkginclude_HEADERS     += mpx.h bitops.h mpw.h
+libmpbase_la_SOURCES   += mpx.c
+TESTS                  += mpx.$t
+libmpbase_la_SOURCES   += karatsuba.h mpx-kmul.c mpx-ksqr.c
+TESTS                  += mpx-kmul.$t mpx-ksqr.$t
+noinst_PROGRAMS                += bittest
+TESTS                  += bittest
+EXTRA_DIST             += t/mpx
+
+## A quick-and-dirty parser, used for parsing descriptions of groups, fields,
+## etc.
+pkginclude_HEADERS     += qdparse.h
+libmath_la_SOURCES     += qdparse.c
+
+## Pollard's `rho' algorithm for determining discrete logarithms.
+pkginclude_HEADERS     += rho.h
+libmath_la_SOURCES     += rho.c
+TESTS                  += rho.$t
+
+###--------------------------------------------------------------------------
+### Prime number checking, searching, and related jobs.
+
+## Generating Lim--Lee groups, i.e., unit groups of finite fields without
+## small subgroups (except for the obvious ones).
+pkginclude_HEADERS     += limlee.h
+libmath_la_SOURCES     += limlee.c
+
+## A table of small prime numbers.
+nodist_pkginclude_HEADERS += primetab.h
+nodist_libmath_la_SOURCES += primetab.c
+CLEANFILES             += primetab.h primetab.c
+BUILT_SOURCES          += primetab.h primetab.c
+noinst_PROGRAMS                += genprimes
+genprimes_LDADD                 = $(mLib_LIBS)
+primetab.h: primetab.c
+primetab.c: genprimes$e
+       $(AM_V_GEN)./genprimes -hprimetab.h -cprimetab.c \
+               -sCATACOMB_PRIMETAB_H \
+               -n256 -t"unsigned short" -iprimetab
+
+## Filtering candidate prime numbers by checking for small factors
+## efficiently.
+pkginclude_HEADERS     += pfilt.h
+libmath_la_SOURCES     += pfilt.c
+
+## Generating prime numbers (and other kinds of numbers which need searching
+## for).
+pkginclude_HEADERS     += pgen.h
+libmath_la_SOURCES     += pgen.c
+libmath_la_SOURCES     += pgen-gcd.c
+libmath_la_SOURCES     += pgen-simul.c
+libmath_la_SOURCES     += pgen-stdev.c
+TESTS                  += pgen.$t
+EXTRA_DIST             += t/pgen
+
+## Finding primitive elements in finite fields.
+pkginclude_HEADERS     += prim.h
+libmath_la_SOURCES     += prim.c
+
+## Iterating over all prime numbers from a given starting point.
+pkginclude_HEADERS     += primeiter.h
+libmath_la_SOURCES     += primeiter.c
+TESTS                  += primeiter.$t
+primeiter.lo: wheel.h
+
+## The Miller--Rabin primality test.
+pkginclude_HEADERS     += rabin.h
+libmath_la_SOURCES     += rabin.c
+
+## Finding `strong' primes, using Gordon's algorithm.  Once upon a time,
+## products of these kinds of numbers were harder to factor.
+pkginclude_HEADERS     += strongprime.h
+libmath_la_SOURCES     += strongprime.c
+
+## A `wheel', used by the prime iteration machinery.
+nodist_pkginclude_HEADERS += wheel.h
+nodist_libmath_la_SOURCES += wheel.c
+CLEANFILES             += wheel.h wheel.c
+noinst_PROGRAMS                += genwheel
+genwheel_LDADD          = $(mLib_LIBS)
+wheel.h: wheel.c
+wheel.c: genwheel$e
+       $(AM_V_GEN)./genwheel -hwheel.h -cwheel.c \
+               -sCATACOMB_WHEEL_H \
+               -n5 -t"unsigned char" -iwheel
+
+###--------------------------------------------------------------------------
+### Binary polynomial arithmetic.
+
+## User-visible binary polynomial arithmetic.
+pkginclude_HEADERS     += gf.h
+libmath_la_SOURCES     += gf-arith.c
+TESTS                  += gf-arith.$t
+libmath_la_SOURCES     += gf-exp.c gf-exp.h
+libmath_la_SOURCES     += gf-gcd.c
+TESTS                  += gf-gcd.$t
+EXTRA_DIST             += t/gf
+
+## Low-level binary polynomial arithmetic.
+pkginclude_HEADERS     += gfx.h
+libmath_la_SOURCES     += gfx.c
+TESTS                  += gfx.$t
+libmath_la_SOURCES     += gfx-kmul.c
+TESTS                  += gfx-kmul.$t
+libmath_la_SOURCES     += gfx-sqr.c
+gfx-sqr.lo: gfx-sqr-tab.h
+TESTS                  += gfx-sqr.$t
+CLEANFILES             += gfx-sqr-tab.h
+noinst_PROGRAMS                += gfx-sqr-mktab
+gfx-sqr-tab.h: gfx-sqr-mktab$e
+       $(AM_V_GEN)./gfx-sqr-mktab >gfx-sqr-tab.h.in && \
+               mv gfx-sqr-tab.h.in gfx-sqr-tab.h
+EXTRA_DIST             += t/gfx
+
+## Conversions between normal and polynomial basis representations for binary
+## fields.
+pkginclude_HEADERS     += gfn.h
+libmath_la_SOURCES     += gfn.c
+TESTS                  += gfn.$t
+EXTRA_DIST             += t/gfn
+
+## Efficient reduction modulo sparse polynomials.
+pkginclude_HEADERS     += gfreduce.h
+libmath_la_SOURCES     += gfreduce.c gfreduce-exp.h
+TESTS                  += gfreduce.$t
+EXTRA_DIST             += t/gfreduce
+
+###--------------------------------------------------------------------------
+### Abstractions for various kinds of algebraic objects.
+
+## Abstract cyclic groups.
+pkginclude_HEADERS     += group.h group-guts.h
+libmath_la_SOURCES     += group-dstr.c
+libmath_la_SOURCES     += group-exp.c group-exp.h
+libmath_la_SOURCES     += group-file.c
+libmath_la_SOURCES     += group-parse.c
+libmath_la_SOURCES     += group-stdops.c
+libmath_la_SOURCES     += group-string.c
+libmath_la_SOURCES     += g-bin.c
+libmath_la_SOURCES     += g-prime.c
+libmath_la_SOURCES     += g-ec.c
+EXTRA_DIST             += group-test.c
+TESTS                  += group-test.$t
+EXTRA_DIST             += t/group
+
+## Abstract finite fields.
+pkginclude_HEADERS     += field.h field-guts.h
+libmath_la_SOURCES     += field.c
+libmath_la_SOURCES     += field-exp.c field-exp.h
+libmath_la_SOURCES     += field-parse.c
+libmath_la_SOURCES     += f-binpoly.c
+libmath_la_SOURCES     += f-niceprime.c
+libmath_la_SOURCES     += f-prime.c
+
+## Table of built-in binary fields.
+pkginclude_HEADERS     += bintab.h
+libmath_la_SOURCES     += bintab.c
+CLEANFILES             += bintab.c
+EXTRA_DIST             += bintab.in bin-gentab.awk
+bintab.c: bintab.in bin-gentab.awk mpdump$e
+       $(AM_V_GEN)awk -f $(srcdir)/bin-gentab.awk \
+               <$(srcdir)/bintab.in >bintab.c.new && \
+       mv bintab.c.new bintab.c
+
+## Table of built-in prime fields.
+pkginclude_HEADERS     += ptab.h
+libmath_la_SOURCES     += ptab.c
+CLEANFILES             += ptab.c
+EXTRA_DIST             += ptab.in p-gentab.awk
+ptab.c: ptab.in p-gentab.awk mpdump$e
+       $(AM_V_GEN)awk -f $(srcdir)/p-gentab.awk \
+               <$(srcdir)/ptab.in >ptab.c.new && \
+       mv ptab.c.new ptab.c
+
+## A utility for building multiprecision integer constants.
+noinst_PROGRAMS                += mpdump
+mpdump_LDADD            = libmpbase.la
+$(mpdump_OBJECTS): mptypes.h
+
+###--------------------------------------------------------------------------
+### Elliptic curve arithmetic.
+
+## Basic elliptic curve arithmetic.
+pkginclude_HEADERS     += ec.h ec-guts.h
+libmath_la_SOURCES     += ec.c
+libmath_la_SOURCES     += ec-exp.c ec-exp.h
+libmath_la_SOURCES     += ec-info.c
+TESTS                  += ec-info.$t
+libmath_la_SOURCES     += ec-bin.c
+TESTS                  += ec-bin.$t
+libmath_la_SOURCES     += ec-prime.c
+TESTS                  += ec-prime.$t
+EXTRA_DIST             += t/ec
+
+## The standard `raw' encoding (`EC2OSP') of elliptic curve points.
+pkginclude_HEADERS     += ec-raw.h
+libmath_la_SOURCES     += ec-raw.c
+
+## Assistance for elliptic-curve keys.
+pkginclude_HEADERS     += ec-keys.h
+libmath_la_SOURCES     += ec-fetch.c
+
+## Test infrastructure for elliptic curves.
+pkginclude_HEADERS     += ec-test.h
+libmath_la_SOURCES     += ec-test.c
+TESTS                  += ec-test.$t
+
+## A table of built-in elliptic curves.
+pkginclude_HEADERS     += ectab.h
+libmath_la_SOURCES     += ectab.c
+CLEANFILES             += ectab.c
+EXTRA_DIST             += ectab.in ec-gentab.awk
+ectab.c: ectab.in ec-gentab.awk mpdump$e
+       $(AM_V_GEN)awk -f $(srcdir)/ec-gentab.awk \
+               <$(srcdir)/ectab.in >ectab.c.new && \
+       mv ectab.c.new ectab.c
+
+###----- That's all, folks --------------------------------------------------
diff --git a/math/bin-gentab.awk b/math/bin-gentab.awk
new file mode 100755 (executable)
index 0000000..a848aed
--- /dev/null
@@ -0,0 +1,100 @@
+#! /usr/bin/awk -f
+
+function banner(name, s, i)
+{
+  s = "/*----- " name " ";
+  while (length(s) < 75) s = s "-";
+  return (s "*/");
+}
+
+function fix(name)
+{
+  gsub(/[^0-9A-Za-z_]+/, "_", name);
+  return (name);
+}
+
+BEGIN {
+  print "/* -*-c-*-";
+  print " *";
+  print " * Table of binary groups [generated]";
+  print " */";
+  print "";
+  print "#include \"bintab.h\"";
+  print "";
+  print "#define N(x) (sizeof(x)/sizeof(*x))";
+  print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }";
+  print "#define NOMP { 0, 0, 0, 0, 0 }";
+  print "";
+  print banner("Binary group data");
+  print "";
+
+  d_i = 0;
+  name = "";
+}
+
+function putmp(x,  d)
+{
+  if (!(x in data)) {
+    print "group " name ": missing " x >"/dev/stderr";
+    exit 1;
+  }
+  d = data[x];
+  if (!(d in cache)) {
+    n = "p_" fix(name) "_" x;
+    print "static mpw " n "[] = {";
+    system("./mpdump " d);
+    print "};";
+    print "";
+    cache[d] = n;
+  }
+  mp[x] = cache[d];
+}
+
+function flush()
+{
+  if (name == "") return;
+  print "/* --- Group " name " --- */";
+  delete mp;
+  print "";
+  putmp("p");
+  putmp("q");
+  putmp("g");
+  print "static bindata bin_" fix(name) " = {";
+  print "  MP(" mp["p"] "),"
+  print "  MP(" mp["q"] "),"
+  print "  MP(" mp["g"] ")"
+  print "};";
+  print "";
+  dname[d_i++] = name;
+  d[name] = name;
+  r[name] = "bin_" fix(name);
+  name = "";
+}
+
+/^[ \t]*(#|$)/ { next; }
+
+$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; }
+
+$1 == "group" { flush(); delete data; name = $2; next; }
+
+{ data[$1] = $2; next; }
+
+END {
+  flush();
+  print banner("Main table");
+  print "";
+  print "const binentry bintab[] = {";
+  for (i = 0; i < d_i; i++) {
+    name = dname[i];
+    rname = d[name];
+    if (!rname in r) {
+      print "group " rname " not found (alias from " name ")" >"/dev/stderr";
+      exit 1;
+    }
+    print "  { \"" name "\", &" r[rname] " },";
+  }
+  print "  { 0, 0 }";
+  print "};"
+  print "";
+  print banner("That's all, folks");
+}
diff --git a/math/bintab.h b/math/bintab.h
new file mode 100644 (file)
index 0000000..dba336c
--- /dev/null
@@ -0,0 +1,55 @@
+/* -*-c-*-
+ *
+ * Table of standard (ish) binary groups
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_BINTAB_H
+#define CATACOMB_BINTAB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "ptab.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef pdata bindata;
+typedef pentry binentry;
+
+/*----- Global variables --------------------------------------------------*/
+
+extern const binentry bintab[];
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/bintab.in b/math/bintab.in
new file mode 100644 (file)
index 0000000..a33badf
--- /dev/null
@@ -0,0 +1,35 @@
+# Standard binary groups
+
+#----- From P1363 annex A ---------------------------------------------------
+
+group p1363-40
+  p 0x200000000000000000000000000000000000000000000065
+  q 0xabbcb671934086d21ff5f7
+  g 0x66704fca38d7962439e5f9bdab4d9ac6f0dd745c72f822e
+
+group p1363-56
+  p 0x100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100d
+  q 0x5538ed0653399777d80d50e508fd01
+  g 0x44e2fd3317b4a1968ce65b7e72f8d64262987d0a818a5a5189a6d588b67317c9ee05a38e3e5691e34933e3e050543d8b
+
+group p1363-64
+  p 0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800001
+  q 0x84b73a6a902299c1aeeb8b537f1ea87c1
+  g 0xce10e3ae38cacb7c1076723b80be855c629c03abef26d2a5ca898f75d2bd794daa9e21781f063ab2785a8c402f976d73e5c8d66072cd950dee1ea722bb8f3d
+
+group p1363-80
+  p 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080043
+  q 0x519f0cb14cf36cfcda7d08fab2b578314c9542801
+  g 0xd0f0d0046d995f82b1599c7bceb20010b2ec0d27748d113c532657584c9ea11ab6be6b7236cfafc2a087503e1ad108e559206d559e7c30f4a516da71fa3e08fc50e03084f18af4a59e9c6835beb67dfd2b47ef8d0ea30d8f65e378e9ba82819ffc0ade685fa6cb346dcecca7134893db0a6950c2beab89ee38508f03f2f1f186
+
+group p1363-112
+  p 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040481
+  q 0x399ac734bd00a6f622bdd00c5f930dcf2ae5d7c521755f7b664f104e423bddd
+  g 0x40154611e5cd5d4826382b23d4ba28fa9d050bb4db5e81b90816fa2823b62328798b70c061734b327e7e3221002a08554e4902f26c476a152380f49e7e2624066de81ef26ddabf4b2c4cc9374f60189e4e5446e04c39d1de05947c54eb6d8c63e498a83d5025ea9fcf2ff3195fb76d76cc2df73918268b72f693a28a01c14622351cc53546bdaacfc95ad19aee16d3d88fbb5fe8143a8a3dcf3d48525be95bef28921edcee081b5269d0b5307ed97f55e5d0218dd17a39f393e017fcfe999626f1fc6ae9a485395a62a3e969d2e0cce55755cc0e22c4356741313d762505c9a2594af3e94d8f913798d92ccf6a73d2447c474ed2924a29856c5c2feeb178a35b15545
+
+group p1363-128
+  p 0x1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002441
+  q 0xa5c52c0d53fc1f43b2cbfd7447d53d55c37004338502dfda0f31b7df76bde74081
+  g 0x9447bb7ca087a37a5268c9e4cd3b9c3eb752272af39657d616181d28f18634368ba972a26b93b2980b391e23d7a9313785a5a17adfd9f810a3677cc20342965e09afc81b8413c5b3054c3adffec6411f088942d5877eef220b2a01cd7c48e8bae8f394b2a0893eb293f6355fc3ea962e503ae1d6fd0c3d718de374100cf89cb9c72e125fac9f930abb9959d03ef18354dd16f3a51e42e2c43ef100a8c3ca9523e6decbdf1f67db454df5781d16d55e94663f9633985d2f76b71a9bb10a985a8c6e8cb4190bef038798e9f402ea8027698e9d28a4ee14f0a6724f38dab82578a0e9600fa5717f40d8f107cb148c896c3061945318b25436c04f84a1b0fa043417bf7904915fa6afaed5fd24c73a5a1328973f39e8bc930ccc3099d7f715f8738b13d0b113899200b2293cdba34a46d22c0fab4d8ed33a71c691ba90687000030ad2fe05b5668520e24edb37edcf43827d9cf0b96ff776f88a2041eadd6902e12428716b46533d765d
+
+#----- That's all, folks ----------------------------------------------------
diff --git a/math/bitops.h b/math/bitops.h
new file mode 100644 (file)
index 0000000..941f71a
--- /dev/null
@@ -0,0 +1,60 @@
+/* -*-c-*-
+ *
+ * Bit operations by truth table
+ *
+ * (c) 2002 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.
+ */
+
+#ifndef CATACOMB_BITOPS_H
+#define CATACOMB_BITOPS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define B0000(x, y) (0u)
+#define B0001(x, y) ((x) & (y))
+#define B0010(x, y) ((x) & ~(y))
+#define B0011(x, y) (x)
+#define B0100(x, y) (~(x) & (y))
+#define B0101(x, y) (y)
+#define B0110(x, y) ((x) ^ (y))
+#define B0111(x, y) ((x) | (y))
+#define B1000(x, y) (~((x) | (y)))
+#define B1001(x, y) (~((x) ^ (y)))
+#define B1010(x, y) (~(y))
+#define B1011(x, y) ((x) | ~(y))
+#define B1100(x, y) (~(x))
+#define B1101(x, y) (~(x) | (y))
+#define B1110(x, y) (~((x) & (y)))
+#define B1111(x, y) (~0u)
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/bittest.c b/math/bittest.c
new file mode 100644 (file)
index 0000000..5f7b1d7
--- /dev/null
@@ -0,0 +1,56 @@
+/* -*-c-*-
+ *
+ * Check the bit operations work
+ *
+ * (c) 2002 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include "bitops.h"
+#include "mpx.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(void)
+{
+  int rc = 0;
+#define CHECK(string) do {                                             \
+  const char *ref = #string;                                           \
+  char buf[5];                                                         \
+  buf[0] = B##string(0u, 0u) & 1u? '1' : '0';                          \
+  buf[1] = B##string(0u, 1u) & 1u? '1' : '0';                          \
+  buf[2] = B##string(1u, 0u) & 1u? '1' : '0';                          \
+  buf[3] = B##string(1u, 1u) & 1u? '1' : '0';                          \
+  buf[4] = 0;                                                          \
+  if (strcmp(buf, ref) != 0) {                                         \
+    fprintf(stderr, "mismatch ref `%s' != buf `%s'\n", ref, buf);      \
+    rc = 1;                                                            \
+  }                                                                    \
+} while (0);
+  MPX_DOBIN(CHECK)
+  return (rc);
+}
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/buf.c b/math/buf.c
new file mode 100644 (file)
index 0000000..01b6a35
--- /dev/null
@@ -0,0 +1,127 @@
+/* -*-c-*-
+ *
+ * Buffer handling
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include "mp.h"
+#include "ec.h"
+#include "buf.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @buf_getmp@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *
+ * Returns:    A multiprecision integer, or null if there wasn't one there.
+ *
+ * Use:                Gets a multiprecision integer from a buffer.
+ */
+
+mp *buf_getmp(buf *b)
+{
+  uint16 sz;
+  size_t n;
+  mp *m;
+  if (buf_getu16(b, &sz) || buf_ensure(b, sz))
+    return (0);
+  m = mp_loadb(MP_NEW, BCUR(b), sz);
+  n = mp_octets(m);
+  if (n != sz && n != 0 && sz != 1) {
+    mp_drop(m);
+    return (0);
+  }
+  BSTEP(b, sz);
+  return (m);
+}
+
+/* --- @buf_putmp@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *             @mp *m@ = a multiprecision integer
+ *
+ * Returns:    Zero if it worked, nonzero if there wasn't enough space.
+ *
+ * Use:                Puts a multiprecision integer to a buffer.
+ */
+
+int buf_putmp(buf *b, mp *m)
+{
+  size_t sz = mp_octets(m);
+  assert(sz < MASK16);
+  if (!sz) sz = 1;
+  if (buf_putu16(b, sz) || buf_ensure(b, sz))
+    return (-1);
+  mp_storeb(m, BCUR(b), sz);
+  BSTEP(b, sz);
+  return (0);
+}
+
+/* --- @buf_getec@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *             @ec *p@ = where to put the point
+ *
+ * Returns:    Zero if it worked, nonzero if it failed.
+ *
+ * Use:                Gets a multiprecision integer from a buffer.  The point must
+ *             be initialized.
+ */
+
+int buf_getec(buf *b, ec *p)
+{
+  mp *x = 0, *y = 0;
+  uint16 n;
+  if (buf_ensure(b, 2)) return (-1);
+  n = LOAD16(BCUR(b)); if (!n) { BSTEP(b, 2); EC_SETINF(p); return (0); }
+  if ((x = buf_getmp(b)) == 0 || (y = buf_getmp(b)) == 0) {
+    mp_drop(x); mp_drop(y); return (-1);
+  }
+  EC_DESTROY(p); p->x = x; p->y = y; p->z = 0;
+  return (0);
+}
+
+/* --- @buf_putec@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *             @ec *p@ = an elliptic curve point
+ *
+ * Returns:    Zero if it worked, nonzero if there wasn't enough space.
+ *
+ * Use:                Puts an elliptic curve point to a buffer.
+ */
+
+int buf_putec(buf *b, ec *p)
+{
+  if (EC_ATINF(p)) return (buf_putu16(b, 0));
+  if (buf_putmp(b, p->x) || buf_putmp(b, p->y)) return (-1);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/buf.h b/math/buf.h
new file mode 100644 (file)
index 0000000..d619416
--- /dev/null
@@ -0,0 +1,104 @@
+/* -*-c-*-
+ *
+ * Reading and writing packet buffers
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_BUF_H
+#define CATACOMB_BUF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @buf_getmp@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *
+ * Returns:    A multiprecision integer, or null if there wasn't one there.
+ *
+ * Use:                Gets a multiprecision integer from a buffer.
+ */
+
+extern mp *buf_getmp(buf */*b*/);
+
+/* --- @buf_putmp@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *             @mp *m@ = a multiprecision integer
+ *
+ * Returns:    Zero if it worked, nonzero if there wasn't enough space.
+ *
+ * Use:                Puts a multiprecision integer to a buffer.
+ */
+
+extern int buf_putmp(buf */*b*/, mp */*m*/);
+
+/* --- @buf_getec@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *             @ec *p@ = where to put the point
+ *
+ * Returns:    Zero if it worked, nonzero if it failed.
+ *
+ * Use:                Gets a multiprecision integer from a buffer.  The point must
+ *             be initialized.
+ */
+
+extern int buf_getec(buf */*b*/, ec */*p*/);
+
+/* --- @buf_putec@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *             @ec *p@ = an elliptic curve point
+ *
+ * Returns:    Zero if it worked, nonzero if there wasn't enough space.
+ *
+ * Use:                Puts an elliptic curve point to a buffer.
+ */
+
+extern int buf_putec(buf */*b*/, ec */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ec-bin.c b/math/ec-bin.c
new file mode 100644 (file)
index 0000000..d91b034
--- /dev/null
@@ -0,0 +1,445 @@
+/* -*-c-*-
+ *
+ * Arithmetic for elliptic curves over binary fields
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/sub.h>
+
+#include "ec.h"
+#include "ec-guts.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+static const ec_ops ec_binops, ec_binprojops;
+
+static ec *ecneg(ec_curve *c, ec *d, const ec *p)
+{
+  EC_COPY(d, p);
+  if (d->x)
+    d->y = F_ADD(c->f, d->y, d->y, d->x);
+  return (d);
+}
+
+static ec *ecprojneg(ec_curve *c, ec *d, const ec *p)
+{
+  EC_COPY(d, p);
+  if (d->x) {
+    mp *t = F_MUL(c->f, MP_NEW, d->x, d->z);
+    d->y = F_ADD(c->f, d->y, d->y, t);
+    MP_DROP(t);
+  }
+  return (d);
+}
+
+static ec *ecfind(ec_curve *c, ec *d, mp *x)
+{
+  field *f = c->f;
+  mp *y, *u, *v;
+
+  if (F_ZEROP(f, x))
+    y = F_SQRT(f, MP_NEW, c->b);
+  else {
+    u = F_SQR(f, MP_NEW, x);           /* %$x^2$% */
+    y = F_MUL(f, MP_NEW, u, c->a);     /* %$a x^2$% */
+    y = F_ADD(f, y, y, c->b);          /* %$a x^2 + b$% */
+    v = F_MUL(f, MP_NEW, u, x);                /* %$x^3$% */
+    y = F_ADD(f, y, y, v);             /* %$A = x^3 + a x^2 + b$% */
+    if (!F_ZEROP(f, y)) {
+      u = F_INV(f, u, u);              /* %$x^{-2}$% */
+      v = F_MUL(f, v, u, y);       /* %$B = A x^{-2} = x + a + b x^{-2}$% */
+      y = F_QUADSOLVE(f, y, v);                /* %$z^2 + z = B$% */
+      if (y) y = F_MUL(f, y, y, x);    /* %$y = z x$% */
+    }
+    MP_DROP(u);
+    MP_DROP(v);
+  }
+  if (!y) return (0);
+  EC_DESTROY(d);
+  d->x = MP_COPY(x);
+  d->y = y;
+  d->z = MP_COPY(f->one);
+  return (d);
+}
+
+static ec *ecdbl(ec_curve *c, ec *d, const ec *a)
+{
+  if (EC_ATINF(a) || F_ZEROP(c->f, a->x))
+    EC_SETINF(d);
+  else {
+    field *f = c->f;
+    mp *lambda;
+    mp *dx, *dy;
+
+    dx = F_INV(f, MP_NEW, a->x);       /* %$x^{-1}$% */
+    dy = F_MUL(f, MP_NEW, dx, a->y);   /* %$y/x$% */
+    lambda = F_ADD(f, dy, dy, a->x);   /* %$\lambda = x + y/x$% */
+
+    dx = F_SQR(f, dx, lambda);         /* %$\lambda^2$% */
+    dx = F_ADD(f, dx, dx, lambda);     /* %$\lambda^2 + \lambda$% */
+    dx = F_ADD(f, dx, dx, c->a);       /* %$x' = a + \lambda^2 + \lambda$% */
+
+    dy = F_ADD(f, MP_NEW, a->x, dx);   /* %$ x + x' $% */
+    dy = F_MUL(f, dy, dy, lambda);     /* %$ (x + x') \lambda$% */
+    dy = F_ADD(f, dy, dy, a->y);       /* %$ (x + x') \lambda + y$% */
+    dy = F_ADD(f, dy, dy, dx);     /* %$ y' = (x + x') \lambda + y + x'$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = 0;
+    MP_DROP(lambda);
+  }
+  return (d);
+}
+
+static ec *ecprojdbl(ec_curve *c, ec *d, const ec *a)
+{
+  if (EC_ATINF(a) || F_ZEROP(c->f, a->x))
+    EC_SETINF(d);
+  else {
+    field *f = c->f;
+    ecctx_bin *cc = (ecctx_bin *)c;
+    mp *dx, *dy, *dz, *u, *v;
+
+    dy = F_SQR(f, MP_NEW, a->z);       /* %$z^2$% */
+    dx = F_MUL(f, MP_NEW, dy, cc->bb); /* %$c z^2$% */
+    dx = F_ADD(f, dx, dx, a->x);       /* %$x + c z^2$% */
+    dz = F_SQR(f, MP_NEW, dx);         /* %$(x + c z^2)^2$% */
+    dx = F_SQR(f, dx, dz);             /* %$x' = (x + c z^2)^4$% */
+
+    dz = F_MUL(f, dz, dy, a->x);       /* %$z' = x z^2$% */
+
+    dy = F_SQR(f, dy, a->x);           /* %$x^2$% */
+    u = F_MUL(f, MP_NEW, a->y, a->z);  /* %$y z$% */
+    u = F_ADD(f, u, u, dz);            /* %$z' + y z$% */
+    u = F_ADD(f, u, u, dy);            /* %$u = z' + x^2 + y z$% */
+
+    v = F_SQR(f, MP_NEW, dy);          /* %$x^4$% */
+    dy = F_MUL(f, dy, v, dz);          /* %$x^4 z'$% */
+    v = F_MUL(f, v, u, dx);            /* %$u x'$% */
+    dy = F_ADD(f, dy, dy, v);          /* %$y' = x^4 z' + u x'$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = dz;
+    MP_DROP(u);
+    MP_DROP(v);
+  }
+  return (d);
+}
+
+static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b)
+{
+  if (a == b)
+    ecdbl(c, d, a);
+  else if (EC_ATINF(a))
+    EC_COPY(d, b);
+  else if (EC_ATINF(b))
+    EC_COPY(d, a);
+  else {
+    field *f = c->f;
+    mp *lambda;
+    mp *dx, *dy;
+
+    if (!MP_EQ(a->x, b->x)) {
+      dx = F_ADD(f, MP_NEW, a->x, b->x); /* %$x_0 + x_1$% */
+      dy = F_INV(f, MP_NEW, dx);       /* %$(x_0 + x_1)^{-1}$% */
+      dx = F_ADD(f, dx, a->y, b->y);   /* %$y_0 + y_1$% */
+      lambda = F_MUL(f, MP_NEW, dy, dx);
+                                 /* %$\lambda = (y_0 + y_1)/(x_0 + x_1)$% */
+
+      dx = F_SQR(f, dx, lambda);       /* %$\lambda^2$% */
+      dx = F_ADD(f, dx, dx, lambda);   /* %$\lambda^2 + \lambda$% */
+      dx = F_ADD(f, dx, dx, c->a);     /* %$a + \lambda^2 + \lambda$% */
+      dx = F_ADD(f, dx, dx, a->x);    /* %$a + \lambda^2 + \lambda + x_0$% */
+      dx = F_ADD(f, dx, dx, b->x);
+                          /* %$x' = a + \lambda^2 + \lambda + x_0 + x_1$% */
+    } else if (!MP_EQ(a->y, b->y) || F_ZEROP(f, a->x)) {
+      EC_SETINF(d);
+      return (d);
+    } else {
+      dx = F_INV(f, MP_NEW, a->x);     /* %$x^{-1}$% */
+      dy = F_MUL(f, MP_NEW, dx, a->y); /* %$y/x$% */
+      lambda = F_ADD(f, dy, dy, a->x); /* %$\lambda = x + y/x$% */
+
+      dx = F_SQR(f, dx, lambda);       /* %$\lambda^2$% */
+      dx = F_ADD(f, dx, dx, lambda);   /* %$\lambda^2 + \lambda$% */
+      dx = F_ADD(f, dx, dx, c->a);    /* %$x' = a + \lambda^2 + \lambda$% */
+      dy = MP_NEW;
+    }
+
+    dy = F_ADD(f, dy, a->x, dx);       /* %$ x + x' $% */
+    dy = F_MUL(f, dy, dy, lambda);     /* %$ (x + x') \lambda$% */
+    dy = F_ADD(f, dy, dy, a->y);       /* %$ (x + x') \lambda + y$% */
+    dy = F_ADD(f, dy, dy, dx);     /* %$ y' = (x + x') \lambda + y + x'$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = 0;
+    MP_DROP(lambda);
+  }
+  return (d);
+}
+
+static ec *ecprojadd(ec_curve *c, ec *d, const ec *a, const ec *b)
+{
+  if (a == b)
+    c->ops->dbl(c, d, a);
+  else if (EC_ATINF(a))
+    EC_COPY(d, b);
+  else if (EC_ATINF(b))
+    EC_COPY(d, a);
+  else {
+    field *f = c->f;
+    mp *dx, *dy, *dz, *u, *uu, *v, *t, *s, *ss, *r, *w, *l;
+
+    dz = F_SQR(f, MP_NEW, b->z);       /* %$z_1^2$% */
+    u = F_MUL(f, MP_NEW, dz, a->x);    /* %$u_0 = x_0 z_1^2$% */
+    t = F_MUL(f, MP_NEW, dz, b->z);    /* %$z_1^3$% */
+    s = F_MUL(f, MP_NEW, t, a->y);     /* %$s_0 = y_0 z_1^3$% */
+
+    dz = F_SQR(f, dz, a->z);           /* %$z_0^2$% */
+    uu = F_MUL(f, MP_NEW, dz, b->x);   /* %$u_1 = x_1 z_0^2$% */
+    t = F_MUL(f, t, dz, a->z);         /* %$z_0^3$% */
+    ss = F_MUL(f, MP_NEW, t, b->y);    /* %$s_1 = y_1 z_0^3$% */
+
+    w = F_ADD(f, u, u, uu);            /* %$r = u_0 + u_1$% */
+    r = F_ADD(f, s, s, ss);            /* %$w = s_0 + s_1$% */
+    if (F_ZEROP(f, w)) {
+      MP_DROP(w);
+      MP_DROP(uu);
+      MP_DROP(ss);
+      MP_DROP(t);
+      MP_DROP(dz);
+      if (F_ZEROP(f, r)) {
+       MP_DROP(r);
+       return (c->ops->dbl(c, d, a));
+      } else {
+       MP_DROP(r);
+       EC_SETINF(d);
+       return (d);
+      }
+    }
+
+    l = F_MUL(f, t, a->z, w);          /* %$l = z_0 w$% */
+
+    dz = F_MUL(f, dz, l, b->z);                /* %$z' = l z_1$% */
+
+    ss = F_MUL(f, ss, r, b->x);                /* %$r x_1$% */
+    t = F_MUL(f, uu, l, b->y);         /* %$l y_1$% */
+    v = F_ADD(f, ss, ss, t);           /* %$v = r x_1 + l y_1$% */
+
+    t = F_ADD(f, t, r, dz);            /* %$t = r + z'$% */
+
+    uu = F_SQR(f, MP_NEW, dz);         /* %$z'^2$% */
+    dx = F_MUL(f, MP_NEW, uu, c->a);   /* %$a z'^2$% */
+    uu = F_MUL(f, uu, t, r);           /* %$t r$% */
+    dx = F_ADD(f, dx, dx, uu);         /* %$a z'^2 + t r$% */
+    r = F_SQR(f, r, w);                        /* %$w^2$% */
+    uu = F_MUL(f, uu, r, w);           /* %$w^3$% */
+    dx = F_ADD(f, dx, dx, uu);         /* %$x' = a z'^2 + t r + w^3$% */
+
+    r = F_SQR(f, r, l);                        /* %$l^2$% */
+    dy = F_MUL(f, uu, v, r);           /* %$v l^2$% */
+    l = F_MUL(f, l, t, dx);            /* %$t x'$% */
+    dy = F_ADD(f, dy, dy, l);          /* %$y' = t x' + v l^2$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = dz;
+    MP_DROP(l);
+    MP_DROP(r);
+    MP_DROP(w);
+    MP_DROP(t);
+    MP_DROP(v);
+  }
+  return (d);
+}
+
+static int eccheck(ec_curve *c, const ec *p)
+{
+  field *f = c->f;
+  int rc;
+  mp *u, *v;
+
+  if (EC_ATINF(p)) return (0);
+  v = F_SQR(f, MP_NEW, p->x);
+  u = F_MUL(f, MP_NEW, v, p->x);
+  v = F_MUL(f, v, v, c->a);
+  u = F_ADD(f, u, u, v);
+  u = F_ADD(f, u, u, c->b);
+  v = F_MUL(f, v, p->x, p->y);
+  u = F_ADD(f, u, u, v);
+  v = F_SQR(f, v, p->y);
+  u = F_ADD(f, u, u, v);
+  rc = F_ZEROP(f, u) ? 0 : -1;
+  mp_drop(u);
+  mp_drop(v);
+  return (rc);
+}
+
+static int ecprojcheck(ec_curve *c, const ec *p)
+{
+  ec t = EC_INIT;
+  int rc;
+
+  c->ops->fix(c, &t, p);
+  rc = eccheck(c, &t);
+  EC_DESTROY(&t);
+  return (rc);
+}
+
+static void ecdestroy(ec_curve *c)
+{
+  ecctx_bin *cc = (ecctx_bin *)c;
+  MP_DROP(cc->c.a);
+  MP_DROP(cc->c.b);
+  if (cc->bb) MP_DROP(cc->bb);
+  DESTROY(cc);
+}
+
+/* --- @ec_bin@, @ec_binproj@ --- *
+ *
+ * Arguments:  @field *f@ = the underlying field for this elliptic curve
+ *             @mp *a, *b@ = the coefficients for this curve
+ *
+ * Returns:    A pointer to the curve, or null.
+ *
+ * Use:                Creates a curve structure for an elliptic curve defined over
+ *             a binary field.  The @binproj@ variant uses projective
+ *             coordinates, which can be a win.
+ */
+
+ec_curve *ec_bin(field *f, mp *a, mp *b)
+{
+  ecctx_bin *cc = CREATE(ecctx_bin);
+  cc->c.ops = &ec_binops;
+  cc->c.f = f;
+  cc->c.a = F_IN(f, MP_NEW, a);
+  cc->c.b = F_IN(f, MP_NEW, b);
+  cc->bb = 0;
+  return (&cc->c);
+}
+
+ec_curve *ec_binproj(field *f, mp *a, mp *b)
+{
+  ecctx_bin *cc = CREATE(ecctx_bin);
+  int i;
+  mp *c, *d;
+
+  cc->c.ops = &ec_binprojops;
+  cc->c.f = f;
+  cc->c.a = F_IN(f, MP_NEW, a);
+  cc->c.b = F_IN(f, MP_NEW, b);
+
+  c = MP_COPY(cc->c.b);
+  for (i = 0; i < f->nbits - 2; i++)
+    c = F_SQR(f, c, c);
+  d = F_SQR(f, MP_NEW, c); d = F_SQR(f, d, d);
+  if (!MP_EQ(d, cc->c.b)) {
+    MP_DROP(c);
+    MP_DROP(d);
+    MP_DROP(cc->c.a);
+    MP_DROP(cc->c.b);
+    DESTROY(cc);
+    return (0);
+  }
+  cc->bb = c;
+  MP_DROP(d);
+  return (&cc->c);
+}
+
+static const ec_ops ec_binops = {
+  "bin",
+  ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix,
+  ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck
+};
+
+static const ec_ops ec_binprojops = {
+  "binproj",
+  ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix,
+  ecfind, ecprojneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck
+};
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
+
+int main(int argc, char *argv[])
+{
+  field *f;
+  ec_curve *c;
+  ec g = EC_INIT, d = EC_INIT;
+  mp *p, *a, *b, *r, *beta;
+  int i, n = argc == 1 ? 1 : atoi(argv[1]);
+
+  printf("ec-bin: ");
+  fflush(stdout);
+  a = MP(0x7ffffffffffffffffffffffffffffffffffffffff);
+  b = MP(0x6645f3cacf1638e139c6cd13ef61734fbc9e3d9fb);
+  p = MP(0x800000000000000000000000000000000000000c9);
+  beta = MP(0x715169c109c612e390d347c748342bcd3b02a0bef);
+  r = MP(0x040000000000000000000292fe77e70c12a4234c32);
+
+  f = field_binnorm(p, beta);
+  c = ec_binproj(f, a, b);
+  g.x = MP(0x0311103c17167564ace77ccb09c681f886ba54ee8);
+  g.y = MP(0x333ac13c6447f2e67613bf7009daf98c87bb50c7f);
+
+  for (i = 0; i < n; i++) {
+    ec_mul(c, &d, &g, r);
+    if (EC_ATINF(&d)) {
+      fprintf(stderr, "zero too early\n");
+      return (1);
+    }
+    ec_add(c, &d, &d, &g);
+    if (!EC_ATINF(&d)) {
+      fprintf(stderr, "didn't reach zero\n");
+      MP_EPRINTX("d.x", d.x);
+      MP_EPRINTX("d.y", d.y);
+      return (1);
+    }
+    ec_destroy(&d);
+  }
+
+  ec_destroy(&g);
+  ec_destroycurve(c);
+  F_DESTROY(f);
+  MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r); MP_DROP(beta);
+  assert(!mparena_count(&mparena_global));
+  printf("ok\n");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/ec-exp.c b/math/ec-exp.c
new file mode 100644 (file)
index 0000000..b2f1ceb
--- /dev/null
@@ -0,0 +1,141 @@
+/* -*-c-*-
+ *
+ * Point multiplication for elliptic curves
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "ec.h"
+#include "ec-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @ec_imul@, @ec_mul@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p@ = pointer to the generator point
+ *             @mp *n@ = integer multiplier
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Multiplies a point by a scalar, returning %$n p$%.  The
+ *             @imul@ variant uses internal representations for argument
+ *             and result.
+ */
+
+ec *ec_imul(ec_curve *c, ec *d, const ec *p, mp *n)
+{
+  ec t = EC_INIT;
+
+  EC_COPY(&t, p);
+  if (t.x && (n->f & MP_BURN))
+    t.x->f |= MP_BURN;
+  MP_SHRINK(n);
+  EC_SETINF(d);
+  if (MP_ZEROP(n))
+    ;
+  else {
+    if (MP_NEGP(n))
+      EC_NEG(c, &t, &t);
+    if (MP_LEN(n) < EXP_THRESH)
+      EXP_SIMPLE(*d, t, n);
+    else
+      EXP_WINDOW(*d, t, n);
+  }
+  EC_DESTROY(&t);
+  return (d);
+}
+
+ec *ec_mul(ec_curve *c, ec *d, const ec *p, mp *n)
+{
+  EC_IN(c, d, p);
+  ec_imul(c, d, d, n);
+  return (EC_OUT(c, d, d));
+}
+
+/* --- @ec_mmul@, @ec_immul@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec_mulfactor *f@ = pointer to vector of factors
+ *             @size_t n@ = number of factors
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Does simultaneous point multiplication.  The @immul@ variant
+ *             uses internal representations for arguments and result.
+ */
+
+#undef EXP_WINSZ
+#define EXP_WINSZ 3
+
+static ec *immul(ec_curve *c, ec *d, ec_mulfactor *f, size_t n)
+{
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    MP_SHRINK(f[i].exp);
+    if (MP_NEGP(f[i].exp))
+      EC_NEG(c, &f[i].base, &f[i].base);
+    if (f[i].base.x && f[i].exp->f & MP_BURN)
+      f[i].base.x->f |= MP_BURN;
+  }
+  EC_SETINF(d);
+  EXP_SIMUL(*d, f, n);
+  for (i = 0; i < n; i++)
+    EC_DESTROY(&f[i].base);
+  xfree(f);
+  return (d);
+}
+
+ec *ec_immul(ec_curve *c, ec *d, const ec_mulfactor *f, size_t n)
+{
+  ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    EC_CREATE(&ff[i].base);
+    EC_COPY(&ff[i].base, &f[i].base);
+    ff[i].exp = f[i].exp;
+  }
+  return (immul(c, d, ff, n));
+}
+
+ec *ec_mmul(ec_curve *c, ec *d, const ec_mulfactor *f, size_t n)
+{
+  ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    EC_CREATE(&ff[i].base);
+    EC_IN(c, &ff[i].base, &f[i].base);
+    ff[i].exp = f[i].exp;
+  }
+  immul(c, d, ff, n);
+  return (EC_OUT(c, d, d));
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/ec-exp.h b/math/ec-exp.h
new file mode 100644 (file)
index 0000000..6cad753
--- /dev/null
@@ -0,0 +1,67 @@
+/* -*-c-*-
+ *
+ * Exponentiation operations for elliptic curves
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_EC_EXP_H
+#define CATACOMB_EC_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentation definitions -----------------------------------------*/
+
+#define EXP_TYPE ec
+
+#define EXP_COPY(d, p) do {                                            \
+  (d).x = MP_COPY((p).x);                                              \
+  (d).y = MP_COPY((p).y);                                              \
+  (d).z = (p).z ? MP_COPY((p).z) : MP_NEW;                             \
+} while (0)
+#define EXP_DROP(x) EC_DESTROY(&(x))
+
+#define EXP_MUL(a, x) EC_ADD(c, &(a), &(a), &(x))
+#define EXP_SQR(a) EC_DBL(c, &(a), &(a))
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) do {                                       \
+  EC_CREATE(&(d));                                                     \
+  EC_ADD(c, &(d), &(x), &(y));                                         \
+} while (0)
+#define EXP_SETSQR(d, x) do {                                          \
+  EC_CREATE(&(d));                                                     \
+  EC_DBL(c, &(d), &(x));                                               \
+} while (0)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ec-fetch.c b/math/ec-fetch.c
new file mode 100644 (file)
index 0000000..3484d52
--- /dev/null
@@ -0,0 +1,89 @@
+/* -*-c-*-
+ *
+ * Key fetching for elliptic curve public and private keys
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "ec-keys.h"
+#include "key.h"
+
+/*----- Key fetching ------------------------------------------------------*/
+
+const key_fetchdef ec_paramfetch[] = {
+  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
+  { 0,         0,                              0,              0 }
+};
+
+const key_fetchdef ec_pubfetch[] = {
+  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
+  { "p",       offsetof(ec_pub, p),            KENC_EC,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+static const key_fetchdef priv[] = {
+  { "x",       offsetof(ec_priv, x),           KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+const key_fetchdef ec_privfetch[] = {
+  { "curve",   offsetof(ec_pub, cstr),         KENC_STRING,    0 },
+  { "p",       offsetof(ec_pub, p),            KENC_EC,        0 },
+  { "private", 0,                              KENC_STRUCT,    priv },
+  { 0,         0,                              0,              0 }
+};
+
+/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- *
+ *
+ * Arguments:  @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to
+ *                     key block to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an elliptic curve key block
+ */
+
+void ec_paramfree(ec_param *ep)
+{
+  if (ep->ei.c) ec_freeinfo(&ep->ei);
+  xfree(ep->cstr);
+}
+
+void ec_pubfree(ec_pub *ep)
+{
+  if (ep->ei.c) ec_freeinfo(&ep->ei);
+  xfree(ep->cstr);
+  EC_DESTROY(&ep->p);
+}
+
+void ec_privfree(ec_priv *ep)
+{
+  if (ep->ei.c) ec_freeinfo(&ep->ei);
+  xfree(ep->cstr);
+  EC_DESTROY(&ep->p);
+  mp_drop(ep->x);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/ec-gentab.awk b/math/ec-gentab.awk
new file mode 100755 (executable)
index 0000000..37ccacc
--- /dev/null
@@ -0,0 +1,114 @@
+#! /usr/bin/awk -f
+
+function banner(name, s, i)
+{
+  s = "/*----- " name " ";
+  while (length(s) < 75) s = s "-";
+  return (s "*/");
+}
+
+function fix(name)
+{
+  gsub(/[^0-9A-Za-z_]+/, "_", name);
+  return (name);
+}
+
+BEGIN {
+  print "/* -*-c-*-";
+  print " *";
+  print " * Table of elliptic curves [generated]";
+  print " */";
+  print "";
+  print "#include \"ectab.h\"";
+  print "";
+  print "#define N(x) (sizeof(x)/sizeof(*x))";
+  print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }";
+  print "#define NOMP { 0, 0, 0, 0, 0 }";
+  print "";
+  print banner("Curve data");
+  print "";
+
+  d_i = 0;
+  name = "";
+}
+
+function putmp(x,  d)
+{
+  if (!(x in data)) {
+    print "curve " name ": missing " x >"/dev/stderr";
+    exit 1;
+  }
+  d = data[x];
+  if (!(d in cache)) {
+    n = "c_" fix(name) "_" x;
+    print "static mpw " n "[] = {";
+    system("./mpdump " d);
+    print "};";
+    print "";
+    cache[d] = n;
+  }
+  mp[x] = cache[d];
+}
+
+function flush()
+{
+  if (name == "") return;
+  print "/* --- Curve " name " --- */";
+  delete mp;
+  print "";
+  putmp("p");
+  if (type == "binnorm") putmp("beta");
+  putmp("a");
+  putmp("b");
+  putmp("r");
+  putmp("h");
+  putmp("gx");
+  putmp("gy");
+  print "static ecdata c_" fix(name) " = {";
+  print "  FTAG_" toupper(type) ",";
+  print "  MP(" mp["p"] "),"
+  if (type == "binnorm")
+    print "  MP(" mp["beta"] "),";
+  else
+    print "  NOMP,";
+  print "  MP(" mp["a"] "),"
+  print "  MP(" mp["b"] "),"
+  print "  MP(" mp["r"] "),"
+  print "  MP(" mp["h"] "),"
+  print "  MP(" mp["gx"] "),"
+  print "  MP(" mp["gy"] ")"
+  print "};";
+  print "";
+  dname[d_i++] = name;
+  d[name] = name;
+  r[name] = "c_" fix(name);
+  name = "";
+}
+
+/^[ \t]*(#|$)/ { next; }
+
+$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; }
+
+$1 == "curve" { flush(); delete data; name = $2; type = $3; next; }
+
+{ data[$1] = $2; next; }
+
+END {
+  flush();
+  print banner("Main table");
+  print "";
+  print "const ecentry ectab[] = {";
+  for (i = 0; i < d_i; i++) {
+    name = dname[i];
+    rname = d[name];
+    if (!rname in r) {
+      print "curve " rname " not found (alias from " name ")" >"/dev/stderr";
+      exit 1;
+    }
+    print "  { \"" name "\", &" r[rname] " },";
+  }
+  print "  { 0, 0 }";
+  print "};"
+  print "";
+  print banner("That's all, folks");
+}
diff --git a/math/ec-guts.h b/math/ec-guts.h
new file mode 100644 (file)
index 0000000..8568e62
--- /dev/null
@@ -0,0 +1,58 @@
+/* -*-c-*-
+ *
+ * Internal structures for built-in elliptic curve types
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_EC_GUTS_H
+#define CATACOMB_EC_GUTS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct ecctx_bin {
+  ec_curve c;
+  mp *bb;
+} ecctx_bin;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ec-info.c b/math/ec-info.c
new file mode 100644 (file)
index 0000000..21d21fd
--- /dev/null
@@ -0,0 +1,779 @@
+/* -*-c-*-
+ *
+ * Elliptic curve information management
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/darray.h>
+
+#include "ec.h"
+#include "ectab.h"
+#include "gf.h"
+#include "keysz.h"
+#include "mpbarrett.h"
+#include "pgen.h"
+#include "primeiter.h"
+#include "mprand.h"
+#include "mpint.h"
+#include "rabin.h"
+
+/*----- Embedding degree checking -----------------------------------------*
+ *
+ * Let %$q = p^m$% be a prime power, and let %$E$% be an elliptic curve over
+ * %$\gf{q}$% with %$n = \#E(\gf{q}) = r h$% where %$r$% is prime.  Then the
+ * Weil and Tate pairings can be used to map %$r$%-torsion points on
+ * %$E(\gf{q})$% onto the %$r$%-th roots of unity (i.e., the order-%$r$%
+ * subgroup) in an extension field %$\gf{p^k}$% of %$\gf{p}$% (%%\emph{not}%%
+ * of %$\gf{q}$% -- see [Hitt]).  We call the smallest such %$k$% the
+ * %%\emph{embedding degree}%% of the curve %$E$%.  The
+ * Menezes-Okamoto-Vanstone (MOV) attack solves the discrete log problem in
+ * %$E(\gf{q})$% by using the pairing and then applying index calculus to
+ * extract a discrete log in %$\gf{p^k}$%; obviously this only works if %$k$%
+ * is small enough.
+ *
+ * The usual check, suggested in, e.g., [P1363] or [SEC1], only covers
+ * extension fields %$\gf{q^\ell}$% of %$\gf{q}$%, which is fine when %$q$%
+ * is prime, but when we're dealing with binary fields it works less well.
+ * Indeed, as [Hitt] demonstrates, the embedding field can actually be
+ * %%\emph{smaller}%% than %$\gf{q}$%, and choosing %$m$% prime doesn't help
+ * (even though I previously thought it did).
+ *
+ * Define the %%\emph{embedding degree bound}%% %$B$% to be the smallest
+ * %$i$% such that discrete logs in %$\gf{p^i}$% are about as hard as in
+ * %$E(\gf{q})$%.
+ *
+ * The embedding group is a subgroup of the multiplicative group
+ * %$\gf{p^k}^*$% which contains %$p^k - 1$% elements; therefore we must have
+ * %$r \mid p^k - 1$%, or, equivalently, %$p^k \equiv 1 \pmod{r}$%.
+ *
+ * The recommended checking procedure, e.g., in [P1363], is just to check
+ * %$q^i \not\equiv 1 \pmod{r}$% for each %$0 < i < B$%.  This is fast when
+ * you only consider extension fields of %$\gf{q}$%, since %$B$% is at most
+ * about 27.  However, as noted above, this is inadequate when %$q$% is a
+ * prime power, and we must check all the extension fields of %$p$%.  Now
+ * %$B$% can be about 15000, which is rather scarier -- we need a better
+ * algorithm.
+ *
+ * As noted, we must have %$p^k \equiv 1 \pmod{r}$%; but by minimality of
+ * %$k$%, we must have %$p^i \not\equiv 1 \pmod{r}$% for %$0 < i < k$%.
+ * Therefore %$p$% generates an order-%$k$% subgroup in %$\gf{r}^*$%, so we
+ * must have %$k \mid r - 1$%.
+ *
+ * Of course, factoring %$r - 1$% is a mug's game; but we're not interested
+ * in the complete factorization -- just the %$B$%-smooth portion.  An
+ * algorithm suggests itself:
+ *
+ *   1. Extract the factors of %$r - 1$% which are less than %$B$%.
+ *
+ *   2. For each divisor %$d$% of %$r - 1$% less than %$B$% (which we can
+ *     construct using this factorization), make sure that
+ *      %$p^d \not\equiv 1 \pmod{r}$%.
+ *
+ * This takes a little while but not ever-so long.
+ *
+ * This is enough for cryptosystems based on the computational Diffie-
+ * Hellman problem to be secure.  However, it's %%\emph{not}%% enough for the
+ * %%\emph{decisional}%% Diffie-Hellman problem to be hard; it appears we
+ * also need to hope that there aren't any suitable distortion maps with
+ * which one can solve the DDH problem.  I don't know how to check for those
+ * at the moment.
+ *
+ * We'll take the subgroup order as indicative of the security level actually
+ * wanted.  Then, to ensure security against the MOV attack, we must ensure
+ * that the embedding degree is sufficiently large that discrete logs in
+ * %$\gf{q^m}$% are at least as hard as discrete logs over the curve.
+ *
+ * We actually allow a small amount of slop in the conversions, in order to
+ * let people pick nice round numbers for their key lengths.
+ *
+ * References:
+ *
+ * [Hitt]  L. Hitt, On an improved definition of embedding degree;
+ *         http://eprint.iacr.org/2006/415
+ *
+ * [P1363] IEEE 1363-2000: Standard Specifications for Public Key
+ *         Cryptography; http://grouper.ieee.org/groups/1363/P1363/index.html
+ *
+ * [SEC1]  SEC 1: Elliptic Curve Cryptography;
+ *         http://www.secg.org/download/aid-385/sec1_final.pdf
+ */
+
+/* --- @movcheck@ --- *
+ *
+ * Arguments:  @mp *r@ = curve subgroup order
+ *             @mp *p@ = field characteristic
+ *             @unsigned long B@ = embedding degree bound
+ *
+ * Returns:    Zero if OK, nonzero if an embedding was found.
+ *
+ * Use:                Checks a curve for embeddings with degree less than the
+ *             stated bound %$B$%.  See above for explanation and a
+ *             description of the algorithm.
+ */
+
+static int movcheck(mp *r, mp *p, unsigned long B)
+{
+  mpmont mm;
+  mp *r1, *pp = MP_NEW, *t = MP_NEW, *u = MP_NEW, *v = MP_NEW, *tt;
+  struct factor {
+    unsigned long f;
+    unsigned c, e;
+  };
+  DA_DECL(factor_v, struct factor);
+  factor_v fv = DA_INIT;
+  size_t nf;
+  struct factor *ff;
+  primeiter pi;
+  mp *BB;
+  unsigned long d, f;
+  unsigned i, j;
+  int rc = 0;
+
+  /* --- Special case --- *
+   *
+   * If %$r = 2$% then (a) Montgomery reduction won't work, and (b) we have
+   * no security worth checking anyway.  Otherwise we're guaranteed that
+   * %$r$% is a prime, so it must be odd.
+   */
+
+  if (MP_EQ(r, MP_TWO))
+    return (0);
+
+  /* --- First factor the %$B%-smooth portion of %$r - 1$% --- *
+   *
+   * We can generate prime numbers up to %$B$% efficiently, so trial division
+   * it is.
+   */
+
+  BB = mp_fromulong(MP_NEW, B);
+  r1 = mp_sub(MP_NEW, r, MP_ONE);
+  primeiter_create(&pi, 0);
+  for (;;) {
+    pp = primeiter_next(&pi, pp);
+    if (MP_CMP(pp, >, BB))
+      break;
+    mp_div(&u, &v, r1, pp);
+    if (!MP_ZEROP(v))
+      continue;
+    i = 0;
+    do {
+      tt = r1; r1 = u; u = tt; i++;
+      mp_div(&u, &v, r1, pp);
+    } while (MP_ZEROP(v));
+    DA_ENSURE(&fv, 1);
+    DA_UNSAFE_EXTEND(&fv, 1);
+    DA_LAST(&fv).f = mp_toulong(pp);
+    DA_LAST(&fv).e = i;
+    DA_LAST(&fv).c = 0;
+  }
+  MP_DROP(BB); MP_DROP(pp); primeiter_destroy(&pi);
+  nf = DA_LEN(&fv); ff = DA(&fv);
+
+  /* --- Now generate divisors of %$r - 1$% less than %$B$% --- *
+   *
+   * For each divisor %$d$%, check whether %$p^d \equiv 1 \pmod{r}$%.
+   */
+
+  mpmont_create(&mm, r);
+  u = mpmont_mul(&mm, u, p, mm.r2);
+  for (;;) {
+
+    /* --- Construct the divisor --- */
+
+    d = 1;
+    for (i = 0; i < nf; i++) {
+      f = ff[i].f; j = ff[i].c; if (!j) continue;
+      for (;;) {
+       if (f >= (B + d - 1)/d) goto toobig;
+       if (j & 1) d *= f;
+       j >>= 1; if (!j) break;
+       f *= f;
+      }
+    }
+    v = mp_fromulong(v, d);
+
+    /* --- Compute %$p^k \bmod r$% and check --- */
+
+    t = mpmont_expr(&mm, t, u, v);
+    if (MP_EQ(t, mm.r)) {
+      rc = -1;
+      break;
+    }
+
+    /* --- Step the divisors along --- */
+
+  toobig:
+    for (i = 0; i < nf; i++) {
+      if (ff[i].c < ff[i].e) {
+       ff[i].c++;
+       goto more;
+      }
+      ff[i].c = 0;
+    }
+    break;
+  more:;
+  }
+
+  /* --- Clear away the debris --- */
+
+  mpmont_destroy(&mm);
+  MP_DROP(t); MP_DROP(u); MP_DROP(v); MP_DROP(r1);
+  DA_DESTROY(&fv);
+  return (rc);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @ec_curveparse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *
+ * Returns:    Elliptic curve pointer if OK, or null.
+ *
+ * Use:                Parses an elliptic curve description, which has the form
+ *
+ *               * a field description
+ *               * an optional `;'
+ *               * `prime', `primeproj', `bin', or `binproj'
+ *               * an optional `:'
+ *               * the %$a$% parameter
+ *               * an optional `,'
+ *               * the %$b$% parameter
+ */
+
+ec_curve *ec_curveparse(qd_parse *qd)
+{
+  mp *a = MP_NEW, *b = MP_NEW;
+  ec_curve *c;
+  field *f;
+
+  if ((f = field_parse(qd)) == 0) goto fail;
+  qd_delim(qd, ';');
+  switch (qd_enum(qd, "prime,primeproj,bin,binproj")) {
+    case 0:
+      if (F_TYPE(f) != FTY_PRIME) {
+       qd->e = "field not prime";
+       goto fail;
+      }
+      qd_delim(qd, ':');
+      if ((a = qd_getmp(qd)) == 0) goto fail;
+      qd_delim(qd, ',');
+      if ((b = qd_getmp(qd)) == 0) goto fail;
+      c = ec_prime(f, a, b);
+      break;
+    case 1:
+      if (F_TYPE(f) != FTY_PRIME) {
+       qd->e = "field not prime";
+       goto fail;
+      }
+      qd_delim(qd, ':');
+      if ((a = qd_getmp(qd)) == 0) goto fail;
+      qd_delim(qd, ',');
+      if ((b = qd_getmp(qd)) == 0) goto fail;
+      c = ec_primeproj(f, a, b);
+      break;
+    case 2:
+      if (F_TYPE(f) != FTY_BINARY) {
+       qd->e = "field not binary";
+       goto fail;
+      }
+      qd_delim(qd, ':');
+      if ((a = qd_getmp(qd)) == 0) goto fail;
+      qd_delim(qd, ',');
+      if ((b = qd_getmp(qd)) == 0) goto fail;
+      c = ec_bin(f, a, b);
+      break;
+    case 3:
+      if (F_TYPE(f) != FTY_BINARY) {
+       qd->e = "field not binary";
+       goto fail;
+      }
+      qd_delim(qd, ':');
+      if ((a = qd_getmp(qd)) == 0) goto fail;
+      qd_delim(qd, ',');
+      if ((b = qd_getmp(qd)) == 0) goto fail;
+      c = ec_binproj(f, a, b);
+      break;
+    default:
+      goto fail;
+  }
+  if (!c) {
+    qd->e = "bad curve parameters";
+    goto fail;
+  }
+  if (a) MP_DROP(a);
+  if (b) MP_DROP(b);
+  return (c);
+
+fail:
+  if (f) F_DESTROY(f);
+  if (a) MP_DROP(a);
+  if (b) MP_DROP(b);
+  return (0);
+}
+
+/* --- @ec_ptparse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *             @ec *p@ = where to put the point
+ *
+ * Returns:    The point address, or null.
+ *
+ * Use:                Parses an elliptic curve point.  This has the form
+ *
+ *               * %$x$%-coordinate
+ *               * optional `,'
+ *               * %$y$%-coordinate
+ */
+
+ec *ec_ptparse(qd_parse *qd, ec *p)
+{
+  mp *x = MP_NEW, *y = MP_NEW;
+
+  if (qd_enum(qd, "inf") >= 0) {
+    EC_SETINF(p);
+    return (p);
+  }
+  if ((x = qd_getmp(qd)) == 0) goto fail;
+  qd_delim(qd, ',');
+  if ((y = qd_getmp(qd)) == 0) goto fail;
+  EC_DESTROY(p);
+  p->x = x;
+  p->y = y;
+  p->z = 0;
+  return (p);
+
+fail:
+  if (x) MP_DROP(x);
+  if (y) MP_DROP(y);
+  return (0);
+}
+
+/* --- @ec_infofromdata@ --- *
+ *
+ * Arguments:  @ec_info *ei@ = where to write the information
+ *             @ecdata *ed@ = raw data
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads elliptic curve information about one of the standard
+ *             curves.
+ */
+
+void ec_infofromdata(ec_info *ei, ecdata *ed)
+{
+  field *f;
+
+  switch (ed->ftag) {
+    case FTAG_PRIME:
+      f = field_prime(&ed->p);
+      ei->c = ec_primeproj(f, &ed->a, &ed->b);
+      break;
+    case FTAG_NICEPRIME:
+      f = field_niceprime(&ed->p);
+      ei->c = ec_primeproj(f, &ed->a, &ed->b);
+      break;
+    case FTAG_BINPOLY:
+      f = field_binpoly(&ed->p);
+      ei->c = ec_binproj(f, &ed->a, &ed->b);
+      break;
+    case FTAG_BINNORM:
+      f = field_binnorm(&ed->p, &ed->beta);
+      ei->c = ec_binproj(f, &ed->a, &ed->b);
+      break;
+    default:
+      abort();
+  }
+
+  assert(f); assert(ei->c);
+  EC_CREATE(&ei->g); ei->g.x = &ed->gx; ei->g.y = &ed->gy; ei->g.z = 0;
+  ei->r = &ed->r; ei->h = &ed->h;
+}
+
+/* --- @ec_infoparse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *             @ec_info *ei@ = curve information block, currently
+ *                     uninitialized
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Parses an elliptic curve information string, and stores the
+ *             information in @ei@.  This is either the name of a standard
+ *             curve, or it has the form
+ *
+ *               * elliptic curve description
+ *               * optional `;'
+ *               * common point
+ *               * optional `:'
+ *               * group order
+ *               * optional `*'
+ *               * cofactor
+ */
+
+int ec_infoparse(qd_parse *qd, ec_info *ei)
+{
+  ec_curve *c = 0;
+  field *f;
+  ec g = EC_INIT;
+  const ecentry *ee;
+  mp *r = MP_NEW, *h = MP_NEW;
+
+  for (ee = ectab; ee->name; ee++) {
+    if (qd_enum(qd, ee->name) >= 0) {
+      ec_infofromdata(ei, ee->data);
+      goto found;
+    }
+  }
+
+  if ((c = ec_curveparse(qd)) == 0) goto fail;
+  qd_delim(qd, ';'); if (!ec_ptparse(qd, &g)) goto fail;
+  qd_delim(qd, ':'); if ((r = qd_getmp(qd)) == 0) goto fail;
+  qd_delim(qd, '*'); if ((h = qd_getmp(qd)) == 0) goto fail;
+  ei->c = c; ei->g = g; ei->r = r; ei->h = h;
+
+found:
+  return (0);
+
+fail:
+  EC_DESTROY(&g);
+  if (r) MP_DROP(r);
+  if (h) MP_DROP(h);
+  if (c) { f = c->f; ec_destroycurve(c); F_DESTROY(f); }
+  return (-1);
+}
+
+/* --- @ec_getinfo@ --- *
+ *
+ * Arguments:  @ec_info *ei@ = where to write the information
+ *             @const char *p@ = string describing a curve
+ *
+ * Returns:    Null on success, or a pointer to an error message.
+ *
+ * Use:                Parses out information about a curve.  The string is either a
+ *             standard curve name, or a curve info string.
+ */
+
+const char *ec_getinfo(ec_info *ei, const char *p)
+{
+  qd_parse qd;
+
+  qd.p = p;
+  qd.e = 0;
+  if (ec_infoparse(&qd, ei))
+    return (qd.e);
+  if (!qd_eofp(&qd)) {
+    ec_freeinfo(ei);
+    return ("junk found at end of string");
+  }
+  return (0);
+}
+
+/* --- @ec_sameinfop@ --- *
+ *
+ * Arguments:  @ec_info *ei, *ej@ = two elliptic curve parameter sets
+ *
+ * Returns:    Nonzero if the curves are identical (not just isomorphic).
+ *
+ * Use:                Checks for sameness of curve parameters.
+ */
+
+int ec_sameinfop(ec_info *ei, ec_info *ej)
+{
+  return (ec_samep(ei->c, ej->c) &&
+         MP_EQ(ei->r, ej->r) && MP_EQ(ei->h, ej->h) &&
+         EC_EQ(&ei->g, &ej->g));
+}
+
+/* --- @ec_freeinfo@ --- *
+ *
+ * Arguments:  @ec_info *ei@ = elliptic curve information block to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees the information block.
+ */
+
+void ec_freeinfo(ec_info *ei)
+{
+  field *f;
+
+  EC_DESTROY(&ei->g);
+  MP_DROP(ei->r);
+  MP_DROP(ei->h);
+  f = ei->c->f; ec_destroycurve(ei->c); F_DESTROY(f);
+}
+
+/* --- @ec_checkinfo@ --- *
+ *
+ * Arguments:  @const ec_info *ei@ = elliptic curve information block
+ *
+ * Returns:    Null if OK, or pointer to error message.
+ *
+ * Use:                Checks an elliptic curve according to the rules in SEC1.
+ */
+
+static const char *gencheck(const ec_info *ei, grand *gr, mp *q, mp *ch)
+{
+  ec_curve *c = ei->c;
+  unsigned long qmbits, rbits, cbits, B;
+  mp *qq;
+  mp *nn;
+  mp *x, *y;
+  ec p;
+  int rc;
+
+  /* --- Check curve isn't anomalous --- */
+
+  if (MP_EQ(ei->r, q)) return ("curve is anomalous");
+
+  /* --- Check %$G \in E \setminus \{ 0 \}$% --- */
+
+  if (EC_ATINF(&ei->g)) return ("generator at infinity");
+  if (ec_check(c, &ei->g)) return ("generator not on curve");
+
+  /* --- Check %$r$% is prime --- */
+
+  if (!pgen_primep(ei->r, gr)) return ("generator order not prime");
+
+  /* --- Check that the cofactor is correct --- *
+   *
+   * Let %$q$% be the size of the field, and let %$n = h r = \#E(\gf{q})$% be
+   * the number of %$\gf{q}$%-rational points on our curve.  Hasse's theorem
+   * tells us that
+   *
+   *   %$|q + 1 - n| \le 2\sqrt{q}$%
+   *
+   * or, if we square both sides,
+   *
+   *   %$(q + 1 - n)^2 \le 4 q$%.
+   *
+   * We'd like the cofactor to be uniquely determined by this equation, which
+   * is possible as long as it's not too big.  (If it is, we have to mess
+   * about with Weil pairings, which is no fun.)  For this, we need the
+   * following inequalities:
+   *
+   *   * %$A = (q + 1 - n)^2 \le 4 q$% (both lower and upper bounds from
+   *    Hasse's theorem);
+   *
+   *   * %$B = (q + 1 - n - r)^2 > 4 q$% (check %$h - 1$% isn't possible);
+   *    and
+   *
+   *   * %$C = (q + 1 - n + r)^2 > 4 q$% (check %$h + 1$% isn't possible).
+   */
+
+  rc = 1;
+  qq = mp_add(MP_NEW, q, MP_ONE);
+  nn = mp_mul(MP_NEW, ei->r, ei->h);
+  nn = mp_sub(nn, qq, nn);
+  qq = mp_lsl(qq, q, 2);
+
+  y = mp_sqr(MP_NEW, nn);
+  if (MP_CMP(y, >, qq)) rc = 0;
+
+  x = mp_sub(MP_NEW, nn, ei->r);
+  y = mp_sqr(y, x);
+  if (MP_CMP(y, <=, qq)) rc = 0;
+
+  x = mp_add(x, nn, ei->r);
+  y = mp_sqr(y, x);
+  if (MP_CMP(y, <=, qq)) rc = 0;
+
+  MP_DROP(x);
+  MP_DROP(y);
+  MP_DROP(nn);
+  MP_DROP(qq);
+  if (!rc) return ("incorrect or ambiguous cofactor");
+
+  /* --- Check %$n G = 0$% --- */
+
+  EC_CREATE(&p);
+  ec_mul(c, &p, &ei->g, ei->r);
+  rc = EC_ATINF(&p);
+  EC_DESTROY(&p);
+  if (!rc) return ("incorrect group order");
+
+  /* --- Check the embedding degree --- */
+
+  rbits = mp_bits(ei->r);
+  cbits = mp_bits(ch);
+  qmbits = keysz_todl(keysz_fromec(rbits * 7/8));
+  B = (qmbits + cbits - 1)/cbits;
+  if (movcheck(ei->r, ch, B))
+    return("curve embedding degree too low");
+
+  /* --- Done --- */
+
+  return (0);
+}
+
+static int primeeltp(mp *x, field *f)
+  { return (!MP_NEGP(x) && MP_CMP(x, <, f->m)); }
+
+static const char *primecheck(const ec_info *ei, grand *gr)
+{
+  ec_curve *c = ei->c;
+  field *f = c->f;
+  mp *x, *y;
+  int rc;
+  const char *err;
+
+  /* --- Check %$p$% is an odd prime --- */
+
+  if (!pgen_primep(f->m, gr)) return ("p not prime");
+
+  /* --- Check %$a$%, %$b$%, %$G_x$% and %$G_y$% are in %$[0, p)$% --- */
+
+  if (!primeeltp(c->a, f)) return ("a out of range");
+  if (!primeeltp(c->b, f)) return ("b out of range");
+  if (!primeeltp(ei->g.x, f)) return ("G_x out of range");
+  if (!primeeltp(ei->g.x, f)) return ("G_y out of range");
+
+  /* --- Check %$4 a^3 + 27 b^2 \not\equiv 0 \pmod{p}$% --- */
+
+  x = F_SQR(f, MP_NEW, c->a);
+  x = F_MUL(f, x, x, c->a);
+  x = F_QDL(f, x, x);
+  y = F_SQR(f, MP_NEW, c->b);
+  y = F_TPL(f, y, y);
+  y = F_TPL(f, y, y);
+  y = F_TPL(f, y, y);
+  x = F_ADD(f, x, x, y);
+  rc = F_ZEROP(f, x);
+  MP_DROP(x);
+  MP_DROP(y);
+  if (rc) return ("not an elliptic curve");
+
+  /* --- Now do the general checks --- */
+
+  err = gencheck(ei, gr, f->m, f->m);
+  return (err);
+}
+
+static const char *bincheck(const ec_info *ei, grand *gr)
+{
+  ec_curve *c = ei->c;
+  field *f = c->f;
+  mp *x;
+  int rc;
+  const char *err;
+
+  /* --- Check that %$m$% is prime --- */
+
+  x = mp_fromuint(MP_NEW, f->nbits);
+  rc = pfilt_smallfactor(x);
+  mp_drop(x);
+  if (rc != PGEN_DONE) return ("degree not prime");
+
+  /* --- Check that %$p$% is irreducible --- */
+
+  if (!gf_irreduciblep(f->m)) return ("p not irreducible");
+
+  /* --- Check that %$a, b, G_x, G_y$% have degree less than %$p$% --- */
+
+  if (mp_bits(c->a) > f->nbits) return ("a out of range");
+  if (mp_bits(c->b) > f->nbits) return ("a out of range");
+  if (mp_bits(ei->g.x) > f->nbits) return ("G_x out of range");
+  if (mp_bits(ei->g.y) > f->nbits) return ("G_y out of range");
+
+  /* --- Check that %$b \ne 0$% --- */
+
+  if (F_ZEROP(f, c->b)) return ("b is zero");
+
+  /* --- Now do the general checks --- */
+
+  x = mp_lsl(MP_NEW, MP_ONE, f->nbits);
+  err = gencheck(ei, gr, x, MP_TWO);
+  mp_drop(x);
+  return (err);
+}
+
+const char *ec_checkinfo(const ec_info *ei, grand *gr)
+{
+  switch (F_TYPE(ei->c->f)) {
+    case FTY_PRIME: return (primecheck(ei, gr)); break;
+    case FTY_BINARY: return (bincheck(ei, gr)); break;
+  }
+  return ("unknown curve type");
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include "fibrand.h"
+
+int main(int argc, char *argv[])
+{
+  const ecentry *ee;
+  const char *e;
+  int ok = 1;
+  int i;
+  grand *gr;
+
+  gr = fibrand_create(0);
+  if (argc > 1) {
+    for (i = 1; i < argc; i++) {
+      ec_info ei;
+      if ((e = ec_getinfo(&ei, argv[i])) != 0)
+       fprintf(stderr, "bad curve spec `%s': %s\n", argv[i], e);
+      else {
+       e = ec_checkinfo(&ei, gr);
+       ec_freeinfo(&ei);
+       if (!e)
+         printf("OK %s\n", argv[i]);
+       else {
+         printf("BAD %s: %s\n", argv[i], e);
+         ok = 0;
+       }
+      }
+      assert(mparena_count(MPARENA_GLOBAL) == 0);
+    }
+  } else {
+    fputs("checking standard curves:", stdout);
+    fflush(stdout);
+    for (ee = ectab; ee->name; ee++) {
+      ec_info ei;
+      ec_infofromdata(&ei, ee->data);
+      e = ec_checkinfo(&ei, gr);
+      ec_freeinfo(&ei);
+      if (e) {
+       printf(" [%s fails: %s]", ee->name, e);
+       ok = 0;
+      } else
+       printf(" %s", ee->name);
+      fflush(stdout);
+      assert(mparena_count(MPARENA_GLOBAL) == 0);
+    }
+    fputs(ok ? " ok\n" : " failed\n", stdout);
+  }
+  gr->ops->destroy(gr);
+  return (!ok);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/ec-keys.h b/math/ec-keys.h
new file mode 100644 (file)
index 0000000..f4a304d
--- /dev/null
@@ -0,0 +1,96 @@
+/* -*-c-*-
+ *
+ * Elliptic curve key-fetching
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_EC_KEYS_H
+#define CATACOMB_EC_KEYS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+#ifndef CATACOMB_KEY_H
+#  include "key.h"
+#endif
+
+/*----- Key structures ----------------------------------------------------*/
+
+typedef struct ec_param {
+  ec_info ei;                          /* Curve information */
+  char *cstr;                          /* Curve definition string */
+} ec_param;
+
+typedef struct ec_pub {
+  ec_info ei;                          /* Curve information */
+  char *cstr;                          /* Curve definition string */
+  ec p;                                        /* Public point */
+} ec_pub;
+
+typedef struct ec_priv {
+  ec_info ei;                          /* Curve information */
+  char *cstr;                          /* Curve definition string */
+  ec p;                                        /* Public point */
+  mp *x;                               /* Secret exponent */
+} ec_priv;
+
+extern const key_fetchdef ec_paramfetch[];
+#define EC_PARAMFETCHSZ 3
+
+extern const key_fetchdef ec_pubfetch[];
+#define EC_PUBFETCHSZ 4
+
+extern const key_fetchdef ec_privfetch[];
+#define EC_PRIVFETCHSZ 7
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @ec_paramfree@, @ec_pubfree@, @ec_privfree@ --- *
+ *
+ * Arguments:  @ec_param *ep@, @ec_pub *ep@, @ec_priv *ep@ = pointer to
+ *                     key block to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an elliptic curve key block
+ */
+
+extern void ec_paramfree(ec_param */*ep*/);
+extern void ec_pubfree(ec_pub */*ep*/);
+extern void ec_privfree(ec_priv */*ep*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ec-prime.c b/math/ec-prime.c
new file mode 100644 (file)
index 0000000..f6a7f96
--- /dev/null
@@ -0,0 +1,449 @@
+/* -*-c-*-
+ *
+ * Elliptic curves over prime fields
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/sub.h>
+
+#include "ec.h"
+
+/*----- Simple prime curves -----------------------------------------------*/
+
+static const ec_ops ec_primeops, ec_primeprojops, ec_primeprojxops;
+
+static ec *ecneg(ec_curve *c, ec *d, const ec *p)
+{
+  EC_COPY(d, p);
+  if (d->y)
+    d->y = F_NEG(c->f, d->y, d->y);
+  return (d);
+}
+
+static ec *ecfind(ec_curve *c, ec *d, mp *x)
+{
+  mp *p, *q;
+  field *f = c->f;
+
+  q = F_SQR(f, MP_NEW, x);
+  p = F_MUL(f, MP_NEW, x, q);
+  q = F_MUL(f, q, x, c->a);
+  p = F_ADD(f, p, p, q);
+  p = F_ADD(f, p, p, c->b);
+  MP_DROP(q);
+  p = F_SQRT(f, p, p);
+  if (!p)
+    return (0);
+  EC_DESTROY(d);
+  d->x = MP_COPY(x);
+  d->y = p;
+  d->z = MP_COPY(f->one);
+  return (d);
+}
+
+static ec *ecdbl(ec_curve *c, ec *d, const ec *a)
+{
+  if (EC_ATINF(a) || F_ZEROP(c->f, a->y))
+    EC_SETINF(d);
+  else {
+    field *f = c->f;
+    mp *lambda;
+    mp *dy, *dx;
+
+    dx = F_SQR(f, MP_NEW, a->x);       /* %$x^2$% */
+    dy = F_DBL(f, MP_NEW, a->y);       /* %$2 y$% */
+    dx = F_TPL(f, dx, dx);             /* %$3 x^2$% */
+    dx = F_ADD(f, dx, dx, c->a);       /* %$3 x^2 + A$% */
+    dy = F_INV(f, dy, dy);             /* %$(2 y)^{-1}$% */
+    lambda = F_MUL(f, MP_NEW, dx, dy); /* %$\lambda = (3 x^2 + A)/(2 y)$% */
+
+    dx = F_SQR(f, dx, lambda);         /* %$\lambda^2$% */
+    dy = F_DBL(f, dy, a->x);           /* %$2 x$% */
+    dx = F_SUB(f, dx, dx, dy);         /* %$x' = \lambda^2 - 2 x */
+    dy = F_SUB(f, dy, a->x, dx);       /* %$x - x'$% */
+    dy = F_MUL(f, dy, lambda, dy);     /* %$\lambda (x - x')$% */
+    dy = F_SUB(f, dy, dy, a->y);       /* %$y' = \lambda (x - x') - y$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = 0;
+    MP_DROP(lambda);
+  }
+  return (d);
+}
+
+static ec *ecprojdbl(ec_curve *c, ec *d, const ec *a)
+{
+  if (EC_ATINF(a) || F_ZEROP(c->f, a->y))
+    EC_SETINF(d);
+  else {
+    field *f = c->f;
+    mp *p, *q, *m, *s, *dx, *dy, *dz;
+
+    p = F_SQR(f, MP_NEW, a->z);                /* %$z^2$% */
+    q = F_SQR(f, MP_NEW, p);           /* %$z^4$% */
+    p = F_MUL(f, p, q, c->a);          /* %$A z^4$% */
+    m = F_SQR(f, MP_NEW, a->x);                /* %$x^2$% */
+    m = F_TPL(f, m, m);                        /* %$3 x^2$% */
+    m = F_ADD(f, m, m, p);             /* %$m = 3 x^2 + A z^4$% */
+
+    q = F_DBL(f, q, a->y);             /* %$2 y$% */
+    dz = F_MUL(f, MP_NEW, q, a->z);    /* %$z' = 2 y z$% */
+
+    p = F_SQR(f, p, q);                        /* %$4 y^2$% */
+    s = F_MUL(f, MP_NEW, p, a->x);     /* %$s = 4 x y^2$% */
+    q = F_SQR(f, q, p);                        /* %$16 y^4$% */
+    q = F_HLV(f, q, q);                        /* %$t = 8 y^4$% */
+
+    p = F_DBL(f, p, s);                        /* %$2 s$% */
+    dx = F_SQR(f, MP_NEW, m);          /* %$m^2$% */
+    dx = F_SUB(f, dx, dx, p);          /* %$x' = m^2 - 2 s$% */
+
+    s = F_SUB(f, s, s, dx);            /* %$s - x'$% */
+    dy = F_MUL(f, p, m, s);            /* %$m (s - x')$% */
+    dy = F_SUB(f, dy, dy, q);          /* %$y' = m (s - x') - t$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = dz;
+    MP_DROP(m);
+    MP_DROP(q);
+    MP_DROP(s);
+  }
+  return (d);
+}
+
+static ec *ecprojxdbl(ec_curve *c, ec *d, const ec *a)
+{
+  if (EC_ATINF(a) || F_ZEROP(c->f, a->y))
+    EC_SETINF(d);
+  else {
+    field *f = c->f;
+    mp *p, *q, *m, *s, *dx, *dy, *dz;
+
+    m = F_SQR(f, MP_NEW, a->z);                /* %$z^2$% */
+    p = F_SUB(f, MP_NEW, a->x, m);     /* %$x - z^2$% */
+    q = F_ADD(f, MP_NEW, a->x, m);     /* %$x + z^2$% */
+    m = F_MUL(f, m, p, q);             /* %$x^2 - z^4$% */
+    m = F_TPL(f, m, m);                        /* %$m = 3 x^2 - 3 z^4$% */
+
+    q = F_DBL(f, q, a->y);             /* %$2 y$% */
+    dz = F_MUL(f, MP_NEW, q, a->z);    /* %$z' = 2 y z$% */
+
+    p = F_SQR(f, p, q);                        /* %$4 y^2$% */
+    s = F_MUL(f, MP_NEW, p, a->x);     /* %$s = 4 x y^2$% */
+    q = F_SQR(f, q, p);                        /* %$16 y^4$% */
+    q = F_HLV(f, q, q);                        /* %$t = 8 y^4$% */
+
+    p = F_DBL(f, p, s);                        /* %$2 s$% */
+    dx = F_SQR(f, MP_NEW, m);          /* %$m^2$% */
+    dx = F_SUB(f, dx, dx, p);          /* %$x' = m^2 - 2 s$% */
+
+    s = F_SUB(f, s, s, dx);            /* %$s - x'$% */
+    dy = F_MUL(f, p, m, s);            /* %$m (s - x')$% */
+    dy = F_SUB(f, dy, dy, q);          /* %$y' = m (s - x') - t$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = dz;
+    MP_DROP(m);
+    MP_DROP(q);
+    MP_DROP(s);
+  }
+  return (d);
+}
+
+static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b)
+{
+  if (a == b)
+    ecdbl(c, d, a);
+  else if (EC_ATINF(a))
+    EC_COPY(d, b);
+  else if (EC_ATINF(b))
+    EC_COPY(d, a);
+  else {
+    field *f = c->f;
+    mp *lambda;
+    mp *dy, *dx;
+
+    if (!MP_EQ(a->x, b->x)) {
+      dy = F_SUB(f, MP_NEW, a->y, b->y); /* %$y_0 - y_1$% */
+      dx = F_SUB(f, MP_NEW, a->x, b->x); /* %$x_0 - x_1$% */
+      dx = F_INV(f, dx, dx);           /* %$(x_0 - x_1)^{-1}$% */
+      lambda = F_MUL(f, MP_NEW, dy, dx);
+                                  /* %$\lambda = (y_0 - y1)/(x_0 - x_1)$% */
+    } else if (F_ZEROP(c->f, a->y) || !MP_EQ(a->y, b->y)) {
+      EC_SETINF(d);
+      return (d);
+    } else {
+      dx = F_SQR(f, MP_NEW, a->x);     /* %$x_0^2$% */
+      dx = F_TPL(f, dx, dx);           /* %$3 x_0^2$% */
+      dx = F_ADD(f, dx, dx, c->a);     /* %$3 x_0^2 + A$% */
+      dy = F_DBL(f, MP_NEW, a->y);     /* %$2 y_0$% */
+      dy = F_INV(f, dy, dy);           /* %$(2 y_0)^{-1}$% */
+      lambda = F_MUL(f, MP_NEW, dx, dy);
+                                   /* %$\lambda = (3 x_0^2 + A)/(2 y_0)$% */
+    }
+
+    dx = F_SQR(f, dx, lambda);         /* %$\lambda^2$% */
+    dx = F_SUB(f, dx, dx, a->x);       /* %$\lambda^2 - x_0$% */
+    dx = F_SUB(f, dx, dx, b->x);       /* %$x' = \lambda^2 - x_0 - x_1$% */
+    dy = F_SUB(f, dy, b->x, dx);       /* %$x_1 - x'$% */
+    dy = F_MUL(f, dy, lambda, dy);     /* %$\lambda (x_1 - x')$% */
+    dy = F_SUB(f, dy, dy, b->y);      /* %$y' = \lambda (x_1 - x') - y_1$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = 0;
+    MP_DROP(lambda);
+  }
+  return (d);
+}
+
+static ec *ecprojadd(ec_curve *c, ec *d, const ec *a, const ec *b)
+{
+  if (a == b)
+    c->ops->dbl(c, d, a);
+  else if (EC_ATINF(a))
+    EC_COPY(d, b);
+  else if (EC_ATINF(b))
+    EC_COPY(d, a);
+  else {
+    field *f = c->f;
+    mp *p, *q, *r, *w, *u, *uu, *s, *ss, *dx, *dy, *dz;
+
+    q = F_SQR(f, MP_NEW, a->z);                /* %$z_0^2$% */
+    u = F_MUL(f, MP_NEW, q, b->x);     /* %$u = x_1 z_0^2$% */
+    p = F_MUL(f, MP_NEW, q, b->y);     /* %$y_1 z_0^2$% */
+    s = F_MUL(f, q, p, a->z);          /* %$s = y_1 z_0^3$% */
+
+    q = F_SQR(f, MP_NEW, b->z);                /* %$z_1^2$% */
+    uu = F_MUL(f, MP_NEW, q, a->x);    /* %$uu = x_0 z_1^2$%*/
+    p = F_MUL(f, p, q, a->y);          /* %$y_0 z_1^2$% */
+    ss = F_MUL(f, q, p, b->z);         /* %$ss = y_0 z_1^3$% */
+
+    w = F_SUB(f, p, uu, u);            /* %$w = uu - u$% */
+    r = F_SUB(f, MP_NEW, ss, s);       /* %$r = ss - s$% */
+    if (F_ZEROP(f, w)) {
+      MP_DROP(w);
+      MP_DROP(u);
+      MP_DROP(s);
+      MP_DROP(uu);
+      MP_DROP(ss);
+      if (F_ZEROP(f, r)) {
+       MP_DROP(r);
+       return (c->ops->dbl(c, d, a));
+      } else {
+       MP_DROP(r);
+       EC_SETINF(d);
+       return (d);
+      }
+    }
+    u = F_ADD(f, u, u, uu);            /* %$t = uu + u$% */
+    s = F_ADD(f, s, s, ss);            /* %$m = ss + r$% */
+
+    uu = F_MUL(f, uu, a->z, w);                /* %$z_0 w$% */
+    dz = F_MUL(f, ss, uu, b->z);       /* %$z' = z_0 z_1 w$% */
+
+    p = F_SQR(f, uu, w);               /* %$w^2$% */
+    q = F_MUL(f, MP_NEW, p, u);                /* %$t w^2$% */
+    u = F_MUL(f, u, p, w);             /* %$w^3$% */
+    p = F_MUL(f, p, u, s);             /* %$m w^3$% */
+
+    dx = F_SQR(f, u, r);               /* %$r^2$% */
+    dx = F_SUB(f, dx, dx, q);          /* %$x' = r^2 - t w^2$% */
+
+    s = F_DBL(f, s, dx);               /* %$2 x'$% */
+    q = F_SUB(f, q, q, s);             /* %$v = t w^2 - 2 x'$% */
+    dy = F_MUL(f, s, q, r);            /* %$v r$% */
+    dy = F_SUB(f, dy, dy, p);          /* %$v r - m w^3$% */
+    dy = F_HLV(f, dy, dy);             /* %$y' = (v r - m w^3)/2$% */
+
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = dz;
+    MP_DROP(p);
+    MP_DROP(q);
+    MP_DROP(r);
+    MP_DROP(w);
+  }
+  return (d);
+}
+
+static int eccheck(ec_curve *c, const ec *p)
+{
+  field *f = c->f;
+  mp *l, *x, *r;
+  int rc;
+  if (EC_ATINF(p)) return (0);
+  l = F_SQR(f, MP_NEW, p->y);
+  x = F_SQR(f, MP_NEW, p->x);
+  r = F_MUL(f, MP_NEW, x, p->x);
+  x = F_MUL(f, x, c->a, p->x);
+  r = F_ADD(f, r, r, x);
+  r = F_ADD(f, r, r, c->b);
+  rc = MP_EQ(l, r) ? 0 : -1;
+  mp_drop(l);
+  mp_drop(x);
+  mp_drop(r);
+  return (rc);
+}
+
+static int ecprojcheck(ec_curve *c, const ec *p)
+{
+  ec t = EC_INIT;
+  int rc;
+
+  c->ops->fix(c, &t, p);
+  rc = eccheck(c, &t);
+  EC_DESTROY(&t);
+  return (rc);
+}
+
+static void ecdestroy(ec_curve *c)
+{
+  MP_DROP(c->a);
+  MP_DROP(c->b);
+  DESTROY(c);
+}
+
+/* --- @ec_prime@, @ec_primeproj@ --- *
+ *
+ * Arguments:  @field *f@ = the underlying field for this elliptic curve
+ *             @mp *a, *b@ = the coefficients for this curve
+ *
+ * Returns:    A pointer to the curve, or null.
+ *
+ * Use:                Creates a curve structure for an elliptic curve defined over
+ *             a prime field.  The @primeproj@ variant uses projective
+ *             coordinates, which can be a win.
+ */
+
+extern ec_curve *ec_prime(field *f, mp *a, mp *b)
+{
+  ec_curve *c = CREATE(ec_curve);
+  c->ops = &ec_primeops;
+  c->f = f;
+  c->a = F_IN(f, MP_NEW, a);
+  c->b = F_IN(f, MP_NEW, b);
+  return (c);
+}
+
+extern ec_curve *ec_primeproj(field *f, mp *a, mp *b)
+{
+  ec_curve *c = CREATE(ec_curve);
+  mp *ax;
+
+  ax = mp_add(MP_NEW, a, MP_THREE);
+  ax = F_IN(f, ax, ax);
+  if (F_ZEROP(f, ax))
+    c->ops = &ec_primeprojxops;
+  else
+    c->ops = &ec_primeprojops;
+  MP_DROP(ax);
+  c->f = f;
+  c->a = F_IN(f, MP_NEW, a);
+  c->b = F_IN(f, MP_NEW, b);
+  return (c);
+}
+
+static const ec_ops ec_primeops = {
+  "prime",
+  ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix,
+  ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck
+};
+
+static const ec_ops ec_primeprojops = {
+  "primeproj",
+  ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix,
+  ecfind, ecneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck
+};
+
+static const ec_ops ec_primeprojxops = {
+  "primeproj",
+  ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix,
+  ecfind, ecneg, ecprojadd, ec_stdsub, ecprojxdbl, ecprojcheck
+};
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
+
+int main(int argc, char *argv[])
+{
+  field *f;
+  ec_curve *c;
+  ec g = EC_INIT, d = EC_INIT;
+  mp *p, *a, *b, *r;
+  int i, n = argc == 1 ? 1 : atoi(argv[1]);
+
+  printf("ec-prime: ");
+  fflush(stdout);
+  a = MP(-3);
+  b = MP(0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef);
+  p = MP(39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319);
+  r = MP(39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942642);
+
+  f = field_niceprime(p);
+  c = ec_primeproj(f, a, b);
+
+  g.x = MP(0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7);
+  g.y = MP(0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f);
+
+  for (i = 0; i < n; i++) {
+    ec_mul(c, &d, &g, r);
+    if (EC_ATINF(&d)) {
+      fprintf(stderr, "zero too early\n");
+      return (1);
+    }
+    ec_add(c, &d, &d, &g);
+    if (!EC_ATINF(&d)) {
+      fprintf(stderr, "didn't reach zero\n");
+      MP_EPRINT("d.x", d.x);
+      MP_EPRINT("d.y", d.y);
+      return (1);
+    }
+    ec_destroy(&d);
+  }
+  ec_destroy(&g);
+  ec_destroycurve(c);
+  F_DESTROY(f);
+  MP_DROP(p); MP_DROP(a); MP_DROP(b); MP_DROP(r);
+  assert(!mparena_count(&mparena_global));
+  printf("ok\n");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/ec-raw.c b/math/ec-raw.c
new file mode 100644 (file)
index 0000000..54310c8
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*-c-*-
+ *
+ * Raw formatting of elliptic curve points
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "ec.h"
+#include "ec-raw.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @ec_putraw@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = elliptic curve
+ *             @buf *b@ = pointer to a buffer
+ *             @const ec *p@ = an elliptic curve point
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Puts an elliptic curve point to the given buffer using the
+ *             standard uncompressed format described in P1383 and SEC1.
+ *             This requires at most @1 + 2 * c->f->noctets@ space in the
+ *             buffer.  We don't do point compression.
+ */
+
+int ec_putraw(ec_curve *c, buf *b, const ec *p)
+{
+  octet *q;
+  size_t n;
+
+  if (EC_ATINF(p)) return (buf_putbyte(b, 0));
+  buf_putbyte(b, 4);
+  n = c->f->noctets;
+  if ((q = buf_get(b, n * 2)) == 0) return (-1);
+  mp_storeb(p->x, q, n);
+  mp_storeb(p->y, q + n, n);
+  return (0);
+}
+
+/* --- @ec_getraw@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = elliptic curve
+ *             @buf *b@ = pointer to a buffer
+ *             @ec *d@ = an elliptic curve point
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Reads an elliptic curve point from the given buffer using the
+ *             standard uncompressed format described in P1383 and SEC1.
+ *             We don't do point compression.
+ */
+
+int ec_getraw(ec_curve *c, buf *b, ec *d)
+{
+  const octet *q;
+  size_t n;
+  int u;
+
+  if ((u = buf_getbyte(b)) < 0) return (-1);
+  if (!u) { EC_SETINF(d); return (0); }
+  if (!(u & 4)) return (-1);
+  n = c->f->noctets;
+  if ((q = buf_get(b, n * 2)) == 0) return (-1);
+  EC_DESTROY(d);
+  d->x = mp_loadb(MP_NEW, q, n);
+  d->y = mp_loadb(MP_NEW, q + n, n);
+  d->z = 0;
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/ec-raw.h b/math/ec-raw.h
new file mode 100644 (file)
index 0000000..4792bd7
--- /dev/null
@@ -0,0 +1,83 @@
+/* -*-c-*-
+ *
+ * Raw formatting of elliptic curve points
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_EC_RAW_H
+#define CATACOMB_EC_RAW_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_BUF_H
+#  include "buf.h"
+#endif
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+/*----- Data formatting ---------------------------------------------------*/
+
+/* --- @ec_putraw@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = elliptic curve
+ *             @buf *b@ = pointer to a buffer
+ *             @const ec *p@ = an elliptic curve point
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Puts an elliptic curve point to the given buffer using the
+ *             standard uncompressed format described in P1383 and SEC1.
+ *             We don't do point compression.
+ */
+
+extern int ec_putraw(ec_curve */*c*/, buf */*b*/, const ec */*p*/);
+
+/* --- @ec_getraw@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = elliptic curve
+ *             @buf *b@ = pointer to a buffer
+ *             @ec *d@ = an elliptic curve point
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Reads an elliptic curve point from the given buffer using the
+ *             standard uncompressed format described in P1383 and SEC1.
+ *             We don't do point compression.
+ */
+
+extern int ec_getraw(ec_curve */*c*/, buf */*b*/, ec */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ec-test.c b/math/ec-test.c
new file mode 100644 (file)
index 0000000..db59294
--- /dev/null
@@ -0,0 +1,345 @@
+/* -*-c-*-
+ *
+ * Code for testing elliptic-curve stuff
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/testrig.h>
+#include <mLib/sub.h>
+
+#include "ec.h"
+#include "ec-test.h"
+
+/*----- Cardboard cut-out elliptic curve ----------------------------------*/
+
+typedef struct ecctx {
+  ec_curve c;
+  unsigned long magic;
+  char *name;
+  ec_curve *real;
+} ecctx;
+
+#define MAGIC 0x3a1f0b07
+
+static void ecDESTROY(ec_curve *cc)
+{
+  ecctx *c = (ecctx *)cc;
+  xfree(c->name);
+  ec_destroycurve(c->real);
+  DESTROY(c);
+}
+
+#define UNOP(OP)                                                       \
+  static ec *ec##OP(ec_curve *cc, ec *d, const ec *p) {                        \
+    ecctx *c = (ecctx *)cc;                                            \
+    return (EC_##OP(c->real, d, p));                                   \
+  }
+
+#define BINOP(OP)                                                      \
+  static ec *ec##OP(ec_curve *cc, ec *d, const ec *p, const ec *q) {   \
+    ecctx *c = (ecctx *)cc;                                            \
+    return (EC_##OP(c->real, d, p, q));                                        \
+  }
+
+UNOP(IN)
+UNOP(OUT)
+UNOP(FIX)
+UNOP(NEG)
+UNOP(DBL)
+BINOP(ADD)
+BINOP(SUB)
+
+#undef UNOP
+#undef BINOP
+
+static ec *ecFIND(ec_curve *cc, ec *d, mp *x)
+{
+  ecctx *c = (ecctx *)cc;
+  return (EC_FIND(c->real, d, x));
+}
+
+static int ecCHECK(ec_curve *cc, const ec *p)
+{
+  ecctx *c = (ecctx *)cc;
+  return (EC_CHECK(c->real, p));
+}
+
+static int ecSAMEP(ec_curve *cc, ec_curve *dd)
+{
+  ecctx *c = (ecctx *)cc, *d = (ecctx *)dd;
+  return (ec_samep(c->real, d->real));
+}
+
+static const ec_ops ecops = {
+  "cardboard",
+  ecDESTROY, ecSAMEP, ecIN, ecOUT, ecFIX,
+  ecFIND, ecNEG, ecADD, ecSUB, ecDBL, ecCHECK
+};
+
+static ec_curve *ec_cutout(ec_curve *real, const char *name)
+{
+  ecctx *c = CREATE(ecctx);
+  c->c.f = real->f;
+  c->c.ops = &ecops;
+  c->c.a = real->a;
+  c->c.b = real->b;
+  c->magic = MAGIC;
+  c->name = xstrdup(name);
+  c->real = real;
+  return (&c->c);
+}
+
+static const char *ec_name(ec_curve *cc)
+{
+  ecctx *c = (ecctx *)cc;
+  assert(c->magic == MAGIC);
+  return (c->name);
+}
+
+/*----- Test field types --------------------------------------------------*/
+
+static void ecvcvt(const char *buf, dstr *d)
+{
+  ec_curve *v;
+  qd_parse qd;
+
+  qd.p = buf;
+  qd.e = 0;
+  if ((v = ec_curveparse(&qd)) == 0) {
+    fprintf(stderr, "bad curve `%.*s|%s': %s\n",
+           qd.p - buf, buf, qd.p, qd.e);
+    exit(1);
+  }
+  dstr_ensure(d, sizeof(v));
+  *(ec_curve **)d->buf = ec_cutout(v, buf);
+  d->len += sizeof(v);
+}
+
+static void ecvdump(dstr *d, FILE *fp)
+{
+  ec_curve *v = *(ec_curve **)d->buf;
+  fprintf(fp, "%s", ec_name(v));
+}
+
+const test_type type_ecurve = { ecvcvt, ecvdump };
+
+static void eccvt(const char *p, dstr *d)
+{
+  ec *a;
+  qd_parse qd;
+
+  qd.p = p;
+  qd.e = 0;
+  dstr_ensure(d, sizeof(ec));
+  a = (ec *)d->buf;
+  d->len += sizeof(ec);
+  ec_create(a);
+  if (!ec_ptparse(&qd, a)) {
+    fprintf(stderr, "bad point `%.*s|%s': %s\n", qd.p - p, p, qd.p, qd.e);
+    exit(1);
+  }
+}
+
+static void ecdodump(ec *a, FILE *fp)
+{
+  if (EC_ATINF(a))
+    fputs("inf", fp);
+  else {
+    fputs("0x", fp);
+    mp_writefile(a->x, fp, 16);
+    fputs(", 0x", fp);
+    mp_writefile(a->y, fp, 16);
+  }
+}
+
+static void ecdump(dstr *d, FILE *fp)
+{
+  ec *a = (ec *)d->buf;
+  ecdodump(a, fp);
+}
+
+const test_type type_ec = { eccvt, ecdump };
+
+/*----- Testing elliptic curve functionality ------------------------------*/
+
+#ifdef TEST_RIG
+
+static void ecdestroy(ec_curve *c)
+{
+  field *f = c->f;
+  ec_destroycurve(c);
+  F_DESTROY(f);
+}
+
+#define UNOP(op)                                                       \
+  static int v##op(dstr v[])                                           \
+  {                                                                    \
+    ec_curve *e = *(ec_curve **)v[0].buf;                              \
+    ec *a = (ec *)v[1].buf;                                            \
+    ec *r = (ec *)v[2].buf;                                            \
+    ec c = EC_INIT;                                                    \
+    int ok = 1;                                                                \
+    ec_##op(e, &c, a);                                                 \
+    if (!EC_EQ(r, &c)) {                                               \
+      fprintf(stderr, #op "failed");                                   \
+      fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);      \
+      fprintf(stderr, "\n    a = "); ecdodump(a, stderr);              \
+      fprintf(stderr, "\n    r = "); ecdodump(r, stderr);              \
+      fprintf(stderr, "\n    c = "); ecdodump(&c, stderr);             \
+      fprintf(stderr, "\n");                                           \
+      ok = 0;                                                          \
+    }                                                                  \
+    EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c);                      \
+    ecdestroy(e);                                                      \
+    return (ok);                                                       \
+  }
+
+#define BINOP(op)                                                      \
+  static int v##op(dstr v[])                                           \
+  {                                                                    \
+    ec_curve *e = *(ec_curve **)v[0].buf;                              \
+    ec *a = (ec *)v[1].buf;                                            \
+    ec *b = (ec *)v[2].buf;                                            \
+    ec *r = (ec *)v[3].buf;                                            \
+    ec c = EC_INIT;                                                    \
+    int ok = 1;                                                                \
+    ec_##op(e, &c, a, b);                                              \
+    if (!EC_EQ(r, &c)) {                                               \
+      fprintf(stderr, #op "failed");                                   \
+      fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);      \
+      fprintf(stderr, "\n    a = "); ecdodump(a, stderr);              \
+      fprintf(stderr, "\n    b = "); ecdodump(b, stderr);              \
+      fprintf(stderr, "\n    r = "); ecdodump(r, stderr);              \
+      fprintf(stderr, "\n    c = "); ecdodump(&c, stderr);             \
+      fprintf(stderr, "\n");                                           \
+      ok = 0;                                                          \
+    }                                                                  \
+    EC_DESTROY(a); EC_DESTROY(b); EC_DESTROY(r); EC_DESTROY(&c);       \
+    ecdestroy(e);                                                      \
+    return (ok);                                                       \
+  }
+
+UNOP(neg)
+UNOP(dbl)
+BINOP(add)
+BINOP(sub)
+
+static int vcheck(dstr v[])
+{
+  ec_curve *e = *(ec_curve **)v[0].buf;
+  ec *a = (ec *)v[1].buf;
+  int r = *(int *)v[2].buf;
+  int c;
+  int ok = 1;
+  c = ec_check(e, a);
+  if (r != c) {
+    fprintf(stderr, "check failed");
+    fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
+    fprintf(stderr, "\n           a = "); ecdodump(a, stderr);
+    fprintf(stderr, "\n           r = %d", r);
+    fprintf(stderr, "\n           c = %d", c);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  EC_DESTROY(a);
+  ecdestroy(e);
+  return (ok);
+}
+
+static int vmul(dstr v[])
+{
+  ec_curve *e = *(ec_curve **)v[0].buf;
+  ec *a = (ec *)v[1].buf;
+  mp *n = *(mp **)v[2].buf;
+  ec *r = (ec *)v[3].buf;
+  ec c = EC_INIT;
+  int ok = 1;
+  ec_mul(e, &c, a, n);
+  if (!EC_EQ(r, &c)) {
+    fprintf(stderr, "mul failed");
+    fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
+    fprintf(stderr, "\n           a = "); ecdodump(a, stderr);
+    fprintf(stderr, "\n           n = "); mp_writefile(n, stderr, 10);
+    fprintf(stderr, "\n           r = "); ecdodump(r, stderr);
+    fprintf(stderr, "\n           c = "); ecdodump(&c, stderr);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  EC_DESTROY(a); EC_DESTROY(r); EC_DESTROY(&c); MP_DROP(n);
+  ecdestroy(e);
+  return (ok);
+}
+
+static int vfind(dstr v[])
+{
+  ec_curve *e = *(ec_curve **)v[0].buf;
+  mp *x = *(mp **)v[1].buf;
+  ec *r = (ec *)v[2].buf;
+  ec c = EC_INIT;
+  int ok = 1;
+  if (!ec_find(e, &c, x)) EC_SETINF(&c);
+  if (!EC_EQ(r, &c)) {
+    fprintf(stderr, "find failed");
+    fprintf(stderr, "\ncurve = "); type_ecurve.dump(v, stderr);
+    fprintf(stderr, "\n           x = "); mp_writefile(x, stderr, 16);
+    fprintf(stderr, "\n           r = "); ecdodump(r, stderr);
+    fprintf(stderr, "\n           c = "); ecdodump(&c, stderr);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  MP_DROP(x); EC_DESTROY(r); EC_DESTROY(&c);
+  ecdestroy(e);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "neg", vneg, { &type_ecurve, &type_ec, &type_ec } },
+  { "dbl", vdbl, { &type_ecurve, &type_ec, &type_ec } },
+  { "add", vadd, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
+  { "sub", vsub, { &type_ecurve, &type_ec, &type_ec, &type_ec } },
+  { "mul", vmul, { &type_ecurve, &type_ec, &type_mp, &type_ec } },
+  { "check", vcheck, { &type_ecurve, &type_ec, &type_int } },
+  { "find", vfind, { &type_ecurve, &type_mp, &type_ec } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/ec");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/ec-test.h b/math/ec-test.h
new file mode 100644 (file)
index 0000000..4fd71e1
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*-c-*-
+ *
+ * Elliptic curve test functions
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_EC_TEST_H
+#define CATACOMB_EC_TEST_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/testrig.h>
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+/*----- Test vector types -------------------------------------------------*/
+
+extern const test_type type_ecurve, type_ec;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ec.c b/math/ec.c
new file mode 100644 (file)
index 0000000..f8b77f5
--- /dev/null
+++ b/math/ec.c
@@ -0,0 +1,422 @@
+/* -*-c-*-
+ *
+ * Elliptic curve definitions
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "ec.h"
+
+/*----- Trivial wrappers --------------------------------------------------*/
+
+/* --- @ec_samep@ --- *
+ *
+ * Arguments:  @ec_curve *c, *d@ = two elliptic curves
+ *
+ * Returns:    Nonzero if the curves are identical (not just isomorphic).
+ *
+ * Use:                Checks for sameness of curves.  This function does the full
+ *             check, not just the curve-type-specific check done by the
+ *             @sampep@ field operation.
+ */
+
+int ec_samep(ec_curve *c, ec_curve *d)
+{
+  return (c == d || (field_samep(c->f, d->f) &&
+                    c->ops == d->ops && EC_SAMEP(c, d)));
+}
+
+/* --- @ec_create@ --- *
+ *
+ * Arguments:  @ec *p@ = pointer to an elliptic-curve point
+ *
+ * Returns:    The argument @p@.
+ *
+ * Use:                Initializes a new point.  The initial value is the additive
+ *             identity (which is universal for all curves).
+ */
+
+ec *ec_create(ec *p) { EC_CREATE(p); return (p); }
+
+/* --- @ec_destroy@ --- *
+ *
+ * Arguments:  @ec *p@ = pointer to an elliptic-curve point
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a point, making it invalid.
+ */
+
+void ec_destroy(ec *p) { EC_DESTROY(p); }
+
+/* --- @ec_atinf@ --- *
+ *
+ * Arguments:  @const ec *p@ = pointer to a point
+ *
+ * Returns:    Nonzero if %$p = O$% is the point at infinity, zero
+ *             otherwise.
+ */
+
+int ec_atinf(const ec *p) { return (EC_ATINF(p)); }
+
+/* --- @ec_setinf@ --- *
+ *
+ * Arguments:  @ec *p@ = pointer to a point
+ *
+ * Returns:    The argument @p@.
+ *
+ * Use:                Sets the given point to be the point %$O$% at infinity.
+ */
+
+ec *ec_setinf(ec *p) { EC_SETINF(p); return (p); }
+
+/* --- @ec_copy@ --- *
+ *
+ * Arguments:  @ec *d@ = pointer to destination point
+ *             @const ec *p@ = pointer to source point
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Creates a copy of an elliptic curve point.
+ */
+
+ec *ec_copy(ec *d, const ec *p) { EC_COPY(d, p); return (d); }
+
+/* --- @ec_eq@ --- *
+ *
+ * Arguments:  @const ec *p, *q@ = two points
+ *
+ * Returns:    Nonzero if the points are equal.  Compares external-format
+ *             points.
+ */
+
+int ec_eq(const ec *p, const ec *q) { return (EC_EQ(p, q)); }
+
+/*----- Standard curve operations -----------------------------------------*/
+
+/* --- @ec_stdsamep@ --- *
+ *
+ * Arguments:  @ec_curve *c, *d@ = two elliptic curves
+ *
+ * Returns:    Nonzero if the curves are identical (not just isomorphic).
+ *
+ * Use:                Simple sameness check on @a@ and @b@ curve members.
+ */
+
+int ec_stdsamep(ec_curve *c, ec_curve *d)
+  { return (MP_EQ(c->a, d->a) && MP_EQ(c->b, d->b)); }
+
+/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination
+ *             @const ec *p@ = pointer to a source point
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                An identity operation if your curve has no internal
+ *             representation.  (The field internal representation is still
+ *             used.)
+ */
+
+ec *ec_idin(ec_curve *c, ec *d, const ec *p)
+{
+  if (EC_ATINF(p))
+    EC_SETINF(d);
+  else {
+    field *f = c->f;
+    d->x = F_IN(f, d->x, p->x);
+    d->y = F_IN(f, d->y, p->y);
+    mp_drop(d->z); d->z = 0;
+  }
+  return (d);
+}
+
+ec *ec_idout(ec_curve *c, ec *d, const ec *p)
+{
+  if (EC_ATINF(p))
+    EC_SETINF(d);
+  else {
+    field *f = c->f;
+    d->x = F_OUT(f, d->x, p->x);
+    d->y = F_OUT(f, d->y, p->y);
+    mp_drop(d->z); d->z = 0;
+  }
+  return (d);
+}
+
+ec *ec_idfix(ec_curve *c, ec *d, const ec *p)
+  { EC_COPY(d, p); return (d); }
+
+/* --- @ec_projin@, @ec_projout@, @ec_projfix@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination
+ *             @const ec *p@ = pointer to a source point
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Conversion functions if your curve operations use a
+ *             projective representation.
+ */
+
+ec *ec_projin(ec_curve *c, ec *d, const ec *p)
+{
+  if (EC_ATINF(p))
+    EC_SETINF(d);
+  else {
+    field *f = c->f;
+    d->x = F_IN(f, d->x, p->x);
+    d->y = F_IN(f, d->y, p->y);
+    mp_drop(d->z); d->z = MP_COPY(f->one);
+  }
+  return (d);
+}
+
+ec *ec_projout(ec_curve *c, ec *d, const ec *p)
+{
+  if (EC_ATINF(p))
+    EC_SETINF(d);
+  else {
+    mp *x, *y, *z, *zz;
+    field *f = c->f;
+    if (p->z == f->one) {
+      d->x = F_OUT(f, d->x, p->x);
+      d->y = F_OUT(f, d->y, p->y);
+    } else {
+      z = F_INV(f, MP_NEW, p->z);
+      zz = F_SQR(f, MP_NEW, z);
+      z = F_MUL(f, z, zz, z);
+      x = F_MUL(f, d->x, p->x, zz);
+      y = F_MUL(f, d->y, p->y, z);
+      mp_drop(z);
+      mp_drop(zz);
+      d->x = F_OUT(f, x, x);
+      d->y = F_OUT(f, y, y);
+    }
+    mp_drop(d->z);
+    d->z = 0;
+  }
+  return (d);
+}
+
+ec *ec_projfix(ec_curve *c, ec *d, const ec *p)
+{
+  if (EC_ATINF(p))
+    EC_SETINF(d);
+  else if (p->z == c->f->one)
+    EC_COPY(d, p);
+  else {
+    mp *z, *zz;
+    field *f = c->f;
+    z = F_INV(f, MP_NEW, p->z);
+    zz = F_SQR(f, MP_NEW, z);
+    z = F_MUL(f, z, zz, z);
+    d->x = F_MUL(f, d->x, p->x, zz);
+    d->y = F_MUL(f, d->y, p->y, z);
+    mp_drop(z);
+    mp_drop(zz);
+    mp_drop(d->z);
+    d->z = MP_COPY(f->one);
+  }
+  return (d);
+}
+
+/* --- @ec_stdsub@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination
+ *             @const ec *p, *q@ = the operand points
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Standard point subtraction operation, in terms of negation
+ *             and addition.  This isn't as efficient as a ready-made
+ *             subtraction operator.
+ */
+
+ec *ec_stdsub(ec_curve *c, ec *d, const ec *p, const ec *q)
+{
+  ec t = EC_INIT;
+  EC_NEG(c, &t, q);
+  EC_FIX(c, &t, &t);
+  EC_ADD(c, d, p, &t);
+  EC_DESTROY(&t);
+  return (d);
+}
+
+/*----- Creating curves ---------------------------------------------------*/
+
+/* --- @ec_destroycurve@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an ellptic curve
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a description of an elliptic curve.
+ */
+
+void ec_destroycurve(ec_curve *c) { c->ops->destroy(c); }
+
+/*----- Real arithmetic ---------------------------------------------------*/
+
+/* --- @ec_find@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @mp *x@ = a possible x-coordinate
+ *
+ * Returns:    Zero if OK, nonzero if there isn't a point there.
+ *
+ * Use:                Finds a point on an elliptic curve with a given x-coordinate.
+ */
+
+ec *ec_find(ec_curve *c, ec *d, mp *x)
+{
+  x = F_IN(c->f, MP_NEW, x);
+  if ((d = EC_FIND(c, d, x)) != 0)
+    EC_OUT(c, d, d);
+  MP_DROP(x);
+  return (d);
+}
+
+/* --- @ec_neg@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p@ = pointer to the operand point
+ *
+ * Returns:    The destination point.
+ *
+ * Use:                Computes the negation of the given point.
+ */
+
+ec *ec_neg(ec_curve *c, ec *d, const ec *p)
+  { EC_IN(c, d, p); EC_NEG(c, d, d); return (EC_OUT(c, d, d)); }
+
+/* --- @ec_add@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p, *q@ = pointers to the operand points
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds two points on an elliptic curve.
+ */
+
+ec *ec_add(ec_curve *c, ec *d, const ec *p, const ec *q)
+{
+  ec pp = EC_INIT, qq = EC_INIT;
+  EC_IN(c, &pp, p);
+  EC_IN(c, &qq, q);
+  EC_ADD(c, d, &pp, &qq);
+  EC_OUT(c, d, d);
+  EC_DESTROY(&pp);
+  EC_DESTROY(&qq);
+  return (d);
+}
+
+/* --- @ec_sub@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p, *q@ = pointers to the operand points
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Subtracts one point from another on an elliptic curve.
+ */
+
+ec *ec_sub(ec_curve *c, ec *d, const ec *p, const ec *q)
+{
+  ec pp = EC_INIT, qq = EC_INIT;
+  EC_IN(c, &pp, p);
+  EC_IN(c, &qq, q);
+  EC_SUB(c, d, &pp, &qq);
+  EC_OUT(c, d, d);
+  EC_DESTROY(&pp);
+  EC_DESTROY(&qq);
+  return (d);
+}
+
+/* --- @ec_dbl@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p@ = pointer to the operand point
+ *
+ * Returns:    ---
+ *
+ * Use:                Doubles a point on an elliptic curve.
+ */
+
+ec *ec_dbl(ec_curve *c, ec *d, const ec *p)
+  { EC_IN(c, d, p); EC_DBL(c, d, d); return (EC_OUT(c, d, d)); }
+
+/* --- @ec_check@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @const ec *p@ = pointer to the point
+ *
+ * Returns:    Zero if OK, nonzero if this is an invalid point.
+ *
+ * Use:                Checks that a point is actually on an elliptic curve.
+ */
+
+int ec_check(ec_curve *c, const ec *p)
+{
+  ec t = EC_INIT;
+  int rc;
+
+  if (EC_ATINF(p))
+    return (0);
+  EC_IN(c, &t, p);
+  rc = EC_CHECK(c, &t);
+  EC_DESTROY(&t);
+  return (rc);
+}
+
+/* --- @ec_rand@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @grand *r@ = random number source
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Finds a random point on the given curve.
+ */
+
+ec *ec_rand(ec_curve *c, ec *d, grand *r)
+{
+  mp *x = MP_NEW;
+  do x = F_RAND(c->f, x, r); while (!EC_FIND(c, d, x));
+  mp_drop(x);
+  if (grand_range(r, 2)) EC_NEG(c, d, d);
+  return (EC_OUT(c, d, d));
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/ec.h b/math/ec.h
new file mode 100644 (file)
index 0000000..cc7649d
--- /dev/null
+++ b/math/ec.h
@@ -0,0 +1,616 @@
+/* -*-c-*-
+ *
+ * Elliptic curve definitions
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_EC_H
+#define CATACOMB_EC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_FIELD_H
+#  include "field.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_QDPARSE_H
+#  include "qdparse.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- An elliptic curve representation --- */
+
+typedef struct ec_curve {
+  const struct ec_ops *ops;            /* Curve operations */
+  field *f;                            /* Underlying field structure */
+  mp *a, *b;                           /* Standard params (internal form) */
+} ec_curve;
+
+/* --- An elliptic curve point --- */
+
+typedef struct ec {
+  mp *x, *y;                           /* Point coordinates */
+  mp *z;                               /* Common denominator (or null) */
+} ec;
+
+/* --- A factor for simultaneous multiplication --- */
+
+typedef struct ec_mulfactor {
+  ec base;                             /* The point */
+  mp *exp;                             /* The exponent */
+} ec_mulfactor;
+
+/* --- Elliptic curve operations --- *
+ *
+ * All operations (apart from @destroy@ and @in@) are guaranteed to be
+ * performed on internal representations of points.
+ *
+ * (Historical note.  We used to guarantee that the second to @add@ and @mul@
+ * was the output of @in@ or @fix@, but this canonification turned out to
+ * make the precomputation in @ec_exp@ too slow.  Projective implementations
+ * must therefore cope with a pair of arbitrary points.)
+ */
+
+typedef struct ec_ops {
+  const char *name;
+  void (*destroy)(ec_curve */*c*/);
+  int (*samep)(ec_curve */*c*/, ec_curve */*d*/);
+  ec *(*in)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+  ec *(*out)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+  ec *(*fix)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+  ec *(*find)(ec_curve */*c*/, ec */*d*/, mp */*x*/);
+  ec *(*neg)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+  ec *(*add)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/);
+  ec *(*sub)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/);
+  ec *(*dbl)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+  int (*check)(ec_curve */*c*/, const ec */*p*/);
+} ec_ops;
+
+#define EC_NAME(c)             (c)->ops->name
+
+#define EC_SAMEP(c, d)         (c)->ops->samep((c), (d))
+#define EC_IN(c, d, p)         (c)->ops->in((c), (d), (p))
+#define EC_OUT(c, d, p)                (c)->ops->out((c), (d), (p))
+#define EC_FIX(c, d, p)                (c)->ops->fix((c), (d), (p))
+
+#define EC_FIND(c, d, x)       (c)->ops->find((c), (d), (x))
+#define EC_NEG(c, d, x)                (c)->ops->neg((c), (d), (x))
+#define EC_ADD(c, d, p, q)     (c)->ops->add((c), (d), (p), (q))
+#define EC_SUB(c, d, p, q)     (c)->ops->sub((c), (d), (p), (q))
+#define EC_DBL(c, d, p)                (c)->ops->dbl((c), (d), (p))
+#define EC_CHECK(c, p)         (c)->ops->check((c), (p))
+
+/* --- Elliptic curve parameters --- */
+
+typedef struct ec_info {
+  ec_curve *c;                         /* The actual curve */
+  ec g;                                        /* The common point */
+  mp *r;                               /* Order of %$g$% */
+  mp *h;                               /* Cofactor %$h = \#E/r$% */
+} ec_info;
+
+/*----- Simple memory management things -----------------------------------*/
+
+/* --- @ec_create@ --- *
+ *
+ * Arguments:  @ec *p@ = pointer to an elliptic-curve point
+ *
+ * Returns:    The argument @p@.
+ *
+ * Use:                Initializes a new point.  The initial value is the additive
+ *             identity (which is universal for all curves).
+ */
+
+#define EC_INIT { MP_NEW, MP_NEW, MP_NEW }
+
+#define EC_CREATE(p) do {                                              \
+  ec *_p = (p);                                                                \
+  _p->x = _p->y = _p->z = MP_NEW;                                      \
+} while (0)
+
+extern ec *ec_create(ec */*p*/);
+
+/* --- @ec_destroy@ --- *
+ *
+ * Arguments:  @ec *p@ = pointer to an elliptic-curve point
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a point, making it invalid.
+ */
+
+#define EC_DESTROY(p) do {                                             \
+  ec *_p = (p);                                                                \
+  if (!EC_ATINF(_p)) {                                                 \
+    MP_DROP(_p->x);                                                    \
+    MP_DROP(_p->y);                                                    \
+    if (_p->z) MP_DROP(_p->z);                                         \
+  }                                                                    \
+} while (0)
+
+extern void ec_destroy(ec */*p*/);
+
+/* --- @ec_atinf@ --- *
+ *
+ * Arguments:  @const ec *p@ = pointer to a point
+ *
+ * Returns:    Nonzero if %$p = O$% is the point at infinity, zero
+ *             otherwise.
+ */
+
+#define EC_ATINF(p) ((p)->x == MP_NEW || (p)->x == MP_NEWSEC)
+
+extern int ec_atinf(const ec */*p*/);
+
+/* --- @ec_setinf@ --- *
+ *
+ * Arguments:  @ec *p@ = pointer to a point
+ *
+ * Returns:    The argument @p@.
+ *
+ * Use:                Sets the given point to be the point %$O$% at infinity.
+ */
+
+#define EC_SETINF(p) do {                                              \
+  ec *_p = (p);                                                                \
+  if (!EC_ATINF(_p)) {                                                 \
+    MP_DROP(_p->x);                                                    \
+    MP_DROP(_p->y);                                                    \
+    if (_p->z) MP_DROP(_p->z);                                         \
+    _p->x = _p->y = _p->z = MP_NEW;                                    \
+    _p->y = MP_NEW;                                                    \
+    _p->z = MP_NEW;                                                    \
+  }                                                                    \
+} while (0)
+
+extern ec *ec_setinf(ec */*p*/);
+
+/* --- @ec_copy@ --- *
+ *
+ * Arguments:  @ec *d@ = pointer to destination point
+ *             @const ec *p@ = pointer to source point
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Creates a copy of an elliptic curve point.
+ */
+
+#define EC_COPY(d, p) do {                                             \
+  ec *_d = (d);                                                                \
+  const ec *_p = (p);                                                  \
+  if (d != p) {                                                                \
+    EC_DESTROY(d);                                                     \
+    if (EC_ATINF(p))                                                   \
+      _d->x = _d->y = _d->z = MP_NEW;                                  \
+    else {                                                             \
+      _d->x = MP_COPY(_p->x);                                          \
+      _d->y = MP_COPY(_p->y);                                          \
+      _d->z = _p->z ? MP_COPY(_p->z) : MP_NEW;                         \
+    }                                                                  \
+  }                                                                    \
+} while (0)
+
+extern ec *ec_copy(ec */*d*/, const ec */*p*/);
+
+/* --- @ec_eq@ --- *
+ *
+ * Arguments:  @const ec *p, *q@ = two points
+ *
+ * Returns:    Nonzero if the points are equal.  Compares external-format
+ *             points.
+ */
+
+#define EC_EQ(p, q)                                                    \
+    ((EC_ATINF(p) && EC_ATINF(q)) ||                                   \
+     (!EC_ATINF(p) && !EC_ATINF(q) &&                                  \
+      MP_EQ((p)->x, (q)->x) &&                                         \
+      MP_EQ((p)->y, (q)->y)))
+
+extern int ec_eq(const ec *p, const ec *q);
+
+/*----- Interesting arithmetic --------------------------------------------*/
+
+/* --- @ec_samep@ --- *
+ *
+ * Arguments:  @ec_curve *c, *d@ = two elliptic curves
+ *
+ * Returns:    Nonzero if the curves are identical (not just isomorphic).
+ *
+ * Use:                Checks for sameness of curves.  This function does the full
+ *             check, not just the curve-type-specific check done by the
+ *             @sampep@ field operation.
+ */
+
+extern int ec_samep(ec_curve */*c*/, ec_curve */*d*/);
+
+/* --- @ec_find@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @mp *x@ = a possible x-coordinate
+ *
+ * Returns:    The destination if OK, or null if no point was found.
+ *
+ * Use:                Finds a point on an elliptic curve with a given
+ *             x-coordinate.  If there is no point with the given
+ *             %$x$%-coordinate, a null pointer is returned and the
+ *             destination is left invalid.
+ */
+
+extern ec *ec_find(ec_curve */*c*/, ec */*d*/, mp */*x*/);
+
+/* --- @ec_rand@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @grand *r@ = random number source
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Finds a random point on the given curve.
+ */
+
+extern ec *ec_rand(ec_curve */*c*/, ec */*d*/, grand */*r*/);
+
+/* --- @ec_neg@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p@ = pointer to the operand point
+ *
+ * Returns:    The destination point.
+ *
+ * Use:                Computes the negation of the given point.
+ */
+
+extern ec *ec_neg(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+
+/* --- @ec_add@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p, *q@ = pointers to the operand points
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Adds two points on an elliptic curve.
+ */
+
+extern ec *ec_add(ec_curve */*c*/, ec */*d*/,
+                 const ec */*p*/, const ec */*q*/);
+
+/* --- @ec_sub@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p, *q@ = pointers to the operand points
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Subtracts one point from another on an elliptic curve.
+ */
+
+extern ec *ec_sub(ec_curve */*c*/, ec */*d*/,
+                 const ec */*p*/, const ec */*q*/);
+
+/* --- @ec_dbl@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p@ = pointer to the operand point
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Doubles a point on an elliptic curve.
+ */
+
+extern ec *ec_dbl(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+
+/* --- @ec_check@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @const ec *p@ = pointer to the point
+ *
+ * Returns:    Zero if OK, nonzero if this is an invalid point.
+ *
+ * Use:                Checks that a point is actually on an elliptic curve.
+ */
+
+extern int ec_check(ec_curve */*c*/, const ec */*p*/);
+
+/* --- @ec_mul@, @ec_imul@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p@ = pointer to the generator point
+ *             @mp *n@ = integer multiplier
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Multiplies a point by a scalar, returning %$n p$%.  The
+ *             @imul@ variant uses internal representations for argument
+ *             and result.
+ */
+
+extern ec *ec_mul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/);
+extern ec *ec_imul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/);
+
+/* --- @ec_mmul@, @ec_immul@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec_mulfactor *f@ = pointer to vector of factors
+ *             @size_t n@ = number of factors
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Does simultaneous point multiplication.  The @immul@ variant
+ *             uses internal representations for arguments and result.
+ */
+
+extern ec *ec_mmul(ec_curve */*c*/, ec */*d*/,
+                  const ec_mulfactor */*f*/, size_t /*n*/);
+extern ec *ec_immul(ec_curve */*c*/, ec */*d*/,
+                   const ec_mulfactor */*f*/, size_t /*n*/);
+
+/*----- Standard curve operations -----------------------------------------*/
+
+/* --- @ec_stdsamep@ --- *
+ *
+ * Arguments:  @ec_curve *c, *d@ = two elliptic curves
+ *
+ * Returns:    Nonzero if the curves are identical (not just isomorphic).
+ *
+ * Use:                Simple sameness check on @a@ and @b@ curve members.
+ */
+
+extern int ec_stdsamep(ec_curve */*c*/, ec_curve */*d*/);
+
+/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination
+ *             @const ec *p@ = pointer to a source point
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                An identity operation if your curve has no internal
+ *             representation.  (The field internal representation is still
+ *             used.)
+ */
+
+extern ec *ec_idin(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+extern ec *ec_idout(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+extern ec *ec_idfix(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+
+/* --- @ec_projin@, @ec_projout@, @ec_projfix@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination
+ *             @const ec *p@ = pointer to a source point
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Conversion functions if your curve operations use a
+ *             projective representation.
+ */
+
+extern ec *ec_projin(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+extern ec *ec_projout(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+extern ec *ec_projfix(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+
+/* --- @ec_stdsub@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination
+ *             @const ec *p, *q@ = the operand points
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Standard point subtraction operation, in terms of negation
+ *             and addition.  This isn't as efficient as a ready-made
+ *             subtraction operator.
+ */
+
+extern ec *ec_stdsub(ec_curve */*c*/, ec */*d*/,
+                    const ec */*p*/, const ec */*q*/);
+
+/*----- Creating curves ---------------------------------------------------*/
+
+/* --- @ec_destroycurve@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an ellptic curve
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a description of an elliptic curve.
+ */
+
+extern void ec_destroycurve(ec_curve */*c*/);
+
+/* --- @ec_prime@, @ec_primeproj@ --- *
+ *
+ * Arguments:  @field *f@ = the underlying field for this elliptic curve
+ *             @mp *a, *b@ = the coefficients for this curve
+ *
+ * Returns:    A pointer to the curve, or null.
+ *
+ * Use:                Creates a curve structure for an elliptic curve defined over
+ *             a prime field.  The @primeproj@ variant uses projective
+ *             coordinates, which can be a win.
+ */
+
+extern ec_curve *ec_prime(field */*f*/, mp */*a*/, mp */*b*/);
+extern ec_curve *ec_primeproj(field */*f*/, mp */*a*/, mp */*b*/);
+
+/* --- @ec_bin@, @ec_binproj@ --- *
+ *
+ * Arguments:  @field *f@ = the underlying field for this elliptic curve
+ *             @mp *a, *b@ = the coefficients for this curve
+ *
+ * Returns:    A pointer to the curve, or null.
+ *
+ * Use:                Creates a curve structure for an elliptic curve defined over
+ *             a binary field.  The @binproj@ variant uses projective
+ *             coordinates, which can be a win.
+ */
+
+extern ec_curve *ec_bin(field */*f*/, mp */*a*/, mp */*b*/);
+extern ec_curve *ec_binproj(field */*f*/, mp */*a*/, mp */*b*/);
+
+/*----- Curve parameter sets ----------------------------------------------*/
+
+/* --- @ec_curveparse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *
+ * Returns:    Elliptic curve pointer if OK, or null.
+ *
+ * Use:                Parses an elliptic curve description, which has the form
+ *
+ *               * a field description
+ *               * an optional `;'
+ *               * `prime', `primeproj', `bin', or `binproj'
+ *               * an optional `:'
+ *               * the %$a$% parameter
+ *               * an optional `,'
+ *               * the %$b$% parameter
+ */
+
+extern ec_curve *ec_curveparse(qd_parse */*qd*/);
+
+/* --- @ec_ptparse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *             @ec *p@ = where to put the point
+ *
+ * Returns:    The point address, or null.
+ *
+ * Use:                Parses an elliptic curve point.  This has the form
+ *
+ *               * %$x$%-coordinate
+ *               * optional `,'
+ *               * %$y$%-coordinate
+ */
+
+extern ec *ec_ptparse(qd_parse */*qd*/, ec */*p*/);
+
+/* --- @ec_infoparse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *             @ec_info *ei@ = curve information block, currently
+ *                     uninitialized
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Parses an elliptic curve information string, and stores the
+ *             information in @ei@.  This has the form
+ *
+ *               * elliptic curve description
+ *               * optional `;'
+ *               * common point
+ *               * optional `:'
+ *               * group order
+ *               * optional `*'
+ *               * cofactor
+ */
+
+extern int ec_infoparse(qd_parse */*qd*/, ec_info */*ei*/);
+
+/* --- @ec_infofromdata@ --- *
+ *
+ * Arguments:  @ec_info *ei@ = where to write the information
+ *             @ecdata *ed@ = raw data
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads elliptic curve information about one of the standard
+ *             curves.
+ */
+
+struct ecdata;
+extern void ec_infofromdata(ec_info */*ei*/, struct ecdata */*ed*/);
+
+/* --- @ec_getinfo@ --- *
+ *
+ * Arguments:  @ec_info *ei@ = where to write the information
+ *             @const char *p@ = string describing a curve
+ *
+ * Returns:    Null on success, or a pointer to an error message.
+ *
+ * Use:                Parses out information about a curve.  The string is either a
+ *             standard curve name, or a curve info string.
+ */
+
+extern const char *ec_getinfo(ec_info */*ei*/, const char */*p*/);
+
+/* --- @ec_sameinfop@ --- *
+ *
+ * Arguments:  @ec_info *ei, *ej@ = two elliptic curve parameter sets
+ *
+ * Returns:    Nonzero if the curves are identical (not just isomorphic).
+ *
+ * Use:                Checks for sameness of curve parameters.
+ */
+
+extern int ec_sameinfop(ec_info */*ei*/, ec_info */*ej*/);
+
+/* --- @ec_freeinfo@ --- *
+ *
+ * Arguments:  @ec_info *ei@ = elliptic curve information block to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees the information block.
+ */
+
+extern void ec_freeinfo(ec_info */*ei*/);
+
+/* --- @ec_checkinfo@ --- *
+ *
+ * Arguments:  @const ec_info *ei@ = elliptic curve information block
+ *
+ * Returns:    Null if OK, or pointer to error message.
+ *
+ * Use:                Checks an elliptic curve according to the rules in SEC1.
+ */
+
+extern const char *ec_checkinfo(const ec_info */*ei*/, grand */*gr*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ectab.h b/math/ectab.h
new file mode 100644 (file)
index 0000000..38d3b30
--- /dev/null
@@ -0,0 +1,72 @@
+/* -*-c-*-
+ *
+ * Table of standard elliptic curves
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_ECTAB_H
+#define CATACOMB_ECTAB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "ec.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct ecdata {
+  unsigned ftag;                       /* The kind of curve this is */
+  mp p, beta;                          /* Modulus, and conversion magic */
+  mp a, b;                             /* Elliptic curve parameters */
+  mp r;                                        /* Order of common point %$g$% */
+  mp h;                                        /* Cofactor %$h = \#E/r$% */
+  mp gx, gy;                           /* Common point */
+} ecdata;
+
+enum {
+  FTAG_PRIME,                          /* Prime but not nice */
+  FTAG_NICEPRIME,                      /* Nice prime field */
+  FTAG_BINPOLY,                                /* Binary field, poly basis */
+  FTAG_BINNORM                         /* Binary field, normal basis */
+};
+
+typedef struct ecentry {
+  const char *name;
+  ecdata *data;
+} ecentry;
+
+/*----- Global variables --------------------------------------------------*/
+
+extern const ecentry ectab[];
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ectab.in b/math/ectab.in
new file mode 100644 (file)
index 0000000..0e7c8cb
--- /dev/null
@@ -0,0 +1,634 @@
+# Standard ellipic curves
+
+#----- Curves from SEC2 -----------------------------------------------------
+
+curve secp112r1 prime
+  p 0xdb7c2abf62e35e668076bead208b
+  a 0xdb7c2abf62e35e668076bead2088
+  b 0x659ef8ba043916eede8911702b22
+  r 0xdb7c2abf62e35e7628dfac6561c5
+  h 1
+  gx 0x09487239995a5ee76b55f9c2f098
+  gy 0xa89ce5af8724c0a23e0e0ff77500
+curve secp112r2 prime
+  p 0xdb7c2abf62e35e668076bead208b
+  a 0x6127c24c05f38a0aaaf65c0ef02c
+  b 0x51def1815db5ed74fcc34c85d709
+  r 0x36df0aafd8b8d7597ca10520d04b
+  h 4
+  gx 0x4ba30ab5e892b4e1649dd0928643
+  gy 0xadcd46f5882e3747def36e956e97
+
+curve secp128r1 niceprime
+  p 0xfffffffdffffffffffffffffffffffff
+  a 0xfffffffdfffffffffffffffffffffffc
+  b 0xe87579c11079f43dd824993c2cee5ed3
+  r 0xfffffffe0000000075a30d1b9038a115
+  h 1
+  gx 0x161ff7528b899b2d0c28607ca52c5b86
+  gy 0xcf5ac8395bafeb13c02da292dded7a83
+curve secp128r2 niceprime
+  p 0xfffffffdffffffffffffffffffffffff
+  a 0xd6031998d1b3bbfebf59cc9bbff9aee1
+  b 0x5eeefca380d02919dc2c6558bb6d8a5d
+  r 0x3fffffff7fffffffbe0024720613b5a3
+  h 4
+  gx 0x7b6aa5d85e572983e6fb32a7cdebc140
+  gy 0x27b6916a894d3aee7106fe805fc34b44
+
+curve secp160k1 niceprime
+  p 0xfffffffffffffffffffffffffffffffeffffac73
+  a 0
+  b 7
+  r 0x0100000000000000000001b8fa16dfab9aca16b6b3
+  h 1
+  gx 0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebb
+  gy 0x938cf935318fdced6bc28286531733c3f03c4fee
+curve secp160r1 niceprime
+  p 0xffffffffffffffffffffffffffffffff7fffffff
+  a 0xffffffffffffffffffffffffffffffff7ffffffc
+  b 0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45
+  r 0x0100000000000000000001f4c8f927aed3ca752257
+  h 1
+  gx 0x4a96b5688ef573284664698968c38bb913cbfc82
+  gy 0x23a628553168947d59dcc912042351377ac5fb32
+curve secp160r2 niceprime
+  p 0xfffffffffffffffffffffffffffffffeffffac73
+  a 0xfffffffffffffffffffffffffffffffeffffac70
+  b 0xb4e134d3fb59eb8bab57274904664d5af50388ba
+  r 0x0100000000000000000000351ee786a818f3a1a16b
+  h 1
+  gx 0x52dcb034293a117e1f4ff11b30f7199d3144ce6d
+  gy 0xfeaffef2e331f296e071fa0df9982cfea7d43f2e
+
+curve secp192k1 niceprime
+  p 0xfffffffffffffffffffffffffffffffffffffffeffffee37
+  a 0
+  b 3
+  r 0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d
+  h 1
+  gx 0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d
+  gy 0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d
+curve secp192r1 niceprime
+  p 0xfffffffffffffffffffffffffffffffeffffffffffffffff
+  a 0xfffffffffffffffffffffffffffffffefffffffffffffffc
+  b 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1
+  r 0xffffffffffffffffffffffff99def836146bc9b1b4d22831
+  h 1
+  gx 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
+  gy 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811
+
+curve secp224k1 niceprime
+  p 0xfffffffffffffffffffffffffffffffffffffffffffffffeffffe56d
+  a 0
+  b 5
+  r 0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7
+  h 1
+  gx 0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c
+  gy 0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5
+curve secp224r1 niceprime
+  p 0xffffffffffffffffffffffffffffffff000000000000000000000001
+  a 0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe
+  b 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
+  r 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
+  h 1
+  gx 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
+  gy 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34
+
+curve secp256k1 niceprime
+  p 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
+  a 0
+  b 7
+  r 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
+  h 1
+  gx 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
+  gy 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
+curve secp256r1 niceprime
+  p 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
+  a 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc
+  b 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
+  r 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
+  h 1
+  gx 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
+  gy 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
+
+curve secp384r1 niceprime
+  p 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff
+  a 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc
+  b 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef
+  r 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973
+  h 1
+  gx 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7
+  gy 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f
+
+curve secp521r1 niceprime
+  p 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  a 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc
+  b 0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00
+  r 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409
+  h 1
+  gx 0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66
+  gy 0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650
+
+curve sect113r1 binpoly
+  p 0x20000000000000000000000000201
+  a 0x003088250ca6e7c7fe649ce85820f7
+  b 0x00e8bee4d3e2260744188be0e9c723
+  r 0x0100000000000000d9ccec8a39e56f
+  h 2
+  gx 0x009d73616f35f4ab1407d73562c10f
+  gy 0x00a52830277958ee84d1315ed31886
+curve sect113r2 binpoly
+  p 0x20000000000000000000000000201
+  a 0x00689918dbec7e5a0dd6dfc0aa55c7
+  b 0x0095e9a9ec9b297bd4bf36e059184f
+  r 0x010000000000000108789b2496af93
+  h 2
+  gx 0x01a57a6a7b26ca5ef52fcdb8164797
+  gy 0x00b3adc94ed1fe674c06e695baba1d
+
+curve sect131r1 binpoly
+  p 0x80000000000000000000000000000010d
+  a 0x07a11b09a76b562144418ff3ff8c2570b8
+  b 0x0217c05610884b63b9c6c7291678f9d341
+  r 0x0400000000000000023123953a9464b54d
+  h 2
+  gx 0x0081baf91fdf9833c40f9c181343638399
+  gy 0x078c6e7ea38c001f73c8134b1b4ef9e150
+curve sect131r2 binpoly
+  p 0x80000000000000000000000000000010d
+  a 0x03e5a88919d7cafcbf415f07c2176573b2
+  b 0x04b8266a46c55657ac734ce38f018f2192
+  r 0x0400000000000000016954a233049ba98f
+  h 2
+  gx 0x0356dcd8f2f95031ad652d23951bb366a8
+  gy 0x0648f06d867940a5366d9e265de9eb240f
+
+curve sect163k1 binpoly
+  p 0x800000000000000000000000000000000000000c9
+  a 1
+  b 1
+  r 0x04000000000000000000020108a2e0cc0d99f8a5ef
+  h 2
+  gx 0x02fe13c0537bbc11acaa07d793de4e6d5e5c94eee8
+  gy 0x0289070fb05d38ff58321f2e800536d538ccdaa3d9
+curve sect163r1 binpoly
+  p 0x800000000000000000000000000000000000000c9
+  a 0x07b6882caaefa84f9554ff8428bd88e246d2782ae2
+  b 0x0713612dcddcb40aab946bda29ca91f73af958afd9
+  r 0x03ffffffffffffffffffff48aab689c29ca710279b
+  h 2
+  gx 0x0369979697ab43897789566789567f787a7876a654
+  gy 0x00435edb42efafb2989d51fefce3c80988f41ff883
+curve sect163r2 binpoly
+  p 0x800000000000000000000000000000000000000c9
+  a 1
+  b 0x020a601907b8c953ca1481eb10512f78744a3205fd
+  r 0x040000000000000000000292fe77e70c12a4234c33
+  h 2
+  gx 0x03f0eba16286a2d57ea0991168d4994637e8343e36
+  gy 0x00d51fbc6c71a0094fa2cdd545b11c5c0c797324f1
+
+curve sect193r1 binpoly
+  p 0x2000000000000000000000000000000000000000000008001
+  a 0x0017858feb7a98975169e171f77b4087de098ac8a911df7b01
+  b 0x00fdfb49bfe6c3a89facadaa7a1e5bbc7cc1c2e5d831478814
+  r 0x01000000000000000000000000c7f34a778f443acc920eba49
+  h 2
+  gx 0x01f481bc5f0ff84a74ad6cdf6fdef4bf6179625372d8c0c5e1
+  gy 0x0025e399f2903712ccf3ea9e3a1ad17fb0b3201b6af7ce1b05
+curve sect193r2 binpoly
+  p 0x2000000000000000000000000000000000000000000008001
+  a 0x0163f35a5137c2ce3ea6ed8667190b0bc43ecd69977702709b
+  b 0x00c9bb9e8927d4d64c377e2ab2856a5b16e3efb7f61d4316ae
+  r 0x010000000000000000000000015aab561b005413ccd4ee99d5
+  h 2
+  gx 0x00d9b67d192e0367c803f39e1a7e82ca14a651350aae617e8f
+  gy 0x01ce94335607c304ac29e7defbd9ca01f596f927224cdecf6c
+
+curve sect233k1 binpoly
+  p 0x20000000000000000000000000000000000000004000000000000000001
+  a 0
+  b 1
+  r 0x8000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf
+  h 4
+  gx 0x017232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126
+  gy 0x01db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3
+curve sect233r1 binpoly
+  p 0x20000000000000000000000000000000000000004000000000000000001
+  a 1
+  b 0x0066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad
+  r 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7
+  h 2
+  gx 0x00fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b
+  gy 0x01006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052
+
+curve sect239k1 binpoly
+  p 0x800000000000000000004000000000000000000000000000000000000001
+  a 0
+  b 1
+  r 0x2000000000000000000000000000005a79fec67cb6e91f1c1da800e478a5
+  h 4
+  gx 0x29a0b6a887a983e9730988a68727a8b2d126c44cc2cc7b2a6555193035dc
+  gy 0x76310804f12e549bdb011c103089e73510acb275fc312a5dc6b76553f0ca
+
+curve sect283k1 binpoly
+  p 0x800000000000000000000000000000000000000000000000000000000000000000010a1
+  a 0
+  b 1
+  r 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61
+  h 4
+  gx 0x0503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836
+  gy 0x01ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259
+curve sect283r1 binpoly
+  p 0x800000000000000000000000000000000000000000000000000000000000000000010a1
+  a 1
+  b 0x027b680ac8b8596da5a4af8a19a0303fca97fd7645309fa2a581485af6263e313b79a2f5
+  r 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307
+  h 2
+  gx 0x05f939258db7dd90e1934f8c70b0dfec2eed25b8557eac9c80e2e198f8cdbecd86b12053
+  gy 0x03676854fe24141cb98fe6d4b20d02b4516ff702350eddb0826779c813f0df45be8112f4
+
+curve sect409k1 binpoly
+  p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
+  a 0
+  b 1
+  r 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf
+  h 4
+  gx 0x0060f05f658f49c1ad3ab1890f7184210efd0987e307c84c27accfb8f9f67cc2c460189eb5aaaa62ee222eb1b35540cfe9023746
+  gy 0x01e369050b7c4e42acba1dacbf04299c3460782f918ea427e6325165e9ea10e3da5f6c42e9c55215aa9ca27a5863ec48d8e0286b
+curve sect409r1 binpoly
+  p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
+  a 1
+  b 0x0021a5c2c8ee9feb5c4b9a753b7b476b7fd6422ef1f3dd674761fa99d6ac27c8a9a197b272822f6cd57a55aa4f50ae317b13545f
+  r 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173
+  h 2
+  gx 0x015d4860d088ddb3496b0c6064756260441cde4af1771d4db01ffe5b34e59703dc255a868a1180515603aeab60794e54bb7996a7
+  gy 0x0061b1cfab6be5f32bbfa78324ed106a7636b9c5a7bd198d0158aa4f5488d08f38514f1fdf4b4f40d2181b3681c364ba0273c706
+
+curve sect571k1 binpoly
+  p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
+  a 0
+  b 1
+  r 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001
+  h 4
+  gx 0x026eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972
+  gy 0x0349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3
+curve sect571r1 binpoly
+  p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
+  a 1
+  b 0x02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a
+  r 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47
+  h 2
+  gx 0x0303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19
+  gy 0x037bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b
+
+#----- Curves from ANSI X9.62 -----------------------------------------------
+#
+# The conversion factors for the normal basis representations were generated
+# because none were given in the document.
+
+curve ansi-c2pnb163v1 binpoly
+  p 0x080000000000000000000000000000000000000107
+  a 0x072546b5435234a422e0789675f432c89435de5242
+  b 0x00c9517d06d5240d3cff38c74b20b6cd4d6f9dd4d9
+  r 0x0400000000000000000001e60fc8821cc74daeafc1
+  h 2
+  gx 0x07af69989546103d79329fcc3d74880f33bbe803cb
+  gy 0x01ec23211b5966adea1d3f87f7ea5848aef0b7ca9f
+curve ansi-c2pnb163v2 binpoly
+  p 0x080000000000000000000000000000000000000107
+  a 0x0108b39e77c4b108bed981ed0e890e117c511cf072
+  b 0x0667aceb38af4e488c407433ffae4f1c811638df20
+  r 0x03fffffffffffffffffffdf64de1151adbb78f10a7
+  h 2
+  gx 0x0024266e4eb5106d0a964d92c4860e2671db9b6cc5
+  gy 0x079f684ddf6684c5cd258b3890021b2386dfd19fc5
+curve ansi-c2pnb163v3 binpoly
+  p 0x080000000000000000000000000000000000000107
+  a 0x07a526c63d3e25a256a007699f5447e32ae456b50e
+  b 0x03f7061798eb99e238fd6f1bf95b48feeb4854252b
+  r 0x03fffffffffffffffffffe1aee140f110aff961309
+  h 2
+  gx 0x02f9f87b7c574d0bdecf8a22e6524775f98cdebdcb
+  gy 0x05b935590c155e17ea48eb3ff3718b893df59a05d0
+
+curve ansi-c2tnb191v1 binpoly
+  p 0x800000000000000000000000000000000000000000000201
+  a 0x2866537b676752636a68f56554e12640276b649ef7526267
+  b 0x2e45ef571f00786f67b0081b9495a3d95462f5de0aa185ec
+  r 0x40000000000000000000000004a20e90c39067c893bbb9a5
+  h 2
+  gx 0x36b3daf8a23206f9c4f299d7b21a9c369137f2c84ae1aa0d
+  gy 0x765be73433b3f95e332932e70ea245ca2418ea0ef98018fb
+curve ansi-c2tnb191v2 binpoly
+  p 0x800000000000000000000000000000000000000000000201
+  a 0x401028774d7777c7b7666d1366ea432071274f89ff01e718
+  b 0x0620048d28bcbd03b6249c99182b7c8cd19700c362c46a01
+  r 0x20000000000000000000000050508cb89f652824e06b8173
+  h 4
+  gx 0x3809b2b7cc1b28cc5a87926aad83fd28789e81e2c9e3bf10
+  gy 0x17434386626d14f3dbf01760d9213a3e1cf37aec437d668a
+curve ansi-c2tnb191v3 binpoly
+  p 0x800000000000000000000000000000000000000000000201
+  a 0x6c01074756099122221056911c77d77e77a777e7e7e77fcb
+  b 0x71fe1af926cf847989efef8db459f66394d90f32ad3f15e8
+  r 0x155555555555555555555555610c0b196812bfb6288a3ea3
+  h 6
+  gx 0x375d4ce24fde434489de8746e71786015009e66e38a926dd
+  gy 0x545a39176196575d985999366e6ad34ce0a77cd7127b06be
+curve ansi-c2onb191v1 binnorm
+  p 0x800000000000000000000000000000000000000000000201
+  beta 0x19c409a7f85383bf0ef72b097a5c7398013a2dba6269292d
+  a 0x65903e04e1e4924253e26a3c9ac28c758bd8184a3fb680e8
+  b 0x54678621b190cfce282ade219d5b3a065e3f4b3ffdebb29b
+  r 0x4000000000000000000000009cf2d6e3901dac4c32eec65d
+  h 2
+  gx 0x5a2c69a32e8638e51ccefaad05350a978457cb5fb6df994a
+  gy 0x0f32fe0fa0e902f19b17d363c269f4f5cfe8087618569954
+curve ansi-c2onb191v2 binnorm
+  p 0x800000000000000000000000000000000000000000000201
+  beta 0x19c409a7f85383bf0ef72b097a5c7398013a2dba6269292d
+  a 0x25f8d06c97c822536d469cd5170cdd7bb9f500bd6db110fb
+  b 0x75ff570e35ca94fb3780c2619d081c17aa59fbd5e591c1c4
+  r 0x0fffffffffffffffffffffffeeb354b7270b2992b7818627
+  h 8
+  gx 0x2a16910e8f6c4b199be24213857abc9c992edfb2471f3c68
+  gy 0x1592dbfebeb81a7c071b744d5e2f9e242ea65b81138a3468  
+
+curve ansi-c2tnb239v1 binpoly
+  p 0x800000000000000000000000000000000000000000000000001000000001
+  a 0x32010857077c5431123a46b808906756f543423e8d27877578125778ac76
+  b 0x790408f2eedaf392b012edefb3392f30f4327c0ca3f31fc383c422aa8c16
+  r 0x2000000000000000000000000000000f4d42ffe1492a4993f1cad666e447
+  h 4
+  gx 0x57927098fa932e7c0a96d3fd5b706ef7e5f5c156e16b7e7c86038552e91d
+  gy 0x61d8ee5077c33fecf6f1a16b268de469c3c7744ea9a971649fc7a9616305
+curve ansi-c2tnb239v2 binpoly
+  p 0x800000000000000000000000000000000000000000000000001000000001
+  a 0x4230017757a767fae42398569b746325d45313af0766266479b75654e65f
+  b 0x5037ea654196cff0cd82b2c14a2fcf2e3ff8775285b545722f03eacdb74b
+  r 0x1555555555555555555555555555553c6f2885259c31e3fcdf154624522d
+  h 6
+  gx 0x28f9d04e900069c8dc47a08534fe76d2b900b7d7ef31f5709f200c4ca205
+  gy 0x5667334c45aff3b5a03bad9dd75e2c71a99362567d5453f7fa6e227ec833
+curve ansi-c2tnb239v3 binpoly
+  p 0x800000000000000000000000000000000000000000000000001000000001
+  a 0x01238774666a67766d6676f778e676b66999176666e687666d8766c66a9f
+  b 0x6a941977ba9f6a435199acfc51067ed587f519c5ecb541b8e44111de1d40
+  r 0x0cccccccccccccccccccccccccccccac4912d2d9df903ef9888b8a0e4cff
+  h 10
+  gx 0x70f6e9d04d289c4e89913ce3530bfde903977d42b146d539bf1bde4e9c92
+  gy 0x2e5a0eaf6e5e1305b9004dce5c0ed7fe59a35608f33837c816d80b79f461
+curve ansi-c2onb239v1 binnorm
+  p 0x800000000000000000000000000000000000000000000000001000000001
+  beta 0x3b5ce9846911b248f9347018a7ac8cce3662cee952ba45becd02d4b903ec
+  a 0x182dd45f5d470239b8983fea47b8b292641c57f9bf84baecde8bb3adce30
+  b 0x147a9c1d4c2ce9be5d34ec02797f76667ebad5a3f93fa2a524bfde91ef28
+  r 0x200000000000000000000000000000474f7e69f42fe430931d0b455aae8b
+  h 4
+  gx 0x4912ad657f1d1c6b32edb9942c95e226b06fb012cd40fdea0d72197c8104
+  gy 0x01f1fbc3d21168fd3f66c441c2b5c6cfdcd9ed3e13646b7a4db9a3b0c286
+curve ansi-c2onb239v2 binnorm
+  p 0x800000000000000000000000000000000000000000000000001000000001
+  beta 0x3b5ce9846911b248f9347018a7ac8cce3662cee952ba45becd02d4b903ec
+  a 0x1ecf1b9d28d8017505e17475d3df2982e243ca5cb5e9f94a3f36124a486e
+  b 0x3ee257250d1a2e66cef23aa0f25b12388de8a10ff9554f90afbaa9a08b6d
+  r 0x1555555555555555555555555555558cf77a5d0589d2a9340d963b7ad703
+  h 6
+  gx 0x5f949ccb694f26b96d191e8925205a719929e93c37174cb6c7f659a37b85
+  gy 0x2d788d605ac81069e9964fd6edbae8bbf582a5c409a1078cf487a147ceb2
+  ## The spec seems bogus: the suggested base point G isn't in the
+  ## subgroup!  The point above is h G.
+  ##gx 0x193279fc543e9f5f7119189785b9c60b249be4820baf6c24bdfa2813f8b8
+  ##gy 0x5da021e5af77604051fc5c38da8293c1eeeaa00f046eeb93b6c8b774bb9b
+
+curve ansi-c2tnb359v1 binpoly
+  p 0x800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001
+  a 0x5667676a654b20754f356ea92017d946567c46675556f19556a04616b567d223a5e05656fb549016a96656a557
+  b 0x2472e2d0197c49363f1fe7f5b6db075d52b6947d135d8ca445805d39bc345626089687742b6329e70680231988
+  r 0x01af286bca1af286bca1af286bca1af286bca1af286bc9fb8f6b85c556892c20a7eb964fe7719e74f490758d3b
+  h 76
+  gx 0x3c258ef3047767e7ede0f1fdaa79daee3841366a132e163aced4ed2401df9c6bdcde98e8e707c07a2239b1b097
+  gy 0x53d7e08529547048121e9c95f3791dd804963948f34fae7bf44ea82365dc7868fe57e4ae2de211305a407104bd
+
+curve ansi-c2tnb431v1 binpoly
+  p 0x800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001
+  a 0x1a827ef00dd6fc0e234caf046c6a5d8a85395b236cc4ad2cf32a0cadbdc9ddf620b0eb9906d0957f6c6feacd615468df104de296cd8f
+  b 0x10d9b4a3d9047d8b154359abfb1b7f5485b04ceb868237ddc9deda982a679a5a919b626d4e50a8dd731b107a9962381fb5d807bf2618
+  r 0x000340340340340340340340340340340340340340340340340340340323c313fab50589703b5ec68d3587fec60d161cc149c1ad4a91
+  h 10080
+  gx 0x120fc05d3c67a99de161d2f4092622feca701be4f50f4758714e8a87bbf2a658ef8c21e7c5efe965361f6c2999c0c247b0dbd70ce6b7
+  gy 0x20d0af8903a96f8d5fa2c255745d3c451b302c9346d9b7e485e7bce41f6b591f3e8f6addcbb0bc4c2f947a7de1a89b625d6a598b3760
+
+# These curves aren't included because their degree isn't prime (so they
+# may be vulnerable to Weil descent)
+# ansi-c2pnb176w1 is bad: 176 isn't prime
+# ansi-c2pnb208v1 is bad: 208 isn't prime
+# ansi-c2pnb272w1 is bad: 272 isn't prime
+# ansi-c2pnb304w1 is bad: 304 isn't prime
+# ansi-c2pnb368w1 is bad: 368 isn't prime
+
+alias ansi-prime192v1 secp192r1
+curve ansi-prime192v2 niceprime
+  p 0xfffffffffffffffffffffffffffffffeffffffffffffffff
+  a 0xfffffffffffffffffffffffffffffffefffffffffffffffc
+  b 0xcc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953
+  r 0xfffffffffffffffffffffffe5fb1a724dc80418648d8dd31
+  h 1
+  gx 0xeea2bae7e1497842f2de7769cfe9c989c072ad696f48034a
+  gy 0x6574d11d69b6ec7a672bb82a083df2f2b0847de970b2de15
+curve ansi-prime192v3 niceprime
+  p 0xfffffffffffffffffffffffffffffffeffffffffffffffff
+  a 0xfffffffffffffffffffffffffffffffefffffffffffffffc
+  b 0x22123dc2395a05caa7423daeccc94760a7d462256bd56916
+  r 0xffffffffffffffffffffffff7a62d031c83f4294f640ec13
+  h 1
+  gx 0x7d29778100c65a1da1783716588dce2b8b4aee8e228f1896
+  gy 0x38a90f22637337334b49dcb66a6dc8f9978aca7648a943b0
+
+curve ansi-prime239v1 niceprime
+  p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff
+  a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc
+  b 0x6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a
+  r 0x7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b
+  h 1
+  gx 0x0ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf
+  gy 0x7debe8e4e90a5dae6e4054ca530ba04654b36818ce226b39fccb7b02f1ae
+curve ansi-prime239v2 niceprime
+  p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff
+  a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc
+  b 0x617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c
+  r 0x7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063
+  h 1
+  gx 0x38af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7
+  gy 0x5b0125e4dbea0ec7206da0fc01d9b081329fb555de6ef460237dff8be4ba
+curve ansi-prime239v3 niceprime
+  p 0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff
+  a 0x7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc
+  b 0x255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e
+  r 0x7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551
+  h 1
+  gx 0x6768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a
+  gy 0x1607e6898f390c06bc1d552bad226f3b6fcfe48b6e818499af18e3ed6cf3
+
+alias ansi-prime256v1 secp256r1
+
+#----- Curves from ANSI X9.63 -----------------------------------------------
+#
+# These are just duplicates of the SEC curves.
+
+alias ansit163k1 sect163k1
+alias ansit163r1 sect163r1
+alias ansit163r2 sect163r2
+alias ansit193r1 sect193r1
+alias ansit193r2 sect193r2
+alias ansit233k1 sect233k1
+alias ansit233r1 sect233r1
+alias ansit239k1 sect239k1
+alias ansit283k1 sect283k1
+alias ansit283r1 sect283r1
+alias ansit409k1 sect409k1
+alias ansit409r1 sect409r1
+alias ansit571k1 sect571k1
+alias ansit571r1 sect571r1
+
+alias ansip160k1 secp160k1
+alias ansip160r1 secp160r1
+alias ansip160r2 secp160r2
+alias ansip192k1 secp192k1
+alias ansip192r1 secp192r1
+alias ansip224k1 secp224k1
+alias ansip224r1 secp224r1
+alias ansip256k1 secp256k1
+alias ansip256r1 secp256r1
+alias ansip384r1 secp384r1
+alias ansip521r1 secp521r1
+
+#----- Curves from RFC2414 (Oakley) -----------------------------------------
+#
+# The Oakley curves are not good:
+#   oakley155 has too large a cofactor
+#   oakley185's field has composite degree
+# Hence, we include neither here.
+
+#----- NIST curves from FIPS186-2 -------------------------------------------
+#
+# These are duplicates of SEC2 curves.  However, the normal basis
+# representations aren't in SEC, so we give them here.  (Conversion factors
+# from FIPS186-2.
+
+alias nist-p192 secp192r1
+alias nist-p224 secp224r1
+alias nist-p256 secp256r1
+alias nist-p384 secp384r1
+alias nist-p521 secp521r1
+
+alias nist-k163 sect163k1
+alias nist-k233 sect233k1
+alias nist-k283 sect283k1
+alias nist-k409 sect409k1
+alias nist-k571 sect571k1
+
+alias nist-b163 sect163r2
+alias nist-b233 sect233r1
+alias nist-b283 sect283r1
+alias nist-b409 sect409r1
+alias nist-b571 sect571r1
+
+curve nist-k163n binnorm
+  p 0x800000000000000000000000000000000000000c9
+  beta 0x715169c109c612e390d347c748342bcd3b02a0bef
+  a 0x7ffffffffffffffffffffffffffffffffffffffff
+  b 0x7ffffffffffffffffffffffffffffffffffffffff
+  r 0x04000000000000000000020108a2e0cc0d99f8a5ef
+  h 2
+  gx 0x05679b353caa46825fea2d3713ba450da0c2a4541
+  gy 0x235b7c6710050689906bac3d9dec76a835591edb2
+curve nist-b163n binnorm
+  p 0x800000000000000000000000000000000000000c9
+  beta 0x715169c109c612e390d347c748342bcd3b02a0bef
+  a 0x7ffffffffffffffffffffffffffffffffffffffff
+  b 0x6645f3cacf1638e139c6cd13ef61734fbc9e3d9fb
+  r 0x040000000000000000000292fe77e70c12a4234c33
+  h 2
+  gx 0x0311103c17167564ace77ccb09c681f886ba54ee8
+  gy 0x333ac13c6447f2e67613bf7009daf98c87bb50c7f
+
+curve nist-k233n binnorm
+  p 0x20000000000000000000000000000000000000004000000000000000001
+  beta 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
+  a 0
+  b 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  r 0x8000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf
+  h 4
+  gx 0x0fde76d9dcd26e643ac26f1aa901aa129784b71fc0722b2d05614d650b3
+  gy 0x0643e317633155c9e0447ba8020a3c43177450ee036d633501434cac978
+curve nist-b233n binnorm
+  p 0x20000000000000000000000000000000000000004000000000000000001
+  beta 0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
+  a 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  b 0x1a003e0962d4f9a8e407c904a9538163adb825212600c7752ad52233279
+  r 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7
+  h 2
+  gx 0x18b863524b3cdfefb94f2784e0b116faac54404bc9162a363bab84a14c5
+  gy 0x04925df77bd8b8ff1a5ff519417822bfedf2bbd752644292c98c7af6e02
+
+curve nist-k283n binnorm
+  p 0x800000000000000000000000000000000000000000000000000000000000000000010a1
+  beta 0x31e0ed791c3282dc5624a720818049d053e8c7ab8663792bc1d792eba9867fc7b317a99
+  a 0
+  b 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  r 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61
+  h 4
+  gx 0x3ab9593f8db09fc188f1d7c4ac9fcc3e57fcd3bdb15024b212c70229de5fcd92eb0ea60
+  gy 0x2118c4755e7345cd8f603ef93b98b106fe8854ffeb9a3b304634cc83a0e759f0c2686b1
+curve nist-b283n binnorm
+  p 0x800000000000000000000000000000000000000000000000000000000000000000010a1
+  beta 0x31e0ed791c3282dc5624a720818049d053e8c7ab8663792bc1d792eba9867fc7b317a99
+  a 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  b 0x157261b894739fb5a13503f55f0b3f10c5601166633102201138cc180c0206bdafbc951
+  r 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307
+  h 2
+  gx 0x749468e464ee468634b21f7f61cb700701817e6bc36a2364cb8906e940948eaa463c35d
+  gy 0x62968bd3b489ac5c9b859da68475c315bafcdc4ccd0dc905b70f62446f49c052f49c08c
+
+curve nist-k409n binnorm
+  p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
+  beta 0x0dfa06be206aa97b7a41fffb9b0c55f8f048062fbe8381b4248adf92912ccc8e3f91a24e1cfb3950532b988971c23042e85708d
+  a 0
+  b 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  r 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf
+  h 4
+  gx 0x1b559c7cba2422e3affe13343e808b55e012d726ca0b7e6a63aeafbc1e3a98e10ca0fcf98350c3b7f89a9754a8e1dc0713cec4a
+  gy 0x16d8c42052f07e7713e7490eff318ba1abd6fef8a5433c894b24f5c817aeb79852496fbee803a47bc8a203878ebf1c499afd7d6
+curve nist-b409n binnorm
+  p 0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
+  beta 0x0dfa06be206aa97b7a41fffb9b0c55f8f048062fbe8381b4248adf92912ccc8e3f91a24e1cfb3950532b988971c23042e85708d
+  a 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  b 0x124d0651c3d3772f7f5a1fe6e715559e2129bdfa04d52f7b6ac7c532cf0ed06f610072d88ad2fdcc50c6fde72843670f8b3742a
+  r 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173
+  h 2
+  gx 0x0ceacbc9f475767d8e69f3b5dfab39813685262bcacf22b84c7b6dd981899e7318c96f0761f77c602c016ced7c548de830d708f
+  gy 0x199d64ba8f089c6db0e0b61e80bb95934afd0caf2e8be76d1c5e9affc7476df49142691ad30390288aa09bcc59c1573aa3c009a
+
+curve nist-k571n binnorm
+  p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
+  beta 0x452186bbf5840a0bcf8c9f02a54efa04e813b43c3d4149606c4d27b487bf107393c8907f79d9778beb35ee87467d3288274caebda6ce05aeb4ca5cf3c3044bd4372232f2c1a27c4
+  a 0
+  b 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  r 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001
+  h 4
+  gx 0x04bb2dba418d0db107adae003427e5d7cc139acb465e5934f0bea2ab2f3622bc29b3d5b9aa7a1fdfd5d8be66057c1008e71e484bcd98f22bf8476423767367429ef2ec5bc3ebcf7
+  gy 0x44cbb57de20788d2c952d7b56cf39bd3e89b18984bd124e751ceff4369dd8dac6a59e6e745df44d8220ce22aa2c852cfcbbef49ebaa98bd2483e33180e04286feaa253050caff60
+curve nist-b571n binnorm
+  p 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
+  beta 0x452186bbf5840a0bcf8c9f02a54efa04e813b43c3d4149606c4d27b487bf107393c8907f79d9778beb35ee87467d3288274caebda6ce05aeb4ca5cf3c3044bd4372232f2c1a27c4
+  a 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  b 0x3762d0d47116006179da35688eeaccf591a5cdea75000118d9608c59132d43426101a1dfb3774115f586623f75f00001ce611983c1275fa31f5bc9f4be1a0f467f01ca885c74777
+  r 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47
+  h 2
+  gx 0x0735e035def5925cc33173eb2a8ce7767522b466d278b650a2916127dfea9d2d361089f0a7a0247a184e1c70d417866e0fe0feb0ff8f2f3f9176418f97d117e624e2015df1662a8
+  gy 0x04a36420572616cdf7e606fccadaecfc3b76dab0eb1248dd03fbdfc9cd3242c4726be579855e812de7ec5c500b4576a24628048b6a72d880062eed0dd34b1096d3acbb6b01a4a97
+
+#----- That's all, folks-----------------------------------------------------
diff --git a/math/exp.c b/math/exp.c
new file mode 100644 (file)
index 0000000..4ddfa6d
--- /dev/null
@@ -0,0 +1,69 @@
+/* -*-c-*-
+ *
+ * Generalized exponentiation
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define EXP_TYPE /* Hack */
+#include "exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @exp_simulnext@ --- *
+ *
+ * Arguments:  @exp_simul *e@ = pointer to state structure
+ *             @size_t x@ = a current accumulator
+ *
+ * Returns:    The next column of bits.
+ *
+ * Use:                Scans the next column of bits for a simultaneous
+ *             exponentiation.
+ */
+
+size_t exp_simulnext(exp_simul *e, size_t x)
+{
+  size_t i;
+
+  /* --- Move to the next word along --- */
+
+  if (!e->b) {
+    e->o--;
+    for (i = 0; i < e->n; i++)
+      e->s[i].w = e->o < e->s[i].len ? e->s[i].v[e->o] : 0;
+    e->b = MPW_BITS;
+  }
+
+  /* --- Scan out a column of bits --- */
+
+  for (i = 0; i < e->n; i++) {
+    x = (x << 1) | ((e->s[i].w >> (MPW_BITS - 1)) & 1u);
+    e->s[i].w <<= 1;
+  }
+  e->b--;
+  return (x);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/exp.h b/math/exp.h
new file mode 100644 (file)
index 0000000..41581c5
--- /dev/null
@@ -0,0 +1,420 @@
+/* -*-c-*-
+ *
+ * Generalized exponentiation
+ *
+ * (c) 2001 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.
+ */
+
+#ifdef CATACOMB_EXP_H
+#  error "Multiple inclusion of <catacomb/exp.h>"
+#endif
+
+#define CATACOMB_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/alloc.h>
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct exp_simulscan {
+  mpw w;
+  size_t len;
+  const mpw *v;
+} exp_simulscan;
+
+typedef struct exp_simul {
+  unsigned b;
+  size_t o, n;
+  exp_simulscan *s;
+} exp_simul;
+
+/*----- Macros provided ---------------------------------------------------*/
+
+/* --- Parameters --- */
+
+#ifndef EXP_WINSZ                      /* Sliding window size */
+#  define EXP_WINSZ 4                  /* Predefine if you need to */
+#endif
+
+/* --- These are determined from the window size --- *
+ *
+ * Given a %$k$%-bit exponent, I expect to do %$k/2$% multiplies if I use the
+ * simple way.  If I use an n-bit sliding window, then I do %$2^n$%
+ * multiplies up front, but I only do %$(2^n - 1)/2^n k/n$% multiplies for
+ * the exponentiation.  This is a win when
+ *
+ *   %$k \ge \frac{n 2^{n+1}}{n - 2}$%
+ */
+
+#define EXP_TABSZ (1 << EXP_WINSZ)
+#define EXP_THRESH                                                     \
+    ((EXP_WINSZ * (2 << EXP_WINSZ))/((EXP_WINSZ - 2) * MPW_BITS))
+
+/* --- Required operations --- *
+ *
+ * The macros here are independent of the underlying group elements.  You
+ * must provide the necessary group operations and other definitions.  The
+ * group operation is assumed to be written multiplicatively.
+ *
+ * @EXP_TYPE@                  The type of a group element, e.g., @mp *@.
+ *
+ * @EXP_COPY(d, x)@            Makes @d@ be a copy of @x@.
+ *
+ * @EXP_DROP(x)@               Discards the element @x@, reclaiming any
+ *                             memory it used.
+ *
+ * @EXP_MUL(a, x)@             Multiplies @a@ by @x@ (writing the result
+ *                             back to @a@).
+ *
+ * @EXP_FIX(x)@                        Makes @x@ be a canonical representation of
+ *                             its value.  All multiplications have the
+ *                             right argument canonical.
+ *
+ * @EXP_SQR(a)@                        Multiplies @a@ by itself.
+ *
+ * @EXP_SETMUL(d, x, y)@       Sets @d@ to be the product of @x@ and @y@.
+ *                             The value @d@ has not been initialized.
+ *
+ * @EXP_SETSQR(d, x)@          Sets @d@ to be the square of @x@.
+ *
+ * Only @EXP_TYPE@, @EXP_MUL@ and @EXP_SQR@ are required for simple
+ * exponentation.  Sliding window and simultaneous exponentation require all
+ * of the operations.
+ */
+
+#ifndef EXP_TYPE
+#  error "EXP_TYPE not defined for <catacomb/exp.h>"
+#endif
+
+/* --- @EXP_SIMPLE@ --- *
+ *
+ * Arguments:  @a@ = the result object, initially a multiplicative identity
+ *             @g@ = the object to exponentiate
+ *             @x@ = the exponent, as a multiprecision integer
+ *
+ * Use:                Performs a simple left-to-right exponentiation.  At the end
+ *             of the code, the answer is left in @a@; @g@ and @x@ are
+ *             unchanged.
+ */
+
+#define EXP_SIMPLE(a, g, x) do {                                       \
+  mpscan sc;                                                           \
+  unsigned sq = 0;                                                     \
+                                                                       \
+  /* --- Begin scanning --- */                                         \
+                                                                       \
+  mp_rscan(&sc, x);                                                    \
+  if (!MP_RSTEP(&sc))                                                  \
+    goto exp_simple_exit;                                              \
+  while (!MP_RBIT(&sc))                                                        \
+    MP_RSTEP(&sc);                                                     \
+                                                                       \
+  /* --- Do the main body of the work --- */                           \
+                                                                       \
+  EXP_FIX(g);                                                          \
+  for (;;) {                                                           \
+    EXP_MUL(a, g);                                                     \
+    sq = 0;                                                            \
+    for (;;) {                                                         \
+      if (!MP_RSTEP(&sc))                                              \
+       goto exp_simple_done;                                           \
+      sq++;                                                            \
+      if (MP_RBIT(&sc))                                                        \
+       break;                                                          \
+    }                                                                  \
+    while (sq--) EXP_SQR(a);                                           \
+  }                                                                    \
+                                                                       \
+  /* --- Do a final round of squaring --- */                           \
+                                                                       \
+exp_simple_done:                                                       \
+  while (sq--) EXP_SQR(a);                                             \
+exp_simple_exit:;                                                      \
+} while (0)
+
+/* --- @EXP_WINDOW@ --- *
+ *
+ * Arguments:  @a@ = the result object, initially a multiplicative identity
+ *             @g@ = the object to exponentiate
+ *             @x@ = the exponent, as a multiprecision integer
+ *
+ * Use:                Performs a sliding-window exponentiation.  At the end of the
+ *             code, the answer is left in @a@; @g@ and @x@ are unchanged.
+ */
+
+#define EXP_WINDOW(a, g, x) do {                                       \
+  EXP_TYPE *v;                                                         \
+  EXP_TYPE g2;                                                         \
+  unsigned i, sq = 0;                                                  \
+  mpscan sc;                                                           \
+                                                                       \
+  /* --- Get going --- */                                              \
+                                                                       \
+  mp_rscan(&sc, x);                                                    \
+  if (!MP_RSTEP(&sc))                                                  \
+    goto exp_window_exit;                                              \
+                                                                       \
+  /* --- Do the precomputation --- */                                  \
+                                                                       \
+  EXP_FIX(g);                                                          \
+  EXP_SETSQR(g2, g);                                                   \
+  EXP_FIX(g2);                                                         \
+  v = xmalloc(EXP_TABSZ * sizeof(EXP_TYPE));                           \
+  EXP_COPY(v[0], g);                                                   \
+  for (i = 1; i < EXP_TABSZ; i++) {                                    \
+    EXP_SETMUL(v[i], v[i - 1], g2);                                    \
+    EXP_FIX(v[i]);                                                     \
+  }                                                                    \
+  EXP_DROP(g2);                                                                \
+                                                                       \
+  /* --- Skip top-end zero bits --- *                                  \
+   *                                                                   \
+   * If the initial step worked, there must be a set bit somewhere, so \
+   * keep stepping until I find it.                                    \
+   */                                                                  \
+                                                                       \
+  while (!MP_RBIT(&sc))                                                        \
+    MP_RSTEP(&sc);                                                     \
+                                                                       \
+  /* --- Now for the main work --- */                                  \
+                                                                       \
+  for (;;) {                                                           \
+    unsigned l = 1;                                                    \
+    unsigned z = 0;                                                    \
+                                                                       \
+    /* --- The next bit is set, so read a window index --- *           \
+     *                                                                 \
+     * Reset @i@ to zero and increment @sq@.  Then, until either I read        \
+     * @WINSZ@ bits or I run out of bits, scan in a bit: if it's clear,        \
+     * bump the @z@ counter; if it's set, push a set bit into @i@,     \
+     * shift it over by @z@ bits, bump @sq@ by @z + 1@ and clear @z@.  \
+     * By the end of this palaver, @i@ is an index to the precomputed  \
+     * value in @v@.                                                   \
+     */                                                                        \
+                                                                       \
+    i = 0;                                                             \
+    sq++;                                                              \
+    while (l < EXP_WINSZ && MP_RSTEP(&sc)) {                           \
+      l++;                                                             \
+      if (!MP_RBIT(&sc))                                               \
+       z++;                                                            \
+      else {                                                           \
+       i = ((i << 1) | 1) << z;                                        \
+       sq += z + 1;                                                    \
+       z = 0;                                                          \
+      }                                                                        \
+    }                                                                  \
+                                                                       \
+    /* --- Do the squaring --- *                                       \
+     *                                                                 \
+     * Remember that @sq@ carries over from the zero-skipping stuff    \
+     * below.                                                          \
+     */                                                                        \
+                                                                       \
+    while (sq--) EXP_SQR(a);                                           \
+                                                                       \
+    /* --- Do the multiply --- */                                      \
+                                                                       \
+    EXP_MUL(a, v[i]);                                                  \
+                                                                       \
+    /* --- Now grind along through the rest of the bits --- */         \
+                                                                       \
+    sq = z;                                                            \
+    for (;;) {                                                         \
+      if (!MP_RSTEP(&sc))                                              \
+       goto exp_window_done;                                           \
+      if (MP_RBIT(&sc))                                                        \
+       break;                                                          \
+      sq++;                                                            \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  /* --- Do a final round of squaring --- */                           \
+                                                                       \
+exp_window_done:                                                       \
+  while (sq--) EXP_SQR(a);                                             \
+  for (i = 0; i < EXP_TABSZ; i++)                                      \
+    EXP_DROP(v[i]);                                                    \
+  xfree(v);                                                            \
+exp_window_exit:;                                                      \
+} while (0)
+
+/* --- @EXP_SIMUL@ --- *
+ *
+ * Arguments:  @a@ = the result object, initially a multiplicative identity
+ *             @f@ = pointer to a vector of base/exp pairs
+ *             @n@ = the number of base/exp pairs
+ *
+ * Use:                Performs a simultaneous sliding-window exponentiation.  The
+ *             @f@ table is an array of structures containing members @base@
+ *             of type @EXP_TYPE@, and @exp@ of type @mp *@.
+ */
+
+#define EXP_SIMUL(a, f, n) do {                                                \
+  size_t i, j, jj, k;                                                  \
+  size_t vn = 1 << (EXP_WINSZ * n), m = (1 << n) - 1;                  \
+  EXP_TYPE *v = xmalloc(vn * sizeof(EXP_TYPE));                                \
+  exp_simul e;                                                         \
+  unsigned sq = 0;                                                     \
+                                                                       \
+  /* --- Fill in the precomputed table --- */                          \
+                                                                       \
+  j = 1;                                                               \
+  for (i = 0; i < n; i++) {                                            \
+    EXP_COPY(v[j], f[n - 1 - i].base);                                 \
+    EXP_FIX(v[j]);                                                     \
+    j <<= 1;                                                           \
+  }                                                                    \
+  k = n * EXP_WINSZ;                                                   \
+  jj = 1;                                                              \
+  for (; i < k; i++) {                                                 \
+    EXP_SETSQR(v[j], v[jj]);                                           \
+    EXP_FIX(v[j]);                                                     \
+    j <<= 1; jj <<= 1;                                                 \
+  }                                                                    \
+  for (i = 1; i < vn; i <<= 1) {                                       \
+    for (j = 1; j < i; j++) {                                          \
+      EXP_SETMUL(v[j + i], v[j], v[i]);                                        \
+      EXP_FIX(v[j + i]);                                               \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  /* --- Set up the bitscanners --- *                                  \
+   *                                                                   \
+   * Got to use custom scanners, to keep them all in sync.             \
+   */                                                                  \
+                                                                       \
+  e.n = n;                                                             \
+  e.b = 0;                                                             \
+  e.s = xmalloc(n * sizeof(*e.s));                                     \
+  e.o = 0;                                                             \
+  for (i = 0; i < n; i++) {                                            \
+    MP_SHRINK(f[i].exp);                                               \
+    e.s[i].len = MP_LEN(f[i].exp);                                     \
+    e.s[i].v = f[i].exp->v;                                            \
+    if (e.s[i].len > e.o)                                              \
+      e.o = e.s[i].len;                                                        \
+  }                                                                    \
+                                                                       \
+  /* --- Skip as far as a nonzero column in the exponent matrix --- */ \
+                                                                       \
+  do {                                                                 \
+    if (!e.o && !e.b)                                                  \
+      goto exp_simul_done;                                             \
+    i = exp_simulnext(&e, 0);                                          \
+  } while (!(i & m));                                                  \
+                                                                       \
+  /* --- Now for the main work --- */                                  \
+                                                                       \
+  for (;;) {                                                           \
+    unsigned l = 1;                                                    \
+    unsigned z = 0;                                                    \
+                                                                       \
+    /* --- Just read a nonzero column, so read a window index --- *    \
+     *                                                                 \
+     * Clear high bits of @i@ and increment @sq@.  Then, until either I        \
+     * read @WINSZ@ columns or I run out, scan in a column and append  \
+     * it to @i@.  If it's zero, bump the @z@ counter; if it's nonzero,        \
+     * bump @sq@ by @z + 1@ and clear @z@.  By the end of this palaver,        \
+     * @i@ is an index to the precomputed value in @v@, followed by    \
+     * @n * z@ zero bits.                                              \
+     */                                                                        \
+                                                                       \
+    sq++;                                                              \
+    while (l < EXP_WINSZ && (e.o || e.b)) {                            \
+      l++;                                                             \
+      i = exp_simulnext(&e, i);                                                \
+      if (!(i & m))                                                    \
+       z++;                                                            \
+      else {                                                           \
+       sq += z + 1;                                                    \
+       z = 0;                                                          \
+      }                                                                        \
+    }                                                                  \
+                                                                       \
+    /* --- Do the squaring --- *                                       \
+     *                                                                 \
+     * Remember that @sq@ carries over from the zero-skipping stuff    \
+     * below.                                                          \
+     */                                                                        \
+                                                                       \
+    while (sq--) EXP_SQR(a);                                           \
+                                                                       \
+    /* --- Do the multiply --- */                                      \
+                                                                       \
+    i >>= (z * n);                                                     \
+    EXP_MUL(a, v[i]);                                                  \
+                                                                       \
+    /* --- Now grind along through the rest of the bits --- */         \
+                                                                       \
+    sq = z;                                                            \
+    for (;;) {                                                         \
+      if (!e.o && !e.b)                                                        \
+       goto exp_simul_done;                                            \
+      if ((i = exp_simulnext(&e, 0)) != 0)                             \
+       break;                                                          \
+      sq++;                                                            \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  /* --- Do a final round of squaring --- */                           \
+                                                                       \
+exp_simul_done:                                                                \
+  while (sq--) EXP_SQR(a);                                             \
+  for (i = 1; i < vn; i++)                                             \
+    EXP_DROP(v[i]);                                                    \
+  xfree(v);                                                            \
+  xfree(e.s);                                                          \
+} while (0)
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @exp_simulnext@ --- *
+ *
+ * Arguments:  @exp_simul *e@ = pointer to state structure
+ *             @size_t x@ = a current accumulator
+ *
+ * Returns:    The next column of bits.
+ *
+ * Use:                Scans the next column of bits for a simultaneous
+ *             exponentiation.
+ */
+
+extern size_t exp_simulnext(exp_simul */*e*/, size_t /*x*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
diff --git a/math/f-binpoly.c b/math/f-binpoly.c
new file mode 100644 (file)
index 0000000..2ed270e
--- /dev/null
@@ -0,0 +1,182 @@
+/* -*-c-*-
+ *
+ * Binary fields with polynomial basis representation
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/sub.h>
+
+#include "field.h"
+#include "field-guts.h"
+#include "mprand.h"
+
+/*----- Polynomial basis --------------------------------------------------*/
+
+/* --- Field operations --- */
+
+static void fdestroy(field *ff) {
+  fctx_binpoly *f = (fctx_binpoly *)ff;
+  gfreduce_destroy(&f->r); MP_DROP(f->f.q);
+  DESTROY(f);
+}
+
+static mp *frand(field *f, mp *d, grand *r) {
+  return (mprand(d, f->nbits, r, 0));
+}
+
+static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); }
+
+static mp *fadd(field *ff, mp *d, mp *x, mp *y) { return (gf_add(d, x, y)); }
+
+static mp *fmul(field *ff, mp *d, mp *x, mp *y) {
+  fctx_binpoly *f = (fctx_binpoly *)ff; d = gf_mul(d, x, y);
+  return (gfreduce_do(&f->r, d, d));
+}
+
+static mp *fsqr(field *ff, mp *d, mp *x) {
+  fctx_binpoly *f = (fctx_binpoly *)ff; d = gf_sqr(d, x);
+  return (gfreduce_do(&f->r, d, d));
+}
+
+static mp *finv(field *ff, mp *d, mp *x) {
+  fctx_binpoly *f = (fctx_binpoly *)ff;
+  d = gf_modinv(d, x, f->r.p);
+  return (d);
+}
+
+static mp *freduce(field *ff, mp *d, mp *x) {
+  fctx_binpoly *f = (fctx_binpoly *)ff;
+  return (gfreduce_do(&f->r, d, x));
+}
+
+static mp *fsqrt(field *ff, mp *d, mp *x) {
+  fctx_binpoly *f = (fctx_binpoly *)ff;
+  return (gfreduce_sqrt(&f->r, d, x));
+}
+
+static mp *fquadsolve(field *ff, mp *d, mp *x) {
+  fctx_binpoly *f = (fctx_binpoly *)ff;
+  return (gfreduce_quadsolve(&f->r, d, x));
+}
+
+/* --- Field operations table --- */
+
+static const field_ops fops = {
+  FTY_BINARY, "binpoly",
+  fdestroy, frand, field_stdsamep,
+  freduce, field_id,
+  fzerop, field_id, fadd, fadd, fmul, fsqr, finv, freduce, fsqrt,
+  fquadsolve,
+  0, 0, 0, 0
+};
+
+/* --- @field_binpoly@ --- *
+ *
+ * Arguments:  @mp *p@ = the reduction polynomial
+ *
+ * Returns:    A pointer to the field.
+ *
+ * Use:                Creates a field structure for a binary field mod @p@.
+ */
+
+field *field_binpoly(mp *p)
+{
+  fctx_binpoly *f = CREATE(fctx_binpoly);
+  f->f.ops = &fops;
+  f->f.zero = MP_ZERO;
+  f->f.one = MP_ONE;
+  f->f.nbits = mp_bits(p) - 1;
+  f->f.noctets = (f->f.nbits + 7) >> 3;
+  gfreduce_create(&f->r, p);
+  f->f.m = f->r.p;
+  f->f.q = mp_lsl(MP_NEW, MP_ONE, f->f.nbits);
+  return (&f->f);
+}
+
+/*----- Normal basis ------------------------------------------------------*/
+
+/* --- Field operations --- */
+
+static void fndestroy(field *ff) {
+  fctx_binnorm *f = (fctx_binnorm *)ff; gfreduce_destroy(&f->f.r);
+  gfn_destroy(&f->ntop); gfn_destroy(&f->pton); MP_DROP(f->f.f.q);
+  DESTROY(f);
+}
+
+static int fnsamep(field *ff, field *gg) {
+  fctx_binnorm *f = (fctx_binnorm *)ff, *g = (fctx_binnorm *)gg;
+  return (MP_EQ(f->ntop.r[0], g->ntop.r[0]) && field_stdsamep(ff, gg));
+}
+
+static mp *fnin(field *ff, mp *d, mp *x) {
+  fctx_binnorm *f = (fctx_binnorm *)ff;
+  return (gfn_transform(&f->ntop, d, x));
+}
+
+static mp *fnout(field *ff, mp *d, mp *x) {
+  fctx_binnorm *f = (fctx_binnorm *)ff;
+  return (gfn_transform(&f->pton, d, x));
+}
+
+/* --- Field operations table --- */
+
+static const field_ops fnops = {
+  FTY_BINARY, "binnorm",
+  fndestroy, frand, fnsamep,
+  fnin, fnout,
+  fzerop, field_id, fadd, fadd, fmul, fsqr, finv, freduce, fsqrt,
+  fquadsolve,
+  0, 0, 0, 0
+};
+
+/* --- @field_binnorm@ --- *
+ *
+ * Arguments:  @mp *p@ = the reduction polynomial
+ *             @mp *beta@ = representation of normal point
+ *
+ * Returns:    A pointer to the field.
+ *
+ * Use:                Creates a field structure for a binary field mod @p@ which
+ *             uses a normal basis representation externally.  Computations
+ *             are still done on a polynomial-basis representation.
+ */
+
+field *field_binnorm(mp *p, mp *beta)
+{
+  fctx_binnorm *f = CREATE(fctx_binnorm);
+  f->f.f.ops = &fnops;
+  f->f.f.zero = MP_ZERO;
+  f->f.f.one = MP_ONE;
+  f->f.f.nbits = mp_bits(p) - 1;
+  f->f.f.noctets = (f->f.f.nbits + 7) >> 3;
+  gfreduce_create(&f->f.r, p);
+  f->f.f.m = f->f.r.p;
+  f->f.f.q = mp_lsl(MP_NEW, MP_ONE, f->f.f.nbits);
+  gfn_create(p, beta, &f->ntop, &f->pton);
+  return (&f->f.f);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/f-niceprime.c b/math/f-niceprime.c
new file mode 100644 (file)
index 0000000..342cb86
--- /dev/null
@@ -0,0 +1,162 @@
+/* -*-c-*-
+ *
+ * Prime fields with efficient reduction for special-form primes
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/sub.h>
+
+#include "field.h"
+#include "field-guts.h"
+#include "mprand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Field operations --- */
+
+static void fdestroy(field *ff) {
+  fctx_niceprime *f = (fctx_niceprime *)ff;
+  mpreduce_destroy(&f->r);
+  DESTROY(f);
+}
+
+static mp *frand(field *ff, mp *d, grand *r) {
+  fctx_niceprime *f = (fctx_niceprime *)ff;
+  return (mprand_range(d, f->r.p, r, 0));
+}
+
+static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); }
+
+static mp *fneg(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff;
+  return (mp_sub(d, f->r.p, x));
+}
+
+static mp *fadd(field *ff, mp *d, mp *x, mp *y) {
+  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_add(d, x, y);
+  if (MP_NEGP(d)) d = mp_add(d, d, f->r.p);
+  else if (MP_CMP(d, >, f->r.p)) d = mp_sub(d, d, f->r.p);
+  return (d);
+}
+
+static mp *fsub(field *ff, mp *d, mp *x, mp *y) {
+  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_sub(d, x, y);
+  if (MP_NEGP(d)) d = mp_add(d, d, f->r.p);
+  else if (MP_CMP(d, >, f->r.p)) d = mp_sub(d, d, f->r.p);
+  return (d);
+}
+
+static mp *fmul(field *ff, mp *d, mp *x, mp *y) {
+  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_mul(d, x, y);
+  return (mpreduce_do(&f->r, d, d));
+}
+
+static mp *fsqr(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_sqr(d, x);
+  return (mpreduce_do(&f->r, d, d));
+}
+
+static mp *finv(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff;
+  d = mp_modinv(d, x, f->r.p);
+  return (d);
+}
+
+static mp *freduce(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff;
+  return (mpreduce_do(&f->r, d, x));
+}
+
+static mp *fsqrt(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff;
+  return (mp_modsqrt(d, x, f->r.p));
+}
+
+static mp *fdbl(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_lsl(d, x, 1);
+  if (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p);
+  return (d);
+}
+
+static mp *ftpl(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff; MP_DEST(d, MP_LEN(x) + 1, x->f);
+  MPX_UMULN(d->v, d->vl, x->v, x->vl, 3); d->f &= ~MP_UNDEF;
+  while (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p);
+  return (d);
+}
+
+static mp *fqdl(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff; d = mp_lsl(d, x, 2);
+  while (MP_CMP(d, >=, f->r.p)) d = mp_sub(d, d, f->r.p);
+  return (d);
+}
+
+static mp *fhlv(field *ff, mp *d, mp *x) {
+  fctx_niceprime *f = (fctx_niceprime *)ff;
+  if (MP_ZEROP(x)) { MP_COPY(x); MP_DROP(d); return (x); }
+  if (x->v[0] & 1) { d = mp_add(d, x, f->r.p); x = d; }
+  return (mp_lsr(d, x, 1));
+}
+
+/* --- Field operations table --- */
+
+static const field_ops fops = {
+  FTY_PRIME, "niceprime",
+  fdestroy, frand, field_stdsamep,
+  freduce, field_id,
+  fzerop, fneg, fadd, fsub, fmul, fsqr, finv, freduce, fsqrt,
+  0,
+  fdbl, ftpl, fqdl, fhlv
+};
+
+/* --- @field_niceprime@ --- *
+ *
+ * Arguments:  @mp *p@ = the characteristic of the field
+ *
+ * Returns:    A pointer to the field, or null.
+ *
+ * Use:                Creates a field structure for a prime field of size %$p$%,
+ *             using efficient reduction for nice primes.
+ */
+
+field *field_niceprime(mp *p)
+{
+  fctx_niceprime *f = CREATE(fctx_niceprime);
+  f->f.ops = &fops;
+  f->f.zero = MP_ZERO;
+  f->f.one = MP_ONE;
+  f->f.nbits = mp_bits(p);
+  f->f.noctets = (f->f.nbits + 7) >> 3;
+  if (mpreduce_create(&f->r, p)) {
+    DESTROY(f);
+    return (0);
+  }
+  f->f.m = f->r.p;
+  f->f.q = f->r.p;
+  return (&f->f);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/f-prime.c b/math/f-prime.c
new file mode 100644 (file)
index 0000000..d9c5c17
--- /dev/null
@@ -0,0 +1,176 @@
+/* -*-c-*-
+ *
+ * Prime fields with Montgomery arithmetic
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/sub.h>
+
+#include "field.h"
+#include "mprand.h"
+#include "field-guts.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Field operations --- */
+
+static void fdestroy(field *ff) {
+  fctx_prime *f = (fctx_prime *)ff;
+  mpmont_destroy(&f->mm);
+  DESTROY(f);
+}
+
+static mp *frand(field *ff, mp *d, grand *r) {
+  fctx_prime *f = (fctx_prime *)ff;
+  return (mprand_range(d, f->mm.m, r, 0));
+}
+
+static mp *fin(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff;
+  mp_div(0, &d, x, f->mm.m);
+  return (mpmont_mul(&f->mm, d, d, f->mm.r2));
+}
+
+static mp *fout(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff;
+  return (mpmont_reduce(&f->mm, d, x));
+}
+
+static int fzerop(field *ff, mp *x) { return (MP_ZEROP(x)); }
+
+static mp *fneg(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff;
+  return (mp_sub(d, f->mm.m, x));
+}
+
+static mp *fadd(field *ff, mp *d, mp *x, mp *y) {
+  fctx_prime *f = (fctx_prime *)ff; d = mp_add(d, x, y);
+  if (MP_NEGP(d)) d = mp_add(d, d, f->mm.m);
+  else if (MP_CMP(d, >, f->mm.m)) d = mp_sub(d, d, f->mm.m);
+  return (d);
+}
+
+static mp *fsub(field *ff, mp *d, mp *x, mp *y) {
+  fctx_prime *f = (fctx_prime *)ff; d = mp_sub(d, x, y);
+  if (MP_NEGP(d)) d = mp_add(d, d, f->mm.m);
+  else if (MP_CMP(d, >, f->mm.m)) d = mp_sub(d, d, f->mm.m);
+  return (d);
+}
+
+static mp *fmul(field *ff, mp *d, mp *x, mp *y) {
+  fctx_prime *f = (fctx_prime *)ff;
+  return (mpmont_mul(&f->mm, d, x, y));
+}
+
+static mp *fsqr(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff; d = mp_sqr(d, x);
+  return (mpmont_reduce(&f->mm, d, d));
+}
+
+static mp *finv(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff; d = mpmont_reduce(&f->mm, d, x);
+  d = mp_modinv(d, d, f->mm.m); return (mpmont_mul(&f->mm, d, d, f->mm.r2));
+}
+
+static mp *freduce(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff;
+  mp_div(0, &d, x, f->mm.m);
+  return (d);
+}
+
+static mp *fsqrt(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff; d = mpmont_reduce(&f->mm, d, x);
+  d = mp_modsqrt(d, d, f->mm.m); if (!d) return (d);
+  return (mpmont_mul(&f->mm, d, d, f->mm.r2));
+}
+
+static mp *fdbl(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff; d = mp_lsl(d, x, 1);
+  if (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m);
+  return (d);
+}
+
+static mp *ftpl(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff; MP_DEST(d, MP_LEN(x) + 1, x->f);
+  MPX_UMULN(d->v, d->vl, x->v, x->vl, 3); d->f &= ~MP_UNDEF;
+  while (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m);
+  return (d);
+}
+
+static mp *fqdl(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff; d = mp_lsl(d, x, 2);
+  while (MP_CMP(d, >=, f->mm.m)) d = mp_sub(d, d, f->mm.m);
+  return (d);
+}
+
+static mp *fhlv(field *ff, mp *d, mp *x) {
+  fctx_prime *f = (fctx_prime *)ff;
+  if (MP_ZEROP(x)) { MP_COPY(x); MP_DROP(d); return (x); }
+  if (x->v[0] & 1) { d = mp_add(d, x, f->mm.m); x = d; }
+  return (mp_lsr(d, x, 1));
+}
+
+/* --- Field operations table --- */
+
+static const field_ops fops = {
+  FTY_PRIME, "prime",
+  fdestroy, frand, field_stdsamep,
+  fin, fout,
+  fzerop, fneg, fadd, fsub, fmul, fsqr, finv, freduce, fsqrt,
+  0,
+  fdbl, ftpl, fqdl, fhlv
+};
+
+/* --- @field_prime@ --- *
+ *
+ * Arguments:  @mp *p@ = the characteristic of the field
+ *
+ * Returns:    A pointer to the field or null.
+ *
+ * Use:                Creates a field structure for a prime field of size %$p$%,
+ *             using Montgomery reduction for arithmetic.
+ */
+
+field *field_prime(mp *p)
+{
+  fctx_prime *f;
+
+  f = CREATE(fctx_prime);
+  f->f.ops = &fops;
+  if (mpmont_create(&f->mm, p)) {
+    DESTROY(f);
+    return (0);
+  }
+  f->f.zero = MP_ZERO;
+  f->f.one = f->mm.r;
+  f->f.m = f->mm.m;
+  f->f.nbits = mp_bits(p);
+  f->f.noctets = (f->f.nbits + 7) >> 3;
+  f->f.q = f->mm.m;
+  return (&f->f);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/field-exp.c b/math/field-exp.c
new file mode 100644 (file)
index 0000000..bbadb86
--- /dev/null
@@ -0,0 +1,71 @@
+/* -*-c-*-
+ *
+ * Exponentiation in finite fields
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "field.h"
+#include "field-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @field_exp@ --- *
+ *
+ * Arguments:  @field *f@ = pointer to field
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e$%.
+ *
+ * Use:                Exponentiation in a finite field.  Note that all quantities
+ *             are in internal format.
+ */
+
+mp *field_exp(field *f, mp *d, mp *a, mp *e)
+{
+  mp *x = MP_COPY(f->one);
+  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
+
+  MP_COPY(a);
+  MP_SHRINK(e);
+  if (MP_ZEROP(e))
+    ;
+  else {
+    if (MP_NEGP(e))
+      a = F_INV(f, a, a);
+    if (MP_LEN(e) < EXP_THRESH)
+      EXP_SIMPLE(x, a, e);
+    else
+      EXP_WINDOW(x, a, e);
+  }
+  mp_drop(d);
+  mp_drop(spare);
+  mp_drop(a);
+  return (x);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/field-exp.h b/math/field-exp.h
new file mode 100644 (file)
index 0000000..70dda63
--- /dev/null
@@ -0,0 +1,57 @@
+/* -*-c-*-
+ *
+ * Exponentiation in finite fields
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_FIELD_EXP_H
+#define CATACOMB_FIELD_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentiation definitions ----------------------------------------*/
+
+#define EXP_TYPE mp *
+
+#define EXP_COPY(d, x) d = MP_COPY(x)
+#define EXP_DROP(x) MP_DROP(x)
+
+#define EXP_MUL(a, x) a = F_MUL(f, a, a, x)
+#define EXP_SQR(a) a = F_SQR(f, a, a)
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) d = F_MUL(f, MP_NEW, x, y)
+#define EXP_SETSQR(d, x) d = F_SQR(f, MP_NEW, x)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/field-guts.h b/math/field-guts.h
new file mode 100644 (file)
index 0000000..1122b6c
--- /dev/null
@@ -0,0 +1,97 @@
+/* -*-c-*-
+ *
+ * Internal structures for built-in fields
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_FIELD_GUTS_H
+#define CATACOMB_FIELD_GUTS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+#ifndef CATACOMB_MPMONT_H
+#  include "mpmont.h"
+#endif
+
+#ifndef CATACOMB_MPREDUCE_H
+#  include "mpreduce.h"
+#endif
+
+#ifndef CATACOMB_GF_H
+#  include "gf.h"
+#endif
+
+#ifndef CATACOMB_GFN_H
+#  include "gfn.h"
+#endif
+
+#ifndef CATACOMB_GFREDUCE_H
+#  include "gfreduce.h"
+#endif
+
+#ifndef CATACOMB_FIELD_H
+#  include "field.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct fctx_prime {
+  field f;
+  mpmont mm;
+} fctx_prime;
+
+typedef struct fctx_niceprime {
+  field f;
+  mpreduce r;
+} fctx_niceprime;
+
+typedef struct fctx_binpoly {
+  field f;
+  gfreduce r;
+} fctx_binpoly;
+
+typedef struct fctx_binnorm {
+  fctx_binpoly f;
+  gfn ntop, pton;
+} fctx_binnorm;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/field-parse.c b/math/field-parse.c
new file mode 100644 (file)
index 0000000..eed08fa
--- /dev/null
@@ -0,0 +1,85 @@
+/* -*-c-*-
+ *
+ * Parse field descriptions
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "field.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @field_parse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *
+ * Returns:    Field pointer if OK, or null.
+ *
+ * Use:                Parses a field description, which has the form
+ *
+ *               * `prime', `niceprime' or `binpoly'
+ *               * an optional `:'
+ *               * the field modulus
+ */
+
+field *field_parse(qd_parse *qd)
+{
+  field *f = 0;
+  mp *m = MP_NEW, *b = MP_NEW;
+
+  switch (qd_enum(qd, "prime,niceprime,binpoly,binnorm")) {
+    case 0:
+      qd_delim(qd, ':');
+      if ((m = qd_getmp(qd)) == 0) goto done;
+      f = field_prime(m);
+      break;
+    case 1:
+      qd_delim(qd, ':');
+      if ((m = qd_getmp(qd)) == 0) goto done;
+      f = field_niceprime(m);
+      break;
+    case 2:
+      qd_delim(qd, ':');
+      if ((m = qd_getmp(qd)) == 0) goto done;
+      f = field_binpoly(m);
+      break;
+    case 3:
+      qd_delim(qd, ':');
+      if ((m = qd_getmp(qd)) == 0) goto done;
+      qd_delim(qd, ',');
+      if ((b = qd_getmp(qd)) == 0) goto done;
+      f = field_binnorm(m, b);
+      break;
+    default:
+      goto done;
+  }
+  if (!f) qd->e = "bad field parameters";
+done:
+  mp_drop(m);
+  mp_drop(b);
+  return (f);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/field.c b/math/field.c
new file mode 100644 (file)
index 0000000..0198fca
--- /dev/null
@@ -0,0 +1,76 @@
+/* -*-c-*-
+ *
+ * Abstract field operations
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "field.h"
+#include "mp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @field_id@ --- *
+ *
+ * Arguments:  @field *f@ = pointer to a field
+ *             @mp *d@ = a destination element
+ *             @mp *x@ = a source element
+ *
+ * Returns:    The result element.
+ *
+ * Use:                An identity operation which can be used if your field has no
+ *             internal representation.
+ */
+
+mp *field_id(field *f, mp *d, mp *x)
+  { x = MP_COPY(x); if (d) MP_DROP(d); return (x); }
+
+/* --- @field_samep@ --- *
+ *
+ * Arguments:  @field *f, *g@ = two fields
+ *
+ * Returns:    Nonzero if the fields are identical (not just isomorphic).
+ *
+ * Use:                Checks for sameness of fields.  This function does the full
+ *             check, not just the field-type-specific check done by the
+ *             @sampep@ field operation.
+ */
+
+int field_samep(field *f, field *g)
+  { return (f == g || (f->ops == g->ops && F_SAMEP(f, g))); }
+
+/* --- @field_stdsamep@ --- *
+ *
+ * Arguments:  @field *f, *g@ = two fields
+ *
+ * Returns:    Nonzero if the fields are identical (not just isomorphic).
+ *
+ * Use:                Standard sameness check, based on equality of the @m@
+ *             member.
+ */
+
+int field_stdsamep(field *f, field *g) { return (MP_EQ(f->m, g->m)); }
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/field.h b/math/field.h
new file mode 100644 (file)
index 0000000..c1ec030
--- /dev/null
@@ -0,0 +1,265 @@
+/* -*-c-*-
+ *
+ * Definitions for field arithmetic
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_FIELD_H
+#define CATACOMB_FIELD_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_QDPARSE_H
+#  include "qdparse.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct field {
+  const struct field_ops *ops;         /* Field operations */
+  mp *zero, *one;                      /* Identities in the field */
+  mp *m;                               /* Modulus (prime and binary) */
+  unsigned long nbits;                 /* Length of field element in bits */
+  size_t noctets;                      /* Length of element in octets */
+  mp *q;                               /* Number of elements in field */
+} field;
+
+enum {
+  FTY_PRIME,
+  FTY_BINARY
+};
+
+typedef struct field_ops {
+
+  /* --- General information --- */
+
+  unsigned ty;                         /* What kind of field this is */
+  const char *name;                    /* Human-readable name string */
+
+  /* --- Universal operations --- */
+
+  void (*destroy)(field */*f*/);
+  mp *(*rand)(field */*f*/, mp */*d*/, grand */*r*/);
+  int (*samep)(field */*f*/, field */*g*/);
+
+  mp *(*in)(field */*f*/, mp */*d*/, mp */*x*/);
+  mp *(*out)(field */*f*/, mp */*d*/, mp */*x*/);
+
+  int (*zerop)(field */*f*/, mp */*x*/);
+  mp *(*neg)(field */*f*/, mp */*d*/, mp */*x*/);
+  mp *(*add)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
+  mp *(*sub)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
+  mp *(*mul)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
+  mp *(*sqr)(field */*f*/, mp */*d*/, mp */*x*/);
+  mp *(*inv)(field */*f*/, mp */*d*/, mp */*x*/);
+  mp *(*reduce)(field */*f*/, mp */*d*/, mp */*x*/);
+  mp *(*sqrt)(field */*f*/, mp */*d*/, mp */*x*/);
+
+  /* --- Operations for binary fields only --- */
+
+  mp *(*quadsolve)(field */*f*/, mp */*d*/, mp */*x*/);
+
+  /* --- Operations for prime fields only --- */
+
+  mp *(*dbl)(field */*f*/, mp */*d*/, mp */*x*/);
+  mp *(*tpl)(field */*f*/, mp */*d*/, mp */*x*/);
+  mp *(*qdl)(field */*f*/, mp */*d*/, mp */*x*/);
+  mp *(*hlv)(field */*f*/, mp */*d*/, mp */*x*/);
+
+} field_ops;
+
+#define F_TYPE(f)              (f)->ops->ty
+#define F_NAME(f)              (f)->ops->name
+
+#define F_DESTROY(f)           (f)->ops->destroy((f))
+#define F_RAND(f, d, r)                (f)->ops->rand((f), (d), (r))
+#define F_SAMEP(f, g)          (f)->ops->samep((f), (g))
+
+#define F_IN(f, d, x)          (f)->ops->in((f), (d), (x))
+#define F_OUT(f, d, x)         (f)->ops->out((f), (d), (x))
+
+#define F_ZEROP(f, x)          (f)->ops->zerop((f), (x))
+#define F_NEG(f, d, x)         (f)->ops->neg((f), (d), (x))
+#define F_ADD(f, d, x, y)      (f)->ops->add((f), (d), (x), (y))
+#define F_SUB(f, d, x, y)      (f)->ops->sub((f), (d), (x), (y))
+#define F_MUL(f, d, x, y)      (f)->ops->mul((f), (d), (x), (y))
+#define F_SQR(f, d, x)         (f)->ops->sqr((f), (d), (x))
+#define F_INV(f, d, x)         (f)->ops->inv((f), (d), (x))
+#define F_REDUCE(f, d, x)      (f)->ops->reduce((f), (d), (x))
+#define F_SQRT(f, d, x)                (f)->ops->sqrt((f), (d), (x))
+
+#define F_QUADSOLVE(f, d, x)   (f)->ops->quadsolve((f), (d), (x))
+
+#define F_DBL(f, d, x)         (f)->ops->dbl((f), (d), (x))
+#define F_TPL(f, d, x)         (f)->ops->tpl((f), (d), (x))
+#define F_QDL(f, d, x)         (f)->ops->qdl((f), (d), (x))
+#define F_HLV(f, d, x)         (f)->ops->hlv((f), (d), (x))
+
+/*----- Helpful field operations ------------------------------------------*/
+
+/* --- @field_id@ --- *
+ *
+ * Arguments:  @field *f@ = pointer to a field
+ *             @mp *d@ = a destination element
+ *             @mp *x@ = a source element
+ *
+ * Returns:    The result element.
+ *
+ * Use:                An identity operation which can be used if your field has no
+ *             internal representation.
+ */
+
+extern mp *field_id(field */*f*/, mp */*d*/, mp */*x*/);
+
+/* --- @field_samep@ --- *
+ *
+ * Arguments:  @field *f, *g@ = two fields
+ *
+ * Returns:    Nonzero if the fields are identical (not just isomorphic).
+ *
+ * Use:                Checks for sameness of fields.  This function does the full
+ *             check, not just the field-type-specific check done by the
+ *             @sampep@ field operation.
+ */
+
+extern int field_samep(field */*f*/, field */*g*/);
+
+/* --- @field_stdsamep@ --- *
+ *
+ * Arguments:  @field *f, *g@ = two fields
+ *
+ * Returns:    Nonzero if the fields are identical (not just isomorphic).
+ *
+ * Use:                Standard sameness check, based on equality of the @m@
+ *             member.
+ */
+
+extern int field_stdsamep(field */*f*/, field */*g*/);
+
+/*----- Arithmetic --------------------------------------------------------*/
+
+/* --- @field_exp@ --- *
+ *
+ * Arguments:  @field *f@ = pointer to field
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e$%.
+ *
+ * Use:                Exponentiation in a finite field.  Note that all quantities
+ *             are in internal format.  This is a generic implementation
+ *             suitable for use with all fields and is not intended to be
+ *             optimal.
+ */
+
+extern mp *field_exp(field */*f*/, mp */*d*/, mp */*a*/, mp */*e*/);
+
+/*----- Creating fields ---------------------------------------------------*/
+
+/* --- @field_prime@ --- *
+ *
+ * Arguments:  @mp *p@ = the characteristic of the field
+ *
+ * Returns:    A pointer to the field.
+ *
+ * Use:                Creates a field structure for a prime field of size %$p$%,
+ *             using Montgomery reduction for arithmetic.
+ */
+
+extern field *field_prime(mp */*p*/);
+
+/* --- @field_niceprime@ --- *
+ *
+ * Arguments:  @mp *p@ = the characteristic of the field
+ *
+ * Returns:    A pointer to the field, or null.
+ *
+ * Use:                Creates a field structure for a prime field of size %$p$%,
+ *             using efficient reduction for nice primes.
+ */
+
+extern field *field_niceprime(mp */*p*/);
+
+/* --- @field_binpoly@ --- *
+ *
+ * Arguments:  @mp *p@ = an irreducible polynomial over %$\gf{2}$%
+ *
+ * Returns:    A pointer to the field.
+ *
+ * Use:                Creates a field structure for a binary field using naive
+ *             arithmetic.
+ */
+
+extern field *field_binpoly(mp */*p*/);
+
+/* --- @field_binnorm@ --- *
+ *
+ * Arguments:  @mp *p@ = the reduction polynomial
+ *             @mp *beta@ = representation of normal point
+ *
+ * Returns:    A pointer to the field.
+ *
+ * Use:                Creates a field structure for a binary field mod @p@ which
+ *             uses a normal basis representation externally.  Computations
+ *             are still done on a polynomial-basis representation.
+ */
+
+extern field *field_binnorm(mp */*p*/, mp */*beta*/);
+
+/* --- @field_parse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *
+ * Returns:    Field pointer if OK, or null.
+ *
+ * Use:                Parses a field description, which has the form
+ *
+ *               * `prime', `niceprime', `binpoly', or `binnorm'
+ *               * an optional `:'
+ *               * the field modulus
+ *               * for `binnorm', an optional `,' and the beta value
+ */
+
+extern field *field_parse(qd_parse */*qd*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/g-bin.c b/math/g-bin.c
new file mode 100644 (file)
index 0000000..79a989f
--- /dev/null
@@ -0,0 +1,177 @@
+/* -*-c-*-
+ *
+ * Abstraction for prime groups
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/sub.h>
+
+#include "mpmont.h"
+#include "pgen.h"
+
+#define ge mp *
+#include "group.h"
+#include "group-guts.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Group operations --- */
+
+static void gdestroygroup(group *gg) {
+  gctx_bin *g = (gctx_bin *)gg;
+  mp_drop(g->gen); mp_drop(g->g.r); mp_drop(g->g.h);
+  gfreduce_destroy(&g->r);
+  DESTROY(g);
+}
+
+static mp **gcreate(group *gg)
+  { mp **x = CREATE(mp *); *x = MP_COPY(*gg->i); return (x); }
+
+static void gcopy(group *gg, mp **d, mp **x)
+  { mp *t = MP_COPY(*x); MP_DROP(*d); *d = t; }
+
+static void gburn(group *gg, mp **x) { (*x)->f |= MP_BURN; }
+
+static void gdestroy(group *gg, mp **x) { MP_DROP(*x); DESTROY(x); }
+
+static int gsamep(group *gg, group *hh) {
+  gctx_bin *g = (gctx_bin *)gg, *h = (gctx_bin *)hh;
+  return (MP_EQ(g->r.p, h->r.p));
+}
+
+static int geq(group *gg, mp **x, mp **y) { return (MP_EQ(*x, *y)); }
+
+static const char *gcheck(group *gg, grand *gr) {
+  gctx_bin *g = (gctx_bin *)gg; int rc; mp *t, *tt;
+  if (!gf_irreduciblep(g->r.p)) return ("p is not irreducible");
+  t = mp_mul(MP_NEW, g->g.r, g->g.h); t = mp_add(t, t, MP_ONE);
+  tt = mp_lsl(MP_NEW, MP_ONE, g->g.nbits);
+  rc = MP_EQ(t, tt); MP_DROP(t); MP_DROP(tt);
+  if (!rc) return ("not a subgroup");
+  return (group_stdcheck(gg, gr));
+}
+
+static void gmul(group *gg, mp **d, mp **x, mp **y) {
+  gctx_bin *g = (gctx_bin *)gg; mp *r = gf_mul(*d, *x, *y);
+  *d = gfreduce_do(&g->r, r, r);
+}
+
+static void gsqr(group *gg, mp **d, mp **x) {
+  gctx_bin *g = (gctx_bin *)gg; mp *r = gf_sqr(*d, *x);
+  *d = gfreduce_do(&g->r, r, r);
+}
+
+static void ginv(group *gg, mp **d, mp **x)
+  { gctx_bin *g = (gctx_bin *)gg; *d = gf_modinv(*d, *x, g->r.p); }
+
+static void gexp(group *gg, mp **d, mp **x, mp *n)
+  { gctx_bin *g = (gctx_bin *)gg; *d = gfreduce_exp(&g->r, *d, *x, n); }
+
+static int gread(group *gg, mp **d, const mptext_ops *ops, void *p) {
+  mp *t; if ((t = mp_read(MP_NEW, 0, ops, p)) == 0) return (-1);
+  mp_drop(*d); *d = t; return (0);
+}
+
+static int gwrite(group *gg, mp **x, const mptext_ops *ops, void *p) {
+  int rc = -1;
+  if (!ops->put("0x", 2, p) && !mp_write(*x, 16, ops, p)) rc = 0;
+  return (rc);
+}
+
+static mp *gtoint(group *gg, mp *d, mp **x) { return MP_COPY(*x); }
+
+static int gfromint(group *gg, mp **d, mp *x) { *d = MP_COPY(x); return 0; }
+
+static int gtobuf(group *gg, buf *b, mp **x)
+  { int rc = buf_putmp(b, *x); return (rc); }
+
+static int gfrombuf(group *gg, buf *b, mp **d) {
+  gctx_bin *g = (gctx_bin *)gg; mp *x;
+  if ((x = buf_getmp(b)) == 0) return (-1);
+  MP_DROP(*d); *d = gfreduce_do(&g->r, x, x);
+  return (0);
+}
+
+static int gtoraw(group *gg, buf *b, mp **x) {
+  gctx_bin * g = (gctx_bin *)gg; octet *q;
+  if ((q = buf_get(b, g->g.noctets)) == 0) return (-1);
+  mp_storeb(*x, q, g->g.noctets); return (0);
+}
+
+static int gfromraw(group *gg, buf *b, mp **d) {
+  gctx_bin * g = (gctx_bin *)gg; mp *x; octet *q;
+  if ((q = buf_get(b, g->g.noctets)) == 0) return (-1);
+  x = mp_loadb(MP_NEW, q, g->g.noctets);
+  MP_DROP(*d); *d = gfreduce_do(&g->r, x, x);
+  return (0);
+}
+
+/* --- @group_binary@ --- *
+ *
+ * Arguments:  @const gbin_param *gb@ = group parameters
+ *
+ * Returns:    A pointer to the group, or null.
+ *
+ * Use:                Constructs an abstract group interface for a subgroup of a
+ *             prime field.  Group elements are @mp *@ pointers.
+ */
+
+static const group_ops gops = {
+  GTY_BINARY, "bin",
+  gdestroygroup, gcreate, gcopy, gburn, gdestroy,
+  gsamep, geq, group_stdidentp,
+  gcheck,
+  gmul, gsqr, ginv, group_stddiv, gexp, group_stdmexp,
+  gread, gwrite,
+  gtoint, gfromint, group_stdtoec, group_stdfromec, gtobuf, gfrombuf,
+  gtoraw, gfromraw
+};
+
+group *group_binary(const gbin_param *gb)
+{
+  gctx_bin *g;
+  mp *t;
+
+  if (!MP_POSP(gb->p))
+    return (0);
+  g = CREATE(gctx_bin);
+  g->g.ops = &gops;
+  g->g.nbits = mp_bits(gb->p) - 1;
+  g->g.noctets = (g->g.nbits + 7) >> 3;
+  gfreduce_create(&g->r, gb->p);
+  g->one = MP_ONE;
+  g->g.i = &g->one;
+  g->gen = MP_COPY(gb->g);
+  g->g.g = &g->gen;
+  g->g.r = MP_COPY(gb->q);
+  t = mp_lsl(MP_NEW, MP_ONE, g->g.nbits);
+  t = mp_sub(t, t, MP_ONE);
+  g->g.h = MP_NEW; mp_div(&g->g.h, 0, t, gb->q);
+  MP_DROP(t);
+  return (&g->g);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/g-ec.c b/math/g-ec.c
new file mode 100644 (file)
index 0000000..f885c40
--- /dev/null
@@ -0,0 +1,216 @@
+/* -*-c-*-
+ *
+ * Abstraction for elliptic curve groups
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <ctype.h>
+
+#include <mLib/sub.h>
+
+#define ge ec
+#include "group.h"
+#include "ec-raw.h"
+#include "group-guts.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Group operations --- */
+
+static void gdestroygroup(group *gg) {
+  gctx_ec *g = (gctx_ec *)gg;
+  EC_DESTROY(&g->gen);
+  ec_freeinfo(&g->ei);
+  DESTROY(g);
+}
+
+static ec *gcreate(group *gg)
+  { ec *x = CREATE(ec); EC_CREATE(x); return (x); }
+
+static void gcopy(group *gg, ec *d, ec *x) { EC_COPY(d, x); }
+
+static void gburn(group *gg, ec *x) { if (x->x) (x->x)->f |= MP_BURN; }
+
+static void gdestroy(group *gg, ec *x) { EC_DESTROY(x); DESTROY(x); }
+
+static int gsamep(group *gg, group *hh) {
+  gctx_ec *g = (gctx_ec *)gg, *h = (gctx_ec *)hh;
+  return (ec_sameinfop(&g->ei, &h->ei));
+}
+
+static int geq(group *gg, ec *x, ec *y) {
+  gctx_ec *g = (gctx_ec *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y);
+  return (EC_EQ(x, y));
+}
+
+static int gidentp(group *gg, ec *x) { return (EC_ATINF(x)); }
+
+static const char *gcheck(group *gg, grand *gr)
+  { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); }
+
+static void gmul(group *gg, ec *d, ec *x, ec *y)
+  { gctx_ec *g = (gctx_ec *)gg; EC_ADD(g->ei.c, d, x, y); }
+
+static void gsqr(group *gg, ec *d, ec *x)
+  { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); }
+
+static void ginv(group *gg, ec *d, ec *x)
+  { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); }
+
+static void gdiv(group *gg, ec *d, ec *x, ec *y)
+  { gctx_ec *g = (gctx_ec *)gg; EC_SUB(g->ei.c, d, x, y); }
+
+static void gexp(group *gg, ec *d, ec *x, mp *n)
+  { gctx_ec *g = (gctx_ec *)gg; ec_imul(g->ei.c, d, x, n); }
+
+static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) {
+  gctx_ec *g = (gctx_ec *)gg; size_t i;
+  ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
+  for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; }
+  ec_immul(g->ei.c, d, ff, n); xfree(ff);
+}
+
+static int gread(group *gg, ec *d, const mptext_ops *ops, void *p) {
+  gctx_ec *g = (gctx_ec *)gg;
+  ec t = EC_INIT;
+  int rc = -1;
+  int ch;
+
+  ch = ops->get(p);
+  if (tolower(ch) == 'i') {
+    if (tolower(ops->get(p)) != 'n' || tolower(ops->get(p)) != 'f')
+      return (-1);
+    EC_SETINF(d);
+    return (0);
+  }
+  ops->unget(ch, p);
+  if ((t.x = mp_read(MP_NEW, 0, ops, p)) == 0) goto done;
+  do ch = ops->get(p); while (ch == ',' || isspace(ch)); ops->unget(ch, p);
+  if ((t.y = mp_read(MP_NEW, 0, ops, p)) == 0) goto done;
+  EC_IN(g->ei.c, &t, &t);
+  if (EC_CHECK(g->ei.c, &t)) goto done;
+  EC_COPY(d, &t); rc = 0;
+  EC_DESTROY(&t);
+done:
+  return (rc);
+}
+
+static int gwrite(group *gg, ec *x, const mptext_ops *ops, void *p) {
+  gctx_ec *g = (gctx_ec *)gg; int rc = -1; ec t = EC_INIT;
+  EC_OUT(g->ei.c, &t, x); if (EC_ATINF(&t)) rc = ops->put("inf", 3, p);
+  else if (!ops->put("0x", 2, p) && !mp_write(t.x, 16, ops, p) &&
+          !ops->put(", 0x", 4, p) && !mp_write(t.y, 16, ops, p)) rc = 0;
+  EC_DESTROY(&t); return (rc);
+}
+
+static mp *gtoint(group *gg, mp *d, ec *x) {
+  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0;
+  else { EC_OUT(g->ei.c, &t, x); i = MP_COPY(t.x); EC_DESTROY(&t); }
+  mp_drop(d); return (i);
+}
+
+static int gfromint(group *gg, ec *d, mp *x) {
+  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT;
+  if (!ec_find(g->ei.c, &t, x)) return (-1);
+  EC_IN(g->ei.c, d, &t); EC_DESTROY(&t); return (0);
+}
+
+static int gtoec(group *gg, ec *d, ec *x)
+  { gctx_ec *g = (gctx_ec *)gg; EC_OUT(g->ei.c, d, x); return (0); }
+
+static int gfromec(group *gg, ec *d, const ec *x) {
+  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x);
+  rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t);
+  return (rc);
+}
+
+static int gtobuf(group *gg, buf *b, ec *x) {
+  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
+  EC_OUT(g->ei.c, &t, x); rc = buf_putec(b, &t); EC_DESTROY(&t); return (rc);
+}
+
+static int gfrombuf(group *gg, buf *b, ec *d) {
+  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
+  if (buf_getec(b, &t)) return (-1);
+  EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t);
+  if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc);
+}
+
+static int gtoraw(group *gg, buf *b, ec *x) {
+  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
+  EC_OUT(g->ei.c, &t, x); rc = ec_putraw(g->ei.c, b, &t);
+  EC_DESTROY(&t); return (rc);
+}
+
+static int gfromraw(group *gg, buf *b, ec *d) {
+  gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
+  if (ec_getraw(g->ei.c, b, &t)) return (-1);
+  EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t);
+  if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc);
+}
+
+/* --- @group_ec@ --- *
+ *
+ * Arguments:  @const ec_info *ei@ = elliptic curve parameters
+ *
+ * Returns:    A pointer to the group.
+ *
+ * Use:                Constructs an abstract group interface for an elliptic curve
+ *             group.  Group elements are @ec@ structures.  The contents of
+ *             the @ec_info@ structure becomes the property of the @group@
+ *             object; you can (and should) free the structure itself, but
+ *             calling @ec_freeinfo@ on it is not allowed.
+ */
+
+static const group_ops gops = {
+  GTY_EC, "ec",
+  gdestroygroup, gcreate, gcopy, gburn, gdestroy,
+  gsamep, geq, gidentp,
+  gcheck,
+  gmul, gsqr, ginv, gdiv, gexp, gmexp,
+  gread, gwrite,
+  gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw
+};
+
+group *group_ec(const ec_info *ei)
+{
+  gctx_ec *g = CREATE(gctx_ec);
+
+  g->g.ops = &gops;
+  g->g.nbits = ei->c->f->nbits * 2;
+  g->g.noctets = ei->c->f->noctets * 2 + 1;
+  g->ei = *ei;
+  EC_CREATE(&g->id);
+  g->g.i = &g->id;
+  EC_CREATE(&g->gen);
+  g->g.g = &g->gen;
+  EC_IN(g->ei.c, &g->gen, &ei->g);
+  g->g.r = ei->r;
+  g->g.h = ei->h;
+  return (&g->g);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/g-prime.c b/math/g-prime.c
new file mode 100644 (file)
index 0000000..892e743
--- /dev/null
@@ -0,0 +1,188 @@
+/* -*-c-*-
+ *
+ * Abstraction for prime groups
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/sub.h>
+
+#include "mpmont.h"
+#include "pgen.h"
+
+#define ge mp *
+#include "group.h"
+#include "group-guts.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Group operations --- */
+
+static void gdestroygroup(group *gg) {
+  gctx_prime *g = (gctx_prime *)gg;
+  mp_drop(g->gen); mp_drop(g->g.r); mp_drop(g->g.h);
+  mpmont_destroy(&g->mm);
+  DESTROY(g);
+}
+
+static mp **gcreate(group *gg)
+  { mp **x = CREATE(mp *); *x = MP_COPY(*gg->i); return (x); }
+
+static void gcopy(group *gg, mp **d, mp **x)
+  { mp *t = MP_COPY(*x); MP_DROP(*d); *d = t; }
+
+static void gburn(group *gg, mp **x) { (*x)->f |= MP_BURN; }
+
+static void gdestroy(group *gg, mp **x) { MP_DROP(*x); DESTROY(x); }
+
+static int gsamep(group *gg, group *hh) {
+  gctx_prime *g = (gctx_prime *)gg, *h = (gctx_prime *)hh;
+  return (MP_EQ(g->mm.m, h->mm.m));
+}
+
+static int geq(group *gg, mp **x, mp **y) { return (MP_EQ(*x, *y)); }
+
+static const char *gcheck(group *gg, grand *gr) {
+  gctx_prime *g = (gctx_prime *)gg; int rc; mp *t;
+  if (!pgen_primep(g->mm.m, gr)) return ("p is not prime");
+  t = mp_mul(MP_NEW, g->g.r, g->g.h); t = mp_add(t, t, MP_ONE);
+  rc = MP_EQ(t, g->mm.m); MP_DROP(t); if (!rc) return ("not a subgroup");
+  return (group_stdcheck(gg, gr));
+}
+
+static void gmul(group *gg, mp **d, mp **x, mp **y)
+  { gctx_prime *g = (gctx_prime *)gg; *d = mpmont_mul(&g->mm, *d, *x, *y); }
+
+static void gsqr(group *gg, mp **d, mp **x) {
+  gctx_prime *g = (gctx_prime *)gg; mp *r = mp_sqr(*d, *x);
+  *d = mpmont_reduce(&g->mm, r, r);
+}
+
+static void ginv(group *gg, mp **d, mp **x) {
+  gctx_prime *g = (gctx_prime *)gg; mp *r = mpmont_reduce(&g->mm, *d, *x);
+  r = mp_modinv(r, r, g->mm.m); *d = mpmont_mul(&g->mm, r, r, g->mm.r2);
+}
+
+static void gexp(group *gg, mp **d, mp **x, mp *n)
+  { gctx_prime *g = (gctx_prime *)gg; *d = mpmont_expr(&g->mm, *d, *x, n); }
+
+static void gmexp(group *gg, mp **d, const group_expfactor *f, size_t n) {
+  gctx_prime *g = (gctx_prime *)gg; size_t i;
+  mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor));
+  for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; }
+  *d = mpmont_mexpr(&g->mm, *d, ff, n); xfree(ff);
+}
+
+static int gread(group *gg, mp **d, const mptext_ops *ops, void *p) {
+  gctx_prime *g = (gctx_prime *)gg; mp *t;
+  if ((t = mp_read(MP_NEW, 0, ops, p)) == 0) return (-1);
+  mp_drop(*d); *d = mpmont_mul(&g->mm, t, t, g->mm.r2); return (0);
+}
+
+static int gwrite(group *gg, mp **x, const mptext_ops *ops, void *p) {
+  gctx_prime *g = (gctx_prime *)gg;
+  mp *t = mpmont_reduce(&g->mm, MP_NEW, *x);
+  int rc = mp_write(t, 10, ops, p); MP_DROP(t); return (rc);
+}
+
+static mp *gtoint(group *gg, mp *d, mp **x) {
+  gctx_prime *g = (gctx_prime *)gg;
+  return (mpmont_reduce(&g->mm, d, *x));
+}
+
+static int gfromint(group *gg, mp **d, mp *x) {
+  gctx_prime *g = (gctx_prime *)gg; mp_div(0, d, x, g->mm.m);
+  *d = mpmont_mul(&g->mm, *d, *d, g->mm.r2); return (0);
+}
+
+static int gtobuf(group *gg, buf *b, mp **x) {
+  gctx_prime *g = (gctx_prime *)gg;
+  mp *t = mpmont_reduce(&g->mm, MP_NEW, *x);
+  int rc = buf_putmp(b, t); MP_DROP(t); return (rc);
+}
+
+static int gfrombuf(group *gg, buf *b, mp **d) {
+  gctx_prime * g = (gctx_prime *)gg; mp *x;
+  if ((x = buf_getmp(b)) == 0) return (-1);
+  mp_div(0, &x, x, g->mm.m); mp_drop(*d);
+  *d = mpmont_mul(&g->mm, x, x, g->mm.r2); return(0);
+}
+
+static int gtoraw(group *gg, buf *b, mp **x) {
+  gctx_prime *g = (gctx_prime *)gg; octet *q;
+  mp *t = mpmont_reduce(&g->mm, MP_NEW, *x);
+  if ((q = buf_get(b, g->g.noctets)) == 0) { MP_DROP(t); return (-1); }
+  mp_storeb(t, q, g->g.noctets); MP_DROP(t); return (0);
+}
+
+static int gfromraw(group *gg, buf *b, mp **d) {
+  gctx_prime * g = (gctx_prime *)gg; mp *x; octet *q;
+  if ((q = buf_get(b, g->g.noctets)) == 0) return (-1);
+  x = mp_loadb(MP_NEW, q, g->g.noctets);
+  mp_div(0, &x, x, g->mm.m); mp_drop(*d);
+  *d = mpmont_mul(&g->mm, x, x, g->mm.r2); return(0);
+}
+
+/* --- @group_prime@ --- *
+ *
+ * Arguments:  @const gprime_param *gp@ = group parameters
+ *
+ * Returns:    A pointer to the group, or null.
+ *
+ * Use:                Constructs an abstract group interface for a subgroup of a
+ *             prime field.  Group elements are @mp *@ pointers.
+ */
+
+static const group_ops gops = {
+  GTY_PRIME, "prime",
+  gdestroygroup, gcreate, gcopy, gburn, gdestroy,
+  gsamep, geq, group_stdidentp,
+  gcheck,
+  gmul, gsqr, ginv, group_stddiv, gexp, gmexp,
+  gread, gwrite,
+  gtoint, gfromint, group_stdtoec, group_stdfromec, gtobuf, gfrombuf,
+  gtoraw, gfromraw
+};
+
+group *group_prime(const gprime_param *gp)
+{
+  gctx_prime *g;
+
+  if (!MP_POSP(gp->p) || !MP_ODDP(gp->p))
+    return (0);
+  g = CREATE(gctx_prime);
+  g->g.ops = &gops;
+  g->g.nbits = mp_bits(gp->p);
+  g->g.noctets = (g->g.nbits + 7) >> 3;
+  mpmont_create(&g->mm, gp->p);
+  g->g.i = &g->mm.r;
+  g->gen = mpmont_mul(&g->mm, MP_NEW, gp->g, g->mm.r2);
+  g->g.g = &g->gen;
+  g->g.r = MP_COPY(gp->q);
+  g->g.h = MP_NEW; mp_div(&g->g.h, 0, gp->p, gp->q);
+  return (&g->g);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/genlimits.c b/math/genlimits.c
new file mode 100644 (file)
index 0000000..22c9f5f
--- /dev/null
@@ -0,0 +1,280 @@
+/* -*-c-*-
+ *
+ * Generate limit MPs for C types
+ *
+ * (c) 2006 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#if __STDC_VERSION__ >= 199900l
+#  include <stdint.h>
+#  include <inttypes.h>
+#endif
+
+#include "mp.h"
+#include "mpint.h"
+
+/*----- Data types --------------------------------------------------------*/
+
+/* --- Hack for GCC --- *
+ *
+ * WG14 in their infinite wisdom decided not to use the GCC constant name.
+ */
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)
+#  define EXT __extension__
+#else
+#  define EXT
+#endif
+
+#if defined(LONG_LONG_MIN) && !defined(LLONG_MIN)
+#  define LLONG_MIN EXT LONG_LONG_MIN
+#endif
+
+#if defined(LONG_LONG_MAX) && !defined(LLONG_MAX)
+#  define LLONG_MAX EXT LONG_LONG_MAX
+#endif
+
+#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
+#  define ULLONG_MAX EXT ULONG_LONG_MAX
+#endif
+
+/* --- Choose the largest integer type --- */
+
+#if defined(INTMAX_MAX)
+  typedef intmax_t imax;
+#elif defined(LLONG_MAX)
+  EXT typedef long long imax;
+#else
+  typedef long imax;
+#endif
+
+#if defined(UINTMAX_MAX)
+  typedef uintmax_t umax;
+#elif defined(ULLONG_MAX)
+  EXT typedef unsigned long long umax;
+#else
+  typedef unsigned long umax;
+#endif
+
+/*----- Main code ---------------------------------------------------------*/
+
+#define TABSZ 64
+
+enum { NEG, POS, NSIGN };
+
+umax cmap[TABSZ];
+int gmap[TABSZ][NSIGN];
+struct { int g, s; } qmap[TABSZ];
+int dumpp = 0;
+
+static int n, q;
+
+static void dump(mp *x)
+{
+  int i, w, n;
+
+  fputs("  ", stdout);
+  w = (MPW_BITS + 3)/4;
+  n = 1;
+  while (2 + 2 * n * (4 + w) < 72) n <<= 1;
+  i = 0;
+  for (;;) {
+    printf("0x%0*x", w, x->v[i]);
+    i++;
+    if (i >= MP_LEN(x)) break;
+    fputs(",", stdout);
+    if (i % n) fputs(" ", stdout); else fputs("\n  ", stdout);
+  }
+  fputs("\n", stdout);
+}
+
+static void doemit(umax c, int s, int *gg, int *qq)
+{
+  int i;
+  mp *x = MP_NEW;
+
+  for (i = 0; i < n; i++) {
+    if (cmap[i] == c)
+      goto found;
+  }
+
+  assert(i < TABSZ);
+  n = i + 1;
+  cmap[i] = c;
+  gmap[i][POS] = gmap[i][NEG] = -1;
+  if (dumpp) {
+    MP_FROMINT(x, umax, c);
+    printf("static mpw guts_%d[] = {\n", q);
+    dump(x);
+    fputs("};\n\n", stdout);
+    MP_DROP(x);
+  }
+
+found:
+  *gg = i;
+  if (gmap[i][s] < 0) {
+    assert(q < TABSZ);
+    gmap[i][s] = q;
+    qmap[q].g = i;
+    qmap[q].s = s;
+    q++;
+  }
+  *qq = gmap[i][s];
+}
+
+static void emit(imax c, int *gg, int *qq)
+{
+  umax uc;
+  int s;
+
+  if (c >= 0) { uc = c; s = POS; }
+  else { uc = -c; s = NEG; }
+  doemit(uc, s, gg, qq);
+}
+
+static void uemit(umax c, int *gg, int *qq) { doemit(c, POS, gg, qq); }
+
+struct {
+  const char *name;
+  imax min;
+  umax max;
+  int gmin, gmax;
+  int qmin, qmax;
+} tab[] = {
+  { "SCHAR",   SCHAR_MIN,      SCHAR_MAX },
+  { "CHAR",    CHAR_MIN,       CHAR_MAX },
+  { "UCHAR",   0,              UCHAR_MAX },
+  { "UINT8",   0,              0xff },
+  { "SHRT",    SHRT_MIN,       SHRT_MAX },
+  { "USHRT",   0,              USHRT_MAX },
+  { "UINT16",  0,              0xffff },
+  { "INT",     INT_MIN,        INT_MAX },
+  { "UINT",    0,              UINT_MAX },
+  { "LONG",    LONG_MIN,       LONG_MAX },
+  { "ULONG",   0,              ULONG_MAX },
+  { "UINT32",  0,              0xffffffff },
+#ifdef LLONG_MAX
+  { "LLONG",   LLONG_MIN,      LLONG_MAX },
+  { "ULLONG",  0,              ULLONG_MAX },
+#endif
+  { "SIZET",   0,              ~(size_t)0 },
+  { 0 }
+};
+
+static void dogen(void)
+{
+  int i;
+
+  for (i = 0; tab[i].name; i++) {
+    if (tab[i].min)
+      emit(tab[i].min, &tab[i].gmin, &tab[i].qmin);
+    uemit(tab[i].max, &tab[i].gmax, &tab[i].qmax);
+  }
+}
+
+static void cgen(void)
+{
+  int i;
+
+  fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * C integer limits [generated]\n\
+ */\n\
+\n\
+#include \"mplimits.h\"\n\
+\n\
+#define N(x) (sizeof(x)/sizeof(*x))\n\
+#define MPpos(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }\n\
+#define MPneg(x) { x, x + N(x), N(x), 0, MP_CONST|MP_NEG, 0 }\n\
+\n",
+       stdout);
+  dumpp = 1;
+  dogen();
+
+  fputs("mp mp_limits[] = {\n", stdout);
+  for (i = 0; i < q; i++)
+    printf("  MP%s(guts_%d),\n", qmap[i].s ? "pos" : "neg", qmap[i].g);
+  fputs("};\n", stdout);
+}
+
+static void hgen(void)
+{
+  int i;
+
+  fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * C integer limits [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_MPLIMITS_H\n\
+#define CATACOMB_MPLIMITS_H\n\
+\n\
+#ifndef CATACOMB_MP_H\n\
+#  include \"mp.h\"\n\
+#endif\n\
+\n\
+extern mp mp_limits[];\n\
+\n",
+       stdout);
+  dogen();
+
+  for (i = 0; tab[i].name; i++) {
+    if (tab[i].min) {
+      printf("#define MP_%s_MIN (&mp_limits[%d])\n",
+            tab[i].name, gmap[tab[i].qmin][NEG]);
+    }
+    printf("#define MP_%s_MAX (&mp_limits[%d])\n",
+          tab[i].name, gmap[tab[i].qmax][POS]);
+  }
+  fputs("\n#endif\n", stdout);
+}
+
+int main(int argc, char *argv[])
+{
+  const char *what = argc == 2 ? argv[1] : "<bogus>";
+
+  switch (what[0]) {
+    case 'c': cgen(); break;
+    case 'h': hgen(); break;
+    default:
+      fprintf(stderr, "unknown action `%s'\n", what);
+      exit(1);
+  }
+  if (fflush(stdout) || fclose(stdout)) {
+    fprintf(stderr, "error writing output: %s\n", strerror(errno));
+    exit(1);
+  }
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/genprimes.c b/math/genprimes.c
new file mode 100644 (file)
index 0000000..a4bf64a
--- /dev/null
@@ -0,0 +1,191 @@
+/* -*-c-*-
+ *
+ * Generate prime number table
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/darray.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+
+/*----- Data structures ---------------------------------------------------*/
+
+DA_DECL(intv, int);
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  int p_max = 0, p_n = 0;
+  char *type = "unsigned int";
+  char *header = "primetab.h";
+  char *source = "primetab.c";
+  char *name = "primetab";
+  char *sym = 0;
+  intv p = DA_INIT;
+  int i;
+
+  ego(argv[0]);
+
+  for (;;) {
+    int i = getopt(argc, argv, "h:c:i:n:m:t:s:");
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'h':
+       header = optarg;
+       break;
+      case 'c':
+       source = optarg;
+       break;
+      case 'i':
+       name = optarg;
+       break;
+      case 'n':
+       p_max = 0;
+       p_n = atoi(optarg);
+       break;
+      case 'm':
+       p_n = 0;
+       p_max = atoi(optarg);
+       break;
+      case 't':
+       type = optarg;
+       break;
+      case 's':
+       sym = optarg;
+       break;
+      default:
+       pquis(stderr, "Usage: $ [-n nprimes] [-m maxprime] [-t type]\n");
+       exit(EXIT_FAILURE);
+    }
+  }
+
+  if (!p_max && !p_n)
+    die(EXIT_FAILURE, "bad arguments to `-n' or `-m'");
+
+  if (p_n || p_max >= 2)
+    DA_PUSH(&p, 2);
+  for (i = 3; (!p_max && !p_n) ||
+             (p_n && DA_LEN(&p) < p_n) ||
+             (p_max && i <= p_max);
+       i += 2) {
+    int j;
+    for (j = 0; j < DA_LEN(&p); j++) {
+      if (i % DA(&p)[j] == 0)
+       goto composite;
+    }
+    DA_PUSH(&p, i);
+  composite:;
+  }
+
+  {
+    FILE *fp = fopen(header, "w");
+    dstr d = DSTR_INIT;
+    char *q;
+    if (!fp)
+      die(EXIT_FAILURE, "couldn't write `%s': %s", header, strerror(errno));
+    if (!sym) {
+      for (q = header; *q; q++) {
+       int ch = (unsigned char)*q;
+       if (isalnum(ch))
+         ch = toupper(ch);
+       else
+         ch = '_';
+       DPUTC(&d, ch);
+      }
+      DPUTZ(&d);
+      sym = d.buf;
+    }
+    fprintf(fp, "\
+/* -*-c-*-\n\
+ *\n\
+ * Table of small prime numbers [generated]\n\
+ */\n\
+\n\
+#ifndef %s\n\
+#define %s\n\
+\n\
+#define NPRIME %luu\n\
+#define MAXPRIME %uu\n\
+\n\
+typedef %s smallprime;\n\
+extern const smallprime %s[];\n\
+\n\
+#endif\n\
+",
+           sym, sym,
+           (unsigned long)DA_LEN(&p),
+           DA_LAST(&p),
+           type, name);
+    dstr_destroy(&d);
+    if (fclose(fp) == EOF) {
+      remove(header);
+      die(EXIT_FAILURE, "error writing `%s': %s", header, strerror(errno));
+    }
+  }
+
+  {
+    FILE *fp = fopen(source, "w");
+    int i;
+    if (!fp)
+      die(EXIT_FAILURE, "couldn't write `%s': %s", source, strerror(errno));
+    fprintf(fp, "\
+/* -*-c-*-\n\
+ *\n\
+ * Table of small prime numbers [generated]\n\
+ */\n\
+\n\
+#include \"%s\"\n\
+\n\
+const %s %s[] = {",
+           header, type, name);
+    for (i = 0; i < DA_LEN(&p); i++) {
+      if (i % 8 == 0)
+       fputs("\n  ", fp);
+      fprintf(fp, "%5i, ", DA(&p)[i]);
+    }
+    fputs("\n\
+};\n\
+", fp);
+    if (fclose(fp) == EOF) {
+      remove(source);
+      die(EXIT_FAILURE, "error writing `%s': %s", source, strerror(errno));
+    }
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from genwheel.c
rename to math/genwheel.c
diff --git a/math/gf-arith.c b/math/gf-arith.c
new file mode 100644 (file)
index 0000000..1c67c74
--- /dev/null
@@ -0,0 +1,307 @@
+/* -*-c-*-
+ *
+ * Basic arithmetic on binary polynomials
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "gf.h"
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define MAX(x, y) ((x) >= (y) ? (x) : (y))
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gf_add@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @a@ added to @b@.
+ */
+
+mp *gf_add(mp *d, mp *a, mp *b)
+{
+  MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & MP_BURN);
+  gfx_add(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+  d->f = (a->f | b->f) & MP_BURN;
+  MP_SHRINK(d);
+  return (d);
+}
+
+/* --- @gf_mul@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @a@ multiplied by @b@.
+ */
+
+mp *gf_mul(mp *d, mp *a, mp *b)
+{
+  a = MP_COPY(a);
+  b = MP_COPY(b);
+
+  if (MP_LEN(a) <= MPK_THRESH || MP_LEN(b) <= GFK_THRESH) {
+    MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF);
+    gfx_mul(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+  } else {
+    size_t m = MAX(MP_LEN(a), MP_LEN(b));
+    mpw *s;
+    MP_DEST(d, 2 * m, a->f | b->f | MP_UNDEF);
+    s = mpalloc(d->a, 3 * m);
+    gfx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + 3 * m);
+    mpfree(d->a, s);
+  }
+
+  d->f = (a->f | b->f) & MP_BURN;
+  MP_SHRINK(d);
+  MP_DROP(a);
+  MP_DROP(b);
+  return (d);
+}
+
+/* --- @gf_sqr@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *
+ * Returns:    Result, @a@ squared.
+ */
+
+mp *gf_sqr(mp *d, mp *a)
+{
+  MP_COPY(a);
+  MP_DEST(d, 2 * MP_LEN(a), a->f & MP_BURN);
+  gfx_sqr(d->v, d->vl, a->v, a->vl);
+  d->f = a->f & MP_BURN;
+  MP_SHRINK(d);
+  MP_DROP(a);
+  return (d);
+}
+
+/* --- @gf_div@ --- *
+ *
+ * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
+ *             @mp *a, *b@ = sources
+ *
+ * Use:                Calculates the quotient and remainder when @a@ is divided by
+ *             @b@.  The destinations @*qq@ and @*rr@ must be distinct.
+ *             Either of @qq@ or @rr@ may be null to indicate that the
+ *             result is irrelevant.  (Discarding both results is silly.)
+ *             There is a performance advantage if @a == *rr@.
+ */
+
+void gf_div(mp **qq, mp **rr, mp *a, mp *b)
+ {
+  mp *r = rr ? *rr : MP_NEW;
+  mp *q = qq ? *qq : MP_NEW;
+
+  /* --- Set the remainder up right --- */
+
+  b = MP_COPY(b);
+  a = MP_COPY(a);
+  if (r)
+    MP_DROP(r);
+  r = a;
+  MP_DEST(r, MP_LEN(b) + 2, a->f | b->f);
+
+  /* --- Fix up the quotient too --- */
+
+  r = MP_COPY(r);
+  MP_DEST(q, MP_LEN(r), r->f | MP_UNDEF);
+  MP_DROP(r);
+
+  /* --- Perform the calculation --- */
+
+  gfx_div(q->v, q->vl, r->v, r->vl, b->v, b->vl);
+
+  /* --- Sort out the sign of the results --- *
+   *
+   * If the signs of the arguments differ, and the remainder is nonzero, I
+   * must add one to the absolute value of the quotient and subtract the
+   * remainder from @b@.
+   */
+
+  q->f = (r->f | b->f) & MP_BURN;
+  r->f = (r->f | b->f) & MP_BURN;
+
+  /* --- Store the return values --- */
+
+  MP_DROP(b);
+
+  if (!qq)
+    MP_DROP(q);
+  else {
+    MP_SHRINK(q);
+    *qq = q;
+  }
+
+  if (!rr)
+    MP_DROP(r);
+  else {
+    MP_SHRINK(r);
+    *rr = r;
+  }
+}
+
+/* --- @gf_irreduciblep@ --- *
+ *
+ * Arguments:  @mp *f@ = a polynomial
+ *
+ * Returns:    Nonzero if the polynomial is irreducible; otherwise zero.
+ */
+
+int gf_irreduciblep(mp *f)
+{
+  unsigned long m;
+  mp *u = MP_TWO;
+  mp *v = MP_NEW;
+
+  if (MP_ZEROP(f))
+    return (0);
+  else if (MP_LEN(f) == 1) {
+    if (f->v[0] < 2) return (0);
+    if (f->v[0] < 4) return (1);
+  }
+  m = (mp_bits(f) - 1)/2;
+  while (m) {
+    u = gf_sqr(u, u);
+    gf_div(0, &u, u, f);
+    v = gf_add(v, u, MP_TWO);
+    gf_gcd(&v, 0, 0, v, f);
+    if (!MP_EQ(v, MP_ONE)) break;
+    m--;
+  }
+  MP_DROP(u);
+  MP_DROP(v);
+  return (!m);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b)
+{
+  if (!MP_EQ(expect, result)) {
+    fprintf(stderr, "\n*** %s failed", op);
+    fputs("\n*** a     = ", stderr); mp_writefile(a, stderr, 16);
+    fputs("\n*** b     = ", stderr); mp_writefile(b, stderr, 16);
+    fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 16);
+    fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 16);
+    fputc('\n', stderr);
+    return (0);
+  }
+  return (1);
+}
+
+#define RIG(name, op)                                                  \
+  static int t##name(dstr *v)                                          \
+  {                                                                    \
+    mp *a = *(mp **)v[0].buf;                                          \
+    mp *b = *(mp **)v[1].buf;                                          \
+    mp *r = *(mp **)v[2].buf;                                          \
+    mp *c = op(MP_NEW, a, b);                                          \
+    int ok = verify(#name, r, c, a, b);                                        \
+    mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(r);                    \
+    assert(mparena_count(MPARENA_GLOBAL) == 0);                                \
+    return (ok);                                                       \
+  }
+
+RIG(add, gf_add)
+RIG(mul, gf_mul)
+RIG(exp, gf_exp)
+
+#undef RIG
+
+static int tsqr(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  mp *r = *(mp **)v[1].buf;
+  mp *c = MP_NEW;
+  int ok = 1;
+  c = gf_sqr(MP_NEW, a);
+  ok &= verify("sqr", r, c, a, MP_ZERO);
+  mp_drop(a); mp_drop(r); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tdiv(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  mp *b = *(mp **)v[1].buf;
+  mp *q = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *c = MP_NEW, *d = MP_NEW;
+  int ok = 1;
+  gf_div(&c, &d, a, b);
+  ok &= verify("div(quotient)", q, c, a, b);
+  ok &= verify("div(remainder)", r, d, a, b);
+  mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(d); mp_drop(r); mp_drop(q);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tirred(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  int r = *(int *)v[1].buf;
+  int c = gf_irreduciblep(a);
+  int ok = 1;
+  if (r != c) {
+    ok = 0;
+    fprintf(stderr, "\n*** irred failed");
+    fputs("\n*** a     = ", stderr); mp_writefile(a, stderr, 16);
+    fprintf(stderr, "\n*** r     = %d\n", r);
+    fprintf(stderr, "*** c     = %d\n", c);
+  }
+  mp_drop(a);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "add", tadd, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "sqr", tsqr, { &type_mp, &type_mp, 0 } },
+  { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "irred", tirred, { &type_mp, &type_int, 0 } },
+  { 0, 0, { 0 } },
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/gf");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gf-exp.c b/math/gf-exp.c
new file mode 100644 (file)
index 0000000..14c40d3
--- /dev/null
@@ -0,0 +1,65 @@
+/* -*-c-*-
+ *
+ * Exponentiation for binary polynomials
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+
+#include "gf.h"
+#include "gf-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gf_exp@ --- *
+ *
+ * Arguments:  @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e$%.
+ */
+
+mp *gf_exp(mp *d, mp *a, mp *e)
+{
+  mp *x = MP_ONE;
+  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
+  assert(!MP_NEGP(e));
+
+  MP_COPY(a);
+  if (MP_ZEROP(e))
+    ;
+  else if (MP_LEN(e) < EXP_THRESH)
+    EXP_SIMPLE(x, a, e);
+  else
+    EXP_WINDOW(x, a, e);
+  mp_drop(d);
+  mp_drop(spare);
+  mp_drop(a);
+  return (x);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gf-exp.h b/math/gf-exp.h
new file mode 100644 (file)
index 0000000..189fc76
--- /dev/null
@@ -0,0 +1,67 @@
+/* -*-c-*-
+ *
+ * Exponentiation for binary polynomials
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_GF_EXP_H
+#define CATACOMB_GF_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentiation ----------------------------------------------------*/
+
+#define EXP_TYPE mp *
+
+#define EXP_COPY(d, x) d = MP_COPY(x)
+#define EXP_DROP(x) MP_DROP(x)
+
+#define EXP_MUL(a, x) do {                                             \
+  mp *t = gf_mul(spare, a, x);                                         \
+  spare = a;                                                           \
+  a = t;                                                               \
+} while (0)
+
+#define EXP_SQR(a) do {                                                        \
+  mp *t = gf_sqr(spare, a);                                            \
+  spare = a;                                                           \
+  a = t;                                                               \
+} while (0)
+
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) d = gf_mul(MP_NEW, x, y)
+#define EXP_SETSQR(d, x) d = gf_sqr(MP_NEW, x)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/gf-gcd.c b/math/gf-gcd.c
new file mode 100644 (file)
index 0000000..f81aac7
--- /dev/null
@@ -0,0 +1,261 @@
+/* -*-c-*-
+ *
+ * Euclidian algorithm on binary polynomials
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "gf.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gf_gcd@ --- *
+ *
+ * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
+ *             @mp *a, *b@ = sources (must be nonzero)
+ *
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
+ *             @ax + by = gcd(a, b)@.  This is useful for computing modular
+ *             inverses.
+ */
+
+void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b)
+{
+  mp *x = MP_ONE, *X = MP_ZERO;
+  mp *y = MP_ZERO, *Y = MP_ONE;
+  mp *u, *v;
+  mp *q = MP_NEW, *t, *spare = MP_NEW;
+  unsigned f = 0;
+
+#define f_swap 1u
+#define f_ext 2u
+
+  /* --- Sort out some initial flags --- */
+
+  if (xx || yy)
+    f |= f_ext;
+
+  /* --- Ensure that @a@ is larger than @b@ --- *
+   *
+   * If they're the same length we don't care which order they're in, so this
+   * unsigned comparison is fine.
+   */
+
+  if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) {
+    t = a; a = b; b = t;
+    f |= f_swap;
+  }
+
+  /* --- Check for zeroness --- */
+
+  if (MP_EQ(b, MP_ZERO)) {
+
+    /* --- Store %$|a|$% as the GCD --- */
+
+    if (gcd) {
+      if (*gcd) MP_DROP(*gcd);
+      a = MP_COPY(a);
+      *gcd = a;
+    }
+
+    /* --- Store %$1$% and %$0$% in the appropriate bins --- */
+
+    if (f & f_ext) {
+      if (f & f_swap) {
+       mp **t = xx; xx = yy; yy = t;
+      }
+      if (xx) {
+       if (*xx) MP_DROP(*xx);
+       if (MP_EQ(a, MP_ZERO))
+         *xx = MP_ZERO;
+       else
+         *xx = MP_ONE;
+      }
+      if (yy) {
+       if (*yy) MP_DROP(*yy);
+       *yy = MP_ZERO;
+      }
+    }
+    return;
+  }
+
+  /* --- Main extended Euclidean algorithm --- */
+
+  u = MP_COPY(a);
+  v = MP_COPY(b);
+
+  while (!MP_ZEROP(v)) {
+    gf_div(&q, &u, u, v);
+    if (f & f_ext) {
+      t = gf_mul(spare, X, q);
+      t = gf_add(t, t, x);
+      spare = x; x = X; X = t;
+      t = gf_mul(spare, Y, q);
+      t = gf_add(t, t, y);
+      spare = y; y = Y; Y = t;
+    }
+    t = u; u = v; v = t;
+  }
+
+  MP_DROP(q); if (spare) MP_DROP(spare);
+  if (!gcd)
+    MP_DROP(u);
+  else {
+    if (*gcd) MP_DROP(*gcd);
+    u->f &= ~MP_NEG;
+    *gcd = u;
+  }
+
+  /* --- Perform a little normalization --- */
+
+  if (f & f_ext) {
+
+    /* --- If @a@ and @b@ got swapped, swap the coefficients back --- */
+
+    if (f & f_swap) {
+      t = x; x = y; y = t;
+      t = a; a = b; b = t;
+    }
+
+    /* --- Store the results --- */
+
+    if (!xx)
+      MP_DROP(x);
+    else {
+      if (*xx) MP_DROP(*xx);
+      *xx = x;
+    }
+
+    if (!yy)
+      MP_DROP(y);
+    else {
+      if (*yy) MP_DROP(*yy);
+      *yy = y;
+    }
+  }
+
+  MP_DROP(v);
+  MP_DROP(X); MP_DROP(Y);
+}
+
+/* -- @gf_modinv@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *x@ = argument
+ *             @mp *p@ = modulus
+ *
+ * Returns:    The inverse %$x^{-1} \bmod p$%.
+ *
+ * Use:                Computes a modular inverse, the catch being that the
+ *             arguments and results are binary polynomials.  An assertion
+ *             fails if %$p$% has no inverse.
+ */
+
+mp *gf_modinv(mp *d, mp *x, mp *p)
+{
+  mp *g = MP_NEW;
+  gf_gcd(&g, 0, &d, p, x);
+  assert(MP_EQ(g, MP_ONE));
+  mp_drop(g);
+  return (d);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int gcd(dstr *v)
+{
+  int ok = 1;
+  mp *a = *(mp **)v[0].buf;
+  mp *b = *(mp **)v[1].buf;
+  mp *g = *(mp **)v[2].buf;
+  mp *x = *(mp **)v[3].buf;
+  mp *y = *(mp **)v[4].buf;
+
+  mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW;
+  gf_gcd(&gg, &xx, &yy, a, b);
+  if (!MP_EQ(x, xx)) {
+    fputs("\n*** gf_gcd(x) failed", stderr);
+    fputs("\na     = ", stderr); mp_writefile(a, stderr, 16);
+    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 16);
+    fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 16);
+    fputs("\nresult = ", stderr); mp_writefile(xx, stderr, 16);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+  if (!MP_EQ(y, yy)) {
+    fputs("\n*** gf_gcd(y) failed", stderr);
+    fputs("\na     = ", stderr); mp_writefile(a, stderr, 16);
+    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 16);
+    fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 16);
+    fputs("\nresult = ", stderr); mp_writefile(yy, stderr, 16);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  if (!ok) {
+    mp *ax = gf_mul(MP_NEW, a, xx);
+    mp *by = gf_mul(MP_NEW, b, yy);
+    ax = gf_add(ax, ax, by);
+    if (MP_EQ(ax, gg))
+      fputs("\n*** (Alternative result found.)\n", stderr);
+    MP_DROP(ax);
+    MP_DROP(by);
+  }
+
+  if (!MP_EQ(g, gg)) {
+    fputs("\n*** gf_gcd(gcd) failed", stderr);
+    fputs("\na     = ", stderr); mp_writefile(a, stderr, 16);
+    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 16);
+    fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 16);
+    fputs("\nresult = ", stderr); mp_writefile(gg, stderr, 16);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+  MP_DROP(a); MP_DROP(b); MP_DROP(g); MP_DROP(x); MP_DROP(y);
+  MP_DROP(gg); MP_DROP(xx); MP_DROP(yy);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "gcd", gcd, { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/gf");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gf.h b/math/gf.h
new file mode 100644 (file)
index 0000000..edc91fa
--- /dev/null
+++ b/math/gf.h
@@ -0,0 +1,149 @@
+/* -*-c-*-
+ *
+ * Arithmetic on binary polynomials
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_GF_H
+#define CATACOMB_GF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_GFX_H
+#  include "gfx.h"
+#endif
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @gf_add@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @a@ added to @b@.
+ */
+
+extern mp *gf_add(mp */*d*/, mp */*a*/, mp */*b*/);
+#define gf_sub gf_add
+
+/* --- @gf_mul@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @a@ multiplied by @b@.
+ */
+
+extern mp *gf_mul(mp */*d*/, mp */*a*/, mp */*b*/);
+
+/* --- @gf_sqr@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *
+ * Returns:    Result, @a@ squared.
+ */
+
+extern mp *gf_sqr(mp */*d*/, mp */*a*/);
+
+/* --- @gf_div@ --- *
+ *
+ * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
+ *             @mp *a, *b@ = sources
+ *
+ * Use:                Calculates the quotient and remainder when @a@ is divided by
+ *             @b@.  The destinations @*qq@ and @*rr@ must be distinct.
+ *             Either of @qq@ or @rr@ may be null to indicate that the
+ *             result is irrelevant.  (Discarding both results is silly.)
+ *             There is a performance advantage if @a == *rr@.
+ */
+
+extern void gf_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/);
+
+/* --- @gf_exp@ --- *
+ *
+ * Arguments:  @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e$%.
+ */
+
+extern mp *gf_exp(mp */*d*/, mp */*a*/, mp */*e*/);
+
+/* --- @gf_irreduciblep@ --- *
+ *
+ * Arguments:  @mp *f@ = a polynomial
+ *
+ * Returns:    Nonzero if the polynomial is irreducible; otherwise zero.
+ */
+
+extern int gf_irreduciblep(mp */*f*/);
+
+/* --- @gf_gcd@ --- *
+ *
+ * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
+ *             @mp *a, *b@ = sources (must be nonzero)
+ *
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
+ *             @ax + by = gcd(a, b)@.  This is useful for computing modular
+ *             inverses.
+ */
+
+extern void gf_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/,
+                  mp */*a*/, mp */*b*/);
+
+/* -- @gf_modinv@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *x@ = argument
+ *             @mp *p@ = modulus
+ *
+ * Returns:    The inverse %$x^{-1} \bmod p$%.
+ *
+ * Use:                Computes a modular inverse, the catch being that the
+ *             arguments and results are binary polynomials.  An assertion
+ *             fails if %$p$% has no inverse.
+ */
+
+extern mp *gf_modinv(mp */*d*/, mp */*x*/, mp */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/gfn.c b/math/gfn.c
new file mode 100644 (file)
index 0000000..c9b90c0
--- /dev/null
@@ -0,0 +1,272 @@
+/* -*-c-*-
+ *
+ * Normal-basis translation for binary fields
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "gfreduce.h"
+#include "gfn.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gfn_copy@ --- *
+ *
+ * Arguments:  @gfn *d@ = where to put the copy
+ *             @const gfn *s@ = where the source is
+ *
+ * Returns:    ---
+ *
+ * Use:                Makes a copy of a translation matrix.
+ */
+
+void gfn_copy(gfn *d, const gfn *s)
+{
+  size_t i;
+
+  d->n = s->n;
+  d->r = xmalloc(s->n * sizeof(mp *));
+  for (i = 0; i < s->n; i++)
+    d->r[i] = MP_COPY(s->r[i]);
+}
+
+/* --- @gfn_destroy@ --- *
+ *
+ * Arguments:  @gfn *m@ = a transformation matrix to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees up a transformation matrix when it's no longer wanted.
+ */
+
+void gfn_destroy(gfn *m)
+  { size_t i; for (i = 0; i < m->n; i++) MP_DROP(m->r[i]); xfree(m->r); }
+
+/* --- @gfn_identity@ --- *
+ *
+ * Arguments:  @gfn *m@ = where to put the matrix
+ *             @size_t n@ = size of the matrix
+ *
+ * Returns:    ---
+ *
+ * Use:                Fills @m@ with an identity matrix.
+ */
+
+void gfn_identity(gfn *m, size_t n)
+{
+  size_t i;
+
+  m->n = n;
+  m->r = xmalloc(n * sizeof(mp *));
+  m->r[0] = MP_ONE;
+  for (i = 1; i < n; i++)
+    m->r[i] = mp_lsl(MP_NEW, m->r[i - 1], 1);
+}
+
+/* --- @gfn_invert@ --- *
+ *
+ * Arguments:  @gfn *m@ = a transformation matrix
+ *
+ * Returns:    Zero if successful, nonzero if the matrix was singular.
+ *
+ * Use:                Inverts a transformation matrix.
+ */
+
+int gfn_invert(gfn *m)
+{
+  size_t i, j;
+  gfn mm;
+  mp *t;
+  int rc = -1;
+
+  mm = *m;
+  gfn_identity(m, mm.n);
+  for (i = 0; i < mm.n; i++) {
+    if (!mp_testbit(mm.r[i], i)) {
+      for (j = i + 1; j < mm.n; j++) {
+       if (mp_testbit(mm.r[j], i))
+         goto found_set;
+      }
+      goto fail;
+    found_set:
+      t = mm.r[i]; mm.r[i] = mm.r[j]; mm.r[j] = t;
+      t = m->r[i]; m->r[i] = m->r[j]; m->r[j] = t;
+    }
+    for (j = 0; j < mm.n; j++) {
+      if (j == i) continue;
+      if (mp_testbit(mm.r[j], i)) {
+       mm.r[j] = mp_xor(mm.r[j], mm.r[j], mm.r[i]);
+       m->r[j] = mp_xor(m->r[j], m->r[j], m->r[i]);
+      }
+    }
+  }
+  rc = 0;
+fail:
+  gfn_destroy(&mm);
+  return (rc);
+}
+
+/* --- @gfn_transform@ --- *
+ *
+ * Arguments:  @gfn *m@ = conversion matrix to apply
+ *             @mp *d@ = destination pointer
+ *             @mp *x@ = input value
+ *
+ * Returns:    The transformed element.
+ *
+ * Use:                Transforms a field element according to the given matrix.
+ */
+
+mp *gfn_transform(gfn *m, mp *d, mp *x)
+{
+  mp *y = MP_ZERO;
+  size_t i;
+  mpscan sc;
+
+  for (i = 0, mp_scan(&sc, x); i < m->n && mp_step(&sc); i++)
+    if (mp_bit(&sc)) y = mp_xor(y, y, m->r[i]);
+  mp_drop(d);
+  return (y);
+}
+
+/* --- @gfn_create@ --- *
+ *
+ * Arguments:  @mp *p@ = modulus for polynomial basis
+ *             @mp *beta@ = the generator of the normal basis, expressed
+ *                     relative to the polynomial basis
+ *             @gfn *ntop@ = output normal-to-polynomail conversion matrix
+ *             @gfn *pton@ = output polynomial-to-normal conversion matrix
+ *
+ * Returns:    Zero if it worked, nonzero otherwise (e.g., if %$\beta$%
+ *             doesn't generate a proper basis).
+ *
+ * Use:                Constructs conversion matrices between polynomial and normal
+ *             basis representations of binary field elements.
+ */
+
+int gfn_create(mp *p, mp *beta, gfn *ntop, gfn *pton)
+{
+  size_t m = mp_bits(p) - 1;
+  size_t i;
+  gfreduce gr;
+  gfn *np, tmp;
+
+  /* --- We start by building the the @ntop@ matrix --- *
+   *
+   * For mad reasons, the string representation of normal-basis elements is
+   * backwards.
+   */
+
+  gfreduce_create(&gr, p);
+  np = ntop ? ntop : &tmp;
+  np->n = m;
+  np->r = xmalloc(m * sizeof(mp *));
+  np->r[m - 1] = MP_COPY(beta);
+  for (i = m - 1; i--; ) {
+    mp *x = gf_sqr(MP_NEW, np->r[i + 1]);
+    np->r[i] = gfreduce_do(&gr, x, x);
+  }
+  gfreduce_destroy(&gr);
+
+  /* --- That was easy -- now invert it --- */
+
+  if (pton) {
+    if (ntop) gfn_copy(pton, np); else *pton = *np;
+    if (gfn_invert(pton)) {
+      gfn_destroy(pton);
+      if (ntop) gfn_destroy(ntop);
+      return (-1);
+    }
+  }
+
+  /* --- And we're done --- */
+
+  return (0);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int check(dstr *v)
+{
+  mp *p = *(mp **)v[0].buf;
+  mp *beta = *(mp **)v[1].buf;
+  mp *xp = *(mp **)v[2].buf;
+  mp *xn = *(mp **)v[3].buf;
+  mp *y = MP_NEW;
+  gfn pton, ntop, ii;
+  size_t i;
+  int ok = 1;
+
+  gfn_create(p, beta, &ntop, &pton);
+  gfn_identity(&ii, pton.n);
+  for (i = 0; i < pton.n; i++) {
+    y = gfn_transform(&ntop, y, pton.r[i]);
+    if (!MP_EQ(y, ii.r[i])) {
+      ok = 0;
+      fprintf(stderr, "*** inverse pton->ntop check failed (row %lu)\n",
+             (unsigned long)i);
+      MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta);
+      MP_EPRINTX("*** computed", y);
+    }
+  }
+  gfn_destroy(&ii);
+  y = gfn_transform(&pton, y, xp);
+  if (!MP_EQ(y, xn)) {
+    ok = 0;
+    fprintf(stderr, "*** pton failed\n");
+    MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta);
+    MP_EPRINTX("*** xp", xp); MP_EPRINTX("*** xn", xn);
+    MP_EPRINTX("*** computed", y);
+  }
+  y = gfn_transform(&ntop, y, xn);
+  if (!MP_EQ(y, xp)) {
+    ok = 0;
+    fprintf(stderr, "*** ntop failed\n");
+    MP_EPRINTX("*** p", p); MP_EPRINTX("*** beta", beta);
+    MP_EPRINTX("*** xp", xp); MP_EPRINTX("*** xn", xn);
+    MP_EPRINTX("*** computed", y);
+  }
+  gfn_destroy(&pton); gfn_destroy(&ntop);
+  mp_drop(p); mp_drop(beta); mp_drop(xp); mp_drop(xn); mp_drop(y);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "gfn", check, { &type_mp, &type_mp, &type_mp, &type_mp } },
+  { 0 }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, tests, SRCDIR "/t/gfn");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gfn.h b/math/gfn.h
new file mode 100644 (file)
index 0000000..11ecb44
--- /dev/null
@@ -0,0 +1,130 @@
+/* -*-c-*-
+ *
+ * Normal-basis translation for binary fields
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_GFN_H
+#define CATACOMB_GFN_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "gf.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct gfn {
+  size_t n;                            /* Number of rows */
+  mp **r;                              /* Array of the rows */
+} gfn;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @gfn_copy@ --- *
+ *
+ * Arguments:  @gfn *d@ = where to put the copy
+ *             @const gfn *s@ = where the source is
+ *
+ * Returns:    ---
+ *
+ * Use:                Makes a copy of a translation matrix.
+ */
+
+extern void gfn_copy(gfn */*d*/, const gfn */*s*/);
+
+/* --- @gfn_destroy@ --- *
+ *
+ * Arguments:  @gfn *m@ = a transformation matrix to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees up a transformation matrix when it's no longer wanted.
+ */
+
+extern void gfn_destroy(gfn */*m*/);
+
+/* --- @gfn_identity@ --- *
+ *
+ * Arguments:  @gfn *m@ = where to put the matrix
+ *             @size_t n@ = size of the matrix
+ *
+ * Returns:    ---
+ *
+ * Use:                Fills @m@ with an identity matrix.
+ */
+
+extern void gfn_identity(gfn */*m*/, size_t /*n*/);
+
+/* --- @gfn_invert@ --- *
+ *
+ * Arguments:  @gfn *m@ = a transformation matrix
+ *
+ * Returns:    Zero if successful, nonzero if the matrix was singular.
+ *
+ * Use:                Inverts a transformation matrix.
+ */
+
+extern int gfn_invert(gfn */*m*/);
+
+/* --- @gfn_transform@ --- *
+ *
+ * Arguments:  @gfn *m@ = conversion matrix to apply
+ *             @mp *d@ = destination pointer
+ *             @mp *x@ = input value
+ *
+ * Returns:    The transformed element.
+ *
+ * Use:                Transforms a field element according to the given matrix.
+ */
+
+extern mp *gfn_transform(gfn */*m*/, mp */*d*/, mp */*x*/);
+
+/* --- @gfn_create@ --- *
+ *
+ * Arguments:  @mp *p@ = modulus for polynomial basis
+ *             @mp *beta@ = the generator of the normal basis, expressed
+ *                     relative to the polynomial basis
+ *             @gfn *ntop@ = output normal-to-polynomail conversion matrix
+ *             @gfn *pton@ = output polynomial-to-normal conversion matrix
+ *
+ * Returns:    Zero if it worked, nonzero otherwise (e.g., if %$\beta$%
+ *             doesn't generate a proper basis).
+ *
+ * Use:                Constructs conversion matrices between polynomial and normal
+ *             basis representations of binary field elements.
+ */
+
+extern int gfn_create(mp */*p*/, mp */*beta*/, gfn */*ntop*/, gfn */*pton*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/gfreduce-exp.h b/math/gfreduce-exp.h
new file mode 100644 (file)
index 0000000..93af649
--- /dev/null
@@ -0,0 +1,74 @@
+/* -*-c-*-
+ *
+ * Exponentiation operations for binary field reduction
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_GFREDUCE_EXP_H
+#define CATACOMB_GFREDUCE_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentiation definitions ----------------------------------------*/
+
+#define EXP_TYPE mp *
+
+#define EXP_COPY(d, x) d = MP_COPY(x)
+#define EXP_DROP(x) MP_DROP(x)
+
+#define EXP_MUL(a, x) do {                                             \
+  mp *t = gf_mul(spare, a, x);                                         \
+  spare = a;                                                           \
+  a = gfreduce_do(gr, t, t);                                           \
+} while (0)
+
+#define EXP_SQR(a) do {                                                        \
+  mp *t = gf_sqr(spare, a);                                            \
+  spare = a;                                                           \
+  a = gfreduce_do(gr, t, t);                                           \
+} while (0)
+
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) do {                                       \
+  d = gf_mul(MP_NEW, x, y);                                            \
+  d = gfreduce_do(gr, d, d);                                           \
+} while (0)
+
+#define EXP_SETSQR(d, x) do {                                          \
+  d = gf_sqr(MP_NEW, x);                                               \
+  d = gfreduce_do(gr, d, d);                                           \
+} while (0)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/gfreduce.c b/math/gfreduce.c
new file mode 100644 (file)
index 0000000..164122d
--- /dev/null
@@ -0,0 +1,650 @@
+/* -*-c-*-
+ *
+ * Efficient reduction modulo sparse binary polynomials
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/alloc.h>
+#include <mLib/darray.h>
+#include <mLib/macros.h>
+
+#include "gf.h"
+#include "gfreduce.h"
+#include "gfreduce-exp.h"
+#include "fibrand.h"
+#include "mprand.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+DA_DECL(instr_v, gfreduce_instr);
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- What's going on here? --- *
+ *
+ * Let's face it, @gfx_div@ sucks.  It works (I hope), but it's not in any
+ * sense fast.  Here, we do efficient reduction modulo sparse polynomials.
+ *
+ * Suppose we have a polynomial @X@ we're trying to reduce mod @P@.  If we
+ * take the topmost nonzero word of @X@, call it @w@, then we can eliminate
+ * it by subtracting off @w P x^{k}@ for an appropriate value of @k@.  The
+ * trick is in observing that if @P@ is sparse we can do this multiplication
+ * and subtraction efficiently, just by XORing appropriate shifts of @w@ into
+ * @X@.
+ *
+ * The first tricky bit is in working out when to stop.  I'll use eight-bit
+ * words to demonstrate what I'm talking about.
+ *
+ *  xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
+ *                 001ppppp pppppppp pppppppp pppppppp
+ *                   |<rp>|
+ *                   |<------------ bp ------------->|
+ *                 |<------------ nw --------------->|
+ *
+ * The trick of taking whole words off of @X@ stops working when there are
+ * only @nw@ words left.  Then we have to mask off the bottom bits of @w@
+ * before continuing.
+ */
+
+/* --- @gfreduce_create@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = structure to fill in
+ *             @mp *x@ = a (hopefully sparse) polynomial
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context structure for reduction.
+ */
+
+void gfreduce_create(gfreduce *r, mp *p)
+{
+  instr_v iv = DA_INIT;
+  unsigned long d;
+  unsigned dw;
+  mpscan sc;
+  unsigned long i;
+  gfreduce_instr *ip;
+  unsigned f = 0;
+  size_t w, ww, wi, wl, ll, bb;
+
+  /* --- Sort out the easy stuff --- */
+
+  d = mp_bits(p); assert(d); d--;
+  r->lim = d/MPW_BITS;
+  dw = d%MPW_BITS;
+  if (!dw)
+    r->mask = 0;
+  else {
+    r->mask = MPW(((mpw)-1) << dw);
+    r->lim++;
+  }
+  r->p = mp_copy(p);
+
+  /* --- Stash a new instruction --- */
+
+#define INSTR(op_, arg_) do {                                          \
+  DA_ENSURE(&iv, 1);                                                   \
+  DA(&iv)[DA_LEN(&iv)].op = (op_);                                     \
+  DA(&iv)[DA_LEN(&iv)].arg = (arg_);                                   \
+  DA_EXTEND(&iv, 1);                                                   \
+} while (0)
+
+#define f_lsr 1u
+
+  w = (d + MPW_BITS - 1)/MPW_BITS;
+  INSTR(GFRI_LOAD, w);
+  wi = DA_LEN(&iv);
+  f = 0;
+  ll = 0;
+  bb = MPW_BITS - dw;
+  for (i = 0, mp_scan(&sc, p); mp_step(&sc) && i < d; i++) {
+    if (!mp_bit(&sc))
+      continue;
+    ww = (d - i + MPW_BITS - 1)/MPW_BITS;
+    if (ww != w) {
+      wl = DA_LEN(&iv);
+      INSTR(GFRI_STORE, w);
+      if (!ll)
+       ll = DA_LEN(&iv);
+      if (!(f & f_lsr))
+       INSTR(GFRI_LOAD, ww);
+      else {
+       INSTR(GFRI_LOAD, w - 1);
+       for (; wi < wl; wi++) {
+         ip = &DA(&iv)[wi];
+         assert(ip->op == GFRI_LSL);
+         if (ip->arg)
+           INSTR(GFRI_LSR, MPW_BITS - ip->arg);
+       }
+       if (w - 1 != ww) {
+         INSTR(GFRI_STORE, w - 1);
+         INSTR(GFRI_LOAD, ww);
+       }
+       f &= ~f_lsr;
+      }
+      w = ww;
+      wi = DA_LEN(&iv);
+    }
+    INSTR(GFRI_LSL, (bb + i)%MPW_BITS);
+    if ((bb + i)%MPW_BITS)
+      f |= f_lsr;
+  }
+  wl = DA_LEN(&iv);
+  INSTR(GFRI_STORE, w);
+  if (!ll)
+    ll = DA_LEN(&iv);
+  if (f & f_lsr) {
+    INSTR(GFRI_LOAD, w - 1);
+    for (; wi < wl; wi++) {
+      ip = &DA(&iv)[wi];
+      assert(ip->op == GFRI_LSL);
+      if (ip->arg)
+       INSTR(GFRI_LSR, MPW_BITS - ip->arg);
+    }
+    INSTR(GFRI_STORE, w - 1);
+  }
+
+#undef INSTR
+
+  r->in = DA_LEN(&iv);
+  r->iv = xmalloc(r->in * sizeof(gfreduce_instr));
+  r->liv = r->iv + ll;
+  memcpy(r->iv, DA(&iv), r->in * sizeof(gfreduce_instr));
+  DA_DESTROY(&iv);
+}
+
+/* --- @gfreduce_destroy@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = structure to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Reclaims the resources from a reduction context.
+ */
+
+void gfreduce_destroy(gfreduce *r)
+{
+  mp_drop(r->p);
+  xfree(r->iv);
+}
+
+/* --- @gfreduce_dump@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = structure to dump
+ *             @FILE *fp@ = file to dump on
+ *
+ * Returns:    ---
+ *
+ * Use:                Dumps a reduction context.
+ */
+
+void gfreduce_dump(gfreduce *r, FILE *fp)
+{
+  size_t i;
+
+  fprintf(fp, "poly = "); mp_writefile(r->p, fp, 16);
+  fprintf(fp, "\n  lim = %lu; mask = %lx\n",
+         (unsigned long)r->lim, (unsigned long)r->mask);
+  for (i = 0; i < r->in; i++) {
+    static const char *opname[] = { "load", "lsl", "lsr", "store" };
+    assert(r->iv[i].op < N(opname));
+    fprintf(fp, "  %s %lu\n",
+           opname[r->iv[i].op],
+           (unsigned long)r->iv[i].arg);
+  }
+}
+
+/* --- @gfreduce_do@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = source
+ *
+ * Returns:    Destination, @x@ reduced modulo the reduction poly.
+ */
+
+static void run(const gfreduce_instr *i, const gfreduce_instr *il,
+               mpw *v, mpw z)
+{
+  mpw w = 0;
+
+  for (; i < il; i++) {
+    switch (i->op) {
+      case GFRI_LOAD: w = *(v - i->arg); break;
+      case GFRI_LSL: w ^= z << i->arg; break;
+      case GFRI_LSR: w ^= z >> i->arg; break;
+      case GFRI_STORE: *(v - i->arg) = MPW(w); break;
+      default: abort();
+    }
+  }
+}
+
+mp *gfreduce_do(gfreduce *r, mp *d, mp *x)
+{
+  mpw *v, *vl;
+  const gfreduce_instr *il;
+  mpw z;
+
+  /* --- Try to reuse the source's space --- */
+
+  MP_COPY(x);
+  if (d) MP_DROP(d);
+  MP_DEST(x, MP_LEN(x), x->f);
+
+  /* --- Do the reduction --- */
+
+  il = r->iv + r->in;
+  if (MP_LEN(x) >= r->lim) {
+    v = x->v + r->lim;
+    vl = x->vl;
+    while (vl-- > v) {
+      while (*vl) {
+       z = *vl;
+       *vl = 0;
+       run(r->iv, il, vl, z);
+      }
+    }
+    if (r->mask) {
+      while (*vl & r->mask) {
+       z = *vl & r->mask;
+       *vl &= ~r->mask;
+       run(r->iv, il, vl, z);
+      }
+    }
+  }
+
+  /* --- Done --- */
+
+  MP_SHRINK(x);
+  return (x);
+}
+
+/* --- @gfreduce_sqrt@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = pointer to reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = some polynomial
+ *
+ * Returns:    The square root of @x@ modulo @r->p@, or null.
+ */
+
+mp *gfreduce_sqrt(gfreduce *r, mp *d, mp *x)
+{
+  mp *y = MP_COPY(x);
+  mp *z, *spare = MP_NEW;
+  unsigned long m = mp_bits(r->p) - 1;
+  unsigned long i;
+
+  for (i = 0; i < m - 1; i++) {
+    mp *t = gf_sqr(spare, y);
+    spare = y;
+    y = gfreduce_do(r, t, t);
+  }
+  z = gf_sqr(spare, y);
+  z = gfreduce_do(r, z, z);
+  if (!MP_EQ(x, z)) {
+    mp_drop(y);
+    y = 0;
+  }
+  mp_drop(z);
+  mp_drop(d);
+  return (y);
+}
+
+/* --- @gfreduce_trace@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = pointer to reduction context
+ *             @mp *x@ = some polynomial
+ *
+ * Returns:    The trace of @x@. (%$\Tr(x)=x + x^2 + \cdots + x^{2^{m-1}}$%
+ *             if %$x \in \gf{2^m}$%).
+ */
+
+int gfreduce_trace(gfreduce *r, mp *x)
+{
+  mp *y = MP_COPY(x);
+  mp *spare = MP_NEW;
+  unsigned long m = mp_bits(r->p) - 1;
+  unsigned long i;
+  int rc;
+
+  for (i = 0; i < m - 1; i++) {
+    mp *t = gf_sqr(spare, y);
+    spare = y;
+    y = gfreduce_do(r, t, t);
+    y = gf_add(y, y, x);
+  }
+  rc = !MP_ZEROP(y);
+  mp_drop(spare);
+  mp_drop(y);
+  return (rc);
+}
+
+/* --- @gfreduce_halftrace@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = pointer to reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = some polynomial
+ *
+ * Returns:    The half-trace of @x@.
+ *             (%$\HfTr(x)= x + x^{2^2} + \cdots + x^{2^{m-1}}$%
+ *             if %$x \in \gf{2^m}$% with %$m$% odd).
+ */
+
+mp *gfreduce_halftrace(gfreduce *r, mp *d, mp *x)
+{
+  mp *y = MP_COPY(x);
+  mp *spare = MP_NEW;
+  unsigned long m = mp_bits(r->p) - 1;
+  unsigned long i;
+
+  mp_drop(d);
+  for (i = 0; i < m - 1; i += 2) {
+    mp *t = gf_sqr(spare, y);
+    spare = y;
+    y = gfreduce_do(r, t, t);
+    t = gf_sqr(spare, y);
+    spare = y;
+    y = gfreduce_do(r, t, t);
+    y = gf_add(y, y, x);
+  }
+  mp_drop(spare);
+  return (y);
+}
+
+/* --- @gfreduce_quadsolve@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = pointer to reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = some polynomial
+ *
+ * Returns:    A polynomial @y@ such that %$y^2 + y = x$%, or null.
+ */
+
+mp *gfreduce_quadsolve(gfreduce *r, mp *d, mp *x)
+{
+  unsigned long m = mp_bits(r->p) - 1;
+  mp *t;
+
+  MP_COPY(x);
+  if (m & 1)
+    d = gfreduce_halftrace(r, d, x);
+  else {
+    mp *z, *w, *rho = MP_NEW;
+    mp *spare = MP_NEW;
+    grand *fr = fibrand_create(0);
+    unsigned long i;
+
+    for (;;) {
+      rho = mprand(rho, m, fr, 0);
+      z = MP_ZERO;
+      w = MP_COPY(rho);
+      for (i = 0; i < m - 1; i++) {
+       t = gf_sqr(spare, z); spare = z; z = gfreduce_do(r, t, t);
+       t = gf_sqr(spare, w); spare = w; w = gfreduce_do(r, t, t);
+       t = gf_mul(spare, w, x); t = gfreduce_do(r, t, t); spare = t;
+       z = gf_add(z, z, t);
+       w = gf_add(w, w, rho);
+      }
+      if (!MP_ZEROP(w))
+       break;
+      MP_DROP(z);
+      MP_DROP(w);
+    }
+    if (d) MP_DROP(d);
+    MP_DROP(w);
+    MP_DROP(spare);
+    MP_DROP(rho);
+    fr->ops->destroy(fr);
+    d = z;
+  }
+
+  t = gf_sqr(MP_NEW, d); t = gfreduce_do(r, t, t); t = gf_add(t, t, d);
+  if (!MP_EQ(t, x)) {
+    MP_DROP(d);
+    d = 0;
+  }
+  MP_DROP(t);
+  MP_DROP(x);
+  if (d) d->v[0] &= ~(mpw)1;
+  return (d);
+}
+
+/* --- @gfreduce_exp@ --- *
+ *
+ * Arguments:  @gfreduce *gr@ = pointer to reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e \bmod m$%.
+ */
+
+mp *gfreduce_exp(gfreduce *gr, mp *d, mp *a, mp *e)
+{
+  mp *x = MP_ONE;
+  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
+
+  MP_SHRINK(e);
+  MP_COPY(a);
+  if (MP_ZEROP(e))
+    ;
+  else {
+    if (MP_NEGP(e))
+      a = gf_modinv(a, a, gr->p);
+    if (MP_LEN(e) < EXP_THRESH)
+      EXP_SIMPLE(x, a, e);
+    else
+      EXP_WINDOW(x, a, e);
+  }
+  mp_drop(d);
+  mp_drop(a);
+  mp_drop(spare);
+  return (x);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
+
+static int vreduce(dstr *v)
+{
+  mp *d = *(mp **)v[0].buf;
+  mp *n = *(mp **)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *c;
+  int ok = 1;
+  gfreduce rr;
+
+  gfreduce_create(&rr, d);
+  c = gfreduce_do(&rr, MP_NEW, n);
+  if (!MP_EQ(c, r)) {
+    fprintf(stderr, "\n*** reduction failed\n*** ");
+    gfreduce_dump(&rr, stderr);
+    fprintf(stderr, "\n*** n = "); mp_writefile(n, stderr, 16);
+    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
+    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  gfreduce_destroy(&rr);
+  mp_drop(n); mp_drop(d); mp_drop(r); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vmodexp(dstr *v)
+{
+  mp *p = *(mp **)v[0].buf;
+  mp *g = *(mp **)v[1].buf;
+  mp *x = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *c;
+  int ok = 1;
+  gfreduce rr;
+
+  gfreduce_create(&rr, p);
+  c = gfreduce_exp(&rr, MP_NEW, g, x);
+  if (!MP_EQ(c, r)) {
+    fprintf(stderr, "\n*** modexp failed\n*** ");
+    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
+    fprintf(stderr, "\n*** g = "); mp_writefile(g, stderr, 16);
+    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
+    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
+    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  gfreduce_destroy(&rr);
+  mp_drop(p); mp_drop(g); mp_drop(r); mp_drop(x); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vsqrt(dstr *v)
+{
+  mp *p = *(mp **)v[0].buf;
+  mp *x = *(mp **)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *c;
+  int ok = 1;
+  gfreduce rr;
+
+  gfreduce_create(&rr, p);
+  c = gfreduce_sqrt(&rr, MP_NEW, x);
+  if (!MP_EQ(c, r)) {
+    fprintf(stderr, "\n*** sqrt failed\n*** ");
+    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
+    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
+    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
+    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  gfreduce_destroy(&rr);
+  mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vtr(dstr *v)
+{
+  mp *p = *(mp **)v[0].buf;
+  mp *x = *(mp **)v[1].buf;
+  int r = *(int *)v[2].buf, c;
+  int ok = 1;
+  gfreduce rr;
+
+  gfreduce_create(&rr, p);
+  c = gfreduce_trace(&rr, x);
+  if (c != r) {
+    fprintf(stderr, "\n*** trace failed\n*** ");
+    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
+    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
+    fprintf(stderr, "\n*** c = %d", c);
+    fprintf(stderr, "\n*** r = %d", r);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  gfreduce_destroy(&rr);
+  mp_drop(p); mp_drop(x);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vhftr(dstr *v)
+{
+  mp *p = *(mp **)v[0].buf;
+  mp *x = *(mp **)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *c;
+  int ok = 1;
+  gfreduce rr;
+
+  gfreduce_create(&rr, p);
+  c = gfreduce_halftrace(&rr, MP_NEW, x);
+  if (!MP_EQ(c, r)) {
+    fprintf(stderr, "\n*** halftrace failed\n*** ");
+    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
+    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
+    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
+    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  gfreduce_destroy(&rr);
+  mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vquad(dstr *v)
+{
+  mp *p = *(mp **)v[0].buf;
+  mp *x = *(mp **)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *c;
+  int ok = 1;
+  gfreduce rr;
+
+  gfreduce_create(&rr, p);
+  c = gfreduce_quadsolve(&rr, MP_NEW, x);
+  if (!MP_EQ(c, r)) {
+    fprintf(stderr, "\n*** quadsolve failed\n*** ");
+    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 16);
+    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 16);
+    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 16);
+    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 16);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  gfreduce_destroy(&rr);
+  mp_drop(p); mp_drop(r); mp_drop(x); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "reduce", vreduce, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "modexp", vmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { "sqrt", vsqrt, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "trace", vtr, { &type_mp, &type_mp, &type_int, 0 } },
+  { "halftrace", vhftr, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "quadsolve", vquad, { &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/gfreduce");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gfreduce.h b/math/gfreduce.h
new file mode 100644 (file)
index 0000000..2c8a884
--- /dev/null
@@ -0,0 +1,176 @@
+/* -*-c-*-
+ *
+ * Reduction modulo sparse binary polynomials
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_GFREDUCE_H
+#define CATACOMB_GFREDUCE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GF_H
+#  include "gf.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct gfreduce_instr {
+  unsigned op;                         /* Instruction opcode */
+  size_t arg;                          /* Immediate argument */
+} gfreduce_instr;
+
+enum {
+  GFRI_LOAD,                           /* Load @p[arg]@ */
+  GFRI_LSL,                            /* XOR with @w << arg@ */
+  GFRI_LSR,                            /* XOR with @w >> arg@ */
+  GFRI_STORE,                          /* Store @p[arg]@ */
+  GFRI_MAX
+};
+
+typedef struct gfreduce {
+  size_t lim;                          /* Word of degree bit */
+  mpw mask;                            /* Mask for degree word */
+  mp *p;                               /* Copy of the polynomial */
+  size_t in;                           /* Number of instruction words */
+  gfreduce_instr *iv, *liv;            /* Vector of instructions */
+} gfreduce;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @gfreduce_create@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = structure to fill in
+ *             @mp *x@ = a (hopefully sparse) polynomial
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context structure for reduction.
+ */
+
+extern void gfreduce_create(gfreduce */*r*/, mp */*p*/);
+
+/* --- @gfreduce_destroy@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = structure to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Reclaims the resources from a reduction context.
+ */
+
+extern void gfreduce_destroy(gfreduce */*r*/);
+
+/* --- @gfreduce_dump@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = structure to dump
+ *             @FILE *fp@ = file to dump on
+ *
+ * Returns:    ---
+ *
+ * Use:                Dumps a reduction context.
+ */
+
+extern void gfreduce_dump(gfreduce */*r*/, FILE */*fp*/);
+
+/* --- @gfreduce_do@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = source
+ *
+ * Returns:    Destination, @x@ reduced modulo the reduction poly.
+ */
+
+extern mp *gfreduce_do(gfreduce */*r*/, mp */*d*/, mp */*x*/);
+
+/* --- @gfreduce_sqrt@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = pointer to reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = some polynomial
+ *
+ * Returns:    The square root of @x@ modulo @r->p@, or null.
+ */
+
+extern mp *gfreduce_sqrt(gfreduce */*r*/, mp */*d*/, mp */*x*/);
+
+/* --- @gfreduce_trace@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = pointer to reduction context
+ *             @mp *x@ = some polynomial
+ *
+ * Returns:    The trace of @x@. (%$\Tr(x)=x + x^2 + \cdots + x^{2^{m-1}}$%
+ *             if %$x \in \gf{2^m}$%).
+ */
+
+extern int gfreduce_trace(gfreduce */*r*/, mp */*x*/);
+
+/* --- @gfreduce_halftrace@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = pointer to reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = some polynomial
+ *
+ * Returns:    The half-trace of @x@.
+ *             (%$\HfTr(x)= x + x^{2^2} + \cdots + x^{2^{m-1}}$%
+ *             if %$x \in \gf{2^m}$% with %$m$% odd).
+ */
+
+extern mp *gfreduce_halftrace(gfreduce */*r*/, mp */*d*/, mp */*x*/);
+
+/* --- @gfreduce_quadsolve@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = pointer to reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = some polynomial
+ *
+ * Returns:    A polynomial @y@ such that %$y^2 + y = x$%, or null.
+ */
+
+extern mp *gfreduce_quadsolve(gfreduce */*r*/, mp */*d*/, mp */*x*/);
+
+/* --- @gfreduce_exp@ --- *
+ *
+ * Arguments:  @gfreduce *gr@ = pointer to reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e \bmod m$%.
+ */
+
+extern mp *gfreduce_exp(gfreduce */*gr*/, mp */*d*/, mp */*a*/, mp */*e*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/gfx-kmul.c b/math/gfx-kmul.c
new file mode 100644 (file)
index 0000000..5a5838a
--- /dev/null
@@ -0,0 +1,247 @@
+/* -*-c-*-
+ *
+ * Karatsuba's multiplication algorithm on binary polynomials
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "gfx.h"
+#include "karatsuba.h"
+
+/*----- Tweakables --------------------------------------------------------*/
+
+#ifdef TEST_RIG
+#  undef GFK_THRESH
+#  define GFK_THRESH 1
+#endif
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gfx_kmul@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
+ *             @const mpw *av, *avl@ = pointer to first argument
+ *             @const mpw *bv, *bvl@ = pointer to second argument
+ *             @mpw *sv, *svl@ = pointer to scratch workspace
+ *
+ * Returns:    ---
+ *
+ * Use:                Multiplies two binary polynomials using Karatsuba's
+ *             algorithm.  This is rather faster than traditional long
+ *             multiplication (e.g., @gfx_umul@) on polynomials with large
+ *             degree, although more expensive on small ones.
+ *
+ *             The destination must be twice as large as the larger
+ *             argument.  The scratch space must be twice as large as the
+ *             larger argument.
+ */
+
+void gfx_kmul(mpw *dv, mpw *dvl,
+             const mpw *av, const mpw *avl,
+             const mpw *bv, const mpw *bvl,
+             mpw *sv, mpw *svl)
+{
+  const mpw *avm, *bvm;
+  size_t m;
+
+  /* --- Dispose of easy cases to @mpx_umul@ --- *
+   *
+   * Karatsuba is only a win on large numbers, because of all the
+   * recursiveness and bookkeeping.  The recursive calls make a quick check
+   * to see whether to bottom out to @gfx_umul@ which should help quite a
+   * lot, but sometimes the only way to know is to make sure...
+   */
+
+  MPX_SHRINK(av, avl);
+  MPX_SHRINK(bv, bvl);
+
+  if (avl - av <= GFK_THRESH || bvl - bv <= GFK_THRESH) {
+    gfx_mul(dv, dvl, av, avl, bv, bvl);
+    return;
+  }
+
+  /* --- How the algorithm works --- *
+   *
+   * Let %$A = xb + y$% and %$B = ub + v$%.  Then, simply by expanding,
+   * %$AB = x u b^2 + b(x v + y u) + y v$%.  That's not helped any, because
+   * I've got four multiplications, each four times easier than the one I
+   * started with.  However, note that I can rewrite the coefficient of %$b$%
+   * as %$xv + yu = (x + y)(u + v) - xu - yv$%.  The terms %$xu$% and %$yv$%
+   * I've already calculated, and that leaves only one more multiplication to
+   * do.  So now I have three multiplications, each four times easier, and
+   * that's a win.
+   */
+
+  /* --- First things --- *
+   *
+   * Sort out where to break the factors in half.  I'll choose the midpoint
+   * of the larger one, since this minimizes the amount of work I have to do
+   * most effectively.
+   */
+
+  if (avl - av > bvl - bv) {
+    m = (avl - av + 1) >> 1;
+    avm = av + m;
+    if (bvl - bv > m)
+      bvm = bv + m;
+    else
+      bvm = bvl;
+  } else {
+    m = (bvl - bv + 1) >> 1;
+    bvm = bv + m;
+    if (avl - av > m)
+      avm = av + m;
+    else
+      avm = avl;
+  }
+
+  /* --- Sort out the middle term --- */
+
+  {
+    mpw *bsv = sv + m, *ssv = bsv + m;
+    mpw *rdv = dv + m, *rdvl = rdv + 2 * m;
+
+    assert(rdvl <= dvl);
+    assert(ssv <= svl);
+    UXOR2(sv, bsv, av, avm, avm, avl);
+    UXOR2(bsv, ssv, bv, bvm, bvm, bvl);
+    if (m > GFK_THRESH)
+      gfx_kmul(rdv, rdvl, sv, bsv, bsv, ssv, ssv, svl);
+    else
+      gfx_mul(rdv, rdvl, sv, bsv, bsv, ssv);
+  }
+
+  /* --- Sort out the other two terms --- */
+
+  {
+    mpw *svm = sv + m, *ssv = svm + m;
+    mpw *tdv = dv + m;
+    mpw *rdv = tdv + m;
+
+    if (avl == avm || bvl == bvm)
+      MPX_ZERO(rdv + m, dvl);
+    else {
+      if (m > GFK_THRESH)
+       gfx_kmul(sv, ssv, avm, avl, bvm, bvl, ssv, svl);
+      else
+       gfx_mul(sv, ssv, avm, avl, bvm, bvl);
+      MPX_COPY(rdv + m, dvl, svm, ssv);
+      UXOR(rdv, sv, svm);
+      UXOR(tdv, sv, ssv);
+    }
+
+    if (m > GFK_THRESH)
+      gfx_kmul(sv, ssv, av, avm, bv, bvm, ssv, svl);
+    else
+      gfx_mul(sv, ssv, av, avm, bv, bvm);
+    MPX_COPY(dv, tdv, sv, svm);
+    UXOR(tdv, sv, ssv);
+    UXOR(tdv, svm, ssv);
+  }
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/alloc.h>
+#include <mLib/testrig.h>
+
+#define ALLOC(v, vl, sz) do {                                          \
+  size_t _sz = (sz);                                                   \
+  mpw *_vv = xmalloc(MPWS(_sz));                                       \
+  mpw *_vvl = _vv + _sz;                                               \
+  (v) = _vv;                                                           \
+  (vl) = _vvl;                                                         \
+} while (0)
+
+#define LOAD(v, vl, d) do {                                            \
+  const dstr *_d = (d);                                                        \
+  mpw *_v, *_vl;                                                       \
+  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
+  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
+  (v) = _v;                                                            \
+  (vl) = _vl;                                                          \
+} while (0)
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
+{
+  fputs(msg, stderr);
+  MPX_SHRINK(v, vl);
+  while (v < vl)
+    fprintf(stderr, " %08lx", (unsigned long)*--vl);
+  fputc('\n', stderr);
+}
+
+static int mul(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  mpw *s, *sl;
+  size_t m;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(b, bl, &v[1]);
+  LOAD(c, cl, &v[2]);
+  m = MAX(al - a, bl - b) + 1;
+  ALLOC(d, dl, 2 * m);
+  ALLOC(s, sl, 2 * m);
+
+  gfx_kmul(d, dl, a, al, b, bl, s, sl);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** mul failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("      b", b, bl);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(c); xfree(d); xfree(s);
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "mul", mul, { &type_hex, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/gfx");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gfx-sqr-mktab.c b/math/gfx-sqr-mktab.c
new file mode 100644 (file)
index 0000000..1ecd995
--- /dev/null
@@ -0,0 +1,89 @@
+/* -*-c-*-
+ *
+ * Build table for squaring of binary polynomials
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Main code ---------------------------------------------------------*/
+
+static void mktab(uint16 *t)
+{
+  unsigned i, j, x;
+
+  for (i = 0; i < 256; i++) {
+    x = 0;
+    for (j = 0; j < 8; j++) {
+      if (i & (1 << j))
+       x |= 1 << (2 * j);
+    }
+    t[i] = x;
+  }
+}
+
+int main(void)
+{
+  uint16 t[256];
+  unsigned i;
+
+  mktab(t);
+fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * Bit spacing table for binary polynomial squaring\n\
+ */\n\
+\n\
+#ifndef GFX_SQR_TAB_H\n\
+#define GFX_SQR_TAB_H\n\
+\n\
+#define GFX_SQRTAB {                                                   \\\n\
+  ", stdout);
+
+  for (i = 0; i < 256; i++) {
+    printf("0x%04x", t[i]);
+    if (i == 255)
+      puts("   \\\n}\n");
+    else if (i % 8 == 7)
+      fputs(", \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  fputs("#endif\n", stdout);
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gfx-sqr.c b/math/gfx-sqr.c
new file mode 100644 (file)
index 0000000..8e26f36
--- /dev/null
@@ -0,0 +1,212 @@
+/* -*-c-*-
+ *
+ * Sqaring binary polynomials
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mpx.h"
+#include "gfx.h"
+#include "gfx-sqr-tab.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static const uint16 tab[256] = GFX_SQRTAB;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gfx_sqr@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = argument vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs squaring of binary polynomials.
+ */
+
+void gfx_sqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl)
+{
+  mpd a = 0, aa = 0;
+  unsigned b = 0, bb = 0;
+
+  /* --- Simple stuff --- */
+
+  if (dv >= dvl)
+    return;
+  MPX_SHRINK(av, avl);
+
+  /* --- The main algorithm --- *
+   *
+   * Our method depends on the fact that, in a field of characteristic 2, we
+   * have that %$(a + b)^2 = a^2 + b^2$%.  Thus, to square a polynomial, it's
+   * sufficient just to put a zero bit between each of the bits of the
+   * original argument.  We use a precomputed table for this, and work on
+   * entire octets at a time.  Life is more complicated because we've got to
+   * be careful of bizarre architectures which don't have words with a
+   * multiple of 8 bits in them.
+   */
+
+  for (;;) {
+
+    /* --- Input buffering --- */
+
+    if (b < 8) {
+      if (av >= avl)
+       break;
+      a |= *av++ << b;
+      b += MPW_BITS;
+    }
+
+    /* --- Do the work in the middle --- */
+
+    aa |= (mpd)(tab[U8(a)]) << bb;
+    bb += 16;
+    a >>= 8;
+    b -= 8;
+
+    /* --- Output buffering --- */
+
+    if (bb >= MPW_BITS) {
+      *dv++ = MPW(aa);
+      if (dv >= dvl)
+       return;
+      aa >>= MPW_BITS;
+      bb -= MPW_BITS;
+    }
+  }
+
+  /* --- Flush the input buffer --- */
+
+  if (b) for (;;) {
+    aa |= (mpd)(tab[U8(a)]) << bb;
+    bb += 16;
+    if (bb > MPW_BITS) {
+      *dv++ = MPW(aa);
+      if (dv >= dvl)
+       return;
+      aa >>= MPW_BITS;
+      bb -= MPW_BITS;
+    }
+    a >>= 8;
+    if (b <= 8)
+      break;
+    else
+      b -= 8;
+  }
+
+  /* --- Flush the output buffer --- */
+
+  if (bb) for (;;) {
+    *dv++ = MPW(aa);
+    if (dv >= dvl)
+      return;
+    aa >>= MPW_BITS;
+    if (bb <= MPW_BITS)
+      break;
+    else
+      bb -= MPW_BITS;
+  }
+
+  /* --- Zero the rest of everything --- */
+
+  MPX_ZERO(dv, dvl);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define ALLOC(v, vl, sz) do {                                          \
+  size_t _sz = (sz);                                                   \
+  mpw *_vv = xmalloc(MPWS(_sz));                                       \
+  mpw *_vvl = _vv + _sz;                                               \
+  (v) = _vv;                                                           \
+  (vl) = _vvl;                                                         \
+} while (0)
+
+#define LOAD(v, vl, d) do {                                            \
+  const dstr *_d = (d);                                                        \
+  mpw *_v, *_vl;                                                       \
+  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
+  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
+  (v) = _v;                                                            \
+  (vl) = _vl;                                                          \
+} while (0)
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
+{
+  fputs(msg, stderr);
+  MPX_SHRINK(v, vl);
+  while (v < vl)
+    fprintf(stderr, " %08lx", (unsigned long)*--vl);
+  fputc('\n', stderr);
+}
+
+static int vsqr(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(b, bl, &v[1]);
+  ALLOC(d, dl, 2 * (al - a));
+
+  gfx_sqr(d, dl, a, al);
+  if (!mpx_ueq(d, dl, b, bl)) {
+    fprintf(stderr, "\n*** vsqr failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("expected", b, bl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(d);
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "sqr", vsqr, { &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/gfx");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gfx.c b/math/gfx.c
new file mode 100644 (file)
index 0000000..56bea48
--- /dev/null
@@ -0,0 +1,387 @@
+/* -*-c-*-
+ *
+ * Low-level arithmetic on binary polynomials
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+
+#include "mpx.h"
+#include "mpscan.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gfx_add@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = first addend vector base and limit
+ *             @const mpw *bv, *bvl@ = second addend vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds two %$\gf{2}$% polynomials.  This is the same as
+ *             subtraction.
+ */
+
+void gfx_add(mpw *dv, mpw *dvl,
+            const mpw *av, const mpw *avl,
+            const mpw *bv, const mpw *bvl)
+{
+  MPX_SHRINK(av, avl);
+  MPX_SHRINK(bv, bvl);
+
+  while (av < avl || bv < bvl) {
+    mpw a, b;
+    if (dv >= dvl)
+      return;
+    a = (av < avl) ? *av++ : 0;
+    b = (bv < bvl) ? *bv++ : 0;
+    *dv++ = a ^ b;
+  }
+  if (dv < dvl)
+    MPX_ZERO(dv, dvl);
+}
+
+/* --- @gfx_acc@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = addend vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds the addend into the destination.  This is considerably
+ *             faster than the three-address add call.
+ */
+
+void gfx_acc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl)
+{
+  size_t dlen, alen;
+
+  MPX_SHRINK(av, avl);
+  dlen = dvl - dv;
+  alen = avl - av;
+  if (dlen < alen)
+    avl = av + dlen;
+  while (av < avl)
+    *dv++ ^= *av++;
+}
+
+/* --- @gfx_accshift@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = addend vector base and limit
+ *             @size_t n@ = number of bits to shift
+ *
+ * Returns:    ---
+ *
+ * Use:                Shifts the argument left by %$n$% places and adds it to the
+ *             destination.  This is a primitive used by multiplication and
+ *             division.
+ */
+
+void gfx_accshift(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
+{
+  size_t c = n / MPW_BITS;
+  mpw x = 0, y;
+  size_t dlen, alen;
+
+  /* --- Sort out the shift amounts --- */
+
+  if (dvl - dv < c)
+    return;
+  dv += c;
+  n %= MPW_BITS;
+  if (!n) {
+    gfx_acc(dv, dvl, av, avl);
+    return;
+  }
+  c = MPW_BITS - n;
+
+  /* --- Sort out vector lengths --- */
+
+  MPX_SHRINK(av, avl);
+  dlen = dvl - dv;
+  alen = avl - av;
+  if (dlen < alen)
+    avl = av + dlen;
+
+  /* --- Now do the hard work --- */
+
+  while (av < avl) {
+    y = *av++;
+    *dv++ ^= MPW((y << n) | (x >> c));
+    x = y;
+  }
+  if (dv < dvl)
+    *dv++ ^= x >> c;
+}
+
+/* --- @gfx_mul@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = first argument vector base and limit
+ *             @const mpw *bv, *bvl@ = second argument vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Does multiplication of polynomials over %$\gf{2}$%.
+ */
+
+void gfx_mul(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,
+            const mpw *bv, const mpw *bvl)
+{
+  mpscan sc;
+  const mpw *v;
+  mpw *vv;
+  mpw z;
+  mpd x, y;
+
+  MPX_SHRINK(av, avl);
+  MPX_SHRINK(bv, bvl);
+  MPSCAN_INITX(&sc, av, avl);
+  MPX_ZERO(dv, dvl);
+
+  while (bv < bvl && dv < dvl) {
+    x = 0;
+    for (v = av, vv = dv++; v < avl && vv < dvl; v++) {
+      z = *bv; y = *v;
+      while (z) {
+       if (z & 1u) x ^= y;
+       z >>= 1; y <<= 1;
+      }
+      *vv++ ^= MPW(x);
+      x >>= MPW_BITS;
+    }
+    if (vv < dvl)
+      *vv++ = MPW(x);
+    bv++;
+  }
+}
+
+/* --- @gfx_div@ --- *
+ *
+ * Arguments:  @mpw *qv, *qvl@ = quotient vector base and limit
+ *             @mpw *rv, *rvl@ = dividend/remainder vector base and limit
+ *             @const mpw *dv, *dvl@ = divisor vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs division on polynomials over %$\gf{2}$%.
+ */
+
+void gfx_div(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl,
+            const mpw *dv, const mpw *dvl)
+{
+  size_t dlen, rlen, qlen;
+  size_t dbits;
+  mpw *rvv, *rvd;
+  unsigned rvm, n, qi;
+  mpw q;
+
+  MPX_SHRINK(rv, rvl);
+  MPX_SHRINK(dv, dvl);
+  assert(((void)"division by zero in gfx_div", dv < dvl));
+  MPX_BITS(dbits, dv, dvl);
+  dlen = dvl - dv;
+  rlen = rvl - rv;
+  qlen = qvl - qv;
+
+  MPX_ZERO(qv, qvl);
+  if (dlen > rlen)
+    return;
+  rvd = rvl - dlen;
+  rvv = rvl - 1;
+  rvm = 1 << (MPW_BITS - 1);
+  n = MPW_BITS - (dbits % MPW_BITS);
+  if (n == MPW_BITS)
+    n = 0;
+  q = 0;
+  qi = rvd - rv;
+
+  for (;;) {
+    q <<= 1;
+    if (*rvv & rvm) {
+      q |= 1;
+      gfx_accshift(rvd, rvl, dv, dvl, n);
+    }
+    rvm >>= 1;
+    if (!rvm) {
+      rvm = 1 << (MPW_BITS - 1);
+      rvv--;
+    }
+    if (n)
+      n--;
+    else {
+      if (qi < qlen)
+       qv[qi] = q;
+      q = 0;
+      qi--;
+      if (rvd == rv)
+       break;
+      n = MPW_BITS - 1;
+      rvd--;
+    }
+  }
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define ALLOC(v, vl, sz) do {                                          \
+  size_t _sz = (sz);                                                   \
+  mpw *_vv = xmalloc(MPWS(_sz));                                       \
+  mpw *_vvl = _vv + _sz;                                               \
+  (v) = _vv;                                                           \
+  (vl) = _vvl;                                                         \
+} while (0)
+
+#define LOAD(v, vl, d) do {                                            \
+  const dstr *_d = (d);                                                        \
+  mpw *_v, *_vl;                                                       \
+  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
+  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
+  (v) = _v;                                                            \
+  (vl) = _vl;                                                          \
+} while (0)
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
+{
+  fputs(msg, stderr);
+  MPX_SHRINK(v, vl);
+  while (v < vl)
+    fprintf(stderr, " %08lx", (unsigned long)*--vl);
+  fputc('\n', stderr);
+}
+
+static int vadd(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(b, bl, &v[1]);
+  LOAD(c, cl, &v[2]);
+  ALLOC(d, dl, MAX(al - a, bl - b) + 1);
+
+  gfx_add(d, dl, a, al, b, bl);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** vadd failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("      b", b, bl);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int vmul(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(b, bl, &v[1]);
+  LOAD(c, cl, &v[2]);
+  ALLOC(d, dl, (al - a) + (bl - b));
+
+  gfx_mul(d, dl, a, al, b, bl);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** vmul failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("      b", b, bl);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int vdiv(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *q, *ql;
+  mpw *r, *rl;
+  mpw *qq, *qql;
+  int ok = 1;
+
+  ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len);
+  LOAD(b, bl, &v[1]);
+  LOAD(q, ql, &v[2]);
+  LOAD(r, rl, &v[3]);
+  ALLOC(qq, qql, al - a);
+
+  gfx_div(qq, qql, a, al, b, bl);
+  if (!mpx_ueq(qq, qql, q, ql) ||
+      !mpx_ueq(a, al, r, rl)) {
+    fprintf(stderr, "\n*** vdiv failed\n");
+    dumpmp(" divisor", b, bl);
+    dumpmp("expect r", r, rl);
+    dumpmp("result r", a, al);
+    dumpmp("expect q", q, ql);
+    dumpmp("result q", qq, qql);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(r); xfree(q); xfree(qq);
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "add", vadd, { &type_hex, &type_hex, &type_hex, 0 } },
+  { "mul", vmul, { &type_hex, &type_hex, &type_hex, 0 } },
+  { "div", vdiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/gfx");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/gfx.h b/math/gfx.h
new file mode 100644 (file)
index 0000000..214ec2b
--- /dev/null
@@ -0,0 +1,173 @@
+/* -*-c-*-
+ *
+ * Low-level arithmetic on binary polynomials
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_GFX_H
+#define CATACOMB_GFX_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MPX_H
+#  include "mpx.h"
+#endif
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @gfx_add@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = first addend vector base and limit
+ *             @const mpw *bv, *bvl@ = second addend vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds two %$\gf{2}$% polynomials.  This is the same as
+ *             subtraction.
+ */
+
+extern void gfx_add(mpw */*dv*/, mpw */*dvl*/,
+                   const mpw */*av*/, const mpw */*avl*/,
+                   const mpw */*bv*/, const mpw */*bvl*/);
+
+/* --- @gfx_acc@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = addend vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds the addend into the destination.  This is considerably
+ *             faster than the three-address add call.
+ */
+
+extern void gfx_acc(mpw */*dv*/, mpw */*dvl*/,
+                   const mpw */*av*/, const mpw */*avl*/);
+
+/* --- @gfx_accshift@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = addend vector base and limit
+ *             @size_t n@ = number of bits to shift
+ *
+ * Returns:    ---
+ *
+ * Use:                Shifts the argument left by %$n$% places and adds it to the
+ *             destination.  This is a primitive used by multiplication and
+ *             division.
+ */
+
+extern void gfx_accshift(mpw */*dv*/, mpw */*dvl*/,
+                        const mpw */*av*/, const mpw */*avl*/,
+                        size_t /*n*/);
+
+/* --- @gfx_mul@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = first argument vector base and limit
+ *             @const mpw *bv, *bvl@ = second argument vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Does multiplication of polynomials over %$\gf{2}$%.
+ */
+
+extern void gfx_mul(mpw */*dv*/, mpw */*dvl*/,
+                   const mpw */*av*/, const mpw */*avl*/,
+                   const mpw */*bv*/, const mpw */*bvl*/);
+
+/* --- @gfx_sqr@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = argument vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs squaring of binary polynomials.
+ */
+
+extern void gfx_sqr(mpw */*dv*/, mpw */*dvl*/,
+                   const mpw */*av*/, const mpw */*avl*/);
+
+/* --- @gfx_div@ --- *
+ *
+ * Arguments:  @mpw *qv, *qvl@ = quotient vector base and limit
+ *             @mpw *rv, *rvl@ = dividend/remainder vector base and limit
+ *             @const mpw *dv, *dvl@ = divisor vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs division on polynomials over %$\gf{2}$%.
+ */
+
+extern void gfx_div(mpw */*qv*/, mpw */*qvl*/, mpw */*rv*/, mpw */*rvl*/,
+                   const mpw */*dv*/, const mpw */*dvl*/);
+
+/*----- Karatsuba multiplication algorithms -------------------------------*/
+
+/* --- @GFK_THRESH@ --- *
+ *
+ * This is the limiting length for using Karatsuba algorithms.  It's best to
+ * use the simpler classical multiplication method on numbers smaller than
+ * this.
+ */
+
+#define GFK_THRESH 2
+
+/* --- @gfx_kmul@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
+ *             @const mpw *av, *avl@ = pointer to first argument
+ *             @const mpw *bv, *bvl@ = pointer to second argument
+ *             @mpw *sv, *svl@ = pointer to scratch workspace
+ *
+ * Returns:    ---
+ *
+ * Use:                Multiplies two binary polynomials using Karatsuba's
+ *             algorithm.  This is rather faster than traditional long
+ *             multiplication (e.g., @gfx_umul@) on polynomials with large
+ *             degree, although more expensive on small ones.
+ *
+ *             The destination must be twice as large as the larger
+ *             argument.  The scratch space must be twice as large as the
+ *             larger argument.
+ */
+
+extern void gfx_kmul(mpw */*dv*/, mpw */*dvl*/,
+                    const mpw */*av*/, const mpw */*avl*/,
+                    const mpw */*bv*/, const mpw */*bvl*/,
+                    mpw */*sv*/, mpw */*svl*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/group-dstr.c b/math/group-dstr.c
new file mode 100644 (file)
index 0000000..4714183
--- /dev/null
@@ -0,0 +1,83 @@
+/* -*-c-*-
+ *
+ * Dynamic string I/O for group elements
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "group.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @group_readdstr@ --- *
+ *
+ * Arguments:  @group *g@ = an abstract group
+ *             @ge *d@ = destination group element
+ *             @dstr *dd@ = string to read from
+ *             @size_t *off@ = offset to start at (updated)
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Parses a group element from a dynamic string.
+ */
+
+int group_readdstr(group *g, ge *d, dstr *dd, size_t *off)
+{
+  mptext_dstrctx md;
+
+  md.d = dd;
+  md.i = off ? *off : 0;
+  if (G_READ(g, d, &mptext_dstrops, &md))
+    return (-1);
+  if (off) *off = md.i;
+  return (0);
+}
+
+/* --- @group_writedstr@ --- *
+ *
+ * Arguments:  @group *g@ = an abstract group
+ *             @ge *x@ = a group element
+ *             @dstr *d@ = string to write to
+ *             @size_t sz@ = how long the buffer is
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Writes a group element to a dstr buffer.
+ */
+
+int group_writedstr(group *g, ge *x, dstr *d)
+{
+  mptext_dstrctx md;
+
+  md.d = d;
+  if (G_WRITE(g, x, &mptext_dstrops, &md))
+    return (-1);
+  DPUTZ(d);
+  return (0);
+}
+
+
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/group-exp.c b/math/group-exp.c
new file mode 100644 (file)
index 0000000..083da9e
--- /dev/null
@@ -0,0 +1,107 @@
+/* -*-c-*-
+ *
+ * Exponentiation for abstract groups
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "group.h"
+#include "group-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @group_stdexp@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @ge *x@ = base element
+ *             @mp *n@ = exponent
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = x^n$% efficiently.
+ */
+
+void group_stdexp(group *gg, ge *d, ge *x, mp *n)
+{
+  ge *t = G_CREATE(gg);
+
+  G_COPY(gg, t, x);
+  MP_SHRINK(n);
+  G_COPY(gg, d, gg->i);
+  if (n->f & MP_BURN)
+    G_BURN(gg, t);
+  if (MP_ZEROP(n))
+    ;
+  else {
+    if (MP_NEGP(n))
+      G_INV(gg, t, t);
+    if (MP_LEN(n) < EXP_THRESH)
+      EXP_SIMPLE(d, t, n);
+    else
+      EXP_WINDOW(d, t, n);
+  }
+  G_DESTROY(gg, t);
+}
+
+/* --- @group_stdmexp@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @const group_expfactor *f@ = vector of factors
+ *             @size_t n@ = number of factors
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently.
+ */
+
+#undef EXP_WINSZ
+#define EXP_WINSZ 3
+
+void group_stdmexp(group *gg, ge *d, const group_expfactor *f, size_t n)
+{
+  group_expfactor *ff = xmalloc(n * sizeof(group_expfactor));
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    ff[i].base = G_CREATE(gg);
+    MP_SHRINK(f[i].exp);
+    if (MP_NEGP(f[i].exp))
+      G_INV(gg, ff[i].base, f[i].base);
+    else
+      G_COPY(gg, ff[i].base, f[i].base);
+    if (f[i].exp->f & MP_BURN)
+      G_BURN(gg, ff[i].base);
+    ff[i].exp = f[i].exp;
+  }
+  G_COPY(gg, d, gg->i);
+  EXP_SIMUL(d, ff, n);
+  for (i = 0; i < n; i++)
+    G_DESTROY(gg, ff[i].base);
+  xfree(ff);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/group-exp.h b/math/group-exp.h
new file mode 100644 (file)
index 0000000..0bc029c
--- /dev/null
@@ -0,0 +1,66 @@
+/* -*-c-*-
+ *
+ * Exponentiation operations for abstract groups
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_GROUP_EXP_H
+#define CATACOMB_GROUP_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentation definitions -----------------------------------------*/
+
+#define EXP_TYPE ge *
+
+#define EXP_COPY(d, p) do {                                            \
+  (d) = G_CREATE(gg);                                                  \
+  G_COPY(gg, (d), (p));                                                        \
+} while (0)
+#define EXP_DROP(x) G_DESTROY(gg, (x))
+
+#define EXP_MUL(a, x) G_MUL(gg, (a), (a), (x))
+#define EXP_SQR(a) G_SQR(gg, (a), (a));
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) do {                                       \
+  (d) = G_CREATE(gg);                                                  \
+  G_MUL(gg, (d), (x), (y));                                            \
+} while (0)
+#define EXP_SETSQR(d, x) do {                                          \
+  (d) = G_CREATE(gg);                                                  \
+  G_SQR(gg, (d), (x));                                                 \
+} while (0)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/group-file.c b/math/group-file.c
new file mode 100644 (file)
index 0000000..bb95df1
--- /dev/null
@@ -0,0 +1,62 @@
+/* -*-c-*-
+ *
+ * File I/O for group elements
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "group.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @group_readfile@ --- *
+ *
+ * Arguments:  @group *g@ = an abstract group
+ *             @ge *d@ = destination group element
+ *             @FILE *fp@ = the file to read from
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Parses a group element from a file.
+ */
+
+int group_readfile(group *g, ge *d, FILE *fp)
+  { return (G_READ(g, d, &mptext_fileops, fp)); }
+
+/* --- @group_writefile@ --- *
+ *
+ * Arguments:  @group *g@ = an abstract group
+ *             @ge *x@ = a group element
+ *             @FILE *fp@ = the file to write on
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Writes a group element to a file.
+ */
+
+int group_writefile(group *g, ge *x, FILE *fp)
+  { return (G_WRITE(g, x, &mptext_fileops, fp)); }
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/group-guts.h b/math/group-guts.h
new file mode 100644 (file)
index 0000000..c34d89c
--- /dev/null
@@ -0,0 +1,84 @@
+/* -*-c-*-
+ *
+ * Internal structures for built-in groups
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_GROUP_GUTS_H
+#define CATACOMB_GROUP_GUTS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_EC_H
+#  include "ec.h"
+#endif
+
+#ifndef CATACOMB_MPMONT_H
+#  include "mpmont.h"
+#endif
+
+#ifndef CATACOMB_GFREDUCE_H
+#  include "gfreduce.h"
+#endif
+
+#ifndef CATACOMB_GROUP_H
+#  include "group.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct gctx_prime {
+  group g;
+  mp *gen;
+  mpmont mm;
+} gctx_prime;
+
+typedef struct gctx_ec {
+  group g;
+  ec id, gen;
+  ec_info ei;
+} gctx_ec;
+
+typedef struct gctx_bin {
+  group g;
+  mp *gen;
+  mp *one;
+  gfreduce r;
+} gctx_bin;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/group-parse.c b/math/group-parse.c
new file mode 100644 (file)
index 0000000..b46898d
--- /dev/null
@@ -0,0 +1,95 @@
+/* -*-c-*-
+ *
+ * Parse group description strings
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Trivial IP Encryption (TrIPE).
+ *
+ * TrIPE is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * TrIPE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with TrIPE; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "group.h"
+#include "dh.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @group_parse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = quick-and-dirty parser
+ *
+ * Returns:    Group pointer, or null for failure.
+ *
+ * Use:                Parses a group description and returns the group.  This has
+ *             the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and
+ *             SPEC is the appropriate kind of group specification of the
+ *             given type.
+ */
+
+group *group_parse(qd_parse *qd)
+{
+  group *g = 0;
+
+  switch (qd_enum(qd, "prime,ec")) {
+    case 0: {
+      dh_param dp;
+      qd_delim(qd, '{');
+      if (dh_parse(qd, &dp)) goto ouch;
+      qd_delim(qd, '}');
+      g = group_prime(&dp);
+      dh_paramfree(&dp);
+    } break;
+    case 1: {
+      ec_info ei;
+      qd_delim(qd, '{');
+      if (ec_infoparse(qd, &ei)) goto ouch;
+      qd_delim(qd, '}');
+      g = group_ec(&ei);
+    } break;
+  }
+  if (!g) qd->e = "bad group parameters";
+ouch:
+  return (g);
+}
+
+/* --- @group_fromstring@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to string to read
+ *             @group **gg@ = where to put the group pointer
+ *
+ * Returns:    Null if OK, or an error string.
+ *
+ * Use:                Parses a group spec from a string, and returns the group.
+ */
+
+const char *group_fromstring(const char *p, group **gg)
+{
+  group *g;
+  qd_parse qd;
+
+  qd.p = p;
+  qd.e = 0;
+  if ((g = group_parse(&qd)) == 0) return (qd.e);
+  if (!qd_eofp(&qd)) { G_DESTROYGROUP(g); return ("junk at end of string"); }
+  *gg = g;
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/group-stdops.c b/math/group-stdops.c
new file mode 100644 (file)
index 0000000..b0f8753
--- /dev/null
@@ -0,0 +1,166 @@
+/* -*-c-*-
+ *
+ * Standard group operations
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "group.h"
+#include "pgen.h"
+
+/*----- Handy functions ---------------------------------------------------*/
+
+/* --- @group_check@ --- *
+ *
+ * Arguments:  @group *g@ = an abstract group
+ *             @ge *x@ = a group element
+ *
+ * Returns:    Zero on success, nonzero for failure.
+ *
+ * Use:                Checks that @x@ is a valid group element.  This may take a
+ *             while, since it checks that %$x \ne 1$% and %$x^r = 1$%.
+ */
+
+int group_check(group *g, ge *x)
+{
+  ge *d = G_CREATE(g);
+  int rc;
+
+  G_EXP(g, d, x, g->r);
+  rc = (G_IDENTP(g, d) && !G_IDENTP(g, x));
+  G_DESTROY(g, d);
+  if (!rc) return (-1);
+  return (0);
+}
+
+/* --- @group_samep@ --- *
+ *
+ * Arguments:  @group *g, *h@ = two abstract groups
+ *
+ * Returns:    Nonzero if the groups are in fact identical (not just
+ *             isomorphic).
+ *
+ * Use:                Checks to see whether two groups are actually the same.  This
+ *             function does the full check: the group operatrion @samep@
+ *             just does the group-specific details.
+ */
+
+int group_samep(group *g, group *h)
+{
+  return (g == h || (g->ops == h->ops &&
+                    MP_EQ(g->r, h->r) && MP_EQ(g->h, h->h) &&
+                    G_EQ(g, g->i, h->i) && G_EQ(g, g->g, h->g) &&
+                    G_SAMEP(g, h)));
+}
+
+/*----- Standard implementations ------------------------------------------*/
+
+/* --- @group_stdidentp@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *x@ = group element
+ *
+ * Returns:    Nonzero if %$x$% is the group identity.
+ */
+
+int group_stdidentp(group *g, ge *x) { return (G_EQ(g, x, g->i)); }
+
+/* --- @group_stdsqr@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @ge *x@ = group element
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = x^2$% as %$d = x x$%.
+ */
+
+void group_stdsqr(group *g, ge *d, ge *x) { G_MUL(g, d, x, x); }
+
+/* --- @group_stddiv@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @ge *x@ = dividend
+ *             @ge *y@ = divisor
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = x/y$% as %$d = x y^{-1}$%.
+ */
+
+void group_stddiv(group *g, ge *d, ge *x, ge *y)
+  { G_INV(g, d, y); G_MUL(g, d, x, d); }
+
+/* --- @group_stdtoec@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ec *d@ = destination point
+ *             @ge *x@ = group element
+ *
+ * Returns:    @-1@, indicating failure.
+ *
+ * Use:                Fails to convert a group element to an elliptic curve point.
+ */
+
+int group_stdtoec(group *g, ec *d, ge *x) { return (-1); }
+
+/* --- @group_stdfromec@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @const ec *p@ = elliptic curve point
+ *
+ * Returns:    Zero for success, @-1@ on failure.
+ *
+ * Use:                Converts %$p$% to a group element by converting its %$x$%-
+ *             coordinate.
+ */
+
+int group_stdfromec(group *g, ge *d, const ec *p)
+  { if (EC_ATINF(p)) return (-1); return (G_FROMINT(g, d, p->x)); }
+
+/* --- @group_stdcheck@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @grand *gr@ = random number source.
+ *
+ * Returns:    Null on success, or a pointer to an error message.
+ */
+
+const char *group_stdcheck(group *g, grand *gr)
+{
+  ge *t;
+  int rc;
+
+  if (!pgen_primep(g->r, gr)) return ("group order not prime");
+  t = G_CREATE(g); G_EXP(g, t, g->g, g->r);
+  rc = G_IDENTP(g, t); G_DESTROY(g, t);
+  if (!rc) return ("generator not in the group");
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/group-string.c b/math/group-string.c
new file mode 100644 (file)
index 0000000..09db3ea
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*-c-*-
+ *
+ * String I/O for group elements
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "group.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @group_readstring@ --- *
+ *
+ * Arguments:  @group *g@ = an abstract group
+ *             @ge *d@ = destination group element
+ *             @const char *p@ = where the string is
+ *             @char **end@ = where to put the end pointer
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Parses a group element from a string.
+ */
+
+int group_readstring(group *g, ge *d, const char *p, char **end)
+{
+  mptext_stringctx ms;
+
+  ms.buf = (/*unconst*/ char *)p;
+  ms.lim = (/*unconst*/ char *)p + strlen(p);
+  if (G_READ(g, d, &mptext_stringops, &ms))
+    return (-1);
+  if (end) *end = ms.buf;
+  return (0);
+}
+
+/* --- @group_writestring@ --- *
+ *
+ * Arguments:  @group *g@ = an abstract group
+ *             @ge *x@ = a group element
+ *             @char *p@ = where the string should go
+ *             @size_t sz@ = how long the buffer is
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Writes a group element to a string buffer.
+ */
+
+int group_writestring(group *g, ge *x, char *p, size_t sz)
+{
+  mptext_stringctx ms;
+
+  ms.buf = p;
+  ms.lim = p + sz - 1;
+  if (G_WRITE(g, x, &mptext_stringops, &ms))
+    return (-1);
+  *ms.buf = 0;
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/group-test.c b/math/group-test.c
new file mode 100644 (file)
index 0000000..7cd0cd2
--- /dev/null
@@ -0,0 +1,561 @@
+/* -*-c-*-
+ *
+ * Testing group operations
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+
+#include <mLib/testrig.h>
+
+#include "group.h"
+#include "fibrand.h"
+#include "ec.h"
+#include "ec-test.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+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 show(group *g, const char *p, ge *x) {
+  fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr);
+  putc('\n', stderr);
+}
+
+static void showec(const char *p, ec *q) {
+  fprintf(stderr, "*** %s = ", p);
+  if (EC_ATINF(q)) fprintf(stderr, "inf\n");
+  else {
+    mp_writefile(q->x, stderr, 16); fputs(", ", stderr);
+    mp_writefile(q->x, stderr, 16); putchar('\n');
+  }
+}
+
+static void showmp(const char *p, mp *x, int r) {
+  fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r);
+  putc('\n', stderr);
+}
+
+static int check(const char *op, const char *gd, group *g,
+                ge *r, ge *c, ...) {
+  va_list ap;
+
+  if (G_EQ(g, r, c)) return (1);
+  fprintf(stderr, "\n*** %s failed\n", op);
+  fprintf(stderr, "*** group: %s\n", gd);
+  va_start(ap, c);
+  for (;;) {
+    const char *p; ge *x;
+    p = va_arg(ap, const char *); if (!p) break;
+    x = va_arg(ap, ge *); show(g, p, x);
+  }
+  show(g, "expected", r);
+  show(g, "computed", c);
+  return (0);
+}
+
+/*----- Actual tests ------------------------------------------------------*/
+
+static int vcheck(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  grand *gr = fibrand_create(0);
+  const char *e = G_CHECK(g, gr);
+  int ok = 1;
+  gr->ops->destroy(gr);
+  if (!e) e = "ok";
+  G_DESTROYGROUP(g);
+  if (strcmp(e, v[1].buf)) {
+    ok = 0;
+    fprintf(stderr, "*** check failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    fprintf(stderr, "*** expected: %s\n", v[1].buf);
+    fprintf(stderr, "*** returned: %s\n", e);
+  }
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vcheckelt(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  int ir = *(int *)v[2].buf;
+  int ic = group_check(g, x);
+  int ok = 1;
+  if (ir != ic) {
+    ok = 0;
+    fprintf(stderr, "*** check failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    show(g, "x", x);
+    fprintf(stderr, "*** expected %s\n", ir ? "failure" : "success");
+  }
+  G_DESTROY(g, x);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vmul(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  ge *y = getge(g, v[2].buf);
+  ge *r = getge(g, v[3].buf);
+  ge *c = G_CREATE(g);
+  int ok = 1;
+  G_MUL(g, c, x, y);
+  ok &= check("mul", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
+  G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vsqr(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  ge *r = getge(g, v[2].buf);
+  ge *c = G_CREATE(g);
+  int ok = 1;
+  G_SQR(g, c, x);
+  ok &= check("sqr", v[0].buf, g, r, c, "x", x, (char *)0);
+  G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vinv(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  ge *r = getge(g, v[2].buf);
+  ge *c = G_CREATE(g);
+  int ok = 1;
+  G_INV(g, c, x);
+  ok &= check("inv", v[0].buf, g, r, c, "x", x, (char *)0);
+  G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vdiv(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  ge *y = getge(g, v[2].buf);
+  ge *r = getge(g, v[3].buf);
+  ge *c = G_CREATE(g);
+  int ok = 1;
+  G_DIV(g, c, x, y);
+  ok &= check("div", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
+  group_stddiv(g, c, x, y);
+  ok &= check("stddiv", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
+  G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vexp(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  mp *n = *(mp **)v[2].buf;
+  ge *r = getge(g, v[3].buf);
+  ge *c = G_CREATE(g);
+  int ok = 1;
+  G_EXP(g, c, x, n);
+  if (!G_EQ(g, r, c)) {
+    ok = 0;
+    fprintf(stderr, "\n*** exp failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    show(g, "x", x); showmp("n", n, 10);
+    show(g, "expected", r); show(g, "computed", c);
+  }
+  group_stdexp(g, c, x, n);
+  if (!G_EQ(g, r, c)) {
+    ok = 0;
+    fprintf(stderr, "\n*** stdexp failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    show(g, "x", x); showmp("n", n, 10);
+    show(g, "expected", r); show(g, "computed", c);
+  }
+  G_DESTROY(g, x); MP_DROP(n); G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vmexp(size_t n, dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *c, *r;
+  group_expfactor *f = xmalloc(n * sizeof(group_expfactor));
+  int ok = 1;
+  size_t i;
+  for (i = 0; i < n; i++) {
+    f[i].base = getge(g, v[1 + 2 * i].buf);
+    f[i].exp = *(mp **)v[2 + 2 * i].buf;
+  }
+  r = getge(g, v[1 + 2 * n].buf);
+  c = G_CREATE(g);
+  G_MEXP(g, c, f, n);
+  if (!G_EQ(g, r, c)) {
+    ok = 0;
+    fprintf(stderr, "\n*** mexp failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    for (i = 0; i < n; i++) {
+      show(g, "base", f[i].base);
+      showmp("exp", f[i].exp, 10);
+    }
+    show(g, "expected", r); show(g, "computed", c);
+  }
+  group_stdmexp(g, c, f, n);
+  if (!G_EQ(g, r, c)) {
+    ok = 0;
+    fprintf(stderr, "\n*** stdmexp failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    for (i = 0; i < n; i++) {
+      show(g, "base", f[i].base);
+      showmp("exp", f[i].exp, 10);
+    }
+    show(g, "expected", r); show(g, "computed", c);
+  }
+  for (i = 0; i < n; i++) { G_DESTROY(g, f[i].base); MP_DROP(f[i].exp); }
+  G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vmexp1(dstr *v) { return vmexp(1, v); }
+static int vmexp2(dstr *v) { return vmexp(2, v); }
+static int vmexp3(dstr *v) { return vmexp(3, v); }
+static int vmexp4(dstr *v) { return vmexp(4, v); }
+
+static int vtoint(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  int ir = *(int *)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *c;
+  int ic;
+  int ok = 1;
+  c = G_TOINT(g, MP_NEW, x);
+  ic = c ? 0 : -1;
+  if (ir != ic || (!ic && !MP_EQ(r, c))) {
+    ok = 0;
+    fprintf(stderr, "\n*** toint failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    if (ir) fprintf(stderr, "*** expected failure\n");
+    else { show(g, "x", x); showmp("expected", r, 16);
+    showmp("computed", c, 16); }
+  }
+  G_DESTROY(g, x); mp_drop(r); mp_drop(c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vfromint(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  mp *x = *(mp **)v[1].buf;
+  int ir = *(int *)v[2].buf;
+  ge *r = getge(g, v[3].buf);
+  int ic;
+  ge *c = G_CREATE(g);
+  int ok = 1;
+  ic = G_FROMINT(g, c, x);
+  if (ir != ic || (!ic && !G_EQ(g, r, c))) {
+    ok = 0;
+    fprintf(stderr, "\n*** fromint failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    showmp("x", x, 16); if (ir) fprintf(stderr, "*** should have failed\n");
+    else { show(g, "expected", r); show(g, "computed", c); }
+  }
+  MP_DROP(x); G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vtoec(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  int ir = *(int *)v[2].buf;
+  ec *r = (ec *)v[3].buf;
+  int ic;
+  ec c = EC_INIT;
+  int ok = 1;
+  ic = G_TOEC(g, &c, x);
+  if (ir != ic || (!ic && !EC_EQ(r, &c))) {
+    ok = 0;
+    fprintf(stderr, "\n*** toec failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    show(g, "x", x);
+    if (ir) fprintf(stderr, "*** should have failed\n");
+    else { showec("expected", r); showec("computed", &c); }
+  }
+  G_DESTROY(g, x); EC_DESTROY(&c); EC_DESTROY(r);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vfromec(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ec *p = (ec *)v[1].buf;
+  int ir = *(int *)v[2].buf;
+  ge *r = getge(g, v[3].buf);
+  int ic;
+  ge *c = G_CREATE(g);
+  int ok = 1;
+  ic = G_FROMEC(g, c, p);
+  if (ir != ic || (!ic && !G_EQ(g, r, c))) {
+    ok = 0;
+    fprintf(stderr, "\n*** fromec failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    showec("p", p); if (ir) fprintf(stderr, "*** should have failed\n");
+    else { show(g, "expected", r); show(g, "computed", c); }
+  }
+  EC_DESTROY(p); G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vtobuf(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  int ir = *(int *)v[2].buf;
+  dstr c = DSTR_INIT;
+  int ic;
+  buf b;
+  int ok = 1;
+
+  dstr_ensure(&c, v[3].len);
+  buf_init(&b, c.buf, v[3].len);
+  ic = G_TOBUF(g, &b, x);
+  c.len = BLEN(&b);
+  if (ic != ir || (!ic && (c.len != v[3].len ||
+                          memcmp(c.buf, v[3].buf, c.len)))) {
+    ok = 0;
+    fprintf(stderr, "*** tobuf failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    show(g, "x", x);
+    if (ir) fprintf(stderr, "*** expected failure\n");
+    else {
+      fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
+      fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
+      fputc('\n', stderr);
+    }
+  }
+  G_DESTROY(g, x); dstr_destroy(&c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vfrombuf(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  int ir = *(int *)v[2].buf;
+  ge *r = getge(g, v[3].buf);
+  int ic;
+  ge *c = G_CREATE(g);
+  buf b;
+  int ok = 1;
+
+  buf_init(&b, v[1].buf, v[1].len);
+  ic = G_FROMBUF(g, &b, c);
+  if ((ic < 0) != (ir < 0) || (ir >= 0 &&
+                              (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
+    ok = 0;
+    fprintf(stderr, "*** frombuf failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
+    fputc('\n', stderr);
+    if (ir < 0) fprintf(stderr, "*** expected failure\n");
+    else {
+      show(g, "expected", r); show(g, "computed", c);
+      fprintf(stderr, "*** expected used = %d\n", ir);
+      fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
+    }
+  }
+  G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vtoraw(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  ge *x = getge(g, v[1].buf);
+  int ir = *(int *)v[2].buf;
+  dstr c = DSTR_INIT;
+  int ic;
+  buf b;
+  int ok = 1;
+
+  dstr_ensure(&c, v[3].len);
+  buf_init(&b, c.buf, v[3].len);
+  ic = G_TORAW(g, &b, x);
+  c.len = BLEN(&b);
+  if (ic != ir || (!ic && (c.len != v[3].len ||
+                          memcmp(c.buf, v[3].buf, c.len)))) {
+    ok = 0;
+    fprintf(stderr, "*** toraw failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    show(g, "x", x);
+    if (ir) fprintf(stderr, "*** expected failure\n");
+    else {
+      fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
+      fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
+      fputc('\n', stderr);
+    }
+  }
+  G_DESTROY(g, x); dstr_destroy(&c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vfromraw(dstr *v)
+{
+  group *g = getgroup(v[0].buf);
+  int ir = *(int *)v[2].buf;
+  ge *r = getge(g, v[3].buf);
+  int ic;
+  ge *c = G_CREATE(g);
+  buf b;
+  int ok = 1;
+
+  buf_init(&b, v[1].buf, v[1].len);
+  ic = G_FROMRAW(g, &b, c);
+  if ((ic < 0) != (ir < 0) || (ir >= 0 &&
+                              (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
+    ok = 0;
+    fprintf(stderr, "*** fromraw failed\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
+    fputc('\n', stderr);
+    if (ir < 0) fprintf(stderr, "*** expected failure\n");
+    else {
+      show(g, "expected", r); show(g, "computed", c);
+      fprintf(stderr, "*** expected used = %d\n", ir);
+      fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
+    }
+  }
+  G_DESTROY(g, r); G_DESTROY(g, c);
+  G_DESTROYGROUP(g);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static const test_chunk tests[] = {
+  { "check",   vcheck,         { &type_string, &type_string } },
+  { "checkelt",        vcheckelt,      { &type_string, &type_string, &type_int } },
+  { "mul",     vmul,           { &type_string, &type_string,
+                                 &type_string, &type_string } },
+  { "sqr",     vsqr,           { &type_string, &type_string,
+                                 &type_string } },
+  { "inv",     vinv,           { &type_string, &type_string,
+                                 &type_string } },
+  { "div",     vdiv,           { &type_string, &type_string,
+                                 &type_string, &type_string } },
+  { "exp",     vexp,           { &type_string, &type_string,
+                                 &type_mp, &type_string } },
+  { "mexp-1",  vmexp1,         { &type_string,
+                                 &type_string, &type_mp,
+                                 &type_string } },
+  { "mexp-2",  vmexp2,         { &type_string,
+                                 &type_string, &type_mp,
+                                 &type_string, &type_mp,
+                                 &type_string } },
+  { "mexp-3",  vmexp3,         { &type_string,
+                                 &type_string, &type_mp,
+                                 &type_string, &type_mp,
+                                 &type_string, &type_mp,
+                                 &type_string } },
+  { "mexp-4",  vmexp4,         { &type_string,
+                                 &type_string, &type_mp,
+                                 &type_string, &type_mp,
+                                 &type_string, &type_mp,
+                                 &type_string, &type_mp,
+                                 &type_string } },
+  { "toint",   vtoint,         { &type_string, &type_string,
+                                 &type_int, &type_mp } },
+  { "fromint", vfromint,       { &type_string, &type_mp,
+                                 &type_int, &type_string } },
+  { "toec",    vtoec,          { &type_string, &type_string,
+                                 &type_int, &type_ec } },
+  { "fromec",  vfromec,        { &type_string, &type_ec,
+                                 &type_int, &type_string } },
+  { "tobuf",   vtobuf,         { &type_string, &type_string,
+                                 &type_int, &type_hex } },
+  { "frombuf", vfrombuf,       { &type_string, &type_hex,
+                                 &type_int, &type_string } },
+  { "toraw",   vtoraw,         { &type_string, &type_string,
+                                 &type_int, &type_hex } },
+  { "fromraw", vfromraw,       { &type_string, &type_hex,
+                                 &type_int, &type_string } },
+  { 0 }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/group");
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/group.h b/math/group.h
new file mode 100644 (file)
index 0000000..cdfbdd4
--- /dev/null
@@ -0,0 +1,409 @@
+/* -*-c-*-
+ *
+ * General cyclic group abstraction
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_GROUP_H
+#define CATACOMB_GROUP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#ifndef CATACOMB_BUF_H
+#  include "buf.h"
+#endif
+
+#ifndef CATACOMB_DH_H
+#  include "ec.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_QDPARSE_H
+#  include "qdparse.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+#ifndef ge
+  typedef struct ge ge;                        /* Group element (abstract type) */
+#endif
+
+typedef struct group_ {
+  const struct group_ops *ops;         /* Operations table */
+  size_t nbits;                                /* Size of an element in bits */
+  size_t noctets;                      /* Size of raw element in octets */
+  ge *i;                               /* Identity element */
+  ge *g;                               /* Generator element */
+  mp *r;                               /* Order of the generator */
+  mp *h;                               /* Cofactor */
+} group;
+
+typedef struct group_expfactor {
+  ge *base;                            /* The base */
+  mp *exp;                             /* The exponent */
+} group_expfactor;
+
+typedef struct group_ops {
+
+  /* --- General information --- */
+
+  unsigned ty;                         /* Type of this group */
+  const char *name;                    /* Textual name string */
+
+  /* --- Memory management --- */
+
+  void (*destroygroup)(group */*g*/);
+  ge *(*create)(group */*g*/);
+  void (*copy)(group */*g*/, ge */*d*/, ge */*x*/);
+  void (*burn)(group */*g*/, ge */*x*/);
+  void (*destroy)(group */*g*/, ge */*e*/);
+
+  /* --- Comparisons --- */
+
+  int (*samep)(group */*g*/, group */*h*/);
+  int (*eq)(group */*g*/, ge */*x*/, ge */*y*/);
+  int (*identp)(group */*g*/, ge */*x*/);
+
+  /* --- Other stuff --- */
+
+  const char *(*check)(group */*g*/, grand */*gr*/);
+
+  /* --- Arithmetic --- */
+
+  void (*mul)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
+  void (*sqr)(group */*g*/, ge */*d*/, ge */*x*/);
+  void (*inv)(group */*g*/, ge */*d*/, ge */*x*/);
+  void (*div)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
+  void (*exp)(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/);
+  void (*mexp)(group */*g*/, ge */*d*/,
+              const group_expfactor */*f*/, size_t /*n*/);
+
+  /* --- Debugging --- */
+
+  int (*read)(group */*g*/, ge */*d*/,
+             const mptext_ops */*ops*/, void */*p*/);
+  int (*write)(group */*g*/, ge */*x*/,
+              const mptext_ops */*ops*/, void */*p*/);
+
+  /* --- Conversions --- */
+
+  mp *(*toint)(group */*g*/, mp */*d*/, ge */*x*/);
+  int (*fromint)(group */*g*/, ge */*d*/, mp */*x*/);
+  int (*toec)(group */*g*/, ec */*d*/, ge */*x*/);
+  int (*fromec)(group */*g*/, ge */*d*/, const ec */*p*/);
+  int (*tobuf)(group */*h*/, buf */*b*/, ge */*x*/);
+  int (*frombuf)(group */*h*/, buf */*b*/, ge */*d*/);
+  int (*toraw)(group */*h*/, buf */*b*/, ge */*x*/);
+  int (*fromraw)(group */*h*/, buf */*b*/, ge */*d*/);
+
+} group_ops;
+
+enum {
+  GTY_PRIME,                           /* Prime field subgroup */
+  GTY_BINARY,                          /* Binary feld subgroup */
+  GTY_EC                               /* Elliptic curve group */
+};
+
+#define G_NAME(g)              (g)->ops->name
+#define G_TYPE(g)              (g)->ops->ty
+
+#define G_DESTROYGROUP(g)      (g)->ops->destroygroup((g))
+#define G_CREATE(g)            (g)->ops->create((g))
+#define G_COPY(g, d, x)                (g)->ops->copy((g), (d), (x))
+#define G_BURN(g, x)           (g)->ops->burn((g), (x))
+#define G_DESTROY(g, x)                (g)->ops->destroy((g), (x))
+
+#define G_SAMEP(g, h)          (g)->ops->samep((g), (h))
+#define G_EQ(g, x, y)          (g)->ops->eq((g), (x), (y))
+#define G_IDENTP(g, x)         (g)->ops->identp((g), (x))
+
+#define G_CHECK(g, gr)         (g)->ops->check((g), (gr))
+
+#define G_MUL(g, d, x, y)      (g)->ops->mul((g), (d), (x), (y))
+#define G_SQR(g, d, x)         (g)->ops->sqr((g), (d), (x))
+#define G_INV(g, d, x)         (g)->ops->inv((g), (d), (x))
+#define G_DIV(g, d, x, y)      (g)->ops->div((g), (d), (x), (y))
+#define G_EXP(g, d, x, n)      (g)->ops->exp((g), (d), (x), (n))
+#define G_MEXP(g, d, f, n)     (g)->ops->mexp((g), (d), (f), (n))
+
+#define G_READ(g, d, o, p)     (g)->ops->read((g), (d), (o), (p))
+#define G_WRITE(g, x, o, p)    (g)->ops->write((g), (x), (o), (p))
+
+#define G_TOINT(g, d, x)       (g)->ops->toint((g), (d), (x))
+#define G_FROMINT(g, d, x)     (g)->ops->fromint((g), (d), (x))
+#define G_TOEC(g, d, x)                (g)->ops->toec((g), (d), (x))
+#define G_FROMEC(g, d, p)      (g)->ops->fromec((g), (d), (p))
+#define G_TOBUF(g, b, x)       (g)->ops->tobuf((g), (b), (x))
+#define G_FROMBUF(g, b, d)     (g)->ops->frombuf((g), (b), (d))
+#define G_TORAW(g, b, x)       (g)->ops->toraw((g), (b), (x))
+#define G_FROMRAW(g, b, d)     (g)->ops->fromraw((g), (b), (d))
+
+/*----- Handy functions ---------------------------------------------------*/
+
+/* --- @group_check@ --- *
+ *
+ * Arguments:  @group *g@ = an abstract group
+ *             @ge *x@ = a group element
+ *
+ * Returns:    Zero on success, nonzero for failure.
+ *
+ * Use:                Checks that @x@ is a valid group element.  This may take a
+ *             while, since it checks that %$x^h \ne 1$%.
+ */
+
+extern int group_check(group */*g*/, ge */*x*/);
+
+/* --- @group_samep@ --- *
+ *
+ * Arguments:  @group *g, *h@ = two abstract groups
+ *
+ * Returns:    Nonzero if the groups are in fact identical (not just
+ *             isomorphic).
+ *
+ * Use:                Checks to see whether two groups are actually the same.  This
+ *             function does the full check: the group operatrion @samep@
+ *             just does the group-specific details.
+ */
+
+extern int group_samep(group */*g*/, group */*h*/);
+
+/*----- Textual I/O on group elements -------------------------------------*/
+
+extern int group_readstring(group */*g*/, ge */*d*/,
+                           const char */*p*/, char **/*end*/);
+extern int group_writestring(group */*g*/, ge */*d*/,
+                            char */*p*/, size_t /*sz*/);
+
+extern int group_readfile(group */*g*/, ge */*d*/, FILE */*fp*/);
+extern int group_writefile(group */*g*/, ge */*x*/, FILE */*fp*/);
+
+extern int group_readdstr(group */*g*/, ge */*d*/,
+                         dstr */*dd*/, size_t */*off*/);
+extern int group_writedstr(group */*g*/, ge */*x*/, dstr */*d*/);
+
+/*----- Standard implementations ------------------------------------------*/
+
+/* --- @group_stdidentp@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *x@ = group element
+ *
+ * Returns:    Nonzero if %$x$% is the group identity.
+ */
+
+extern int group_stdidentp(group */*g*/, ge */*x*/);
+
+/* --- @group_stdcheck@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @grand *gr@ = random number source.
+ *
+ * Returns:    Null on success, or a pointer to an error message.
+ */
+
+extern const char *group_stdcheck(group */*g*/, grand */*gr*/);
+
+/* --- @group_stdsqr@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @ge *x@ = group element
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = x^2$% as %$d = x x$%.
+ */
+
+extern void group_stdsqr(group */*g*/, ge */*d*/, ge */*x*/);
+
+/* --- @group_stddiv@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @ge *x@ = dividend
+ *             @ge *y@ = divisor
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = x/y$% as %$d = x y^{-1}$%.
+ */
+
+extern void group_stddiv(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
+
+/* --- @group_stdexp@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @ge *x@ = base element
+ *             @mp *n@ = exponent
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = x^n$% efficiently.
+ */
+
+extern void group_stdexp(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/);
+
+/* --- @group_stdmexp@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @const group_expfactor *f@ = vector of factors
+ *             @size_t n@ = number of factors
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently.
+ */
+
+extern void group_stdmexp(group */*g*/, ge */*d*/,
+                         const group_expfactor */*f*/, size_t /*n*/);
+
+/* --- @group_stdtoec@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ec *d@ = destination point
+ *             @ge *x@ = group element
+ *
+ * Returns:    @-1@, indicating failure.
+ *
+ * Use:                Fails to convert a group element to an elliptic curve point.
+ */
+
+extern int group_stdtoec(group */*g*/, ec */*d*/, ge */*x*/);
+
+/* --- @group_stdfromec@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @const ec *p@ = elliptic curve point
+ *
+ * Returns:    Zero for success, @-1@ on failure.
+ *
+ * Use:                Converts %$p$% to a group element by converting its %$x$%-
+ *             coordinate.
+ */
+
+extern int group_stdfromec(group */*g*/, ge */*d*/, const ec */*p*/);
+
+/*----- Prime field subgroups ---------------------------------------------*/
+
+typedef struct gprime_param {
+  mp *p, *q;                           /* Prime numbers %$p$% and %$q$% */
+  mp *g;                               /* Generates order-%$q$% subgroup */
+} gprime_param;
+
+/* --- @group_prime@ --- *
+ *
+ * Arguments:  @const gprime_param *gp@ = group parameters
+ *
+ * Returns:    A pointer to the group, or null.
+ *
+ * Use:                Constructs an abstract group interface for a subgroup of a
+ *             prime field.  Group elements are @mp *@ pointers.
+ */
+
+group *group_prime(const gprime_param */*gp*/);
+
+/*----- Binary field subgroups --------------------------------------------*/
+
+typedef gprime_param gbin_param;
+
+/* --- @group_binary@ --- *
+ *
+ * Arguments:  @const gbin_param *gb@ = group parameters
+ *
+ * Returns:    A pointer to the group, or null.
+ *
+ * Use:                Constructs an abstract group interface for a subgroup of a
+ *             prime field.  Group elements are @mp *@ pointers.
+ */
+
+group *group_binary(const gbin_param */*gp*/);
+
+/*----- Elliptic curve groups ---------------------------------------------*/
+
+/* --- @group_ec@ --- *
+ *
+ * Arguments:  @const ec_info *ei@ = elliptic curve parameters
+ *
+ * Returns:    A pointer to the group, or null.
+ *
+ * Use:                Constructs an abstract group interface for an elliptic curve
+ *             group.  Group elements are @ec@ structures.  The contents of
+ *             the @ec_info@ structure becomes the property of the @group@
+ *             object; you can (and should) free the structure itself, but
+ *             calling @ec_freeinfo@ on it is not allowed.
+ */
+
+group *group_ec(const ec_info */*ei*/);
+
+/*----- General group initialization --------------------------------------*/
+
+/* --- @group_parse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = quick-and-dirty parser
+ *
+ * Returns:    Group pointer, or null for failure.
+ *
+ * Use:                Parses a group description and returns the group.  This has
+ *             the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and
+ *             SPEC is the appropriate kind of group specification of the
+ *             given type.
+ */
+
+extern group *group_parse(qd_parse */*qd*/);
+
+/* --- @group_fromstring@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to string to read
+ *             @group **gg@ = where to put the group pointer
+ *
+ * Returns:    Null if OK, or an error string.
+ *
+ * Use:                Parses a group spec from a string, and returns the group.
+ */
+
+extern const char *group_fromstring(const char */*p*/, group **/*gg*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/karatsuba.h b/math/karatsuba.h
new file mode 100644 (file)
index 0000000..015f7b0
--- /dev/null
@@ -0,0 +1,142 @@
+/* -*-c-*-
+ *
+ * Macros for Karatsuba functions
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_KARATSUBA_H
+#define CATACOMB_KARATSUBA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MPW_H
+#  include "mpw.h"
+#endif
+
+/*----- Normal arithmetic macros ------------------------------------------*/
+
+#define UADD(dv, av, avl) do {                                         \
+  mpw *_dv = (dv);                                                     \
+  const mpw *_av = (av), *_avl = (avl);                                        \
+  mpw _c = 0;                                                          \
+                                                                       \
+  while (_av < _avl) {                                                 \
+    mpw _a, _b;                                                                \
+    mpd _x;                                                            \
+    _a = *_av++;                                                       \
+    _b = *_dv;                                                         \
+    _x = (mpd)_a + (mpd)_b + _c;                                       \
+    *_dv++ = MPW(_x);                                                  \
+    _c = _x >> MPW_BITS;                                               \
+  }                                                                    \
+  while (_c) {                                                         \
+    mpd _x = (mpd)*_dv + (mpd)_c;                                      \
+    *_dv++ = MPW(_x);                                                  \
+    _c = _x >> MPW_BITS;                                               \
+  }                                                                    \
+} while (0)
+
+#define UADD2(dv, dvl, av, avl, bv, bvl) do {                          \
+  mpw *_dv = (dv), *_dvl = (dvl);                                      \
+  const mpw *_av = (av), *_avl = (avl);                                        \
+  const mpw *_bv = (bv), *_bvl = (bvl);                                        \
+  mpw _c = 0;                                                          \
+                                                                       \
+  while (_av < _avl || _bv < _bvl) {                                   \
+    mpw _a, _b;                                                                \
+    mpd _x;                                                            \
+    _a = (_av < _avl) ? *_av++ : 0;                                    \
+    _b = (_bv < _bvl) ? *_bv++ : 0;                                    \
+    _x = (mpd)_a + (mpd)_b + _c;                                       \
+    *_dv++ = MPW(_x);                                                  \
+    _c = _x >> MPW_BITS;                                               \
+  }                                                                    \
+  *_dv++ = _c;                                                         \
+  while (_dv < _dvl)                                                   \
+    *_dv++ = 0;                                                                \
+} while (0)
+
+#define USUB(dv, av, avl) do {                                         \
+  mpw *_dv = (dv);                                                     \
+  const mpw *_av = (av), *_avl = (avl);                                        \
+  mpw _c = 0;                                                          \
+                                                                       \
+  while (_av < _avl) {                                                 \
+    mpw _a, _b;                                                                \
+    mpd _x;                                                            \
+    _a = *_av++;                                                       \
+    _b = *_dv;                                                         \
+    _x = (mpd)_b - (mpd)_a - _c;                                       \
+    *_dv++ = MPW(_x);                                                  \
+    if (_x >> MPW_BITS)                                                        \
+      _c = 1;                                                          \
+    else                                                               \
+      _c = 0;                                                          \
+  }                                                                    \
+  while (_c) {                                                         \
+    mpd _x = (mpd)*_dv - (mpd)_c;                                      \
+    *_dv++ = MPW(_x);                                                  \
+    if (_x >> MPW_BITS)                                                        \
+      _c = 1;                                                          \
+    else                                                               \
+      _c = 0;                                                          \
+  }                                                                    \
+} while (0)
+
+/*----- Binary polynomial arithmetic macros -------------------------------*/
+
+#define UXOR(dv, av, avl) do {                                         \
+  mpw *_dv = (dv);                                                     \
+  const mpw *_av = (av), *_avl = (avl);                                        \
+                                                                       \
+  while (_av < _avl)                                                   \
+    *_dv++ ^= *_av++;                                                  \
+} while (0)
+
+#define UXOR2(dv, dvl, av, avl, bv, bvl) do {                          \
+  mpw *_dv = (dv), *_dvl = (dvl);                                      \
+  const mpw *_av = (av), *_avl = (avl);                                        \
+  const mpw *_bv = (bv), *_bvl = (bvl);                                        \
+                                                                       \
+  while (_av < _avl || _bv < _bvl) {                                   \
+    mpw _a, _b;                                                                \
+    _a = (_av < _avl) ? *_av++ : 0;                                    \
+    _b = (_bv < _bvl) ? *_bv++ : 0;                                    \
+    *_dv++ = _a ^ _b;                                                  \
+  }                                                                    \
+  while (_dv < _dvl)                                                   \
+    *_dv++ = 0;                                                                \
+} while (0)
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/limlee.c b/math/limlee.c
new file mode 100644 (file)
index 0000000..b20965a
--- /dev/null
@@ -0,0 +1,396 @@
+/* -*-c-*-
+ *
+ * Generate Lim-Lee primes
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+
+#include "limlee.h"
+#include "mpmul.h"
+#include "mprand.h"
+#include "pgen.h"
+#include "rabin.h"
+
+/*----- Stepping through combinations -------------------------------------*/
+
+/* --- @comb_init@ --- *
+ *
+ * Arguments:  @octet *c@ = pointer to byte-flag array
+ *             @unsigned n@ = number of items in the array
+ *             @unsigned r@ = number of desired items
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a byte-flag array which, under the control of
+ *             @comb_next@, will step through all combinations of @r@ chosen
+ *             elements.
+ */
+
+static void comb_init(octet *c, unsigned n, unsigned r)
+{
+  memset(c, 0, n - r);
+  memset(c + (n - r), 1, r);
+}
+
+/* --- @comb_next@ --- *
+ *
+ * Arguments:  @octet *c@ = pointer to byte-flag array
+ *             @unsigned n@ = number of items in the array
+ *             @unsigned r@ = number of desired items
+ *
+ * Returns:    Nonzero if another combination was returned, zero if we've
+ *             reached the end.
+ *
+ * Use:                Steps on to the next combination in sequence.
+ */
+
+static int comb_next(octet *c, unsigned n, unsigned r)
+{
+  unsigned g = 0;
+
+  /* --- How the algorithm works --- *
+   *
+   * Set bits start at the end and work their way towards the start.
+   * Excepting bits already at the start, we scan for the lowest set bit, and
+   * move it one place nearer the start.  A group of bits at the start are
+   * counted and reset just below the `moved' bit.  If there is no moved bit
+   * then we're done.
+   */
+
+  /* --- Count the group at the start --- */
+
+  for (; *c; c++) {
+    g++;
+    *c = 0;
+  }
+  if (g == r)
+    return (0);
+
+  /* --- Move the next bit down one --- *
+   *
+   * There must be one, because otherwise we'd have counted %$r$% bits
+   * earlier.
+   */
+
+  for (; !*c; c++)
+    ;
+  *c = 0;
+  g++;
+  for (; g; g--)
+    *--c = 1;
+  return (1);
+}
+
+/*----- Default prime generator -------------------------------------------*/
+
+static void llgen(limlee_factor *f, unsigned pl, limlee_stepctx *l)
+{
+  pgen_filterctx pf;
+  rabin r;
+  mp *p;
+
+again:
+  p = mprand(l->newp, pl, l->r, 1);
+  pf.step = 2;
+  p = pgen(l->d.buf, p, p, l->iev, l->iec, 0, pgen_filter, &pf,
+          rabin_iters(pl), pgen_test, &r);
+  if (!p)
+    goto again;
+  f->p = p;
+}
+
+static void llfree(limlee_factor *f, limlee_stepctx *l)
+{
+  mp_drop(f->p);
+}
+
+static const limlee_primeops primeops_simple = { llgen, llfree };
+
+/*----- Lim-Lee stepper ---------------------------------------------------*/
+
+/* --- @init@ --- *
+ *
+ * Arguments:  @pgen_event *ev@ = pointer to event block
+ *             @limlee_stepctx *l@ = pointer to Lim-Lee context
+ *
+ * Returns:    A @PGEN@ result code.
+ *
+ * Use:                Initializes the stepper.
+ */
+
+static int init(pgen_event *ev, limlee_stepctx *l)
+{
+  size_t i;
+  unsigned qql;
+
+  /* --- First of all, decide on a number of factors to make --- */
+
+  l->nf = l->pl / l->ql;
+  qql = l->pl % l->ql;
+  if (!l->nf)
+    return (PGEN_ABORT);
+  else if (qql && l->nf > 1) {
+    l->nf--;
+    qql += l->ql;
+  }
+
+  /* --- Now decide on how many primes I'll actually generate --- *
+   *
+   * The formula %$m = \max(3 n + 5, 25)$% comes from GPG's prime generation
+   * library.
+   */
+
+  l->poolsz = l->nf * 3 + 5;
+  if (l->poolsz < 25)
+    l->poolsz = 25;
+
+  /* --- Allocate and initialize the various tables --- */
+
+  l->c = xmalloc(l->poolsz);
+  l->v = xmalloc(l->poolsz * sizeof(limlee_factor));
+  comb_init(l->c, l->poolsz, l->nf);
+  for (i = 0; i < l->poolsz; i++)
+    l->v[i].p = 0;
+
+  /* --- Other bits of initialization --- */
+
+  l->seq = 0;
+  dstr_create(&l->d);
+  if (!l->pops) {
+    l->pops = &primeops_simple;
+    l->pc = 0;
+  }
+
+  /* --- Find a big prime --- */
+
+  if (!qql)
+    l->qq.p = 0;
+  else {
+    dstr_putf(&l->d, "%s*", ev->name);
+    l->pops->pgen(&l->qq, qql, l);
+  }
+
+  return (PGEN_TRY);
+}
+
+/* --- @next@ --- *
+ *
+ * Arguments:  @int rq@ = request which triggered this call
+ *             @pgen_event *ev@ = pointer to event block
+ *             @limlee_stepctx *l@ = pointer to Lim-Lee context
+ *
+ * Returns:    A @PGEN@ result code.
+ *
+ * Use:                Initializes the stepper.
+ */
+
+static int next(int rq, pgen_event *ev, limlee_stepctx *l)
+{
+  mp *p;
+  int rc;
+
+  mp_drop(ev->m);
+
+  for (;;) {
+    size_t i;
+    mpmul mm = MPMUL_INIT;
+
+    /* --- Step on to next combination --- */
+
+    if (rq == PGEN_TRY && !comb_next(l->c, l->poolsz, l->nf)) {
+      for (i = 0; i < l->poolsz; i++) {
+       l->pops->pfree(&l->v[i], l);
+       l->v[i].p = 0;
+      }
+    }
+    rq = PGEN_TRY; /* For next time through */
+
+    /* --- Gather up some factors --- */
+
+    if (l->qq.p)
+      mpmul_add(&mm, l->qq.p);
+    for (i = 0; i < l->poolsz; i++) {
+      if (!l->c[i])
+       continue;
+      if (!l->v[i].p) {
+       DRESET(&l->d);
+       dstr_putf(&l->d, "%s_%lu", ev->name, l->seq++);
+       l->pops->pgen(&l->v[i], l->ql, l);
+      }
+      mpmul_add(&mm, l->v[i].p);
+    }
+
+    /* --- Check it for small factors --- */
+
+    p = mpmul_done(&mm);
+    p = mp_lsl(p, p, 1);
+    p->v[0] |= 1;
+    if ((rc = pfilt_smallfactor(p)) != PGEN_FAIL)
+      break;
+    mp_drop(p);
+  }
+
+  ev->m = p;
+  return (rc);
+}
+
+/* --- @done@ --- *
+ *
+ * Arguments:  @pgen_event *ev@ = pointer to event block
+ *             @limlee_stepctx *l@ = pointer to Lim-Lee context
+ *
+ * Returns:    A @PGEN@ result code.
+ *
+ * Use:                Finalizes the stepper.  The output values in the context
+ *             take on their final results; other resources are discarded.
+ */
+
+static int done(pgen_event *ev, limlee_stepctx *l)
+{
+  size_t i, j;
+  limlee_factor *v;
+
+  /* --- If an output vector of factors is wanted, produce one --- */
+
+  if (!(l->f & LIMLEE_KEEPFACTORS))
+    v = 0;
+  else {
+    if (l->qq.p)
+      l->nf++;
+    v = xmalloc(l->nf * sizeof(limlee_factor));
+  }
+
+  for (i = 0, j = 0; i < l->poolsz; i++) {
+    if (v && l->c[i])
+      v[j++] = l->v[i];
+    else if (l->v[i].p)
+      l->pops->pfree(&l->v[i], l);
+  }
+
+  if (l->qq.p) {
+    if (v)
+      v[j++] = l->qq;
+    else
+      l->pops->pfree(&l->qq, l);
+  }
+
+  xfree(l->v);
+  l->v = v;
+
+  /* --- Free other resources --- */
+
+  xfree(l->c);
+  dstr_destroy(&l->d);
+
+  /* --- Done --- */
+
+  return (PGEN_DONE);
+}
+
+/* --- @limlee_step@ --- */
+
+int limlee_step(int rq, pgen_event *ev, void *p)
+{
+  limlee_stepctx *l = p;
+  int rc;
+
+  switch (rq) {
+    case PGEN_BEGIN:
+      if ((rc = init(ev, l)) != PGEN_TRY)
+       return (rc);
+    case PGEN_TRY:
+      return (next(rq, ev, l));
+    case PGEN_DONE:
+      return (done(ev, l));
+  }
+  return (PGEN_ABORT);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @limlee@ --- *
+ *
+ * Arguments:  @const char *name@ = pointer to name root
+ *             @mp *d@ = pointer to destination integer
+ *             @mp *newp@ = how to generate factor primes
+ *             @unsigned ql@ = size of individual factors
+ *             @unsigned pl@ = size of large prime
+ *             @grand *r@ = a random number source
+ *             @unsigned on@ = number of outer attempts to make
+ *             @pgen_proc *oev@ = outer event handler function
+ *             @void *oec@ = argument for the outer event handler
+ *             @pgen_proc *iev@ = inner event handler function
+ *             @void *iec@ = argument for the inner event handler
+ *             @size_t *nf@, @mp ***f@ = output array for factors
+ *
+ * Returns:    A Lim-Lee prime, or null if generation failed.
+ *
+ * Use:                Generates Lim-Lee primes.  A Lim-Lee prime %$p$% is one which
+ *             satisfies %$p = 2 \prod_i q_i + 1$%, where all of the %$q_i$%
+ *             are large enough to resist square-root discrete log
+ *             algorithms.
+ *
+ *             If we succeed, and @f@ is non-null, we write the array of
+ *             factors chosen to @f@ for the benefit of the caller.
+ */
+
+mp *limlee(const char *name, mp *d, mp *newp,
+          unsigned ql, unsigned pl, grand *r,
+          unsigned on, pgen_proc *oev, void *oec,
+          pgen_proc *iev, void *iec,
+          size_t *nf, mp ***f)
+{
+  limlee_stepctx l;
+  rabin rr;
+
+  l.f = 0; if (f) l.f |= LIMLEE_KEEPFACTORS;
+  l.newp = newp;
+  l.pl = pl; l.ql = ql;
+  l.pops = 0;
+  l.iev = iev;
+  l.iec = iec;
+  l.r = r;
+
+  d = pgen(name, d, 0, oev, oec, on, limlee_step, &l,
+          rabin_iters(pl), pgen_test, &rr);
+
+  if (d && f) {
+    mp **v;
+    size_t i;
+    v = xmalloc(l.nf * sizeof(mp *));
+    for (i = 0; i < l.nf; i++)
+      v[i] = l.v[i].p;
+    xfree(l.v);
+    *f = v;
+    *nf = l.nf;
+  }
+
+  return (d);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/limlee.h b/math/limlee.h
new file mode 100644 (file)
index 0000000..d22b5a7
--- /dev/null
@@ -0,0 +1,138 @@
+/* -*-c-*-
+ *
+ * Generate Lim-Lee primes
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_LIMLEE_H
+#define CATACOMB_LIMLEE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_PGEN_H
+#  include "pgen.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct limlee_factor {
+  mp *p;                               /* The actual prime */
+  unsigned tag;                                /* A tag, usable by the generator */
+  void *more;                          /* Pointer to more data */
+} limlee_factor;
+
+typedef struct limlee_stepctx {
+
+  /* --- To be initialized by the caller --- */
+
+  unsigned f;                          /* Various useful flags */
+  mp *newp;                            /* Initial valid for new primes */
+  unsigned ql, pl;                     /* Size of factors and result */
+  const struct limlee_primeops *pops;  /* Pointer to generator ops */
+  void *pc;                            /* Context ptr for generator ops */
+  pgen_proc *iev;                      /* Event handler for inner @pgen@ */
+  void *iec;                           /* Context for inner @pgen@ */
+  grand *r;                            /* Random number generator */
+
+  /* --- Output values --- */
+
+  size_t nf;                           /* Number of factors wanted */
+  limlee_factor *v;                    /* Vector of factors */
+
+  /* --- Maintained internally --- */
+
+  octet *c;                            /* Combination byte-flag vector */
+  unsigned long seq;                   /* Sequence number for primes */
+  size_t poolsz;                       /* Size of the small-prime pool */
+  dstr d;                              /* String for subprime name */
+  limlee_factor qq;                    /* Big prime to pick up slack */
+
+} limlee_stepctx;
+
+typedef struct limlee_primeops {
+  void (*pgen)(limlee_factor */*f*/, unsigned /*pl*/, limlee_stepctx */*l*/);
+  void (*pfree)(limlee_factor */*f*/, limlee_stepctx */*l*/);
+} limlee_primeops;
+
+/* --- Flags --- */
+
+#define LIMLEE_KEEPFACTORS 1u
+
+/*----- The Lim-Lee stepper function --------------------------------------*/
+
+extern pgen_proc limlee_step;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @limlee@ --- *
+ *
+ * Arguments:  @const char *name@ = pointer to name root
+ *             @mp *d@ = pointer to destination integer
+ *             @mp *newp@ = how to generate factor primes
+ *             @unsigned ql@ = size of individual factors
+ *             @unsigned pl@ = size of large prime
+ *             @grand *r@ = a random number source
+ *             @unsigned on@ = number of outer attempts to make
+ *             @pgen_proc *oev@ = outer event handler function
+ *             @void *oec@ = argument for the outer event handler
+ *             @pgen_proc *iev@ = inner event handler function
+ *             @void *iec@ = argument for the inner event handler
+ *             @size_t *nf@, @mp ***f@ = output array for factors
+ *
+ * Returns:    A Lim-Lee prime, or null if generation failed.
+ *
+ * Use:                Generates Lim-Lee primes.  A Lim-Lee prime %$p$% is one which
+ *             satisfies %$p = 2 \prod_i q_i + 1$%, where all of the %$q_i$%
+ *             are large enough to resist square-root discrete log
+ *             algorithms.
+ *
+ *             If we succeed, and @f@ is non-null, we write the array of
+ *             factors chosen to @f@ for the benefit of the caller.
+ */
+
+extern mp *limlee(const char */*name*/, mp */*d*/, mp */*newp*/,
+                 unsigned /*ql*/, unsigned /*pl*/, grand */*r*/,
+                 unsigned /*on*/, pgen_proc */*oev*/, void */*oec*/,
+                 pgen_proc */*iev*/, void */*iec*/,
+                 size_t */*nf*/, mp ***/*f*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mp-arith.c b/math/mp-arith.c
new file mode 100644 (file)
index 0000000..2d7d635
--- /dev/null
@@ -0,0 +1,929 @@
+/* -*-c-*-
+ *
+ * Basic arithmetic on multiprecision integers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define MAX(x, y) ((x) >= (y) ? (x) : (y))
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *             @size_t n@ = number of bits to move
+ *
+ * Returns:    Result, @a@ shifted left or right by @n@.
+ *
+ * Use:                Bitwise shift operators.  @mp_lslc@ fills the bits introduced
+ *             on the right with ones instead of zeroes: it's used
+ *             internally by @mp_lsl2c@, though it may be useful on its
+ *             own.
+ */
+
+mp *mp_lsl(mp *d, mp *a, size_t n)
+{
+  MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f);
+  mpx_lsl(d->v, d->vl, a->v, a->vl, n);
+  d->f = a->f & (MP_NEG | MP_BURN);
+  MP_SHRINK(d);
+  return (d);
+}
+
+mp *mp_lslc(mp *d, mp *a, size_t n)
+{
+  MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f);
+  mpx_lslc(d->v, d->vl, a->v, a->vl, n);
+  d->f = a->f & (MP_NEG | MP_BURN);
+  MP_SHRINK(d);
+  return (d);
+}
+
+mp *mp_lsr(mp *d, mp *a, size_t n)
+{
+  MP_DEST(d, MP_LEN(a), a->f);
+  mpx_lsr(d->v, d->vl, a->v, a->vl, n);
+  d->f = a->f & (MP_NEG | MP_BURN);
+  MP_SHRINK(d);
+  return (d);
+}
+
+/* --- @mp_lsl2c@, @mp_lsr2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *             @size_t n@ = number of bits to move
+ *
+ * Returns:    Result, @a@ shifted left or right by @n@.  Handles the
+ *             pretence of sign-extension for negative numbers.
+ */
+
+mp *mp_lsl2c(mp *d, mp *a, size_t n)
+{
+  if (!MP_NEGP(a))
+    return (mp_lsl(d, a, n));
+  d = mp_not2c(d, a);
+  d = mp_lslc(d, d, n);
+  d = mp_not2c(d, d);
+  return (d);
+}
+
+mp *mp_lsr2c(mp *d, mp *a, size_t n)
+{
+  if (!MP_NEGP(a))
+    return (mp_lsr(d, a, n));
+  d = mp_not2c(d, a);
+  d = mp_lsr(d, d, n);
+  d = mp_not2c(d, d);
+  return (d);
+}
+
+/* --- @mp_testbit@ --- *
+ *
+ * Arguments:  @mp *x@ = a large integer
+ *             @unsigned long n@ = which bit to test
+ *
+ * Returns:    Nonzero if the bit is set, zero if not.
+ */
+
+int mp_testbit(mp *x, unsigned long n)
+{
+  if (n > MPW_BITS * MP_LEN(x))
+    return (0);
+  return ((x->v[n/MPW_BITS] >> n%MPW_BITS) & 1u);
+}
+
+/* --- @mp_testbit2c@ --- *
+ *
+ * Arguments:  @mp *x@ = a large integer
+ *             @unsigned long n@ = which bit to test
+ *
+ * Returns:    Nonzero if the bit is set, zero if not.  Fakes up two's
+ *             complement representation.
+ */
+
+int mp_testbit2c(mp *x, unsigned long n)
+{
+  int r;
+  if (!MP_NEGP(x))
+    return (mp_testbit(x, n));
+  x = mp_not2c(MP_NEW, x);
+  r = !mp_testbit(x, n);
+  MP_DROP(x);
+  return (r);
+}
+
+/* --- @mp_setbit@, @mp_clearbit@ --- *
+ *
+ * Arguments:  @mp *d@ = a destination
+ *             @mp *x@ = a large integer
+ *             @unsigned long n@ = which bit to modify
+ *
+ * Returns:    The argument @x@, with the appropriate bit set or cleared.
+ */
+
+mp *mp_setbit(mp *d, mp *x, unsigned long n)
+{
+  size_t rq;
+
+  rq = n + MPW_BITS; rq -= rq % MPW_BITS;
+  if (d != x) {
+    if (d) MP_DROP(d);
+    d = MP_COPY(x);
+  }
+  MP_DEST(d, rq, x->f & (MP_NEG | MP_BURN));
+  d->v[n/MPW_BITS] |= 1 << n%MPW_BITS;
+  return (d);
+}
+
+mp *mp_clearbit(mp *d, mp *x, unsigned long n)
+{
+  size_t rq;
+
+  rq = n + MPW_BITS; rq -= rq % MPW_BITS;
+  if (d != x) {
+    if (d) MP_DROP(d);
+    d = MP_COPY(x);
+  }
+  MP_DEST(d, rq, x->f & (MP_NEG | MP_BURN));
+  d->v[n/MPW_BITS] &= ~(1 << n%MPW_BITS);
+  return (d);
+}
+
+/* --- @mp_setbit2c@, @mp_clearbit2c@ --- *
+ *
+ * Arguments:  @mp *d@ = a destination
+ *             @mp *x@ = a large integer
+ *             @unsigned long n@ = which bit to modify
+ *
+ * Returns:    The argument @x@, with the appropriate bit set or cleared.
+ *             Fakes up two's complement representation.
+ */
+
+mp *mp_setbit2c(mp *d, mp *x, unsigned long n)
+{
+  if (!MP_NEGP(x))
+    return mp_setbit(d, x, n);
+  d = mp_not2c(d, x);
+  d = mp_clearbit(d, d, n);
+  d = mp_not2c(d, d);
+  return (d);
+}
+
+mp *mp_clearbit2c(mp *d, mp *x, unsigned long n)
+{
+  if (!MP_NEGP(x))
+    return mp_clearbit(d, x, n);
+  d = mp_not2c(d, x);
+  d = mp_setbit(d, d, n);
+  d = mp_not2c(d, d);
+  return (d);
+}
+
+/* --- @mp_eq@ --- *
+ *
+ * Arguments:  @const mp *a, *b@ = two numbers
+ *
+ * Returns:    Nonzero if the numbers are equal.
+ */
+
+int mp_eq(const mp *a, const mp *b) { return (MP_EQ(a, b)); }
+
+/* --- @mp_cmp@ --- *
+ *
+ * Arguments:  @const mp *a, *b@ = two numbers
+ *
+ * Returns:    Less than, equal to or greater than zero, according to
+ *             whether @a@ is less than, equal to or greater than @b@.
+ */
+
+int mp_cmp(const mp *a, const mp *b)
+{
+  if (!((a->f ^ b->f) & MP_NEG)) {
+    if (a->f & MP_NEG)
+      return (-mpx_ucmp(a->v, a->vl, b->v, b->vl));
+    else
+      return (mpx_ucmp(a->v, a->vl, b->v, b->vl));
+  } else if (a->f & MP_NEG)
+    return (-1);
+  else
+    return (+1);
+}
+
+/* --- @mp_neg@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = argument
+ *
+ * Returns:    The negation of the argument.
+ *
+ * Use:                Negates its argument.
+ */
+
+mp *mp_neg(mp *d, mp *a)
+{
+  /* --- Surprising amounts of messing about required --- */
+
+  MP_SHRINK(a);
+  MP_COPY(a);
+  if (d)
+    MP_DROP(d);
+  if (a->v == a->vl)
+    return (a);
+  MP_DEST(a, MP_LEN(a), a->f);
+  a->f ^= MP_NEG;
+  return (a);
+}
+
+/* --- @mp_bitop@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    The result of the given bitwise operation.  These functions
+ *             don't handle negative numbers at all sensibly.  For that, use
+ *             the @...2c@ variants.  The functions are named after the
+ *             truth tables they generate:
+ *
+ *                     a:      0011
+ *                     b:      0101
+ *                     @mpx_bitXXXX@
+ */
+
+#define MP_BITBINOP(string)                                            \
+                                                                       \
+mp *mp_bit##string(mp *d, mp *a, mp *b)                                        \
+{                                                                      \
+  MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & ~MP_NEG);      \
+  mpx_bit##string(d->v, d->vl, a->v, a->vl, b->v, b->vl);              \
+  d->f = (a->f | b->f) & MP_BURN;                                      \
+  MP_SHRINK(d);                                                                \
+  return (d);                                                          \
+}
+
+MPX_DOBIN(MP_BITBINOP)
+
+/* --- @mp_not@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *
+ * Returns:    The bitwise complement of the source.
+ */
+
+mp *mp_not(mp *d, mp *a)
+{
+  MP_DEST(d, MP_LEN(a), a->f);
+  mpx_not(d->v, d->vl, a->v, a->vl);
+  d->f = a->f & MP_BURN;
+  MP_SHRINK(d);
+  return (d);
+}
+
+/* --- @mp_bitop2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    The result of the given bitwise operation.  Negative numbers
+ *             are treated as two's complement, sign-extended infinitely to
+ *             the left.  The functions are named after the truth tables
+ *             they generate:
+ *
+ *                     a:      0011
+ *                     b:      0101
+ *                     @mpx_bitXXXX@
+ */
+
+/* --- How this actually works --- *
+ *
+ * The two arguments are inverted (with a sign-swap) if they're currently
+ * negative.  This means that we end up using a different function (one which
+ * reinverts as we go) for the main operation.  Also, if the sign would be
+ * negative at the end, we preinvert the output and then invert again with a
+ * sign-swap.
+ *
+ * Start with:                 wxyz      WXYZ
+ * If @a@ negative:            yzwx  or  YZWX
+ * If @b@ negative:            xwzy      XWZY
+ * If both negative:           zyxw      ZYXW
+ */
+
+#define MP_BIT2CBINOP(n, base, an, bn, abn, p_base, p_an, p_bn, p_abn) \
+                                                                       \
+mp *mp_bit##n##2c(mp *d, mp *a, mp *b)                                 \
+{                                                                      \
+  if (!((a->f | b->f) & MP_NEG)) {     /* Both positive */             \
+    d = mp_bit##base(d, a, b);                                         \
+    p_base                                                             \
+  } else if (!(b->f & MP_NEG)) {       /* Only @b@ positive */         \
+    MP_COPY(b);                                                                \
+    d = mp_not2c(d, a);                                                        \
+    d = mp_bit##an(d, d, b);                                           \
+    MP_DROP(b);                                                                \
+    p_an                                                               \
+  } else if (!(a->f & MP_NEG)) {       /* Only @a@ positive */         \
+    MP_COPY(a);                                                                \
+    d = mp_not2c(d, b);                                                        \
+    d = mp_bit##bn(d, a, d);                                           \
+    MP_DROP(a);                                                                \
+    p_bn                                                               \
+  } else {                             /* Both negative */             \
+    mp *t = mp_not2c(MP_NEW, a);                                       \
+    d = mp_not2c(d, b);                                                        \
+    d = mp_bit##abn(d, t, d);                                          \
+    MP_DROP(t);                                                                \
+    p_abn                                                              \
+  }                                                                    \
+  return (d);                                                          \
+}                                                                      \
+
+#define NEG d = mp_not2c(d, d);
+#define POS
+MP_BIT2CBINOP(0000, 0000, 0000, 0000, 0000, POS, POS, POS, POS)
+MP_BIT2CBINOP(0001, 0001, 0100, 0010, 0111, POS, POS, POS, NEG)
+MP_BIT2CBINOP(0010, 0010, 0111, 0001, 0100, POS, NEG, POS, POS)
+MP_BIT2CBINOP(0011, 0011, 0011, 0011, 0011, POS, NEG, POS, NEG)
+MP_BIT2CBINOP(0100, 0100, 0001, 0111, 0010, POS, POS, NEG, POS)
+MP_BIT2CBINOP(0101, 0101, 0101, 0101, 0101, POS, POS, NEG, NEG)
+MP_BIT2CBINOP(0110, 0110, 0110, 0110, 0110, POS, NEG, NEG, POS)
+MP_BIT2CBINOP(0111, 0111, 0010, 0100, 0001, POS, NEG, NEG, NEG)
+MP_BIT2CBINOP(1000, 0111, 0010, 0100, 0001, NEG, POS, POS, POS)
+MP_BIT2CBINOP(1001, 0110, 0110, 0110, 0110, NEG, POS, POS, NEG)
+MP_BIT2CBINOP(1010, 0101, 0101, 0101, 0101, NEG, NEG, POS, POS)
+MP_BIT2CBINOP(1011, 0100, 0001, 0111, 0010, NEG, NEG, POS, NEG)
+MP_BIT2CBINOP(1100, 0011, 0011, 0011, 0011, NEG, POS, NEG, POS)
+MP_BIT2CBINOP(1101, 0010, 0111, 0001, 0100, NEG, POS, NEG, NEG)
+MP_BIT2CBINOP(1110, 0001, 0100, 0010, 0111, NEG, NEG, NEG, POS)
+MP_BIT2CBINOP(1111, 0000, 0000, 0000, 0000, NEG, NEG, NEG, NEG)
+#undef NEG
+#undef POS
+
+/* --- @mp_not2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *
+ * Returns:    The sign-extended complement of the argument.
+ */
+
+mp *mp_not2c(mp *d, mp *a)
+{
+  mpw one = 1;
+
+  MP_DEST(d, MP_LEN(a) + 1, a->f);
+  if (d == a) {
+    if (MP_NEGP(a))
+      MPX_USUBN(d->v, d->vl, 1);
+    else
+      MPX_UADDN(d->v, d->vl, 1);
+  } else {
+    if (MP_NEGP(a))
+      mpx_usub(d->v, d->vl, a->v, a->vl, &one, &one + 1);
+    else
+      mpx_uadd(d->v, d->vl, a->v, a->vl, &one, &one + 1);
+  }
+  d->f = (a->f & (MP_NEG | MP_BURN)) ^ MP_NEG;
+  MP_SHRINK(d);
+  return (d);
+}
+
+/* --- @mp_add@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @a@ added to @b@.
+ */
+
+mp *mp_add(mp *d, mp *a, mp *b)
+{
+  MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)) + 1, a->f | b->f);
+  if (!((a->f ^ b->f) & MP_NEG))
+    mpx_uadd(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+  else {
+    if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) {
+      mp *t = a; a = b; b = t;
+    }
+    mpx_usub(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+  }
+  d->f = ((a->f | b->f) & MP_BURN) | (a->f & MP_NEG);
+  MP_SHRINK(d);
+  return (d);
+}
+
+/* --- @mp_sub@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @b@ subtracted from @a@.
+ */
+
+mp *mp_sub(mp *d, mp *a, mp *b)
+{
+  unsigned sgn = 0;
+  MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)) + 1, a->f | b->f);
+  if ((a->f ^ b->f) & MP_NEG)
+    mpx_uadd(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+  else {
+    if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) {
+      mp *t = a; a = b; b = t;
+      sgn = MP_NEG;
+    }
+    mpx_usub(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+  }
+  d->f = ((a->f | b->f) & MP_BURN) | ((a->f ^ sgn) & MP_NEG);
+  MP_SHRINK(d);
+  return (d);
+}
+
+/* --- @mp_mul@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @a@ multiplied by @b@.
+ */
+
+mp *mp_mul(mp *d, mp *a, mp *b)
+{
+  a = MP_COPY(a);
+  b = MP_COPY(b);
+
+  if (MP_LEN(a) <= MPK_THRESH || MP_LEN(b) <= MPK_THRESH) {
+    MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF);
+    mpx_umul(d->v, d->vl, a->v, a->vl, b->v, b->vl);
+  } else {
+    size_t m = MAX(MP_LEN(a), MP_LEN(b));
+    mpw *s;
+    MP_DEST(d, 3 * m, a->f | b->f | MP_UNDEF);
+    s = mpalloc(d->a, 5 * m);
+    mpx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + 5 * m);
+    mpfree(d->a, s);
+  }
+
+  d->f = ((a->f | b->f) & MP_BURN) | ((a->f ^ b->f) & MP_NEG);
+  MP_SHRINK(d);
+  MP_DROP(a);
+  MP_DROP(b);
+  return (d);
+}
+
+/* --- @mp_sqr@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *
+ * Returns:    Result, @a@ squared.
+ */
+
+mp *mp_sqr(mp *d, mp *a)
+{
+  size_t m = MP_LEN(a);
+
+  a = MP_COPY(a);
+  if (m > MPK_THRESH) {
+    mpw *s;
+    MP_DEST(d, 3 * m, a->f | MP_UNDEF);
+    s = mpalloc(d->a, 5 * m);
+    mpx_ksqr(d->v, d->vl, a->v, a->vl, s, s + 5 * m);
+    mpfree(d->a, s);
+  } else {
+    MP_DEST(d, 2 * m + 2, a->f | MP_UNDEF);
+    mpx_usqr(d->v, d->vl, a->v, a->vl);
+  }
+  d->f = a->f & MP_BURN;
+  MP_SHRINK(d);
+  MP_DROP(a);
+  return (d);
+}
+
+/* --- @mp_div@ --- *
+ *
+ * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
+ *             @mp *a, *b@ = sources
+ *
+ * Use:                Calculates the quotient and remainder when @a@ is divided by
+ *             @b@.  The destinations @*qq@ and @*rr@ must be distinct.
+ *             Either of @qq@ or @rr@ may be null to indicate that the
+ *             result is irrelevant.  (Discarding both results is silly.)
+ *             There is a performance advantage if @a == *rr@.
+ *
+ *             The behaviour when @a@ and @b@ have the same sign is
+ *             straightforward.  When the signs differ, this implementation
+ *             chooses @r@ to have the same sign as @b@, rather than the
+ *             more normal choice that the remainder has the same sign as
+ *             the dividend.  This makes modular arithmetic a little more
+ *             straightforward.
+ */
+
+void mp_div(mp **qq, mp **rr, mp *a, mp *b)
+ {
+  mp *r = rr ? *rr : MP_NEW;
+  mp *q = qq ? *qq : MP_NEW;
+  mpw *sv, *svl;
+
+  /* --- Set the remainder up right --- *
+   *
+   * Just in case the divisor is larger, be able to cope with this.  It's not
+   * important in @mpx_udiv@, but it is here because of the sign correction.
+   */
+
+  b = MP_COPY(b);
+  a = MP_COPY(a);
+  if (r)
+    MP_DROP(r);
+  r = a;
+  MP_DEST(r, MAX(MP_LEN(a), MP_LEN(b)) + 2, a->f | b->f);
+
+  /* --- Fix up the quotient too --- */
+
+  r = MP_COPY(r);
+  MP_DEST(q, MP_LEN(r), r->f | MP_UNDEF);
+  MP_DROP(r);
+
+  /* --- Set up some temporary workspace --- */
+
+  {
+    size_t rq = MP_LEN(b) + 1;
+    sv = mpalloc(r->a, rq);
+    svl = sv + rq;
+  }
+
+  /* --- Perform the calculation --- */
+
+  mpx_udiv(q->v, q->vl, r->v, r->vl, b->v, b->vl, sv, svl);
+
+  /* --- Sort out the sign of the results --- *
+   *
+   * If the signs of the arguments differ, and the remainder is nonzero, I
+   * must add one to the absolute value of the quotient and subtract the
+   * remainder from @b@.
+   */
+
+  q->f = ((r->f | b->f) & MP_BURN) | ((r->f ^ b->f) & MP_NEG);
+  if (MP_NEGP(q)) {
+    mpw *v;
+    for (v = r->v; v < r->vl; v++) {
+      if (*v) {
+       MPX_UADDN(q->v, q->vl, 1);
+       mpx_usub(r->v, r->vl, b->v, b->vl, r->v, r->vl);
+       break;
+      }
+    }
+  }
+
+  r->f = ((r->f | b->f) & MP_BURN) | (b->f & MP_NEG);
+
+  /* --- Store the return values --- */
+
+  mpfree(r->a, sv);
+  MP_DROP(b);
+
+  if (!qq)
+    MP_DROP(q);
+  else {
+    MP_SHRINK(q);
+    *qq = q;
+  }
+
+  if (!rr)
+    MP_DROP(r);
+  else {
+    MP_SHRINK(r);
+    *rr = r;
+  }
+}
+
+/* --- @mp_odd@ --- *
+ *
+ * Arguments:  @mp *d@ = pointer to destination integer
+ *             @mp *m@ = pointer to source integer
+ *             @size_t *s@ = where to store the power of 2
+ *
+ * Returns:    An odd integer integer %$t$% such that %$m = 2^s t$%.
+ *
+ * Use:                Computes a power of two and an odd integer which, when
+ *             multiplied, give a specified result.  This sort of thing is
+ *             useful in number theory quite often.
+ */
+
+mp *mp_odd(mp *d, mp *m, size_t *s)
+{
+  size_t ss = 0;
+  const mpw *v, *vl;
+
+  v = m->v;
+  vl = m->vl;
+  for (; !*v && v < vl; v++)
+    ss += MPW_BITS;
+  if (v >= vl)
+    ss = 0;
+  else {
+    mpw x = *v;
+    unsigned z = MPW_P2;
+    mpw mask = ((mpw)1 << z) - 1;
+
+    while (z) {
+      if (!(x & mask)) {
+       x >>= z;
+       ss += z;
+      }
+      z >>= 1;
+      mask >>= z;
+    }
+  }
+
+  *s = ss;
+  return (mp_lsr(d, m, ss));
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b)
+{
+  if (!MP_EQ(expect, result)) {
+    fprintf(stderr, "\n*** %s failed", op);
+    fputs("\n*** a     = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\n*** b     = ", stderr); mp_writefile(b, stderr, 10);
+    fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 10);
+    fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 10);
+    fputc('\n', stderr);
+    return (0);
+  }
+  return (1);
+}
+
+#define RIG(name, op)                                                  \
+  static int t##name(dstr *v)                                          \
+  {                                                                    \
+    mp *a = *(mp **)v[0].buf;                                          \
+    mpw n = *(int *)v[1].buf;                                          \
+    mp b;                                                              \
+    mp *r = *(mp **)v[2].buf;                                          \
+    mp *c = op(MP_NEW, a, n);                                          \
+    int ok;                                                            \
+    mp_build(&b, &n, &n + 1);                                          \
+    ok = verify(#name, r, c, a, &b);                                   \
+    mp_drop(a); mp_drop(c); mp_drop(r);                                        \
+    assert(mparena_count(MPARENA_GLOBAL) == 0);                                \
+    return (ok);                                                       \
+  }
+
+RIG(lsl, mp_lsl)
+RIG(lsr, mp_lsr)
+RIG(lsl2c, mp_lsl2c)
+RIG(lsr2c, mp_lsr2c)
+
+#undef RIG
+
+#define RIG(name, op)                                                  \
+  static int t##name(dstr *v)                                          \
+  {                                                                    \
+    mp *a = *(mp **)v[0].buf;                                          \
+    mp *b = *(mp **)v[1].buf;                                          \
+    mp *r = *(mp **)v[2].buf;                                          \
+    mp *c = op(MP_NEW, a, b);                                          \
+    int ok = verify(#name, r, c, a, b);                                        \
+    mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(r);                    \
+    assert(mparena_count(MPARENA_GLOBAL) == 0);                                \
+    return (ok);                                                       \
+  }
+
+RIG(add, mp_add)
+RIG(sub, mp_sub)
+RIG(mul, mp_mul)
+RIG(exp, mp_exp)
+
+#undef RIG
+
+static int tdiv(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  mp *b = *(mp **)v[1].buf;
+  mp *q = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *c = MP_NEW, *d = MP_NEW;
+  int ok = 1;
+  mp_div(&c, &d, a, b);
+  ok &= verify("div(quotient)", q, c, a, b);
+  ok &= verify("div(remainder)", r, d, a, b);
+  mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(d); mp_drop(r); mp_drop(q);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tbin(dstr *v)
+{
+  static mp *(*fn[])(mp *, mp *, mp *) = {
+#define DO(string) mp_bit##string##2c,
+MPX_DOBIN(DO)
+#undef DO
+  };
+  int ok = 1;
+  unsigned op = 0;
+  mp *a = *(mp **)v[1].buf;
+  mp *b = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *c;
+
+  if (strcmp(v[0].buf, "and") == 0) op = 1;
+  else if (strcmp(v[0].buf, "or") == 0) op = 7;
+  else if (strcmp(v[0].buf, "nand") == 0) op = 14;
+  else if (strcmp(v[0].buf, "nor") == 0) op = 8;
+  else if (strcmp(v[0].buf, "xor") == 0) op = 6;
+  else {
+    char *p = v[0].buf;
+    while (*p) {
+      op <<= 1;
+      if (*p++ == '1')
+       op |= 1;
+    }
+  }
+
+  c = fn[op](MP_NEW, a, b);
+  ok = verify(v[0].buf, r, c, a, b);
+  mp_drop(a); mp_drop(b); mp_drop(r); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tset(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  unsigned long n = *(unsigned long *)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *c;
+  int ok = 1;
+
+  c = mp_setbit2c(MP_NEW, a, n);
+  if (!MP_EQ(c, r)) {
+    ok = 0;
+    fprintf(stderr, "\n***setbit (set) failed");
+    fputs("\n*** a  = ", stderr); mp_writefile(a, stderr, 16);
+    fprintf(stderr, "\n*** n  = %lu", n);
+    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 16);
+    fputs("\n*** c = ", stderr); mp_writefile(c, stderr, 16);
+    fputc('\n', stderr);
+  }
+  if (!mp_testbit2c(r, n)) {
+    ok = 0;
+    fprintf(stderr, "\n***setbit (test) failed");
+    fprintf(stderr, "\n*** n  = %lu", n);
+    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 16);
+    fputc('\n', stderr);
+  }
+  mp_drop(a);
+  mp_drop(r);
+  mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tclr(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  unsigned long n = *(unsigned long *)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *c;
+  int ok = 1;
+
+  c = mp_clearbit2c(MP_NEW, a, n);
+  if (!MP_EQ(c, r)) {
+    ok = 0;
+    fprintf(stderr, "\n***clrbit (set) failed");
+    fputs("\n*** a  = ", stderr); mp_writefile(a, stderr, 16);
+    fprintf(stderr, "\n*** n  = %lu", n);
+    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 16);
+    fputs("\n*** c = ", stderr); mp_writefile(c, stderr, 16);
+    fputc('\n', stderr);
+  }
+  if (mp_testbit2c(r, n)) {
+    ok = 0;
+    fprintf(stderr, "\n***clrbit (test) failed");
+    fprintf(stderr, "\n*** n  = %lu", n);
+    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 16);
+    fputc('\n', stderr);
+  }
+  mp_drop(a);
+  mp_drop(c);
+  mp_drop(r);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tneg(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  mp *r = *(mp **)v[1].buf;
+  int ok = 1;
+  mp *n = mp_neg(MP_NEW, a);
+  if (!MP_EQ(r, n)) {
+    ok = 0;
+    fprintf(stderr, "\n*** neg failed\n");
+    fputs("\n*** a  = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\n*** n  = ", stderr); mp_writefile(n, stderr, 10);
+    fputc('\n', stderr);
+  }
+  mp_drop(n);
+  n = mp_neg(a, a);
+  if (!MP_EQ(r, n)) {
+    ok = 0;
+    fprintf(stderr, "\n*** neg failed\n");
+    fputs("\n*** a* = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\n*** n  = ", stderr); mp_writefile(n, stderr, 10);
+    fputc('\n', stderr);
+  }
+  mp_drop(a);
+  mp_drop(r);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int todd(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  size_t rs = *(uint32 *)v[1].buf;
+  mp *rt = *(mp **)v[2].buf;
+  int ok = 1;
+  mp *t;
+  size_t s;
+  t = mp_odd(MP_NEW, a, &s);
+  if (s != rs || !MP_EQ(t, rt)) {
+    ok = 0;
+    fprintf(stderr, "\n*** odd failed");
+    fputs("\n*** a  = ", stderr); mp_writefile(a, stderr, 10);
+    fprintf(stderr, "\n*** s  = %lu", (unsigned long)s);
+    fputs("\n*** t  = ", stderr); mp_writefile(t, stderr, 10);
+    fprintf(stderr, "\n*** rs = %lu", (unsigned long)rs);
+    fputs("\n*** rt = ", stderr); mp_writefile(rt, stderr, 10);
+    fputc('\n', stderr);
+  }
+  mp_drop(a);
+  mp_drop(rt);
+  mp_drop(t);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "lsl", tlsl, { &type_mp, &type_int, &type_mp, 0 } },
+  { "lsr", tlsr, { &type_mp, &type_int, &type_mp, 0 } },
+  { "lsl2c", tlsl2c, { &type_mp, &type_int, &type_mp, 0 } },
+  { "lsr2c", tlsr2c, { &type_mp, &type_int, &type_mp, 0 } },
+  { "setbit", tset, { &type_mp, &type_ulong, &type_mp, 0 } },
+  { "clrbit", tclr, { &type_mp, &type_ulong, &type_mp, 0 } },
+  { "add", tadd, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "sub", tsub, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "bin2c", tbin, { &type_string, &type_mp, &type_mp, &type_mp, 0 } },
+  { "odd", todd, { &type_mp, &type_uint32, &type_mp, 0 } },
+  { "neg", tneg, { &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } },
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mp");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-const.c b/math/mp-const.c
new file mode 100644 (file)
index 0000000..b35a0e6
--- /dev/null
@@ -0,0 +1,49 @@
+/* -*-c-*-
+ *
+ * Useful multiprecision constants
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+static mpw mpw_const[] = { 1, 2, 3, 4, 5, 10, 256 };
+
+mp mp_const[] = {
+  { &mpw_const[0], &mpw_const[0], 0, 0, MP_CONST, 0 },
+  { &mpw_const[0], &mpw_const[0] + 1, 1, 0, MP_CONST, 0 },
+  { &mpw_const[1], &mpw_const[1] + 1, 1, 0, MP_CONST, 0 },
+  { &mpw_const[2], &mpw_const[2] + 1, 1, 0, MP_CONST, 0 },
+  { &mpw_const[3], &mpw_const[3] + 1, 1, 0, MP_CONST, 0 },
+  { &mpw_const[4], &mpw_const[4] + 1, 1, 0, MP_CONST, 0 },
+  { &mpw_const[5], &mpw_const[5] + 1, 1, 0, MP_CONST, 0 },
+  { &mpw_const[6], &mpw_const[6] + 1, 1, 0, MP_CONST, 0 },
+  { &mpw_const[0], &mpw_const[0] + 1, 1, 0, MP_CONST | MP_NEG, 0 },
+  { 0, mpw_const, 1, 0, MP_CONST | MP_BURN, 0 },
+};
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-exp.c b/math/mp-exp.c
new file mode 100644 (file)
index 0000000..9ef2fa0
--- /dev/null
@@ -0,0 +1,65 @@
+/* -*-c-*-
+ *
+ * Exponentiation for large integers
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+
+#include "mp.h"
+#include "mp-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_exp@ --- *
+ *
+ * Arguments:  @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e$%.
+ */
+
+mp *mp_exp(mp *d, mp *a, mp *e)
+{
+  mp *x = MP_ONE;
+  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
+  assert(!MP_NEGP(e));
+
+  MP_COPY(a);
+  if (MP_ZEROP(e))
+    ;
+  else if (MP_LEN(e) < EXP_THRESH)
+    EXP_SIMPLE(x, a, e);
+  else
+    EXP_WINDOW(x, a, e);
+  mp_drop(d);
+  mp_drop(spare);
+  mp_drop(a);
+  return (x);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-exp.h b/math/mp-exp.h
new file mode 100644 (file)
index 0000000..d0fce30
--- /dev/null
@@ -0,0 +1,67 @@
+/* -*-c-*-
+ *
+ * Exponentiation for large integers
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_MP_EXP_H
+#define CATACOMB_MP_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentiation ----------------------------------------------------*/
+
+#define EXP_TYPE mp *
+
+#define EXP_COPY(d, x) d = MP_COPY(x)
+#define EXP_DROP(x) MP_DROP(x)
+
+#define EXP_MUL(a, x) do {                                             \
+  mp *t = mp_mul(spare, a, x);                                         \
+  spare = a;                                                           \
+  a = t;                                                               \
+} while (0)
+
+#define EXP_SQR(a) do {                                                        \
+  mp *t = mp_sqr(spare, a);                                            \
+  spare = a;                                                           \
+  a = t;                                                               \
+} while (0)
+
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) d = mp_mul(MP_NEW, x, y)
+#define EXP_SETSQR(d, x) d = mp_sqr(MP_NEW, x)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mp-fibonacci.c b/math/mp-fibonacci.c
new file mode 100644 (file)
index 0000000..9b37ebf
--- /dev/null
@@ -0,0 +1,271 @@
+/* -*-c-*-
+ *
+ * Compute the %$n$%th Fibonacci number
+ *
+ * (c) 2013 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpint.h"
+
+/*----- About the algorithm -----------------------------------------------*
+ *
+ * Define %$F_0 = 0$% and %$F_1 = 1$%, and %$F_{k+1} = F_k + F_{k-1}$% for
+ * all %$k$%.  (This defines %$F_k$% for negative %$k$% too, by
+ * %$F_{k-1} = F_{k+1} - F_k$%; in particular, %$F_{-1} = 1$% and
+ * %$F_{-2} = -1$%.)  We say that %$F_k$% is the %$k$%th Fibonacci number.
+ *
+ * We work in the ring %$\ZZ[t]/(t^2 - t -1)$%.  Every residue class in this
+ * ring contains a unique representative with degree at most 1.  I claim that
+ * %$t^k = F_k t + F_{k-1}$% for all %$k$%.  Certainly %$t = F_1 t + F_0$%.
+ * Note that %$t (F_{-1} t + F_{-2}) = t (t - 1) = t^2 - t = 1$%, so the
+ * claim holds for %$k = -1$%.  Suppose, inductively, that it holds for
+ * %$k$%; then %$t^{k+1} = t \cdot t^k = F_k t^2 + F_{k-1} t = {}$%
+ * %$(F_k + F_{k-1}) t + F_k = F_{k+1} t + F_k$%; and %$t^{k-1} = {}$%
+ * %$t^{-1} t^k = (t - 1) t^k = t^{k+1} - t^k = {}$%
+ * %$(F_{k+1} - F_k) t + (F_k - F_{k-1}) = F_{k-1} t + F_{k-2}$%, proving the
+ * claim.
+ *
+ * So we can compute Fibonacci numbers by exponentiating in this ring.
+ * Squaring and multiplication work like this.
+ *
+ *   * Square: %$(a t + b)^2 = a^2 t^2 + 2 a b t + b^2 = {}$%
+ *     %$(a^2 + 2 a b) t + (a^2 + b^2)$%
+ *
+ *   * Multiply: %$(a t + b)(c t + d) = a c t^2 + (a d + b c) t + b d = {}$%
+ *     %$(a c + a d + b c) t + (a c + b d)$%.
+ */
+
+/*----- Exponentiation machinery ------------------------------------------*/
+
+/* --- @struct fib@ --- *
+ *
+ * A simple structure tracking polynomial coefficients.
+ */
+
+struct fib {
+  int n;                               /* Exponent for this entry */
+  mp *a, *b;                           /* Coefficients: %$a t + b$% */
+};
+
+#define MAX 100                                /* Saturation bounds for exponent */
+#define MIN -100
+
+/* --- @CLAMP@ --- *
+ *
+ * Clamp @n@ within the upper and lower bounds.
+ */
+
+#define CLAMP(n) do {                                                  \
+  if (n > MAX) n = MAX; else if (n < MIN) n = MIN;                     \
+} while (0)
+
+/* --- Basic structure maintenance functions --- */
+
+static void fib_init(struct fib *f)
+  { f->a = f->b = MP_NEW; }
+
+static void fib_drop(struct fib *f)
+  { if (f->a) MP_DROP(f->a); if (f->b) MP_DROP(f->b); }
+
+static void fib_copy(struct fib *d, struct fib *x)
+  { d->n = x->n; d->a = MP_COPY(x->a); d->b = MP_COPY(x->b); }
+
+/* --- @fib_sqr@ --- *
+ *
+ * Arguments:  @struct fib *d@ = destination structure
+ *             @struct fib *x@ = operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @d@ to the square of @x@.
+ */
+
+static void fib_sqr(struct fib *d, struct fib *x)
+{
+  mp *aa, *t;
+
+  /* --- Special case: if @x@ is the identity then just copy --- */
+
+  if (!x->n) {
+    if (d != x) { fib_drop(d); fib_copy(d, x); }
+    return;
+  }
+
+  /* --- Compute the result --- */
+
+  aa = mp_sqr(MP_NEW, x->a);           /* %$a^2$% */
+
+  t = mp_mul(d->a, x->a, x->b);                /* %$t = a b$% */
+  t = mp_lsl(t, t, 1);                 /* %$t = 2 a b$% */
+  d->a = mp_add(t, t, aa);             /* %$a' = a^2 + 2 a b$% */
+
+  t = mp_sqr(d->b, x->b);              /* %$t = b^2$% */
+  d->b = mp_add(t, t, aa);             /* %$b' = a^2 + b^2$% */
+
+  /* --- Sort out the exponent on the result --- */
+
+  d->n = 2*x->n; CLAMP(d->n);
+
+  /* --- Done --- */
+
+  MP_DROP(aa);
+}
+
+/* --- @fib_mul@ --- *
+ *
+ * Arguments:  @struct fib *d@ = destination structure
+ *             @struct fib *x, *y@ = operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @d@ to the product of @x@ and @y@.
+ */
+
+static void fib_mul(struct fib *d, struct fib *x, struct fib *y)
+{
+  mp *t, *u, *bd;
+
+  /* --- Lots of special cases for low exponents --- */
+
+  if (y->n == 0) {
+  copy_x:
+    if (d != x) { fib_drop(d); fib_copy(d, x); }
+    return;
+  } else if (x->n == 0) { x = y; goto copy_x; }
+  else if (y->n == -1) {
+  dec_x:
+    t = mp_sub(d->a, x->a, x->b);
+    d->a = MP_COPY(x->b); if (d->b) MP_DROP(d->b); d->b = t;
+    d->n = x->n - 1; CLAMP(d->n);
+    return;
+  } else if (y->n == +1) {
+  inc_x:
+    t = mp_add(d->b, x->a, x->b);
+    d->b = MP_COPY(x->a); if (d->a) MP_DROP(d->a); d->a = t;
+    d->n = x->n + 1; CLAMP(d->n);
+    return;
+  } else if (x->n == -1) { x = y; goto dec_x; }
+  else if (x->n == +1) { x = y; goto inc_x; }
+
+  /* --- Compute the result --- */
+
+  bd = mp_mul(MP_NEW, x->b, y->b);     /* %$b d$% */
+  t = mp_add(MP_NEW, x->a, x->b);      /* %$t = a + b$% */
+  u = mp_add(MP_NEW, y->a, y->b);      /* %$u = c + d$% */
+  t = mp_mul(t, t, u);                 /* %$t = (a + b)(c + d)$% */
+  u = mp_mul(u, x->a, y->a);           /* %$u = a c$% */
+
+  d->a = mp_sub(d->a, t, bd);          /* %$a' = a c + a d + b c$% */
+  d->b = mp_add(d->b, u, bd);          /* %$b' = a c + b d$% */
+
+  /* --- Sort out the exponent on the result --- */
+
+  if (x->n == MIN || x->n == MAX) d->n = x->n;
+  else if (y->n == MIN || y->n == MAX) d->n = y->n;
+  else { d->n = x->n + y->n; CLAMP(d->n); }
+
+  /* --- Done --- */
+
+  MP_DROP(bd); MP_DROP(t); MP_DROP(u);
+}
+
+/* --- Exponentiation --- */
+
+#define EXP_TYPE                       struct fib
+#define EXP_COPY(d, x)                 fib_copy(&d, &x)
+#define EXP_DROP(x)                    fib_drop(&x)
+#define EXP_FIX(d)
+
+#define EXP_SQR(x)                     fib_sqr(&x, &x)
+#define EXP_MUL(x, y)                  fib_mul(&x, &x, &y)
+#define EXP_SETSQR(d, x)               fib_init(&d); fib_sqr(&d, &x)
+#define EXP_SETMUL(d, x, y)            fib_init(&d); fib_mul(&d, &x, &y)
+
+#include "exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_fibonacci@ --- *
+ *
+ * Arguments:  @long n@ = index desired (may be negative)
+ *
+ * Returns:    The %$n$%th Fibonacci number.
+ */
+
+mp *mp_fibonacci(long n)
+{
+  struct fib d, g;
+  mp *nn;
+
+  d.n = 0; d.a = MP_ZERO; d.b = MP_ONE;
+  if (n >= 0) { g.n = 1; g.a = MP_ONE; g.b = MP_ZERO; }
+  else { g.n = -1; g.a = MP_ONE; g.b = MP_MONE; n = -n; }
+  nn = mp_fromlong(MP_NEW, n);
+
+  EXP_WINDOW(d, g, nn);
+
+  MP_DROP(nn); fib_drop(&g); MP_DROP(d.b);
+  return (d.a);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int vfib(dstr *v)
+{
+  long x = *(long *)v[0].buf;
+  mp *fx = *(mp **)v[1].buf;
+  mp *y = mp_fibonacci(x);
+  int ok = 1;
+  if (!MP_EQ(fx, y)) {
+    fprintf(stderr, "fibonacci failed\n");
+    MP_FPRINTF(stderr, (stderr, "fib(%ld) = ", x), fx);
+    MP_EPRINT("result", y);
+    ok = 0;
+  }
+  mp_drop(fx);
+  mp_drop(y);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "fibonacci", vfib, { &type_long, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, tests, SRCDIR "/t/mp");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from mp-fibonacci.h
rename to math/mp-fibonacci.h
diff --git a/math/mp-gcd.c b/math/mp-gcd.c
new file mode 100644 (file)
index 0000000..6e059e3
--- /dev/null
@@ -0,0 +1,345 @@
+/* -*-c-*-
+ *
+ * Extended GCD calculation
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_gcd@ --- *
+ *
+ * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
+ *             @mp *a, *b@ = sources (must be nonzero)
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
+ *             @ax + by = gcd(a, b)@.  This is useful for computing modular
+ *             inverses.
+ */
+
+void mp_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b)
+{
+  mp *x = MP_ONE, *X = MP_ZERO;
+  mp *y = MP_ZERO, *Y = MP_ONE;
+  mp *u, *v;
+  mp *q = MP_NEW, *t, *spare = MP_NEW;
+  unsigned f = 0;
+
+#define f_swap 1u
+#define f_aneg 2u
+#define f_bneg 4u
+#define f_ext 8u
+
+  /* --- Sort out some initial flags --- */
+
+  if (xx || yy)
+    f |= f_ext;
+
+  if (MP_NEGP(a))
+    f |= f_aneg;
+  if (MP_NEGP(b))
+    f |= f_bneg;
+
+  /* --- Ensure that @a@ is larger than @b@ --- *
+   *
+   * Use absolute values here!
+   */
+
+  if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) {
+    t = a; a = b; b = t;
+    f |= f_swap;
+  }
+
+  /* --- Check for zeroness --- */
+
+  if (MP_ZEROP(b)) {
+
+    /* --- Store %$|a|$% as the GCD --- */
+
+    if (gcd) {
+      if (*gcd) MP_DROP(*gcd);
+      a = MP_COPY(a);
+      if (MP_NEGP(a)) {
+       MP_SPLIT(a);
+       a->f &= ~MP_NEG;
+       f |= f_aneg;
+      }
+      *gcd = a;
+    }
+
+    /* --- Store %$1$% and %$0$% in the appropriate bins --- */
+
+    if (f & f_ext) {
+      if (f & f_swap) {
+       mp **tt = xx; xx = yy; yy = tt;
+      }
+      if (xx) {
+       if (*xx) MP_DROP(*xx);
+       if (MP_EQ(a, MP_ZERO))
+         *xx = MP_ZERO;
+       else if (f & f_aneg)
+         *xx = MP_MONE;
+       else
+         *xx = MP_ONE;
+      }
+      if (yy) {
+       if (*yy) MP_DROP(*yy);
+       *yy = MP_ZERO;
+      }
+    }
+    return;
+  }
+
+  /* --- Force the signs on the arguments and take copies --- */
+
+  a = MP_COPY(a);
+  b = MP_COPY(b);
+
+  MP_SPLIT(a); a->f &= ~MP_NEG;
+  MP_SPLIT(b); b->f &= ~MP_NEG;
+
+  u = MP_COPY(a);
+  v = MP_COPY(b);
+
+  /* --- Main extended Euclidean algorithm --- */
+
+  while (!MP_ZEROP(v)) {
+    mp_div(&q, &u, u, v);
+    if (f & f_ext) {
+      t = mp_mul(spare, X, q);
+      t = mp_sub(t, x, t);
+      spare = x; x = X; X = t;
+      t = mp_mul(spare, Y, q);
+      t = mp_sub(t, y, t);
+      spare = y; y = Y; Y = t;
+    }
+    t = u; u = v; v = t;
+  }
+
+  MP_DROP(q); if (spare) MP_DROP(spare);
+  if (!gcd)
+    MP_DROP(u);
+  else {
+    if (*gcd) MP_DROP(*gcd);
+    u->f &= ~MP_NEG;
+    *gcd = u;
+  }
+
+  /* --- Perform a little normalization --- *
+   *
+   * Ensure that the coefficient returned is positive, if there is only one.
+   * If there are two, favour @y@.  Of course, if the original arguments were
+   * negative then I'll need to twiddle their signs as well.
+   */
+
+  if (f & f_ext) {
+
+    /* --- If @a@ and @b@ got swapped, swap the coefficients back --- */
+
+    if (f & f_swap) {
+      t = x; x = y; y = t;
+      t = a; a = b; b = t;
+    }
+
+    /* --- Sort out the signs --- *
+     *
+     * Note that %$ax + by = a(x - b) + b(y + a)$%.
+     *
+     * This is currently bodgy.  It needs sorting out at some time.
+     */
+
+    if (yy) {
+      if (MP_NEGP(y)) {
+       do {
+         y = mp_add(y, y, a);
+         x = mp_sub(x, x, b);
+       } while (MP_NEGP(y));
+      } else {
+       while (MP_CMP(y, >=, a)) {
+         y = mp_sub(y, y, a);
+         x = mp_add(x, x, b);
+       }
+      }
+    } else {
+      if (MP_NEGP(x)) {
+       do
+         x = mp_add(x, x, b);
+       while (MP_NEGP(x));
+      } else {
+       while (MP_CMP(x, >=, b))
+         x = mp_sub(x, x, b);
+      }
+    }
+
+    /* --- Twiddle the signs --- */
+
+    if (f & f_aneg)
+      x->f ^= MP_NEG;
+    if (f & f_bneg)
+      y->f ^= MP_NEG;
+
+    /* --- Store the results --- */
+
+    if (!xx)
+      MP_DROP(x);
+    else {
+      if (*xx) MP_DROP(*xx);
+      *xx = x;
+    }
+
+    if (!yy)
+      MP_DROP(y);
+    else {
+      if (*yy) MP_DROP(*yy);
+      *yy = y;
+    }
+  }
+
+  MP_DROP(v);
+  MP_DROP(X); MP_DROP(Y);
+  MP_DROP(a); MP_DROP(b);
+}
+
+/* -- @mp_modinv@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *x@ = argument
+ *             @mp *p@ = modulus
+ *
+ * Returns:    The inverse %$x^{-1} \bmod p$%.
+ *
+ * Use:                Computes a modular inverse.    An assertion fails if %$p$%
+ *             has no inverse.
+ */
+
+mp *mp_modinv(mp *d, mp *x, mp *p)
+{
+  mp *g = MP_NEW;
+  mp_gcd(&g, 0, &d, p, x);
+  assert(MP_EQ(g, MP_ONE));
+  mp_drop(g);
+  return (d);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int modinv(dstr *v)
+{
+  int ok = 1;
+  mp *x = *(mp **)v[0].buf;
+  mp *m = *(mp **)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+
+  mp *y = mp_modinv(MP_NEW, x, m);
+  if (!MP_EQ(y, r)) {
+    fputs("\n*** mp_modinv failed", stderr);
+    fputs("\nx     = ", stderr); mp_writefile(x, stderr, 10);
+    fputs("\nm     = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\nexpect = ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\nresult = ", stderr); mp_writefile(y, stderr, 10);
+    ok = 0;
+  }
+  MP_DROP(x); MP_DROP(m); MP_DROP(r); MP_DROP(y);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int gcd(dstr *v)
+{
+  int ok = 1;
+  mp *a = *(mp **)v[0].buf;
+  mp *b = *(mp **)v[1].buf;
+  mp *g = *(mp **)v[2].buf;
+  mp *x = *(mp **)v[3].buf;
+  mp *y = *(mp **)v[4].buf;
+
+  mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW;
+  mp_gcd(&gg, &xx, &yy, a, b);
+  if (!MP_EQ(x, xx)) {
+    fputs("\n*** mp_gcd(x) failed", stderr);
+    fputs("\na     = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 10);
+    fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 10);
+    fputs("\nresult = ", stderr); mp_writefile(xx, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+  if (!MP_EQ(y, yy)) {
+    fputs("\n*** mp_gcd(y) failed", stderr);
+    fputs("\na     = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 10);
+    fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 10);
+    fputs("\nresult = ", stderr); mp_writefile(yy, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  if (!ok) {
+    mp *ax = mp_mul(MP_NEW, a, xx);
+    mp *by = mp_mul(MP_NEW, b, yy);
+    ax = mp_add(ax, ax, by);
+    if (MP_EQ(ax, gg))
+      fputs("\n*** (Alternative result found.)\n", stderr);
+    MP_DROP(ax);
+    MP_DROP(by);
+  }
+
+  if (!MP_EQ(g, gg)) {
+    fputs("\n*** mp_gcd(gcd) failed", stderr);
+    fputs("\na     = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 10);
+    fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 10);
+    fputs("\nresult = ", stderr); mp_writefile(gg, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+  MP_DROP(a); MP_DROP(b); MP_DROP(g); MP_DROP(x); MP_DROP(y);
+  MP_DROP(gg); MP_DROP(xx); MP_DROP(yy);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "gcd", gcd, { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { "modinv", modinv, { &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mp");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-io.c b/math/mp-io.c
new file mode 100644 (file)
index 0000000..d7046f3
--- /dev/null
@@ -0,0 +1,279 @@
+/* -*-c-*-
+ *
+ * Loading and storing of multiprecision integers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_octets@ --- *
+ *
+ * Arguments:  @const mp *m@ = a multiprecision integer
+ *
+ * Returns:    The number of octets required to represent @m@.
+ *
+ * Use:                Calculates the external storage required for a multiprecision
+ *             integer.
+ */
+
+size_t mp_octets(const mp *m)
+{
+  size_t sz;
+  MPX_OCTETS(sz, m->v, m->vl);
+  return (sz);
+}
+
+/* --- @mp_octets2c@ --- *
+ *
+ * Arguments:  @const mp *m@ = a multiprecision integer
+ *
+ * Returns:    The number of octets required to represent @m@.
+ *
+ * Use:                Calculates the external storage required for a multiprecision
+ *             integer represented as two's complement.
+ */
+
+size_t mp_octets2c(const mp *m)
+{
+  size_t sz;
+  MPX_OCTETS2C(sz, m->v, m->vl);
+  return (sz);
+}
+
+/* --- @mp_bits@ --- *
+ *
+ * Arguments:  @const mp *m@ = a multiprecision integer
+ *
+ * Returns:    The number of bits required to represent @m@.
+ *
+ * Use:                Calculates the external storage required for a multiprecision
+ *             integer.
+ */
+
+unsigned long mp_bits(const mp *m)
+{
+  unsigned long bits;
+  MPX_BITS(bits, m->v, m->vl);
+  return (bits);
+}
+
+/* --- @mp_loadl@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @const void *pv@ = pointer to source data
+ *             @size_t sz@ = size of the source data
+ *
+ * Returns:    Resulting multiprecision number.
+ *
+ * Use:                Loads a multiprecision number from an array of octets.  The
+ *             first byte in the array is the least significant.  More
+ *             formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$%
+ *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
+ */
+
+mp *mp_loadl(mp *d, const void *pv, size_t sz)
+{
+  MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
+  mpx_loadl(d->v, d->vl, pv, sz);
+  d->f &= ~(MP_UNDEF | MP_NEG);
+  mp_shrink(d);
+  return (d);
+}
+
+/* --- @mp_storel@ --- *
+ *
+ * Arguments:  @const mp *m@ = source
+ *             @void *pv@ = pointer to output array
+ *             @size_t sz@ = size of the output array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a multiprecision number in an array of octets.  The
+ *             first byte in the array is the least significant.  If the
+ *             array is too small to represent the number, high-order bits
+ *             are truncated; if the array is too large, high order bytes
+ *             are filled with zeros.  More formally, if the number is
+ *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
+ *             then the array is %$b_0, b_1, \ldots, b_{n-1}$%.
+ */
+
+void mp_storel(const mp *m, void *pv, size_t sz)
+{
+  mpx_storel(m->v, m->vl, pv, sz);
+}
+
+/* --- @mp_loadb@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @const void *pv@ = pointer to source data
+ *             @size_t sz@ = size of the source data
+ *
+ * Returns:    Resulting multiprecision number.
+ *
+ * Use:                Loads a multiprecision number from an array of octets.  The
+ *             last byte in the array is the least significant.  More
+ *             formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$%
+ *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
+ */
+
+mp *mp_loadb(mp *d, const void *pv, size_t sz)
+{
+  MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
+  mpx_loadb(d->v, d->vl, pv, sz);
+  d->f &= ~(MP_UNDEF | MP_NEG);
+  mp_shrink(d);
+  return (d);
+}
+
+/* --- @mp_storeb@ --- *
+ *
+ * Arguments:  @const mp *m@ = source
+ *             @void *pv@ = pointer to output array
+ *             @size_t sz@ = size of the output array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a multiprecision number in an array of octets.  The
+ *             last byte in the array is the least significant.  If the
+ *             array is too small to represent the number, high-order bits
+ *             are truncated; if the array is too large, high order bytes
+ *             are filled with zeros.  More formally, if the number is
+ *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
+ *             then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%.
+ */
+
+void mp_storeb(const mp *m, void *pv, size_t sz)
+{
+  mpx_storeb(m->v, m->vl, pv, sz);
+}
+
+/* --- @mp_loadl2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @const void *pv@ = pointer to source data
+ *             @size_t sz@ = size of the source data
+ *
+ * Returns:    Resulting multiprecision number.
+ *
+ * Use:                Loads a multiprecision number from an array of octets as
+ *             two's complement.  The first byte in the array is the least
+ *             significant.
+ */
+
+mp *mp_loadl2c(mp *d, const void *pv, size_t sz)
+{
+  const octet *ov = pv;
+  MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
+  if (!sz || !(ov[sz - 1] & 0x80)) {
+    mpx_loadl(d->v, d->vl, pv, sz);
+    d->f &= ~MP_NEG;
+  } else {
+    mpx_loadl2cn(d->v, d->vl, pv, sz);
+    d->f |= MP_NEG;
+  }
+  d->f &= ~MP_UNDEF;
+  mp_shrink(d);
+  return (d);
+}
+
+/* --- @mp_storel2c@ --- *
+ *
+ * Arguments:  @const mp *m@ = source
+ *             @void *pv@ = pointer to output array
+ *             @size_t sz@ = size of the output array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a multiprecision number in an array of octets as two's
+ *             complement.  The first byte in the array is the least
+ *             significant.  If the array is too small to represent the
+ *             number, high-order bits are truncated; if the array is too
+ *             large, high order bytes are sign-extended.
+ */
+
+void mp_storel2c(const mp *m, void *pv, size_t sz)
+{
+  if (MP_NEGP(m))
+    mpx_storel2cn(m->v, m->vl, pv, sz);
+  else
+    mpx_storel(m->v, m->vl, pv, sz);
+}
+
+/* --- @mp_loadb2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @const void *pv@ = pointer to source data
+ *             @size_t sz@ = size of the source data
+ *
+ * Returns:    Resulting multiprecision number.
+ *
+ * Use:                Loads a multiprecision number from an array of octets as
+ *             two's complement.  The last byte in the array is the least
+ *             significant.
+ */
+
+mp *mp_loadb2c(mp *d, const void *pv, size_t sz)
+{
+  const octet *ov = pv;
+  MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
+  if (!sz || !(ov[0] & 0x80)) {
+    mpx_loadb(d->v, d->vl, pv, sz);
+    d->f &= ~MP_NEG;
+  } else {
+    mpx_loadb2cn(d->v, d->vl, pv, sz);
+    d->f |= MP_NEG;
+  }
+  d->f &= ~MP_UNDEF;
+  mp_shrink(d);
+  return (d);
+}
+
+/* --- @mp_storeb2c@ --- *
+ *
+ * Arguments:  @const mp *m@ = source
+ *             @void *pv@ = pointer to output array
+ *             @size_t sz@ = size of the output array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a multiprecision number in an array of octets, as
+ *             two's complement.  The last byte in the array is the least
+ *             significant.  If the array is too small to represent the
+ *             number, high-order bits are truncated; if the array is too
+ *             large, high order bytes are sign-extended.
+ */
+
+void mp_storeb2c(const mp *m, void *pv, size_t sz)
+{
+  if (MP_NEGP(m))
+    mpx_storeb2cn(m->v, m->vl, pv, sz);
+  else
+    mpx_storeb(m->v, m->vl, pv, sz);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-jacobi.c b/math/mp-jacobi.c
new file mode 100644 (file)
index 0000000..1a2835b
--- /dev/null
@@ -0,0 +1,201 @@
+/* -*-c-*-
+ *
+ * Compute Jacobi symbol
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_jacobi@ --- *
+ *
+ * Arguments:  @mp *a@ = an integer
+ *             @mp *n@ = another integer
+ *
+ * Returns:    @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%.
+ *
+ * Use:                Computes the Kronecker symbol %$\jacobi{a}{n}$%.  If @n@ is
+ *             prime, this is the Legendre symbol and is equal to 1 if and
+ *             only if @a@ is a quadratic residue mod @n@.  The result is
+ *             zero if and only if @a@ and @n@ have a common factor greater
+ *             than one.
+ *
+ *             If @n@ is composite, then this computes the Kronecker symbol
+ *
+ *               %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$%
+ *
+ *             where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the
+ *             prime factorization of %$n$%.  The missing bits are:
+ *
+ *               * %$\jacobi{a}{1} = 1$%;
+ *               * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if
+ *                 positive;
+ *               * %$\jacobi{a}{0} = 0$%;
+ *               * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is
+ *                 congruent to 1 or 7 (mod 8), or %$-1$% otherwise.
+ *
+ *             If %$n$% is positive and odd, then this is the Jacobi
+ *             symbol.  (The Kronecker symbol is a consistant domain
+ *             extension; the Jacobi symbol was implemented first, and the
+ *             name stuck.)
+ */
+
+int mp_jacobi(mp *a, mp *n)
+{
+  int s = 1;
+  size_t p2;
+
+  /* --- Handle zero specially --- *
+   *
+   * I can't find any specific statement for what to do when %$n = 0$%; PARI
+   * opts to set %$\jacobi{\pm1}{0} = \pm 1$% and %$\jacobi{a}{0} = 0$% for
+   * other %$a$%.
+   */
+
+  if (MP_ZEROP(n)) {
+    if (MP_EQ(a, MP_ONE)) return (+1);
+    else if (MP_EQ(a, MP_MONE)) return (-1);
+    else return (0);
+  }
+
+  /* --- Deal with powers of two --- *
+   *
+   * This implicitly takes a copy of %$n$%.  Copy %$a$% at the same time to
+   * make cleanup easier.
+   */
+
+  MP_COPY(a);
+  n = mp_odd(MP_NEW, n, &p2);
+  if (p2) {
+    if (MP_EVENP(a)) {
+      s = 0;
+      goto done;
+    } else if ((p2 & 1) && ((a->v[0] & 7) == 3 || (a->v[0] & 7) == 5))
+      s = -s;
+  }
+
+  /* --- Deal with negative %$n$% --- */
+
+  if (MP_NEGP(n)) {
+    n = mp_neg(n, n);
+    if (MP_NEGP(a))
+      s = -s;
+  }
+
+  /* --- Check for unit %$n$% --- */
+
+  if (MP_EQ(n, MP_ONE))
+    goto done;
+
+  /* --- Reduce %$a$% modulo %$n$% --- */
+
+  if (MP_NEGP(a) || MP_CMP(a, >=, n))
+    mp_div(0, &a, a, n);
+
+  /* --- Main recursive mess, flattened out into something nice --- */
+
+  for (;;) {
+    mpw nn;
+    size_t e;
+
+    /* --- Some simple special cases --- */
+
+    MP_SHRINK(a);
+    if (MP_ZEROP(a)) {
+      s = 0;
+      goto done;
+    }
+
+    /* --- Main case with powers of two --- */
+
+    a = mp_odd(a, a, &e);
+    nn = n->v[0] & 7;
+    if ((e & 1) && (nn == 3 || nn == 5))
+      s = -s;
+    if (MP_LEN(a) == 1 && a->v[0] == 1)
+      goto done;
+    if ((nn & 3) == 3 && (a->v[0] & 3) == 3)
+      s = -s;
+
+    /* --- Reduce and swap --- */
+
+    mp_div(0, &n, n, a);
+    { mp *t = n; n = a; a = t; }
+  }
+
+  /* --- Wrap everything up --- */
+
+done:
+  MP_DROP(a);
+  MP_DROP(n);
+  return (s);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int verify(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  mp *n = *(mp **)v[1].buf;
+  int s = *(int *)v[2].buf;
+  int j = mp_jacobi(a, n);
+  int ok = 1;
+
+  if (s != j) {
+    fputs("\n*** fail", stderr);
+    fputs("a = ", stderr); mp_writefile(a, stderr, 10); fputc('\n', stderr);
+    fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr);
+    fprintf(stderr, "s = %i\n", s);
+    fprintf(stderr, "j = %i\n", j);
+    ok = 0;
+  }
+
+  mp_drop(a);
+  mp_drop(n);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "jacobi", verify, { &type_mp, &type_mp, &type_int, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mp");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-mem.c b/math/mp-mem.c
new file mode 100644 (file)
index 0000000..e1840ee
--- /dev/null
@@ -0,0 +1,334 @@
+/* -*-c-*-
+ *
+ * Memory management for multiprecision numbers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/sub.h>
+
+
+#include "mp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_new@ --- *
+ *
+ * Arguments:  @size_t sz@ = size of vector required
+ *             @unsigned f@ = flags to set
+ *
+ * Returns:    Pointer to a new MP structure.
+ *
+ * Use:                Allocates a new multiprecision integer.  The data space is
+ *             allocated from either the standard global or secret arena,
+ *             depending on the initial flags requested.
+ */
+
+mp *mp_new(size_t sz, unsigned f)
+{
+  mp *m = CREATE(mp);
+  m->a = (f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL;
+  m->v = mpalloc(m->a, sz);
+  m->vl = m->v + sz;
+  m->sz = sz;
+  m->f = f & ~(MP_CONST | MP_DESTROYED);
+  m->ref = 1;
+  return (m);
+}
+
+/* --- @mp_create@ --- *
+ *
+ * Arguments:  @size_t sz@ = size of vector required
+ *
+ * Returns:    Pointer to pristine new MP structure with enough memory
+ *             bolted onto it.
+ *
+ * Use:                Creates a new multiprecision integer, initially zero.  The
+ *             integer has a single reference.
+ */
+
+mp *mp_create(size_t sz)
+{
+  mp *m = CREATE(mp);
+  m->v = mpalloc(MPARENA_GLOBAL, sz);
+  m->vl = m->v + sz;
+  m->sz = sz;
+  m->a = MPARENA_GLOBAL;
+  m->f = MP_UNDEF;
+  m->ref = 1;
+  return (m);
+}
+
+/* --- @mp_createsecure@ --- *
+ *
+ * Arguments:  @size_t sz@ = size of vector required
+ *
+ * Returns:    Pointer to pristine new MP structure with enough memory
+ *             bolted onto it.
+ *
+ * Use:                Creates a new multiprecision integer with indeterminate
+ *             contents.  The integer has a single reference.  The integer's
+ *             data space is allocated from the secure arena.  Its burn flag
+ *             is set.
+ */
+
+mp *mp_createsecure(size_t sz)
+{
+  mp *m = CREATE(mp);
+  m->v = mpalloc(MPARENA_SECURE, sz);
+  m->vl = m->v + sz;
+  m->sz = sz;
+  m->a = MPARENA_SECURE;
+  m->f = MP_UNDEF | MP_BURN;
+  m->ref = 1;
+  return (m);
+}
+
+/* --- @mp_build@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to an MP block to fill in
+ *             @mpw *v@ = pointer to a word array
+ *             @mpw *vl@ = pointer just past end of array
+ *
+ * Returns:    ---
+ *
+ * Use:                Creates a multiprecision integer representing some smallish
+ *             number.  You must provide storage for the number and dispose
+ *             of it when you've finished with it.  The number is marked as
+ *             constant while it exists.
+ */
+
+void mp_build(mp *m, mpw *v, mpw *vl)
+{
+  m->v = v;
+  m->vl = vl;
+  m->sz = vl - v;
+  m->a = MPARENA_GLOBAL;
+  m->f = MP_CONST;
+  m->ref = 1;
+}
+
+/* --- @mp_destroy@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a multiprecision integer. The reference count isn't
+ *             checked.  Don't use this function if you don't know what
+ *             you're doing: use @mp_drop@ instead.
+ */
+
+void mp_destroy(mp *m)
+{
+  assert(((void)"Destroying a free integer", !(m->f & MP_DESTROYED)));
+  assert(((void)"Attempted to destroy a constant", !(m->f & MP_CONST)));
+  if (m->f & MP_BURN)
+    memset(m->v, 0, MPWS(m->sz));
+  mpfree(m->a, m->v);
+  m->f |= MP_DESTROYED;
+  DESTROY(m);
+}
+
+/* --- @mp_copy@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    A copy of the given multiprecision integer.
+ *
+ * Use:                Copies the given integer.  In fact you just get another
+ *             reference to the same old one again.
+ */
+
+mp *mp_copy(mp *m) { return MP_COPY(m); }
+
+/* --- @mp_drop@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Drops a reference to an integer which isn't wanted any more.
+ *             If there are no more references, the integer is destroyed.
+ */
+
+void mp_drop(mp *m) { if (m) MP_DROP(m); }
+
+/* --- @mp_split@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    A reference to the same integer, possibly with a different
+ *             address.
+ *
+ * Use:                Splits off a modifiable version of the integer referred to.
+ */
+
+mp *mp_split(mp *m) { MP_SPLIT(m); return (m); }
+
+/* --- @mp_resize@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *             @size_t sz@ = new size
+ *
+ * Returns:    ---
+ *
+ * Use:                Changes an integer's size.  The length and value are not
+ *             changed.  It is an error to
+ */
+
+void mp_resize(mp *m, size_t sz) { MP_RESIZE(m, sz); }
+
+/* --- @mp_ensure@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *             @size_t sz@ = required length
+ *
+ * Returns:    ---
+ *
+ * Use:                Changes an integer's length.  If there is not enough space
+ *             allocated for the new length then the size is increased.  It
+ */
+
+void mp_ensure(mp *m, size_t sz) { MP_ENSURE(m, sz); }
+
+/* --- @mp_dest@ --- *
+ *
+ * Arguments:  @mp *m@ = a suggested destination integer
+ *             @size_t sz@ = size required for result, in digits
+ *             @unsigned f@ = various flags
+ *
+ * Returns:    A pointer to an appropriate destination.
+ *
+ * Use:                Converts a suggested destination into a real destination with
+ *             the required properties.  If the real destination is @d@,
+ *             then the following properties will hold:
+ *
+ *               * @d@ will have exactly one reference.
+ *
+ *               * If @m@ is not @MP_NEW@, then the contents of @m@ will not
+ *                 change, unless @f@ has the @MP_UNDEF@ flag set.
+ *
+ *               * If @m@ is not @MP_NEW@, then he reference count of @m@ on
+ *                 entry is equal to the sum of the counts of @d@ and @m@ on
+ *                 exit.
+ *
+ *               * The size of @d@ will be at least @sz@.
+ *
+ *               * If @f@ has the @MP_BURN@ flag set, then @d@ will be
+ *                 allocated from @MPARENA_SECURE@.
+ *
+ *             Understanding this function is crucial to using Catacomb's
+ *             multiprecision integer library effectively.
+ */
+
+mp *mp_dest(mp *m, size_t sz, unsigned f)
+{
+  /* --- If no destination, make one --- */
+
+  if (m == MP_NEWSEC)
+    m = mp_new(sz, f | MP_UNDEF | MP_BURN);
+  else if (m == MP_NEW)
+    m = mp_new(sz, f | MP_UNDEF);
+  else {
+    size_t len = MP_LEN(m);
+    unsigned undef = (m->f | f) & MP_UNDEF;
+
+    /* --- If the value must be preserved, the block can't shrink --- */
+
+    if (!undef && sz < len)
+      sz = len;
+
+    /* --- Otherwise check whether the destination is suitable --- */
+
+    if (m->ref > 1 || (m->f & MP_CONST) ||
+       sz > m->sz || ((f & ~m->f) & MP_BURN)) {
+
+      /* --- No -- allocate a new buffer --- *
+       *
+       * The buffer must be secure if (a) the caller requested a secure
+       * buffer, or (b) the old buffer is secure and I'm not allowed to
+       * discard the old contents.
+       */
+
+      mparena *a;
+      mpw *v;
+
+      if ((f & MP_BURN) || (!undef && (m->f & MP_BURN)))
+       a = MPARENA_SECURE;
+      else
+       a = MPARENA_GLOBAL;
+      v = mpalloc(a, sz);
+
+      /* --- Copy the data over --- */
+
+      if (!undef) {
+       memcpy(v, m->v, MPWS(len));
+       if (sz - len > 0)
+         memset(v + len, 0, MPWS(sz - len));
+      }
+
+      /* --- If @m@ has other references, make a new node --- *
+       *
+       * Otherwise dispose of the old buffer.
+       */
+
+      if (!(m->f & MP_CONST) && m->ref == 1) {
+       if (m->f & MP_BURN)
+         memset(m->v, 0, MPWS(m->sz));
+       mpfree(m->a, m->v);
+      } else {
+       mp *mm = CREATE(mp);
+       mm->ref = 1;
+       mm->f = m->f;
+       m->ref--;
+       m = mm;
+      }
+
+      /* --- Fix up the node --- */
+
+      m->v = v;
+      m->vl = v + sz;
+      m->sz = sz;
+      m->f = ((m->f & ~(MP_CONST | MP_BURN)) |
+             (f & (MP_BURN | MP_UNDEF)));
+      m->a = a;
+    }
+
+    /* --- If the number is growing in its buffer, fix it up --- */
+
+    else if (sz > len) {
+      if (!undef)
+       memset(m->vl, 0, MPWS(sz - len));
+      m->vl = m->v + sz;
+    }
+  }
+
+  /* --- Done --- */
+
+  return (m);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-misc.c b/math/mp-misc.c
new file mode 100644 (file)
index 0000000..35cdc8e
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*-c-*-
+ *
+ * Miscellaneous multiprecision support functions
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+
+/*----- Basic manipulation ------------------------------------------------*/
+
+/* --- @mp_shrink@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reduces the recorded length of an integer.  This doesn't
+ *             reduce the amount of memory used, although it can improve
+ *             performance a bit.  To reduce memory, use @mp_minimize@
+ *             instead.  This can't change the value of an integer, and is
+ *             therefore safe to use even when there are multiple
+ *             references.
+ */
+
+void mp_shrink(mp *m) { MP_SHRINK(m); }
+
+/* --- @mp_minimize@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reduces the amount of memory an integer uses.  It's best to
+ *             do this to numbers which aren't going to change in the
+ *             future.
+ */
+
+void mp_minimize(mp *m)
+{
+  MP_SHRINK(m);
+  MP_RESIZE(m, MP_LEN(m));
+}
+
+/*----- Bit scanning ------------------------------------------------------*/
+
+/* --- @mp_scan@ --- *
+ *
+ * Arguments:  @mpscan *sc@ = pointer to bitscanner block
+ *             @const mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a bitscanner on a multiprecision integer.
+ */
+
+void mp_scan(mpscan *sc, const mp *m) { MP_SCAN(sc, m); }
+
+/* --- @mp_scan@ --- *
+ *
+ * Arguments:  @mpscan *sc@ = pointer to bitscanner block
+ *             @const mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a reverse bitscanner on a multiprecision
+ *             integer.
+ */
+
+void mp_rscan(mpscan *sc, const mp *m) { MP_RSCAN(sc, m); }
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-modexp.c b/math/mp-modexp.c
new file mode 100644 (file)
index 0000000..f52e5b0
--- /dev/null
@@ -0,0 +1,111 @@
+/* -*-c-*-
+ *
+ * General-purpose modular exponentiation
+ *
+ * (c) 2006 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpbarrett.h"
+#include "mpmont.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_modexp@ --- *
+ *
+ * Arguments:  @mp *d@ = fake destination
+ *             @mp *x@ = base of exponentiation
+ *             @mp *e@ = exponent
+ *             @mp *n@ = modulus (must be positive)
+ *
+ * Returns:    The value %$x^e \bmod n$%.
+ */
+
+mp *mp_modexp(mp *d, mp *x, mp *e, mp *n)
+{
+  if (MP_ODDP(n)) {
+    mpmont mm;
+    mpmont_create(&mm, n);
+    d = mpmont_exp(&mm, d, x, e);
+    mpmont_destroy(&mm);
+  } else {
+    mpbarrett mb;
+    mpbarrett_create(&mb, n);
+    d = mpbarrett_exp(&mb, d, x, e);
+    mpbarrett_destroy(&mb);
+  }
+  return (d);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int tmodexp(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  mp *b = *(mp **)v[1].buf;
+  mp *m = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *mr;
+  int ok = 1;
+
+  mr = mp_modexp(MP_NEW, a, b, m);
+
+  if (!MP_EQ(mr, r)) {
+    fputs("\n*** modexp failed", stderr);
+    fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\n e = ", stderr); mp_writefile(b, stderr, 10);
+    fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  MP_DROP(m);
+  MP_DROP(a);
+  MP_DROP(b);
+  MP_DROP(r);
+  MP_DROP(mr);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return ok;
+}
+
+static test_chunk tests[] = {
+  { "modexp", tmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mp");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-modsqrt.c b/math/mp-modsqrt.c
new file mode 100644 (file)
index 0000000..b4a11fa
--- /dev/null
@@ -0,0 +1,207 @@
+/* -*-c-*-
+ *
+ * Compute square roots modulo a prime
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fibrand.h"
+#include "grand.h"
+#include "mp.h"
+#include "mpmont.h"
+#include "mprand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_modsqrt@ --- *
+ *
+ * Arguments:  @mp *d@ = destination integer
+ *             @mp *a@ = source integer
+ *             @mp *p@ = modulus (must be prime)
+ *
+ * Returns:    If %$a$% is a quadratic residue, a square root of %$a$%; else
+ *             a null pointer.
+ *
+ * Use:                Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%,
+ *             if one exists; else a null pointer.  This function will not
+ *             work if %$p$% is composite: you must factor the modulus, take
+ *             a square root mod each factor, and recombine the results
+ *             using the Chinese Remainder Theorem.
+ *
+ *             We guarantee that the square root returned is the smallest
+ *             one (i.e., the `positive' square root).
+ */
+
+mp *mp_modsqrt(mp *d, mp *a, mp *p)
+{
+  mpmont mm;
+  mp *t;
+  size_t s;
+  mp *b;
+  mp *ainv;
+  mp *c, *r;
+  size_t i, j;
+  mp *dd, *mone;
+
+  /* --- Cope if %$a \not\in Q_p$% --- */
+
+  if (mp_jacobi(a, p) != 1) {
+    mp_drop(d);
+    return (0);
+  }
+
+  /* --- Choose some quadratic non-residue --- */
+
+  {
+    grand *g = fibrand_create(0);
+
+    b = MP_NEW;
+    do
+      b = mprand_range(b, p, g, 0);
+    while (mp_jacobi(b, p) != -1);
+    g->ops->destroy(g);
+  }
+
+  /* --- Find the inverse of %$a$% --- */
+
+  ainv = mp_modinv(MP_NEW, a, p);
+
+  /* --- Split %$p - 1$% into a power of two and an odd number --- */
+
+  t = mp_sub(MP_NEW, p, MP_ONE);
+  t = mp_odd(t, t, &s);
+
+  /* --- Now to really get going --- */
+
+  mpmont_create(&mm, p);
+  b = mpmont_mul(&mm, b, b, mm.r2);
+  c = mpmont_expr(&mm, b, b, t);
+  t = mp_add(t, t, MP_ONE);
+  t = mp_lsr(t, t, 1);
+  dd = mpmont_mul(&mm, MP_NEW, a, mm.r2);
+  r = mpmont_expr(&mm, t, dd, t);
+  mp_drop(dd);
+  ainv = mpmont_mul(&mm, ainv, ainv, mm.r2);
+
+  mone = mp_sub(MP_NEW, p, mm.r);
+
+  dd = MP_NEW;
+
+  for (i = 1; i < s; i++) {
+
+    /* --- Compute %$d_0 = r^2a^{-1}$% --- */
+
+    dd = mp_sqr(dd, r);
+    dd = mpmont_reduce(&mm, dd, dd);
+    dd = mpmont_mul(&mm, dd, dd, ainv);
+
+    /* --- Now %$d = d_0^{2^{s - i - 1}}$% --- */
+
+    for (j = i; j < s - 1; j++) {
+      dd = mp_sqr(dd, dd);
+      dd = mpmont_reduce(&mm, dd, dd);
+    }
+
+    /* --- Fiddle at the end --- */
+
+    if (MP_EQ(dd, mone))
+      r = mpmont_mul(&mm, r, r, c);
+    c = mp_sqr(c, c);
+    c = mpmont_reduce(&mm, c, c);
+  }
+
+  /* --- Done, so tidy up --- *
+   *
+   * Canonify the answer.
+   */
+
+  d = mpmont_reduce(&mm, d, r);
+  r = mp_sub(r, p, d);
+  if (MP_CMP(r, <, d)) { mp *tt = r; r = d; d = tt; }
+  mp_drop(ainv);
+  mp_drop(r); mp_drop(c);
+  mp_drop(dd);
+  mp_drop(mone);
+  mpmont_destroy(&mm);
+
+  return (d);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int verify(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  mp *p = *(mp **)v[1].buf;
+  mp *rr = *(mp **)v[2].buf;
+  mp *r = mp_modsqrt(MP_NEW, a, p);
+  int ok = 0;
+
+  if (!r)
+    ok = 0;
+  else if (MP_EQ(r, rr))
+    ok = 1;
+
+  if (!ok) {
+    fputs("\n*** fail\n", stderr);
+    fputs("a  = ", stderr); mp_writefile(a, stderr, 10); fputc('\n', stderr);
+    fputs("p  = ", stderr); mp_writefile(p, stderr, 10); fputc('\n', stderr);
+    if (r) {
+      fputs("r = ", stderr);
+      mp_writefile(r, stderr, 10);
+      fputc('\n', stderr);
+    } else
+      fputs("r = <undef>\n", stderr);
+    fputs("rr = ", stderr); mp_writefile(rr, stderr, 10); fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(a);
+  mp_drop(p);
+  mp_drop(r);
+  mp_drop(rr);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "modsqrt", verify, { &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mp");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-sqrt.c b/math/mp-sqrt.c
new file mode 100644 (file)
index 0000000..2dbe418
--- /dev/null
@@ -0,0 +1,153 @@
+/* -*-c-*-
+ *
+ * Compute integer square roots
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_sqrt@ --- *
+ *
+ * Arguments:  @mp *d@ = pointer to destination integer
+ *             @mp *a@ = (nonnegative) integer to take square root of
+ *
+ * Returns:    The largest integer %$x$% such that %$x^2 \le a$%.
+ *
+ * Use:                Computes integer square roots.
+ *
+ *             The current implementation isn't very good: it uses the
+ *             Newton-Raphson method to find an approximation to %$a$%.  If
+ *             there's any demand for a better version, I'll write one.
+ */
+
+mp *mp_sqrt(mp *d, mp *a)
+{
+  unsigned long z;
+  mp *q = MP_NEW, *r = MP_NEW;
+
+  /* --- Sanity preservation --- */
+
+  assert(!MP_NEGP(a));
+
+  /* --- Deal with trivial cases --- */
+
+  MP_SHRINK(a);
+  if (MP_ZEROP(a)) {
+    mp_drop(d);
+    return (MP_ZERO);
+  }
+
+  /* --- Find an initial guess of about the right size --- */
+
+  z = mp_bits(a);
+  z >>= 1;
+  mp_copy(a);
+  d = mp_lsr(d, a, z);
+
+  /* --- Main approximation --- *
+   *
+   * We use the Newton-Raphson recurrence relation
+   *
+   *   %$x_{i+1} = x_i - \frac{x_i^2 - a}{2 x_i}$%
+   *
+   * We inspect the term %$q = x^2 - a$% to see when to stop.  Increasing
+   * %$x$% is pointless when %$-q < 2 x + 1$%.
+   */
+
+  for (;;) {
+    q = mp_sqr(q, d);
+    q = mp_sub(q, q, a);
+    if (MP_ZEROP(q))
+      break;
+    if (MP_NEGP(q)) {
+      r = mp_lsl(r, d, 1);
+      r->f |= MP_NEG;
+      if (MP_CMP(q, >=, r))
+       break;
+    }
+    mp_div(&r, &q, q, d);
+    r = mp_lsr(r, r, 1);
+    if (r->v == r->vl)
+      d = mp_sub(d, d, MP_ONE);
+    else
+      d = mp_sub(d, d, r);
+  }
+
+  /* --- Finished, at last --- */
+
+  mp_drop(a);
+  mp_drop(q);
+  mp_drop(r);
+  return (d);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int verify(dstr *v)
+{
+  mp *a = *(mp **)v[0].buf;
+  mp *qq = *(mp **)v[1].buf;
+  mp *q = mp_sqrt(MP_NEW, a);
+  int ok = 1;
+
+  if (!MP_EQ(q, qq)) {
+    ok = 0;
+    fputs("\n*** sqrt failed", stderr);
+    fputs("\n*** a     = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\n*** result = ", stderr); mp_writefile(q, stderr, 10);
+    fputs("\n*** expect = ", stderr); mp_writefile(qq, stderr, 10);
+    fputc('\n', stderr);
+  }
+
+  mp_drop(a);
+  mp_drop(q);
+  mp_drop(qq);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "sqrt", verify, { &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } },
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mp");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp-test.c b/math/mp-test.c
new file mode 100644 (file)
index 0000000..ebc4833
--- /dev/null
@@ -0,0 +1,62 @@
+/* -*-c-*-
+ *
+ * Testing functionality for multiprecision integers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/dstr.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+#include <mLib/testrig.h>
+
+#include "mp.h"
+#include "mptext.h"
+
+/*----- The `MP' testrig data type ----------------------------------------*/
+
+static void mp_cvt(const char *buf, dstr *d)
+{
+  mp *m;
+  DENSURE(d, sizeof(mp *));
+  m = mp_readstring(MP_NEW, (char *)buf, 0, 0);
+  if (!m)
+    die(1, "bad integer `%s'", buf);
+  *(mp **)d->buf = m;
+}
+
+static void mp_dump(dstr *d, FILE *fp)
+{
+  mp *m = *(mp **)d->buf;
+  mp_writefile(m, fp, 10);
+}
+
+const test_type type_mp = { mp_cvt, mp_dump };
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mp.h b/math/mp.h
new file mode 100644 (file)
index 0000000..cfaeed5
--- /dev/null
+++ b/math/mp.h
@@ -0,0 +1,1024 @@
+/* -*-c-*-
+ *
+ * Simple multiprecision arithmetic
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MP_H
+#define CATACOMB_MP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <string.h>
+
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_MPW_H
+#  include "mpw.h"
+#endif
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_MPARENA_H
+#  include "mparena.h"
+#endif
+
+#ifndef CATACOMB_MPX_H
+#  include "mpx.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- A multiprecision integer --- */
+
+typedef struct mp {
+  mpw *v, *vl;                         /* Vector of digits, current limit */
+  size_t sz;                           /* Size of digit buffer in words */
+  mparena *a;                          /* Arena for buffer allocation */
+  unsigned f;                          /* Flags (see below) */
+  unsigned ref;                                /* Reference counter */
+} mp;
+
+#define MP_NEG 1u                      /* Negative (signed magnitude) */
+#define MP_BURN 2u                     /* Secret (viral flag) */
+#define MP_CONST 4u                    /* Uses strange memory allocation */
+#define MP_UNDEF 8u                    /* Contains nothing interesting */
+#define MP_DESTROYED 16u               /* Has been destroyed */
+
+/* --- A factor for simultaneous exponentation --- *
+ *
+ * Used by the Montgomery and Barrett exponentiators.
+ */
+
+typedef struct mp_expfactor {
+  mp *base;
+  mp *exp;
+} mp_expfactor;
+
+/*----- Useful constants --------------------------------------------------*/
+
+extern mp mp_const[];
+
+#define MP_ZERO         (&mp_const[0])
+#define MP_ONE  (&mp_const[1])
+#define MP_TWO  (&mp_const[2])
+#define MP_THREE (&mp_const[3])
+#define MP_FOUR         (&mp_const[4])
+#define MP_FIVE         (&mp_const[5])
+#define MP_TEN  (&mp_const[6])
+#define MP_256  (&mp_const[7])
+#define MP_MONE         (&mp_const[8])
+
+#define MP_NEW ((mp *)0)
+#define MP_NEWSEC (&mp_const[9])
+
+/*----- Trivial macros ----------------------------------------------------*/
+
+/* --- @MP_LEN@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    Length of the integer, in words.
+ */
+
+#define MP_LEN(m) ((m)->vl - ((m)->v))
+
+/*----- Memory management and reference counting --------------------------*/
+
+/* --- @mp_new@ --- *
+ *
+ * Arguments:  @size_t sz@ = size of vector required
+ *             @unsigned f@ = flags to set
+ *
+ * Returns:    Pointer to a new MP structure.
+ *
+ * Use:                Allocates a new multiprecision integer.  The data space is
+ *             allocated from either the standard global or secret arena,
+ *             depending on the initial flags requested.
+ */
+
+extern mp *mp_new(size_t /*sz*/, unsigned /*f*/);
+
+/* --- @mp_create@ --- *
+ *
+ * Arguments:  @size_t sz@ = size of vector required
+ *
+ * Returns:    Pointer to pristine new MP structure with enough memory
+ *             bolted onto it.
+ *
+ * Use:                Creates a new multiprecision integer with indeterminate
+ *             contents.  The integer has a single reference.
+ */
+
+extern mp *mp_create(size_t /*sz*/);
+
+/* --- @mp_createsecure@ --- *
+ *
+ * Arguments:  @size_t sz@ = size of vector required
+ *
+ * Returns:    Pointer to pristine new MP structure with enough memory
+ *             bolted onto it.
+ *
+ * Use:                Creates a new multiprecision integer with indeterminate
+ *             contents.  The integer has a single reference.  The integer's
+ *             data space is allocated from the secure arena.  Its burn flag
+ *             is set.
+ */
+
+extern mp *mp_createsecure(size_t /*sz*/);
+
+/* --- @mp_build@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to an MP block to fill in
+ *             @mpw *v@ = pointer to a word array
+ *             @mpw *vl@ = pointer just past end of array
+ *
+ * Returns:    ---
+ *
+ * Use:                Creates a multiprecision integer representing some smallish
+ *             number.  You must provide storage for the number and dispose
+ *             of it when you've finished with it.  The number is marked as
+ *             constant while it exists.
+ */
+
+extern void mp_build(mp */*m*/, mpw */*v*/, mpw */*vl*/);
+
+/* --- @mp_destroy@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a multiprecision integer. The reference count isn't
+ *             checked.  Don't use this function if you don't know what
+ *             you're doing: use @mp_drop@ instead.
+ */
+
+extern void mp_destroy(mp */*m*/);
+
+/* --- @mp_copy@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    A copy of the given multiprecision integer.
+ *
+ * Use:                Copies the given integer.  In fact you just get another
+ *             reference to the same old one again.
+ */
+
+extern mp *mp_copy(mp */*m*/);
+
+#define MP_COPY(m) ((m)->ref++, (m))
+
+/* --- @mp_drop@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Drops a reference to an integer which isn't wanted any more.
+ *             If there are no more references, the integer is destroyed.
+ */
+
+extern void mp_drop(mp */*m*/);
+
+#define MP_DROP(m) do {                                                        \
+  mp *_mm = (m);                                                       \
+  _mm->ref--;                                                          \
+  if (_mm->ref == 0 && !(_mm->f & MP_CONST))                           \
+    mp_destroy(_mm);                                                   \
+} while (0)
+
+/* --- @mp_split@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    A reference to the same integer, possibly with a different
+ *             address.
+ *
+ * Use:                Splits off a modifiable version of the integer referred to.
+ */
+
+extern mp *mp_split(mp */*m*/);
+
+#define MP_SPLIT(m) do {                                               \
+  mp *_m = (m);                                                                \
+  if ((_m->f & MP_CONST) || _m->ref > 1) {                             \
+    size_t _len = MP_LEN(_m);                                          \
+    mp *_mm = mp_new(_len, _m->f);                                     \
+    if (!(_m->f & MP_UNDEF))                                           \
+      memcpy(_mm->v, _m->v, MPWS(_len));                               \
+    _m->ref--;                                                         \
+    _m = _mm;                                                          \
+  }                                                                    \
+  (m) = _m;                                                            \
+} while (0)
+
+/* --- @mp_resize@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *             @size_t sz@ = new size
+ *
+ * Returns:    ---
+ *
+ * Use:                Resizes the vector containing the integer's digits.  The new
+ *             size must be at least as large as the current integer's
+ *             length.  This isn't really intended for client use.
+ */
+
+extern void mp_resize(mp */*m*/, size_t /*sz*/);
+
+#define MP_RESIZE(m, ssz) do {                                         \
+  mp *_m = (m);                                                                \
+  size_t _sz = (ssz);                                                  \
+  mparena *_a = (_m->f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL;   \
+  mpw *_v;                                                             \
+  size_t _len = MP_LEN(_m);                                            \
+  assert(((void)"can't make size less than length", _sz >= _len));     \
+  _v = mpalloc(_a, _sz);                                               \
+  if (!(_m->f & MP_UNDEF))                                             \
+    memcpy(_v, _m->v, MPWS(_len));                                     \
+  if (_m->f & MP_BURN)                                                 \
+    memset(_m->v, 0, MPWS(_m->sz));                                    \
+  mpfree(_m->a, _m->v);                                                        \
+  _m->a = _a;                                                          \
+  _m->v = _v;                                                          \
+  _m->vl = _v + _len;                                                  \
+} while (0)
+
+/* --- @mp_ensure@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *             @size_t sz@ = required size
+ *
+ * Returns:    ---
+ *
+ * Use:                Ensures that the integer has enough space for @sz@ digits.
+ *             The value is not changed.
+ */
+
+extern void mp_ensure(mp */*m*/, size_t /*sz*/);
+
+#define MP_ENSURE(m, ssz) do {                                         \
+  mp *_m = (m);                                                                \
+  size_t _ssz = (ssz);                                                 \
+  size_t _len = MP_LEN(_m);                                            \
+  if (_ssz >= _len) {                                                  \
+    if (_ssz > _m->sz)                                                 \
+      mp_resize(_m, _ssz);                                             \
+    if (!(_m->f & MP_UNDEF) && _ssz > _len)                            \
+      memset(_m->vl, 0, MPWS(_ssz - _len));                            \
+    _m->vl = _m->v + _ssz;                                             \
+  }                                                                    \
+} while (0)
+
+/* --- @mp_dest@ --- *
+ *
+ * Arguments:  @mp *m@ = a suggested destination integer
+ *             @size_t sz@ = size required for result, in digits
+ *             @unsigned f@ = various flags
+ *
+ * Returns:    A pointer to an appropriate destination.
+ *
+ * Use:                Converts a suggested destination into a real destination with
+ *             the required properties.  If the real destination is @d@,
+ *             then the following properties will hold:
+ *
+ *               * @d@ will have exactly one reference.
+ *
+ *               * If @m@ is not @MP_NEW@, then the contents of @m@ will not
+ *                 change, unless @f@ has the @MP_UNDEF@ flag set.
+ *
+ *               * If @m@ is not @MP_NEW@, then he reference count of @m@ on
+ *                 entry is equal to the sum of the counts of @d@ and @m@ on
+ *                 exit.
+ *
+ *               * The size of @d@ will be at least @sz@.
+ *
+ *               * If @f@ has the @MP_BURN@ flag set, then @d@ will be
+ *                 allocated from @MPARENA_SECURE@.
+ *
+ *             Understanding this function is crucial to using Catacomb's
+ *             multiprecision integer library effectively.
+ */
+
+extern mp *mp_dest(mp */*m*/, size_t /*sz*/, unsigned /*f*/);
+
+#define MP_DEST(m, ssz, f) do {                                                \
+  mp *_m = (m);                                                                \
+  size_t _ssz = (ssz);                                                 \
+  unsigned _f = (f);                                                   \
+  _m = mp_dest(_m, _ssz, _f);                                          \
+  (m) = _m;                                                            \
+} while (0)
+
+/*----- Size manipulation -------------------------------------------------*/
+
+/* --- @mp_shrink@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reduces the recorded length of an integer.  This doesn't
+ *             reduce the amount of memory used, although it can improve
+ *             performance a bit.  To reduce memory, use @mp_minimize@
+ *             instead.  This can't change the value of an integer, and is
+ *             therefore safe to use even when there are multiple
+ *             references.
+ */
+
+extern void mp_shrink(mp */*m*/);
+
+#define MP_SHRINK(m) do {                                              \
+  mp *_mm = (m);                                                       \
+  MPX_SHRINK(_mm->v, _mm->vl);                                         \
+  if (MP_ZEROP(_mm))                                                   \
+    _mm->f &= ~MP_NEG;                                                 \
+} while (0)
+
+/* --- @mp_minimize@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Reduces the amount of memory an integer uses.  It's best to
+ *             do this to numbers which aren't going to change in the
+ *             future.
+ */
+
+extern void mp_minimize(mp */*m*/);
+
+/*----- Bit scanning ------------------------------------------------------*/
+
+#ifndef CATACOMB_MPSCAN_H
+#  include "mpscan.h"
+#endif
+
+/* --- @mp_scan@ --- *
+ *
+ * Arguments:  @mpscan *sc@ = pointer to bitscanner block
+ *             @const mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a bitscanner on a multiprecision integer.
+ */
+
+extern void mp_scan(mpscan */*sc*/, const mp */*m*/);
+
+#define MP_SCAN(sc, m) do {                                            \
+  const mp *_mm = (m);                                                 \
+  mpscan *_sc = (sc);                                                  \
+  MPSCAN_INITX(_sc, _mm->v, _mm->vl);                                  \
+} while (0)
+
+/* --- @mp_rscan@ --- *
+ *
+ * Arguments:  @mpscan *sc@ = pointer to bitscanner block
+ *             @const mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a reverse bitscanner on a multiprecision
+ *             integer.
+ */
+
+extern void mp_rscan(mpscan */*sc*/, const mp */*m*/);
+
+#define MP_RSCAN(sc, m) do {                                           \
+  const mp *_mm = (m);                                                 \
+  mpscan *_sc = (sc);                                                  \
+  MPSCAN_RINITX(_sc, _mm->v, _mm->vl);                                 \
+} while (0)
+
+/* --- Other bitscanning aliases --- */
+
+#define mp_step mpscan_step
+#define mp_bit mpscan_bit
+#define mp_rstep mpscan_rstep
+#define mp_rbit mpscan_rbit
+
+#define MP_STEP MPSCAN_STEP
+#define MP_BIT MPSCAN_BIT
+#define MP_RSTEP MPSCAN_RSTEP
+#define MP_RBIT MPSCAN_RBIT
+
+/*----- Loading and storing -----------------------------------------------*/
+
+/* --- @mp_octets@ --- *
+ *
+ * Arguments:  @const mp *m@ = a multiprecision integer
+ *
+ * Returns:    The number of octets required to represent @m@.
+ *
+ * Use:                Calculates the external storage required for a multiprecision
+ *             integer.
+ */
+
+extern size_t mp_octets(const mp */*m*/);
+
+/* --- @mp_octets2c@ --- *
+ *
+ * Arguments:  @const mp *m@ = a multiprecision integer
+ *
+ * Returns:    The number of octets required to represent @m@.
+ *
+ * Use:                Calculates the external storage required for a multiprecision
+ *             integer represented as two's complement.
+ */
+
+extern size_t mp_octets2c(const mp */*m*/);
+
+/* --- @mp_bits@ --- *
+ *
+ * Arguments:  @const mp *m@ = a multiprecision integer
+ *
+ * Returns:    The number of bits required to represent @m@.
+ *
+ * Use:                Calculates the external storage required for a multiprecision
+ *             integer.
+ */
+
+extern unsigned long mp_bits(const mp */*m*/);
+
+/* --- @mp_loadl@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @const void *pv@ = pointer to source data
+ *             @size_t sz@ = size of the source data
+ *
+ * Returns:    Resulting multiprecision number.
+ *
+ * Use:                Loads a multiprecision number from an array of octets.  The
+ *             first byte in the array is the least significant.  More
+ *             formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$%
+ *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
+ */
+
+extern mp *mp_loadl(mp */*d*/, const void */*pv*/, size_t /*sz*/);
+
+/* --- @mp_storel@ --- *
+ *
+ * Arguments:  @const mp *m@ = source
+ *             @void *pv@ = pointer to output array
+ *             @size_t sz@ = size of the output array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a multiprecision number in an array of octets.  The
+ *             first byte in the array is the least significant.  If the
+ *             array is too small to represent the number, high-order bits
+ *             are truncated; if the array is too large, high order bytes
+ *             are filled with zeros.  More formally, if the number is
+ *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
+ *             then the array is %$b_0, b_1, \ldots, b_{n-1}$%.
+ */
+
+extern void mp_storel(const mp */*m*/, void */*pv*/, size_t /*sz*/);
+
+/* --- @mp_loadb@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @const void *pv@ = pointer to source data
+ *             @size_t sz@ = size of the source data
+ *
+ * Returns:    Resulting multiprecision number.
+ *
+ * Use:                Loads a multiprecision number from an array of octets.  The
+ *             last byte in the array is the least significant.  More
+ *             formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$%
+ *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
+ */
+
+extern mp *mp_loadb(mp */*d*/, const void */*pv*/, size_t /*sz*/);
+
+/* --- @mp_storeb@ --- *
+ *
+ * Arguments:  @const mp *m@ = source
+ *             @void *pv@ = pointer to output array
+ *             @size_t sz@ = size of the output array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a multiprecision number in an array of octets.  The
+ *             last byte in the array is the least significant.  If the
+ *             array is too small to represent the number, high-order bits
+ *             are truncated; if the array is too large, high order bytes
+ *             are filled with zeros.  More formally, if the number is
+ *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
+ *             then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%.
+ */
+
+extern void mp_storeb(const mp */*m*/, void */*pv*/, size_t /*sz*/);
+
+/* --- @mp_loadl2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @const void *pv@ = pointer to source data
+ *             @size_t sz@ = size of the source data
+ *
+ * Returns:    Resulting multiprecision number.
+ *
+ * Use:                Loads a multiprecision number from an array of octets as
+ *             two's complement.  The first byte in the array is the least
+ *             significant.
+ */
+
+extern mp *mp_loadl2c(mp */*d*/, const void */*pv*/, size_t /*sz*/);
+
+/* --- @mp_storel2c@ --- *
+ *
+ * Arguments:  @const mp *m@ = source
+ *             @void *pv@ = pointer to output array
+ *             @size_t sz@ = size of the output array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a multiprecision number in an array of octets as two's
+ *             complement.  The first byte in the array is the least
+ *             significant.  If the array is too small to represent the
+ *             number, high-order bits are truncated; if the array is too
+ *             large, high order bytes are sign-extended.
+ */
+
+extern void mp_storel2c(const mp */*m*/, void */*pv*/, size_t /*sz*/);
+
+/* --- @mp_loadb2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @const void *pv@ = pointer to source data
+ *             @size_t sz@ = size of the source data
+ *
+ * Returns:    Resulting multiprecision number.
+ *
+ * Use:                Loads a multiprecision number from an array of octets as
+ *             two's complement.  The last byte in the array is the least
+ *             significant.
+ */
+
+extern mp *mp_loadb2c(mp */*d*/, const void */*pv*/, size_t /*sz*/);
+
+/* --- @mp_storeb2c@ --- *
+ *
+ * Arguments:  @const mp *m@ = source
+ *             @void *pv@ = pointer to output array
+ *             @size_t sz@ = size of the output array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a multiprecision number in an array of octets, as
+ *             two's complement.  The last byte in the array is the least
+ *             significant.  If the array is too small to represent the
+ *             number, high-order bits are truncated; if the array is too
+ *             large, high order bytes are sign-extended.
+ */
+
+extern void mp_storeb2c(const mp */*m*/, void */*pv*/, size_t /*sz*/);
+
+/*----- Bit operations ----------------------------------------------------*/
+
+/* --- @mp_not@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *
+ * Returns:    The bitwise complement of the source.
+ */
+
+extern mp *mp_not(mp */*d*/, mp */*a*/);
+
+/* --- @mp_bitop@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    The result of the given bitwise operation.  These functions
+ *             don't handle negative numbers at all sensibly.  For that, use
+ *             the @...2c@ variants.  The functions are named after the
+ *             truth tables they generate:
+ *
+ *                     a:      0011
+ *                     b:      0101
+ *                     @mpx_bitXXXX@
+ */
+
+#define MP_BITDECL(string)                                             \
+  extern mp *mp_bit##string(mp */*d*/, mp */*a*/, mp */*b*/);
+MPX_DOBIN(MP_BITDECL)
+
+/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- *
+ *
+ * Synonyms for the commonly-used functions.
+ */
+
+#define mp_and mp_bit0001
+#define mp_or  mp_bit0111
+#define mp_nand mp_bit1110
+#define mp_nor mp_bit1000
+#define mp_xor mp_bit0110
+
+/* --- @mp_testbit@ --- *
+ *
+ * Arguments:  @mp *x@ = a large integer
+ *             @unsigned long n@ = which bit to test
+ *
+ * Returns:    Nonzero if the bit is set, zero if not.
+ */
+
+extern int mp_testbit(mp */*x*/, unsigned long /*n*/);
+
+/* --- @mp_setbit@, @mp_clearbit@ --- *
+ *
+ * Arguments:  @mp *d@ = a destination
+ *             @mp *x@ = a large integer
+ *             @unsigned long n@ = which bit to modify
+ *
+ * Returns:    The argument @x@, with the appropriate bit set or cleared.
+ */
+
+extern mp *mp_setbit(mp */*d*/, mp */*x*/, unsigned long /*n*/);
+extern mp *mp_clearbit(mp */*d*/, mp */*x*/, unsigned long /*n*/);
+
+/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *             @size_t n@ = number of bits to move
+ *
+ * Returns:    Result, @a@ shifted left or right by @n@.
+ *
+ * Use:                Bitwise shift operators.  @mp_lslc@ fills the bits introduced
+ *             on the right with ones instead of zeroes: it's used
+ *             internally by @mp_lsl2c@, though it may be useful on its
+ *             own.
+ */
+
+extern mp *mp_lsl(mp */*d*/, mp */*a*/, size_t /*n*/);
+extern mp *mp_lslc(mp */*d*/, mp */*a*/, size_t /*n*/);
+extern mp *mp_lsr(mp */*d*/, mp */*a*/, size_t /*n*/);
+
+/* --- @mp_not2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *
+ * Returns:    The sign-extended complement of the argument.
+ */
+
+extern mp *mp_not2c(mp */*d*/, mp */*a*/);
+
+/* --- @mp_bitop2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    The result of the given bitwise operation.  Negative numbers
+ *             are treated as two's complement, sign-extended infinitely to
+ *             the left.  The functions are named after the truth tables
+ *             they generate:
+ *
+ *                     a:      0011
+ *                     b:      0101
+ *                     @mpx_bitXXXX@
+ */
+
+#define MP_BIT2CDECL(string)                                           \
+  extern mp *mp_bit##string##2c(mp */*d*/, mp */*a*/, mp */*b*/);
+MPX_DOBIN(MP_BIT2CDECL)
+
+/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- *
+ *
+ * Synonyms for the commonly-used functions.
+ */
+
+#define mp_and2c  mp_bit00012c
+#define mp_or2c          mp_bit01112c
+#define mp_nand2c mp_bit11102c
+#define mp_nor2c  mp_bit10002c
+#define mp_xor2c  mp_bit01102c
+
+/* --- @mp_lsl2c@, @mp_lsr2c@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *             @size_t n@ = number of bits to move
+ *
+ * Returns:    Result, @a@ shifted left or right by @n@.  Handles the
+ *             pretence of sign-extension for negative numbers.
+ */
+
+extern mp *mp_lsl2c(mp */*d*/, mp */*a*/, size_t /*n*/);
+extern mp *mp_lsr2c(mp */*d*/, mp */*a*/, size_t /*n*/);
+
+/* --- @mp_testbit2c@ --- *
+ *
+ * Arguments:  @mp *x@ = a large integer
+ *             @unsigned long n@ = which bit to test
+ *
+ * Returns:    Nonzero if the bit is set, zero if not.  Fakes up two's
+ *             complement representation.
+ */
+
+extern int mp_testbit2c(mp */*x*/, unsigned long /*n*/);
+
+/* --- @mp_setbit2c@, @mp_clearbit2c@ --- *
+ *
+ * Arguments:  @mp *d@ = a destination
+ *             @mp *x@ = a large integer
+ *             @unsigned long n@ = which bit to modify
+ *
+ * Returns:    The argument @x@, with the appropriate bit set or cleared.
+ *             Fakes up two's complement representation.
+ */
+
+extern mp *mp_setbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/);
+extern mp *mp_clearbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/);
+
+/*----- Comparisons -------------------------------------------------------*/
+
+/* --- @mp_eq@ --- *
+ *
+ * Arguments:  @const mp *a, *b@ = two numbers
+ *
+ * Returns:    Nonzero if the numbers are equal.
+ */
+
+extern int mp_eq(const mp */*a*/, const mp */*b*/);
+
+#define MP_EQ(a, b)                                                    \
+  ((((a)->f ^ (b)->f) & MP_NEG) == 0 &&                                        \
+   mpx_ueq((a)->v, (a)->vl, (b)->v, (b)->vl))
+
+/* --- @mp_cmp@ --- *
+ *
+ * Arguments:  @const mp *a, *b@ = two numbers
+ *
+ * Returns:    Less than, equal to or greater than zero, according to
+ *             whether @a@ is less than, equal to or greater than @b@.
+ */
+
+extern int mp_cmp(const mp */*a*/, const mp */*b*/);
+
+#define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0)
+
+/* --- Other handy macros --- */
+
+#define MP_NEGP(x) ((x)->f & MP_NEG)
+#define MP_ZEROP(x) (!MP_LEN(x))
+#define MP_POSP(x) (!MP_NEGP(x) && !MP_ZEROP(x))
+#define MP_ODDP(x) (!MP_ZEROP(x) && ((x)->v[0] & 1u))
+#define MP_EVENP(x) (!MP_ODDP(x))
+
+/*----- Arithmetic operations ---------------------------------------------*/
+
+/* --- @mp_neg@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = argument
+ *
+ * Returns:    The negation of the argument.
+ *
+ * Use:                Negates its argument.
+ */
+
+extern mp *mp_neg(mp */*d*/, mp */*a*/);
+
+/* --- @mp_add@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @a@ added to @b@.
+ */
+
+extern mp *mp_add(mp */*d*/, mp */*a*/, mp */*b*/);
+
+/* --- @mp_sub@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @b@ subtracted from @a@.
+ */
+
+extern mp *mp_sub(mp */*d*/, mp */*a*/, mp */*b*/);
+
+/* --- @mp_mul@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a, *b@ = sources
+ *
+ * Returns:    Result, @a@ multiplied by @b@.
+ */
+
+extern mp *mp_mul(mp */*d*/, mp */*a*/, mp */*b*/);
+
+/* --- @mp_sqr@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *a@ = source
+ *
+ * Returns:    Result, @a@ squared.
+ */
+
+extern mp *mp_sqr(mp */*d*/, mp */*a*/);
+
+/* --- @mp_div@ --- *
+ *
+ * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
+ *             @mp *a, *b@ = sources
+ *
+ * Use:                Calculates the quotient and remainder when @a@ is divided by
+ *             @b@.
+ */
+
+extern void mp_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/);
+
+/* --- @mp_exp@ --- *
+ *
+ * Arguments:  @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e$%.
+ */
+
+extern mp *mp_exp(mp */*d*/, mp */*a*/, mp */*e*/);
+
+/* --- @mp_odd@ --- *
+ *
+ * Arguments:  @mp *d@ = pointer to destination integer
+ *             @mp *m@ = pointer to source integer
+ *             @size_t *s@ = where to store the power of 2
+ *
+ * Returns:    An odd integer integer %$t$% such that %$m = 2^s t$%.
+ *
+ * Use:                Computes a power of two and an odd integer which, when
+ *             multiplied, give a specified result.  This sort of thing is
+ *             useful in number theory quite often.
+ */
+
+extern mp *mp_odd(mp */*d*/, mp */*m*/, size_t */*s*/);
+
+/*----- More advanced algorithms ------------------------------------------*/
+
+/* --- @mp_sqrt@ --- *
+ *
+ * Arguments:  @mp *d@ = pointer to destination integer
+ *             @mp *a@ = (nonnegative) integer to take square root of
+ *
+ * Returns:    The largest integer %$x$% such that %$x^2 \le a$%.
+ *
+ * Use:                Computes integer square roots.
+ *
+ *             The current implementation isn't very good: it uses the
+ *             Newton-Raphson method to find an approximation to %$a$%.  If
+ *             there's any demand for a better version, I'll write one.
+ */
+
+extern mp *mp_sqrt(mp */*d*/, mp */*a*/);
+
+/* --- @mp_gcd@ --- *
+ *
+ * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
+ *             @mp *a, *b@ = sources (must be nonzero)
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
+ *             @ax + by = gcd(a, b)@.  This is useful for computing modular
+ *             inverses.  Neither @a@ nor @b@ may be zero.
+ */
+
+extern void mp_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/,
+                  mp */*a*/, mp */*b*/);
+
+/* -- @mp_modinv@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *x@ = argument
+ *             @mp *p@ = modulus
+ *
+ * Returns:    The inverse %$x^{-1} \bmod p$%.
+ *
+ * Use:                Computes a modular inverse.    An assertion fails if %$p$%
+ *             has no inverse.
+ */
+
+extern mp *mp_modinv(mp */*d*/, mp */*x*/, mp */*p*/);
+
+/* --- @mp_jacobi@ --- *
+ *
+ * Arguments:  @mp *a@ = an integer
+ *             @mp *n@ = another integer
+ *
+ * Returns:    @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%.
+ *
+ * Use:                Computes the Kronecker symbol %$\jacobi{a}{n}$%.  If @n@ is
+ *             prime, this is the Legendre symbol and is equal to 1 if and
+ *             only if @a@ is a quadratic residue mod @n@.  The result is
+ *             zero if and only if @a@ and @n@ have a common factor greater
+ *             than one.
+ *
+ *             If @n@ is composite, then this computes the Kronecker symbol
+ *
+ *               %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$%
+ *
+ *             where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the
+ *             prime factorization of %$n$%.  The missing bits are:
+ *
+ *               * %$\jacobi{a}{1} = 1$%;
+ *               * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if
+ *                 positive;
+ *               * %$\jacobi{a}{0} = 0$%;
+ *               * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is
+ *                 congruent to 1 or 7 (mod 8), or %$-1$% otherwise.
+ *
+ *             If %$n$% is positive and odd, then this is the Jacobi
+ *             symbol.  (The Kronecker symbol is a consistant domain
+ *             extension; the Jacobi symbol was implemented first, and the
+ *             name stuck.)
+ */
+
+extern int mp_jacobi(mp */*a*/, mp */*n*/);
+
+/* --- @mp_modsqrt@ --- *
+ *
+ * Arguments:  @mp *d@ = destination integer
+ *             @mp *a@ = source integer
+ *             @mp *p@ = modulus (must be prime)
+ *
+ * Returns:    If %$a$% is a quadratic residue, a square root of %$a$%; else
+ *             a null pointer.
+ *
+ * Use:                Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%,
+ *             if one exists; else a null pointer.  This function will not
+ *             work if %$p$% is composite: you must factor the modulus, take
+ *             a square root mod each factor, and recombine the results
+ *             using the Chinese Remainder Theorem.
+ *
+ *             We guarantee that the square root returned is the smallest
+ *             one (i.e., the `positive' square root).
+ */
+
+extern mp *mp_modsqrt(mp */*d*/, mp */*a*/, mp */*p*/);
+
+/* --- @mp_modexp@ --- *
+ *
+ * Arguments:  @mp *d@ = fake destination
+ *             @mp *x@ = base of exponentiation
+ *             @mp *e@ = exponent
+ *             @mp *n@ = modulus (must be positive)
+ *
+ * Returns:    The value %$x^e \bmod n$%.
+ */
+
+extern mp *mp_modexp(mp */*d*/, mp */*x*/, mp */*e*/, mp */*n*/);
+
+/*----- Test harness support ----------------------------------------------*/
+
+#include <mLib/testrig.h>
+
+#ifndef CATACOMB_MPTEXT_H
+#  include "mptext.h"
+#endif
+
+extern const test_type type_mp;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mparena.c b/math/mparena.c
new file mode 100644 (file)
index 0000000..bbe5867
--- /dev/null
@@ -0,0 +1,338 @@
+/* -*-c-*-
+ *
+ * Allocation and freeing of MP buffers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/arena.h>
+#include <mLib/exc.h>
+#include <mLib/sub.h>
+
+#include "mparena.h"
+
+/*----- Tweakables --------------------------------------------------------*/
+
+/* --- @MPARENA_TRIVIAL@ --- *
+ *
+ * Make the allocator a passthrough.  It immediately calls the underlying
+ * allocation functions rather than attempting to keep track of blocks
+ * itself.
+ */
+
+#define MPARENA_TRIVIAL
+
+/* --- @MPARENA_DEBUG@ --- *
+ *
+ * The name of an output trace file to which logging information about the
+ * state of arena trees should be written.  If unset, no logging is done.
+ */
+
+/* #define MPARENA_DEBUG "mparena.out" */
+
+/*----- Static variables --------------------------------------------------*/
+
+#ifdef MPARENA_DEBUG
+  static FILE *debugfp = 0;
+
+#  define MPARENA_OPENFILE do {                                                \
+    if (!debugfp) {                                                    \
+      if ((debugfp = fopen(MPARENA_DEBUG, "w")) == 0) {                        \
+       fprintf(stderr, "couldn't open debug output file\n");           \
+       exit(EXIT_FAILURE);                                             \
+      }                                                                        \
+    }                                                                  \
+  } while (0)
+
+#endif
+
+/*----- Standard arenas ---------------------------------------------------*/
+
+mparena mparena_global = MPARENA_INIT;
+mparena mparena_secure = MPARENA_INIT;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @tdump@ --- *
+ *
+ * Arguments:  @mparena_node *n@ = pointer to tree node to dump
+ *
+ * Returns:    ---
+ *
+ * Use:                Recursively dumps out the allocation tree.
+ */
+
+#ifdef MPARENA_DEBUG
+
+static void tdump(mparena_node *n)
+{
+  if (!n)
+    putc('*', debugfp);
+  else {
+    putc('(', debugfp);
+    tdump(n->left);
+    fprintf(debugfp, ", %u, ", n->v[0]);
+    tdump(n->right);
+    putc(')', debugfp);
+  }
+}
+
+#endif
+
+/* --- @mparena_create@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an MP arena so that blocks can be allocated from
+ *             it.
+ */
+
+void mparena_create(mparena *a)
+{
+  a->root = 0;
+  a->n = 0;
+  a->a = &arena_stdlib;
+}
+
+/* --- @mparena_setarena@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to MP arena block
+ *             @arena *aa@ = pointer to arena
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets the underlying arena for an MP arena.
+ */
+
+extern void mparena_setarena(mparena *a, arena *aa) { a->a = aa; }
+
+/* --- @mparena_destroy@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an MP arena, and all the vectors held within it.  The
+ *             blocks which are currently allocated can be freed into some
+ *             other arena.
+ */
+
+static void tfree(mparena *a, mparena_node *n)
+{
+  A_FREE(a->a, n->v);
+  if (n->left)
+    tfree(a, n->left);
+  if (n->right)
+    tfree(a, n->right);
+  DESTROY(n);
+}
+
+void mparena_destroy(mparena *a)
+{
+  tfree(a, a->root);
+  a->root = 0;
+}
+
+/* --- @mparena_count@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *
+ * Returns:    Number of allocated blocks from this arena.
+ *
+ * Use:                Reports the number of blocks allocated from the arena and not
+ *             yet freed.
+ */
+
+unsigned mparena_count(mparena *a)
+{
+  return (a->n);
+}
+
+/* --- @mpalloc@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *             @size_t sz@ = number of digits required
+ *
+ * Returns:    Pointer to a suitably sized block.
+ *
+ * Use:                Allocates a lump of data suitable for use as an array of MP
+ *             digits.
+ */
+
+#ifdef MPARENA_TRIVIAL
+
+mpw *mpalloc(mparena *a, size_t sz)
+{
+  mpw *v;
+  if (!sz) return (0);
+  a->n++;
+  v = A_ALLOC(a->a, MPWS(sz));
+  if (!v)
+    THROW(EXC_NOMEM);
+  return (v);
+}
+
+#else
+
+mpw *mpalloc(mparena *a, size_t sz)
+{
+  mparena_node **nn, *n;
+  mpw *v;
+
+  nn = &a->root;
+
+#ifdef MPARENA_DEBUG
+  MPARENA_OPENFILE;
+  fprintf(debugfp, "alloc %u\n before: ", sz);
+  tdump(a->root); putc('\n', debugfp);
+#endif
+
+  /* --- First, find a block which is big enough --- */
+
+again:
+  n = *nn;
+  if (!n) {
+#ifdef MPARENA_DEBUG
+    fputs("  failed\n", debugfp);
+#endif
+    if ((v = A_ALLOC(a->a, MPWS(sz + 1))) == 0)
+      THROW(EXC_NOMEM);
+    v[0] = sz;
+    a->n++;
+    return (v + 1);
+  }
+  if (n->v[0] < sz) {
+    nn = &n->right;
+    goto again;
+  }
+
+  /* --- Now try to find a smaller block which is suitable --- */
+
+  while (n->left && n->left->v[0] >= sz) {
+    nn = &n->left;
+    n = *nn;
+  }
+
+  /* --- If the block we've got is still too large, start digging --- */
+
+  if (n->v[0] > sz * 2) {
+    nn = &n->left;
+    goto again;
+  }
+
+  /* --- I've now found a suitable block --- */
+
+  v = n->v;
+
+  /* --- Remove this node from the tree --- */
+
+  if (!n->left)
+    *nn = n->right;
+  else if (!n->right)
+    *nn = n->left;
+  else {
+    mparena_node *left = n->left;
+    mparena_node *p = *nn = n->right;
+    while (p->left)
+      p = p->left;
+    p->left = left;
+  }
+
+#ifdef MPARENA_DEBUG
+  fputs("  after: ", debugfp);
+  tdump(a->root); putc('\n', debugfp);
+#endif
+
+  /* --- Get rid of this node now --- */
+
+  DESTROY(n);
+  a->n++;
+  return (v + 1);
+}
+
+#endif
+
+/* --- @mpfree@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *             @mpw *v@ = pointer to allocated vector
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns an MP vector to an arena.
+ */
+
+#ifdef MPARENA_TRIVIAL
+
+void mpfree(mparena *a, mpw *v)
+{
+  if (!v) return;
+  a->n--;
+  A_FREE(a->a, v);
+}
+
+#else
+
+void mpfree(mparena *a, mpw *v)
+{
+  mparena_node **nn, *n;
+  size_t sz = *--v;
+
+#ifdef MPARENA_DEBUG
+  MPARENA_OPENFILE;
+  fprintf(debugfp, "free %u\n  before: ", sz);
+  tdump(a->root); putc('\n', debugfp);
+#endif
+
+  nn = &a->root;
+  while (*nn) {
+    n = *nn;
+    if (n->v[0] > sz)
+      nn = &n->left;
+    else
+      nn = &n->right;
+  }
+
+  n = CREATE(mparena_node);
+  n->left = n->right = 0;
+  n->v = v;
+  *nn = n;
+  a->n--;
+
+#ifdef MPARENA_DEBUG
+  fputs("  after: ", debugfp);
+  tdump(a->root); putc('\n', debugfp);
+#endif
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mparena.h b/math/mparena.h
new file mode 100644 (file)
index 0000000..21cacf1
--- /dev/null
@@ -0,0 +1,160 @@
+/* -*-c-*-
+ *
+ * Allocation and freeing of MP buffers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPARENA_H
+#define CATACOMB_MPARENA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/arena.h>
+
+#ifndef CATACOMB_MPW_H
+#  include "mpw.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- @mparena_node@ --- *
+ *
+ * For internal use by the MP arena manager.  The free blocks are held in a
+ * binary tree by size, held in the first digit of each vector.
+ */
+
+typedef struct mparena_node {
+  struct mparena_node *left, *right;
+  mpw *v;
+} mparena_node;
+
+/* --- @mparena@ --- *
+ *
+ * The actual arena.
+ */
+
+typedef struct mparena {
+  mparena_node *root;
+  unsigned n;
+  arena *a;
+} mparena;
+
+/*----- Standard arenas ---------------------------------------------------*/
+
+extern mparena mparena_global;
+#define MPARENA_GLOBAL (&mparena_global)
+
+extern mparena mparena_secure;
+#define MPARENA_SECURE (&mparena_secure)
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mparena_create@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an MP arena so that blocks can be allocated from
+ *             it.
+ */
+
+extern void mparena_create(mparena */*a*/);
+
+#define MPARENA_INIT { 0, 0, &arena_stdlib }
+
+/* --- @mparena_setarena@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to MP arena block
+ *             @arena *aa@ = pointer to arena
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets the underlying arena for an MP arena.
+ */
+
+extern void mparena_setarena(mparena */*a*/, arena */*aa*/);
+
+/* --- @mparena_destroy@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an MP arena, and all the vectors held within it.  The
+ *             blocks which are currently allocated can be freed into some
+ *             other MP arena, as long as the underlying arenas are the
+ *             same.
+ */
+
+extern void mparena_destroy(mparena */*a*/);
+
+/* --- @mparena_count@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *
+ * Returns:    Number of allocated blocks from this arena.
+ *
+ * Use:                Reports the number of blocks allocated from the arena and not
+ *             yet freed.
+ */
+
+extern unsigned mparena_count(mparena */*a*/);
+
+/* --- @mpalloc@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *             @size_t sz@ = number of digits required
+ *
+ * Returns:    Pointer to a suitably sized block.
+ *
+ * Use:                Allocates a lump of data suitable for use as an array of MP
+ *             digits.
+ */
+
+extern mpw *mpalloc(mparena */*a*/, size_t /*sz*/);
+
+/* --- @mpfree@ --- *
+ *
+ * Arguments:  @mparena *a@ = pointer to arena block
+ *             @mpw *v@ = pointer to allocated vector
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns an MP vector to an arena.
+ */
+
+extern void mpfree(mparena */*a*/, mpw */*v*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpbarrett-exp.c b/math/mpbarrett-exp.c
new file mode 100644 (file)
index 0000000..44cad7e
--- /dev/null
@@ -0,0 +1,122 @@
+/* -*-c-*-
+ *
+ * Modular exponentiation using Barrett reduction
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpbarrett.h"
+#include "mpbarrett-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpbarrett_exp@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e \bmod m$%.
+ */
+
+mp *mpbarrett_exp(mpbarrett *mb, mp *d, mp *a, mp *e)
+{
+  mp *x = MP_ONE;
+  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
+
+  MP_COPY(a);
+  MP_SHRINK(e);
+  if (MP_ZEROP(e))
+    ;
+  else {
+    if (MP_NEGP(e))
+      a = mp_modinv(a, a, mb->m);
+    if (MP_LEN(e) < EXP_THRESH)
+      EXP_SIMPLE(x, a, e);
+    else
+      EXP_WINDOW(x, a, e);
+  }
+  mp_drop(d);
+  mp_drop(spare);
+  mp_drop(a);
+  return (x);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int vexp(dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  mp *a = *(mp **)v[1].buf;
+  mp *b = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *mr;
+  int ok = 1;
+
+  mpbarrett mb;
+  mpbarrett_create(&mb, m);
+
+  mr = mpbarrett_exp(&mb, MP_NEW, a, b);
+
+  if (!MP_EQ(mr, r)) {
+    fputs("\n*** barrett modexp failed", stderr);
+    fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\n e = ", stderr); mp_writefile(b, stderr, 10);
+    fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(m);
+  mp_drop(a);
+  mp_drop(b);
+  mp_drop(r);
+  mp_drop(mr);
+  mpbarrett_destroy(&mb);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return ok;
+}
+
+static test_chunk tests[] = {
+  { "mpbarrett-exp", vexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mpbarrett");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpbarrett-exp.h b/math/mpbarrett-exp.h
new file mode 100644 (file)
index 0000000..08741f3
--- /dev/null
@@ -0,0 +1,74 @@
+/* -*-c-*-
+ *
+ * Exponentiation operations for Barrett reduction
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_MPBARRETT_EXP_H
+#define CATACOMB_MPBARRETT_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentation definitions -----------------------------------------*/
+
+#define EXP_TYPE mp *
+
+#define EXP_COPY(d, x) d = MP_COPY(x)
+#define EXP_DROP(x) MP_DROP(x)
+
+#define EXP_MUL(a, x) do {                                             \
+  mp *t = mp_mul(spare, a, x);                                         \
+  spare = a;                                                           \
+  a = mpbarrett_reduce(mb, t, t);                                      \
+} while (0)
+
+#define EXP_SQR(a) do {                                                        \
+  mp *t = mp_sqr(spare, a);                                            \
+  spare = a;                                                           \
+  a = mpbarrett_reduce(mb, t, t);                                      \
+} while (0)
+
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) do {                                       \
+  d = mp_mul(MP_NEW, x, y);                                            \
+  d = mpbarrett_reduce(mb, d, d);                                      \
+} while (0)
+
+#define EXP_SETSQR(d, x) do {                                          \
+  d = mp_sqr(MP_NEW, x);                                               \
+  d = mpbarrett_reduce(mb, d, d);                                      \
+} while (0)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpbarrett-mexp.c b/math/mpbarrett-mexp.c
new file mode 100644 (file)
index 0000000..a221f10
--- /dev/null
@@ -0,0 +1,175 @@
+/* -*-c-*-
+ *
+ * Multiple simultaneous exponentiations
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpbarrett.h"
+
+#define EXP_WINSZ 3
+#include "mpbarrett-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpbarrett_mexp@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *             @mp *d@ = fake destination
+ *             @const mp_expfactor *f@ = pointer to array of factors
+ *             @size_t n@ = number of factors supplied
+ *
+ * Returns:    If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the
+ *             exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result
+ *             is:
+ *
+ *             %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$%
+ */
+
+mp *mpbarrett_mexp(mpbarrett *mb, mp *d, const mp_expfactor *f, size_t n)
+{
+  mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor));
+  mp *a = MP_ONE;
+  mp *spare;
+  mp *g = MP_NEW;
+  size_t i;
+
+  spare = MP_NEW;
+  for (i = 0; i < n; i++) {
+    if (f[i].exp->f & MP_BURN)
+      spare = MP_NEWSEC;
+    if (MP_NEGP(f[i].exp))
+      ff[i].base = mp_modinv(MP_NEW, f[i].base, mb->m);
+    else
+      ff[i].base = MP_COPY(f[i].base);
+    ff[i].exp = f[i].exp;
+  }
+  mp_drop(g);
+  EXP_SIMUL(a, ff, n);
+  mp_drop(d);
+  mp_drop(spare);
+  for (i = 0; i < n; i++)
+    mp_drop(ff[i].base);
+  xfree(ff);
+  return (a);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int verify(size_t n, dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  mp_expfactor *f = xmalloc(n * sizeof(*f));
+  mp *r, *rr;
+  size_t i, j;
+  mpbarrett mb;
+  int ok = 1;
+
+  j = 1;
+  for (i = 0; i < n; i++) {
+    f[i].base = *(mp **)v[j++].buf;
+    f[i].exp = *(mp **)v[j++].buf;
+  }
+
+  rr = *(mp **)v[j].buf;
+  mpbarrett_create(&mb, m);
+  r = mpbarrett_mexp(&mb, MP_NEW, f, n);
+  if (!MP_EQ(r, rr)) {
+    fputs("\n*** mexp failed\n", stderr);
+    fputs("m = ", stderr); mp_writefile(m, stderr, 10);
+    for (i = 0; i < n; i++) {
+      fprintf(stderr, "\ng_%u = ", i);
+      mp_writefile(f[i].base, stderr, 10);
+      fprintf(stderr, "\ne_%u = ", i);
+      mp_writefile(f[i].exp, stderr, 10);
+    }
+    fputs("\nr = ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\nR = ", stderr); mp_writefile(rr, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  for (i = 0; i < n; i++) {
+    MP_DROP(f[i].base);
+    MP_DROP(f[i].exp);
+  }
+  MP_DROP(m);
+  MP_DROP(r);
+  MP_DROP(rr);
+  mpbarrett_destroy(&mb);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int t1(dstr *v) { return verify(1, v); }
+static int t2(dstr *v) { return verify(2, v); }
+static int t3(dstr *v) { return verify(3, v); }
+static int t4(dstr *v) { return verify(4, v); }
+static int t5(dstr *v) { return verify(5, v); }
+
+static test_chunk tests[] = {
+  { "mexp-1", t1, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "mexp-2", t2, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "mexp-3", t3, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "mexp-4", t4, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "mexp-5", t5, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mpbarrett");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpbarrett.c b/math/mpbarrett.c
new file mode 100644 (file)
index 0000000..cadb9b3
--- /dev/null
@@ -0,0 +1,211 @@
+/* -*-c-*-
+ *
+ * Barrett modular reduction
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpbarrett.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpbarrett_create@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *             @mp *m@ = modulus to work to
+ *
+ *
+ * Returns:    Zero on success, nonzero on error.
+ *
+ * Use:                Initializes a Barrett reduction context ready for use.
+ */
+
+int mpbarrett_create(mpbarrett *mb, mp *m)
+{
+  mp *b;
+
+  /* --- Validate the arguments --- */
+
+  if (!MP_POSP(m))
+    return (-1);
+
+  /* --- Compute %$\mu$% --- */
+
+  mp_shrink(m);
+  mb->k = MP_LEN(m);
+  mb->m = MP_COPY(m);
+  b = mp_new(2 * mb->k + 1, 0);
+  MPX_ZERO(b->v, b->vl - 1);
+  b->vl[-1] = 1;
+  mp_div(&b, 0, b, m);
+  mb->mu = b;
+  return (0);
+}
+
+/* --- @mpbarrett_destroy@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a Barrett reduction context releasing any resources
+ *             claimed.
+ */
+
+void mpbarrett_destroy(mpbarrett *mb)
+{
+  mp_drop(mb->m);
+  mp_drop(mb->mu);
+}
+
+/* --- @mpbarrett_reduce@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *             @mp *d@ = destination for result
+ *             @mp *m@ = number to reduce
+ *
+ * Returns:    The residue of @m@ modulo the number in the reduction
+ *             context.
+ *
+ * Use:                Performs an efficient modular reduction.
+ */
+
+mp *mpbarrett_reduce(mpbarrett *mb, mp *d, mp *m)
+{
+  mp *q;
+  size_t k = mb->k;
+
+  /* --- Special case if @m@ is too small --- */
+
+  if (MP_LEN(m) < k) {
+    m = MP_COPY(m);
+    if (d)
+      MP_DROP(d);
+    return (m);
+  }
+
+  /* --- First stage --- */
+
+  {
+    mp qq;
+    mp_build(&qq, m->v + (k - 1), m->vl);
+    q = mp_mul(MP_NEW, &qq, mb->mu);
+    if (MP_LEN(q) <= k) {
+      m = MP_COPY(m);
+      if (d)
+       MP_DROP(d);
+      MP_DROP(q);
+      return (m);
+    }
+  }
+
+  /* --- Second stage --- */
+
+  {
+    mp *r;
+    mpw *mvl;
+
+    MP_COPY(m);
+    if (MP_LEN(m) <= k + 1)
+      mvl = m->vl;
+    else
+      mvl = m->v + k + 1;
+    r = mp_new(k + 1, (q->f | mb->m->f) & MP_BURN);
+    mpx_umul(r->v, r->vl, q->v + k + 1, q->vl, mb->m->v, mb->m->vl);
+    MP_DEST(d, k + 1, r->f | MP_UNDEF);
+    mpx_usub(d->v, d->vl, m->v, mvl, r->v, r->vl);
+    d->f = (m->f | r->f) & (MP_BURN | MP_NEG);
+    MP_DROP(r);
+    MP_DROP(q);
+    MP_DROP(m);
+  }
+
+  /* --- Final stage --- */
+
+  MP_SHRINK(d);
+  while (MPX_UCMP(d->v, d->vl, >=, mb->m->v, mb->m->vl))
+    mpx_usub(d->v, d->vl, d->v, d->vl, mb->m->v, mb->m->vl);
+
+  /* --- Fix up the sign --- */
+
+  if (d->f & MP_NEG) {
+    mpx_usub(d->v, d->vl, mb->m->v, mb->m->vl, d->v, d->vl);
+    d->f &= ~MP_NEG;
+  }
+
+  MP_SHRINK(d);
+  return (d);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int vmod(dstr *v)
+{
+  mp *x = *(mp **)v[0].buf;
+  mp *n = *(mp **)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *s;
+  mpbarrett mb;
+  int ok = 1;
+
+  mpbarrett_create(&mb, n);
+  s = mpbarrett_reduce(&mb, MP_NEW, x);
+
+  if (!MP_EQ(s, r)) {
+    fputs("\n*** barrett reduction failure\n", stderr);
+    fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr);
+    fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr);
+    fputs("r = ", stderr); mp_writefile(r, stderr, 10); fputc('\n', stderr);
+    fputs("s = ", stderr); mp_writefile(s, stderr, 10); fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mpbarrett_destroy(&mb);
+  mp_drop(x);
+  mp_drop(n);
+  mp_drop(r);
+  mp_drop(s);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "mpbarrett-reduce", vmod, { &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mpbarrett");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpbarrett.h b/math/mpbarrett.h
new file mode 100644 (file)
index 0000000..40e0fe4
--- /dev/null
@@ -0,0 +1,141 @@
+/* -*-c-*-
+ *
+ * Barrett modular reduction
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on Barrett reduction ----------------------------------------*
+ *
+ * Barrett reduction is a technique for computing modular residues.  Unlike
+ * Montgomery reduction, it doesn't have restrictions on the modulus (except
+ * that it be positive) and doesn't confuse matters by putting an extra
+ * factor all the way through your computation.
+ *
+ * It's useful for slightly less heavy-duty work than Montgomery reduction
+ * because the precomputation phase is rather simpler, involving a single
+ * division operation.
+ *
+ * Sometimes it's useful to exponentiate modulo an even number, so there's a
+ * modexp routine provided which uses Barrett reduction rather than
+ * Montgomery reduction.  This is handy when you're working on indices in an
+ * even-order cyclic group or something.
+ */
+
+#ifndef CATACOMB_MPBARRETT_H
+#define CATACOMB_MPBARRETT_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct mpbarrett {
+  mp *m;
+  mp *mu;
+  size_t k;
+} mpbarrett;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mpbarrett_create@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *             @mp *m@ = modulus to work to
+ *
+ * Returns:    Zero on success, nonzero on error.
+ *
+ * Use:                Initializes a Barrett reduction context ready for use.
+ */
+
+extern int mpbarrett_create(mpbarrett */*mb*/, mp */*m*/);
+
+/* --- @mpbarrett_destroy@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a Barrett reduction context releasing any resources
+ *             claimed.
+ */
+
+extern void mpbarrett_destroy(mpbarrett */*mb*/);
+
+/* --- @mpbarrett_reduce@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *             @mp *d@ = destination for result
+ *             @mp *m@ = number to reduce
+ *
+ * Returns:    The residue of @m@ modulo the number in the reduction
+ *             context.
+ *
+ * Use:                Performs an efficient modular reduction.
+ */
+
+extern mp *mpbarrett_reduce(mpbarrett */*mb*/, mp */*d*/, mp */*m*/);
+
+/* --- @mpbarrett_exp@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e \bmod m$%.
+ */
+
+extern mp *mpbarrett_exp(mpbarrett */*mb*/, mp */*d*/, mp */*a*/, mp */*e*/);
+
+/* --- @mpbarrett_mexp@ --- *
+ *
+ * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
+ *             @mp *d@ = fake destination
+ *             @const mp_expfactor *f@ = pointer to array of factors
+ *             @size_t n@ = number of factors supplied
+ *
+ * Returns:    If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the
+ *             exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result
+ *             is:
+ *
+ *             %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$%
+ */
+
+extern mp *mpbarrett_mexp(mpbarrett */*mb*/, mp */*d*/,
+                         const mp_expfactor */*f*/, size_t /*n*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpcrt.c b/math/mpcrt.c
new file mode 100644 (file)
index 0000000..a8f805f
--- /dev/null
@@ -0,0 +1,291 @@
+/* -*-c-*-
+ *
+ * Chinese Remainder Theorem computations (Gauss's algorithm)
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpcrt.h"
+#include "mpmul.h"
+#include "mpbarrett.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpcrt_create@ --- *
+ *
+ * Arguments:  @mpcrt *c@ = pointer to CRT context
+ *             @mpcrt_mod *v@ = pointer to vector of moduli
+ *             @size_t k@ = number of moduli
+ *             @mp *n@ = product of all moduli (@MP_NEW@ if unknown)
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context for solving Chinese Remainder Theorem
+ *             problems.  The vector of moduli can be incomplete.  Omitted
+ *             items must be left as null pointers.  Not all combinations of
+ *             missing things can be coped with, even if there is
+ *             technically enough information to cope.  For example, if @n@
+ *             is unspecified, all the @m@ values must be present, even if
+ *             there is one modulus with both @m@ and @n@ (from which the
+ *             product of all moduli could clearly be calculated).
+ */
+
+void mpcrt_create(mpcrt *c, mpcrt_mod *v, size_t k, mp *n)
+{
+  size_t i;
+
+  /* --- Simple initialization things --- */
+
+  c->k = k;
+  c->v = v;
+
+  /* --- Work out @n@ if I don't have it already --- */
+
+  if (n != MP_NEW)
+    n = MP_COPY(n);
+  else {
+    mpmul mm;
+    mpmul_init(&mm);
+    for (i = 0; i < k; i++)
+      mpmul_add(&mm, v[i].m);
+    n = mpmul_done(&mm);
+  }
+
+  /* --- A quick hack if %$k = 2$% --- */
+
+  if (k == 2) {
+
+    /* --- The %$n / n_i$% values are trivial in this case --- */
+
+    if (!v[0].n)
+      v[0].n = MP_COPY(v[1].m);
+    if (!v[1].n)
+      v[1].n = MP_COPY(v[0].m);
+
+    /* --- Now sort out the inverses --- *
+     *
+     * @mp_gcd@ will ensure that the first argument is negative.
+     */
+
+    if (!v[0].ni && !v[1].ni) {
+      mp *g = MP_NEW;
+      mp_gcd(&g, &v[0].ni, &v[1].ni, v[0].n, v[1].n);
+      assert(MP_EQ(g, MP_ONE));
+      mp_drop(g);
+      v[0].ni = mp_add(v[0].ni, v[0].ni, v[1].n);
+    } else {
+      int i, j;
+      mp *x;
+
+      if (!v[0].ni)
+       i = 0, j = 1;
+      else
+       i = 1, j = 0;
+
+      x = mp_mul(MP_NEW, v[j].n, v[j].ni);
+      x = mp_sub(x, x, MP_ONE);
+      mp_div(&x, 0, x, v[i].n);
+      v[i].ni = x;
+    }
+  }
+
+  /* --- Set up the Barrett context --- */
+
+  mpbarrett_create(&c->mb, n);
+
+  /* --- Walk through filling in @n@, @ni@ and @nnir@ --- */
+
+  for (i = 0; i < k; i++) {
+    if (!v[i].n)
+      mp_div(&v[i].n, 0, n, v[i].m);
+    if (!v[i].ni)
+      v[i].ni = mp_modinv(MP_NEW, v[i].n, v[i].m);
+    if (!v[i].nni)
+      v[i].nni = mp_mul(MP_NEW, v[i].n, v[i].ni);
+  }
+
+  /* --- Done --- */
+
+  mp_drop(n);
+}
+
+/* --- @mpcrt_destroy@ --- *
+ *
+ * Arguments:  @mpcrt *c@ - pointer to CRT context
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a CRT context, releasing all the resources it holds.
+ */
+
+void mpcrt_destroy(mpcrt *c)
+{
+  size_t i;
+
+  for (i = 0; i < c->k; i++) {
+    if (c->v[i].m) mp_drop(c->v[i].m);
+    if (c->v[i].n) mp_drop(c->v[i].n);
+    if (c->v[i].ni) mp_drop(c->v[i].ni);
+    if (c->v[i].nni) mp_drop(c->v[i].nni);
+  }
+  mpbarrett_destroy(&c->mb);
+}
+
+/* --- @mpcrt_solve@ --- *
+ *
+ * Arguments:  @mpcrt *c@ = pointer to CRT context
+ *             @mp *d@ = fake destination
+ *             @mp **v@ = array of residues
+ *
+ * Returns:    The unique solution modulo the product of the individual
+ *             moduli, which leaves the given residues.
+ *
+ * Use:                Constructs a result given its residue modulo an array of
+ *             coprime integers.  This can be used to improve performance of
+ *             RSA encryption or Blum-Blum-Shub generation if the factors
+ *             of the modulus are known, since results can be computed mod
+ *             each of the individual factors and then combined at the end.
+ *             This is rather faster than doing the full-scale modular
+ *             exponentiation.
+ */
+
+mp *mpcrt_solve(mpcrt *c, mp *d, mp **v)
+{
+  mp *a = MP_ZERO;
+  mp *x = MP_NEW;
+  size_t i;
+
+  for (i = 0; i < c->k; i++) {
+    x = mp_mul(x, c->v[i].nni, v[i]);
+    x = mpbarrett_reduce(&c->mb, x, x);
+    a = mp_add(a, a, x);
+  }
+  if (x)
+    MP_DROP(x);
+  a = mpbarrett_reduce(&c->mb, a, a);
+  if (d != MP_NEW)
+    MP_DROP(d);
+  return (a);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int verify(size_t n, dstr *v)
+{
+  mpcrt_mod *m = xmalloc(n * sizeof(mpcrt_mod));
+  mp **r = xmalloc(n * sizeof(mp *));
+  mpcrt c;
+  mp *a, *b;
+  size_t i;
+  int ok = 1;
+
+  for (i = 0; i < n; i++) {
+    r[i] = *(mp **)v[2 * i].buf;
+    m[i].m = *(mp **)v[2 * i + 1].buf;
+    m[i].n = 0;
+    m[i].ni = 0;
+    m[i].nni = 0;
+  }
+  a = *(mp **)v[2 * n].buf;
+
+  mpcrt_create(&c, m, n, 0);
+  b = mpcrt_solve(&c, MP_NEW, r);
+
+  if (!MP_EQ(a, b)) {
+    fputs("\n*** failed\n", stderr);
+    fputs("n = ", stderr);
+    mp_writefile(c.mb.m, stderr, 10);
+    for (i = 0; i < n; i++) {
+      fprintf(stderr, "\nr[%u] = ", i);
+      mp_writefile(r[i], stderr, 10);
+      fprintf(stderr, "\nm[%u] = ", i);
+      mp_writefile(m[i].m, stderr, 10);
+      fprintf(stderr, "\nN[%u] = ", i);
+      mp_writefile(m[i].n, stderr, 10);
+      fprintf(stderr, "\nM[%u] = ", i);
+      mp_writefile(m[i].ni, stderr, 10);
+    }
+    fputs("\nresult = ", stderr);
+    mp_writefile(b, stderr, 10);
+    fputs("\nexpect = ", stderr);
+    mp_writefile(a, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  for (i = 0; i < n; i++)
+    mp_drop(r[i]);
+  mp_drop(a);
+  mp_drop(b);
+  mpcrt_destroy(&c);
+  xfree(m);
+  xfree(r);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int crt1(dstr *v) { return verify(1, v); }
+static int crt2(dstr *v) { return verify(2, v); }
+static int crt3(dstr *v) { return verify(3, v); }
+static int crt4(dstr *v) { return verify(4, v); }
+static int crt5(dstr *v) { return verify(5, v); }
+
+static test_chunk tests[] = {
+  { "crt-1", crt1, { &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "crt-2", crt2, { &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "crt-3", crt3, { &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "crt-4", crt4, { &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "crt-5", crt5, { &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mpcrt");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpcrt.h b/math/mpcrt.h
new file mode 100644 (file)
index 0000000..cebdce5
--- /dev/null
@@ -0,0 +1,123 @@
+/* -*-c-*-
+ *
+ * Chinese Remainder Theorem computations (Gauss's algorithm)
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPCRT_H
+#define CATACOMB_MPCRT_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_MPBARRETT_H
+#  include "mpbarrett.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct mpcrt_mod {
+  mp *m;                               /* %$n_i$% -- the modulus */
+  mp *n;                               /* %$N_i = n / n_i$% */
+  mp *ni;                              /* %$M_i = N_i^{-1} \bmod n_i$% */
+  mp *nni;                             /* %$N_i M_i \bmod m$% */
+} mpcrt_mod;
+
+typedef struct mpcrt {
+  size_t k;                            /* Number of distinct moduli */
+  mpbarrett mb;                                /* Barrett context for product */
+  mpcrt_mod *v;                                /* Vector of information for each */
+} mpcrt;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mpcrt_create@ --- *
+ *
+ * Arguments:  @mpcrt *c@ = pointer to CRT context
+ *             @mpcrt_mod *v@ = pointer to vector of moduli
+ *             @size_t k@ = number of moduli
+ *             @mp *n@ = product of all moduli (@MP_NEW@ if unknown)
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context for solving Chinese Remainder Theorem
+ *             problems.  The vector of moduli can be incomplete.  Omitted
+ *             items must be left as null pointers.  Not all combinations of
+ *             missing things can be coped with, even if there is
+ *             technically enough information to cope.  For example, if @n@
+ *             is unspecified, all the @m@ values must be present, even if
+ *             there is one modulus with both @m@ and @n@ (from which the
+ *             product of all moduli could clearly be calculated).
+ */
+
+extern void mpcrt_create(mpcrt */*c*/, mpcrt_mod */*v*/,
+                        size_t /*k*/, mp */*n*/);
+
+/* --- @mpcrt_destroy@ --- *
+ *
+ * Arguments:  @mpcrt *c@ - pointer to CRT context
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a CRT context, releasing all the resources it holds.
+ */
+
+extern void mpcrt_destroy(mpcrt */*c*/);
+
+/* --- @mpcrt_solve@ --- *
+ *
+ * Arguments:  @mpcrt *c@ = pointer to CRT context
+ *             @mp *d@ = fake destination
+ *             @mp **v@ = array of residues
+ *
+ * Returns:    The unique solution modulo the product of the individual
+ *             moduli, which leaves the given residues.
+ *
+ * Use:                Constructs a result given its residue modulo an array of
+ *             coprime integers.  This can be used to improve performance of
+ *             RSA encryption or Blum-Blum-Shub generation if the factors
+ *             of the modulus are known, since results can be computed mod
+ *             each of the individual factors and then combined at the end.
+ *             This is rather faster than doing the full-scale modular
+ *             exponentiation.
+ */
+
+extern mp *mpcrt_solve(mpcrt */*c*/, mp */*d*/, mp **/*v*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpdump.c b/math/mpdump.c
new file mode 100644 (file)
index 0000000..3eb2883
--- /dev/null
@@ -0,0 +1,72 @@
+/* -*-c-*-
+ *
+ * Dump a multiprecision integer as C data
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  mp *x;
+  int i;
+  int w, n;
+
+  if (argc != 2) {
+    fprintf(stderr, "%s: missing argument\n", argv[0]);
+    return (1);
+  }
+  if ((x = mp_readstring(0, argv[1], 0, 0)) == 0) {
+    fprintf(stderr, "%s: bad integer `%s'", argv[0], argv[1]);
+    return (1);
+  }
+  fputs("  ", stdout);
+  w = (MPW_BITS + 3)/4;
+  n = 1;
+  while (2 + 2 * n * (4 + w) < 72) n <<= 1;
+  i = 0;
+  for (;;) {
+    printf("0x%0*x", w, x->v[i]);
+    i++;
+    if (i >= MP_LEN(x)) break;
+    fputs(",", stdout);
+    if (i % n) fputs(" ", stdout); else fputs("\n  ", stdout);
+  }
+  if (fflush(stdout) || ferror(stdout)) {
+    fprintf(stderr, "%s: error writing data: %s", argv[0], strerror(errno));
+    return (1);
+  }
+  fputs("\n", stdout);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpint.c b/math/mpint.c
new file mode 100644 (file)
index 0000000..d89fb07
--- /dev/null
@@ -0,0 +1,177 @@
+/* -*-c-*-
+ *
+ * Conversion between MPs and standard C integers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mpint.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Conversion from C integers --- */
+
+#define FROM(name, type)                                               \
+  mp *mp_from##name(mp *d, type i) {                                   \
+    MP_FROMINT(d, type, i);                                            \
+    return (d);                                                                \
+  }
+
+FROM(short, short)
+FROM(ushort, unsigned short)
+FROM(int, int)
+FROM(uint, unsigned)
+FROM(uint32, uint32)
+FROM(long, long)
+FROM(ulong, unsigned long)
+
+#undef FROM
+
+/* --- Conversion to C integers --- */
+
+#define TO(name, type, max)                                            \
+  type mp_to##name(const mp *m)                                                \
+  {                                                                    \
+    type i;                                                            \
+    MP_TOINT(m, type, max, i);                                         \
+    return (i);                                                                \
+  }
+
+TO(short, short, SHRT_MAX)
+TO(ushort, unsigned short, USHRT_MAX)
+TO(int, int, INT_MAX)
+TO(uint, unsigned, UINT_MAX)
+TO(uint32, uint32, 0xffffffff)
+TO(long, long, LONG_MAX)
+TO(ulong, unsigned long, ULONG_MAX)
+
+#undef TO
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int fromuint(dstr *v)
+{
+  unsigned long i = *(unsigned long *)v[0].buf;
+  mp *m = *(mp **)v[1].buf;
+  mp *d = mp_fromuint(MP_NEW, i);
+  int ok = 1;
+
+  if (!MP_EQ(d, m)) {
+    fputs("\n*** fromint failed.\n", stderr);
+    fprintf(stderr, "i = %lu", i);
+    fputs("\nexpect = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\nresult = ", stderr); mp_writefile(d, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(m);
+  mp_drop(d);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int fromint(dstr *v)
+{
+  long i = *(long *)v[0].buf;
+  mp *m = *(mp **)v[1].buf;
+  mp *d = mp_fromint(MP_NEW, i);
+  int ok = 1;
+
+  if (!MP_EQ(d, m)) {
+    fputs("\n*** fromint failed.\n", stderr);
+    fprintf(stderr, "i = %li", i);
+    fputs("\nexpect = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\nresult = ", stderr); mp_writefile(d, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(m);
+  mp_drop(d);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int touint(dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  unsigned long i = *(unsigned long *)v[1].buf;
+  unsigned j = mp_touint(m);
+  int ok = 1;
+
+  if ((unsigned)i != j) {
+    fputs("\n*** touint failed.\n", stderr);
+    fputs("m = ", stderr); mp_writefile(m, stderr, 10);
+    fprintf(stderr, "\nexpect = %lu; result = %u\n", i, j);
+    ok = 0;
+  }
+
+  mp_drop(m);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int toint(dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  long i = *(long *)v[1].buf;
+  int j = mp_toint(m);
+  int ok = 1;
+
+  if (i != j) {
+    fputs("\n*** toint failed.\n", stderr);
+    fputs("m = ", stderr); mp_writefile(m, stderr, 10);
+    fprintf(stderr, "\nexpect = %li; result = %i\n", i, j);
+    ok = 0;
+  }
+
+  mp_drop(m);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "fromuint", fromuint, { &type_ulong, &type_mp, 0 } },
+  { "fromint", fromint, { &type_long, &type_mp, 0 } },
+  { "touint", touint, { &type_mp, &type_ulong, 0 } },
+  { "toint", toint, { &type_mp, &type_long, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mpint");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpint.h b/math/mpint.h
new file mode 100644 (file)
index 0000000..7867f6a
--- /dev/null
@@ -0,0 +1,190 @@
+/* -*-c-*-
+ *
+ * Conversion between MPs and standard C integers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPINT_H
+#define CATACOMB_MPINT_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <limits.h>
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Generic translation macros ----------------------------------------*/
+
+/* --- @MP_FROMINT@ --- *
+ *
+ * Arguments:  @d@ = destination multiprecision integer
+ *             @type@ = type of integer which @i@ is
+ *             @i@ = a standard C integer
+ *
+ * Use:                Stores the value of @i@ in @d@.  This macro is actually
+ *             rather subtle in places.  Be careful what you change.
+ */
+
+#define MP_FROMINT(d, type, i) do {                                    \
+  type _i = (i);                                                       \
+  size_t _o = 0;                                                       \
+  mp *_d = (d);                                                                \
+  size_t _sz = 4;                                                      \
+                                                                       \
+  MP_DEST(_d, _sz, 0);                                                 \
+  _d->f &= ~(MP_NEG | MP_UNDEF);                                       \
+                                                                       \
+  if (_i >= 0) {                                                       \
+    while (_i) {                                                       \
+      if (_o == _sz) {                                                 \
+       _sz <<= 1;                                                      \
+       MP_ENSURE(_d, _sz);                                             \
+      }                                                                        \
+      _d->v[_o++] = MPW(_i);                                           \
+      if (_i <= MPW_MAX)                                               \
+       break;                                                          \
+      else                                                             \
+       _i /= (type)MPW_MAX + 1;                                        \
+    }                                                                  \
+  } else {                                                             \
+    _d->f |= MP_NEG;                                                   \
+    while (_i) {                                                       \
+      if (_o == _sz) {                                                 \
+       _sz <<= 1;                                                      \
+       MP_ENSURE(_d, _sz);                                             \
+      }                                                                        \
+      _d->v[_o++] = MPW(-_i);                                          \
+      if (_i >= -MPW_MAX)                                              \
+       break;                                                          \
+      else                                                             \
+       _i /= (type)MPW_MAX + 1;                                        \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  _d->vl = _d->v + _o;                                                 \
+  (d) = _d;                                                            \
+} while (0)
+
+/* --- @MP_TOINT@ --- *
+ *
+ * Arguments:  @m@ = a multiprecision integer
+ *             @type@ = the type of @i@
+ *             @max@ = the largest value @i@ can represent
+ *             @i@ = an integer variable
+ *
+ * Use:                Stores the value of a multiprecision integer in a standard C
+ *             integer.  If the value won't fit, the behaviour is determined
+ *             by the type of @i@: if @i@ is unsigned, the value of the
+ *             multiprecision integer modulo @max + 1@ is stored; if @i@ is
+ *             signed, the behaviour is undefined.
+ *
+ *             If you don't want to be bitten by these sorts of things, keep
+ *             copies of @INT_MAX@ or whatever is appropriate in
+ *             multiprecision form and compare before conversion.
+ */
+
+#define MP_TOINT(m, type, max, i) do {                                 \
+  type _i = 0;                                                         \
+  type _max = (max);                                                   \
+  unsigned _s = 0;                                                     \
+  const mp *_m = (m);                                                  \
+  const mpw *_v = _m->v, *_vl = _m->vl;                                        \
+                                                                       \
+  /* --- Do all the arithmetic in negative numbers --- */              \
+                                                                       \
+  while (_v < _vl && _max > 0) {                                       \
+    _i -= *_v << _s;                                                   \
+    _s += MPW_BITS;                                                    \
+    _v++;                                                              \
+    _max /= (mpd)MPW_MAX + 1;                                          \
+  }                                                                    \
+  if (!MP_NEGP(_m))                                                    \
+    _i = -_i;                                                          \
+  (i) = _i;                                                            \
+} while (0)
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mp_fromINT@ --- *
+ *
+ * Arguments:  @mp *d@ = pointer to destination multiprecision integer
+ *             @INT i@ = standard C integer to convert
+ *
+ * Returns:    The resulting multiprecision integer.
+ *
+ * Use:                Converts a standard C integer to a multiprecision integer.
+ */
+
+#define mp_fromINT(name, type)                                         \
+  extern mp *mp_from##name(mp */*d*/, type /*i*/)
+
+mp_fromINT(short, short);
+mp_fromINT(ushort, unsigned short);
+mp_fromINT(int, int);
+mp_fromINT(uint, unsigned);
+mp_fromINT(uint32, uint32);
+mp_fromINT(long, long);
+mp_fromINT(ulong, unsigned long);
+
+#undef mp_fromINT
+
+/* --- @mp_toINT@ --- *
+ *
+ * Arguments:  @const mp *m@ = pointer to a multiprecision integer
+ *
+ * Returns:    The value of the integer @m@ as a C integer.
+ *
+ * Use:                Converts a multiprecision integer to a standard C integer.
+ *             If the value of the multiprecision integer cannot be
+ *             represented in the return type, and the return type is
+ *             unsigned, it is reduced modulo @TYPE_MAX + 1@; if the return
+ *             type is signed, the behaviour is undefined.
+ */
+
+#define mp_toINT(name, type)                                           \
+  extern type mp_to##name(const mp */*m*/)
+
+mp_toINT(short, short);
+mp_toINT(ushort, unsigned short);
+mp_toINT(int, int);
+mp_toINT(uint, unsigned);
+mp_toINT(uint32, uint32);
+mp_toINT(long, long);
+mp_toINT(ulong, unsigned long);
+
+#undef mp_toINT
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpmont-exp.c b/math/mpmont-exp.c
new file mode 100644 (file)
index 0000000..0ea554e
--- /dev/null
@@ -0,0 +1,145 @@
+/* -*-c-*-
+ *
+ * Modular exponentiation with Montgomery reduction
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpmont.h"
+#include "mpmont-exp.h"
+
+/*----- Exponentiation ----------------------------------------------------*/
+
+/* --- @mpmont_expr@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$(a R^{-1})^e R \bmod m$%.
+ */
+
+mp *mpmont_expr(mpmont *mm, mp *d, mp *a, mp *e)
+{
+  mp *x = MP_COPY(mm->r);
+  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
+
+  MP_COPY(a);
+  MP_SHRINK(e);
+  if (MP_ZEROP(e))
+    ;
+  else {
+    if (MP_NEGP(e)) {
+      a = mpmont_reduce(mm, a, a);
+      a = mp_modinv(a, a, mm->m);
+      a = mpmont_mul(mm, a, a, mm->r2);
+    }
+    if (MP_LEN(e) < EXP_THRESH)
+      EXP_SIMPLE(x, a, e);
+    else
+      EXP_WINDOW(x, a, e);
+  }
+  mp_drop(d);
+  mp_drop(spare);
+  mp_drop(a);
+  return (x);
+}
+
+/* --- @mpmont_exp@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e \bmod m$%.
+ */
+
+mp *mpmont_exp(mpmont *mm, mp *d, mp *a, mp *e)
+{
+  e = MP_COPY(e);
+  d = mpmont_mul(mm, d, a, mm->r2);
+  d = mpmont_expr(mm, d, d, e);
+  d = mpmont_reduce(mm, d, d);
+  MP_DROP(e);
+  return (d);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int texp(dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  mp *a = *(mp **)v[1].buf;
+  mp *b = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *mr;
+  int ok = 1;
+
+  mpmont mm;
+  mpmont_create(&mm, m);
+
+  mr = mpmont_exp(&mm, MP_NEW, a, b);
+
+  if (!MP_EQ(mr, r)) {
+    fputs("\n*** montgomery modexp failed", stderr);
+    fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
+    fputs("\n e = ", stderr); mp_writefile(b, stderr, 10);
+    fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  MP_DROP(m);
+  MP_DROP(a);
+  MP_DROP(b);
+  MP_DROP(r);
+  MP_DROP(mr);
+  mpmont_destroy(&mm);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return ok;
+}
+
+static test_chunk tests[] = {
+  { "exp", texp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } },
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mpmont");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpmont-exp.h b/math/mpmont-exp.h
new file mode 100644 (file)
index 0000000..7ae714d
--- /dev/null
@@ -0,0 +1,71 @@
+/* -*-c-*-
+ *
+ * Exponentiation operations for Montgomery reduction
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_MPMONT_EXP_H
+#define CATACOMB_MPMONT_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentation definitions -----------------------------------------*/
+
+#define EXP_TYPE mp *
+
+#define EXP_COPY(d, x) d = MP_COPY(x)
+#define EXP_DROP(x) MP_DROP(x)
+
+#define EXP_MUL(a, x) do {                                             \
+  mp *t = mpmont_mul(mm, spare, a, x);                                 \
+  spare = a;                                                           \
+  a = t;                                                               \
+} while (0)
+
+#define EXP_SQR(a) do {                                                        \
+  mp *t = mp_sqr(spare, a);                                            \
+  spare = a;                                                           \
+  a = mpmont_reduce(mm, t, t);                                         \
+} while (0)
+
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) d = mpmont_mul(mm, MP_NEW, x, y)
+
+#define EXP_SETSQR(d, x) do {                                          \
+  d = mp_sqr(MP_NEW, x);                                               \
+  d = mpmont_reduce(mm, d, d);                                         \
+} while (0)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpmont-mexp.c b/math/mpmont-mexp.c
new file mode 100644 (file)
index 0000000..e0f37b5
--- /dev/null
@@ -0,0 +1,211 @@
+/* -*-c-*-
+ *
+ * Multiple simultaneous exponentiations
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpmont.h"
+
+#define EXP_WINSZ 3
+#include "mpmont-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpmont_mexpr@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = fake destination
+ *             @const mp_expfactor *f@ = pointer to array of factors
+ *             @size_t n@ = number of factors supplied
+ *
+ * Returns:    If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the
+ *             exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result
+ *             is:
+ *
+ *             %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$%
+ *
+ *             except that the %$g_i$% and result are in Montgomery form.
+ */
+
+static mp *mexpr(mpmont *mm, mp *d, mp_expfactor *f, size_t n)
+{
+  mp *a = MP_COPY(mm->r);
+  mp *spare = MP_NEW;
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    mp *t;
+    if (f[i].exp->f & MP_BURN)
+      spare = MP_NEWSEC;
+    if (MP_NEGP(f[i].exp)) {
+      t = mpmont_reduce(mm, f[i].base, f[i].base);
+      t = mp_modinv(t, t, mm->m);
+      f[i].base = mpmont_mul(mm, t, t, mm->r2);
+    }
+  }
+  EXP_SIMUL(a, f, n);
+  mp_drop(d);
+  mp_drop(spare);
+  for (i = 0; i < n; i++)
+    MP_DROP(f[i].base);
+  xfree(f);
+  return (a);
+}
+
+mp *mpmont_mexpr(mpmont *mm, mp *d, const mp_expfactor *f, size_t n)
+{
+  mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor));
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    ff[i].base = MP_COPY(f[i].base);
+    ff[i].exp = f[i].exp;
+  }
+  return (mexpr(mm, d, ff, n));
+}
+
+/* --- @mpmont_mexp@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = fake destination
+ *             @const mp_expfactor *f@ = pointer to array of factors
+ *             @size_t n@ = number of factors supplied
+ *
+ * Returns:    Product of bases raised to exponents, all mod @m@.
+ *
+ * Use:                Convenient interface over @mpmont_mexpr@.
+ */
+
+mp *mpmont_mexp(mpmont *mm, mp *d, const mp_expfactor *f, size_t n)
+{
+  mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor));
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    ff[i].base = mpmont_mul(mm, MP_NEW, f[i].base, mm->r2);
+    ff[i].exp = f[i].exp;
+  }
+  d = mexpr(mm, d, ff, n);
+  return (mpmont_reduce(mm, d, d));
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int verify(size_t n, dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  mp_expfactor *f = xmalloc(n * sizeof(*f));
+  mp *r, *rr;
+  size_t i, j;
+  mpmont mm;
+  int ok = 1;
+
+  j = 1;
+  for (i = 0; i < n; i++) {
+    f[i].base = *(mp **)v[j++].buf;
+    f[i].exp = *(mp **)v[j++].buf;
+  }
+
+  rr = *(mp **)v[j].buf;
+  mpmont_create(&mm, m);
+  r = mpmont_mexp(&mm, MP_NEW, f, n);
+  if (!MP_EQ(r, rr)) {
+    fputs("\n*** mexp failed\n", stderr);
+    fputs("m = ", stderr); mp_writefile(m, stderr, 10);
+    for (i = 0; i < n; i++) {
+      fprintf(stderr, "\ng_%u = ", i);
+      mp_writefile(f[i].base, stderr, 10);
+      fprintf(stderr, "\ne_%u = ", i);
+      mp_writefile(f[i].exp, stderr, 10);
+    }
+    fputs("\nr = ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\nR = ", stderr); mp_writefile(rr, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  for (i = 0; i < n; i++) {
+    MP_DROP(f[i].base);
+    MP_DROP(f[i].exp);
+  }
+  MP_DROP(m);
+  MP_DROP(r);
+  MP_DROP(rr);
+  mpmont_destroy(&mm);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int t1(dstr *v) { return verify(1, v); }
+static int t2(dstr *v) { return verify(2, v); }
+static int t3(dstr *v) { return verify(3, v); }
+static int t4(dstr *v) { return verify(4, v); }
+static int t5(dstr *v) { return verify(5, v); }
+
+static test_chunk tests[] = {
+  { "mexp-1", t1, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "mexp-2", t2, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "mexp-3", t3, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "mexp-4", t4, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { "mexp-5", t5, { &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, &type_mp,
+                   &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mpmont");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpmont.c b/math/mpmont.c
new file mode 100644 (file)
index 0000000..88efaca
--- /dev/null
@@ -0,0 +1,427 @@
+/* -*-c-*-
+ *
+ * Montgomery reduction
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpmont.h"
+
+/*----- Tweakables --------------------------------------------------------*/
+
+/* --- @MPMONT_DISABLE@ --- *
+ *
+ * Replace all the clever Montgomery reduction with good old-fashioned long
+ * division.
+ */
+
+/* #define MPMONT_DISABLE */
+
+/*----- Reduction and multiplication --------------------------------------*/
+
+/* --- @mpmont_create@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *m@ = modulus to use
+ *
+ * Returns:    Zero on success, nonzero on error.
+ *
+ * Use:                Initializes a Montgomery reduction context ready for use.
+ *             The argument @m@ must be a positive odd integer.
+ */
+
+#ifdef MPMONT_DISABLE
+
+int mpmont_create(mpmont *mm, mp *m)
+{
+  mp_shrink(m);
+  mm->m = MP_COPY(m);
+  mm->r = MP_ONE;
+  mm->r2 = MP_ONE;
+  mm->mi = MP_ONE;
+  return (0);
+}
+
+#else
+
+int mpmont_create(mpmont *mm, mp *m)
+{
+  size_t n = MP_LEN(m);
+  mp *r2 = mp_new(2 * n + 1, 0);
+  mp r;
+
+  /* --- Take a copy of the modulus --- */
+
+ if (!MP_POSP(m) || !MP_ODDP(m))
+   return (-1);
+  mm->m = MP_COPY(m);
+
+  /* --- Determine %$R^2$% --- */
+
+  mm->n = n;
+  MPX_ZERO(r2->v, r2->vl - 1);
+  r2->vl[-1] = 1;
+
+  /* --- Find the magic value @mi@ --- */
+
+  mp_build(&r, r2->v + n, r2->vl);
+  mm->mi = mp_modinv(MP_NEW, m, &r);
+  mm->mi = mp_sub(mm->mi, &r, mm->mi);
+
+  /* --- Discover the values %$R \bmod m$% and %$R^2 \bmod m$% --- */
+
+  mm->r2 = MP_NEW;
+  mp_div(0, &mm->r2, r2, m);
+  mm->r = mpmont_reduce(mm, MP_NEW, mm->r2);
+  MP_DROP(r2);
+  return (0);
+}
+
+#endif
+
+/* --- @mpmont_destroy@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to a Montgomery reduction context
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a context when it's no longer of any use to
+ *             anyone.
+ */
+
+void mpmont_destroy(mpmont *mm)
+{
+  MP_DROP(mm->m);
+  MP_DROP(mm->r);
+  MP_DROP(mm->r2);
+  MP_DROP(mm->mi);
+}
+
+/* --- @mpmont_reduce@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = destination
+ *             @mp *a@ = source, assumed positive
+ *
+ * Returns:    Result, %$a R^{-1} \bmod m$%.
+ */
+
+#ifdef MPMONT_DISABLE
+
+mp *mpmont_reduce(mpmont *mm, mp *d, mp *a)
+{
+  mp_div(0, &d, a, mm->m);
+  return (d);
+}
+
+#else
+
+mp *mpmont_reduce(mpmont *mm, mp *d, mp *a)
+{
+  size_t n = mm->n;
+
+  /* --- Check for serious Karatsuba reduction --- */
+
+  if (n > MPK_THRESH * 3) {
+    mp al;
+    mpw *vl;
+    mp *u;
+
+    if (MP_LEN(a) >= n)
+      vl = a->v + n;
+    else
+      vl = a->vl;
+    mp_build(&al, a->v, vl);
+    u = mp_mul(MP_NEW, &al, mm->mi);
+    if (MP_LEN(u) > n)
+      u->vl = u->v + n;
+    u = mp_mul(u, u, mm->m);
+    d = mp_add(d, a, u);
+    mp_drop(u);
+  }
+
+  /* --- Otherwise do it the hard way --- */
+
+  else {
+    mpw *dv, *dvl;
+    mpw *mv, *mvl;
+    mpw mi;
+    size_t k = n;
+
+    /* --- Initial conditioning of the arguments --- */
+
+    a = MP_COPY(a);
+    if (d)
+      MP_DROP(d);
+    d = a;
+    MP_DEST(d, 2 * n + 1, a->f);
+
+    dv = d->v; dvl = d->vl;
+    mv = mm->m->v; mvl = mm->m->vl;
+
+    /* --- Let's go to work --- */
+
+    mi = mm->mi->v[0];
+    while (k--) {
+      mpw u = MPW(*dv * mi);
+      MPX_UMLAN(dv, dvl, mv, mvl, u);
+      dv++;
+    }
+  }
+
+  /* --- Wrap everything up --- */
+
+  memmove(d->v, d->v + n, MPWS(MP_LEN(d) - n));
+  d->vl -= n;
+  if (MPX_UCMP(d->v, d->vl, >=, mm->m->v, mm->m->vl))
+    mpx_usub(d->v, d->vl, d->v, d->vl, mm->m->v, mm->m->vl);
+  if (d->f & MP_NEG) {
+    mpx_usub(d->v, d->vl, mm->m->v, mm->m->vl, d->v, d->vl);
+    d->f &= ~MP_NEG;
+  }
+  MP_SHRINK(d);
+  return (d);
+}
+
+#endif
+
+/* --- @mpmont_mul@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = destination
+ *             @mp *a, *b@ = sources, assumed positive
+ *
+ * Returns:    Result, %$a b R^{-1} \bmod m$%.
+ */
+
+#ifdef MPMONT_DISABLE
+
+mp *mpmont_mul(mpmont *mm, mp *d, mp *a, mp *b)
+{
+  d = mp_mul(d, a, b);
+  mp_div(0, &d, d, mm->m);
+  return (d);
+}
+
+#else
+
+mp *mpmont_mul(mpmont *mm, mp *d, mp *a, mp *b)
+{
+  if (mm->n > MPK_THRESH * 3) {
+    d = mp_mul(d, a, b);
+    d = mpmont_reduce(mm, d, d);
+  } else {
+    mpw *dv, *dvl;
+    mpw *av, *avl;
+    mpw *bv, *bvl;
+    mpw *mv, *mvl;
+    mpw y;
+    size_t n, i;
+    mpw mi;
+
+    /* --- Initial conditioning of the arguments --- */
+
+    if (MP_LEN(a) > MP_LEN(b)) {
+      mp *t = a; a = b; b = t;
+    }
+    n = MP_LEN(mm->m);
+
+    a = MP_COPY(a);
+    b = MP_COPY(b);
+    MP_DEST(d, 2 * n + 1, a->f | b->f | MP_UNDEF);
+    dv = d->v; dvl = d->vl;
+    MPX_ZERO(dv, dvl);
+    av = a->v; avl = a->vl;
+    bv = b->v; bvl = b->vl;
+    mv = mm->m->v; mvl = mm->m->vl;
+    y = *bv;
+
+    /* --- Montgomery multiplication phase --- */
+
+    i = 0;
+    mi = mm->mi->v[0];
+    while (i < n && av < avl) {
+      mpw x = *av++;
+      mpw u = MPW((*dv + x * y) * mi);
+      MPX_UMLAN(dv, dvl, bv, bvl, x);
+      MPX_UMLAN(dv, dvl, mv, mvl, u);
+      dv++;
+      i++;
+    }
+
+    /* --- Simpler Montgomery reduction phase --- */
+
+    while (i < n) {
+      mpw u = MPW(*dv * mi);
+      MPX_UMLAN(dv, dvl, mv, mvl, u);
+      dv++;
+      i++;
+    }
+
+    /* --- Done --- */
+
+    memmove(d->v, dv, MPWS(dvl - dv));
+    d->vl -= dv - d->v;
+    if (MPX_UCMP(d->v, d->vl, >=, mm->m->v, mm->m->vl))
+      mpx_usub(d->v, d->vl, d->v, d->vl, mm->m->v, mm->m->vl);
+    if ((a->f ^ b->f) & MP_NEG)
+      mpx_usub(d->v, d->vl, mm->m->v, mm->m->vl, d->v, d->vl);
+    MP_SHRINK(d);
+    d->f = (a->f | b->f) & MP_BURN;
+    MP_DROP(a);
+    MP_DROP(b);
+  }
+
+  return (d);
+}
+
+#endif
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int tcreate(dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  mp *mi = *(mp **)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *r2 = *(mp **)v[3].buf;
+
+  mpmont mm;
+  int ok = 1;
+
+  mpmont_create(&mm, m);
+
+  if (mm.mi->v[0] != mi->v[0]) {
+    fprintf(stderr, "\n*** bad mi: found %lu, expected %lu",
+           (unsigned long)mm.mi->v[0], (unsigned long)mi->v[0]);
+    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  if (!MP_EQ(mm.r, r)) {
+    fputs("\n*** bad r", stderr);
+    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\nexpected ", stderr); mp_writefile(r, stderr, 10);
+    fputs("\n  found ", stderr); mp_writefile(mm.r, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  if (!MP_EQ(mm.r2, r2)) {
+    fputs("\n*** bad r2", stderr);
+    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\nexpected ", stderr); mp_writefile(r2, stderr, 10);
+    fputs("\n  found ", stderr); mp_writefile(mm.r2, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  MP_DROP(m);
+  MP_DROP(mi);
+  MP_DROP(r);
+  MP_DROP(r2);
+  mpmont_destroy(&mm);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tmul(dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  mp *a = *(mp **)v[1].buf;
+  mp *b = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  int ok = 1;
+
+  mpmont mm;
+  mpmont_create(&mm, m);
+
+  {
+    mp *qr = mp_mul(MP_NEW, a, b);
+    mp_div(0, &qr, qr, m);
+
+    if (!MP_EQ(qr, r)) {
+      fputs("\n*** classical modmul failed", stderr);
+      fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
+      fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
+      fputs("\n b = ", stderr); mp_writefile(b, stderr, 10);
+      fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
+      fputs("\nqr = ", stderr); mp_writefile(qr, stderr, 10);
+      fputc('\n', stderr);
+      ok = 0;
+    }
+
+    mp_drop(qr);
+  }
+
+  {
+    mp *ar = mpmont_mul(&mm, MP_NEW, a, mm.r2);
+    mp *br = mpmont_mul(&mm, MP_NEW, b, mm.r2);
+    mp *mr = mpmont_mul(&mm, MP_NEW, ar, br);
+    mr = mpmont_reduce(&mm, mr, mr);
+    if (!MP_EQ(mr, r)) {
+      fputs("\n*** montgomery modmul failed", stderr);
+      fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
+      fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
+      fputs("\n b = ", stderr); mp_writefile(b, stderr, 10);
+      fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
+      fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10);
+      fputc('\n', stderr);
+      ok = 0;
+    }
+    MP_DROP(ar); MP_DROP(br);
+    mp_drop(mr);
+  }
+
+
+  MP_DROP(m);
+  MP_DROP(a);
+  MP_DROP(b);
+  MP_DROP(r);
+  mpmont_destroy(&mm);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return ok;
+}
+
+static test_chunk tests[] = {
+  { "create", tcreate, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { "mul", tmul, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } },
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mpmont");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpmont.h b/math/mpmont.h
new file mode 100644 (file)
index 0000000..9973ec3
--- /dev/null
@@ -0,0 +1,201 @@
+/* -*-c-*-
+ *
+ * Montgomery reduction
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPMONT_H
+#define CATACOMB_MPMONT_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Notes on Montgomery reduction -------------------------------------*
+ *
+ * Given a little bit of precomputation, Montgomery reduction enables modular
+ * reductions of products to be calculated rather rapidly, without recourse
+ * to annoying things like division.
+ *
+ * Before starting, you need to do a little work.  In particular, the
+ * following things need to be worked out:
+ *
+ *   * %$m$%, which is the modulus you'll be working with.  This must be odd,
+ *     otherwise the whole thing doesn't work.  You're better off using
+ *     Barrett reduction if your modulus might be even.
+ *
+ *   * %$b$%, the radix of the number system you're in (here, it's
+ *     @MPW_MAX + 1@).
+ *
+ *   * %$-m^{-1} \bmod b$%, a useful number for the reduction step.  (This
+ *     means that the modulus mustn't be even.  This shouldn't be a problem.)
+ *
+ *   * %$R = b^n > m > b^{n - 1}$%, or at least %$\log_2 R$%.
+ *
+ *   * %$R \bmod m$% and %$R^2 \bmod m$%, which are useful when doing
+ *     calculations such as exponentiation.
+ *
+ * The result of a Montgomery reduction of %$x$% is %$x R^{-1} \bmod m$%,
+ * which doesn't look ever-so useful.  The trick is to initially apply a
+ * factor of %$R$% to all of your numbers so that when you multiply and
+ * perform a Montgomery reduction you get %$(x R \cdot y R) R^{-1} \bmod m$%,
+ * which is just %$x y R \bmod m$%.  Thanks to distributivity, even additions
+ * and subtractions can be performed on numbers in this form -- the extra
+ * factor of %$R$% just runs through all the calculations until it's finally
+ * stripped out by a final reduction operation.
+ */
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- A Montgomery reduction context --- */
+
+typedef struct mpmont {
+  mp *m;                               /* Modulus */
+  mp *mi;                              /* %$-m^{-1} \bmod R$% */
+  size_t n;                            /* %$\log_b R$% */
+  mp *r, *r2;                          /* %$R \bmod m$%, %$R^2 \bmod m$% */
+} mpmont;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mpmont_create@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *m@ = modulus to use
+ *
+ * Returns:    Zero on success, nonzero on error.
+ *
+ * Use:                Initializes a Montgomery reduction context ready for use.
+ *             The argument @m@ must be a positive odd integer.
+ */
+
+extern int mpmont_create(mpmont */*mm*/, mp */*m*/);
+
+/* --- @mpmont_destroy@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to a Montgomery reduction context
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a context when it's no longer of any use to
+ *             anyone.
+ */
+
+extern void mpmont_destroy(mpmont */*mm*/);
+
+/* --- @mpmont_reduce@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = destination
+ *             @mp *a@ = source, assumed positive
+ *
+ * Returns:    Result, %$a R^{-1} \bmod m$%.
+ */
+
+extern mp *mpmont_reduce(mpmont */*mm*/, mp */*d*/, mp */*a*/);
+
+/* --- @mpmont_mul@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = destination
+ *             @mp *a, *b@ = sources, assumed positive
+ *
+ * Returns:    Result, %$a b R^{-1} \bmod m$%.
+ */
+
+extern mp *mpmont_mul(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*b*/);
+
+/* --- @mpmont_expr@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$(a R^{-1})^e R \bmod m$%.  This is useful if
+ *             further modular arithmetic is to be performed on the result.
+ */
+
+extern mp *mpmont_expr(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*e*/);
+
+/* --- @mpmont_exp@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e \bmod m$%.
+ */
+
+extern mp *mpmont_exp(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*e*/);
+
+/* --- @mpmont_mexpr@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = fake destination
+ *             @const mp_expfactor *f@ = pointer to array of factors
+ *             @size_t n@ = number of factors supplied
+ *
+ * Returns:    If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the
+ *             exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result
+ *             is:
+ *
+ *             %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$%
+ *
+ *
+ *             except that the %$g_i$% and result are in Montgomery form.
+ */
+
+extern mp *mpmont_mexpr(mpmont */*mm*/, mp */*d*/,
+                       const mp_expfactor */*f*/, size_t /*n*/);
+
+/* --- @mpmont_mexp@ --- *
+ *
+ * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
+ *             @mp *d@ = fake destination
+ *             @const mp_expfactor *f@ = pointer to array of factors
+ *             @size_t n@ = number of factors supplied
+ *
+ * Returns:    Product of bases raised to exponents, all mod @m@.
+ *
+ * Use:                Convenient interface over @mpmont_mexpr@.
+ */
+
+extern mp *mpmont_mexp(mpmont */*mm*/, mp */*d*/,
+                      const mp_expfactor */*f*/, size_t /*n*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpmul.c b/math/mpmul.c
new file mode 100644 (file)
index 0000000..e168bc1
--- /dev/null
@@ -0,0 +1,179 @@
+/* -*-c-*-
+ *
+ * Multiply many small numbers together
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpint.h"
+#include "mpmul.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpmul_init@ --- *
+ *
+ * Arguments:  @mpmul *b@ = pointer to multiplier context to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a big multiplier context for use.
+ */
+
+void mpmul_init(mpmul *b)
+{
+  b->i = 0;
+}
+
+/* --- @mpmul_add@ --- *
+ *
+ * Arguments:  @mpmul *b@ = pointer to multiplier context
+ *             @mp *x@ = the next factor to multiply in
+ *
+ * Returns:    ---
+ *
+ * Use:                Contributes another factor to the mix.  It's important that
+ *             the integer lasts at least as long as the multiplication
+ *             context; this sort of rules out @mp_build@ integers.
+ */
+
+#define HWM (MPMUL_DEPTH - 20)
+#define LWM (MPMUL_DEPTH / 2)
+
+void mpmul_add(mpmul *b, mp *x)
+{
+  size_t i = b->i;
+
+  /* --- Now do the reduction step --- */
+
+  x = MP_COPY(x);
+
+  while (i > 0) {
+    if (MP_LEN(b->v[i - 1]) > MP_LEN(x))
+      break;
+    i--;
+    x = mp_mul(x, x, b->v[i]);
+    MP_DROP(b->v[i]);
+  }
+
+  if (i > HWM) {
+    while (i > LWM || (i > 0 && MP_LEN(b->v[i - 1]) <= MP_LEN(x))) {
+      i--;
+      x = mp_mul(x, x, b->v[i]);
+      MP_DROP(b->v[i]);
+    }
+  }
+
+  b->v[i++] = x;
+  b->i = i;
+}
+
+/* --- @mpmul_done@ --- *
+ *
+ * Arguments:  @mpmul *b@ = pointer to big multiplication context
+ *
+ * Returns:    The product of all the numbers contributed.
+ *
+ * Use:                Returns a (large) product of numbers.  The context is
+ *             deallocated.
+ */
+
+mp *mpmul_done(mpmul *b)
+{
+  size_t i = b->i;
+  mp *x;
+
+  if (!i)
+    return (MP_ONE);
+  i--;
+  x = b->v[i];
+  while (i > 0) {
+    i--;
+    x = mp_mul(x, x, b->v[i]);
+    MP_DROP(b->v[i]);
+  }
+  return (x);
+}
+
+/* --- @mp_factorial@ --- *
+ *
+ * Arguments:  @unsigned long i@ = number whose factorial should be
+ *                     computed.
+ *
+ * Returns:    The requested factorial.
+ */
+
+mp *mp_factorial(unsigned long i)
+{
+  unsigned long j;
+  mp *x = MP_NEW;
+  mpmul b = MPMUL_INIT;
+
+  for (j = 1; j <= i; j++) {
+    x = mp_fromulong(x, j);
+    mpmul_add(&b, x);
+  }
+  mp_drop(x);
+  return (mpmul_done(&b));
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int vfact(dstr *v)
+{
+  unsigned long x = *(unsigned long *)v[0].buf;
+  mp *fx = *(mp **)v[1].buf;
+  mp *y = mp_factorial(x);
+  int ok = 1;
+  if (!MP_EQ(fx, y)) {
+    fprintf(stderr, "factorial failed\n");
+    MP_FPRINTF(stderr, (stderr, "%lu! = ", x), fx);
+    MP_EPRINT("result", y);
+    ok = 0;
+  }
+  mp_drop(fx);
+  mp_drop(y);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "factorial", vfact, { &type_ulong, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, tests, SRCDIR "/t/mp");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpmul.h b/math/mpmul.h
new file mode 100644 (file)
index 0000000..1dfb587
--- /dev/null
@@ -0,0 +1,139 @@
+/* -*-c-*-
+ *
+ * Multiply many small numbers together
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_MPMUL_H
+#define CATACOMB_MPMUL_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+/* --- How the algorithm works --- *
+ *
+ * Multiplication on large integers is least wasteful when the numbers
+ * multiplied are approximately the same size.  When a new multiplier is
+ * added to the system, we push it onto a stack.  Then we `reduce' the stack:
+ * while the value on the top of the stack is not shorter than the value
+ * below it, replace the top two elements by their product.
+ *
+ * Let %$b$% be the radix of our multiprecision integers, and let %$Z$% be
+ * the maximum number of digits.  Then the largest integer we can represent
+ * is %$M - 1 = b^Z - 1$%.  We could assume that all of the integers we're
+ * given are about the same size.  This would give us the same upper bound as
+ * that derived in `mptext.c'.
+ *
+ * However, we're in less control over our inputs.  In particular, if a
+ * sequence of integers with strictly decreasing lengths is input then we're
+ * sunk.  Suppose that the stack contains, from top to bottom, %$b^i$%,
+ * %$b^{i+1}$%, ..., %$b^n$%.  The final product will therefore be
+ * %$p = b^{(n+i)(n-i+1)/2}$%.  We must now find the maximum stack depth
+ * %$d = n - i$% such that %$p > M$%.
+ *
+ * Taking logs of both sides gives that %$(d + 2 i)(d + 1) > 2 Z$%.  We can
+ * maximize %$d$% by taking %$i = 0$%, which gives that %$d^2 + d > 2 Z$%, so
+ * %$d$% must be approximately %$(\sqrt{8 Z + 1} - 1)/2$%, which is
+ * uncomfortably large.
+ *
+ * We compromise by choosing double the `mptext' bound and imposing high- and
+ * low-water marks for forced reduction.
+ */
+
+#define MPMUL_DEPTH (2 * (CHAR_BIT * sizeof(size_t) + 10))
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct mpmul {
+  size_t i;
+  mp *v[MPMUL_DEPTH];
+} mpmul;
+
+#define MPMUL_INIT { 0 }
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mpmul_init@ --- *
+ *
+ * Arguments:  @mpmul *b@ = pointer to multiplier context to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a big multiplier context for use.
+ */
+
+extern void mpmul_init(mpmul */*b*/);
+
+/* --- @mpmul_add@ --- *
+ *
+ * Arguments:  @mpmul *b@ = pointer to multiplier context
+ *             @mp *x@ = the next factor to multiply in
+ *
+ * Returns:    ---
+ *
+ * Use:                Contributes another factor to the mix.  It's important that
+ *             the integer lasts at least as long as the multiplication
+ *             context; this sort of rules out @mp_build@ integers.
+ */
+
+extern void mpmul_add(mpmul */*b*/, mp */*x*/);
+
+/* --- @mpmul_done@ --- *
+ *
+ * Arguments:  @mpmul *b@ = pointer to big multiplication context
+ *
+ * Returns:    The product of all the numbers contributed.
+ *
+ * Use:                Returns a (large) product of numbers.  The context is
+ *             deallocated.
+ */
+
+extern mp *mpmul_done(mpmul */*b*/);
+
+/* --- @mp_factorial@ --- *
+ *
+ * Arguments:  @unsigned long i@ = number whose factorial should be
+ *                     computed.
+ *
+ * Returns:    The requested factorial.
+ */
+
+extern mp *mp_factorial(unsigned long /*i*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mprand.c b/math/mprand.c
new file mode 100644 (file)
index 0000000..eb779cb
--- /dev/null
@@ -0,0 +1,138 @@
+/* -*-c-*-
+ *
+ * Generate a random multiprecision integer
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/alloc.h>
+
+#include "grand.h"
+#include "mp.h"
+#include "mprand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mprand@ --- *
+ *
+ * Arguments:  @mp *d@ = destination integer
+ *             @unsigned b@ = number of bits
+ *             @grand *r@ = pointer to random number source
+ *             @mpw or@ = mask to OR with low-order bits
+ *
+ * Returns:    A random integer with the requested number of bits.
+ *
+ * Use:                Constructs an arbitrarily large pseudorandom integer.
+ *             Assuming that the generator @r@ is good, the result is
+ *             uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%.
+ *             The result is then ORred with the given @or@ value.  This
+ *             will often be 1, to make the result odd.
+ */
+
+mp *mprand(mp *d, unsigned b, grand *r, mpw or)
+{
+  size_t sz = (b + 7) >> 3;
+  arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global;
+  octet *v = x_alloc(a, sz);
+  unsigned m;
+
+  /* --- Fill buffer with random data --- */
+
+  r->ops->fill(r, v, sz);
+
+  /* --- Force into the correct range --- *
+   *
+   * This is slightly tricky.  Oh, well.
+   */
+
+  b = (b - 1) & 7;
+  m = (1 << b);
+  v[0] = (v[0] & (m - 1)) | m;
+
+  /* --- Mask, load and return --- */
+
+  d = mp_loadb(d, v, sz);
+  d->v[0] |= or;
+  memset(v, 0, sz);
+  x_free(a, v);
+  return (d);
+}
+
+/* --- @mprand_range@ --- *
+ *
+ * Arguments:  @mp *d@ = destination integer
+ *             @mp *l@ = limit for random number
+ *             @grand *r@ = random number source
+ *             @mpw or@ = mask for low-order bits
+ *
+ * Returns:    A pseudorandom integer, unformly distributed over the
+ *             interval %$[0, l)$%.
+ *
+ * Use:                Generates a uniformly-distributed pseudorandom number in the
+ *             appropriate range.
+ */
+
+mp *mprand_range(mp *d, mp *l, grand *r, mpw or)
+{
+  size_t b = mp_bits(l);
+  size_t sz = (b + 7) >> 3;
+  arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global;
+  octet *v = x_alloc(a, sz);
+  unsigned m;
+
+  /* --- The algorithm --- *
+   *
+   * Rather simpler than most.  Find the number of bits in the number %$l$%
+   * (i.e., the integer %$b$% such that %$2^{b - 1} \le l < 2^b$%), and
+   * generate pseudorandom integers with %$n$% bits (but not, unlike in the
+   * function above, with the top bit forced to 1).  If the integer is
+   * greater than or equal to %$l$%, try again.
+   *
+   * This is similar to the algorithms used in @lcrand_range@ and friends,
+   * except that I've forced the `raw' range of the random numbers such that
+   * %$l$% itself is the largest multiple of %$l$% in the range (since, by
+   * the inequality above, %$2^b \le 2l$%).  This removes the need for costly
+   * division and remainder operations.
+   *
+   * As usual, the number of iterations expected is two.
+   */
+
+  b = ((b - 1) & 7) + 1;
+  m = (1 << b) - 1;
+  do {
+    r->ops->fill(r, v, sz);
+    v[0] &= m;
+    d = mp_loadb(d, v, sz);
+    d->v[0] |= or;
+  } while (MP_CMP(d, >=, l));
+
+  /* --- Done --- */
+
+  memset(v, 0, sz);
+  x_free(a, v);
+  return (d);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mprand.h b/math/mprand.h
new file mode 100644 (file)
index 0000000..0c193c0
--- /dev/null
@@ -0,0 +1,87 @@
+/* -*-c-*-
+ *
+ * Generate a random multiprecision integer
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPRAND_H
+#define CATACOMB_MPRAND_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mprand@ --- *
+ *
+ * Arguments:  @mp *d@ = destination integer
+ *             @unsigned b@ = number of bits
+ *             @grand *r@ = pointer to random number source
+ *             @mpw or@ = mask to OR with low-order bits
+ *
+ * Returns:    A random integer with the requested number of bits
+ *
+ * Use:                Constructs an arbitrarily large pseudorandom integer.
+ *             Assuming that the generator @r@ is good, the result is
+ *             uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%.
+ *             The result is then ORred with the given @or@ value.  This
+ *             will often be 1, to make the result odd.
+ */
+
+extern mp *mprand(mp */*d*/, unsigned /*b*/, grand */*r*/, mpw /*or*/);
+
+/* --- @mprand_range@ --- *
+ *
+ * Arguments:  @mp *d@ = destination integer
+ *             @mp *l@ = limit for random number
+ *             @grand *r@ = random number source
+ *             @mpw or@ = mask for low-order bits
+ *
+ * Returns:    A pseudorandom integer, unformly distributed over the
+ *             interval %$[0, l)$%.
+ *
+ * Use:                Generates a uniformly-distributed pseudorandom number in the
+ *             appropriate range.
+ */
+
+extern mp *mprand_range(mp */*d*/, mp */*l*/, grand */*r*/, mpw /*or*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpreduce-exp.h b/math/mpreduce-exp.h
new file mode 100644 (file)
index 0000000..f314514
--- /dev/null
@@ -0,0 +1,74 @@
+/* -*-c-*-
+ *
+ * Exponentiation operations for binary field reduction
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_MPREDUCE_EXP_H
+#define CATACOMB_MPREDUCE_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentiation definitions ----------------------------------------*/
+
+#define EXP_TYPE mp *
+
+#define EXP_COPY(d, x) d = MP_COPY(x)
+#define EXP_DROP(x) MP_DROP(x)
+
+#define EXP_MUL(a, x) do {                                             \
+  mp *t = mp_mul(spare, a, x);                                         \
+  spare = a;                                                           \
+  a = mpreduce_do(mr, t, t);                                           \
+} while (0)
+
+#define EXP_SQR(a) do {                                                        \
+  mp *t = mp_sqr(spare, a);                                            \
+  spare = a;                                                           \
+  a = mpreduce_do(mr, t, t);                                           \
+} while (0)
+
+#define EXP_FIX(x)
+
+#define EXP_SETMUL(d, x, y) do {                                       \
+  d = mp_mul(MP_NEW, x, y);                                            \
+  d = mpreduce_do(mr, d, d);                                           \
+} while (0)
+
+#define EXP_SETSQR(d, x) do {                                          \
+  d = mp_sqr(MP_NEW, x);                                               \
+  d = mpreduce_do(mr, d, d);                                           \
+} while (0)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpreduce.c b/math/mpreduce.c
new file mode 100644 (file)
index 0000000..669f516
--- /dev/null
@@ -0,0 +1,438 @@
+/* -*-c-*-
+ *
+ * Efficient reduction modulo nice primes
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/darray.h>
+#include <mLib/macros.h>
+
+#include "mp.h"
+#include "mpreduce.h"
+#include "mpreduce-exp.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+DA_DECL(instr_v, mpreduce_instr);
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpreduce_create@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = structure to fill in
+ *             @mp *x@ = an integer
+ *
+ * Returns:    Zero if successful; nonzero on failure.
+ *
+ * Use:                Initializes a context structure for reduction.
+ */
+
+int mpreduce_create(mpreduce *r, mp *p)
+{
+  mpscan sc;
+  enum { Z = 0, Z1 = 2, X = 4, X0 = 6 };
+  unsigned st = Z;
+  instr_v iv = DA_INIT;
+  unsigned long d, i;
+  unsigned op;
+  size_t w, b, bb;
+
+  /* --- Fill in the easy stuff --- */
+
+  if (!MP_POSP(p))
+    return (-1);
+  d = mp_bits(p);
+  r->lim = d/MPW_BITS;
+  r->s = d%MPW_BITS;
+  if (r->s)
+    r->lim++;
+  r->p = mp_copy(p);
+
+  /* --- Stash a new instruction --- */
+
+#define INSTR(op_, argx_, argy_) do {                                  \
+  DA_ENSURE(&iv, 1);                                                   \
+  DA(&iv)[DA_LEN(&iv)].op = (op_);                                     \
+  DA(&iv)[DA_LEN(&iv)].argx = (argx_);                                 \
+  DA(&iv)[DA_LEN(&iv)].argy = (argy_);                                 \
+  DA_EXTEND(&iv, 1);                                                   \
+} while (0)
+
+  /* --- Main loop --- *
+   *
+   * A simple state machine decomposes @p@ conveniently into positive and
+   * negative powers of 2.  The pure form of the state machine is left below
+   * for reference (and in case I need inspiration for a NAF exponentiator).
+   */
+
+#ifdef DEBUG
+  for (i = 0, mp_scan(&sc, p); mp_step(&sc); i++) {
+    switch (st | mp_bit(&sc)) {
+      case  Z | 1: st = Z1; break;
+      case Z1 | 0: st =         Z; printf("+ %lu\n", i - 1); break;
+      case Z1 | 1: st =         X; printf("- %lu\n", i - 1); break;
+      case  X | 0: st = X0; break;
+      case X0 | 1: st =         X; printf("- %lu\n", i - 1); break;
+      case X0 | 0: st =         Z; printf("+ %lu\n", i - 1); break;
+    }
+  }
+  if (st >= X) printf("+ %lu\n", i - 1);
+  st = Z;
+#endif
+
+  bb = MPW_BITS - (d + 1)%MPW_BITS;
+  for (i = 0, mp_scan(&sc, p); i < d && mp_step(&sc); i++) {
+    switch (st | mp_bit(&sc)) {
+      case  Z | 1: st = Z1; break;
+      case Z1 | 0: st =         Z; op = MPRI_SUB; goto instr;
+      case Z1 | 1: st =         X; op = MPRI_ADD; goto instr;
+      case  X | 0: st = X0; break;
+      case X0 | 1: st =         X; op = MPRI_ADD; goto instr;
+      case X0 | 0: st =         Z; op = MPRI_SUB; goto instr;
+      instr:
+       w = (d - i)/MPW_BITS + 1;
+       b = (bb + i)%MPW_BITS;
+       INSTR(op | !!b, w, b);
+    }
+  }
+  if (DA_LEN(&iv) && (DA(&iv)[DA_LEN(&iv) - 1].op & ~1u) == MPRI_SUB) {
+    mp_drop(r->p);
+    DA_DESTROY(&iv);
+    return (-1);
+  }
+
+#undef INSTR
+
+  /* --- Wrap up --- */
+
+  r->in = DA_LEN(&iv);
+  if (!r->in)
+    r->iv = 0;
+  else if (!r->s) {
+    r->iv = xmalloc(r->in * sizeof(mpreduce_instr));
+    memcpy(r->iv, DA(&iv), r->in * sizeof(mpreduce_instr));
+  } else {
+    r->iv = xmalloc(r->in * 2 * sizeof(mpreduce_instr));
+    for (i = 0; i < r->in; i++) {
+      r->iv[i] = DA(&iv)[i];
+      op = r->iv[i].op & ~1u;
+      w = r->iv[i].argx;
+      b = r->iv[i].argy;
+      b += r->s;
+      if (b >= MPW_BITS) {
+       b -= MPW_BITS;
+       w--;
+      }
+      if (b) op |= 1;
+      r->iv[i + r->in].op = op;
+      r->iv[i + r->in].argx = w;
+      r->iv[i + r->in].argy = b;
+    }
+  }
+  DA_DESTROY(&iv);
+
+#ifdef DEBUG
+  mpreduce_dump(r, stdout);
+#endif
+  return (0);
+}
+
+/* --- @mpreduce_destroy@ --- *
+ *
+ * Arguments:  @mpreduce *r@ = structure to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Reclaims the resources from a reduction context.
+ */
+
+void mpreduce_destroy(mpreduce *r)
+{
+  mp_drop(r->p);
+  if (r->iv) xfree(r->iv);
+}
+
+/* --- @mpreduce_dump@ --- *
+ *
+ * Arguments:  @mpreduce *r@ = structure to dump
+ *             @FILE *fp@ = file to dump on
+ *
+ * Returns:    ---
+ *
+ * Use:                Dumps a reduction context.
+ */
+
+void mpreduce_dump(mpreduce *r, FILE *fp)
+{
+  size_t i;
+  static const char *opname[] = { "add", "addshift", "sub", "subshift" };
+
+  fprintf(fp, "mod = "); mp_writefile(r->p, fp, 16);
+  fprintf(fp, "\n  lim = %lu; s = %d\n", (unsigned long)r->lim, r->s);
+  for (i = 0; i < r->in; i++) {
+    assert(r->iv[i].op < N(opname));
+    fprintf(fp, "  %s %lu %lu\n",
+           opname[r->iv[i].op],
+           (unsigned long)r->iv[i].argx,
+           (unsigned long)r->iv[i].argy);
+  }
+  if (r->s) {
+    fprintf(fp, "tail end charlie\n");
+    for (i = r->in; i < 2 * r->in; i++) {
+      assert(r->iv[i].op < N(opname));
+      fprintf(fp, "  %s %lu %lu\n",
+             opname[r->iv[i].op],
+             (unsigned long)r->iv[i].argx,
+             (unsigned long)r->iv[i].argy);
+    }
+  }
+}
+
+/* --- @mpreduce_do@ --- *
+ *
+ * Arguments:  @mpreduce *r@ = reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = source
+ *
+ * Returns:    Destination, @x@ reduced modulo the reduction poly.
+ */
+
+static void run(const mpreduce_instr *i, const mpreduce_instr *il,
+               mpw *v, mpw z)
+{
+  for (; i < il; i++) {
+#ifdef DEBUG
+    mp vv;
+    mp_build(&vv, v - i->argx, v + 1);
+    printf("  0x"); mp_writefile(&vv, stdout, 16);
+    printf(" %c (0x%lx << %u) == 0x",
+          (i->op & ~1u) == MPRI_ADD ? '+' : '-',
+          (unsigned long)z,
+          i->argy);
+#endif
+    switch (i->op) {
+      case MPRI_ADD: MPX_UADDN(v - i->argx, v + 1, z); break;
+      case MPRI_ADDLSL: mpx_uaddnlsl(v - i->argx, v + 1, z, i->argy); break;
+      case MPRI_SUB: MPX_USUBN(v - i->argx, v + 1, z); break;
+      case MPRI_SUBLSL: mpx_usubnlsl(v - i->argx, v + 1, z, i->argy); break;
+      default:
+       abort();
+    }
+#ifdef DEBUG
+    mp_build(&vv, v - i->argx, v + 1);
+    mp_writefile(&vv, stdout, 16);
+    printf("\n");
+#endif
+  }
+}
+
+mp *mpreduce_do(mpreduce *r, mp *d, mp *x)
+{
+  mpw *v, *vl;
+  const mpreduce_instr *il;
+  mpw z;
+
+#ifdef DEBUG
+  mp *_r = 0, *_rr = 0;
+#endif
+
+  /* --- If source is negative, divide --- */
+
+  if (MP_NEGP(x)) {
+    mp_div(0, &d, x, r->p);
+    return (d);
+  }
+
+  /* --- Try to reuse the source's space --- */
+
+  MP_COPY(x);
+  if (d) MP_DROP(d);
+  MP_DEST(x, MP_LEN(x), x->f);
+
+  /* --- Do the reduction --- */
+
+#ifdef DEBUG
+  _r = MP_NEW;
+  mp_div(0, &_r, x, r->p);
+  MP_PRINTX("x", x);
+  _rr = 0;
+#endif
+
+  il = r->iv + r->in;
+  if (MP_LEN(x) >= r->lim) {
+    v = x->v + r->lim;
+    vl = x->vl;
+    while (vl-- > v) {
+      while (*vl) {
+       z = *vl;
+       *vl = 0;
+       run(r->iv, il, vl, z);
+#ifdef DEBUG
+       MP_PRINTX("x", x);
+       mp_div(0, &_rr, x, r->p);
+       assert(MP_EQ(_r, _rr));
+#endif
+      }
+    }
+    if (r->s) {
+      while (*vl >> r->s) {
+       z = *vl >> r->s;
+       *vl &= ((1 << r->s) - 1);
+       run(r->iv + r->in, il + r->in, vl, z);
+#ifdef DEBUG
+       MP_PRINTX("x", x);
+       mp_div(0, &_rr, x, r->p);
+       assert(MP_EQ(_r, _rr));
+#endif
+      }
+    }
+  }
+
+  /* --- Finishing touches --- */
+
+  MP_SHRINK(x);
+  if (MP_CMP(x, >=, r->p))
+    x = mp_sub(x, x, r->p);
+
+  /* --- Done --- */
+
+#ifdef DEBUG
+  assert(MP_EQ(_r, x));
+  mp_drop(_r);
+  mp_drop(_rr);
+#endif
+  return (x);
+}
+
+/* --- @mpreduce_exp@ --- *
+ *
+ * Arguments:  @mpreduce *mr@ = pointer to reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e \bmod m$%.
+ */
+
+mp *mpreduce_exp(mpreduce *mr, mp *d, mp *a, mp *e)
+{
+  mp *x = MP_ONE;
+  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
+
+  MP_SHRINK(e);
+  MP_COPY(a);
+  if (MP_ZEROP(e))
+    ;
+  else {
+    if (MP_NEGP(e))
+      a = mp_modinv(a, a, mr->p);
+    if (MP_LEN(e) < EXP_THRESH)
+      EXP_SIMPLE(x, a, e);
+    else
+      EXP_WINDOW(x, a, e);
+  }
+  mp_drop(a);
+  mp_drop(d);
+  mp_drop(spare);
+  return (x);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+
+#ifdef TEST_RIG
+
+#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
+
+static int vreduce(dstr *v)
+{
+  mp *d = *(mp **)v[0].buf;
+  mp *n = *(mp **)v[1].buf;
+  mp *r = *(mp **)v[2].buf;
+  mp *c;
+  int ok = 1;
+  mpreduce rr;
+
+  mpreduce_create(&rr, d);
+  c = mpreduce_do(&rr, MP_NEW, n);
+  if (!MP_EQ(c, r)) {
+    fprintf(stderr, "\n*** reduction failed\n*** ");
+    mpreduce_dump(&rr, stderr);
+    fprintf(stderr, "\n*** n = "); mp_writefile(n, stderr, 10);
+    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 10);
+    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 10);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  mpreduce_destroy(&rr);
+  mp_drop(n); mp_drop(d); mp_drop(r); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vmodexp(dstr *v)
+{
+  mp *p = *(mp **)v[0].buf;
+  mp *g = *(mp **)v[1].buf;
+  mp *x = *(mp **)v[2].buf;
+  mp *r = *(mp **)v[3].buf;
+  mp *c;
+  int ok = 1;
+  mpreduce rr;
+
+  mpreduce_create(&rr, p);
+  c = mpreduce_exp(&rr, MP_NEW, g, x);
+  if (!MP_EQ(c, r)) {
+    fprintf(stderr, "\n*** modexp failed\n*** ");
+    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 10);
+    fprintf(stderr, "\n*** g = "); mp_writefile(g, stderr, 10);
+    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 10);
+    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 10);
+    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 10);
+    fprintf(stderr, "\n");
+    ok = 0;
+  }
+  mpreduce_destroy(&rr);
+  mp_drop(p); mp_drop(g); mp_drop(r); mp_drop(x); mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "reduce", vreduce, { &type_mp, &type_mp, &type_mp, 0 } },
+  { "modexp", vmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/mpreduce");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpreduce.h b/math/mpreduce.h
new file mode 100644 (file)
index 0000000..c90c93f
--- /dev/null
@@ -0,0 +1,126 @@
+/* -*-c-*-
+ *
+ * Efficient reduction modulo nice primes
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_MPREDUCE_H
+#define CATACOMB_MPREDUCE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct mpreduce_instr {
+  unsigned op;                         /* Instruction opcode */
+  size_t argx, argy;                   /* Immediate arguments */
+} mpreduce_instr;
+
+enum {
+  MPRI_ADD,                            /* Add @p@ offset by @x@ words */
+  MPRI_ADDLSL,                         /* Add @p << y@ offset by @x@ */
+  MPRI_SUB,                            /* Sub @p@ offset by @x@ words */
+  MPRI_SUBLSL,                         /* Sub @p << y@ offset by @x@ */
+  MPRI_MAX
+};
+
+typedef struct mpreduce {
+  size_t lim;                          /* Word containing top bit */
+  unsigned s;                          /* Shift for top word */
+  mp *p;                               /* Copy of the modulus */
+  size_t in;                           /* Number of instruction words */
+  mpreduce_instr *iv;                  /* Vector of instructions */
+} mpreduce;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mpreduce_create@ --- *
+ *
+ * Arguments:  @gfreduce *r@ = structure to fill in
+ *             @mp *x@ = an integer
+ *
+ * Returns:    Zero for success, nonzero on error.
+ *
+ * Use:                Initializes a context structure for reduction.
+ */
+
+extern int mpreduce_create(mpreduce */*r*/, mp */*p*/);
+
+/* --- @mpreduce_destroy@ --- *
+ *
+ * Arguments:  @mpreduce *r@ = structure to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Reclaims the resources from a reduction context.
+ */
+
+extern void mpreduce_destroy(mpreduce */*r*/);
+
+/* --- @mpreduce_dump@ --- *
+ *
+ * Arguments:  @mpreduce *r@ = structure to dump
+ *             @FILE *fp@ = file to dump on
+ *
+ * Returns:    ---
+ *
+ * Use:                Dumps a reduction context.
+ */
+
+extern void mpreduce_dump(mpreduce */*r*/, FILE */*fp*/);
+
+/* --- @mpreduce_do@ --- *
+ *
+ * Arguments:  @mpreduce *r@ = reduction context
+ *             @mp *d@ = destination
+ *             @mp *x@ = source
+ *
+ * Returns:    Destination, @x@ reduced modulo the reduction poly.
+ */
+
+extern mp *mpreduce_do(mpreduce */*r*/, mp */*d*/, mp */*x*/);
+
+/* --- @mpreduce_exp@ --- *
+ *
+ * Arguments:  @mpreduce *mr@ = pointer to reduction context
+ *             @mp *d@ = fake destination
+ *             @mp *a@ = base
+ *             @mp *e@ = exponent
+ *
+ * Returns:    Result, %$a^e \bmod m$%.
+ */
+
+extern mp *mpreduce_exp(mpreduce */*mr*/, mp */*d*/, mp */*a*/, mp */*e*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpscan.c b/math/mpscan.c
new file mode 100644 (file)
index 0000000..4b8c971
--- /dev/null
@@ -0,0 +1,120 @@
+/* -*-c-*-
+ *
+ * Sequential bit scan of multiprecision integers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mpscan.h"
+
+/*----- Right-to-left scanning --------------------------------------------*/
+
+/* --- @mpscan_initx@ --- *
+ *
+ * Arguments:  @mpscan *m@ = pointer to bitscanner structure
+ *             @const mpw *v, *vl@ = vector of words to scan
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a bitscanner from a low-level vector-and-length
+ *             representation of an integer.  Initially no bit is ready; you
+ *             must call @mpscan_step@ before anything useful will come
+ *             out.
+ */
+
+void mpscan_initx(mpscan *m, const mpw *v, const mpw *vl)
+{
+  MPSCAN_INITX(m, v, vl);
+}
+
+/* --- @mpscan_step@ --- *
+ *
+ * Arguments:  @mpscan *m@ = pointer to bitscanner
+ *
+ * Returns:    Nonzero if there is another bit to read.
+ *
+ * Use:                Steps on to the next bit in the integer.  The macro version
+ *             evaluates its argument multiple times.
+ */
+
+int mpscan_step(mpscan *m) { return (MPSCAN_STEP(m)); }
+
+/* --- @mpscan_bit@ --- *
+ *
+ * Arguments:  @const mpscan *m@ = pointer to bitscanner
+ *
+ * Returns:    The value of the current bit.
+ *
+ * Use:                Reads the value of the current bit looked at by a
+ *             bitscanner.
+ */
+
+int mpscan_bit(const mpscan *m) { return (MPSCAN_BIT(m)); }
+
+/*----- Left-to right-scanning --------------------------------------------*/
+
+/* --- @mpscan_rinitx@ --- *
+ *
+ * Arguments:  @mpscan *m@ = pointer to bitscanner structure
+ *             @const mpw *v, *vl@ = vector of words to scan
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a reverse bitscanner from a low-level
+ *             vector-and-length representation of an integer.  Initially no
+ *             bit is ready; you must call @mpscan_rstep@ before anything
+ *             useful will come out.
+ */
+
+void mpscan_rinitx(mpscan *m, const mpw *v, const mpw *vl)
+{
+  MPSCAN_RINITX(m, v, vl);
+}
+
+/* --- @mpscan_rstep@ --- *
+ *
+ * Arguments:  @mpscan *m@ = pointer to bitscanner
+ *
+ * Returns:    Nonzero if there is another bit to read.
+ *
+ * Use:                Steps on to the next bit in the integer.  The macro version
+ *             evaluates its argument multiple times.
+ */
+
+int mpscan_rstep(mpscan *m) { return (MPSCAN_RSTEP(m)); }
+
+/* --- @mpscan_rbit@ --- *
+ *
+ * Arguments:  @const mpscan *m@ = pointer to bitscanner
+ *
+ * Returns:    The value of the current bit.
+ *
+ * Use:                Reads the value of the current bit looked at by a
+ *             reverse bitscanner.
+ */
+
+int mpscan_rbit(const mpscan *m) { return (MPSCAN_RBIT(m)); }
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpscan.h b/math/mpscan.h
new file mode 100644 (file)
index 0000000..8ba4bd7
--- /dev/null
@@ -0,0 +1,170 @@
+/* -*-c-*-
+ *
+ * Sequential bit scan of multiprecision integers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPSCAN_H
+#define CATACOMB_MPSCAN_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MPW_H
+#  include "mpw.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct mpscan {
+  const mpw *v, *vl;                   /* Vector of words to scan */
+  mpw w;                               /* Current word to scan */
+  int bits;                            /* Number of bits left in @w@ */
+} mpscan;
+
+/*----- Right-to-left scanning --------------------------------------------*/
+
+/* --- @mpscan_initx@ --- *
+ *
+ * Arguments:  @mpscan *m@ = pointer to bitscanner structure
+ *             @const mpw *v, *vl@ = vector of words to scan
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a bitscanner from a low-level base-and-limit
+ *             representation of an integer.  Initially no bit is ready; you
+ *             must call @mpscan_step@ before anything useful will come
+ *             out.
+ */
+
+#define MPSCAN_INITX(m_, v_, vl_) do {                                 \
+  mpscan *_m = (m_);                                                   \
+  _m->v = (v_);                                                                \
+  _m->vl = (vl_);                                                      \
+  _m->bits = 0;                                                                \
+} while (0)
+
+extern void mpscan_initx(mpscan */*m*/, const mpw */*v*/, const mpw */*vl*/);
+
+/* --- @mpscan_step@ --- *
+ *
+ * Arguments:  @mpscan *m@ = pointer to bitscanner
+ *
+ * Returns:    Nonzero if there is another bit to read.
+ *
+ * Use:                Steps on to the next bit in the integer.  The macro version
+ *             evaluates its argument multiple times.
+ */
+
+#define MPSCAN_STEP(m)                                                 \
+  ((m)->bits ? ((m)->w >>= 1, (m)->bits--, 1) :                                \
+   (m)->v < (m)->vl ? ((m)->w = *(m)->v++,                             \
+                      (m)->bits = MPW_BITS - 1, 1) :                   \
+   0)
+
+extern int mpscan_step(mpscan */*m*/);
+
+/* --- @mpscan_bit@ --- *
+ *
+ * Arguments:  @const mpscan *m@ = pointer to bitscanner
+ *
+ * Returns:    The value of the current bit.
+ *
+ * Use:                Reads the value of the current bit looked at by a
+ *             bitscanner.
+ */
+
+#define MPSCAN_BIT(m) ((m)->w & 1)
+
+extern int mpscan_bit(const mpscan */*m*/);
+
+/*----- Left-to right-scanning --------------------------------------------*/
+
+/* --- @mpscan_rinitx@ --- *
+ *
+ * Arguments:  @mpscan *m@ = pointer to bitscanner structure
+ *             @const mpw *v, *vl@ = vector of words to scan
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a reverse bitscanner from a low-level
+ *             vector-and-length representation of an integer.  Initially no
+ *             bit is ready; you must call @mpscan_rstep@ before anything
+ *             useful will come out.
+ */
+
+#define MPSCAN_RINITX(m_, v_, vl_) do {                                        \
+  mpscan *_m = (m_);                                                   \
+  _m->v = (v_);                                                                \
+  _m->vl = (vl_);                                                      \
+  while (_m->vl > _m->v && !_m->vl[-1])                                        \
+    _m->vl--;                                                          \
+  _m->bits = 0;                                                                \
+} while (0)
+
+extern void mpscan_rinitx(mpscan */*m*/,
+                         const mpw */*v*/, const mpw */*vl*/);
+
+/* --- @mpscan_rstep@ --- *
+ *
+ * Arguments:  @mpscan *m@ = pointer to bitscanner
+ *
+ * Returns:    Nonzero if there is another bit to read.
+ *
+ * Use:                Steps on to the next bit in the integer.  The macro version
+ *             evaluates its argument multiple times.
+ */
+
+#define MPSCAN_RSTEP(m)                                                        \
+  ((m)->bits ? ((m)->w <<= 1, (m)->bits--, 1) :                                \
+   (m)->vl > (m)->v ? ((m)->w = *--(m)->vl,                            \
+                      (m)->bits = MPW_BITS - 1, 1) :                   \
+   0)
+
+extern int mpscan_rstep(mpscan */*m*/);
+
+/* --- @mpscan_rbit@ --- *
+ *
+ * Arguments:  @const mpscan *m@ = pointer to bitscanner
+ *
+ * Returns:    The value of the current bit.
+ *
+ * Use:                Reads the value of the current bit looked at by a
+ *             reverse bitscanner.
+ */
+
+#define MPSCAN_RBIT(m) (((m)->w >> (MPW_BITS - 1)) & 1)
+
+extern int mpscan_rbit(const mpscan */*m*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mptext-dstr.c b/math/mptext-dstr.c
new file mode 100644 (file)
index 0000000..bb52390
--- /dev/null
@@ -0,0 +1,86 @@
+/* -*-c-*-
+ *
+ * Reading and writing large integers on strings
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "mptext.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Operations table --- */
+
+static int get(void *p)
+{
+  mptext_dstrctx *c = p;
+  if (c->i >= c->d->len)
+    return (EOF);
+  return ((unsigned char)c->d->buf[c->i++]);
+}
+
+static void unget(int ch, void *p)
+{
+  mptext_dstrctx *c = p;
+  if (ch == EOF || c->i == 0)
+    return;
+  c->i--;
+}
+
+static int put(const char *s, size_t sz, void *p)
+{
+  mptext_dstrctx *c = p;
+  DPUTM(c->d, s, sz);
+  return (0);
+}
+
+const mptext_ops mptext_dstrops = { get, unget, put };
+
+/* --- Convenience functions --- */
+
+mp *mp_readdstr(mp *m, dstr *d, size_t *off, int radix)
+{
+  mptext_dstrctx c;
+  c.d = d;
+  c.i = off ? *off : 0;
+  m = mp_read(m, radix, &mptext_dstrops, &c);
+  if (off)
+    *off = c.i;
+  return (m);
+}
+
+int mp_writedstr(mp *m, dstr *d, int radix)
+{
+  mptext_dstrctx c;
+  int rc;
+  c.d = d;
+  rc = mp_write(m, radix, &mptext_dstrops, &c);
+  DPUTZ(d);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mptext-file.c b/math/mptext-file.c
new file mode 100644 (file)
index 0000000..aefcd49
--- /dev/null
@@ -0,0 +1,62 @@
+/* -*-c-*-
+ *
+ * Reading and writing large integers on files
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+
+#include "mptext.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Operations table --- */
+
+static int get(void *p) { FILE *fp = p; return getc(fp); }
+
+static void unget(int ch, void *p) { FILE *fp = p; ungetc(ch, fp); }
+
+static int put(const char *s, size_t sz, void *p)
+{
+  FILE *fp = p;
+  return (fwrite(s, 1, sz, fp) != sz);
+}
+
+const mptext_ops mptext_fileops = { get, unget, put };
+
+/* --- Convenience functions --- */
+
+mp *mp_readfile(mp *m, FILE *fp, int radix)
+{
+  return mp_read(m, radix, &mptext_fileops, fp);
+}
+
+int mp_writefile(mp *m, FILE *fp, int radix)
+{
+  return mp_write(m, radix, &mptext_fileops, fp);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mptext-len.c b/math/mptext-len.c
new file mode 100644 (file)
index 0000000..352dba2
--- /dev/null
@@ -0,0 +1,97 @@
+/* -*-c-*-
+ *
+ * Work out length of a number's string representation
+ *
+ * (c) 2002 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mptext.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mptext_len@ --- *
+ *
+ * Arguments:  @mp *x@ = number to work on
+ *             @int r@ = radix the number will be expressed in
+ *
+ * Returns:    The number of digits needed to represent the number in the
+ *             given base.  This will not include space for a leading sign
+ *             (use @MP_NEGP@ to check that, or just add one on for luck);
+ *             neither will it add space for a terminating null.  In general
+ *             the answer will be an overestimate.
+ */
+
+size_t mptext_len(mp *x, int r)
+{
+  unsigned long b = mp_bits(x);
+  int s, ss = 2;
+  size_t n;
+  unsigned d = 0;
+
+  /* --- Huh? --- *
+   *
+   * The number of digits is at most %$\lceil b \log 2/\log r \rceil$%.  We
+   * produce an underestimate of %$\log_2 r = \log r/\log 2$% and divide by
+   * that.  How?  By linear interpolation between known points on the curve.
+   * The known points are precisely the powers of 2, so we can find a pair
+   * efficiently by doubling up.  The log curve is convex, so linear
+   * interpolation between points on the curve is always an underestimate.
+   *
+   * The integer maths here is a bit weird, so here's how it works.  If
+   * %$s = 2^d$% is the power of 2 below %$r$% then we want to compute
+   * %$\lceil b/(d + (r - s)/s) \rceil = \lceil (b s)/(s(d - 1) + r \rceil$%
+   * which is %$\lfloor (r + s (b + d - 1) - 1)/(r + s(d - 1)) \rfloor$%.
+   * Gluing the whole computation together like this makes the code hard to
+   * read, but means that there are fewer possibilities for rounding errors
+   * and thus we get a tighter bound.
+   */
+
+  /* --- Find the right pair of points --- */
+
+  if (r < 0) r = -r;
+  do {
+    s = ss;
+    d++;
+    if (r == s) {
+      n = (b + (d - 1))/d;
+      goto done;
+    }
+    ss = s << 1;
+  } while (ss <= r);
+
+  /* --- Do the interpolation --- */
+
+  n = (r + s*(b + d - 1) - 1)/(r + s*(d - 1));
+
+  /* --- Fixups --- */
+
+done:
+  if (!n)
+    n = 1;
+  return (n);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mptext-string.c b/math/mptext-string.c
new file mode 100644 (file)
index 0000000..c70ca94
--- /dev/null
@@ -0,0 +1,96 @@
+/* -*-c-*-
+ *
+ * Reading and writing large integers on strings
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include "mptext.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Operations table --- */
+
+static int get(void *p)
+{
+  mptext_stringctx *c = p;
+  if (c->buf >= c->lim)
+    return (EOF);
+  return ((unsigned char)*c->buf++);
+}
+
+static void unget(int ch, void *p)
+{
+  mptext_stringctx *c = p;
+  if (ch != EOF)
+    c->buf--;
+}
+
+static int put(const char *s, size_t sz, void *p)
+{
+  mptext_stringctx *c = p;
+  int rc = 0;
+  if (sz > c->lim - c->buf) {
+    sz = c->lim - c->buf;
+    rc = EOF;
+  }
+  if (sz) {
+    memcpy(c->buf, s, sz);
+    c->buf += sz;
+  }
+  return (rc);
+}
+
+const mptext_ops mptext_stringops = { get, unget, put };
+
+/* --- Convenience functions --- */
+
+mp *mp_readstring(mp *m, const char *p, char **end, int radix)
+{
+  mptext_stringctx c;
+  c.buf = (/*unconst */ char *)p;
+  c.lim = c.buf + strlen(p);
+  m = mp_read(m, radix, &mptext_stringops, &c);
+  if (end)
+    *end = c.buf;
+  return (m);
+}
+
+int mp_writestring(mp *m, char *p, size_t sz, int radix)
+{
+  mptext_stringctx c;
+  int rc;
+  if (!sz)
+    return (0);
+  c.buf = p;
+  c.lim = p + sz - 1;
+  rc = mp_write(m, radix, &mptext_stringops, &c);
+  *c.buf = 0;
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mptext.c b/math/mptext.c
new file mode 100644 (file)
index 0000000..5d4640e
--- /dev/null
@@ -0,0 +1,849 @@
+/* -*-c-*-
+ *
+ * Textual representation of multiprecision numbers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "mp.h"
+#include "mptext.h"
+#include "paranoia.h"
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+/* --- Maximum recursion depth --- *
+ *
+ * This is the number of bits in a @size_t@ object.  Why?
+ *
+ * To see this, let %$b = \textit{MPW\_MAX} + 1$% and let %$Z$% be the
+ * largest @size_t@ value.  Then the largest possible @mp@ is %$M - 1$% where
+ * %$M = b^Z$%.  Let %$r$% be a radix to read or write.  Since the recursion
+ * squares the radix at each step, the highest number reached by the
+ * recursion is %$d$%, where:
+ *
+ *   %$r^{2^d} = b^Z$%.
+ *
+ * Solving gives that %$d = \lg \log_r b^Z$%.  If %$r = 2$%, this is maximum,
+ * so choosing %$d = \lg \lg b^Z = \lg (Z \lg b) = \lg Z + \lg \lg b$%.
+ *
+ * Expressing %$\lg Z$% as @CHAR_BIT * sizeof(size_t)@ yields an
+ * overestimate, since a @size_t@ representation may contain `holes'.
+ * Choosing to represent %$\lg \lg b$% by 10 is almost certainly sufficient
+ * for `some time to come'.
+ */
+
+#define DEPTH (CHAR_BIT * sizeof(size_t) + 10)
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mp_read@ --- *
+ *
+ * Arguments:  @mp *m@ = destination multiprecision number
+ *             @int radix@ = base to assume for data (or zero to guess)
+ *             @const mptext_ops *ops@ = pointer to operations block
+ *             @void *p@ = data for the operations block
+ *
+ * Returns:    The integer read, or zero if it didn't work.
+ *
+ * Use:                Reads an integer from some source.  If the @radix@ is
+ *             specified, the number is assumed to be given in that radix,
+ *             with the letters `a' (either upper- or lower-case) upwards
+ *             standing for digits greater than 9.  Otherwise, base 10 is
+ *             assumed unless the number starts with `0' (octal), `0x' (hex)
+ *             or `nnn_' (base `nnn').  An arbitrary amount of whitespace
+ *             before the number is ignored.
+ */
+
+/* --- About the algorithm --- *
+ *
+ * The algorithm here is rather aggressive.  I maintain an array of
+ * successive squarings of the radix, and a stack of partial results, each
+ * with a counter attached indicating which radix square to multiply by.
+ * Once the item at the top of the stack reaches the same counter level as
+ * the next item down, they are combined together and the result is given a
+ * counter level one higher than either of the results.
+ *
+ * Gluing the results together at the end is slightly tricky.  Pay attention
+ * to the code.
+ *
+ * This is more complicated because of the need to handle the slightly
+ * bizarre syntax.
+ */
+
+mp *mp_read(mp *m, int radix, const mptext_ops *ops, void *p)
+{
+  int ch;                              /* Current char being considered */
+  unsigned f = 0;                      /* Flags about the current number */
+  int r;                               /* Radix to switch over to */
+  mpw rd;                              /* Radix as an @mp@ digit */
+  mp rr;                               /* The @mp@ for the radix */
+  unsigned nf = m ? m->f & MP_BURN : 0;        /* New @mp@ flags */
+
+  /* --- Stacks --- */
+
+  mp *pow[DEPTH];                      /* List of powers */
+  unsigned pows;                       /* Next index to fill */
+  struct { unsigned i; mp *m; } s[DEPTH]; /* Main stack */
+  unsigned sp;                         /* Current stack pointer */
+
+  /* --- Flags --- */
+
+#define f_neg 1u
+#define f_ok 2u
+#define f_start 4u
+
+  /* --- Initialize the stacks --- */
+
+  mp_build(&rr, &rd, &rd + 1);
+  pow[0] = &rr;
+  pows = 1;
+
+  sp = 0;
+
+  /* --- Initialize the destination number --- */
+
+  if (m)
+    MP_DROP(m);
+
+  /* --- Read an initial character --- */
+
+  ch = ops->get(p);
+  if (radix >= 0) {
+    while (isspace(ch))
+      ch = ops->get(p);
+  }
+
+  /* --- Handle an initial sign --- */
+
+  if (radix >= 0 && (ch == '-' || ch == '+')) {
+    if (ch == '-')
+      f |= f_neg;
+    do ch = ops->get(p); while isspace(ch);
+  }
+
+  /* --- If the radix is zero, look for leading zeros --- */
+
+  if (radix > 0) {
+    assert(((void)"ascii radix must be <= 62", radix <= 62));
+    rd = radix;
+    r = -1;
+  } else if (radix < 0) {
+    rd = -radix;
+    assert(((void)"binary radix must fit in a byte", rd <= UCHAR_MAX));
+    r = -1;
+  } else if (ch != '0') {
+    rd = 10;
+    r = 0;
+  } else {
+    ch = ops->get(p);
+    switch (ch) {
+      case 'x':
+       rd = 16;
+       goto prefix;
+      case 'o':
+       rd = 8;
+       goto prefix;
+      case 'b':
+       rd = 2;
+       goto prefix;
+      prefix:
+       ch = ops->get(p);
+       break;
+      default:
+       rd = 8;
+       f |= f_ok;
+    }
+    r = -1;
+  }
+
+  /* --- Use fast algorithm for binary radix --- *
+   *
+   * This is the restart point after having parsed a radix number from the
+   * input.  We check whether the radix is binary, and if so use a fast
+   * algorithm which just stacks the bits up in the right order.
+   */
+
+restart:
+  switch (rd) {
+    unsigned bit;
+
+    case   2: bit = 1; goto bin;
+    case   4: bit = 2; goto bin;
+    case   8: bit = 3; goto bin;
+    case  16: bit = 4; goto bin;
+    case  32: bit = 5; goto bin;
+    case  64: bit = 6; goto bin;
+    case 128: bit = 7; goto bin;
+    default:
+      break;
+
+  /* --- The fast binary algorithm --- *
+   *
+   * We stack bits up starting at the top end of a word.  When one word is
+   * full, we write it to the integer, and start another with the left-over
+   * bits.  When the array in the integer is full, we resize using low-level
+   * calls and copy the current data to the top end.  Finally, we do a single
+   * bit-shift when we know where the end of the number is.
+   */
+
+  bin: {
+    mpw a = 0;
+    unsigned b = MPW_BITS;
+    size_t len, n;
+    mpw *v;
+
+    m = mp_dest(MP_NEW, 1, nf);
+    len = n = m->sz;
+    n = len;
+    v = m->v + n;
+    for (;; ch = ops->get(p)) {
+      unsigned x;
+
+      if (ch < 0)
+       break;
+
+      /* --- Check that the character is a digit and in range --- */
+
+      if (radix < 0)
+       x = ch % rd;
+      else {
+       if (!isalnum(ch))
+         break;
+       if (ch >= '0' && ch <= '9')
+         x = ch - '0';
+       else {
+         if (rd <= 36)
+           ch = tolower(ch);
+         if (ch >= 'a' && ch <= 'z')   /* ASCII dependent! */
+           x = ch - 'a' + 10;
+         else if (ch >= 'A' && ch <= 'Z')
+           x = ch - 'A' + 36;
+         else
+           break;
+       }
+      }
+      if (x >= rd)
+       break;
+
+      /* --- Feed the digit into the accumulator --- */
+
+      f |= f_ok;
+      if (!x && !(f & f_start))
+       continue;
+      f |= f_start;
+      if (b > bit) {
+       b -= bit;
+       a |= MPW(x) << b;
+      } else {
+       a |= MPW(x) >> (bit - b);
+       b += MPW_BITS - bit;
+       *--v = MPW(a);
+       n--;
+       if (!n) {
+         n = len;
+         len <<= 1;
+         v = mpalloc(m->a, len);
+         memcpy(v + n, m->v, MPWS(n));
+         mpfree(m->a, m->v);
+         m->v = v;
+         v = m->v + n;
+       }
+       a = (b < MPW_BITS) ? MPW(x) << b : 0;
+      }
+    }
+
+    /* --- Finish up --- */
+
+    if (!(f & f_ok)) {
+      mp_drop(m);
+      m = 0;
+    } else {
+      *--v = MPW(a);
+      n--;
+      m->sz = len;
+      m->vl = m->v + len;
+      m->f &= ~MP_UNDEF;
+      m = mp_lsr(m, m, (unsigned long)n * MPW_BITS + b);
+    }
+    ops->unget(ch, p);
+    goto done;
+  }}
+
+  /* --- Time to start --- */
+
+  for (;; ch = ops->get(p)) {
+    unsigned x;
+
+    if (ch < 0)
+      break;
+
+    /* --- An underscore indicates a numbered base --- */
+
+    if (ch == '_' && r > 0 && r <= 62) {
+      unsigned i;
+
+      /* --- Clear out the stacks --- */
+
+      for (i = 1; i < pows; i++)
+       MP_DROP(pow[i]);
+      pows = 1;
+      for (i = 0; i < sp; i++)
+       MP_DROP(s[i].m);
+      sp = 0;
+
+      /* --- Restart the search --- */
+
+      rd = r;
+      r = -1;
+      f &= ~f_ok;
+      ch = ops->get(p);
+      goto restart;
+    }
+
+    /* --- Check that the character is a digit and in range --- */
+
+    if (radix < 0)
+      x = ch % rd;
+    else {
+      if (!isalnum(ch))
+       break;
+      if (ch >= '0' && ch <= '9')
+       x = ch - '0';
+      else {
+       if (rd <= 36)
+         ch = tolower(ch);
+       if (ch >= 'a' && ch <= 'z')     /* ASCII dependent! */
+         x = ch - 'a' + 10;
+       else if (ch >= 'A' && ch <= 'Z')
+         x = ch - 'A' + 36;
+       else
+         break;
+      }
+    }
+
+    /* --- Sort out what to do with the character --- */
+
+    if (x >= 10 && r >= 0)
+      r = -1;
+    if (x >= rd)
+      break;
+
+    if (r >= 0)
+      r = r * 10 + x;
+
+    /* --- Stick the character on the end of my integer --- */
+
+    assert(((void)"Number is too unimaginably huge", sp < DEPTH));
+    s[sp].m = m = mp_new(1, nf);
+    m->v[0] = x;
+    s[sp].i = 0;
+
+    /* --- Now grind through the stack --- */
+
+    while (sp > 0 && s[sp - 1].i == s[sp].i) {
+
+      /* --- Combine the top two items --- */
+
+      sp--;
+      m = s[sp].m;
+      m = mp_mul(m, m, pow[s[sp].i]);
+      m = mp_add(m, m, s[sp + 1].m);
+      s[sp].m = m;
+      MP_DROP(s[sp + 1].m);
+      s[sp].i++;
+
+      /* --- Make a new radix power if necessary --- */
+
+      if (s[sp].i >= pows) {
+       assert(((void)"Number is too unimaginably huge", pows < DEPTH));
+       pow[pows] = mp_sqr(MP_NEW, pow[pows - 1]);
+       pows++;
+      }
+    }
+    f |= f_ok;
+    sp++;
+  }
+
+  ops->unget(ch, p);
+
+  /* --- If we're done, compute the rest of the number --- */
+
+  if (f & f_ok) {
+    if (!sp)
+      return (MP_ZERO);
+    else {
+      mp *z = MP_ONE;
+      sp--;
+
+      while (sp > 0) {
+
+       /* --- Combine the top two items --- */
+
+       sp--;
+       m = s[sp].m;
+       z = mp_mul(z, z, pow[s[sp + 1].i]);
+       m = mp_mul(m, m, z);
+       m = mp_add(m, m, s[sp + 1].m);
+       s[sp].m = m;
+       MP_DROP(s[sp + 1].m);
+
+       /* --- Make a new radix power if necessary --- */
+
+       if (s[sp].i >= pows) {
+         assert(((void)"Number is too unimaginably huge", pows < DEPTH));
+         pow[pows] = mp_sqr(MP_NEW, pow[pows - 1]);
+         pows++;
+       }
+      }
+      MP_DROP(z);
+      m = s[0].m;
+    }
+  } else {
+    unsigned i;
+    for (i = 0; i < sp; i++)
+      MP_DROP(s[i].m);
+  }
+
+  /* --- Clear the radix power list --- */
+
+  {
+    unsigned i;
+    for (i = 1; i < pows; i++)
+      MP_DROP(pow[i]);
+  }
+
+  /* --- Bail out if the number was bad --- */
+
+done:
+  if (!(f & f_ok))
+    return (0);
+
+  /* --- Set the sign and return --- */
+
+  if (f & f_neg)
+    m->f |= MP_NEG;
+  MP_SHRINK(m);
+  return (m);
+
+#undef f_start
+#undef f_neg
+#undef f_ok
+}
+
+/* --- @mp_write@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multi-precision integer
+ *             @int radix@ = radix to use when writing the number out
+ *             @const mptext_ops *ops@ = pointer to an operations block
+ *             @void *p@ = data for the operations block
+ *
+ * Returns:    Zero if it worked, nonzero otherwise.
+ *
+ * Use:                Writes a large integer in textual form.
+ */
+
+/* --- Simple case --- *
+ *
+ * Use a fixed-sized buffer and single-precision arithmetic to pick off
+ * low-order digits.  Put each digit in a buffer, working backwards from the
+ * end.  If the buffer becomes full, recurse to get another one.  Ensure that
+ * there are at least @z@ digits by writing leading zeroes if there aren't
+ * enough real digits.
+ */
+
+static int simple(mpw n, int radix, unsigned z,
+                 const mptext_ops *ops, void *p)
+{
+  int rc = 0;
+  char buf[64];
+  unsigned i = sizeof(buf);
+  int rd = radix > 0 ? radix : -radix;
+
+  do {
+    int ch;
+    mpw x;
+
+    x = n % rd;
+    n /= rd;
+    if (radix < 0)
+      ch = x;
+    else if (x < 10)
+      ch = '0' + x;
+    else if (x < 36)                   /* Ascii specific */
+      ch = 'a' + x - 10;
+    else
+      ch = 'A' + x - 36;
+    buf[--i] = ch;
+    if (z)
+      z--;
+  } while (i && n);
+
+  if (n)
+    rc = simple(n, radix, z, ops, p);
+  else {
+    char zbuf[32];
+    memset(zbuf, (radix < 0) ? 0 : '0', sizeof(zbuf));
+    while (!rc && z >= sizeof(zbuf)) {
+      rc = ops->put(zbuf, sizeof(zbuf), p);
+      z -= sizeof(zbuf);
+    }
+    if (!rc && z)
+      rc = ops->put(zbuf, z, p);
+  }
+  if (!rc)
+    rc = ops->put(buf + i, sizeof(buf) - i, p);
+  BURN(buf);
+  return (rc);
+}
+
+/* --- Complicated case --- *
+ *
+ * If the number is small, fall back to the simple case above.  Otherwise
+ * divide and take remainder by current large power of the radix, and emit
+ * each separately.  Don't emit a zero quotient.  Be very careful about
+ * leading zeroes on the remainder part, because they're deeply significant.
+ */
+
+static int complicated(mp *m, int radix, mp **pr, unsigned i, unsigned z,
+                      const mptext_ops *ops, void *p)
+{
+  int rc = 0;
+  mp *q = MP_NEW;
+  unsigned d = 1 << i;
+
+  if (MP_LEN(m) < 2)
+    return (simple(MP_LEN(m) ? m->v[0] : 0, radix, z, ops, p));
+
+  assert(i);
+  mp_div(&q, &m, m, pr[i]);
+  if (MP_ZEROP(q))
+    d = z;
+  else {
+    if (z > d)
+      z -= d;
+    else
+      z = 0;
+    rc = complicated(q, radix, pr, i - 1, z, ops, p);
+  }
+  if (!rc)
+    rc = complicated(m, radix, pr, i - 1, d, ops, p);
+  mp_drop(q);
+  return (rc);
+}
+
+/* --- Binary case --- *
+ *
+ * Special case for binary output.  Goes much faster.
+ */
+
+static int binary(mp *m, int bit, int radix, const mptext_ops *ops, void *p)
+{
+  mpw *v;
+  mpw a;
+  int rc = 0;
+  unsigned b;
+  unsigned mask;
+  unsigned long n;
+  unsigned f = 0;
+  char buf[8], *q;
+  unsigned x;
+  int ch;
+
+#define f_out 1u
+
+  /* --- Work out where to start --- */
+
+  n = mp_bits(m);
+  if (n % bit)
+    n += bit - (n % bit);
+  b = n % MPW_BITS;
+  n /= MPW_BITS;
+
+  if (n >= MP_LEN(m)) {
+    n--;
+    b += MPW_BITS;
+  }
+
+  v = m->v + n;
+  a = *v;
+  mask = (1 << bit) - 1;
+  q = buf;
+
+  /* --- Main code --- */
+
+  for (;;) {
+    if (b > bit) {
+      b -= bit;
+      x = a >> b;
+    } else {
+      x = a << (bit - b);
+      b += MPW_BITS - bit;
+      if (v == m->v)
+       break;
+      a = *--v;
+      if (b < MPW_BITS)
+       x |= a >> b;
+    }
+    x &= mask;
+    if (!x && !(f & f_out))
+      continue;
+
+    if (radix < 0)
+      ch = x;
+    else if (x < 10)
+      ch = '0' + x;
+    else if (x < 36)
+      ch = 'a' + x - 10;               /* Ascii specific */
+    else
+      ch = 'A' + x - 36;
+    *q++ = ch;
+    if (q >= buf + sizeof(buf)) {
+      if ((rc = ops->put(buf, sizeof(buf), p)) != 0)
+       goto done;
+      q = buf;
+    }
+    f |= f_out;
+  }
+
+  x &= mask;
+  if (radix < 0)
+    ch = x;
+  else if (x < 10)
+    ch = '0' + x;
+  else if (x < 36)
+    ch = 'a' + x - 10;                 /* Ascii specific */
+  else
+    ch = 'A' + x - 36;
+  *q++ = ch;
+  rc = ops->put(buf, q - buf, p);
+
+done:
+  mp_drop(m);
+  return (rc);
+
+#undef f_out
+}
+
+/* --- Main driver code --- */
+
+int mp_write(mp *m, int radix, const mptext_ops *ops, void *p)
+{
+  int rc;
+
+  if (MP_EQ(m, MP_ZERO))
+    return (ops->put(radix > 0 ? "0" : "\0", 1, p));
+
+  /* --- Set various things up --- */
+
+  m = MP_COPY(m);
+  MP_SPLIT(m);
+
+  /* --- Check the radix for sensibleness --- */
+
+  if (radix > 0)
+    assert(((void)"ascii radix must be <= 62", radix <= 62));
+  else if (radix < 0)
+    assert(((void)"binary radix must fit in a byte", -radix <= UCHAR_MAX));
+  else
+    assert(((void)"radix can't be zero in mp_write", 0));
+
+  /* --- If the number is negative, sort that out --- */
+
+  if (MP_NEGP(m)) {
+    assert(radix > 0);
+    if (ops->put("-", 1, p))
+      return (EOF);
+    m->f &= ~MP_NEG;
+  }
+
+  /* --- Handle binary radix --- */
+
+  switch (radix) {
+    case   2: case   -2: return (binary(m, 1, radix, ops, p));
+    case   4: case   -4: return (binary(m, 2, radix, ops, p));
+    case   8: case   -8: return (binary(m, 3, radix, ops, p));
+    case  16: case  -16: return (binary(m, 4, radix, ops, p));
+    case  32: case  -32: return (binary(m, 5, radix, ops, p));
+             case  -64: return (binary(m, 6, radix, ops, p));
+             case -128: return (binary(m, 7, radix, ops, p));
+  }
+
+  /* --- If the number is small, do it the easy way --- */
+
+  if (MP_LEN(m) < 2)
+    rc = simple(MP_LEN(m) ? m->v[0] : 0, radix, 0, ops, p);
+
+  /* --- Use a clever algorithm --- *
+   *
+   * Square the radix repeatedly, remembering old results, until I get
+   * something more than half the size of the number @m@.  Use this to divide
+   * the number: the quotient and remainder will be approximately the same
+   * size, and I'll have split them on a digit boundary, so I can just emit
+   * the quotient and remainder recursively, in order.
+   */
+
+  else {
+    mp *pr[DEPTH];
+    size_t target = (MP_LEN(m) + 1) / 2;
+    unsigned i = 0;
+    mp *z = mp_new(1, 0);
+
+    /* --- Set up the exponent table --- */
+
+    z->v[0] = (radix > 0 ? radix : -radix);
+    z->f = 0;
+    for (;;) {
+      assert(((void)"Number is too unimaginably huge", i < DEPTH));
+      pr[i++] = z;
+      if (MP_LEN(z) > target)
+       break;
+      z = mp_sqr(MP_NEW, z);
+    }
+
+    /* --- Write out the answer --- */
+
+    rc = complicated(m, radix, pr, i - 1, 0, ops, p);
+
+    /* --- Tidy away the array --- */
+
+    while (i > 0)
+      mp_drop(pr[--i]);
+  }
+
+  /* --- Tidying up code --- */
+
+  MP_DROP(m);
+  return (rc);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int verify(dstr *v)
+{
+  int ok = 1;
+  int ib = *(int *)v[0].buf, ob = *(int *)v[2].buf;
+  dstr d = DSTR_INIT;
+  size_t off = 0;
+  mp *m = mp_readdstr(MP_NEW, &v[1], &off, ib);
+  if (m) {
+    if (!ob) {
+      fprintf(stderr, "*** unexpected successful parse\n"
+                     "*** input [%2i] =     ", ib);
+      if (ib < 0)
+       type_hex.dump(&v[1], stderr);
+      else
+       fputs(v[1].buf, stderr);
+      mp_writedstr(m, &d, 10);
+      fprintf(stderr, "\n*** (value = %s)\n", d.buf);
+      ok = 0;
+    } else {
+      mp_writedstr(m, &d, ob);
+      if (d.len != v[3].len || memcmp(d.buf, v[3].buf, d.len) != 0) {
+       fprintf(stderr, "*** failed read or write\n"
+                       "*** input [%2i]      = ", ib);
+       if (ib < 0)
+         type_hex.dump(&v[1], stderr);
+       else
+         fputs(v[1].buf, stderr);
+       fprintf(stderr, "\n*** output [%2i]     = ", ob);
+       if (ob < 0)
+         type_hex.dump(&d, stderr);
+       else
+         fputs(d.buf, stderr);
+       fprintf(stderr, "\n*** expected [%2i]   = ", ob);
+       if (ob < 0)
+         type_hex.dump(&v[3], stderr);
+       else
+         fputs(v[3].buf, stderr);
+       fputc('\n', stderr);
+       ok = 0;
+      }
+    }
+    mp_drop(m);
+  } else {
+    if (ob) {
+      fprintf(stderr, "*** unexpected parse failure\n"
+                     "*** input [%2i]    = ", ib);
+      if (ib < 0)
+       type_hex.dump(&v[1], stderr);
+      else
+       fputs(v[1].buf, stderr);
+      fprintf(stderr, "\n*** expected [%2i]   = ", ob);
+      if (ob < 0)
+       type_hex.dump(&v[3], stderr);
+      else
+       fputs(v[3].buf, stderr);
+      fputc('\n', stderr);
+      ok = 0;
+    }
+  }
+
+  if (v[1].len - off != v[4].len ||
+      memcmp(v[1].buf + off, v[4].buf, v[4].len) != 0) {
+    fprintf(stderr, "*** leftovers incorrect\n"
+                   "*** input [%2i]    = ", ib);
+    if (ib < 0)
+      type_hex.dump(&v[1], stderr);
+    else
+      fputs(v[1].buf, stderr);
+    fprintf(stderr, "\n*** expected `%s'\n"
+                   "*** found `%s'\n",
+           v[4].buf, v[1].buf + off);
+    ok = 0;
+  }
+
+  dstr_destroy(&d);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "mptext-ascii", verify,
+    { &type_int, &type_string, &type_int, &type_string, &type_string, 0 } },
+  { "mptext-bin-in", verify,
+    { &type_int, &type_hex, &type_int, &type_string, &type_string, 0 } },
+  { "mptext-bin-out", verify,
+    { &type_int, &type_string, &type_int, &type_hex, &type_string, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/mptext");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mptext.h b/math/mptext.h
new file mode 100644 (file)
index 0000000..8d9342d
--- /dev/null
@@ -0,0 +1,184 @@
+/* -*-c-*-
+ *
+ * Textual representation of multiprecision numbers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPTEXT_H
+#define CATACOMB_MPTEXT_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct mptext_ops {
+  int (*get)(void */*p*/);
+  void (*unget)(int /*ch*/, void */*p*/);
+  int (*put)(const char */*s*/, size_t /*len*/, void */*p*/);
+} mptext_ops;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mp_read@ --- *
+ *
+ * Arguments:  @mp *m@ = destination multiprecision number
+ *             @int radix@ = base to assume for data (or zero to guess)
+ *             @const mptext_ops *ops@ = pointer to operations block
+ *             @void *p@ = data for the operations block
+ *
+ * Returns:    The integer read, or zero if it didn't work.
+ *
+ * Use:                Reads an integer from some source.  If the @radix@ is
+ *             specified, the number is assumed to be given in that radix,
+ *             with the letters `a' (either upper- or lower-case) upwards
+ *             standing for digits greater than 9.  Otherwise, base 10 is
+ *             assumed unless the number starts with `0' (octal), `0x' (hex)
+ *             or `nnn_' (base `nnn').  An arbitrary amount of whitespace
+ *             before the number is ignored.
+ */
+
+extern mp *mp_read(mp */*m*/, int /*radix*/,
+                  const mptext_ops */*ops*/, void */*p*/);
+
+/* --- @mp_write@ --- *
+ *
+ * Arguments:  @mp *m@ = pointer to a multi-precision integer
+ *             @int radix@ = radix to use when writing the number out
+ *             @const mptext_ops *ops@ = pointer to an operations block
+ *             @void *p@ = data for the operations block
+ *
+ * Returns:    Zero if it worked, nonzero otherwise.
+ *
+ * Use:                Writes a large integer in textual form.
+ */
+
+extern int mp_write(mp */*m*/, int /*radix*/,
+                   const mptext_ops */*ops*/, void */*p*/);
+
+/* --- @mptext_len@ --- *
+ *
+ * Arguments:  @mp *x@ = number to work on
+ *             @int r@ = radix the number will be expressed in
+ *
+ * Returns:    The number of digits needed to represent the number in the
+ *             given base.  This will not include space for a leading sign
+ *             (use @MP_NEGP@ to check that, or just add one on for luck);
+ *             neither will it add space for a terminating null.  In general
+ *             the answer will be an overestimate.
+ */
+
+extern size_t mptext_len(mp */*x*/, int /*r*/);
+
+/*----- File I/O ----------------------------------------------------------*/
+
+#include <stdio.h>
+
+/* --- Operations table --- *
+ *
+ * The @mptext_fileops@ expect the pointer argument to be a @FILE *@.
+ */
+
+extern const mptext_ops mptext_fileops;
+
+/* --- Convenience functions --- */
+
+extern mp *mp_readfile(mp */*m*/, FILE */*fp*/, int /*radix*/);
+extern int mp_writefile(mp */*m*/, FILE */*fp*/, int /*radix*/);
+
+#define MP_DOFPRINTFR(fp, args, m, r) do {                             \
+  fprintf args;                                                                \
+  if (m)                                                               \
+    mp_writefile(m, fp, r);                                            \
+  else                                                                 \
+    fputs("<null>", fp);                                               \
+  fputc('\n', fp);                                                     \
+} while (0)
+
+#define MP_DOFPRINTR(fp, name, m, r)                                   \
+  MP_DOFPRINTFR(fp, (fp, "%s = ", name), m, r)
+
+#define MP_PRINT(name, m) MP_DOFPRINTR(stdout, name, m, 10)
+#define MP_EPRINT(name, m) MP_DOFPRINTR(stderr, name, m, 10)
+#define MP_PRINTX(name, m) MP_DOFPRINTR(stdout, name, m, 16)
+#define MP_EPRINTX(name, m) MP_DOFPRINTR(stderr, name, m, 16)
+
+#define MP_FPRINTF(fp, args, m) MP_DOFPRINTFR(fp, args, m, 10)
+#define MP_FPRINTFX(fp, args, m) MP_DOFPRINTFR(fp, args, m, 16)
+
+/*----- String I/O --------------------------------------------------------*/
+
+/* --- Context format --- */
+
+typedef struct mptext_stringctx {
+  char *buf;
+  char *lim;
+} mptext_stringctx;
+
+/* --- Operations table --- */
+
+extern const mptext_ops mptext_stringops;
+
+/* --- Convenience functions --- */
+
+extern mp *mp_readstring(mp */*m*/, const char */*p*/, char **/*end*/,
+                        int /*radix*/);
+extern int mp_writestring(mp */*m*/, char */*p*/, size_t /*sz*/,
+                         int /*radix*/);
+
+/*----- Dynamic string I/O ------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+/* --- Context format --- */
+
+typedef struct mptext_dstrctx {
+  dstr *d;
+  size_t i;
+} mptext_dstrctx;
+
+/* --- Operations table --- */
+
+extern const mptext_ops mptext_dstrops;
+
+/* --- Convenience functions --- */
+
+extern mp *mp_readdstr(mp */*m*/, dstr */*d*/, size_t */*off*/,
+                      int /*radix*/);
+extern int mp_writedstr(mp */*m*/, dstr */*d*/, int /*radix*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mptypes.c b/math/mptypes.c
new file mode 100644 (file)
index 0000000..807ffee
--- /dev/null
@@ -0,0 +1,212 @@
+/* -*-c-*-
+ *
+ * Generate `mptypes.h' header file for current architecture
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _GNU_SOURCE
+#include "config.h"
+
+#include <stdio.h>
+#include <limits.h>
+#if __STDC_VERSION__ >= 199900l
+#  include <stdint.h>
+#  include <inttypes.h>
+#endif
+
+/*----- Data types --------------------------------------------------------*/
+
+/* --- Hack for GCC --- *
+ *
+ * WG14 in their infinite wisdom decided not to use the GCC constant name.
+ */
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)
+#  define EXT __extension__
+#else
+#  define EXT
+#endif
+
+#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
+#  define ULLONG_MAX ULONG_LONG_MAX
+#endif
+
+/* --- Choose the largest integer type --- */
+
+#if defined(UINTMAX_MAX) && defined(PRIuMAX)
+  typedef uintmax_t umax;
+# define P_UMAX PRIuMAX
+#elif defined(ULLONG_MAX)
+  EXT typedef unsigned long long umax;
+# define P_UMAX "llu"
+#else
+  typedef unsigned long umax;
+# define P_UMAX "lu"
+#endif
+
+/* --- Table of interesting types --- *
+ *
+ * These are in preference order.
+ */
+
+enum {
+  f_stdint = 1u,
+  f_ext = 2u
+};
+
+struct itype {
+  const char *name;
+  const char *suff;
+  umax max;
+  unsigned flags;
+  unsigned bits;
+} tytab[] = {
+  { "unsigned int",            "u",    UINT_MAX,               0 },
+  { "unsigned short",          "u",    USHRT_MAX,              0 },
+  { "unsigned long",           "ul",   ULONG_MAX,              0 },
+#ifdef ULLONG_MAX
+  { "unsigned long long",      "ull",  EXT ULLONG_MAX,         f_ext },
+#endif
+#ifdef UINTMAX_MAX
+  { "uintmax_t",               "u",    UINTMAX_MAX,            f_stdint },
+#endif
+  { 0,                         0 },
+};
+
+typedef struct itype itype;
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  itype *i;
+  itype *largest, *mpw, *mpd;
+  const static char *extstr = "CATACOMB_MPTYPES_EXTENSION ";
+  unsigned p2;
+
+  /* --- Find the bitcounts --- */
+
+  for (i = tytab; i->name; i++) {
+    unsigned bits;
+    umax u = i->max;
+    for (bits = 0; u; bits++)
+      u >>= 1;
+    i->bits = bits;
+  }
+
+  /* --- Now try to find the interesting types --- *
+   *
+   * The first thing to do is to find the largest type.  Then I find the
+   * `best' type which is less than half that size, and then the `best' type
+   * which is twice as big as that one.
+   */
+
+#if defined(FORCE_MPW_CUSSID)
+  largest = mpd = &tytab[3];
+  mpw = &tytab[2];
+  mpw->bits = 19; mpw->max = 0x7ffff;
+  mpd->bits = 38; mpd->max = 0x3fffffffffll;
+#elif defined(FORCE_MPW_SHORT)
+  largest = mpd = &tytab[2];
+  mpw = &tytab[1];
+  mpw->bits = 16; mpw->max = 0xffff;
+  mpd->bits = 32; mpd->max = 0xffffffff;
+#else
+  largest = tytab;
+  for (i = tytab; i->name; i++) {
+    if (i->bits > largest->bits)
+      largest = i;
+  }
+  for (mpw = 0, i = tytab; i->name; i++) {
+    if (i->bits * 2 <= largest->bits && (!mpw || i->bits > mpw->bits))
+      mpw = i;
+  }
+  if (!mpw)
+    mpw = tytab;
+  for (mpd = 0, i = tytab; i->name; i++) {
+    if (i->bits >= mpw->bits * 2 && (!mpd || i->bits < mpd->bits))
+      mpd = i;
+  }
+  if (!mpd) {
+    static itype w, d;
+    d = w = *mpw;
+    w.bits /= 2; w.max = ~(~((umax)0) << w.bits);
+    d.bits = w.bits * 2; d.max = ~(~((umax)0) << d.bits);
+    mpw = &w; mpd = &d;
+  }
+#endif
+  for (p2 = 1; (p2 << 1) < mpw->bits; p2 <<= 1);
+
+  /* --- Output time --- */
+
+  puts("\
+/* -*-c-*-\n\
+ *\n\
+ * mptypes.h [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_MPTYPES_H\n\
+#define CATACOMB_MPTYPES_H\n\
+");
+  if ((mpd->flags | mpw->flags) & f_stdint) {
+    puts("\
+#if __STDC_VERSION__ >= 199900l\n\
+#  include <stdint.h>\n\
+#endif\n\
+");
+  }
+  if ((mpd->flags | mpw->flags) & f_ext) {
+    printf("\
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)\n\
+#  define %s __extension__\n\
+#else\n\
+#  define %s\n\
+#endif\n\
+", extstr, extstr);
+  }
+  printf("\
+%stypedef %s mpw;\n\
+#define MPW_BITS %u\n\
+#define MPW_P2 %u\n\
+#define MPW_MAX %s%" P_UMAX "%s\n\
+\n\
+%stypedef %s mpd;\n\
+#define MPD_BITS %u\n\
+#define MPD_MAX %s%" P_UMAX "%s\n\
+\n\
+#endif\n\
+",
+  mpw->flags & f_ext ? extstr : "", mpw->name,
+  mpw->bits, p2,
+  mpw->flags & f_ext ? extstr : "", mpw->max, mpw->suff,
+  mpd->flags & f_ext ? extstr : "", mpd->name,
+  mpd->bits,
+  mpd->flags & f_ext ? extstr : "", mpd->max, mpd->suff);
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpw.h b/math/mpw.h
new file mode 100644 (file)
index 0000000..fa66316
--- /dev/null
@@ -0,0 +1,83 @@
+/* -*-c-*-
+ *
+ * Very low-level multiprecision definitions
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPW_H
+#define CATACOMB_MPW_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_BITS_H
+#  include <mLib/bits.h>
+#endif
+
+#ifndef CATACOMB_MPTYPES_H
+#  include "mptypes.h"
+#endif
+
+/*----- Useful macros -----------------------------------------------------*/
+
+/* --- @MPW@ --- *
+ *
+ * Arguments:  @x@ = an unsigned value
+ *
+ * Use:                Expands to the value of @x@ masked and typecast to a
+ *             multiprecision integer word.
+ */
+
+#define MPW(x) ((mpw)((x) & MPW_MAX))
+
+/* --- @MPWS@ --- *
+ *
+ * Arguments:  @n@ = number of words
+ *
+ * Use:                Expands to the number of bytes occupied by a given number of
+ *             words.
+ */
+
+#define MPWS(n) ((n) * sizeof(mpw))
+
+/* --- @MPW_RQ@ --- *
+ *
+ * Arguments:  @sz@ = size of an octet array, in octets
+ *
+ * Use:                Expands to the number of @mpw@ words required to represent
+ *             the number held in the octet array.
+ */
+
+#define MPW_RQ(sz) (((sz) * 8 + MPW_BITS - 1) / MPW_BITS)
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/mpx-kmul.c b/math/mpx-kmul.c
new file mode 100644 (file)
index 0000000..35a3deb
--- /dev/null
@@ -0,0 +1,247 @@
+/* -*-c-*-
+ *
+ * Karatsuba's multiplication algorithm
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "mpx.h"
+#include "karatsuba.h"
+
+/*----- Tweakables --------------------------------------------------------*/
+
+#ifdef TEST_RIG
+#  undef MPK_THRESH
+#  define MPK_THRESH 4                 /* Smallest possible correct value */
+#endif
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpx_kmul@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
+ *             @const mpw *av, *avl@ = pointer to first argument
+ *             @const mpw *bv, *bvl@ = pointer to second argument
+ *             @mpw *sv, *svl@ = pointer to scratch workspace
+ *
+ * Returns:    ---
+ *
+ * Use:                Multiplies two multiprecision integers using Karatsuba's
+ *             algorithm.  This is rather faster than traditional long
+ *             multiplication (e.g., @mpx_umul@) on large numbers, although
+ *             more expensive on small ones.
+ *
+ *             The destination must be three times as large as the larger
+ *             argument.  The scratch space must be five times as large as
+ *             the larger argument.
+ */
+
+void mpx_kmul(mpw *dv, mpw *dvl,
+             const mpw *av, const mpw *avl,
+             const mpw *bv, const mpw *bvl,
+             mpw *sv, mpw *svl)
+{
+  const mpw *avm, *bvm;
+  size_t m;
+
+  /* --- Dispose of easy cases to @mpx_umul@ --- *
+   *
+   * Karatsuba is only a win on large numbers, because of all the
+   * recursiveness and bookkeeping.  The recursive calls make a quick check
+   * to see whether to bottom out to @mpx_umul@ which should help quite a
+   * lot, but sometimes the only way to know is to make sure...
+   */
+
+  MPX_SHRINK(av, avl);
+  MPX_SHRINK(bv, bvl);
+
+  if (avl - av <= MPK_THRESH || bvl - bv <= MPK_THRESH) {
+    mpx_umul(dv, dvl, av, avl, bv, bvl);
+    return;
+  }
+
+  /* --- How the algorithm works --- *
+   *
+   * Let %$A = xb + y$% and %$B = ub + v$%.  Then, simply by expanding,
+   * %$AB = x u b^2 + b(x v + y u) + y v$%.  That's not helped any, because
+   * I've got four multiplications, each four times easier than the one I
+   * started with.  However, note that I can rewrite the coefficient of %$b$%
+   * as %$xv + yu = (x + y)(u + v) - xu - yv$%.  The terms %$xu$% and %$yv$%
+   * I've already calculated, and that leaves only one more multiplication to
+   * do.  So now I have three multiplications, each four times easier, and
+   * that's a win.
+   */
+
+  /* --- First things --- *
+   *
+   * Sort out where to break the factors in half.  I'll choose the midpoint
+   * of the larger one, since this minimizes the amount of work I have to do
+   * most effectively.
+   */
+
+  if (avl - av > bvl - bv) {
+    m = (avl - av + 1) >> 1;
+    avm = av + m;
+    if (bvl - bv > m)
+      bvm = bv + m;
+    else
+      bvm = bvl;
+  } else {
+    m = (bvl - bv + 1) >> 1;
+    bvm = bv + m;
+    if (avl - av > m)
+      avm = av + m;
+    else
+      avm = avl;
+  }
+
+  /* --- Sort out the middle term --- */
+
+  {
+    mpw *bsv = sv + m + 1, *ssv = bsv + m + 1;
+    mpw *rdv = dv + m, *rdvl = rdv + 2 * (m + 2);
+
+    assert(rdvl <= dvl);
+    assert(ssv <= svl);
+    UADD2(sv, bsv, av, avm, avm, avl);
+    UADD2(bsv, ssv, bv, bvm, bvm, bvl);
+    if (m > MPK_THRESH)
+      mpx_kmul(rdv, rdvl, sv, bsv, bsv, ssv, ssv, svl);
+    else
+      mpx_umul(rdv, rdvl, sv, bsv, bsv, ssv);
+  }
+
+  /* --- Sort out the other two terms --- */
+
+  {
+    mpw *svm = sv + m, *svn = svm + m, *ssv = svn + 4;
+    mpw *tdv = dv + m;
+    mpw *rdv = tdv + m;
+
+    if (avl == avm || bvl == bvm)
+      MPX_ZERO(rdv + m + 1, dvl);
+    else {
+      if (m > MPK_THRESH)
+       mpx_kmul(sv, ssv, avm, avl, bvm, bvl, ssv, svl);
+      else
+       mpx_umul(sv, ssv, avm, avl, bvm, bvl);
+      MPX_COPY(rdv + m + 1, dvl, svm + 1, svn);
+      UADD(rdv, sv, svm + 1);
+      USUB(tdv, sv, svn);
+    }
+
+    if (m > MPK_THRESH)
+      mpx_kmul(sv, ssv, av, avm, bv, bvm, ssv, svl);
+    else
+      mpx_umul(sv, ssv, av, avm, bv, bvm);
+    MPX_COPY(dv, tdv, sv, svm);
+    USUB(tdv, sv, svn);
+    UADD(tdv, svm, svn);
+  }
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/alloc.h>
+#include <mLib/testrig.h>
+
+#define ALLOC(v, vl, sz) do {                                          \
+  size_t _sz = (sz);                                                   \
+  mpw *_vv = xmalloc(MPWS(_sz));                                       \
+  mpw *_vvl = _vv + _sz;                                               \
+  (v) = _vv;                                                           \
+  (vl) = _vvl;                                                         \
+} while (0)
+
+#define LOAD(v, vl, d) do {                                            \
+  const dstr *_d = (d);                                                        \
+  mpw *_v, *_vl;                                                       \
+  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
+  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
+  (v) = _v;                                                            \
+  (vl) = _vl;                                                          \
+} while (0)
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
+{
+  fputs(msg, stderr);
+  MPX_SHRINK(v, vl);
+  while (v < vl)
+    fprintf(stderr, " %08lx", (unsigned long)*--vl);
+  fputc('\n', stderr);
+}
+
+static int umul(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  mpw *s, *sl;
+  size_t m;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(b, bl, &v[1]);
+  LOAD(c, cl, &v[2]);
+  m = MAX(al - a, bl - b) + 1;
+  ALLOC(d, dl, 3 * m);
+  ALLOC(s, sl, 5 * m);
+
+  mpx_kmul(d, dl, a, al, b, bl, s, sl);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** umul failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("      b", b, bl);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(c); xfree(d); xfree(s);
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/mpx");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpx-ksqr.c b/math/mpx-ksqr.c
new file mode 100644 (file)
index 0000000..e96040b
--- /dev/null
@@ -0,0 +1,211 @@
+/* -*-c-*-
+ *
+ * Karatsuba-based squaring algorithm
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "mpx.h"
+#include "karatsuba.h"
+
+/*----- Tweakables --------------------------------------------------------*/
+
+#ifdef TEST_RIG
+#  undef MPK_THRESH
+#  define MPK_THRESH 4
+#endif
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mpx_ksqr@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
+ *             @const mpw *av, *avl@ = pointer to first argument
+ *             @mpw *sv, *svl@ = pointer to scratch workspace
+ *
+ * Returns:    ---
+ *
+ * Use:                Squares a multiprecision integers using something similar to
+ *             Karatsuba's multiplication algorithm.  This is rather faster
+ *             than traditional long multiplication (e.g., @mpx_umul@) on
+ *             large numbers, although more expensive on small ones, and
+ *             rather simpler than full-blown Karatsuba multiplication.
+ *
+ *             The destination must be three times as large as the larger
+ *             argument.  The scratch space must be five times as large as
+ *             the larger argument.
+ */
+
+void mpx_ksqr(mpw *dv, mpw *dvl,
+             const mpw *av, const mpw *avl,
+             mpw *sv, mpw *svl)
+{
+  const mpw *avm;
+  size_t m;
+
+  /* --- Dispose of easy cases to @mpx_usqr@ --- *
+   *
+   * Karatsuba is only a win on large numbers, because of all the
+   * recursiveness and bookkeeping.  The recursive calls make a quick check
+   * to see whether to bottom out to @mpx_usqr@ which should help quite a
+   * lot, but sometimes the only way to know is to make sure...
+   */
+
+  MPX_SHRINK(av, avl);
+
+  if (avl - av <= MPK_THRESH) {
+    mpx_usqr(dv, dvl, av, avl);
+    return;
+  }
+
+  /* --- How the algorithm works --- *
+   *
+   * The identity for squaring is known to all schoolchildren.
+   * Let %$A = xb + y$%.  Then %$A^2 = x^2 b^2 + 2 x y b + y^2$%.  Now,
+   * %$(x + y)^2 - x^2 - y^2 = 2 x y$%, which means I only need to do three
+   * squarings.
+   */
+
+  /* --- First things --- *
+   *
+   * Sort out where to break the factor in half.
+   */
+
+  m = (avl - av + 1) >> 1;
+  avm = av + m;
+
+  /* --- Sort out everything --- */
+
+  {
+    mpw *svm = sv + m, *svn = svm + m, *ssv = svn + 4;
+    mpw *tdv = dv + m;
+    mpw *rdv = tdv + m;
+
+    assert(rdv + m + 4 < dvl);
+    assert(ssv < svl);
+    UADD2(sv, svm, av, avm, avm, avl);
+    if (m > MPK_THRESH)
+      mpx_ksqr(tdv, rdv + m + 4, sv, svm + 1, ssv, svl);
+    else
+      mpx_usqr(tdv, rdv + m + 4, sv, svm + 1);
+
+    if (m > MPK_THRESH)
+      mpx_ksqr(sv, ssv, avm, avl, ssv, svl);
+    else
+      mpx_usqr(sv, ssv, avm, avl);
+    MPX_COPY(rdv + m + 1, dvl, svm + 1, svn);
+    UADD(rdv, sv, svm + 1);
+    USUB(tdv, sv, svn);
+
+    if (m > MPK_THRESH)
+      mpx_ksqr(sv, ssv, av, avm, ssv, svl);
+    else
+      mpx_usqr(sv, ssv, av, avm);
+    MPX_COPY(dv, tdv, sv, svm);
+    UADD(tdv, svm, svn);
+    USUB(tdv, sv, svn);
+  }
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/alloc.h>
+#include <mLib/testrig.h>
+
+#define ALLOC(v, vl, sz) do {                                          \
+  size_t _sz = (sz);                                                   \
+  mpw *_vv = xmalloc(MPWS(_sz));                                       \
+  mpw *_vvl = _vv + _sz;                                               \
+  (v) = _vv;                                                           \
+  (vl) = _vvl;                                                         \
+} while (0)
+
+#define LOAD(v, vl, d) do {                                            \
+  const dstr *_d = (d);                                                        \
+  mpw *_v, *_vl;                                                       \
+  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
+  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
+  (v) = _v;                                                            \
+  (vl) = _vl;                                                          \
+} while (0)
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
+{
+  fputs(msg, stderr);
+  MPX_SHRINK(v, vl);
+  while (v < vl)
+    fprintf(stderr, " %08lx", (unsigned long)*--vl);
+  fputc('\n', stderr);
+}
+
+static int usqr(dstr *v)
+{
+  mpw *a, *al;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  mpw *s, *sl;
+  size_t m;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(c, cl, &v[1]);
+  m = al - a + 1;
+  ALLOC(d, dl, 3 * m);
+  ALLOC(s, sl, 5 * m);
+
+  mpx_ksqr(d, dl, a, al, s, sl);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** usqr failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(c); xfree(d); xfree(s);
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "usqr", usqr, { &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/mpx");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpx.c b/math/mpx.c
new file mode 100644 (file)
index 0000000..1294124
--- /dev/null
@@ -0,0 +1,1737 @@
+/* -*-c-*-
+ *
+ * Low-level multiprecision arithmetic
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "mptypes.h"
+#include "mpx.h"
+#include "bitops.h"
+
+/*----- Loading and storing -----------------------------------------------*/
+
+/* --- @mpx_storel@ --- *
+ *
+ * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
+ *             @void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores an MP in an octet array, least significant octet
+ *             first.  High-end octets are silently discarded if there
+ *             isn't enough space for them.
+ */
+
+void mpx_storel(const mpw *v, const mpw *vl, void *pp, size_t sz)
+{
+  mpw n, w = 0;
+  octet *p = pp, *q = p + sz;
+  unsigned bits = 0;
+
+  while (p < q) {
+    if (bits < 8) {
+      if (v >= vl) {
+       *p++ = U8(w);
+       break;
+      }
+      n = *v++;
+      *p++ = U8(w | n << bits);
+      w = n >> (8 - bits);
+      bits += MPW_BITS - 8;
+    } else {
+      *p++ = U8(w);
+      w >>= 8;
+      bits -= 8;
+    }
+  }
+  memset(p, 0, q - p);
+}
+
+/* --- @mpx_loadl@ --- *
+ *
+ * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
+ *             @const void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads an MP in an octet array, least significant octet
+ *             first.  High-end octets are ignored if there isn't enough
+ *             space for them.
+ */
+
+void mpx_loadl(mpw *v, mpw *vl, const void *pp, size_t sz)
+{
+  unsigned n;
+  mpw w = 0;
+  const octet *p = pp, *q = p + sz;
+  unsigned bits = 0;
+
+  if (v >= vl)
+    return;
+  while (p < q) {
+    n = U8(*p++);
+    w |= n << bits;
+    bits += 8;
+    if (bits >= MPW_BITS) {
+      *v++ = MPW(w);
+      w = n >> (MPW_BITS - bits + 8);
+      bits -= MPW_BITS;
+      if (v >= vl)
+       return;
+    }
+  }
+  *v++ = w;
+  MPX_ZERO(v, vl);
+}
+
+/* --- @mpx_storeb@ --- *
+ *
+ * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
+ *             @void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores an MP in an octet array, most significant octet
+ *             first.  High-end octets are silently discarded if there
+ *             isn't enough space for them.
+ */
+
+void mpx_storeb(const mpw *v, const mpw *vl, void *pp, size_t sz)
+{
+  mpw n, w = 0;
+  octet *p = pp, *q = p + sz;
+  unsigned bits = 0;
+
+  while (q > p) {
+    if (bits < 8) {
+      if (v >= vl) {
+       *--q = U8(w);
+       break;
+      }
+      n = *v++;
+      *--q = U8(w | n << bits);
+      w = n >> (8 - bits);
+      bits += MPW_BITS - 8;
+    } else {
+      *--q = U8(w);
+      w >>= 8;
+      bits -= 8;
+    }
+  }
+  memset(p, 0, q - p);
+}
+
+/* --- @mpx_loadb@ --- *
+ *
+ * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
+ *             @const void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads an MP in an octet array, most significant octet
+ *             first.  High-end octets are ignored if there isn't enough
+ *             space for them.
+ */
+
+void mpx_loadb(mpw *v, mpw *vl, const void *pp, size_t sz)
+{
+  unsigned n;
+  mpw w = 0;
+  const octet *p = pp, *q = p + sz;
+  unsigned bits = 0;
+
+  if (v >= vl)
+    return;
+  while (q > p) {
+    n = U8(*--q);
+    w |= n << bits;
+    bits += 8;
+    if (bits >= MPW_BITS) {
+      *v++ = MPW(w);
+      w = n >> (MPW_BITS - bits + 8);
+      bits -= MPW_BITS;
+      if (v >= vl)
+       return;
+    }
+  }
+  *v++ = w;
+  MPX_ZERO(v, vl);
+}
+
+/* --- @mpx_storel2cn@ --- *
+ *
+ * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
+ *             @void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a negative MP in an octet array, least significant
+ *             octet first, as two's complement.  High-end octets are
+ *             silently discarded if there isn't enough space for them.
+ *             This obviously makes the output bad.
+ */
+
+void mpx_storel2cn(const mpw *v, const mpw *vl, void *pp, size_t sz)
+{
+  unsigned c = 1;
+  unsigned b = 0;
+  mpw n, w = 0;
+  octet *p = pp, *q = p + sz;
+  unsigned bits = 0;
+
+  while (p < q) {
+    if (bits < 8) {
+      if (v >= vl) {
+       b = w;
+       break;
+      }
+      n = *v++;
+      b = w | n << bits;
+      w = n >> (8 - bits);
+      bits += MPW_BITS - 8;
+    } else {
+      b = w;
+      w >>= 8;
+      bits -= 8;
+    }
+    b = U8(~b + c);
+    c = c && !b;
+    *p++ = b;
+  }
+  while (p < q) {
+    b = U8(~b + c);
+    c = c && !b;
+    *p++ = b;
+    b = 0;
+  }
+}
+
+/* --- @mpx_loadl2cn@ --- *
+ *
+ * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
+ *             @const void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads a negative MP in an octet array, least significant
+ *             octet first, as two's complement.  High-end octets are
+ *             ignored if there isn't enough space for them.  This probably
+ *             means you made the wrong choice coming here.
+ */
+
+void mpx_loadl2cn(mpw *v, mpw *vl, const void *pp, size_t sz)
+{
+  unsigned n;
+  unsigned c = 1;
+  mpw w = 0;
+  const octet *p = pp, *q = p + sz;
+  unsigned bits = 0;
+
+  if (v >= vl)
+    return;
+  while (p < q) {
+    n = U8(~(*p++) + c);
+    c = c && !n;
+    w |= n << bits;
+    bits += 8;
+    if (bits >= MPW_BITS) {
+      *v++ = MPW(w);
+      w = n >> (MPW_BITS - bits + 8);
+      bits -= MPW_BITS;
+      if (v >= vl)
+       return;
+    }
+  }
+  *v++ = w;
+  MPX_ZERO(v, vl);
+}
+
+/* --- @mpx_storeb2cn@ --- *
+ *
+ * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
+ *             @void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a negative MP in an octet array, most significant
+ *             octet first, as two's complement.  High-end octets are
+ *             silently discarded if there isn't enough space for them,
+ *             which probably isn't what you meant.
+ */
+
+void mpx_storeb2cn(const mpw *v, const mpw *vl, void *pp, size_t sz)
+{
+  mpw n, w = 0;
+  unsigned b = 0;
+  unsigned c = 1;
+  octet *p = pp, *q = p + sz;
+  unsigned bits = 0;
+
+  while (q > p) {
+    if (bits < 8) {
+      if (v >= vl) {
+       b = w;
+       break;
+      }
+      n = *v++;
+      b = w | n << bits;
+      w = n >> (8 - bits);
+      bits += MPW_BITS - 8;
+    } else {
+      b = w;
+      w >>= 8;
+      bits -= 8;
+    }
+    b = U8(~b + c);
+    c = c && !b;
+    *--q = b;
+  }
+  while (q > p) {
+    b = ~b + c;
+    c = c && !(b & 0xff);
+    *--q = b;
+    b = 0;
+  }
+}
+
+/* --- @mpx_loadb2cn@ --- *
+ *
+ * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
+ *             @const void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads a negative MP in an octet array, most significant octet
+ *             first as two's complement.  High-end octets are ignored if
+ *             there isn't enough space for them.  This probably means you
+ *             chose this function wrongly.
+ */
+
+void mpx_loadb2cn(mpw *v, mpw *vl, const void *pp, size_t sz)
+{
+  unsigned n;
+  unsigned c = 1;
+  mpw w = 0;
+  const octet *p = pp, *q = p + sz;
+  unsigned bits = 0;
+
+  if (v >= vl)
+    return;
+  while (q > p) {
+    n = U8(~(*--q) + c);
+    c = c && !n;
+    w |= n << bits;
+    bits += 8;
+    if (bits >= MPW_BITS) {
+      *v++ = MPW(w);
+      w = n >> (MPW_BITS - bits + 8);
+      bits -= MPW_BITS;
+      if (v >= vl)
+       return;
+    }
+  }
+  *v++ = w;
+  MPX_ZERO(v, vl);
+}
+
+/*----- Logical shifting --------------------------------------------------*/
+
+/* --- @mpx_lsl@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = source vector base and limit
+ *             @size_t n@ = number of bit positions to shift by
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs a logical shift left operation on an integer.
+ */
+
+void mpx_lsl(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
+{
+  size_t nw;
+  unsigned nb;
+
+  /* --- Trivial special case --- */
+
+  if (n == 0)
+    MPX_COPY(dv, dvl, av, avl);
+
+  /* --- Single bit shifting --- */
+
+  else if (n == 1) {
+    mpw w = 0;
+    while (av < avl) {
+      mpw t;
+      if (dv >= dvl)
+       goto done;
+      t = *av++;
+      *dv++ = MPW((t << 1) | w);
+      w = t >> (MPW_BITS - 1);
+    }
+    if (dv >= dvl)
+      goto done;
+    *dv++ = MPW(w);
+    MPX_ZERO(dv, dvl);
+    goto done;
+  }
+
+  /* --- Break out word and bit shifts for more sophisticated work --- */
+
+  nw = n / MPW_BITS;
+  nb = n % MPW_BITS;
+
+  /* --- Handle a shift by a multiple of the word size --- */
+
+  if (nb == 0) {
+    if (nw >= dvl - dv)
+      MPX_ZERO(dv, dvl);
+    else {
+      MPX_COPY(dv + nw, dvl, av, avl);
+      memset(dv, 0, MPWS(nw));
+    }
+  }
+
+  /* --- And finally the difficult case --- *
+   *
+   * This is a little convoluted, because I have to start from the end and
+   * work backwards to avoid overwriting the source, if they're both the same
+   * block of memory.
+   */
+
+  else {
+    mpw w;
+    size_t nr = MPW_BITS - nb;
+    size_t dvn = dvl - dv;
+    size_t avn = avl - av;
+
+    if (dvn <= nw) {
+      MPX_ZERO(dv, dvl);
+      goto done;
+    }
+
+    if (dvn > avn + nw) {
+      size_t off = avn + nw + 1;
+      MPX_ZERO(dv + off, dvl);
+      dvl = dv + off;
+      w = 0;
+    } else {
+      avl = av + dvn - nw;
+      w = *--avl << nb;
+    }
+
+    while (avl > av) {
+      mpw t = *--avl;
+      *--dvl = MPW((t >> nr) | w);
+      w = t << nb;
+    }
+
+    *--dvl = MPW(w);
+    MPX_ZERO(dv, dvl);
+  }
+
+done:;
+}
+
+/* --- @mpx_lslc@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = source vector base and limit
+ *             @size_t n@ = number of bit positions to shift by
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs a logical shift left operation on an integer, only
+ *             it fills in the bits with ones instead of zeroes.
+ */
+
+void mpx_lslc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
+{
+  size_t nw;
+  unsigned nb;
+
+  /* --- Trivial special case --- */
+
+  if (n == 0)
+    MPX_COPY(dv, dvl, av, avl);
+
+  /* --- Single bit shifting --- */
+
+  else if (n == 1) {
+    mpw w = 1;
+    while (av < avl) {
+      mpw t;
+      if (dv >= dvl)
+       goto done;
+      t = *av++;
+      *dv++ = MPW((t << 1) | w);
+      w = t >> (MPW_BITS - 1);
+    }
+    if (dv >= dvl)
+      goto done;
+    *dv++ = MPW(w);
+    MPX_ZERO(dv, dvl);
+    goto done;
+  }
+
+  /* --- Break out word and bit shifts for more sophisticated work --- */
+
+  nw = n / MPW_BITS;
+  nb = n % MPW_BITS;
+
+  /* --- Handle a shift by a multiple of the word size --- */
+
+  if (nb == 0) {
+    if (nw >= dvl - dv)
+      MPX_ONE(dv, dvl);
+    else {
+      MPX_COPY(dv + nw, dvl, av, avl);
+      MPX_ONE(dv, dv + nw);
+    }
+  }
+
+  /* --- And finally the difficult case --- *
+   *
+   * This is a little convoluted, because I have to start from the end and
+   * work backwards to avoid overwriting the source, if they're both the same
+   * block of memory.
+   */
+
+  else {
+    mpw w;
+    size_t nr = MPW_BITS - nb;
+    size_t dvn = dvl - dv;
+    size_t avn = avl - av;
+
+    if (dvn <= nw) {
+      MPX_ONE(dv, dvl);
+      goto done;
+    }
+
+    if (dvn > avn + nw) {
+      size_t off = avn + nw + 1;
+      MPX_ZERO(dv + off, dvl);
+      dvl = dv + off;
+      w = 0;
+    } else {
+      avl = av + dvn - nw;
+      w = *--avl << nb;
+    }
+
+    while (avl > av) {
+      mpw t = *--avl;
+      *--dvl = MPW((t >> nr) | w);
+      w = t << nb;
+    }
+
+    *--dvl = MPW((MPW_MAX >> nr) | w);
+    MPX_ONE(dv, dvl);
+  }
+
+done:;
+}
+
+/* --- @mpx_lsr@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = source vector base and limit
+ *             @size_t n@ = number of bit positions to shift by
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs a logical shift right operation on an integer.
+ */
+
+void mpx_lsr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
+{
+  size_t nw;
+  unsigned nb;
+
+  /* --- Trivial special case --- */
+
+  if (n == 0)
+    MPX_COPY(dv, dvl, av, avl);
+
+  /* --- Single bit shifting --- */
+
+  else if (n == 1) {
+    mpw w = av < avl ? *av++ >> 1 : 0;
+    while (av < avl) {
+      mpw t;
+      if (dv >= dvl)
+       goto done;
+      t = *av++;
+      *dv++ = MPW((t << (MPW_BITS - 1)) | w);
+      w = t >> 1;
+    }
+    if (dv >= dvl)
+      goto done;
+    *dv++ = MPW(w);
+    MPX_ZERO(dv, dvl);
+    goto done;
+  }
+
+  /* --- Break out word and bit shifts for more sophisticated work --- */
+
+  nw = n / MPW_BITS;
+  nb = n % MPW_BITS;
+
+  /* --- Handle a shift by a multiple of the word size --- */
+
+  if (nb == 0) {
+    if (nw >= avl - av)
+      MPX_ZERO(dv, dvl);
+    else
+      MPX_COPY(dv, dvl, av + nw, avl);
+  }
+
+  /* --- And finally the difficult case --- */
+
+  else {
+    mpw w;
+    size_t nr = MPW_BITS - nb;
+
+    av += nw;
+    w = av < avl ? *av++ : 0;
+    while (av < avl) {
+      mpw t;
+      if (dv >= dvl)
+       goto done;
+      t = *av++;
+      *dv++ = MPW((w >> nb) | (t << nr));
+      w = t;
+    }
+    if (dv < dvl) {
+      *dv++ = MPW(w >> nb);
+      MPX_ZERO(dv, dvl);
+    }
+  }
+
+done:;
+}
+
+/*----- Bitwise operations ------------------------------------------------*/
+
+/* --- @mpx_bitop@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector
+ *             @const mpw *av, *avl@ = first source vector
+ *             @const mpw *bv, *bvl@ = second source vector
+ *
+ * Returns:    ---
+ *
+ * Use;                Provides the dyadic boolean functions.
+ */
+
+#define MPX_BITBINOP(string)                                           \
+                                                                       \
+void mpx_bit##string(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, \
+                    const mpw *bv, const mpw *bvl)                     \
+{                                                                      \
+  MPX_SHRINK(av, avl);                                                 \
+  MPX_SHRINK(bv, bvl);                                                 \
+                                                                       \
+  while (dv < dvl) {                                                   \
+    mpw a, b;                                                          \
+    a = (av < avl) ? *av++ : 0;                                                \
+    b = (bv < bvl) ? *bv++ : 0;                                                \
+    *dv++ = B##string(a, b);                                           \
+  }                                                                    \
+}
+
+MPX_DOBIN(MPX_BITBINOP)
+
+void mpx_not(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl)
+{
+  MPX_SHRINK(av, avl);
+
+  while (dv < dvl) {
+    mpw a;
+    a = (av < avl) ? *av++ : 0;
+    *dv++ = ~a;
+  }
+}
+
+/*----- Unsigned arithmetic -----------------------------------------------*/
+
+/* --- @mpx_2c@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector
+ *             @const mpw *v, *vl@ = source vector
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates the two's complement of @v@.
+ */
+
+void mpx_2c(mpw *dv, mpw *dvl, const mpw *v, const mpw *vl)
+{
+  mpw c = 0;
+  while (dv < dvl && v < vl)
+    *dv++ = c = MPW(~*v++);
+  if (dv < dvl) {
+    if (c > MPW_MAX / 2)
+      c = MPW(~0);
+    while (dv < dvl)
+      *dv++ = c;
+  }
+  MPX_UADDN(dv, dvl, 1);
+}
+
+/* --- @mpx_ueq@ --- *
+ *
+ * Arguments:  @const mpw *av, *avl@ = first argument vector base and limit
+ *             @const mpw *bv, *bvl@ = second argument vector base and limit
+ *
+ * Returns:    Nonzero if the two vectors are equal.
+ *
+ * Use:                Performs an unsigned integer test for equality.
+ */
+
+int mpx_ueq(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl)
+{
+  MPX_SHRINK(av, avl);
+  MPX_SHRINK(bv, bvl);
+  if (avl - av != bvl - bv)
+    return (0);
+  while (av < avl) {
+    if (*av++ != *bv++)
+      return (0);
+  }
+  return (1);
+}
+
+/* --- @mpx_ucmp@ --- *
+ *
+ * Arguments:  @const mpw *av, *avl@ = first argument vector base and limit
+ *             @const mpw *bv, *bvl@ = second argument vector base and limit
+ *
+ * Returns:    Less than, equal to, or greater than zero depending on
+ *             whether @a@ is less than, equal to or greater than @b@,
+ *             respectively.
+ *
+ * Use:                Performs an unsigned integer comparison.
+ */
+
+int mpx_ucmp(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl)
+{
+  MPX_SHRINK(av, avl);
+  MPX_SHRINK(bv, bvl);
+
+  if (avl - av > bvl - bv)
+    return (+1);
+  else if (avl - av < bvl - bv)
+    return (-1);
+  else while (avl > av) {
+    mpw a = *--avl, b = *--bvl;
+    if (a > b)
+      return (+1);
+    else if (a < b)
+      return (-1);
+  }
+  return (0);
+}
+
+/* --- @mpx_uadd@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = first addend vector base and limit
+ *             @const mpw *bv, *bvl@ = second addend vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer addition.  If the result overflows
+ *             the destination vector, high-order bits are discarded.  This
+ *             means that two's complement addition happens more or less for
+ *             free, although that's more a side-effect than anything else.
+ *             The result vector may be equal to either or both source
+ *             vectors, but may not otherwise overlap them.
+ */
+
+void mpx_uadd(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,
+             const mpw *bv, const mpw *bvl)
+{
+  mpw c = 0;
+
+  while (av < avl || bv < bvl) {
+    mpw a, b;
+    mpd x;
+    if (dv >= dvl)
+      return;
+    a = (av < avl) ? *av++ : 0;
+    b = (bv < bvl) ? *bv++ : 0;
+    x = (mpd)a + (mpd)b + c;
+    *dv++ = MPW(x);
+    c = x >> MPW_BITS;
+  }
+  if (dv < dvl) {
+    *dv++ = c;
+    MPX_ZERO(dv, dvl);
+  }
+}
+
+/* --- @mpx_uaddn@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = source and destination base and limit
+ *             @mpw n@ = other addend
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds a small integer to a multiprecision number.
+ */
+
+void mpx_uaddn(mpw *dv, mpw *dvl, mpw n) { MPX_UADDN(dv, dvl, n); }
+
+/* --- @mpx_uaddnlsl@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination and first argument vector
+ *             @mpw a@ = second argument
+ *             @unsigned o@ = offset in bits
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d + 2^o a$%.  If the result overflows then
+ *             high-order bits are discarded, as usual.  We must have
+ *             @0 < o < MPW_BITS@.
+ */
+
+void mpx_uaddnlsl(mpw *dv, mpw *dvl, mpw a, unsigned o)
+{
+  mpd x = (mpd)a << o;
+
+  while (x && dv < dvl) {
+    x += *dv;
+    *dv++ = MPW(x);
+    x >>= MPW_BITS;
+  }
+}
+
+/* --- @mpx_usub@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = first argument vector base and limit
+ *             @const mpw *bv, *bvl@ = second argument vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer subtraction.  If the result
+ *             overflows the destination vector, high-order bits are
+ *             discarded.  This means that two's complement subtraction
+ *             happens more or less for free, althuogh that's more a side-
+ *             effect than anything else.  The result vector may be equal to
+ *             either or both source vectors, but may not otherwise overlap
+ *             them.
+ */
+
+void mpx_usub(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,
+             const mpw *bv, const mpw *bvl)
+{
+  mpw c = 0;
+
+  while (av < avl || bv < bvl) {
+    mpw a, b;
+    mpd x;
+    if (dv >= dvl)
+      return;
+    a = (av < avl) ? *av++ : 0;
+    b = (bv < bvl) ? *bv++ : 0;
+    x = (mpd)a - (mpd)b - c;
+    *dv++ = MPW(x);
+    if (x >> MPW_BITS)
+      c = 1;
+    else
+      c = 0;
+  }
+  if (c)
+    c = MPW_MAX;
+  while (dv < dvl)
+    *dv++ = c;
+}
+
+/* --- @mpx_usubn@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = source and destination base and limit
+ *             @n@ = subtrahend
+ *
+ * Returns:    ---
+ *
+ * Use:                Subtracts a small integer from a multiprecision number.
+ */
+
+void mpx_usubn(mpw *dv, mpw *dvl, mpw n) { MPX_USUBN(dv, dvl, n); }
+
+/* --- @mpx_uaddnlsl@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination and first argument vector
+ *             @mpw a@ = second argument
+ *             @unsigned o@ = offset in bits
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d + 2^o a$%.  If the result overflows then
+ *             high-order bits are discarded, as usual.  We must have
+ *             @0 < o < MPW_BITS@.
+ */
+
+void mpx_usubnlsl(mpw *dv, mpw *dvl, mpw a, unsigned o)
+{
+  mpw b = a >> (MPW_BITS - o);
+  a <<= o;
+
+  if (dv < dvl) {
+    mpd x = (mpd)*dv - MPW(a);
+    *dv++ = MPW(x);
+    if (x >> MPW_BITS)
+      b++;
+    MPX_USUBN(dv, dvl, b);
+  }
+}
+
+/* --- @mpx_umul@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = multiplicand vector base and limit
+ *             @const mpw *bv, *bvl@ = multiplier vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer multiplication.  If the result
+ *             overflows the desination vector, high-order bits are
+ *             discarded.  The result vector may not overlap the argument
+ *             vectors in any way.
+ */
+
+void mpx_umul(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,
+             const mpw *bv, const mpw *bvl)
+{
+  /* --- This is probably worthwhile on a multiply --- */
+
+  MPX_SHRINK(av, avl);
+  MPX_SHRINK(bv, bvl);
+
+  /* --- Deal with a multiply by zero --- */
+
+  if (bv == bvl) {
+    MPX_ZERO(dv, dvl);
+    return;
+  }
+
+  /* --- Do the initial multiply and initialize the accumulator --- */
+
+  MPX_UMULN(dv, dvl, av, avl, *bv++);
+
+  /* --- Do the remaining multiply/accumulates --- */
+
+  while (dv < dvl && bv < bvl) {
+    mpw m = *bv++;
+    mpw c = 0;
+    const mpw *avv = av;
+    mpw *dvv = ++dv;
+
+    while (avv < avl) {
+      mpd x;
+      if (dvv >= dvl)
+       goto next;
+      x = (mpd)*dvv + (mpd)m * (mpd)*avv++ + c;
+      *dvv++ = MPW(x);
+      c = x >> MPW_BITS;
+    }
+    MPX_UADDN(dvv, dvl, c);
+  next:;
+  }
+}
+
+/* --- @mpx_umuln@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = multiplicand vector base and limit
+ *             @mpw m@ = multiplier
+ *
+ * Returns:    ---
+ *
+ * Use:                Multiplies a multiprecision integer by a single-word value.
+ *             The destination and source may be equal.  The destination
+ *             is completely cleared after use.
+ */
+
+void mpx_umuln(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m)
+  { MPX_UMULN(dv, dvl, av, avl, m); }
+
+/* --- @mpx_umlan@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination/accumulator base and limit
+ *             @const mpw *av, *avl@ = multiplicand vector base and limit
+ *             @mpw m@ = multiplier
+ *
+ * Returns:    ---
+ *
+ * Use:                Multiplies a multiprecision integer by a single-word value
+ *             and adds the result to an accumulator.
+ */
+
+void mpx_umlan(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m)
+  { MPX_UMLAN(dv, dvl, av, avl, m); }
+
+/* --- @mpx_usqr@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *av@ = source vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer squaring.  The result vector must
+ *             not overlap the source vector in any way.
+ */
+
+void mpx_usqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl)
+{
+  MPX_ZERO(dv, dvl);
+
+  /* --- Main loop --- */
+
+  while (av < avl) {
+    const mpw *avv = av;
+    mpw *dvv = dv;
+    mpw a = *av;
+    mpd c;
+
+    /* --- Stop if I've run out of destination --- */
+
+    if (dvv >= dvl)
+      break;
+
+    /* --- Work out the square at this point in the proceedings --- */
+
+    {
+      mpd x = (mpd)a * (mpd)a + *dvv;
+      *dvv++ = MPW(x);
+      c = MPW(x >> MPW_BITS);
+    }
+
+    /* --- Now fix up the rest of the vector upwards --- */
+
+    avv++;
+    while (dvv < dvl && avv < avl) {
+      mpd x = (mpd)a * (mpd)*avv++;
+      mpd y = ((x << 1) & MPW_MAX) + c + *dvv;
+      c = (x >> (MPW_BITS - 1)) + (y >> MPW_BITS);
+      *dvv++ = MPW(y);
+    }
+    while (dvv < dvl && c) {
+      mpd x = c + *dvv;
+      *dvv++ = MPW(x);
+      c = x >> MPW_BITS;
+    }
+
+    /* --- Get ready for the next round --- */
+
+    av++;
+    dv += 2;
+  }
+}
+
+/* --- @mpx_udiv@ --- *
+ *
+ * Arguments:  @mpw *qv, *qvl@ = quotient vector base and limit
+ *             @mpw *rv, *rvl@ = dividend/remainder vector base and limit
+ *             @const mpw *dv, *dvl@ = divisor vector base and limit
+ *             @mpw *sv, *svl@ = scratch workspace
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer division.  If the result overflows
+ *             the quotient vector, high-order bits are discarded.  (Clearly
+ *             the remainder vector can't overflow.)  The various vectors
+ *             may not overlap in any way.  Yes, I know it's a bit odd
+ *             requiring the dividend to be in the result position but it
+ *             does make some sense really.  The remainder must have
+ *             headroom for at least two extra words.  The scratch space
+ *             must be at least one word larger than the divisor.
+ */
+
+void mpx_udiv(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl,
+             const mpw *dv, const mpw *dvl,
+             mpw *sv, mpw *svl)
+{
+  unsigned norm = 0;
+  size_t scale;
+  mpw d, dd;
+
+  /* --- Initialize the quotient --- */
+
+  MPX_ZERO(qv, qvl);
+
+  /* --- Perform some sanity checks --- */
+
+  MPX_SHRINK(dv, dvl);
+  assert(((void)"division by zero in mpx_udiv", dv < dvl));
+
+  /* --- Normalize the divisor --- *
+   *
+   * The algorithm requires that the divisor be at least two digits long.
+   * This is easy to fix.
+   */
+
+  {
+    unsigned b;
+
+    d = dvl[-1];
+    for (b = MPW_P2; b; b >>= 1) {
+      if (d <= (MPW_MAX >> b)) {
+       d <<= b;
+       norm += b;
+      }
+    }
+    if (dv + 1 == dvl)
+      norm += MPW_BITS;
+  }
+
+  /* --- Normalize the dividend/remainder to match --- */
+
+  if (norm) {
+    mpx_lsl(rv, rvl, rv, rvl, norm);
+    mpx_lsl(sv, svl, dv, dvl, norm);
+    dv = sv;
+    dvl = svl;
+    MPX_SHRINK(dv, dvl);
+  }
+
+  MPX_SHRINK(rv, rvl);
+  d = dvl[-1];
+  dd = dvl[-2];
+
+  /* --- Work out the relative scales --- */
+
+  {
+    size_t rvn = rvl - rv;
+    size_t dvn = dvl - dv;
+
+    /* --- If the divisor is clearly larger, notice this --- */
+
+    if (dvn > rvn) {
+      mpx_lsr(rv, rvl, rv, rvl, norm);
+      return;
+    }
+
+    scale = rvn - dvn;
+  }
+
+  /* --- Calculate the most significant quotient digit --- *
+   *
+   * Because the divisor has its top bit set, this can only happen once.  The
+   * pointer arithmetic is a little contorted, to make sure that the
+   * behaviour is defined.
+   */
+
+  if (MPX_UCMP(rv + scale, rvl, >=, dv, dvl)) {
+    mpx_usub(rv + scale, rvl, rv + scale, rvl, dv, dvl);
+    if (qvl - qv > scale)
+      qv[scale] = 1;
+  }
+
+  /* --- Now for the main loop --- */
+
+  {
+    mpw *rvv = rvl - 2;
+
+    while (scale) {
+      mpw q;
+      mpd rh;
+
+      /* --- Get an estimate for the next quotient digit --- */
+
+      mpw r = rvv[1];
+      mpw rr = rvv[0];
+      mpw rrr = *--rvv;
+
+      scale--;
+      rh = ((mpd)r << MPW_BITS) | rr;
+      if (r == d)
+       q = MPW_MAX;
+      else
+       q = MPW(rh / d);
+
+      /* --- Refine the estimate --- */
+
+      {
+       mpd yh = (mpd)d * q;
+       mpd yy = (mpd)dd * q;
+       mpw yl;
+
+       if (yy > MPW_MAX)
+         yh += yy >> MPW_BITS;
+       yl = MPW(yy);
+
+       while (yh > rh || (yh == rh && yl > rrr)) {
+         q--;
+         yh -= d;
+         if (yl < dd)
+           yh--;
+         yl = MPW(yl - dd);
+       }
+      }
+
+      /* --- Remove a chunk from the dividend --- */
+
+      {
+       mpw *svv;
+       const mpw *dvv;
+       mpw mc = 0, sc = 0;
+
+       /* --- Calculate the size of the chunk --- *
+        *
+        * This does the whole job of calculating @r >> scale - qd@.
+        */
+
+       for (svv = rv + scale, dvv = dv;
+            dvv < dvl && svv < rvl;
+            svv++, dvv++) {
+         mpd x = (mpd)*dvv * (mpd)q + mc;
+         mc = x >> MPW_BITS;
+         x = (mpd)*svv - MPW(x) - sc;
+         *svv = MPW(x);
+         if (x >> MPW_BITS)
+           sc = 1;
+         else
+           sc = 0;
+       }
+
+       if (svv < rvl) {
+         mpd x = (mpd)*svv - mc - sc;
+         *svv++ = MPW(x);
+         if (x >> MPW_BITS)
+           sc = MPW_MAX;
+         else
+           sc = 0;
+         while (svv < rvl)
+           *svv++ = sc;
+       }
+
+       /* --- Fix if the quotient was too large --- *
+        *
+        * This doesn't seem to happen very often.
+        */
+
+       if (rvl[-1] > MPW_MAX / 2) {
+         mpx_uadd(rv + scale, rvl, rv + scale, rvl, dv, dvl);
+         q--;
+       }
+      }
+
+      /* --- Done for another iteration --- */
+
+      if (qvl - qv > scale)
+       qv[scale] = q;
+      r = rr;
+      rr = rrr;
+    }
+  }
+
+  /* --- Now fiddle with unnormalizing and things --- */
+
+  mpx_lsr(rv, rvl, rv, rvl, norm);
+}
+
+/* --- @mpx_udivn@ --- *
+ *
+ * Arguments:  @mpw *qv, *qvl@ = storage for the quotient (may overlap
+ *                     dividend)
+ *             @const mpw *rv, *rvl@ = dividend
+ *             @mpw d@ = single-precision divisor
+ *
+ * Returns:    Remainder after divison.
+ *
+ * Use:                Performs a single-precision division operation.
+ */
+
+mpw mpx_udivn(mpw *qv, mpw *qvl, const mpw *rv, const mpw *rvl, mpw d)
+{
+  size_t i;
+  size_t ql = qvl - qv;
+  mpd r = 0;
+
+  i = rvl - rv;
+  while (i > 0) {
+    i--;
+    r = (r << MPW_BITS) | rv[i];
+    if (i < ql)
+      qv[i] = r / d;
+    r %= d;
+  }
+  return (MPW(r));
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#include "mpscan.h"
+
+#define ALLOC(v, vl, sz) do {                                          \
+  size_t _sz = (sz);                                                   \
+  mpw *_vv = xmalloc(MPWS(_sz));                                       \
+  mpw *_vvl = _vv + _sz;                                               \
+  (v) = _vv;                                                           \
+  (vl) = _vvl;                                                         \
+} while (0)
+
+#define LOAD(v, vl, d) do {                                            \
+  const dstr *_d = (d);                                                        \
+  mpw *_v, *_vl;                                                       \
+  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
+  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
+  (v) = _v;                                                            \
+  (vl) = _vl;                                                          \
+} while (0)
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+static void dumpbits(const char *msg, const void *pp, size_t sz)
+{
+  const octet *p = pp;
+  fputs(msg, stderr);
+  for (; sz; sz--)
+    fprintf(stderr, " %02x", *p++);
+  fputc('\n', stderr);
+}
+
+static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
+{
+  fputs(msg, stderr);
+  MPX_SHRINK(v, vl);
+  while (v < vl)
+    fprintf(stderr, " %08lx", (unsigned long)*--vl);
+  fputc('\n', stderr);
+}
+
+static int chkscan(const mpw *v, const mpw *vl,
+                  const void *pp, size_t sz, int step)
+{
+  mpscan mps;
+  const octet *p = pp;
+  unsigned bit = 0;
+  int ok = 1;
+
+  mpscan_initx(&mps, v, vl);
+  while (sz) {
+    unsigned x = *p;
+    int i;
+    p += step;
+    for (i = 0; i < 8 && MPSCAN_STEP(&mps); i++) {
+      if (MPSCAN_BIT(&mps) != (x & 1)) {
+       fprintf(stderr,
+               "\n*** error, step %i, bit %u, expected %u, found %u\n",
+               step, bit, x & 1, MPSCAN_BIT(&mps));
+       ok = 0;
+      }
+      x >>= 1;
+      bit++;
+    }
+    sz--;
+  }
+
+  return (ok);
+}
+
+static int loadstore(dstr *v)
+{
+  dstr d = DSTR_INIT;
+  size_t sz = MPW_RQ(v->len) * 2, diff;
+  mpw *m, *ml;
+  int ok = 1;
+
+  dstr_ensure(&d, v->len);
+  m = xmalloc(MPWS(sz));
+
+  for (diff = 0; diff < sz; diff += 5) {
+    size_t oct;
+
+    ml = m + sz - diff;
+
+    mpx_loadl(m, ml, v->buf, v->len);
+    if (!chkscan(m, ml, v->buf, v->len, +1))
+      ok = 0;
+    MPX_OCTETS(oct, m, ml);
+    mpx_storel(m, ml, d.buf, d.sz);
+    if (memcmp(d.buf, v->buf, oct) != 0) {
+      dumpbits("\n*** storel failed", d.buf, d.sz);
+      ok = 0;
+    }
+
+    mpx_loadb(m, ml, v->buf, v->len);
+    if (!chkscan(m, ml, v->buf + v->len - 1, v->len, -1))
+      ok = 0;
+    MPX_OCTETS(oct, m, ml);
+    mpx_storeb(m, ml, d.buf, d.sz);
+    if (memcmp(d.buf + d.sz - oct, v->buf + v->len - oct, oct) != 0) {
+      dumpbits("\n*** storeb failed", d.buf, d.sz);
+      ok = 0;
+    }
+  }
+
+  if (!ok)
+    dumpbits("input data", v->buf, v->len);
+
+  xfree(m);
+  dstr_destroy(&d);
+  return (ok);
+}
+
+static int twocl(dstr *v)
+{
+  dstr d = DSTR_INIT;
+  mpw *m, *ml;
+  size_t sz;
+  int ok = 1;
+
+  sz = v[0].len; if (v[1].len > sz) sz = v[1].len;
+  dstr_ensure(&d, sz);
+
+  sz = MPW_RQ(sz);
+  m = xmalloc(MPWS(sz));
+  ml = m + sz;
+
+  mpx_loadl(m, ml, v[0].buf, v[0].len);
+  mpx_storel2cn(m, ml, d.buf, v[1].len);
+  if (memcmp(d.buf, v[1].buf, v[1].len)) {
+    dumpbits("\n*** storel2cn failed", d.buf, v[1].len);
+    ok = 0;
+  }
+
+  mpx_loadl2cn(m, ml, v[1].buf, v[1].len);
+  mpx_storel(m, ml, d.buf, v[0].len);
+  if (memcmp(d.buf, v[0].buf, v[0].len)) {
+    dumpbits("\n*** loadl2cn failed", d.buf, v[0].len);
+    ok = 0;
+  }
+
+  if (!ok) {
+    dumpbits("pos", v[0].buf, v[0].len);
+    dumpbits("neg", v[1].buf, v[1].len);
+  }
+
+  xfree(m);
+  dstr_destroy(&d);
+
+  return (ok);
+}
+
+static int twocb(dstr *v)
+{
+  dstr d = DSTR_INIT;
+  mpw *m, *ml;
+  size_t sz;
+  int ok = 1;
+
+  sz = v[0].len; if (v[1].len > sz) sz = v[1].len;
+  dstr_ensure(&d, sz);
+
+  sz = MPW_RQ(sz);
+  m = xmalloc(MPWS(sz));
+  ml = m + sz;
+
+  mpx_loadb(m, ml, v[0].buf, v[0].len);
+  mpx_storeb2cn(m, ml, d.buf, v[1].len);
+  if (memcmp(d.buf, v[1].buf, v[1].len)) {
+    dumpbits("\n*** storeb2cn failed", d.buf, v[1].len);
+    ok = 0;
+  }
+
+  mpx_loadb2cn(m, ml, v[1].buf, v[1].len);
+  mpx_storeb(m, ml, d.buf, v[0].len);
+  if (memcmp(d.buf, v[0].buf, v[0].len)) {
+    dumpbits("\n*** loadb2cn failed", d.buf, v[0].len);
+    ok = 0;
+  }
+
+  if (!ok) {
+    dumpbits("pos", v[0].buf, v[0].len);
+    dumpbits("neg", v[1].buf, v[1].len);
+  }
+
+  xfree(m);
+  dstr_destroy(&d);
+
+  return (ok);
+}
+
+static int lsl(dstr *v)
+{
+  mpw *a, *al;
+  int n = *(int *)v[1].buf;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(c, cl, &v[2]);
+  ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS);
+
+  mpx_lsl(d, dl, a, al, n);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** lsl(%i) failed\n", n);
+    dumpmp("      a", a, al);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int lslc(dstr *v)
+{
+  mpw *a, *al;
+  int n = *(int *)v[1].buf;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(c, cl, &v[2]);
+  ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS);
+
+  mpx_lslc(d, dl, a, al, n);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** lslc(%i) failed\n", n);
+    dumpmp("      a", a, al);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int lsr(dstr *v)
+{
+  mpw *a, *al;
+  int n = *(int *)v[1].buf;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(c, cl, &v[2]);
+  ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS + 1);
+
+  mpx_lsr(d, dl, a, al, n);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** lsr(%i) failed\n", n);
+    dumpmp("      a", a, al);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int uadd(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(b, bl, &v[1]);
+  LOAD(c, cl, &v[2]);
+  ALLOC(d, dl, MAX(al - a, bl - b) + 1);
+
+  mpx_uadd(d, dl, a, al, b, bl);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** uadd failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("      b", b, bl);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int usub(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(b, bl, &v[1]);
+  LOAD(c, cl, &v[2]);
+  ALLOC(d, dl, al - a);
+
+  mpx_usub(d, dl, a, al, b, bl);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** usub failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("      b", b, bl);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int umul(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(b, bl, &v[1]);
+  LOAD(c, cl, &v[2]);
+  ALLOC(d, dl, (al - a) + (bl - b));
+
+  mpx_umul(d, dl, a, al, b, bl);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** umul failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("      b", b, bl);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int usqr(dstr *v)
+{
+  mpw *a, *al;
+  mpw *c, *cl;
+  mpw *d, *dl;
+  int ok = 1;
+
+  LOAD(a, al, &v[0]);
+  LOAD(c, cl, &v[1]);
+  ALLOC(d, dl, 2 * (al - a));
+
+  mpx_usqr(d, dl, a, al);
+  if (!mpx_ueq(d, dl, c, cl)) {
+    fprintf(stderr, "\n*** usqr failed\n");
+    dumpmp("      a", a, al);
+    dumpmp("expected", c, cl);
+    dumpmp("  result", d, dl);
+    ok = 0;
+  }
+
+  xfree(a); xfree(c); xfree(d);
+  return (ok);
+}
+
+static int udiv(dstr *v)
+{
+  mpw *a, *al;
+  mpw *b, *bl;
+  mpw *q, *ql;
+  mpw *r, *rl;
+  mpw *qq, *qql;
+  mpw *s, *sl;
+  int ok = 1;
+
+  ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len);
+  LOAD(b, bl, &v[1]);
+  LOAD(q, ql, &v[2]);
+  LOAD(r, rl, &v[3]);
+  ALLOC(qq, qql, al - a);
+  ALLOC(s, sl, (bl - b) + 1);
+
+  mpx_udiv(qq, qql, a, al, b, bl, s, sl);
+  if (!mpx_ueq(qq, qql, q, ql) ||
+      !mpx_ueq(a, al, r, rl)) {
+    fprintf(stderr, "\n*** udiv failed\n");
+    dumpmp(" divisor", b, bl);
+    dumpmp("expect r", r, rl);
+    dumpmp("result r", a, al);
+    dumpmp("expect q", q, ql);
+    dumpmp("result q", qq, qql);
+    ok = 0;
+  }
+
+  xfree(a); xfree(b); xfree(r); xfree(q); xfree(s); xfree(qq);
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "load-store", loadstore, { &type_hex, 0 } },
+  { "2cl", twocl, { &type_hex, &type_hex, } },
+  { "2cb", twocb, { &type_hex, &type_hex, } },
+  { "lsl", lsl, { &type_hex, &type_int, &type_hex, 0 } },
+  { "lslc", lslc, { &type_hex, &type_int, &type_hex, 0 } },
+  { "lsr", lsr, { &type_hex, &type_int, &type_hex, 0 } },
+  { "uadd", uadd, { &type_hex, &type_hex, &type_hex, 0 } },
+  { "usub", usub, { &type_hex, &type_hex, &type_hex, 0 } },
+  { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } },
+  { "usqr", usqr, { &type_hex, &type_hex, 0 } },
+  { "udiv", udiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/mpx");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/mpx.h b/math/mpx.h
new file mode 100644 (file)
index 0000000..4d6288e
--- /dev/null
@@ -0,0 +1,789 @@
+/* -*-c-*-
+ *
+ * Low level multiprecision arithmetic
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_MPX_H
+#define CATACOMB_MPX_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- The idea ----------------------------------------------------------*
+ *
+ * This file provides functions and macros which work on vectors of words as
+ * unsigned multiprecision integers.  The interface works in terms of base
+ * and limit pointers (i.e., a pointer to the start of a vector, and a
+ * pointer just past its end) rather than base pointer and length, because
+ * that requires more arithmetic and state to work on.
+ *
+ * The interfaces are slightly bizarre in other ways.  Try to use the
+ * higher-level functions where you can: they're rather better designed to
+ * actually be friendly and useful.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#ifndef CATACOMB_MPW_H
+#  include "mpw.h"
+#endif
+
+/*----- General manipulation ----------------------------------------------*/
+
+/* --- @MPX_SHRINK@ --- *
+ *
+ * Arguments:  @const mpw *v@ = pointer to vector of words
+ *             @const mpw *vl@ = (updated) current limit of vector
+ *
+ * Use:                Shrinks down the limit of a multiprecision integer vector.
+ */
+
+#define MPX_SHRINK(v, vl) do {                                         \
+  const mpw *_vv = (v), *_vvl = (vl);                                  \
+  while (_vvl > _vv && !_vvl[-1])                                      \
+    _vvl--;                                                            \
+  (vl) = (mpw *)_vvl;                                                  \
+} while (0)
+
+/* --- @MPX_BITS@ --- *
+ *
+ * Arguments:  @unsigned long b@ = result variable
+ *             @const mpw *v@ = pointer to array of words
+ *             @const mpw *vl@ = limit of vector (from @MPX_SHRINK@)
+ *
+ * Use:                Calculates the number of bits in a multiprecision value.
+ */
+
+#define MPX_BITS(b, v, vl) do {                                                \
+  const mpw *_v = (v), *_vl = (vl);                                    \
+  MPX_SHRINK(_v, _vl);                                                 \
+  if (_v == _vl)                                                       \
+    (b) = 0;                                                           \
+  else {                                                               \
+    unsigned long _b = MPW_BITS * (_vl - _v - 1) + 1;                  \
+    mpw _w = _vl[-1];                                                  \
+    unsigned _k = MPW_P2;                                              \
+    while (_k) {                                                       \
+      if (_w >> _k) {                                                  \
+       _w >>= _k;                                                      \
+       _b += _k;                                                       \
+      }                                                                        \
+      _k >>= 1;                                                                \
+    }                                                                  \
+    (b) = _b;                                                          \
+  }                                                                    \
+} while (0)
+
+/* --- @MPX_OCTETS@ --- *
+ *
+ * Arguments:  @size_t o@ = result variable
+ *             @const mpw *v, *vl@ = pointer to array of words
+ *
+ * Use:                Calculates the number of octets in a multiprecision value.
+ */
+
+#define MPX_OCTETS(o, v, vl) do {                                      \
+  unsigned long _bb;                                                   \
+  MPX_BITS(_bb, (v), (vl));                                            \
+  (o) = (_bb + 7) >> 3;                                                        \
+} while (0)
+
+/* --- @MPX_OCTETS2C@ --- *
+ *
+ * Arguments:  @size_t o@ = result variable
+ *             @const mpw *v, *vl@ = pointer to array of words
+ *
+ * Use:                Calculates the number of octets in a multiprecision value, if
+ *             you represent it as two's complement.
+ */
+
+#define MPX_OCTETS2C(o, v, vl) do {                                    \
+  unsigned long _bb;                                                   \
+  MPX_BITS(_bb, (v), (vl));                                            \
+  (o) = (_bb >> 3) + 1;                                                        \
+} while (0)
+
+/* --- @MPX_COPY@ --- *
+ *
+ * Arguments:  @dv, dvl@ = destination vector base and limit
+ *             @av, avl@ = source vector base and limit
+ *
+ * Use:                Copies a multiprecision integer.
+ */
+
+#define MPX_COPY(dv, dvl, av, avl) do {                                        \
+  mpw *_dv = (dv), *_dvl = (dvl);                                      \
+  size_t _dn = _dvl - _dv;                                             \
+  const mpw *_av = (av), *_avl = (avl);                                        \
+  size_t _an = _avl - _av;                                             \
+  if (_av == _dv) {                                                    \
+    if (_dvl > _avl)                                                   \
+      memset(_dv, 0, MPWS(_dn - _an));                                 \
+  } else if (_an >= _dn)                                               \
+    memmove(_dv, _av, MPWS(_dn));                                      \
+  else {                                                               \
+    memmove(_dv, _av, MPWS(_an));                                      \
+    memset(_dv + _an, 0, MPWS(_dn - _an));                             \
+  }                                                                    \
+} while (0)
+
+/* --- @MPX_ZERO@ --- *
+ *
+ * Arguments:  @v, vl@ = base and limit of vector to clear
+ *
+ * Use:                Zeroes the area between the two vector pointers.
+ */
+
+#define MPX_ZERO(v, vl) do {                                           \
+  mpw *_v = (v), *_vl = (vl);                                          \
+  if (_v < _vl)                                                                \
+    memset(_v, 0, MPWS(_vl - _v));                                     \
+} while (0)
+
+/* --- @MPX_ONE@ --- *
+ *
+ * Arguments:  @v, vl@ = base and limit of vector to clear
+ *
+ * Use:                Fills the area between the two vector pointers with ones.
+ */
+
+#define MPX_ONE(v, vl) do {                                            \
+  mpw * _v = (v);                                                      \
+  const mpw *_vl = (vl);                                               \
+  while (_v < _vl)                                                     \
+    *_v++ = MPW_MAX;                                                   \
+} while (0)
+
+/*----- Loading and storing -----------------------------------------------*/
+
+/* --- @mpx_storel@ --- *
+ *
+ * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
+ *             @void *p@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores an MP in an octet array, least significant octet
+ *             first.  High-end octets are silently discarded if there
+ *             isn't enough space for them.
+ */
+
+extern void mpx_storel(const mpw */*v*/, const mpw */*vl*/,
+                      void */*p*/, size_t /*sz*/);
+
+/* --- @mpx_loadl@ --- *
+ *
+ * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
+ *             @const void *p@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads an MP in an octet array, least significant octet
+ *             first.  High-end octets are ignored if there isn't enough
+ *             space for them.
+ */
+
+extern void mpx_loadl(mpw */*v*/, mpw */*vl*/,
+                     const void */*p*/, size_t /*sz*/);
+
+/* --- @mpx_storeb@ --- *
+ *
+ * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
+ *             @void *p@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores an MP in an octet array, most significant octet
+ *             first.  High-end octets are silently discarded if there
+ *             isn't enough space for them.
+ */
+
+extern void mpx_storeb(const mpw */*v*/, const mpw */*vl*/,
+                      void */*p*/, size_t /*sz*/);
+
+/* --- @mpx_loadb@ --- *
+ *
+ * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
+ *             @const void *p@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads an MP in an octet array, most significant octet
+ *             first.  High-end octets are ignored if there isn't enough
+ *             space for them.
+ */
+
+extern void mpx_loadb(mpw */*v*/, mpw */*vl*/,
+                     const void */*p*/, size_t /*sz*/);
+
+/* --- @mpx_storel2cn@ --- *
+ *
+ * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
+ *             @void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a negative MP in an octet array, least significant
+ *             octet first, as two's complement.  High-end octets are
+ *             silently discarded if there isn't enough space for them.
+ *             This obviously makes the output bad.
+ */
+
+extern void mpx_storel2cn(const mpw */*v*/, const mpw */*vl*/,
+                         void */*p*/, size_t /*sz*/);
+
+/* --- @mpx_loadl2cn@ --- *
+ *
+ * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
+ *             @const void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads a negative MP in an octet array, least significant
+ *             octet first, as two's complement.  High-end octets are
+ *             ignored if there isn't enough space for them.  This probably
+ *             means you made the wrong choice coming here.
+ */
+
+extern void mpx_loadl2cn(mpw */*v*/, mpw */*vl*/,
+                        const void */*p*/, size_t /*sz*/);
+
+/* --- @mpx_storeb2cn@ --- *
+ *
+ * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
+ *             @void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a negative MP in an octet array, most significant
+ *             octet first, as two's complement.  High-end octets are
+ *             silently discarded if there isn't enough space for them,
+ *             which probably isn't what you meant.
+ */
+
+extern void mpx_storeb2cn(const mpw */*v*/, const mpw */*vl*/,
+                         void */*p*/, size_t /*sz*/);
+
+/* --- @mpx_loadb2cn@ --- *
+ *
+ * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
+ *             @const void *pp@ = pointer to octet array
+ *             @size_t sz@ = size of octet array
+ *
+ * Returns:    ---
+ *
+ * Use:                Loads a negative MP in an octet array, most significant octet
+ *             first as two's complement.  High-end octets are ignored if
+ *             there isn't enough space for them.  This probably means you
+ *             chose this function wrongly.
+ */
+
+extern void mpx_loadb2cn(mpw */*v*/, mpw */*vl*/,
+                        const void */*p*/, size_t /*sz*/);
+
+
+/*----- Logical shifting --------------------------------------------------*/
+
+/* --- @mpx_lsl@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = source vector base and limit
+ *             @size_t n@ = number of bit positions to shift by
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs a logical shift left operation on an integer.
+ */
+
+extern void mpx_lsl(mpw */*dv*/, mpw */*dvl*/,
+                   const mpw */*av*/, const mpw */*avl*/,
+                   size_t /*n*/);
+
+/* --- @mpx_lslc@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = source vector base and limit
+ *             @size_t n@ = number of bit positions to shift by
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs a logical shift left operation on an integer, only
+ *             it fills in the bits with ones instead of zeroes.
+ */
+
+extern void mpx_lslc(mpw */*dv*/, mpw */*dvl*/,
+                    const mpw */*av*/, const mpw */*avl*/,
+                    size_t /*n*/);
+
+/* --- @mpx_lsr@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = source vector base and limit
+ *             @size_t n@ = number of bit positions to shift by
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs a logical shift right operation on an integer.
+ */
+
+extern void mpx_lsr(mpw */*dv*/, mpw */*dvl*/,
+                   const mpw */*av*/, const mpw */*avl*/,
+                   size_t /*n*/);
+
+/*----- Bitwise operations ------------------------------------------------*/
+
+/* --- @mpx_bitop@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector
+ *             @const mpw *av, *avl@ = first source vector
+ *             @const mpw *bv, *bvl@ = second source vector
+ *
+ * Returns:    ---
+ *
+ * Use:                Provide the dyadic boolean functions.  The functions are
+ *             named after the truth table they generate:
+ *
+ *                     a:      0011
+ *                     b:      0101
+ *                     @mpx_bitXXXX@
+ */
+
+#define MPX_DOBIN(what)                                                        \
+  what(0000) what(0001) what(0010) what(0011)                          \
+  what(0100) what(0101) what(0110) what(0111)                          \
+  what(1000) what(1001) what(1010) what(1011)                          \
+  what(1100) what(1101) what(1110) what(1111)
+
+#define MPX_BITDECL(string)                                            \
+  extern void mpx_bit##string(mpw */*dv*/, mpw */*dvl*/,               \
+                             const mpw */*av*/, const mpw */*avl*/,    \
+                             const mpw */*bv*/, const mpw */*bvl*/);
+MPX_DOBIN(MPX_BITDECL)
+
+/* --- @mpx_[n]and@, @mpx_[n]or@, @mpx_xor@ --- *
+ *
+ * Synonyms for the commonly-used functions above.
+ */
+
+#define mpx_and         mpx_bit0001
+#define mpx_or  mpx_bit0111
+#define mpx_nand mpx_bit1110
+#define mpx_nor         mpx_bit1000
+#define mpx_xor         mpx_bit0110
+
+/* --- @mpx_not@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector
+ *             @const mpw *av, *avl@ = first source vector
+ *
+ * Returns:    ---
+ *
+ * Use;                Bitwise NOT.
+ */
+
+extern void mpx_not(mpw */*dv*/, mpw */*dvl*/,
+                   const mpw */*av*/, const mpw */*avl*/);
+
+/*----- Unsigned arithmetic -----------------------------------------------*/
+
+/* --- @mpx_2c@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector
+ *             @const mpw *v, *vl@ = source vector
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates the two's complement of @v@.
+ */
+
+extern void mpx_2c(mpw */*dv*/, mpw */*dvl*/,
+                  const mpw */*v*/, const mpw */*vl*/);
+
+/* --- @mpx_ueq@ --- *
+ *
+ * Arguments:  @const mpw *av, *avl@ = first argument vector base and limit
+ *             @const mpw *bv, *bvl@ = second argument vector base and limit
+ *
+ * Returns:    Nonzero if the two vectors are equal.
+ *
+ * Use:                Performs an unsigned integer test for equality.
+ */
+
+extern int mpx_ueq(const mpw */*av*/, const mpw */*avl*/,
+                  const mpw */*bv*/, const mpw */*bvl*/);
+
+/* --- @mpx_ucmp@ --- *
+ *
+ * Arguments:  @const mpw *av, *avl@ = first argument vector base and limit
+ *             @const mpw *bv, *bvl@ = second argument vector base and limit
+ *
+ * Returns:    Less than, equal to, or greater than zero depending on
+ *             whether @a@ is less than, equal to or greater than @b@,
+ *             respectively.
+ *
+ * Use:                Performs an unsigned integer comparison.
+ */
+
+#define MPX_UCMP(av, avl, op, dv, dvl)                                 \
+  (mpx_ucmp((av), (avl), (dv), (dvl)) op 0)
+
+extern int mpx_ucmp(const mpw */*av*/, const mpw */*avl*/,
+                   const mpw */*bv*/, const mpw */*bvl*/);
+
+/* --- @mpx_uadd@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = first addend vector base and limit
+ *             @const mpw *bv, *bvl@ = second addend vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer addition.  If the result overflows
+ *             the destination vector, high-order bits are discarded.  This
+ *             means that two's complement addition happens more or less for
+ *             free, although that's more a side-effect than anything else.
+ *             The result vector may be equal to either or both source
+ *             vectors, but may not otherwise overlap them.
+ */
+
+extern void mpx_uadd(mpw */*dv*/, mpw */*dvl*/,
+                    const mpw */*av*/, const mpw */*avl*/,
+                    const mpw */*bv*/, const mpw */*bvl*/);
+
+/* --- @mpx_uaddn@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = source and destination base and limit
+ *             @mpw n@ = other addend
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds a small integer to a multiprecision number.
+ */
+
+#define MPX_UADDN(dv, dvl, n) do {                                     \
+  mpw *_ddv = (dv), *_ddvl = (dvl);                                    \
+  mpw _c = (n);                                                                \
+                                                                       \
+  while (_c && _ddv < _ddvl) {                                         \
+    mpd _x = (mpd)*_ddv + (mpd)_c;                                     \
+    *_ddv++ = MPW(_x);                                                 \
+    _c = _x >> MPW_BITS;                                               \
+  }                                                                    \
+} while (0)
+
+extern void mpx_uaddn(mpw */*dv*/, mpw */*dvl*/, mpw /*n*/);
+
+/* --- @mpx_uaddnlsl@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination and first argument vector
+ *             @mpw a@ = second argument
+ *             @unsigned o@ = offset in bits
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d + 2^o a$%.  If the result overflows then
+ *             high-order bits are discarded, as usual.  We must have
+ *             @0 < o < MPW_BITS@.
+ */
+
+extern void mpx_uaddnlsl(mpw */*dv*/, mpw */*dvl*/,
+                        mpw /*a*/, unsigned /*o*/);
+
+/* --- @mpx_usub@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = first argument vector base and limit
+ *             @const mpw *bv, *bvl@ = second argument vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer subtraction.  If the result
+ *             overflows the destination vector, high-order bits are
+ *             discarded.  This means that two's complement subtraction
+ *             happens more or less for free, although that's more a side-
+ *             effect than anything else.  The result vector may be equal to
+ *             either or both source vectors, but may not otherwise overlap
+ *             them.
+ */
+
+extern void mpx_usub(mpw */*dv*/, mpw */*dvl*/,
+                    const mpw */*av*/, const mpw */*avl*/,
+                    const mpw */*bv*/, const mpw */*bvl*/);
+
+/* --- @mpx_usubn@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = source and destination base and limit
+ *             @n@ = subtrahend
+ *
+ * Returns:    ---
+ *
+ * Use:                Subtracts a small integer from a multiprecision number.
+ */
+
+#define MPX_USUBN(dv, dvl, n) do {                                     \
+  mpw *_ddv = (dv), *_ddvl = (dvl);                                    \
+  mpw _c = (n);                                                                \
+                                                                       \
+  while (_ddv < _ddvl) {                                               \
+    mpd _x = (mpd)*_ddv - (mpd)_c;                                     \
+    *_ddv++ = MPW(_x);                                                 \
+    if (_x >> MPW_BITS)                                                        \
+      _c = 1;                                                          \
+    else                                                               \
+      break;                                                           \
+  }                                                                    \
+} while (0)
+
+extern void mpx_usubn(mpw */*dv*/, mpw */*dvl*/, mpw /*n*/);
+
+/* --- @mpx_usubnlsl@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination and first argument vector
+ *             @mpw a@ = second argument
+ *             @unsigned o@ = offset in bits
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d - 2^o a$%.  If the result overflows then
+ *             high-order bits are discarded, as usual, so you get two's
+ *             complement.  Which might be what you wanted...  We must have
+ *             @0 < o < MPW_BITS@.
+ */
+
+extern void mpx_usubnlsl(mpw */*dv*/, mpw */*dvl*/,
+                        mpw /*a*/, unsigned /*o*/);
+
+/* --- @mpx_umul@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = multiplicand vector base and limit
+ *             @const mpw *bv, *bvl@ = multiplier vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer multiplication.  If the result
+ *             overflows the desination vector, high-order bits are
+ *             discarded.  The result vector may not overlap the argument
+ *             vectors in any way.
+ */
+
+extern void mpx_umul(mpw */*dv*/, mpw */*dvl*/,
+                    const mpw */*av*/, const mpw */*avl*/,
+                    const mpw */*bv*/, const mpw */*bvl*/);
+
+/* --- @mpx_umuln@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *avl@ = multiplicand vector base and limit
+ *             @mpw m@ = multiplier
+ *
+ * Returns:    ---
+ *
+ * Use:                Multiplies a multiprecision integer by a single-word value.
+ *             The destination and source may be equal.  The destination
+ *             is completely cleared after use.
+ */
+
+#define MPX_UMULN(dv, dvl, av, avl, m) do {                            \
+  mpw *_dv = (dv), *_dvl = (dvl);                                      \
+  const mpw *_av = (av), *_avl = (avl);                                        \
+  mpw _c = 0;                                                          \
+  mpd _m = (m);                                                                \
+                                                                       \
+  while (_av < _avl) {                                                 \
+    mpd _x;                                                            \
+    if (_dv >= _dvl)                                                   \
+      break;                                                           \
+    _x = (mpd)_m * (mpd)*_av++ + _c;                                   \
+    *_dv++ = MPW(_x);                                                  \
+    _c = _x >> MPW_BITS;                                               \
+  }                                                                    \
+  if (_dv < _dvl) {                                                    \
+    *_dv++ = MPW(_c);                                                  \
+    MPX_ZERO(_dv, _dvl);                                               \
+  }                                                                    \
+} while (0)
+
+extern void mpx_umuln(mpw */*dv*/, mpw */*dvl*/,
+                     const mpw */*av*/, const mpw */*avl*/, mpw m);
+
+/* --- @mpx_umlan@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination/accumulator base and limit
+ *             @const mpw *av, *avl@ = multiplicand vector base and limit
+ *             @mpw m@ = multiplier
+ *
+ * Returns:    ---
+ *
+ * Use:                Multiplies a multiprecision integer by a single-word value
+ *             and adds the result to an accumulator.
+ */
+
+#define MPX_UMLAN(dv, dvl, av, avl, m) do {                            \
+  mpw *_dv = (dv), *_dvl = (dvl);                                      \
+  const mpw *_av = (av), *_avl = (avl);                                        \
+  mpw _cc = 0;                                                         \
+  mpd _m = (m);                                                                \
+                                                                       \
+  while (_dv < _dvl && _av < _avl) {                                   \
+    mpd _x;                                                            \
+    _x = (mpd)*_dv + (mpd)_m * (mpd)*_av++ + _cc;                      \
+    *_dv++ = MPW(_x);                                                  \
+    _cc = _x >> MPW_BITS;                                              \
+  }                                                                    \
+  MPX_UADDN(_dv, _dvl, _cc);                                           \
+} while (0)
+
+extern void mpx_umlan(mpw */*dv*/, mpw */*dvl*/,
+                     const mpw */*av*/, const mpw */*avl*/, mpw m);
+
+/* --- @mpx_usqr@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
+ *             @const mpw *av, *av@ = source vector base and limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer squaring.  The result vector must
+ *             not overlap the source vector in any way.
+ */
+
+extern void mpx_usqr(mpw */*dv*/, mpw */*dvl*/,
+                    const mpw */*av*/, const mpw */*avl*/);
+
+/* --- @mpx_udiv@ --- *
+ *
+ * Arguments:  @mpw *qv, *qvl@ = quotient vector base and limit
+ *             @mpw *rv, *rvl@ = dividend/remainder vector base and limit
+ *             @const mpw *dv, *dvl@ = divisor vector base and limit
+ *             @mpw *sv, *svl@ = scratch workspace
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs unsigned integer division.  If the result overflows
+ *             the quotient vector, high-order bits are discarded.  (Clearly
+ *             the remainder vector can't overflow.)  The various vectors
+ *             may not overlap in any way.  Yes, I know it's a bit odd
+ *             requiring the dividend to be in the result position but it
+ *             does make some sense really.  The remainder must have
+ *             headroom for at least two extra words.  The scratch space
+ *             must be at least one word larger than the divisor.
+ */
+
+extern void mpx_udiv(mpw */*qv*/, mpw */*qvl*/, mpw */*rv*/, mpw */*rvl*/,
+                    const mpw */*dv*/, const mpw */*dvl*/,
+                    mpw */*sv*/, mpw */*svl*/);
+
+/* --- @mpx_udivn@ --- *
+ *
+ * Arguments:  @mpw *qv, *qvl@ = storage for the quotient (may overlap
+ *                     dividend)
+ *             @const mpw *rv, *rvl@ = dividend
+ *             @mpw d@ = single-precision divisor
+ *
+ * Returns:    Remainder after divison.
+ *
+ * Use:                Performs a single-precision division operation.
+ */
+
+extern mpw mpx_udivn(mpw */*qv*/, mpw */*qvl*/,
+                    const mpw */*rv*/, const mpw */*rvl*/, mpw /*d*/);
+
+/*----- Karatsuba multiplication algorithms -------------------------------*/
+
+/* --- @MPK_THRESH@ --- *
+ *
+ * This is the limiting length for using Karatsuba algorithms.  It's best to
+ * use the simpler classical multiplication method on numbers smaller than
+ * this.  It is unsafe to make this constant less than four (i.e., the
+ * algorithms will fail).
+ */
+
+#define MPK_THRESH 16
+
+/* --- @mpx_kmul@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
+ *             @const mpw *av, *avl@ = pointer to first argument
+ *             @const mpw *bv, *bvl@ = pointer to second argument
+ *             @mpw *sv, *svl@ = pointer to scratch workspace
+ *
+ * Returns:    ---
+ *
+ * Use:                Multiplies two multiprecision integers using Karatsuba's
+ *             algorithm.  This is rather faster than traditional long
+ *             multiplication (e.g., @mpx_umul@) on large numbers, although
+ *             more expensive on small ones.
+ *
+ *             The destination must be three times as large as the larger
+ *             argument.  The scratch space must be five times as large as
+ *             the larger argument.
+ */
+
+extern void mpx_kmul(mpw */*dv*/, mpw */*dvl*/,
+                    const mpw */*av*/, const mpw */*avl*/,
+                    const mpw */*bv*/, const mpw */*bvl*/,
+                    mpw */*sv*/, mpw */*svl*/);
+
+/* --- @mpx_ksqr@ --- *
+ *
+ * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
+ *             @const mpw *av, *avl@ = pointer to first argument
+ *             @mpw *sv, *svl@ = pointer to scratch workspace
+ *
+ * Returns:    ---
+ *
+ * Use:                Squares a multiprecision integers using something similar to
+ *             Karatsuba's multiplication algorithm.  This is rather faster
+ *             than traditional long multiplication (e.g., @mpx_umul@) on
+ *             large numbers, although more expensive on small ones, and
+ *             rather simpler than full-blown Karatsuba multiplication.
+ *
+ *             The destination must be three times as large as the larger
+ *             argument.  The scratch space must be five times as large as
+ *             the larger argument.
+ */
+
+extern void mpx_ksqr(mpw */*dv*/, mpw */*dvl*/,
+                    const mpw */*av*/, const mpw */*avl*/,
+                    mpw */*sv*/, mpw */*svl*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/p-gentab.awk b/math/p-gentab.awk
new file mode 100755 (executable)
index 0000000..f0dd357
--- /dev/null
@@ -0,0 +1,100 @@
+#! /usr/bin/awk -f
+
+function banner(name, s, i)
+{
+  s = "/*----- " name " ";
+  while (length(s) < 75) s = s "-";
+  return (s "*/");
+}
+
+function fix(name)
+{
+  gsub(/[^0-9A-Za-z_]+/, "_", name);
+  return (name);
+}
+
+BEGIN {
+  print "/* -*-c-*-";
+  print " *";
+  print " * Table of prime groups [generated]";
+  print " */";
+  print "";
+  print "#include \"ptab.h\"";
+  print "";
+  print "#define N(x) (sizeof(x)/sizeof(*x))";
+  print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }";
+  print "#define NOMP { 0, 0, 0, 0, 0 }";
+  print "";
+  print banner("Prime data");
+  print "";
+
+  d_i = 0;
+  name = "";
+}
+
+function putmp(x,  d)
+{
+  if (!(x in data)) {
+    print "group " name ": missing " x >"/dev/stderr";
+    exit 1;
+  }
+  d = data[x];
+  if (!(d in cache)) {
+    n = "p_" fix(name) "_" x;
+    print "static mpw " n "[] = {";
+    system("./mpdump " d);
+    print "};";
+    print "";
+    cache[d] = n;
+  }
+  mp[x] = cache[d];
+}
+
+function flush()
+{
+  if (name == "") return;
+  print "/* --- Group " name " --- */";
+  delete mp;
+  print "";
+  putmp("p");
+  putmp("q");
+  putmp("g");
+  print "static pdata p_" fix(name) " = {";
+  print "  MP(" mp["p"] "),"
+  print "  MP(" mp["q"] "),"
+  print "  MP(" mp["g"] ")"
+  print "};";
+  print "";
+  dname[d_i++] = name;
+  d[name] = name;
+  r[name] = "p_" fix(name);
+  name = "";
+}
+
+/^[ \t]*(#|$)/ { next; }
+
+$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; }
+
+$1 == "group" { flush(); delete data; name = $2; next; }
+
+{ data[$1] = $2; next; }
+
+END {
+  flush();
+  print banner("Main table");
+  print "";
+  print "const pentry ptab[] = {";
+  for (i = 0; i < d_i; i++) {
+    name = dname[i];
+    rname = d[name];
+    if (!rname in r) {
+      print "group " rname " not found (alias from " name ")" >"/dev/stderr";
+      exit 1;
+    }
+    print "  { \"" name "\", &" r[rname] " },";
+  }
+  print "  { 0, 0 }";
+  print "};"
+  print "";
+  print banner("That's all, folks");
+}
diff --git a/math/pfilt.c b/math/pfilt.c
new file mode 100644 (file)
index 0000000..de049cb
--- /dev/null
@@ -0,0 +1,327 @@
+/* -*-c-*-
+ *
+ * Finding and testing prime numbers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpint.h"
+#include "pfilt.h"
+#include "pgen.h"
+#include "primetab.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @smallenough@ --- *
+ *
+ * Arguments:  @mp *m@ = integer to test
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Assuming that @m@ has been tested by trial division on every
+ *             prime in the small-primes array, this function will return
+ *             @PGEN_DONE@ if the number is less than the square of the
+ *             largest small prime.
+ */
+
+static int smallenough(mp *m)
+{
+  static mp *max = 0;
+  int rc = PGEN_TRY;
+
+  if (!max) {
+    max = mp_fromuint(MP_NEW, MAXPRIME);
+    max = mp_sqr(max, max);
+    max->a->n--; /* Permanent allocation */
+  }
+  if (MP_CMP(m, <=, MP_ONE))
+    rc = PGEN_FAIL;
+  else if (MP_CMP(m, <, max))
+    rc = PGEN_DONE;
+  return (rc);
+}
+
+/* --- @pfilt_smallfactor@ --- *
+ *
+ * Arguments:  @mp *m@ = integer to test
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Tests a number by dividing by a number of small primes.  This
+ *             is a useful first step if you're testing random primes; for
+ *             sequential searches, @pfilt_create@ works better.
+ */
+
+int pfilt_smallfactor(mp *m)
+{
+  int rc = PGEN_TRY;
+  int i;
+  size_t sz = MP_LEN(m);
+  mparena *a = m->a ? m->a : MPARENA_GLOBAL;
+  mpw *v = mpalloc(a, sz);
+
+  /* --- Fill in the residues --- */
+
+  for (i = 0; i < NPRIME; i++) {
+    if (!mpx_udivn(v, v + sz, m->v, m->vl, primetab[i])) {
+      if (MP_LEN(m) == 1 && m->v[0] == primetab[i])
+       rc = PGEN_DONE;
+      else
+       rc = PGEN_FAIL;
+      break;
+    }
+  }
+
+  /* --- Check for small primes --- */
+
+  if (rc == PGEN_TRY)
+    rc = smallenough(m);
+
+  /* --- Done --- */
+
+  mpfree(a, v);
+  return (rc);
+}
+
+/* --- @pfilt_create@ --- *
+ *
+ * Arguments:  @pfilt *p@ = pointer to prime filtering context
+ *             @mp *m@ = pointer to initial number to test
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Tests an initial number for primality by computing its
+ *             residue modulo various small prime numbers.  This is fairly
+ *             quick, but not particularly certain.  If a @PGEN_TRY@
+ *             result is returned, perform Rabin-Miller tests to confirm.
+ */
+
+int pfilt_create(pfilt *p, mp *m)
+{
+  int rc = PGEN_TRY;
+  int i;
+  size_t sz = MP_LEN(m);
+  mparena *a = m->a ? m->a : MPARENA_GLOBAL;
+  mpw *v = mpalloc(a, sz);
+
+  /* --- Take a copy of the number --- */
+
+  mp_shrink(m);
+  p->m = MP_COPY(m);
+
+  /* --- Fill in the residues --- */
+
+  for (i = 0; i < NPRIME; i++) {
+    p->r[i] = mpx_udivn(v, v + sz, m->v, m->vl, primetab[i]);
+    if (!p->r[i] && rc == PGEN_TRY) {
+      if (MP_LEN(m) == 1 && m->v[0] == primetab[i])
+       rc = PGEN_DONE;
+      else
+       rc = PGEN_FAIL;
+    }
+  }
+
+  /* --- Check for small primes --- */
+
+  if (rc == PGEN_TRY)
+    rc = smallenough(m);
+
+  /* --- Done --- */
+
+  mpfree(a, v);
+  return (rc);
+}
+
+/* --- @pfilt_destroy@ --- *
+ *
+ * Arguments:  @pfilt *p@ = pointer to prime filtering context
+ *
+ * Returns:    ---
+ *
+ * Use:                Discards a context and all the resources it holds.
+ */
+
+void pfilt_destroy(pfilt *p)
+{
+  mp_drop(p->m);
+}
+
+/* --- @pfilt_step@ --- *
+ *
+ * Arguments:  @pfilt *p@ = pointer to prime filtering context
+ *             @mpw step@ = how much to step the number
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Steps a number by a small amount.  Stepping is much faster
+ *             than initializing with a new number.  The test performed is
+ *             the same simple one used by @primetab_create@, so @PGEN_TRY@
+ *             results should be followed up by a Rabin-Miller test.
+ */
+
+int pfilt_step(pfilt *p, mpw step)
+{
+  int rc = PGEN_TRY;
+  int i;
+
+  /* --- Add the step on to the number --- */
+
+  p->m = mp_split(p->m);
+  mp_ensure(p->m, MP_LEN(p->m) + 1);
+  mpx_uaddn(p->m->v, p->m->vl, step);
+  mp_shrink(p->m);
+
+  /* --- Update the residue table --- */
+
+  for (i = 0; i < NPRIME; i++) {
+    p->r[i] = (p->r[i] + step) % primetab[i];
+    if (!p->r[i] && rc == PGEN_TRY) {
+      if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i])
+       rc = PGEN_DONE;
+      else
+       rc = PGEN_FAIL;
+    }
+  }
+
+  /* --- Check for small primes --- */
+
+  if (rc == PGEN_TRY)
+    rc = smallenough(p->m);
+
+  /* --- Done --- */
+
+  return (rc);
+}
+
+/* --- @pfilt_muladd@ --- *
+ *
+ * Arguments:  @pfilt *p@ = destination prime filtering context
+ *             @const pfilt *q@ = source prime filtering context
+ *             @mpw m@ = number to multiply by
+ *             @mpw a@ = number to add
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Multiplies the number in a prime filtering context by a
+ *             small value and then adds a small value.  The destination
+ *             should either be uninitialized or the same as the source.
+ *
+ *             Common things to do include multiplying by 2 and adding 0 to
+ *             turn a prime into a jump for finding other primes with @q@ as
+ *             a factor of @p - 1@, or multiplying by 2 and adding 1.
+ */
+
+int pfilt_muladd(pfilt *p, const pfilt *q, mpw m, mpw a)
+{
+  int rc = PGEN_TRY;
+  int i;
+
+  /* --- Multiply the big number --- */
+
+  {
+    mp *d = mp_new(MP_LEN(q->m) + 2, q->m->f);
+    mpx_umuln(d->v, d->vl, q->m->v, q->m->vl, m);
+    mpx_uaddn(d->v, d->vl, a);
+    if (p == q)
+      mp_drop(p->m);
+    mp_shrink(d);
+    p->m = d;
+  }
+
+  /* --- Gallivant through the residue table --- */
+
+  for (i = 0; i < NPRIME; i++) {
+    p->r[i] = (q->r[i] * m + a) % primetab[i];
+    if (!p->r[i] && rc == PGEN_TRY) {
+      if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i])
+       rc = PGEN_DONE;
+      else
+       rc = PGEN_FAIL;
+    }
+  }
+
+  /* --- Check for small primes --- */
+
+  if (rc == PGEN_TRY)
+    rc = smallenough(p->m);
+
+  /* --- Finished --- */
+
+  return (rc);
+}
+
+/* --- @pfilt_jump@ --- *
+ *
+ * Arguments:  @pfilt *p@ = pointer to prime filtering context
+ *             @const pfilt *j@ = pointer to another filtering context
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Steps a number by a large amount.  Even so, jumping is much
+ *             faster than initializing a new number.  The test peformed is
+ *             the same simple one used by @primetab_create@, so @PGEN_TRY@
+ *             results should be followed up by a Rabin-Miller test.
+ *
+ *             Note that the number stored in the @j@ context is probably
+ *             better off being even than prime.  The important thing is
+ *             that all of the residues for the number have already been
+ *             computed.
+ */
+
+int pfilt_jump(pfilt *p, const pfilt *j)
+{
+  int rc = PGEN_TRY;
+  int i;
+
+  /* --- Add the step on --- */
+
+  p->m = mp_add(p->m, p->m, j->m);
+
+  /* --- Update the residue table --- */
+
+  for (i = 0; i < NPRIME; i++) {
+    p->r[i] = p->r[i] + j->r[i];
+    if (p->r[i] > primetab[i])
+      p->r[i] -= primetab[i];
+    if (!p->r[i] && rc == PGEN_TRY) {
+      if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i])
+       rc = PGEN_DONE;
+      else
+       rc = PGEN_FAIL;
+    }
+  }
+
+  /* --- Check for small primes --- */
+
+  if (rc == PGEN_TRY)
+    rc = smallenough(p->m);
+
+  /* --- Done --- */
+
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/pfilt.h b/math/pfilt.h
new file mode 100644 (file)
index 0000000..a667614
--- /dev/null
@@ -0,0 +1,155 @@
+/* -*-c-*-
+ *
+ * Finding and testing prime numbers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_PFILT_H
+#define CATACOMB_PFILT_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_PRIMETAB_H
+#  include "primetab.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct pfilt {
+  mp *m;
+  smallprime r[NPRIME];
+} pfilt;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @pfilt_smallfactor@ --- *
+ *
+ * Arguments:  @mp *m@ = integer to test
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Tests a number by dividing by a number of small primes.  This
+ *             is a useful first step if you're testing random primes; for
+ *             sequential searches, @pfilt_create@ works better.
+ */
+
+extern int pfilt_smallfactor(mp */*m*/);
+
+/* --- @pfilt_create@ --- *
+ *
+ * Arguments:  @pfilt *p@ = pointer to prime filtering context
+ *             @mp *m@ = pointer to initial number to test
+ *
+ * Returns:    A @PGEN@ result code.
+ *
+ * Use:                Tests an initial number for primality by computing its
+ *             residue modulo various small prime numbers.  This is fairly
+ *             quick, but not particularly certain.  If a @PGEN_TRY@
+ *             result is returned, perform Rabin-Miller tests to confirm.
+ */
+
+extern int pfilt_create(pfilt */*p*/, mp */*m*/);
+
+/* --- @pfilt_destroy@ --- *
+ *
+ * Arguments:  @pfilt *p@ = pointer to prime filtering context
+ *
+ * Returns:    ---
+ *
+ * Use:                Discards a context and all the resources it holds.
+ */
+
+extern void pfilt_destroy(pfilt */*p*/);
+
+/* --- @pfilt_step@ --- *
+ *
+ * Arguments:  @pfilt *p@ = pointer to prime filtering context
+ *             @mpw step@ = how much to step the number
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Steps a number by a small amount.  Stepping is much faster
+ *             than initializing with a new number.  The test performed is
+ *             the same simple one used by @primetab_create@, so @PGEN_TRY@
+ *             results should be followed up by a Rabin-Miller test.
+ */
+
+extern int pfilt_step(pfilt */*p*/, mpw /*step*/);
+
+/* --- @pfilt_muladd@ --- *
+ *
+ * Arguments:  @pfilt *p@ = destination prime filtering context
+ *             @const pfilt *q@ = source prime filtering context
+ *             @mpw m@ = number to multiply by
+ *             @mpw a@ = number to add
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Multiplies the number in a prime filtering context by a
+ *             small value and then adds a small value.  The destination
+ *             should either be uninitialized or the same as the source.
+ *
+ *             Common things to do include multiplying by 2 and adding 0 to
+ *             turn a prime into a jump for finding other primes with @q@ as
+ *             a factor of @p - 1@, or multiplying by 2 and adding 1.
+ */
+
+extern int pfilt_muladd(pfilt */*p*/, const pfilt */*q*/,
+                       mpw /*m*/, mpw /*a*/);
+
+/* --- @pfilt_jump@ --- *
+ *
+ * Arguments:  @pfilt *p@ = pointer to prime filtering context
+ *             @const pfilt *j@ = pointer to another filtering context
+ *
+ * Returns:    One of the @PGEN@ result codes.
+ *
+ * Use:                Steps a number by a large amount.  Even so, jumping is much
+ *             faster than initializing a new number.  The test peformed is
+ *             the same simple one used by @primetab_create@, so @PGEN_TRY@
+ *             results should be followed up by a Rabin-Miller test.
+ *
+ *             Note that the number stored in the @j@ context is probably
+ *             better off being even than prime.  The important thing is
+ *             that all of the residues for the number have already been
+ *             computed.
+ */
+
+extern int pfilt_jump(pfilt */*p*/, const pfilt */*j*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/pgen-gcd.c b/math/pgen-gcd.c
new file mode 100644 (file)
index 0000000..1d205b5
--- /dev/null
@@ -0,0 +1,101 @@
+/* -*-c-*-
+ *
+ * Prime search stepper ensuring a low GCD for %$(p - 1)/2$%
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "pgen.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+int pgen_gcdstep(int rq, pgen_event *ev, void *p)
+{
+  pgen_gcdstepctx *g = p;
+  int rc = PGEN_ABORT;
+
+  switch (rq) {
+
+    /* --- Set everything up --- *
+     *
+     * Call things off if @p@ and @jp@ have common factors, or if @q@, @r@
+     * and @jq@ have common factors greater than @max@.
+     */
+
+    case PGEN_BEGIN: {
+      mp *p = ev->m;
+      mp_gcd(&g->g, 0, 0, p, g->jp.m);
+      if (MP_CMP(g->g, >, MP_ONE))
+       return (PGEN_ABORT);
+      g->q = mp_lsr(MP_NEW, p, 1);
+      g->jq = mp_lsr(MP_NEW, g->jp.m, 1);
+      mp_gcd(&g->g, 0, 0, g->q, g->jq);
+      mp_gcd(&g->g, 0, 0, g->g, g->r);
+      if (MP_CMP(g->g, >, g->max)) {
+       mp_drop(g->q);
+       mp_drop(g->jq);
+       return (PGEN_ABORT);
+      }
+      rc = pfilt_create(&g->p, p);
+      mp_drop(p);
+    } break;
+
+    /* --- Grind through another iteration --- */
+
+    case PGEN_TRY:
+      mp_drop(ev->m);
+      rc = pfilt_jump(&g->p, &g->jp);
+      g->q = mp_add(g->q, g->q, g->jq);
+      break;
+
+    /* --- Finished --- */
+
+    case PGEN_DONE:
+      pfilt_destroy(&g->p);
+      mp_drop(g->q);
+      mp_drop(g->jq);
+      return (PGEN_DONE);
+  }
+
+  /* --- Step on until everything is OK --- */
+
+  for (;;) {
+    if (rc != PGEN_FAIL) {
+      mp_gcd(&g->g, 0, 0, g->r, g->q);
+      if (MP_CMP(g->g, >, g->max))
+       rc = PGEN_FAIL;
+    }
+    if (rc != PGEN_FAIL)
+      break;
+    rc = pfilt_jump(&g->p, &g->jp);
+    g->q = mp_add(g->q, g->q, g->jq);
+  }
+
+  ev->m = MP_COPY(g->p.m);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/pgen-simul.c b/math/pgen-simul.c
new file mode 100644 (file)
index 0000000..03deeb1
--- /dev/null
@@ -0,0 +1,168 @@
+/* -*-c-*-
+ *
+ * Simultaneous prime search
+ *
+ * (c) 2006 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdlib.h>
+
+#include <mLib/macros.h>
+
+#include "mprand.h"
+#include "pgen.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rcmerge@ --- *
+ *
+ * Arguments:  @int a, b@ = a pair of @PGEN@ return codes
+ *
+ * Returns:    The overall return code capturing both.
+ */
+
+static int rcmerge(int a, int b)
+{
+#define FROB(state)                                                    \
+    if (a == PGEN_##state || b == PGEN_##state) return (PGEN_##state)
+  FROB(FAIL);
+  FROB(TRY);
+  FROB(PASS);
+#undef FROB
+  return (PGEN_DONE);
+}
+
+/* --- @pgen_simulstep@ --- *
+ *
+ * Step a collection of numbers simultaneously.
+ */
+
+int pgen_simulstep(int rq, pgen_event *ev, void *p)
+{
+  pgen_simulctx *ss = p;
+  pgen_simulprime *sp;
+  int rc = PGEN_ABORT, nrc;
+  unsigned i;
+  mp *q;
+
+  assert(ss->n);
+  switch (rq) {
+    case PGEN_BEGIN:
+      rc = PGEN_DONE;
+      q = MP_NEW;
+      for (i = 0; i < ss->n; i++) {
+       sp = &ss->v[i];
+       q = mp_mul(q, ss->step, sp->mul);
+       if (MP_LEN(q) <= 1)
+         sp->u.step = q->v[0];
+       else {
+         sp->u.jump = xmalloc(sizeof(pfilt));
+         pfilt_create(sp->u.jump, q);
+         sp->f |= PGENF_JUMP;
+       }
+       q = mp_mul(q, ev->m, sp->mul);
+       q = mp_add(q, q, sp->add);
+       nrc = pfilt_create(&sp->p, q);
+       rc = rcmerge(rc, nrc);
+      }
+      MP_DROP(q);
+      if (rc != PGEN_FAIL)
+       goto done;
+    case PGEN_TRY:
+      for (;;) {
+       rc = PGEN_DONE;
+       for (i = 0; i < ss->n; i++) {
+         sp = &ss->v[i];
+         if (sp->f & PGENF_JUMP)
+           nrc = pfilt_jump(&sp->p, sp->u.jump);
+         else
+           nrc = pfilt_step(&sp->p, sp->u.step);
+         rc = rcmerge(rc, nrc);
+       }
+       if (rc != PGEN_FAIL)
+         goto done;
+      }
+    done:
+      mp_drop(ev->m);
+      ev->m = MP_COPY(ss->v[0].p.m);
+      break;
+    case PGEN_DONE:
+      for (i = 0; i < ss->n; i++) {
+       sp = &ss->v[i];
+       if (sp->f & PGENF_JUMP) {
+         pfilt_destroy(sp->u.jump);
+         xfree(sp->u.jump);
+       }
+       if (sp->f & PGENF_KEEP)
+         sp->u.x = MP_COPY(sp->p.m);
+       pfilt_destroy(&sp->p);
+      }
+      rc = PGEN_DONE;
+      break;
+  }
+  return (rc);
+}
+
+/* --- @pgen_simultest@ --- *
+ *
+ * Test a collection of numbers simultaneously.
+ */
+
+int pgen_simultest(int rq, pgen_event *ev, void *p)
+{
+  pgen_simulctx *ss = p;
+  pgen_simulprime *sp;
+  int rc;
+  unsigned i;
+  mp *m;
+
+  assert(ss->n);
+  switch (rq) {
+    case PGEN_BEGIN:
+      for (i = 0; i < ss->n; i++)
+       rabin_create(&ss->v[i].r, ss->v[i].p.m);
+      rc = PGEN_TRY;
+      break;
+    case PGEN_TRY:
+      m = MP_NEW;
+      for (i = 0; i < ss->n; i++) {
+       sp = &ss->v[i];
+       m = mprand_range(m, sp->p.m, ev->r, 0);
+       rc = rabin_test(&sp->r, m);
+       if (rc != PGEN_PASS)
+         break;
+      }
+      mp_drop(m);
+      break;
+    case PGEN_DONE:
+      for (i = 0; i < ss->n; i++)
+       rabin_destroy(&ss->v[i].r);
+      rc = PGEN_DONE;
+      break;
+  }
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/pgen-stdev.c b/math/pgen-stdev.c
new file mode 100644 (file)
index 0000000..117fb27
--- /dev/null
@@ -0,0 +1,129 @@
+/* -*-c-*-
+ *
+ * Standard event handlers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pgen.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @pgen_evspin@ --- *
+ *
+ * Displays a spinning baton to show progress.
+ */
+
+int pgen_evspin(int rq, pgen_event *ev, void *p)
+{
+  static char spinner[] = "/-\\|";
+  static char *q = spinner;
+
+  switch (rq) {
+    case PGEN_PASS:
+    case PGEN_FAIL:
+      putchar(*q++);
+      putchar('\b');
+      fflush(stdout);
+      if (!*q)
+       q = spinner;
+      break;
+    case PGEN_DONE:
+    case PGEN_ABORT:
+      putchar(' ');
+      putchar('\b');
+      fflush(stdout);
+      break;
+  }
+  return (0);
+}
+
+/* --- @pgen_ev@ --- *
+ *
+ * Traditional event handler, shows dots for each test.
+ */
+
+int pgen_ev(int rq, pgen_event *ev, void *p)
+{
+  switch (rq) {
+    case PGEN_BEGIN:
+      printf("Searching for %s: ", ev->name);
+      fflush(stdout);
+      break;
+    case PGEN_FAIL:
+      putchar('.');
+      fflush(stdout);
+      break;
+    case PGEN_PASS:
+      putchar('+');
+      fflush(stdout);
+      break;
+    case PGEN_DONE:
+      puts("+ ok");
+      break;
+    case PGEN_ABORT:
+      puts(" failed");
+      break;
+  }
+  return (0);
+}
+
+/* --- @pgen_subev@ --- *
+ *
+ * Subsidiary event handler, mainly for Lim-Lee searches and so on.
+ */
+
+int pgen_subev(int rq, pgen_event *ev, void *p)
+{
+  switch (rq) {
+    case PGEN_BEGIN:
+      printf("[%s: ", ev->name);
+      fflush(stdout);
+      break;
+    case PGEN_FAIL:
+      putchar('.');
+      fflush(stdout);
+      break;
+    case PGEN_PASS:
+      putchar('+');
+      fflush(stdout);
+      break;
+    case PGEN_DONE:
+      fputs("+]", stdout);
+      fflush(stdout);
+      break;
+    case PGEN_ABORT:
+      fputs(" failed]", stdout);
+      fflush(stdout);
+      break;
+  }
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/pgen.c b/math/pgen.c
new file mode 100644 (file)
index 0000000..9a822f5
--- /dev/null
@@ -0,0 +1,420 @@
+/* -*-c-*-
+ *
+ * Prime generation glue
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fibrand.h"
+#include "grand.h"
+#include "mp.h"
+#include "mprand.h"
+#include "pgen.h"
+#include "pfilt.h"
+#include "rabin.h"
+
+/*----- Standard prime filter ---------------------------------------------*/
+
+/* --- @pgen_filter@ --- */
+
+int pgen_filter(int rq, pgen_event *ev, void *p)
+{
+  pgen_filterctx *f = p;
+  int rc = PGEN_FAIL;
+
+  switch (rq) {
+    case PGEN_BEGIN:
+      rc = pfilt_create(&f->f, ev->m);
+      mp_drop(ev->m);
+      break;
+    case PGEN_TRY:
+      mp_drop(ev->m);
+      break;
+    case PGEN_DONE:
+      pfilt_destroy(&f->f);
+      return (PGEN_DONE);
+    default:
+      rc = PGEN_ABORT;
+      break;
+  }
+
+  if (rc == PGEN_FAIL && !((f->step | f->f.m->v[0]) & 1))
+    rc = pfilt_step(&f->f, 1);
+  while (rc == PGEN_FAIL)
+    rc = pfilt_step(&f->f, f->step);
+  ev->m = MP_COPY(f->f.m);
+  return (rc);
+}
+
+/* --- @pgen_jump@ --- *
+ *
+ * Similar to the standard @pgen_filter@, but jumps in large steps rather
+ * than small ones.
+ */
+
+int pgen_jump(int rq, pgen_event *ev, void *p)
+{
+  pgen_jumpctx *f = p;
+  int rc = PGEN_ABORT;
+
+  switch (rq) {
+    case PGEN_BEGIN: {
+      mp *g = MP_NEW;
+      mp_gcd(&g, 0, 0, ev->m, f->j->m);
+      if (MP_CMP(g, >, MP_ONE)) {
+       mp_drop(g);
+       return (PGEN_ABORT);
+      }
+      mp_drop(g);
+      rc = pfilt_create(&f->f, ev->m);
+      mp_drop(ev->m);
+    } break;
+    case PGEN_TRY:
+      mp_drop(ev->m);
+      rc = pfilt_jump(&f->f, f->j);
+      break;
+    case PGEN_DONE:
+      pfilt_destroy(&f->f);
+      return (PGEN_DONE);
+  }
+
+  while (rc == PGEN_FAIL)
+    rc = pfilt_jump(&f->f, f->j);
+  ev->m = MP_COPY(f->f.m);
+  return (rc);
+}
+
+/*----- Standard prime test -----------------------------------------------*/
+
+/* --- @pgen_test@ --- */
+
+int pgen_test(int rq, pgen_event *ev, void *p)
+{
+  rabin *r = p;
+  int rc = PGEN_ABORT;
+
+  switch (rq) {
+    case PGEN_BEGIN:
+      rabin_create(r, ev->m);
+      rc = PGEN_TRY;
+      break;
+    case PGEN_TRY:
+      if (!ev->tests)
+       rc = rabin_rtest(r, MP_TWO);
+      else {
+       mp *a = mprand_range(MP_NEW, ev->m, ev->r, 0);
+       rc = rabin_rtest(r, a);
+       mp_drop(a);
+      }
+      break;
+    case PGEN_DONE:
+      rabin_destroy(r);
+      rc = PGEN_DONE;
+      break;
+  }
+
+  return (rc);
+}
+
+/*----- The main driver ---------------------------------------------------*/
+
+/* --- @pgen@ --- *
+ *
+ * Arguments:  @const char *name@ = name of the value being searched for
+ *             @mp *d@ = destination for the result integer
+ *             @mp *m@ = start value to pass to stepper
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = context argument for event andler
+ *             @unsigned steps@ = number of steps to take in search
+ *             @pgen_proc *step@ = stepper function to use
+ *             @void *sctx@ = context argument for stepper
+ *             @unsigned tests@ = number of tests to make
+ *             @pgen_proc *test@ = tester function to use
+ *             @void *tctx@ = context argument for tester
+ *
+ * Returns:    Pointer to final result, or null.
+ *
+ * Use:                A generalized prime-number search skeleton.  Yes, that's a
+ *             scary number of arguments.
+ */
+
+mp *pgen(const char *name, mp *d, mp *m, pgen_proc *event, void *ectx,
+        unsigned steps, pgen_proc *step, void *sctx,
+        unsigned tests, pgen_proc *test, void *tctx)
+{
+  pgen_event ev;
+  int rq, rc;
+  pgen_proc *proc;
+  void *ctx;
+  int p;
+
+  enum { P_STEP, P_TEST };
+
+  /* --- Set up the initial event block --- */
+
+  ev.name = name;
+  if (m)
+    ev.m = MP_COPY(m);
+  else
+    ev.m = 0;
+  ev.steps = 0;
+  ev.tests = 0;
+  ev.r = fibrand_create(0);
+
+  /* --- Tell the event handler we're under way --- */
+
+  if (event && event(PGEN_BEGIN, &ev, ectx) == PGEN_ABORT) {
+    ev.r->ops->destroy(ev.r);
+    return (0);
+  }
+
+  /* --- Set up for the initial call --- */
+
+  proc = step; ctx = sctx; p = P_STEP; rq = PGEN_BEGIN;
+
+  /* --- Enter the great maelstrom of state transitions --- */
+
+  for (;;) {
+    unsigned act = 0;
+
+#define A_STEP 1u
+#define A_TEST 2u
+#define A_EVENT 4u
+#define A_ENDTEST 8u
+#define A_ENDSTEP 16u
+#define A_DONE 32u
+
+    /* --- Call the procedure and decide what to do next --- */
+
+    rc = proc(rq, &ev, ctx);
+    switch (rc) {
+      case PGEN_TRY:
+       if (p == P_TEST)
+         rq = PGEN_TRY;
+       else {
+         act |= A_EVENT;
+         proc = test; ctx = tctx; p = P_TEST;
+         rq = PGEN_BEGIN;
+       }
+       break;
+      case PGEN_PASS:
+       act |= A_TEST | A_EVENT;
+       if (p == P_TEST)
+         rq = PGEN_TRY;
+       else {
+         proc = test; ctx = tctx; p = P_TEST;
+         rq = PGEN_BEGIN;
+       }
+       break;
+      case PGEN_FAIL:
+       act |= A_STEP;
+       if (p == P_TEST) {
+         act |= A_ENDTEST | A_EVENT;
+         proc = step; ctx = sctx; p = P_STEP;
+       }
+       rq = PGEN_TRY;
+       break;
+      case PGEN_DONE:
+       act |= A_EVENT | A_DONE | A_ENDSTEP;
+       if (p == P_TEST)
+         act |= A_ENDTEST;
+       break;
+      case PGEN_ABORT:
+       act |= A_EVENT | A_DONE;
+       if (p == P_TEST || rq == PGEN_TRY)
+         act |= A_ENDSTEP;
+       if (p == P_TEST && rq != PGEN_BEGIN)
+         act |= A_ENDTEST;
+       break;
+      default:
+       assert(((void)"Invalid response from function", 0));
+       break;
+    }
+
+    /* --- If decrementing counters is requested, do that --- */
+
+    if ((act & A_STEP) && steps) {
+      ev.steps++;
+      if (ev.steps == steps) {
+       act |= A_EVENT | A_ENDSTEP | A_DONE;
+       rc = PGEN_ABORT;
+      }
+      ev.tests = 0;
+    }
+
+    if ((act & A_TEST) && tests) {
+      ev.tests++;
+      if (ev.tests == tests) {
+       act |= A_ENDTEST | A_ENDSTEP | A_DONE;
+       rc = PGEN_DONE;
+      }
+    }
+
+    /* --- Report an event if so directed --- */
+
+    if ((act & A_EVENT) && event && event(rc, &ev, ectx) == PGEN_ABORT) {
+      rc = PGEN_ABORT;
+      if (!(act & A_DONE)) {
+       act |= A_ENDSTEP | A_DONE;
+       if (p == P_TEST)
+         act |= A_ENDTEST;
+      }
+    }
+
+    /* --- Close down tester and stepper functions --- */
+
+    if (act & A_ENDTEST)
+      test(PGEN_DONE, &ev, tctx);
+    if (act & A_ENDSTEP)
+      step(PGEN_DONE, &ev, sctx);
+
+    /* --- Stop the entire test if necessary --- */
+
+    if (act & A_DONE)
+      break;
+  }
+
+  /* --- Tidy up and return --- */
+
+  if (rc == PGEN_ABORT) {
+    mp_drop(ev.m);
+    ev.m = 0;
+  }
+  ev.r->ops->destroy(ev.r);
+  mp_drop(d);
+
+  return (ev.m);
+}
+
+/* --- @pgen_primep@ --- *
+ *
+ * Arguments:  @mp *p@ = a number to check
+ *             @grand *gr@ = a random number source
+ *
+ * Returns:    Nonzero if @p@ is really prime.
+ */
+
+int pgen_primep(mp *p, grand *gr)
+{
+  int i;
+  rabin r;
+  mp *x = MP_NEW;
+
+  if (MP_NEGP(p)) return (0);
+  switch (pfilt_smallfactor(p)) {
+    case PGEN_DONE: return (1);
+    case PGEN_FAIL: return (0);
+  }
+  rabin_create(&r, p);
+  for (i = 32; i; i--) {
+    x = mprand_range(x, p, gr, 0);
+    if (rabin_rtest(&r, x) == PGEN_FAIL)
+      break;
+  }
+  MP_DROP(x);
+  rabin_destroy(&r);
+  return (!i);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int t_primep(dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  int e = *(int *)v[1].buf;
+  int r;
+  grand *rng;
+  int ok = 1;
+
+  rng = fibrand_create(0);
+  r = pgen_primep(m, rng);
+  GR_DESTROY(rng);
+  if (e != r) {
+    fputs("\n*** primep failed", stderr);
+    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
+    fprintf(stderr, "\nexpected %d", e);
+    fprintf(stderr, "\nreported %d", r);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(m);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int verify(dstr *v)
+{
+  mp *m = *(mp **)v[0].buf;
+  mp *q = *(mp **)v[1].buf;
+  mp *p;
+  int ok = 1;
+
+  pgen_filterctx pf;
+  rabin r;
+
+  pf.step = 2;
+  p = pgen("p", MP_NEW, m, pgen_evspin, 0, 0, pgen_filter, &pf,
+          rabin_iters(mp_bits(m)), pgen_test, &r);
+  if (!p || !MP_EQ(p, q)) {
+    fputs("\n*** pgen failed", stderr);
+    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
+    fputs("\np = ", stderr); mp_writefile(p, stderr, 10);
+    fputs("\nq = ", stderr); mp_writefile(q, stderr, 10);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(m);
+  mp_drop(q);
+  mp_drop(p);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "pgen", verify, { &type_mp, &type_mp, 0 } },
+  { "primep", t_primep, { &type_mp, &type_int, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/pgen");
+  return (0);
+}
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/pgen.h b/math/pgen.h
new file mode 100644 (file)
index 0000000..b103c30
--- /dev/null
@@ -0,0 +1,289 @@
+/* -*-c-*-
+ *
+ * Prime generation glue
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_PGEN_H
+#define CATACOMB_PGEN_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_PFILT_H
+#  include "pfilt.h"
+#endif
+
+#ifndef CATACOMB_RABIN_H
+#  include "rabin.h"
+#endif
+
+/*----- Event handling ----------------------------------------------------*
+ *
+ * Different programs and architectures will want to show progress of prime
+ * searches and similar processes in different ways.  Of course, for simple
+ * searches, it's possible to use the @pfilt@ and @rabin@ functions and
+ * maintain control over the general control flow throughout the search.
+ *
+ * For more complex cases, this sort of control is undesirable.  It's
+ * possible to specify an event handler which is informed in abstract about
+ * the search.  The event handler can also request the search be aborted.
+ */
+
+/* --- Event code constants --- *
+ *
+ * You're allowed to rely on the values of @PGEN_DONE@ and @PGEN_ABORT@.
+ */
+
+enum {
+  PGEN_BEGIN = 1,                      /* Search for value begins */
+  PGEN_TRY,                            /* A new candidate has appeared */
+  PGEN_FAIL,                           /* The candidate failed the test */
+  PGEN_PASS,                           /* The candidate passed a test */
+  PGEN_DONE = 0,                       /* A good value has been found */
+  PGEN_ABORT = -1                      /* The search has been aborted */
+};
+
+/* --- Event information --- *
+ *
+ * Note that the pseudorandom number generator supplied is not
+ * cryptographically strong.
+ */
+
+typedef struct pgen_event {
+  const char *name;                    /* Which quantity is being found */
+  mp *m;                               /* Current value under test */
+  unsigned steps;                      /* Number of candidates left */
+  unsigned tests;                      /* Tests left before passing */
+  grand *r;                            /* Source of random numbers */
+} pgen_event;
+
+/*----- Prime search parameters -------------------------------------------*
+ *
+ * The prime search is parameterized in a large number of ways, although this
+ * isn't so much of a surprise given the different sorts of properties
+ * required from prime numbers in cryptographic applications.
+ *
+ * There are two main things which need to be configured: stepping, and
+ * testing.  (Filtering is done as part of stepping.)
+ *
+ * The functions here provide a toolkit for constructing stepping and testing
+ * routines.  In a lot of cases, the functions can be used directly; in
+ * others, simple bits of glue need be written.
+ *
+ * Two types of functions are defined: steppers and testers, but their
+ * interfaces are substantially similar.  Each is given a request code, a
+ * context block and an event block.  It is meant to update its context and
+ * the event block and return an event code.
+ *
+ * A call with a request of @PGEN_BEGIN@ asks the stepper or tester to
+ * initialize itself using the information in its event block and context.  A
+ * return of @PGEN_FAIL@ reports an immediate failure; @PGEN_ABORT@ reports a
+ * fatal problem; @PGEN_DONE@ reports immediate success.  @PGEN_TRY@ reports
+ * successful initialization and requests test iterations.
+ *
+ * A call to a stepper with a request of @PGEN_TRY@ asks it to step to the
+ * next possible candidate, replacing the value @m@ in the event block with
+ * the new candidate.  A call to a tester with a request of @PGEN_TRY@
+ * runs one pass of the test.  It should return @PGEN_FAIL@ to report a
+ * failure, @PGEN_PASS@ to report a success and request another iteration,
+ * @PGEN_DONE@ to report final acceptance and @PGEN_ABORT@ to terminate the
+ * search unsuccessfully.  Note that even if the search is aborted, a
+ * shutdown request is still made.
+ *
+ * A call with a request of @PGEN_DONE@ closes down the stepper or tester.
+ * After a successful initialization (i.e., a return of something other than
+ * @PGEN_ABORT@), a shutdown call is guaranteed.  The return code is ignored.
+ */
+
+typedef int pgen_proc(int /*rq*/, pgen_event */*ev*/, void */*p*/);
+
+/*----- Simple handler functions ------------------------------------------*/
+
+/* --- @pgen_filter@ --- *
+ *
+ * A prime generation context contains the information required for the
+ * simple prime filter and tester presented here.
+ */
+
+typedef struct pgen_filterctx {
+  unsigned step;                       /* Step size (set by client) */
+  pfilt f;                             /* The rapid prime filter */
+} pgen_filterctx;
+
+extern pgen_proc pgen_filter;
+
+/* --- @pgen_jump@ --- *
+ *
+ * Similar to the standard @pgen_filter@, but jumps in large steps rather
+ * than small ones.
+ */
+
+typedef struct pgen_jumpctx {
+  const pfilt *j;
+  pfilt f;
+} pgen_jumpctx;
+
+extern pgen_proc pgen_jump;
+
+/* --- @pgen_test@ --- *
+ *
+ * Runs the Rabin-Miller primality test.  The context block is simply a
+ * @rabin@ context.
+ */
+
+extern pgen_proc pgen_test;
+
+/*----- Simultaneous primality checking -----------------------------------*/
+
+typedef struct pgen_simulprime {
+  mp *mul, *add;                       /* Arguments from the client */
+  unsigned f;                          /* Flags, set by client, changed */
+#define PGENF_KEEP 1u                  /*   Keep this prime's value */
+#define PGENF_JUMP 8u                  /*   Use jump table, not stepping */
+  pfilt p;                             /* This prime's filter */
+  rabin r;                             /* Rabin testing context */
+  union {
+    mpw step;                          /* The simple step to use */
+    pfilt *jump;                       /* The jump to move by */
+    mp *x;                             /* The result, if wanted */
+  } u;
+} pgen_simulprime;
+
+typedef struct pgen_simulctx {
+  pgen_simulprime *v;                  /* Vector of related primes */
+  unsigned n;                          /* Size of the vector */
+  mp *step;                            /* Basic stepping value */
+} pgen_simulctx;
+
+/* --- @pgen_simulstep@ --- *
+ *
+ * Step a collection of numbers simultaneously.
+ */
+
+extern pgen_proc pgen_simulstep;
+
+/* --- @pgen_simultest@ --- *
+ *
+ * Test a collection of numbers simultaneously.
+ */
+
+extern pgen_proc pgen_simultest;
+
+/*----- Miscellaneous steppers and testers --------------------------------*/
+
+typedef struct pgen_gcdstepctx {
+  pfilt p, jp;                         /* Prime filter and step filter */
+  mp *q, *jq;                          /* %$p - 1$%, and a step value*/
+  mp *r;                               /* Other argument for GCD */
+  mp *g;                               /* GCD output (must be inited) */
+  mp *max;                             /* Maximum permissible GCD */
+} pgen_gcdstepctx;
+
+/* --- @pgen_gcdstep@ --- *
+ *
+ * Steps @p@ and @q@, until @p@ has no small factors, and
+ * %$\gcd(p, r) \le max$%.
+ */
+
+extern pgen_proc pgen_gcdstep;
+
+/*----- Standard event handlers -------------------------------------------*/
+
+/* --- @pgen_evspin@ --- *
+ *
+ * Displays a spinning baton to show progress.
+ */
+
+extern pgen_proc pgen_evspin;
+
+/* --- @pgen_ev@ --- *
+ *
+ * Traditional event handler, shows dots for each test.
+ */
+
+extern pgen_proc pgen_ev;
+
+/* --- @pgen_subev@ --- *
+ *
+ * Subsidiary event handler, mainly for Lim-Lee searches and so on.
+ */
+
+extern pgen_proc pgen_subev;
+
+/*----- The main driver ---------------------------------------------------*/
+
+/* --- @pgen@ --- *
+ *
+ * Arguments:  @const char *name@ = name of the value being searched for
+ *             @mp *d@ = destination for resulting integer
+ *             @mp *m@ = start value to pass to stepper
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = context argument for event andler
+ *             @unsigned steps@ = number of steps to take in search
+ *             @pgen_proc *step@ = stepper function to use
+ *             @void *sctx@ = context argument for stepper
+ *             @unsigned tests@ = number of tests to make
+ *             @pgen_proc *test@ = tester function to use
+ *             @void *tctx@ = context argument for tester
+ *
+ * Returns:    The resulting value, or null.
+ *
+ * Use:                A generalized prime-number search skeleton.  Yes, that's a
+ *             scary number of arguments.
+ */
+
+extern mp *pgen(const char */*name*/, mp */*d*/, mp */*m*/,
+               pgen_proc */*event*/, void */*ectx*/,
+               unsigned /*steps*/, pgen_proc */*step*/, void */*sctx*/,
+               unsigned /*tests*/, pgen_proc */*test*/, void */*tctx*/);
+
+/* --- @pgen_primep@ --- *
+ *
+ * Arguments:  @mp *p@ = a number to check
+ *             @grand *gr@ = a random number source
+ *
+ * Returns:    Nonzero if @p@ is really prime.
+ */
+
+extern int pgen_primep(mp */*p*/, grand */*gr*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/prim.c b/math/prim.c
new file mode 100644 (file)
index 0000000..0003122
--- /dev/null
@@ -0,0 +1,107 @@
+/* -*-c-*-
+ *
+ * Finding primitive elements
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpint.h"
+#include "mpmont.h"
+#include "mprand.h"
+#include "pgen.h"
+#include "prim.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @prim_test@ --- */
+
+int prim_test(int rq, pgen_event *ev, void *p)
+{
+  prim_ctx *c = p;
+  int rc = rq;
+
+  switch (rq) {
+    case PGEN_BEGIN:
+      return (PGEN_TRY);
+    case PGEN_TRY: {
+      mp *x;
+      rc = PGEN_FAIL;
+
+      if (!c->exp)
+       x = mp_copy(ev->m);
+      else {
+       x = mpmont_exp(&c->mm, MP_NEW, ev->m, c->exp);
+       if (MP_EQ(x, MP_ONE))
+         goto done;
+      }
+      if (c->n == 0)
+       goto ok;
+      else {
+       size_t n = c->n;
+       mp **f = c->f;
+       mp *y = MP_NEW;
+       while (n) {
+         y = mpmont_exp(&c->mm, y, x, *f);
+         if (MP_EQ(y, MP_ONE)) {
+           mp_drop(y);
+           goto done;
+         }
+         n--; f++;
+       }
+       mp_drop(y);
+      }
+    ok:
+      rc = PGEN_DONE;
+      mp_drop(ev->m);
+      ev->m = x;
+      break;
+    done:
+      mp_drop(x);
+    } break;
+  }
+
+  return (rc);
+}
+
+/* --- Trivial stepping functions -----------------------------------------*/
+
+/* --- @prim_step@ --- */
+
+int prim_step(int rq, pgen_event *ev, void *p)
+{
+  unsigned *i = p;
+  switch (rq) {
+    case PGEN_BEGIN:
+    case PGEN_TRY:
+      if (*i >= NPRIME)
+       return PGEN_FAIL;
+      ev->m = mp_fromint(ev->m, primetab[(*i)++]);
+      return (PGEN_TRY);
+  }
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/prim.h b/math/prim.h
new file mode 100644 (file)
index 0000000..4b3dff3
--- /dev/null
@@ -0,0 +1,89 @@
+/* -*-c-*-
+ *
+ * Finding primitive elements
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_PRIM_H
+#define CATACOMB_PRIM_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_MPMONT_H
+#  include "mpmont.h"
+#endif
+
+#ifndef CATACOMB_PGEN_H
+#  include "pgen.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- @prim_ctx@ --- *
+ *
+ * All fields must be configured by the client.  Set @n@ to zero to discover
+ * generators of the subgroup of order %$m / f$%.
+ *
+ * Let %$p = \prod q_i + 1$% be a prime number.  In order to find an element
+ * %$g$% with order %$o$%, we choose elements %$h_j$% from %$\gf{p}^*$%,
+ * compute $%g_j = h_j^{p/o}$%, rejecting %$h_j$% where %$g_j = 1$%, and then
+ * for each proper prime factor %$q_i$% of %$p/o$% we check that
+ * %$g^{f_i} \ne 1$%, where the %$f_i$% are cofactors of the %$q_i$%
+ * (%$f_i q_i = p/o$%).
+ */
+
+typedef struct prim_ctx {
+  mpmont mm;                           /* Montgomery context for modulus */
+  mp *exp;                             /* Exponent (%$p/o$%; may be zero) */
+  size_t n;                            /* Number of cofactors */
+  mp **f;                              /* Array of cofactors */
+} prim_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @prim_test@ --- */
+
+extern pgen_proc prim_test;
+
+/* --- @prim_step@ --- */
+
+extern pgen_proc prim_step;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/primeiter.c b/math/primeiter.c
new file mode 100644 (file)
index 0000000..463fc47
--- /dev/null
@@ -0,0 +1,254 @@
+/* -*-c-*-
+ *
+ * Iterate over small primes efficiently
+ *
+ * (c) 2007 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fibrand.h"
+#include "mp.h"
+#include "pgen.h"
+#include "primeiter.h"
+#include "primetab.h"
+#include "wheel.h"
+
+/*----- Theory ------------------------------------------------------------*
+ *
+ * For small primes, we can just pluck them out of the small primes table.
+ * For larger primes, we can test them individually, or build a sieve or
+ * something, but since we don't know when to stop, that could be tricky.
+ *
+ * We've built a `wheel', as follows.  Let %$m$% be the product of the first
+ * %$n$% primes.  There are %$\phi(m)$% integers %$n_i$%, with %$0 < n_i <
+ * m$% coprime to %$m$%, and any integer %$j > n$% must be congruent to some
+ * %$n_i$% modulo %$m$%.  The wheel itself doesn't list the %$n_i$%, but
+ * rather the differences %$\delta_i = n_i - n_{i-1}$% (wrapping around
+ * appropriately at the ends), so you can just add simple offsets to step
+ * onwards.  The wheel assumes you start at 1 and move on round.
+ */
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @wheelsync@ --- *
+ *
+ * Arguments:  @primeiter *pi@ = iterator to synchronize
+ *             @mp *where@ = value to synchronize
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets up the wheel index to match the given integer.  After
+ *             this, we can step along the wheel to find candidate primes.
+ */
+
+static void wheelsync(primeiter *pi, mp *where)
+{
+  mpw w;
+  mp t;
+  mpw rr;
+  mp *r = MP_NEW;
+  unsigned i, n;
+
+  w = WHEELMOD;
+  mp_build(&t, &w, &w + 1);
+  mp_div(0, &r, where, &t);
+  rr = MP_ZEROP(r) ? 0 : r->v[0];
+
+  for (i = 0, n = 1; rr > n; n += wheel[i], i++);
+  w = n - rr;
+  pi->p = mp_add(MP_NEW, where, &t);
+  pi->i = i;
+  pi->r = fibrand_create(0);
+  MP_DROP(r);
+}
+
+/* --- @primeiter_create@ --- *
+ *
+ * Arguments:  @primeiter *pi@ = pointer to an iterator structure
+ *             @mp *start@ = where to start
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a prime iterator.  The first output will be the
+ *             smallest prime not less than @start@.
+ */
+
+void primeiter_create(primeiter *pi, mp *start)
+{
+  mpw n;
+  unsigned l, h, m;
+
+  if (!start || MP_CMP(start, <=, MP_TWO))
+    start = MP_TWO;
+
+  if (MP_LEN(start) <= 1) {
+    n = start->v[0];
+    if (n <= MAXPRIME) {
+      l = 0;
+      h = NPRIME;
+      for (;;) {
+       m = l + (h - l)/2;
+       if (primetab[m] == n) break;
+       else if (m == l) { m++; break; }
+       else if (primetab[m] < n) l = m;
+       else h = m;
+      }
+      pi->i = m;
+      pi->mode = PIMODE_PTAB;
+      mp_build(&pi->pp, &pi->w, &pi->w + 1);
+      pi->p = &pi->pp;
+      return;
+    }
+  }
+
+  wheelsync(pi, start);
+  pi->mode = PIMODE_STALL;
+}
+
+/* --- @primeiter_destroy@ --- *
+ *
+ * Arguments:  @primeiter *pi@ = pointer to iterator structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees up an iterator structure when it's no longer wanted.
+ */
+
+void primeiter_destroy(primeiter *pi)
+{
+  switch (pi->mode) {
+    case PIMODE_PTAB:
+      break;
+    case PIMODE_STALL:
+    case PIMODE_WHEEL:
+      MP_DROP(pi->p);
+      GR_DESTROY(pi->r);
+      break;
+    default:
+      abort();
+  }
+}
+
+/* --- @primeiter_next@ --- *
+ *
+ * Arguments:  @primeiter *pi@ = pointer to an iterator structure
+ *             @mp *d@ = fake destination
+ *
+ * Returns:    The next prime number from the iterator.
+ *
+ * Use:                Returns a new prime number.
+ */
+
+mp *primeiter_next(primeiter *pi, mp *d)
+{
+  mp *p;
+
+  switch (pi->mode) {
+    case PIMODE_PTAB:
+      pi->w = primetab[pi->i++];
+      if (pi->i >= NPRIME) {
+       wheelsync(pi, pi->p);
+       pi->mode = PIMODE_WHEEL;
+      }
+      p = MP_COPY(pi->p);
+      MP_SPLIT(p);
+      break;
+    case PIMODE_STALL:
+      pi->mode = PIMODE_WHEEL;
+      goto loop;
+    case PIMODE_WHEEL:
+      do {
+       MP_DEST(pi->p, MP_LEN(pi->p) + 1, pi->p->f);
+       MPX_UADDN(pi->p->v, pi->p->vl, wheel[pi->i++]);
+       MP_SHRINK(pi->p);
+       if (pi->i >= WHEELN) pi->i = 0;
+      loop:;
+      } while (!pgen_primep(pi->p, pi->r));
+      p = MP_COPY(pi->p);
+      break;
+    default:
+      abort();
+  }
+  if (d) MP_DROP(d);
+  return (p);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/macros.h>
+#include <mLib/testrig.h>
+
+static int test(dstr *v)
+{
+  mp *start = *(mp **)v[0].buf;
+  mp *pp[5], *ret[5];
+  int i;
+  primeiter pi;
+  int ok = 1;
+
+  for (i = 0; i < N(pp); i++)
+    pp[i] = *(mp **)v[i + 1].buf;
+  primeiter_create(&pi, start);
+  for (i = 0; i < N(pp); i++) {
+    ret[i] = primeiter_next(&pi, MP_NEW);
+    if (!MP_EQ(ret[i], pp[i])) ok = 0;
+  }
+  if (!ok) {
+    fprintf(stderr, "\n*** primeiter test failure:\n***   start = ");
+    mp_writefile(start, stderr, 10);
+    for (i = 0; i < N(pp); i++) {
+      fprintf(stderr, "\n***   p[%d] = ", i);
+      mp_writefile(ret[i], stderr, 10);
+      fprintf(stderr, " %s ", MP_EQ(ret[i], pp[i]) ? "==" : "!=");
+      mp_writefile(pp[i], stderr, 10);
+    }
+    fputc('\n', stderr);
+  }
+  for (i = 0; i < N(pp); i++) {
+    MP_DROP(pp[i]);
+    MP_DROP(ret[i]);
+  }
+  primeiter_destroy(&pi);
+  MP_DROP(start);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "primeiter", test,
+    { &type_mp,  &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, } },
+  { 0 }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, tests, SRCDIR "/t/pgen");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from primeiter.h
rename to math/primeiter.h
diff --git a/math/ptab.h b/math/ptab.h
new file mode 100644 (file)
index 0000000..4ddeeb1
--- /dev/null
@@ -0,0 +1,62 @@
+/* -*-c-*-
+ *
+ * Table of standard prime groups
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_PTAB_H
+#define CATACOMB_PTAB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct pdata {
+  mp p;                                        /* The modulus */
+  mp q;                                        /* The group order */
+  mp g;                                        /* The generator */
+} pdata;
+
+typedef struct pentry {
+  const char *name;
+  pdata *data;
+} pentry;
+
+/*----- Global variables --------------------------------------------------*/
+
+extern const pentry ptab[];
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/ptab.in b/math/ptab.in
new file mode 100644 (file)
index 0000000..162d0c9
--- /dev/null
@@ -0,0 +1,217 @@
+# Standard prime groups
+
+#----- Groups from Oakley (RFC2412) -----------------------------------------
+
+group oakley768
+  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff
+  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff
+  g 2
+
+group oakley1024
+  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff
+  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f67329c0ffffffffffffffff
+  g 2
+
+group oakley1536
+  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff
+  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba36046511b993ffffffffffffffff
+  g 2
+
+#----- Groups from RFC3526 --------------------------------------------------
+
+group oakley2048
+  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff
+  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba36046511b993ffffffffffffffff
+  g 2
+
+group oakley3072
+  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff
+  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549d69657fffffffffffffff
+  g 2
+
+group oakley4096
+  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff
+  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0318ccffffffffffffffff
+  g 2
+
+group oakley6144
+  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff
+  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f617794b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36e620127fffffffffffffff
+  g 2
+
+group oakley8192
+  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff
+  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f617794b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36df08acba51c937897f72f21c3bbe5b54996fc66c5f626839dc98dd1de4195b46cee9803a0fd3dfc57e23f692bb7b49b5d212331d55b1ce2d727ab41a11da3a15f8e4bc11c78b65f1ceb296f1fedc5f7e42456c911117025201be0389f5abd40d11f8639a39fe3236751835a5e5e44317c1c2eefd4ea5bfd16043f43cb41981f6adee9d03159e7ad9d13c53369509fc1fa27c16ef9887703a55b51b22cbf44cd012aee0b2798e628423428efcd5a40caef6bf50d8ea885ebf73a6b9fd79b5e18f67d1341ac8237a75c3cfc92004a1c5a40e366bc44d00176af71c15e48c86d37e013723caac7223ab3bf4d54f1828713b2b4a6fe40fab74405cb738b064c06ecc76e9efffffffffffffffff
+  g 2
+
+#----- Lim-Lee groups generated by hand -------------------------------------
+#
+# I generated these using utils/genpgroups.  It took a rather long time.
+
+# --- catacomb-ll-128-512 ---
+#
+# keyid = 3db35e07
+# seed = PbNeB774QFw0xJvLDEn3bUx6hJw=
+# fingerprint = fb47344e-9bfcd0e-e986c772-48edc231-861cb5fb
+
+group catacomb-ll-128-512
+  p 9749248307666198278625282069621029423614285873414870747628872221551255623823205551438908261067675576856742534707535779666498916029617598868013496631088223
+  q 271499434142083095503643289076442321059
+  g 572938290446952786361356734705597783874760982871814854106633812061613480394314443743197177265739535298268868306029572450131746639710824513310586144336987
+#:factor 271499434142083095503643289076442321059
+#:factor 251174382438405784142034780246853570853
+#:factor 259658226261043076610234546745792177763
+#:factor 275292752516630714214627215608643381611
+
+# --- catacomb-ll-160-1024 ---
+#
+# keyid = 98f62cc8
+# seed = mPYsyKXF6PoNTkl5uZE64gKEf20=
+# fingerprint = 6ab1f087-5614561c-5d388443-b1f02eac-38248fe6
+
+group catacomb-ll-160-1024
+  p 69775951038073580217048751187698556149910661999359201823421066000439190288124938297116840422332973903349265313226189724474672148172906743149961449018143681316055777549225333684417216672046201528908637006946721694566251047975893301628540057123962444434130461052652526277961662241061299058137499738575071867183
+  q 741802303617786660769426556982216255271020758647
+  g 24031880137812767104513348688448999056754549625670167617628008814539123937598464069755252337842705625768270002772600104095116713027947418314704258588569425678035630653993833866258334547988915311887541947589468379164053328339235797437698686107421712042993209960764868024283667188725341401853595169622553906137
+#:factor 741802303617786660769426556982216255271020758647
+#:factor 1436145082693042410533997633791272917636904431479
+#:factor 1053371763883815722032496338163704236230178616951
+#:factor 1215995718665420681503927009463070333378310191827
+#:factor 1448192360714741582009673893725822727433041298541
+#:factor 17654251325616983743094122151298023764308424678047987263690296014551
+
+# --- catacomb-ll-192-1536 ---
+#
+# keyid = 7efe5c2c
+# seed = fv5cLMXgGO2voYGTQ5K525Xtf9E=
+# fingerprint = ae9d47b9-e303daa5-9677023d-764b338b-53f03c4e
+
+group catacomb-ll-192-1536
+  p 271163844483056215974969265313967454661676256266511940924304321373021958106999031565631233996938091358447023677706317722695337026864685384345663120704730255257202847527192911265950638087504732115876440997750045081880863038141607482083211725689822517898206821836185159703555104632867971994304356879518337226475272092974597967943366038800089283400183985773753490774687966167193456249452974119129018696293050595073100284829925638444204379135326678813960293114732959
+  q 3265942811645946563242629602041107481841853511350443184197
+  g 216185318413290469366405581500018842001794769819261149347277739848511992115259660705539911431188902360038442052949313200461450240469139278699145891151900315976816130082310914969548643710915174155521909660265659882527478738966654443422798664706090262812802264667406360583964285545011889176706871228354070760597031811706100156760441692822039947686308668974200473374152063439445019790248156400822413220452383963514887723177708643429977392740800552485785350546387634
+#:factor 3265942811645946563242629602041107481841853511350443184197
+#:factor 4203281750074745560664516895168522022509720946720609480259
+#:factor 5008750505930402098755083797499946811957880698185704286517
+#:factor 5437815993255342021982036827752826453901545498474314278259
+#:factor 3856915640937851719940744630159301063173277801391043813291
+#:factor 6054082443893470116716978196535076127652382149483455623509
+#:factor 4527580176039500642864307604310793340910014541817043735439
+#:factor 3430016280837410693307976287901159907499384818919106315351
+
+# --- catacomb-ll-224-2048 ---
+#
+# keyid = e2824699
+# seed = 4oJGmZFnxNgns4UExrPWJXJDQYY=
+# fingerprint = 5b3631f1-f388bca-554c1df1-3774fee9-cd46747c
+
+group catacomb-ll-224-2048
+  p 3113844893182469436423817481922802329154474934213986369565700235348098440269001480103560846535113493144522446351379349356211385191632945710341444495577638160076546999114567117877732507854868463110804063964212132228977417231690350182211790515961798314443291574015832300281633156990779527484905381392680532643288437519954295652416759988107781937077836044809781096660654460207183523575424301901443740349094152501352983589721328225459512044516684078781305909247963063040562914192132284695886353707336911126238203292592145886841905764429235683487108646920559740458905874135798982283901137307047131586817745416509850061963
+  q 18749474022970964965792505501868745784157349746475161167020805104727
+  g 1018599075350815414286530684646967825916370747779291600517646276513566802791874935821816063520500873842729343817973803895278528701892043836290994612088035311589900475691176610297248816678701309707300454643927577686742011376684351525767933769045470869869290385506108485669189456183746644562327923152628958690988304340204333382573235567919004822811151873260798098816157572583867825397056414990908538555039226503662448878536483457742053639607062687899859473980884756925814541061907505350254827583321961201313954703462583072253230646667723110441238195386606218014837851495231172030604130800244334912972408067680590879980
+#:factor 18749474022970964965792505501868745784157349746475161167020805104727
+#:factor 26459793266106143518700371316953986751950547842631163615799385478033
+#:factor 23385205652191135191327958583020476187937251160152256504448581299573
+#:factor 17287418736358368314036906794523064561326146990020019216549187737103
+#:factor 16800288948485454351848726052252844830400274721321174607061304165751
+#:factor 14817124042645057452868896146782513905071983176482538876644503596827
+#:factor 24089412810223523640445605527780074479098235298741910558499656689361
+#:factor 18919386933765812741111621380736732547216460099506859126765656541087
+#:factor 68423637472150676252123752731403397187923476268634988015857219241126016100451
+
+# --- catacomb-ll-256-3072 ---
+#
+# keyid = e6a15ce1
+# seed = 5qFc4fL01gTjyvNMZH5BvwETZco=
+# fingerprint = 904df4e7-74941baa-40d589c8-fecad932-2b3b7c8d
+
+group catacomb-ll-256-3072
+  p 635937223373484887991140560420669529960468634418212194527199243018802509220923645480563049852948379631872315326364181219863391536284352632127476573990043945919830000350264391397346335414535975554209931971547284463207275833747975949070870172306582775948778222246682185331862354083029804303222690541851195763223409045953191584611635790362191424339883737168342809190665629632289528654983812904611647818546832860081714363504512892885600580448186423533085059295328609139522690627823102925150246378111221377628009667319528150747320084312110336288028683700603719073769314245952464113622780032073817850603131463761017417455806035107984621889773217138911836476354442521466189648565925624512100087534918369360007697883847802211797655614684090408428715299537509886614640500137409891381649298835563011151796284848165977247286439820050405175697064122759870661294968492275655767983096727976056361878300352234381528837008128941375285251387
+  q 89271282791461757245617785540129155142212959423277129581512553253419075634703
+  g 293025651734044707050351995205142657657141955131408425452312245943331353163428637443799381119408990271553007202915223601376791534187122912295000993316207089139736477148501917083144416322685925261624358336253378688806309805096283386698409139605996997308008266491782991490291726095895573563845937760385377670846794792328581579165150512160132493375389995617711312966986681865792948443127326586291576561351005982500369077653940283008076332825908419690031303502192009860824429031526378047535596212801179578879818504990773143072529887215206211778546705082334239130823956177702608427222251531070457604183947814624087379251368161182770323100074409926426428526795865215674068539423364010352920515052672366811052717283396264950182005583498061313136436293898863077084485762289185337928869086731032780517039420605615746259170222257438835029958473402842467194409561307509136616954789698181252705567549441508247668319257495617674881793988
+#:factor 89271282791461757245617785540129155142212959423277129581512553253419075634703
+#:factor 85831054040144766435760746678768685031101307134949905606966042252247846736739
+#:factor 106974241938861083915762659525277908624697359844432666343676471334975764276049
+#:factor 74188558205228235051388929541366735789893711666871143431413381703129034070571
+#:factor 64157908398727096384500697645883202842334928055247546726538359334678953374533
+#:factor 91888021786522811643506031866522514605588426773858897142365239694153824388723
+#:factor 86202112980065410413258705060295663522206392211838714986438313175672540034679
+#:factor 101718718485667336124248700072690338405530751717394437871691123315096947983183
+#:factor 86666452227843804499517643692692014159268339780015078349842908985056208435853
+#:factor 107755126504421076829573915729759110231793946298489260169446357640494497518059
+#:factor 106001951238340530179427922980522671485637210826387486585015951056665476348869
+#:factor 102183593360154313236939029184315018977616435836107396944951781361526011480879
+
+# --- catacomb-ll-384-7680 ---
+#
+# keyid = 5269085d
+# seed = UmkIXe0NUh9EHPOO8u8wF8mhLQE=
+# fingerprint = 79071929-98fc59d-90b7743e-c5c2b654-9bb79c2f
+
+group catacomb-ll-384-7680
+  p 216559231449171871041190135626382624797124950735238103903411263023444445882521628396323446917201544947387362748232352479621010825720892522010264595137021526116731147020276163999389935515909942333859243831227670403913428432731504427389273023004939424753052775358161721558889434984752937404659922107755872908503276779890720154023419646466364753857461405783464469564625360217138090672724105361675896756808274354930058114085554600822147968649870032508764648998263671769796991884663568970203225077040350146289614179408735323764473153776149414398483161820946251418283039309221276673125231280207218356527486085198155052448482264858753938528034551335541575510835605019724293894867922725429018142837363943168309374088743910487619039647758175469460668571266467909654776838430687432194443218576000354284573578578313918222270250431668826898042163427173702446261012188950489694384130788197898956349943432660613123480611964086340909829616693038723512697569973817087806925553170590595578662024721424212829104524679861074838515062614572669868082762235959143570965134389478420007029121452023331460602894158087970348076496609174310151629106271427215947168306439928345126945165118709319486831988505313790613950433545275492703644799196726129007271379101141097250063655345163597099147393517021524375283410477077887674889864364373504345856902602031627659096612965600880097793678105801528551273968273016116586602655943987294387646704481664853571904789295943497201543689680443816576374462034616478062083674538453821741357423160686683957869164976227205380757021506255070600142017516211729170052461889059117212201165174680435195480761191462787291840078314124775690821420091760461597315155088442641783854597704388729214697745034805817520117506496545607796864049406793174516710815917428415700817370248228453077064519820749224220930454265603643316849024708084260878037824529368824330161019279087245044637182254878850971615729695143996520927935652887799292993748602455597137301552603377186175439256163850872771856775561289081476860168359000521640192117573827877302113899996287468260783657370603418752653187994927154468272901154316379212588059218864942163650290968975838491996852452140839172227541162524444316754170785930872965059072588210184084993896704348797801907146398460530513820150529386362374102968643080903455218783795163739396580563
+  q 33126499307317576797871833023217004335728314922050873541842362900543256622519036793987373377351818708943025119171013
+  g 96859294361547047642162231787698695293269170366381491039992704638487946870512955047635144422727688206850890592577601738386271033615655069759857614095318767501569475658225621379418176050399654722867097565799361229947796756782330159878485797280010527792372818398073347477883450716624241650342576251700830368197267161507895940250335059430229713885285808307538641824823453590259949699610056770268667527819173674245700546468626735701216914339359142650715456068873883323510582206093162545301581421872580614739960541059105320799303366751068487975658774037067271201124075671594347915071804828018801863090776942278748696864666275555399479604564578677796647983816263014540144519577131864786690922226752900095101570448042330169808811588582992274222974333043374060077106932770817928804830739464113061207244668378493315384242428432594357567083170258903374723309088233501818385465347016865045003737737429798873421728939731524368763227995005635265743181878570394577251864081145075962862658667595276249717296728684048617249986325764929873684993115348889870151843083280953797610712542442651569528403369291638278579344023829005801861314384307223035852089456550106858884145475380292972702972023699980804060437666725813022897101316874650121913713231347979141680903702045096621935190730276560295174524297300767314797689155407477601193107232938299830541221417725759368288595613473097104008577963940594171976537149511040148774289702490489315160512871522386217608881824304091006999472822494018964857391111674528315676869116824677355671824612095554583261258648450847127015033139359148253652027620146044628375304786435643476708542206375787159378427699020092463186472971399347599749181816424274424067915825882710114752513444732397713670497772986582958901510359579133132479016445445133604454907255125008080844594331635493230874836372234145675198053154029087315214747182882002718722228763467363382722967777319004806095376893995711476881150741027724250087088999020456989167082293444606242846362570237792721708356293491203816603574491100293039203889820292140596922368098350519693304511861932465759110608906269402554390780611082681465359527185555358515709411662470414648813606479086286524570875988991968332315775966514438221552899748093614170849525785168229994381907745855683962639488177828929551456219770877454135407893035439949325975780350
+#:factor 33126499307317576797871833023217004335728314922050873541842362900543256622519036793987373377351818708943025119171013
+#:factor 39355538213779465581327905402419970362362827155309917911796788256581129259700838386618633466328785307910060598484089
+#:factor 24990988056514685939227489925894893740599480412356885556635114159485308445876939770393364881549529860169928180358751
+#:factor 29710393998736802825004025579677917729092552502321819764111039726208854433428942095508492913578932136133436765710137
+#:factor 30739990822741028562742164007270587796692423847729505877569973917995737943042778723217469119645159801429991709987411
+#:factor 38467104071408925475553899301420008676544897864238119086844380566779548268491996551153519861871328607592273248640063
+#:factor 26249202441547885968346939762119297860863007366370739789532392353072352597721946778221716140197625626869457398407943
+#:factor 35113510884533077462576668870689443131037411172656549819745724383911555364605887073198680214468558440325573744139273
+#:factor 22799521027155572453510717469170377645186972219918245680012037643676230864376926993221681405925996643835629140041553
+#:factor 35237903572957790995889936270089932531166269466107290813994448142778414605138387309936585467385466822473088271031989
+#:factor 27428052831286394078655137717030752972732374814011687175621160166365055343004612251793080304507732432129056200291727
+#:factor 20653805003557030567582482355924457431196786739428479408853799555350943953733271029133593962324338862058432369521581
+#:factor 20826184829221859923080357759745090302065026449606341016497732724141145977802307612276509411486570418197846062995143
+#:factor 26186565771074398017481590713676896769947111595943534554546789381717976098676902111563130714755073678247235508588839
+#:factor 25062273677906610062620640227124848504281876654137470308684277968100792708156285085199790540571827305085913619650939
+#:factor 28620246516918127020366359691491908359742867622666550018522929993024502416569436771205673472786682579926850748107811
+#:factor 37856943506407240881326721106883344091018942980536189030625919515240362253893275735656123073145875668656864714642553
+#:factor 22067087486134964177557541373312161142485654981859077450341811542291069526079170766664489890765256439946132722899891
+#:factor 23098926790257626751285008739153477597734517594763012574497649607286859624287080618144594023194033634778511868647877
+#:factor 29874082012645596638985309976826212131328113612069017684649166404247820505933961130580996098120522635385267888074961
+
+# --- catacomb-ll-512-15360 ---
+#
+# keyid = eb8239f8
+# seed = 64I5+NMQg5J7WZeXPpo7dsXLiAs=
+# fingerprint = c9addb82-dd632399-3dc1de81-40bf1c07-8ca10f5f
+
+group catacomb-ll-512-15360
+  p 267737496760767722068079882470300794033605836807622482067410964171393411520919176256914869964612479175351332823409449521645606004586415623871847948375817498161847543702485018137658512658395575254789459353699345744602369381934625059696198589413369531883820496222659510755499199435844896264025524352060302680951373940575374076136832975200291005032514098640691398905405952695332479714616633295008654736506041813997134163987333741695846413097366684661344684616003601739167823328153896592432168889551779922529269033348086812310042261625165919052730860791202842844956446296689792441147970214424901342118997798159010536443797638756041327664696059380444566468860999953138675880647585649322318597258428498912095373426547986582540102395757192981849426353427220562438871461011279156327503538285028350335365137967747204548916792891345433172565689300894798309981237564346356082832141951952353587270953547648554401212070076679138112680602893278933373210074307452631417834131238872904464712762382727721405307974548332455937227001307804713345124421010621912271858653169426612004330651882144263970965845286327430353225544353979151213153918381850147302137013870443565447267408929820734324527586605299075224612369180273167439366180804630758969753426630886643792237194705165542753979443278245006454216061793688914453452033873682552924255069369382991399006219888447629091144761962816311838278453426744318329244891747907726689490072483441687762777514940810025483492250932938902924371182177616985098416863622505393245791898509271049937545780547703178646787153221220148776603371623990916784487761937997154509142207118563842540149656720890488789518041789234252783231203642923485126118874925205605743388337049290048102619379144553450612454492744292824661671019548713713568495220254740410669480812494122553523238166010275744321977341774600646768663036548131650974040647199495585196626323527740836162430085342052052727637724463434046775500298250476314587684591403987781101547180153540252142742428325763088665202774890061858211471865412555929191623058633649510807447665649697908545538433271811034260583364231115893882106660460362988412359863944207083315791203817813275002751650497247445133621959259165882426036642183903263726738720790482023621515505915532731458799675555130983697925269194130788271555917528320139537585237789448433361057472038619150612530155365282694361060208517945072413778375766282508764808188838406430261098030072276397680381934641479775177012533402001805227189560517281847643477431969193260714721511089510106902236389858739200666246366584470443084819740458839115330024642751710950508392249199171525940200641812690856715538273687610654143705053231753228288281925749573248819830807718047751291456635357252049651851428004843642993442708365926756086784864901619631645046021861362898457472437142021009316121209673296032419273205690055243737394068612057117222448137828274568145532165778912543711623225896980785464025683101674037519994362712933363700839222229325067956938417486554365785132752607665421070796369679950679278370647133471481601224482043380412158088958751348091674065435762606782309017939064656880665108380755999804750464216396676060064634049102602879726529064753147592949810279608808566906092860843406668537037778792512924649747927350781700804454803517161392276648064085521072720776995493746790698252658256127300427299712765912635964190588872362794322452414626926829451697570056145597909237733397993006318713907266282999209757835954408527578538863449022305050578740139814278853085620493082736691092281414370903171187358162080568284465302364244005694005210033241390491480461570699307912480038911233821105644446152512328525805707483171601688919032664561976430006629718308661207667153016502452884195148963125673969191706827403727809879672157011607257925720399770233625156155404482591336975116607711326594730647784392952199755924399936290034962258677008541859799419880022170446493041811273344503041707889648677394173861246482375736320283850849220544488123549088485079584855817373424359266678858651199243166073560382077730099987468377705636637242565948949985751205620857554830109239961545967537041510571588045286127240744618124771659845616409968497542978672000492769104999131872897737410994487787465125717465733543538344980281077012185860886320520255782307357238375948751409954873680258342250057671086544607706855079362474966284884466968233383764211808745671425930931575698296989086335739534025778159969392356967742191929914522690322438276604838230279525053780117636662663017876019549874233270026169569062088907790243918806941605480559016625665402398248013040463246716327424411605332836931485156524858341673845209004633198457099
+  q 10571951456907669779892620647342646690819262609396359690524502534177633120229168340667942575812279188027386527234551758107216468763903236115143427787743501
+  g 128598894907195188417229808251635947329739807715046258519185506584473330204570377688022234101083503575628247088869022751684161661116289139941422707052770784716284088672813457818076409289020116060576402861848262767893027233018967673188177319672220467630868456703363498829958429433052255385200803148036151824908127072135772477213206484282052574102804738136991255543544214210006836913841655431369354618035834267490750490209475650037611036969604510775085809840648347935149597993597050657382149424122551607765060905481452516927446598515527477247171478999535528834297030357374539135945862618225434749983777290822601640168801388457093291990583760394365529485898194260738109655976435021259260994433703250576566622543068851481307975157566559105117105696734982421364733215553702481282493676675415951561410801018648748202526310066348347675957920894052908634114299749835690825285958913309859395516637946391466247723186108045362984213928977339986546180336619120165000686737182828914686039307870836014970214762767616169050313307016785283407848979763838796901889533929991249262241241357085858440003100578599589303213283823231174826022087580289633445725655404503623057795603361275581688344479184031083934546255260431689248986625244613768138643274300512818504921212079442823382330541009102805040432664579664706843475903526712081265964789883073385412340566450530204050902742402634241295067292054198743776821135490852456571373786221834566840691504860631528594003016940806795952907191256706618335919348660172917691296581810487025804834121410117485699086165420315964836248122689453219355409068053887775439819365185836341867035959423656535221657069676936301160422526984733243805036094607065902991385803575050051402498313584896099087939918378394590246964040554542516556529955127714323667109459918696040305338316628605973670322139489914621903381403168134305230387553206034949296665589019458435333656497975595505186840554679289490725712215379119708936656398805481443817609780446044759428279250269061044353577054755809478942400511447476504959503019924384501854940670343756700595741830432409860516378561836547983052719529231317929703619794317736666240984610506873930809661048521360303804091987776920298335472932445807825891843426486417538296088228895526448505937443508396033850769937257926518277775854316505029339507246170910597358345642816471561799639718384521695469006324992746905242127842686811730217295508863843618253667094515294426385046337302700840651870607339402514793220932482394311605909804968180513732290422195401488734272875219573971965851758260974945420620612963750578280530090049561109078297429042230921153112538935821627493853510065306244811588574295137834903557863723543417221594934011392570967713979066781470665113263579679078346927299350593423807794432345965954214411279192997560913500420482135209761870894770590428753377060355446520714577823849327411455211803153798853005451969647921330963739815383804967938950844708859220970746343764387380686978388124365668599015606571832777646186264005031394838487124138566127931419400765659300590631175744824203747372760896426041038824093171455170878742081716134501047540584551546098074082811645710233649110893608312835114875022232159365133137870471783950558791394747886849817239478618258433146217414467845273035067690658728958244690182678308246002614307639728716544214919926387449699076757255860035522872191741413862595318802625699582434142963070125555096411118677017567085204173949296857347553686296332447084040218420742023614270285859547357310153777066869597179554114216347704995773693933927290606278271631839500986041846119745101489053876898923820486679517034985529967206488771012442386273647914758788794352696546007225147463040960836917540476556158171204978341050270842436674153236983839541594662370682859252061101201529771658391958638069866925173982823135401442054529882771497178435812973944610940759337374490667655762675502138898683030596178493879840530527200986100162672072577140966652435656059897085134772326082774218777784721364471952331014224241827859689552691557210912017591834455185827870287610792949837996937421382409243563221525985357912277040622211893182331275112628740300448802121194783069108322399073099060064264166221152635853834406853391568903009131371873111346754163371271208724745835028574196362705248110621990890004232459546556494832519339269358637289654972986665902221815201810894863582325166306449650465453223955176919686048223394344108072515484536428726902347665256053780647893633252440024422896973060032376625419596170725316577542832012274755089837231069989343909974684844834831911679673118788567527167638795212119760473587068197787346864147296908951760670987133395
+#:factor 10571951456907669779892620647342646690819262609396359690524502534177633120229168340667942575812279188027386527234551758107216468763903236115143427787743501
+#:factor 9012440645643314246834973626922261248430582884321541587438489180023988737512032104254581442848613136311423618140795155753411152808972231131191495364696113
+#:factor 11664407479888990184202139277551028676651013424643181979060212470678705307128063234525963058666093887020686441365922823734852909082402446828730382752979229
+#:factor 9087876611156307298284101521955646383324933273215705601366986444355710006473522774817841755272381080750837076062838195845188516807677339637355892566997161
+#:factor 7850875653648084112022472229380028253695299668265516016947697170686003077850514907765524197019907612330445487029463301633628025237963893050671557196181037
+#:factor 9811668747595937862696556986818901047696541620978343479470960055182987731849807766456487932153408355304918692734270804755894967739728440775732045253975867
+#:factor 6850528828310882434413759447618080765577150578105428774266564959349750426580886713871673166366380181300391220234049862529092166014652885149727426581950889
+#:factor 6821638102376526854453397172384749542254164092866952888824098621712040405559147454526516007481215285840029382069182522430838260284493396455708010177523951
+#:factor 9678671090017306504471193471606002503207329774194080688795341865275315066168913972420992866933767238945244749299859823721414058505077146271463652017042439
+#:factor 11393931156044806890317196442201195583808258792085050704419049073069764825659064050709401048990965128349659629815212528487569661791997378607235211682046767
+#:factor 9017010040179947675396805634091838536572796142622751259821087175550548949037522734269840576513891007984351108919567391192649737362028379518075599077332061
+#:factor 8471151817163912127252174076707115691748601873337141861143247343372659043906393812132481208054508793108003038614600545971718635646265794386795278691754067
+#:factor 13197493938382376428309109637837242582358905975783852842417135134626200360303237020546312789639222633029539785097700295596040150049781404432593082545583687
+#:factor 8575974070132361564362415034026161716899096825228901868850832979622821929082521380113628505749265007300639809003377137159593961387754096563405572654530453
+#:factor 10685309091824418682668636366538457951831463604934567645475353414106697701363236027779367582469465499678424648685247868794321185827903765405464064983847047
+#:factor 7832579167103862778682606390694147440819353518240318233355101493037014682039100415001767021498559727856779744520541030712369584582339760294936511514528613
+#:factor 11443136038500921044854720404653372565248054144656073888671297768218410197327711069816877279851418893039887799451033119855767890079711768713385653679344477
+#:factor 11688409215583921110956357044321797822832780718093563289058981511879157867538826225803418406379935887495839460956831051786990678735417867002006878510530001
+#:factor 8269373232168928931276034385529570570419130675409379232099124396037402056853784630410470739109999093193671624909979089535332341276117302614326085797220209
+#:factor 9186395703395988275207810642702730047142932136743815395858445937000755684133671310159954341948067614705752787518132853542049279332346920436340054839993081
+#:factor 6795425485592182949378541037739159131046423659599522629955532628051588695375698396588579193598504741404656736703919260744390720003440892800061391975968543
+#:factor 10396118888753141861444655191592919753341123585411878553552147287212817173935858961195926696707128865851883589958560492545922923504442555855283863684690883
+#:factor 9200414943820306382018413241324240995480578531923453792659897506893121059804164387167396258851931504929883516095987516319887977740512884087194394964391023
+#:factor 12530634260640146540037552613265173527563597551474945252217132553909981324169848692185513076985582524700624840690045385961239986165286808674599194021249909
+#:factor 11777196311833624813129143516165715650218942159782423895657055945748378658698548936802659687190537166673298770529607439929019151210938035218664232208577273
+#:factor 7348262210091125168844276092746402631926760996426639974638799774896265368458530624040379440531440039323922186709965290812433008147988187233036235954446539
+#:factor 7495895476596043082228459599736776072884975040533651752897223545444099013720437774241963953093854938504409948988231217421899198126781802901186687835439671
+#:factor 7552446094981741253426497231778914956993354256770700433779133501020398264257537810327407638749096379083785811976115762275583243733103646262540268854635459
+#:factor 11876032185719044257059947481606348236079583968867505900797840767914468036111126560459281957584518925180041310466390015937147792402479266081314053413722009
+#:factor 9583540052593144013269177059658457027998433819569867982260511279574493019496581755069425156501941108339618548765191994601041609651011729970172839875903479
+
+#----- That's all, folks ----------------------------------------------------
diff --git a/math/qdparse.c b/math/qdparse.c
new file mode 100644 (file)
index 0000000..217cc62
--- /dev/null
@@ -0,0 +1,141 @@
+/* -*-c-*-
+ *
+ * Quick-and-dirty parser
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <ctype.h>
+#include <string.h>
+
+#include "qdparse.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @qd_skipspc@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *
+ * Returns:    ---
+ *
+ * Use:                Skips spaces in the string.  No errors.
+ */
+
+void qd_skipspc(qd_parse *qd)
+{
+  while (isspace((unsigned char)*qd->p))
+    qd->p++;
+}
+
+/* --- @qd_delim@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *             @int ch@ = character to compare with
+ *
+ * Returns:    Nonzero if it was, zero if it wasn't.
+ *
+ * Use:                Checks the next (non-whitespace) character is what we
+ *             expect.  If it is, the character is eaten; otherwise it's no
+ *             big deal.
+ */
+
+int qd_delim(qd_parse *qd, int ch)
+{
+  qd_skipspc(qd);
+  if (*qd->p != ch)
+    return (0);
+  qd->p++;
+  return (1);
+}
+
+/* --- @qd_enum@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *             @const char *e@ = list of enum strings, space separated
+ *
+ * Returns:    Index of the string matched, or @-1@.
+ *
+ * Use:                Matches a keyword.
+ */
+
+int qd_enum(qd_parse *qd, const char *e)
+{
+  size_t n;
+  int i = 0;
+
+  qd_skipspc(qd);
+  for (;;) {
+    e += strspn(e, ", ");
+    if (!*e) break;
+    n = strcspn(e, ", ");
+    if (strncmp(qd->p, e, n) == 0 && !isalnum((unsigned char)qd->p[n])) {
+      qd->p += n;
+      return (i);
+    }
+    i++; e += n;
+  }
+  qd->e = "unrecognized keyword";
+  return (-1);
+}
+
+/* --- @qd_getmp@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *
+ * Returns:    The integer extracted, or null.
+ *
+ * Use:                Parses a multiprecision integer from a string.
+ */
+
+mp *qd_getmp(qd_parse *qd)
+{
+  char *q;
+  mp *m;
+
+  qd_skipspc(qd);
+  m = mp_readstring(MP_NEW, qd->p, &q, 0);
+  if (m && !isalnum((unsigned char)*q))
+    qd->p = q;
+  else {
+    mp_drop(m);
+    qd->e = "bad number";
+  }
+  return (m);
+}
+
+/* --- @qd_eofp@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *
+ * Returns:    Nonzero if at EOF, zero otherwise.
+ */
+
+int qd_eofp(qd_parse *qd)
+{
+  qd_skipspc(qd);
+  return (!*qd->p);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/qdparse.h b/math/qdparse.h
new file mode 100644 (file)
index 0000000..9e56b6b
--- /dev/null
@@ -0,0 +1,113 @@
+/* -*-c-*-
+ *
+ * Quick-and-dirty parser
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_QDPARSE_H
+#define CATACOMB_QDPARSE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct qd_parse {
+  const char *p;                       /* Where we are right now */
+  const char *e;                       /* Error string (output) */
+} qd_parse;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @qd_skipspc@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *
+ * Returns:    ---
+ *
+ * Use:                Skips spaces in the string.  No errors.
+ */
+
+extern void qd_skipspc(qd_parse */*qd*/);
+
+/* --- @qd_delim@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *             @int ch@ = character to compare with
+ *
+ * Returns:    Nonzero if it was, zero if it wasn't.
+ *
+ * Use:                Checks the next (non-whitespace) character is what we
+ *             expect.  If it is, the character is eaten; otherwise it's no
+ *             big deal.
+ */
+
+extern int qd_delim(qd_parse */*qd*/, int /*ch*/);
+
+/* --- @qd_enum@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *             @const char *e@ = list of enum strings, space separated
+ *
+ * Returns:    Index of the string matched, or @-1@.
+ *
+ * Use:                Matches a keyword.
+ */
+
+extern int qd_enum(qd_parse */*qd*/, const char */*e*/);
+
+/* --- @qd_getmp@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *
+ * Returns:    The integer extracted, or null.
+ *
+ * Use:                Parses a multiprecision integer from a string.
+ */
+
+extern mp *qd_getmp(qd_parse */*qd*/);
+
+/* --- @qd_eofp@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = context
+ *
+ * Returns:    Nonzero if at EOF, zero otherwise.
+ */
+
+extern int qd_eofp(qd_parse */*qd*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/rabin.c b/math/rabin.c
new file mode 100644 (file)
index 0000000..b543eef
--- /dev/null
@@ -0,0 +1,197 @@
+/* -*-c-*-
+ *
+ * Miller-Rabin primality test
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpbarrett.h"
+#include "mpmont.h"
+#include "pgen.h"
+#include "rabin.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rabin_create@ --- *
+ *
+ * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
+ *             @mp *m@ = pointer to number to test
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Precomputes some useful values for performing the
+ *             Miller-Rabin probabilistic primality test.
+ */
+
+int rabin_create(rabin *r, mp *m)
+{
+  mp *m1 = mp_sub(MP_NEW, m, MP_ONE);
+  if (mpmont_create(&r->mm, m)) {
+    MP_DROP(m1);
+    return (-1);
+  }
+  r->r = mp_odd(MP_NEW, m1, &r->s);
+  r->m1 = mp_sub(MP_NEW, m, r->mm.r);
+  mp_drop(m1);
+  return (0);
+}
+
+/* --- @rabin_destroy@ --- *
+ *
+ * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a Rabin-Miller context when it's no longer
+ *             needed.
+ */
+
+void rabin_destroy(rabin *r)
+{
+  mp_drop(r->r);
+  mp_drop(r->m1);
+  mpmont_destroy(&r->mm);
+}
+
+/* --- @rabin_test@, @rabin_rtest@ --- *
+ *
+ * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
+ *             @mp *g@ = base to test the number against
+ *
+ * Returns:    Either @PGEN_FAIL@ if the test failed, or @PGEN_PASS@
+ *             if it succeeded.
+ *
+ * Use:                Performs a single iteration of the Rabin-Miller primality
+ *             test.  The @rtest@ variant assumes that %$g$% is either
+ *             already in Montgomery representation, or you don't care.
+ */
+
+int rabin_rtest(rabin *r, mp *g)
+{
+  mp *y;
+  mp *dd, *spare = MP_NEW;
+  size_t j;
+  int rc = PGEN_FAIL;
+
+  /* --- Calculate %$y R = g^r R \bmod m$% --- *
+   *
+   * If %$y = 1$% or %$y = m - 1$% then %$m$% is prime.  If course, note that
+   * @y@ here has an extra factor of %$R$%.
+   */
+
+  y = mpmont_expr(&r->mm, MP_NEW, g, r->r);
+  if (MP_EQ(y, r->mm.r) || MP_EQ(y, r->m1)) {
+    rc = PGEN_PASS;
+    goto done;
+  }
+
+  /* --- Now for the main loop --- *
+   *
+   * If %$y^{2^j} \ne m - 1$% for any %$0 \le j < s$% then %$m$% is
+   * composite.  Of course, %$j = 0$% has already been tested.
+   */
+
+  for (j = 1; j < r->s; j++) {
+    dd = mp_sqr(spare, y);
+    dd = mpmont_reduce(&r->mm, dd, dd);
+    spare = y; y = dd;
+    if (MP_EQ(y, r->mm.r))
+      break;
+    if (MP_EQ(y, r->m1)) {
+      rc = PGEN_PASS;
+      break;
+    }
+  }
+
+  /* --- Done --- */
+
+done:
+  if (spare != MP_NEW)
+    MP_DROP(spare);
+  MP_DROP(y);
+  return (rc);
+}
+
+int rabin_test(rabin *r, mp *g)
+{
+  int rc;
+  g = mpmont_mul(&r->mm, MP_NEW, g, r->mm.r2);
+  rc = rabin_rtest(r, g);
+  mp_drop(g);
+  return (rc);
+}
+
+/* --- @rabin_iters@ --- *
+ *
+ * Arguments:  @unsigned len@ = number of bits in value
+ *
+ * Returns:    Number of iterations recommended.
+ *
+ * Use:                Returns the recommended number of iterations to ensure that a
+ *             number with @len@ bits is really prime.
+ */
+
+int rabin_iters(unsigned len)
+{
+  static const struct {
+    unsigned b;
+    int i;
+  } *p, *q, tab[] = {
+    { 100, 27 },
+    { 150, 18 },
+    { 200, 15 },
+    { 250, 12 },
+    { 300, 9 },
+    { 350, 8 },
+    { 400, 7 },
+    { 450, 6 },
+    { 550, 5 },
+    { 650, 4 },
+    { 850, 3 },
+    { 1300, 2 }
+  };
+
+  unsigned i;
+
+  /* --- Binary search through the table --- */
+
+  p = tab;
+  q = tab + (sizeof(tab)/sizeof(tab[0]));
+  for (;;) {
+    i = (q - p) / 2;
+    if (!i)
+      break;
+    if (len >= p[i].b && len < p[i + 1].b)
+      break;
+    if (len > p[i].b)
+      p = p + i;
+    else
+      q = p + i;
+  }
+  return (p[i].i);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/rabin.h b/math/rabin.h
new file mode 100644 (file)
index 0000000..c3eec72
--- /dev/null
@@ -0,0 +1,119 @@
+/* -*-c-*-
+ *
+ * Miller-Rabin primality test
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_RABIN_H
+#define CATACOMB_RABIN_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_MPMONT_H
+#  include "mpmont.h"
+#endif
+
+#ifndef CATACOMB_PFILT_H
+#  include "pfilt.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rabin {
+  mpmont mm;                           /* Montgomery arithmetic context */
+  size_t s;                            /* %$m = 2^s r + 1$% */
+  mp *r;                               /* %$m = 2^s r + 1$% */
+  mp *m1;                              /* %$(m - 1)R \bmod m$% */
+} rabin;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rabin_create@ --- *
+ *
+ * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
+ *             @mp *m@ = pointer to number to test
+ *
+ * Returns:    Zero on success, nonzero for failure.
+ *
+ * Use:                Precomputes some useful values for performing the
+ *             Miller-Rabin probabilistic primality test.
+ */
+
+extern int rabin_create(rabin */*r*/, mp */*m*/);
+
+/* --- @rabin_destroy@ --- *
+ *
+ * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a Rabin-Miller context when it's no longer
+ *             needed.
+ */
+
+extern void rabin_destroy(rabin */*r*/);
+
+/* --- @rabin_test@, @rabin_rtest@ --- *
+ *
+ * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
+ *             @mp *g@ = base to test the number against
+ *
+ * Returns:    Either @PGEN_FAIL@ if the test failed, or @PGEN_PASS@
+ *             if it succeeded.
+ *
+ * Use:                Performs a single iteration of the Rabin-Miller primality
+ *             test.  The @rtest@ variant assumes that %$g$% is either
+ *             already in Montgomery representation, or you don't care.
+ */
+
+extern int rabin_rtest(rabin */*r*/, mp */*g*/);
+extern int rabin_test(rabin */*r*/, mp */*g*/);
+
+/* --- @rabin_iters@ --- *
+ *
+ * Arguments:  @unsigned len@ = number of bits in value
+ *
+ * Returns:    Number of iterations recommended.
+ *
+ * Use:                Returns the recommended number of iterations to ensure that a
+ *             number with @len@ bits is really prime.
+ */
+
+extern int rabin_iters(unsigned /*len*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/rho.c b/math/rho.c
new file mode 100644 (file)
index 0000000..fc5076b
--- /dev/null
@@ -0,0 +1,298 @@
+/* -*-c-*-
+ *
+ * Pollard's rho algorithm for discrete logs
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fibrand.h"
+#include "mp.h"
+#include "mpmont.h"
+#include "mprand.h"
+#include "rho.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rho@ --- *
+ *
+ * Arguments:  @rho_ctx *cc@ = pointer to the context structure
+ *             @void *x, *y@ = two (equal) base values (try 1)
+ *             @mp *a, *b@ = logs of %$x$% (see below)
+ *
+ * Returns:    The discrete logarithm %$\log_g a$%, or null if the algorithm
+ *             failed.  (This is unlikely, though possible.)
+ *
+ * Use:                Uses Pollard's rho algorithm to compute discrete logs in the
+ *             group %$G$% generated by %$g$%.
+ *
+ *             The algorithm works by finding a cycle in a pseudo-random
+ *             walk.  The function @ops->split@ should return an element
+ *             from %$\{\,0, 1, 2\,\}$% according to its argument, in order
+ *             to determine the walk.  At each step in the walk, we know a
+ *             group element %$x \in G$% together with its representation as
+ *             a product of powers of %$g$% and $%a$% (i.e., we know that
+ *             %$x = g^\alpha a^\beta$% for some %$\alpha$%, %$\beta$%).
+ *
+ *             Locating a cycle gives us a collision
+ *
+ *               %$g^{\alpha} a^{\beta} = g^{\alpha'} a^{\beta'}$%
+ *
+ *             Taking logs of both sides (to base %$g$%) gives us that
+ *
+ *               %$\log a\equiv\frac{\alpha-\alpha'}{\beta'-\beta}\bmod{n}$%
+ *
+ *             Good initial values are %$x = y = 1$% (the multiplicative
+ *             identity of %$G$%) and %$\alpha\equiv\beta\equiv0\bmod{n}$%.
+ *             If that doesn't work then start choosing more `interesting'
+ *             values.
+ *
+ *             Note that the algorithm requires minimal space but
+ *             %$O(\sqrt{n})$% time.  Don't do this on large groups,
+ *             particularly if you can find a decent factor base.
+ *
+ *             Finally, note that this function will free the input values
+ *             when it's finished with them.  This probably isn't a great
+ *             problem.
+ */
+
+static void step(rho_ctx *cc, void *x, mp **a, mp **b)
+{
+  switch (cc->ops->split(x)) {
+    case 0:
+      cc->ops->mul(x, cc->g, cc->c);
+      *a = mp_add(*a, *a, MP_ONE);
+      if (MP_CMP(*a, >=, cc->n))
+       *a = mp_sub(*a, *a, cc->n);
+      break;
+    case 1:
+      cc->ops->sqr(x, cc->c);
+      *a = mp_lsl(*a, *a, 1);
+      if (MP_CMP(*a, >=, cc->n))
+       *a = mp_sub(*a, *a, cc->n);
+      *b = mp_lsl(*b, *b, 1);
+      if (MP_CMP(*b, >=, cc->n))
+       *b = mp_sub(*b, *b, cc->n);
+      break;
+    case 2:
+      cc->ops->mul(x, cc->a, cc->c);
+      *b = mp_add(*b, *b, MP_ONE);
+      if (MP_CMP(*b, >=, cc->n))
+       *b = mp_sub(*b, *b, cc->n);
+      break;
+  }
+}
+
+mp *rho(rho_ctx *cc, void *x, void *y, mp *a, mp *b)
+{
+  mp *aa = MP_COPY(a), *bb = MP_COPY(b);
+  mp *g;
+
+  /* --- Grind through the random walk until we find a collision --- */
+
+  do {
+    step(cc, x, &a, &b);
+    step(cc, y, &aa, &bb);
+    step(cc, y, &aa, &bb);
+  } while (!cc->ops->eq(x, y));
+  cc->ops->drop(x);
+  cc->ops->drop(y);
+
+  /* --- Now sort out the mess --- */
+
+  aa = mp_sub(aa, a, aa);
+  bb = mp_sub(bb, bb, b);
+  g = MP_NEW;
+  mp_gcd(&g, &bb, 0, bb, cc->n);
+  if (!MP_EQ(g, MP_ONE)) {
+    mp_drop(aa);
+    aa = 0;
+  } else {
+    aa = mp_mul(aa, aa, bb);
+    mp_div(0, &aa, aa, cc->n);
+  }
+
+  /* --- Done --- */
+
+  mp_drop(bb);
+  mp_drop(g);
+  mp_drop(a);
+  mp_drop(b);
+  return (aa);
+}
+
+/* --- @rho_prime@ --- *
+ *
+ * Arguments:  @mp *g@ = generator for the group
+ *             @mp *a@ = value to find the logarithm of
+ *             @mp *n@ = order of the group
+ *             @mp *p@ = prime size of the underlying prime field
+ *
+ * Returns:    The discrete logarithm %$\log_g a$%.
+ *
+ * Use:                Computes discrete logarithms in a subgroup of a prime field.
+ */
+
+static void prime_sqr(void *x, void *c)
+{
+  mp **p = x;
+  mp *a = *p;
+  a = mp_sqr(a, a);
+  a = mpmont_reduce(c, a, a);
+  *p = a;
+}
+
+static void prime_mul(void *x, void *y, void *c)
+{
+  mp **p = x;
+  mp *a = *p;
+  a = mpmont_mul(c, a, a, y);
+  *p = a;
+}
+
+static int prime_eq(void *x, void *y)
+{
+  return (MP_EQ(*(mp **)x, *(mp **)y));
+}
+
+static int prime_split(void *x)
+{
+  /* --- Notes on the splitting function --- *
+   *
+   * The objective is to produce a simple pseudorandom mapping from the
+   * underlying field \gf{p} to \{\,0, 1, 2\,\}$%.  This is further
+   * constrained by the fact that we must not have %$1 \mapsto 1$% (since
+   * otherwise the stepping function above will loop).
+   *
+   * The function we choose is very simple: we take the least significant
+   * word from the integer, add one (to prevent the %$1 \mapsto 1$% property
+   * described above) and reduce modulo 3.  This is slightly biased against
+   * the result 2, but this doesn't appear to be relevant.
+   */
+
+  return (((*(mp **)x)->v[0] + 1) % 3);
+}
+
+static void prime_drop(void *x)
+{
+  MP_DROP(*(mp **)x);
+}
+
+static const rho_ops prime_ops = {
+  prime_sqr, prime_mul, prime_eq, prime_split, prime_drop
+};
+
+mp *rho_prime(mp *g, mp *a, mp *n, mp *p)
+{
+  rho_ctx cc;
+  grand *r = 0;
+  mpmont mm;
+  mp *x, *y;
+  mp *aa, *bb;
+  mp *l;
+
+  /* --- Initialization --- */
+
+  mpmont_create(&mm, p);
+  cc.ops = &prime_ops;
+  cc.c = &mm;
+  cc.n = n;
+  cc.g = mpmont_mul(&mm, MP_NEW, g, mm.r2);
+  cc.a = mpmont_mul(&mm, MP_NEW, a, mm.r2);
+  x = MP_COPY(mm.r);
+  y = MP_COPY(x);
+  aa = bb = MP_ZERO;
+
+  /* --- The main loop --- */
+
+  while ((l = rho(&cc, &x, &y, aa, bb)) == 0) {
+    mp_expfactor f[2];
+
+    if (!r)
+      r = fibrand_create(0);
+    aa = mprand_range(MP_NEW, n, r, 0);
+    bb = mprand_range(MP_NEW, n, r, 0);
+    f[0].base = cc.g; f[0].exp = aa;
+    f[1].base = cc.a; f[1].exp = bb;
+    x = mpmont_mexpr(&mm, MP_NEW, f, 2);
+    y = MP_COPY(x);
+  }
+
+  /* --- Throw everything away now --- */
+
+  if (r)
+    r->ops->destroy(r);
+  mp_drop(cc.g);
+  mp_drop(cc.a);
+  mpmont_destroy(&mm);
+  return (l);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "dh.h"
+
+int main(void)
+{
+  dh_param dp;
+  mp *x, *y;
+  grand *r = fibrand_create(0);
+  mpmont mm;
+  mp *l;
+  int ok;
+
+  fputs("rho: ", stdout);
+  fflush(stdout);
+
+  dh_gen(&dp, 32, 256, 0, r, pgen_evspin, 0);
+  x = mprand_range(MP_NEW, dp.q, r, 0);
+  mpmont_create(&mm, dp.p);
+  y = mpmont_exp(&mm, MP_NEW, dp.g, x);
+  mpmont_destroy(&mm);
+  l = rho_prime(dp.g, y, dp.q, dp.p);
+  if (MP_EQ(x, l)) {
+    fputs(". ok\n", stdout);
+    ok = 1;
+  } else {
+    fputs("\n*** rho (discrete logs) failed\n", stdout);
+    ok = 0;
+  }
+
+  mp_drop(l);
+  mp_drop(x);
+  mp_drop(y);
+  r->ops->destroy(r);
+  dh_paramfree(&dp);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+
+  return (ok ? 0 : EXIT_FAILURE);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/rho.h b/math/rho.h
new file mode 100644 (file)
index 0000000..0817fe8
--- /dev/null
@@ -0,0 +1,129 @@
+/* -*-c-*-
+ *
+ * Pollard's rho algorithm for discrete logs
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_RHO_H
+#define CATACOMB_RHO_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- The group operations table --- */
+
+typedef struct rho_ops {
+  void (*sqr)(void *x, void *c);
+  void (*mul)(void *x, void *y, void *c);
+  int (*eq)(void *x, void *y);
+  int (*split)(void *x);
+  void (*drop)(void *x);
+} rho_ops;
+
+/* --- The Pollard's rho context structure --- */
+
+typedef struct rho_ctx {
+  const rho_ops *ops;                  /* Group operations table */
+  void *c;                             /* Context for group operations */
+  void *g, *a;                         /* Generator and argument for log */
+  mp *n;                               /* Cyclic group order */
+} rho_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rho@ --- *
+ *
+ * Arguments:  @rho_ctx *cc@ = pointer to the context structure
+ *             @void *x, *y@ = two (equal) base values (try 1)
+ *             @mp *a, *b@ = logs of %$x$% (see below)
+ *
+ * Returns:    The discrete logarithm %$\log_g a$%, or null if the algorithm
+ *             failed.  (This is unlikely, though possible.)
+ *
+ * Use:                Uses Pollard's rho algorithm to compute discrete logs in the
+ *             group %$G$% generated by %$g$%.
+ *
+ *             The algorithm works by finding a cycle in a pseudo-random
+ *             walk.  The function @ops->split@ should return an element
+ *             from %$\{\,0, 1, 2\,\}$% according to its argument, in order
+ *             to determine the walk.  At each step in the walk, we know a
+ *             group element %$x \in G$% together with its representation as
+ *             a product of powers of %$g$% and $%a$% (i.e., we know that
+ *             %$x = g^\alpha a^\beta$% for some %$\alpha$%, %$\beta$%).
+ *
+ *             Locating a cycle gives us a collision
+ *
+ *               %$g^{\alpha} a^{\beta} = g^{\alpha'} a^{\beta'}$%
+ *
+ *             Taking logs of both sides (to base %$g$%) gives us that
+ *
+ *               %$\log a\equiv\frac{\alpha-\alpha'}{\beta'-\beta}\bmod{n}$%
+ *
+ *             Good initial values are %$x = y = 1$% (the multiplicative
+ *             identity of %$G$%) and %$\alpha\equiv\beta\equiv0\bmod{n}$%.
+ *             If that doesn't work then start choosing more `interesting'
+ *             values.
+ *
+ *             Note that the algorithm requires minimal space but
+ *             %$O(\sqrt{n})$% time.  Don't do this on large groups,
+ *             particularly if you can find a decent factor base.
+ *
+ *             Finally, note that this function will free the input values
+ *             when it's finished with them.  This probably isn't a great
+ *             problem.
+ */
+
+extern mp *rho(rho_ctx */*cc*/, void */*x*/, void */*y*/,
+              mp */*a*/, mp */*b*/);
+
+/* --- @rho_prime@ --- *
+ *
+ * Arguments:  @mp *g@ = generator for the group
+ *             @mp *a@ = value to find the logarithm of
+ *             @mp *n@ = order of the group
+ *             @mp *p@ = prime size of the underlying prime field
+ *
+ * Returns:    The discrete logarithm %$\log_g a$%.
+ *
+ * Use:                Computes discrete logarithms in a subgroup of a prime field.
+ */
+
+extern mp *rho_prime(mp */*g*/, mp */*a*/, mp */*n*/, mp */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/strongprime.c b/math/strongprime.c
new file mode 100644 (file)
index 0000000..6acac17
--- /dev/null
@@ -0,0 +1,203 @@
+/* -*-c-*-
+ *
+ * Generate `strong' prime numbers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "grand.h"
+#include "mp.h"
+#include "mpmont.h"
+#include "mprand.h"
+#include "pgen.h"
+#include "pfilt.h"
+#include "rabin.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @strongprime_setup@ --- *
+ *
+ * Arguments:  @const char *name@ = pointer to name root
+ *             @mp *d@ = destination for search start point
+ *             @pfilt *f@ = where to store filter jump context
+ *             @unsigned nbits@ = number of bits wanted
+ *             @grand *r@ = random number source
+ *             @unsigned n@ = number of attempts to make
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for the event handler
+ *
+ * Returns:    A starting point for a `strong' prime search, or zero.
+ *
+ * Use:                Sets up for a strong prime search, so that primes with
+ *             particular properties can be found.  It's probably important
+ *             to note that the number left in the filter context @f@ is
+ *             congruent to 2 (mod 4).
+ */
+
+mp *strongprime_setup(const char *name, mp *d, pfilt *f, unsigned nbits,
+                     grand *r, unsigned n, pgen_proc *event, void *ectx)
+{
+  mp *s, *t, *q;
+  dstr dn = DSTR_INIT;
+
+  mp *rr = d;
+  pgen_filterctx c;
+  pgen_jumpctx j;
+  rabin rb;
+
+  /* --- The bitslop parameter --- *
+   *
+   * There's quite a lot of prime searching to be done.  The constant
+   * @BITSLOP@ is a (low) approximation to the base-2 log of the expected
+   * number of steps to find a prime number.  Experimentation shows that
+   * numbers around 10 seem to be good.
+   */
+
+#define BITSLOP 12
+
+  /* --- Choose two primes %$s$% and %$t$% of half the required size --- */
+
+  assert(((void)"nbits too small in strongprime_setup", nbits/2 > BITSLOP));
+  nbits = nbits/2 - BITSLOP;
+  c.step = 1;
+
+  rr = mprand(rr, nbits, r, 1);
+  DRESET(&dn); dstr_putf(&dn, "%s [s]", name);
+  if ((s = pgen(dn.buf, MP_NEWSEC, rr, event, ectx, n, pgen_filter, &c,
+          rabin_iters(nbits), pgen_test, &rb)) == 0)
+    goto fail_s;
+
+  rr = mprand(rr, nbits, r, 1);
+  DRESET(&dn); dstr_putf(&dn, "%s [t]", name);
+  if ((t = pgen(dn.buf, MP_NEWSEC, rr, event, ectx, n, pgen_filter, &c,
+               rabin_iters(nbits), pgen_test, &rb)) == 0)
+    goto fail_t;
+
+  /* --- Choose a suitable value for %$r = 2it + 1$% for some %$i$% --- */
+
+  rr = mp_lsl(rr, t, 1);
+  pfilt_create(&c.f, rr);
+  rr = mp_lsl(rr, rr, BITSLOP - 1);
+  rr = mp_add(rr, rr, MP_ONE);
+  DRESET(&dn); dstr_putf(&dn, "%s [r]", name);
+  j.j = &c.f;
+  nbits += BITSLOP;
+  q = pgen(dn.buf, MP_NEW, rr, event, ectx, n, pgen_jump, &j,
+          rabin_iters(nbits), pgen_test, &rb);
+  pfilt_destroy(&c.f);
+  if (!q)
+    goto fail_r;
+
+  /* --- Select a suitable starting-point for finding %$p$% --- *
+   *
+   * This computes %$p_0 = 2(s^{r - 2} \bmod r)s - 1$%.
+   */
+
+  {
+    mpmont mm;
+
+    mpmont_create(&mm, q);
+    rr = mp_sub(rr, q, MP_TWO);
+    rr = mpmont_exp(&mm, rr, s, rr);
+    mpmont_destroy(&mm);
+    rr = mp_mul(rr, rr, s);
+    rr = mp_lsl(rr, rr, 1);
+    rr = mp_sub(rr, rr, MP_ONE);
+  }
+
+  /* --- Now find %$p = p_0 + 2jrs$% for some %$j$% --- */
+
+  {
+    mp *x;
+    x = mp_mul(MP_NEW, q, s);
+    x = mp_lsl(x, x, 1);
+    pfilt_create(f, x);
+    x = mp_lsl(x, x, BITSLOP - 1);
+    rr = mp_add(rr, rr, x);
+    mp_drop(x);
+  }
+
+  /* --- Return the result --- */
+
+  mp_drop(q);
+  mp_drop(t);
+  mp_drop(s);
+  dstr_destroy(&dn);
+  return (rr);
+
+  /* --- Tidy up if something failed --- */
+
+fail_r:
+  mp_drop(t);
+fail_t:
+  mp_drop(s);
+fail_s:
+  mp_drop(rr);
+  dstr_destroy(&dn);
+  return (0);
+
+#undef BITSLOP
+}
+
+/* --- @strongprime@ --- *
+ *
+ * Arguments:  @const char *name@ = pointer to name root
+ *             @mp *d@ = destination integer
+ *             @unsigned nbits@ = number of bits wanted
+ *             @grand *r@ = random number source
+ *             @unsigned n@ = number of attempts to make
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for the event handler
+ *
+ * Returns:    A `strong' prime, or zero.
+ *
+ * Use:                Finds `strong' primes.  A strong prime %$p$% is such that
+ *
+ *               * %$p - 1$% has a large prime factor %$r$%,
+ *               * %$p + 1$% has a large prime factor %$s$%, and
+ *               * %$r - 1$% has a large prime factor %$t$%.
+ *
+ *             The numbers produced may be slightly larger than requested,
+ *             by a few bits.
+ */
+
+mp *strongprime(const char *name, mp *d, unsigned nbits, grand *r,
+               unsigned n, pgen_proc *event, void *ectx)
+{
+  pfilt f;
+  pgen_jumpctx j;
+  rabin rb;
+
+  d = strongprime_setup(name, d, &f, nbits, r, n, event, ectx);
+  j.j = &f;
+  d = pgen(name, d, d, event, ectx, n, pgen_jump, &j,
+          rabin_iters(nbits), pgen_test, &rb);
+  pfilt_destroy(&f);
+  return (d);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/math/strongprime.h b/math/strongprime.h
new file mode 100644 (file)
index 0000000..6f39f50
--- /dev/null
@@ -0,0 +1,103 @@
+/* -*-c-*-
+ *
+ * Generate `strong' prime numbers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_STRONGPRIME_H
+#define CATACOMB_STRONGPRIME_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_PGEN_H
+#  include "pgen.h"
+#endif
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @strongprime_setup@ --- *
+ *
+ * Arguments:  @const char *name@ = pointer to name root
+ *             @mp *d@ = destination for search start point
+ *             @pfilt *f@ = where to store filter jump context
+ *             @unsigned nbits@ = number of bits wanted
+ *             @grand *r@ = random number source
+ *             @unsigned n@ = number of attempts to make
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for the event handler
+ *
+ * Returns:    A starting point for a `strong' prime search, or zero.
+ *
+ * Use:                Sets up for a strong prime search, so that primes with
+ *             particular properties can be found.  It's probably important
+ *             to note that the number left in the filter context @f@ is
+ *             congruent to 2 (mod 4).
+ */
+
+extern mp *strongprime_setup(const char */*name*/, mp */*d*/, pfilt */*f*/,
+                            unsigned /*nbits*/, grand */*r*/,
+                            unsigned /*n*/, pgen_proc */*event*/,
+                            void */*ectx*/);
+
+/* --- @strongprime@ --- *
+ *
+ * Arguments:  @const char *name@ = pointer to name root
+ *             @mp *d@ = destination integer
+ *             @unsigned nbits@ = number of bits wanted
+ *             @grand *r@ = random number source
+ *             @unsigned n@ = number of attempts to make
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for the event handler
+ *
+ * Returns:    A `strong' prime, or zero.
+ *
+ * Use:                Finds `strong' primes.  A strong prime %$p$% is such that
+ *
+ *               * %$p - 1$% has a large prime factor %$r$%,
+ *               * %$p + 1$% has a large prime factor %$s$%, and
+ *               * %$r - 1$% has a large prime factor %$t$%.
+ *
+ *             The numbers produced may be slightly larger than requested,
+ *             by a few bits.
+ */
+
+extern mp *strongprime(const char */*name*/, mp */*d*/, unsigned /*nbits*/,
+                      grand */*r*/, unsigned /*n*/,
+                      pgen_proc */*event*/, void */*ectx*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/math/t/ec b/math/t/ec
new file mode 100644 (file)
index 0000000..92fb26a
--- /dev/null
+++ b/math/t/ec
@@ -0,0 +1,451 @@
+# Elliptic curve tests
+
+check {
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    0;
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810"
+    -1;
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"
+    0;
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411,
+      0xdccf19d3e76abfa05d529c07575f54c94fa5fc9f3decc246"
+    0;
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    0;
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810"
+    -1;
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"
+    0;
+
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    0;
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810"
+    -1;
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"
+    0;
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411,
+      0xdccf19d3e76abfa05d529c07575f54c94fa5fc9f3decc246"
+    0;
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    0;
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810"
+    -1;
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"
+    0;
+
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1"
+    0;
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f0"
+    -1;
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    0;
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1"
+    0;
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f0"
+    -1;
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    0;
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0591168d4994637e8343e36,
+      0x7fa8423c5ae194b56cdf21998ad8a721ef1201b8c"
+    0;
+}
+
+find {
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811";
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1011 inf;
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411
+    "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411,
+      0x2330e62c1895405fa2ad63f8a8a0ab35b05a0360c2133db9";
+
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811";
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1011 inf;
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411
+    "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411,
+      0x2330e62c1895405fa2ad63f8a8a0ab35b05a0360c2133db9";
+
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    0x3f0eba16286a2d57ea0991168d4994637e8343e36
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7";
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    0x310eba16386a2d57ea0591168d4997637e8745e36 inf;
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    0x3f0eba16286a2d57ea0591168d4994637e8343e36
+    "0x3f0eba16286a2d57ea0591168d4994637e8343e36,
+      0x7fa8423c5ae194b56cdf21998ad8a721ef1201b8c";
+}
+
+neg {
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1";
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1";
+}
+
+dbl {
+  "prime: 23 prime: 1, 1" "4, 0" inf;
+  "prime: 23 primeproj: 1, 1" "4, 0" inf;
+
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
+      0x49ed3be7f510e30e2462c517ad39038e493fc573c";
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
+      0x49ed3be7f510e30e2462c517ad39038e493fc573c";
+
+  "binpoly: 0x020000000000000000000000000000200000000000000001
+    bin: 0, 0x1ee9"
+    "0x18, 0xd"
+    "0x1bd555555555555555555555555554e8000000000000158,
+      0x14e999999999999999999999999998d7000000000001fe6";
+}
+
+add {
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
+
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
+
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
+      0x49ed3be7f510e30e2462c517ad39038e493fc573c"
+    "0x634000577f86aa315009d6f9b906691f6edd691fe,
+      0x235a3db7a94446301e666cafea5e12cb331f4a140";
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
+      0x49ed3be7f510e30e2462c517ad39038e493fc573c"
+    "0x634000577f86aa315009d6f9b906691f6edd691fe,
+      0x235a3db7a94446301e666cafea5e12cb331f4a140";
+}
+
+sub {
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x634000577f86aa315009d6f9b906691f6edd691fe,
+      0x235a3db7a94446301e666cafea5e12cb331f4a140"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
+      0x49ed3be7f510e30e2462c517ad39038e493fc573c";
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x634000577f86aa315009d6f9b906691f6edd691fe,
+      0x235a3db7a94446301e666cafea5e12cb331f4a140"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
+      0x49ed3be7f510e30e2462c517ad39038e493fc573c";
+}
+
+mul {
+  "prime: 23 prime: 1, 1" "0, 1" 28 inf;
+  "prime: 23 prime: 1, 1" "0, 1" 29 "0, 1";
+  "prime: 23 primeproj: 1, 1" "0, 1" 28 inf;
+  "prime: 23 primeproj: 1, 1" "0, 1" 29 "0, 1";
+
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+     6277101735386680763835789423176059013767194773182842284080
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+     6277101735386680763835789423176059013767194773182842284081
+     inf;
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+     6277101735386680763835789423176059013767194773182842284080
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+  "prime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+     6277101735386680763835789423176059013767194773182842284081
+     inf;
+
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+     6277101735386680763835789423176059013767194773182842284080
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+     6277101735386680763835789423176059013767194773182842284081
+     inf;
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+     6277101735386680763835789423176059013767194773182842284080
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+  "niceprime: 6277101735386680763835789423207666416083908700390324961279
+     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+     6277101735386680763835789423176059013767194773182842284081
+     inf;
+
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    5846006549323611672814742442876390689256843201586
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0xd51fbc6c71a0094fa2cdd545b11c5c0c797324f1";
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    5846006549323611672814742442876390689256843201587
+    inf;
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    5846006549323611672814742442876390689256843201586
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0xd51fbc6c71a0094fa2cdd545b11c5c0c797324f1";
+  "binpoly: 0x800000000000000000000000000000000000000c9
+    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
+    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
+      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
+    5846006549323611672814742442876390689256843201587
+    inf;
+
+  "binpoly: 0x800000000000000000000000000000000000000c9; bin: 1, 1"
+    "0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8,
+      0x289070fb05d38ff58321f2e800536d538ccdaa3d9"
+    5846006549323611672814741753598448348329118574063
+    inf;
+  "binpoly: 0x800000000000000000000000000000000000000c9; binproj: 1, 1"
+    "0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8,
+      0x289070fb05d38ff58321f2e800536d538ccdaa3d9"
+    5846006549323611672814741753598448348329118574063
+    inf;
+}
diff --git a/math/t/gf b/math/t/gf
new file mode 100644 (file)
index 0000000..0ed1c49
--- /dev/null
+++ b/math/t/gf
@@ -0,0 +1,89 @@
+# Test cases for higher-level binary poly arithmetic.
+
+add {
+  0 0 0;
+  1 1 0;
+  1 2 3;
+  4 5 1;
+  0x7fb838a8a0a95046b9d9d9fb4440f7bb
+    0xc1a7bd3b4e853fc92d4e1588719986aa
+    0xbe1f8593ee2c6f8f9497cc7335d97111;
+  0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b21
+    0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b22 3;
+}
+
+mul {
+  0 0 0;
+  1 0 0;
+  0 1 0;
+  1 1 1;
+  0x7fb838a8a0a95046b9d9d9fb4440f7bb
+    0xc1a7bd3b4e853fc92d4e1588719986aa
+    0x207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e;
+  0xc1a7bd3b4e853fc92d4e1588719986aa
+    0x283ed59f1226dcefa7ff0ef87ceff5d5
+    0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b22;
+  0xbe1f8593ee2c6f8f9497cc7335d97111
+    0x35a8e33503b3695be00528f8b82db931
+    0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b21;
+}
+
+sqr {
+  0 0;
+  1 1;
+  3 5;
+  0x7fb838a8a0a95046b9d9d9fb4440f7bb
+    0x1555454005404440440044411100101445415141514155451010100055154545;
+  0x01f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3
+    0x0155004001541441551011510504111011050015141444454140511111554414010450154545041554440501455004140401514041104554415000450141144505;
+}
+
+div {
+  0 1 0 0;
+  0x207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e
+    0x7fb838a8a0a95046b9d9d9fb4440f7bb
+    0xc1a7bd3b4e853fc92d4e1588719986aa 0;
+  0x6e0e2a282a5411ae76767ed1103deef069ef4ed3a14ff24b
+    0x5385621c6661aaa35a24150d2c08332e
+    0x01c2334cc957151dc7
+    0x398c4111da6d06cdf3d83704ee403101;
+}
+
+exp {
+  4 0 1;
+  4 1 4;
+  0x7 2 0x15;
+  3 563 0xf000f000f000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000f000f000f;
+}
+
+irred {
+  0 0;
+  1 0;
+  2 1;
+  0xc1a7bd3b4e853fc92d4e1588719986aa 0;
+  0x800000000000000000000000000000000000000c9 1;
+  0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 1;
+}
+
+gcd {
+  0xc1a7bd3b4e853fc92d4e1588719986aa
+    0xbe1f8593ee2c6f8f9497cc7335d97111
+    3
+    0x283ed59f1226dcefa7ff0ef87ceff5d5
+    0x35a8e33503b3695be00528f8b82db931;
+  0xbe1f8593ee2c6f8f9497cc7335d97111
+    0xc1a7bd3b4e853fc92d4e1588719986aa
+    3
+    0x35a8e33503b3695be00528f8b82db931
+    0x283ed59f1226dcefa7ff0ef87ceff5d5;
+  0x800000000000000000000000000000000000000c9
+    4
+    1
+    1
+    0x20000000000000000000000000000000000000032;
+  0x800000000000000000000000000000000000000c9
+    0x3f0eba16286a2d57ea0991168d4994637e8343e36
+    1
+    0xa17e704470d80cb5a78f295db0ce543dda16a169
+    0x3c8c172e24598e90b9542e6b8f6571f54be572b50;
+}
diff --git a/math/t/gfn b/math/t/gfn
new file mode 100644 (file)
index 0000000..f7720e1
--- /dev/null
@@ -0,0 +1,32 @@
+# Normal basis conversions
+
+gfn {
+  0x800000000000000000000000000000000000000c9
+  0x715169c109c612e390d347c748342bcd3b02a0bef
+  0 0;
+
+  0x800000000000000000000000000000000000000c9
+  0x715169c109c612e390d347c748342bcd3b02a0bef
+  1
+  0x7ffffffffffffffffffffffffffffffffffffffff;
+
+  0x800000000000000000000000000000000000000c9
+  0x715169c109c612e390d347c748342bcd3b02a0bef
+  0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8
+  0x05679b353caa46825fea2d3713ba450da0c2a4541;
+
+  0x20000000000000000000000000000000000000004000000000000000001
+  0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
+  0x066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad
+  0x1a003e0962d4f9a8e407c904a9538163adb825212600c7752ad52233279;
+
+  0x20000000000000000000000000000000000000004000000000000000001
+  0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
+  0x0fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b
+  0x18b863524b3cdfefb94f2784e0b116faac54404bc9162a363bab84a14c5;
+
+  0x20000000000000000000000000000000000000004000000000000000001
+  0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
+  0x1006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052
+  0x04925df77bd8b8ff1a5ff519417822bfedf2bbd752644292c98c7af6e02;
+}
diff --git a/math/t/gfreduce b/math/t/gfreduce
new file mode 100644 (file)
index 0000000..f712316
--- /dev/null
@@ -0,0 +1,79 @@
+# Test efficient polynomial reduction
+
+reduce {
+         0x10000000
+  0x4509823098098435
+          0x8098435;
+  0x100000000000000050002
+    0x4509823098098435
+    0x4509823098098435;
+  0x100000000000000050002
+    0x450982309809843545609843098560803495
+    0x144f98a2f5cbc4773cfd;
+  0xb2ca471b0867d5fae2e4f27a2d2706da
+    0xf254423fef93d5d7a76ecf22c656c1352c53257875945d33
+    0x582f783fc210f72814780e69b0bd29ff;
+}
+
+modexp {
+  0x20000000000000000000000000000000000000000000000000000000000001001
+  0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  0
+  1;
+  0x20000000000000000000000000000000000000000000000000000000000001001
+  0x02
+  0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  1;
+  0x20000000000000000000000000000000000000000000000000000000000001001
+  0x435932098459080438094509845
+  0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  1;
+  0x10000000000000000000000000000000000000000003
+  0x02
+  0x0fffffffffffffffffffffffffffffffffffffffffff
+  1;
+  0x10000000000000000000000000000000000000000003
+  0x34235950984598345900983409845690805680985
+  0x0fffffffffffffffffffffffffffffffffffffffffff
+  1;
+
+  0x800000000000000000000000000000000000000c9
+  0x3f0eba16286a2d57ea0991168d4994637e8343e36
+  -1
+  0x3c8c172e24598e90b9542e6b8f6571f54be572b50;
+  0x800000000000000000000000000000000000000c9
+  0x3c8c172e24598e90b9542e6b8f6571f54be572b50
+  342345
+  0x3521fe2666efe92ca4eb160a286e0fd9427b84a62;
+  0x800000000000000000000000000000000000000c9
+  0x3f0eba16286a2d57ea0991168d4994637e8343e36
+  -342345
+  0x3521fe2666efe92ca4eb160a286e0fd9427b84a62;
+}
+
+sqrt {
+  0x20000000000000000000000000000000000000000000000000000000000001001
+  0x1f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3
+    0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa;
+  0x10000000000000000000000000000000000000000003
+    0x4594094509835690805698083560980459903450984
+    0x820291881a244a02840a2f8ece3f23f88f38bf0b3a;
+}
+
+halftrace {
+  0x20000000000000000000000000000000000000000000000000000000000001001
+  0x174e65c7d14a8ec286df8c7df17662f13f1d3563f13c8c63f23f5d0bd5d1b45cd
+   0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9d;
+}
+
+quadsolve {
+  0x20000000000000000000000000000000000000000000000000000000000001001
+  0x174e65c7d14a8ec286df8c7df17662f13f1d3563f13c8c63f23f5d0bd5d1b45cd
+   0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c;
+  0x10000000000000000000000000000000000000000003
+   0x3b818b447e90713da04f13c3b07cb5e2681d08e4700
+   0x27aa17c97dfa80bbdef9f91b243c6e6ddba1a223cac;
+  0x800000000000000000000000000000000000000c9
+    0x158fe327cc763a2fd7371ee80641ed1871a32aaa8
+    0x29ab0d7da05ffc3f1b3f97ac10e2092694aadbb7c;
+}
diff --git a/math/t/gfx b/math/t/gfx
new file mode 100644 (file)
index 0000000..c0a873a
--- /dev/null
@@ -0,0 +1,527 @@
+# Test vectors for low-level GF functions
+
+# --- Addition (and subtraction) ---
+
+add {
+  # --- Simple sanity tests ---
+
+  01 01 00;
+  02 02 00;
+  03 01 02;
+
+  # --- Random data tests ---
+
+  7fb838a8a0a95046b9d9d9fb4440f7bb
+    c1a7bd3b4e853fc92d4e1588719986aa
+    be1f8593ee2c6f8f9497cc7335d97111;
+  8d68905434b020ccb849e17a03a5c441
+    d2a104aaf523699c1cc7a93174d21d9c
+    5fc994fec1934950a48e484b7777d9dd;
+  027aa17c97dfa80bbdef9f91b243c6e6
+    ddba1a223cad8a39e9c986879ad21b75
+    dfc0bb5eab722232542619162891dd93;
+  d668328b2594570198fd840b4783f5d9
+    f474e9ef071c418acf1f71b9cccdd179
+    221cdb642288168b57e2f5b28b4e24a0;
+  509e024b27fb8b3655da3938d0c04f92
+    3fa219832f73843c0ae8c4f4715f633c
+    6f3c1bc808880f0a5f32fdcca19f2cae;
+  13e8b9d83c66bc5fa56e2debbab3c9c2
+    6bb190b76e090abd7f6375a6921ad17e
+    7859296f526fb6e2da0d584d28a918bc;
+  3c98c1fd7d6e4ff9adae43a38ed0f2b3
+    101f88d732a51bbe40080cabd06002
+    3c88de75aa5ceae213ee4baf250092b1;
+  2774d74b7453e63c2d314e0be52eaf79
+    54c0dc1a0bedbafcb0b707fe5e496a20
+    73b40b517fbe5cc09d8649f5bb67c559;
+  75b9d1662c48f8c40ee4e9b3138a0b59
+    0ca3e9d4c75a6e2b493d7efb8554e9f8
+    791a38b2eb1296ef47d9974896dee2a1;
+  501591c68468a7d8ecfcae3f419ecb52
+    b0ad24cd246361f779e8317e94977c57
+    e0b8b50ba00bc62f95149f41d509b705;
+  6fa69209a292924f04fb5b3469a1068b
+    d9a06e9ac90f02ad095ff84f30a9addd
+    b606fc936b9d90e20da4a37b5908ab56;
+  ce596f2830ab988dfa7dc0add68214af
+    860c30b9a27c7b2759666dd71ec578c3
+    48555f9192d7e3aaa31bad7ac8476c6c;
+  862361325b5f7a6b506b948d55697ce3
+    95142973169fbae5410a22bb88ca63ee
+    133748414dc0c08e1161b636dda31f0d;
+  237495a82a6755689df073af2a56f88c
+    ab46613ddf7787fd1be42272fcb1be44
+    8832f495f510d295861451ddd6e746c8;
+  6b2d8d2b513277cfb03d8a5731234a3d
+    9cc41fbd7189a3b5b0ff2f3746eb9bc6
+    f7e9929620bbd47a00c2a56077c8d1fb;
+  af7baf1a8ce5d42eca4353de181d085a
+    c59bde6136dda59a839605252d1dd390
+    6ae0717bba3871b449d556fb3500dbca;
+  566a7c0f9adc5a021c1759e2c80708c0
+    28d1c20f2b8613b5e1ba8e3005aef30f
+    7ebbbe00b15a49b7fdadd7d2cda9fbcf;
+  a7d716d198bf6bb3d32ba364f722de52
+    4c9a1fa66d2d0cf7935d45e83b9ce326
+    eb4d0977f59267444076e68cccbe3d74;
+  310d8bb131c4bed327529185c4d46db8
+    2742ea95019b5f186c3c848744743d4a
+    164f6124305fe1cb4b6e150280a050f2;
+  70f5bfbf5f18a3deef4230b875b3a0af
+    93c9240145720297b96a404941792a21
+    e33c9bbe1a6aa149562870f134ca8a8e;
+  1ff7c9eaebd3b76791632b609a962992
+    bc3aca2e99d965238d8433eafd717279
+    a3cd03c4720ad2441ce7188a67e75beb;
+  3d1693836d0964dea42c5e80a4307b6c
+    aed5dcd2e9e918e0ff9577f5ceb66256
+    93c34f5184e07c3e5bb929756a86193a;
+  35706029aec609b55c48ab09df59744e
+    6d9b5b4dbeb1779580cba9bbc9fb8921
+    58eb3b6410777e20dc8302b216a2fd6f;
+  7a166f842cc6c36c09508e2b23dbad97
+    01e3fc1cacc040e96217a7281a4273d2
+    7bf59398800683856b4729033999de45;
+  510ce80a4ab0f9eae5f6c3281e7506c5
+    06351138a1ecb6be56a84f1b28a26368
+    5739f932eb5c4f54b35e8c3336d765ad;
+  31bfc6590de44898c40c31bb3aaddebc
+    82b37993094c9ff6498c55ba1cced0f8
+    b30cbfca04a8d76e8d80640126630e44;
+  d00d48a90eb9e89586cc3566b28fa5ea
+    0f502f973c2f17ad79543b20a92f2905
+    df5d673e3296ff38ff980e461ba08cef;
+  df63dead9d7aea0d3fca68123b0812ae
+    ae059fd909978bc6b8824b04e113fa2a
+    7166417494ed61cb87482316da1be884;
+  4c982bd2b93a027fd08ad69227a51506
+    bdc1112c061be0756685473011c61067
+    f1593afebf21e20ab60f91a236630561;
+  dc241c84816a1a50a7ad21519e6abd3a
+    f2c4d8d96bf32d999fdc7c37cfddac67
+    2ee0c45dea9937c938715d6651b7115d;
+  a466ee3984566e4947a28704ecd99d2f
+    0a5e90153ae473c9bee43aafaec08446
+    ae387e2cbeb21d80f946bdab42191969;
+  8698e5d4eede21f8d4791d69fc4cfb22
+    7b4bb531b633dfcb80d9bd35e10d4f6b
+    fdd350e558edfe3354a0a05c1d41b449;
+  4d2462e835a51ee5be30ea2bc6abbb1b
+    fb36217f8dd0fe234bb7dcb778130156
+    b6124397b875e0c6f587369cbeb8ba4d;
+  abf5c76c26bf952d64667f5049bbe6b5
+    436fbd0ad52336b0c9d2987ac79d2909
+    e89a7a66f39ca39dadb4e72a8e26cfbc;
+  8943b34ab9bc6f6839c09a9852492238
+    38b2304265ac16c80f84be3d61a82628
+    b1f18308dc1079a0364424a533e10410;
+  ae2730b3374140b33de67be248766cc7
+    1831ce84d756a4bda1c1ee22ed047d61
+    b616fe37e017e40e9c2795c0a57211a6;
+  4a87ef0f6bc691cab6d79253876ca89e
+    c0c2f4c479ffc90aeafe0598a4ac4d4b
+    8a451bcb123958c05c2997cb23c0e5d5;
+  63b2aad38a2d3b4cf681d892ed460110
+    d707531874bbc8fa22a49fd26142c631
+    b4b5f9cbfe96f3b6d42547408c04c721;
+  f44ef4d8cd19e4f6f6264c59360de94e
+    eb619a0c5fb3c490d382ff4a5d47a0f9
+    1f2f6ed492aa206625a4b3136b4a49b7;
+  786fa5572011847269ba3f51db1226
+    a1c8ac92fa365013326e0daac2dce7b9
+    a1b0c337ad1641974007b7959307f59f;
+}
+
+mul {
+  # --- Simple sanity tests ---
+
+  00 05 00;
+  01 05 05;
+  05 01 05;
+  05 00 00;
+
+  # --- Random data tests ---
+
+  7fb838a8a0a95046b9d9d9fb4440f7bb
+    c1a7bd3b4e853fc92d4e1588719986aa
+    207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e;
+  8d68905434b020ccb849e17a03a5c441
+    d2a104aaf523699c1cc7a93174d21d9c
+    6c75a24ff82d63e8f9425d862be997fd7517511b2563189a6f0a238b33e60a9c;
+  027aa17c97dfa80bbdef9f91b243c6e6
+    ddba1a223cad8a39e9c986879ad21b75
+    019d5567c392730cf1fbc627f1de7ff20438e649e5ba7e7299fcea4ad4c7ac5e;
+  d668328b2594570198fd840b4783f5d9
+    f474e9ef071c418acf1f71b9cccdd179
+    4a7d1a3b7b904b1b135cb89e6f37a38d7f20fcc9bd7b9ec9f0c38114d2a742e1;
+  509e024b27fb8b3655da3938d0c04f92
+    3fa219832f73843c0ae8c4f4715f633c
+    0c0ff0782f813600eda5b73c0d2deaf072ed8b9e98e94991bd2578b776063fb8;
+  13e8b9d83c66bc5fa56e2debbab3c9c2
+    6bb190b76e090abd7f6375a6921ad17e
+    0626e9a14f2ada51ad47ae2385248d361142636fed5f062be9fa0a0567f14c7c;
+  3c98c1fd7d6e4ff9adae43a38ed0f2b3
+    101f88d732a51bbe40080cabd06002
+    03cb092534c593a9f834c21f1af0da8e604c416ec14e3fca1a72ba4c2b4566;
+  2774d74b7453e63c2d314e0be52eaf79
+    54c0dc1a0bedbafcb0b707fe5e496a20
+    0b2dd510554c5442d5871586392f81d08322aa0cf052f64ee507d59ef730b520;
+  75b9d1662c48f8c40ee4e9b3138a0b59
+    0ca3e9d4c75a6e2b493d7efb8554e9f8
+    024ff62a8d33d8c51560088e304cc9b13ccec97899ba476083b86f8c1dc28fb8;
+  501591c68468a7d8ecfcae3f419ecb52
+    b0ad24cd246361f779e8317e94977c57
+    2728b02f09e5cfc78d1b5e45d0b65d58aa353e8e5a928dc80a3fd523b464291e;
+  6fa69209a292924f04fb5b3469a1068b
+    d9a06e9ac90f02ad095ff84f30a9addd
+    29e8250c13db619580291b6d03317cf82d3f97c58aa1dc247c4d4ad25870b80f;
+  ce596f2830ab988dfa7dc0add68214af
+    860c30b9a27c7b2759666dd71ec578c3
+    658c3e0257c6986e4d0b7fd1c2296182f48c395f7a01acdb623702a83c0be9b1;
+  862361325b5f7a6b506b948d55697ce3
+    95142973169fbae5410a22bb88ca63ee
+    49e7469f9f53f214425455d15b9b5cc6309617f18db3e02b98aabe1b134dbd72;
+  237495a82a6755689df073af2a56f88c
+    ab46613ddf7787fd1be42272fcb1be44
+    14a2fbfb8b9621a60325ba6fc7c979b0caa46c7a5ffb865d01859f058621c930;
+  6b2d8d2b513277cfb03d8a5731234a3d
+    9cc41fbd7189a3b5b0ff2f3746eb9bc6
+    31ff31cfbb97615558ec4becb92036b6b8715ab6df7ed6dc18caff6e0641d24e;
+  af7baf1a8ce5d42eca4353de181d085a
+    c59bde6136dda59a839605252d1dd390
+    7e281956a0ae84282a4a600a9a434bcca6f89a9a661f03ac47dcd20ef2b066a0;
+  566a7c0f9adc5a021c1759e2c80708c0
+    28d1c20f2b8613b5e1ba8e3005aef30f
+    0845bd0d5a46401395876a7992ee9762842ea8d7202222e29b973a042a703c40;
+  a7d716d198bf6bb3d32ba364f722de52
+    4c9a1fa66d2d0cf7935d45e83b9ce326
+    2e09cac5254876c45a7dacddd71f13b394ca8ab95413ab681f554c50737839ac;
+  310d8bb131c4bed327529185c4d46db8
+    2742ea95019b5f186c3c848744743d4a
+    06baa3a8c8864b5ea1f998b6138db08924f3a49ddf1ecc22fa93110323aac0b0;
+  70f5bfbf5f18a3deef4230b875b3a0af
+    93c9240145720297b96a404941792a21
+    3fc325d1e5c637ab818172e3fdb51be97a28903ee232125797ead652b391734f;
+  1ff7c9eaebd3b76791632b609a962992
+    bc3aca2e99d965238d8433eafd717279
+    0d78c92f0d674c76fd9e71ace29b1ca58da8a67530a148bcf8815b395de46ee2;
+  3d1693836d0964dea42c5e80a4307b6c
+    aed5dcd2e9e918e0ff9577f5ceb66256
+    185d9d9d173a78a2ea8a86cef12ac9a560f5c1fd96a3e40d47f2d34798d02ea8;
+  35706029aec609b55c48ab09df59744e
+    6d9b5b4dbeb1779580cba9bbc9fb8921
+    0aa132382fb96e788f85a52888a8ef7fa645e17dfaaf35444566c2a56584c38e;
+  7a166f842cc6c36c09508e2b23dbad97
+    01e3fc1cacc040e96217a7281a4273d2
+    567d64a30f28d71578a9ced5624a950fe065d706cf3318c80c3883f126c51e;
+  510ce80a4ab0f9eae5f6c3281e7506c5
+    06351138a1ecb6be56a84f1b28a26368
+    01e80b50adeebb3790d5249eb4170d093b88ab1d42d0737d3dad6825e181f0c8;
+  31bfc6590de44898c40c31bb3aaddebc
+    82b37993094c9ff6498c55ba1cced0f8
+    18a13563df977554b9d470e4c5009f7ec1c62f561a9cb2041a51e7af81e2f8a0;
+  d00d48a90eb9e89586cc3566b28fa5ea
+    0f502f973c2f17ad79543b20a92f2905
+    048955ee72a928a69b16cc80502568ece68198c8947935283c725a2e6f00c842;
+  df63dead9d7aea0d3fca68123b0812ae
+    ae059fd909978bc6b8824b04e113fa2a
+    706606ae02e140bbf3783da276f47110834defb48e89270797e86251e27369ec;
+  4c982bd2b93a027fd08ad69227a51506
+    bdc1112c061be0756685473011c61067
+    283989fcc502efa3d0006b67465f3ebe7950cac8d54daf45215e09bd6058ea52;
+  dc241c84816a1a50a7ad21519e6abd3a
+    f2c4d8d96bf32d999fdc7c37cfddac67
+    4ebfbaf107e1e74583f1a0c6de06f2a4c230c1a96329d8bac1d95d122ce8a266;
+  a466ee3984566e4947a28704ecd99d2f
+    0a5e90153ae473c9bee43aafaec08446
+    044e0764b72ad37e86d87cca3b32c4d6797a7a9b2e8ab414e0c33617d2113922;
+  8698e5d4eede21f8d4791d69fc4cfb22
+    7b4bb531b633dfcb80d9bd35e10d4f6b
+    3c8785b738a800087fb26dc2562ebd676188a1f5e3b60d51463172a5ef5906b6;
+  4d2462e835a51ee5be30ea2bc6abbb1b
+    fb36217f8dd0fe234bb7dcb778130156
+    3a1f7deaeed3275707c611b83b64b4514d9b8508ed4b0827a7001be9488af62a;
+  abf5c76c26bf952d64667f5049bbe6b5
+    436fbd0ad52336b0c9d2987ac79d2909
+    2b38ad58100db6e6bffc52c6e7622581cc5daf65c0b4f7b87dab8313af786e1d;
+  8943b34ab9bc6f6839c09a9852492238
+    38b2304265ac16c80f84be3d61a82628
+    1daa464b09e5db4bef2c404c1be1fb6d6e0c5911ee10a1d7eba409e33b26c6c0;
+  ae2730b3374140b33de67be248766cc7
+    1831ce84d756a4bda1c1ee22ed047d61
+    0f8cb866e66f56fdfd530784d441c8b37d6e0b2a87e3ea6a0a2d6f4387e076e7;
+  4a87ef0f6bc691cab6d79253876ca89e
+    c0c2f4c479ffc90aeafe0598a4ac4d4b
+    37d54041b0e7d641ee3495897524f1ef4a4dad9671261e4aa03fba0bfadb0cd2;
+  63b2aad38a2d3b4cf681d892ed460110
+    d707531874bbc8fa22a49fd26142c631
+    2e25fc4f13fd3839c0698ca373d24ca2bfe572ad3ae46a50c1294237d30c5210;
+  f44ef4d8cd19e4f6f6264c59360de94e
+    eb619a0c5fb3c490d382ff4a5d47a0f9
+    5f20a07a81d4ed9f3d1fd9fef61318d01a58ea810b12ae3976dbe6c2406b2a9e;
+  786fa5572011847269ba3f51db1226
+    a1c8ac92fa365013326e0daac2dce7b9
+    336397c17a1fde4e90cbb9113a5fcd48239d39fee0807e66f8622d97b144b6;
+}
+
+sqr {
+  # --- Simple sanity tests ---
+
+  00 00;
+  01 01;
+  03 05;
+
+  # --- Random data tests ---
+
+  7fb838a8a0a95046b9d9d9fb4440f7bb
+    1555454005404440440044411100101445415141514155451010100055154545;
+  c1a7bd3b4e853fc92d4e1588719986aa
+    5001441545510545105440110555504104511054011140401501414140144444;
+  8d68905434b020ccb849e17a03a5c441
+    4051144041001110051045000400505045401041540115440005441150101001;
+  d2a104aaf523699c1cc7a93174d21d9c
+    5104440100104444551104051441415001505015444105011510510401514150;
+  027aa17c97dfa80bbdef9f91b243c6e6
+    04154444011550411551554440004545515455415541014504100550145414;
+  ddba1a223cad8a39e9c986879ad21b75
+    5151454401440404055044514044054154415041401440154144510401451511;
+  d668328b2594570198fd840b4783f5d9
+    5114144005044045041141101115000141405551401000451015400555115141;
+  f474e9ef071c418acf1f71b9cccdd179
+    5510151054415455001501501001404450550155150145415050505151011541;
+  509e024b27fb8b3655da3938d0c04f92
+    1100415400041045041555454045051411115144054105405100500010554104;
+  3fa219832f73843c0ae8c4f4715f633c
+    0555440401414005045515054010055000445440501055101501115514050550;
+  13e8b9d83c66bc5fa56e2debbab3c9c2
+    0105544045415140055014144550115544111454045154454544450550415004;
+  6bb190b76e090abd7f6375a6921ad17e
+    1445450141004515145400410044455115551405151144144104014451011554;
+  3c98c1fd7d6e4ff9adae43a38ed0f2b3
+    0550414050015551155114541055554144514454100544054054510055044505;
+  101f88d732a51bbe40080cabd06002
+    010001554040511505044411014545541000004000504445510014000004;
+  2774d74b7453e63c2d314e0be52eaf79
+    0415151051151045151011055414055004510501105400455411045444551541;
+  54c0dc1a0bedbafcb0b707fe5e496a20
+    1110500051500144004554514544555045004515001555541154104114440400;
+  75b9d1662c48f8c40ee4e9b3138a0b59
+    1511454151011414045010405540501000545410544145050105404400451141;
+  0ca3e9d4c75a6e2b493d7efb8554e9f8
+    50440554415110501511441454044510410551155455454011111054415540;
+  501591c68468a7d8ecfcae3f419ecb52
+    1100011141015014401014404415514054505550445405551001415450451104;
+  b0ad24cd246361f779e8317e94977c57
+    4500445104105051041014051401551515415440050115544110411515501115;
+  6fa69209a292924f04fb5b3469a1068b
+    1455441441040041440441044104105500105545114505101441440100144045;
+  d9a06e9ac90f02ad095ff84f30a9addd
+    5141440014544144504100550004445100411155554010550500444144515151;
+  ce596f2830ab988dfa7dc0add68214af
+    5054114114550440050044454140405155441551500044515114400401104455;
+  860c30b9a27c7b2759666dd71ec578c3
+    4014005005004541440415501545041511411414145151150154501115405005;
+  862361325b5f7a6b506b948d55697ce3
+    4014040514010504114511551544144511001445411040511111144115505405;
+  95142973169fbae5410a22bb88ca63ee
+    4111011004411505011441554544541110010044040445454040504414055454;
+  237495a82a6755689df073af2a56f88c
+    0405151041114440044414151111144041515500150544550444111455404050;
+  ab46613ddf7787fd1be42272fcb1be44
+    4445101414010551515515154015555101455410040415045550450145541010;
+  6b2d8d2b513277cfb03d8a5731234a3d
+    1445045140510445110105041515505545000551404411150501040510440551;
+  9cc41fbd7189a3b5b0ff2f3746eb9bc6
+    4150501001554551150140414405451145005555045505151014544541455014;
+  af7baf1a8ce5d42eca4353de181d085a
+    4455154544550144405054115110045450441005110551540140015100401144;
+  c59bde6136dda59a839605252d1dd390
+    5011414551541401051451514411414440054114001104110451015151054100;
+  566a7c0f9adc5a021c1759e2c80708c0
+    1114144415500055414451501144000401500115114154045040001500405000;
+  28d1c20f2b8613b5e1ba8e3005aef30f
+    0440510150040055044540140105451154014544405405000011445455050055;
+  a7d716d198bf6bb3d32ba364f722de52
+    4415511501145101414045551445450551050445440514105515040451541104;
+  4c9a1fa66d2d0cf7935d45e83b9ce326
+    1050414401554414145104510050551541051151101154400545415054050414;
+  310d8bb131c4bed327529185c4d46db8
+    0501005140454501050150104554510504151104410140115010511014514540;
+  2742ea95019b5f186c3c848744743d4a
+    0415100454444111000141451155014014500550401040151010151005511044;
+  70f5bfbf5f18a3deef4230b875b3a0af
+    1500551145554555115501404405515454551004050045401511450544004455;
+  93c9240145720297b96a404941792a21
+    4105504104100001101115040004411545411444100010411001154104440401;
+
+  # --- Regression ---
+
+  01f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3
+    0155004001541441551011510504111011050015141444454140511111554414010450154545041554440501455004140401514041104554415000450141144505;
+}
+
+div {
+  # --- Random data tests ---
+
+  6e0e2a282a5411ae76767ed1103deef069ef4ed3a14ff24b
+    5385621c6661aaa35a24150d2c08332e
+    01c2334cc957151dc7
+    398c4111da6d06cdf3d83704ee403101;
+  785e80e9711074a8412abd48da670731ea
+    4c5d348767009ea85f25f7ea02ef7be7
+    01c4
+    0b17de61cc808487285b72f14fa23336;
+  d921e3736edd0d111e56c51cf4e4c343cd690dbaeb34194592ca2b80cc7e
+    c205a3c1faecfa3a74f7838e20c5678f
+    012492f38367090dbc739e8a15c414
+    34570d4431e79cc4d3ff2a583c3a56b2;
+  06e7333745e54278092c9fee2cd95768e4e343013e48fe88660cbdce
+    10f02ba313d1c57d8cf04fa2e760f19a
+    6c1708dd11c7305e9d0a1974
+    0dd6757486f880c40590ed673c22ddc6;
+  bf4adc5bd775679384d763216edc12157afec6eb4d2435a2fc793183fafadc
+    9ff35b5c87471da1e56600203f11ae65
+    014fd82ad3ab0ef9bda71f5d88ab3fe1
+    3b599b787383608d59ba518513d7d0d9;
+  0377c80101957a0c0044ee9ae96e8a7cc785a629c1
+    7ca5d5ef2a981b83417db75f9616e0ff
+    0b71080c88
+    2d21297ee7c68552c11b6199fa1d55b9;
+  1c92d440eb73a2cc5891f1881dc9d366271416b21947d3a98eb4dc5692
+    7afdf70aa9d3f0a02b238d08d14fb1d9
+    4c61f24d2263168cc50b2d3126
+    2674528444adc656d5bfe3915849a064;
+  0ae3f419ecb52b0ad24cd246361f779e8317e94977c576fa69209a292924f04f
+    b5b3469a1068bd9a06e9ac90f02ad095
+    13ecfde29e5a9f5ff20fae44744397d7
+    58be1a2775d5b0424b7e9ef4450e9e34;
+  613cc2a6b7773965bca0c2ae6237e9f702b75a0852be1830c2e689f1ec9d6599
+    b75c7b15e30e188d84c96d7de9ad41ae
+    e3c34ccd80ca28706fdcd10562bd60cd
+    466ece9c2f57ebe70b744c210507d37f;
+  3555a5f38e5450a5cc5a7eeb9504288aee23298fb8
+    8dd256a0a99d55a277c1cebca95be232
+    6fa74dc1f5
+    0fdf1eba1901a220dce11aff114ba7a2;
+  23309eefbbc3fe8df211397e58df223596c695a8993be7d81ec52b
+    9891a51ece620fdeb8c4d1dad87f979b
+    4be153fb895358027814ae
+    7d23cf0b5d1b872877af14ab1b35ea49;
+  0175cde357bdd78d4672ea176521a9ef0c0e842d62cdef309b6ed2
+    cd41cb0292968ee9c82b353e07cd6e2d
+    037f62f06af153d6ad8c01
+    3d1533e7afd150b592fb196354585cff;
+  8705d678b201c2300a347083cae184ed
+    786ea38c016bbcc3e9f5c5b4662fdaec
+    03
+    0fb632ecb1bd0774302a3e5f6091ebd9;
+  0195d1b27b916f29264d0fd33696867bc9aea2f41dce71931886c5d898e25f69
+    93a948c2e26a36dc13a1754a80cdaf8c
+    034aeb96693c049c2af77e1a7b277a5e
+    3d9d04738de1dc0a7654b8115a7ee1e1;
+  79090e88e87a94e1eb7f7ebe3147bdde846170
+    eb67415f279248028ae4052f72d48092
+    9686d1
+    7100e616ea381ee5d0b2ffb7a67ee942;
+  f254423fef93d5d7a76ecf22c656c1352c53257875945d33
+    b2ca471b0867d5fae2e4f27a2d2706da
+    01bad680bd4a0132ee
+    582f783fc210f72814780e69b0bd29ff;
+  c9bd4858bd014860f6d95dabb9a5d3d231
+    c1ff2aefeb9d6cc4ac6ae0c0535d8c13
+    011f
+    17949a58ebcb086a5350c3aceffbc4e0;
+  0b8915613beb2e89cdb36b69b7d62ef2b0197537793f71
+    242f42cdf08598d86d812a11c5647b75
+    56ddd25003c7e7
+    1aa0da3ff44f29eb5db54ea6a970dd5a;
+  e03c7f839598081d2c42f4e503484e7a4a219d0149561f3d5cbed8
+    6503cea0d8a0c6a227143d96d7cad509
+    02c53788cff1530e65640225
+    078acf15737c0320afbac57f23098cd5;
+  0165144c6d0637f8cb21bc8913188186376755bbd790566f32612993fec931
+    8ab74399da1f1a01a91521d73d12b0d9
+    02ed5b96b580b772606cb77ff49191
+    58d92bf9fb6f5fb9f0975b3e2f5ad1f8;
+  02b35947d2f507a817cb9e178bd6bcaa1d9054979482efb1ef
+    56cebd75069fe534091d8409575702cf
+    08114f9866c8343218
+    2504e1784d51b5c26cad8df6357b0567;
+  109978bc6b8824b04e113fa2a4c982bd2b93a027fd08ad69227a51506bdc11
+    12c061be0756685473011c61067dc241
+    012013fcb240a4d4f394c40f357c666b
+    040d8ec7359c8fa7cb6864bb6fe2b6ba;
+  0240b50d2853d690a8cf355e9d79626c6cb5f996cccfee3e1be7eed633
+    d233771cc22b3724a3d14382766cce97
+    07b0d38444572f483317b557d4
+    7b499146cd46dab3812cf4691d3bbe5f;
+  025e90153ae473c9bee43aafaec084468698e5d4eede21f8d4
+    791d69fc4cfb227b4bb531b633dfcb80
+    0d396769c6e551b981
+    0f0854faf0c35a4ffa142b21d0047354;
+  0de9af086a7b5a69231741ad28f72df187515e355dd8dfd9b10bfc6e87f1
+    1a5dbee5bbc0980ab55fae3b6135fca9
+    89b00eb8894915d87ca6943ac6fd
+    06fa712cefe56e4dddbccc3b389d7bc4;
+  12333fa824ddf35aa1b7de856a919b5864e94c3d63ce94
+    84c4a1d9a55cde37b41ce04d4c292491
+    257b652b91361c
+    6b6611dde69c73a3bdde7b6fd01d6748;
+  038b2304265ac16c80f84be3d61a82628ae2
+    730b3374140b33de67be248766cc7183
+    0864
+    1519f8ad4b7430e93c72ce04104d044e;
+  1d09aead497b4383dc45da08fac2950fde1e
+    d78d23956daf24a70ed9513d8185e988
+    2b5e
+    227af9cc9eff71a25a89d3a5f95fc5ee;
+  01ff9215d5fc0b3149589a96c76555a7145a7699ed03b125da8c0221ae0ea630
+    e97791f445493fa4c2858c63e89de9b1
+    027c8467e27a018bbb903b85aeeff4c1
+    79ff4a78de0c7c1a9a87d63368ddcf41;
+  033c9edec4c98b26c1bd29dd6c33418bf678921a705fe94ba8f4
+    1f200f0df4aae402308e4d3747ea3b62
+    2b085586f038a6997a7a
+    095479470eacc695a289163c245933c0;
+  01a8722b24be8d9404cc9b836ab0b739ee57ae60ed
+    0ba579d54afea4a7386c2ae3664c3d93
+    3e54693717
+    0619d78694ac997bedf949a21bf9a024;
+  112bf3440706f9935e8221356e908bdd1972bc0b7d4540a76c779d845f604fc2
+    2d27eaf11c8af56eab46d787c409293a
+    b779548b4b726be09029b5b6e414316b
+    1498f6cd6bbed85fe55529a41188ce9c;
+  5fbb399787dc1c088ae1b1a868a8fd68071662aebe6859d764d8c66d
+    0ae272c16095b2e0b88f60f0bb2c77c1
+    09593fefe3ac800d34fa59a9d1
+    022c8aa8970653e5946394aaf55db47c;
+  0ba36adf7f6695ffcaf3cb4f671fcf1167c79f
+    d24e71e6be0662a608ddaac25c3174b7
+    1836b1
+    5a783d61e236025be73de15c60fb1738;
+  28b2a0867669dbc51f86661c3a1f6a1d5565284547a3f4f2f934
+    22bd5df7bc0c1e6a863a1a1c448733e7
+    01540ca5dc8900d40c3dd7
+    0eb263f6f9b698becce9b975cac485b1;
+  15503e6802be9c85711f75250539c76426f91b77
+    91cc2ed96c4eee210ed0cb5251934085
+    2f2129de
+    5430a3c98a336b14edef0d41d93dfad1;
+  011816c74ce3765423825661feba199268be5453932b36d6
+    a8a09df55f7606d260f79ad1825ec8ac
+    02b46a057ab9b6d8
+    5d970c88da5e61edfcf5b0afb7112c76;
+  0e58c4591e74eede082861a82117d4d41239247c
+    22afdfd47592ee3f4e9777003ee9e7ad
+    7437cb93
+    0faa41dc7710ab02ea755b778975ffdb;
+  019717a6f636f25b0467f5ae365c2ba5b8
+    801bf58c5282787aec5c66702e80efd5
+    03
+    173bb862c174d38b531104a62faa95c7;
+  1af0354e3dfc333b46c5efa3354f8a0cb6bb41
+    8d59fafe11fd9b7a2f687a13696d4315
+    375fa9
+    1993cbf7dfda1e1ce89c043dc306dbdc;
+}
diff --git a/math/t/group b/math/t/group
new file mode 100644 (file)
index 0000000..a2a820f
--- /dev/null
@@ -0,0 +1,318 @@
+# Test group abstraction, and a bunch of other things.
+
+check {
+  "prime { 29, 7, 16 }" "ok";
+  "prime { 29, 6, 5 }" "not a subgroup";
+  "prime { 21, 2, 2 }" "p is not prime";
+  "prime { 29, 14, 9 }" "group order not prime";
+
+  "ec { secp224r1 }" "ok";
+
+  "prime { catacomb-ll-160-1024 }" "ok";
+
+  "ec {
+     prime:
+       0xdb7c2abf62e35e668076bead208b
+     primeproj:
+       0xdb7c2abf62e35e668076bead2088, 0x659ef8ba043916eede8911702b22
+     0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500
+     0xdb7c2abf62e35e7628dfac6561c5 * 1
+  }" "ok";
+
+  "ec {
+     prime:
+       0xdb7c2abf62e35e668076bead208b
+     primeproj:
+       0xdb7c2abf62e35e668076bead2088, 0x659ef8ba043916eede8911702b22
+       0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500
+       0xdb7c2abf62e35e7628dfac6561c5 * 2
+  }" "incorrect or ambiguous cofactor";
+
+  # --- This one's oakley-155 ---
+
+  "ec {
+    binpoly: 0x0800000000000000000000004000000000000001
+    binproj: 0, 0x7338F
+    0xaa089ae4666a422e714651ad9372213fa65a93,
+      0x12d29c630dda76010397809a6816be6d2ffa815
+    0xaaaaaaaaaaaaaaaaaab1fcf1e206f421a3ea1b * 12
+  }" "degree not prime";
+
+}
+
+checkelt {
+  "prime { 29, 7, 16 }" 16 0;
+  "prime { 29, 7, 16 }" 2 -1;
+
+  "ec { secp112r1 } "
+    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
+    0;
+
+  "ec {
+    binpoly: 0x0800000000000000000000004000000000000001
+    binproj: 0, 0x7338F
+    0xaa089ae4666a422e714651ad9372213fa65a93,
+      0x12d29c630dda76010397809a6816be6d2ffa815
+    0xaaaaaaaaaaaaaaaaaab1fcf1e206f421a3ea1b * 12
+  }"
+  "0x7b, 0x1c8"
+  -1;
+
+}
+
+mul {
+  "prime { 29, 7, 16 }" 8 7 27;
+
+  "prime { catacomb-ll-128-512 }"
+    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
+    32459289443738057373904596685867555624839649360339363831766212033645755638497600605981483758068704145575847399920657057013890131443911836862688141735006
+    3947634573386515057215934636174241616115542585724861166389751782289048647501330677434616929656928819642658111077814577650964230037753641582364366136933940;
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
+}
+
+sqr {
+  "prime { 29, 7, 16 }" 8 6;
+
+  "prime { catacomb-ll-128-512 }"
+    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
+    1140714521254648115393410274780412972862841854751618635120376750594285456137894804866135103112174518443866054055338095672091997366768745026933347678925721;
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+}
+
+inv {
+  "prime { 29, 7, 16 }" 9 13;
+
+  "prime { catacomb-ll-128-512 }"
+    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
+    5876676858790113051879264634636727534122591023949326683791506203503263391580079717512212895466773363712551406785344528808275608153699681298608650332072384;
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
+}
+
+div {
+  "prime { 29, 7, 16 }" 9 5 25;
+
+  "prime { catacomb-ll-128-512 }"
+    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
+    1926426135381827210395257472845875618319108487720857260583372274154852182951667715700282388176779441854588992736540698662997833538400244234146123792411051
+    24069337702503046127918930405335466791703796668849861281722901639361967869381088162761943434867448224639537469251486209856612215080111132649928233405085;
+
+  "ec { nist-p192 }"
+    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
+       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
+     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
+       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
+}
+
+exp {
+  "prime { 29, 7, 16 }" 3 12 16;
+
+  "prime { 29, 7, 16 }" 3 -12 20;
+
+  "prime { catacomb-ll-128-512 }"
+    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
+    147362842169670001895012880214773009850
+    5743039465765061017258257285641279669186626264432710496849307123351095219091264933384359874588390730293795471675184250790999035405886273905917889887366080;
+
+  "prime { catacomb-ll-128-512 }"
+    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
+    -147362842169670001895012880214773009850
+    3548613102603269389984811279864031309564549180885835723408511495891024326106890973751615845620404633717662823827170012116865930893524976817060348977482376;
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    6277101735386680763835789423176059013767194773182842284081
+    inf;
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    3131675836296406071791252329528905062261497366991742517193
+    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
+      0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb";
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    3131675836296406071791252329528905062261497366991742517193
+    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
+      0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb";
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    -3131675836296406071791252329528905062261497366991742517193
+    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
+      0x3916ef6b34cbece1ac63c24da080cd97f107201fc5774904";
+}
+
+mexp-1 {
+  "prime { 29, 7, 16 }" 3 12 16;
+  "prime { 29, 7, 16 }" 3 -12 20;
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    3131675836296406071791252329528905062261497366991742517193
+    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
+      0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb";
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    -3131675836296406071791252329528905062261497366991742517193
+    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
+      0x3916ef6b34cbece1ac63c24da080cd97f107201fc5774904";
+}
+
+mexp-2 {
+  "prime { 29, 7, 16 }" 3 12 8 2 9;
+  "prime { 29, 7, 16 }" 3 -12 8 2 4;
+
+  "prime { catacomb-ll-128-512 }"
+   3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
+   -147362842169670001895012880214773009850
+   130340428707563070626027539288099297037336608388990593367322442443880297841210613523501678207607756678300142264348927299637006055881968995671289567513600
+   91626412351157168611316239052073981423
+   1022777063245982511046303002728993765008184164346724419524981660559588777350492245381260023136750231183070065817596986237402046431653662723677455952067221;
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    -3131675836296406071791252329528905062261497366991742517193
+    "0xea711858c23d92f9964655910bc90a197a915e90111cf11b,
+      0x664189a1d8b2bb24f2b2ac64b19e2178118842e6ba9f4ad5"
+    1110875761630725856340142297645383444629395595869672555585
+    "0xaa25bb0bf38b06821e8641c1afb8bc078dbe11c3cf9bc97,
+       0xf1a4c09d621fb52736f6010ae90e9bc9771ac017a62098f9";
+}
+
+toint {
+  "prime { 29, 7, 16 }" 15 0 15;
+  "prime { 29, 7, 16 }" 0 0 0;
+
+  "ec { nist-p192 }" inf -1 0;
+
+  "ec { nist-p192 }"
+    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    0 602046282375688656758213480587526111916698976636884684818;
+}
+
+fromint {
+  "prime { 29, 7, 16 }" 15 0 15;
+  "prime { 29, 7, 16 }" 0 0 0;
+  "prime { 29, 7, 16 }" 39527306161272833161358334459 0 19;
+
+  "ec { nist-p192 }" 1 -1 inf;
+  "ec { nist-p192 }" 0
+    0 "0, 0x7b685605ee600cb363db5ea912f2bb5e3a0a2e0e60360f12";
+}
+
+toec {
+  "prime { 29, 7, 16 }" 0 -1 inf;
+  "ec { nist-p192 }" inf 0 inf;
+  "ec { secp112r1 }"
+    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
+    0
+    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500";
+}
+
+fromec {
+  "prime { 29, 7, 16 }" inf -1 0;
+  "prime { 29, 7, 16 }" "39527306161272833161358334459, 9" 0 19;
+
+  "ec { secp112r1 }" inf 0 inf;
+  "ec { nist-p192 }" "1, 5" -1 inf;
+
+  "ec { secp112r1 }"
+    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
+    0
+    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500";
+}
+
+tobuf {
+  "prime { 29, 7, 16 }" 22 -1 "00";
+  "prime { 29, 7, 16 }" 22 0 "000116";
+  "prime { 29, 7, 16 }" 0 -1 "0000";
+  "prime { 29, 7, 16 }" 0 0 "000100";
+
+  "ec { secp112r1 }" inf 0 "0000";
+  "ec { secp112r1 }"
+    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
+    0 "000e09487239995a5ee76b55f9c2f098000ea89ce5af8724c0a23e0e0ff77500";
+  "ec { nist-p192 }"
+    "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"
+    0 "00010000188497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed";
+}
+
+frombuf {
+  "prime { 29, 7, 16 }" "00" -1 0;
+  "prime { 29, 7, 16 }" "000116" 3 22;
+  "prime { 29, 7, 16 }" "00000e" 2 0;
+  "prime { 29, 7, 16 }" "000100ff" 3 0;
+
+  "ec { secp112r1 }" "0000" 2 inf;
+  "ec { secp112r1 }"
+    "000e09487239995a5ee76b55f9c2f098000ea89ce5af8724c0a23e0e0ff77500f00d"
+    32 "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500";
+  "ec { secp112r1 }" "0001000001001ee7" -1 inf;
+  "ec { nist-p192 }"
+    "00010000188497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0eddead"
+    29, "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed";
+}
+
+toraw {
+  "prime { 29, 7, 16 }" 22 -1 "";
+  "prime { 29, 7, 16 }" 22 0 "16";
+  "prime { 29, 7, 16 }" 0 -1 "";
+  "prime { 29, 7, 16 }" 0 0 "00";
+  "prime { 4294967311, 364289, 18767 }" 4285559121 0 "00ff707151";
+  "prime { 4294967311, 364289, 18767 }" 4285559121 -1 "ff707151";
+
+  "ec { secp112r1 }" inf 0 "00";
+  "ec { secp112r1 }"
+    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
+    0 "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff77500";
+  "ec { nist-p192 }"
+    "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"
+    0 "040000000000000000000000000000000000000000000000008497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed";
+}
+
+fromraw {
+  "prime { 29, 7, 16 }" "" -1 0;
+  "prime { 29, 7, 16 }" "160bad" 1 22;
+  "prime { 29, 7, 16 }" "00" 1 0;
+  "prime { 4294967311, 364289, 18767 }" "00ff707151e7c0" 5 4285559121;
+  "prime { 4294967311, 364289, 18767 }" "ff707151" -1 0;
+
+  "ec { secp112r1 }" "" -1 inf;
+  "ec { secp112r1 }" "00" 1 inf;
+  "ec { secp112r1 }"
+    "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff775" -1 inf;
+  "ec { secp112r1 }"
+    "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff77500"
+    29 "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500";
+  "ec { nist-p192 }"
+    "070000000000000000000000000000000000000000000000008497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed00deadbeef"
+    49 "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed";
+}
diff --git a/math/t/mp b/math/t/mp
new file mode 100644 (file)
index 0000000..fe74f07
--- /dev/null
+++ b/math/t/mp
@@ -0,0 +1,326 @@
+# Test vectors for MP functions
+
+add {
+  5 4 9; 5 -4 1; -5 4 -1; -5 -4 -9;
+  0xffffffff 1 0x100000000;
+}
+
+sub {
+  5 4 1; 5 -4 9; -5 4 -9; -5 -4 -1;
+  4 5 -1; 4 -5 9; -4 5 -9; -4 -5 1;
+}
+
+mul {
+  5 4 20; -5 4 -20; 5 -4 -20; -5 -4 20;
+  0x10000 0x10000 0x100000000;
+}
+
+div {
+  9 4 2 1; -9 4 -3 3; 9 -4 -3 -3; -9 -4 2 -1;
+  -3 6277101735386680763835789423207666416083908700390324961279
+    -1 6277101735386680763835789423207666416083908700390324961276;
+  3131675836296406071791252329528905062261497366991742517193
+    1110875761630725856340142297645383444629395595869672555585
+    2 909924313034954359110967734238138173002706175252397406023;
+  3131675836296406071791252329528905062261497366991742517193
+    53
+    59088223326347284373419855274130284193613157867768726739 26;
+  1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919
+  776259046150354467565459065629240877815667024717257156601175597451483119974551053629334726938295821221455003840144432114575401859459023171316363806515641491872190410445098144254585345658296587683734775881559921685818610503605288959
+  2 1;
+}
+
+exp {
+  4 0 1;
+  4 1 4;
+  7 2 49;
+  3 564 124849745640593184256214502788000232711984346194239284918599169775251467106591187580476305077269760425019686159071753053924227569816588462643229463821875763427430576080998505780547826368760514503807579784278708008217584939464444237989070811887584423210788916656247499281;
+}
+
+bin2c {
+  and 5 3 1;
+  or 5 3 7;
+  xor 5 3 6;
+  1111 0 0 -1;
+  or 45 -7 -3;
+  xor 0x343cd5 -0x6a49c -0x32984f;
+}
+
+lsr2c {
+  -1 5 -1;
+  1 5 0;
+  -6 2 -2;
+  5 0 5;
+  -4 0 -4;
+  7 2 1;
+ -7 2 -2;
+  -7 20 -1;
+}
+
+lsl2c {
+  -1 5 -32;
+  5 0 5;
+  -4 0 -4;
+  7 2 28;
+  -7 2 -28;
+  0xc0000000 1 0x180000000;
+  -0xc0000000 1 -0x180000000;
+  -1 32 -0x100000000;
+}
+
+setbit {
+  0 40 0x10000000000;
+  0x87348 40 0x10000087348;
+  5 1 7;
+  7 1 7;
+  -3 1 -1;
+}
+
+clrbit {
+  0x10000000000 40 0;
+  0x87348 40 0x87348;
+  5 1 5;
+  7 1 5;
+  -1 1 -3;
+}
+
+neg {
+  0 0;
+  15 -15;
+  -15 15;
+}
+
+odd {
+  1 0 1;
+  2 1 1;
+  4 2 1;
+  12 2 3;
+  0x10000000000000 52 1;
+  0x10000000400000 22 0x40000001;
+}
+
+sqrt {
+  0 0;
+  1 1;
+  4 2;
+  9 3;
+ 16 4;
+ 99 9;
+100 10;
+101 10;
+120 10;
+121 11;
+
+10106623487257186586 3179091613;
+14565040310136678240 3816417208;
+}
+
+gcd {
+  # --- Simple tests ---
+
+  16 12 4 -11 15;
+  12 16 4 -1 1;
+  693 609 21 -7 8;
+  4398082908043 90980984098081324 1 -32483863573352089 1570292150447;
+
+  # --- Negative argument tests ---
+
+  16 -12 4 -11 -15;
+  -16 12 4 11 15;
+  -12 -16 4 1 -1;
+  -12 16 4 1 1;
+  -693 609 21 7 8;
+  693 -609 21 -7 -8;
+
+  # --- Zero argument tests ---
+
+  15 0 15 1 0;
+  0 15 15 0 1;
+  -5 0 5 -1 0;
+  0 -5 5 0 -1;
+  0 0 0 0 0;
+
+  # --- Random number tests ---
+
+  829561629303257626084392170900075 32498098450983560651904114638965
+    5 -29340810037249902802634060204608 748967211613630574419802053172497;
+
+  5509672937670943767152343650729669537671508
+  398326674296699796695672966992514673531
+  17
+  -4158709420138833210339208344965073815
+  57523460582278135926717203882531035926727;
+
+  324098408098290809832490802984098208098324
+  23430980840982340982098409823089098443
+  1
+  -4158709420138833210339208344965073815
+  57523460582278135926717203882531035926727;
+
+  # --- RSA test ---
+  #
+  # The first number is (p - 1)(q - 1) from `mpmont'.  The second is a
+  # random number (it's actually prime, but that doesn't matter) which I
+  # can use as an RSA encryption exponent.  The last is the partner
+  # decryption exponent, produced using the extended GCD algorithm.
+
+  665251164384574309450646977867043764321191240895546832784045453360
+  5945908509680983480596809586040589085680968709809890671
+  1
+  -4601007896041464028712478963832994007038251361995647370
+  514778499400157641662814932021958856708417966520837469125919104431;
+
+  # --- Misery ---
+  #
+  # Some bugs discovered during RSA testing.
+
+  100000423751500546004561515884626739136961367515520675987004088469753859696407139054406989735113827981148062449057870561788973142250811838720214530386151198455545176591384352343648452329042764530196327665219224050630680827543991306749402959935685172017409062967157813233001567797128414009962262840951763040181
+  44895767034162990997987303986882660674722497505237491649296190658571471979065889234144353811843706629535512848235473808330181517421970135930320187227697512315919757806204341545022714991717913006031724818461724742069401359454784533576615919680949125073761586043027941204059690093447093117249681641020785611986
+  1
+  -44146175664861261172356293340716833133750232401287328189797639296698679436925232375473973898100363205157703913050824405116878299310008848005045714833814493992539429428295945643439440068026313232881493081836812480325977761600303456915493177366981470223898994906470419007730670657168179659899713837827764669213
+  98330790743257232930640417364963717704786040860302439189781385170246412183980882564239377268174203679366339563908361674571088519452885615348465535190260914996055274486493192655677181637142116473172979503236297658204730543049175626205461452256333155750566288282331419748434569978343545573401114593095927172889;
+
+  44895767034162990997987303986882660674722497505237491649296190658571471979065889234144353811843706629535512848235473808330181517421970135930320187227697512315919757806204341545022714991717913006031724818461724742069401359454784533576615919680949125073761586043027941204059690093447093117249681641020785611986
+  100000423751500546004561515884626739136961367515520675987004088469753859696407139054406989735113827981148062449057870561788973142250811838720214530386151198455545176591384352343648452329042764530196327665219224050630680827543991306749402959935685172017409062967157813233001567797128414009962262840951763040181
+  1
+  -1669633008243313073921098519663021432175326655218236797222703299507447512426256490167612466939624301781722885149508887217884622797926223371748995195890283459489902104891159687971270691900648057023348161982926392425950284494815680543941507679352016266842774684826393484566997818784868436561148247855835867292
+  749591369301729825631010646165827540972265103950163459498551361872792542140656858670379913743343424377808935184649403213303218111961287925274472393883018323380328377908395901583274923691599773150231736624912261743423597854481076661122742313967654849862591136557522196329019436278913457349967803193020942773;
+
+  # --- Some other bugs ---
+
+  19504439280113284806725522136967618725661733412699408177537810327183285842670
+  1
+  1
+  0
+  1;
+}
+
+modinv {
+  5 9 2;
+  15 64 47;
+  564566436 546457643 408896426;
+}
+
+jacobi {
+  4 5 1;
+  6 7 -1;
+  15 27 0;
+  2132498039840981 98729378979237498798347932749951 1;
+  98729378979237498798347932749951 2132498039840981 1;
+
+  # --- Kronecker extension ---
+
+  0 0 0;
+  1 0 1;
+  -1 0 -1;
+  2 0 0;
+
+  2132498039840981 197458757958474997596695865499902 -1;
+  98729378979237498798347932749951 4264996079681962 1;
+  98729378979237498798347932749951 -4264996079681962 1;
+  -98729378979237498798347932749951 -4264996079681962 -1;
+
+  # --- Random tests made by PARI/gp ---
+
+  22 -19 -1;
+  48 -37 1;
+  -13 29 1;
+  -19 2 -1;
+  -43 31 1;
+  -12 -7 -1;
+  -14 -34 0;
+  -30 -29 -1;
+  25 26 1;
+  -27 20 -1;
+  -5 -45 0;
+  9 -42 0;
+  -51 -3 0;
+  -39 35 -1;
+  37 30 1;
+  13 18 -1;
+  -28 6 0;
+  -49 -15 1;
+  -1 1 1;
+  -9 13 1;
+  -47 44 -1;
+  -14 -30 0;
+  37 -36 1;
+  45 9 0;
+  -29 30 -1;
+  49 49 0;
+  -27 -10 -1;
+  -35 -25 0;
+  17 14 -1;
+  -35 29 1;
+  -1 33 1;
+  38 -11 1;
+  3 -24 0;
+  5 -25 0;
+  -31 22 -1;
+  40 30 0;
+  -43 26 -1;
+  -22 10 0;
+  11 -29 -1;
+  40 -18 0;
+}
+
+modsqrt {
+  1 3 1;
+  4 5 2;
+  9775592058107450692 13391974640168007623 3264570455655810730;
+  8155671698868891620 10189552848261357803 2073812183305821596;
+  3248339460720824413 8976233780911635437 1220523478429582717;
+  3447751741648956439 10155704720805654949 2812971608818169892;
+  1453601744816463433 3095659104519735473 1260511572497628526;
+  3366261317119810224 3756232416311497601 610261287187759737;
+  3869491397135339653 5762828162167967567 2788500156455085147;
+  660864223630638896 1729533840094059799 671335997718840076;
+}
+
+modexp {
+
+  # --- Montgomery exponentiation ---
+
+  435365332435654643667 8745435676786567758678547
+    4325987397987458979875737589783
+    2439674515119108242643169132064;
+  0xfffffffdfffffffffffffffffffffffe 0 0xfffffffdffffffffffffffffffffffff 1;
+  1804289383 -8939035539979879765 8939489893434234331 6139425926295484741;
+
+  # --- Barrett exponentiation ---
+
+  435365332435654643667 8745435676786567758678547
+    4325987397987458979875737589782
+    2425191520487853884024972777945;
+}
+
+factorial {
+  0 1;
+  1 1;
+  2 2;
+  3 6;
+  4 24;
+  5 120;
+  30 265252859812191058636308480000000;
+  100 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000;
+  500
+   1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+}
+
+fibonacci {
+  -20 -6765;
+  -19 4181;
+  -10 -55;
+  -9 34;
+  -2 -1;
+  -1 1;
+  0 0;
+  1 1;
+  2 1;
+  5 5;
+  10 55;
+  19 4181;
+  20 6765;
+  100 354224848179261915075;
+  1000 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875;
+}
diff --git a/math/t/mpbarrett b/math/t/mpbarrett
new file mode 100644 (file)
index 0000000..c492ece
--- /dev/null
@@ -0,0 +1,133 @@
+# Test vectors for Barrett modular reduction
+
+mpbarrett-reduce {
+  17 11 6;
+  -17 11 5;
+
+  0x8ab316d0d1a2e88535cf77c1172881ead70d592c59e9c5fbc16e4b0c4dc49481
+  0x18ca3bf7ee3c6d7bab3f144b015ccc6c25472843d346b461
+  0x02c1815029b766b96ad4507dc1af8151307961c6d161d065;
+
+  0x8117d1663ee63341eb8faeff304549f0f8b32d587acc2fd5597ea6a31625881d
+  0xdc85df77dfb61876805623bcbed325b99d00c2cd65c252c879
+  0x395da02e8a6c66476467c4e04f328d8208cc411e3d1e96e14c;
+
+  0x63791966f2ad44a6df11bcc87c6b7c2400c74e69f7e3ca02fcac12b3bf56238b
+  0xa49e473b8f7539d89cdb002d73182558773eec10db93cc6049d8c5533e
+  0x65caf6833baa118b53c7bdc44a831605ca382b5993beead59f3971d13f;
+
+  0x9ca438db3e0f79305987292e8ec6174e6c313f7904ebb35a349a700e3ae63a37
+  0xb24c93d499c7073b8f7aac718c1f12da1a8fc8bccdd47b49
+  0x46393cb15e38cbbc8a85698151a113f28081b4c8f6ed232e;
+
+  0x8214fd17858a4a913015412b5331eb9654faeb5156a674b1e5f6550a68957146
+  0xc4f0ebaad6c0ee0111c57667ea8e0a254f3068f212949e20ededa89a7da6
+  0x3fde916ba21d19414d4316041420ca59d8b01aa2acf3f3ef106245c1915c;
+
+  0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa
+  0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773
+  0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6;
+
+  0xae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c
+  0xc33c890f030644d88cc65f8ccf99c625c9b9fa21d4eb153e52ef89df54130855
+  0xae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c;
+
+  0x65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc
+  0xd8a1d326fee87d55f39f15b5b2cfe71f5146083928
+  0x859c41164983547c03134b99530e25a0f874315964;
+
+  -0x65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc
+  0xd8a1d326fee87d55f39f15b5b2cfe71f5146083928
+  0x53059210b56528d9f08bca1c5fc1c17e58d1d6dfc4;
+}
+
+mpbarrett-exp {
+  4325987397987458979875737589783
+  435365332435654643667
+  8745435676786567758678547
+  2439674515119108242643169132064;
+
+  8939489893434234331 1804289383 454353454354565 6139425926295484741;
+  8939489893434234331 1804289383 8939489893434234330 1;
+
+  # --- Negative exponents ---
+
+  0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1;
+  8939489893434234331 1804289383 -8939035539979879765 6139425926295484741;
+
+  # --- DSA public key derivation ---
+
+  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
+  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  0x1234
+  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47;
+
+  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
+  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
+  0x23a252f60bae4907a8ed5b6203e2b1da32848cd9
+  0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074;
+
+  # --- Quick RSA test ---
+
+  905609324890967090294090970600361            # This is p
+  3
+  905609324890967090294090970600360            # This is (p - 1)
+  1;                                           # Fermat test: p is prime
+
+  734589569806680985408670989082927            # This is q
+  5
+  734589569806680985408670989082926            # And this is (q - 1)
+  1;                                           # Fermat again: q is prime
+
+  # --- Encrypt a message ---
+  #
+  # The public and private exponents are from the GCD test.  The message
+  # is just obvious.  The modulus is the product of the two primes above.
+
+  665251164384574309450646977867045404520085938543622535546005136647
+  123456789012345678901234567890123456789012345678901234567890
+  5945908509680983480596809586040589085680968709809890671
+  25906467774034212974484417859588980567136610347807401817990462701;
+
+  # --- And decrypt it again ---
+
+  665251164384574309450646977867045404520085938543622535546005136647
+  25906467774034212974484417859588980567136610347807401817990462701
+  514778499400157641662814932021958856708417966520837469125919104431
+  123456789012345678901234567890123456789012345678901234567890;
+
+  # --- Strange bug ---
+  #
+  # Strange memory corruption bug causing mpbarrett_reduce to hang.
+  # Seems to have vanished on a clean rebuild so maybe this was just build
+  # fluff or something.  Leave it here to pick up regression.
+
+  30916300184138066757562815127455898754391418637651479989257882011612153138316483396290143656363307389355307404813205623380378799585065876990874918745873480056891738964426752
+  2 44329
+  10975270953088118598390528358454369816072092233138947812823085741431681835772475760228604878294514156761050649439713085882651077696501584961485141097470430535290622475239424;
+}
+
+# --- Simultaneous exponentiation ---
+
+mexp-1 {
+  4325987397987458979875737589783
+  435365332435654643667
+  8745435676786567758678547
+  2439674515119108242643169132064;
+}
+
+mexp-2 {
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  0xbf655bd046f0b35ec791b004804afcbb8ef7d69d
+  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
+  0x821a926312e97adeabcc8d082b5278978a2df4b0
+  0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e;
+
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  0xbf655bd046f0b35ec791b004804afcbb8ef7d69d
+  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
+  -0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adabb090e849367fc31d4c6a97bac0b4be56a79a0de0
+  0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e;
+}
diff --git a/math/t/mpcrt b/math/t/mpcrt
new file mode 100644 (file)
index 0000000..89665b6
--- /dev/null
@@ -0,0 +1,19 @@
+# Test vectors for Chinese Remainder Theorem solution (Gauss's algorithm)
+
+crt-1 {
+  1 5 1;
+  3498243289823 4534543545463431 3498243289823;
+}
+
+crt-2 {
+  3 7 7 13 59;
+  39845 435435221 43534545 32423423467 13736097689153284731;
+
+  2200541929485233317342398 498459898455435345676576793
+  13046769915260439091721075347560767438958354488807168684311588308214063361125238823412234206191582332588 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493526197
+ 14756532044160797319048143986538019326281096778844833416304858521742332925502855547148214406728673769162624068049034315018936294558;
+}
+
+crt-4 {
+  2 5 1 7 3 11 8 13 2192;
+}
diff --git a/math/t/mpint b/math/t/mpint
new file mode 100644 (file)
index 0000000..9c3263d
--- /dev/null
@@ -0,0 +1,50 @@
+# Test vectors for conversion between MP ints and C ints
+#
+# The tests look messy because I'm fighting with atoi here as well as the
+# integer conversion routines I'm trying to test.
+
+fromuint {
+  0 0;
+  1 1;
+  -5 0xfffffffb;
+  0x7ffff 0x7ffff;
+  0x80000 0x80000;
+  0xfffff 0xfffff;
+  0x7fffffff 0x7fffffff;
+  0x80000000 0x80000000;               # Bastard torture test
+  0xffffffff 0xffffffff;
+}
+
+fromint {
+  0 0;
+  1 1;
+  -5 -5;
+  0x7ffff 0x7ffff;
+  0x80000 0x80000;
+  0xfffff 0xfffff;
+  0x7fffffff 0x7fffffff;
+  -0x80000000 -0x80000000;             # Bastard torture test
+}
+
+touint {
+  0 0;
+  1 1;
+  -5 -5;
+  0x7ffff 0x7ffff;
+  0x80000 0x80000;
+  0xfffff 0xfffff;
+  0x7fffffff 0x7fffffff;
+  0x80000000 -0x80000000;              # Bastard torture test
+  0xffffffff 0xffffffff;
+}
+
+toint {
+  0 0;
+  1 1;
+  -5 -5;
+  0x7ffff 0x7ffff;
+  0x80000 0x80000;
+  0xfffff 0xfffff;
+  0x7fffffff 0x7fffffff;
+  -0x80000000 -0x80000000;             # Bastard torture test
+}
diff --git a/math/t/mpmont b/math/t/mpmont
new file mode 100644 (file)
index 0000000..27e03c1
--- /dev/null
@@ -0,0 +1,113 @@
+# Test vectors for Montgomery reduction
+
+create {
+  340809809850981098423498794792349    # m
+  266454859                            # -m^{-1} mod b
+  130655606683780235388773757767708    # R mod m
+  237786678640282040194246459306177;   # R^2 mod m
+}
+
+mul {
+  43289823545
+  234324324
+  6456542564
+  10807149256;
+
+  51518627314818829164222247085233898246715229794943812733936714788310185005015428803253311691709787911812368198649776769324928993075889524373913555618270874746833913595051625422038974326537979654635530320271853851973343513053953211672797425464186157719021174955241645388345195723368057041032310152242301620397
+  7041548659011846562361842096561083537784928869240554198760844555642215260669458833049231069318370838770180094409088437631986867239713464317243824963669990014087444248250948204574690463940534304651099653802302150197753463246181762684347288736386534346725039618007392334267637262008343417972878515511486456037
+  21451817224897484023627307128311082613304580637202546848860538836010530320943159719981586919811151828606838777812233053319458755053306547823820900602281867134174742586071226220962576712633552196944784360512851517812225731562588375896089193406088239903885470354101095713609394462435076126493339021945199401247
+  48192532305912989641372170084506981675917951543147719789775743631071830656350879578731578070582102149232280305157616093002880139716311910835926678896882798493523792373475521651115163420137602661060123597773253524671874189844988793471524978853764238038494563159505836018994860909028653670132922744758133798212;
+}
+
+exp {
+  4325987397987458979875737589783
+  435365332435654643667
+  8745435676786567758678547
+  2439674515119108242643169132064;
+
+  # --- Bizarre bug ---
+  #
+  # This was caused by omission of the test-and-subtract step in the
+  # Montgomery reduction.
+
+  8939489893434234331 1804289383 454353454354565 6139425926295484741;
+  8939489893434234331 1804289383 8939489893434234330 1;
+
+  # --- Negative and zero exponents ---
+
+  0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1;
+  8939489893434234331 1804289383 -8939035539979879765 6139425926295484741;
+
+  # --- DSA public key derivation ---
+
+  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
+  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  0x1234
+  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47;
+
+  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
+  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
+  0x23a252f60bae4907a8ed5b6203e2b1da32848cd9
+  0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074;
+
+  # --- Quick RSA test ---
+
+  905609324890967090294090970600361            # This is p
+  3
+  905609324890967090294090970600360            # This is (p - 1)
+  1;                                           # Fermat test: p is prime
+
+  734589569806680985408670989082927            # This is q
+  5
+  734589569806680985408670989082926            # And this is (q - 1)
+  1;                                           # Fermat again: q is prime
+
+  # --- Encrypt a message ---
+  #
+  # The public and private exponents are from the GCD test.  The message
+  # is just obvious.  The modulus is the product of the two primes above.
+
+  665251164384574309450646977867045404520085938543622535546005136647
+  123456789012345678901234567890123456789012345678901234567890
+  5945908509680983480596809586040589085680968709809890671
+  25906467774034212974484417859588980567136610347807401817990462701;
+
+  # --- And decrypt it again ---
+
+  665251164384574309450646977867045404520085938543622535546005136647
+  25906467774034212974484417859588980567136610347807401817990462701
+  514778499400157641662814932021958856708417966520837469125919104431
+  123456789012345678901234567890123456789012345678901234567890;
+
+  # --- Regression ---
+
+  3986624077014487421577005607434178981611827907415414229383186257799185035259267946499319317546248903815958429965343062841026732183070884484415037389112766124480881891335541864933360040451772640848433986354946570483859801429553601029855169093153120649968457991955067742589996787220443833463413655161718521778024152687493646856649224308444934694934177848997119462792993163729623894124424825605063456003809024630116233635811919734143467917391222413748618664640084816819791040047135721631646389562380726980090637225607902904093720467390446340147754975063914238763877962986901317873962501987398883284691263121949707967483
+  2169501609694605731113683435915932024263931111070470928071742781553833481227229665038394569450673541955381439893533586899516369125587996614390351130855433932967123352056637148142399218614659226596196082977912512097782590337133839376057748669786776861900003976657975002808400242688631641605350346310303557783077961976578644612942618488786721156576047036803063809499458142391930097492829437793780428298460587910313123127299017105180518995858168981798364124607742910479678852164938149352363613709839015911625193499208078080300810729238501127706236236987807659841302058153641198634312186169690290317377895433013774581020
+  51190650099377934681679689372059155651634030541122059023228371179527051284414
+  2182336244564627050476203952083643687109210844491929333865487949231032236266424033053219865356293652087346833773990958617081657598928894294027838097457060132084513275728637155311686562443969707442331856969523833049082440569661820589637161378175422424940183890787723213162895088451684485064228413121825045190532424942855250521728705814032313019282814300698512615465322506857392325469773301168485302267577566759375501214494771698910873834970265937979350795050000891405548412798945017578510891723221844676960980502437259841806090144299798005080365645221451715661064400809603224286845878809241930399832108000526121054958;
+}
+
+# --- Simultaneous exponentiation ---
+
+mexp-1 {
+  4325987397987458979875737589783
+  435365332435654643667
+  8745435676786567758678547
+  2439674515119108242643169132064;
+}
+
+mexp-2 {
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  0xbf655bd046f0b35ec791b004804afcbb8ef7d69d
+  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
+  0x821a926312e97adeabcc8d082b5278978a2df4b0
+  0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e;
+
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  0xbf655bd046f0b35ec791b004804afcbb8ef7d69d
+  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
+  -0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adabb090e849367fc31d4c6a97bac0b4be56a79a0de0
+  0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e;
+}
diff --git a/math/t/mpreduce b/math/t/mpreduce
new file mode 100644 (file)
index 0000000..2fb8f09
--- /dev/null
@@ -0,0 +1,31 @@
+# Tests for efficient reduction
+
+reduce {
+  0xc000 0x16cb3 0xacb3;
+  0x8000 0x345545 0x5545;
+
+  0xfffef 0x100000 0x11;
+
+  0x1ffffffe 0x26fc6567 0x6fc6569;
+  0x3ffffffe 0x45445dc0 0x5445dc2;
+  0x7ffffffe 0xd4827a70 0x54827a72;
+
+  0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773
+  0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa
+  0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6;
+
+  0xfffffffdffffffffffffffffffffffff
+  0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b
+  0xa019c198b9d9d9fb4440f7bc415ff5e4;
+}
+
+modexp {
+  0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1;
+  0xfffffffdffffffffffffffffffffffff 2
+    0xfffffffdfffffffffffffffffffffffe 1;
+  0xfffffffdffffffffffffffffffffffff 2
+    0xfffffffdfffffffffffffffffffffffd
+    0x7fffffff000000000000000000000000;
+  8939489893434234331 1804289383
+    -8939035539979879765 6139425926295484741;
+}
diff --git a/math/t/mptext b/math/t/mptext
new file mode 100644 (file)
index 0000000..fadaef6
--- /dev/null
@@ -0,0 +1,88 @@
+# Test vectors for MP textual I/O
+
+mptext-ascii {
+  # --- Perfectly valid things ---
+
+  10 0                                 10 0 "";
+  0 0                                  10 0 "";
+  10 52                                        10 52 "";
+  10 654365464655464577673765769678    10 654365464655464577673765769678 "";
+  10 654365464655464577673765769678    16 8425e6d06f272b9a2d73ed1ce "";
+  10 596569802840985608098409867       8 366570443501403714657464766613 "";
+  16 8425E6D06F272B9A2D73ED1CE         10 654365464655464577673765769678 "";
+  0 654365464655464577673765769678     16 8425e6d06f272b9a2d73ed1ce "";
+  0 16_8425E6D06F272B9A2D73ED1CE       10 654365464655464577673765769678 "";
+  0 -0x8425E6D06F272B9A2D73ED1CE       10 -654365464655464577673765769678 "";
+  0 -8_366570443501403714657464766613  10 -596569802840985608098409867 "";
+  8 -366570443501403714657464766613    10 -596569802840985608098409867 "";
+  0 0366570443501403714657464766613    10 596569802840985608098409867 "";
+
+  # --- Bogus things ---
+
+  10 "" 0 0 "";                        # Empty string fails
+  10 foo 0 0 "foo";            # Non-numeric character
+  10 134f 10 134 "f";          # Stop parsing when reaching `f'
+  4 12345 10 27 "45";          # Stop parsing when reaching `4'
+  0 63_ 10 63 "_";             # 37 is an invalid base, so stop at `_'
+  0 36_ 0 0 "";                        # 36 is a valid base, so restart and fail
+
+  # --- Big bases ---
+
+  62 0 10 0 "";
+  10 0 62 0 "";
+  36 A 10 10 "";
+  36 Z 10 35 "";
+  37 A 10 36 "";
+  10 36 37 A "";
+  62 Z 10 61 "";
+
+  0 36_a 10 10 "";
+  0 36_A 10 10 "";
+  0 37_A 10 36 "";
+
+  0 0x10 10 16 "";
+  0 0o10 10 8 "";
+  0 0b10 10 2 "";
+  0 010 10 8 "";
+
+  # --- Word-boundary tests for binary-radix translation ---
+
+  0 0                                  16 0 "";
+  8 1234567012                         8 1234567012 "";
+  8 12345670123                                8 12345670123 "";
+  8 123456701234                       8 123456701234 "";
+
+  16 1234567                           16 1234567 "";
+  16 12345678                          16 12345678 "";
+  16 123456789                         16 123456789 "";
+
+  10 -4009356060                       16 -eef9eb1c "";
+
+  # --- Cussidness ---
+
+  0 -0                                 10 0 "";
+
+  # --- Bugs ---
+
+  16 84d192cd06ae59691897fa409da6198d5269325d
+  16 84d192cd06ae59691897fa409da6198d5269325d "";
+
+  16 -9802d5c5d5a73f9d4e694a8920f95231b4017f3ec6a4654ace3fa3d85879e5964dade0e051d57f13c275dab1df3da5331f39271efb2792d1dad4460fd5eb5c21fbf355456f523e5631e623074ff9b3e85cf5e0a9336c8d8b8621b24c4e625800ee0152d12c8e22658a66ade38cb4453ab6e4958114717355186649a6cc20d9f5ae2207f99814965035072a9f2121c8f9dd22ab134181378906291aae97287b62a2f592bbceb4198c9cd78e1968bf1e16865c3c6ce9c777232f186b5da240a24523a07faca9de44eba510c91917e099372e67a6a66e93fe7aaefcb9c5485e1a889eae721ab6407586880a95575a968b43bdf50323627aa0fcddfa4e198b0008
+  10 -74959454570640520505374182178324326240748657042677990093617716411759477136824854815262670168473667077524864904515489090301434501507378472350618141578200289566815110468728966378289347050752371322168328511598641143081017162500179880923097593329564317427467179672704707842937085621549781627579801356509572397210965270406925309382945647493757499822518272539171346319468210919037390479279679328187057939609889863122790083219768061816093131875491575840052493376341193028052061557296969558099473333023971577236615940525630787016398581105441977909848659239970133974969366933817929047771871736452423855320657946133173829640 "";
+
+  10 687036505685680036980563991304827689190226068191165515873309582371531653761560838357887565473014960851061079052387145199258972778940173525017542879674305252823453991900595437468144352005006881129612951699750949026636206282574720840178116341517038998609517724307448384647380133273761360084019113505091720961437658149042479826982973196933684563380877276612883608481996579884762706391098995123384485837872544276099219443948234067623442105312332114374763392077663374681230289067615025968182722516808457505932863951619224171887832194148545132638772027329666389477813640620737624951105503846166715576529533580414958055708947608220960395455545922617914622611716584821091744228076205865701038484061060900340103461251087987631583104425599437283952841086221737575051158322973751353914369450945591184550003693808660890173148206999627057352641910478408389852121815588924208719373851205997267929487223022997903565246821511833717944887785333763131071163649350968541111796906733695518487580626938892775883629672280655177072837819344983336811201072380418330154409415723975489649421805372088286721361996667976678161505679350285875598457893785891475462099191282531966080162136450154198672623485698300307676277037616099696441730508788295411634665370788798384809584417102543248560317224205079917990766513568040641690632751952309869792602319263342525778046078743231821682847703178976601855555261436480615639995150308874740741630953255447186244703692652027199198662385455033073594432232250325046519267763604243367272471024553800469955272676941568451192546782745963075159357666087761637705388608592656535848292947073782242206595438203903079185128849386496430347274188109070907185471363018498891836986716946253163675821471661778024303689714601286352436391739170368727508436484115845640636653283093361670039386061546795520151041150800979484160765783927564359393959237330742523328888527872599693558141880251962681735003114604660394550415472363991770499647732372855076408144546777820449665557724138072899691283182780416000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+  10 687036505685680036980563991304827689190226068191165515873309582371531653761560838357887565473014960851061079052387145199258972778940173525017542879674305252823453991900595437468144352005006881129612951699750949026636206282574720840178116341517038998609517724307448384647380133273761360084019113505091720961437658149042479826982973196933684563380877276612883608481996579884762706391098995123384485837872544276099219443948234067623442105312332114374763392077663374681230289067615025968182722516808457505932863951619224171887832194148545132638772027329666389477813640620737624951105503846166715576529533580414958055708947608220960395455545922617914622611716584821091744228076205865701038484061060900340103461251087987631583104425599437283952841086221737575051158322973751353914369450945591184550003693808660890173148206999627057352641910478408389852121815588924208719373851205997267929487223022997903565246821511833717944887785333763131071163649350968541111796906733695518487580626938892775883629672280655177072837819344983336811201072380418330154409415723975489649421805372088286721361996667976678161505679350285875598457893785891475462099191282531966080162136450154198672623485698300307676277037616099696441730508788295411634665370788798384809584417102543248560317224205079917990766513568040641690632751952309869792602319263342525778046078743231821682847703178976601855555261436480615639995150308874740741630953255447186244703692652027199198662385455033073594432232250325046519267763604243367272471024553800469955272676941568451192546782745963075159357666087761637705388608592656535848292947073782242206595438203903079185128849386496430347274188109070907185471363018498891836986716946253163675821471661778024303689714601286352436391739170368727508436484115845640636653283093361670039386061546795520151041150800979484160765783927564359393959237330742523328888527872599693558141880251962681735003114604660394550415472363991770499647732372855076408144546777820449665557724138072899691283182780416000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 "";
+}
+
+mptext-bin-in {
+  -10 010203040506070809 10 123456789 "";
+  -100 01172d4359 10 123456789 "";
+  -90 09124709 10 6713199 "";
+}
+
+mptext-bin-out {
+  10 123456789 -10 010203040506070809 "";
+  10 123456789 -100 01172d4359 "";
+  10 6713199 -90 09124709 "";
+  10 0 -10 00 "";
+}
diff --git a/math/t/mpx b/math/t/mpx
new file mode 100644 (file)
index 0000000..bf104e9
--- /dev/null
@@ -0,0 +1,888 @@
+# Test vectors for low-level MP functions
+
+# --- Load-store tests ---
+#
+# The test loads each number, as both big- and little-endian, and compares it
+# against the original octet version using a different method.  It then
+# stores the value to another octet array and compares.  This is done for
+# various sizes of MP, to ensure that truncation works correctly.
+
+load-store {
+  "";
+  00;
+  0123;
+  0123456789abcdef0123456789abcdef0123456789ab;
+  00000123456789abcdef01234789abcdef0123456789ab;
+  0123456789abcdef23456789abcdef0123456789ab0000;
+  80f8c5606bff51bac932859a4fb6331c4023b32b65cd95f4edc1d1c919fcc078;
+  522f8b1de257972a25ec49c9ff56340e2684e847ef2fa4d5714d7c8d454e90f6;
+}
+
+# --- Two's complement tests ---
+
+2cb {
+  "" "";
+  00 00;
+  000000 00000000000000000000;
+  01 ff;
+  0123456789abcdef fedcba9876543211;
+  0123456789abcdef fffffffedcba9876543211;
+  0100000000 ffffff00000000;
+  00000000c1a4bc4b ffffffff3e5b43b5;
+  ffffffff3e5b43b5 00000000c1a4bc4b;
+}
+
+2cl {
+  "" "";
+  00 00;
+  000000 00000000000000000000;
+  01 ff;
+  efcdab8967452301 1132547698badcfe;
+  efcdab8967452301 1132547698badcfeffffffff;
+  0000000001 00000000ffffffff;
+  4bbca4c100000000 b5435b3effffffff;
+  b5435b3effffffff 4bbca4c100000000;
+}
+
+# --- Shift tests ---
+
+lsl {
+  # --- Simple sanity checks ---
+
+  01 2 04;
+  01 4 10;
+
+  7 -1 0;
+
+  # --- Copy shifts ---
+
+  01 0 01;
+  0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef;
+
+  # --- Single bit shifts ---
+
+  01 1 02;
+  ff000000 1 01fe000000;
+
+  # --- Word-size shifts (assumes 32-bit words) ---
+
+  0123456789abcdef0123456789abcdef 32
+  0123456789abcdef0123456789abcdef00000000;
+
+  # --- Random tests ---
+
+  13bbec3a734e0b8b5155600b0826b913 90
+  4eefb0e9cd382e2d4555802c209ae44c0000000000000000000000;
+
+  d6ca6a99fe49b256f80e9643e2bd4f3e 80
+  d6ca6a99fe49b256f80e9643e2bd4f3e00000000000000000000;
+
+  c94784b40d54de614084915915531ddc 59
+  064a3c25a06aa6f30a04248ac8aa98eee000000000000000;
+
+  a63c314a39cc37f950b3d530c95ead00 84
+  0a63c314a39cc37f950b3d530c95ead00000000000000000000000;
+
+  842d03a339f5004cfd311e2bb23216ac 62
+  210b40e8ce7d40133f4c478aec8c85ab0000000000000000;
+
+  9a8e659739bf9ee7aa908b7c058c5e7e 123
+  04d4732cb9cdfcf73d54845be02c62f3f0000000000000000000000000000000;
+
+  287f5774f212db87bcd83a1bbb7b1ad5 6
+  0a1fd5dd3c84b6e1ef360e86eedec6b540;
+
+  ec1739174d9d4438d3093cf378605a5c 63
+  760b9c8ba6cea21c69849e79bc302d2e0000000000000000;
+
+  3dfa8ad6a60a783639d05aa5fbfd993d 46
+  0f7ea2b5a9829e0d8e7416a97eff664f400000000000;
+
+  e4e93a80b6d25b34c23aca3a0d06d76c 63
+  72749d405b692d9a611d651d06836bb60000000000000000;
+
+  5a4cf5becb4b64a1a31637c91b6415fd 102
+  16933d6fb2d2d92868c58df246d9057f40000000000000000000000000;
+
+  d92f60928b67416c1e20bd9e09026115 69
+  1b25ec12516ce82d83c417b3c1204c22a00000000000000000;
+
+  eae78f56200d7734f7eb68479fe09d51 18
+  03ab9e3d588035dcd3dfada11e7f8275440000;
+
+  4c9c215ead951513d969d66614016f6e 28
+  04c9c215ead951513d969d66614016f6e0000000;
+
+  5cb1e4d625eac0393644fe6a7e3ff788 33
+  b963c9ac4bd580726c89fcd4fc7fef1000000000;
+
+  68b23795968766c77b1897c88a5d6ba8 78
+  1a2c8de565a1d9b1dec625f222975aea00000000000000000000;
+
+  3d96cd168c74f9015afb691d629f3f6d 72
+  3d96cd168c74f9015afb691d629f3f6d000000000000000000;
+
+  38fa8f63dc426399e0f9b5c01231e02c 95
+  1c7d47b1ee2131ccf07cdae00918f016000000000000000000000000;
+
+  90176b493061899ec95677ccc58b8cdf 78
+  2405dad24c186267b2559df33162e337c0000000000000000000;
+
+  0706e95da68f32a4231ab184d16cbff7 33
+  0e0dd2bb4d1e654846356309a2d97fee00000000;
+}
+
+lslc {
+  # --- Simple sanity checks ---
+
+  01 2 07;
+  01 4 1f;
+
+  7 -1 0;
+
+  # --- Copy shifts ---
+
+  01 0 01;
+  0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef;
+
+  # --- Single bit shifts ---
+
+  01 1 03;
+  ff000000 1 01fe000001;
+
+  # --- Word-size shifts (assumes 32-bit words) ---
+
+  0123456789abcdef0123456789abcdef 32
+  0123456789abcdef0123456789abcdefffffffff;
+
+  # --- Random tests ---
+
+  13bbec3a734e0b8b5155600b0826b913 90
+  4eefb0e9cd382e2d4555802c209ae44fffffffffffffffffffffff;
+
+  d6ca6a99fe49b256f80e9643e2bd4f3e 80
+  d6ca6a99fe49b256f80e9643e2bd4f3effffffffffffffffffff;
+
+  c94784b40d54de614084915915531ddc 59
+  064a3c25a06aa6f30a04248ac8aa98eee7ffffffffffffff;
+
+  a63c314a39cc37f950b3d530c95ead00 84
+  0a63c314a39cc37f950b3d530c95ead00fffffffffffffffffffff;
+
+  842d03a339f5004cfd311e2bb23216ac 62
+  210b40e8ce7d40133f4c478aec8c85ab3fffffffffffffff;
+
+  9a8e659739bf9ee7aa908b7c058c5e7e 123
+  04d4732cb9cdfcf73d54845be02c62f3f7ffffffffffffffffffffffffffffff;
+
+  287f5774f212db87bcd83a1bbb7b1ad5 6
+  0a1fd5dd3c84b6e1ef360e86eedec6b57f;
+
+  ec1739174d9d4438d3093cf378605a5c 63
+  760b9c8ba6cea21c69849e79bc302d2e7fffffffffffffff;
+
+  3dfa8ad6a60a783639d05aa5fbfd993d 46
+  0f7ea2b5a9829e0d8e7416a97eff664f7fffffffffff;
+
+  e4e93a80b6d25b34c23aca3a0d06d76c 63
+  72749d405b692d9a611d651d06836bb67fffffffffffffff;
+
+  5a4cf5becb4b64a1a31637c91b6415fd 102
+  16933d6fb2d2d92868c58df246d9057f7fffffffffffffffffffffffff;
+
+  d92f60928b67416c1e20bd9e09026115 69
+  1b25ec12516ce82d83c417b3c1204c22bfffffffffffffffff;
+
+  eae78f56200d7734f7eb68479fe09d51 18
+  03ab9e3d588035dcd3dfada11e7f827547ffff;
+
+  4c9c215ead951513d969d66614016f6e 28
+  04c9c215ead951513d969d66614016f6efffffff;
+
+  5cb1e4d625eac0393644fe6a7e3ff788 33
+  b963c9ac4bd580726c89fcd4fc7fef11ffffffff;
+
+  68b23795968766c77b1897c88a5d6ba8 78
+  1a2c8de565a1d9b1dec625f222975aea3fffffffffffffffffff;
+
+  3d96cd168c74f9015afb691d629f3f6d 72
+  3d96cd168c74f9015afb691d629f3f6dffffffffffffffffff;
+
+  38fa8f63dc426399e0f9b5c01231e02c 95
+  1c7d47b1ee2131ccf07cdae00918f0167fffffffffffffffffffffff;
+
+  90176b493061899ec95677ccc58b8cdf 78
+  2405dad24c186267b2559df33162e337ffffffffffffffffffff;
+
+  0706e95da68f32a4231ab184d16cbff7 33
+  0e0dd2bb4d1e654846356309a2d97fefffffffff;
+}
+
+lsr {
+  # --- Simple sanity checks ---
+
+  04 2 01;
+  10 4 01;
+  7 -1 0;
+  7 32 0;
+
+  # --- Copy shifts ---
+
+  01 0 01;
+  0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef;
+
+  # --- Single bit shifts ---
+
+  02 1 01;
+  01fe000000 1 ff000000;
+
+  # --- Word-size shifts (assumes 32-bit words) ---
+
+  0123456789abcdef0123456789abcdef 32
+  0123456789abcdef01234567;
+
+  # --- Random tests ---
+
+  eb4f57af83f78c0d67b3a6ad84e62378 120
+  eb;
+
+  c6a207d80522139f1fe168028d6afa8c 45
+  0635103ec029109cf8ff0b;
+
+  6027a129cf726a80445bf42a310ecd30 51
+  0c04f42539ee4d50088b;
+
+  fb0cc20512774733c783bfea0ea3b503 36
+  0fb0cc20512774733c783bfe;
+
+  4f9884d0ec9fc9e3be6ac15382803eaa 107
+  09f310;
+
+  e47895de118466ac7b16188284b35fb9 55
+  01c8f12bbc2308cd58f6;
+
+  22dfd1386bd2a5c4b6da0d619485e735 10
+  08b7f44e1af4a9712db68358652179;
+
+  489fab826eb8ce9f41084c2b4ea3bb25 117
+  0244;
+
+  f6f7735e7d89edfa05482a6b19b1d7b6 53
+  07b7bb9af3ec4f6fd02a;
+
+  bd4eda78b316190a28840f382a90bc63 80
+  bd4eda78b316;
+
+  af9f01ddcecf1d21b0af4c318df98e4f 39
+  015f3e03bb9d9e3a43615e98;
+
+  64d53464e8524ef2529389b14f2b9940 19
+  0c9aa68c9d0a49de4a52713629e5;
+
+  ce49d3be79896131d044f41274ff13ee 99
+  19c93a77;
+
+  25a05fcae2ed3d9e2486cd633bd51070 18
+  096817f2b8bb4f678921b358cef5;
+
+  8a29be64acc97626d097231c4f3df4aa 82
+  228a6f992b32;
+
+  ac27fc4590675fb16ecfbf774dc8e591 14
+  02b09ff116419d7ec5bb3efddd3723;
+
+  b72f02eb26b965133db98adcedfe1e37 44
+  0b72f02eb26b965133db98;
+
+  afc634103a039f37b8f9f98b1d94ac85 52
+  0afc634103a039f37b8f;
+
+  f670a78a3801b81e0a00e5b5deb81a47 57
+  7b3853c51c00dc0f05;
+
+  3a1d23d0d00fa4e165ba2b54eccd8f8d 92
+  03a1d23d0d;
+}
+
+# --- Arithmetic tests ---
+#
+# For each of the fundamental operations, there's a sequence of simple tests
+# which ensure that the functions are working even slightly correctly.  Then
+# there are some tests aimed at limit conditions in the algorithm.  Finally,
+# some random tests dreamed up by the Perl script `mpx-gen.pl' are given.
+
+uadd {
+
+  # --- Simple sanity checks ---
+
+  00 00 00;
+  00 01 01;
+  01 00 01;
+
+  # --- Carry propagation tests ---
+
+    ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+                                                         01
+  0100000000000000000000000000000000000000000000000000000000;
+
+                                                         01
+    ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  0100000000000000000000000000000000000000000000000000000000;
+
+    7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80
+    80808080808080808080808080808080
+  0100000000000000000000000000000000;
+
+  # --- Random data tests ---
+
+  272724be3cc4179a4b387bcd1acf24e1107be9bbb4dbd68408303df3537c83e0
+  c80ff7173b00d75c83bb38948118fecd9c16ec3bc2d5d051057a1ad8dbfa3349
+  ef371bd577c4eef6cef3b4619be823aeac92d5f777b1a6d50daa58cc2f76b729;
+
+  257099bff6868847d89969cfc691e1f5e0af7516360493a8dae919704eea7385
+  b4408b380c648d50175dfa8b9c1d8aa68f71f67b540045ed3f92f2aa19145cb2
+  d9b124f802eb1597eff7645b62af6c9c70216b918a04d9961a7c0c1a67fed037;
+
+  11978446632ed887ce26aeabf9997a9ae9600da7cb6d431e6ab5dc932b427eec
+  652931ca2eb81d3113453615d16e60de08b3777a6060d7f1775c916253b1e666
+  76c0b61091e6f5b8e16be4c1cb07db78f21385222bce1b0fe2126df57ef46552;
+
+  73d3697b4f886a8b242c21cb39151055937f36a6000849d0d1e526ce666a7d52
+  209e8d770ab7352e5441f74af428a2e9b791dabb655fd78d8a722055e896d7fe
+  9471f6f25a3f9fb9786e19162d3db33f4b1111616568215e5c5747244f015550;
+
+  3e47ae33e633861903e0960b1ef8c8c8900a659cb3e03a1cf1ba04eed5e3f93d
+  b844b1b685b21fce078e0db2b960e22dd1e81aac33062b6d9ed1ab68b8cbbd67
+  f68c5fea6be5a5e70b6ea3bdd859aaf661f28048e6e6658a908bb0578eafb6a4;
+
+  23156b15f2b9a6598b6703cda3177d7432016bb388989d5e33a5cb8778aca38f
+  77197a3167c282ed511bf0eb865be89624e4b5e1e9dd4b7d44acd59d41287639
+  9a2ee5475a7c2946dc82f4b92973660a56e621957275e8db7852a124b9d519c8;
+
+  ed61746de1ab76f33cf25878088b24a389d79ecd65df792954a5788a887982a7
+  b673af9ad91712c6d64f05cc14fbd503b04345aca5695ef26cad9ca1f1460496
+  01a3d52408bac289ba13415e441d86f9a73a1ae47a0b48d81bc153152c79bf873d;
+
+  46a147c2b345b5ba782b600d1811975cd6a75b9bb6fa6db6bd8c594ecead30b3
+  3dff366370a27aef1ec46b32c4946f90ef75c7263f71703be87074ba18705391
+  84a07e2623e830a996efcb3fdca606edc61d22c1f66bddf2a5fcce08e71d8444;
+
+  a1756514e2f8c5805538ad1b85bafebeb1d4ba9c61d19fbf2f286518eeac08fe
+  4646f60744b71c5d7e2a5f66250e0295fc6ddf5acae1f2397ad37403a6881e24
+  e7bc5b1c27afe1ddd3630c81aac90154ae4299f72cb391f8a9fbd91c95342722;
+
+  cf5f959a7c1d3d0027f62303d4a517bd5acadde74db6f18bee67aed2ee1bbb23
+  76e38874ce5c3b7fe616b20f2ace6cf550190d9bad4b2fd80bf6deaff8a329c5
+  0146431e0f4a7978800e0cd512ff7384b2aae3eb82fb022163fa5e8d82e6bee4e8;
+
+  1dee3d9ad0cc6212e5843a57d736fad4675c422efbbac6d625a0f45ee90b7d73
+  d6df29c49292fe633ec60e597d0c5688eb0ba6c134b7c041689fed3e72535c55
+  f4cd675f635f6076244a48b15443515d5267e8f0307287178e40e19d5b5ed9c8;
+
+  3ba228e4e40cb50141845ae8b7318b43c6643765ace7ce83a069f1787ece6058
+  06b3792dbbde4db5f47be20035524962224fdaa18be7dd9eda23f1671e6ad33d
+  4255a2129feb02b736003ce8ec83d4a5e8b4120738cfac227a8de2df9d393395;
+
+  e7ff758bb68a5a6106962113f72f9705dc0641ad029741f7c57a5320d030ad32
+  7fd185b393c432dba9892a0b67aa12a85be6e1643cdfe8404963fe92f4f668bb
+  0167d0fb3f4a4e8d3cb01f4b1f5ed9a9ae37ed23113f772a380ede51b3c52715ed;
+
+  a5bb634cb6ffda70661189874605f802cc34a8960a137130f238638d9a9e72c1
+  ddccdab554733987e04a5aa8674b5eba27f594f37cdec51b3b5745dfa159aab7
+  0183883e020b7313f8465be42fad5156bcf42a3d8986f2364c2d8fa96d3bf81d78;
+
+  76888f3fc82690a4681e30b5f94efd08d03b7eb1c814ed01cde866847e3c75a4
+  78d0869abb1b1fafc582ccd8bb0c27d7ba51de9832d3b0cd8ca366d27d268788
+  ef5915da8341b0542da0fd8eb45b24e08a8d5d49fae89dcf5a8bcd56fb62fd2c;
+
+  24fbb9214449c926753d15573ca07552ff219c97c43824182a6dbabed6872610
+  be3795a426052f168129345d33c6dded8ae8de0e0cbdbcc7c2b3f3386031b548
+  e3334ec56a4ef83cf66649b4706753408a0a7aa5d0f5e0dfed21adf736b8db58;
+
+  97b74ea8ef087496a84b73ee7d8713a13a511f40cc9a19f613a10891774fbc9a
+  fe8dd31272be1f79ee524d736c7fbd3a2c1718b918b072025612a1f2176cf53b
+  01964521bb61c69410969dc161ea06d0db666837f9e54a8bf869b3aa838ebcb1d5;
+
+  66a6b572a25f6f97ec5b7e7e393bfd686b69c083cd673feab076b9923133a46a
+  e7b501c43dafc08bc521b15be8a1ca9dffe174c282111ea9eb0bac34fd0584b7
+  014e5bb736e00f3023b17d2fda21ddc8066b4b35464f785e949b8265c72e392921;
+
+  59a803f729f14d54c35de20cdf9ce5b8e2f430016448c80e9d3e2ec608f8bd67
+  7a5a9cf43d1d70e200c5bc7baf4dad57e5892866bb3ced09eb0ed096214509b3
+  d402a0eb670ebe36c4239e888eea9310c87d58681f85b518884cff5c2a3dc71a;
+
+  d26914575527153ca24945f0e83df5b0480c8840e1e6807b71d008068b082c7d
+  281c235d8f8773649c75baba0c302f99f3c526c971cf3daf976deba0bdb3f38f
+  fa8537b4e4ae88a13ebf00aaf46e254a3bd1af0a53b5be2b093df3a748bc200c;
+}
+
+usub {
+
+  # --- Simple sanity tests ---
+
+  01 00 01;
+  02 01 01;
+  05 03 02;
+
+  # --- Carry propagation tests ---
+
+  0100000000 01 ffffffff;
+  010000000000000000 01 ffffffffffffffff;
+
+  # --- Random data tests ---
+
+  a024729f63161b8fbb711008eb863b9e2044a77ccc7bccf19437471e51a4beec
+  9239ec16929055e3a156768fa1432c56d997ba51c1efbed4c791f062d95641a5
+  0dea8688d085c5ac1a1a99794a430f4746aced2b0a8c0e1ccca556bb784e7d47;
+
+  8ab8ea06c7afbdfe6636590f748fdd376a2dd9c708e7923541e134687fbfd526
+  8896da6b7c98b78a0ea2c9cae23d7065a94daea56d1c919a7db2583da936bd8d
+  02220f9b4b17067457938f4492526cd1c0e02b219bcb009ac42edc2ad6891799;
+
+  fedfecaf26399ad6eda68c7c5cada4aed095e82182e3df696cae47e521c382a4
+  7510069be2896480db0beedc6c5497e79bd7ac5e9fc14bf9ca460c7f99aa6834
+  89cfe61343b03656129a9d9ff0590cc734be3bc2e322936fa2683b6588191a70;
+
+  ffb81ed18909fda98730e146735c21d3914122faf84882dc688237371825739b
+  d7eb8f85d95888d2c4dc7b9fbbe689e2ce529f8870b2487ce28d192ef3ac2317
+  27cc8f4bafb174d6c25465a6b77597f0c2ee837287963a5f85f51e0824795084;
+
+  c3c2c77bc0867d30c58c1eb786ab7feed60f9e0e2dcfd6ed97725fff364c7b5b
+  a936ff836dd8dd063ab05e4fc7176e8c05a45ddaa7f701e4184b4fd371ce968a
+  1a8bc7f852ada02a8adbc067bf941162d06b403385d8d5097f27102bc47de4d1;
+
+  ef76a6e2dc6ba3317dcec6e338a20cf12eb852388204efe290a3b1536f6b198b
+  3eb8d18b7903d682d713859f258ddbc13aae32392a4267b0cd1481c036ab5baf
+  b0bdd5576367ccaea6bb41441314312ff40a1fff57c28831c38f2f9338bfbddc;
+
+  5cf09a0f0488a077e2983b4a854c28fc7a11f7befc196824f7990fadacfc26db
+  0f46fbc396b81c512b7a0ec003759de05a967101a3ec50b7cbf84f42708f396c
+  4da99e4b6dd08426b71e2c8a81d68b1c1f7b86bd582d176d2ba0c06b3c6ced6f;
+
+  ea9b202602ad3219e3d3a8fbaf042c3cec8a3d7f16923855b0ae67b8ebf57b50
+  850568cdebe8fe9f91c3d8bb4bc525158bd8590b235f46d6d556bf969e2f24f4
+  6595b75816c4337a520fd040633f072760b1e473f332f17edb57a8224dc6565c;
+
+  fab03a9f849f408b4af55746316f8e3a81c6359b3c3ba1ebd1d8b9e7a983a03b
+  a60ecaf59c0c7d0ce3ef4d6d9006880efc9c6e0edcafbf7291b009e7b3cb03e4
+  54a16fa9e892c37e670609d8a169062b8529c78c5f8be2794028affff5b89c57;
+
+  ef7de9bf497c4c47d323a379a42789925606f700e786622b280aec1ee6e13901
+  8a4197e881f1d2f6a09296e6d826ea628aec658b4bf7e9c436ab7e70746c4c87
+  653c51d6c78a795132910c92cc009f2fcb1a91759b8e7866f15f6dae7274ec7a;
+
+  9cf0d943545ee18ca59af6f547cfb45de41b1d52c996f482728fe68993d3a966
+  58ad4b10fc09cf4f4f4a1488e36ed3beb0a2a9e8c8ec042aba113b2144ff1939
+  44438e325855123d5650e26c6460e09f3378736a00aaf057b87eab684ed4902d;
+
+  3e0e637d1f4ff5b6d58549f8011ae0a885bbdcb5c478777417e6293c108c7c0c
+  09e06b0b986110817123a2a5aad0c178bac3005315628424d849216a43b71ac4
+  342df87186eee5356461a752564a1f2fcaf8dc62af15f34f3f9d07d1ccd56148;
+
+  c3b4cb636f76027a876150753e266774af9350d3e68713adcc39cff5e389e285
+  a4abec0b5d38bc91310f3b9e3e12d0c4af2984ba710a6309544340ac3c94e121
+  1f08df58123d45e9565214d7001396b00069cc19757cb0a477f68f49a6f50164;
+
+  175402d43706fcdb3caf41cd8de6822447e39f3a0ed2f00d4d315a1cc03b5bfa
+  0ffd7d0692776dbce6e112902472edba5ec4c1500412d9bcd24472da90889b7e
+  075685cda48f8f1e55ce2f3d69739469e91eddea0ac016507aece7422fb2c07c;
+
+  f6060bfae1e558606d44496967e0eafe805e6f60d1c4a8f886574c9d6c6989da
+  e933391716ffc61eda9c547e7bdd41799ecc56e05178ebd7e2068d32467aace6
+  0cd2d2e3cae5924192a7f4eaec03a984e1921880804bbd20a450bf6b25eedcf4;
+
+  cfd8ba6b7173b72451f370c7a7dad7754ea2323e52f622c1490ff2d3ccf5753e
+  b4e23f1700a3fe1d5f0465cf3666235f1c7460ffebce87c8b8d551ceab09ed1b
+  1af67b5470cfb906f2ef0af87174b416322dd13e67279af8903aa10521eb8823;
+
+  ebf9500e9cda50607204618fa6cf2f29f2e0af023237034f1a3e72787364370d
+  0e826c97712e73f32d850d4cf63925fe8c8ed86396350432b9971900a4068cbe
+  dd76e3772babdc6d447f5442b096092b6651d69e9c01ff1c60a75977cf5daa4f;
+
+  c4f9d29310ea767aa8dd0af418447dd3dc2c220c48591f99b6dbf0521f7a5640
+  6d72f5441ca9dbafcbf4db9701d6c667c1d5376251de09468e3efbf1fb04cd95
+  5786dd4ef4409acadce82f5d166db76c1a56eaa9f67b1653289cf460247588ab;
+
+  91af1ae9122ba385deae3f9b478c8270a2d2221396fb3639b44e06e3a1ae9817
+  08966b342d42332d2155fe03fef2d3f84b415d1fda1168a5c63d0f9b86b77cce
+  8918afb4e4e97058bd5841974899ae785790c4f3bce9cd93ee10f7481af71b49;
+
+  976e1fa5146093d794691c63d1aff7ceb5851bb6196909eb51fbe4640829b208
+  1e8a3a0a9050c307cd94a65793371f88eebe42ae8893b1ff984357d597c884d1
+  78e3e59a840fd0cfc6d4760c3e78d845c6c6d90790d557ebb9b88c8e70612d37;
+}
+
+umul {
+
+  # --- Simple sanity tests ---
+
+  01 00 00;
+  00 01 00;
+  01 45 45;
+  45 01 45;
+
+  # --- Random tests ---
+
+  4162c300b3e157e9cd1301d499c20121
+  10549901fc6dcb85882440087bd398ff
+  042bc7ac8fe08ceefb098f286cdd84fd037906ead144324e361c488a221db7df;
+
+  f4c0a35591d6567a3ead2846f4350141
+  58bb07247f8a7591b7acfa727118ad8d
+  54d507b0e32175976a30766da14de0726a8ffbdc7ef0291a7389759422229dcd;
+
+  5d0965f58c9d794ca477ca2349900193
+  2cbff5f50dbae1965e3aec1108c36d17
+  104360ec53eef2e669285143dc0d01c9ccf31a77dc302bf8d45356feb794bb35;
+
+  1a438b12e1babb4c68ae4606694fd1be
+  5bac6d40fdea39c2f1f6ce285f028d36
+  0967b3069413a0fac34c03fdf67e2f5187232be344bbc6011849688052d7e414;
+
+  59e648d1f656407efc7c9b622de6bc6f
+  0dd07d6e4dc035816236aa0cd512e424
+  04d9e8da01ea1a42b1b9670a4a14694cd104406f346a0598b65e0ae58f135b9c;
+
+  55c69d7a662a945e6a535911e7abdfc4
+  9883a7ea2c89f5a873b5bae63cf5ac73
+  331a0a66497eb713fb09b260f8774aa97765c13bb040d7917a4b7cb9a321350c;
+
+  bb15812991a5a01c6e803475d5f2f1c8
+  66782adade0952e8ab51a2fda6a5f611
+  4ae262dc95488914177d07869caf42dd008ecfc3c092df3007fca8702f603e48;
+
+  b06a37683348e8e46ccd954ff0348a82
+  e158b834e442cf83aa863dde751525b7
+  9b4a7e266b977f83598e6288efafd0f517d9658a2bda86adec7e1835143dccee;
+
+  b7f66a5ca27d276bdbad5995aac0f676
+  8f05519b9acbe85369aad7a865a0bc5e
+  66c677de9ba98e4c527c86b80ad1485c41782c3e0be53dba2f547fa0ff992754;
+
+  b7f43225f41056548b095f359b6a3b83
+  966a8ba6772991700ead0e01bde39120
+  6c15a4d835ec2367ec41c566ce63a098c496aec8a5b041fc7c91e6601525a360;
+
+  87277faca81e1bb28e0e24e4bbf5e8c3
+  5f126e08716855110489045453e69dcc
+  3231633f7a7eb05793df2c7761d793a634faeb021fda1a404f05b2edefe71264;
+
+  3358074e192e79ba42c186ead80404a9
+  dc1df51ac8c3328107638e83b17f777a
+  2c25a8688faf32cb8b1d4b454cd4a2ad1130df69188cd2ec44cc8806f8ebc78a;
+
+  7ad1d7a04f7588af0ff7bf29c13533c9
+  0785d4d4d5f1d25aa6dcf744662ab2d6
+  039bf2064b716e3befa638d510131596518b1d91833200ba19ae6aff15750c06;
+
+  8b8a4c2ef785abd1607b663b3088e37c
+  fcc67dfa767e06d97cfd5341ded07e42
+  89c854a034d2cc29ebb34f379d6a74a9996d261774b1e7ba965e98204001adf8;
+
+  1c9ea6a1b9aba96124dd8abfd3dd78b1
+  93ecdfc3f4c188819e777f082b77e4c6
+  108994f4961164206f1a97cc0f39edc29faf2bad99d164fc60c06ccff20ffce6;
+
+  c6d9a8a4760fffb11ac2d38b62f62a89
+  c0989f4e8aabd21f7a2b38ec27afb783
+  9599cb75abf86c37db000858bd671992ecde9d440cc765855287391f8f06b31b;
+
+  5d48ba3dba86c0e9d3922cab8d88c5b7
+  5186010a8c3fc4e3499534669a13f219
+  1db4d7602500cc34de718d5892f79db44096a6c6705cf6e9ca8b438cdfd74cdf;
+
+  d009f15fd77915f113e471884e464462
+  cad68bffeb24842cc083f5496b10e36a
+  a4d6328ac530f0615ca3b0aebeaf104960e120609c58710eee206cc3f3db3694;
+
+  343f0033e5648741936c20439bf044c3
+  9b26545821fb1270515566d970e566bb
+  1fa9f7b01c40607bdc8f554e57555de879784cdb1eebfcc3a75918d27656ec71;
+
+  08d95fc1d6dd6b9423c7bb033598df0c
+  6c03f5958677efd383509141bf257375
+  03bbd76f19ba19e3f255c24063f6384d4ac913d9e582392589a525195bcc547c;
+
+  # --- Karatsuba regression ---
+  #
+  # This bug was caused by kmul (a) choosing the split point too low on
+  # odd-sized inputs and (b) not allocating enough workspace.
+
+  21a9269d7b8b63cf18faa933b3c868ba1e8cb3f00b57e197709abf96eeb9bf12e8fe22b3
+  0144c992b68e3ca712678215d5bc968702ccfea17717737ba501a38d26fa5091ba
+  2ab495f91afd7c36f85ece6fd58577f995de88d62a98a07c6d9e3500ae67b0f100bc709d1f30894662774d0cadfba091788c427cc6f4bacb26e42cf92f6e4494e03c990e;
+
+  # --- Larger number tests for Karatsuba ---
+
+  416e63549e2cf08fb225058b3545cb4a47cbf9
+  de38c473c27f7bdef02a084192b3e17f435cf7
+  38cc3c7f360737411df7b52a222a3672c6e0d39f0a868479176a6143e1129d44d5aa61be493f;
+
+  aa20b1355073f21c57530d2f90bc40e47ac463
+  8315dfa60e97ff3dab7a6f61fcec2cd5b6f127
+  571d43fda6ce14a78534ac72c50b58738d62630766a59a7cec1a63433e499b1b5eac5ef71e15;
+
+  f641594177c8c364d922c659a8f7ae0460c7d74b266c8cc258ad5f
+  5948dd29fc5172c37c31da6957779a1bebe452d8deba26c5d3d390
+  55e2cf27aa49f938584dca4044d944077e226206c6f8c7688e8760f3b5c106413fd0ef4b63a97991da86fd113ff4822a41f76913d270;
+
+  a4170f55dfa135c4bdd3a921a8c1567eebc6b799fb62b0dd27b089
+  7b7d619e07a5d01427348c05605f67196b2923b074787c375977ac
+  4f277232c75290f0c5fed384dba2aaa23fe4a360ea63ee45fb6c0134b36a09a9163f3c767d498b8dcd31e5deaef386d4a9b7d85b4b0c;
+
+  250e7a0c7035df81429572d3f772720e723b710d54b9eb5f16814117980f0559bf12b82e00c5b3904e
+  1be3c88b01ce53a70c12f74dcc247823846ac6c06a9cb41b86794900006045f05e29da23b81523aa9f
+  04097fbcf75616fef7b6b91680963f7e0cf1bf72bc5f453e46136fc92b20ae8a30d7ae7965f8271de854442b93562ebaa9ee09fba4a7b79ef8b26718b12424419dc301496dc0d6cfb04e4f7a3a3729046c72;
+
+  af3148a72dcf1340f6b5a3b2fc1cacd7e6f9e60a13de5c91c37bb850f0e930683c2dc96882a9f62b76
+  48603cc656908b34c70ed826da8c3414d5845100f53cb6f9f370a4c7708a9b8ffd787537048f89493a
+  3187b8818bf644805c880d189bbf606ca23e01431cf5b3b633db48a1202aa346f6a0e3958c7264fa1de2d92660345e820f4f3659cf0040a28fb9b725f7ab83610c9c056062326f776ce871696eede0507ebc;
+
+  0b1cc934a2f6244b93c8ac10881de20349d133642ac19fa0be3acacbf4429d0ec7bbad2f41534a693647b7c02e683cde249e36f008fb68e96de65c8a268eb1ea
+  12444899c13f0ee85a4f47024f06d8a5746f0d9fec02e57c6d87a7bba17c1454fe6387bff5b96e38ce6142b9eebe249865c52b617b8966e6f93b16f612a91155
+  cafcf1ea9f16a56f9ac4635d58992a789c51b6d7e53b5e1d8b59d5c1850c5c6ac2297839af44b29d5cf440772f98fd9d090ccec2d56adeb113bd3459d620b0b02679b72f3170ea8e2bd4486eebf2496d8be01cfe86923e5bbeb6f91582dfb95c6ef0a52cbc068081dc363b31dbd2ed80e3267d973ea39f82e276002eab9cb2;
+
+  3ba5a9c550b8cf6c3b87cc106b6551221a0dc90ac193ebcc526e4e5f53cf012fa6e05b155dcb3c4c0e1a90a01062a67ec434f6744195349194770711ea836a8b
+  54f04f121d22db842523e9bf75727d5b0e9ef17e6d727918894927fade87ceeb2106684c4af7c49653425e29f7a91abf8adec4de2ca499df2534644397e454ac
+  13ca59703f4c087c16a9a7bc7022904a37a469c1d0fd9fa7ffabe8f7d887fe1572c0bf5c75fde6913b565f8106bba9c26c9bbce190a9b8967112d74c0ac3d4ff9d2a385b96833e3c456d5601c74d8d2c9fff35abc60e7cc15d7c680f20757c13a415f1b8fbe3c6c32434aa36c528473dd20ea39f0e5ee22d1cd23040900d3164;
+
+  # --- More Karatsuba bugs ---
+
+  3fef06998b0ddd140e01527426ea409b2b9e640f223dfd652229fd17eb99d44f6be6d4935505df676f48c8fcbfe2d5096345d6509267aa40c54d427f0cce45cd0f8fa7e4a22492d7ed4ffa45e3c0e5e3c25c841943fb2cecd6ee9275ae93c4e15e2d9f8f317c44c541ed52a6338b0fb9f7f7f4dea78cf7ef5201837c00a6d4d2
+  0260acc6378341b2b894dacab3a44b914f19292bb32898b155584a406161bb04ad9c14db20888dfcdab613b368b5c699305c4e9b226d90f9523fbcb6293407bd2bb18bf7bdba8539fb577f19b72124c2d83a2bc31f44366e917ddc705085b79fe9e0df0e98e4f6ae3df63d9b321382c18b95de1dc4d1db93b3092c9c6f8c9764
+  9802d5c5d5a73f9d4e694a8920f951ce4bfe80c13a35cd5332a556136b83495a2e9b4d2ed53aae1218d2e1c41349311f86b1ee1f2ad5cd3c5b264e8e68906ca45bd7d0fc8e8a5a9648f458cecba41fd0848a04f506bb11ddb378f3214085cf865ba5533cfd73b28b1e12784f447b156f59a3b68e6ec68303ddfce59ce33ca386ff3316e6a5e6f9b4201682aa9e59a6d7cb9315a492457640acca19fc7dc3a25a316fea9a0f1d32838b7f911650647f996551263c2d001fa1c720753afca316c7137300ff93f2ddd2846ce14c55d0ead626f681bd11707f9674905396a9bc9a889eae721ab6407586880a95575a968b43bdf50323627aa0fcddfa4e198b0008;
+}
+
+usqr {
+
+  # --- Sanity check tests ---
+
+  00 00;
+  01 01;
+  02 04;
+  ff fe01;
+
+  # --- Random tests ---
+
+  d573446554727d0f05ad3ccd03665c2f
+  b1f903b723d65fefeb935ef5c50ab18da09777b28b8a093adab73a5cb0a5d0a1;
+
+  27ed6604397ef6acdb3f1906e5c0be25
+  063a313b55fe82206c4e69624c2afd726dcf52c1efc9d0f81c948907f6baf159;
+
+  869593eda5bbb87109593218d3c99f86
+  46c0ee42519e3a8ce80f19b6bd60332254e1e144350898d77e803ce2c7d3ba24;
+
+  94edc3ffcbd975677c95b44e7f4a8164
+  56a3c77441629088100fea8b3e510352c9904877e9705b9e150e7b004735ef10;
+
+  4a3b7b546f9f15a09bd35d6de3b33f82
+  1586711ee4ddaaf121f7e4311d3e182948ed5569def0257e099be8d66b8d3e04;
+
+  adf038609b8f95940806994831db9409
+  762e8d9c53ce25e6641019bd974169acd1aa3e95968b13e80c97d2120f006851;
+
+  337e87847e2ddf24444fac6f64c6cc66
+  0a5ba888786f7db6d9c28a7482545e31ce687996024edfdc05ae3a8480fab8a4;
+
+  0b2c882b8a7dcad93cffc77be4436e62
+  7cdb72d54cb539de9fc55d68b9ca4731ad6b1bef79fd0dd12c9c8d86e45d84;
+
+  298a1b9f23f7e77dc288c177a492843c
+  06bd875ac41323efd9b958064f96e74d84faf58a2c43f4bec525750ff8bdee10;
+
+  f58345742a51bd04c80b3791a688871e
+  eb74864080bb96f90ac10021b82af6ea9acd21af8b8c103739a14c06bf30a784;
+
+  0c720ed1384848bc57e6f92cd98541cd
+  9ae434d07874574a5702724fcaf6d27f5686744f03aa444afe9762f9ebbe29;
+
+  37e91e1c9a3f237a08dda2e6919dbfa8
+  0c35ff381de29f85eb03c278ca9623be8603ac9f744c826d08e91630f38c1e40;
+
+  8b270d9328ea8561db59a8ac4e651d05
+  4ba36eb2f1fd6b0cbd6f71ac36aabe1be53e21ae9afd4c9ce1715456f53c2219;
+
+  5e64af22a077e8832538dc9ff235bea0
+  22ce1836b8b5c880ea1e00f95f339ee776d8edda0563e498c98f726efc31e400;
+
+  8e6d67cd33ac976b183475e54afdb715
+  4f3d8de934283d046ebdb7263c73978e60c2e68179cb3edf79c266dd867107b9;
+
+  27f566956e3fa7141088402630e929e8
+  063cb07f0ab7d5d22828664724da2dd261c14526d80f7760aa04b4f44f2c2240;
+
+  e26c74de93a02296693ee98e552d5524
+  c843ac4bcdcdc37c3ef17997e8d013d1d4ecff5a58a22e2be50d1e80f2f8ed10;
+
+  ca53baed02dd4ba78cf7a3963b438395
+  9fe83e60c6b25a7b58d1f84a5905081769b4c5b5c9b1d63a5bec2110d19fd4b9;
+
+  d6e517000ade8ef62963e890a472d530
+  b463cf763a508b234fbf75a75781c97b5a9963b8f8456d23d05a2aa81048e900;
+
+  c4245e0ce04fe1151ca17eb8aeb6e3e3
+  9647b52e4da6dc80171bd5495ab519835e871bf915ee7e59f1fe2ac165a05b49;
+
+  # --- Large tests for Karatsuba ---
+
+  8390d2dfc9770526e8c4820e1cccca0e8e19d2
+  439d89bef1a65f537e59e74590df3ef10b7e78066ac2af7b5c910e1929de102b491b9f92b044;
+
+  26c4cb564d57970bc3dd00c0c1690c7f1a2e9a
+  05df03a59c9e6ab7bfed79ff8f32811303e46f94c2e8d9abcab5bdac1040e7fdaf5a4bc3b4a4;
+
+  599b3cceca39690c06425127a95b84310cddef
+  1f5d4e6a797662648e4b09abeee439415b76cae52e7cf9db1a54b7f99afb9c00b6130cce8521;
+
+  485b65b3d5edb34810402943ccfbe37a137f8f
+  147389d69e9730f86b04a1782fd15611e6f8dc2e99abc812be0cb82efb2a1ad538aa7ac931e1;
+
+  5a243e54da1f87a8fe23c8b0988b3574aa77c1fe620a5d25b8e03295aebe6c6e135a17
+  1fbd80f54068ba081e793c1aad443094416a75e2e708337618e4ff02ca9dd26bad87cdc0f758342df39a56625c956c971b1f7f18f7d3cb6a1880a574bb7b06a6ca4a431e2e11;
+
+  f5c57a7610feec56586de369136ee25aaf5d3861ad80033410c410658332ca856e4cce
+  ebf394bbb0d2d75ba78b75ae018c77f417cc1c67f0aa587d070980386e14f2b59d9a580d8d483b4df7f6a8d4a44ec8786a87d1da031bb5c288c3afc65d931471786c2412f5c4;
+
+  5bc4457e00bcacf257200a96eadf90359cbd9f6a2c2c69b5ea2e4c5d3939f0ce100c06
+  20e51fe210546e478bfb9d2b0418df921974417799951533f317498439caed52a75c4c66db81910b3fc4f4fb3711cc25f2b4ef151a2023b6e52e64e1d5b7dffb0b9b29509024;
+
+  4b51f1e0a9206173d39a0f1f4eea558dbd9d1ca2d41671b2d27b1b77391e76504e14c0
+  16291df497ccc32ee92a9037b78ff10828c2645dfbf91541f3a0d963892d59c5cd966ffe1e1ebb2dfe6f434fae44da11ae2d2357876b711feba596612c102b8905c8a6ae9000;
+
+  10f63541b2bc5a7d241f887d0b3d182dc473a06c4fb275259112b2fecc9455d7b1eb5b2e9b5c3646c35121d05f1ae99f1ad990c7f0e48b002bd5fdd253c68b56
+  011fb3729baf522bcaed9a966645754804b2cc80168de9f93544e17d5b6d6b81c516f68b72580257f15e3f95bc6eec22608c3055de04051598bf4a76975d111a59d6b02a2fc42de65926cee5d5b97b6c7fc85e00dd59bfdac2c95bc80b7657582b2853244e55b507594a83d5bd87b7a83016dbbc104ce596bdaaed6d98de80e4;
+
+  9e40b3c041505a5e266109f752d85ae3abcbdd28bfc70bbb2c7228bc1564ea893cdda0350689610b74babfe45b14da9708f28c22e3999c841fc70075dd0535cb
+  61d3ee3baef64371ce0416d3f5a6e687903413ad06e85ebbffb9ea0ae9e8cc290fe9dc1cec429e0a294b18121ee29755baf4306861e092e5c1f1def03953f559766787a222368b64594b7be2eeea0698d1fc630446714e681210b5a66e0433b6c43038c0ff213cd14fc0a1fb71789d57b097ab44d859f8bc912f2a89a33baef9;
+
+  d35af50f523d29f53bf0126ccddf4f3052ddb44eeaead360b5f36aad902ba105a921880cefb12caf5e1b3719a40596732d265e996e491f82ca2edf08adca131e
+  ae7f10487aecfa7f91217020f96a1cb00d81545deaf9730daa2c7113e84e76c7e54a1b14971d26750816a696d55622ae1dbd56befdc12a656e66e1d10e87c3bc209e0903635784af6d48a4d7ec84634efb91b7efbfff724bb50ace7d4684d2e72eb7eef84ed5cfd14a7602ceded675da541646febcaa285396b23338b8c57784;
+
+  3df659f884c6a31c5b332efc44fbd70fea46b81adb241fc651af038380f8c476a471f06382ebe55eba339d84edb33a03002ac505d93c61a42ba20e36a691c287
+  0eff53f178849510a118db72c5620423c2991365b06e8caa76300f3df554cf8830c9833f6ec1d33c850b1bb380e33a486a9963b63b5228229fd7e9bdd308bc810aa5e74ccc0e65a2af40c9a287c67e69e841495b0221110f35ed6319bda0dcb0b02174b666df4766eea05481f6a80fe4b93a06fe475d58ae3002303904bee331;
+}
+
+udiv {
+
+  # --- Simple tests ---
+
+  09 04 02 01;
+  ffe3 01 ffe3 00;
+  cdef fedc 00 cdef;
+
+  # --- Random tests ---
+
+  8ab316d0d1a2e88535cf77c1172881ead70d592c59e9c5fbc16e4b0c4dc49481
+  18ca3bf7ee3c6d7bab3f144b015ccc6c25472843d346b461
+  059850f995ddeb799c
+  02c1815029b766b96ad4507dc1af8151307961c6d161d065;
+
+  8117d1663ee63341eb8faeff304549f0f8b32d587acc2fd5597ea6a31625881d
+  dc85df77dfb61876805623bcbed325b99d00c2cd65c252c879
+  95dc734282eb19
+  395da02e8a6c66476467c4e04f328d8208cc411e3d1e96e14c;
+
+  63791966f2ad44a6df11bcc87c6b7c2400c74e69f7e3ca02fcac12b3bf56238b
+  a49e473b8f7539d89cdb002d73182558773eec10db93cc6049d8c5533e
+  9ab11a
+  65caf6833baa118b53c7bdc44a831605ca382b5993beead59f3971d13f;
+
+  9ca438db3e0f79305987292e8ec6174e6c313f7904ebb35a349a700e3ae63a37
+  b24c93d499c7073b8f7aac718c1f12da1a8fc8bccdd47b49
+  e0e779304869fdc1
+  46393cb15e38cbbc8a85698151a113f28081b4c8f6ed232e;
+
+  8214fd17858a4a913015412b5331eb9654faeb5156a674b1e5f6550a68957146
+  c4f0ebaad6c0ee0111c57667ea8e0a254f3068f212949e20ededa89a7da6
+  a917
+  3fde916ba21d19414d4316041420ca59d8b01aa2acf3f3ef106245c1915c;
+
+  55a487a70935360158bd55542eb46271f90f7312e77344c4ca6a580a80810612
+  8996dd0613f846
+  9f58fe011d73a8750454d9bffb55906e9bcf563e0c48b5b608
+  4cfd95e3e17fe2;
+
+  6a13e1be50ecdd7011f9ced42269615efb38fcd3e5477bc57377138cf1ff9519
+  fda103ff99ff21
+  6b11bf2670bf080ef7c5aa0fa5989324e88e3e581c0e7507ba
+  717db69e0d501f;
+
+  367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa
+  72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773
+  7965572732ac
+  08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6;
+
+  6da07a0a1f9a7dd93e1f82be23fd5e7814b84fc74d4566dd83914adf368c1689
+  3cc71e64
+  01cdc15d7d825955c50ccca72fc5a16f9a7dd04363b12d8354d3088e51
+  299000e5;
+
+  001f5d985f594315d8c58f2d654304c8417f683b65d6d3246b89960e5f6c133c
+  5bbc034d956a17998a30a3
+  5787e7e94449592b493486bd9a323f939ad9bfde
+  1298fecf49a80ad72148e2;
+
+  ae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c
+  c33c890f030644d88cc65f8ccf99c625c9b9fa21d4eb153e52ef89df54130855
+  00
+  ae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c;
+
+  65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc
+  d8a1d326fee87d55f39f15b5b2cfe71f5146083928
+  7805090edf620d22dac08f
+  859c41164983547c03134b99530e25a0f874315964;
+
+  5d9e7037d70e822c2ce4b3d93f3e20d437a047aa94103296cc041e1b7ea0d9ae
+  d2b14235853f6bac6fdba208897d
+  71c036bc8940293745e65c49f9b0bc1a8aa3
+  700473d994c1cd61ab24f661ed17;
+
+  3a826450bde36cf03de1d6829f7e21af52beb2655e2c902ed634f84e135b241c
+  3023b54e1deda493ad0b4558
+  01372549e716f70dd3c6bb31f193682b7a9355a7fc
+  04359aabd8bfdf8dd3ce797c;
+
+  bdcfd9593348eb1567377e0d4f4bfe8a26acac14b56f7dfd82beddb4f11c2373
+  1f0356b60ad66f4fd7dda57cfc6d1aa374108bd4841127c8
+  061ed1e07aff1c094d
+  0e313b6052859863725786d1459434762ccad8540bad244b;
+
+  293be875d1251920e18102446ceec021da8d8d24aabe49c5911d19ddc3db516d
+  b66e4ce3aa7390a9d888c5d22176bea5c36ae962ae8f252cdf3642556641271c
+  00
+  293be875d1251920e18102446ceec021da8d8d24aabe49c5911d19ddc3db516d;
+
+  5f1085256c5fb856ceab16f2372b6b7024c7d1fcfa7039a0555bb1496c0bc92b
+  c46c1fcd4a8a9cb91775f901af0ab42e39015e09fc737ae2011899b34322cd
+  7b
+  b091ddc98f1f09e065684e681146ddef6429ce2e24bd95bed4df704aca10ac;
+
+  82ea5bd086409cf3681e55e6133626ce9579db9eb01a0411db9c8521c3c66c2c
+  605a13a7d4b75f1094260227cd4cab
+  015bd5405d6bfd4571e54bc47a1b089abfd7
+  3074a3c84ec3bfa32e0db1b349738f;
+
+  3b68662228026ec9e9be8206d3226edd265552a3dbe15a7aa399eba05a69a6c3
+  a0f4265e8f59474132846bfb15
+  5e7d40f138e2a107a52f85a0eb6f92a1c3ec97
+  1508f62d27e7fad09e3d423160;
+
+  82a5058150e570c9eef1f4e5d55d3cf261de28a17f4735caec8bb38e1813978a
+  620d87bb63872a40fc2092b0ed7d3ec4b648be41
+  0155177e99a8a5113226ff8270
+  2ea2205327e66d75990cc999fc2380883ee4591a;
+
+  # --- Bugs ---
+
+  1a923b3406cbe81b093ce418f6a73107f504502b2e3d1b200762fcf6062723de405cab0aea00000000000000000000000000000000
+  184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000
+  0117d3db34ad005954459be9abedd0e5deb4ea0000000000000000
+  00;
+
+  ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff
+  7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff
+  02 01;
+
+  26737e 0ffffc 02 067386;
+}
diff --git a/math/t/mpx-gen b/math/t/mpx-gen
new file mode 100755 (executable)
index 0000000..891e4d6
--- /dev/null
@@ -0,0 +1,118 @@
+#! /usr/bin/awk -f
+#
+# Generate test vectors for MPX testing
+
+# --- Generate an `l'-byte hex number ---
+
+function r(l,  i, s, x)
+{
+  if (!l) l = len;
+  s = "";
+  for (i = 0; i < l; i++) {
+    x = int(rand() * 256);
+    s = s sprintf("%02X", x);
+  }
+  return (s);
+}
+
+# --- Main code ---
+
+BEGIN {
+
+  # --- Initialization ---
+
+  i = 1;
+  if (i in ARGV) len = ARGV[i++]; else len = 32;
+  if (i in ARGV) op = ARGV[i++]; else op = "+";
+  if (i in ARGV) rep = ARGV[i++]; else rep = 1;
+
+  # --- Output filters ---
+  #
+  # This is complicated.  `bc' emits numbers split over multiple lines with
+  # backslashes.  It also doesn't pad to an even number of digits, which the
+  # test rig is expecting, or use lower-case, which looks nicer.
+  #
+  # The first bit matches a line ending with a backslash.  If it finds one,
+  # it appends the next line, removes the backslash/newline pair, and loops
+  # around to the top.
+  #
+  # The next substitution translates the whole kaboodle into lower-case.
+  #
+  # The next one looks for an off number of hex digits and prepends a zero if
+  # it finds one.
+  #
+  # The one after that just indents by two spaces. The final one sticks a
+  # semicolon on the end.
+
+  bc = "bc | sed '\
+:top\n\
+/\\\\$/ {\n\
+  N\n\
+  s/\\\\\\\n\
+//;\n\
+  b top;\n\
+}\n\
+y/ABCDEF/abcdef/\n\
+s/^[0-9a-f]\\([0-9a-f][0-9a-f]\\)*$/0&/\n\
+s/^/  /\n\
+$ s/$/;/'";
+  out = "sed 'y/ABCDEF/abcdef/; s/^/  /'"
+
+  # --- Main code ---
+
+  srand();
+
+  while (rep--) {
+    x = r();
+
+    print "obase = 16" | bc;
+    print "ibase = 16" | bc;
+
+    # --- Shifting operations ---
+
+    if (op == "<<" || op == ">>") {
+      y = int(rand() * len * 4) + int(rand() * len * 4);
+      rop = (op == "<<" ? "*" : "/");
+      z = sprintf("%X", y);
+      print x, y | out;
+      print x, rop, "(2 ^ " z ")" | bc;
+    }
+
+    # --- Division ---
+
+    else if (op == "/") {
+      ylen = int(rand() * len) + 1;
+      y = r(ylen);
+      print x | out;
+      print y | out;
+      print x, "/", y | bc;
+      print x, "%", y | bc;
+    }
+
+    # --- Squaring ---
+
+    else if (op == "2") {
+      print x | out;
+      print x, "*", x | bc;
+    }
+
+    # --- Other operations ---
+
+    else {
+      y = r();
+      if (op == "-" && x < y) {
+       t = x; x = y; y = t;
+      }
+      print x | out;
+      print y | out;
+      print x, op, y | bc;
+    }
+
+    close(out);
+    close(bc);
+    if (rep)
+      print;
+  }
+
+  exit 0;
+}
diff --git a/math/t/pgen b/math/t/pgen
new file mode 100644 (file)
index 0000000..8d52d19
--- /dev/null
@@ -0,0 +1,38 @@
+# Test vectors for prime number finder
+
+pgen {
+  2 2;
+  3 3;
+  245 251;
+
+  4294967295 4294967311;
+
+  # --- These can take a little while ---
+
+  498459898455435345676576789 498459898455435345676576793;
+  40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493525769 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493526197;
+  166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520173 166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520257;
+}
+
+primep {
+  -5 0;
+  -1 0;
+  0 0;
+  1 0;
+  2 1;
+  3 1;
+  4 0;
+  40301809 1;
+  40301811 0;
+}
+
+primeiter {
+  0 2 3 5 7 11;
+  2 2 3 5 7 11;
+  3 3 5 7 11 13;
+  4 5 7 11 13 17;
+
+  2309 2309 2311 2333 2339 2341;
+  7878 7879 7883 7901 7907 7919;
+  7879 7879 7883 7901 7907 7919;
+}
diff --git a/maurer.c b/maurer.c
deleted file mode 100644 (file)
index a6dd31a..0000000
--- a/maurer.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/* -*-c-*-
- *
- * $Id: maurer.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Maurer's universal statistical test
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-
-#include "maurer.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct bitscan {
-  const octet *p;
-  unsigned b;
-  uint32 a;
-} bitscan;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @maurer_init@ --- *
- *
- * Arguments:  @maurer_ctx *m@ = pointer to a context to initialize
- *             @unsigned l@ = number of bits to take at a time
- *
- * Returns:    Minimum recommended amount of data to test.
- *
- * Use:                Initializes a Maurer testing context.  Note that @l@ values
- *             larger than 16 are not supported, and values less than 6 can
- *             give bizarre results.
- */
-
-unsigned long maurer_init(maurer_ctx *m, unsigned l)
-{
-  size_t i;
-
-  assert(((void)"(maurer_init): chunks larger than 16 bits not supported",
-         0 < l && l <= 16));
-
-  m->l = l;
-  m->a = 0;
-  m->b = 0;
-  m->n = 0;
-  m->x = 0;
-
-  m->t = xmalloc(sizeof(unsigned long) << l);
-  for (i = 0; i < (1 << l); i++)
-    m->t[i] = 0;
-  return (((1000ul << l) * l + 7)/8);
-}
-
-/* --- @bits@ --- *
- *
- * Arguments:  @maurer_ctx *m@ = pointer to testing context
- *             @const octet **p@ = address of a buffer pointer
- *             @const octet *q@ = limit of the buffer pointer
- *             @unsigned *x@ = address to store next chunk
- *
- * Returns:    Nonzero if some more bits arrived.
- *
- * Use:                Reads some bits from a buffer.
- */
-
-static int bits(maurer_ctx *m, const octet **p, const octet *q, unsigned *x)
-{
-  while (m->b < m->l) {
-    if (*p >= q)
-      return (0);
-    m->a |= U8(*(*p)++) << m->b;
-    m->b += 8;
-  }
-  *x = m->a & ((1 << m->l) - 1);
-  m->a >>= m->l;
-  m->b -= m->l;
-  m->n++;
-  return (1);
-}
-
-/* --- @maurer_test@ --- *
- *
- * Arguments:  @maurer_ctx *m@ = pointer to a Maurer testing context
- *             @const void *buf@ = pointer to a buffer of data
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    ---
- *
- * Use:                Scans a buffer of data and updates the testing context.
- */
-
-void maurer_test(maurer_ctx *m, const void *buf, size_t sz)
-{
-  const octet *p = buf, *l = p + sz;
-  unsigned long q = 10 << m->l;
-  unsigned x;
-
-  /* --- Initialize the table --- */
-
-  while (m->n < q) {
-    if (!bits(m, &p, l, &x))
-      return;
-    m->t[x] = m->n;
-  }
-
-  /* --- Update the statistic --- */
-
-  while (bits(m, &p, l, &x)) {
-    m->x += log(m->n - m->t[x]);
-    m->t[x] = m->n;
-  }
-}
-
-/* --- @maurer_done@ --- *
- *
- * Arguments:  @maurer_ctx *m@ = pointer to a Maurer testing context
- *
- * Returns:    The statistic %$Z_u = (X_u - \mu)/\sigma$%, which should be
- *             normally distributed with a mean of 0 and variance of 1.
- *
- * Use:                Returns the result of Maurer's universal statistical test.
- *             Also frees the memory allocated during initialization.
- *
- *             If insufficient data was received, the value @HUGE_VAL@ is
- *             returned.
- */
-
-double maurer_done(maurer_ctx *m)
-{
-  double x, mu, c, sigma;
-  unsigned long q = 10 << m->l, k;
-
-  /* --- Table for means and variances --- */
-
-  struct { double mu, var_1; } vtab[] = {
-    {  0.7326495, 0.690 },
-    {  1.5374383, 1.338 },
-    {  2.4016068, 1.901 },
-    {  3.3112247, 2.358 },
-    {  4.2534266, 2.705 },
-    {  5.2177052, 2.945 },
-    {  6.1962507, 3.125 },
-    {  7.1836656, 3.238 },
-    {  8.1764248, 3.311 },
-    {  9.1723243, 3.356 },
-    { 10.170032 , 3.384 },
-    { 11.168765 , 3.401 },
-    { 12.168070 , 3.410 },
-    { 13.167693 , 3.416 },
-    { 14.167488 , 3.419 },
-    { 15.167379 , 3.421 }
-  };
-
-  /* --- Check for bogus requests --- */
-
-  if (m->n < q) {
-    x = HUGE_VAL;
-    goto done;
-  }
-
-  /* --- Do the maths --- *
-   *
-   * This produces %$X_u$%, which should be normally distributed with a mean
-   * and variance we can compute.
-   */
-
-  k = m->n - q;
-  x = m->x/(k * log(2));
-
-  /* --- Now translate this into %$Z_u$% distributed as %$N(0, 1)$% --- */
-
-  mu = vtab[m->l - 1].mu;
-  c = 0.7 - 0.8/m->l + (1.6 + 12.8/m->l) * pow(k, -4.0/m->l);
-  sigma = sqrt(c * c * vtab[m->l - 1].var_1 / k);
-  x = (x - mu)/sigma;
-
-  /* --- Done (phew!) --- */
-
-done:
-  xfree(m->t);
-  return (x);
-}
-
-/* --- @maurer@ --- *
- *
- * Arguments:  @const octet *p@ = pointer to a buffer of data
- *             @size_t sz@ = size of the buffer
- *             @unsigned l@ = number of bits to take at a time
- *
- * Returns:    The statistic %$Z_u$%.
- *
- * Use:                Simple interface to Maurer's universal statistical test.  For
- *             large %$l$% you should use the more complicated restartable
- *             interface.
- */
-
-double maurer(const octet *p, size_t sz, unsigned l)
-{
-  maurer_ctx m;
-
-  maurer_init(&m, l);
-  maurer_test(&m, p, sz);
-  return (maurer_done(&m));
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/maurer.h b/maurer.h
deleted file mode 100644 (file)
index 7373660..0000000
--- a/maurer.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* -*-c-*-
- *
- * $Id: maurer.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Maurer's universal statistical test
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_MAURER_H
-#define CATACOMB_MAURER_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct maurer_ctx {
-  unsigned l;                          /* Chunk size, in bits */
-  uint32 a;                            /* Bitscanner accumulator */
-  unsigned b;                          /* Number of bits in accumulator */
-  unsigned long n;                     /* Number of chunks read so far */
-  double x;                            /* Statistic value */
-  unsigned long *t;                    /* Offset table */
-} maurer_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @maurer_init@ --- *
- *
- * Arguments:  @maurer_ctx *m@ = pointer to a context to initialize
- *             @unsigned l@ = number of bits to take at a time
- *
- * Returns:    Minimum recommended amount of data to test.
- *
- * Use:                Initializes a Maurer testing context.  Note that @l@ values
- *             larger than 16 are not supported, and values less than 6 can
- *             give bizarre results.
- */
-
-extern unsigned long maurer_init(maurer_ctx */*m*/, unsigned /*l*/);
-
-/* --- @maurer_test@ --- *
- *
- * Arguments:  @maurer_ctx *m@ = pointer to a Maurer testing context
- *             @const void *buf@ = pointer to a buffer of data
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    ---
- *
- * Use:                Scans a buffer of data and updates the testing context.
- */
-
-extern void maurer_test(maurer_ctx */*m*/,
-                       const void */*buf*/, size_t /*sz*/);
-
-/* --- @maurer_done@ --- *
- *
- * Arguments:  @maurer_ctx *m@ = pointer to a Maurer testing context
- *
- * Returns:    The statistic %$Z_u = (X_u - \mu)/\sigma$%, which should be
- *             normally distributed with a mean of 0 and variance of 1.
- *
- * Use:                Returns the result of Maurer's universal statistical test.
- *             Also frees the memory allocated during initialization.
- *
- *             If insufficient data was received, the value @HUGE_VAL@ is
- *             returned.
- */
-
-extern double maurer_done(maurer_ctx */*m*/);
-
-/* --- @maurer@ --- *
- *
- * Arguments:  @const octet *p@ = pointer to a buffer of data
- *             @size_t sz@ = size of the buffer
- *             @unsigned l@ = number of bits to take at a time
- *
- * Returns:    The statistic %$Z_u$%.
- *
- * Use:                Simple interface to Maurer's universal statistical test.  For
- *             large %$l$% you should use the more complicated restartable
- *             interface.
- */
-
-extern double maurer(const octet */*p*/, size_t /*sz*/, unsigned /*l*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/md2-tab.h b/md2-tab.h
deleted file mode 100644 (file)
index 4217e77..0000000
--- a/md2-tab.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*-c-*-
- *
- * $Id: md2-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Tables for MD2
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_MD2_TAB_H
-#define CATACOMB_MD2_TAB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- S-box table -------------------------------------------------------*/
-
-#define MD2_S {                                                                \
-  0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01,                      \
-  0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13,                      \
-  0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c,                      \
-  0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca,                      \
-  0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16,                      \
-  0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,                      \
-  0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49,                      \
-  0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a,                      \
-  0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f,                      \
-  0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21,                      \
-  0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27,                      \
-  0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,                      \
-  0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1,                      \
-  0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6,                      \
-  0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6,                      \
-  0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1,                      \
-  0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,                      \
-  0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,                      \
-  0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6,                      \
-  0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f,                      \
-  0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a,                      \
-  0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26,                      \
-  0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09,                      \
-  0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,                      \
-  0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa,                      \
-  0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a,                      \
-  0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d,                      \
-  0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39,                      \
-  0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4,                      \
-  0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,                      \
-  0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a,                      \
-  0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14                       \
-}
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/md2.c b/md2.c
deleted file mode 100644 (file)
index 987eb39..0000000
--- a/md2.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/* -*-c-*-
- *
- * $Id: md2.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The MD2 message digest function
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "md2.h"
-#include "md2-tab.h"
-
-/*----- Tables ------------------------------------------------------------*/
-
-static const octet s[256] = MD2_S;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @md2_compress@ --- *
- *
- * Arguments:  @md2_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                MD2 compression and checksum function.
- */
-
-void md2_compress(md2_ctx *ctx, const void *sbuf)
-{
-  unsigned i;
-  unsigned t;
-  octet x[MD2_BUFSZ];
-  octet y[MD2_BUFSZ];
-
-  /* --- Handy macro for doing something lots of times --- */
-
-#define DO(what, where) do {                                           \
-  what(where,  0); what(where, 1); what(where,  2); what(where,  3);   \
-  what(where,  4); what(where, 5); what(where,  6); what(where,  7);   \
-  what(where,  8); what(where, 9); what(where, 10); what(where, 11);   \
-  what(where, 12); what(where, 13); what(where, 14); what(where, 15);  \
-} while (0)
-
-  /* --- Do the hashing first to avoid corrupting the checksum --- */
-
-  memcpy(x, sbuf, sizeof(x));
-#define X(z, i) y[i] = z[i] ^ ctx->h[i]
-  DO(X, x);
-#undef X
-
-  t = 0;
-  for (i = 0; i < 18; i++) {
-#define X(z, i) t = z[i] ^= s[t];
-    DO(X, ctx->h);
-    DO(X, x);
-    DO(X, y);
-#undef X
-    t = U8(t + i);
-  }
-
-  /* --- Now compute the checksum --- */
-
-  t = ctx->c[MD2_BUFSZ - 1];
-#define X(z, i) t = ctx->c[i] ^= s[z[i] ^ t]
-  DO(X, ((const octet *)sbuf));
-#undef X
-
-#undef DO
-}
-
-/* --- @md2_init@ --- *
- *
- * Arguments:  @md2_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void md2_init(md2_ctx *ctx)
-{
-  memset(ctx->c, 0, sizeof(ctx->c));
-  memset(ctx->h, 0, sizeof(ctx->h));
-  ctx->off = 0;
-}
-
-/* --- @md2_set@ --- *
- *
- * Arguments:  @md2_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 md2_set(md2_ctx *ctx, const void *buf, unsigned long count)
-{
-  const octet *p = buf;
-  memcpy(ctx->h, p, MD2_BUFSZ);
-  memcpy(ctx->c, p + MD2_BUFSZ, MD2_BUFSZ);
-  ctx->off = 0;
-}
-
-/* --- @md2_hash@ --- *
- *
- * Arguments:  @md2_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 md2_hash(md2_ctx *ctx, const void *buf, size_t sz)
-{
-  const octet *bbuf = (octet *)buf;
-
-  /* --- Code automatically expanded from @HASH_BUFFER@ and tidied --- */
-
-  if (ctx->off + sz < MD2_BUFSZ) {
-    memcpy(ctx->buf + ctx->off, bbuf, sz);
-    ctx->off += sz;
-  } else {
-    if (ctx->off) {
-      size_t s = MD2_BUFSZ - ctx->off;
-      memcpy(ctx->buf + ctx->off, bbuf, s);
-      md2_compress(ctx, ctx->buf);
-      sz -= s;
-      bbuf += s;
-    }
-    while (sz >= MD2_BUFSZ) {
-      md2_compress(ctx, bbuf);
-      sz -= MD2_BUFSZ; bbuf += MD2_BUFSZ;
-    }
-    if (sz)
-      memcpy(ctx->buf, bbuf, sz);
-    ctx->off = sz;
-  }
-}
-
-/* --- @md2_done@ --- *
- *
- * Arguments:  @md2_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void md2_done(md2_ctx *ctx, void *hash)
-{
-  unsigned pad = MD2_BUFSZ - ctx->off;
-  unsigned i;
-  for (i = ctx->off; i < MD2_BUFSZ; i++)
-    ctx->buf[i] = pad;
-  md2_compress(ctx, ctx->buf);
-  md2_compress(ctx, ctx->c);
-  memcpy(hash, ctx->h, MD2_BUFSZ);
-}
-
-/* --- @md2_state@ --- *
- *
- * Arguments:  @md2_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 @md2_set@.
- */
-
-unsigned long md2_state(md2_ctx *ctx, void *state)
-{
-  octet *p = state;
-  memcpy(p, ctx->h, MD2_BUFSZ);
-  memcpy(p + MD2_BUFSZ, ctx->c, MD2_BUFSZ);
-  return (0);
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(MD2, md2)
-
-/* --- Test code --- */
-
-HASH_TEST(MD2, md2)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/md2.h b/md2.h
deleted file mode 100644 (file)
index 4d2b884..0000000
--- a/md2.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* -*-c-*-
- *
- * $Id: md2.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The MD2 message digest function
- *
- * (c) 2001 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.
- */
-
-/*----- Notes on the MD2 hash function ------------------------------------*
- *
- * MD2 was designed by Ron Rivest.  It's not recommended for new applications
- * because only the `checksum' part of the function resists collision-finding
- * attacks.  It's not very fast either.  However, it's still used in
- * standards, and having it available can be useful.
- */
-
-#ifndef CATACOMB_MD2_H
-#define CATACOMB_MD2_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define MD2_BUFSZ 16
-#define MD2_HASHSZ 16
-#define MD2_STATESZ 32
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct md2_ctx {
-  octet c[MD2_BUFSZ];                  /* Checksum buffer */
-  octet h[MD2_BUFSZ];                  /* Hash result buffer */
-  octet buf[MD2_BUFSZ];                        /* Input buffer */
-  unsigned off;                                /* Offset into buffer */
-} md2_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @md2_compress@ --- *
- *
- * Arguments:  @md2_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                MD2 compression function.
- */
-
-extern void md2_compress(md2_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @md2_init@ --- *
- *
- * Arguments:  @md2_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void md2_init(md2_ctx */*ctx*/);
-
-/* --- @md2_set@ --- *
- *
- * Arguments:  @md2_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 md2_set(md2_ctx */*ctx*/, const void */*buf*/,
-                   unsigned long /*count*/);
-
-/* --- @md2_hash@ --- *
- *
- * Arguments:  @md2_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 md2_hash(md2_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @md2_done@ --- *
- *
- * Arguments:  @md2_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 md2_done(md2_ctx */*ctx*/, void */*hash*/);
-
-/* --- @md2_state@ --- *
- *
- * Arguments:  @md2_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 @md2_set@.
- */
-
-extern unsigned long md2_state(md2_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash md2;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/md4.c b/md4.c
deleted file mode 100644 (file)
index 5d43817..0000000
--- a/md4.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* -*-c-*-
- *
- * $Id: md4.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The MD4 message digest function
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "md4.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @md4_compress@ --- *
- *
- * Arguments:  @md4_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-160 compression function.
- */
-
-void md4_compress(md4_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d;
-  uint32 buf[16];
-
-  /* --- Fetch the chaining variables --- */
-
-  a = ctx->a;
-  b = ctx->b;
-  c = ctx->c;
-  d = ctx->d;
-
-  /* --- 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)) | ((x) & (z)) | ((y) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-#define T(w, x, y, z, i, r, k, f) do {                                 \
-  uint32 _t = w + f(x, y, z) + buf[i] + k;                             \
-  w = ROL32(_t, r);                                                    \
-} while (0)
-
-#define FF(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x00000000, F)
-#define GG(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x5a827999, G)
-#define HH(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x6ed9eba1, H)
-
-  /* --- The main compression function --- */
-
-  FF(a, b, c, d,  0,  3);
-  FF(d, a, b, c,  1,  7);
-  FF(c, d, a, b,  2, 11);
-  FF(b, c, d, a,  3, 19);
-  FF(a, b, c, d,  4,  3);
-  FF(d, a, b, c,  5,  7);
-  FF(c, d, a, b,  6, 11);
-  FF(b, c, d, a,  7, 19);
-  FF(a, b, c, d,  8,  3);
-  FF(d, a, b, c,  9,  7);
-  FF(c, d, a, b, 10, 11);
-  FF(b, c, d, a, 11, 19);
-  FF(a, b, c, d, 12,  3);
-  FF(d, a, b, c, 13,  7);
-  FF(c, d, a, b, 14, 11);
-  FF(b, c, d, a, 15, 19);
-
-  GG(a, b, c, d,  0,  3);
-  GG(d, a, b, c,  4,  5);
-  GG(c, d, a, b,  8,  9);
-  GG(b, c, d, a, 12, 13);
-  GG(a, b, c, d,  1,  3);
-  GG(d, a, b, c,  5,  5);
-  GG(c, d, a, b,  9,  9);
-  GG(b, c, d, a, 13, 13);
-  GG(a, b, c, d,  2,  3);
-  GG(d, a, b, c,  6,  5);
-  GG(c, d, a, b, 10,  9);
-  GG(b, c, d, a, 14, 13);
-  GG(a, b, c, d,  3,  3);
-  GG(d, a, b, c,  7,  5);
-  GG(c, d, a, b, 11,  9);
-  GG(b, c, d, a, 15, 13);
-
-  HH(a, b, c, d,  0,  3);
-  HH(d, a, b, c,  8,  9);
-  HH(c, d, a, b,  4, 11);
-  HH(b, c, d, a, 12, 15);
-  HH(a, b, c, d,  2,  3);
-  HH(d, a, b, c, 10,  9);
-  HH(c, d, a, b,  6, 11);
-  HH(b, c, d, a, 14, 15);
-  HH(a, b, c, d,  1,  3);
-  HH(d, a, b, c,  9,  9);
-  HH(c, d, a, b,  5, 11);
-  HH(b, c, d, a, 13, 15);
-  HH(a, b, c, d,  3,  3);
-  HH(d, a, b, c, 11,  9);
-  HH(c, d, a, b,  7, 11);
-  HH(b, c, d, a, 15, 15);
-
-  /* --- Update the chaining variables --- */
-
-  ctx->a += a;
-  ctx->b += b;
-  ctx->c += c;
-  ctx->d += d;
-}
-
-/* --- @md4_init@ --- *
- *
- * Arguments:  @md4_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void md4_init(md4_ctx *ctx)
-{
-  ctx->a = 0x67452301;
-  ctx->b = 0xefcdab89;
-  ctx->c = 0x98badcfe;
-  ctx->d = 0x10325476;
-  ctx->off = 0;
-  ctx->nl = ctx->nh = 0;
-}
-
-/* --- @md4_set@ --- *
- *
- * Arguments:  @md4_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 md4_set(md4_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->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @md4_hash@ --- *
- *
- * Arguments:  @md4_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 md4_hash(md4_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(MD4, md4, ctx, buf, sz);
-}
-
-/* --- @md4_done@ --- *
- *
- * Arguments:  @md4_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void md4_done(md4_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  HASH_MD5STRENGTH(MD4, md4, 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);
-}
-
-/* --- @md4_state@ --- *
- *
- * Arguments:  @md4_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 @md4_set@.
- */
-
-unsigned long md4_state(md4_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);
-  return (ctx->nl | ((ctx->nh >> 16) >> 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(MD4, md4)
-
-/* --- Test rig --- */
-
-HASH_TEST(MD4, md4)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/md4.h b/md4.h
deleted file mode 100644 (file)
index d33d8ce..0000000
--- a/md4.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*-c-*-
- *
- * $Id: md4.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * The MD4 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Notes on the MD4 hash function ------------------------------------*
- *
- * MD4 was designed by Ron Rivest.  It's now well and truly broken: not only
- * have collisions been discovered, a slightly cut-down version has been
- * shown to be non-preimage-resistant.  On the other hand, MD4 is fast and
- * makes a good heavy-duty checksum.  Just don't rely on it being
- * cryptographically strong, 'cos it ain't.
- */
-
-#ifndef CATACOMB_MD4_H
-#define CATACOMB_MD4_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define MD4_BUFSZ 64
-#define MD4_HASHSZ 16
-#define MD4_STATESZ 16
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct md4_ctx {
-  uint32 a, b, c, d;                   /* Chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[MD4_BUFSZ];                        /* Accumulation buffer */
-} md4_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @md4_compress@ --- *
- *
- * Arguments:  @md4_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                MD4 compression function.
- */
-
-extern void md4_compress(md4_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @md4_init@ --- *
- *
- * Arguments:  @md4_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void md4_init(md4_ctx */*ctx*/);
-
-/* --- @md4_set@ --- *
- *
- * Arguments:  @md4_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 md4_set(md4_ctx */*ctx*/, const void */*buf*/,
-                   unsigned long /*count*/);
-
-/* --- @md4_hash@ --- *
- *
- * Arguments:  @md4_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 md4_hash(md4_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @md4_done@ --- *
- *
- * Arguments:  @md4_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 md4_done(md4_ctx */*ctx*/, void */*hash*/);
-
-/* --- @md4_state@ --- *
- *
- * Arguments:  @md4_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 @md4_set@.
- */
-
-extern unsigned long md4_state(md4_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash md4;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/md5.c b/md5.c
deleted file mode 100644 (file)
index a062c72..0000000
--- a/md5.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* -*-c-*-
- *
- * $Id: md5.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The MD5 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "md5.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @md5_compress@ --- *
- *
- * Arguments:  @md5_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                MD5 compression function.
- */
-
-void md5_compress(md5_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d;
-  uint32 buf[16];
-
-  /* --- Fetch the chaining variables --- */
-
-  a = ctx->a;
-  b = ctx->b;
-  c = ctx->c;
-  d = ctx->d;
-
-  /* --- 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) & (z)) | ((y) & ~(z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-
-#define T(w, x, y, z, i, r, k, f) do {                                 \
-  uint32 _t = w + f(x, y, z) + buf[i] + k;                             \
-  w = ROL32(_t, r) + x;                                                        \
-} while (0)
-
-#define FF(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, F)
-#define GG(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, G)
-#define HH(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, H)
-#define II(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, I)
-
-  /* --- The main compression function --- */
-
-  FF(a, b, c, d,  0,  7, 0xd76aa478);
-  FF(d, a, b, c,  1, 12, 0xe8c7b756);
-  FF(c, d, a, b,  2, 17, 0x242070db);
-  FF(b, c, d, a,  3, 22, 0xc1bdceee);
-  FF(a, b, c, d,  4,  7, 0xf57c0faf);
-  FF(d, a, b, c,  5, 12, 0x4787c62a);
-  FF(c, d, a, b,  6, 17, 0xa8304613);
-  FF(b, c, d, a,  7, 22, 0xfd469501);
-  FF(a, b, c, d,  8,  7, 0x698098d8);
-  FF(d, a, b, c,  9, 12, 0x8b44f7af);
-  FF(c, d, a, b, 10, 17, 0xffff5bb1);
-  FF(b, c, d, a, 11, 22, 0x895cd7be);
-  FF(a, b, c, d, 12,  7, 0x6b901122);
-  FF(d, a, b, c, 13, 12, 0xfd987193);
-  FF(c, d, a, b, 14, 17, 0xa679438e);
-  FF(b, c, d, a, 15, 22, 0x49b40821);
-
-  GG(a, b, c, d,  1,  5, 0xf61e2562);
-  GG(d, a, b, c,  6,  9, 0xc040b340);
-  GG(c, d, a, b, 11, 14, 0x265e5a51);
-  GG(b, c, d, a,  0, 20, 0xe9b6c7aa);
-  GG(a, b, c, d,  5,  5, 0xd62f105d);
-  GG(d, a, b, c, 10,  9, 0x02441453);
-  GG(c, d, a, b, 15, 14, 0xd8a1e681);
-  GG(b, c, d, a,  4, 20, 0xe7d3fbc8);
-  GG(a, b, c, d,  9,  5, 0x21e1cde6);
-  GG(d, a, b, c, 14,  9, 0xc33707d6);
-  GG(c, d, a, b,  3, 14, 0xf4d50d87);
-  GG(b, c, d, a,  8, 20, 0x455a14ed);
-  GG(a, b, c, d, 13,  5, 0xa9e3e905);
-  GG(d, a, b, c,  2,  9, 0xfcefa3f8);
-  GG(c, d, a, b,  7, 14, 0x676f02d9);
-  GG(b, c, d, a, 12, 20, 0x8d2a4c8a);
-
-  HH(a, b, c, d,  5,  4, 0xfffa3942);
-  HH(d, a, b, c,  8, 11, 0x8771f681);
-  HH(c, d, a, b, 11, 16, 0x6d9d6122);
-  HH(b, c, d, a, 14, 23, 0xfde5380c);
-  HH(a, b, c, d,  1,  4, 0xa4beea44);
-  HH(d, a, b, c,  4, 11, 0x4bdecfa9);
-  HH(c, d, a, b,  7, 16, 0xf6bb4b60);
-  HH(b, c, d, a, 10, 23, 0xbebfbc70);
-  HH(a, b, c, d, 13,  4, 0x289b7ec6);
-  HH(d, a, b, c,  0, 11, 0xeaa127fa);
-  HH(c, d, a, b,  3, 16, 0xd4ef3085);
-  HH(b, c, d, a,  6, 23, 0x04881d05);
-  HH(a, b, c, d,  9,  4, 0xd9d4d039);
-  HH(d, a, b, c, 12, 11, 0xe6db99e5);
-  HH(c, d, a, b, 15, 16, 0x1fa27cf8);
-  HH(b, c, d, a,  2, 23, 0xc4ac5665);
-
-  II(a, b, c, d,  0,  6, 0xf4292244);
-  II(d, a, b, c,  7, 10, 0x432aff97);
-  II(c, d, a, b, 14, 15, 0xab9423a7);
-  II(b, c, d, a,  5, 21, 0xfc93a039);
-  II(a, b, c, d, 12,  6, 0x655b59c3);
-  II(d, a, b, c,  3, 10, 0x8f0ccc92);
-  II(c, d, a, b, 10, 15, 0xffeff47d);
-  II(b, c, d, a,  1, 21, 0x85845dd1);
-  II(a, b, c, d,  8,  6, 0x6fa87e4f);
-  II(d, a, b, c, 15, 10, 0xfe2ce6e0);
-  II(c, d, a, b,  6, 15, 0xa3014314);
-  II(b, c, d, a, 13, 21, 0x4e0811a1);
-  II(a, b, c, d,  4,  6, 0xf7537e82);
-  II(d, a, b, c, 11, 10, 0xbd3af235);
-  II(c, d, a, b,  2, 15, 0x2ad7d2bb);
-  II(b, c, d, a,  9, 21, 0xeb86d391);
-
-  /* --- Update the chaining variables --- */
-
-  ctx->a += a;
-  ctx->b += b;
-  ctx->c += c;
-  ctx->d += d;
-}
-
-/* --- @md5_init@ --- *
- *
- * Arguments:  @md5_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void md5_init(md5_ctx *ctx)
-{
-  ctx->a = 0x67452301;
-  ctx->b = 0xefcdab89;
-  ctx->c = 0x98badcfe;
-  ctx->d = 0x10325476;
-  ctx->off = 0;
-  ctx->nl = ctx->nh = 0;
-}
-
-/* --- @md5_set@ --- *
- *
- * Arguments:  @md5_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 md5_set(md5_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->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @md5_hash@ --- *
- *
- * Arguments:  @md5_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 md5_hash(md5_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(MD5, md5, ctx, buf, sz);
-}
-
-/* --- @md5_done@ --- *
- *
- * Arguments:  @md5_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void md5_done(md5_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  HASH_MD5STRENGTH(MD5, md5, 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);
-}
-
-/* --- @md5_state@ --- *
- *
- * Arguments:  @md5_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 @md5_set@.
- */
-
-unsigned long md5_state(md5_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);
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(MD5, md5)
-
-/* --- Test code --- */
-
-HASH_TEST(MD5, md5)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/md5.h b/md5.h
deleted file mode 100644 (file)
index 291ceca..0000000
--- a/md5.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/* -*-c-*-
- *
- * $Id: md5.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * The MD5 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Notes on the MD5 hash function ------------------------------------*
- *
- * MD5 was designed by Ron Rivest.  It was intended to be a more conservative
- * design than the slightly earlier MD4, and indeed while MD4 has been pretty
- * much demolished by subsequent cryptanalysis, MD5 is still standing
- * shakily.  It's provided here not because the author recommends its use but
- * because it's a common standard, and is often handy in non-cryptographic
- * applications.  It's also still useful in constructions such as HMAC.
- */
-
-#ifndef CATACOMB_MD5_H
-#define CATACOMB_MD5_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define MD5_BUFSZ 64
-#define MD5_HASHSZ 16
-#define MD5_STATESZ 16
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct md5_ctx {
-  uint32 a, b, c, d;                   /* Chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[MD5_BUFSZ];                        /* Accumulation buffer */
-} md5_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @md5_compress@ --- *
- *
- * Arguments:  @md5_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                MD5 compression function.
- */
-
-extern void md5_compress(md5_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @md5_init@ --- *
- *
- * Arguments:  @md5_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void md5_init(md5_ctx */*ctx*/);
-
-/* --- @md5_set@ --- *
- *
- * Arguments:  @md5_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 md5_set(md5_ctx */*ctx*/, const void */*buf*/,
-                   unsigned long /*count*/);
-
-/* --- @md5_hash@ --- *
- *
- * Arguments:  @md5_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 md5_hash(md5_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @md5_done@ --- *
- *
- * Arguments:  @md5_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 md5_done(md5_ctx */*ctx*/, void */*hash*/);
-
-/* --- @md5_state@ --- *
- *
- * Arguments:  @md5_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 @md5_set@.
- */
-
-extern unsigned long md5_state(md5_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash md5;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mgf-def.h b/mgf-def.h
deleted file mode 100644 (file)
index 6d9f4e5..0000000
--- a/mgf-def.h
+++ /dev/null
@@ -1,460 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mgf-def.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Definitions for the MGF-1 mask generator
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_MGF_DEF_H
-#define CATACOMB_MGF_DEF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-#define MGF_DEF(PRE, pre)                                              \
-                                                                       \
-/* --- Useful constants --- */                                         \
-                                                                       \
-const octet pre##_mgfkeysz[] = { KSZ_ANY, PRE##_HASHSZ };              \
-                                                                       \
-/* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- *                                \
- *                                                                     \
- * Arguments:  @pre_mgfctx *k@ = pointer to context to initialize      \
- *             @const void *p@ = pointer to data to contribute         \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                A multi-step keying procedure for initializing an MGF   \
- *             context.  The data is contributed to a hashing context  \
- *             which is then used for mask generation.  If you only    \
- *             have a fixed buffer, you can save a lot of effort by    \
- *             simply calling @pre_mgfinit@.                           \
- */                                                                    \
-                                                                       \
-void pre##_mgfkeybegin(pre##_mgfctx *k)                                        \
-{                                                                      \
-  k->c = 0;                                                            \
-  k->bsz = 0;                                                          \
-  pre##_init(&k->k);                                                   \
-}                                                                      \
-                                                                       \
-void pre##_mgfkeyadd(pre##_mgfctx *k, const void *p, size_t sz)                \
-{                                                                      \
-  pre##_hash(&k->k, p, sz);                                            \
-}                                                                      \
-                                                                       \
-/* ---- @pre_mgfinit@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_mgfctx *k@ = pointer to context to initialize      \
- *             @const void *p@ = pointer to data to contribute         \
- *             @size_t sz@ = size of data to contribute                \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                A simpler interface to initialization if all of your    \
- *             keying material is in one place.                        \
- */                                                                    \
-                                                                       \
-void pre##_mgfinit(pre##_mgfctx *k, const void *p, size_t sz)          \
-{                                                                      \
-  k->c = 0;                                                            \
-  k->bsz = 0;                                                          \
-  pre##_init(&k->k);                                                   \
-  pre##_hash(&k->k, p, sz);                                            \
-}                                                                      \
-                                                                       \
-/* --- @pre_mgfencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_mgfctx *k@ = pointer to masking context            \
- *             @const void *s@ = pointer to source buffer              \
- *             @void *d@ = pointer to destination buffer               \
- *             @size_t sz@ = size of buffers                           \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Outputs pseudorandom data, or masks an input buffer.    \
- *                                                                     \
- *             If @s@ is nonzero, the source material is exclusive-    \
- *             orred with the generated mask.  If @d@ is zero, the     \
- *             generator is simply spun around for a while, which      \
- *             isn't very useful.                                      \
- */                                                                    \
-                                                                       \
-void pre##_mgfencrypt(pre##_mgfctx *k, const void *s,                  \
-                     void *d, size_t sz)                               \
-{                                                                      \
-  const octet *ss = s;                                                 \
-  octet *dd = d;                                                       \
-                                                                       \
-  /* --- Empty the buffer if there's anything there --- */             \
-                                                                       \
-  if (k->bsz) {                                                                \
-    const octet *p = k->buf + PRE##_HASHSZ - k->bsz;                   \
-    size_t n = sz > k->bsz ? k->bsz : sz;                              \
-    sz -= n;                                                           \
-    k->bsz -= n;                                                       \
-    if (dd) {                                                          \
-      if (!ss) {                                                       \
-       memcpy(dd, p, n);                                               \
-       dd += n;                                                        \
-      } else {                                                         \
-       while (n) {                                                     \
-         *dd++ = *ss++ ^ *p++;                                         \
-         n--;                                                          \
-       }                                                               \
-      }                                                                        \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  /* --- While necessary, generate some more mask --- */               \
-                                                                       \
-  while (sz) {                                                         \
-    pre##_ctx c = k->k;                /* Not quick! */                        \
-    size_t n;                                                          \
-                                                                       \
-    STORE32(k->buf, k->c);                                             \
-    k->c++;                                                            \
-    pre##_hash(&c, k->buf, 4);                                         \
-    pre##_done(&c, k->buf);                                            \
-    n = sz > PRE##_HASHSZ ? PRE##_HASHSZ : sz;                         \
-    k->bsz = PRE##_HASHSZ - n;                                         \
-    sz -= n;                                                           \
-    if (dd) {                                                          \
-      const octet *p = k->buf;                                         \
-      if (!ss) {                                                       \
-       memcpy(dd, p, n);                                               \
-       dd += n;                                                        \
-      } else {                                                         \
-       while (n) {                                                     \
-         *dd++ = *ss++ ^ *p++;                                         \
-         n--;                                                          \
-       }                                                               \
-      }                                                                        \
-    }                                                                  \
-  }                                                                    \
-}                                                                      \
-                                                                       \
-/* --- @pre_mgfsetindex@ --- *                                         \
- *                                                                     \
- * Arguments:  @pre_mgfctx *k@ = pointer to masking context            \
- *             @uint32 *c@ = new index to set                          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets a new index.  This may be used to step around the  \
- *             output stream in a rather crude way.                    \
- */                                                                    \
-                                                                       \
-void pre##_mgfsetindex(pre##_mgfctx *k, uint32 c)                      \
-{                                                                      \
-  k->c = c;                                                            \
-  k->bsz = 0;                                                          \
-}                                                                      \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-static const gcipher_ops gops;                                         \
-                                                                       \
-typedef struct gctx {                                                  \
-  gcipher c;                                                           \
-  pre##_mgfctx k;                                                      \
-} gctx;                                                                        \
-                                                                       \
-static gcipher *ginit(const void *k, size_t sz)                                \
-{                                                                      \
-  gctx *g = S_CREATE(gctx);                                            \
-  g->c.ops = &gops;                                                    \
-  pre##_mgfinit(&g->k, k, sz);                                         \
-  return (&g->c);                                                      \
-}                                                                      \
-                                                                       \
-static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_mgfencrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
-                                                                       \
-static void gdestroy(gcipher *c)                                       \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static const gcipher_ops gops = {                                      \
-  &pre##_mgf,                                                          \
-  gencrypt, gencrypt, gdestroy, 0, 0                                   \
-};                                                                     \
-                                                                       \
-const gccipher pre##_mgf = {                                           \
-  #pre "-mgf", pre##_mgfkeysz, 0,                                      \
-  ginit                                                                        \
-};                                                                     \
-                                                                       \
-/* --- Generic random number generator interface --- */                        \
-                                                                       \
-typedef struct grctx {                                                 \
-  grand r;                                                             \
-  pre##_mgfctx k;                                                      \
-} grctx;                                                               \
-                                                                       \
-static void grdestroy(grand *r)                                                \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static int grmisc(grand *r, unsigned op, ...)                          \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  va_list ap;                                                          \
-  int rc = 0;                                                          \
-  va_start(ap, op);                                                    \
-                                                                       \
-  switch (op) {                                                                \
-    case GRAND_CHECK:                                                  \
-      switch (va_arg(ap, unsigned)) {                                  \
-       case GRAND_CHECK:                                               \
-       case GRAND_SEEDINT:                                             \
-       case GRAND_SEEDUINT32:                                          \
-       case GRAND_SEEDBLOCK:                                           \
-       case GRAND_SEEDRAND:                                            \
-         rc = 1;                                                       \
-         break;                                                        \
-       default:                                                        \
-         rc = 0;                                                       \
-         break;                                                        \
-      }                                                                        \
-      break;                                                           \
-    case GRAND_SEEDINT:                                                        \
-      pre##_mgfsetindex(&g->k, va_arg(ap, unsigned));                  \
-      break;                                                           \
-    case GRAND_SEEDUINT32:                                             \
-      pre##_mgfsetindex(&g->k, va_arg(ap, uint32));                    \
-      break;                                                           \
-    case GRAND_SEEDBLOCK: {                                            \
-      const void *p = va_arg(ap, const void *);                                \
-      size_t sz = va_arg(ap, size_t);                                  \
-      pre##_hash(&g->k.k, p, sz);                                      \
-    } break;                                                           \
-    case GRAND_SEEDRAND: {                                             \
-      octet buf[PRE##_BUFSZ];                                          \
-      grand *rr = va_arg(ap, grand *);                                 \
-      rr->ops->fill(rr, buf, sizeof(buf));                             \
-      pre##_hash(&g->k.k, buf, sizeof(buf));                           \
-    } break;                                                           \
-    default:                                                           \
-      GRAND_BADOP;                                                     \
-      break;                                                           \
-  }                                                                    \
-                                                                       \
-  va_end(ap);                                                          \
-  return (rc);                                                         \
-}                                                                      \
-                                                                       \
-static octet grbyte(grand *r)                                          \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  octet o;                                                             \
-  pre##_mgfencrypt(&g->k, 0, &o, 1);                                   \
-  return (o);                                                          \
-}                                                                      \
-                                                                       \
-static uint32 grword(grand *r)                                         \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  octet b[4];                                                          \
-  pre##_mgfencrypt(&g->k, 0, b, sizeof(b));                            \
-  return (LOAD32(b));                                                  \
-}                                                                      \
-                                                                       \
-static void grfill(grand *r, void *p, size_t sz)                       \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  pre##_mgfencrypt(&g->k, 0, p, sz);                                   \
-}                                                                      \
-                                                                       \
-static const grand_ops grops = {                                       \
-  #pre "-mgf",                                                         \
-  GRAND_CRYPTO, 0,                                                     \
-  grmisc, grdestroy,                                                   \
-  grword, grbyte, grword, grand_range, grfill                          \
-};                                                                     \
-                                                                       \
-/* --- @pre_mgfrand@ --- *                                             \
- *                                                                     \
- * Arguments:  @const void *k@ = pointer to key material               \
- *             @size_t sz@ = size of key material                      \
- *                                                                     \
- * Returns:    Pointer to a generic random number generator instance.  \
- *                                                                     \
- * Use:                Creates a random number interface wrapper around an     \
- *             MGF-1-mode hash function.                               \
- */                                                                    \
-                                                                       \
-extern grand *pre##_mgfrand(const void *k, size_t sz)                  \
-{                                                                      \
-  grctx *g = S_CREATE(grctx);                                          \
-  g->r.ops = &grops;                                                   \
-  pre##_mgfinit(&g->k, k, sz);                                         \
-  return (&g->r);                                                      \
-}                                                                      \
-                                                                       \
-MGF_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @MGF_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use:                Standard test rig for MGF functions.
- */
-
-#define MGF_TEST(PRE, pre)                                             \
-                                                                       \
-/* --- Initial plaintext for the test --- */                           \
-                                                                       \
-static const octet text[] = TEXT;                                      \
-                                                                       \
-/* --- Key and IV to use --- */                                                \
-                                                                       \
-static const octet key[] = KEY;                                                \
-                                                                       \
-/* --- Buffers for encryption and decryption output --- */             \
-                                                                       \
-static octet ct[sizeof(text)];                                         \
-static octet pt[sizeof(text)];                                         \
-                                                                       \
-static void hexdump(const octet *p, size_t sz)                         \
-{                                                                      \
-  const octet *q = p + sz;                                             \
-  for (sz = 0; p < q; p++, sz++) {                                     \
-    printf("%02x", *p);                                                        \
-    if ((sz + 1) % PRE##_HASHSZ == 0)                                  \
-      putchar(':');                                                    \
-  }                                                                    \
-}                                                                      \
-                                                                       \
-int main(void)                                                         \
-{                                                                      \
-  size_t sz = 0, rest;                                                 \
-  pre##_mgfctx ctx;                                                    \
-  int status = 0;                                                      \
-  int done = 0;                                                                \
-                                                                       \
-  size_t keysz = strlen((const char *)key);                            \
-                                                                       \
-  fputs(#pre "-mgf: ", stdout);                                                \
-                                                                       \
-  pre##_mgfinit(&ctx, key, keysz);                                     \
-                                                                       \
-  while (sz <= sizeof(text)) {                                         \
-    rest = sizeof(text) - sz;                                          \
-    memcpy(ct, text, sizeof(text));                                    \
-    pre##_mgfsetindex(&ctx, 0);                                                \
-    pre##_mgfencrypt(&ctx, ct, ct, sz);                                        \
-    pre##_mgfencrypt(&ctx, ct + sz, ct + sz, rest);                    \
-    memcpy(pt, ct, sizeof(text));                                      \
-    pre##_mgfsetindex(&ctx, 0);                                                \
-    pre##_mgfencrypt(&ctx, pt, pt, rest);                              \
-    pre##_mgfencrypt(&ctx, pt + rest, pt + rest, sz);                  \
-    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
-      done++;                                                          \
-      if (sizeof(text) < 40 || done % 8 == 0)                          \
-       fputc('.', stdout);                                             \
-      if (done % 480 == 0)                                             \
-       fputs("\n\t", stdout);                                          \
-      fflush(stdout);                                                  \
-    } else {                                                           \
-      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
-      status = 1;                                                      \
-      printf("\tplaintext      = "); hexdump(text, sz);                        \
-       printf(", "); hexdump(text + sz, rest);                         \
-       fputc('\n', stdout);                                            \
-      printf("\tciphertext     = "); hexdump(ct, sz);                  \
-       printf(", "); hexdump(ct + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      printf("\trecovered text = "); hexdump(pt, sz);                  \
-       printf(", "); hexdump(pt + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      fputc('\n', stdout);                                             \
-    }                                                                  \
-    if (sz < 63)                                                       \
-      sz++;                                                            \
-    else                                                               \
-      sz += 9;                                                         \
-  }                                                                    \
-                                                                       \
-  fputs(status ? " failed\n" : " ok\n", stdout);                       \
-  return (status);                                                     \
-}
-
-#else
-#  define MGF_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mgf.h b/mgf.h
deleted file mode 100644 (file)
index 273d5b0..0000000
--- a/mgf.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mgf.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The MGF mask generation function
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the MGF-1 mask generating function -----------------------*
- *
- * The idea of a mask-generating function is that given an input of arbitrary
- * size, it can emit a pseudorandom output `mask' of arbitrary size.  This is
- * used in PKCS#1 OAEP (RFC2437).  My recommendation would be to use a decent
- * stream cipher instead, like RC4 or SEAL.  MGF-1 isn't very fast.
- */
-
-#ifndef CATACOMB_MGF_H
-#define CATACOMB_MGF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-#define MGF_DECL(PRE, pre)                                             \
-                                                                       \
-/* --- An MGF generation context --- */                                        \
-                                                                       \
-typedef struct pre##_mgfctx {                                          \
-  pre##_ctx k;                         /* Underlying key context */    \
-  uint32 c;                            /* Counter */                   \
-  octet buf[PRE##_HASHSZ];             /* Output buffer */             \
-  size_t bsz;                          /* Size of buffered data */     \
-} pre##_mgfctx;                                                                \
-                                                                       \
-/* --- Other useful constants --- */                                   \
-                                                                       \
-extern const octet pre##_mgfkeysz[];                                   \
-                                                                       \
-/* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- *                                \
- *                                                                     \
- * Arguments:  @pre_mgfctx *k@ = pointer to context to initialize      \
- *             @const void *p@ = pointer to data to contribute         \
- *             @size_t sz@ = size of data to contribute                \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                A multi-step keying procedure for initializing an MGF   \
- *             context.  The data is contributed to a hashing context  \
- *             which is then used for mask generation.  If you only    \
- *             have a fixed buffer, you can save a lot of effort by    \
- *             simply calling @pre_mgfinit@.                           \
- */                                                                    \
-                                                                       \
-extern void pre##_mgfkeybegin(pre##_mgfctx */*k*/);                    \
-extern void pre##_mgfkeyadd(pre##_mgfctx */*k*/,                       \
-                           const void */*p*/, size_t /*sz*/);          \
-                                                                       \
-/* ---- @pre_mgfinit@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_mgfctx *k@ = pointer to context to initialize      \
- *             @const void *p@ = pointer to data to contribute         \
- *             @size_t sz@ = size of data to contribute                \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                A simpler interface to initialization if all of your    \
- *             keying material is in one place.                        \
- */                                                                    \
-                                                                       \
-extern void pre##_mgfinit(pre##_mgfctx */*k*/,                         \
-                         const void */*p*/, size_t /*sz*/);            \
-                                                                       \
-/* --- @pre_mgfencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_mgfctx *k@ = pointer to masking context            \
- *             @const void *s@ = pointer to source buffer              \
- *             @void *d@ = pointer to destination buffer               \
- *             @size_t sz@ = size of buffers                           \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Outputs pseudorandom data, or masks an input buffer.    \
- *                                                                     \
- *             If @s@ is nonzero, the source material is exclusive-    \
- *             orred with the generated mask.  If @d@ is zero, the     \
- *             generator is simply spun around for a while, which      \
- *             isn't very useful.                                      \
- */                                                                    \
-                                                                       \
-extern void pre##_mgfencrypt(pre##_mgfctx */*k*/, const void */*s*/,   \
-                            void */*d*/, size_t /*sz*/);               \
-                                                                       \
-/* --- @pre_mgfsetindex@ --- *                                         \
- *                                                                     \
- * Arguments:  @pre_mgfctx *k@ = pointer to masking context            \
- *             @uint32 *c@ = new index to set                          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets a new index.  This may be used to step around the  \
- *             output stream in a rather crude way.                    \
- */                                                                    \
-                                                                       \
-extern void pre##_mgfsetindex(pre##_mgfctx */*k*/, uint32 /*c*/);      \
-                                                                       \
-/* --- @pre_mgfrand@ --- *                                             \
- *                                                                     \
- * Arguments:  @const void *k@ = pointer to key material               \
- *             @size_t sz@ = size of key material                      \
- *                                                                     \
- * Returns:    Pointer to a generic random number generator instance.  \
- *                                                                     \
- * Use:                Creates a random number interface wrapper around an     \
- *             MGF-1-mode hash function.                               \
- */                                                                    \
-                                                                       \
-extern grand *pre##_mgfrand(const void */*k*/, size_t /*sz*/);         \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-extern const gccipher pre##_mgf;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/misc/Makefile.am b/misc/Makefile.am
new file mode 100644 (file)
index 0000000..f5f380a
--- /dev/null
@@ -0,0 +1,51 @@
+### -*-makefile-*-
+###
+### Build script for miscellaneous cryptography
+###
+### (c) 2013 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.
+
+include $(top_srcdir)/vars.am
+
+noinst_LTLIBRARIES      = libmisc.la
+libmisc_la_SOURCES      =
+
+###--------------------------------------------------------------------------
+### Secret sharing.
+
+## Efficient sharing over GF(2^8).
+pkginclude_HEADERS     += gfshare.h
+libmisc_la_SOURCES     += gfshare.c
+gfshare.lo: gfshare-tab.h
+CLEANFILES             += gfshare-tab.h
+noinst_PROGRAMS                += gfshare-mktab
+gfshare-tab.h: gfshare-mktab$e
+       $(AM_V_GEN)./gfshare-mktab >gfshare-tab.h.new && \
+               mv gfshare-tab.h.new gfshare-tab.h
+TESTS                  += gfshare.$t
+
+## Number-theoretic sharing over GF(p).
+pkginclude_HEADERS     += share.h
+libmisc_la_SOURCES     += share.c
+TESTS                  += share.$t
+
+###----- That's all, folks --------------------------------------------------
diff --git a/misc/gfshare-mktab.c b/misc/gfshare-mktab.c
new file mode 100644 (file)
index 0000000..9fc073f
--- /dev/null
@@ -0,0 +1,106 @@
+/* -*-c-*-
+ *
+ * Generate tables for %$\gf{2^8}$% multiplication
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define MOD 0x11d
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  octet log[256], alog[256];
+  unsigned x;
+  unsigned i;
+
+  x = 1;
+  for (i = 0; i < 255; i++) {
+    alog[i] = x;
+    log[x] = i;
+    x <<= 1;
+    if (x & 0x100)
+      x ^= MOD;
+  }
+  log[0] = 0;
+  alog[255] = 1;
+
+  fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * Log tables for secret sharing in %$\\gf{2^8}$% [generated]\n\
+ */\n\
+\n\
+#ifndef GFSHARE_TAB_H\n\
+#define GFSHARE_TAB_H\n\
+\n\
+#define GFSHARE_LOG {                                                  \\\n\
+  ", stdout);
+
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", log[i]);
+    if (i == 255)
+      puts("                   \\\n}\n");
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  fputs("\
+#define GFSHARE_EXP {                                                  \\\n\
+  ", stdout);
+
+  for (i = 0; i < 510; i++) {
+    printf("0x%02x", alog[i % 255]);
+    if (i == 509)
+      puts("                                   \\\n}\n");
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Done --- */
+
+  fputs("#endif\n", stdout);
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/misc/gfshare.c b/misc/gfshare.c
new file mode 100644 (file)
index 0000000..0eb076b
--- /dev/null
@@ -0,0 +1,339 @@
+/* -*-c-*-
+ *
+ * Secret sharing over %$\gf{2^8}$%
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+
+#include "arena.h"
+#include "gfshare.h"
+#include "gfshare-tab.h"
+#include "grand.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static const octet gflog[] = GFSHARE_LOG, gfexp[] = GFSHARE_EXP;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gfshare_create@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share context to initialize
+ *             @unsigned t@ = threshold for the system
+ *             @size_t sz@ = size of the secret
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a sharing context.
+ */
+
+void gfshare_create(gfshare *s, unsigned t, size_t sz)
+{
+  s->t = t;
+  s->i = 0;
+  s->sz = sz;
+  s->v = 0;
+}
+
+/* --- @gfshare_destroy@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share context to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a sharing context.  The allocations for the
+ *             individual shares and the vector @v@ are freed; the secret is
+ *             left alone.
+ */
+
+void gfshare_destroy(gfshare *s)
+{
+  if (s->v)
+    XS_FREE(s->v);
+}
+
+/* --- @gfshare_mkshares@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share context to fill in
+ *             @grand *r@ = pointer to random number source
+ *             @const void *buf@ = pointer to the secret to share
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a sharing context to be able to create shares.
+ *             The context structure is expected to be mostly filled in.  In
+ *             particular, @t@ must be initialized.  If @v@ is zero, a
+ *             vector of appropriate size is allocated.  You should use the
+ *             macro @GFSHARE_INIT@ or @gfshare_create@ to construct sharing
+ *             contexts.
+ */
+
+void gfshare_mkshares(gfshare *s, grand *r, const void *buf)
+{
+  s->v = XS_ALLOC(s->sz * s->t);
+  r->ops->fill(r, s->v, s->sz * (s->t - 1));
+  memcpy(s->v + s->sz * (s->t - 1), buf, s->sz);
+}
+
+/* --- @gfshare_get@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share conext
+ *             @unsigned x@ = share index to fetch
+ *             @void *buf@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Extracts a share from the system.  You may extract up to 255
+ *             shares from the system.  Shares are indexed from 0.
+ */
+
+void gfshare_get(gfshare *s, unsigned x, void *buf)
+{
+  unsigned i;
+  const octet *p = s->v;
+  unsigned ilog = gflog[x + 1];
+
+  /* --- Evaluate the polynomial at %$x = i + 1$% --- */
+
+  memcpy(buf, p, s->sz);
+  p += s->sz;
+
+  for (i = 1; i < s->t; i++) {
+    octet *q = buf;
+    unsigned k;
+    for (k = 0; k < s->sz; k++) {
+      unsigned qq = *q;
+      if (qq)
+       qq = gfexp[ilog + gflog[qq]];
+      *q++ = qq ^ *p++;
+    }
+  }
+}
+
+/* --- @gfshare_addedp@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to sharing context
+ *             @unsigned x@ = which share number to check
+ *
+ * Returns:    Nonzero if share @x@ has been added already, zero if it
+ *             hasn't.
+ */
+
+int gfshare_addedp(gfshare *s, unsigned x)
+{
+  unsigned i;
+
+  for (i = 0; i < s->i; i++) {
+    if (GFSHARE_INDEX(s, i) == x + 1)
+      return (1);
+  }
+  return (0);
+}
+
+/* --- @gfshare_add@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to sharing context
+ *             @unsigned x@ = which share number this is
+ *             @const void *y@ = the share value
+ *
+ * Returns:    Number of shares required before recovery may be performed.
+ *
+ * Use:                Adds a share to the context.  The context must have been
+ *             initialized with the correct threshold @t@.
+ */
+
+unsigned gfshare_add(gfshare *s, unsigned x, const void *y)
+{
+  octet *p;
+
+  assert(((void)"Share context is full", s->i < s->t));
+  assert(((void)"Share already present", !gfshare_addedp(s, x)));
+
+  /* --- If no vector has been allocated, create one --- */
+
+  if (!s->v) {
+    s->v = XS_ALLOC(s->t * (s->sz + 1));
+    s->i = 0;
+  }
+
+  /* --- Store the share in the vector --- */
+
+  p = &GFSHARE_INDEX(s, s->i);
+  *p++ = x + 1;
+  memcpy(p, y, s->sz);
+  s->i++;
+
+  /* --- Done --- */
+
+  return (s->t - s->i);
+}
+
+/* --- @gfshare_combine@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share context
+ *             @void *buf@ = pointer to output buffer for the secret
+ *
+ * Returns:    ---
+ *
+ * Use:                Reconstructs a secret, given enough shares.
+ */
+
+void gfshare_combine(gfshare *s, void *buf)
+{
+  unsigned i, j;
+  unsigned xi, xj;
+
+  /* --- Sanity checking --- */
+
+  assert(((void)"Not enough shares yet", s->i == s->t));
+
+  /* --- Grind through the shares --- */
+
+  memset(buf, 0, s->sz);
+
+  for (i = 0; i < s->t; i++) {
+    octet *p = buf;
+    octet *q = &GFSHARE_INDEX(s, i);
+    unsigned c = 0, ci = 0;
+
+    /* --- Compute the magic coefficient --- */
+
+    xi = *q++;
+    for (j = 0; j < s->t; j++) {
+      if (i == j)
+       continue;
+      xj = GFSHARE_INDEX(s, j);
+      c += gflog[xj];
+      if (c >= 0xff)
+       c -= 0xff;
+      ci += gflog[xi ^ xj];
+      if (ci >= 0xff)
+       ci -= 0xff;
+    }
+    if (ci > c)
+      c += 0xff;
+    c -= ci;
+
+    /* --- Work out another layer of the secret --- */
+
+    p = buf;
+    for (j = 0; j < s->sz; j++) {
+      if (*q)
+       *p ^= gfexp[c + gflog[*q]];
+      p++, q++;
+    }
+  }
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include "fibrand.h"
+
+static int verify(grand *r)
+{
+  unsigned n = r->ops->range(r, 16) + 8;
+  unsigned t = r->ops->range(r, n - 1) + 1;
+  unsigned len = r->ops->range(r, 32) + 1;
+
+  octet *v = xmalloc(t * len);
+  unsigned *p = xmalloc(n * sizeof(unsigned));
+  octet *sec = xmalloc(len), *sbuf = xmalloc(len);
+  gfshare s;
+  unsigned i;
+
+  int ok = 1;
+
+  for (i = 0; i < n; i++)
+    p[i] = i;
+  for (i = 0; i < t; i++) {
+    unsigned long j = r->ops->range(r, n - i);
+    unsigned x = p[i];
+    p[i] = p[i + j];
+    p[i + j] = x;
+  }
+
+  r->ops->fill(r, sec, len);
+
+  gfshare_create(&s, t, len);
+
+  gfshare_mkshares(&s, r, sec);
+  for (i = 0; i < t; i++)
+    gfshare_get(&s, p[i], v + (i * len));
+  gfshare_destroy(&s);
+
+  gfshare_create(&s, t, len);
+  for (i = 0; i < t; i++)
+    gfshare_add(&s, p[i], v + (i * len));
+  gfshare_combine(&s, sbuf);
+  gfshare_destroy(&s);
+
+  if (memcmp(sec, sbuf, len) != 0) {
+    ok = 0;
+    fprintf(stderr, "\nbad recombination of shares\n");
+  };
+
+  xfree(sec);
+  xfree(sbuf);
+
+  xfree(v);
+  xfree(p);
+
+  return (ok);
+}
+
+int main(void)
+{
+  grand *r = fibrand_create(0);
+  unsigned i;
+  int ok = 1;
+
+  fputs("gfshare: ", stdout);
+  for (i = 0; i < 40; i++) {
+    if (!verify(r))
+      ok = 0;
+    fputc('.', stdout);
+    fflush(stdout);
+  }
+
+  if (ok)
+    fputs(" ok\n", stdout);
+  else
+    fputs(" failed\n", stdout);
+  return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/misc/gfshare.h b/misc/gfshare.h
new file mode 100644 (file)
index 0000000..3337e3b
--- /dev/null
@@ -0,0 +1,180 @@
+/* -*-c-*-
+ *
+ * Secret sharing over %$\gf{2^8}$%
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the system -----------------------------------------------*
+ *
+ * This uses a variant of Shamir's secret sharing system.  Shamir's original
+ * system used polynomials modulo a large prime.  This implementation instead
+ * uses the field %$\gf{2^8}$%, represented by
+ *
+ *   %$\gf{2}[x]/(x^8 + x^4 + x^3 + x^2 + 1)$%
+ *
+ * and shares each byte of the secret independently.  It is therefore limited
+ * to 255 players, although this probably isn't a serious limitation in
+ * practice.
+ *
+ * Share creation and reconstruction is extremely efficient.  Contrast the
+ * performance of the straightforward implementation based on multiprecision
+ * arithmetic.
+ */
+
+#ifndef CATACOMB_GFSHARE_H
+#define CATACOMB_GFSHARE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- A secret sharing context --- */
+
+typedef struct gfshare {
+  unsigned t;                          /* Threshold */
+  unsigned i;                          /* Next free slot in vector */
+  size_t sz;                           /* Size of the secret and shares */
+  octet *v;                            /* Vector of share information */
+} gfshare;
+
+#define GFSHARE_INIT(t, sz) { t, 0, sz, 0 }
+
+#define GFSHARE_INDEX(s, i) ((s)->v[(i) * ((s)->sz + 1)])
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @gfshare_create@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share context to initialize
+ *             @unsigned t@ = threshold for the system
+ *             @size_t sz@ = size of the secret
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a sharing context.
+ */
+
+extern void gfshare_create(gfshare */*s*/, unsigned /*t*/, size_t /*sz*/);
+
+/* --- @gfshare_destroy@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share context to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a sharing context.  The allocations for the
+ *             individual shares and the vector @v@ are freed; the secret is
+ *             left alone.
+ */
+
+extern void gfshare_destroy(gfshare */*s*/);
+
+/* --- @gfshare_mkshares@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share context to fill in
+ *             @grand *r@ = pointer to random number source
+ *             @const void *buf@ = pointer to the secret to share
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a sharing context to be able to create shares.
+ *             The context structure is expected to be mostly filled in.  In
+ *             particular, @t@ must be initialized.  If @v@ is zero, a
+ *             vector of appropriate size is allocated.  You should use the
+ *             macro @GFSHARE_INIT@ or @gfshare_create@ to construct sharing
+ *             contexts.
+ */
+
+extern void gfshare_mkshares(gfshare */*s*/, grand */*r*/,
+                            const void */*buf*/);
+
+/* --- @gfshare_get@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share conext
+ *             @unsigned x@ = share index to fetch
+ *             @void *buf@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Extracts a share from the system.  You may extract up to 255
+ *             shares from the system.  Shares are indexed from 0.
+ */
+
+extern void gfshare_get(gfshare */*s*/, unsigned /*x*/, void */*buf*/);
+
+/* --- @gfshare_addedp@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to sharing context
+ *             @unsigned x@ = which share number to check
+ *
+ * Returns:    Nonzero if share @x@ has been added already, zero if it
+ *             hasn't.
+ */
+
+extern int gfshare_addedp(gfshare */*s*/, unsigned /*x*/);
+
+/* --- @gfshare_add@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to sharing context
+ *             @unsigned x@ = which share number this is
+ *             @const void *y@ = the share value
+ *
+ * Returns:    Number of shares required before recovery may be performed.
+ *
+ * Use:                Adds a share to the context.  The context must have been
+ *             initialized with the correct threshold @t@.
+ */
+
+extern unsigned gfshare_add(gfshare */*s*/,
+                           unsigned /*x*/, const void */*y*/);
+
+/* --- @gfshare_combine@ --- *
+ *
+ * Arguments:  @gfshare *s@ = pointer to share context
+ *             @void *buf@ = pointer to output buffer for the secret
+ *
+ * Returns:    ---
+ *
+ * Use:                Reconstructs a secret, given enough shares.
+ */
+
+extern void gfshare_combine(gfshare */*s*/, void */*buf*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/misc/share.c b/misc/share.c
new file mode 100644 (file)
index 0000000..e99781e
--- /dev/null
@@ -0,0 +1,380 @@
+/* -*-c-*-
+ *
+ * Shamir's secret sharing
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "grand.h"
+#include "mp.h"
+#include "mpint.h"
+#include "mpbarrett.h"
+#include "mprand.h"
+#include "pgen.h"
+#include "rabin.h"
+#include "share.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @share_create@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share context to initialize
+ *             @unsigned t@ = threshold for the system
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a sharing context.
+ */
+
+void share_create(share *s, unsigned t)
+{
+  s->t = t;
+  s->i = 0;
+  s->p = 0;
+  s->v = 0;
+}
+
+/* --- @share_destroy@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share context to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a sharing context.  All memory is freed, all
+ *             integers are dropped.
+ */
+
+void share_destroy(share *s)
+{
+  unsigned i;
+
+  /* --- Dispose of the share vector --- */
+
+  if (s->v) {
+    for (i = 0; i < s->t; i++)
+      mp_drop(s->v[i].y);
+    xfree(s->v);
+  }
+
+  /* --- Other stuff --- */
+
+  mp_drop(s->p);
+}
+
+/* --- @share_mkshares@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share context to fill in
+ *             @grand *r@ = pointer to random number source
+ *             @mp *n@ = the secret to share
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a sharing context to be able to create shares.
+ *             The context structure is expected to be mostly filled in.  In
+ *             particular, @t@ must be initialized.  If @p@ is zero, a prime
+ *             number of appropriate size is generated automatically.  If
+ *             @v@ is zero, a vector of appropriate size is allocated.  You
+ *             should use the macro @SHARE_INIT@ or @share_create@ to
+ *             construct sharing contexts.
+ */
+
+void share_mkshares(share *s, grand *r, mp *n)
+{
+  unsigned i;
+
+  /* --- If there's no prime, construct one --- */
+
+  if (!s->p) {
+    pgen_filterctx pf;
+    rabin pr;
+    mp *p;
+    unsigned bits = (mp_octets(n) + 1) * 8;
+
+    pf.step = 2;
+    p = mprand(MP_NEW, bits, r, 1);
+    s->p = pgen("p", p, p, 0, 0, 0, pgen_filter, &pf,
+               rabin_iters(bits), pgen_test, &pr);
+  }
+
+  /* --- Construct the polynomial --- */
+
+  if (!s->v)
+    s->v = xmalloc(s->t * sizeof(share_pt));
+  for (i = 0; i < s->t - 1; i++)
+    s->v[i].y = mprand_range(MP_NEWSEC, s->p, r, 0);
+  s->v[s->t - 1].y = mp_copy(n);
+}
+
+/* --- @share_get@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share conext
+ *             @mp *d@ = destination for the share
+ *             @unsigned x@ = share index to fetch
+ *
+ * Returns:    The share, as requested.
+ *
+ * Use:                Extracts a share from the system.  You may extract @MPW_MAX@
+ *             shares, or @s->p@ shares from the system, whichever is
+ *             smaller.  Shares are indexed from 0.
+ */
+
+mp *share_get(share *s, mp *d, unsigned x)
+{
+  mpbarrett mb;
+  mpw uw = x + 1;
+  mp u;
+  unsigned i;
+
+  /* --- Various bits of initialization --- */
+
+  mp_build(&u, &uw, &uw + 1);
+  mp_drop(d);
+
+  /* --- Evaluate the polynomial at %$x = i + 1$% --- */
+
+  d = MP_ZERO;
+  mpbarrett_create(&mb, s->p);
+  for (i = 0; i < s->t; i++) {
+    d = mp_mul(d, d, &u);
+    d = mp_add(d, d, s->v[i].y);
+    d = mpbarrett_reduce(&mb, d, d);
+  }
+  mpbarrett_destroy(&mb);
+
+  return (d);
+}
+
+/* --- @share_addedp@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to sharing context
+ *             @unsigned x@ = which share number to check
+ *
+ * Returns:    Nonzero if share @x@ has been added already, zero if it
+ *             hasn't.
+ */
+
+int share_addedp(share *s, unsigned x)
+{
+  unsigned i;
+
+  for (i = 0; i < s->i; i++) {
+    if (s->v[i].x == x + 1)
+      return (1);
+  }
+  return (0);
+}
+
+/* --- @share_add@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to sharing context
+ *             @unsigned x@ = which share number this is
+ *             @mp *y@ = the share value
+ *
+ * Returns:    Number of shares required before recovery may be performed.
+ *
+ * Use:                Adds a share to the context.  The context must have been
+ *             initialized with the correct prime @p@ and threshold @t@.
+ */
+
+unsigned share_add(share *s, unsigned x, mp *y)
+{
+  assert(((void)"Share context is full", s->i < s->t));
+  assert(((void)"Share already present", !share_addedp(s, x)));
+
+  /* --- If no vector has been allocated, create one --- */
+
+  if (!s->v) {
+    unsigned i;
+    s->v = xmalloc(s->t * sizeof(share_pt));
+    s->i = 0;
+    for (i = 0; i < s->t; i++)
+      s->v[i].y = 0;
+  }
+
+  /* --- Store the share in the vector --- */
+
+  s->v[s->i].x = x + 1;
+  s->v[s->i].y = mp_copy(y);
+  s->i++;
+
+  /* --- Done --- */
+
+  return (s->t - s->i);
+}
+
+/* --- @share_combine@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share context
+ *
+ * Returns:    The secret, as a multiprecision integer.
+ *
+ * Use:                Reconstructs a secret, given enough shares.
+ */
+
+mp *share_combine(share *s)
+{
+  mp *a = MP_ZERO;
+  mpbarrett mb;
+  unsigned i, j;
+  mp ii, jj;
+  mpw iiw, jjw;
+  mp *m = MP_NEW;
+
+  /* --- Sanity checking --- */
+
+  assert(((void)"Not enough shares yet", s->i == s->t));
+
+  /* --- Initialization --- */
+
+  mpbarrett_create(&mb, s->p);
+  mp_build(&ii, &iiw, &iiw + 1);
+  mp_build(&jj, &jjw, &jjw + 1);
+
+  /* --- Grind through the shares --- */
+
+  for (i = 0; i < s->t; i++) {
+    mp *c = MP_ONE;
+
+    iiw = s->v[i].x;
+    for (j = 0; j < s->t; j++) {
+      if (i == j)
+       continue;
+      jjw = s->v[j].x;
+      if (s->v[j].x >= s->v[i].x)
+       m = mp_sub(m, &jj, &ii);
+      else {
+       m = mp_sub(m, &ii, &jj);
+       m = mp_sub(m, s->p, m);
+      }
+      m = mp_modinv(m, m, s->p);
+      c = mp_mul(c, c, &jj);
+      c = mpbarrett_reduce(&mb, c, c);
+      c = mp_mul(c, c, m);
+      c = mpbarrett_reduce(&mb, c, c);
+    }
+    c = mp_mul(c, c, s->v[i].y);
+    c = mpbarrett_reduce(&mb, c, c);
+    a = mp_add(a, a, c);
+    mp_drop(c);
+  }
+
+  a = mpbarrett_reduce(&mb, a, a);
+  mp_drop(m);
+  mpbarrett_destroy(&mb);
+  return (a);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include "fibrand.h"
+
+static int verify(grand *r)
+{
+  unsigned n = r->ops->range(r, 16) + 8;
+  unsigned t = r->ops->range(r, n - 1) + 1;
+  unsigned len = r->ops->range(r, 160);
+
+  mp **v = xmalloc(t * sizeof(mp *));
+  unsigned *p = xmalloc(n * sizeof(unsigned));
+  mp *sec = mprand(MP_NEW, len, r, 0);
+  share s;
+  mp *pp;
+  mp *ss;
+  unsigned i;
+
+  int ok = 1;
+
+  for (i = 0; i < n; i++)
+    p[i] = i;
+  for (i = 0; i < t; i++) {
+    unsigned long j = r->ops->range(r, n - i);
+    unsigned x = p[i];
+    p[i] = p[i + j];
+    p[i + j] = x;
+  }
+
+  share_create(&s, t);
+  share_mkshares(&s, r, sec);
+  for (i = 0; i < t; i++)
+    v[i] = share_get(&s, MP_NEW, p[i]);
+  pp = mp_copy(s.p);
+  share_destroy(&s);
+  assert(mparena_count(MPARENA_GLOBAL) + mparena_count(MPARENA_SECURE) == t + 2);
+
+  share_create(&s, t);
+  s.p = pp;
+  for (i = 0; i < t; i++)
+    share_add(&s, p[i], v[i]);
+  ss = share_combine(&s);
+  share_destroy(&s);
+
+  if (!MP_EQ(sec, ss)) {
+    ok = 0;
+    fprintf(stderr, "\nbad recombination of shares\n");
+  };
+
+  mp_drop(sec);
+  mp_drop(ss);
+
+  for (i = 0; i < t; i++)
+    mp_drop(v[i]);
+
+  xfree(v);
+  xfree(p);
+
+  assert(mparena_count(MPARENA_GLOBAL) + mparena_count(MPARENA_SECURE) == 0);
+  return (ok);
+}
+
+int main(void)
+{
+  grand *r = fibrand_create(0);
+  unsigned i;
+  int ok = 1;
+
+  fputs("share: ", stdout);
+  for (i = 0; i < 40; i++) {
+    if (!verify(r))
+      ok = 0;
+    fputc('.', stdout);
+    fflush(stdout);
+  }
+
+  if (ok)
+    fputs(" ok\n", stdout);
+  else
+    fputs(" failed\n", stdout);
+  return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/misc/share.h b/misc/share.h
new file mode 100644 (file)
index 0000000..9b82fdd
--- /dev/null
@@ -0,0 +1,177 @@
+/* -*-c-*-
+ *
+ * Shamir's secret sharing
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the sharing system ---------------------------------------*
+ *
+ * Shamir's secret-sharing system is based on polynomial interpolation modulo
+ * a prime number.  It is `perfect' in that fewer participants than the
+ * threshold can derive no information about the secret by pooling their
+ * shares, and `ideal' in that the shares are the same size as the secret.
+ *
+ * This implementation stays close to the definition, in order to support
+ * other schemes for (e.g.) threshold cryptography.  It is, however, rather
+ * slow.
+ */
+
+#ifndef CATACOMB_SHARE_H
+#define CATACOMB_SHARE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- A secret sharing context --- */
+
+typedef struct share_pt {
+  unsigned x;                          /* Index of this share */
+  mp *y;                               /* Payload of this share */
+} share_pt;
+
+typedef struct share {
+  unsigned t;                          /* Threshold */
+  unsigned i;                          /* Next free slot in the vector */
+  mp *p;                               /* Modulus for arithmetic */
+  share_pt *v;                         /* Vector of share information */
+} share;
+
+#define SHARE_INIT(t) { t, 0, 0, 0 }
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @share_create@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share context to initialize
+ *             @unsigned t@ = threshold for the system
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a sharing context.
+ */
+
+extern void share_create(share */*s*/, unsigned /*t*/);
+
+/* --- @share_destroy@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share context to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a sharing context.  All memory is freed, all
+ *             integers are dropped.
+ */
+
+extern void share_destroy(share */*s*/);
+
+/* --- @share_mkshares@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share context to fill in
+ *             @grand *r@ = pointer to random number source
+ *             @mp *n@ = the secret to share
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a sharing context to be able to create shares.
+ *             The context structure is expected to be mostly filled in.  In
+ *             particular, @t@ must be initialized.  If @p@ is zero, a prime
+ *             number of appropriate size is generated automatically.  If
+ *             @v@ is zero, a vector of appropriate size is allocated.  You
+ *             should use the macro @SHARE_INIT@ or @share_create@ to
+ *             construct sharing contexts.
+ */
+
+extern void share_mkshares(share */*s*/, grand */*r*/, mp */*n*/);
+
+/* --- @share_get@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share conext
+ *             @mp *d@ = destination for the share
+ *             @unsigned x@ = share index to fetch
+ *
+ * Returns:    The share, as requested.
+ *
+ * Use:                Extracts a share from the system.  You may extract @MPW_MAX@
+ *             shares, or @s->p@ shares from the system, whichever is
+ *             smaller.  Shares are indexed from 0.
+ */
+
+extern mp *share_get(share */*s*/, mp */*d*/, unsigned /*x*/);
+
+/* --- @share_addedp@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to sharing context
+ *             @unsigned x@ = which share number to check
+ *
+ * Returns:    Nonzero if share @x@ has been added already, zero if it
+ *             hasn't.
+ */
+
+extern int share_addedp(share */*s*/, unsigned /*x*/);
+
+/* --- @share_add@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to sharing context
+ *             @unsigned x@ = which share number this is
+ *             @mp *y@ = the share value
+ *
+ * Returns:    Number of shares required before recovery may be performed.
+ *
+ * Use:                Adds a share to the context.  The context must have been
+ *             initialized with the correct prime @p@ and threshold @t@.
+ */
+
+extern unsigned share_add(share */*s*/, unsigned /*x*/, mp */*y*/);
+
+/* --- @share_combine@ --- *
+ *
+ * Arguments:  @share *s@ = pointer to share context
+ *
+ * Returns:    The secret, as a multiprecision integer.
+ *
+ * Use:                Reconstructs a secret, given enough shares.
+ */
+
+extern mp *share_combine(share */*s*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/mkpgroups b/mkpgroups
deleted file mode 100755 (executable)
index b40c23b..0000000
--- a/mkpgroups
+++ /dev/null
@@ -1,42 +0,0 @@
-#! /usr/bin/python
-
-import catacomb as C
-import mLib as M
-from sys import stdin
-
-kf = C.KeyFile('pgroups.kr', C.KOPEN_WRITE)
-
-for line in stdin:
-  line = line.strip()
-  if line == '' or (line.startswith('#') and not line.startswith('#:')):
-    continue
-  F = line.split()
-  if F[0] == 'group':
-    name = F[1]
-    if not name.startswith('catacomb'):
-      continue
-    def snarf(what):
-      F = stdin.next().split()
-      assert F[0] == what
-      return F[1]
-    p = C.MP(snarf('p'))
-    q = C.MP(snarf('q'))
-    g = C.MP(snarf('g'))
-    ff = []
-    while True:
-      F = stdin.next().split()
-      if not F or F[0] != '#:factor':
-       break
-      ff.append(C.MP(F[1]))
-    seed = C.rmd160().hash(name).done()
-    k = kf.newkey(C.ReadBuffer(seed).getu32(), 'dh-param')
-    k.tag = name
-    k.data = C.KeyDataStructured({
-      'p': C.KeyDataMP(p, 'shared'),
-      'q': C.KeyDataMP(q, 'shared'),
-      'g': C.KeyDataMP(g, 'shared')
-    })
-    k.attr['factor'] = ', '.join([f.tostring() for f in ff])
-    k.attr['genseed'] = M.base64_encode(seed)
-    k.attr['seedalg'] = 'rmd160-mgf'
-kf.save()
diff --git a/mkphrase.c b/mkphrase.c
deleted file mode 100644 (file)
index 1a5beab..0000000
+++ /dev/null
@@ -1,458 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generate passphrases from word lists
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "config.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-#include <mLib/darray.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sym.h>
-
-#include "grand.h"
-#include "noise.h"
-#include "rand.h"
-
-/*----- Global state ------------------------------------------------------*/
-
-static unsigned min = 0, max = 256;    /* Word length bounds */
-static unsigned minbits = 128, maxbits = UINT_MAX; /* Acceptable entropy */
-static unsigned count = 1;             /* How many passphrases to make */
-
-static const char wchars[] = "abcdefghijklmnopqrstuvwxyz'";
-
-typedef struct ppgen_ops {
-  const char *name;                    /* Name of the generator */
-  void *(*init)(void);                 /* Initialize generator */
-  void (*scan)(FILE */*fp*/, void */*p*/); /* Scan an input word list */
-  void (*endscan)(void */*p*/);                /* Scanning phase completed */
-  double (*gen)(dstr */*d*/, grand */*r*/, void */*p*/);
-                                       /* Emit word and return entropy */
-  void (*done)(void */*p*/);           /* Close down generator */
-} ppgen_ops;
-
-/*----- Word list ---------------------------------------------------------*/
-
-#ifndef STRING_V
-#  define STRING_V
-   DA_DECL(string_v, char *);
-#endif
-
-typedef struct wlist {
-  string_v sv;
-  sym_table tab;
-  char *buf;
-  double logp;
-} wlist;
-
-static void *wordlist_init(void)
-{
-  wlist *w = xmalloc(sizeof(wlist));
-  sym_create(&w->tab);
-  w->logp = 0;
-  return (w);
-}
-
-static void wordlist_scan(FILE *fp, void *p)
-{
-  wlist *w = p;
-  dstr d = DSTR_INIT;
-  unsigned f = 0;
-
-  for (;;) {
-    int ch = getc(fp);
-    if (ch == EOF || isspace(ch)) {
-      DPUTZ(&d);
-      if (f && d.len >= min && d.len <= max)
-       sym_find(&w->tab, d.buf, d.len + 1, sizeof(sym_base), 0);
-      f = 0;
-      DRESET(&d);
-      if (ch == EOF)
-       break;
-      continue;
-    }
-    ch = tolower(ch);
-    if (strchr(wchars, ch)) {
-      DPUTC(&d, ch);
-      f = 1;
-    }
-  }
-
-  dstr_destroy(&d);
-}
-
-static void wordlist_endscan(void *p)
-{
-  wlist *w = p;
-  size_t buflen = 0;
-  sym_iter i;
-  sym_base *b;
-  char *q;
-
-  for (sym_mkiter(&i, &w->tab); (b = sym_next(&i)) != 0; )
-    buflen += b->len;
-  w->buf = xmalloc(buflen);
-  q = w->buf;
-  DA_CREATE(&w->sv);
-  for (sym_mkiter(&i, &w->tab); (b = sym_next(&i)) != 0; ) {
-    memcpy(q, SYM_NAME(b), b->len);
-    DA_PUSH(&w->sv, q);
-    q += b->len;
-  }
-  sym_destroy(&w->tab);
-  w->logp = log(DA_LEN(&w->sv))/log(2);
-}
-
-static double wordlist_gen(dstr *d, grand *r, void *p)
-{
-  wlist *w = p;
-  uint32 i = r->ops->range(r, DA_LEN(&w->sv));
-  DPUTS(d, DA(&w->sv)[i]);
-  return (w->logp);
-}
-
-static void wordlist_done(void *p)
-{
-  wlist *w = p;
-  xfree(w->buf);
-  DA_DESTROY(&w->sv);
-  xfree(w);
-}
-
-static ppgen_ops wordlist_ops = {
-  "wordlist",
-  wordlist_init, wordlist_scan, wordlist_endscan, wordlist_gen, wordlist_done
-};
-
-/*----- Markov word model -------------------------------------------------*/
-
-enum {
-  C_START = 27,
-  C_END,
-  VECSZ
-};
-
-typedef struct node {
-  uint32 count;
-  uint32 p[VECSZ];
-} node;
-
-static void *markov_init(void)
-{
-  node (*model)[VECSZ][VECSZ][VECSZ] = xmalloc(sizeof(*model));
-  unsigned i, j, k, l;
-
-  for (i = 0; i < VECSZ; i++) {
-    for (j = 0; j < VECSZ; j++) {
-      for (k = 0; k < VECSZ; k++) {
-       node *n = &(*model)[i][j][k];
-       n->count = 0;
-       for (l = 0; l < VECSZ; l++)
-         n->p[l] = 0;
-      }
-    }
-  }
-
-  return (model);
-}
-
-static void markov_scan(FILE *fp, void *p)
-{
-  node (*model)[VECSZ][VECSZ][VECSZ] = p;
-  unsigned i = C_START, j = C_START, k = C_START, l = C_END;
-
-  for (;;) {
-    int ch = getc(fp);
-    const char *q;
-    node *n = &(*model)[i][j][k];
-
-    if (ch == EOF || isspace(ch)) {
-      if (l != C_END) {
-       l = C_END;
-       n->count++;
-       n->p[l]++;
-       i = j = k = C_START;
-      }
-      if (ch == EOF)
-       break;
-      continue;
-    }
-
-    if ((q = strchr(wchars, tolower(ch))) == 0)
-      continue;
-    l = q - wchars;
-    n->count++;
-    n->p[l]++;
-    i = j; j = k; k = l;
-  }
-}
-
-static double markov_gen(dstr *d, grand *r, void *p)
-{
-  node (*model)[VECSZ][VECSZ][VECSZ] = p;
-  unsigned i = C_START, j = C_START, k = C_START, l;
-  double logp = 0;
-  double log2 = log(2);
-
-  for (;;) {
-    node *n = &(*model)[i][j][k];
-    uint32 z = r->ops->range(r, n->count);
-    for (l = 0; z >= n->p[l]; z -= n->p[l++])
-      ;
-    logp -= log((double)n->p[l]/(double)n->count)/log2;
-    if (l == C_END)
-      break;
-    DPUTC(d, wchars[l]);
-    i = j; j = k; k = l;
-  }
-
-  return (logp);
-}
-
-static void markov_done(void *p)
-{
-  node (*model)[VECSZ][VECSZ][VECSZ] = p;
-  xfree(model);
-}
-
-static ppgen_ops markov_ops = {
-  "markov",
-  markov_init, markov_scan, 0, markov_gen, markov_done
-};
-
-/*----- Main code ---------------------------------------------------------*/
-
-static ppgen_ops *ppgentab[] = {
-  &markov_ops,
-  &wordlist_ops,
-  0
-};
-
-static void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "\
-Usage: $ [-p] [-b MIN[-MAX]] [-g GEN] [-n COUNT]\n\
-\t[-r [MIN-]MAX] WORDLIST...\n                   \
-");
-}
-
-static void help(FILE *fp)
-{
-  ppgen_ops **ops;
-  version(fp);
-  fputc('\n', fp);
-  usage(fp);
-  pquis(fp, "\n\
-Generates random passphrases with the requested level of entropy.  Options\n\
-supported are:\n\
-\n\
--h, --help             Show this help text.\n\
--v, --version          Show the program's version number.\n\
--u, --usage            Show a terse usage summary.\n\
--b, --bits=MIN[-MAX]   Minimum and maximum bits of entropy.\n\
--g, --generator=GEN    Use passphrase generator GEN.\n\
--n, --count=COUNT      Generate COUNT passphrases.\n\
--p, --probability      Show -log_2 of probability for each phrase.\n\
--r, --range=[MIN-]MAX  Supply minimum and maximum word lengths.\n\
-\n\
-Generators currently available:");
-  for (ops = ppgentab; *ops; ops++)
-    fprintf(fp, " %s", (*ops)->name);
-  fputc('\n', fp);
-}
-
-int main(int argc, char *argv[])
-{
-  ppgen_ops *ops = ppgentab[0];
-  unsigned f = 0;
-  void *ctx;
-  dstr d = DSTR_INIT;
-  dstr dd = DSTR_INIT;
-  unsigned i;
-
-#define f_bogus 1u
-#define f_showp 2u
-
-  ego(argv[0]);
-  for (;;) {
-    static struct option opts[] = {
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'v' },
-      { "usage",       0,              0,      'u' },
-      { "bits",                OPTF_ARGREQ,    0,      'b' },
-      { "generator",   OPTF_ARGREQ,    0,      'g' },
-      { "count",       OPTF_ARGREQ,    0,      'n' },
-      { "probability", 0,              0,      'p' },
-      { "range",       OPTF_ARGREQ,    0,      'r' },
-      { 0,             0,              0,      0 }
-    };
-    int i = mdwopt(argc, argv, "hvu b:g:n:pr:", opts, 0, 0, 0);
-
-    if (i < 0)
-      break;
-    switch (i) {
-      case 'h':
-       help(stdout);
-       exit(0);
-      case 'v':
-       version(stdout);
-       exit(0);
-      case 'u':
-       usage(stdout);
-       exit(0);
-      case 'b': {
-       char *p;
-       minbits = strtoul(optarg, &p, 0);
-       if (*p == '-')
-         maxbits = strtoul(p + 1, &p, 0);
-       else
-         maxbits = UINT_MAX;
-       if (*p || minbits > maxbits)
-         die(EXIT_FAILURE, "bad entropy range `%s'", optarg);
-      } break;
-      case 'g': {
-       ppgen_ops **p;
-       size_t n = strlen(optarg);
-       ops = 0;
-       for (p = ppgentab; *p; p++) {
-         if (strncmp(optarg, (*p)->name, n) == 0) {
-           if (!(*p)->name[n]) {
-             ops = *p;
-             break;
-           } else if (ops)
-             die(EXIT_FAILURE, "ambiguous generator name `%s'", optarg);
-           ops = *p;
-         }
-       }
-       if (!ops)
-         die(EXIT_FAILURE, "unknown generator name `%s'", optarg);
-      } break;
-      case 'n': {
-       char *p;
-       unsigned long n = strtoul(optarg, &p, 0);
-       if (*p)
-         die(EXIT_FAILURE, "bad integer `%s'", optarg);
-       count = n;
-      } break;
-      case 'p':
-       f |= f_showp;
-       break;
-      case 'r': {
-       char *p;
-       unsigned long n = min, nn = max;
-       nn = strtoul(optarg, &p, 0);
-       if (*p == '-') {
-         n = nn;
-         nn = strtoul(p + 1, &p, 0);
-       }
-       if (*p || min > max)
-         die(EXIT_FAILURE, "bad range string `%s'", optarg);
-       min = n; max = nn;
-      } break;
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-
-  argc -= optind;
-  argv += optind;
-  if ((f & f_bogus) || !argc) {
-    usage(stderr);
-    exit(EXIT_FAILURE);
-  }
-
-  rand_noisesrc(RAND_GLOBAL, &noise_source);
-  rand_seed(RAND_GLOBAL, 160);
-
-  ctx = ops->init();
-  while (*argv) {
-    if (strcmp(*argv, "-") == 0)
-      ops->scan(stdin, ctx);
-    else {
-      FILE *fp = fopen(*argv, "r");
-      if (!fp) {
-       die(EXIT_FAILURE, "error opening file `%s': %s",
-           *argv, strerror(errno));
-      }
-      ops->scan(fp, ctx);
-      fclose(fp);
-    }
-    argv++;
-  }
-  if (ops->endscan)
-    ops->endscan(ctx);
-
-  for (i = 0; !count || i < count; ) {
-    double logp = 0;
-    DRESET(&d);
-    while (logp < minbits) {
-      double pp;
-      DRESET(&dd);
-      pp = ops->gen(&dd, &rand_global, ctx);
-      if (!pp || dd.len < min || dd.len > max)
-       continue;
-      if (logp)
-       DPUTC(&d, ' ');
-      DPUTD(&d, &dd);
-      logp += pp;
-    }
-    if (logp >= (double)maxbits + 1)
-      continue;
-    dstr_write(&d, stdout);
-    if (f & f_showp)
-      printf(" [%g]", logp);
-    fputc('\n', stdout);
-    i++;
-  }
-
-  ops->done(ctx);
-  dstr_destroy(&d);
-  dstr_destroy(&dd);
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/modes.am.in b/modes.am.in
deleted file mode 100644 (file)
index 88ee217..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-%## -*-makefile-*-
-%#
-### -*-makefile-*- GENERATED from modes.make.in
-###
-### Lots of lists of crypto primitives in various modes of operation.
-
-SYMM_TESTS =
-
-GENMODES_C =
-GENMODES_H =
-
-%repeat
-GENMODES_C += @blkc-@blkcmode.c
-GENMODES_H += @blkc-@blkcmode.h
-SYMM_TESTS += @blkc-@blkcmode.$t
-%end
-
-%repeat
-GENMODES_C += @hash-@hashmode.c
-GENMODES_H += @hash-@hashmode.h
-SYMM_TESTS += @hash-@hashmode.$t
-%end
-
-MODE_H =
-%repeat
-MODE_H += @blkcmode.h @blkcmode-def.h
-%end
-%repeat
-MODE_H += @hashmode.h @hashmode-def.h
-%end
-
-BLKC_C =
-BLKC_H =
-%repeat
-BLKC_C += @blkc.c
-BLKC_H += @blkc.h
-SYMM_TESTS += @blkc.$t
-%end
-
-HASH_C =
-HASH_H =
-%repeat
-HASH_C += @hash.c
-HASH_H += @hash.h
-SYMM_TESTS += @hash.$t
-%end
-
-CIPHER_MODES =
-%repeat
-CIPHER_MODES += @blkc-@blkcciphermode
-%end
-%repeat
-CIPHER_MODES += @hash-@hashciphermode
-%end
-
-MAC_MODES =
-%repeat
-MAC_MODES += @hash-@hashmacmode
-%end
-
-SYMM_TEST_FILES =
-%repeat
-SYMM_TEST_FILES += tests/@blkc
-%end
-%repeat
-SYMM_TEST_FILES += tests/@hash
-%end
diff --git a/mp-arith.c b/mp-arith.c
deleted file mode 100644 (file)
index f00af54..0000000
+++ /dev/null
@@ -1,931 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Basic arithmetic on multiprecision integers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-
-/*----- Macros ------------------------------------------------------------*/
-
-#define MAX(x, y) ((x) >= (y) ? (x) : (y))
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *             @size_t n@ = number of bits to move
- *
- * Returns:    Result, @a@ shifted left or right by @n@.
- *
- * Use:                Bitwise shift operators.  @mp_lslc@ fills the bits introduced
- *             on the right with ones instead of zeroes: it's used
- *             internally by @mp_lsl2c@, though it may be useful on its
- *             own.
- */
-
-mp *mp_lsl(mp *d, mp *a, size_t n)
-{
-  MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f);
-  mpx_lsl(d->v, d->vl, a->v, a->vl, n);
-  d->f = a->f & (MP_NEG | MP_BURN);
-  MP_SHRINK(d);
-  return (d);
-}
-
-mp *mp_lslc(mp *d, mp *a, size_t n)
-{
-  MP_DEST(d, MP_LEN(a) + (n + MPW_BITS - 1) / MPW_BITS, a->f);
-  mpx_lslc(d->v, d->vl, a->v, a->vl, n);
-  d->f = a->f & (MP_NEG | MP_BURN);
-  MP_SHRINK(d);
-  return (d);
-}
-
-mp *mp_lsr(mp *d, mp *a, size_t n)
-{
-  MP_DEST(d, MP_LEN(a), a->f);
-  mpx_lsr(d->v, d->vl, a->v, a->vl, n);
-  d->f = a->f & (MP_NEG | MP_BURN);
-  MP_SHRINK(d);
-  return (d);
-}
-
-/* --- @mp_lsl2c@, @mp_lsr2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *             @size_t n@ = number of bits to move
- *
- * Returns:    Result, @a@ shifted left or right by @n@.  Handles the
- *             pretence of sign-extension for negative numbers.
- */
-
-mp *mp_lsl2c(mp *d, mp *a, size_t n)
-{
-  if (!MP_NEGP(a))
-    return (mp_lsl(d, a, n));
-  d = mp_not2c(d, a);
-  d = mp_lslc(d, d, n);
-  d = mp_not2c(d, d);
-  return (d);
-}
-
-mp *mp_lsr2c(mp *d, mp *a, size_t n)
-{
-  if (!MP_NEGP(a))
-    return (mp_lsr(d, a, n));
-  d = mp_not2c(d, a);
-  d = mp_lsr(d, d, n);
-  d = mp_not2c(d, d);
-  return (d);
-}
-
-/* --- @mp_testbit@ --- *
- *
- * Arguments:  @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to test
- *
- * Returns:    Nonzero if the bit is set, zero if not.
- */
-
-int mp_testbit(mp *x, unsigned long n)
-{
-  if (n > MPW_BITS * MP_LEN(x))
-    return (0);
-  return ((x->v[n/MPW_BITS] >> n%MPW_BITS) & 1u);
-}
-
-/* --- @mp_testbit2c@ --- *
- *
- * Arguments:  @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to test
- *
- * Returns:    Nonzero if the bit is set, zero if not.  Fakes up two's
- *             complement representation.
- */
-
-int mp_testbit2c(mp *x, unsigned long n)
-{
-  int r;
-  if (!MP_NEGP(x))
-    return (mp_testbit(x, n));
-  x = mp_not2c(MP_NEW, x);
-  r = !mp_testbit(x, n);
-  MP_DROP(x);
-  return (r);
-}
-
-/* --- @mp_setbit@, @mp_clearbit@ --- *
- *
- * Arguments:  @mp *d@ = a destination
- *             @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to modify
- *
- * Returns:    The argument @x@, with the appropriate bit set or cleared.
- */
-
-mp *mp_setbit(mp *d, mp *x, unsigned long n)
-{
-  size_t rq;
-
-  rq = n + MPW_BITS; rq -= rq % MPW_BITS;
-  if (d != x) {
-    if (d) MP_DROP(d);
-    d = MP_COPY(x);
-  }
-  MP_DEST(d, rq, x->f & (MP_NEG | MP_BURN));
-  d->v[n/MPW_BITS] |= 1 << n%MPW_BITS;
-  return (d);
-}
-
-mp *mp_clearbit(mp *d, mp *x, unsigned long n)
-{
-  size_t rq;
-
-  rq = n + MPW_BITS; rq -= rq % MPW_BITS;
-  if (d != x) {
-    if (d) MP_DROP(d);
-    d = MP_COPY(x);
-  }
-  MP_DEST(d, rq, x->f & (MP_NEG | MP_BURN));
-  d->v[n/MPW_BITS] &= ~(1 << n%MPW_BITS);
-  return (d);
-}
-
-/* --- @mp_setbit2c@, @mp_clearbit2c@ --- *
- *
- * Arguments:  @mp *d@ = a destination
- *             @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to modify
- *
- * Returns:    The argument @x@, with the appropriate bit set or cleared.
- *             Fakes up two's complement representation.
- */
-
-mp *mp_setbit2c(mp *d, mp *x, unsigned long n)
-{
-  if (!MP_NEGP(x))
-    return mp_setbit(d, x, n);
-  d = mp_not2c(d, x);
-  d = mp_clearbit(d, d, n);
-  d = mp_not2c(d, d);
-  return (d);
-}
-
-mp *mp_clearbit2c(mp *d, mp *x, unsigned long n)
-{
-  if (!MP_NEGP(x))
-    return mp_clearbit(d, x, n);
-  d = mp_not2c(d, x);
-  d = mp_setbit(d, d, n);
-  d = mp_not2c(d, d);
-  return (d);
-}
-
-/* --- @mp_eq@ --- *
- *
- * Arguments:  @const mp *a, *b@ = two numbers
- *
- * Returns:    Nonzero if the numbers are equal.
- */
-
-int mp_eq(const mp *a, const mp *b) { return (MP_EQ(a, b)); }
-
-/* --- @mp_cmp@ --- *
- *
- * Arguments:  @const mp *a, *b@ = two numbers
- *
- * Returns:    Less than, equal to or greater than zero, according to
- *             whether @a@ is less than, equal to or greater than @b@.
- */
-
-int mp_cmp(const mp *a, const mp *b)
-{
-  if (!((a->f ^ b->f) & MP_NEG)) {
-    if (a->f & MP_NEG)
-      return (-mpx_ucmp(a->v, a->vl, b->v, b->vl));
-    else
-      return (mpx_ucmp(a->v, a->vl, b->v, b->vl));
-  } else if (a->f & MP_NEG)
-    return (-1);
-  else
-    return (+1);
-}
-
-/* --- @mp_neg@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = argument
- *
- * Returns:    The negation of the argument.
- *
- * Use:                Negates its argument.
- */
-
-mp *mp_neg(mp *d, mp *a)
-{
-  /* --- Surprising amounts of messing about required --- */
-
-  MP_SHRINK(a);
-  MP_COPY(a);
-  if (d)
-    MP_DROP(d);
-  if (a->v == a->vl)
-    return (a);
-  MP_DEST(a, MP_LEN(a), a->f);
-  a->f ^= MP_NEG;
-  return (a);
-}
-
-/* --- @mp_bitop@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    The result of the given bitwise operation.  These functions
- *             don't handle negative numbers at all sensibly.  For that, use
- *             the @...2c@ variants.  The functions are named after the
- *             truth tables they generate:
- *
- *                     a:      0011
- *                     b:      0101
- *                     @mpx_bitXXXX@
- */
-
-#define MP_BITBINOP(string)                                            \
-                                                                       \
-mp *mp_bit##string(mp *d, mp *a, mp *b)                                        \
-{                                                                      \
-  MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)), (a->f | b->f) & ~MP_NEG);      \
-  mpx_bit##string(d->v, d->vl, a->v, a->vl, b->v, b->vl);              \
-  d->f = (a->f | b->f) & MP_BURN;                                      \
-  MP_SHRINK(d);                                                                \
-  return (d);                                                          \
-}
-
-MPX_DOBIN(MP_BITBINOP)
-
-/* --- @mp_not@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    The bitwise complement of the source.
- */
-
-mp *mp_not(mp *d, mp *a)
-{
-  MP_DEST(d, MP_LEN(a), a->f);
-  mpx_not(d->v, d->vl, a->v, a->vl);
-  d->f = a->f & MP_BURN;
-  MP_SHRINK(d);
-  return (d);
-}
-
-/* --- @mp_bitop2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    The result of the given bitwise operation.  Negative numbers
- *             are treated as two's complement, sign-extended infinitely to
- *             the left.  The functions are named after the truth tables
- *             they generate:
- *
- *                     a:      0011
- *                     b:      0101
- *                     @mpx_bitXXXX@
- */
-
-/* --- How this actually works --- *
- *
- * The two arguments are inverted (with a sign-swap) if they're currently
- * negative.  This means that we end up using a different function (one which
- * reinverts as we go) for the main operation.  Also, if the sign would be
- * negative at the end, we preinvert the output and then invert again with a
- * sign-swap.
- *
- * Start with:                 wxyz      WXYZ
- * If @a@ negative:            yzwx  or  YZWX
- * If @b@ negative:            xwzy      XWZY
- * If both negative:           zyxw      ZYXW
- */
-
-#define MP_BIT2CBINOP(n, base, an, bn, abn, p_base, p_an, p_bn, p_abn) \
-                                                                       \
-mp *mp_bit##n##2c(mp *d, mp *a, mp *b)                                 \
-{                                                                      \
-  if (!((a->f | b->f) & MP_NEG)) {     /* Both positive */             \
-    d = mp_bit##base(d, a, b);                                         \
-    p_base                                                             \
-  } else if (!(b->f & MP_NEG)) {       /* Only @b@ positive */         \
-    MP_COPY(b);                                                                \
-    d = mp_not2c(d, a);                                                        \
-    d = mp_bit##an(d, d, b);                                           \
-    MP_DROP(b);                                                                \
-    p_an                                                               \
-  } else if (!(a->f & MP_NEG)) {       /* Only @a@ positive */         \
-    MP_COPY(a);                                                                \
-    d = mp_not2c(d, b);                                                        \
-    d = mp_bit##bn(d, a, d);                                           \
-    MP_DROP(a);                                                                \
-    p_bn                                                               \
-  } else {                             /* Both negative */             \
-    mp *t = mp_not2c(MP_NEW, a);                                       \
-    d = mp_not2c(d, b);                                                        \
-    d = mp_bit##abn(d, t, d);                                          \
-    MP_DROP(t);                                                                \
-    p_abn                                                              \
-  }                                                                    \
-  return (d);                                                          \
-}                                                                      \
-
-#define NEG d = mp_not2c(d, d);
-#define POS
-MP_BIT2CBINOP(0000, 0000, 0000, 0000, 0000, POS, POS, POS, POS)
-MP_BIT2CBINOP(0001, 0001, 0100, 0010, 0111, POS, POS, POS, NEG)
-MP_BIT2CBINOP(0010, 0010, 0111, 0001, 0100, POS, NEG, POS, POS)
-MP_BIT2CBINOP(0011, 0011, 0011, 0011, 0011, POS, NEG, POS, NEG)
-MP_BIT2CBINOP(0100, 0100, 0001, 0111, 0010, POS, POS, NEG, POS)
-MP_BIT2CBINOP(0101, 0101, 0101, 0101, 0101, POS, POS, NEG, NEG)
-MP_BIT2CBINOP(0110, 0110, 0110, 0110, 0110, POS, NEG, NEG, POS)
-MP_BIT2CBINOP(0111, 0111, 0010, 0100, 0001, POS, NEG, NEG, NEG)
-MP_BIT2CBINOP(1000, 0111, 0010, 0100, 0001, NEG, POS, POS, POS)
-MP_BIT2CBINOP(1001, 0110, 0110, 0110, 0110, NEG, POS, POS, NEG)
-MP_BIT2CBINOP(1010, 0101, 0101, 0101, 0101, NEG, NEG, POS, POS)
-MP_BIT2CBINOP(1011, 0100, 0001, 0111, 0010, NEG, NEG, POS, NEG)
-MP_BIT2CBINOP(1100, 0011, 0011, 0011, 0011, NEG, POS, NEG, POS)
-MP_BIT2CBINOP(1101, 0010, 0111, 0001, 0100, NEG, POS, NEG, NEG)
-MP_BIT2CBINOP(1110, 0001, 0100, 0010, 0111, NEG, NEG, NEG, POS)
-MP_BIT2CBINOP(1111, 0000, 0000, 0000, 0000, NEG, NEG, NEG, NEG)
-#undef NEG
-#undef POS
-
-/* --- @mp_not2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    The sign-extended complement of the argument.
- */
-
-mp *mp_not2c(mp *d, mp *a)
-{
-  mpw one = 1;
-
-  MP_DEST(d, MP_LEN(a) + 1, a->f);
-  if (d == a) {
-    if (MP_NEGP(a))
-      MPX_USUBN(d->v, d->vl, 1);
-    else
-      MPX_UADDN(d->v, d->vl, 1);
-  } else {
-    if (MP_NEGP(a))
-      mpx_usub(d->v, d->vl, a->v, a->vl, &one, &one + 1);
-    else
-      mpx_uadd(d->v, d->vl, a->v, a->vl, &one, &one + 1);
-  }
-  d->f = (a->f & (MP_NEG | MP_BURN)) ^ MP_NEG;
-  MP_SHRINK(d);
-  return (d);
-}
-
-/* --- @mp_add@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ added to @b@.
- */
-
-mp *mp_add(mp *d, mp *a, mp *b)
-{
-  MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)) + 1, a->f | b->f);
-  if (!((a->f ^ b->f) & MP_NEG))
-    mpx_uadd(d->v, d->vl, a->v, a->vl, b->v, b->vl);
-  else {
-    if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) {
-      mp *t = a; a = b; b = t;
-    }
-    mpx_usub(d->v, d->vl, a->v, a->vl, b->v, b->vl);
-  }
-  d->f = ((a->f | b->f) & MP_BURN) | (a->f & MP_NEG);
-  MP_SHRINK(d);
-  return (d);
-}
-
-/* --- @mp_sub@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @b@ subtracted from @a@.
- */
-
-mp *mp_sub(mp *d, mp *a, mp *b)
-{
-  unsigned sgn = 0;
-  MP_DEST(d, MAX(MP_LEN(a), MP_LEN(b)) + 1, a->f | b->f);
-  if ((a->f ^ b->f) & MP_NEG)
-    mpx_uadd(d->v, d->vl, a->v, a->vl, b->v, b->vl);
-  else {
-    if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) {
-      mp *t = a; a = b; b = t;
-      sgn = MP_NEG;
-    }
-    mpx_usub(d->v, d->vl, a->v, a->vl, b->v, b->vl);
-  }
-  d->f = ((a->f | b->f) & MP_BURN) | ((a->f ^ sgn) & MP_NEG);
-  MP_SHRINK(d);
-  return (d);
-}
-
-/* --- @mp_mul@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ multiplied by @b@.
- */
-
-mp *mp_mul(mp *d, mp *a, mp *b)
-{
-  a = MP_COPY(a);
-  b = MP_COPY(b);
-
-  if (MP_LEN(a) <= MPK_THRESH || MP_LEN(b) <= MPK_THRESH) {
-    MP_DEST(d, MP_LEN(a) + MP_LEN(b), a->f | b->f | MP_UNDEF);
-    mpx_umul(d->v, d->vl, a->v, a->vl, b->v, b->vl);
-  } else {
-    size_t m = MAX(MP_LEN(a), MP_LEN(b));
-    mpw *s;
-    MP_DEST(d, 3 * m, a->f | b->f | MP_UNDEF);
-    s = mpalloc(d->a, 5 * m);
-    mpx_kmul(d->v, d->vl, a->v, a->vl, b->v, b->vl, s, s + 5 * m);
-    mpfree(d->a, s);
-  }
-
-  d->f = ((a->f | b->f) & MP_BURN) | ((a->f ^ b->f) & MP_NEG);
-  MP_SHRINK(d);
-  MP_DROP(a);
-  MP_DROP(b);
-  return (d);
-}
-
-/* --- @mp_sqr@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    Result, @a@ squared.
- */
-
-mp *mp_sqr(mp *d, mp *a)
-{
-  size_t m = MP_LEN(a);
-
-  a = MP_COPY(a);
-  if (m > MPK_THRESH) {
-    mpw *s;
-    MP_DEST(d, 3 * m, a->f | MP_UNDEF);
-    s = mpalloc(d->a, 5 * m);
-    mpx_ksqr(d->v, d->vl, a->v, a->vl, s, s + 5 * m);
-    mpfree(d->a, s);
-  } else {
-    MP_DEST(d, 2 * m + 2, a->f | MP_UNDEF);
-    mpx_usqr(d->v, d->vl, a->v, a->vl);
-  }
-  d->f = a->f & MP_BURN;
-  MP_SHRINK(d);
-  MP_DROP(a);
-  return (d);
-}
-
-/* --- @mp_div@ --- *
- *
- * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
- *             @mp *a, *b@ = sources
- *
- * Use:                Calculates the quotient and remainder when @a@ is divided by
- *             @b@.  The destinations @*qq@ and @*rr@ must be distinct.
- *             Either of @qq@ or @rr@ may be null to indicate that the
- *             result is irrelevant.  (Discarding both results is silly.)
- *             There is a performance advantage if @a == *rr@.
- *
- *             The behaviour when @a@ and @b@ have the same sign is
- *             straightforward.  When the signs differ, this implementation
- *             chooses @r@ to have the same sign as @b@, rather than the
- *             more normal choice that the remainder has the same sign as
- *             the dividend.  This makes modular arithmetic a little more
- *             straightforward.
- */
-
-void mp_div(mp **qq, mp **rr, mp *a, mp *b)
- {
-  mp *r = rr ? *rr : MP_NEW;
-  mp *q = qq ? *qq : MP_NEW;
-  mpw *sv, *svl;
-
-  /* --- Set the remainder up right --- *
-   *
-   * Just in case the divisor is larger, be able to cope with this.  It's not
-   * important in @mpx_udiv@, but it is here because of the sign correction.
-   */
-
-  b = MP_COPY(b);
-  a = MP_COPY(a);
-  if (r)
-    MP_DROP(r);
-  r = a;
-  MP_DEST(r, MAX(MP_LEN(a), MP_LEN(b)) + 2, a->f | b->f);
-
-  /* --- Fix up the quotient too --- */
-
-  r = MP_COPY(r);
-  MP_DEST(q, MP_LEN(r), r->f | MP_UNDEF);
-  MP_DROP(r);
-
-  /* --- Set up some temporary workspace --- */
-
-  {
-    size_t rq = MP_LEN(b) + 1;
-    sv = mpalloc(r->a, rq);
-    svl = sv + rq;
-  }
-
-  /* --- Perform the calculation --- */
-
-  mpx_udiv(q->v, q->vl, r->v, r->vl, b->v, b->vl, sv, svl);
-
-  /* --- Sort out the sign of the results --- *
-   *
-   * If the signs of the arguments differ, and the remainder is nonzero, I
-   * must add one to the absolute value of the quotient and subtract the
-   * remainder from @b@.
-   */
-
-  q->f = ((r->f | b->f) & MP_BURN) | ((r->f ^ b->f) & MP_NEG);
-  if (MP_NEGP(q)) {
-    mpw *v;
-    for (v = r->v; v < r->vl; v++) {
-      if (*v) {
-       MPX_UADDN(q->v, q->vl, 1);
-       mpx_usub(r->v, r->vl, b->v, b->vl, r->v, r->vl);
-       break;
-      }
-    }
-  }
-
-  r->f = ((r->f | b->f) & MP_BURN) | (b->f & MP_NEG);
-
-  /* --- Store the return values --- */
-
-  mpfree(r->a, sv);
-  MP_DROP(b);
-
-  if (!qq)
-    MP_DROP(q);
-  else {
-    MP_SHRINK(q);
-    *qq = q;
-  }
-
-  if (!rr)
-    MP_DROP(r);
-  else {
-    MP_SHRINK(r);
-    *rr = r;
-  }
-}
-
-/* --- @mp_odd@ --- *
- *
- * Arguments:  @mp *d@ = pointer to destination integer
- *             @mp *m@ = pointer to source integer
- *             @size_t *s@ = where to store the power of 2
- *
- * Returns:    An odd integer integer %$t$% such that %$m = 2^s t$%.
- *
- * Use:                Computes a power of two and an odd integer which, when
- *             multiplied, give a specified result.  This sort of thing is
- *             useful in number theory quite often.
- */
-
-mp *mp_odd(mp *d, mp *m, size_t *s)
-{
-  size_t ss = 0;
-  const mpw *v, *vl;
-
-  v = m->v;
-  vl = m->vl;
-  for (; !*v && v < vl; v++)
-    ss += MPW_BITS;
-  if (v >= vl)
-    ss = 0;
-  else {
-    mpw x = *v;
-    unsigned z = MPW_P2;
-    mpw mask = ((mpw)1 << z) - 1;
-
-    while (z) {
-      if (!(x & mask)) {
-       x >>= z;
-       ss += z;
-      }
-      z >>= 1;
-      mask >>= z;
-    }
-  }
-
-  *s = ss;
-  return (mp_lsr(d, m, ss));
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int verify(const char *op, mp *expect, mp *result, mp *a, mp *b)
-{
-  if (!MP_EQ(expect, result)) {
-    fprintf(stderr, "\n*** %s failed", op);
-    fputs("\n*** a     = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\n*** b     = ", stderr); mp_writefile(b, stderr, 10);
-    fputs("\n*** result = ", stderr); mp_writefile(result, stderr, 10);
-    fputs("\n*** expect = ", stderr); mp_writefile(expect, stderr, 10);
-    fputc('\n', stderr);
-    return (0);
-  }
-  return (1);
-}
-
-#define RIG(name, op)                                                  \
-  static int t##name(dstr *v)                                          \
-  {                                                                    \
-    mp *a = *(mp **)v[0].buf;                                          \
-    mpw n = *(int *)v[1].buf;                                          \
-    mp b;                                                              \
-    mp *r = *(mp **)v[2].buf;                                          \
-    mp *c = op(MP_NEW, a, n);                                          \
-    int ok;                                                            \
-    mp_build(&b, &n, &n + 1);                                          \
-    ok = verify(#name, r, c, a, &b);                                   \
-    mp_drop(a); mp_drop(c); mp_drop(r);                                        \
-    assert(mparena_count(MPARENA_GLOBAL) == 0);                                \
-    return (ok);                                                       \
-  }
-
-RIG(lsl, mp_lsl)
-RIG(lsr, mp_lsr)
-RIG(lsl2c, mp_lsl2c)
-RIG(lsr2c, mp_lsr2c)
-
-#undef RIG
-
-#define RIG(name, op)                                                  \
-  static int t##name(dstr *v)                                          \
-  {                                                                    \
-    mp *a = *(mp **)v[0].buf;                                          \
-    mp *b = *(mp **)v[1].buf;                                          \
-    mp *r = *(mp **)v[2].buf;                                          \
-    mp *c = op(MP_NEW, a, b);                                          \
-    int ok = verify(#name, r, c, a, b);                                        \
-    mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(r);                    \
-    assert(mparena_count(MPARENA_GLOBAL) == 0);                                \
-    return (ok);                                                       \
-  }
-
-RIG(add, mp_add)
-RIG(sub, mp_sub)
-RIG(mul, mp_mul)
-RIG(exp, mp_exp)
-
-#undef RIG
-
-static int tdiv(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  mp *b = *(mp **)v[1].buf;
-  mp *q = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *c = MP_NEW, *d = MP_NEW;
-  int ok = 1;
-  mp_div(&c, &d, a, b);
-  ok &= verify("div(quotient)", q, c, a, b);
-  ok &= verify("div(remainder)", r, d, a, b);
-  mp_drop(a); mp_drop(b); mp_drop(c); mp_drop(d); mp_drop(r); mp_drop(q);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tbin(dstr *v)
-{
-  static mp *(*fn[])(mp *, mp *, mp *) = {
-#define DO(string) mp_bit##string##2c,
-MPX_DOBIN(DO)
-#undef DO
-  };
-  int ok = 1;
-  unsigned op = 0;
-  mp *a = *(mp **)v[1].buf;
-  mp *b = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *c;
-
-  if (strcmp(v[0].buf, "and") == 0) op = 1;
-  else if (strcmp(v[0].buf, "or") == 0) op = 7;
-  else if (strcmp(v[0].buf, "nand") == 0) op = 14;
-  else if (strcmp(v[0].buf, "nor") == 0) op = 8;
-  else if (strcmp(v[0].buf, "xor") == 0) op = 6;
-  else {
-    char *p = v[0].buf;
-    while (*p) {
-      op <<= 1;
-      if (*p++ == '1')
-       op |= 1;
-    }
-  }
-
-  c = fn[op](MP_NEW, a, b);
-  ok = verify(v[0].buf, r, c, a, b);
-  mp_drop(a); mp_drop(b); mp_drop(r); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tset(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  unsigned long n = *(unsigned long *)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *c;
-  int ok = 1;
-
-  c = mp_setbit2c(MP_NEW, a, n);
-  if (!MP_EQ(c, r)) {
-    ok = 0;
-    fprintf(stderr, "\n***setbit (set) failed");
-    fputs("\n*** a  = ", stderr); mp_writefile(a, stderr, 16);
-    fprintf(stderr, "\n*** n  = %lu", n);
-    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 16);
-    fputs("\n*** c = ", stderr); mp_writefile(c, stderr, 16);
-    fputc('\n', stderr);
-  }
-  if (!mp_testbit2c(r, n)) {
-    ok = 0;
-    fprintf(stderr, "\n***setbit (test) failed");
-    fprintf(stderr, "\n*** n  = %lu", n);
-    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 16);
-    fputc('\n', stderr);
-  }
-  mp_drop(a);
-  mp_drop(r);
-  mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tclr(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  unsigned long n = *(unsigned long *)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *c;
-  int ok = 1;
-
-  c = mp_clearbit2c(MP_NEW, a, n);
-  if (!MP_EQ(c, r)) {
-    ok = 0;
-    fprintf(stderr, "\n***clrbit (set) failed");
-    fputs("\n*** a  = ", stderr); mp_writefile(a, stderr, 16);
-    fprintf(stderr, "\n*** n  = %lu", n);
-    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 16);
-    fputs("\n*** c = ", stderr); mp_writefile(c, stderr, 16);
-    fputc('\n', stderr);
-  }
-  if (mp_testbit2c(r, n)) {
-    ok = 0;
-    fprintf(stderr, "\n***clrbit (test) failed");
-    fprintf(stderr, "\n*** n  = %lu", n);
-    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 16);
-    fputc('\n', stderr);
-  }
-  mp_drop(a);
-  mp_drop(c);
-  mp_drop(r);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tneg(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  mp *r = *(mp **)v[1].buf;
-  int ok = 1;
-  mp *n = mp_neg(MP_NEW, a);
-  if (!MP_EQ(r, n)) {
-    ok = 0;
-    fprintf(stderr, "\n*** neg failed\n");
-    fputs("\n*** a  = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\n*** n  = ", stderr); mp_writefile(n, stderr, 10);
-    fputc('\n', stderr);
-  }
-  mp_drop(n);
-  n = mp_neg(a, a);
-  if (!MP_EQ(r, n)) {
-    ok = 0;
-    fprintf(stderr, "\n*** neg failed\n");
-    fputs("\n*** a* = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\n*** r  = ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\n*** n  = ", stderr); mp_writefile(n, stderr, 10);
-    fputc('\n', stderr);
-  }
-  mp_drop(a);
-  mp_drop(r);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int todd(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  size_t rs = *(uint32 *)v[1].buf;
-  mp *rt = *(mp **)v[2].buf;
-  int ok = 1;
-  mp *t;
-  size_t s;
-  t = mp_odd(MP_NEW, a, &s);
-  if (s != rs || !MP_EQ(t, rt)) {
-    ok = 0;
-    fprintf(stderr, "\n*** odd failed");
-    fputs("\n*** a  = ", stderr); mp_writefile(a, stderr, 10);
-    fprintf(stderr, "\n*** s  = %lu", (unsigned long)s);
-    fputs("\n*** t  = ", stderr); mp_writefile(t, stderr, 10);
-    fprintf(stderr, "\n*** rs = %lu", (unsigned long)rs);
-    fputs("\n*** rt = ", stderr); mp_writefile(rt, stderr, 10);
-    fputc('\n', stderr);
-  }
-  mp_drop(a);
-  mp_drop(rt);
-  mp_drop(t);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "lsl", tlsl, { &type_mp, &type_int, &type_mp, 0 } },
-  { "lsr", tlsr, { &type_mp, &type_int, &type_mp, 0 } },
-  { "lsl2c", tlsl2c, { &type_mp, &type_int, &type_mp, 0 } },
-  { "lsr2c", tlsr2c, { &type_mp, &type_int, &type_mp, 0 } },
-  { "setbit", tset, { &type_mp, &type_ulong, &type_mp, 0 } },
-  { "clrbit", tclr, { &type_mp, &type_ulong, &type_mp, 0 } },
-  { "add", tadd, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "sub", tsub, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "mul", tmul, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "div", tdiv, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { "exp", texp, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "bin2c", tbin, { &type_string, &type_mp, &type_mp, &type_mp, 0 } },
-  { "odd", todd, { &type_mp, &type_uint32, &type_mp, 0 } },
-  { "neg", tneg, { &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } },
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mp");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-const.c b/mp-const.c
deleted file mode 100644 (file)
index dc31007..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mp-const.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Useful multiprecision constants
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-static mpw mpw_const[] = { 1, 2, 3, 4, 5, 10, 256 };
-
-mp mp_const[] = {
-  { &mpw_const[0], &mpw_const[0], 0, 0, MP_CONST, 0 },
-  { &mpw_const[0], &mpw_const[0] + 1, 1, 0, MP_CONST, 0 },
-  { &mpw_const[1], &mpw_const[1] + 1, 1, 0, MP_CONST, 0 },
-  { &mpw_const[2], &mpw_const[2] + 1, 1, 0, MP_CONST, 0 },
-  { &mpw_const[3], &mpw_const[3] + 1, 1, 0, MP_CONST, 0 },
-  { &mpw_const[4], &mpw_const[4] + 1, 1, 0, MP_CONST, 0 },
-  { &mpw_const[5], &mpw_const[5] + 1, 1, 0, MP_CONST, 0 },
-  { &mpw_const[6], &mpw_const[6] + 1, 1, 0, MP_CONST, 0 },
-  { &mpw_const[0], &mpw_const[0] + 1, 1, 0, MP_CONST | MP_NEG, 0 },
-  { 0, mpw_const, 1, 0, MP_CONST | MP_BURN, 0 },
-};
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-exp.c b/mp-exp.c
deleted file mode 100644 (file)
index 9cb56ee..0000000
--- a/mp-exp.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Exponentiation for large integers
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-
-#include "mp.h"
-#include "mp-exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_exp@ --- *
- *
- * Arguments:  @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e$%.
- */
-
-mp *mp_exp(mp *d, mp *a, mp *e)
-{
-  mp *x = MP_ONE;
-  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
-  assert(!MP_NEGP(e));
-
-  MP_COPY(a);
-  if (MP_ZEROP(e))
-    ;
-  else if (MP_LEN(e) < EXP_THRESH)
-    EXP_SIMPLE(x, a, e);
-  else
-    EXP_WINDOW(x, a, e);
-  mp_drop(d);
-  mp_drop(spare);
-  mp_drop(a);
-  return (x);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-exp.h b/mp-exp.h
deleted file mode 100644 (file)
index 2e5dbf2..0000000
--- a/mp-exp.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Exponentiation for large integers
- *
- * (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.
- */
-
-#ifndef CATACOMB_MP_EXP_H
-#define CATACOMB_MP_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentiation ----------------------------------------------------*/
-
-#define EXP_TYPE mp *
-
-#define EXP_COPY(d, x) d = MP_COPY(x)
-#define EXP_DROP(x) MP_DROP(x)
-
-#define EXP_MUL(a, x) do {                                             \
-  mp *t = mp_mul(spare, a, x);                                         \
-  spare = a;                                                           \
-  a = t;                                                               \
-} while (0)
-
-#define EXP_SQR(a) do {                                                        \
-  mp *t = mp_sqr(spare, a);                                            \
-  spare = a;                                                           \
-  a = t;                                                               \
-} while (0)
-
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) d = mp_mul(MP_NEW, x, y)
-#define EXP_SETSQR(d, x) d = mp_sqr(MP_NEW, x)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mp-fibonacci.c b/mp-fibonacci.c
deleted file mode 100644 (file)
index e103979..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/* -*-c-*-
- *
- * Compute the %$n$%th Fibonacci number
- *
- * (c) 2013 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpint.h"
-
-/*----- About the algorithm -----------------------------------------------*
- *
- * Define %$F_0 = 0$% and %$F_1 = 1$%, and %$F_{k+1} = F_k + F_{k-1}$% for
- * all %$k$%.  (This defines %$F_k$% for negative %$k$% too, by
- * %$F_{k-1} = F_{k+1} - F_k$%; in particular, %$F_{-1} = 1$% and
- * %$F_{-2} = -1$%.)  We say that %$F_k$% is the %$k$%th Fibonacci number.
- *
- * We work in the ring %$\ZZ[t]/(t^2 - t -1)$%.  Every residue class in this
- * ring contains a unique representative with degree at most 1.  I claim that
- * %$t^k = F_k t + F_{k-1}$% for all %$k$%.  Certainly %$t = F_1 t + F_0$%.
- * Note that %$t (F_{-1} t + F_{-2}) = t (t - 1) = t^2 - t = 1$%, so the
- * claim holds for %$k = -1$%.  Suppose, inductively, that it holds for
- * %$k$%; then %$t^{k+1} = t \cdot t^k = F_k t^2 + F_{k-1} t = {}$%
- * %$(F_k + F_{k-1}) t + F_k = F_{k+1} t + F_k$%; and %$t^{k-1} = {}$%
- * %$t^{-1} t^k = (t - 1) t^k = t^{k+1} - t^k = {}$%
- * %$(F_{k+1} - F_k) t + (F_k - F_{k-1}) = F_{k-1} t + F_{k-2}$%, proving the
- * claim.
- *
- * So we can compute Fibonacci numbers by exponentiating in this ring.
- * Squaring and multiplication work like this.
- *
- *   * Square: %$(a t + b)^2 = a^2 t^2 + 2 a b t + b^2 = {}$%
- *     %$(a^2 + 2 a b) t + (a^2 + b^2)$%
- *
- *   * Multiply: %$(a t + b)(c t + d) = a c t^2 + (a d + b c) t + b d = {}$%
- *     %$(a c + a d + b c) t + (a c + b d)$%.
- */
-
-/*----- Exponentiation machinery ------------------------------------------*/
-
-/* --- @struct fib@ --- *
- *
- * A simple structure tracking polynomial coefficients.
- */
-
-struct fib {
-  int n;                               /* Exponent for this entry */
-  mp *a, *b;                           /* Coefficients: %$a t + b$% */
-};
-
-#define MAX 100                                /* Saturation bounds for exponent */
-#define MIN -100
-
-/* --- @CLAMP@ --- *
- *
- * Clamp @n@ within the upper and lower bounds.
- */
-
-#define CLAMP(n) do {                                                  \
-  if (n > MAX) n = MAX; else if (n < MIN) n = MIN;                     \
-} while (0)
-
-/* --- Basic structure maintenance functions --- */
-
-static void fib_init(struct fib *f)
-  { f->a = f->b = MP_NEW; }
-
-static void fib_drop(struct fib *f)
-  { if (f->a) MP_DROP(f->a); if (f->b) MP_DROP(f->b); }
-
-static void fib_copy(struct fib *d, struct fib *x)
-  { d->n = x->n; d->a = MP_COPY(x->a); d->b = MP_COPY(x->b); }
-
-/* --- @fib_sqr@ --- *
- *
- * Arguments:  @struct fib *d@ = destination structure
- *             @struct fib *x@ = operand
- *
- * Returns:    ---
- *
- * Use:                Set @d@ to the square of @x@.
- */
-
-static void fib_sqr(struct fib *d, struct fib *x)
-{
-  mp *aa, *t;
-
-  /* --- Special case: if @x@ is the identity then just copy --- */
-
-  if (!x->n) {
-    if (d != x) { fib_drop(d); fib_copy(d, x); }
-    return;
-  }
-
-  /* --- Compute the result --- */
-
-  aa = mp_sqr(MP_NEW, x->a);           /* %$a^2$% */
-
-  t = mp_mul(d->a, x->a, x->b);                /* %$t = a b$% */
-  t = mp_lsl(t, t, 1);                 /* %$t = 2 a b$% */
-  d->a = mp_add(t, t, aa);             /* %$a' = a^2 + 2 a b$% */
-
-  t = mp_sqr(d->b, x->b);              /* %$t = b^2$% */
-  d->b = mp_add(t, t, aa);             /* %$b' = a^2 + b^2$% */
-
-  /* --- Sort out the exponent on the result --- */
-
-  d->n = 2*x->n; CLAMP(d->n);
-
-  /* --- Done --- */
-
-  MP_DROP(aa);
-}
-
-/* --- @fib_mul@ --- *
- *
- * Arguments:  @struct fib *d@ = destination structure
- *             @struct fib *x, *y@ = operands
- *
- * Returns:    ---
- *
- * Use:                Set @d@ to the product of @x@ and @y@.
- */
-
-static void fib_mul(struct fib *d, struct fib *x, struct fib *y)
-{
-  mp *t, *u, *bd;
-
-  /* --- Lots of special cases for low exponents --- */
-
-  if (y->n == 0) {
-  copy_x:
-    if (d != x) { fib_drop(d); fib_copy(d, x); }
-    return;
-  } else if (x->n == 0) { x = y; goto copy_x; }
-  else if (y->n == -1) {
-  dec_x:
-    t = mp_sub(d->a, x->a, x->b);
-    d->a = MP_COPY(x->b); if (d->b) MP_DROP(d->b); d->b = t;
-    d->n = x->n - 1; CLAMP(d->n);
-    return;
-  } else if (y->n == +1) {
-  inc_x:
-    t = mp_add(d->b, x->a, x->b);
-    d->b = MP_COPY(x->a); if (d->a) MP_DROP(d->a); d->a = t;
-    d->n = x->n + 1; CLAMP(d->n);
-    return;
-  } else if (x->n == -1) { x = y; goto dec_x; }
-  else if (x->n == +1) { x = y; goto inc_x; }
-
-  /* --- Compute the result --- */
-
-  bd = mp_mul(MP_NEW, x->b, y->b);     /* %$b d$% */
-  t = mp_add(MP_NEW, x->a, x->b);      /* %$t = a + b$% */
-  u = mp_add(MP_NEW, y->a, y->b);      /* %$u = c + d$% */
-  t = mp_mul(t, t, u);                 /* %$t = (a + b)(c + d)$% */
-  u = mp_mul(u, x->a, y->a);           /* %$u = a c$% */
-
-  d->a = mp_sub(d->a, t, bd);          /* %$a' = a c + a d + b c$% */
-  d->b = mp_add(d->b, u, bd);          /* %$b' = a c + b d$% */
-
-  /* --- Sort out the exponent on the result --- */
-
-  if (x->n == MIN || x->n == MAX) d->n = x->n;
-  else if (y->n == MIN || y->n == MAX) d->n = y->n;
-  else { d->n = x->n + y->n; CLAMP(d->n); }
-
-  /* --- Done --- */
-
-  MP_DROP(bd); MP_DROP(t); MP_DROP(u);
-}
-
-/* --- Exponentiation --- */
-
-#define EXP_TYPE                       struct fib
-#define EXP_COPY(d, x)                 fib_copy(&d, &x)
-#define EXP_DROP(x)                    fib_drop(&x)
-#define EXP_FIX(d)
-
-#define EXP_SQR(x)                     fib_sqr(&x, &x)
-#define EXP_MUL(x, y)                  fib_mul(&x, &x, &y)
-#define EXP_SETSQR(d, x)               fib_init(&d); fib_sqr(&d, &x)
-#define EXP_SETMUL(d, x, y)            fib_init(&d); fib_mul(&d, &x, &y)
-
-#include "exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_fibonacci@ --- *
- *
- * Arguments:  @long n@ = index desired (may be negative)
- *
- * Returns:    The %$n$%th Fibonacci number.
- */
-
-mp *mp_fibonacci(long n)
-{
-  struct fib d, g;
-  mp *nn;
-
-  d.n = 0; d.a = MP_ZERO; d.b = MP_ONE;
-  if (n >= 0) { g.n = 1; g.a = MP_ONE; g.b = MP_ZERO; }
-  else { g.n = -1; g.a = MP_ONE; g.b = MP_MONE; n = -n; }
-  nn = mp_fromlong(MP_NEW, n);
-
-  EXP_WINDOW(d, g, nn);
-
-  MP_DROP(nn); fib_drop(&g); MP_DROP(d.b);
-  return (d.a);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int vfib(dstr *v)
-{
-  long x = *(long *)v[0].buf;
-  mp *fx = *(mp **)v[1].buf;
-  mp *y = mp_fibonacci(x);
-  int ok = 1;
-  if (!MP_EQ(fx, y)) {
-    fprintf(stderr, "fibonacci failed\n");
-    MP_FPRINTF(stderr, (stderr, "fib(%ld) = ", x), fx);
-    MP_EPRINT("result", y);
-    ok = 0;
-  }
-  mp_drop(fx);
-  mp_drop(y);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "fibonacci", vfib, { &type_long, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, tests, SRCDIR "/tests/mp");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-gcd.c b/mp-gcd.c
deleted file mode 100644 (file)
index 40531c7..0000000
--- a/mp-gcd.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Extended GCD calculation
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_gcd@ --- *
- *
- * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
- *             @mp *a, *b@ = sources (must be nonzero)
- *
- * Returns:    ---
- *
- * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
- *             @ax + by = gcd(a, b)@.  This is useful for computing modular
- *             inverses.
- */
-
-void mp_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b)
-{
-  mp *x = MP_ONE, *X = MP_ZERO;
-  mp *y = MP_ZERO, *Y = MP_ONE;
-  mp *u, *v;
-  mp *q = MP_NEW, *t, *spare = MP_NEW;
-  unsigned f = 0;
-
-#define f_swap 1u
-#define f_aneg 2u
-#define f_bneg 4u
-#define f_ext 8u
-
-  /* --- Sort out some initial flags --- */
-
-  if (xx || yy)
-    f |= f_ext;
-
-  if (MP_NEGP(a))
-    f |= f_aneg;
-  if (MP_NEGP(b))
-    f |= f_bneg;
-
-  /* --- Ensure that @a@ is larger than @b@ --- *
-   *
-   * Use absolute values here!
-   */
-
-  if (MPX_UCMP(a->v, a->vl, <, b->v, b->vl)) {
-    t = a; a = b; b = t;
-    f |= f_swap;
-  }
-
-  /* --- Check for zeroness --- */
-
-  if (MP_ZEROP(b)) {
-
-    /* --- Store %$|a|$% as the GCD --- */
-
-    if (gcd) {
-      if (*gcd) MP_DROP(*gcd);
-      a = MP_COPY(a);
-      if (MP_NEGP(a)) {
-       MP_SPLIT(a);
-       a->f &= ~MP_NEG;
-       f |= f_aneg;
-      }
-      *gcd = a;
-    }
-
-    /* --- Store %$1$% and %$0$% in the appropriate bins --- */
-
-    if (f & f_ext) {
-      if (f & f_swap) {
-       mp **tt = xx; xx = yy; yy = tt;
-      }
-      if (xx) {
-       if (*xx) MP_DROP(*xx);
-       if (MP_EQ(a, MP_ZERO))
-         *xx = MP_ZERO;
-       else if (f & f_aneg)
-         *xx = MP_MONE;
-       else
-         *xx = MP_ONE;
-      }
-      if (yy) {
-       if (*yy) MP_DROP(*yy);
-       *yy = MP_ZERO;
-      }
-    }
-    return;
-  }
-
-  /* --- Force the signs on the arguments and take copies --- */
-
-  a = MP_COPY(a);
-  b = MP_COPY(b);
-
-  MP_SPLIT(a); a->f &= ~MP_NEG;
-  MP_SPLIT(b); b->f &= ~MP_NEG;
-
-  u = MP_COPY(a);
-  v = MP_COPY(b);
-
-  /* --- Main extended Euclidean algorithm --- */
-
-  while (!MP_ZEROP(v)) {
-    mp_div(&q, &u, u, v);
-    if (f & f_ext) {
-      t = mp_mul(spare, X, q);
-      t = mp_sub(t, x, t);
-      spare = x; x = X; X = t;
-      t = mp_mul(spare, Y, q);
-      t = mp_sub(t, y, t);
-      spare = y; y = Y; Y = t;
-    }
-    t = u; u = v; v = t;
-  }
-
-  MP_DROP(q); if (spare) MP_DROP(spare);
-  if (!gcd)
-    MP_DROP(u);
-  else {
-    if (*gcd) MP_DROP(*gcd);
-    u->f &= ~MP_NEG;
-    *gcd = u;
-  }
-
-  /* --- Perform a little normalization --- *
-   *
-   * Ensure that the coefficient returned is positive, if there is only one.
-   * If there are two, favour @y@.  Of course, if the original arguments were
-   * negative then I'll need to twiddle their signs as well.
-   */
-
-  if (f & f_ext) {
-
-    /* --- If @a@ and @b@ got swapped, swap the coefficients back --- */
-
-    if (f & f_swap) {
-      t = x; x = y; y = t;
-      t = a; a = b; b = t;
-    }
-
-    /* --- Sort out the signs --- *
-     *
-     * Note that %$ax + by = a(x - b) + b(y + a)$%.
-     *
-     * This is currently bodgy.  It needs sorting out at some time.
-     */
-
-    if (yy) {
-      if (MP_NEGP(y)) {
-       do {
-         y = mp_add(y, y, a);
-         x = mp_sub(x, x, b);
-       } while (MP_NEGP(y));
-      } else {
-       while (MP_CMP(y, >=, a)) {
-         y = mp_sub(y, y, a);
-         x = mp_add(x, x, b);
-       }
-      }
-    } else {
-      if (MP_NEGP(x)) {
-       do
-         x = mp_add(x, x, b);
-       while (MP_NEGP(x));
-      } else {
-       while (MP_CMP(x, >=, b))
-         x = mp_sub(x, x, b);
-      }
-    }
-
-    /* --- Twiddle the signs --- */
-
-    if (f & f_aneg)
-      x->f ^= MP_NEG;
-    if (f & f_bneg)
-      y->f ^= MP_NEG;
-
-    /* --- Store the results --- */
-
-    if (!xx)
-      MP_DROP(x);
-    else {
-      if (*xx) MP_DROP(*xx);
-      *xx = x;
-    }
-
-    if (!yy)
-      MP_DROP(y);
-    else {
-      if (*yy) MP_DROP(*yy);
-      *yy = y;
-    }
-  }
-
-  MP_DROP(v);
-  MP_DROP(X); MP_DROP(Y);
-  MP_DROP(a); MP_DROP(b);
-}
-
-/* -- @mp_modinv@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *x@ = argument
- *             @mp *p@ = modulus
- *
- * Returns:    The inverse %$x^{-1} \bmod p$%.
- *
- * Use:                Computes a modular inverse.    An assertion fails if %$p$%
- *             has no inverse.
- */
-
-mp *mp_modinv(mp *d, mp *x, mp *p)
-{
-  mp *g = MP_NEW;
-  mp_gcd(&g, 0, &d, p, x);
-  assert(MP_EQ(g, MP_ONE));
-  mp_drop(g);
-  return (d);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int modinv(dstr *v)
-{
-  int ok = 1;
-  mp *x = *(mp **)v[0].buf;
-  mp *m = *(mp **)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-
-  mp *y = mp_modinv(MP_NEW, x, m);
-  if (!MP_EQ(y, r)) {
-    fputs("\n*** mp_modinv failed", stderr);
-    fputs("\nx     = ", stderr); mp_writefile(x, stderr, 10);
-    fputs("\nm     = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\nexpect = ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\nresult = ", stderr); mp_writefile(y, stderr, 10);
-    ok = 0;
-  }
-  MP_DROP(x); MP_DROP(m); MP_DROP(r); MP_DROP(y);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int gcd(dstr *v)
-{
-  int ok = 1;
-  mp *a = *(mp **)v[0].buf;
-  mp *b = *(mp **)v[1].buf;
-  mp *g = *(mp **)v[2].buf;
-  mp *x = *(mp **)v[3].buf;
-  mp *y = *(mp **)v[4].buf;
-
-  mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW;
-  mp_gcd(&gg, &xx, &yy, a, b);
-  if (!MP_EQ(x, xx)) {
-    fputs("\n*** mp_gcd(x) failed", stderr);
-    fputs("\na     = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 10);
-    fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 10);
-    fputs("\nresult = ", stderr); mp_writefile(xx, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-  if (!MP_EQ(y, yy)) {
-    fputs("\n*** mp_gcd(y) failed", stderr);
-    fputs("\na     = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 10);
-    fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 10);
-    fputs("\nresult = ", stderr); mp_writefile(yy, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  if (!ok) {
-    mp *ax = mp_mul(MP_NEW, a, xx);
-    mp *by = mp_mul(MP_NEW, b, yy);
-    ax = mp_add(ax, ax, by);
-    if (MP_EQ(ax, gg))
-      fputs("\n*** (Alternative result found.)\n", stderr);
-    MP_DROP(ax);
-    MP_DROP(by);
-  }
-
-  if (!MP_EQ(g, gg)) {
-    fputs("\n*** mp_gcd(gcd) failed", stderr);
-    fputs("\na     = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\nb     = ", stderr); mp_writefile(b, stderr, 10);
-    fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 10);
-    fputs("\nresult = ", stderr); mp_writefile(gg, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-  MP_DROP(a); MP_DROP(b); MP_DROP(g); MP_DROP(x); MP_DROP(y);
-  MP_DROP(gg); MP_DROP(xx); MP_DROP(yy);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "gcd", gcd, { &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { "modinv", modinv, { &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mp");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-io.c b/mp-io.c
deleted file mode 100644 (file)
index 9639a99..0000000
--- a/mp-io.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Loading and storing of multiprecision integers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_octets@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of octets required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer.
- */
-
-size_t mp_octets(const mp *m)
-{
-  size_t sz;
-  MPX_OCTETS(sz, m->v, m->vl);
-  return (sz);
-}
-
-/* --- @mp_octets2c@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of octets required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer represented as two's complement.
- */
-
-size_t mp_octets2c(const mp *m)
-{
-  size_t sz;
-  MPX_OCTETS2C(sz, m->v, m->vl);
-  return (sz);
-}
-
-/* --- @mp_bits@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of bits required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer.
- */
-
-unsigned long mp_bits(const mp *m)
-{
-  unsigned long bits;
-  MPX_BITS(bits, m->v, m->vl);
-  return (bits);
-}
-
-/* --- @mp_loadl@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets.  The
- *             first byte in the array is the least significant.  More
- *             formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$%
- *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
- */
-
-mp *mp_loadl(mp *d, const void *pv, size_t sz)
-{
-  MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
-  mpx_loadl(d->v, d->vl, pv, sz);
-  d->f &= ~(MP_UNDEF | MP_NEG);
-  mp_shrink(d);
-  return (d);
-}
-
-/* --- @mp_storel@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets.  The
- *             first byte in the array is the least significant.  If the
- *             array is too small to represent the number, high-order bits
- *             are truncated; if the array is too large, high order bytes
- *             are filled with zeros.  More formally, if the number is
- *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
- *             then the array is %$b_0, b_1, \ldots, b_{n-1}$%.
- */
-
-void mp_storel(const mp *m, void *pv, size_t sz)
-{
-  mpx_storel(m->v, m->vl, pv, sz);
-}
-
-/* --- @mp_loadb@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets.  The
- *             last byte in the array is the least significant.  More
- *             formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$%
- *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
- */
-
-mp *mp_loadb(mp *d, const void *pv, size_t sz)
-{
-  MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
-  mpx_loadb(d->v, d->vl, pv, sz);
-  d->f &= ~(MP_UNDEF | MP_NEG);
-  mp_shrink(d);
-  return (d);
-}
-
-/* --- @mp_storeb@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets.  The
- *             last byte in the array is the least significant.  If the
- *             array is too small to represent the number, high-order bits
- *             are truncated; if the array is too large, high order bytes
- *             are filled with zeros.  More formally, if the number is
- *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
- *             then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%.
- */
-
-void mp_storeb(const mp *m, void *pv, size_t sz)
-{
-  mpx_storeb(m->v, m->vl, pv, sz);
-}
-
-/* --- @mp_loadl2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets as
- *             two's complement.  The first byte in the array is the least
- *             significant.
- */
-
-mp *mp_loadl2c(mp *d, const void *pv, size_t sz)
-{
-  const octet *ov = pv;
-  MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
-  if (!sz || !(ov[sz - 1] & 0x80)) {
-    mpx_loadl(d->v, d->vl, pv, sz);
-    d->f &= ~MP_NEG;
-  } else {
-    mpx_loadl2cn(d->v, d->vl, pv, sz);
-    d->f |= MP_NEG;
-  }
-  d->f &= ~MP_UNDEF;
-  mp_shrink(d);
-  return (d);
-}
-
-/* --- @mp_storel2c@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets as two's
- *             complement.  The first byte in the array is the least
- *             significant.  If the array is too small to represent the
- *             number, high-order bits are truncated; if the array is too
- *             large, high order bytes are sign-extended.
- */
-
-void mp_storel2c(const mp *m, void *pv, size_t sz)
-{
-  if (MP_NEGP(m))
-    mpx_storel2cn(m->v, m->vl, pv, sz);
-  else
-    mpx_storel(m->v, m->vl, pv, sz);
-}
-
-/* --- @mp_loadb2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets as
- *             two's complement.  The last byte in the array is the least
- *             significant.
- */
-
-mp *mp_loadb2c(mp *d, const void *pv, size_t sz)
-{
-  const octet *ov = pv;
-  MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
-  if (!sz || !(ov[0] & 0x80)) {
-    mpx_loadb(d->v, d->vl, pv, sz);
-    d->f &= ~MP_NEG;
-  } else {
-    mpx_loadb2cn(d->v, d->vl, pv, sz);
-    d->f |= MP_NEG;
-  }
-  d->f &= ~MP_UNDEF;
-  mp_shrink(d);
-  return (d);
-}
-
-/* --- @mp_storeb2c@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets, as
- *             two's complement.  The last byte in the array is the least
- *             significant.  If the array is too small to represent the
- *             number, high-order bits are truncated; if the array is too
- *             large, high order bytes are sign-extended.
- */
-
-void mp_storeb2c(const mp *m, void *pv, size_t sz)
-{
-  if (MP_NEGP(m))
-    mpx_storeb2cn(m->v, m->vl, pv, sz);
-  else
-    mpx_storeb(m->v, m->vl, pv, sz);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-jacobi.c b/mp-jacobi.c
deleted file mode 100644 (file)
index 3674f22..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Compute Jacobi symbol
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_jacobi@ --- *
- *
- * Arguments:  @mp *a@ = an integer
- *             @mp *n@ = another integer
- *
- * Returns:    @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%.
- *
- * Use:                Computes the Kronecker symbol %$\jacobi{a}{n}$%.  If @n@ is
- *             prime, this is the Legendre symbol and is equal to 1 if and
- *             only if @a@ is a quadratic residue mod @n@.  The result is
- *             zero if and only if @a@ and @n@ have a common factor greater
- *             than one.
- *
- *             If @n@ is composite, then this computes the Kronecker symbol
- *
- *               %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$%
- *
- *             where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the
- *             prime factorization of %$n$%.  The missing bits are:
- *
- *               * %$\jacobi{a}{1} = 1$%;
- *               * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if
- *                 positive;
- *               * %$\jacobi{a}{0} = 0$%;
- *               * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is
- *                 congruent to 1 or 7 (mod 8), or %$-1$% otherwise.
- *
- *             If %$n$% is positive and odd, then this is the Jacobi
- *             symbol.  (The Kronecker symbol is a consistant domain
- *             extension; the Jacobi symbol was implemented first, and the
- *             name stuck.)
- */
-
-int mp_jacobi(mp *a, mp *n)
-{
-  int s = 1;
-  size_t p2;
-
-  /* --- Handle zero specially --- *
-   *
-   * I can't find any specific statement for what to do when %$n = 0$%; PARI
-   * opts to set %$\jacobi{\pm1}{0} = \pm 1$% and %$\jacobi{a}{0} = 0$% for
-   * other %$a$%.
-   */
-
-  if (MP_ZEROP(n)) {
-    if (MP_EQ(a, MP_ONE)) return (+1);
-    else if (MP_EQ(a, MP_MONE)) return (-1);
-    else return (0);
-  }
-
-  /* --- Deal with powers of two --- *
-   *
-   * This implicitly takes a copy of %$n$%.  Copy %$a$% at the same time to
-   * make cleanup easier.
-   */
-
-  MP_COPY(a);
-  n = mp_odd(MP_NEW, n, &p2);
-  if (p2) {
-    if (MP_EVENP(a)) {
-      s = 0;
-      goto done;
-    } else if ((p2 & 1) && ((a->v[0] & 7) == 3 || (a->v[0] & 7) == 5))
-      s = -s;
-  }
-
-  /* --- Deal with negative %$n$% --- */
-
-  if (MP_NEGP(n)) {
-    n = mp_neg(n, n);
-    if (MP_NEGP(a))
-      s = -s;
-  }
-
-  /* --- Check for unit %$n$% --- */
-
-  if (MP_EQ(n, MP_ONE))
-    goto done;
-
-  /* --- Reduce %$a$% modulo %$n$% --- */
-
-  if (MP_NEGP(a) || MP_CMP(a, >=, n))
-    mp_div(0, &a, a, n);
-
-  /* --- Main recursive mess, flattened out into something nice --- */
-
-  for (;;) {
-    mpw nn;
-    size_t e;
-
-    /* --- Some simple special cases --- */
-
-    MP_SHRINK(a);
-    if (MP_ZEROP(a)) {
-      s = 0;
-      goto done;
-    }
-
-    /* --- Main case with powers of two --- */
-
-    a = mp_odd(a, a, &e);
-    nn = n->v[0] & 7;
-    if ((e & 1) && (nn == 3 || nn == 5))
-      s = -s;
-    if (MP_LEN(a) == 1 && a->v[0] == 1)
-      goto done;
-    if ((nn & 3) == 3 && (a->v[0] & 3) == 3)
-      s = -s;
-
-    /* --- Reduce and swap --- */
-
-    mp_div(0, &n, n, a);
-    { mp *t = n; n = a; a = t; }
-  }
-
-  /* --- Wrap everything up --- */
-
-done:
-  MP_DROP(a);
-  MP_DROP(n);
-  return (s);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int verify(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  mp *n = *(mp **)v[1].buf;
-  int s = *(int *)v[2].buf;
-  int j = mp_jacobi(a, n);
-  int ok = 1;
-
-  if (s != j) {
-    fputs("\n*** fail", stderr);
-    fputs("a = ", stderr); mp_writefile(a, stderr, 10); fputc('\n', stderr);
-    fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr);
-    fprintf(stderr, "s = %i\n", s);
-    fprintf(stderr, "j = %i\n", j);
-    ok = 0;
-  }
-
-  mp_drop(a);
-  mp_drop(n);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "jacobi", verify, { &type_mp, &type_mp, &type_int, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mp");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-mem.c b/mp-mem.c
deleted file mode 100644 (file)
index fcb6c4d..0000000
--- a/mp-mem.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mp-mem.c,v 1.8 2004/04/08 16:17:32 mdw Exp $
- *
- * Memory management for multiprecision numbers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/sub.h>
-
-
-#include "mp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_new@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *             @unsigned f@ = flags to set
- *
- * Returns:    Pointer to a new MP structure.
- *
- * Use:                Allocates a new multiprecision integer.  The data space is
- *             allocated from either the standard global or secret arena,
- *             depending on the initial flags requested.
- */
-
-mp *mp_new(size_t sz, unsigned f)
-{
-  mp *m = CREATE(mp);
-  m->a = (f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL;
-  m->v = mpalloc(m->a, sz);
-  m->vl = m->v + sz;
-  m->sz = sz;
-  m->f = f & ~(MP_CONST | MP_DESTROYED);
-  m->ref = 1;
-  return (m);
-}
-
-/* --- @mp_create@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *
- * Returns:    Pointer to pristine new MP structure with enough memory
- *             bolted onto it.
- *
- * Use:                Creates a new multiprecision integer, initially zero.  The
- *             integer has a single reference.
- */
-
-mp *mp_create(size_t sz)
-{
-  mp *m = CREATE(mp);
-  m->v = mpalloc(MPARENA_GLOBAL, sz);
-  m->vl = m->v + sz;
-  m->sz = sz;
-  m->a = MPARENA_GLOBAL;
-  m->f = MP_UNDEF;
-  m->ref = 1;
-  return (m);
-}
-
-/* --- @mp_createsecure@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *
- * Returns:    Pointer to pristine new MP structure with enough memory
- *             bolted onto it.
- *
- * Use:                Creates a new multiprecision integer with indeterminate
- *             contents.  The integer has a single reference.  The integer's
- *             data space is allocated from the secure arena.  Its burn flag
- *             is set.
- */
-
-mp *mp_createsecure(size_t sz)
-{
-  mp *m = CREATE(mp);
-  m->v = mpalloc(MPARENA_SECURE, sz);
-  m->vl = m->v + sz;
-  m->sz = sz;
-  m->a = MPARENA_SECURE;
-  m->f = MP_UNDEF | MP_BURN;
-  m->ref = 1;
-  return (m);
-}
-
-/* --- @mp_build@ --- *
- *
- * Arguments:  @mp *m@ = pointer to an MP block to fill in
- *             @mpw *v@ = pointer to a word array
- *             @mpw *vl@ = pointer just past end of array
- *
- * Returns:    ---
- *
- * Use:                Creates a multiprecision integer representing some smallish
- *             number.  You must provide storage for the number and dispose
- *             of it when you've finished with it.  The number is marked as
- *             constant while it exists.
- */
-
-void mp_build(mp *m, mpw *v, mpw *vl)
-{
-  m->v = v;
-  m->vl = vl;
-  m->sz = vl - v;
-  m->a = MPARENA_GLOBAL;
-  m->f = MP_CONST;
-  m->ref = 1;
-}
-
-/* --- @mp_destroy@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Destroys a multiprecision integer. The reference count isn't
- *             checked.  Don't use this function if you don't know what
- *             you're doing: use @mp_drop@ instead.
- */
-
-void mp_destroy(mp *m)
-{
-  assert(((void)"Destroying a free integer", !(m->f & MP_DESTROYED)));
-  assert(((void)"Attempted to destroy a constant", !(m->f & MP_CONST)));
-  if (m->f & MP_BURN)
-    memset(m->v, 0, MPWS(m->sz));
-  mpfree(m->a, m->v);
-  m->f |= MP_DESTROYED;
-  DESTROY(m);
-}
-
-/* --- @mp_copy@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    A copy of the given multiprecision integer.
- *
- * Use:                Copies the given integer.  In fact you just get another
- *             reference to the same old one again.
- */
-
-mp *mp_copy(mp *m) { return MP_COPY(m); }
-
-/* --- @mp_drop@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Drops a reference to an integer which isn't wanted any more.
- *             If there are no more references, the integer is destroyed.
- */
-
-void mp_drop(mp *m) { if (m) MP_DROP(m); }
-
-/* --- @mp_split@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    A reference to the same integer, possibly with a different
- *             address.
- *
- * Use:                Splits off a modifiable version of the integer referred to.
- */
-
-mp *mp_split(mp *m) { MP_SPLIT(m); return (m); }
-
-/* --- @mp_resize@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *             @size_t sz@ = new size
- *
- * Returns:    ---
- *
- * Use:                Changes an integer's size.  The length and value are not
- *             changed.  It is an error to
- */
-
-void mp_resize(mp *m, size_t sz) { MP_RESIZE(m, sz); }
-
-/* --- @mp_ensure@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *             @size_t sz@ = required length
- *
- * Returns:    ---
- *
- * Use:                Changes an integer's length.  If there is not enough space
- *             allocated for the new length then the size is increased.  It
- */
-
-void mp_ensure(mp *m, size_t sz) { MP_ENSURE(m, sz); }
-
-/* --- @mp_dest@ --- *
- *
- * Arguments:  @mp *m@ = a suggested destination integer
- *             @size_t sz@ = size required for result, in digits
- *             @unsigned f@ = various flags
- *
- * Returns:    A pointer to an appropriate destination.
- *
- * Use:                Converts a suggested destination into a real destination with
- *             the required properties.  If the real destination is @d@,
- *             then the following properties will hold:
- *
- *               * @d@ will have exactly one reference.
- *
- *               * If @m@ is not @MP_NEW@, then the contents of @m@ will not
- *                 change, unless @f@ has the @MP_UNDEF@ flag set.
- *
- *               * If @m@ is not @MP_NEW@, then he reference count of @m@ on
- *                 entry is equal to the sum of the counts of @d@ and @m@ on
- *                 exit.
- *
- *               * The size of @d@ will be at least @sz@.
- *
- *               * If @f@ has the @MP_BURN@ flag set, then @d@ will be
- *                 allocated from @MPARENA_SECURE@.
- *
- *             Understanding this function is crucial to using Catacomb's
- *             multiprecision integer library effectively.
- */
-
-mp *mp_dest(mp *m, size_t sz, unsigned f)
-{
-  /* --- If no destination, make one --- */
-
-  if (m == MP_NEWSEC)
-    m = mp_new(sz, f | MP_UNDEF | MP_BURN);
-  else if (m == MP_NEW)
-    m = mp_new(sz, f | MP_UNDEF);
-  else {
-    size_t len = MP_LEN(m);
-    unsigned undef = (m->f | f) & MP_UNDEF;
-
-    /* --- If the value must be preserved, the block can't shrink --- */
-
-    if (!undef && sz < len)
-      sz = len;
-
-    /* --- Otherwise check whether the destination is suitable --- */
-
-    if (m->ref > 1 || (m->f & MP_CONST) ||
-       sz > m->sz || ((f & ~m->f) & MP_BURN)) {
-
-      /* --- No -- allocate a new buffer --- *
-       *
-       * The buffer must be secure if (a) the caller requested a secure
-       * buffer, or (b) the old buffer is secure and I'm not allowed to
-       * discard the old contents.
-       */
-
-      mparena *a;
-      mpw *v;
-
-      if ((f & MP_BURN) || (!undef && (m->f & MP_BURN)))
-       a = MPARENA_SECURE;
-      else
-       a = MPARENA_GLOBAL;
-      v = mpalloc(a, sz);
-
-      /* --- Copy the data over --- */
-
-      if (!undef) {
-       memcpy(v, m->v, MPWS(len));
-       if (sz - len > 0)
-         memset(v + len, 0, MPWS(sz - len));
-      }
-
-      /* --- If @m@ has other references, make a new node --- *
-       *
-       * Otherwise dispose of the old buffer.
-       */
-
-      if (!(m->f & MP_CONST) && m->ref == 1) {
-       if (m->f & MP_BURN)
-         memset(m->v, 0, MPWS(m->sz));
-       mpfree(m->a, m->v);
-      } else {
-       mp *mm = CREATE(mp);
-       mm->ref = 1;
-       mm->f = m->f;
-       m->ref--;
-       m = mm;
-      }
-
-      /* --- Fix up the node --- */
-
-      m->v = v;
-      m->vl = v + sz;
-      m->sz = sz;
-      m->f = ((m->f & ~(MP_CONST | MP_BURN)) |
-             (f & (MP_BURN | MP_UNDEF)));
-      m->a = a;
-    }
-
-    /* --- If the number is growing in its buffer, fix it up --- */
-
-    else if (sz > len) {
-      if (!undef)
-       memset(m->vl, 0, MPWS(sz - len));
-      m->vl = m->v + sz;
-    }
-  }
-
-  /* --- Done --- */
-
-  return (m);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-misc.c b/mp-misc.c
deleted file mode 100644 (file)
index 90bdc37..0000000
--- a/mp-misc.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mp-misc.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Miscellaneous multiprecision support functions
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-
-/*----- Basic manipulation ------------------------------------------------*/
-
-/* --- @mp_shrink@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Reduces the recorded length of an integer.  This doesn't
- *             reduce the amount of memory used, although it can improve
- *             performance a bit.  To reduce memory, use @mp_minimize@
- *             instead.  This can't change the value of an integer, and is
- *             therefore safe to use even when there are multiple
- *             references.
- */
-
-void mp_shrink(mp *m) { MP_SHRINK(m); }
-
-/* --- @mp_minimize@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Reduces the amount of memory an integer uses.  It's best to
- *             do this to numbers which aren't going to change in the
- *             future.
- */
-
-void mp_minimize(mp *m)
-{
-  MP_SHRINK(m);
-  MP_RESIZE(m, MP_LEN(m));
-}
-
-/*----- Bit scanning ------------------------------------------------------*/
-
-/* --- @mp_scan@ --- *
- *
- * Arguments:  @mpscan *sc@ = pointer to bitscanner block
- *             @const mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Initializes a bitscanner on a multiprecision integer.
- */
-
-void mp_scan(mpscan *sc, const mp *m) { MP_SCAN(sc, m); }
-
-/* --- @mp_scan@ --- *
- *
- * Arguments:  @mpscan *sc@ = pointer to bitscanner block
- *             @const mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Initializes a reverse bitscanner on a multiprecision
- *             integer.
- */
-
-void mp_rscan(mpscan *sc, const mp *m) { MP_RSCAN(sc, m); }
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-modexp.c b/mp-modexp.c
deleted file mode 100644 (file)
index ff2cbe0..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * General-purpose modular exponentiation
- *
- * (c) 2006 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpbarrett.h"
-#include "mpmont.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_modexp@ --- *
- *
- * Arguments:  @mp *d@ = fake destination
- *             @mp *x@ = base of exponentiation
- *             @mp *e@ = exponent
- *             @mp *n@ = modulus (must be positive)
- *
- * Returns:    The value %$x^e \bmod n$%.
- */
-
-mp *mp_modexp(mp *d, mp *x, mp *e, mp *n)
-{
-  if (MP_ODDP(n)) {
-    mpmont mm;
-    mpmont_create(&mm, n);
-    d = mpmont_exp(&mm, d, x, e);
-    mpmont_destroy(&mm);
-  } else {
-    mpbarrett mb;
-    mpbarrett_create(&mb, n);
-    d = mpbarrett_exp(&mb, d, x, e);
-    mpbarrett_destroy(&mb);
-  }
-  return (d);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int tmodexp(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  mp *b = *(mp **)v[1].buf;
-  mp *m = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *mr;
-  int ok = 1;
-
-  mr = mp_modexp(MP_NEW, a, b, m);
-
-  if (!MP_EQ(mr, r)) {
-    fputs("\n*** modexp failed", stderr);
-    fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\n e = ", stderr); mp_writefile(b, stderr, 10);
-    fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  MP_DROP(m);
-  MP_DROP(a);
-  MP_DROP(b);
-  MP_DROP(r);
-  MP_DROP(mr);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return ok;
-}
-
-static test_chunk tests[] = {
-  { "modexp", tmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mp");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-modsqrt.c b/mp-modsqrt.c
deleted file mode 100644 (file)
index 1791185..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mp-modsqrt.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Compute square roots modulo a prime
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "fibrand.h"
-#include "grand.h"
-#include "mp.h"
-#include "mpmont.h"
-#include "mprand.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_modsqrt@ --- *
- *
- * Arguments:  @mp *d@ = destination integer
- *             @mp *a@ = source integer
- *             @mp *p@ = modulus (must be prime)
- *
- * Returns:    If %$a$% is a quadratic residue, a square root of %$a$%; else
- *             a null pointer.
- *
- * Use:                Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%,
- *             if one exists; else a null pointer.  This function will not
- *             work if %$p$% is composite: you must factor the modulus, take
- *             a square root mod each factor, and recombine the results
- *             using the Chinese Remainder Theorem.
- *
- *             We guarantee that the square root returned is the smallest
- *             one (i.e., the `positive' square root).
- */
-
-mp *mp_modsqrt(mp *d, mp *a, mp *p)
-{
-  mpmont mm;
-  mp *t;
-  size_t s;
-  mp *b;
-  mp *ainv;
-  mp *c, *r;
-  size_t i, j;
-  mp *dd, *mone;
-
-  /* --- Cope if %$a \not\in Q_p$% --- */
-
-  if (mp_jacobi(a, p) != 1) {
-    mp_drop(d);
-    return (0);
-  }
-
-  /* --- Choose some quadratic non-residue --- */
-
-  {
-    grand *g = fibrand_create(0);
-
-    b = MP_NEW;
-    do
-      b = mprand_range(b, p, g, 0);
-    while (mp_jacobi(b, p) != -1);
-    g->ops->destroy(g);
-  }
-
-  /* --- Find the inverse of %$a$% --- */
-
-  ainv = mp_modinv(MP_NEW, a, p);
-
-  /* --- Split %$p - 1$% into a power of two and an odd number --- */
-
-  t = mp_sub(MP_NEW, p, MP_ONE);
-  t = mp_odd(t, t, &s);
-
-  /* --- Now to really get going --- */
-
-  mpmont_create(&mm, p);
-  b = mpmont_mul(&mm, b, b, mm.r2);
-  c = mpmont_expr(&mm, b, b, t);
-  t = mp_add(t, t, MP_ONE);
-  t = mp_lsr(t, t, 1);
-  dd = mpmont_mul(&mm, MP_NEW, a, mm.r2);
-  r = mpmont_expr(&mm, t, dd, t);
-  mp_drop(dd);
-  ainv = mpmont_mul(&mm, ainv, ainv, mm.r2);
-
-  mone = mp_sub(MP_NEW, p, mm.r);
-
-  dd = MP_NEW;
-
-  for (i = 1; i < s; i++) {
-
-    /* --- Compute %$d_0 = r^2a^{-1}$% --- */
-
-    dd = mp_sqr(dd, r);
-    dd = mpmont_reduce(&mm, dd, dd);
-    dd = mpmont_mul(&mm, dd, dd, ainv);
-
-    /* --- Now %$d = d_0^{2^{s - i - 1}}$% --- */
-
-    for (j = i; j < s - 1; j++) {
-      dd = mp_sqr(dd, dd);
-      dd = mpmont_reduce(&mm, dd, dd);
-    }
-
-    /* --- Fiddle at the end --- */
-
-    if (MP_EQ(dd, mone))
-      r = mpmont_mul(&mm, r, r, c);
-    c = mp_sqr(c, c);
-    c = mpmont_reduce(&mm, c, c);
-  }
-
-  /* --- Done, so tidy up --- *
-   *
-   * Canonify the answer.
-   */
-
-  d = mpmont_reduce(&mm, d, r);
-  r = mp_sub(r, p, d);
-  if (MP_CMP(r, <, d)) { mp *tt = r; r = d; d = tt; }
-  mp_drop(ainv);
-  mp_drop(r); mp_drop(c);
-  mp_drop(dd);
-  mp_drop(mone);
-  mpmont_destroy(&mm);
-
-  return (d);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int verify(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  mp *p = *(mp **)v[1].buf;
-  mp *rr = *(mp **)v[2].buf;
-  mp *r = mp_modsqrt(MP_NEW, a, p);
-  int ok = 0;
-
-  if (!r)
-    ok = 0;
-  else if (MP_EQ(r, rr))
-    ok = 1;
-
-  if (!ok) {
-    fputs("\n*** fail\n", stderr);
-    fputs("a  = ", stderr); mp_writefile(a, stderr, 10); fputc('\n', stderr);
-    fputs("p  = ", stderr); mp_writefile(p, stderr, 10); fputc('\n', stderr);
-    if (r) {
-      fputs("r = ", stderr);
-      mp_writefile(r, stderr, 10);
-      fputc('\n', stderr);
-    } else
-      fputs("r = <undef>\n", stderr);
-    fputs("rr = ", stderr); mp_writefile(rr, stderr, 10); fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(a);
-  mp_drop(p);
-  mp_drop(r);
-  mp_drop(rr);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "modsqrt", verify, { &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mp");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-sqrt.c b/mp-sqrt.c
deleted file mode 100644 (file)
index 1491021..0000000
--- a/mp-sqrt.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Compute integer square roots
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_sqrt@ --- *
- *
- * Arguments:  @mp *d@ = pointer to destination integer
- *             @mp *a@ = (nonnegative) integer to take square root of
- *
- * Returns:    The largest integer %$x$% such that %$x^2 \le a$%.
- *
- * Use:                Computes integer square roots.
- *
- *             The current implementation isn't very good: it uses the
- *             Newton-Raphson method to find an approximation to %$a$%.  If
- *             there's any demand for a better version, I'll write one.
- */
-
-mp *mp_sqrt(mp *d, mp *a)
-{
-  unsigned long z;
-  mp *q = MP_NEW, *r = MP_NEW;
-
-  /* --- Sanity preservation --- */
-
-  assert(!MP_NEGP(a));
-
-  /* --- Deal with trivial cases --- */
-
-  MP_SHRINK(a);
-  if (MP_ZEROP(a)) {
-    mp_drop(d);
-    return (MP_ZERO);
-  }
-
-  /* --- Find an initial guess of about the right size --- */
-
-  z = mp_bits(a);
-  z >>= 1;
-  mp_copy(a);
-  d = mp_lsr(d, a, z);
-
-  /* --- Main approximation --- *
-   *
-   * We use the Newton-Raphson recurrence relation
-   *
-   *   %$x_{i+1} = x_i - \frac{x_i^2 - a}{2 x_i}$%
-   *
-   * We inspect the term %$q = x^2 - a$% to see when to stop.  Increasing
-   * %$x$% is pointless when %$-q < 2 x + 1$%.
-   */
-
-  for (;;) {
-    q = mp_sqr(q, d);
-    q = mp_sub(q, q, a);
-    if (MP_ZEROP(q))
-      break;
-    if (MP_NEGP(q)) {
-      r = mp_lsl(r, d, 1);
-      r->f |= MP_NEG;
-      if (MP_CMP(q, >=, r))
-       break;
-    }
-    mp_div(&r, &q, q, d);
-    r = mp_lsr(r, r, 1);
-    if (r->v == r->vl)
-      d = mp_sub(d, d, MP_ONE);
-    else
-      d = mp_sub(d, d, r);
-  }
-
-  /* --- Finished, at last --- */
-
-  mp_drop(a);
-  mp_drop(q);
-  mp_drop(r);
-  return (d);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int verify(dstr *v)
-{
-  mp *a = *(mp **)v[0].buf;
-  mp *qq = *(mp **)v[1].buf;
-  mp *q = mp_sqrt(MP_NEW, a);
-  int ok = 1;
-
-  if (!MP_EQ(q, qq)) {
-    ok = 0;
-    fputs("\n*** sqrt failed", stderr);
-    fputs("\n*** a     = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\n*** result = ", stderr); mp_writefile(q, stderr, 10);
-    fputs("\n*** expect = ", stderr); mp_writefile(qq, stderr, 10);
-    fputc('\n', stderr);
-  }
-
-  mp_drop(a);
-  mp_drop(q);
-  mp_drop(qq);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "sqrt", verify, { &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } },
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mp");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp-test.c b/mp-test.c
deleted file mode 100644 (file)
index 55c9ae9..0000000
--- a/mp-test.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mp-test.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Testing functionality for multiprecision integers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/dstr.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-#include <mLib/testrig.h>
-
-#include "mp.h"
-#include "mptext.h"
-
-/*----- The `MP' testrig data type ----------------------------------------*/
-
-static void mp_cvt(const char *buf, dstr *d)
-{
-  mp *m;
-  DENSURE(d, sizeof(mp *));
-  m = mp_readstring(MP_NEW, (char *)buf, 0, 0);
-  if (!m)
-    die(1, "bad integer `%s'", buf);
-  *(mp **)d->buf = m;
-}
-
-static void mp_dump(dstr *d, FILE *fp)
-{
-  mp *m = *(mp **)d->buf;
-  mp_writefile(m, fp, 10);
-}
-
-const test_type type_mp = { mp_cvt, mp_dump };
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mp.h b/mp.h
deleted file mode 100644 (file)
index 13f97d1..0000000
--- a/mp.h
+++ /dev/null
@@ -1,1026 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Simple multiprecision arithmetic
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MP_H
-#define CATACOMB_MP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <string.h>
-
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_MPW_H
-#  include "mpw.h"
-#endif
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_MPARENA_H
-#  include "mparena.h"
-#endif
-
-#ifndef CATACOMB_MPX_H
-#  include "mpx.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- A multiprecision integer --- */
-
-typedef struct mp {
-  mpw *v, *vl;                         /* Vector of digits, current limit */
-  size_t sz;                           /* Size of digit buffer in words */
-  mparena *a;                          /* Arena for buffer allocation */
-  unsigned f;                          /* Flags (see below) */
-  unsigned ref;                                /* Reference counter */
-} mp;
-
-#define MP_NEG 1u                      /* Negative (signed magnitude) */
-#define MP_BURN 2u                     /* Secret (viral flag) */
-#define MP_CONST 4u                    /* Uses strange memory allocation */
-#define MP_UNDEF 8u                    /* Contains nothing interesting */
-#define MP_DESTROYED 16u               /* Has been destroyed */
-
-/* --- A factor for simultaneous exponentation --- *
- *
- * Used by the Montgomery and Barrett exponentiators.
- */
-
-typedef struct mp_expfactor {
-  mp *base;
-  mp *exp;
-} mp_expfactor;
-
-/*----- Useful constants --------------------------------------------------*/
-
-extern mp mp_const[];
-
-#define MP_ZERO         (&mp_const[0])
-#define MP_ONE  (&mp_const[1])
-#define MP_TWO  (&mp_const[2])
-#define MP_THREE (&mp_const[3])
-#define MP_FOUR         (&mp_const[4])
-#define MP_FIVE         (&mp_const[5])
-#define MP_TEN  (&mp_const[6])
-#define MP_256  (&mp_const[7])
-#define MP_MONE         (&mp_const[8])
-
-#define MP_NEW ((mp *)0)
-#define MP_NEWSEC (&mp_const[9])
-
-/*----- Trivial macros ----------------------------------------------------*/
-
-/* --- @MP_LEN@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    Length of the integer, in words.
- */
-
-#define MP_LEN(m) ((m)->vl - ((m)->v))
-
-/*----- Memory management and reference counting --------------------------*/
-
-/* --- @mp_new@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *             @unsigned f@ = flags to set
- *
- * Returns:    Pointer to a new MP structure.
- *
- * Use:                Allocates a new multiprecision integer.  The data space is
- *             allocated from either the standard global or secret arena,
- *             depending on the initial flags requested.
- */
-
-extern mp *mp_new(size_t /*sz*/, unsigned /*f*/);
-
-/* --- @mp_create@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *
- * Returns:    Pointer to pristine new MP structure with enough memory
- *             bolted onto it.
- *
- * Use:                Creates a new multiprecision integer with indeterminate
- *             contents.  The integer has a single reference.
- */
-
-extern mp *mp_create(size_t /*sz*/);
-
-/* --- @mp_createsecure@ --- *
- *
- * Arguments:  @size_t sz@ = size of vector required
- *
- * Returns:    Pointer to pristine new MP structure with enough memory
- *             bolted onto it.
- *
- * Use:                Creates a new multiprecision integer with indeterminate
- *             contents.  The integer has a single reference.  The integer's
- *             data space is allocated from the secure arena.  Its burn flag
- *             is set.
- */
-
-extern mp *mp_createsecure(size_t /*sz*/);
-
-/* --- @mp_build@ --- *
- *
- * Arguments:  @mp *m@ = pointer to an MP block to fill in
- *             @mpw *v@ = pointer to a word array
- *             @mpw *vl@ = pointer just past end of array
- *
- * Returns:    ---
- *
- * Use:                Creates a multiprecision integer representing some smallish
- *             number.  You must provide storage for the number and dispose
- *             of it when you've finished with it.  The number is marked as
- *             constant while it exists.
- */
-
-extern void mp_build(mp */*m*/, mpw */*v*/, mpw */*vl*/);
-
-/* --- @mp_destroy@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Destroys a multiprecision integer. The reference count isn't
- *             checked.  Don't use this function if you don't know what
- *             you're doing: use @mp_drop@ instead.
- */
-
-extern void mp_destroy(mp */*m*/);
-
-/* --- @mp_copy@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    A copy of the given multiprecision integer.
- *
- * Use:                Copies the given integer.  In fact you just get another
- *             reference to the same old one again.
- */
-
-extern mp *mp_copy(mp */*m*/);
-
-#define MP_COPY(m) ((m)->ref++, (m))
-
-/* --- @mp_drop@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Drops a reference to an integer which isn't wanted any more.
- *             If there are no more references, the integer is destroyed.
- */
-
-extern void mp_drop(mp */*m*/);
-
-#define MP_DROP(m) do {                                                        \
-  mp *_mm = (m);                                                       \
-  _mm->ref--;                                                          \
-  if (_mm->ref == 0 && !(_mm->f & MP_CONST))                           \
-    mp_destroy(_mm);                                                   \
-} while (0)
-
-/* --- @mp_split@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    A reference to the same integer, possibly with a different
- *             address.
- *
- * Use:                Splits off a modifiable version of the integer referred to.
- */
-
-extern mp *mp_split(mp */*m*/);
-
-#define MP_SPLIT(m) do {                                               \
-  mp *_m = (m);                                                                \
-  if ((_m->f & MP_CONST) || _m->ref > 1) {                             \
-    size_t _len = MP_LEN(_m);                                          \
-    mp *_mm = mp_new(_len, _m->f);                                     \
-    if (!(_m->f & MP_UNDEF))                                           \
-      memcpy(_mm->v, _m->v, MPWS(_len));                               \
-    _m->ref--;                                                         \
-    _m = _mm;                                                          \
-  }                                                                    \
-  (m) = _m;                                                            \
-} while (0)
-
-/* --- @mp_resize@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *             @size_t sz@ = new size
- *
- * Returns:    ---
- *
- * Use:                Resizes the vector containing the integer's digits.  The new
- *             size must be at least as large as the current integer's
- *             length.  This isn't really intended for client use.
- */
-
-extern void mp_resize(mp */*m*/, size_t /*sz*/);
-
-#define MP_RESIZE(m, ssz) do {                                         \
-  mp *_m = (m);                                                                \
-  size_t _sz = (ssz);                                                  \
-  mparena *_a = (_m->f & MP_BURN) ? MPARENA_SECURE : MPARENA_GLOBAL;   \
-  mpw *_v;                                                             \
-  size_t _len = MP_LEN(_m);                                            \
-  assert(((void)"can't make size less than length", _sz >= _len));     \
-  _v = mpalloc(_a, _sz);                                               \
-  if (!(_m->f & MP_UNDEF))                                             \
-    memcpy(_v, _m->v, MPWS(_len));                                     \
-  if (_m->f & MP_BURN)                                                 \
-    memset(_m->v, 0, MPWS(_m->sz));                                    \
-  mpfree(_m->a, _m->v);                                                        \
-  _m->a = _a;                                                          \
-  _m->v = _v;                                                          \
-  _m->vl = _v + _len;                                                  \
-} while (0)
-
-/* --- @mp_ensure@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *             @size_t sz@ = required size
- *
- * Returns:    ---
- *
- * Use:                Ensures that the integer has enough space for @sz@ digits.
- *             The value is not changed.
- */
-
-extern void mp_ensure(mp */*m*/, size_t /*sz*/);
-
-#define MP_ENSURE(m, ssz) do {                                         \
-  mp *_m = (m);                                                                \
-  size_t _ssz = (ssz);                                                 \
-  size_t _len = MP_LEN(_m);                                            \
-  if (_ssz >= _len) {                                                  \
-    if (_ssz > _m->sz)                                                 \
-      mp_resize(_m, _ssz);                                             \
-    if (!(_m->f & MP_UNDEF) && _ssz > _len)                            \
-      memset(_m->vl, 0, MPWS(_ssz - _len));                            \
-    _m->vl = _m->v + _ssz;                                             \
-  }                                                                    \
-} while (0)
-
-/* --- @mp_dest@ --- *
- *
- * Arguments:  @mp *m@ = a suggested destination integer
- *             @size_t sz@ = size required for result, in digits
- *             @unsigned f@ = various flags
- *
- * Returns:    A pointer to an appropriate destination.
- *
- * Use:                Converts a suggested destination into a real destination with
- *             the required properties.  If the real destination is @d@,
- *             then the following properties will hold:
- *
- *               * @d@ will have exactly one reference.
- *
- *               * If @m@ is not @MP_NEW@, then the contents of @m@ will not
- *                 change, unless @f@ has the @MP_UNDEF@ flag set.
- *
- *               * If @m@ is not @MP_NEW@, then he reference count of @m@ on
- *                 entry is equal to the sum of the counts of @d@ and @m@ on
- *                 exit.
- *
- *               * The size of @d@ will be at least @sz@.
- *
- *               * If @f@ has the @MP_BURN@ flag set, then @d@ will be
- *                 allocated from @MPARENA_SECURE@.
- *
- *             Understanding this function is crucial to using Catacomb's
- *             multiprecision integer library effectively.
- */
-
-extern mp *mp_dest(mp */*m*/, size_t /*sz*/, unsigned /*f*/);
-
-#define MP_DEST(m, ssz, f) do {                                                \
-  mp *_m = (m);                                                                \
-  size_t _ssz = (ssz);                                                 \
-  unsigned _f = (f);                                                   \
-  _m = mp_dest(_m, _ssz, _f);                                          \
-  (m) = _m;                                                            \
-} while (0)
-
-/*----- Size manipulation -------------------------------------------------*/
-
-/* --- @mp_shrink@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Reduces the recorded length of an integer.  This doesn't
- *             reduce the amount of memory used, although it can improve
- *             performance a bit.  To reduce memory, use @mp_minimize@
- *             instead.  This can't change the value of an integer, and is
- *             therefore safe to use even when there are multiple
- *             references.
- */
-
-extern void mp_shrink(mp */*m*/);
-
-#define MP_SHRINK(m) do {                                              \
-  mp *_mm = (m);                                                       \
-  MPX_SHRINK(_mm->v, _mm->vl);                                         \
-  if (MP_ZEROP(_mm))                                                   \
-    _mm->f &= ~MP_NEG;                                                 \
-} while (0)
-
-/* --- @mp_minimize@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Reduces the amount of memory an integer uses.  It's best to
- *             do this to numbers which aren't going to change in the
- *             future.
- */
-
-extern void mp_minimize(mp */*m*/);
-
-/*----- Bit scanning ------------------------------------------------------*/
-
-#ifndef CATACOMB_MPSCAN_H
-#  include "mpscan.h"
-#endif
-
-/* --- @mp_scan@ --- *
- *
- * Arguments:  @mpscan *sc@ = pointer to bitscanner block
- *             @const mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Initializes a bitscanner on a multiprecision integer.
- */
-
-extern void mp_scan(mpscan */*sc*/, const mp */*m*/);
-
-#define MP_SCAN(sc, m) do {                                            \
-  const mp *_mm = (m);                                                 \
-  mpscan *_sc = (sc);                                                  \
-  MPSCAN_INITX(_sc, _mm->v, _mm->vl);                                  \
-} while (0)
-
-/* --- @mp_rscan@ --- *
- *
- * Arguments:  @mpscan *sc@ = pointer to bitscanner block
- *             @const mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    ---
- *
- * Use:                Initializes a reverse bitscanner on a multiprecision
- *             integer.
- */
-
-extern void mp_rscan(mpscan */*sc*/, const mp */*m*/);
-
-#define MP_RSCAN(sc, m) do {                                           \
-  const mp *_mm = (m);                                                 \
-  mpscan *_sc = (sc);                                                  \
-  MPSCAN_RINITX(_sc, _mm->v, _mm->vl);                                 \
-} while (0)
-
-/* --- Other bitscanning aliases --- */
-
-#define mp_step mpscan_step
-#define mp_bit mpscan_bit
-#define mp_rstep mpscan_rstep
-#define mp_rbit mpscan_rbit
-
-#define MP_STEP MPSCAN_STEP
-#define MP_BIT MPSCAN_BIT
-#define MP_RSTEP MPSCAN_RSTEP
-#define MP_RBIT MPSCAN_RBIT
-
-/*----- Loading and storing -----------------------------------------------*/
-
-/* --- @mp_octets@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of octets required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer.
- */
-
-extern size_t mp_octets(const mp */*m*/);
-
-/* --- @mp_octets2c@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of octets required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer represented as two's complement.
- */
-
-extern size_t mp_octets2c(const mp */*m*/);
-
-/* --- @mp_bits@ --- *
- *
- * Arguments:  @const mp *m@ = a multiprecision integer
- *
- * Returns:    The number of bits required to represent @m@.
- *
- * Use:                Calculates the external storage required for a multiprecision
- *             integer.
- */
-
-extern unsigned long mp_bits(const mp */*m*/);
-
-/* --- @mp_loadl@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets.  The
- *             first byte in the array is the least significant.  More
- *             formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$%
- *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
- */
-
-extern mp *mp_loadl(mp */*d*/, const void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_storel@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets.  The
- *             first byte in the array is the least significant.  If the
- *             array is too small to represent the number, high-order bits
- *             are truncated; if the array is too large, high order bytes
- *             are filled with zeros.  More formally, if the number is
- *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
- *             then the array is %$b_0, b_1, \ldots, b_{n-1}$%.
- */
-
-extern void mp_storel(const mp */*m*/, void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_loadb@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets.  The
- *             last byte in the array is the least significant.  More
- *             formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$%
- *             then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
- */
-
-extern mp *mp_loadb(mp */*d*/, const void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_storeb@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets.  The
- *             last byte in the array is the least significant.  If the
- *             array is too small to represent the number, high-order bits
- *             are truncated; if the array is too large, high order bytes
- *             are filled with zeros.  More formally, if the number is
- *             %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
- *             then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%.
- */
-
-extern void mp_storeb(const mp */*m*/, void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_loadl2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets as
- *             two's complement.  The first byte in the array is the least
- *             significant.
- */
-
-extern mp *mp_loadl2c(mp */*d*/, const void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_storel2c@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets as two's
- *             complement.  The first byte in the array is the least
- *             significant.  If the array is too small to represent the
- *             number, high-order bits are truncated; if the array is too
- *             large, high order bytes are sign-extended.
- */
-
-extern void mp_storel2c(const mp */*m*/, void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_loadb2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @const void *pv@ = pointer to source data
- *             @size_t sz@ = size of the source data
- *
- * Returns:    Resulting multiprecision number.
- *
- * Use:                Loads a multiprecision number from an array of octets as
- *             two's complement.  The last byte in the array is the least
- *             significant.
- */
-
-extern mp *mp_loadb2c(mp */*d*/, const void */*pv*/, size_t /*sz*/);
-
-/* --- @mp_storeb2c@ --- *
- *
- * Arguments:  @const mp *m@ = source
- *             @void *pv@ = pointer to output array
- *             @size_t sz@ = size of the output array
- *
- * Returns:    ---
- *
- * Use:                Stores a multiprecision number in an array of octets, as
- *             two's complement.  The last byte in the array is the least
- *             significant.  If the array is too small to represent the
- *             number, high-order bits are truncated; if the array is too
- *             large, high order bytes are sign-extended.
- */
-
-extern void mp_storeb2c(const mp */*m*/, void */*pv*/, size_t /*sz*/);
-
-/*----- Bit operations ----------------------------------------------------*/
-
-/* --- @mp_not@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    The bitwise complement of the source.
- */
-
-extern mp *mp_not(mp */*d*/, mp */*a*/);
-
-/* --- @mp_bitop@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    The result of the given bitwise operation.  These functions
- *             don't handle negative numbers at all sensibly.  For that, use
- *             the @...2c@ variants.  The functions are named after the
- *             truth tables they generate:
- *
- *                     a:      0011
- *                     b:      0101
- *                     @mpx_bitXXXX@
- */
-
-#define MP_BITDECL(string)                                             \
-  extern mp *mp_bit##string(mp */*d*/, mp */*a*/, mp */*b*/);
-MPX_DOBIN(MP_BITDECL)
-
-/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- *
- *
- * Synonyms for the commonly-used functions.
- */
-
-#define mp_and mp_bit0001
-#define mp_or  mp_bit0111
-#define mp_nand mp_bit1110
-#define mp_nor mp_bit1000
-#define mp_xor mp_bit0110
-
-/* --- @mp_testbit@ --- *
- *
- * Arguments:  @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to test
- *
- * Returns:    Nonzero if the bit is set, zero if not.
- */
-
-extern int mp_testbit(mp */*x*/, unsigned long /*n*/);
-
-/* --- @mp_setbit@, @mp_clearbit@ --- *
- *
- * Arguments:  @mp *d@ = a destination
- *             @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to modify
- *
- * Returns:    The argument @x@, with the appropriate bit set or cleared.
- */
-
-extern mp *mp_setbit(mp */*d*/, mp */*x*/, unsigned long /*n*/);
-extern mp *mp_clearbit(mp */*d*/, mp */*x*/, unsigned long /*n*/);
-
-/* --- @mp_lsl@, @mp_lslc@, @mp_lsr@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *             @size_t n@ = number of bits to move
- *
- * Returns:    Result, @a@ shifted left or right by @n@.
- *
- * Use:                Bitwise shift operators.  @mp_lslc@ fills the bits introduced
- *             on the right with ones instead of zeroes: it's used
- *             internally by @mp_lsl2c@, though it may be useful on its
- *             own.
- */
-
-extern mp *mp_lsl(mp */*d*/, mp */*a*/, size_t /*n*/);
-extern mp *mp_lslc(mp */*d*/, mp */*a*/, size_t /*n*/);
-extern mp *mp_lsr(mp */*d*/, mp */*a*/, size_t /*n*/);
-
-/* --- @mp_not2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    The sign-extended complement of the argument.
- */
-
-extern mp *mp_not2c(mp */*d*/, mp */*a*/);
-
-/* --- @mp_bitop2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    The result of the given bitwise operation.  Negative numbers
- *             are treated as two's complement, sign-extended infinitely to
- *             the left.  The functions are named after the truth tables
- *             they generate:
- *
- *                     a:      0011
- *                     b:      0101
- *                     @mpx_bitXXXX@
- */
-
-#define MP_BIT2CDECL(string)                                           \
-  extern mp *mp_bit##string##2c(mp */*d*/, mp */*a*/, mp */*b*/);
-MPX_DOBIN(MP_BIT2CDECL)
-
-/* --- @mp_[n]and@, @mp_[n]or@, @mp_[n]xor@, @mp_not@ --- *
- *
- * Synonyms for the commonly-used functions.
- */
-
-#define mp_and2c  mp_bit00012c
-#define mp_or2c          mp_bit01112c
-#define mp_nand2c mp_bit11102c
-#define mp_nor2c  mp_bit10002c
-#define mp_xor2c  mp_bit01102c
-
-/* --- @mp_lsl2c@, @mp_lsr2c@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *             @size_t n@ = number of bits to move
- *
- * Returns:    Result, @a@ shifted left or right by @n@.  Handles the
- *             pretence of sign-extension for negative numbers.
- */
-
-extern mp *mp_lsl2c(mp */*d*/, mp */*a*/, size_t /*n*/);
-extern mp *mp_lsr2c(mp */*d*/, mp */*a*/, size_t /*n*/);
-
-/* --- @mp_testbit2c@ --- *
- *
- * Arguments:  @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to test
- *
- * Returns:    Nonzero if the bit is set, zero if not.  Fakes up two's
- *             complement representation.
- */
-
-extern int mp_testbit2c(mp */*x*/, unsigned long /*n*/);
-
-/* --- @mp_setbit2c@, @mp_clearbit2c@ --- *
- *
- * Arguments:  @mp *d@ = a destination
- *             @mp *x@ = a large integer
- *             @unsigned long n@ = which bit to modify
- *
- * Returns:    The argument @x@, with the appropriate bit set or cleared.
- *             Fakes up two's complement representation.
- */
-
-extern mp *mp_setbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/);
-extern mp *mp_clearbit2c(mp */*d*/, mp */*x*/, unsigned long /*n*/);
-
-/*----- Comparisons -------------------------------------------------------*/
-
-/* --- @mp_eq@ --- *
- *
- * Arguments:  @const mp *a, *b@ = two numbers
- *
- * Returns:    Nonzero if the numbers are equal.
- */
-
-extern int mp_eq(const mp */*a*/, const mp */*b*/);
-
-#define MP_EQ(a, b)                                                    \
-  ((((a)->f ^ (b)->f) & MP_NEG) == 0 &&                                        \
-   mpx_ueq((a)->v, (a)->vl, (b)->v, (b)->vl))
-
-/* --- @mp_cmp@ --- *
- *
- * Arguments:  @const mp *a, *b@ = two numbers
- *
- * Returns:    Less than, equal to or greater than zero, according to
- *             whether @a@ is less than, equal to or greater than @b@.
- */
-
-extern int mp_cmp(const mp */*a*/, const mp */*b*/);
-
-#define MP_CMP(a, op, b) (mp_cmp((a), (b)) op 0)
-
-/* --- Other handy macros --- */
-
-#define MP_NEGP(x) ((x)->f & MP_NEG)
-#define MP_ZEROP(x) (!MP_LEN(x))
-#define MP_POSP(x) (!MP_NEGP(x) && !MP_ZEROP(x))
-#define MP_ODDP(x) (!MP_ZEROP(x) && ((x)->v[0] & 1u))
-#define MP_EVENP(x) (!MP_ODDP(x))
-
-/*----- Arithmetic operations ---------------------------------------------*/
-
-/* --- @mp_neg@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = argument
- *
- * Returns:    The negation of the argument.
- *
- * Use:                Negates its argument.
- */
-
-extern mp *mp_neg(mp */*d*/, mp */*a*/);
-
-/* --- @mp_add@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ added to @b@.
- */
-
-extern mp *mp_add(mp */*d*/, mp */*a*/, mp */*b*/);
-
-/* --- @mp_sub@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @b@ subtracted from @a@.
- */
-
-extern mp *mp_sub(mp */*d*/, mp */*a*/, mp */*b*/);
-
-/* --- @mp_mul@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a, *b@ = sources
- *
- * Returns:    Result, @a@ multiplied by @b@.
- */
-
-extern mp *mp_mul(mp */*d*/, mp */*a*/, mp */*b*/);
-
-/* --- @mp_sqr@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *a@ = source
- *
- * Returns:    Result, @a@ squared.
- */
-
-extern mp *mp_sqr(mp */*d*/, mp */*a*/);
-
-/* --- @mp_div@ --- *
- *
- * Arguments:  @mp **qq, **rr@ = destination, quotient and remainder
- *             @mp *a, *b@ = sources
- *
- * Use:                Calculates the quotient and remainder when @a@ is divided by
- *             @b@.
- */
-
-extern void mp_div(mp **/*qq*/, mp **/*rr*/, mp */*a*/, mp */*b*/);
-
-/* --- @mp_exp@ --- *
- *
- * Arguments:  @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e$%.
- */
-
-extern mp *mp_exp(mp */*d*/, mp */*a*/, mp */*e*/);
-
-/* --- @mp_odd@ --- *
- *
- * Arguments:  @mp *d@ = pointer to destination integer
- *             @mp *m@ = pointer to source integer
- *             @size_t *s@ = where to store the power of 2
- *
- * Returns:    An odd integer integer %$t$% such that %$m = 2^s t$%.
- *
- * Use:                Computes a power of two and an odd integer which, when
- *             multiplied, give a specified result.  This sort of thing is
- *             useful in number theory quite often.
- */
-
-extern mp *mp_odd(mp */*d*/, mp */*m*/, size_t */*s*/);
-
-/*----- More advanced algorithms ------------------------------------------*/
-
-/* --- @mp_sqrt@ --- *
- *
- * Arguments:  @mp *d@ = pointer to destination integer
- *             @mp *a@ = (nonnegative) integer to take square root of
- *
- * Returns:    The largest integer %$x$% such that %$x^2 \le a$%.
- *
- * Use:                Computes integer square roots.
- *
- *             The current implementation isn't very good: it uses the
- *             Newton-Raphson method to find an approximation to %$a$%.  If
- *             there's any demand for a better version, I'll write one.
- */
-
-extern mp *mp_sqrt(mp */*d*/, mp */*a*/);
-
-/* --- @mp_gcd@ --- *
- *
- * Arguments:  @mp **gcd, **xx, **yy@ = where to write the results
- *             @mp *a, *b@ = sources (must be nonzero)
- *
- * Returns:    ---
- *
- * Use:                Calculates @gcd(a, b)@, and two numbers @x@ and @y@ such that
- *             @ax + by = gcd(a, b)@.  This is useful for computing modular
- *             inverses.  Neither @a@ nor @b@ may be zero.
- */
-
-extern void mp_gcd(mp **/*gcd*/, mp **/*xx*/, mp **/*yy*/,
-                  mp */*a*/, mp */*b*/);
-
-/* -- @mp_modinv@ --- *
- *
- * Arguments:  @mp *d@ = destination
- *             @mp *x@ = argument
- *             @mp *p@ = modulus
- *
- * Returns:    The inverse %$x^{-1} \bmod p$%.
- *
- * Use:                Computes a modular inverse.    An assertion fails if %$p$%
- *             has no inverse.
- */
-
-extern mp *mp_modinv(mp */*d*/, mp */*x*/, mp */*p*/);
-
-/* --- @mp_jacobi@ --- *
- *
- * Arguments:  @mp *a@ = an integer
- *             @mp *n@ = another integer
- *
- * Returns:    @-1@, @0@ or @1@ -- the Jacobi symbol %$J(a, n)$%.
- *
- * Use:                Computes the Kronecker symbol %$\jacobi{a}{n}$%.  If @n@ is
- *             prime, this is the Legendre symbol and is equal to 1 if and
- *             only if @a@ is a quadratic residue mod @n@.  The result is
- *             zero if and only if @a@ and @n@ have a common factor greater
- *             than one.
- *
- *             If @n@ is composite, then this computes the Kronecker symbol
- *
- *               %$\jacobi{a}{n}=\jacobi{a}{u}\prod_i\jacobi{a}{p_i}^{e_i}$%
- *
- *             where %$n = u p_0^{e_0} \ldots p_{n-1}^{e_{n-1}}$% is the
- *             prime factorization of %$n$%.  The missing bits are:
- *
- *               * %$\jacobi{a}{1} = 1$%;
- *               * %$\jacobi{a}{-1} = 1$% if @a@ is negative, or 1 if
- *                 positive;
- *               * %$\jacobi{a}{0} = 0$%;
- *               * %$\jacobi{a}{2}$ is 0 if @a@ is even, 1 if @a@ is
- *                 congruent to 1 or 7 (mod 8), or %$-1$% otherwise.
- *
- *             If %$n$% is positive and odd, then this is the Jacobi
- *             symbol.  (The Kronecker symbol is a consistant domain
- *             extension; the Jacobi symbol was implemented first, and the
- *             name stuck.)
- */
-
-extern int mp_jacobi(mp */*a*/, mp */*n*/);
-
-/* --- @mp_modsqrt@ --- *
- *
- * Arguments:  @mp *d@ = destination integer
- *             @mp *a@ = source integer
- *             @mp *p@ = modulus (must be prime)
- *
- * Returns:    If %$a$% is a quadratic residue, a square root of %$a$%; else
- *             a null pointer.
- *
- * Use:                Returns an integer %$x$% such that %$x^2 \equiv a \pmod{p}$%,
- *             if one exists; else a null pointer.  This function will not
- *             work if %$p$% is composite: you must factor the modulus, take
- *             a square root mod each factor, and recombine the results
- *             using the Chinese Remainder Theorem.
- *
- *             We guarantee that the square root returned is the smallest
- *             one (i.e., the `positive' square root).
- */
-
-extern mp *mp_modsqrt(mp */*d*/, mp */*a*/, mp */*p*/);
-
-/* --- @mp_modexp@ --- *
- *
- * Arguments:  @mp *d@ = fake destination
- *             @mp *x@ = base of exponentiation
- *             @mp *e@ = exponent
- *             @mp *n@ = modulus (must be positive)
- *
- * Returns:    The value %$x^e \bmod n$%.
- */
-
-extern mp *mp_modexp(mp */*d*/, mp */*x*/, mp */*e*/, mp */*n*/);
-
-/*----- Test harness support ----------------------------------------------*/
-
-#include <mLib/testrig.h>
-
-#ifndef CATACOMB_MPTEXT_H
-#  include "mptext.h"
-#endif
-
-extern const test_type type_mp;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mparena.c b/mparena.c
deleted file mode 100644 (file)
index c726912..0000000
--- a/mparena.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Allocation and freeing of MP buffers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/arena.h>
-#include <mLib/exc.h>
-#include <mLib/sub.h>
-
-#include "mparena.h"
-
-/*----- Tweakables --------------------------------------------------------*/
-
-/* --- @MPARENA_TRIVIAL@ --- *
- *
- * Make the allocator a passthrough.  It immediately calls the underlying
- * allocation functions rather than attempting to keep track of blocks
- * itself.
- */
-
-#define MPARENA_TRIVIAL
-
-/* --- @MPARENA_DEBUG@ --- *
- *
- * The name of an output trace file to which logging information about the
- * state of arena trees should be written.  If unset, no logging is done.
- */
-
-/* #define MPARENA_DEBUG "mparena.out" */
-
-/*----- Static variables --------------------------------------------------*/
-
-#ifdef MPARENA_DEBUG
-  static FILE *debugfp = 0;
-
-#  define MPARENA_OPENFILE do {                                                \
-    if (!debugfp) {                                                    \
-      if ((debugfp = fopen(MPARENA_DEBUG, "w")) == 0) {                        \
-       fprintf(stderr, "couldn't open debug output file\n");           \
-       exit(EXIT_FAILURE);                                             \
-      }                                                                        \
-    }                                                                  \
-  } while (0)
-
-#endif
-
-/*----- Standard arenas ---------------------------------------------------*/
-
-mparena mparena_global = MPARENA_INIT;
-mparena mparena_secure = MPARENA_INIT;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @tdump@ --- *
- *
- * Arguments:  @mparena_node *n@ = pointer to tree node to dump
- *
- * Returns:    ---
- *
- * Use:                Recursively dumps out the allocation tree.
- */
-
-#ifdef MPARENA_DEBUG
-
-static void tdump(mparena_node *n)
-{
-  if (!n)
-    putc('*', debugfp);
-  else {
-    putc('(', debugfp);
-    tdump(n->left);
-    fprintf(debugfp, ", %u, ", n->v[0]);
-    tdump(n->right);
-    putc(')', debugfp);
-  }
-}
-
-#endif
-
-/* --- @mparena_create@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *
- * Returns:    ---
- *
- * Use:                Initializes an MP arena so that blocks can be allocated from
- *             it.
- */
-
-void mparena_create(mparena *a)
-{
-  a->root = 0;
-  a->n = 0;
-  a->a = &arena_stdlib;
-}
-
-/* --- @mparena_setarena@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to MP arena block
- *             @arena *aa@ = pointer to arena
- *
- * Returns:    ---
- *
- * Use:                Sets the underlying arena for an MP arena.
- */
-
-extern void mparena_setarena(mparena *a, arena *aa) { a->a = aa; }
-
-/* --- @mparena_destroy@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *
- * Returns:    ---
- *
- * Use:                Frees an MP arena, and all the vectors held within it.  The
- *             blocks which are currently allocated can be freed into some
- *             other arena.
- */
-
-static void tfree(mparena *a, mparena_node *n)
-{
-  A_FREE(a->a, n->v);
-  if (n->left)
-    tfree(a, n->left);
-  if (n->right)
-    tfree(a, n->right);
-  DESTROY(n);
-}
-
-void mparena_destroy(mparena *a)
-{
-  tfree(a, a->root);
-  a->root = 0;
-}
-
-/* --- @mparena_count@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *
- * Returns:    Number of allocated blocks from this arena.
- *
- * Use:                Reports the number of blocks allocated from the arena and not
- *             yet freed.
- */
-
-unsigned mparena_count(mparena *a)
-{
-  return (a->n);
-}
-
-/* --- @mpalloc@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *             @size_t sz@ = number of digits required
- *
- * Returns:    Pointer to a suitably sized block.
- *
- * Use:                Allocates a lump of data suitable for use as an array of MP
- *             digits.
- */
-
-#ifdef MPARENA_TRIVIAL
-
-mpw *mpalloc(mparena *a, size_t sz)
-{
-  mpw *v;
-  if (!sz) return (0);
-  a->n++;
-  v = A_ALLOC(a->a, MPWS(sz));
-  if (!v)
-    THROW(EXC_NOMEM);
-  return (v);
-}
-
-#else
-
-mpw *mpalloc(mparena *a, size_t sz)
-{
-  mparena_node **nn, *n;
-  mpw *v;
-
-  nn = &a->root;
-
-#ifdef MPARENA_DEBUG
-  MPARENA_OPENFILE;
-  fprintf(debugfp, "alloc %u\n before: ", sz);
-  tdump(a->root); putc('\n', debugfp);
-#endif
-
-  /* --- First, find a block which is big enough --- */
-
-again:
-  n = *nn;
-  if (!n) {
-#ifdef MPARENA_DEBUG
-    fputs("  failed\n", debugfp);
-#endif
-    if ((v = A_ALLOC(a->a, MPWS(sz + 1))) == 0)
-      THROW(EXC_NOMEM);
-    v[0] = sz;
-    a->n++;
-    return (v + 1);
-  }
-  if (n->v[0] < sz) {
-    nn = &n->right;
-    goto again;
-  }
-
-  /* --- Now try to find a smaller block which is suitable --- */
-
-  while (n->left && n->left->v[0] >= sz) {
-    nn = &n->left;
-    n = *nn;
-  }
-
-  /* --- If the block we've got is still too large, start digging --- */
-
-  if (n->v[0] > sz * 2) {
-    nn = &n->left;
-    goto again;
-  }
-
-  /* --- I've now found a suitable block --- */
-
-  v = n->v;
-
-  /* --- Remove this node from the tree --- */
-
-  if (!n->left)
-    *nn = n->right;
-  else if (!n->right)
-    *nn = n->left;
-  else {
-    mparena_node *left = n->left;
-    mparena_node *p = *nn = n->right;
-    while (p->left)
-      p = p->left;
-    p->left = left;
-  }
-
-#ifdef MPARENA_DEBUG
-  fputs("  after: ", debugfp);
-  tdump(a->root); putc('\n', debugfp);
-#endif
-
-  /* --- Get rid of this node now --- */
-
-  DESTROY(n);
-  a->n++;
-  return (v + 1);
-}
-
-#endif
-
-/* --- @mpfree@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *             @mpw *v@ = pointer to allocated vector
- *
- * Returns:    ---
- *
- * Use:                Returns an MP vector to an arena.
- */
-
-#ifdef MPARENA_TRIVIAL
-
-void mpfree(mparena *a, mpw *v)
-{
-  if (!v) return;
-  a->n--;
-  A_FREE(a->a, v);
-}
-
-#else
-
-void mpfree(mparena *a, mpw *v)
-{
-  mparena_node **nn, *n;
-  size_t sz = *--v;
-
-#ifdef MPARENA_DEBUG
-  MPARENA_OPENFILE;
-  fprintf(debugfp, "free %u\n  before: ", sz);
-  tdump(a->root); putc('\n', debugfp);
-#endif
-
-  nn = &a->root;
-  while (*nn) {
-    n = *nn;
-    if (n->v[0] > sz)
-      nn = &n->left;
-    else
-      nn = &n->right;
-  }
-
-  n = CREATE(mparena_node);
-  n->left = n->right = 0;
-  n->v = v;
-  *nn = n;
-  a->n--;
-
-#ifdef MPARENA_DEBUG
-  fputs("  after: ", debugfp);
-  tdump(a->root); putc('\n', debugfp);
-#endif
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mparena.h b/mparena.h
deleted file mode 100644 (file)
index 94b69ad..0000000
--- a/mparena.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mparena.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Allocation and freeing of MP buffers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPARENA_H
-#define CATACOMB_MPARENA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/arena.h>
-
-#ifndef CATACOMB_MPW_H
-#  include "mpw.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- @mparena_node@ --- *
- *
- * For internal use by the MP arena manager.  The free blocks are held in a
- * binary tree by size, held in the first digit of each vector.
- */
-
-typedef struct mparena_node {
-  struct mparena_node *left, *right;
-  mpw *v;
-} mparena_node;
-
-/* --- @mparena@ --- *
- *
- * The actual arena.
- */
-
-typedef struct mparena {
-  mparena_node *root;
-  unsigned n;
-  arena *a;
-} mparena;
-
-/*----- Standard arenas ---------------------------------------------------*/
-
-extern mparena mparena_global;
-#define MPARENA_GLOBAL (&mparena_global)
-
-extern mparena mparena_secure;
-#define MPARENA_SECURE (&mparena_secure)
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mparena_create@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *
- * Returns:    ---
- *
- * Use:                Initializes an MP arena so that blocks can be allocated from
- *             it.
- */
-
-extern void mparena_create(mparena */*a*/);
-
-#define MPARENA_INIT { 0, 0, &arena_stdlib }
-
-/* --- @mparena_setarena@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to MP arena block
- *             @arena *aa@ = pointer to arena
- *
- * Returns:    ---
- *
- * Use:                Sets the underlying arena for an MP arena.
- */
-
-extern void mparena_setarena(mparena */*a*/, arena */*aa*/);
-
-/* --- @mparena_destroy@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *
- * Returns:    ---
- *
- * Use:                Frees an MP arena, and all the vectors held within it.  The
- *             blocks which are currently allocated can be freed into some
- *             other MP arena, as long as the underlying arenas are the
- *             same.
- */
-
-extern void mparena_destroy(mparena */*a*/);
-
-/* --- @mparena_count@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *
- * Returns:    Number of allocated blocks from this arena.
- *
- * Use:                Reports the number of blocks allocated from the arena and not
- *             yet freed.
- */
-
-extern unsigned mparena_count(mparena */*a*/);
-
-/* --- @mpalloc@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *             @size_t sz@ = number of digits required
- *
- * Returns:    Pointer to a suitably sized block.
- *
- * Use:                Allocates a lump of data suitable for use as an array of MP
- *             digits.
- */
-
-extern mpw *mpalloc(mparena */*a*/, size_t /*sz*/);
-
-/* --- @mpfree@ --- *
- *
- * Arguments:  @mparena *a@ = pointer to arena block
- *             @mpw *v@ = pointer to allocated vector
- *
- * Returns:    ---
- *
- * Use:                Returns an MP vector to an arena.
- */
-
-extern void mpfree(mparena */*a*/, mpw */*v*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpbarrett-exp.c b/mpbarrett-exp.c
deleted file mode 100644 (file)
index ef8fa59..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Modular exponentiation using Barrett reduction
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpbarrett.h"
-#include "mpbarrett-exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpbarrett_exp@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e \bmod m$%.
- */
-
-mp *mpbarrett_exp(mpbarrett *mb, mp *d, mp *a, mp *e)
-{
-  mp *x = MP_ONE;
-  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
-
-  MP_COPY(a);
-  MP_SHRINK(e);
-  if (MP_ZEROP(e))
-    ;
-  else {
-    if (MP_NEGP(e))
-      a = mp_modinv(a, a, mb->m);
-    if (MP_LEN(e) < EXP_THRESH)
-      EXP_SIMPLE(x, a, e);
-    else
-      EXP_WINDOW(x, a, e);
-  }
-  mp_drop(d);
-  mp_drop(spare);
-  mp_drop(a);
-  return (x);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int vexp(dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  mp *a = *(mp **)v[1].buf;
-  mp *b = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *mr;
-  int ok = 1;
-
-  mpbarrett mb;
-  mpbarrett_create(&mb, m);
-
-  mr = mpbarrett_exp(&mb, MP_NEW, a, b);
-
-  if (!MP_EQ(mr, r)) {
-    fputs("\n*** barrett modexp failed", stderr);
-    fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\n e = ", stderr); mp_writefile(b, stderr, 10);
-    fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(m);
-  mp_drop(a);
-  mp_drop(b);
-  mp_drop(r);
-  mp_drop(mr);
-  mpbarrett_destroy(&mb);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return ok;
-}
-
-static test_chunk tests[] = {
-  { "mpbarrett-exp", vexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mpbarrett");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpbarrett-exp.h b/mpbarrett-exp.h
deleted file mode 100644 (file)
index ee5043d..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpbarrett-exp.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Exponentiation operations for Barrett reduction
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_MPBARRETT_EXP_H
-#define CATACOMB_MPBARRETT_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentation definitions -----------------------------------------*/
-
-#define EXP_TYPE mp *
-
-#define EXP_COPY(d, x) d = MP_COPY(x)
-#define EXP_DROP(x) MP_DROP(x)
-
-#define EXP_MUL(a, x) do {                                             \
-  mp *t = mp_mul(spare, a, x);                                         \
-  spare = a;                                                           \
-  a = mpbarrett_reduce(mb, t, t);                                      \
-} while (0)
-
-#define EXP_SQR(a) do {                                                        \
-  mp *t = mp_sqr(spare, a);                                            \
-  spare = a;                                                           \
-  a = mpbarrett_reduce(mb, t, t);                                      \
-} while (0)
-
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) do {                                       \
-  d = mp_mul(MP_NEW, x, y);                                            \
-  d = mpbarrett_reduce(mb, d, d);                                      \
-} while (0)
-
-#define EXP_SETSQR(d, x) do {                                          \
-  d = mp_sqr(MP_NEW, x);                                               \
-  d = mpbarrett_reduce(mb, d, d);                                      \
-} while (0)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpbarrett-mexp.c b/mpbarrett-mexp.c
deleted file mode 100644 (file)
index 2cfda96..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Multiple simultaneous exponentiations
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpbarrett.h"
-
-#define EXP_WINSZ 3
-#include "mpbarrett-exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpbarrett_mexp@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *             @mp *d@ = fake destination
- *             @const mp_expfactor *f@ = pointer to array of factors
- *             @size_t n@ = number of factors supplied
- *
- * Returns:    If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the
- *             exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result
- *             is:
- *
- *             %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$%
- */
-
-mp *mpbarrett_mexp(mpbarrett *mb, mp *d, const mp_expfactor *f, size_t n)
-{
-  mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor));
-  mp *a = MP_ONE;
-  mp *spare;
-  mp *g = MP_NEW;
-  size_t i;
-
-  spare = MP_NEW;
-  for (i = 0; i < n; i++) {
-    if (f[i].exp->f & MP_BURN)
-      spare = MP_NEWSEC;
-    if (MP_NEGP(f[i].exp))
-      ff[i].base = mp_modinv(MP_NEW, f[i].base, mb->m);
-    else
-      ff[i].base = MP_COPY(f[i].base);
-    ff[i].exp = f[i].exp;
-  }
-  mp_drop(g);
-  EXP_SIMUL(a, ff, n);
-  mp_drop(d);
-  mp_drop(spare);
-  for (i = 0; i < n; i++)
-    mp_drop(ff[i].base);
-  xfree(ff);
-  return (a);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int verify(size_t n, dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  mp_expfactor *f = xmalloc(n * sizeof(*f));
-  mp *r, *rr;
-  size_t i, j;
-  mpbarrett mb;
-  int ok = 1;
-
-  j = 1;
-  for (i = 0; i < n; i++) {
-    f[i].base = *(mp **)v[j++].buf;
-    f[i].exp = *(mp **)v[j++].buf;
-  }
-
-  rr = *(mp **)v[j].buf;
-  mpbarrett_create(&mb, m);
-  r = mpbarrett_mexp(&mb, MP_NEW, f, n);
-  if (!MP_EQ(r, rr)) {
-    fputs("\n*** mexp failed\n", stderr);
-    fputs("m = ", stderr); mp_writefile(m, stderr, 10);
-    for (i = 0; i < n; i++) {
-      fprintf(stderr, "\ng_%u = ", i);
-      mp_writefile(f[i].base, stderr, 10);
-      fprintf(stderr, "\ne_%u = ", i);
-      mp_writefile(f[i].exp, stderr, 10);
-    }
-    fputs("\nr = ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\nR = ", stderr); mp_writefile(rr, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  for (i = 0; i < n; i++) {
-    MP_DROP(f[i].base);
-    MP_DROP(f[i].exp);
-  }
-  MP_DROP(m);
-  MP_DROP(r);
-  MP_DROP(rr);
-  mpbarrett_destroy(&mb);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int t1(dstr *v) { return verify(1, v); }
-static int t2(dstr *v) { return verify(2, v); }
-static int t3(dstr *v) { return verify(3, v); }
-static int t4(dstr *v) { return verify(4, v); }
-static int t5(dstr *v) { return verify(5, v); }
-
-static test_chunk tests[] = {
-  { "mexp-1", t1, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "mexp-2", t2, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "mexp-3", t3, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "mexp-4", t4, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "mexp-5", t5, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mpbarrett");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpbarrett.c b/mpbarrett.c
deleted file mode 100644 (file)
index 13210b3..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Barrett modular reduction
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpbarrett.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpbarrett_create@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *             @mp *m@ = modulus to work to
- *
- *
- * Returns:    Zero on success, nonzero on error.
- *
- * Use:                Initializes a Barrett reduction context ready for use.
- */
-
-int mpbarrett_create(mpbarrett *mb, mp *m)
-{
-  mp *b;
-
-  /* --- Validate the arguments --- */
-
-  if (!MP_POSP(m))
-    return (-1);
-
-  /* --- Compute %$\mu$% --- */
-
-  mp_shrink(m);
-  mb->k = MP_LEN(m);
-  mb->m = MP_COPY(m);
-  b = mp_new(2 * mb->k + 1, 0);
-  MPX_ZERO(b->v, b->vl - 1);
-  b->vl[-1] = 1;
-  mp_div(&b, 0, b, m);
-  mb->mu = b;
-  return (0);
-}
-
-/* --- @mpbarrett_destroy@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *
- * Returns:    ---
- *
- * Use:                Destroys a Barrett reduction context releasing any resources
- *             claimed.
- */
-
-void mpbarrett_destroy(mpbarrett *mb)
-{
-  mp_drop(mb->m);
-  mp_drop(mb->mu);
-}
-
-/* --- @mpbarrett_reduce@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *             @mp *d@ = destination for result
- *             @mp *m@ = number to reduce
- *
- * Returns:    The residue of @m@ modulo the number in the reduction
- *             context.
- *
- * Use:                Performs an efficient modular reduction.
- */
-
-mp *mpbarrett_reduce(mpbarrett *mb, mp *d, mp *m)
-{
-  mp *q;
-  size_t k = mb->k;
-
-  /* --- Special case if @m@ is too small --- */
-
-  if (MP_LEN(m) < k) {
-    m = MP_COPY(m);
-    if (d)
-      MP_DROP(d);
-    return (m);
-  }
-
-  /* --- First stage --- */
-
-  {
-    mp qq;
-    mp_build(&qq, m->v + (k - 1), m->vl);
-    q = mp_mul(MP_NEW, &qq, mb->mu);
-    if (MP_LEN(q) <= k) {
-      m = MP_COPY(m);
-      if (d)
-       MP_DROP(d);
-      MP_DROP(q);
-      return (m);
-    }
-  }
-
-  /* --- Second stage --- */
-
-  {
-    mp *r;
-    mpw *mvl;
-
-    MP_COPY(m);
-    if (MP_LEN(m) <= k + 1)
-      mvl = m->vl;
-    else
-      mvl = m->v + k + 1;
-    r = mp_new(k + 1, (q->f | mb->m->f) & MP_BURN);
-    mpx_umul(r->v, r->vl, q->v + k + 1, q->vl, mb->m->v, mb->m->vl);
-    MP_DEST(d, k + 1, r->f | MP_UNDEF);
-    mpx_usub(d->v, d->vl, m->v, mvl, r->v, r->vl);
-    d->f = (m->f | r->f) & (MP_BURN | MP_NEG);
-    MP_DROP(r);
-    MP_DROP(q);
-    MP_DROP(m);
-  }
-
-  /* --- Final stage --- */
-
-  MP_SHRINK(d);
-  while (MPX_UCMP(d->v, d->vl, >=, mb->m->v, mb->m->vl))
-    mpx_usub(d->v, d->vl, d->v, d->vl, mb->m->v, mb->m->vl);
-
-  /* --- Fix up the sign --- */
-
-  if (d->f & MP_NEG) {
-    mpx_usub(d->v, d->vl, mb->m->v, mb->m->vl, d->v, d->vl);
-    d->f &= ~MP_NEG;
-  }
-
-  MP_SHRINK(d);
-  return (d);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int vmod(dstr *v)
-{
-  mp *x = *(mp **)v[0].buf;
-  mp *n = *(mp **)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *s;
-  mpbarrett mb;
-  int ok = 1;
-
-  mpbarrett_create(&mb, n);
-  s = mpbarrett_reduce(&mb, MP_NEW, x);
-
-  if (!MP_EQ(s, r)) {
-    fputs("\n*** barrett reduction failure\n", stderr);
-    fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr);
-    fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr);
-    fputs("r = ", stderr); mp_writefile(r, stderr, 10); fputc('\n', stderr);
-    fputs("s = ", stderr); mp_writefile(s, stderr, 10); fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mpbarrett_destroy(&mb);
-  mp_drop(x);
-  mp_drop(n);
-  mp_drop(r);
-  mp_drop(s);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "mpbarrett-reduce", vmod, { &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mpbarrett");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpbarrett.h b/mpbarrett.h
deleted file mode 100644 (file)
index 71d9ba7..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Barrett modular reduction
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on Barrett reduction ----------------------------------------*
- *
- * Barrett reduction is a technique for computing modular residues.  Unlike
- * Montgomery reduction, it doesn't have restrictions on the modulus (except
- * that it be positive) and doesn't confuse matters by putting an extra
- * factor all the way through your computation.
- *
- * It's useful for slightly less heavy-duty work than Montgomery reduction
- * because the precomputation phase is rather simpler, involving a single
- * division operation.
- *
- * Sometimes it's useful to exponentiate modulo an even number, so there's a
- * modexp routine provided which uses Barrett reduction rather than
- * Montgomery reduction.  This is handy when you're working on indices in an
- * even-order cyclic group or something.
- */
-
-#ifndef CATACOMB_MPBARRETT_H
-#define CATACOMB_MPBARRETT_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct mpbarrett {
-  mp *m;
-  mp *mu;
-  size_t k;
-} mpbarrett;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mpbarrett_create@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *             @mp *m@ = modulus to work to
- *
- * Returns:    Zero on success, nonzero on error.
- *
- * Use:                Initializes a Barrett reduction context ready for use.
- */
-
-extern int mpbarrett_create(mpbarrett */*mb*/, mp */*m*/);
-
-/* --- @mpbarrett_destroy@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *
- * Returns:    ---
- *
- * Use:                Destroys a Barrett reduction context releasing any resources
- *             claimed.
- */
-
-extern void mpbarrett_destroy(mpbarrett */*mb*/);
-
-/* --- @mpbarrett_reduce@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *             @mp *d@ = destination for result
- *             @mp *m@ = number to reduce
- *
- * Returns:    The residue of @m@ modulo the number in the reduction
- *             context.
- *
- * Use:                Performs an efficient modular reduction.
- */
-
-extern mp *mpbarrett_reduce(mpbarrett */*mb*/, mp */*d*/, mp */*m*/);
-
-/* --- @mpbarrett_exp@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e \bmod m$%.
- */
-
-extern mp *mpbarrett_exp(mpbarrett */*mb*/, mp */*d*/, mp */*a*/, mp */*e*/);
-
-/* --- @mpbarrett_mexp@ --- *
- *
- * Arguments:  @mpbarrett *mb@ = pointer to Barrett reduction context
- *             @mp *d@ = fake destination
- *             @const mp_expfactor *f@ = pointer to array of factors
- *             @size_t n@ = number of factors supplied
- *
- * Returns:    If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the
- *             exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result
- *             is:
- *
- *             %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$%
- */
-
-extern mp *mpbarrett_mexp(mpbarrett */*mb*/, mp */*d*/,
-                         const mp_expfactor */*f*/, size_t /*n*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpcrt.c b/mpcrt.c
deleted file mode 100644 (file)
index bf6459f..0000000
--- a/mpcrt.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Chinese Remainder Theorem computations (Gauss's algorithm)
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpcrt.h"
-#include "mpmul.h"
-#include "mpbarrett.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpcrt_create@ --- *
- *
- * Arguments:  @mpcrt *c@ = pointer to CRT context
- *             @mpcrt_mod *v@ = pointer to vector of moduli
- *             @size_t k@ = number of moduli
- *             @mp *n@ = product of all moduli (@MP_NEW@ if unknown)
- *
- * Returns:    ---
- *
- * Use:                Initializes a context for solving Chinese Remainder Theorem
- *             problems.  The vector of moduli can be incomplete.  Omitted
- *             items must be left as null pointers.  Not all combinations of
- *             missing things can be coped with, even if there is
- *             technically enough information to cope.  For example, if @n@
- *             is unspecified, all the @m@ values must be present, even if
- *             there is one modulus with both @m@ and @n@ (from which the
- *             product of all moduli could clearly be calculated).
- */
-
-void mpcrt_create(mpcrt *c, mpcrt_mod *v, size_t k, mp *n)
-{
-  size_t i;
-
-  /* --- Simple initialization things --- */
-
-  c->k = k;
-  c->v = v;
-
-  /* --- Work out @n@ if I don't have it already --- */
-
-  if (n != MP_NEW)
-    n = MP_COPY(n);
-  else {
-    mpmul mm;
-    mpmul_init(&mm);
-    for (i = 0; i < k; i++)
-      mpmul_add(&mm, v[i].m);
-    n = mpmul_done(&mm);
-  }
-
-  /* --- A quick hack if %$k = 2$% --- */
-
-  if (k == 2) {
-
-    /* --- The %$n / n_i$% values are trivial in this case --- */
-
-    if (!v[0].n)
-      v[0].n = MP_COPY(v[1].m);
-    if (!v[1].n)
-      v[1].n = MP_COPY(v[0].m);
-
-    /* --- Now sort out the inverses --- *
-     *
-     * @mp_gcd@ will ensure that the first argument is negative.
-     */
-
-    if (!v[0].ni && !v[1].ni) {
-      mp *g = MP_NEW;
-      mp_gcd(&g, &v[0].ni, &v[1].ni, v[0].n, v[1].n);
-      assert(MP_EQ(g, MP_ONE));
-      mp_drop(g);
-      v[0].ni = mp_add(v[0].ni, v[0].ni, v[1].n);
-    } else {
-      int i, j;
-      mp *x;
-
-      if (!v[0].ni)
-       i = 0, j = 1;
-      else
-       i = 1, j = 0;
-
-      x = mp_mul(MP_NEW, v[j].n, v[j].ni);
-      x = mp_sub(x, x, MP_ONE);
-      mp_div(&x, 0, x, v[i].n);
-      v[i].ni = x;
-    }
-  }
-
-  /* --- Set up the Barrett context --- */
-
-  mpbarrett_create(&c->mb, n);
-
-  /* --- Walk through filling in @n@, @ni@ and @nnir@ --- */
-
-  for (i = 0; i < k; i++) {
-    if (!v[i].n)
-      mp_div(&v[i].n, 0, n, v[i].m);
-    if (!v[i].ni)
-      v[i].ni = mp_modinv(MP_NEW, v[i].n, v[i].m);
-    if (!v[i].nni)
-      v[i].nni = mp_mul(MP_NEW, v[i].n, v[i].ni);
-  }
-
-  /* --- Done --- */
-
-  mp_drop(n);
-}
-
-/* --- @mpcrt_destroy@ --- *
- *
- * Arguments:  @mpcrt *c@ - pointer to CRT context
- *
- * Returns:    ---
- *
- * Use:                Destroys a CRT context, releasing all the resources it holds.
- */
-
-void mpcrt_destroy(mpcrt *c)
-{
-  size_t i;
-
-  for (i = 0; i < c->k; i++) {
-    if (c->v[i].m) mp_drop(c->v[i].m);
-    if (c->v[i].n) mp_drop(c->v[i].n);
-    if (c->v[i].ni) mp_drop(c->v[i].ni);
-    if (c->v[i].nni) mp_drop(c->v[i].nni);
-  }
-  mpbarrett_destroy(&c->mb);
-}
-
-/* --- @mpcrt_solve@ --- *
- *
- * Arguments:  @mpcrt *c@ = pointer to CRT context
- *             @mp *d@ = fake destination
- *             @mp **v@ = array of residues
- *
- * Returns:    The unique solution modulo the product of the individual
- *             moduli, which leaves the given residues.
- *
- * Use:                Constructs a result given its residue modulo an array of
- *             coprime integers.  This can be used to improve performance of
- *             RSA encryption or Blum-Blum-Shub generation if the factors
- *             of the modulus are known, since results can be computed mod
- *             each of the individual factors and then combined at the end.
- *             This is rather faster than doing the full-scale modular
- *             exponentiation.
- */
-
-mp *mpcrt_solve(mpcrt *c, mp *d, mp **v)
-{
-  mp *a = MP_ZERO;
-  mp *x = MP_NEW;
-  size_t i;
-
-  for (i = 0; i < c->k; i++) {
-    x = mp_mul(x, c->v[i].nni, v[i]);
-    x = mpbarrett_reduce(&c->mb, x, x);
-    a = mp_add(a, a, x);
-  }
-  if (x)
-    MP_DROP(x);
-  a = mpbarrett_reduce(&c->mb, a, a);
-  if (d != MP_NEW)
-    MP_DROP(d);
-  return (a);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int verify(size_t n, dstr *v)
-{
-  mpcrt_mod *m = xmalloc(n * sizeof(mpcrt_mod));
-  mp **r = xmalloc(n * sizeof(mp *));
-  mpcrt c;
-  mp *a, *b;
-  size_t i;
-  int ok = 1;
-
-  for (i = 0; i < n; i++) {
-    r[i] = *(mp **)v[2 * i].buf;
-    m[i].m = *(mp **)v[2 * i + 1].buf;
-    m[i].n = 0;
-    m[i].ni = 0;
-    m[i].nni = 0;
-  }
-  a = *(mp **)v[2 * n].buf;
-
-  mpcrt_create(&c, m, n, 0);
-  b = mpcrt_solve(&c, MP_NEW, r);
-
-  if (!MP_EQ(a, b)) {
-    fputs("\n*** failed\n", stderr);
-    fputs("n = ", stderr);
-    mp_writefile(c.mb.m, stderr, 10);
-    for (i = 0; i < n; i++) {
-      fprintf(stderr, "\nr[%u] = ", i);
-      mp_writefile(r[i], stderr, 10);
-      fprintf(stderr, "\nm[%u] = ", i);
-      mp_writefile(m[i].m, stderr, 10);
-      fprintf(stderr, "\nN[%u] = ", i);
-      mp_writefile(m[i].n, stderr, 10);
-      fprintf(stderr, "\nM[%u] = ", i);
-      mp_writefile(m[i].ni, stderr, 10);
-    }
-    fputs("\nresult = ", stderr);
-    mp_writefile(b, stderr, 10);
-    fputs("\nexpect = ", stderr);
-    mp_writefile(a, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  for (i = 0; i < n; i++)
-    mp_drop(r[i]);
-  mp_drop(a);
-  mp_drop(b);
-  mpcrt_destroy(&c);
-  xfree(m);
-  xfree(r);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int crt1(dstr *v) { return verify(1, v); }
-static int crt2(dstr *v) { return verify(2, v); }
-static int crt3(dstr *v) { return verify(3, v); }
-static int crt4(dstr *v) { return verify(4, v); }
-static int crt5(dstr *v) { return verify(5, v); }
-
-static test_chunk tests[] = {
-  { "crt-1", crt1, { &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "crt-2", crt2, { &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "crt-3", crt3, { &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "crt-4", crt4, { &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "crt-5", crt5, { &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mpcrt");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpcrt.h b/mpcrt.h
deleted file mode 100644 (file)
index c108916..0000000
--- a/mpcrt.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpcrt.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Chinese Remainder Theorem computations (Gauss's algorithm)
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPCRT_H
-#define CATACOMB_MPCRT_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_MPBARRETT_H
-#  include "mpbarrett.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct mpcrt_mod {
-  mp *m;                               /* %$n_i$% -- the modulus */
-  mp *n;                               /* %$N_i = n / n_i$% */
-  mp *ni;                              /* %$M_i = N_i^{-1} \bmod n_i$% */
-  mp *nni;                             /* %$N_i M_i \bmod m$% */
-} mpcrt_mod;
-
-typedef struct mpcrt {
-  size_t k;                            /* Number of distinct moduli */
-  mpbarrett mb;                                /* Barrett context for product */
-  mpcrt_mod *v;                                /* Vector of information for each */
-} mpcrt;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mpcrt_create@ --- *
- *
- * Arguments:  @mpcrt *c@ = pointer to CRT context
- *             @mpcrt_mod *v@ = pointer to vector of moduli
- *             @size_t k@ = number of moduli
- *             @mp *n@ = product of all moduli (@MP_NEW@ if unknown)
- *
- * Returns:    ---
- *
- * Use:                Initializes a context for solving Chinese Remainder Theorem
- *             problems.  The vector of moduli can be incomplete.  Omitted
- *             items must be left as null pointers.  Not all combinations of
- *             missing things can be coped with, even if there is
- *             technically enough information to cope.  For example, if @n@
- *             is unspecified, all the @m@ values must be present, even if
- *             there is one modulus with both @m@ and @n@ (from which the
- *             product of all moduli could clearly be calculated).
- */
-
-extern void mpcrt_create(mpcrt */*c*/, mpcrt_mod */*v*/,
-                        size_t /*k*/, mp */*n*/);
-
-/* --- @mpcrt_destroy@ --- *
- *
- * Arguments:  @mpcrt *c@ - pointer to CRT context
- *
- * Returns:    ---
- *
- * Use:                Destroys a CRT context, releasing all the resources it holds.
- */
-
-extern void mpcrt_destroy(mpcrt */*c*/);
-
-/* --- @mpcrt_solve@ --- *
- *
- * Arguments:  @mpcrt *c@ = pointer to CRT context
- *             @mp *d@ = fake destination
- *             @mp **v@ = array of residues
- *
- * Returns:    The unique solution modulo the product of the individual
- *             moduli, which leaves the given residues.
- *
- * Use:                Constructs a result given its residue modulo an array of
- *             coprime integers.  This can be used to improve performance of
- *             RSA encryption or Blum-Blum-Shub generation if the factors
- *             of the modulus are known, since results can be computed mod
- *             each of the individual factors and then combined at the end.
- *             This is rather faster than doing the full-scale modular
- *             exponentiation.
- */
-
-extern mp *mpcrt_solve(mpcrt */*c*/, mp */*d*/, mp **/*v*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpdump.c b/mpdump.c
deleted file mode 100644 (file)
index 1d80f40..0000000
--- a/mpdump.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpdump.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Dump a multiprecision integer as C data
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "mp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
-  mp *x;
-  int i;
-  int w, n;
-
-  if (argc != 2) {
-    fprintf(stderr, "%s: missing argument\n", argv[0]);
-    return (1);
-  }
-  if ((x = mp_readstring(0, argv[1], 0, 0)) == 0) {
-    fprintf(stderr, "%s: bad integer `%s'", argv[0], argv[1]);
-    return (1);
-  }
-  fputs("  ", stdout);
-  w = (MPW_BITS + 3)/4;
-  n = 1;
-  while (2 + 2 * n * (4 + w) < 72) n <<= 1;
-  i = 0;
-  for (;;) {
-    printf("0x%0*x", w, x->v[i]);
-    i++;
-    if (i >= MP_LEN(x)) break;
-    fputs(",", stdout);
-    if (i % n) fputs(" ", stdout); else fputs("\n  ", stdout);
-  }
-  if (fflush(stdout) || ferror(stdout)) {
-    fprintf(stderr, "%s: error writing data: %s", argv[0], strerror(errno));
-    return (1);
-  }
-  fputs("\n", stdout);
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpint.c b/mpint.c
deleted file mode 100644 (file)
index 7c1b8cc..0000000
--- a/mpint.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpint.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Conversion between MPs and standard C integers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mpint.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Conversion from C integers --- */
-
-#define FROM(name, type)                                               \
-  mp *mp_from##name(mp *d, type i) {                                   \
-    MP_FROMINT(d, type, i);                                            \
-    return (d);                                                                \
-  }
-
-FROM(short, short)
-FROM(ushort, unsigned short)
-FROM(int, int)
-FROM(uint, unsigned)
-FROM(uint32, uint32)
-FROM(long, long)
-FROM(ulong, unsigned long)
-
-#undef FROM
-
-/* --- Conversion to C integers --- */
-
-#define TO(name, type, max)                                            \
-  type mp_to##name(const mp *m)                                                \
-  {                                                                    \
-    type i;                                                            \
-    MP_TOINT(m, type, max, i);                                         \
-    return (i);                                                                \
-  }
-
-TO(short, short, SHRT_MAX)
-TO(ushort, unsigned short, USHRT_MAX)
-TO(int, int, INT_MAX)
-TO(uint, unsigned, UINT_MAX)
-TO(uint32, uint32, 0xffffffff)
-TO(long, long, LONG_MAX)
-TO(ulong, unsigned long, ULONG_MAX)
-
-#undef TO
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int fromuint(dstr *v)
-{
-  unsigned long i = *(unsigned long *)v[0].buf;
-  mp *m = *(mp **)v[1].buf;
-  mp *d = mp_fromuint(MP_NEW, i);
-  int ok = 1;
-
-  if (!MP_EQ(d, m)) {
-    fputs("\n*** fromint failed.\n", stderr);
-    fprintf(stderr, "i = %lu", i);
-    fputs("\nexpect = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\nresult = ", stderr); mp_writefile(d, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(m);
-  mp_drop(d);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int fromint(dstr *v)
-{
-  long i = *(long *)v[0].buf;
-  mp *m = *(mp **)v[1].buf;
-  mp *d = mp_fromint(MP_NEW, i);
-  int ok = 1;
-
-  if (!MP_EQ(d, m)) {
-    fputs("\n*** fromint failed.\n", stderr);
-    fprintf(stderr, "i = %li", i);
-    fputs("\nexpect = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\nresult = ", stderr); mp_writefile(d, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(m);
-  mp_drop(d);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int touint(dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  unsigned long i = *(unsigned long *)v[1].buf;
-  unsigned j = mp_touint(m);
-  int ok = 1;
-
-  if ((unsigned)i != j) {
-    fputs("\n*** touint failed.\n", stderr);
-    fputs("m = ", stderr); mp_writefile(m, stderr, 10);
-    fprintf(stderr, "\nexpect = %lu; result = %u\n", i, j);
-    ok = 0;
-  }
-
-  mp_drop(m);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int toint(dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  long i = *(long *)v[1].buf;
-  int j = mp_toint(m);
-  int ok = 1;
-
-  if (i != j) {
-    fputs("\n*** toint failed.\n", stderr);
-    fputs("m = ", stderr); mp_writefile(m, stderr, 10);
-    fprintf(stderr, "\nexpect = %li; result = %i\n", i, j);
-    ok = 0;
-  }
-
-  mp_drop(m);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "fromuint", fromuint, { &type_ulong, &type_mp, 0 } },
-  { "fromint", fromint, { &type_long, &type_mp, 0 } },
-  { "touint", touint, { &type_mp, &type_ulong, 0 } },
-  { "toint", toint, { &type_mp, &type_long, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mpint");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpint.h b/mpint.h
deleted file mode 100644 (file)
index dbf9065..0000000
--- a/mpint.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Conversion between MPs and standard C integers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPINT_H
-#define CATACOMB_MPINT_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <limits.h>
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Generic translation macros ----------------------------------------*/
-
-/* --- @MP_FROMINT@ --- *
- *
- * Arguments:  @d@ = destination multiprecision integer
- *             @type@ = type of integer which @i@ is
- *             @i@ = a standard C integer
- *
- * Use:                Stores the value of @i@ in @d@.  This macro is actually
- *             rather subtle in places.  Be careful what you change.
- */
-
-#define MP_FROMINT(d, type, i) do {                                    \
-  type _i = (i);                                                       \
-  size_t _o = 0;                                                       \
-  mp *_d = (d);                                                                \
-  size_t _sz = 4;                                                      \
-                                                                       \
-  MP_DEST(_d, _sz, 0);                                                 \
-  _d->f &= ~(MP_NEG | MP_UNDEF);                                       \
-                                                                       \
-  if (_i >= 0) {                                                       \
-    while (_i) {                                                       \
-      if (_o == _sz) {                                                 \
-       _sz <<= 1;                                                      \
-       MP_ENSURE(_d, _sz);                                             \
-      }                                                                        \
-      _d->v[_o++] = MPW(_i);                                           \
-      if (_i <= MPW_MAX)                                               \
-       break;                                                          \
-      else                                                             \
-       _i /= (type)MPW_MAX + 1;                                        \
-    }                                                                  \
-  } else {                                                             \
-    _d->f |= MP_NEG;                                                   \
-    while (_i) {                                                       \
-      if (_o == _sz) {                                                 \
-       _sz <<= 1;                                                      \
-       MP_ENSURE(_d, _sz);                                             \
-      }                                                                        \
-      _d->v[_o++] = MPW(-_i);                                          \
-      if (_i >= -MPW_MAX)                                              \
-       break;                                                          \
-      else                                                             \
-       _i /= (type)MPW_MAX + 1;                                        \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  _d->vl = _d->v + _o;                                                 \
-  (d) = _d;                                                            \
-} while (0)
-
-/* --- @MP_TOINT@ --- *
- *
- * Arguments:  @m@ = a multiprecision integer
- *             @type@ = the type of @i@
- *             @max@ = the largest value @i@ can represent
- *             @i@ = an integer variable
- *
- * Use:                Stores the value of a multiprecision integer in a standard C
- *             integer.  If the value won't fit, the behaviour is determined
- *             by the type of @i@: if @i@ is unsigned, the value of the
- *             multiprecision integer modulo @max + 1@ is stored; if @i@ is
- *             signed, the behaviour is undefined.
- *
- *             If you don't want to be bitten by these sorts of things, keep
- *             copies of @INT_MAX@ or whatever is appropriate in
- *             multiprecision form and compare before conversion.
- */
-
-#define MP_TOINT(m, type, max, i) do {                                 \
-  type _i = 0;                                                         \
-  type _max = (max);                                                   \
-  unsigned _s = 0;                                                     \
-  const mp *_m = (m);                                                  \
-  const mpw *_v = _m->v, *_vl = _m->vl;                                        \
-                                                                       \
-  /* --- Do all the arithmetic in negative numbers --- */              \
-                                                                       \
-  while (_v < _vl && _max > 0) {                                       \
-    _i -= *_v << _s;                                                   \
-    _s += MPW_BITS;                                                    \
-    _v++;                                                              \
-    _max /= (mpd)MPW_MAX + 1;                                          \
-  }                                                                    \
-  if (!MP_NEGP(_m))                                                    \
-    _i = -_i;                                                          \
-  (i) = _i;                                                            \
-} while (0)
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mp_fromINT@ --- *
- *
- * Arguments:  @mp *d@ = pointer to destination multiprecision integer
- *             @INT i@ = standard C integer to convert
- *
- * Returns:    The resulting multiprecision integer.
- *
- * Use:                Converts a standard C integer to a multiprecision integer.
- */
-
-#define mp_fromINT(name, type)                                         \
-  extern mp *mp_from##name(mp */*d*/, type /*i*/)
-
-mp_fromINT(short, short);
-mp_fromINT(ushort, unsigned short);
-mp_fromINT(int, int);
-mp_fromINT(uint, unsigned);
-mp_fromINT(uint32, uint32);
-mp_fromINT(long, long);
-mp_fromINT(ulong, unsigned long);
-
-#undef mp_fromINT
-
-/* --- @mp_toINT@ --- *
- *
- * Arguments:  @const mp *m@ = pointer to a multiprecision integer
- *
- * Returns:    The value of the integer @m@ as a C integer.
- *
- * Use:                Converts a multiprecision integer to a standard C integer.
- *             If the value of the multiprecision integer cannot be
- *             represented in the return type, and the return type is
- *             unsigned, it is reduced modulo @TYPE_MAX + 1@; if the return
- *             type is signed, the behaviour is undefined.
- */
-
-#define mp_toINT(name, type)                                           \
-  extern type mp_to##name(const mp */*m*/)
-
-mp_toINT(short, short);
-mp_toINT(ushort, unsigned short);
-mp_toINT(int, int);
-mp_toINT(uint, unsigned);
-mp_toINT(uint32, uint32);
-mp_toINT(long, long);
-mp_toINT(ulong, unsigned long);
-
-#undef mp_toINT
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpmont-exp.c b/mpmont-exp.c
deleted file mode 100644 (file)
index 6959baf..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Modular exponentiation with Montgomery reduction
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpmont.h"
-#include "mpmont-exp.h"
-
-/*----- Exponentiation ----------------------------------------------------*/
-
-/* --- @mpmont_expr@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$(a R^{-1})^e R \bmod m$%.
- */
-
-mp *mpmont_expr(mpmont *mm, mp *d, mp *a, mp *e)
-{
-  mp *x = MP_COPY(mm->r);
-  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
-
-  MP_COPY(a);
-  MP_SHRINK(e);
-  if (MP_ZEROP(e))
-    ;
-  else {
-    if (MP_NEGP(e)) {
-      a = mpmont_reduce(mm, a, a);
-      a = mp_modinv(a, a, mm->m);
-      a = mpmont_mul(mm, a, a, mm->r2);
-    }
-    if (MP_LEN(e) < EXP_THRESH)
-      EXP_SIMPLE(x, a, e);
-    else
-      EXP_WINDOW(x, a, e);
-  }
-  mp_drop(d);
-  mp_drop(spare);
-  mp_drop(a);
-  return (x);
-}
-
-/* --- @mpmont_exp@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e \bmod m$%.
- */
-
-mp *mpmont_exp(mpmont *mm, mp *d, mp *a, mp *e)
-{
-  e = MP_COPY(e);
-  d = mpmont_mul(mm, d, a, mm->r2);
-  d = mpmont_expr(mm, d, d, e);
-  d = mpmont_reduce(mm, d, d);
-  MP_DROP(e);
-  return (d);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int texp(dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  mp *a = *(mp **)v[1].buf;
-  mp *b = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *mr;
-  int ok = 1;
-
-  mpmont mm;
-  mpmont_create(&mm, m);
-
-  mr = mpmont_exp(&mm, MP_NEW, a, b);
-
-  if (!MP_EQ(mr, r)) {
-    fputs("\n*** montgomery modexp failed", stderr);
-    fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
-    fputs("\n e = ", stderr); mp_writefile(b, stderr, 10);
-    fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  MP_DROP(m);
-  MP_DROP(a);
-  MP_DROP(b);
-  MP_DROP(r);
-  MP_DROP(mr);
-  mpmont_destroy(&mm);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return ok;
-}
-
-static test_chunk tests[] = {
-  { "exp", texp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } },
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mpmont");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpmont-exp.h b/mpmont-exp.h
deleted file mode 100644 (file)
index 7730524..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpmont-exp.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Exponentiation operations for Montgomery reduction
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_MPMONT_EXP_H
-#define CATACOMB_MPMONT_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentation definitions -----------------------------------------*/
-
-#define EXP_TYPE mp *
-
-#define EXP_COPY(d, x) d = MP_COPY(x)
-#define EXP_DROP(x) MP_DROP(x)
-
-#define EXP_MUL(a, x) do {                                             \
-  mp *t = mpmont_mul(mm, spare, a, x);                                 \
-  spare = a;                                                           \
-  a = t;                                                               \
-} while (0)
-
-#define EXP_SQR(a) do {                                                        \
-  mp *t = mp_sqr(spare, a);                                            \
-  spare = a;                                                           \
-  a = mpmont_reduce(mm, t, t);                                         \
-} while (0)
-
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) d = mpmont_mul(mm, MP_NEW, x, y)
-
-#define EXP_SETSQR(d, x) do {                                          \
-  d = mp_sqr(MP_NEW, x);                                               \
-  d = mpmont_reduce(mm, d, d);                                         \
-} while (0)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpmont-mexp.c b/mpmont-mexp.c
deleted file mode 100644 (file)
index 92f40c3..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Multiple simultaneous exponentiations
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpmont.h"
-
-#define EXP_WINSZ 3
-#include "mpmont-exp.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpmont_mexpr@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = fake destination
- *             @const mp_expfactor *f@ = pointer to array of factors
- *             @size_t n@ = number of factors supplied
- *
- * Returns:    If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the
- *             exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result
- *             is:
- *
- *             %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$%
- *
- *             except that the %$g_i$% and result are in Montgomery form.
- */
-
-static mp *mexpr(mpmont *mm, mp *d, mp_expfactor *f, size_t n)
-{
-  mp *a = MP_COPY(mm->r);
-  mp *spare = MP_NEW;
-  size_t i;
-
-  for (i = 0; i < n; i++) {
-    mp *t;
-    if (f[i].exp->f & MP_BURN)
-      spare = MP_NEWSEC;
-    if (MP_NEGP(f[i].exp)) {
-      t = mpmont_reduce(mm, f[i].base, f[i].base);
-      t = mp_modinv(t, t, mm->m);
-      f[i].base = mpmont_mul(mm, t, t, mm->r2);
-    }
-  }
-  EXP_SIMUL(a, f, n);
-  mp_drop(d);
-  mp_drop(spare);
-  for (i = 0; i < n; i++)
-    MP_DROP(f[i].base);
-  xfree(f);
-  return (a);
-}
-
-mp *mpmont_mexpr(mpmont *mm, mp *d, const mp_expfactor *f, size_t n)
-{
-  mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor));
-  size_t i;
-
-  for (i = 0; i < n; i++) {
-    ff[i].base = MP_COPY(f[i].base);
-    ff[i].exp = f[i].exp;
-  }
-  return (mexpr(mm, d, ff, n));
-}
-
-/* --- @mpmont_mexp@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = fake destination
- *             @const mp_expfactor *f@ = pointer to array of factors
- *             @size_t n@ = number of factors supplied
- *
- * Returns:    Product of bases raised to exponents, all mod @m@.
- *
- * Use:                Convenient interface over @mpmont_mexpr@.
- */
-
-mp *mpmont_mexp(mpmont *mm, mp *d, const mp_expfactor *f, size_t n)
-{
-  mp_expfactor *ff = xmalloc(n * sizeof(mp_expfactor));
-  size_t i;
-
-  for (i = 0; i < n; i++) {
-    ff[i].base = mpmont_mul(mm, MP_NEW, f[i].base, mm->r2);
-    ff[i].exp = f[i].exp;
-  }
-  d = mexpr(mm, d, ff, n);
-  return (mpmont_reduce(mm, d, d));
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int verify(size_t n, dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  mp_expfactor *f = xmalloc(n * sizeof(*f));
-  mp *r, *rr;
-  size_t i, j;
-  mpmont mm;
-  int ok = 1;
-
-  j = 1;
-  for (i = 0; i < n; i++) {
-    f[i].base = *(mp **)v[j++].buf;
-    f[i].exp = *(mp **)v[j++].buf;
-  }
-
-  rr = *(mp **)v[j].buf;
-  mpmont_create(&mm, m);
-  r = mpmont_mexp(&mm, MP_NEW, f, n);
-  if (!MP_EQ(r, rr)) {
-    fputs("\n*** mexp failed\n", stderr);
-    fputs("m = ", stderr); mp_writefile(m, stderr, 10);
-    for (i = 0; i < n; i++) {
-      fprintf(stderr, "\ng_%u = ", i);
-      mp_writefile(f[i].base, stderr, 10);
-      fprintf(stderr, "\ne_%u = ", i);
-      mp_writefile(f[i].exp, stderr, 10);
-    }
-    fputs("\nr = ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\nR = ", stderr); mp_writefile(rr, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  for (i = 0; i < n; i++) {
-    MP_DROP(f[i].base);
-    MP_DROP(f[i].exp);
-  }
-  MP_DROP(m);
-  MP_DROP(r);
-  MP_DROP(rr);
-  mpmont_destroy(&mm);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int t1(dstr *v) { return verify(1, v); }
-static int t2(dstr *v) { return verify(2, v); }
-static int t3(dstr *v) { return verify(3, v); }
-static int t4(dstr *v) { return verify(4, v); }
-static int t5(dstr *v) { return verify(5, v); }
-
-static test_chunk tests[] = {
-  { "mexp-1", t1, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "mexp-2", t2, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "mexp-3", t3, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "mexp-4", t4, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { "mexp-5", t5, { &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, &type_mp,
-                   &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mpmont");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpmont.c b/mpmont.c
deleted file mode 100644 (file)
index 65b3fcc..0000000
--- a/mpmont.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Montgomery reduction
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpmont.h"
-
-/*----- Tweakables --------------------------------------------------------*/
-
-/* --- @MPMONT_DISABLE@ --- *
- *
- * Replace all the clever Montgomery reduction with good old-fashioned long
- * division.
- */
-
-/* #define MPMONT_DISABLE */
-
-/*----- Reduction and multiplication --------------------------------------*/
-
-/* --- @mpmont_create@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *m@ = modulus to use
- *
- * Returns:    Zero on success, nonzero on error.
- *
- * Use:                Initializes a Montgomery reduction context ready for use.
- *             The argument @m@ must be a positive odd integer.
- */
-
-#ifdef MPMONT_DISABLE
-
-int mpmont_create(mpmont *mm, mp *m)
-{
-  mp_shrink(m);
-  mm->m = MP_COPY(m);
-  mm->r = MP_ONE;
-  mm->r2 = MP_ONE;
-  mm->mi = MP_ONE;
-  return (0);
-}
-
-#else
-
-int mpmont_create(mpmont *mm, mp *m)
-{
-  size_t n = MP_LEN(m);
-  mp *r2 = mp_new(2 * n + 1, 0);
-  mp r;
-
-  /* --- Take a copy of the modulus --- */
-
- if (!MP_POSP(m) || !MP_ODDP(m))
-   return (-1);
-  mm->m = MP_COPY(m);
-
-  /* --- Determine %$R^2$% --- */
-
-  mm->n = n;
-  MPX_ZERO(r2->v, r2->vl - 1);
-  r2->vl[-1] = 1;
-
-  /* --- Find the magic value @mi@ --- */
-
-  mp_build(&r, r2->v + n, r2->vl);
-  mm->mi = mp_modinv(MP_NEW, m, &r);
-  mm->mi = mp_sub(mm->mi, &r, mm->mi);
-
-  /* --- Discover the values %$R \bmod m$% and %$R^2 \bmod m$% --- */
-
-  mm->r2 = MP_NEW;
-  mp_div(0, &mm->r2, r2, m);
-  mm->r = mpmont_reduce(mm, MP_NEW, mm->r2);
-  MP_DROP(r2);
-  return (0);
-}
-
-#endif
-
-/* --- @mpmont_destroy@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to a Montgomery reduction context
- *
- * Returns:    ---
- *
- * Use:                Disposes of a context when it's no longer of any use to
- *             anyone.
- */
-
-void mpmont_destroy(mpmont *mm)
-{
-  MP_DROP(mm->m);
-  MP_DROP(mm->r);
-  MP_DROP(mm->r2);
-  MP_DROP(mm->mi);
-}
-
-/* --- @mpmont_reduce@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = destination
- *             @mp *a@ = source, assumed positive
- *
- * Returns:    Result, %$a R^{-1} \bmod m$%.
- */
-
-#ifdef MPMONT_DISABLE
-
-mp *mpmont_reduce(mpmont *mm, mp *d, mp *a)
-{
-  mp_div(0, &d, a, mm->m);
-  return (d);
-}
-
-#else
-
-mp *mpmont_reduce(mpmont *mm, mp *d, mp *a)
-{
-  size_t n = mm->n;
-
-  /* --- Check for serious Karatsuba reduction --- */
-
-  if (n > MPK_THRESH * 3) {
-    mp al;
-    mpw *vl;
-    mp *u;
-
-    if (MP_LEN(a) >= n)
-      vl = a->v + n;
-    else
-      vl = a->vl;
-    mp_build(&al, a->v, vl);
-    u = mp_mul(MP_NEW, &al, mm->mi);
-    if (MP_LEN(u) > n)
-      u->vl = u->v + n;
-    u = mp_mul(u, u, mm->m);
-    d = mp_add(d, a, u);
-    mp_drop(u);
-  }
-
-  /* --- Otherwise do it the hard way --- */
-
-  else {
-    mpw *dv, *dvl;
-    mpw *mv, *mvl;
-    mpw mi;
-    size_t k = n;
-
-    /* --- Initial conditioning of the arguments --- */
-
-    a = MP_COPY(a);
-    if (d)
-      MP_DROP(d);
-    d = a;
-    MP_DEST(d, 2 * n + 1, a->f);
-
-    dv = d->v; dvl = d->vl;
-    mv = mm->m->v; mvl = mm->m->vl;
-
-    /* --- Let's go to work --- */
-
-    mi = mm->mi->v[0];
-    while (k--) {
-      mpw u = MPW(*dv * mi);
-      MPX_UMLAN(dv, dvl, mv, mvl, u);
-      dv++;
-    }
-  }
-
-  /* --- Wrap everything up --- */
-
-  memmove(d->v, d->v + n, MPWS(MP_LEN(d) - n));
-  d->vl -= n;
-  if (MPX_UCMP(d->v, d->vl, >=, mm->m->v, mm->m->vl))
-    mpx_usub(d->v, d->vl, d->v, d->vl, mm->m->v, mm->m->vl);
-  if (d->f & MP_NEG) {
-    mpx_usub(d->v, d->vl, mm->m->v, mm->m->vl, d->v, d->vl);
-    d->f &= ~MP_NEG;
-  }
-  MP_SHRINK(d);
-  return (d);
-}
-
-#endif
-
-/* --- @mpmont_mul@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = destination
- *             @mp *a, *b@ = sources, assumed positive
- *
- * Returns:    Result, %$a b R^{-1} \bmod m$%.
- */
-
-#ifdef MPMONT_DISABLE
-
-mp *mpmont_mul(mpmont *mm, mp *d, mp *a, mp *b)
-{
-  d = mp_mul(d, a, b);
-  mp_div(0, &d, d, mm->m);
-  return (d);
-}
-
-#else
-
-mp *mpmont_mul(mpmont *mm, mp *d, mp *a, mp *b)
-{
-  if (mm->n > MPK_THRESH * 3) {
-    d = mp_mul(d, a, b);
-    d = mpmont_reduce(mm, d, d);
-  } else {
-    mpw *dv, *dvl;
-    mpw *av, *avl;
-    mpw *bv, *bvl;
-    mpw *mv, *mvl;
-    mpw y;
-    size_t n, i;
-    mpw mi;
-
-    /* --- Initial conditioning of the arguments --- */
-
-    if (MP_LEN(a) > MP_LEN(b)) {
-      mp *t = a; a = b; b = t;
-    }
-    n = MP_LEN(mm->m);
-
-    a = MP_COPY(a);
-    b = MP_COPY(b);
-    MP_DEST(d, 2 * n + 1, a->f | b->f | MP_UNDEF);
-    dv = d->v; dvl = d->vl;
-    MPX_ZERO(dv, dvl);
-    av = a->v; avl = a->vl;
-    bv = b->v; bvl = b->vl;
-    mv = mm->m->v; mvl = mm->m->vl;
-    y = *bv;
-
-    /* --- Montgomery multiplication phase --- */
-
-    i = 0;
-    mi = mm->mi->v[0];
-    while (i < n && av < avl) {
-      mpw x = *av++;
-      mpw u = MPW((*dv + x * y) * mi);
-      MPX_UMLAN(dv, dvl, bv, bvl, x);
-      MPX_UMLAN(dv, dvl, mv, mvl, u);
-      dv++;
-      i++;
-    }
-
-    /* --- Simpler Montgomery reduction phase --- */
-
-    while (i < n) {
-      mpw u = MPW(*dv * mi);
-      MPX_UMLAN(dv, dvl, mv, mvl, u);
-      dv++;
-      i++;
-    }
-
-    /* --- Done --- */
-
-    memmove(d->v, dv, MPWS(dvl - dv));
-    d->vl -= dv - d->v;
-    if (MPX_UCMP(d->v, d->vl, >=, mm->m->v, mm->m->vl))
-      mpx_usub(d->v, d->vl, d->v, d->vl, mm->m->v, mm->m->vl);
-    if ((a->f ^ b->f) & MP_NEG)
-      mpx_usub(d->v, d->vl, mm->m->v, mm->m->vl, d->v, d->vl);
-    MP_SHRINK(d);
-    d->f = (a->f | b->f) & MP_BURN;
-    MP_DROP(a);
-    MP_DROP(b);
-  }
-
-  return (d);
-}
-
-#endif
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-static int tcreate(dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  mp *mi = *(mp **)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *r2 = *(mp **)v[3].buf;
-
-  mpmont mm;
-  int ok = 1;
-
-  mpmont_create(&mm, m);
-
-  if (mm.mi->v[0] != mi->v[0]) {
-    fprintf(stderr, "\n*** bad mi: found %lu, expected %lu",
-           (unsigned long)mm.mi->v[0], (unsigned long)mi->v[0]);
-    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  if (!MP_EQ(mm.r, r)) {
-    fputs("\n*** bad r", stderr);
-    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\nexpected ", stderr); mp_writefile(r, stderr, 10);
-    fputs("\n  found ", stderr); mp_writefile(mm.r, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  if (!MP_EQ(mm.r2, r2)) {
-    fputs("\n*** bad r2", stderr);
-    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\nexpected ", stderr); mp_writefile(r2, stderr, 10);
-    fputs("\n  found ", stderr); mp_writefile(mm.r2, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  MP_DROP(m);
-  MP_DROP(mi);
-  MP_DROP(r);
-  MP_DROP(r2);
-  mpmont_destroy(&mm);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tmul(dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  mp *a = *(mp **)v[1].buf;
-  mp *b = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  int ok = 1;
-
-  mpmont mm;
-  mpmont_create(&mm, m);
-
-  {
-    mp *qr = mp_mul(MP_NEW, a, b);
-    mp_div(0, &qr, qr, m);
-
-    if (!MP_EQ(qr, r)) {
-      fputs("\n*** classical modmul failed", stderr);
-      fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
-      fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
-      fputs("\n b = ", stderr); mp_writefile(b, stderr, 10);
-      fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
-      fputs("\nqr = ", stderr); mp_writefile(qr, stderr, 10);
-      fputc('\n', stderr);
-      ok = 0;
-    }
-
-    mp_drop(qr);
-  }
-
-  {
-    mp *ar = mpmont_mul(&mm, MP_NEW, a, mm.r2);
-    mp *br = mpmont_mul(&mm, MP_NEW, b, mm.r2);
-    mp *mr = mpmont_mul(&mm, MP_NEW, ar, br);
-    mr = mpmont_reduce(&mm, mr, mr);
-    if (!MP_EQ(mr, r)) {
-      fputs("\n*** montgomery modmul failed", stderr);
-      fputs("\n m = ", stderr); mp_writefile(m, stderr, 10);
-      fputs("\n a = ", stderr); mp_writefile(a, stderr, 10);
-      fputs("\n b = ", stderr); mp_writefile(b, stderr, 10);
-      fputs("\n r = ", stderr); mp_writefile(r, stderr, 10);
-      fputs("\nmr = ", stderr); mp_writefile(mr, stderr, 10);
-      fputc('\n', stderr);
-      ok = 0;
-    }
-    MP_DROP(ar); MP_DROP(br);
-    mp_drop(mr);
-  }
-
-
-  MP_DROP(m);
-  MP_DROP(a);
-  MP_DROP(b);
-  MP_DROP(r);
-  mpmont_destroy(&mm);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return ok;
-}
-
-static test_chunk tests[] = {
-  { "create", tcreate, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { "mul", tmul, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } },
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mpmont");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpmont.h b/mpmont.h
deleted file mode 100644 (file)
index 745cf5a..0000000
--- a/mpmont.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Montgomery reduction
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPMONT_H
-#define CATACOMB_MPMONT_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Notes on Montgomery reduction -------------------------------------*
- *
- * Given a little bit of precomputation, Montgomery reduction enables modular
- * reductions of products to be calculated rather rapidly, without recourse
- * to annoying things like division.
- *
- * Before starting, you need to do a little work.  In particular, the
- * following things need to be worked out:
- *
- *   * %$m$%, which is the modulus you'll be working with.  This must be odd,
- *     otherwise the whole thing doesn't work.  You're better off using
- *     Barrett reduction if your modulus might be even.
- *
- *   * %$b$%, the radix of the number system you're in (here, it's
- *     @MPW_MAX + 1@).
- *
- *   * %$-m^{-1} \bmod b$%, a useful number for the reduction step.  (This
- *     means that the modulus mustn't be even.  This shouldn't be a problem.)
- *
- *   * %$R = b^n > m > b^{n - 1}$%, or at least %$\log_2 R$%.
- *
- *   * %$R \bmod m$% and %$R^2 \bmod m$%, which are useful when doing
- *     calculations such as exponentiation.
- *
- * The result of a Montgomery reduction of %$x$% is %$x R^{-1} \bmod m$%,
- * which doesn't look ever-so useful.  The trick is to initially apply a
- * factor of %$R$% to all of your numbers so that when you multiply and
- * perform a Montgomery reduction you get %$(x R \cdot y R) R^{-1} \bmod m$%,
- * which is just %$x y R \bmod m$%.  Thanks to distributivity, even additions
- * and subtractions can be performed on numbers in this form -- the extra
- * factor of %$R$% just runs through all the calculations until it's finally
- * stripped out by a final reduction operation.
- */
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- A Montgomery reduction context --- */
-
-typedef struct mpmont {
-  mp *m;                               /* Modulus */
-  mp *mi;                              /* %$-m^{-1} \bmod R$% */
-  size_t n;                            /* %$\log_b R$% */
-  mp *r, *r2;                          /* %$R \bmod m$%, %$R^2 \bmod m$% */
-} mpmont;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mpmont_create@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *m@ = modulus to use
- *
- * Returns:    Zero on success, nonzero on error.
- *
- * Use:                Initializes a Montgomery reduction context ready for use.
- *             The argument @m@ must be a positive odd integer.
- */
-
-extern int mpmont_create(mpmont */*mm*/, mp */*m*/);
-
-/* --- @mpmont_destroy@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to a Montgomery reduction context
- *
- * Returns:    ---
- *
- * Use:                Disposes of a context when it's no longer of any use to
- *             anyone.
- */
-
-extern void mpmont_destroy(mpmont */*mm*/);
-
-/* --- @mpmont_reduce@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = destination
- *             @mp *a@ = source, assumed positive
- *
- * Returns:    Result, %$a R^{-1} \bmod m$%.
- */
-
-extern mp *mpmont_reduce(mpmont */*mm*/, mp */*d*/, mp */*a*/);
-
-/* --- @mpmont_mul@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = destination
- *             @mp *a, *b@ = sources, assumed positive
- *
- * Returns:    Result, %$a b R^{-1} \bmod m$%.
- */
-
-extern mp *mpmont_mul(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*b*/);
-
-/* --- @mpmont_expr@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$(a R^{-1})^e R \bmod m$%.  This is useful if
- *             further modular arithmetic is to be performed on the result.
- */
-
-extern mp *mpmont_expr(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*e*/);
-
-/* --- @mpmont_exp@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e \bmod m$%.
- */
-
-extern mp *mpmont_exp(mpmont */*mm*/, mp */*d*/, mp */*a*/, mp */*e*/);
-
-/* --- @mpmont_mexpr@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = fake destination
- *             @const mp_expfactor *f@ = pointer to array of factors
- *             @size_t n@ = number of factors supplied
- *
- * Returns:    If the bases are %$g_0, g_1, \ldots, g_{n-1}$% and the
- *             exponents are %$e_0, e_1, \ldots, e_{n-1}$% then the result
- *             is:
- *
- *             %$g_0^{e_0} g_1^{e_1} \ldots g_{n-1}^{e_{n-1}} \bmod m$%
- *
- *
- *             except that the %$g_i$% and result are in Montgomery form.
- */
-
-extern mp *mpmont_mexpr(mpmont */*mm*/, mp */*d*/,
-                       const mp_expfactor */*f*/, size_t /*n*/);
-
-/* --- @mpmont_mexp@ --- *
- *
- * Arguments:  @mpmont *mm@ = pointer to Montgomery reduction context
- *             @mp *d@ = fake destination
- *             @const mp_expfactor *f@ = pointer to array of factors
- *             @size_t n@ = number of factors supplied
- *
- * Returns:    Product of bases raised to exponents, all mod @m@.
- *
- * Use:                Convenient interface over @mpmont_mexpr@.
- */
-
-extern mp *mpmont_mexp(mpmont */*mm*/, mp */*d*/,
-                      const mp_expfactor */*f*/, size_t /*n*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpmul.c b/mpmul.c
deleted file mode 100644 (file)
index 1f932b0..0000000
--- a/mpmul.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpmul.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Multiply many small numbers together
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpint.h"
-#include "mpmul.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpmul_init@ --- *
- *
- * Arguments:  @mpmul *b@ = pointer to multiplier context to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a big multiplier context for use.
- */
-
-void mpmul_init(mpmul *b)
-{
-  b->i = 0;
-}
-
-/* --- @mpmul_add@ --- *
- *
- * Arguments:  @mpmul *b@ = pointer to multiplier context
- *             @mp *x@ = the next factor to multiply in
- *
- * Returns:    ---
- *
- * Use:                Contributes another factor to the mix.  It's important that
- *             the integer lasts at least as long as the multiplication
- *             context; this sort of rules out @mp_build@ integers.
- */
-
-#define HWM (MPMUL_DEPTH - 20)
-#define LWM (MPMUL_DEPTH / 2)
-
-void mpmul_add(mpmul *b, mp *x)
-{
-  size_t i = b->i;
-
-  /* --- Now do the reduction step --- */
-
-  x = MP_COPY(x);
-
-  while (i > 0) {
-    if (MP_LEN(b->v[i - 1]) > MP_LEN(x))
-      break;
-    i--;
-    x = mp_mul(x, x, b->v[i]);
-    MP_DROP(b->v[i]);
-  }
-
-  if (i > HWM) {
-    while (i > LWM || (i > 0 && MP_LEN(b->v[i - 1]) <= MP_LEN(x))) {
-      i--;
-      x = mp_mul(x, x, b->v[i]);
-      MP_DROP(b->v[i]);
-    }
-  }
-
-  b->v[i++] = x;
-  b->i = i;
-}
-
-/* --- @mpmul_done@ --- *
- *
- * Arguments:  @mpmul *b@ = pointer to big multiplication context
- *
- * Returns:    The product of all the numbers contributed.
- *
- * Use:                Returns a (large) product of numbers.  The context is
- *             deallocated.
- */
-
-mp *mpmul_done(mpmul *b)
-{
-  size_t i = b->i;
-  mp *x;
-
-  if (!i)
-    return (MP_ONE);
-  i--;
-  x = b->v[i];
-  while (i > 0) {
-    i--;
-    x = mp_mul(x, x, b->v[i]);
-    MP_DROP(b->v[i]);
-  }
-  return (x);
-}
-
-/* --- @mp_factorial@ --- *
- *
- * Arguments:  @unsigned long i@ = number whose factorial should be
- *                     computed.
- *
- * Returns:    The requested factorial.
- */
-
-mp *mp_factorial(unsigned long i)
-{
-  unsigned long j;
-  mp *x = MP_NEW;
-  mpmul b = MPMUL_INIT;
-
-  for (j = 1; j <= i; j++) {
-    x = mp_fromulong(x, j);
-    mpmul_add(&b, x);
-  }
-  mp_drop(x);
-  return (mpmul_done(&b));
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int vfact(dstr *v)
-{
-  unsigned long x = *(unsigned long *)v[0].buf;
-  mp *fx = *(mp **)v[1].buf;
-  mp *y = mp_factorial(x);
-  int ok = 1;
-  if (!MP_EQ(fx, y)) {
-    fprintf(stderr, "factorial failed\n");
-    MP_FPRINTF(stderr, (stderr, "%lu! = ", x), fx);
-    MP_EPRINT("result", y);
-    ok = 0;
-  }
-  mp_drop(fx);
-  mp_drop(y);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "factorial", vfact, { &type_ulong, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, tests, SRCDIR "/tests/mp");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpmul.h b/mpmul.h
deleted file mode 100644 (file)
index bd1f156..0000000
--- a/mpmul.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpmul.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Multiply many small numbers together
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_MPMUL_H
-#define CATACOMB_MPMUL_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-/* --- How the algorithm works --- *
- *
- * Multiplication on large integers is least wasteful when the numbers
- * multiplied are approximately the same size.  When a new multiplier is
- * added to the system, we push it onto a stack.  Then we `reduce' the stack:
- * while the value on the top of the stack is not shorter than the value
- * below it, replace the top two elements by their product.
- *
- * Let %$b$% be the radix of our multiprecision integers, and let %$Z$% be
- * the maximum number of digits.  Then the largest integer we can represent
- * is %$M - 1 = b^Z - 1$%.  We could assume that all of the integers we're
- * given are about the same size.  This would give us the same upper bound as
- * that derived in `mptext.c'.
- *
- * However, we're in less control over our inputs.  In particular, if a
- * sequence of integers with strictly decreasing lengths is input then we're
- * sunk.  Suppose that the stack contains, from top to bottom, %$b^i$%,
- * %$b^{i+1}$%, ..., %$b^n$%.  The final product will therefore be
- * %$p = b^{(n+i)(n-i+1)/2}$%.  We must now find the maximum stack depth
- * %$d = n - i$% such that %$p > M$%.
- *
- * Taking logs of both sides gives that %$(d + 2 i)(d + 1) > 2 Z$%.  We can
- * maximize %$d$% by taking %$i = 0$%, which gives that %$d^2 + d > 2 Z$%, so
- * %$d$% must be approximately %$(\sqrt{8 Z + 1} - 1)/2$%, which is
- * uncomfortably large.
- *
- * We compromise by choosing double the `mptext' bound and imposing high- and
- * low-water marks for forced reduction.
- */
-
-#define MPMUL_DEPTH (2 * (CHAR_BIT * sizeof(size_t) + 10))
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct mpmul {
-  size_t i;
-  mp *v[MPMUL_DEPTH];
-} mpmul;
-
-#define MPMUL_INIT { 0 }
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mpmul_init@ --- *
- *
- * Arguments:  @mpmul *b@ = pointer to multiplier context to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a big multiplier context for use.
- */
-
-extern void mpmul_init(mpmul */*b*/);
-
-/* --- @mpmul_add@ --- *
- *
- * Arguments:  @mpmul *b@ = pointer to multiplier context
- *             @mp *x@ = the next factor to multiply in
- *
- * Returns:    ---
- *
- * Use:                Contributes another factor to the mix.  It's important that
- *             the integer lasts at least as long as the multiplication
- *             context; this sort of rules out @mp_build@ integers.
- */
-
-extern void mpmul_add(mpmul */*b*/, mp */*x*/);
-
-/* --- @mpmul_done@ --- *
- *
- * Arguments:  @mpmul *b@ = pointer to big multiplication context
- *
- * Returns:    The product of all the numbers contributed.
- *
- * Use:                Returns a (large) product of numbers.  The context is
- *             deallocated.
- */
-
-extern mp *mpmul_done(mpmul */*b*/);
-
-/* --- @mp_factorial@ --- *
- *
- * Arguments:  @unsigned long i@ = number whose factorial should be
- *                     computed.
- *
- * Returns:    The requested factorial.
- */
-
-extern mp *mp_factorial(unsigned long /*i*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mprand.c b/mprand.c
deleted file mode 100644 (file)
index c0f9675..0000000
--- a/mprand.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mprand.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate a random multiprecision integer
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/alloc.h>
-
-#include "grand.h"
-#include "mp.h"
-#include "mprand.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mprand@ --- *
- *
- * Arguments:  @mp *d@ = destination integer
- *             @unsigned b@ = number of bits
- *             @grand *r@ = pointer to random number source
- *             @mpw or@ = mask to OR with low-order bits
- *
- * Returns:    A random integer with the requested number of bits.
- *
- * Use:                Constructs an arbitrarily large pseudorandom integer.
- *             Assuming that the generator @r@ is good, the result is
- *             uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%.
- *             The result is then ORred with the given @or@ value.  This
- *             will often be 1, to make the result odd.
- */
-
-mp *mprand(mp *d, unsigned b, grand *r, mpw or)
-{
-  size_t sz = (b + 7) >> 3;
-  arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global;
-  octet *v = x_alloc(a, sz);
-  unsigned m;
-
-  /* --- Fill buffer with random data --- */
-
-  r->ops->fill(r, v, sz);
-
-  /* --- Force into the correct range --- *
-   *
-   * This is slightly tricky.  Oh, well.
-   */
-
-  b = (b - 1) & 7;
-  m = (1 << b);
-  v[0] = (v[0] & (m - 1)) | m;
-
-  /* --- Mask, load and return --- */
-
-  d = mp_loadb(d, v, sz);
-  d->v[0] |= or;
-  memset(v, 0, sz);
-  x_free(a, v);
-  return (d);
-}
-
-/* --- @mprand_range@ --- *
- *
- * Arguments:  @mp *d@ = destination integer
- *             @mp *l@ = limit for random number
- *             @grand *r@ = random number source
- *             @mpw or@ = mask for low-order bits
- *
- * Returns:    A pseudorandom integer, unformly distributed over the
- *             interval %$[0, l)$%.
- *
- * Use:                Generates a uniformly-distributed pseudorandom number in the
- *             appropriate range.
- */
-
-mp *mprand_range(mp *d, mp *l, grand *r, mpw or)
-{
-  size_t b = mp_bits(l);
-  size_t sz = (b + 7) >> 3;
-  arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global;
-  octet *v = x_alloc(a, sz);
-  unsigned m;
-
-  /* --- The algorithm --- *
-   *
-   * Rather simpler than most.  Find the number of bits in the number %$l$%
-   * (i.e., the integer %$b$% such that %$2^{b - 1} \le l < 2^b$%), and
-   * generate pseudorandom integers with %$n$% bits (but not, unlike in the
-   * function above, with the top bit forced to 1).  If the integer is
-   * greater than or equal to %$l$%, try again.
-   *
-   * This is similar to the algorithms used in @lcrand_range@ and friends,
-   * except that I've forced the `raw' range of the random numbers such that
-   * %$l$% itself is the largest multiple of %$l$% in the range (since, by
-   * the inequality above, %$2^b \le 2l$%).  This removes the need for costly
-   * division and remainder operations.
-   *
-   * As usual, the number of iterations expected is two.
-   */
-
-  b = ((b - 1) & 7) + 1;
-  m = (1 << b) - 1;
-  do {
-    r->ops->fill(r, v, sz);
-    v[0] &= m;
-    d = mp_loadb(d, v, sz);
-    d->v[0] |= or;
-  } while (MP_CMP(d, >=, l));
-
-  /* --- Done --- */
-
-  memset(v, 0, sz);
-  x_free(a, v);
-  return (d);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mprand.h b/mprand.h
deleted file mode 100644 (file)
index cb51e1c..0000000
--- a/mprand.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mprand.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate a random multiprecision integer
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPRAND_H
-#define CATACOMB_MPRAND_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mprand@ --- *
- *
- * Arguments:  @mp *d@ = destination integer
- *             @unsigned b@ = number of bits
- *             @grand *r@ = pointer to random number source
- *             @mpw or@ = mask to OR with low-order bits
- *
- * Returns:    A random integer with the requested number of bits
- *
- * Use:                Constructs an arbitrarily large pseudorandom integer.
- *             Assuming that the generator @r@ is good, the result is
- *             uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%.
- *             The result is then ORred with the given @or@ value.  This
- *             will often be 1, to make the result odd.
- */
-
-extern mp *mprand(mp */*d*/, unsigned /*b*/, grand */*r*/, mpw /*or*/);
-
-/* --- @mprand_range@ --- *
- *
- * Arguments:  @mp *d@ = destination integer
- *             @mp *l@ = limit for random number
- *             @grand *r@ = random number source
- *             @mpw or@ = mask for low-order bits
- *
- * Returns:    A pseudorandom integer, unformly distributed over the
- *             interval %$[0, l)$%.
- *
- * Use:                Generates a uniformly-distributed pseudorandom number in the
- *             appropriate range.
- */
-
-extern mp *mprand_range(mp */*d*/, mp */*l*/, grand */*r*/, mpw /*or*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpreduce-exp.h b/mpreduce-exp.h
deleted file mode 100644 (file)
index c22fd47..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpreduce-exp.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Exponentiation operations for binary field reduction
- *
- * (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.
- */
-
-#ifndef CATACOMB_MPREDUCE_EXP_H
-#define CATACOMB_MPREDUCE_EXP_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Exponentiation definitions ----------------------------------------*/
-
-#define EXP_TYPE mp *
-
-#define EXP_COPY(d, x) d = MP_COPY(x)
-#define EXP_DROP(x) MP_DROP(x)
-
-#define EXP_MUL(a, x) do {                                             \
-  mp *t = mp_mul(spare, a, x);                                         \
-  spare = a;                                                           \
-  a = mpreduce_do(mr, t, t);                                           \
-} while (0)
-
-#define EXP_SQR(a) do {                                                        \
-  mp *t = mp_sqr(spare, a);                                            \
-  spare = a;                                                           \
-  a = mpreduce_do(mr, t, t);                                           \
-} while (0)
-
-#define EXP_FIX(x)
-
-#define EXP_SETMUL(d, x, y) do {                                       \
-  d = mp_mul(MP_NEW, x, y);                                            \
-  d = mpreduce_do(mr, d, d);                                           \
-} while (0)
-
-#define EXP_SETSQR(d, x) do {                                          \
-  d = mp_sqr(MP_NEW, x);                                               \
-  d = mpreduce_do(mr, d, d);                                           \
-} while (0)
-
-#include "exp.h"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpreduce.c b/mpreduce.c
deleted file mode 100644 (file)
index 5016f29..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Efficient reduction modulo nice primes
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/darray.h>
-#include <mLib/macros.h>
-
-#include "mp.h"
-#include "mpreduce.h"
-#include "mpreduce-exp.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-DA_DECL(instr_v, mpreduce_instr);
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpreduce_create@ --- *
- *
- * Arguments:  @gfreduce *r@ = structure to fill in
- *             @mp *x@ = an integer
- *
- * Returns:    Zero if successful; nonzero on failure.
- *
- * Use:                Initializes a context structure for reduction.
- */
-
-int mpreduce_create(mpreduce *r, mp *p)
-{
-  mpscan sc;
-  enum { Z = 0, Z1 = 2, X = 4, X0 = 6 };
-  unsigned st = Z;
-  instr_v iv = DA_INIT;
-  unsigned long d, i;
-  unsigned op;
-  size_t w, b, bb;
-
-  /* --- Fill in the easy stuff --- */
-
-  if (!MP_POSP(p))
-    return (-1);
-  d = mp_bits(p);
-  r->lim = d/MPW_BITS;
-  r->s = d%MPW_BITS;
-  if (r->s)
-    r->lim++;
-  r->p = mp_copy(p);
-
-  /* --- Stash a new instruction --- */
-
-#define INSTR(op_, argx_, argy_) do {                                  \
-  DA_ENSURE(&iv, 1);                                                   \
-  DA(&iv)[DA_LEN(&iv)].op = (op_);                                     \
-  DA(&iv)[DA_LEN(&iv)].argx = (argx_);                                 \
-  DA(&iv)[DA_LEN(&iv)].argy = (argy_);                                 \
-  DA_EXTEND(&iv, 1);                                                   \
-} while (0)
-
-  /* --- Main loop --- *
-   *
-   * A simple state machine decomposes @p@ conveniently into positive and
-   * negative powers of 2.  The pure form of the state machine is left below
-   * for reference (and in case I need inspiration for a NAF exponentiator).
-   */
-
-#ifdef DEBUG
-  for (i = 0, mp_scan(&sc, p); mp_step(&sc); i++) {
-    switch (st | mp_bit(&sc)) {
-      case  Z | 1: st = Z1; break;
-      case Z1 | 0: st =         Z; printf("+ %lu\n", i - 1); break;
-      case Z1 | 1: st =         X; printf("- %lu\n", i - 1); break;
-      case  X | 0: st = X0; break;
-      case X0 | 1: st =         X; printf("- %lu\n", i - 1); break;
-      case X0 | 0: st =         Z; printf("+ %lu\n", i - 1); break;
-    }
-  }
-  if (st >= X) printf("+ %lu\n", i - 1);
-  st = Z;
-#endif
-
-  bb = MPW_BITS - (d + 1)%MPW_BITS;
-  for (i = 0, mp_scan(&sc, p); i < d && mp_step(&sc); i++) {
-    switch (st | mp_bit(&sc)) {
-      case  Z | 1: st = Z1; break;
-      case Z1 | 0: st =         Z; op = MPRI_SUB; goto instr;
-      case Z1 | 1: st =         X; op = MPRI_ADD; goto instr;
-      case  X | 0: st = X0; break;
-      case X0 | 1: st =         X; op = MPRI_ADD; goto instr;
-      case X0 | 0: st =         Z; op = MPRI_SUB; goto instr;
-      instr:
-       w = (d - i)/MPW_BITS + 1;
-       b = (bb + i)%MPW_BITS;
-       INSTR(op | !!b, w, b);
-    }
-  }
-  if (DA_LEN(&iv) && (DA(&iv)[DA_LEN(&iv) - 1].op & ~1u) == MPRI_SUB) {
-    mp_drop(r->p);
-    DA_DESTROY(&iv);
-    return (-1);
-  }
-
-#undef INSTR
-
-  /* --- Wrap up --- */
-
-  r->in = DA_LEN(&iv);
-  if (!r->in)
-    r->iv = 0;
-  else if (!r->s) {
-    r->iv = xmalloc(r->in * sizeof(mpreduce_instr));
-    memcpy(r->iv, DA(&iv), r->in * sizeof(mpreduce_instr));
-  } else {
-    r->iv = xmalloc(r->in * 2 * sizeof(mpreduce_instr));
-    for (i = 0; i < r->in; i++) {
-      r->iv[i] = DA(&iv)[i];
-      op = r->iv[i].op & ~1u;
-      w = r->iv[i].argx;
-      b = r->iv[i].argy;
-      b += r->s;
-      if (b >= MPW_BITS) {
-       b -= MPW_BITS;
-       w--;
-      }
-      if (b) op |= 1;
-      r->iv[i + r->in].op = op;
-      r->iv[i + r->in].argx = w;
-      r->iv[i + r->in].argy = b;
-    }
-  }
-  DA_DESTROY(&iv);
-
-#ifdef DEBUG
-  mpreduce_dump(r, stdout);
-#endif
-  return (0);
-}
-
-/* --- @mpreduce_destroy@ --- *
- *
- * Arguments:  @mpreduce *r@ = structure to free
- *
- * Returns:    ---
- *
- * Use:                Reclaims the resources from a reduction context.
- */
-
-void mpreduce_destroy(mpreduce *r)
-{
-  mp_drop(r->p);
-  if (r->iv) xfree(r->iv);
-}
-
-/* --- @mpreduce_dump@ --- *
- *
- * Arguments:  @mpreduce *r@ = structure to dump
- *             @FILE *fp@ = file to dump on
- *
- * Returns:    ---
- *
- * Use:                Dumps a reduction context.
- */
-
-void mpreduce_dump(mpreduce *r, FILE *fp)
-{
-  size_t i;
-  static const char *opname[] = { "add", "addshift", "sub", "subshift" };
-
-  fprintf(fp, "mod = "); mp_writefile(r->p, fp, 16);
-  fprintf(fp, "\n  lim = %lu; s = %d\n", (unsigned long)r->lim, r->s);
-  for (i = 0; i < r->in; i++) {
-    assert(r->iv[i].op < N(opname));
-    fprintf(fp, "  %s %lu %lu\n",
-           opname[r->iv[i].op],
-           (unsigned long)r->iv[i].argx,
-           (unsigned long)r->iv[i].argy);
-  }
-  if (r->s) {
-    fprintf(fp, "tail end charlie\n");
-    for (i = r->in; i < 2 * r->in; i++) {
-      assert(r->iv[i].op < N(opname));
-      fprintf(fp, "  %s %lu %lu\n",
-             opname[r->iv[i].op],
-             (unsigned long)r->iv[i].argx,
-             (unsigned long)r->iv[i].argy);
-    }
-  }
-}
-
-/* --- @mpreduce_do@ --- *
- *
- * Arguments:  @mpreduce *r@ = reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = source
- *
- * Returns:    Destination, @x@ reduced modulo the reduction poly.
- */
-
-static void run(const mpreduce_instr *i, const mpreduce_instr *il,
-               mpw *v, mpw z)
-{
-  for (; i < il; i++) {
-#ifdef DEBUG
-    mp vv;
-    mp_build(&vv, v - i->argx, v + 1);
-    printf("  0x"); mp_writefile(&vv, stdout, 16);
-    printf(" %c (0x%lx << %u) == 0x",
-          (i->op & ~1u) == MPRI_ADD ? '+' : '-',
-          (unsigned long)z,
-          i->argy);
-#endif
-    switch (i->op) {
-      case MPRI_ADD: MPX_UADDN(v - i->argx, v + 1, z); break;
-      case MPRI_ADDLSL: mpx_uaddnlsl(v - i->argx, v + 1, z, i->argy); break;
-      case MPRI_SUB: MPX_USUBN(v - i->argx, v + 1, z); break;
-      case MPRI_SUBLSL: mpx_usubnlsl(v - i->argx, v + 1, z, i->argy); break;
-      default:
-       abort();
-    }
-#ifdef DEBUG
-    mp_build(&vv, v - i->argx, v + 1);
-    mp_writefile(&vv, stdout, 16);
-    printf("\n");
-#endif
-  }
-}
-
-mp *mpreduce_do(mpreduce *r, mp *d, mp *x)
-{
-  mpw *v, *vl;
-  const mpreduce_instr *il;
-  mpw z;
-
-#ifdef DEBUG
-  mp *_r = 0, *_rr = 0;
-#endif
-
-  /* --- If source is negative, divide --- */
-
-  if (MP_NEGP(x)) {
-    mp_div(0, &d, x, r->p);
-    return (d);
-  }
-
-  /* --- Try to reuse the source's space --- */
-
-  MP_COPY(x);
-  if (d) MP_DROP(d);
-  MP_DEST(x, MP_LEN(x), x->f);
-
-  /* --- Do the reduction --- */
-
-#ifdef DEBUG
-  _r = MP_NEW;
-  mp_div(0, &_r, x, r->p);
-  MP_PRINTX("x", x);
-  _rr = 0;
-#endif
-
-  il = r->iv + r->in;
-  if (MP_LEN(x) >= r->lim) {
-    v = x->v + r->lim;
-    vl = x->vl;
-    while (vl-- > v) {
-      while (*vl) {
-       z = *vl;
-       *vl = 0;
-       run(r->iv, il, vl, z);
-#ifdef DEBUG
-       MP_PRINTX("x", x);
-       mp_div(0, &_rr, x, r->p);
-       assert(MP_EQ(_r, _rr));
-#endif
-      }
-    }
-    if (r->s) {
-      while (*vl >> r->s) {
-       z = *vl >> r->s;
-       *vl &= ((1 << r->s) - 1);
-       run(r->iv + r->in, il + r->in, vl, z);
-#ifdef DEBUG
-       MP_PRINTX("x", x);
-       mp_div(0, &_rr, x, r->p);
-       assert(MP_EQ(_r, _rr));
-#endif
-      }
-    }
-  }
-
-  /* --- Finishing touches --- */
-
-  MP_SHRINK(x);
-  if (MP_CMP(x, >=, r->p))
-    x = mp_sub(x, x, r->p);
-
-  /* --- Done --- */
-
-#ifdef DEBUG
-  assert(MP_EQ(_r, x));
-  mp_drop(_r);
-  mp_drop(_rr);
-#endif
-  return (x);
-}
-
-/* --- @mpreduce_exp@ --- *
- *
- * Arguments:  @mpreduce *mr@ = pointer to reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e \bmod m$%.
- */
-
-mp *mpreduce_exp(mpreduce *mr, mp *d, mp *a, mp *e)
-{
-  mp *x = MP_ONE;
-  mp *spare = (e->f & MP_BURN) ? MP_NEWSEC : MP_NEW;
-
-  MP_SHRINK(e);
-  MP_COPY(a);
-  if (MP_ZEROP(e))
-    ;
-  else {
-    if (MP_NEGP(e))
-      a = mp_modinv(a, a, mr->p);
-    if (MP_LEN(e) < EXP_THRESH)
-      EXP_SIMPLE(x, a, e);
-    else
-      EXP_WINDOW(x, a, e);
-  }
-  mp_drop(a);
-  mp_drop(d);
-  mp_drop(spare);
-  return (x);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-
-#ifdef TEST_RIG
-
-#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
-
-static int vreduce(dstr *v)
-{
-  mp *d = *(mp **)v[0].buf;
-  mp *n = *(mp **)v[1].buf;
-  mp *r = *(mp **)v[2].buf;
-  mp *c;
-  int ok = 1;
-  mpreduce rr;
-
-  mpreduce_create(&rr, d);
-  c = mpreduce_do(&rr, MP_NEW, n);
-  if (!MP_EQ(c, r)) {
-    fprintf(stderr, "\n*** reduction failed\n*** ");
-    mpreduce_dump(&rr, stderr);
-    fprintf(stderr, "\n*** n = "); mp_writefile(n, stderr, 10);
-    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 10);
-    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 10);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  mpreduce_destroy(&rr);
-  mp_drop(n); mp_drop(d); mp_drop(r); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int vmodexp(dstr *v)
-{
-  mp *p = *(mp **)v[0].buf;
-  mp *g = *(mp **)v[1].buf;
-  mp *x = *(mp **)v[2].buf;
-  mp *r = *(mp **)v[3].buf;
-  mp *c;
-  int ok = 1;
-  mpreduce rr;
-
-  mpreduce_create(&rr, p);
-  c = mpreduce_exp(&rr, MP_NEW, g, x);
-  if (!MP_EQ(c, r)) {
-    fprintf(stderr, "\n*** modexp failed\n*** ");
-    fprintf(stderr, "\n*** p = "); mp_writefile(p, stderr, 10);
-    fprintf(stderr, "\n*** g = "); mp_writefile(g, stderr, 10);
-    fprintf(stderr, "\n*** x = "); mp_writefile(x, stderr, 10);
-    fprintf(stderr, "\n*** c = "); mp_writefile(c, stderr, 10);
-    fprintf(stderr, "\n*** r = "); mp_writefile(r, stderr, 10);
-    fprintf(stderr, "\n");
-    ok = 0;
-  }
-  mpreduce_destroy(&rr);
-  mp_drop(p); mp_drop(g); mp_drop(r); mp_drop(x); mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "reduce", vreduce, { &type_mp, &type_mp, &type_mp, 0 } },
-  { "modexp", vmodexp, { &type_mp, &type_mp, &type_mp, &type_mp, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/mpreduce");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpreduce.h b/mpreduce.h
deleted file mode 100644 (file)
index 80037d1..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Efficient reduction modulo nice primes
- *
- * (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.
- */
-
-#ifndef CATACOMB_MPREDUCE_H
-#define CATACOMB_MPREDUCE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct mpreduce_instr {
-  unsigned op;                         /* Instruction opcode */
-  size_t argx, argy;                   /* Immediate arguments */
-} mpreduce_instr;
-
-enum {
-  MPRI_ADD,                            /* Add @p@ offset by @x@ words */
-  MPRI_ADDLSL,                         /* Add @p << y@ offset by @x@ */
-  MPRI_SUB,                            /* Sub @p@ offset by @x@ words */
-  MPRI_SUBLSL,                         /* Sub @p << y@ offset by @x@ */
-  MPRI_MAX
-};
-
-typedef struct mpreduce {
-  size_t lim;                          /* Word containing top bit */
-  unsigned s;                          /* Shift for top word */
-  mp *p;                               /* Copy of the modulus */
-  size_t in;                           /* Number of instruction words */
-  mpreduce_instr *iv;                  /* Vector of instructions */
-} mpreduce;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mpreduce_create@ --- *
- *
- * Arguments:  @gfreduce *r@ = structure to fill in
- *             @mp *x@ = an integer
- *
- * Returns:    Zero for success, nonzero on error.
- *
- * Use:                Initializes a context structure for reduction.
- */
-
-extern int mpreduce_create(mpreduce */*r*/, mp */*p*/);
-
-/* --- @mpreduce_destroy@ --- *
- *
- * Arguments:  @mpreduce *r@ = structure to free
- *
- * Returns:    ---
- *
- * Use:                Reclaims the resources from a reduction context.
- */
-
-extern void mpreduce_destroy(mpreduce */*r*/);
-
-/* --- @mpreduce_dump@ --- *
- *
- * Arguments:  @mpreduce *r@ = structure to dump
- *             @FILE *fp@ = file to dump on
- *
- * Returns:    ---
- *
- * Use:                Dumps a reduction context.
- */
-
-extern void mpreduce_dump(mpreduce */*r*/, FILE */*fp*/);
-
-/* --- @mpreduce_do@ --- *
- *
- * Arguments:  @mpreduce *r@ = reduction context
- *             @mp *d@ = destination
- *             @mp *x@ = source
- *
- * Returns:    Destination, @x@ reduced modulo the reduction poly.
- */
-
-extern mp *mpreduce_do(mpreduce */*r*/, mp */*d*/, mp */*x*/);
-
-/* --- @mpreduce_exp@ --- *
- *
- * Arguments:  @mpreduce *mr@ = pointer to reduction context
- *             @mp *d@ = fake destination
- *             @mp *a@ = base
- *             @mp *e@ = exponent
- *
- * Returns:    Result, %$a^e \bmod m$%.
- */
-
-extern mp *mpreduce_exp(mpreduce */*mr*/, mp */*d*/, mp */*a*/, mp */*e*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpscan.c b/mpscan.c
deleted file mode 100644 (file)
index a939333..0000000
--- a/mpscan.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpscan.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Sequential bit scan of multiprecision integers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mpscan.h"
-
-/*----- Right-to-left scanning --------------------------------------------*/
-
-/* --- @mpscan_initx@ --- *
- *
- * Arguments:  @mpscan *m@ = pointer to bitscanner structure
- *             @const mpw *v, *vl@ = vector of words to scan
- *
- * Returns:    ---
- *
- * Use:                Initializes a bitscanner from a low-level vector-and-length
- *             representation of an integer.  Initially no bit is ready; you
- *             must call @mpscan_step@ before anything useful will come
- *             out.
- */
-
-void mpscan_initx(mpscan *m, const mpw *v, const mpw *vl)
-{
-  MPSCAN_INITX(m, v, vl);
-}
-
-/* --- @mpscan_step@ --- *
- *
- * Arguments:  @mpscan *m@ = pointer to bitscanner
- *
- * Returns:    Nonzero if there is another bit to read.
- *
- * Use:                Steps on to the next bit in the integer.  The macro version
- *             evaluates its argument multiple times.
- */
-
-int mpscan_step(mpscan *m) { return (MPSCAN_STEP(m)); }
-
-/* --- @mpscan_bit@ --- *
- *
- * Arguments:  @const mpscan *m@ = pointer to bitscanner
- *
- * Returns:    The value of the current bit.
- *
- * Use:                Reads the value of the current bit looked at by a
- *             bitscanner.
- */
-
-int mpscan_bit(const mpscan *m) { return (MPSCAN_BIT(m)); }
-
-/*----- Left-to right-scanning --------------------------------------------*/
-
-/* --- @mpscan_rinitx@ --- *
- *
- * Arguments:  @mpscan *m@ = pointer to bitscanner structure
- *             @const mpw *v, *vl@ = vector of words to scan
- *
- * Returns:    ---
- *
- * Use:                Initializes a reverse bitscanner from a low-level
- *             vector-and-length representation of an integer.  Initially no
- *             bit is ready; you must call @mpscan_rstep@ before anything
- *             useful will come out.
- */
-
-void mpscan_rinitx(mpscan *m, const mpw *v, const mpw *vl)
-{
-  MPSCAN_RINITX(m, v, vl);
-}
-
-/* --- @mpscan_rstep@ --- *
- *
- * Arguments:  @mpscan *m@ = pointer to bitscanner
- *
- * Returns:    Nonzero if there is another bit to read.
- *
- * Use:                Steps on to the next bit in the integer.  The macro version
- *             evaluates its argument multiple times.
- */
-
-int mpscan_rstep(mpscan *m) { return (MPSCAN_RSTEP(m)); }
-
-/* --- @mpscan_rbit@ --- *
- *
- * Arguments:  @const mpscan *m@ = pointer to bitscanner
- *
- * Returns:    The value of the current bit.
- *
- * Use:                Reads the value of the current bit looked at by a
- *             reverse bitscanner.
- */
-
-int mpscan_rbit(const mpscan *m) { return (MPSCAN_RBIT(m)); }
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpscan.h b/mpscan.h
deleted file mode 100644 (file)
index 0d02519..0000000
--- a/mpscan.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpscan.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Sequential bit scan of multiprecision integers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPSCAN_H
-#define CATACOMB_MPSCAN_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MPW_H
-#  include "mpw.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct mpscan {
-  const mpw *v, *vl;                   /* Vector of words to scan */
-  mpw w;                               /* Current word to scan */
-  int bits;                            /* Number of bits left in @w@ */
-} mpscan;
-
-/*----- Right-to-left scanning --------------------------------------------*/
-
-/* --- @mpscan_initx@ --- *
- *
- * Arguments:  @mpscan *m@ = pointer to bitscanner structure
- *             @const mpw *v, *vl@ = vector of words to scan
- *
- * Returns:    ---
- *
- * Use:                Initializes a bitscanner from a low-level base-and-limit
- *             representation of an integer.  Initially no bit is ready; you
- *             must call @mpscan_step@ before anything useful will come
- *             out.
- */
-
-#define MPSCAN_INITX(m_, v_, vl_) do {                                 \
-  mpscan *_m = (m_);                                                   \
-  _m->v = (v_);                                                                \
-  _m->vl = (vl_);                                                      \
-  _m->bits = 0;                                                                \
-} while (0)
-
-extern void mpscan_initx(mpscan */*m*/, const mpw */*v*/, const mpw */*vl*/);
-
-/* --- @mpscan_step@ --- *
- *
- * Arguments:  @mpscan *m@ = pointer to bitscanner
- *
- * Returns:    Nonzero if there is another bit to read.
- *
- * Use:                Steps on to the next bit in the integer.  The macro version
- *             evaluates its argument multiple times.
- */
-
-#define MPSCAN_STEP(m)                                                 \
-  ((m)->bits ? ((m)->w >>= 1, (m)->bits--, 1) :                                \
-   (m)->v < (m)->vl ? ((m)->w = *(m)->v++,                             \
-                      (m)->bits = MPW_BITS - 1, 1) :                   \
-   0)
-
-extern int mpscan_step(mpscan */*m*/);
-
-/* --- @mpscan_bit@ --- *
- *
- * Arguments:  @const mpscan *m@ = pointer to bitscanner
- *
- * Returns:    The value of the current bit.
- *
- * Use:                Reads the value of the current bit looked at by a
- *             bitscanner.
- */
-
-#define MPSCAN_BIT(m) ((m)->w & 1)
-
-extern int mpscan_bit(const mpscan */*m*/);
-
-/*----- Left-to right-scanning --------------------------------------------*/
-
-/* --- @mpscan_rinitx@ --- *
- *
- * Arguments:  @mpscan *m@ = pointer to bitscanner structure
- *             @const mpw *v, *vl@ = vector of words to scan
- *
- * Returns:    ---
- *
- * Use:                Initializes a reverse bitscanner from a low-level
- *             vector-and-length representation of an integer.  Initially no
- *             bit is ready; you must call @mpscan_rstep@ before anything
- *             useful will come out.
- */
-
-#define MPSCAN_RINITX(m_, v_, vl_) do {                                        \
-  mpscan *_m = (m_);                                                   \
-  _m->v = (v_);                                                                \
-  _m->vl = (vl_);                                                      \
-  while (_m->vl > _m->v && !_m->vl[-1])                                        \
-    _m->vl--;                                                          \
-  _m->bits = 0;                                                                \
-} while (0)
-
-extern void mpscan_rinitx(mpscan */*m*/,
-                         const mpw */*v*/, const mpw */*vl*/);
-
-/* --- @mpscan_rstep@ --- *
- *
- * Arguments:  @mpscan *m@ = pointer to bitscanner
- *
- * Returns:    Nonzero if there is another bit to read.
- *
- * Use:                Steps on to the next bit in the integer.  The macro version
- *             evaluates its argument multiple times.
- */
-
-#define MPSCAN_RSTEP(m)                                                        \
-  ((m)->bits ? ((m)->w <<= 1, (m)->bits--, 1) :                                \
-   (m)->vl > (m)->v ? ((m)->w = *--(m)->vl,                            \
-                      (m)->bits = MPW_BITS - 1, 1) :                   \
-   0)
-
-extern int mpscan_rstep(mpscan */*m*/);
-
-/* --- @mpscan_rbit@ --- *
- *
- * Arguments:  @const mpscan *m@ = pointer to bitscanner
- *
- * Returns:    The value of the current bit.
- *
- * Use:                Reads the value of the current bit looked at by a
- *             reverse bitscanner.
- */
-
-#define MPSCAN_RBIT(m) (((m)->w >> (MPW_BITS - 1)) & 1)
-
-extern int mpscan_rbit(const mpscan */*m*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mptext-dstr.c b/mptext-dstr.c
deleted file mode 100644 (file)
index 6a9ad68..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mptext-dstr.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Reading and writing large integers on strings
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#include "mptext.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Operations table --- */
-
-static int get(void *p)
-{
-  mptext_dstrctx *c = p;
-  if (c->i >= c->d->len)
-    return (EOF);
-  return ((unsigned char)c->d->buf[c->i++]);
-}
-
-static void unget(int ch, void *p)
-{
-  mptext_dstrctx *c = p;
-  if (ch == EOF || c->i == 0)
-    return;
-  c->i--;
-}
-
-static int put(const char *s, size_t sz, void *p)
-{
-  mptext_dstrctx *c = p;
-  DPUTM(c->d, s, sz);
-  return (0);
-}
-
-const mptext_ops mptext_dstrops = { get, unget, put };
-
-/* --- Convenience functions --- */
-
-mp *mp_readdstr(mp *m, dstr *d, size_t *off, int radix)
-{
-  mptext_dstrctx c;
-  c.d = d;
-  c.i = off ? *off : 0;
-  m = mp_read(m, radix, &mptext_dstrops, &c);
-  if (off)
-    *off = c.i;
-  return (m);
-}
-
-int mp_writedstr(mp *m, dstr *d, int radix)
-{
-  mptext_dstrctx c;
-  int rc;
-  c.d = d;
-  rc = mp_write(m, radix, &mptext_dstrops, &c);
-  DPUTZ(d);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mptext-file.c b/mptext-file.c
deleted file mode 100644 (file)
index 1eb273a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mptext-file.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Reading and writing large integers on files
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-
-#include "mptext.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Operations table --- */
-
-static int get(void *p) { FILE *fp = p; return getc(fp); }
-
-static void unget(int ch, void *p) { FILE *fp = p; ungetc(ch, fp); }
-
-static int put(const char *s, size_t sz, void *p)
-{
-  FILE *fp = p;
-  return (fwrite(s, 1, sz, fp) != sz);
-}
-
-const mptext_ops mptext_fileops = { get, unget, put };
-
-/* --- Convenience functions --- */
-
-mp *mp_readfile(mp *m, FILE *fp, int radix)
-{
-  return mp_read(m, radix, &mptext_fileops, fp);
-}
-
-int mp_writefile(mp *m, FILE *fp, int radix)
-{
-  return mp_write(m, radix, &mptext_fileops, fp);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mptext-len.c b/mptext-len.c
deleted file mode 100644 (file)
index e8142fb..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Work out length of a number's string representation
- *
- * (c) 2002 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mptext.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mptext_len@ --- *
- *
- * Arguments:  @mp *x@ = number to work on
- *             @int r@ = radix the number will be expressed in
- *
- * Returns:    The number of digits needed to represent the number in the
- *             given base.  This will not include space for a leading sign
- *             (use @MP_NEGP@ to check that, or just add one on for luck);
- *             neither will it add space for a terminating null.  In general
- *             the answer will be an overestimate.
- */
-
-size_t mptext_len(mp *x, int r)
-{
-  unsigned long b = mp_bits(x);
-  int s, ss = 2;
-  size_t n;
-  unsigned d = 0;
-
-  /* --- Huh? --- *
-   *
-   * The number of digits is at most %$\lceil b \log 2/\log r \rceil$%.  We
-   * produce an underestimate of %$\log_2 r = \log r/\log 2$% and divide by
-   * that.  How?  By linear interpolation between known points on the curve.
-   * The known points are precisely the powers of 2, so we can find a pair
-   * efficiently by doubling up.  The log curve is convex, so linear
-   * interpolation between points on the curve is always an underestimate.
-   *
-   * The integer maths here is a bit weird, so here's how it works.  If
-   * %$s = 2^d$% is the power of 2 below %$r$% then we want to compute
-   * %$\lceil b/(d + (r - s)/s) \rceil = \lceil (b s)/(s(d - 1) + r \rceil$%
-   * which is %$\lfloor (r + s (b + d - 1) - 1)/(r + s(d - 1)) \rfloor$%.
-   * Gluing the whole computation together like this makes the code hard to
-   * read, but means that there are fewer possibilities for rounding errors
-   * and thus we get a tighter bound.
-   */
-
-  /* --- Find the right pair of points --- */
-
-  if (r < 0) r = -r;
-  do {
-    s = ss;
-    d++;
-    if (r == s) {
-      n = (b + (d - 1))/d;
-      goto done;
-    }
-    ss = s << 1;
-  } while (ss <= r);
-
-  /* --- Do the interpolation --- */
-
-  n = (r + s*(b + d - 1) - 1)/(r + s*(d - 1));
-
-  /* --- Fixups --- */
-
-done:
-  if (!n)
-    n = 1;
-  return (n);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mptext-string.c b/mptext-string.c
deleted file mode 100644 (file)
index ecb8f18..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mptext-string.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Reading and writing large integers on strings
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include "mptext.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- Operations table --- */
-
-static int get(void *p)
-{
-  mptext_stringctx *c = p;
-  if (c->buf >= c->lim)
-    return (EOF);
-  return ((unsigned char)*c->buf++);
-}
-
-static void unget(int ch, void *p)
-{
-  mptext_stringctx *c = p;
-  if (ch != EOF)
-    c->buf--;
-}
-
-static int put(const char *s, size_t sz, void *p)
-{
-  mptext_stringctx *c = p;
-  int rc = 0;
-  if (sz > c->lim - c->buf) {
-    sz = c->lim - c->buf;
-    rc = EOF;
-  }
-  if (sz) {
-    memcpy(c->buf, s, sz);
-    c->buf += sz;
-  }
-  return (rc);
-}
-
-const mptext_ops mptext_stringops = { get, unget, put };
-
-/* --- Convenience functions --- */
-
-mp *mp_readstring(mp *m, const char *p, char **end, int radix)
-{
-  mptext_stringctx c;
-  c.buf = (/*unconst */ char *)p;
-  c.lim = c.buf + strlen(p);
-  m = mp_read(m, radix, &mptext_stringops, &c);
-  if (end)
-    *end = c.buf;
-  return (m);
-}
-
-int mp_writestring(mp *m, char *p, size_t sz, int radix)
-{
-  mptext_stringctx c;
-  int rc;
-  if (!sz)
-    return (0);
-  c.buf = p;
-  c.lim = p + sz - 1;
-  rc = mp_write(m, radix, &mptext_stringops, &c);
-  *c.buf = 0;
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mptext.c b/mptext.c
deleted file mode 100644 (file)
index 8c00e34..0000000
--- a/mptext.c
+++ /dev/null
@@ -1,851 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Textual representation of multiprecision numbers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "mp.h"
-#include "mptext.h"
-#include "paranoia.h"
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-/* --- Maximum recursion depth --- *
- *
- * This is the number of bits in a @size_t@ object.  Why?
- *
- * To see this, let %$b = \textit{MPW\_MAX} + 1$% and let %$Z$% be the
- * largest @size_t@ value.  Then the largest possible @mp@ is %$M - 1$% where
- * %$M = b^Z$%.  Let %$r$% be a radix to read or write.  Since the recursion
- * squares the radix at each step, the highest number reached by the
- * recursion is %$d$%, where:
- *
- *   %$r^{2^d} = b^Z$%.
- *
- * Solving gives that %$d = \lg \log_r b^Z$%.  If %$r = 2$%, this is maximum,
- * so choosing %$d = \lg \lg b^Z = \lg (Z \lg b) = \lg Z + \lg \lg b$%.
- *
- * Expressing %$\lg Z$% as @CHAR_BIT * sizeof(size_t)@ yields an
- * overestimate, since a @size_t@ representation may contain `holes'.
- * Choosing to represent %$\lg \lg b$% by 10 is almost certainly sufficient
- * for `some time to come'.
- */
-
-#define DEPTH (CHAR_BIT * sizeof(size_t) + 10)
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mp_read@ --- *
- *
- * Arguments:  @mp *m@ = destination multiprecision number
- *             @int radix@ = base to assume for data (or zero to guess)
- *             @const mptext_ops *ops@ = pointer to operations block
- *             @void *p@ = data for the operations block
- *
- * Returns:    The integer read, or zero if it didn't work.
- *
- * Use:                Reads an integer from some source.  If the @radix@ is
- *             specified, the number is assumed to be given in that radix,
- *             with the letters `a' (either upper- or lower-case) upwards
- *             standing for digits greater than 9.  Otherwise, base 10 is
- *             assumed unless the number starts with `0' (octal), `0x' (hex)
- *             or `nnn_' (base `nnn').  An arbitrary amount of whitespace
- *             before the number is ignored.
- */
-
-/* --- About the algorithm --- *
- *
- * The algorithm here is rather aggressive.  I maintain an array of
- * successive squarings of the radix, and a stack of partial results, each
- * with a counter attached indicating which radix square to multiply by.
- * Once the item at the top of the stack reaches the same counter level as
- * the next item down, they are combined together and the result is given a
- * counter level one higher than either of the results.
- *
- * Gluing the results together at the end is slightly tricky.  Pay attention
- * to the code.
- *
- * This is more complicated because of the need to handle the slightly
- * bizarre syntax.
- */
-
-mp *mp_read(mp *m, int radix, const mptext_ops *ops, void *p)
-{
-  int ch;                              /* Current char being considered */
-  unsigned f = 0;                      /* Flags about the current number */
-  int r;                               /* Radix to switch over to */
-  mpw rd;                              /* Radix as an @mp@ digit */
-  mp rr;                               /* The @mp@ for the radix */
-  unsigned nf = m ? m->f & MP_BURN : 0;        /* New @mp@ flags */
-
-  /* --- Stacks --- */
-
-  mp *pow[DEPTH];                      /* List of powers */
-  unsigned pows;                       /* Next index to fill */
-  struct { unsigned i; mp *m; } s[DEPTH]; /* Main stack */
-  unsigned sp;                         /* Current stack pointer */
-
-  /* --- Flags --- */
-
-#define f_neg 1u
-#define f_ok 2u
-#define f_start 4u
-
-  /* --- Initialize the stacks --- */
-
-  mp_build(&rr, &rd, &rd + 1);
-  pow[0] = &rr;
-  pows = 1;
-
-  sp = 0;
-
-  /* --- Initialize the destination number --- */
-
-  if (m)
-    MP_DROP(m);
-
-  /* --- Read an initial character --- */
-
-  ch = ops->get(p);
-  if (radix >= 0) {
-    while (isspace(ch))
-      ch = ops->get(p);
-  }
-
-  /* --- Handle an initial sign --- */
-
-  if (radix >= 0 && (ch == '-' || ch == '+')) {
-    if (ch == '-')
-      f |= f_neg;
-    do ch = ops->get(p); while isspace(ch);
-  }
-
-  /* --- If the radix is zero, look for leading zeros --- */
-
-  if (radix > 0) {
-    assert(((void)"ascii radix must be <= 62", radix <= 62));
-    rd = radix;
-    r = -1;
-  } else if (radix < 0) {
-    rd = -radix;
-    assert(((void)"binary radix must fit in a byte", rd <= UCHAR_MAX));
-    r = -1;
-  } else if (ch != '0') {
-    rd = 10;
-    r = 0;
-  } else {
-    ch = ops->get(p);
-    switch (ch) {
-      case 'x':
-       rd = 16;
-       goto prefix;
-      case 'o':
-       rd = 8;
-       goto prefix;
-      case 'b':
-       rd = 2;
-       goto prefix;
-      prefix:
-       ch = ops->get(p);
-       break;
-      default:
-       rd = 8;
-       f |= f_ok;
-    }
-    r = -1;
-  }
-
-  /* --- Use fast algorithm for binary radix --- *
-   *
-   * This is the restart point after having parsed a radix number from the
-   * input.  We check whether the radix is binary, and if so use a fast
-   * algorithm which just stacks the bits up in the right order.
-   */
-
-restart:
-  switch (rd) {
-    unsigned bit;
-
-    case   2: bit = 1; goto bin;
-    case   4: bit = 2; goto bin;
-    case   8: bit = 3; goto bin;
-    case  16: bit = 4; goto bin;
-    case  32: bit = 5; goto bin;
-    case  64: bit = 6; goto bin;
-    case 128: bit = 7; goto bin;
-    default:
-      break;
-
-  /* --- The fast binary algorithm --- *
-   *
-   * We stack bits up starting at the top end of a word.  When one word is
-   * full, we write it to the integer, and start another with the left-over
-   * bits.  When the array in the integer is full, we resize using low-level
-   * calls and copy the current data to the top end.  Finally, we do a single
-   * bit-shift when we know where the end of the number is.
-   */
-
-  bin: {
-    mpw a = 0;
-    unsigned b = MPW_BITS;
-    size_t len, n;
-    mpw *v;
-
-    m = mp_dest(MP_NEW, 1, nf);
-    len = n = m->sz;
-    n = len;
-    v = m->v + n;
-    for (;; ch = ops->get(p)) {
-      unsigned x;
-
-      if (ch < 0)
-       break;
-
-      /* --- Check that the character is a digit and in range --- */
-
-      if (radix < 0)
-       x = ch % rd;
-      else {
-       if (!isalnum(ch))
-         break;
-       if (ch >= '0' && ch <= '9')
-         x = ch - '0';
-       else {
-         if (rd <= 36)
-           ch = tolower(ch);
-         if (ch >= 'a' && ch <= 'z')   /* ASCII dependent! */
-           x = ch - 'a' + 10;
-         else if (ch >= 'A' && ch <= 'Z')
-           x = ch - 'A' + 36;
-         else
-           break;
-       }
-      }
-      if (x >= rd)
-       break;
-
-      /* --- Feed the digit into the accumulator --- */
-
-      f |= f_ok;
-      if (!x && !(f & f_start))
-       continue;
-      f |= f_start;
-      if (b > bit) {
-       b -= bit;
-       a |= MPW(x) << b;
-      } else {
-       a |= MPW(x) >> (bit - b);
-       b += MPW_BITS - bit;
-       *--v = MPW(a);
-       n--;
-       if (!n) {
-         n = len;
-         len <<= 1;
-         v = mpalloc(m->a, len);
-         memcpy(v + n, m->v, MPWS(n));
-         mpfree(m->a, m->v);
-         m->v = v;
-         v = m->v + n;
-       }
-       a = (b < MPW_BITS) ? MPW(x) << b : 0;
-      }
-    }
-
-    /* --- Finish up --- */
-
-    if (!(f & f_ok)) {
-      mp_drop(m);
-      m = 0;
-    } else {
-      *--v = MPW(a);
-      n--;
-      m->sz = len;
-      m->vl = m->v + len;
-      m->f &= ~MP_UNDEF;
-      m = mp_lsr(m, m, (unsigned long)n * MPW_BITS + b);
-    }
-    ops->unget(ch, p);
-    goto done;
-  }}
-
-  /* --- Time to start --- */
-
-  for (;; ch = ops->get(p)) {
-    unsigned x;
-
-    if (ch < 0)
-      break;
-
-    /* --- An underscore indicates a numbered base --- */
-
-    if (ch == '_' && r > 0 && r <= 62) {
-      unsigned i;
-
-      /* --- Clear out the stacks --- */
-
-      for (i = 1; i < pows; i++)
-       MP_DROP(pow[i]);
-      pows = 1;
-      for (i = 0; i < sp; i++)
-       MP_DROP(s[i].m);
-      sp = 0;
-
-      /* --- Restart the search --- */
-
-      rd = r;
-      r = -1;
-      f &= ~f_ok;
-      ch = ops->get(p);
-      goto restart;
-    }
-
-    /* --- Check that the character is a digit and in range --- */
-
-    if (radix < 0)
-      x = ch % rd;
-    else {
-      if (!isalnum(ch))
-       break;
-      if (ch >= '0' && ch <= '9')
-       x = ch - '0';
-      else {
-       if (rd <= 36)
-         ch = tolower(ch);
-       if (ch >= 'a' && ch <= 'z')     /* ASCII dependent! */
-         x = ch - 'a' + 10;
-       else if (ch >= 'A' && ch <= 'Z')
-         x = ch - 'A' + 36;
-       else
-         break;
-      }
-    }
-
-    /* --- Sort out what to do with the character --- */
-
-    if (x >= 10 && r >= 0)
-      r = -1;
-    if (x >= rd)
-      break;
-
-    if (r >= 0)
-      r = r * 10 + x;
-
-    /* --- Stick the character on the end of my integer --- */
-
-    assert(((void)"Number is too unimaginably huge", sp < DEPTH));
-    s[sp].m = m = mp_new(1, nf);
-    m->v[0] = x;
-    s[sp].i = 0;
-
-    /* --- Now grind through the stack --- */
-
-    while (sp > 0 && s[sp - 1].i == s[sp].i) {
-
-      /* --- Combine the top two items --- */
-
-      sp--;
-      m = s[sp].m;
-      m = mp_mul(m, m, pow[s[sp].i]);
-      m = mp_add(m, m, s[sp + 1].m);
-      s[sp].m = m;
-      MP_DROP(s[sp + 1].m);
-      s[sp].i++;
-
-      /* --- Make a new radix power if necessary --- */
-
-      if (s[sp].i >= pows) {
-       assert(((void)"Number is too unimaginably huge", pows < DEPTH));
-       pow[pows] = mp_sqr(MP_NEW, pow[pows - 1]);
-       pows++;
-      }
-    }
-    f |= f_ok;
-    sp++;
-  }
-
-  ops->unget(ch, p);
-
-  /* --- If we're done, compute the rest of the number --- */
-
-  if (f & f_ok) {
-    if (!sp)
-      return (MP_ZERO);
-    else {
-      mp *z = MP_ONE;
-      sp--;
-
-      while (sp > 0) {
-
-       /* --- Combine the top two items --- */
-
-       sp--;
-       m = s[sp].m;
-       z = mp_mul(z, z, pow[s[sp + 1].i]);
-       m = mp_mul(m, m, z);
-       m = mp_add(m, m, s[sp + 1].m);
-       s[sp].m = m;
-       MP_DROP(s[sp + 1].m);
-
-       /* --- Make a new radix power if necessary --- */
-
-       if (s[sp].i >= pows) {
-         assert(((void)"Number is too unimaginably huge", pows < DEPTH));
-         pow[pows] = mp_sqr(MP_NEW, pow[pows - 1]);
-         pows++;
-       }
-      }
-      MP_DROP(z);
-      m = s[0].m;
-    }
-  } else {
-    unsigned i;
-    for (i = 0; i < sp; i++)
-      MP_DROP(s[i].m);
-  }
-
-  /* --- Clear the radix power list --- */
-
-  {
-    unsigned i;
-    for (i = 1; i < pows; i++)
-      MP_DROP(pow[i]);
-  }
-
-  /* --- Bail out if the number was bad --- */
-
-done:
-  if (!(f & f_ok))
-    return (0);
-
-  /* --- Set the sign and return --- */
-
-  if (f & f_neg)
-    m->f |= MP_NEG;
-  MP_SHRINK(m);
-  return (m);
-
-#undef f_start
-#undef f_neg
-#undef f_ok
-}
-
-/* --- @mp_write@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multi-precision integer
- *             @int radix@ = radix to use when writing the number out
- *             @const mptext_ops *ops@ = pointer to an operations block
- *             @void *p@ = data for the operations block
- *
- * Returns:    Zero if it worked, nonzero otherwise.
- *
- * Use:                Writes a large integer in textual form.
- */
-
-/* --- Simple case --- *
- *
- * Use a fixed-sized buffer and single-precision arithmetic to pick off
- * low-order digits.  Put each digit in a buffer, working backwards from the
- * end.  If the buffer becomes full, recurse to get another one.  Ensure that
- * there are at least @z@ digits by writing leading zeroes if there aren't
- * enough real digits.
- */
-
-static int simple(mpw n, int radix, unsigned z,
-                 const mptext_ops *ops, void *p)
-{
-  int rc = 0;
-  char buf[64];
-  unsigned i = sizeof(buf);
-  int rd = radix > 0 ? radix : -radix;
-
-  do {
-    int ch;
-    mpw x;
-
-    x = n % rd;
-    n /= rd;
-    if (radix < 0)
-      ch = x;
-    else if (x < 10)
-      ch = '0' + x;
-    else if (x < 36)                   /* Ascii specific */
-      ch = 'a' + x - 10;
-    else
-      ch = 'A' + x - 36;
-    buf[--i] = ch;
-    if (z)
-      z--;
-  } while (i && n);
-
-  if (n)
-    rc = simple(n, radix, z, ops, p);
-  else {
-    char zbuf[32];
-    memset(zbuf, (radix < 0) ? 0 : '0', sizeof(zbuf));
-    while (!rc && z >= sizeof(zbuf)) {
-      rc = ops->put(zbuf, sizeof(zbuf), p);
-      z -= sizeof(zbuf);
-    }
-    if (!rc && z)
-      rc = ops->put(zbuf, z, p);
-  }
-  if (!rc)
-    rc = ops->put(buf + i, sizeof(buf) - i, p);
-  BURN(buf);
-  return (rc);
-}
-
-/* --- Complicated case --- *
- *
- * If the number is small, fall back to the simple case above.  Otherwise
- * divide and take remainder by current large power of the radix, and emit
- * each separately.  Don't emit a zero quotient.  Be very careful about
- * leading zeroes on the remainder part, because they're deeply significant.
- */
-
-static int complicated(mp *m, int radix, mp **pr, unsigned i, unsigned z,
-                      const mptext_ops *ops, void *p)
-{
-  int rc = 0;
-  mp *q = MP_NEW;
-  unsigned d = 1 << i;
-
-  if (MP_LEN(m) < 2)
-    return (simple(MP_LEN(m) ? m->v[0] : 0, radix, z, ops, p));
-
-  assert(i);
-  mp_div(&q, &m, m, pr[i]);
-  if (MP_ZEROP(q))
-    d = z;
-  else {
-    if (z > d)
-      z -= d;
-    else
-      z = 0;
-    rc = complicated(q, radix, pr, i - 1, z, ops, p);
-  }
-  if (!rc)
-    rc = complicated(m, radix, pr, i - 1, d, ops, p);
-  mp_drop(q);
-  return (rc);
-}
-
-/* --- Binary case --- *
- *
- * Special case for binary output.  Goes much faster.
- */
-
-static int binary(mp *m, int bit, int radix, const mptext_ops *ops, void *p)
-{
-  mpw *v;
-  mpw a;
-  int rc = 0;
-  unsigned b;
-  unsigned mask;
-  unsigned long n;
-  unsigned f = 0;
-  char buf[8], *q;
-  unsigned x;
-  int ch;
-
-#define f_out 1u
-
-  /* --- Work out where to start --- */
-
-  n = mp_bits(m);
-  if (n % bit)
-    n += bit - (n % bit);
-  b = n % MPW_BITS;
-  n /= MPW_BITS;
-
-  if (n >= MP_LEN(m)) {
-    n--;
-    b += MPW_BITS;
-  }
-
-  v = m->v + n;
-  a = *v;
-  mask = (1 << bit) - 1;
-  q = buf;
-
-  /* --- Main code --- */
-
-  for (;;) {
-    if (b > bit) {
-      b -= bit;
-      x = a >> b;
-    } else {
-      x = a << (bit - b);
-      b += MPW_BITS - bit;
-      if (v == m->v)
-       break;
-      a = *--v;
-      if (b < MPW_BITS)
-       x |= a >> b;
-    }
-    x &= mask;
-    if (!x && !(f & f_out))
-      continue;
-
-    if (radix < 0)
-      ch = x;
-    else if (x < 10)
-      ch = '0' + x;
-    else if (x < 36)
-      ch = 'a' + x - 10;               /* Ascii specific */
-    else
-      ch = 'A' + x - 36;
-    *q++ = ch;
-    if (q >= buf + sizeof(buf)) {
-      if ((rc = ops->put(buf, sizeof(buf), p)) != 0)
-       goto done;
-      q = buf;
-    }
-    f |= f_out;
-  }
-
-  x &= mask;
-  if (radix < 0)
-    ch = x;
-  else if (x < 10)
-    ch = '0' + x;
-  else if (x < 36)
-    ch = 'a' + x - 10;                 /* Ascii specific */
-  else
-    ch = 'A' + x - 36;
-  *q++ = ch;
-  rc = ops->put(buf, q - buf, p);
-
-done:
-  mp_drop(m);
-  return (rc);
-
-#undef f_out
-}
-
-/* --- Main driver code --- */
-
-int mp_write(mp *m, int radix, const mptext_ops *ops, void *p)
-{
-  int rc;
-
-  if (MP_EQ(m, MP_ZERO))
-    return (ops->put(radix > 0 ? "0" : "\0", 1, p));
-
-  /* --- Set various things up --- */
-
-  m = MP_COPY(m);
-  MP_SPLIT(m);
-
-  /* --- Check the radix for sensibleness --- */
-
-  if (radix > 0)
-    assert(((void)"ascii radix must be <= 62", radix <= 62));
-  else if (radix < 0)
-    assert(((void)"binary radix must fit in a byte", -radix <= UCHAR_MAX));
-  else
-    assert(((void)"radix can't be zero in mp_write", 0));
-
-  /* --- If the number is negative, sort that out --- */
-
-  if (MP_NEGP(m)) {
-    assert(radix > 0);
-    if (ops->put("-", 1, p))
-      return (EOF);
-    m->f &= ~MP_NEG;
-  }
-
-  /* --- Handle binary radix --- */
-
-  switch (radix) {
-    case   2: case   -2: return (binary(m, 1, radix, ops, p));
-    case   4: case   -4: return (binary(m, 2, radix, ops, p));
-    case   8: case   -8: return (binary(m, 3, radix, ops, p));
-    case  16: case  -16: return (binary(m, 4, radix, ops, p));
-    case  32: case  -32: return (binary(m, 5, radix, ops, p));
-             case  -64: return (binary(m, 6, radix, ops, p));
-             case -128: return (binary(m, 7, radix, ops, p));
-  }
-
-  /* --- If the number is small, do it the easy way --- */
-
-  if (MP_LEN(m) < 2)
-    rc = simple(MP_LEN(m) ? m->v[0] : 0, radix, 0, ops, p);
-
-  /* --- Use a clever algorithm --- *
-   *
-   * Square the radix repeatedly, remembering old results, until I get
-   * something more than half the size of the number @m@.  Use this to divide
-   * the number: the quotient and remainder will be approximately the same
-   * size, and I'll have split them on a digit boundary, so I can just emit
-   * the quotient and remainder recursively, in order.
-   */
-
-  else {
-    mp *pr[DEPTH];
-    size_t target = (MP_LEN(m) + 1) / 2;
-    unsigned i = 0;
-    mp *z = mp_new(1, 0);
-
-    /* --- Set up the exponent table --- */
-
-    z->v[0] = (radix > 0 ? radix : -radix);
-    z->f = 0;
-    for (;;) {
-      assert(((void)"Number is too unimaginably huge", i < DEPTH));
-      pr[i++] = z;
-      if (MP_LEN(z) > target)
-       break;
-      z = mp_sqr(MP_NEW, z);
-    }
-
-    /* --- Write out the answer --- */
-
-    rc = complicated(m, radix, pr, i - 1, 0, ops, p);
-
-    /* --- Tidy away the array --- */
-
-    while (i > 0)
-      mp_drop(pr[--i]);
-  }
-
-  /* --- Tidying up code --- */
-
-  MP_DROP(m);
-  return (rc);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int verify(dstr *v)
-{
-  int ok = 1;
-  int ib = *(int *)v[0].buf, ob = *(int *)v[2].buf;
-  dstr d = DSTR_INIT;
-  size_t off = 0;
-  mp *m = mp_readdstr(MP_NEW, &v[1], &off, ib);
-  if (m) {
-    if (!ob) {
-      fprintf(stderr, "*** unexpected successful parse\n"
-                     "*** input [%2i] =     ", ib);
-      if (ib < 0)
-       type_hex.dump(&v[1], stderr);
-      else
-       fputs(v[1].buf, stderr);
-      mp_writedstr(m, &d, 10);
-      fprintf(stderr, "\n*** (value = %s)\n", d.buf);
-      ok = 0;
-    } else {
-      mp_writedstr(m, &d, ob);
-      if (d.len != v[3].len || memcmp(d.buf, v[3].buf, d.len) != 0) {
-       fprintf(stderr, "*** failed read or write\n"
-                       "*** input [%2i]      = ", ib);
-       if (ib < 0)
-         type_hex.dump(&v[1], stderr);
-       else
-         fputs(v[1].buf, stderr);
-       fprintf(stderr, "\n*** output [%2i]     = ", ob);
-       if (ob < 0)
-         type_hex.dump(&d, stderr);
-       else
-         fputs(d.buf, stderr);
-       fprintf(stderr, "\n*** expected [%2i]   = ", ob);
-       if (ob < 0)
-         type_hex.dump(&v[3], stderr);
-       else
-         fputs(v[3].buf, stderr);
-       fputc('\n', stderr);
-       ok = 0;
-      }
-    }
-    mp_drop(m);
-  } else {
-    if (ob) {
-      fprintf(stderr, "*** unexpected parse failure\n"
-                     "*** input [%2i]    = ", ib);
-      if (ib < 0)
-       type_hex.dump(&v[1], stderr);
-      else
-       fputs(v[1].buf, stderr);
-      fprintf(stderr, "\n*** expected [%2i]   = ", ob);
-      if (ob < 0)
-       type_hex.dump(&v[3], stderr);
-      else
-       fputs(v[3].buf, stderr);
-      fputc('\n', stderr);
-      ok = 0;
-    }
-  }
-
-  if (v[1].len - off != v[4].len ||
-      memcmp(v[1].buf + off, v[4].buf, v[4].len) != 0) {
-    fprintf(stderr, "*** leftovers incorrect\n"
-                   "*** input [%2i]    = ", ib);
-    if (ib < 0)
-      type_hex.dump(&v[1], stderr);
-    else
-      fputs(v[1].buf, stderr);
-    fprintf(stderr, "\n*** expected `%s'\n"
-                   "*** found `%s'\n",
-           v[4].buf, v[1].buf + off);
-    ok = 0;
-  }
-
-  dstr_destroy(&d);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "mptext-ascii", verify,
-    { &type_int, &type_string, &type_int, &type_string, &type_string, 0 } },
-  { "mptext-bin-in", verify,
-    { &type_int, &type_hex, &type_int, &type_string, &type_string, 0 } },
-  { "mptext-bin-out", verify,
-    { &type_int, &type_string, &type_int, &type_hex, &type_string, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/mptext");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mptext.h b/mptext.h
deleted file mode 100644 (file)
index dade3cf..0000000
--- a/mptext.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Textual representation of multiprecision numbers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPTEXT_H
-#define CATACOMB_MPTEXT_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct mptext_ops {
-  int (*get)(void */*p*/);
-  void (*unget)(int /*ch*/, void */*p*/);
-  int (*put)(const char */*s*/, size_t /*len*/, void */*p*/);
-} mptext_ops;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @mp_read@ --- *
- *
- * Arguments:  @mp *m@ = destination multiprecision number
- *             @int radix@ = base to assume for data (or zero to guess)
- *             @const mptext_ops *ops@ = pointer to operations block
- *             @void *p@ = data for the operations block
- *
- * Returns:    The integer read, or zero if it didn't work.
- *
- * Use:                Reads an integer from some source.  If the @radix@ is
- *             specified, the number is assumed to be given in that radix,
- *             with the letters `a' (either upper- or lower-case) upwards
- *             standing for digits greater than 9.  Otherwise, base 10 is
- *             assumed unless the number starts with `0' (octal), `0x' (hex)
- *             or `nnn_' (base `nnn').  An arbitrary amount of whitespace
- *             before the number is ignored.
- */
-
-extern mp *mp_read(mp */*m*/, int /*radix*/,
-                  const mptext_ops */*ops*/, void */*p*/);
-
-/* --- @mp_write@ --- *
- *
- * Arguments:  @mp *m@ = pointer to a multi-precision integer
- *             @int radix@ = radix to use when writing the number out
- *             @const mptext_ops *ops@ = pointer to an operations block
- *             @void *p@ = data for the operations block
- *
- * Returns:    Zero if it worked, nonzero otherwise.
- *
- * Use:                Writes a large integer in textual form.
- */
-
-extern int mp_write(mp */*m*/, int /*radix*/,
-                   const mptext_ops */*ops*/, void */*p*/);
-
-/* --- @mptext_len@ --- *
- *
- * Arguments:  @mp *x@ = number to work on
- *             @int r@ = radix the number will be expressed in
- *
- * Returns:    The number of digits needed to represent the number in the
- *             given base.  This will not include space for a leading sign
- *             (use @MP_NEGP@ to check that, or just add one on for luck);
- *             neither will it add space for a terminating null.  In general
- *             the answer will be an overestimate.
- */
-
-extern size_t mptext_len(mp */*x*/, int /*r*/);
-
-/*----- File I/O ----------------------------------------------------------*/
-
-#include <stdio.h>
-
-/* --- Operations table --- *
- *
- * The @mptext_fileops@ expect the pointer argument to be a @FILE *@.
- */
-
-extern const mptext_ops mptext_fileops;
-
-/* --- Convenience functions --- */
-
-extern mp *mp_readfile(mp */*m*/, FILE */*fp*/, int /*radix*/);
-extern int mp_writefile(mp */*m*/, FILE */*fp*/, int /*radix*/);
-
-#define MP_DOFPRINTFR(fp, args, m, r) do {                             \
-  fprintf args;                                                                \
-  if (m)                                                               \
-    mp_writefile(m, fp, r);                                            \
-  else                                                                 \
-    fputs("<null>", fp);                                               \
-  fputc('\n', fp);                                                     \
-} while (0)
-
-#define MP_DOFPRINTR(fp, name, m, r)                                   \
-  MP_DOFPRINTFR(fp, (fp, "%s = ", name), m, r)
-
-#define MP_PRINT(name, m) MP_DOFPRINTR(stdout, name, m, 10)
-#define MP_EPRINT(name, m) MP_DOFPRINTR(stderr, name, m, 10)
-#define MP_PRINTX(name, m) MP_DOFPRINTR(stdout, name, m, 16)
-#define MP_EPRINTX(name, m) MP_DOFPRINTR(stderr, name, m, 16)
-
-#define MP_FPRINTF(fp, args, m) MP_DOFPRINTFR(fp, args, m, 10)
-#define MP_FPRINTFX(fp, args, m) MP_DOFPRINTFR(fp, args, m, 16)
-
-/*----- String I/O --------------------------------------------------------*/
-
-/* --- Context format --- */
-
-typedef struct mptext_stringctx {
-  char *buf;
-  char *lim;
-} mptext_stringctx;
-
-/* --- Operations table --- */
-
-extern const mptext_ops mptext_stringops;
-
-/* --- Convenience functions --- */
-
-extern mp *mp_readstring(mp */*m*/, const char */*p*/, char **/*end*/,
-                        int /*radix*/);
-extern int mp_writestring(mp */*m*/, char */*p*/, size_t /*sz*/,
-                         int /*radix*/);
-
-/*----- Dynamic string I/O ------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-/* --- Context format --- */
-
-typedef struct mptext_dstrctx {
-  dstr *d;
-  size_t i;
-} mptext_dstrctx;
-
-/* --- Operations table --- */
-
-extern const mptext_ops mptext_dstrops;
-
-/* --- Convenience functions --- */
-
-extern mp *mp_readdstr(mp */*m*/, dstr */*d*/, size_t */*off*/,
-                      int /*radix*/);
-extern int mp_writedstr(mp */*m*/, dstr */*d*/, int /*radix*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mptypes.c b/mptypes.c
deleted file mode 100644 (file)
index eb8b975..0000000
--- a/mptypes.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generate `mptypes.h' header file for current architecture
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _GNU_SOURCE
-#include "config.h"
-
-#include <stdio.h>
-#include <limits.h>
-#if __STDC_VERSION__ >= 199900l
-#  include <stdint.h>
-#  include <inttypes.h>
-#endif
-
-/*----- Data types --------------------------------------------------------*/
-
-/* --- Hack for GCC --- *
- *
- * WG14 in their infinite wisdom decided not to use the GCC constant name.
- */
-
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)
-#  define EXT __extension__
-#else
-#  define EXT
-#endif
-
-#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
-#  define ULLONG_MAX ULONG_LONG_MAX
-#endif
-
-/* --- Choose the largest integer type --- */
-
-#if defined(UINTMAX_MAX) && defined(PRIuMAX)
-  typedef uintmax_t umax;
-# define P_UMAX PRIuMAX
-#elif defined(ULLONG_MAX)
-  EXT typedef unsigned long long umax;
-# define P_UMAX "llu"
-#else
-  typedef unsigned long umax;
-# define P_UMAX "lu"
-#endif
-
-/* --- Table of interesting types --- *
- *
- * These are in preference order.
- */
-
-enum {
-  f_stdint = 1u,
-  f_ext = 2u
-};
-
-struct itype {
-  const char *name;
-  const char *suff;
-  umax max;
-  unsigned flags;
-  unsigned bits;
-} tytab[] = {
-  { "unsigned int",            "u",    UINT_MAX,               0 },
-  { "unsigned short",          "u",    USHRT_MAX,              0 },
-  { "unsigned long",           "ul",   ULONG_MAX,              0 },
-#ifdef ULLONG_MAX
-  { "unsigned long long",      "ull",  EXT ULLONG_MAX,         f_ext },
-#endif
-#ifdef UINTMAX_MAX
-  { "uintmax_t",               "u",    UINTMAX_MAX,            f_stdint },
-#endif
-  { 0,                         0 },
-};
-
-typedef struct itype itype;
-
-/*----- Main code ---------------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
-  itype *i;
-  itype *largest, *mpw, *mpd;
-  const static char *extstr = "CATACOMB_MPTYPES_EXTENSION ";
-  unsigned p2;
-
-  /* --- Find the bitcounts --- */
-
-  for (i = tytab; i->name; i++) {
-    unsigned bits;
-    umax u = i->max;
-    for (bits = 0; u; bits++)
-      u >>= 1;
-    i->bits = bits;
-  }
-
-  /* --- Now try to find the interesting types --- *
-   *
-   * The first thing to do is to find the largest type.  Then I find the
-   * `best' type which is less than half that size, and then the `best' type
-   * which is twice as big as that one.
-   */
-
-#if defined(FORCE_MPW_CUSSID)
-  largest = mpd = &tytab[3];
-  mpw = &tytab[2];
-  mpw->bits = 19; mpw->max = 0x7ffff;
-  mpd->bits = 38; mpd->max = 0x3fffffffffll;
-#elif defined(FORCE_MPW_SHORT)
-  largest = mpd = &tytab[2];
-  mpw = &tytab[1];
-  mpw->bits = 16; mpw->max = 0xffff;
-  mpd->bits = 32; mpd->max = 0xffffffff;
-#else
-  largest = tytab;
-  for (i = tytab; i->name; i++) {
-    if (i->bits > largest->bits)
-      largest = i;
-  }
-  for (mpw = 0, i = tytab; i->name; i++) {
-    if (i->bits * 2 <= largest->bits && (!mpw || i->bits > mpw->bits))
-      mpw = i;
-  }
-  if (!mpw)
-    mpw = tytab;
-  for (mpd = 0, i = tytab; i->name; i++) {
-    if (i->bits >= mpw->bits * 2 && (!mpd || i->bits < mpd->bits))
-      mpd = i;
-  }
-  if (!mpd) {
-    static itype w, d;
-    d = w = *mpw;
-    w.bits /= 2; w.max = ~(~((umax)0) << w.bits);
-    d.bits = w.bits * 2; d.max = ~(~((umax)0) << d.bits);
-    mpw = &w; mpd = &d;
-  }
-#endif
-  for (p2 = 1; (p2 << 1) < mpw->bits; p2 <<= 1);
-
-  /* --- Output time --- */
-
-  puts("\
-/* -*-c-*-\n\
- *\n\
- * mptypes.h [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_MPTYPES_H\n\
-#define CATACOMB_MPTYPES_H\n\
-");
-  if ((mpd->flags | mpw->flags) & f_stdint) {
-    puts("\
-#if __STDC_VERSION__ >= 199900l\n\
-#  include <stdint.h>\n\
-#endif\n\
-");
-  }
-  if ((mpd->flags | mpw->flags) & f_ext) {
-    printf("\
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)\n\
-#  define %s __extension__\n\
-#else\n\
-#  define %s\n\
-#endif\n\
-", extstr, extstr);
-  }
-  printf("\
-%stypedef %s mpw;\n\
-#define MPW_BITS %u\n\
-#define MPW_P2 %u\n\
-#define MPW_MAX %s%" P_UMAX "%s\n\
-\n\
-%stypedef %s mpd;\n\
-#define MPD_BITS %u\n\
-#define MPD_MAX %s%" P_UMAX "%s\n\
-\n\
-#endif\n\
-",
-  mpw->flags & f_ext ? extstr : "", mpw->name,
-  mpw->bits, p2,
-  mpw->flags & f_ext ? extstr : "", mpw->max, mpw->suff,
-  mpd->flags & f_ext ? extstr : "", mpd->name,
-  mpd->bits,
-  mpd->flags & f_ext ? extstr : "", mpd->max, mpd->suff);
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpw.h b/mpw.h
deleted file mode 100644 (file)
index e37ea16..0000000
--- a/mpw.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpw.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Very low-level multiprecision definitions
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPW_H
-#define CATACOMB_MPW_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_BITS_H
-#  include <mLib/bits.h>
-#endif
-
-#ifndef CATACOMB_MPTYPES_H
-#  include "mptypes.h"
-#endif
-
-/*----- Useful macros -----------------------------------------------------*/
-
-/* --- @MPW@ --- *
- *
- * Arguments:  @x@ = an unsigned value
- *
- * Use:                Expands to the value of @x@ masked and typecast to a
- *             multiprecision integer word.
- */
-
-#define MPW(x) ((mpw)((x) & MPW_MAX))
-
-/* --- @MPWS@ --- *
- *
- * Arguments:  @n@ = number of words
- *
- * Use:                Expands to the number of bytes occupied by a given number of
- *             words.
- */
-
-#define MPWS(n) ((n) * sizeof(mpw))
-
-/* --- @MPW_RQ@ --- *
- *
- * Arguments:  @sz@ = size of an octet array, in octets
- *
- * Use:                Expands to the number of @mpw@ words required to represent
- *             the number held in the octet array.
- */
-
-#define MPW_RQ(sz) (((sz) * 8 + MPW_BITS - 1) / MPW_BITS)
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/mpx-kmul.c b/mpx-kmul.c
deleted file mode 100644 (file)
index 081de88..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Karatsuba's multiplication algorithm
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include "mpx.h"
-#include "karatsuba.h"
-
-/*----- Tweakables --------------------------------------------------------*/
-
-#ifdef TEST_RIG
-#  undef MPK_THRESH
-#  define MPK_THRESH 4                 /* Smallest possible correct value */
-#endif
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpx_kmul@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
- *             @const mpw *av, *avl@ = pointer to first argument
- *             @const mpw *bv, *bvl@ = pointer to second argument
- *             @mpw *sv, *svl@ = pointer to scratch workspace
- *
- * Returns:    ---
- *
- * Use:                Multiplies two multiprecision integers using Karatsuba's
- *             algorithm.  This is rather faster than traditional long
- *             multiplication (e.g., @mpx_umul@) on large numbers, although
- *             more expensive on small ones.
- *
- *             The destination must be three times as large as the larger
- *             argument.  The scratch space must be five times as large as
- *             the larger argument.
- */
-
-void mpx_kmul(mpw *dv, mpw *dvl,
-             const mpw *av, const mpw *avl,
-             const mpw *bv, const mpw *bvl,
-             mpw *sv, mpw *svl)
-{
-  const mpw *avm, *bvm;
-  size_t m;
-
-  /* --- Dispose of easy cases to @mpx_umul@ --- *
-   *
-   * Karatsuba is only a win on large numbers, because of all the
-   * recursiveness and bookkeeping.  The recursive calls make a quick check
-   * to see whether to bottom out to @mpx_umul@ which should help quite a
-   * lot, but sometimes the only way to know is to make sure...
-   */
-
-  MPX_SHRINK(av, avl);
-  MPX_SHRINK(bv, bvl);
-
-  if (avl - av <= MPK_THRESH || bvl - bv <= MPK_THRESH) {
-    mpx_umul(dv, dvl, av, avl, bv, bvl);
-    return;
-  }
-
-  /* --- How the algorithm works --- *
-   *
-   * Let %$A = xb + y$% and %$B = ub + v$%.  Then, simply by expanding,
-   * %$AB = x u b^2 + b(x v + y u) + y v$%.  That's not helped any, because
-   * I've got four multiplications, each four times easier than the one I
-   * started with.  However, note that I can rewrite the coefficient of %$b$%
-   * as %$xv + yu = (x + y)(u + v) - xu - yv$%.  The terms %$xu$% and %$yv$%
-   * I've already calculated, and that leaves only one more multiplication to
-   * do.  So now I have three multiplications, each four times easier, and
-   * that's a win.
-   */
-
-  /* --- First things --- *
-   *
-   * Sort out where to break the factors in half.  I'll choose the midpoint
-   * of the larger one, since this minimizes the amount of work I have to do
-   * most effectively.
-   */
-
-  if (avl - av > bvl - bv) {
-    m = (avl - av + 1) >> 1;
-    avm = av + m;
-    if (bvl - bv > m)
-      bvm = bv + m;
-    else
-      bvm = bvl;
-  } else {
-    m = (bvl - bv + 1) >> 1;
-    bvm = bv + m;
-    if (avl - av > m)
-      avm = av + m;
-    else
-      avm = avl;
-  }
-
-  /* --- Sort out the middle term --- */
-
-  {
-    mpw *bsv = sv + m + 1, *ssv = bsv + m + 1;
-    mpw *rdv = dv + m, *rdvl = rdv + 2 * (m + 2);
-
-    assert(rdvl <= dvl);
-    assert(ssv <= svl);
-    UADD2(sv, bsv, av, avm, avm, avl);
-    UADD2(bsv, ssv, bv, bvm, bvm, bvl);
-    if (m > MPK_THRESH)
-      mpx_kmul(rdv, rdvl, sv, bsv, bsv, ssv, ssv, svl);
-    else
-      mpx_umul(rdv, rdvl, sv, bsv, bsv, ssv);
-  }
-
-  /* --- Sort out the other two terms --- */
-
-  {
-    mpw *svm = sv + m, *svn = svm + m, *ssv = svn + 4;
-    mpw *tdv = dv + m;
-    mpw *rdv = tdv + m;
-
-    if (avl == avm || bvl == bvm)
-      MPX_ZERO(rdv + m + 1, dvl);
-    else {
-      if (m > MPK_THRESH)
-       mpx_kmul(sv, ssv, avm, avl, bvm, bvl, ssv, svl);
-      else
-       mpx_umul(sv, ssv, avm, avl, bvm, bvl);
-      MPX_COPY(rdv + m + 1, dvl, svm + 1, svn);
-      UADD(rdv, sv, svm + 1);
-      USUB(tdv, sv, svn);
-    }
-
-    if (m > MPK_THRESH)
-      mpx_kmul(sv, ssv, av, avm, bv, bvm, ssv, svl);
-    else
-      mpx_umul(sv, ssv, av, avm, bv, bvm);
-    MPX_COPY(dv, tdv, sv, svm);
-    USUB(tdv, sv, svn);
-    UADD(tdv, svm, svn);
-  }
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/alloc.h>
-#include <mLib/testrig.h>
-
-#define ALLOC(v, vl, sz) do {                                          \
-  size_t _sz = (sz);                                                   \
-  mpw *_vv = xmalloc(MPWS(_sz));                                       \
-  mpw *_vvl = _vv + _sz;                                               \
-  (v) = _vv;                                                           \
-  (vl) = _vvl;                                                         \
-} while (0)
-
-#define LOAD(v, vl, d) do {                                            \
-  const dstr *_d = (d);                                                        \
-  mpw *_v, *_vl;                                                       \
-  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
-  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
-  (v) = _v;                                                            \
-  (vl) = _vl;                                                          \
-} while (0)
-
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-
-static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
-{
-  fputs(msg, stderr);
-  MPX_SHRINK(v, vl);
-  while (v < vl)
-    fprintf(stderr, " %08lx", (unsigned long)*--vl);
-  fputc('\n', stderr);
-}
-
-static int umul(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  mpw *s, *sl;
-  size_t m;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(b, bl, &v[1]);
-  LOAD(c, cl, &v[2]);
-  m = MAX(al - a, bl - b) + 1;
-  ALLOC(d, dl, 3 * m);
-  ALLOC(s, sl, 5 * m);
-
-  mpx_kmul(d, dl, a, al, b, bl, s, sl);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** umul failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("      b", b, bl);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(c); xfree(d); xfree(s);
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/mpx");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpx-ksqr.c b/mpx-ksqr.c
deleted file mode 100644 (file)
index ba7aa18..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Karatsuba-based squaring algorithm
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include "mpx.h"
-#include "karatsuba.h"
-
-/*----- Tweakables --------------------------------------------------------*/
-
-#ifdef TEST_RIG
-#  undef MPK_THRESH
-#  define MPK_THRESH 4
-#endif
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mpx_ksqr@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
- *             @const mpw *av, *avl@ = pointer to first argument
- *             @mpw *sv, *svl@ = pointer to scratch workspace
- *
- * Returns:    ---
- *
- * Use:                Squares a multiprecision integers using something similar to
- *             Karatsuba's multiplication algorithm.  This is rather faster
- *             than traditional long multiplication (e.g., @mpx_umul@) on
- *             large numbers, although more expensive on small ones, and
- *             rather simpler than full-blown Karatsuba multiplication.
- *
- *             The destination must be three times as large as the larger
- *             argument.  The scratch space must be five times as large as
- *             the larger argument.
- */
-
-void mpx_ksqr(mpw *dv, mpw *dvl,
-             const mpw *av, const mpw *avl,
-             mpw *sv, mpw *svl)
-{
-  const mpw *avm;
-  size_t m;
-
-  /* --- Dispose of easy cases to @mpx_usqr@ --- *
-   *
-   * Karatsuba is only a win on large numbers, because of all the
-   * recursiveness and bookkeeping.  The recursive calls make a quick check
-   * to see whether to bottom out to @mpx_usqr@ which should help quite a
-   * lot, but sometimes the only way to know is to make sure...
-   */
-
-  MPX_SHRINK(av, avl);
-
-  if (avl - av <= MPK_THRESH) {
-    mpx_usqr(dv, dvl, av, avl);
-    return;
-  }
-
-  /* --- How the algorithm works --- *
-   *
-   * The identity for squaring is known to all schoolchildren.
-   * Let %$A = xb + y$%.  Then %$A^2 = x^2 b^2 + 2 x y b + y^2$%.  Now,
-   * %$(x + y)^2 - x^2 - y^2 = 2 x y$%, which means I only need to do three
-   * squarings.
-   */
-
-  /* --- First things --- *
-   *
-   * Sort out where to break the factor in half.
-   */
-
-  m = (avl - av + 1) >> 1;
-  avm = av + m;
-
-  /* --- Sort out everything --- */
-
-  {
-    mpw *svm = sv + m, *svn = svm + m, *ssv = svn + 4;
-    mpw *tdv = dv + m;
-    mpw *rdv = tdv + m;
-
-    assert(rdv + m + 4 < dvl);
-    assert(ssv < svl);
-    UADD2(sv, svm, av, avm, avm, avl);
-    if (m > MPK_THRESH)
-      mpx_ksqr(tdv, rdv + m + 4, sv, svm + 1, ssv, svl);
-    else
-      mpx_usqr(tdv, rdv + m + 4, sv, svm + 1);
-
-    if (m > MPK_THRESH)
-      mpx_ksqr(sv, ssv, avm, avl, ssv, svl);
-    else
-      mpx_usqr(sv, ssv, avm, avl);
-    MPX_COPY(rdv + m + 1, dvl, svm + 1, svn);
-    UADD(rdv, sv, svm + 1);
-    USUB(tdv, sv, svn);
-
-    if (m > MPK_THRESH)
-      mpx_ksqr(sv, ssv, av, avm, ssv, svl);
-    else
-      mpx_usqr(sv, ssv, av, avm);
-    MPX_COPY(dv, tdv, sv, svm);
-    UADD(tdv, svm, svn);
-    USUB(tdv, sv, svn);
-  }
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/alloc.h>
-#include <mLib/testrig.h>
-
-#define ALLOC(v, vl, sz) do {                                          \
-  size_t _sz = (sz);                                                   \
-  mpw *_vv = xmalloc(MPWS(_sz));                                       \
-  mpw *_vvl = _vv + _sz;                                               \
-  (v) = _vv;                                                           \
-  (vl) = _vvl;                                                         \
-} while (0)
-
-#define LOAD(v, vl, d) do {                                            \
-  const dstr *_d = (d);                                                        \
-  mpw *_v, *_vl;                                                       \
-  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
-  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
-  (v) = _v;                                                            \
-  (vl) = _vl;                                                          \
-} while (0)
-
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-
-static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
-{
-  fputs(msg, stderr);
-  MPX_SHRINK(v, vl);
-  while (v < vl)
-    fprintf(stderr, " %08lx", (unsigned long)*--vl);
-  fputc('\n', stderr);
-}
-
-static int usqr(dstr *v)
-{
-  mpw *a, *al;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  mpw *s, *sl;
-  size_t m;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(c, cl, &v[1]);
-  m = al - a + 1;
-  ALLOC(d, dl, 3 * m);
-  ALLOC(s, sl, 5 * m);
-
-  mpx_ksqr(d, dl, a, al, s, sl);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** usqr failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(c); xfree(d); xfree(s);
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "usqr", usqr, { &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/mpx");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpx.c b/mpx.c
deleted file mode 100644 (file)
index 29e1ded..0000000
--- a/mpx.c
+++ /dev/null
@@ -1,1739 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Low-level multiprecision arithmetic
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "mptypes.h"
-#include "mpx.h"
-#include "bitops.h"
-
-/*----- Loading and storing -----------------------------------------------*/
-
-/* --- @mpx_storel@ --- *
- *
- * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
- *             @void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Stores an MP in an octet array, least significant octet
- *             first.  High-end octets are silently discarded if there
- *             isn't enough space for them.
- */
-
-void mpx_storel(const mpw *v, const mpw *vl, void *pp, size_t sz)
-{
-  mpw n, w = 0;
-  octet *p = pp, *q = p + sz;
-  unsigned bits = 0;
-
-  while (p < q) {
-    if (bits < 8) {
-      if (v >= vl) {
-       *p++ = U8(w);
-       break;
-      }
-      n = *v++;
-      *p++ = U8(w | n << bits);
-      w = n >> (8 - bits);
-      bits += MPW_BITS - 8;
-    } else {
-      *p++ = U8(w);
-      w >>= 8;
-      bits -= 8;
-    }
-  }
-  memset(p, 0, q - p);
-}
-
-/* --- @mpx_loadl@ --- *
- *
- * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
- *             @const void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Loads an MP in an octet array, least significant octet
- *             first.  High-end octets are ignored if there isn't enough
- *             space for them.
- */
-
-void mpx_loadl(mpw *v, mpw *vl, const void *pp, size_t sz)
-{
-  unsigned n;
-  mpw w = 0;
-  const octet *p = pp, *q = p + sz;
-  unsigned bits = 0;
-
-  if (v >= vl)
-    return;
-  while (p < q) {
-    n = U8(*p++);
-    w |= n << bits;
-    bits += 8;
-    if (bits >= MPW_BITS) {
-      *v++ = MPW(w);
-      w = n >> (MPW_BITS - bits + 8);
-      bits -= MPW_BITS;
-      if (v >= vl)
-       return;
-    }
-  }
-  *v++ = w;
-  MPX_ZERO(v, vl);
-}
-
-/* --- @mpx_storeb@ --- *
- *
- * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
- *             @void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Stores an MP in an octet array, most significant octet
- *             first.  High-end octets are silently discarded if there
- *             isn't enough space for them.
- */
-
-void mpx_storeb(const mpw *v, const mpw *vl, void *pp, size_t sz)
-{
-  mpw n, w = 0;
-  octet *p = pp, *q = p + sz;
-  unsigned bits = 0;
-
-  while (q > p) {
-    if (bits < 8) {
-      if (v >= vl) {
-       *--q = U8(w);
-       break;
-      }
-      n = *v++;
-      *--q = U8(w | n << bits);
-      w = n >> (8 - bits);
-      bits += MPW_BITS - 8;
-    } else {
-      *--q = U8(w);
-      w >>= 8;
-      bits -= 8;
-    }
-  }
-  memset(p, 0, q - p);
-}
-
-/* --- @mpx_loadb@ --- *
- *
- * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
- *             @const void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Loads an MP in an octet array, most significant octet
- *             first.  High-end octets are ignored if there isn't enough
- *             space for them.
- */
-
-void mpx_loadb(mpw *v, mpw *vl, const void *pp, size_t sz)
-{
-  unsigned n;
-  mpw w = 0;
-  const octet *p = pp, *q = p + sz;
-  unsigned bits = 0;
-
-  if (v >= vl)
-    return;
-  while (q > p) {
-    n = U8(*--q);
-    w |= n << bits;
-    bits += 8;
-    if (bits >= MPW_BITS) {
-      *v++ = MPW(w);
-      w = n >> (MPW_BITS - bits + 8);
-      bits -= MPW_BITS;
-      if (v >= vl)
-       return;
-    }
-  }
-  *v++ = w;
-  MPX_ZERO(v, vl);
-}
-
-/* --- @mpx_storel2cn@ --- *
- *
- * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
- *             @void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Stores a negative MP in an octet array, least significant
- *             octet first, as two's complement.  High-end octets are
- *             silently discarded if there isn't enough space for them.
- *             This obviously makes the output bad.
- */
-
-void mpx_storel2cn(const mpw *v, const mpw *vl, void *pp, size_t sz)
-{
-  unsigned c = 1;
-  unsigned b = 0;
-  mpw n, w = 0;
-  octet *p = pp, *q = p + sz;
-  unsigned bits = 0;
-
-  while (p < q) {
-    if (bits < 8) {
-      if (v >= vl) {
-       b = w;
-       break;
-      }
-      n = *v++;
-      b = w | n << bits;
-      w = n >> (8 - bits);
-      bits += MPW_BITS - 8;
-    } else {
-      b = w;
-      w >>= 8;
-      bits -= 8;
-    }
-    b = U8(~b + c);
-    c = c && !b;
-    *p++ = b;
-  }
-  while (p < q) {
-    b = U8(~b + c);
-    c = c && !b;
-    *p++ = b;
-    b = 0;
-  }
-}
-
-/* --- @mpx_loadl2cn@ --- *
- *
- * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
- *             @const void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Loads a negative MP in an octet array, least significant
- *             octet first, as two's complement.  High-end octets are
- *             ignored if there isn't enough space for them.  This probably
- *             means you made the wrong choice coming here.
- */
-
-void mpx_loadl2cn(mpw *v, mpw *vl, const void *pp, size_t sz)
-{
-  unsigned n;
-  unsigned c = 1;
-  mpw w = 0;
-  const octet *p = pp, *q = p + sz;
-  unsigned bits = 0;
-
-  if (v >= vl)
-    return;
-  while (p < q) {
-    n = U8(~(*p++) + c);
-    c = c && !n;
-    w |= n << bits;
-    bits += 8;
-    if (bits >= MPW_BITS) {
-      *v++ = MPW(w);
-      w = n >> (MPW_BITS - bits + 8);
-      bits -= MPW_BITS;
-      if (v >= vl)
-       return;
-    }
-  }
-  *v++ = w;
-  MPX_ZERO(v, vl);
-}
-
-/* --- @mpx_storeb2cn@ --- *
- *
- * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
- *             @void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Stores a negative MP in an octet array, most significant
- *             octet first, as two's complement.  High-end octets are
- *             silently discarded if there isn't enough space for them,
- *             which probably isn't what you meant.
- */
-
-void mpx_storeb2cn(const mpw *v, const mpw *vl, void *pp, size_t sz)
-{
-  mpw n, w = 0;
-  unsigned b = 0;
-  unsigned c = 1;
-  octet *p = pp, *q = p + sz;
-  unsigned bits = 0;
-
-  while (q > p) {
-    if (bits < 8) {
-      if (v >= vl) {
-       b = w;
-       break;
-      }
-      n = *v++;
-      b = w | n << bits;
-      w = n >> (8 - bits);
-      bits += MPW_BITS - 8;
-    } else {
-      b = w;
-      w >>= 8;
-      bits -= 8;
-    }
-    b = U8(~b + c);
-    c = c && !b;
-    *--q = b;
-  }
-  while (q > p) {
-    b = ~b + c;
-    c = c && !(b & 0xff);
-    *--q = b;
-    b = 0;
-  }
-}
-
-/* --- @mpx_loadb2cn@ --- *
- *
- * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
- *             @const void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Loads a negative MP in an octet array, most significant octet
- *             first as two's complement.  High-end octets are ignored if
- *             there isn't enough space for them.  This probably means you
- *             chose this function wrongly.
- */
-
-void mpx_loadb2cn(mpw *v, mpw *vl, const void *pp, size_t sz)
-{
-  unsigned n;
-  unsigned c = 1;
-  mpw w = 0;
-  const octet *p = pp, *q = p + sz;
-  unsigned bits = 0;
-
-  if (v >= vl)
-    return;
-  while (q > p) {
-    n = U8(~(*--q) + c);
-    c = c && !n;
-    w |= n << bits;
-    bits += 8;
-    if (bits >= MPW_BITS) {
-      *v++ = MPW(w);
-      w = n >> (MPW_BITS - bits + 8);
-      bits -= MPW_BITS;
-      if (v >= vl)
-       return;
-    }
-  }
-  *v++ = w;
-  MPX_ZERO(v, vl);
-}
-
-/*----- Logical shifting --------------------------------------------------*/
-
-/* --- @mpx_lsl@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = source vector base and limit
- *             @size_t n@ = number of bit positions to shift by
- *
- * Returns:    ---
- *
- * Use:                Performs a logical shift left operation on an integer.
- */
-
-void mpx_lsl(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
-{
-  size_t nw;
-  unsigned nb;
-
-  /* --- Trivial special case --- */
-
-  if (n == 0)
-    MPX_COPY(dv, dvl, av, avl);
-
-  /* --- Single bit shifting --- */
-
-  else if (n == 1) {
-    mpw w = 0;
-    while (av < avl) {
-      mpw t;
-      if (dv >= dvl)
-       goto done;
-      t = *av++;
-      *dv++ = MPW((t << 1) | w);
-      w = t >> (MPW_BITS - 1);
-    }
-    if (dv >= dvl)
-      goto done;
-    *dv++ = MPW(w);
-    MPX_ZERO(dv, dvl);
-    goto done;
-  }
-
-  /* --- Break out word and bit shifts for more sophisticated work --- */
-
-  nw = n / MPW_BITS;
-  nb = n % MPW_BITS;
-
-  /* --- Handle a shift by a multiple of the word size --- */
-
-  if (nb == 0) {
-    if (nw >= dvl - dv)
-      MPX_ZERO(dv, dvl);
-    else {
-      MPX_COPY(dv + nw, dvl, av, avl);
-      memset(dv, 0, MPWS(nw));
-    }
-  }
-
-  /* --- And finally the difficult case --- *
-   *
-   * This is a little convoluted, because I have to start from the end and
-   * work backwards to avoid overwriting the source, if they're both the same
-   * block of memory.
-   */
-
-  else {
-    mpw w;
-    size_t nr = MPW_BITS - nb;
-    size_t dvn = dvl - dv;
-    size_t avn = avl - av;
-
-    if (dvn <= nw) {
-      MPX_ZERO(dv, dvl);
-      goto done;
-    }
-
-    if (dvn > avn + nw) {
-      size_t off = avn + nw + 1;
-      MPX_ZERO(dv + off, dvl);
-      dvl = dv + off;
-      w = 0;
-    } else {
-      avl = av + dvn - nw;
-      w = *--avl << nb;
-    }
-
-    while (avl > av) {
-      mpw t = *--avl;
-      *--dvl = MPW((t >> nr) | w);
-      w = t << nb;
-    }
-
-    *--dvl = MPW(w);
-    MPX_ZERO(dv, dvl);
-  }
-
-done:;
-}
-
-/* --- @mpx_lslc@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = source vector base and limit
- *             @size_t n@ = number of bit positions to shift by
- *
- * Returns:    ---
- *
- * Use:                Performs a logical shift left operation on an integer, only
- *             it fills in the bits with ones instead of zeroes.
- */
-
-void mpx_lslc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
-{
-  size_t nw;
-  unsigned nb;
-
-  /* --- Trivial special case --- */
-
-  if (n == 0)
-    MPX_COPY(dv, dvl, av, avl);
-
-  /* --- Single bit shifting --- */
-
-  else if (n == 1) {
-    mpw w = 1;
-    while (av < avl) {
-      mpw t;
-      if (dv >= dvl)
-       goto done;
-      t = *av++;
-      *dv++ = MPW((t << 1) | w);
-      w = t >> (MPW_BITS - 1);
-    }
-    if (dv >= dvl)
-      goto done;
-    *dv++ = MPW(w);
-    MPX_ZERO(dv, dvl);
-    goto done;
-  }
-
-  /* --- Break out word and bit shifts for more sophisticated work --- */
-
-  nw = n / MPW_BITS;
-  nb = n % MPW_BITS;
-
-  /* --- Handle a shift by a multiple of the word size --- */
-
-  if (nb == 0) {
-    if (nw >= dvl - dv)
-      MPX_ONE(dv, dvl);
-    else {
-      MPX_COPY(dv + nw, dvl, av, avl);
-      MPX_ONE(dv, dv + nw);
-    }
-  }
-
-  /* --- And finally the difficult case --- *
-   *
-   * This is a little convoluted, because I have to start from the end and
-   * work backwards to avoid overwriting the source, if they're both the same
-   * block of memory.
-   */
-
-  else {
-    mpw w;
-    size_t nr = MPW_BITS - nb;
-    size_t dvn = dvl - dv;
-    size_t avn = avl - av;
-
-    if (dvn <= nw) {
-      MPX_ONE(dv, dvl);
-      goto done;
-    }
-
-    if (dvn > avn + nw) {
-      size_t off = avn + nw + 1;
-      MPX_ZERO(dv + off, dvl);
-      dvl = dv + off;
-      w = 0;
-    } else {
-      avl = av + dvn - nw;
-      w = *--avl << nb;
-    }
-
-    while (avl > av) {
-      mpw t = *--avl;
-      *--dvl = MPW((t >> nr) | w);
-      w = t << nb;
-    }
-
-    *--dvl = MPW((MPW_MAX >> nr) | w);
-    MPX_ONE(dv, dvl);
-  }
-
-done:;
-}
-
-/* --- @mpx_lsr@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = source vector base and limit
- *             @size_t n@ = number of bit positions to shift by
- *
- * Returns:    ---
- *
- * Use:                Performs a logical shift right operation on an integer.
- */
-
-void mpx_lsr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
-{
-  size_t nw;
-  unsigned nb;
-
-  /* --- Trivial special case --- */
-
-  if (n == 0)
-    MPX_COPY(dv, dvl, av, avl);
-
-  /* --- Single bit shifting --- */
-
-  else if (n == 1) {
-    mpw w = av < avl ? *av++ >> 1 : 0;
-    while (av < avl) {
-      mpw t;
-      if (dv >= dvl)
-       goto done;
-      t = *av++;
-      *dv++ = MPW((t << (MPW_BITS - 1)) | w);
-      w = t >> 1;
-    }
-    if (dv >= dvl)
-      goto done;
-    *dv++ = MPW(w);
-    MPX_ZERO(dv, dvl);
-    goto done;
-  }
-
-  /* --- Break out word and bit shifts for more sophisticated work --- */
-
-  nw = n / MPW_BITS;
-  nb = n % MPW_BITS;
-
-  /* --- Handle a shift by a multiple of the word size --- */
-
-  if (nb == 0) {
-    if (nw >= avl - av)
-      MPX_ZERO(dv, dvl);
-    else
-      MPX_COPY(dv, dvl, av + nw, avl);
-  }
-
-  /* --- And finally the difficult case --- */
-
-  else {
-    mpw w;
-    size_t nr = MPW_BITS - nb;
-
-    av += nw;
-    w = av < avl ? *av++ : 0;
-    while (av < avl) {
-      mpw t;
-      if (dv >= dvl)
-       goto done;
-      t = *av++;
-      *dv++ = MPW((w >> nb) | (t << nr));
-      w = t;
-    }
-    if (dv < dvl) {
-      *dv++ = MPW(w >> nb);
-      MPX_ZERO(dv, dvl);
-    }
-  }
-
-done:;
-}
-
-/*----- Bitwise operations ------------------------------------------------*/
-
-/* --- @mpx_bitop@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector
- *             @const mpw *av, *avl@ = first source vector
- *             @const mpw *bv, *bvl@ = second source vector
- *
- * Returns:    ---
- *
- * Use;                Provides the dyadic boolean functions.
- */
-
-#define MPX_BITBINOP(string)                                           \
-                                                                       \
-void mpx_bit##string(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, \
-                    const mpw *bv, const mpw *bvl)                     \
-{                                                                      \
-  MPX_SHRINK(av, avl);                                                 \
-  MPX_SHRINK(bv, bvl);                                                 \
-                                                                       \
-  while (dv < dvl) {                                                   \
-    mpw a, b;                                                          \
-    a = (av < avl) ? *av++ : 0;                                                \
-    b = (bv < bvl) ? *bv++ : 0;                                                \
-    *dv++ = B##string(a, b);                                           \
-  }                                                                    \
-}
-
-MPX_DOBIN(MPX_BITBINOP)
-
-void mpx_not(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl)
-{
-  MPX_SHRINK(av, avl);
-
-  while (dv < dvl) {
-    mpw a;
-    a = (av < avl) ? *av++ : 0;
-    *dv++ = ~a;
-  }
-}
-
-/*----- Unsigned arithmetic -----------------------------------------------*/
-
-/* --- @mpx_2c@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector
- *             @const mpw *v, *vl@ = source vector
- *
- * Returns:    ---
- *
- * Use:                Calculates the two's complement of @v@.
- */
-
-void mpx_2c(mpw *dv, mpw *dvl, const mpw *v, const mpw *vl)
-{
-  mpw c = 0;
-  while (dv < dvl && v < vl)
-    *dv++ = c = MPW(~*v++);
-  if (dv < dvl) {
-    if (c > MPW_MAX / 2)
-      c = MPW(~0);
-    while (dv < dvl)
-      *dv++ = c;
-  }
-  MPX_UADDN(dv, dvl, 1);
-}
-
-/* --- @mpx_ueq@ --- *
- *
- * Arguments:  @const mpw *av, *avl@ = first argument vector base and limit
- *             @const mpw *bv, *bvl@ = second argument vector base and limit
- *
- * Returns:    Nonzero if the two vectors are equal.
- *
- * Use:                Performs an unsigned integer test for equality.
- */
-
-int mpx_ueq(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl)
-{
-  MPX_SHRINK(av, avl);
-  MPX_SHRINK(bv, bvl);
-  if (avl - av != bvl - bv)
-    return (0);
-  while (av < avl) {
-    if (*av++ != *bv++)
-      return (0);
-  }
-  return (1);
-}
-
-/* --- @mpx_ucmp@ --- *
- *
- * Arguments:  @const mpw *av, *avl@ = first argument vector base and limit
- *             @const mpw *bv, *bvl@ = second argument vector base and limit
- *
- * Returns:    Less than, equal to, or greater than zero depending on
- *             whether @a@ is less than, equal to or greater than @b@,
- *             respectively.
- *
- * Use:                Performs an unsigned integer comparison.
- */
-
-int mpx_ucmp(const mpw *av, const mpw *avl, const mpw *bv, const mpw *bvl)
-{
-  MPX_SHRINK(av, avl);
-  MPX_SHRINK(bv, bvl);
-
-  if (avl - av > bvl - bv)
-    return (+1);
-  else if (avl - av < bvl - bv)
-    return (-1);
-  else while (avl > av) {
-    mpw a = *--avl, b = *--bvl;
-    if (a > b)
-      return (+1);
-    else if (a < b)
-      return (-1);
-  }
-  return (0);
-}
-
-/* --- @mpx_uadd@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = first addend vector base and limit
- *             @const mpw *bv, *bvl@ = second addend vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer addition.  If the result overflows
- *             the destination vector, high-order bits are discarded.  This
- *             means that two's complement addition happens more or less for
- *             free, although that's more a side-effect than anything else.
- *             The result vector may be equal to either or both source
- *             vectors, but may not otherwise overlap them.
- */
-
-void mpx_uadd(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,
-             const mpw *bv, const mpw *bvl)
-{
-  mpw c = 0;
-
-  while (av < avl || bv < bvl) {
-    mpw a, b;
-    mpd x;
-    if (dv >= dvl)
-      return;
-    a = (av < avl) ? *av++ : 0;
-    b = (bv < bvl) ? *bv++ : 0;
-    x = (mpd)a + (mpd)b + c;
-    *dv++ = MPW(x);
-    c = x >> MPW_BITS;
-  }
-  if (dv < dvl) {
-    *dv++ = c;
-    MPX_ZERO(dv, dvl);
-  }
-}
-
-/* --- @mpx_uaddn@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = source and destination base and limit
- *             @mpw n@ = other addend
- *
- * Returns:    ---
- *
- * Use:                Adds a small integer to a multiprecision number.
- */
-
-void mpx_uaddn(mpw *dv, mpw *dvl, mpw n) { MPX_UADDN(dv, dvl, n); }
-
-/* --- @mpx_uaddnlsl@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination and first argument vector
- *             @mpw a@ = second argument
- *             @unsigned o@ = offset in bits
- *
- * Returns:    ---
- *
- * Use:                Computes %$d + 2^o a$%.  If the result overflows then
- *             high-order bits are discarded, as usual.  We must have
- *             @0 < o < MPW_BITS@.
- */
-
-void mpx_uaddnlsl(mpw *dv, mpw *dvl, mpw a, unsigned o)
-{
-  mpd x = (mpd)a << o;
-
-  while (x && dv < dvl) {
-    x += *dv;
-    *dv++ = MPW(x);
-    x >>= MPW_BITS;
-  }
-}
-
-/* --- @mpx_usub@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = first argument vector base and limit
- *             @const mpw *bv, *bvl@ = second argument vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer subtraction.  If the result
- *             overflows the destination vector, high-order bits are
- *             discarded.  This means that two's complement subtraction
- *             happens more or less for free, althuogh that's more a side-
- *             effect than anything else.  The result vector may be equal to
- *             either or both source vectors, but may not otherwise overlap
- *             them.
- */
-
-void mpx_usub(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,
-             const mpw *bv, const mpw *bvl)
-{
-  mpw c = 0;
-
-  while (av < avl || bv < bvl) {
-    mpw a, b;
-    mpd x;
-    if (dv >= dvl)
-      return;
-    a = (av < avl) ? *av++ : 0;
-    b = (bv < bvl) ? *bv++ : 0;
-    x = (mpd)a - (mpd)b - c;
-    *dv++ = MPW(x);
-    if (x >> MPW_BITS)
-      c = 1;
-    else
-      c = 0;
-  }
-  if (c)
-    c = MPW_MAX;
-  while (dv < dvl)
-    *dv++ = c;
-}
-
-/* --- @mpx_usubn@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = source and destination base and limit
- *             @n@ = subtrahend
- *
- * Returns:    ---
- *
- * Use:                Subtracts a small integer from a multiprecision number.
- */
-
-void mpx_usubn(mpw *dv, mpw *dvl, mpw n) { MPX_USUBN(dv, dvl, n); }
-
-/* --- @mpx_uaddnlsl@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination and first argument vector
- *             @mpw a@ = second argument
- *             @unsigned o@ = offset in bits
- *
- * Returns:    ---
- *
- * Use:                Computes %$d + 2^o a$%.  If the result overflows then
- *             high-order bits are discarded, as usual.  We must have
- *             @0 < o < MPW_BITS@.
- */
-
-void mpx_usubnlsl(mpw *dv, mpw *dvl, mpw a, unsigned o)
-{
-  mpw b = a >> (MPW_BITS - o);
-  a <<= o;
-
-  if (dv < dvl) {
-    mpd x = (mpd)*dv - MPW(a);
-    *dv++ = MPW(x);
-    if (x >> MPW_BITS)
-      b++;
-    MPX_USUBN(dv, dvl, b);
-  }
-}
-
-/* --- @mpx_umul@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = multiplicand vector base and limit
- *             @const mpw *bv, *bvl@ = multiplier vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer multiplication.  If the result
- *             overflows the desination vector, high-order bits are
- *             discarded.  The result vector may not overlap the argument
- *             vectors in any way.
- */
-
-void mpx_umul(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl,
-             const mpw *bv, const mpw *bvl)
-{
-  /* --- This is probably worthwhile on a multiply --- */
-
-  MPX_SHRINK(av, avl);
-  MPX_SHRINK(bv, bvl);
-
-  /* --- Deal with a multiply by zero --- */
-
-  if (bv == bvl) {
-    MPX_ZERO(dv, dvl);
-    return;
-  }
-
-  /* --- Do the initial multiply and initialize the accumulator --- */
-
-  MPX_UMULN(dv, dvl, av, avl, *bv++);
-
-  /* --- Do the remaining multiply/accumulates --- */
-
-  while (dv < dvl && bv < bvl) {
-    mpw m = *bv++;
-    mpw c = 0;
-    const mpw *avv = av;
-    mpw *dvv = ++dv;
-
-    while (avv < avl) {
-      mpd x;
-      if (dvv >= dvl)
-       goto next;
-      x = (mpd)*dvv + (mpd)m * (mpd)*avv++ + c;
-      *dvv++ = MPW(x);
-      c = x >> MPW_BITS;
-    }
-    MPX_UADDN(dvv, dvl, c);
-  next:;
-  }
-}
-
-/* --- @mpx_umuln@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = multiplicand vector base and limit
- *             @mpw m@ = multiplier
- *
- * Returns:    ---
- *
- * Use:                Multiplies a multiprecision integer by a single-word value.
- *             The destination and source may be equal.  The destination
- *             is completely cleared after use.
- */
-
-void mpx_umuln(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m)
-  { MPX_UMULN(dv, dvl, av, avl, m); }
-
-/* --- @mpx_umlan@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination/accumulator base and limit
- *             @const mpw *av, *avl@ = multiplicand vector base and limit
- *             @mpw m@ = multiplier
- *
- * Returns:    ---
- *
- * Use:                Multiplies a multiprecision integer by a single-word value
- *             and adds the result to an accumulator.
- */
-
-void mpx_umlan(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, mpw m)
-  { MPX_UMLAN(dv, dvl, av, avl, m); }
-
-/* --- @mpx_usqr@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *av@ = source vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer squaring.  The result vector must
- *             not overlap the source vector in any way.
- */
-
-void mpx_usqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl)
-{
-  MPX_ZERO(dv, dvl);
-
-  /* --- Main loop --- */
-
-  while (av < avl) {
-    const mpw *avv = av;
-    mpw *dvv = dv;
-    mpw a = *av;
-    mpd c;
-
-    /* --- Stop if I've run out of destination --- */
-
-    if (dvv >= dvl)
-      break;
-
-    /* --- Work out the square at this point in the proceedings --- */
-
-    {
-      mpd x = (mpd)a * (mpd)a + *dvv;
-      *dvv++ = MPW(x);
-      c = MPW(x >> MPW_BITS);
-    }
-
-    /* --- Now fix up the rest of the vector upwards --- */
-
-    avv++;
-    while (dvv < dvl && avv < avl) {
-      mpd x = (mpd)a * (mpd)*avv++;
-      mpd y = ((x << 1) & MPW_MAX) + c + *dvv;
-      c = (x >> (MPW_BITS - 1)) + (y >> MPW_BITS);
-      *dvv++ = MPW(y);
-    }
-    while (dvv < dvl && c) {
-      mpd x = c + *dvv;
-      *dvv++ = MPW(x);
-      c = x >> MPW_BITS;
-    }
-
-    /* --- Get ready for the next round --- */
-
-    av++;
-    dv += 2;
-  }
-}
-
-/* --- @mpx_udiv@ --- *
- *
- * Arguments:  @mpw *qv, *qvl@ = quotient vector base and limit
- *             @mpw *rv, *rvl@ = dividend/remainder vector base and limit
- *             @const mpw *dv, *dvl@ = divisor vector base and limit
- *             @mpw *sv, *svl@ = scratch workspace
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer division.  If the result overflows
- *             the quotient vector, high-order bits are discarded.  (Clearly
- *             the remainder vector can't overflow.)  The various vectors
- *             may not overlap in any way.  Yes, I know it's a bit odd
- *             requiring the dividend to be in the result position but it
- *             does make some sense really.  The remainder must have
- *             headroom for at least two extra words.  The scratch space
- *             must be at least one word larger than the divisor.
- */
-
-void mpx_udiv(mpw *qv, mpw *qvl, mpw *rv, mpw *rvl,
-             const mpw *dv, const mpw *dvl,
-             mpw *sv, mpw *svl)
-{
-  unsigned norm = 0;
-  size_t scale;
-  mpw d, dd;
-
-  /* --- Initialize the quotient --- */
-
-  MPX_ZERO(qv, qvl);
-
-  /* --- Perform some sanity checks --- */
-
-  MPX_SHRINK(dv, dvl);
-  assert(((void)"division by zero in mpx_udiv", dv < dvl));
-
-  /* --- Normalize the divisor --- *
-   *
-   * The algorithm requires that the divisor be at least two digits long.
-   * This is easy to fix.
-   */
-
-  {
-    unsigned b;
-
-    d = dvl[-1];
-    for (b = MPW_P2; b; b >>= 1) {
-      if (d <= (MPW_MAX >> b)) {
-       d <<= b;
-       norm += b;
-      }
-    }
-    if (dv + 1 == dvl)
-      norm += MPW_BITS;
-  }
-
-  /* --- Normalize the dividend/remainder to match --- */
-
-  if (norm) {
-    mpx_lsl(rv, rvl, rv, rvl, norm);
-    mpx_lsl(sv, svl, dv, dvl, norm);
-    dv = sv;
-    dvl = svl;
-    MPX_SHRINK(dv, dvl);
-  }
-
-  MPX_SHRINK(rv, rvl);
-  d = dvl[-1];
-  dd = dvl[-2];
-
-  /* --- Work out the relative scales --- */
-
-  {
-    size_t rvn = rvl - rv;
-    size_t dvn = dvl - dv;
-
-    /* --- If the divisor is clearly larger, notice this --- */
-
-    if (dvn > rvn) {
-      mpx_lsr(rv, rvl, rv, rvl, norm);
-      return;
-    }
-
-    scale = rvn - dvn;
-  }
-
-  /* --- Calculate the most significant quotient digit --- *
-   *
-   * Because the divisor has its top bit set, this can only happen once.  The
-   * pointer arithmetic is a little contorted, to make sure that the
-   * behaviour is defined.
-   */
-
-  if (MPX_UCMP(rv + scale, rvl, >=, dv, dvl)) {
-    mpx_usub(rv + scale, rvl, rv + scale, rvl, dv, dvl);
-    if (qvl - qv > scale)
-      qv[scale] = 1;
-  }
-
-  /* --- Now for the main loop --- */
-
-  {
-    mpw *rvv = rvl - 2;
-
-    while (scale) {
-      mpw q;
-      mpd rh;
-
-      /* --- Get an estimate for the next quotient digit --- */
-
-      mpw r = rvv[1];
-      mpw rr = rvv[0];
-      mpw rrr = *--rvv;
-
-      scale--;
-      rh = ((mpd)r << MPW_BITS) | rr;
-      if (r == d)
-       q = MPW_MAX;
-      else
-       q = MPW(rh / d);
-
-      /* --- Refine the estimate --- */
-
-      {
-       mpd yh = (mpd)d * q;
-       mpd yy = (mpd)dd * q;
-       mpw yl;
-
-       if (yy > MPW_MAX)
-         yh += yy >> MPW_BITS;
-       yl = MPW(yy);
-
-       while (yh > rh || (yh == rh && yl > rrr)) {
-         q--;
-         yh -= d;
-         if (yl < dd)
-           yh--;
-         yl = MPW(yl - dd);
-       }
-      }
-
-      /* --- Remove a chunk from the dividend --- */
-
-      {
-       mpw *svv;
-       const mpw *dvv;
-       mpw mc = 0, sc = 0;
-
-       /* --- Calculate the size of the chunk --- *
-        *
-        * This does the whole job of calculating @r >> scale - qd@.
-        */
-
-       for (svv = rv + scale, dvv = dv;
-            dvv < dvl && svv < rvl;
-            svv++, dvv++) {
-         mpd x = (mpd)*dvv * (mpd)q + mc;
-         mc = x >> MPW_BITS;
-         x = (mpd)*svv - MPW(x) - sc;
-         *svv = MPW(x);
-         if (x >> MPW_BITS)
-           sc = 1;
-         else
-           sc = 0;
-       }
-
-       if (svv < rvl) {
-         mpd x = (mpd)*svv - mc - sc;
-         *svv++ = MPW(x);
-         if (x >> MPW_BITS)
-           sc = MPW_MAX;
-         else
-           sc = 0;
-         while (svv < rvl)
-           *svv++ = sc;
-       }
-
-       /* --- Fix if the quotient was too large --- *
-        *
-        * This doesn't seem to happen very often.
-        */
-
-       if (rvl[-1] > MPW_MAX / 2) {
-         mpx_uadd(rv + scale, rvl, rv + scale, rvl, dv, dvl);
-         q--;
-       }
-      }
-
-      /* --- Done for another iteration --- */
-
-      if (qvl - qv > scale)
-       qv[scale] = q;
-      r = rr;
-      rr = rrr;
-    }
-  }
-
-  /* --- Now fiddle with unnormalizing and things --- */
-
-  mpx_lsr(rv, rvl, rv, rvl, norm);
-}
-
-/* --- @mpx_udivn@ --- *
- *
- * Arguments:  @mpw *qv, *qvl@ = storage for the quotient (may overlap
- *                     dividend)
- *             @const mpw *rv, *rvl@ = dividend
- *             @mpw d@ = single-precision divisor
- *
- * Returns:    Remainder after divison.
- *
- * Use:                Performs a single-precision division operation.
- */
-
-mpw mpx_udivn(mpw *qv, mpw *qvl, const mpw *rv, const mpw *rvl, mpw d)
-{
-  size_t i;
-  size_t ql = qvl - qv;
-  mpd r = 0;
-
-  i = rvl - rv;
-  while (i > 0) {
-    i--;
-    r = (r << MPW_BITS) | rv[i];
-    if (i < ql)
-      qv[i] = r / d;
-    r %= d;
-  }
-  return (MPW(r));
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#include "mpscan.h"
-
-#define ALLOC(v, vl, sz) do {                                          \
-  size_t _sz = (sz);                                                   \
-  mpw *_vv = xmalloc(MPWS(_sz));                                       \
-  mpw *_vvl = _vv + _sz;                                               \
-  (v) = _vv;                                                           \
-  (vl) = _vvl;                                                         \
-} while (0)
-
-#define LOAD(v, vl, d) do {                                            \
-  const dstr *_d = (d);                                                        \
-  mpw *_v, *_vl;                                                       \
-  ALLOC(_v, _vl, MPW_RQ(_d->len));                                     \
-  mpx_loadb(_v, _vl, _d->buf, _d->len);                                        \
-  (v) = _v;                                                            \
-  (vl) = _vl;                                                          \
-} while (0)
-
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-
-static void dumpbits(const char *msg, const void *pp, size_t sz)
-{
-  const octet *p = pp;
-  fputs(msg, stderr);
-  for (; sz; sz--)
-    fprintf(stderr, " %02x", *p++);
-  fputc('\n', stderr);
-}
-
-static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
-{
-  fputs(msg, stderr);
-  MPX_SHRINK(v, vl);
-  while (v < vl)
-    fprintf(stderr, " %08lx", (unsigned long)*--vl);
-  fputc('\n', stderr);
-}
-
-static int chkscan(const mpw *v, const mpw *vl,
-                  const void *pp, size_t sz, int step)
-{
-  mpscan mps;
-  const octet *p = pp;
-  unsigned bit = 0;
-  int ok = 1;
-
-  mpscan_initx(&mps, v, vl);
-  while (sz) {
-    unsigned x = *p;
-    int i;
-    p += step;
-    for (i = 0; i < 8 && MPSCAN_STEP(&mps); i++) {
-      if (MPSCAN_BIT(&mps) != (x & 1)) {
-       fprintf(stderr,
-               "\n*** error, step %i, bit %u, expected %u, found %u\n",
-               step, bit, x & 1, MPSCAN_BIT(&mps));
-       ok = 0;
-      }
-      x >>= 1;
-      bit++;
-    }
-    sz--;
-  }
-
-  return (ok);
-}
-
-static int loadstore(dstr *v)
-{
-  dstr d = DSTR_INIT;
-  size_t sz = MPW_RQ(v->len) * 2, diff;
-  mpw *m, *ml;
-  int ok = 1;
-
-  dstr_ensure(&d, v->len);
-  m = xmalloc(MPWS(sz));
-
-  for (diff = 0; diff < sz; diff += 5) {
-    size_t oct;
-
-    ml = m + sz - diff;
-
-    mpx_loadl(m, ml, v->buf, v->len);
-    if (!chkscan(m, ml, v->buf, v->len, +1))
-      ok = 0;
-    MPX_OCTETS(oct, m, ml);
-    mpx_storel(m, ml, d.buf, d.sz);
-    if (memcmp(d.buf, v->buf, oct) != 0) {
-      dumpbits("\n*** storel failed", d.buf, d.sz);
-      ok = 0;
-    }
-
-    mpx_loadb(m, ml, v->buf, v->len);
-    if (!chkscan(m, ml, v->buf + v->len - 1, v->len, -1))
-      ok = 0;
-    MPX_OCTETS(oct, m, ml);
-    mpx_storeb(m, ml, d.buf, d.sz);
-    if (memcmp(d.buf + d.sz - oct, v->buf + v->len - oct, oct) != 0) {
-      dumpbits("\n*** storeb failed", d.buf, d.sz);
-      ok = 0;
-    }
-  }
-
-  if (!ok)
-    dumpbits("input data", v->buf, v->len);
-
-  xfree(m);
-  dstr_destroy(&d);
-  return (ok);
-}
-
-static int twocl(dstr *v)
-{
-  dstr d = DSTR_INIT;
-  mpw *m, *ml;
-  size_t sz;
-  int ok = 1;
-
-  sz = v[0].len; if (v[1].len > sz) sz = v[1].len;
-  dstr_ensure(&d, sz);
-
-  sz = MPW_RQ(sz);
-  m = xmalloc(MPWS(sz));
-  ml = m + sz;
-
-  mpx_loadl(m, ml, v[0].buf, v[0].len);
-  mpx_storel2cn(m, ml, d.buf, v[1].len);
-  if (memcmp(d.buf, v[1].buf, v[1].len)) {
-    dumpbits("\n*** storel2cn failed", d.buf, v[1].len);
-    ok = 0;
-  }
-
-  mpx_loadl2cn(m, ml, v[1].buf, v[1].len);
-  mpx_storel(m, ml, d.buf, v[0].len);
-  if (memcmp(d.buf, v[0].buf, v[0].len)) {
-    dumpbits("\n*** loadl2cn failed", d.buf, v[0].len);
-    ok = 0;
-  }
-
-  if (!ok) {
-    dumpbits("pos", v[0].buf, v[0].len);
-    dumpbits("neg", v[1].buf, v[1].len);
-  }
-
-  xfree(m);
-  dstr_destroy(&d);
-
-  return (ok);
-}
-
-static int twocb(dstr *v)
-{
-  dstr d = DSTR_INIT;
-  mpw *m, *ml;
-  size_t sz;
-  int ok = 1;
-
-  sz = v[0].len; if (v[1].len > sz) sz = v[1].len;
-  dstr_ensure(&d, sz);
-
-  sz = MPW_RQ(sz);
-  m = xmalloc(MPWS(sz));
-  ml = m + sz;
-
-  mpx_loadb(m, ml, v[0].buf, v[0].len);
-  mpx_storeb2cn(m, ml, d.buf, v[1].len);
-  if (memcmp(d.buf, v[1].buf, v[1].len)) {
-    dumpbits("\n*** storeb2cn failed", d.buf, v[1].len);
-    ok = 0;
-  }
-
-  mpx_loadb2cn(m, ml, v[1].buf, v[1].len);
-  mpx_storeb(m, ml, d.buf, v[0].len);
-  if (memcmp(d.buf, v[0].buf, v[0].len)) {
-    dumpbits("\n*** loadb2cn failed", d.buf, v[0].len);
-    ok = 0;
-  }
-
-  if (!ok) {
-    dumpbits("pos", v[0].buf, v[0].len);
-    dumpbits("neg", v[1].buf, v[1].len);
-  }
-
-  xfree(m);
-  dstr_destroy(&d);
-
-  return (ok);
-}
-
-static int lsl(dstr *v)
-{
-  mpw *a, *al;
-  int n = *(int *)v[1].buf;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(c, cl, &v[2]);
-  ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS);
-
-  mpx_lsl(d, dl, a, al, n);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** lsl(%i) failed\n", n);
-    dumpmp("      a", a, al);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int lslc(dstr *v)
-{
-  mpw *a, *al;
-  int n = *(int *)v[1].buf;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(c, cl, &v[2]);
-  ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS);
-
-  mpx_lslc(d, dl, a, al, n);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** lslc(%i) failed\n", n);
-    dumpmp("      a", a, al);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int lsr(dstr *v)
-{
-  mpw *a, *al;
-  int n = *(int *)v[1].buf;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(c, cl, &v[2]);
-  ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS + 1);
-
-  mpx_lsr(d, dl, a, al, n);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** lsr(%i) failed\n", n);
-    dumpmp("      a", a, al);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int uadd(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(b, bl, &v[1]);
-  LOAD(c, cl, &v[2]);
-  ALLOC(d, dl, MAX(al - a, bl - b) + 1);
-
-  mpx_uadd(d, dl, a, al, b, bl);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** uadd failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("      b", b, bl);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int usub(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(b, bl, &v[1]);
-  LOAD(c, cl, &v[2]);
-  ALLOC(d, dl, al - a);
-
-  mpx_usub(d, dl, a, al, b, bl);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** usub failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("      b", b, bl);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int umul(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(b, bl, &v[1]);
-  LOAD(c, cl, &v[2]);
-  ALLOC(d, dl, (al - a) + (bl - b));
-
-  mpx_umul(d, dl, a, al, b, bl);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** umul failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("      b", b, bl);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int usqr(dstr *v)
-{
-  mpw *a, *al;
-  mpw *c, *cl;
-  mpw *d, *dl;
-  int ok = 1;
-
-  LOAD(a, al, &v[0]);
-  LOAD(c, cl, &v[1]);
-  ALLOC(d, dl, 2 * (al - a));
-
-  mpx_usqr(d, dl, a, al);
-  if (!mpx_ueq(d, dl, c, cl)) {
-    fprintf(stderr, "\n*** usqr failed\n");
-    dumpmp("      a", a, al);
-    dumpmp("expected", c, cl);
-    dumpmp("  result", d, dl);
-    ok = 0;
-  }
-
-  xfree(a); xfree(c); xfree(d);
-  return (ok);
-}
-
-static int udiv(dstr *v)
-{
-  mpw *a, *al;
-  mpw *b, *bl;
-  mpw *q, *ql;
-  mpw *r, *rl;
-  mpw *qq, *qql;
-  mpw *s, *sl;
-  int ok = 1;
-
-  ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len);
-  LOAD(b, bl, &v[1]);
-  LOAD(q, ql, &v[2]);
-  LOAD(r, rl, &v[3]);
-  ALLOC(qq, qql, al - a);
-  ALLOC(s, sl, (bl - b) + 1);
-
-  mpx_udiv(qq, qql, a, al, b, bl, s, sl);
-  if (!mpx_ueq(qq, qql, q, ql) ||
-      !mpx_ueq(a, al, r, rl)) {
-    fprintf(stderr, "\n*** udiv failed\n");
-    dumpmp(" divisor", b, bl);
-    dumpmp("expect r", r, rl);
-    dumpmp("result r", a, al);
-    dumpmp("expect q", q, ql);
-    dumpmp("result q", qq, qql);
-    ok = 0;
-  }
-
-  xfree(a); xfree(b); xfree(r); xfree(q); xfree(s); xfree(qq);
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "load-store", loadstore, { &type_hex, 0 } },
-  { "2cl", twocl, { &type_hex, &type_hex, } },
-  { "2cb", twocb, { &type_hex, &type_hex, } },
-  { "lsl", lsl, { &type_hex, &type_int, &type_hex, 0 } },
-  { "lslc", lslc, { &type_hex, &type_int, &type_hex, 0 } },
-  { "lsr", lsr, { &type_hex, &type_int, &type_hex, 0 } },
-  { "uadd", uadd, { &type_hex, &type_hex, &type_hex, 0 } },
-  { "usub", usub, { &type_hex, &type_hex, &type_hex, 0 } },
-  { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } },
-  { "usqr", usqr, { &type_hex, &type_hex, 0 } },
-  { "udiv", udiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/mpx");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/mpx.h b/mpx.h
deleted file mode 100644 (file)
index 19f5cc7..0000000
--- a/mpx.h
+++ /dev/null
@@ -1,791 +0,0 @@
-/* -*-c-*-
- *
- * $Id: mpx.h,v 1.18 2004/04/08 01:36:15 mdw Exp $
- *
- * Low level multiprecision arithmetic
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_MPX_H
-#define CATACOMB_MPX_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- The idea ----------------------------------------------------------*
- *
- * This file provides functions and macros which work on vectors of words as
- * unsigned multiprecision integers.  The interface works in terms of base
- * and limit pointers (i.e., a pointer to the start of a vector, and a
- * pointer just past its end) rather than base pointer and length, because
- * that requires more arithmetic and state to work on.
- *
- * The interfaces are slightly bizarre in other ways.  Try to use the
- * higher-level functions where you can: they're rather better designed to
- * actually be friendly and useful.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#ifndef CATACOMB_MPW_H
-#  include "mpw.h"
-#endif
-
-/*----- General manipulation ----------------------------------------------*/
-
-/* --- @MPX_SHRINK@ --- *
- *
- * Arguments:  @const mpw *v@ = pointer to vector of words
- *             @const mpw *vl@ = (updated) current limit of vector
- *
- * Use:                Shrinks down the limit of a multiprecision integer vector.
- */
-
-#define MPX_SHRINK(v, vl) do {                                         \
-  const mpw *_vv = (v), *_vvl = (vl);                                  \
-  while (_vvl > _vv && !_vvl[-1])                                      \
-    _vvl--;                                                            \
-  (vl) = (mpw *)_vvl;                                                  \
-} while (0)
-
-/* --- @MPX_BITS@ --- *
- *
- * Arguments:  @unsigned long b@ = result variable
- *             @const mpw *v@ = pointer to array of words
- *             @const mpw *vl@ = limit of vector (from @MPX_SHRINK@)
- *
- * Use:                Calculates the number of bits in a multiprecision value.
- */
-
-#define MPX_BITS(b, v, vl) do {                                                \
-  const mpw *_v = (v), *_vl = (vl);                                    \
-  MPX_SHRINK(_v, _vl);                                                 \
-  if (_v == _vl)                                                       \
-    (b) = 0;                                                           \
-  else {                                                               \
-    unsigned long _b = MPW_BITS * (_vl - _v - 1) + 1;                  \
-    mpw _w = _vl[-1];                                                  \
-    unsigned _k = MPW_P2;                                              \
-    while (_k) {                                                       \
-      if (_w >> _k) {                                                  \
-       _w >>= _k;                                                      \
-       _b += _k;                                                       \
-      }                                                                        \
-      _k >>= 1;                                                                \
-    }                                                                  \
-    (b) = _b;                                                          \
-  }                                                                    \
-} while (0)
-
-/* --- @MPX_OCTETS@ --- *
- *
- * Arguments:  @size_t o@ = result variable
- *             @const mpw *v, *vl@ = pointer to array of words
- *
- * Use:                Calculates the number of octets in a multiprecision value.
- */
-
-#define MPX_OCTETS(o, v, vl) do {                                      \
-  unsigned long _bb;                                                   \
-  MPX_BITS(_bb, (v), (vl));                                            \
-  (o) = (_bb + 7) >> 3;                                                        \
-} while (0)
-
-/* --- @MPX_OCTETS2C@ --- *
- *
- * Arguments:  @size_t o@ = result variable
- *             @const mpw *v, *vl@ = pointer to array of words
- *
- * Use:                Calculates the number of octets in a multiprecision value, if
- *             you represent it as two's complement.
- */
-
-#define MPX_OCTETS2C(o, v, vl) do {                                    \
-  unsigned long _bb;                                                   \
-  MPX_BITS(_bb, (v), (vl));                                            \
-  (o) = (_bb >> 3) + 1;                                                        \
-} while (0)
-
-/* --- @MPX_COPY@ --- *
- *
- * Arguments:  @dv, dvl@ = destination vector base and limit
- *             @av, avl@ = source vector base and limit
- *
- * Use:                Copies a multiprecision integer.
- */
-
-#define MPX_COPY(dv, dvl, av, avl) do {                                        \
-  mpw *_dv = (dv), *_dvl = (dvl);                                      \
-  size_t _dn = _dvl - _dv;                                             \
-  const mpw *_av = (av), *_avl = (avl);                                        \
-  size_t _an = _avl - _av;                                             \
-  if (_av == _dv) {                                                    \
-    if (_dvl > _avl)                                                   \
-      memset(_dv, 0, MPWS(_dn - _an));                                 \
-  } else if (_an >= _dn)                                               \
-    memmove(_dv, _av, MPWS(_dn));                                      \
-  else {                                                               \
-    memmove(_dv, _av, MPWS(_an));                                      \
-    memset(_dv + _an, 0, MPWS(_dn - _an));                             \
-  }                                                                    \
-} while (0)
-
-/* --- @MPX_ZERO@ --- *
- *
- * Arguments:  @v, vl@ = base and limit of vector to clear
- *
- * Use:                Zeroes the area between the two vector pointers.
- */
-
-#define MPX_ZERO(v, vl) do {                                           \
-  mpw *_v = (v), *_vl = (vl);                                          \
-  if (_v < _vl)                                                                \
-    memset(_v, 0, MPWS(_vl - _v));                                     \
-} while (0)
-
-/* --- @MPX_ONE@ --- *
- *
- * Arguments:  @v, vl@ = base and limit of vector to clear
- *
- * Use:                Fills the area between the two vector pointers with ones.
- */
-
-#define MPX_ONE(v, vl) do {                                            \
-  mpw * _v = (v);                                                      \
-  const mpw *_vl = (vl);                                               \
-  while (_v < _vl)                                                     \
-    *_v++ = MPW_MAX;                                                   \
-} while (0)
-
-/*----- Loading and storing -----------------------------------------------*/
-
-/* --- @mpx_storel@ --- *
- *
- * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
- *             @void *p@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Stores an MP in an octet array, least significant octet
- *             first.  High-end octets are silently discarded if there
- *             isn't enough space for them.
- */
-
-extern void mpx_storel(const mpw */*v*/, const mpw */*vl*/,
-                      void */*p*/, size_t /*sz*/);
-
-/* --- @mpx_loadl@ --- *
- *
- * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
- *             @const void *p@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Loads an MP in an octet array, least significant octet
- *             first.  High-end octets are ignored if there isn't enough
- *             space for them.
- */
-
-extern void mpx_loadl(mpw */*v*/, mpw */*vl*/,
-                     const void */*p*/, size_t /*sz*/);
-
-/* --- @mpx_storeb@ --- *
- *
- * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
- *             @void *p@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Stores an MP in an octet array, most significant octet
- *             first.  High-end octets are silently discarded if there
- *             isn't enough space for them.
- */
-
-extern void mpx_storeb(const mpw */*v*/, const mpw */*vl*/,
-                      void */*p*/, size_t /*sz*/);
-
-/* --- @mpx_loadb@ --- *
- *
- * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
- *             @const void *p@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Loads an MP in an octet array, most significant octet
- *             first.  High-end octets are ignored if there isn't enough
- *             space for them.
- */
-
-extern void mpx_loadb(mpw */*v*/, mpw */*vl*/,
-                     const void */*p*/, size_t /*sz*/);
-
-/* --- @mpx_storel2cn@ --- *
- *
- * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
- *             @void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Stores a negative MP in an octet array, least significant
- *             octet first, as two's complement.  High-end octets are
- *             silently discarded if there isn't enough space for them.
- *             This obviously makes the output bad.
- */
-
-extern void mpx_storel2cn(const mpw */*v*/, const mpw */*vl*/,
-                         void */*p*/, size_t /*sz*/);
-
-/* --- @mpx_loadl2cn@ --- *
- *
- * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
- *             @const void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Loads a negative MP in an octet array, least significant
- *             octet first, as two's complement.  High-end octets are
- *             ignored if there isn't enough space for them.  This probably
- *             means you made the wrong choice coming here.
- */
-
-extern void mpx_loadl2cn(mpw */*v*/, mpw */*vl*/,
-                        const void */*p*/, size_t /*sz*/);
-
-/* --- @mpx_storeb2cn@ --- *
- *
- * Arguments:  @const mpw *v, *vl@ = base and limit of source vector
- *             @void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Stores a negative MP in an octet array, most significant
- *             octet first, as two's complement.  High-end octets are
- *             silently discarded if there isn't enough space for them,
- *             which probably isn't what you meant.
- */
-
-extern void mpx_storeb2cn(const mpw */*v*/, const mpw */*vl*/,
-                         void */*p*/, size_t /*sz*/);
-
-/* --- @mpx_loadb2cn@ --- *
- *
- * Arguments:  @mpw *v, *vl@ = base and limit of destination vector
- *             @const void *pp@ = pointer to octet array
- *             @size_t sz@ = size of octet array
- *
- * Returns:    ---
- *
- * Use:                Loads a negative MP in an octet array, most significant octet
- *             first as two's complement.  High-end octets are ignored if
- *             there isn't enough space for them.  This probably means you
- *             chose this function wrongly.
- */
-
-extern void mpx_loadb2cn(mpw */*v*/, mpw */*vl*/,
-                        const void */*p*/, size_t /*sz*/);
-
-
-/*----- Logical shifting --------------------------------------------------*/
-
-/* --- @mpx_lsl@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = source vector base and limit
- *             @size_t n@ = number of bit positions to shift by
- *
- * Returns:    ---
- *
- * Use:                Performs a logical shift left operation on an integer.
- */
-
-extern void mpx_lsl(mpw */*dv*/, mpw */*dvl*/,
-                   const mpw */*av*/, const mpw */*avl*/,
-                   size_t /*n*/);
-
-/* --- @mpx_lslc@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = source vector base and limit
- *             @size_t n@ = number of bit positions to shift by
- *
- * Returns:    ---
- *
- * Use:                Performs a logical shift left operation on an integer, only
- *             it fills in the bits with ones instead of zeroes.
- */
-
-extern void mpx_lslc(mpw */*dv*/, mpw */*dvl*/,
-                    const mpw */*av*/, const mpw */*avl*/,
-                    size_t /*n*/);
-
-/* --- @mpx_lsr@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = source vector base and limit
- *             @size_t n@ = number of bit positions to shift by
- *
- * Returns:    ---
- *
- * Use:                Performs a logical shift right operation on an integer.
- */
-
-extern void mpx_lsr(mpw */*dv*/, mpw */*dvl*/,
-                   const mpw */*av*/, const mpw */*avl*/,
-                   size_t /*n*/);
-
-/*----- Bitwise operations ------------------------------------------------*/
-
-/* --- @mpx_bitop@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector
- *             @const mpw *av, *avl@ = first source vector
- *             @const mpw *bv, *bvl@ = second source vector
- *
- * Returns:    ---
- *
- * Use:                Provide the dyadic boolean functions.  The functions are
- *             named after the truth table they generate:
- *
- *                     a:      0011
- *                     b:      0101
- *                     @mpx_bitXXXX@
- */
-
-#define MPX_DOBIN(what)                                                        \
-  what(0000) what(0001) what(0010) what(0011)                          \
-  what(0100) what(0101) what(0110) what(0111)                          \
-  what(1000) what(1001) what(1010) what(1011)                          \
-  what(1100) what(1101) what(1110) what(1111)
-
-#define MPX_BITDECL(string)                                            \
-  extern void mpx_bit##string(mpw */*dv*/, mpw */*dvl*/,               \
-                             const mpw */*av*/, const mpw */*avl*/,    \
-                             const mpw */*bv*/, const mpw */*bvl*/);
-MPX_DOBIN(MPX_BITDECL)
-
-/* --- @mpx_[n]and@, @mpx_[n]or@, @mpx_xor@ --- *
- *
- * Synonyms for the commonly-used functions above.
- */
-
-#define mpx_and         mpx_bit0001
-#define mpx_or  mpx_bit0111
-#define mpx_nand mpx_bit1110
-#define mpx_nor         mpx_bit1000
-#define mpx_xor         mpx_bit0110
-
-/* --- @mpx_not@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector
- *             @const mpw *av, *avl@ = first source vector
- *
- * Returns:    ---
- *
- * Use;                Bitwise NOT.
- */
-
-extern void mpx_not(mpw */*dv*/, mpw */*dvl*/,
-                   const mpw */*av*/, const mpw */*avl*/);
-
-/*----- Unsigned arithmetic -----------------------------------------------*/
-
-/* --- @mpx_2c@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector
- *             @const mpw *v, *vl@ = source vector
- *
- * Returns:    ---
- *
- * Use:                Calculates the two's complement of @v@.
- */
-
-extern void mpx_2c(mpw */*dv*/, mpw */*dvl*/,
-                  const mpw */*v*/, const mpw */*vl*/);
-
-/* --- @mpx_ueq@ --- *
- *
- * Arguments:  @const mpw *av, *avl@ = first argument vector base and limit
- *             @const mpw *bv, *bvl@ = second argument vector base and limit
- *
- * Returns:    Nonzero if the two vectors are equal.
- *
- * Use:                Performs an unsigned integer test for equality.
- */
-
-extern int mpx_ueq(const mpw */*av*/, const mpw */*avl*/,
-                  const mpw */*bv*/, const mpw */*bvl*/);
-
-/* --- @mpx_ucmp@ --- *
- *
- * Arguments:  @const mpw *av, *avl@ = first argument vector base and limit
- *             @const mpw *bv, *bvl@ = second argument vector base and limit
- *
- * Returns:    Less than, equal to, or greater than zero depending on
- *             whether @a@ is less than, equal to or greater than @b@,
- *             respectively.
- *
- * Use:                Performs an unsigned integer comparison.
- */
-
-#define MPX_UCMP(av, avl, op, dv, dvl)                                 \
-  (mpx_ucmp((av), (avl), (dv), (dvl)) op 0)
-
-extern int mpx_ucmp(const mpw */*av*/, const mpw */*avl*/,
-                   const mpw */*bv*/, const mpw */*bvl*/);
-
-/* --- @mpx_uadd@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = first addend vector base and limit
- *             @const mpw *bv, *bvl@ = second addend vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer addition.  If the result overflows
- *             the destination vector, high-order bits are discarded.  This
- *             means that two's complement addition happens more or less for
- *             free, although that's more a side-effect than anything else.
- *             The result vector may be equal to either or both source
- *             vectors, but may not otherwise overlap them.
- */
-
-extern void mpx_uadd(mpw */*dv*/, mpw */*dvl*/,
-                    const mpw */*av*/, const mpw */*avl*/,
-                    const mpw */*bv*/, const mpw */*bvl*/);
-
-/* --- @mpx_uaddn@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = source and destination base and limit
- *             @mpw n@ = other addend
- *
- * Returns:    ---
- *
- * Use:                Adds a small integer to a multiprecision number.
- */
-
-#define MPX_UADDN(dv, dvl, n) do {                                     \
-  mpw *_ddv = (dv), *_ddvl = (dvl);                                    \
-  mpw _c = (n);                                                                \
-                                                                       \
-  while (_c && _ddv < _ddvl) {                                         \
-    mpd _x = (mpd)*_ddv + (mpd)_c;                                     \
-    *_ddv++ = MPW(_x);                                                 \
-    _c = _x >> MPW_BITS;                                               \
-  }                                                                    \
-} while (0)
-
-extern void mpx_uaddn(mpw */*dv*/, mpw */*dvl*/, mpw /*n*/);
-
-/* --- @mpx_uaddnlsl@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination and first argument vector
- *             @mpw a@ = second argument
- *             @unsigned o@ = offset in bits
- *
- * Returns:    ---
- *
- * Use:                Computes %$d + 2^o a$%.  If the result overflows then
- *             high-order bits are discarded, as usual.  We must have
- *             @0 < o < MPW_BITS@.
- */
-
-extern void mpx_uaddnlsl(mpw */*dv*/, mpw */*dvl*/,
-                        mpw /*a*/, unsigned /*o*/);
-
-/* --- @mpx_usub@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = first argument vector base and limit
- *             @const mpw *bv, *bvl@ = second argument vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer subtraction.  If the result
- *             overflows the destination vector, high-order bits are
- *             discarded.  This means that two's complement subtraction
- *             happens more or less for free, although that's more a side-
- *             effect than anything else.  The result vector may be equal to
- *             either or both source vectors, but may not otherwise overlap
- *             them.
- */
-
-extern void mpx_usub(mpw */*dv*/, mpw */*dvl*/,
-                    const mpw */*av*/, const mpw */*avl*/,
-                    const mpw */*bv*/, const mpw */*bvl*/);
-
-/* --- @mpx_usubn@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = source and destination base and limit
- *             @n@ = subtrahend
- *
- * Returns:    ---
- *
- * Use:                Subtracts a small integer from a multiprecision number.
- */
-
-#define MPX_USUBN(dv, dvl, n) do {                                     \
-  mpw *_ddv = (dv), *_ddvl = (dvl);                                    \
-  mpw _c = (n);                                                                \
-                                                                       \
-  while (_ddv < _ddvl) {                                               \
-    mpd _x = (mpd)*_ddv - (mpd)_c;                                     \
-    *_ddv++ = MPW(_x);                                                 \
-    if (_x >> MPW_BITS)                                                        \
-      _c = 1;                                                          \
-    else                                                               \
-      break;                                                           \
-  }                                                                    \
-} while (0)
-
-extern void mpx_usubn(mpw */*dv*/, mpw */*dvl*/, mpw /*n*/);
-
-/* --- @mpx_usubnlsl@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination and first argument vector
- *             @mpw a@ = second argument
- *             @unsigned o@ = offset in bits
- *
- * Returns:    ---
- *
- * Use:                Computes %$d - 2^o a$%.  If the result overflows then
- *             high-order bits are discarded, as usual, so you get two's
- *             complement.  Which might be what you wanted...  We must have
- *             @0 < o < MPW_BITS@.
- */
-
-extern void mpx_usubnlsl(mpw */*dv*/, mpw */*dvl*/,
-                        mpw /*a*/, unsigned /*o*/);
-
-/* --- @mpx_umul@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = multiplicand vector base and limit
- *             @const mpw *bv, *bvl@ = multiplier vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer multiplication.  If the result
- *             overflows the desination vector, high-order bits are
- *             discarded.  The result vector may not overlap the argument
- *             vectors in any way.
- */
-
-extern void mpx_umul(mpw */*dv*/, mpw */*dvl*/,
-                    const mpw */*av*/, const mpw */*avl*/,
-                    const mpw */*bv*/, const mpw */*bvl*/);
-
-/* --- @mpx_umuln@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *avl@ = multiplicand vector base and limit
- *             @mpw m@ = multiplier
- *
- * Returns:    ---
- *
- * Use:                Multiplies a multiprecision integer by a single-word value.
- *             The destination and source may be equal.  The destination
- *             is completely cleared after use.
- */
-
-#define MPX_UMULN(dv, dvl, av, avl, m) do {                            \
-  mpw *_dv = (dv), *_dvl = (dvl);                                      \
-  const mpw *_av = (av), *_avl = (avl);                                        \
-  mpw _c = 0;                                                          \
-  mpd _m = (m);                                                                \
-                                                                       \
-  while (_av < _avl) {                                                 \
-    mpd _x;                                                            \
-    if (_dv >= _dvl)                                                   \
-      break;                                                           \
-    _x = (mpd)_m * (mpd)*_av++ + _c;                                   \
-    *_dv++ = MPW(_x);                                                  \
-    _c = _x >> MPW_BITS;                                               \
-  }                                                                    \
-  if (_dv < _dvl) {                                                    \
-    *_dv++ = MPW(_c);                                                  \
-    MPX_ZERO(_dv, _dvl);                                               \
-  }                                                                    \
-} while (0)
-
-extern void mpx_umuln(mpw */*dv*/, mpw */*dvl*/,
-                     const mpw */*av*/, const mpw */*avl*/, mpw m);
-
-/* --- @mpx_umlan@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination/accumulator base and limit
- *             @const mpw *av, *avl@ = multiplicand vector base and limit
- *             @mpw m@ = multiplier
- *
- * Returns:    ---
- *
- * Use:                Multiplies a multiprecision integer by a single-word value
- *             and adds the result to an accumulator.
- */
-
-#define MPX_UMLAN(dv, dvl, av, avl, m) do {                            \
-  mpw *_dv = (dv), *_dvl = (dvl);                                      \
-  const mpw *_av = (av), *_avl = (avl);                                        \
-  mpw _cc = 0;                                                         \
-  mpd _m = (m);                                                                \
-                                                                       \
-  while (_dv < _dvl && _av < _avl) {                                   \
-    mpd _x;                                                            \
-    _x = (mpd)*_dv + (mpd)_m * (mpd)*_av++ + _cc;                      \
-    *_dv++ = MPW(_x);                                                  \
-    _cc = _x >> MPW_BITS;                                              \
-  }                                                                    \
-  MPX_UADDN(_dv, _dvl, _cc);                                           \
-} while (0)
-
-extern void mpx_umlan(mpw */*dv*/, mpw */*dvl*/,
-                     const mpw */*av*/, const mpw */*avl*/, mpw m);
-
-/* --- @mpx_usqr@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = destination vector base and limit
- *             @const mpw *av, *av@ = source vector base and limit
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer squaring.  The result vector must
- *             not overlap the source vector in any way.
- */
-
-extern void mpx_usqr(mpw */*dv*/, mpw */*dvl*/,
-                    const mpw */*av*/, const mpw */*avl*/);
-
-/* --- @mpx_udiv@ --- *
- *
- * Arguments:  @mpw *qv, *qvl@ = quotient vector base and limit
- *             @mpw *rv, *rvl@ = dividend/remainder vector base and limit
- *             @const mpw *dv, *dvl@ = divisor vector base and limit
- *             @mpw *sv, *svl@ = scratch workspace
- *
- * Returns:    ---
- *
- * Use:                Performs unsigned integer division.  If the result overflows
- *             the quotient vector, high-order bits are discarded.  (Clearly
- *             the remainder vector can't overflow.)  The various vectors
- *             may not overlap in any way.  Yes, I know it's a bit odd
- *             requiring the dividend to be in the result position but it
- *             does make some sense really.  The remainder must have
- *             headroom for at least two extra words.  The scratch space
- *             must be at least one word larger than the divisor.
- */
-
-extern void mpx_udiv(mpw */*qv*/, mpw */*qvl*/, mpw */*rv*/, mpw */*rvl*/,
-                    const mpw */*dv*/, const mpw */*dvl*/,
-                    mpw */*sv*/, mpw */*svl*/);
-
-/* --- @mpx_udivn@ --- *
- *
- * Arguments:  @mpw *qv, *qvl@ = storage for the quotient (may overlap
- *                     dividend)
- *             @const mpw *rv, *rvl@ = dividend
- *             @mpw d@ = single-precision divisor
- *
- * Returns:    Remainder after divison.
- *
- * Use:                Performs a single-precision division operation.
- */
-
-extern mpw mpx_udivn(mpw */*qv*/, mpw */*qvl*/,
-                    const mpw */*rv*/, const mpw */*rvl*/, mpw /*d*/);
-
-/*----- Karatsuba multiplication algorithms -------------------------------*/
-
-/* --- @MPK_THRESH@ --- *
- *
- * This is the limiting length for using Karatsuba algorithms.  It's best to
- * use the simpler classical multiplication method on numbers smaller than
- * this.  It is unsafe to make this constant less than four (i.e., the
- * algorithms will fail).
- */
-
-#define MPK_THRESH 16
-
-/* --- @mpx_kmul@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
- *             @const mpw *av, *avl@ = pointer to first argument
- *             @const mpw *bv, *bvl@ = pointer to second argument
- *             @mpw *sv, *svl@ = pointer to scratch workspace
- *
- * Returns:    ---
- *
- * Use:                Multiplies two multiprecision integers using Karatsuba's
- *             algorithm.  This is rather faster than traditional long
- *             multiplication (e.g., @mpx_umul@) on large numbers, although
- *             more expensive on small ones.
- *
- *             The destination must be three times as large as the larger
- *             argument.  The scratch space must be five times as large as
- *             the larger argument.
- */
-
-extern void mpx_kmul(mpw */*dv*/, mpw */*dvl*/,
-                    const mpw */*av*/, const mpw */*avl*/,
-                    const mpw */*bv*/, const mpw */*bvl*/,
-                    mpw */*sv*/, mpw */*svl*/);
-
-/* --- @mpx_ksqr@ --- *
- *
- * Arguments:  @mpw *dv, *dvl@ = pointer to destination buffer
- *             @const mpw *av, *avl@ = pointer to first argument
- *             @mpw *sv, *svl@ = pointer to scratch workspace
- *
- * Returns:    ---
- *
- * Use:                Squares a multiprecision integers using something similar to
- *             Karatsuba's multiplication algorithm.  This is rather faster
- *             than traditional long multiplication (e.g., @mpx_umul@) on
- *             large numbers, although more expensive on small ones, and
- *             rather simpler than full-blown Karatsuba multiplication.
- *
- *             The destination must be three times as large as the larger
- *             argument.  The scratch space must be five times as large as
- *             the larger argument.
- */
-
-extern void mpx_ksqr(mpw */*dv*/, mpw */*dvl*/,
-                    const mpw */*av*/, const mpw */*avl*/,
-                    mpw */*sv*/, mpw */*svl*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/noekeon.c b/noekeon.c
deleted file mode 100644 (file)
index 9e0f295..0000000
--- a/noekeon.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* -*-c-*-
- *
- * $Id: noekeon.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The Noekeon block cipher
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "noekeon.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet noekeon_keysz[] = { KSZ_SET, NOEKEON_KEYSZ, 0 };
-
-/*----- Magic constants ---------------------------------------------------*/
-
-/* --- To generate the magic --- *
- *
- * perl -e'@@r=();$x=0x80;for(0..16){push(@@r,$x);$x<<=1;$x^=0x11b
- * if$x&0x100;};print join(", ",map{sprintf"0x%02x",$_}@@r),"\n";'
- */
-
-static const octet rcon[17] = {
-  0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
-  0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
-  0xd4
-};
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @noekeon_init@--- *
- *
- * Arguments:  @noekeon_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Noekeon key buffer.  Noekeon accepts a 128-bit
- *             key.
- */
-
-void noekeon_init(noekeon_ctx *k, const void *buf, size_t sz)
-{
-  const octet *p = buf;
-  static const noekeon_ctx nullkey = { { 0, 0, 0, 0 } };
-
-  KSZ_ASSERT(noekeon, sz);
-  k->k[0] = LOAD32(p + 0);
-  k->k[1] = LOAD32(p + 4);
-  k->k[2] = LOAD32(p + 8);
-  k->k[3] = LOAD32(p + 12);
-  noekeon_eblk(&nullkey, k->k, k->k);
-}
-
-/* --- @noekeon_eblk@, @noekeon_dblk@ --- *
- *
- * Arguments:  @const noekeon_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define GAMMA(a, b, c, d) do {                                         \
-  uint32 _x;                                                           \
-  b ^= ~(c | d); a ^= b & c;                                           \
-  _x = d; d = a; a = _x;                                               \
-  c ^= a ^ b ^ d;                                                      \
-  b ^= ~(c | d); a ^= b & c;                                           \
-} while (0)
-
-#define THETA(ka, kb, kc, kd, a, b, c, d) do {                         \
-  uint32 _x;                                                           \
-  _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x;     \
-  a ^= ka; b ^= kb; c ^= kc; d ^= kd;                                  \
-  _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x;     \
-} while (0)
-
-#define ITHETA(ka, kb, kc, kd, a, b, c, d) do {                                \
-  uint32 _x;                                                           \
-  _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x;     \
-  a ^= ka; b ^= kb; c ^= kc; d ^= kd;                                  \
-  _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x;     \
-} while (0)
-
-#define PI1(a, b, c, d) do {                                           \
-  b = ROL32(b, 1); c = ROL32(c, 5); d = ROL32(d, 2);                   \
-} while (0)
-
-#define PI2(a, b, c, d) do {                                           \
-  b = ROR32(b, 1); c = ROR32(c, 5); d = ROR32(d, 2);                   \
-} while (0)
-
-#define ROUND(r, ka, kb, kc, kd, a, b, c, d) do {                      \
-  a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d);                                \
-  PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d);                 \
-} while (0)
-
-#define IROUND(r, ka, kb, kc, kd, a, b, c, d) do {                     \
-  ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r;                       \
-  PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d);                 \
-} while (0)
-
-void noekeon_eblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst)
-{
-  uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3];
-  uint32 a = src[0], b = src[1], c = src[2], d = src[3];
-  const octet *r = rcon;
-
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-  ROUND(r, ka, kb, kc, kd, a, b, c, d);
-
-  a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-}
-
-void noekeon_dblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst)
-{
-  uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3];
-  uint32 a = src[0], b = src[1], c = src[2], d = src[3];
-  const octet *r = rcon + sizeof(rcon);
-
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-  IROUND(r, ka, kb, kc, kd, a, b, c, d);
-
-  ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r;
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-}
-
-BLKC_TEST(NOEKEON, noekeon)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/noekeon.h b/noekeon.h
deleted file mode 100644 (file)
index e849708..0000000
--- a/noekeon.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*-c-*-
- *
- * $Id: noekeon.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Noekeon block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Noekeon block cipher --------------------------------*
- *
- * A Nessie entry, by Joan Daemen, Michael Peeters, Gilles Van Assche and
- * Vincent Rijmen, two of whom were the designers of the AES winner
- * Rijndael.  It's a simple cipher, based on Serpent-style bit-slicing.
- * Speed is about middle-of-the-road -- about as fast as SAFER, faster than
- * MARS.
- */
-
-#ifndef CATACOMB_NOEKEON_H
-#define CATACOMB_NOEKEON_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define NOEKEON_BLKSZ 16
-#define NOEKEON_KEYSZ 16
-#define NOEKEON_CLASS (N, B, 128)
-
-extern const octet noekeon_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct noekeon_ctx {
-  uint32 k[4];
-} noekeon_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @noekeon_init@ --- *
- *
- * Arguments:  @noekeon_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Noekeon context with a particular key.  This
- *             uses indirect keying.  The key must be 128 bits long.
- */
-
-extern void noekeon_init(noekeon_ctx */*k*/,
-                        const void */*buf*/, size_t /*sz*/);
-
-/* --- @noekeon_eblk@, @noekeon_dblk@ --- *
- *
- * Arguments:  @const noekeon_ctx *k@ = pointer to Noekeon context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void noekeon_eblk(const noekeon_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*dst*/);
-extern void noekeon_dblk(const noekeon_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*dst*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/noise.c b/noise.c
deleted file mode 100644 (file)
index e339317..0000000
--- a/noise.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Acquisition of environmental noise (Unix-specific)
- *
- * (c) 1998 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "config.h"
-
-#include <setjmp.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#ifdef HAVE_SETGROUPS
-#  include <grp.h>
-#endif
-
-#include <mLib/bits.h>
-#include <mLib/tv.h>
-
-#include "noise.h"
-#include "paranoia.h"
-#include "rand.h"
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define NOISE_KIDLIFE 100000           /* @noise_filter@ child lifetime */
-#define MILLION 1000000                        /* One million */
-
-/*----- Noise source definition -------------------------------------------*/
-
-const rand_source noise_source = { noise_acquire, noise_timer };
-
-/*----- Static variables --------------------------------------------------*/
-
-/* --- Timer differences --- */
-
-static unsigned long noise_last;       /* Last time recorded */
-static unsigned long noise_diff;       /* Last first order difference */
-
-/* --- Setuid program handling --- */
-
-static uid_t noise_uid = NOISE_NOSETUID; /* Uid to set to spawn processes */
-static gid_t noise_gid = NOISE_NOSETGID; /* Gid to set to spawn processes */
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @bitcount@ --- *
- *
- * Arguments:  @unsigned long x@ = a word containing bits
- *
- * Returns:    The number of bits set in the word.
- */
-
-static int bitcount(unsigned long x)
-{
-  char ctab[] = { 0, 1, 1, 2, 1, 2, 2, 3,
-                 1, 2, 2, 3, 2, 3, 3, 4 };
-  int count = 0;
-  while (x) {
-    count += ctab[x & 0xfu];
-    x >>= 4;
-  }
-  return (count);
-}
-
-/* --- @timer@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to randomness pool
- *             @struct timeval *tv@ = pointer to time block
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Low-level timer contributor.
- */
-
-static int timer(rand_pool *r, struct timeval *tv)
-{
-  unsigned long x, d, dd;
-  int de, dde;
-  int ret;
-
-  x = tv->tv_usec + MILLION * tv->tv_sec;
-  d = x ^ noise_last;
-  dd = d ^ noise_diff;
-  noise_diff = d;
-  de = bitcount(d);
-  dde = bitcount(dd);
-  rand_add(r, tv, sizeof(*tv), de <= dde ? de : dde);
-  ret = (de || dde);
-  BURN(tv); x = d = dd = de = dde = 0;
-  return (ret);
-}
-
-/* --- @noise_timer@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Contributes the current time to the randomness pool.
- *             A guess at the number of useful bits contributed is made,
- *             based on first and second order bit differences.  This isn't
- *             ever-so reliable, but it's better than nothing.
- */
-
-int noise_timer(rand_pool *r)
-{
-  struct timeval tv;
-  gettimeofday(&tv, 0);
-  return (timer(r, &tv));
-}
-
-/* --- @noise_devrandom@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Attempts to obtain some randomness from the system entropy
- *             pool.  All bits from the device are assumed to be good.
- */
-
-int noise_devrandom(rand_pool *r)
-{
-  int fd;
-  octet buf[RAND_POOLSZ];
-  ssize_t len;
-  int ret = 0;
-
-  /* --- Be nice to other clients of the random device --- *
-   *
-   * Attempt to open the device nonblockingly.  If that works, take up to
-   * one bufferful and then close again.  If there's no data to be read,
-   * then that's tough and we go away again, on the grounds that the device
-   * needs to get some more entropy from somewhere.
-   */
-
-  if ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
-      (fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
-      (fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) {
-    if ((len = read(fd, buf, sizeof(buf))) > 0) {
-      rand_add(r, buf, len, len * 8);
-      BURN(buf);
-      ret = 1;
-    }
-    close(fd);
-  }
-  noise_timer(r);
-  return (ret);
-}
-
-/* --- @noise_setid@ --- *
- *
- * Arguments:  @uid_t uid@ = uid to set
- *             @gid_t gid@ = gid to set
- *
- * Returns:    ---
- *
- * Use:                Sets the user and group ids to be used by @noise_filter@
- *             when running child processes.  This is useful to avoid
- *             giving shell commands (even carefully written ones) undue
- *             privileges.  This interface is Unix-specific
- */
-
-void noise_setid(uid_t uid, gid_t gid)
-{
-  noise_uid = uid;
-  noise_gid = gid;
-}
-
-/* --- @noise_filter@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @int good@ = number of good bits per 1024 bits
- *             @const char *c@ = shell command to run
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Attempts to execute a shell command, and dump it into the
- *             randomness pool.  A very rough estimate of the number of
- *             good bits is made, based on the size of the command's output.
- *             This function calls @waitpid@, so be careful.  Before execing
- *             the command, the process uid and gid are set to the values
- *             given to @noise_setid@, and an attempt is made to reset the
- *             list of supplementary groups.  The environment passed to
- *             the command has been severly lobotimized.  If the command
- *             fails to complete within a short time period, it is killed.
- *             Paranoid use of close-on-exec flags for file descriptors is
- *             recommended.
- *
- *             This interface is Unix-specific.
- */
-
-int noise_filter(rand_pool *r, int good, const char *c)
-{
-  char buf[4096];
-  pid_t kid;
-  int fd[2];
-  struct timeval dead;
-  int ret = 0;
-  const char *env[] = {
-    "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc",
-    0
-  };
-
-  /* --- Remember when this business started --- */
-
-  gettimeofday(&dead, 0);
-  timer(r, &dead);
-
-  /* --- Create a pipe --- */
-
-  if (pipe(fd))
-    return (ret);
-
-  /* --- Fork a child off --- */
-
-  fflush(0);
-  kid = fork();
-  if (kid < 0) {
-    close(fd[0]);
-    close(fd[1]);
-    return (ret);
-  }
-
-  /* --- Handle the child end of the deal --- */
-
-  if (kid == 0) {
-    int f;
-
-    /* --- Set the pipe as standard output, close standard input --- */
-
-    close(0); close(1); close(2);
-
-    if (fd[1] != 1) {
-      if (dup2(fd[1], 1) < 0) _exit(127);
-      close(fd[1]);
-    }
-
-    if ((f = open("/dev/null", O_RDONLY)) != 0 ||
-       (f = open("/dev/null", O_WRONLY)) != 2)
-      _exit(127);
-
-    /* --- Play games with uids --- */
-
-    if (noise_gid != NOISE_NOSETGID) {
-      setgid(noise_gid);
-      setegid(noise_gid);
-#ifdef HAVE_SETGROUPS
-      setgroups(1, &noise_gid);
-#endif
-    }
-
-    if (noise_uid != NOISE_NOSETUID) {
-      setuid(noise_uid);
-      seteuid(noise_uid);
-    }
-
-    /* --- Start the process up --- */
-
-    execle("/bin/sh", "-c", c, (char *)0, env);
-    _exit(127);
-  }
-
-  /* --- Sort out my end of the deal --- */
-
-  close(fd[1]);
-
-  /* --- Decide on the deadline --- */
-
-  TV_ADDL(&dead, &dead, 0, NOISE_KIDLIFE);
-
-  /* --- Now read, and think --- */
-
-  for (;;) {
-    struct timeval now, diff;
-    fd_set rd;
-
-    gettimeofday(&now, 0);
-    timer(r, &now);
-    if (TV_CMP(&now, >, &dead))
-      break;
-    TV_SUB(&diff, &dead, &now);
-
-    FD_ZERO(&rd);
-    FD_SET(fd[0], &rd);
-
-    if (select(fd[0] + 1, &rd, 0, 0, &diff) < 0)
-      break;
-    if (FD_ISSET(fd[0], &rd)) {
-      ssize_t sz;
-      int goodbits;
-
-      if ((sz = read(fd[0], buf, sizeof(buf))) <= 0)
-       break;
-      goodbits = (sz * good) / 128;
-      rand_add(r, buf, sz, goodbits);
-      ret = 1;
-    }
-  }
-
-  /* --- We've finished with it: kill the child process --- *
-   *
-   * This is morally questionable.  On the other hand, I don't want to be
-   * held up in the @waitpid@ call if I can possibly help it.  Maybe a
-   * double-fork is worth doing here.
-   */
-
-  close(fd[0]);
-  BURN(buf);
-  noise_timer(r);
-  kill(kid, SIGKILL);
-  waitpid(kid, 0, 0);
-  return (ret);
-}
-
-/* --- @noise_freewheel@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Runs a free counter for a short while as a desparate attempt
- *             to get randomness from somewhere.  This is actually quite
- *             effective.
- */
-
-#ifdef USE_FREEWHEEL
-
-static jmp_buf fwjmp;
-
-static void fwalarm(int sig)
-{
-  siglongjmp(fwjmp, 1);
-}
-
-int noise_freewheel(rand_pool *r)
-{
-  void (*sigal)(int) = 0;
-  struct itimerval oitv, itv = { { 0, 0 }, { 0, 5000 } };
-  int rc = 0;
-  volatile uint32 fwcount = 0;
-
-  if (!sigsetjmp(fwjmp, 1)) {
-    if ((sigal = signal(SIGALRM, fwalarm)) == SIG_ERR)
-      return (0);
-    if (setitimer(ITIMER_REAL, &itv, &oitv))
-      goto done;
-    for (;;)
-      fwcount++;
-  } else {
-    octet buf[4];
-    STORE32(buf, fwcount);
-    rand_add(r, buf, sizeof(buf), 16);
-    rc = 1;
-  }
-
-done:
-  signal(SIGALRM, sigal);
-  if (oitv.it_value.tv_sec || oitv.it_value.tv_usec)
-    TV_SUB(&oitv.it_value, &oitv.it_value, &itv.it_value);
-  setitimer(ITIMER_REAL, &oitv, 0);
-  return (rc);
-}
-
-#else
-
-int noise_freewheel(rand_pool *r)
-{
-  return (0);
-}
-
-#endif
-
-/* --- @noise_enquire@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Runs some shell commands to enquire about the prevailing
- *             environment.  This can gather quite a lot of low-quality
- *             entropy.
- */
-
-int noise_enquire(rand_pool *r)
-{
-  struct tab {
-    const char *cmd;
-    unsigned rate;
-  } tab[] = {
-    { "ps alxww || ps -elf",   16 },
-    { "netstat -n",             6 },
-    { "ifconfig -a",            8 },
-    { "df",                    20 },
-    { "w",                      6 },
-    { "ls -align /tmp/.",      10 },
-    { 0,                        0 }
-  };
-  int i;
-
-  for (i = 0; tab[i].cmd; i++)
-    noise_filter(r, tab[i].rate, tab[i].cmd);
-  return (1);
-}
-
-/* --- @noise_acquire@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    ---
- *
- * Use:                Acquires some randomness from somewhere.
- */
-
-void noise_acquire(rand_pool *r)
-{
-  unsigned i;
-  for (i = 0; i < 8; i++)
-    noise_freewheel(r);
-  if (!noise_devrandom(r)) {
-    noise_enquire(r);
-    for (i = 0; i < 8; i++)
-      noise_freewheel(r);
-  }
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/noise.h b/noise.h
deleted file mode 100644 (file)
index 48fe6bd..0000000
--- a/noise.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/* -*-c-*-
- *
- * $Id: noise.h,v 1.6 2004/04/08 01:36:15 mdw Exp $
- *
- * Acquisition of environmental noise (Unix-specific)
- *
- * (c) 1998 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.
- */
-
-#ifndef CATACOMB_NOISE_H
-#define CATACOMB_NOISE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <sys/types.h>
-
-#ifndef CATACOMB_RAND_H
-#  include "rand.h"
-#endif
-
-/*----- Noise source definition -------------------------------------------*/
-
-extern const rand_source noise_source;
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define NOISE_NOSETUID ((uid_t)-1)
-#define NOISE_NOSETGID ((gid_t)-1)
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @noise_timer@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Contributes the current time to the randomness pool.
- *             A guess at the number of useful bits contributed is made,
- *             based on first and second order bit differences.  This isn't
- *             ever-so reliable, but it's better than nothing.
- */
-
-extern int noise_timer(rand_pool */*r*/);
-
-/* --- @noise_devrandom@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Attempts to obtain some randomness from the system entropy
- *             pool.  All bits from the device are assumed to be good.
- */
-
-extern int noise_devrandom(rand_pool */*r*/);
-
-/* --- @noise_setid@ --- *
- *
- * Arguments:  @uid_t uid@ = uid to set
- *             @gid_t gid@ = gid to set
- *
- * Returns:    ---
- *
- * Use:                Sets the user and group ids to be used by @noise_filter@
- *             when running child processes.  This is useful to avoid
- *             giving shell commands (even carefully written ones) undue
- *             privileges.  This interface is Unix-specific.
- */
-
-extern void noise_setid(uid_t /*uid*/, gid_t /*gid*/);
-
-/* --- @noise_filter@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @int good@ = number of good bits per 1024 bits
- *             @const char *c@ = shell command to run
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Attempts to execute a shell command, and dump it into the
- *             randomness pool.  A very rough estimate of the number of
- *             good bits is made, based on the size of the command's output.
- *             This function calls @waitpid@, so be careful.  Before execing
- *             the command, the process uid and gid are set to the values
- *             given to @noise_setid@, and an attempt is made to reset the
- *             list of supplementary groups.  The environment passed to
- *             the command has been severly lobotimized.  If the command
- *             fails to complete within a short time period, it is killed.
- *             Paranoid use of close-on-exec flags for file descriptors is
- *             recommended.
- *
- *             This interface is Unix-specific.
- */
-
-extern int noise_filter(rand_pool */*r*/, int /*good*/, const char */*c*/);
-
-/* --- @noise_freewheel@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Runs a free counter for a short while as a desparate attempt
- *             to get randomness from somewhere.  This is actually quite
- *             effective.
- */
-
-int noise_freewheel(rand_pool */*r*/);
-
-/* --- @noise_enquire@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Nonzero if some randomness was contributed.
- *
- * Use:                Runs some shell commands to enquire about the prevailing
- *             environment.  This can gather quite a lot of low-quality
- *             entropy.
- */
-
-extern int noise_enquire(rand_pool */*r*/);
-
-/* --- @noise_acquire@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    ---
- *
- * Use:                Acquires some randomness from somewhere.
- */
-
-extern void noise_acquire(rand_pool */*r*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/oaep.c b/oaep.c
deleted file mode 100644 (file)
index dfcd41b..0000000
--- a/oaep.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* -*-c-*-
- *
- * $Id: oaep.c,v 1.6 2004/04/08 01:36:15 mdw Exp $
- *
- * Optimal asymmetric encryption packing
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-
-#include "ct.h"
-#include "gcipher.h"
-#include "ghash.h"
-#include "grand.h"
-#include "rsa.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @oaep_encode@ --- *
- *
- * Arguments:  @mp *d@ = where to put the answer
- *             @const void *m@ = pointer to message data
- *             @size_t msz@ = size of message data
- *             @octet *b@ = spare buffer
- *             @size_t sz@ = size of the buffer (big enough)
- *             @unsigned long nbits@ = length of bits of @n@
- *             @void *p@ = pointer to OAEP parameter block
- *
- * Returns:    The encoded plaintext, or null on failure.
- *
- * Use:                Implements the operation @EME-OAEP-ENCODE@, as defined in
- *             PKCS#1 v. 2.0 (RFC2437).
- */
-
-mp *oaep_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
-               unsigned long nbits, void *p)
-{
-  oaep *o = p;
-  size_t hsz = o->ch->hashsz;
-  ghash *h;
-  octet *q, *mq;
-  octet *pp;
-  gcipher *c;
-  size_t n;
-
-  /* --- Ensure that everything is sensibly sized --- */
-
-  if (2 * hsz + 2 + msz > sz)
-    return (0);
-
-  /* --- Make the `seed' value --- */
-
-  q = b;
-  *q++ = 0; sz--;
-  mq = q + hsz;
-  GR_FILL(o->r, q, hsz);
-
-  /* --- Fill in the rest of the buffer --- */
-
-  h = GH_INIT(o->ch);
-  GH_HASH(h, o->ep, o->epsz);
-  GH_DONE(h, mq);
-  GH_DESTROY(h);
-  pp = mq + hsz;
-  n = sz - 2 * hsz - msz - 1;
-  memset(pp, 0, n);
-  pp += n;
-  *pp++ = 1;
-  memcpy(pp, m, msz);
-
-  /* --- Do the packing --- */
-
-  n = sz - hsz;
-  c = GC_INIT(o->cc, q, hsz);
-  GC_ENCRYPT(c, mq, mq, n);
-  GC_DESTROY(c);
-
-  c = GC_INIT(o->cc, mq, n);
-  GC_ENCRYPT(c, q, q, hsz);
-  GC_DESTROY(c);
-
-  /* --- Done --- */
-
-  return (mp_loadb(d, b, sz + 1));
-}
-
-/* --- @oaep_decode@ --- *
- *
- * Arguments:  @mp *m@ = the decrypted message
- *             @octet *b@ = pointer to a buffer to work in
- *             @size_t sz@ = the size of the buffer (big enough)
- *             @unsigned long nbits@ = the number of bits in @n@
- *             @void *p@ = pointer to OAEP parameter block
- *
- * Returns:    The length of the output string if successful, negative on
- *             failure.
- *
- * Use:                Implements the operation @EME-OAEP-DECODE@, as defined in
- *             PKCS#1 v. 2.0 (RFC2437).
- */
-
-int oaep_decode(mp *m, octet *b, size_t sz, unsigned long nbits, void *p)
-{
-  oaep *o = p;
-  gcipher *c;
-  ghash *h;
-  octet *q, *mq, *qq;
-  octet *pp;
-  uint32 goodp = 1;
-  size_t n;
-  size_t hsz = o->ch->hashsz;
-
-  /* --- Ensure that the block is large enough --- */
-
-  if (sz < 2 * hsz)                    /* Doesn't depend on ciphertext */
-    return (-1);
-
-  /* --- Decrypt the message --- */
-
-  mp_storeb(m, b, sz);
-  q = b;
-  goodp &= ct_inteq(*q, 0);
-  q++; sz--;
-  mq = q + hsz;
-  qq = q + sz;
-  n = sz - hsz;
-  c = GC_INIT(o->cc, mq, n);
-  GC_DECRYPT(c, q, q, hsz);
-  GC_DESTROY(c);
-
-  c = GC_INIT(o->cc, q, hsz);
-  GC_DECRYPT(c, mq, mq, n);
-  GC_DESTROY(c);
-  q--;
-
-  /* --- Check the hash on the encoding parameters --- */
-
-  h = GH_INIT(o->ch);
-  GH_HASH(h, o->ep, o->epsz);
-  GH_DONE(h, q);
-  GH_DESTROY(h);
-  goodp &= ct_memeq(q, mq, hsz);
-
-  /* --- Now find the start of the actual message --- */
-
-  pp = mq + hsz;
-  while (*pp == 0 && pp < qq)
-    pp++;
-  goodp &= ~ct_intle(qq - b, pp - b);
-  goodp &= ct_inteq(*pp, 1);
-  pp++;
-  n = qq - pp;
-  memmove(q, pp, n);
-  return (goodp ? n : -1);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ofb-def.h b/ofb-def.h
deleted file mode 100644 (file)
index 8250395..0000000
--- a/ofb-def.h
+++ /dev/null
@@ -1,547 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ofb-def.h,v 1.7 2004/04/08 01:36:15 mdw Exp $
- *
- * Definitions for output feedback mode
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_OFB_DEF_H
-#define CATACOMB_OFB_DEF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#ifndef CATACOMB_ARENA_H
-#  include "arena.h"
-#endif
-
-#ifndef CATACOMB_BLKC_H
-#  include "blkc.h"
-#endif
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_PARANOIA_H
-#  include "paranoia.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @OFB_DEF@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use:                Creates definitions for output feedback mode.
- */
-
-#define OFB_DEF(PRE, pre)                                              \
-                                                                       \
-/* --- @pre_ofbgetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @const pre_ofbctx *ctx@ = pointer to OFB context block  \
- *             @void *iv@ = pointer to output data block               \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Reads the currently set IV.  Reading and setting an IV  \
- *             is not transparent to the cipher.  It will add a `step' \
- *             which must be matched by a similar operation during     \
- *             decryption.                                             \
- */                                                                    \
-                                                                       \
-void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv)                 \
-{                                                                      \
-  octet *p = iv;                                                       \
-  unsigned off = ctx->off;                                             \
-  unsigned rest = PRE##_BLKSZ - off;                                   \
-  memcpy(p, ctx->iv + off, rest);                                      \
-  memcpy(p + rest, ctx->iv, off);                                      \
-}                                                                      \
-                                                                       \
-/* --- @pre_ofbsetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
- *             @cnost void *iv@ = pointer to IV to set                 \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the IV to use for subsequent encryption.           \
- */                                                                    \
-                                                                       \
-void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv)                 \
-{                                                                      \
-  memcpy(ctx->iv, iv, PRE##_BLKSZ);                                    \
-  ctx->off = PRE##_BLKSZ;                                              \
-}                                                                      \
-                                                                       \
-/* --- @pre_ofbbdry@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Inserts a boundary during encryption.  Successful       \
- *             decryption must place a similar boundary.               \
- */                                                                    \
-                                                                       \
-void pre##_ofbbdry(pre##_ofbctx *ctx)                                  \
-{                                                                      \
-  uint32 niv[PRE##_BLKSZ / 4];                                         \
-  BLKC_LOAD(PRE, niv, ctx->iv);                                                \
-  pre##_eblk(&ctx->ctx, niv, niv);                                     \
-  BLKC_STORE(PRE, ctx->iv, niv);                                       \
-  ctx->off = PRE##_BLKSZ;                                              \
-  BURN(niv);                                                           \
-}                                                                      \
-                                                                       \
-/* --- @pre_ofbsetkey@ --- *                                           \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the OFB context to use a different cipher key.     \
- */                                                                    \
-                                                                       \
-void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k)            \
-{                                                                      \
-  ctx->ctx = *k;                                                       \
-}                                                                      \
-                                                                       \
-/* --- @pre_ofbinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to cipher context           \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a OFB context ready for use.  You should    \
- *             ensure that the IV chosen is unique: reusing an IV will \
- *             compromise the security of the entire plaintext.  This  \
- *             is equivalent to calls to @pre_init@, @pre_ofbsetkey@   \
- *             and @pre_ofbsetiv@.                                     \
- */                                                                    \
-                                                                       \
-void pre##_ofbinit(pre##_ofbctx *ctx,                                  \
-                    const void *key, size_t sz,                        \
-                    const void *iv)                                    \
-{                                                                      \
-  static const octet zero[PRE##_BLKSZ] = { 0 };                                \
-  pre##_init(&ctx->ctx, key, sz);                                      \
-  pre##_ofbsetiv(ctx, iv ? iv : zero);                                 \
-}                                                                      \
-                                                                       \
-/* --- @pre_ofbencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts or decrypts a block with a block cipher in OFB \
- *             mode: encryption and decryption are the same in OFB.    \
- *             The destination may be null to just churn the feedback  \
- *             round for a bit.  The source may be null to use the     \
- *             cipher as a random data generator.                      \
- */                                                                    \
-                                                                       \
-void pre##_ofbencrypt(pre##_ofbctx *ctx,                               \
-                       const void *src, void *dest,                    \
-                       size_t sz)                                      \
-{                                                                      \
-  const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz)                                                             \
-    return;                                                            \
-                                                                       \
-  /* --- If I can deal with the block from my buffer, do that --- */   \
-                                                                       \
-  if (sz < PRE##_BLKSZ - off)                                          \
-    goto small;                                                                \
-                                                                       \
-  /* --- Finish off what's left in my buffer --- */                    \
-                                                                       \
-  if (!d)                                                              \
-    sz -= PRE##_BLKSZ - off;                                           \
-  else {                                                               \
-    while (off < PRE##_BLKSZ) {                                                \
-      register octet x = s ? *s++ : 0;                                 \
-      *d++ = ctx->iv[off++] ^ x;                                       \
-      sz--;                                                            \
-    }                                                                  \
-  }                                                                    \
-                                                                       \
-  /* --- Main encryption loop --- */                                   \
-                                                                       \
-  {                                                                    \
-    uint32 iv[PRE##_BLKSZ / 4];                                                \
-    BLKC_LOAD(PRE, iv, ctx->iv);                                       \
-                                                                       \
-    for (;;) {                                                         \
-      pre##_eblk(&ctx->ctx, iv, iv);                                   \
-      if (sz < PRE##_BLKSZ)                                            \
-       break;                                                          \
-      if (d) {                                                         \
-       if (!s)                                                         \
-         BLKC_STORE(PRE, d, iv);                                       \
-       else {                                                          \
-         uint32 x[PRE##_BLKSZ / 4];                                    \
-         BLKC_LOAD(PRE, x, s);                                         \
-         BLKC_XSTORE(PRE, d, iv, x);                                   \
-         s += PRE##_BLKSZ;                                             \
-       }                                                               \
-       d += PRE##_BLKSZ;                                               \
-      }                                                                        \
-      sz -= PRE##_BLKSZ;                                               \
-    }                                                                  \
-                                                                       \
-    BLKC_STORE(PRE, ctx->iv, iv);                                      \
-    off = 0;                                                           \
-  }                                                                    \
-                                                                       \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    if (!d)                                                            \
-      off += sz;                                                       \
-    else do {                                                          \
-      register octet x = s ? *s++ : 0;                                 \
-      *d++ = ctx->iv[off++] ^ x;                                       \
-      sz--;                                                            \
-    } while (sz);                                                      \
-  }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
-}                                                                      \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-static const gcipher_ops gops;                                         \
-                                                                       \
-typedef struct gctx {                                                  \
-  gcipher c;                                                           \
-  pre##_ofbctx k;                                                      \
-} gctx;                                                                        \
-                                                                       \
-static gcipher *ginit(const void *k, size_t sz)                                \
-{                                                                      \
-  gctx *g = S_CREATE(gctx);                                            \
-  g->c.ops = &gops;                                                    \
-  pre##_ofbinit(&g->k, k, sz, 0);                                      \
-  return (&g->c);                                                      \
-}                                                                      \
-                                                                       \
-static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_ofbencrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
-                                                                       \
-static void gdestroy(gcipher *c)                                       \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static void gsetiv(gcipher *c, const void *iv)                         \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_ofbsetiv(&g->k, iv);                                           \
-}                                                                      \
-                                                                       \
-static void gbdry(gcipher *c)                                          \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_ofbbdry(&g->k);                                                        \
-}                                                                      \
-                                                                       \
-static const gcipher_ops gops = {                                      \
-  &pre##_ofb,                                                          \
-  gencrypt, gencrypt, gdestroy, gsetiv, gbdry                          \
-};                                                                     \
-                                                                       \
-const gccipher pre##_ofb = {                                           \
-  #pre "-ofb", pre##_keysz, PRE##_BLKSZ,                               \
-  ginit                                                                        \
-};                                                                     \
-                                                                       \
-/* --- Generic random number generator interface --- */                        \
-                                                                       \
-typedef struct grctx {                                                 \
-  grand r;                                                             \
-  pre##_ofbctx k;                                                      \
-} grctx;                                                               \
-                                                                       \
-static void grdestroy(grand *r)                                                \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
-                                                                       \
-static int grmisc(grand *r, unsigned op, ...)                          \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  va_list ap;                                                          \
-  int rc = 0;                                                          \
-  uint32 i;                                                            \
-  octet buf[PRE##_BLKSZ];                                              \
-  va_start(ap, op);                                                    \
-                                                                       \
-  switch (op) {                                                                \
-    case GRAND_CHECK:                                                  \
-      switch (va_arg(ap, unsigned)) {                                  \
-       case GRAND_CHECK:                                               \
-       case GRAND_SEEDINT:                                             \
-       case GRAND_SEEDUINT32:                                          \
-       case GRAND_SEEDBLOCK:                                           \
-       case GRAND_SEEDRAND:                                            \
-         rc = 1;                                                       \
-         break;                                                        \
-       default:                                                        \
-         rc = 0;                                                       \
-         break;                                                        \
-      }                                                                        \
-      break;                                                           \
-    case GRAND_SEEDINT:                                                        \
-      memset(buf, 0, sizeof(buf));                                     \
-      i = va_arg(ap, unsigned);                                                \
-      STORE32(buf, i);                                                 \
-      pre##_ofbsetiv(&g->k, buf);                                      \
-      break;                                                           \
-    case GRAND_SEEDUINT32:                                             \
-      memset(buf, 0, sizeof(buf));                                     \
-      i = va_arg(ap, uint32);                                          \
-      STORE32(buf, i);                                                 \
-      pre##_ofbsetiv(&g->k, buf);                                      \
-      break;                                                           \
-    case GRAND_SEEDBLOCK: {                                            \
-      const void *p = va_arg(ap, const void *);                                \
-      size_t sz = va_arg(ap, size_t);                                  \
-      if (sz < sizeof(buf)) {                                          \
-       memset(buf, 0, sizeof(buf));                                    \
-       memcpy(buf, p, sz);                                             \
-       p = buf;                                                        \
-      }                                                                        \
-      pre##_ofbsetiv(&g->k, p);                                                \
-    } break;                                                           \
-    case GRAND_SEEDRAND: {                                             \
-      grand *rr = va_arg(ap, grand *);                                 \
-      rr->ops->fill(rr, buf, sizeof(buf));                             \
-      pre##_ofbsetiv(&g->k, buf);                                      \
-    } break;                                                           \
-    default:                                                           \
-      GRAND_BADOP;                                                     \
-      break;                                                           \
-  }                                                                    \
-                                                                       \
-  va_end(ap);                                                          \
-  return (rc);                                                         \
-}                                                                      \
-                                                                       \
-static octet grbyte(grand *r)                                          \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  octet o;                                                             \
-  pre##_ofbencrypt(&g->k, 0, &o, 1);                                   \
-  return (o);                                                          \
-}                                                                      \
-                                                                       \
-static uint32 grword(grand *r)                                         \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  octet b[4];                                                          \
-  pre##_ofbencrypt(&g->k, 0, b, sizeof(b));                            \
-  return (LOAD32(b));                                                  \
-}                                                                      \
-                                                                       \
-static void grfill(grand *r, void *p, size_t sz)                       \
-{                                                                      \
-  grctx *g = (grctx *)r;                                               \
-  pre##_ofbencrypt(&g->k, 0, p, sz);                                   \
-}                                                                      \
-                                                                       \
-static const grand_ops grops = {                                       \
-  #pre "-ofb",                                                         \
-  GRAND_CRYPTO, 0,                                                     \
-  grmisc, grdestroy,                                                   \
-  grword, grbyte, grword, grand_range, grfill                          \
-};                                                                     \
-                                                                       \
-/* --- @pre_ofbrand@ --- *                                             \
- *                                                                     \
- * Arguments:  @const void *k@ = pointer to key material               \
- *             @size_t sz@ = size of key material                      \
- *                                                                     \
- * Returns:    Pointer to generic random number generator interface.   \
- *                                                                     \
- * Use:                Creates a random number interface wrapper around an     \
- *             OFB-mode block cipher.                                  \
- */                                                                    \
-                                                                       \
-grand *pre##_ofbrand(const void *k, size_t sz)                         \
-{                                                                      \
-  grctx *g = S_CREATE(grctx);                                          \
-  g->r.ops = &grops;                                                   \
-  pre##_ofbinit(&g->k, k, sz, 0);                                      \
-  return (&g->r);                                                      \
-}                                                                      \
-                                                                       \
-OFB_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @OFB_TEST@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use:                Standard test rig for OFB functions.
- */
-
-#define OFB_TEST(PRE, pre)                                             \
-                                                                       \
-/* --- Initial plaintext for the test --- */                           \
-                                                                       \
-static const octet text[] = TEXT;                                      \
-                                                                       \
-/* --- Key and IV to use --- */                                                \
-                                                                       \
-static const octet key[] = KEY;                                                \
-static const octet iv[] = IV;                                          \
-                                                                       \
-/* --- Buffers for encryption and decryption output --- */             \
-                                                                       \
-static octet ct[sizeof(text)];                                         \
-static octet pt[sizeof(text)];                                         \
-                                                                       \
-static void hexdump(const octet *p, size_t sz)                         \
-{                                                                      \
-  const octet *q = p + sz;                                             \
-  for (sz = 0; p < q; p++, sz++) {                                     \
-    printf("%02x", *p);                                                        \
-    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
-      putchar(':');                                                    \
-  }                                                                    \
-}                                                                      \
-                                                                       \
-int main(void)                                                         \
-{                                                                      \
-  size_t sz = 0, rest;                                                 \
-  pre##_ofbctx ctx;                                                    \
-  int status = 0;                                                      \
-  int done = 0;                                                                \
-  pre##_ctx k;                                                         \
-                                                                       \
-  size_t keysz = PRE##_KEYSZ ?                                         \
-    PRE##_KEYSZ : strlen((const char *)key);                           \
-                                                                       \
-  fputs(#pre "-ofb: ", stdout);                                                \
-                                                                       \
-  pre##_init(&k, key, keysz);                                          \
-  pre##_ofbsetkey(&ctx, &k);                                           \
-                                                                       \
-  while (sz <= sizeof(text)) {                                         \
-    rest = sizeof(text) - sz;                                          \
-    memcpy(ct, text, sizeof(text));                                    \
-    pre##_ofbsetiv(&ctx, iv);                                          \
-    pre##_ofbencrypt(&ctx, ct, ct, sz);                                        \
-    pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest);                    \
-    memcpy(pt, ct, sizeof(text));                                      \
-    pre##_ofbsetiv(&ctx, iv);                                          \
-    pre##_ofbencrypt(&ctx, pt, pt, rest);                              \
-    pre##_ofbencrypt(&ctx, pt + rest, pt + rest, sz);                  \
-    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
-      done++;                                                          \
-      if (sizeof(text) < 40 || done % 8 == 0)                          \
-       fputc('.', stdout);                                             \
-      if (done % 480 == 0)                                             \
-       fputs("\n\t", stdout);                                          \
-      fflush(stdout);                                                  \
-    } else {                                                           \
-      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
-      status = 1;                                                      \
-      printf("\tplaintext      = "); hexdump(text, sz);                        \
-       printf(", "); hexdump(text + sz, rest);                         \
-       fputc('\n', stdout);                                            \
-      printf("\tciphertext     = "); hexdump(ct, sz);                  \
-       printf(", "); hexdump(ct + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      printf("\trecovered text = "); hexdump(pt, sz);                  \
-       printf(", "); hexdump(pt + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      fputc('\n', stdout);                                             \
-    }                                                                  \
-    if (sz < 63)                                                       \
-      sz++;                                                            \
-    else                                                               \
-      sz += 9;                                                         \
-  }                                                                    \
-                                                                       \
-  fputs(status ? " failed\n" : " ok\n", stdout);                       \
-  return (status);                                                     \
-}
-
-#else
-#  define OFB_TEST(PRE, pre)
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ofb.h b/ofb.h
deleted file mode 100644 (file)
index 970acf7..0000000
--- a/ofb.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ofb.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Output feedback for block ciphers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_OFB_H
-#define CATACOMB_OFB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @OFB_DECL@ --- *
- *
- * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use:                Makes declarations for output feedback mode.
- */
-
-#define OFB_DECL(PRE, pre)                                             \
-                                                                       \
-/* --- Output feedback context --- */                                  \
-                                                                       \
-typedef struct pre##_ofbctx {                                          \
-  pre##_ctx ctx;                       /* Underlying cipher context */ \
-  unsigned off;                                /* Current offset in buffer */  \
-  octet iv[PRE##_BLKSZ];               /* Output buffer and IV */      \
-} pre##_ofbctx;                                                                \
-                                                                       \
-/* --- @pre_ofbgetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @const pre_ofbctx *ctx@ = pointer to OFB context block  \
- *             @void *iv@ = pointer to output data block               \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Reads the currently set IV.  Reading and setting an IV  \
- *             is not transparent to the cipher.  It will add a `step' \
- *             which must be matched by a similar operation during     \
- *             decryption.                                             \
- */                                                                    \
-                                                                       \
-extern void pre##_ofbgetiv(const pre##_ofbctx */*ctx*/,                        \
-                          void */*iv*/);                               \
-                                                                       \
-/* --- @pre_ofbsetiv@ --- *                                            \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
- *             @cnost void *iv@ = pointer to IV to set                 \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the IV to use for subsequent encryption.           \
- */                                                                    \
-                                                                       \
-extern void pre##_ofbsetiv(pre##_ofbctx */*ctx*/,                      \
-                          const void */*iv*/);                         \
-                                                                       \
-/* --- @pre_ofbbdry@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Inserts a boundary during encryption.  Successful       \
- *             decryption must place a similar boundary.               \
- */                                                                    \
-                                                                       \
-extern void pre##_ofbbdry(pre##_ofbctx */*ctx*/);                      \
-                                                                       \
-/* --- @pre_ofbsetkey@ --- *                                           \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
- *             @const pre_ctx *k@ = pointer to cipher context          \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Sets the OFB context to use a different cipher key.     \
- */                                                                    \
-                                                                       \
-extern void pre##_ofbsetkey(pre##_ofbctx */*ctx*/,                     \
-                           const pre##_ctx */*k*/);                    \
-                                                                       \
-/* --- @pre_ofbinit@ --- *                                             \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to cipher context           \
- *             @const void *key@ = pointer to the key buffer           \
- *             @size_t sz@ = size of the key                           \
- *             @const void *iv@ = pointer to initialization vector     \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Initializes a OFB context ready for use.  You should    \
- *             ensure that the IV chosen is unique: reusing an IV will \
- *             compromise the security of the entire plaintext.  This  \
- *             is equivalent to calls to @pre_init@, @pre_ofbsetkey@   \
- *             and @pre_ofbsetiv@.                                     \
- */                                                                    \
-                                                                       \
-extern void pre##_ofbinit(pre##_ofbctx */*ctx*/,                       \
-                         const void */*key*/, size_t /*sz*/,           \
-                         const void */*iv*/);                          \
-                                                                       \
-/* --- @pre_ofbencrypt@ --- *                                          \
- *                                                                     \
- * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
- *             @const void *src@ = pointer to source data              \
- *             @void *dest@ = pointer to destination data              \
- *             @size_t sz@ = size of block to be encrypted             \
- *                                                                     \
- * Returns:    ---                                                     \
- *                                                                     \
- * Use:                Encrypts or decrypts a block with a block cipher in OFB \
- *             mode: encryption and decryption are the same in OFB.    \
- *             The destination may be null to just churn the feedback  \
- *             round for a bit.  The source may be null to use the     \
- *             cipher as a random data generator.                      \
- */                                                                    \
-                                                                       \
-extern void pre##_ofbencrypt(pre##_ofbctx */*ctx*/,                    \
-                            const void */*src*/, void */*dest*/,       \
-                            size_t /*sz*/);                            \
-                                                                       \
-/* --- @pre_ofbrand@ --- *                                             \
- *                                                                     \
- * Arguments:  @const void *k@ = pointer to key material               \
- *             @size_t sz@ = size of key material                      \
- *                                                                     \
- * Returns:    Pointer to generic random number generator interface.   \
- *                                                                     \
- * Use:                Creates a random number interface wrapper around an     \
- *             OFB-mode block cipher.                                  \
- */                                                                    \
-                                                                       \
-extern grand *pre##_ofbrand(const void */*k*/, size_t /*sz*/);         \
-                                                                       \
-/* --- Generic cipher interface --- */                                 \
-                                                                       \
-extern const gccipher pre##_ofb;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/p-gentab.awk b/p-gentab.awk
deleted file mode 100755 (executable)
index 09a1c37..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-#! /usr/bin/awk -f
-#
-# $Id$
-
-function banner(name,  s, i)
-{
-  s = "/*----- " name " ";
-  while (length(s) < 75) s = s "-";
-  return (s "*/");
-}
-
-function fix(name)
-{
-  gsub(/[^0-9A-Za-z_]+/, "_", name);
-  return (name);
-}
-
-BEGIN {
-  print "/* -*-c-*-";
-  print " *";
-  print " * Table of prime groups [generated]";
-  print " */";
-  print "";
-  print "#include \"ptab.h\"";
-  print "";
-  print "#define N(x) (sizeof(x)/sizeof(*x))";
-  print "#define MP(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }";
-  print "#define NOMP { 0, 0, 0, 0, 0 }";
-  print "";
-  print banner("Prime data");
-  print "";
-
-  d_i = 0;
-  name = "";
-}
-
-function putmp(x,  d)
-{
-  if (!(x in data)) {
-    print "group " name ": missing " x >"/dev/stderr";
-    exit 1;
-  }
-  d = data[x];
-  if (!(d in cache)) {
-    n = "p_" fix(name) "_" x;
-    print "static mpw " n "[] = {";
-    system("./mpdump " d);
-    print "};";
-    print "";
-    cache[d] = n;
-  }
-  mp[x] = cache[d];
-}
-
-function flush()
-{
-  if (name == "") return;
-  print "/* --- Group " name " --- */";
-  delete mp;
-  print "";
-  putmp("p");
-  putmp("q");
-  putmp("g");
-  print "static pdata p_" fix(name) " = {";
-  print "  MP(" mp["p"] "),"
-  print "  MP(" mp["q"] "),"
-  print "  MP(" mp["g"] ")"
-  print "};";
-  print "";
-  dname[d_i++] = name;
-  d[name] = name;
-  r[name] = "p_" fix(name);
-  name = "";
-}
-
-/^[ \t]*(#|$)/ { next; }
-
-$1 == "alias" { flush(); dname[d_i++] = $2; d[$2] = $3; next; }
-
-$1 == "group" { flush(); delete data; name = $2; next; }
-
-{ data[$1] = $2; next; }
-
-END {
-  flush();
-  print banner("Main table");
-  print "";
-  print "const pentry ptab[] = {";
-  for (i = 0; i < d_i; i++) {
-    name = dname[i];
-    rname = d[name];
-    if (!rname in r) {
-      print "group " rname " not found (alias from " name ")" >"/dev/stderr";
-      exit 1;
-    }
-    print "  { \"" name "\", &" r[rname] " },";
-  }
-  print "  { 0, 0 }";
-  print "};"
-  print "";
-  print banner("That's all, folks");
-}
index 5a2014d..a82387b 100644 (file)
@@ -1,7 +1,5 @@
 %%% -*-latex-*-
 %%%
-%%% $Id: rand.tex,v 1.4 2004/04/08 01:36:15 mdw Exp $
-%%%
 %%% Description of Catacomb's random number generator
 %%%
 %%% (c) 1999 Straylight/Edgeware
diff --git a/paranoia.h b/paranoia.h
deleted file mode 100644 (file)
index e1ad2f5..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*-c-*-
- *
- * $Id: paranoia.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Macros and functions for cryptographic paranoia
- *
- * (c) 1998 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.
- */
-
-#ifndef CATACOMB_PARANOIA_H
-#define CATACOMB_PARANOIA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-/*----- Macros ------------------------------------------------------------*/
-
-#define BURN(x) (memset(&(x), 0, sizeof(x)))
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/passphrase.c b/passphrase.c
deleted file mode 100644 (file)
index 8bbbb9d..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Reading of passphrases (Unix-specific)
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <unistd.h>
-
-#include <mLib/dstr.h>
-
-#include "passphrase.h"
-#include "pixie.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static int fd = -1;
-static unsigned flags = 0;
-
-#define f_fail 1u
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @passphrase_connect@ ---
- *
- * Arguments:  @const char *sock@ = socket name to connect to, or null for
- *             default
- *
- * Returns:    Zero if OK, nonzero if it failed
- *
- * Use:                Attempts to connect to the passphrase pixie.
- */
-
-int passphrase_connect(const char *sock)
-{
-  if (fd != -1)
-    close(fd);
-  if ((fd = pixie_open(sock)) < 0) {
-    flags |= f_fail;
-    return (-1);
-  }
-  flags &= ~f_fail;
-  return (0);
-}
-
-static int pconn(void)
-{
-  if (fd != -1)
-    return (0);
-  if (flags & f_fail)
-    return (-1);
-  return (passphrase_connect(0));
-}
-
-/* --- @passphrase_read@ --- *
- *
- * Arguments:  @const char *tag@ = pointer to passphrase tag string
- *             @unsigned mode@ = reading mode
- *             @char *buf@ = pointer to destination buffer
- *             @size_t sz@ = size of destination buffer
- *
- * Returns:    Zero if successful, nonzero on failure.
- *
- * Use:                Reads a passphrase from the user, using some system-specific
- *             secure mechanism.  The mechanism may keep a cache of
- *             passphrases, so the user may not necessarily be prompted.
- */
-
-int passphrase_read(const char *tag, unsigned mode, char *buf, size_t sz)
-{
-  dstr d = DSTR_INIT;
-  int rc = 1;
-
-  /* --- Try talking to the pixie --- */
-
-  if (!pconn()) {
-    rc = pixie_read(fd, tag, mode, buf, sz);
-    if (rc < 0) {
-      close(fd);
-      fd = -1;
-      return (-1);
-    }
-    if (rc == 0)
-      return (0);
-  }
-
-  /* --- Read from the terminal --- */
-
-  dstr_putf(&d, "%s %s: ",
-           mode == PMODE_READ ? "Passphrase" : "New passphrase",
-           tag);
-  if (pixie_getpass(d.buf, buf, sz))
-    goto fail;
-  if (mode == PMODE_VERIFY) {
-    char b[1024];
-    DRESET(&d);
-    dstr_putf(&d, "Verify passphrase %s: ", tag);
-    if (pixie_getpass(d.buf, b, sizeof(b)) || strcmp(b, buf) != 0) {
-      memset(b, 0, sizeof(b));
-      goto fail;
-    }
-  }
-  dstr_destroy(&d);
-
-  /* --- If the pixie is interested, tell it the new passphrase --- */
-
-  if (fd >= 0)
-    pixie_set(fd, tag, buf);
-  return (0);
-
-  /* --- Tidy up after a failure --- */
-
-fail:
-  dstr_destroy(&d);
-  memset(buf, 0, sz);
-  return (-1);
-}
-
-/* --- @passphrase_cancel@ --- *
- *
- * Arguments:  @const char *tag@ = pointer to passphrase tag string
- *
- * Returns:    ---
- *
- * Use:                Attempts to make the passphrase cache forget about a
- *             particular passphrase.  This may be useful if the passphrase
- *             turns out to be wrong, or if the user is attempting to change
- *             the passphrase.
- */
-
-void passphrase_cancel(const char *tag)
-{
-  if (!pconn())
-    pixie_cancel(fd, tag);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/passphrase.h b/passphrase.h
deleted file mode 100644 (file)
index 89836c3..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Reading passphrases
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_PASSPHRASE_H
-#define CATACOMB_PASSPHRASE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- Passphrase modes --- *
- *
- * @PMODE_VERIFY@ requests that the passphrase be repeated to make sure it's
- * right.
- */
-
-enum {
-  PMODE_READ,
-  PMODE_VERIFY
-};
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @passphrase_connect@ ---
- *
- * Arguments:  @const char *sock@ = socket name to connect to, or null for
- *                     default
- *
- * Returns:    Zero if OK, nonzero if it failed
- *
- * Use:                Attempts to connect to the passphrase pixie.
- */
-
-extern int passphrase_connect(const char */*sock*/);
-
-/* --- @passphrase_read@ --- *
- *
- * Arguments:  @const char *tag@ = pointer to passphrase tag string
- *             @unsigned mode@ = reading mode
- *             @char *buf@ = pointer to destination buffer
- *             @size_t sz@ = size of destination buffer
- *
- * Returns:    Zero if successful, nonzero on failure.
- *
- * Use:                Reads a passphrase from the user, using some system-specific
- *             secure mechanism.  The mechanism may keep a cache of
- *             passphrases, so the user may not necessarily be prompted.
- */
-
-extern int passphrase_read(const char */*tag*/, unsigned /*mode*/,
-                          char */*buf*/, size_t /*sz*/);
-
-/* --- @passphrase_cancel@ --- *
- *
- * Arguments:  @const char *tag@ = pointer to passphrase tag string
- *
- * Returns:    ---
- *
- * Use:                Attempts to make the passphrase cache forget about a
- *             particular passphrase.  This may be useful if the passphrase
- *             turns out to be wrong, or if the user is attempting to change
- *             the passphrase.
- */
-
-extern void passphrase_cancel(const char */*tag*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/pcheck.pl b/pcheck.pl
deleted file mode 100644 (file)
index 3b1447a..0000000
--- a/pcheck.pl
+++ /dev/null
@@ -1,43 +0,0 @@
-#! /usr/bin/perl
-
-# Reads ptab.in or similarly-formatted file; writes a calc script to check
-# it.
-
-while (<>) {
-  next if /^\s*(\#[^!]|$)/;
-  @F = split;
-  if ($F[0] eq "group") {
-    $group = $F[1];
-    $_ = <>; @F = split; $F[0] eq "p" or die $F[0]; $p = $F[1];
-    $_ = <>; @F = split; $F[0] eq "q" or die $F[0]; $q = $F[1];
-    $_ = <>; @F = split; $F[0] eq "g" or die $F[0]; $g = $F[1];
-    print <<EOF;
-      print "testing $group...";
-      p = $p;
-      q = $q;
-      g = $g;
-      if (!ptest(p)) print "  p not prime";
-      if (!ptest(q)) print "  q not prime";
-      if ((p - 1)%q) print "  q doesn't divide p - 1";
-      h = (p - 1)/q;
-      if (pmod(g, q, p) != 1) print "  g doesn't have order q";
-      if (pmod(g, h, p) == 1) print "  g generates overly large group";
-      ff = 2;
-EOF
-    $ll = 0;
-    for (;;) {
-      $_ = <>; @F = split; $F[0] eq "#:factor" or last; $f = $F[1];
-      print <<EOF;
-       f = $f;
-       if (!ptest(f)) print "  factor not prime", f;
-       ff *= f;
-EOF
-      $ll = 1;
-    }
-    if ($ll) {
-      print <<EOF;
-       if (ff != p - 1) print "  missing factors";
-EOF
-    }
-  }
-}
diff --git a/perftest.c b/perftest.c
deleted file mode 100644 (file)
index 3c26937..0000000
+++ /dev/null
@@ -1,616 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Measure performance of various operations (Unix-specific)
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include "config.h"
-
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-#include <mLib/tv.h>
-
-#include "rand.h"
-#include "mp.h"
-#include "mprand.h"
-#include "fibrand.h"
-#include "rsa.h"
-#include "mpmont.h"
-#include "mpbarrett.h"
-#include "dh.h"
-#include "pgen.h"
-#include "ec.h"
-#include "group.h"
-
-#include "cc.h"
-#include "gcipher.h"
-#include "ghash.h"
-#include "gmac.h"
-#include "ectab.h"
-#include "ptab.h"
-
-/*----- Options -----------------------------------------------------------*/
-
-typedef struct opts {
-  const char *name;                    /* Pre-configured named thing */
-  unsigned fbits;                      /* Field size bits */
-  unsigned gbits;                      /* Group size bits */
-  unsigned n;                          /* Number of factors */
-  unsigned i;                          /* Number of intervals (or zero) */
-  double t;                            /* Time for each interval (secs) */
-  unsigned f;                          /* Flags */
-#define OF_NOCHECK 1u                  /*   Don't do group checking */
-} opts;
-
-/*----- Job switch --------------------------------------------------------*/
-
-/* --- Barrett exponentiation --- */
-
-typedef struct bar_ctx {
-  size_t n;
-  mpbarrett b;
-  mp_expfactor *e;
-} bar_ctx;
-
-static void *bar_init(opts *o)
-{
-  bar_ctx *c = CREATE(bar_ctx);
-  gprime_param gp;
-  qd_parse qd;
-  size_t i;
-
-  if (o->name) {
-    qd.p = o->name;
-    if (dh_parse(&qd, &gp))
-      die(1, "bad prime group: %s", qd.e);
-  } else {
-    if (!o->fbits) o->fbits = 1024;
-    dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0);
-  }
-  mpbarrett_create(&c->b, gp.p);
-  if (!o->n) o->n = 1;
-  c->n = o->n;
-  c->e = xmalloc(c->n * sizeof(group_expfactor));
-  for (i = 0; i < c->n; i++) {
-    c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0);
-    c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0);
-  }
-  dh_paramfree(&gp);
-  return (c);
-}
-
-static void bar_run(void *cc)
-{
-  bar_ctx *c = cc;
-  mp *d = mpbarrett_exp(&c->b, MP_NEW, c->e[0].base, c->e[0].exp);
-  MP_DROP(d);
-}
-
-static void barsim_run(void *cc)
-{
-  bar_ctx *c = cc;
-  mp *d = mpbarrett_mexp(&c->b, MP_NEW, c->e, c->n);
-  MP_DROP(d);
-}
-
-/* --- Montgomery exponentiation --- */
-
-typedef struct mont_ctx {
-  size_t n;
-  mpmont m;
-  mp_expfactor *e;
-} mont_ctx;
-
-static void *mont_init(opts *o)
-{
-  mont_ctx *c = CREATE(mont_ctx);
-  gprime_param gp;
-  qd_parse qd;
-  size_t i;
-
-  if (o->name) {
-    qd.p = o->name;
-    if (dh_parse(&qd, &gp))
-      die(1, "bad prime group: %s", qd.e);
-  } else {
-    if (!o->fbits) o->fbits = 1024;
-    dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0);
-  }
-  mpmont_create(&c->m, gp.p);
-  if (!o->n) o->n = 1;
-  c->n = o->n;
-  c->e = xmalloc(c->n * sizeof(mp_expfactor));
-  for (i = 0; i < c->n; i++) {
-    c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0);
-    c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0);
-  }
-  dh_paramfree(&gp);
-  return (c);
-}
-
-static void mont_run(void *cc)
-{
-  mont_ctx *c = cc;
-  mp *d = mpmont_expr(&c->m, MP_NEW, c->e[0].base, c->e[0].exp);
-  MP_DROP(d);
-}
-
-static void montsim_run(void *cc)
-{
-  mont_ctx *c = cc;
-  mp *d = mpmont_mexpr(&c->m, MP_NEW, c->e, c->n);
-  MP_DROP(d);
-}
-
-/* --- Group exponentiation --- */
-
-typedef struct gr_ctx {
-  size_t n;
-  group *g;
-  group_expfactor *e;
-} gr_ctx;
-
-static void *grp_init(opts *o)
-{
-  gr_ctx *c = CREATE(gr_ctx);
-  const char *e;
-  gprime_param gp;
-  qd_parse qd;
-  size_t i;
-
-  if (o->name) {
-    qd.p = o->name;
-    if (dh_parse(&qd, &gp))
-      die(1, "bad prime group: %s", qd.e);
-  } else {
-    if (!o->fbits) o->fbits = 1024;
-    dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0);
-  }
-  c->g = group_prime(&gp);
-  if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0)
-    die(1, "bad group: %s", e);
-  if (!o->n) o->n = 1;
-  c->n = o->n;
-  c->e = xmalloc(c->n * sizeof(group_expfactor));
-  for (i = 0; i < c->n; i++) {
-    c->e[i].base = G_CREATE(c->g);
-    G_FROMINT(c->g, c->e[i].base,
-             mprand_range(MP_NEW, gp.p, &rand_global, 0));
-    c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0);
-  }
-  dh_paramfree(&gp);
-  return (c);
-}
-
-static void *grec_init(opts *o)
-{
-  gr_ctx *c = CREATE(gr_ctx);
-  const char *e;
-  ec_info ei;
-  ec p = EC_INIT;
-  size_t i;
-
-  if (!o->name)
-    die(1, "can't generate elliptic curves");
-  if ((e = ec_getinfo(&ei, o->name)) != 0)
-    die(1, "bad curve: %s", e);
-  c->g = group_ec(&ei);
-  if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0)
-    die(1, "bad group: %s", e);
-  if (!o->n) o->n = 1;
-  c->n = o->n;
-  c->e = xmalloc(c->n * sizeof(group_expfactor));
-  for (i = 0; i < c->n; i++) {
-    c->e[i].base = G_CREATE(c->g);
-    ec_rand(ei.c, &p, &rand_global);
-    G_FROMEC(c->g, c->e[i].base, &p);
-    c->e[i].exp = mprand_range(MP_NEW, ei.r, &rand_global, 0);
-  }
-  EC_DESTROY(&p);
-  return (c);
-}
-
-static void gr_run(void *cc)
-{
-  gr_ctx *c = cc;
-  ge *x = G_CREATE(c->g);
-  G_EXP(c->g, x, c->e[0].base, c->e[0].exp);
-  G_DESTROY(c->g, x);
-}
-
-static void grsim_run(void *cc)
-{
-  gr_ctx *c = cc;
-  ge *x = G_CREATE(c->g);
-  G_MEXP(c->g, x, c->e, c->n);
-  G_DESTROY(c->g, x);
-}
-
-/* --- RSA --- */
-
-typedef struct rsapriv_ctx {
-  rsa_priv rp;
-  rsa_privctx rpc;
-  mp *m;
-} rsapriv_ctx;
-
-static void *rsapriv_init(opts *o)
-{
-  rsapriv_ctx *c = CREATE(rsapriv_ctx);
-
-  if (!o->fbits) o->fbits = 1024;
-  rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0);
-  rsa_privcreate(&c->rpc, &c->rp, 0);
-  c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0);
-  return (c);
-}
-
-static void *rsaprivblind_init(opts *o)
-{
-  rsapriv_ctx *c = CREATE(rsapriv_ctx);
-
-  if (!o->fbits) o->fbits = 1024;
-  rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0);
-  rsa_privcreate(&c->rpc, &c->rp, fibrand_create(0));
-  c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0);
-  return (c);
-}
-
-static void rsapriv_run(void *cc)
-{
-  rsapriv_ctx *c = cc;
-  mp *d = rsa_privop(&c->rpc, MP_NEW, c->m);
-  MP_DROP(d);
-}
-
-typedef struct rsapub_ctx {
-  rsa_pub rp;
-  rsa_pubctx rpc;
-  mp *m;
-} rsapub_ctx;
-
-static void *rsapub_init(opts *o)
-{
-  rsapub_ctx *c = CREATE(rsapub_ctx);
-  rsa_priv rp;
-
-  if (!o->fbits) o->fbits = 1024;
-  rsa_gen(&rp, o->fbits, &rand_global, 0, pgen_evspin, 0);
-  c->rp.n = MP_COPY(rp.n);
-  c->rp.e = MP_COPY(rp.e);
-  rsa_privfree(&rp);
-  rsa_pubcreate(&c->rpc, &c->rp);
-  c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0);
-  return (c);
-}
-
-static void rsapub_run(void *cc)
-{
-  rsapub_ctx *c = cc;
-  mp *d = rsa_pubop(&c->rpc, MP_NEW, c->m);
-  MP_DROP(d);
-}
-
-/* --- Symmetric encryption --- */
-
-typedef struct ksched_ctx {
-  const gccipher *c;
-  octet *k;
-  size_t ksz;
-} ksched_ctx;
-
-static void *ksched_init(opts *o)
-{
-  ksched_ctx *c = CREATE(ksched_ctx);
-  if (!o->name)
-    die(1, "must specify encryption scheme name");
-  if ((c->c = gcipher_byname(o->name)) == 0)
-    die(1, "encryption scheme `%s' not known", o->name);
-  c->ksz = keysz(o->gbits/8, c->c->keysz);
-  c->k = xmalloc(c->ksz);
-  rand_get(RAND_GLOBAL, c->k, c->ksz);
-  return (c);
-}
-
-static void ksched_run(void *cc)
-{
-  ksched_ctx *c = cc;
-  gcipher *gc = GC_INIT(c->c, c->k, c->ksz);
-  GC_DESTROY(gc);
-}
-
-typedef struct enc_ctx {
-  gcipher *c;
-  octet *m;
-  size_t sz;
-  size_t n;
-} enc_ctx;
-
-static void *enc_init(opts *o)
-{
-  enc_ctx *c = CREATE(enc_ctx);
-  const gccipher *cc;
-  size_t ksz;
-  octet *k;
-  if (!o->name)
-    die(1, "must specify encryption scheme name");
-  if ((cc = gcipher_byname(o->name)) == 0)
-    die(1, "encryption scheme `%s' not known", o->name);
-  ksz = keysz(0, cc->keysz);
-  k = xmalloc(ksz);
-  rand_get(RAND_GLOBAL, k, ksz);
-  c->c = GC_INIT(cc, k, ksz);
-  xfree(k);
-  c->sz = o->gbits ? o->gbits : 65536;
-  c->n = o->n ? o->n : 16;
-  c->m = xmalloc(c->sz);
-  return (c);
-}
-
-static void enc_run(void *cc)
-{
-  enc_ctx *c = cc;
-  size_t i;
-  for (i = 0; i < c->n; i++)
-    GC_ENCRYPT(c->c, c->m, c->m, c->sz);
-}
-
-/* --- Hashing --- */
-
-typedef struct hash_ctx {
-  const gchash *h;
-  octet *m;
-  size_t sz;
-  size_t n;
-} hash_ctx;
-
-static void *hash_init(opts *o)
-{
-  hash_ctx *c = CREATE(hash_ctx);
-  if (!o->name)
-    die(1, "must specify hash function name");
-  if ((c->h = ghash_byname(o->name)) == 0)
-    die(1, "hash function `%s' not known", o->name);
-  c->sz = o->gbits ? o->gbits : 65536;
-  c->n = o->n ? o->n : 16;
-  c->m = xmalloc(c->sz);
-  return (c);
-}
-
-static void hash_run(void *cc)
-{
-  hash_ctx *c = cc;
-  size_t i;
-  ghash *h = GH_INIT(c->h);
-  for (i = 0; i < c->n; i++)
-    GH_HASH(h, c->m, c->sz);
-  GH_DONE(h, 0);
-  GH_DESTROY(h);
-}
-
-/* --- Job table --- */
-
-typedef struct jobops {
-  const char *name;
-  void *(*init)(opts *);
-  void (*run)(void *);
-} jobops;
-
-static const jobops jobtab[] = {
-  { "g-prime-exp",             grp_init,               gr_run },
-  { "g-ec-mul",                        grec_init,              gr_run },
-  { "g-prime-exp-sim",         grp_init,               grsim_run },
-  { "g-ec-mul-sim",            grec_init,              grsim_run },
-  { "barrett-exp",             bar_init,               bar_run },
-  { "barrett-exp-sim",         bar_init,               barsim_run },
-  { "mont-exp",                        mont_init,              mont_run },
-  { "mont-exp-sim",            mont_init,              montsim_run },
-  { "rsa-priv",                        rsapriv_init,           rsapriv_run },
-  { "rsa-priv-blind",          rsaprivblind_init,      rsapriv_run },
-  { "rsa-pub",                 rsapub_init,            rsapub_run },
-  { "ksched",                  ksched_init,            ksched_run },
-  { "enc",                     enc_init,               enc_run },
-  { "hash",                    hash_init,              hash_run },
-  { 0,                         0,                      0 }
-};
-
-/*----- Main code ---------------------------------------------------------*/
-
-void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb " VERSION "\n");
-}
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "Usage: $ [-options] job\n");
-}
-
-static void help(FILE *fp)
-{
-  version(fp);
-  putc('\n', fp);
-  usage(fp);
-  pquis(fp, "\n\
-Various performance tests.\n\
-\n\
-Options:\n\
-\n\
--h, --help             Show this help text.\n\
--v, --version          Show program version number.\n\
--u, --usage            Show terse usage message.\n\
--l, --list [ITEM...]   List all the various names of things.\n\
-\n\
--C, --name=NAME                Select curve/DH-group/enc/hash name.\n\
--b, --field-bits       Field size for g-prime and rsa.\n\
--q, --no-check         Don't check field/group for validity.\n\
--B, --group-bits       Group size for g-prime; key size for ksched;\n\
-                         data size for enc and hash.\n\
--n, --factors=COUNT    Number of factors for {exp,mul}-sim.\n\
--i, --intervals=COUNT  Number of intervals to run for.  [0; forever]\n\
--t, --time=TIME                Length of an interval in seconds.  [1]\n\
-");
-}
-
-#define LISTS(LI)                                                      \
-  LI("Lists", list,                                                    \
-     listtab[i].name, listtab[i].name)                                 \
-  LI("Jobs", job,                                                      \
-     jobtab[i].name, jobtab[i].name)                                   \
-  LI("Elliptic curves", ec,                                            \
-     ectab[i].name, ectab[i].name)                                     \
-  LI("Diffie-Hellman groups", dh,                                      \
-     ptab[i].name, ptab[i].name)                                       \
-  LI("Encryption algorithms", cipher,                                  \
-     gciphertab[i], gciphertab[i]->name)                               \
-  LI("Hash functions", hash,                                           \
-     ghashtab[i], ghashtab[i]->name)
-
-MAKELISTTAB(listtab, LISTS)
-
-static unsigned uarg(const char *what, const char *p)
-{
-  char *q;
-  unsigned long u;
-  errno = 0;
-  u = strtoul(p, &q, 0);
-  if (*q || u > UINT_MAX || q == p || errno)
-    die(1, "bad %s `%s'", what, p);
-  return (u);
-}
-
-static double farg(const char *what, const char *p)
-{
-  char *q;
-  double f;
-  errno = 0;
-  f = strtod(p, &q);
-  if (*q || q == p || errno)
-    die(1, "bad %s `%s'", what, p);
-  return (f);
-}
-
-int main(int argc, char *argv[])
-{
-  int i;
-  opts o = { 0 };
-  const jobops *j;
-  struct timeval tv_next, tv_now;
-  double t, ttot;
-  unsigned n;
-  unsigned long ii;
-  clock_t c_start, c_stop;
-  double itot;
-  void *p;
-
-  ego(argv[0]);
-  o.t = 1;
-  for (;;) {
-    static const struct option opts[] = {
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'v' },
-      { "usage",       0,              0,      'u' },
-      { "list",                0,              0,      'l' },
-      { "name",                OPTF_ARGREQ,    0,      'C' },
-      { "field-bits",  OPTF_ARGREQ,    0,      'b' },
-      { "group-bits",  OPTF_ARGREQ,    0,      'B' },
-      { "factors",     OPTF_ARGREQ,    0,      'n' },
-      { "intervals",   OPTF_ARGREQ,    0,      'i' },
-      { "time",                OPTF_ARGREQ,    0,      't' },
-      { "no-check",    0,              0,      'q' },
-      { 0,             0,              0,      0 }
-    };
-
-    i = mdwopt(argc, argv, "hvulC:b:B:n:i:t:q", opts, 0, 0, 0);
-    if (i < 0) break;
-    switch (i) {
-      case 'h': help(stdout); exit(0);
-      case 'v': version(stdout); exit(0);
-      case 'u': usage(stdout); exit(0);
-      case 'l': exit(displaylists(listtab, argv + optind));
-      case 'C': o.name = optarg; break;
-      case 'b': o.fbits = uarg("field bits", optarg); break;
-      case 'B': o.gbits = uarg("subgroup bits", optarg); break;
-      case 'n': o.n = uarg("factor count", optarg); break;
-      case 'i': o.i = uarg("interval count", optarg); break;
-      case 't': o.t = farg("interval length", optarg); break;
-      case 'q': o.f |= OF_NOCHECK; break;
-      default: usage(stderr); exit(1);
-    }
-  }
-  if (optind + 1 != argc) { usage(stderr); exit(1); }
-
-  for (j = jobtab; j->name; j++)
-    if (strcmp(j->name, argv[optind]) == 0) break;
-  if (!j->name) die(1, "unknown job type `%s'", argv[optind]);
-  p = j->init(&o);
-
-  n = 0;
-  ttot = itot =         0;
-  gettimeofday(&tv_now, 0);
-  do {
-    tv_addl(&tv_next, &tv_now, o.t, fmod(o.t * MILLION, MILLION));
-    ii = 0;
-    c_start = clock();
-    do {
-      j->run(p);
-      ii++;
-      gettimeofday(&tv_now, 0);
-    } while (TV_CMP(&tv_now, <, &tv_next));
-    c_stop = clock();
-    t = (double)(c_stop - c_start)/CLOCKS_PER_SEC;
-    itot += ii;
-    ttot += t;
-    printf("%5u: did = %5lu; /sec = %5f; avg /sec = %5f\n",
-          n, ii, ii/t, itot/ttot);
-    fflush(stdout);
-    n++;
-  } while (!o.i || n < o.i);
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/pfilt.c b/pfilt.c
deleted file mode 100644 (file)
index ae99a9b..0000000
--- a/pfilt.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/* -*-c-*-
- *
- * $Id: pfilt.c,v 1.6 2004/04/08 01:36:15 mdw Exp $
- *
- * Finding and testing prime numbers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpint.h"
-#include "pfilt.h"
-#include "pgen.h"
-#include "primetab.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @smallenough@ --- *
- *
- * Arguments:  @mp *m@ = integer to test
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Assuming that @m@ has been tested by trial division on every
- *             prime in the small-primes array, this function will return
- *             @PGEN_DONE@ if the number is less than the square of the
- *             largest small prime.
- */
-
-static int smallenough(mp *m)
-{
-  static mp *max = 0;
-  int rc = PGEN_TRY;
-
-  if (!max) {
-    max = mp_fromuint(MP_NEW, MAXPRIME);
-    max = mp_sqr(max, max);
-    max->a->n--; /* Permanent allocation */
-  }
-  if (MP_CMP(m, <=, MP_ONE))
-    rc = PGEN_FAIL;
-  else if (MP_CMP(m, <, max))
-    rc = PGEN_DONE;
-  return (rc);
-}
-
-/* --- @pfilt_smallfactor@ --- *
- *
- * Arguments:  @mp *m@ = integer to test
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Tests a number by dividing by a number of small primes.  This
- *             is a useful first step if you're testing random primes; for
- *             sequential searches, @pfilt_create@ works better.
- */
-
-int pfilt_smallfactor(mp *m)
-{
-  int rc = PGEN_TRY;
-  int i;
-  size_t sz = MP_LEN(m);
-  mparena *a = m->a ? m->a : MPARENA_GLOBAL;
-  mpw *v = mpalloc(a, sz);
-
-  /* --- Fill in the residues --- */
-
-  for (i = 0; i < NPRIME; i++) {
-    if (!mpx_udivn(v, v + sz, m->v, m->vl, primetab[i])) {
-      if (MP_LEN(m) == 1 && m->v[0] == primetab[i])
-       rc = PGEN_DONE;
-      else
-       rc = PGEN_FAIL;
-      break;
-    }
-  }
-
-  /* --- Check for small primes --- */
-
-  if (rc == PGEN_TRY)
-    rc = smallenough(m);
-
-  /* --- Done --- */
-
-  mpfree(a, v);
-  return (rc);
-}
-
-/* --- @pfilt_create@ --- *
- *
- * Arguments:  @pfilt *p@ = pointer to prime filtering context
- *             @mp *m@ = pointer to initial number to test
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Tests an initial number for primality by computing its
- *             residue modulo various small prime numbers.  This is fairly
- *             quick, but not particularly certain.  If a @PGEN_TRY@
- *             result is returned, perform Rabin-Miller tests to confirm.
- */
-
-int pfilt_create(pfilt *p, mp *m)
-{
-  int rc = PGEN_TRY;
-  int i;
-  size_t sz = MP_LEN(m);
-  mparena *a = m->a ? m->a : MPARENA_GLOBAL;
-  mpw *v = mpalloc(a, sz);
-
-  /* --- Take a copy of the number --- */
-
-  mp_shrink(m);
-  p->m = MP_COPY(m);
-
-  /* --- Fill in the residues --- */
-
-  for (i = 0; i < NPRIME; i++) {
-    p->r[i] = mpx_udivn(v, v + sz, m->v, m->vl, primetab[i]);
-    if (!p->r[i] && rc == PGEN_TRY) {
-      if (MP_LEN(m) == 1 && m->v[0] == primetab[i])
-       rc = PGEN_DONE;
-      else
-       rc = PGEN_FAIL;
-    }
-  }
-
-  /* --- Check for small primes --- */
-
-  if (rc == PGEN_TRY)
-    rc = smallenough(m);
-
-  /* --- Done --- */
-
-  mpfree(a, v);
-  return (rc);
-}
-
-/* --- @pfilt_destroy@ --- *
- *
- * Arguments:  @pfilt *p@ = pointer to prime filtering context
- *
- * Returns:    ---
- *
- * Use:                Discards a context and all the resources it holds.
- */
-
-void pfilt_destroy(pfilt *p)
-{
-  mp_drop(p->m);
-}
-
-/* --- @pfilt_step@ --- *
- *
- * Arguments:  @pfilt *p@ = pointer to prime filtering context
- *             @mpw step@ = how much to step the number
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Steps a number by a small amount.  Stepping is much faster
- *             than initializing with a new number.  The test performed is
- *             the same simple one used by @primetab_create@, so @PGEN_TRY@
- *             results should be followed up by a Rabin-Miller test.
- */
-
-int pfilt_step(pfilt *p, mpw step)
-{
-  int rc = PGEN_TRY;
-  int i;
-
-  /* --- Add the step on to the number --- */
-
-  p->m = mp_split(p->m);
-  mp_ensure(p->m, MP_LEN(p->m) + 1);
-  mpx_uaddn(p->m->v, p->m->vl, step);
-  mp_shrink(p->m);
-
-  /* --- Update the residue table --- */
-
-  for (i = 0; i < NPRIME; i++) {
-    p->r[i] = (p->r[i] + step) % primetab[i];
-    if (!p->r[i] && rc == PGEN_TRY) {
-      if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i])
-       rc = PGEN_DONE;
-      else
-       rc = PGEN_FAIL;
-    }
-  }
-
-  /* --- Check for small primes --- */
-
-  if (rc == PGEN_TRY)
-    rc = smallenough(p->m);
-
-  /* --- Done --- */
-
-  return (rc);
-}
-
-/* --- @pfilt_muladd@ --- *
- *
- * Arguments:  @pfilt *p@ = destination prime filtering context
- *             @const pfilt *q@ = source prime filtering context
- *             @mpw m@ = number to multiply by
- *             @mpw a@ = number to add
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Multiplies the number in a prime filtering context by a
- *             small value and then adds a small value.  The destination
- *             should either be uninitialized or the same as the source.
- *
- *             Common things to do include multiplying by 2 and adding 0 to
- *             turn a prime into a jump for finding other primes with @q@ as
- *             a factor of @p - 1@, or multiplying by 2 and adding 1.
- */
-
-int pfilt_muladd(pfilt *p, const pfilt *q, mpw m, mpw a)
-{
-  int rc = PGEN_TRY;
-  int i;
-
-  /* --- Multiply the big number --- */
-
-  {
-    mp *d = mp_new(MP_LEN(q->m) + 2, q->m->f);
-    mpx_umuln(d->v, d->vl, q->m->v, q->m->vl, m);
-    mpx_uaddn(d->v, d->vl, a);
-    if (p == q)
-      mp_drop(p->m);
-    mp_shrink(d);
-    p->m = d;
-  }
-
-  /* --- Gallivant through the residue table --- */
-
-  for (i = 0; i < NPRIME; i++) {
-    p->r[i] = (q->r[i] * m + a) % primetab[i];
-    if (!p->r[i] && rc == PGEN_TRY) {
-      if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i])
-       rc = PGEN_DONE;
-      else
-       rc = PGEN_FAIL;
-    }
-  }
-
-  /* --- Check for small primes --- */
-
-  if (rc == PGEN_TRY)
-    rc = smallenough(p->m);
-
-  /* --- Finished --- */
-
-  return (rc);
-}
-
-/* --- @pfilt_jump@ --- *
- *
- * Arguments:  @pfilt *p@ = pointer to prime filtering context
- *             @const pfilt *j@ = pointer to another filtering context
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Steps a number by a large amount.  Even so, jumping is much
- *             faster than initializing a new number.  The test peformed is
- *             the same simple one used by @primetab_create@, so @PGEN_TRY@
- *             results should be followed up by a Rabin-Miller test.
- *
- *             Note that the number stored in the @j@ context is probably
- *             better off being even than prime.  The important thing is
- *             that all of the residues for the number have already been
- *             computed.
- */
-
-int pfilt_jump(pfilt *p, const pfilt *j)
-{
-  int rc = PGEN_TRY;
-  int i;
-
-  /* --- Add the step on --- */
-
-  p->m = mp_add(p->m, p->m, j->m);
-
-  /* --- Update the residue table --- */
-
-  for (i = 0; i < NPRIME; i++) {
-    p->r[i] = p->r[i] + j->r[i];
-    if (p->r[i] > primetab[i])
-      p->r[i] -= primetab[i];
-    if (!p->r[i] && rc == PGEN_TRY) {
-      if (MP_LEN(p->m) == 1 && p->m->v[0] == primetab[i])
-       rc = PGEN_DONE;
-      else
-       rc = PGEN_FAIL;
-    }
-  }
-
-  /* --- Check for small primes --- */
-
-  if (rc == PGEN_TRY)
-    rc = smallenough(p->m);
-
-  /* --- Done --- */
-
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/pfilt.h b/pfilt.h
deleted file mode 100644 (file)
index 24f94c7..0000000
--- a/pfilt.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* -*-c-*-
- *
- * $Id: pfilt.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Finding and testing prime numbers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_PFILT_H
-#define CATACOMB_PFILT_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_PRIMETAB_H
-#  include "primetab.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct pfilt {
-  mp *m;
-  smallprime r[NPRIME];
-} pfilt;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @pfilt_smallfactor@ --- *
- *
- * Arguments:  @mp *m@ = integer to test
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Tests a number by dividing by a number of small primes.  This
- *             is a useful first step if you're testing random primes; for
- *             sequential searches, @pfilt_create@ works better.
- */
-
-extern int pfilt_smallfactor(mp */*m*/);
-
-/* --- @pfilt_create@ --- *
- *
- * Arguments:  @pfilt *p@ = pointer to prime filtering context
- *             @mp *m@ = pointer to initial number to test
- *
- * Returns:    A @PGEN@ result code.
- *
- * Use:                Tests an initial number for primality by computing its
- *             residue modulo various small prime numbers.  This is fairly
- *             quick, but not particularly certain.  If a @PGEN_TRY@
- *             result is returned, perform Rabin-Miller tests to confirm.
- */
-
-extern int pfilt_create(pfilt */*p*/, mp */*m*/);
-
-/* --- @pfilt_destroy@ --- *
- *
- * Arguments:  @pfilt *p@ = pointer to prime filtering context
- *
- * Returns:    ---
- *
- * Use:                Discards a context and all the resources it holds.
- */
-
-extern void pfilt_destroy(pfilt */*p*/);
-
-/* --- @pfilt_step@ --- *
- *
- * Arguments:  @pfilt *p@ = pointer to prime filtering context
- *             @mpw step@ = how much to step the number
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Steps a number by a small amount.  Stepping is much faster
- *             than initializing with a new number.  The test performed is
- *             the same simple one used by @primetab_create@, so @PGEN_TRY@
- *             results should be followed up by a Rabin-Miller test.
- */
-
-extern int pfilt_step(pfilt */*p*/, mpw /*step*/);
-
-/* --- @pfilt_muladd@ --- *
- *
- * Arguments:  @pfilt *p@ = destination prime filtering context
- *             @const pfilt *q@ = source prime filtering context
- *             @mpw m@ = number to multiply by
- *             @mpw a@ = number to add
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Multiplies the number in a prime filtering context by a
- *             small value and then adds a small value.  The destination
- *             should either be uninitialized or the same as the source.
- *
- *             Common things to do include multiplying by 2 and adding 0 to
- *             turn a prime into a jump for finding other primes with @q@ as
- *             a factor of @p - 1@, or multiplying by 2 and adding 1.
- */
-
-extern int pfilt_muladd(pfilt */*p*/, const pfilt */*q*/,
-                       mpw /*m*/, mpw /*a*/);
-
-/* --- @pfilt_jump@ --- *
- *
- * Arguments:  @pfilt *p@ = pointer to prime filtering context
- *             @const pfilt *j@ = pointer to another filtering context
- *
- * Returns:    One of the @PGEN@ result codes.
- *
- * Use:                Steps a number by a large amount.  Even so, jumping is much
- *             faster than initializing a new number.  The test peformed is
- *             the same simple one used by @primetab_create@, so @PGEN_TRY@
- *             results should be followed up by a Rabin-Miller test.
- *
- *             Note that the number stored in the @j@ context is probably
- *             better off being even than prime.  The important thing is
- *             that all of the residues for the number have already been
- *             computed.
- */
-
-extern int pfilt_jump(pfilt */*p*/, const pfilt */*j*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/pgen-gcd.c b/pgen-gcd.c
deleted file mode 100644 (file)
index 863b151..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*-c-*-
- *
- * $Id: pgen-gcd.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Prime search stepper ensuring a low GCD for %$(p - 1)/2$%
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "pgen.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-int pgen_gcdstep(int rq, pgen_event *ev, void *p)
-{
-  pgen_gcdstepctx *g = p;
-  int rc = PGEN_ABORT;
-
-  switch (rq) {
-
-    /* --- Set everything up --- *
-     *
-     * Call things off if @p@ and @jp@ have common factors, or if @q@, @r@
-     * and @jq@ have common factors greater than @max@.
-     */
-
-    case PGEN_BEGIN: {
-      mp *p = ev->m;
-      mp_gcd(&g->g, 0, 0, p, g->jp.m);
-      if (MP_CMP(g->g, >, MP_ONE))
-       return (PGEN_ABORT);
-      g->q = mp_lsr(MP_NEW, p, 1);
-      g->jq = mp_lsr(MP_NEW, g->jp.m, 1);
-      mp_gcd(&g->g, 0, 0, g->q, g->jq);
-      mp_gcd(&g->g, 0, 0, g->g, g->r);
-      if (MP_CMP(g->g, >, g->max)) {
-       mp_drop(g->q);
-       mp_drop(g->jq);
-       return (PGEN_ABORT);
-      }
-      rc = pfilt_create(&g->p, p);
-      mp_drop(p);
-    } break;
-
-    /* --- Grind through another iteration --- */
-
-    case PGEN_TRY:
-      mp_drop(ev->m);
-      rc = pfilt_jump(&g->p, &g->jp);
-      g->q = mp_add(g->q, g->q, g->jq);
-      break;
-
-    /* --- Finished --- */
-
-    case PGEN_DONE:
-      pfilt_destroy(&g->p);
-      mp_drop(g->q);
-      mp_drop(g->jq);
-      return (PGEN_DONE);
-  }
-
-  /* --- Step on until everything is OK --- */
-
-  for (;;) {
-    if (rc != PGEN_FAIL) {
-      mp_gcd(&g->g, 0, 0, g->r, g->q);
-      if (MP_CMP(g->g, >, g->max))
-       rc = PGEN_FAIL;
-    }
-    if (rc != PGEN_FAIL)
-      break;
-    rc = pfilt_jump(&g->p, &g->jp);
-    g->q = mp_add(g->q, g->q, g->jq);
-  }
-
-  ev->m = MP_COPY(g->p.m);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/pgen-simul.c b/pgen-simul.c
deleted file mode 100644 (file)
index 175b009..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Simultaneous prime search
- *
- * (c) 2006 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdlib.h>
-
-#include <mLib/macros.h>
-
-#include "mprand.h"
-#include "pgen.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rcmerge@ --- *
- *
- * Arguments:  @int a, b@ = a pair of @PGEN@ return codes
- *
- * Returns:    The overall return code capturing both.
- */
-
-static int rcmerge(int a, int b)
-{
-#define FROB(state)                                                    \
-    if (a == PGEN_##state || b == PGEN_##state) return (PGEN_##state)
-  FROB(FAIL);
-  FROB(TRY);
-  FROB(PASS);
-#undef FROB
-  return (PGEN_DONE);
-}
-
-/* --- @pgen_simulstep@ --- *
- *
- * Step a collection of numbers simultaneously.
- */
-
-int pgen_simulstep(int rq, pgen_event *ev, void *p)
-{
-  pgen_simulctx *ss = p;
-  pgen_simulprime *sp;
-  int rc = PGEN_ABORT, nrc;
-  unsigned i;
-  mp *q;
-
-  assert(ss->n);
-  switch (rq) {
-    case PGEN_BEGIN:
-      rc = PGEN_DONE;
-      q = MP_NEW;
-      for (i = 0; i < ss->n; i++) {
-       sp = &ss->v[i];
-       q = mp_mul(q, ss->step, sp->mul);
-       if (MP_LEN(q) <= 1)
-         sp->u.step = q->v[0];
-       else {
-         sp->u.jump = xmalloc(sizeof(pfilt));
-         pfilt_create(sp->u.jump, q);
-         sp->f |= PGENF_JUMP;
-       }
-       q = mp_mul(q, ev->m, sp->mul);
-       q = mp_add(q, q, sp->add);
-       nrc = pfilt_create(&sp->p, q);
-       rc = rcmerge(rc, nrc);
-      }
-      MP_DROP(q);
-      if (rc != PGEN_FAIL)
-       goto done;
-    case PGEN_TRY:
-      for (;;) {
-       rc = PGEN_DONE;
-       for (i = 0; i < ss->n; i++) {
-         sp = &ss->v[i];
-         if (sp->f & PGENF_JUMP)
-           nrc = pfilt_jump(&sp->p, sp->u.jump);
-         else
-           nrc = pfilt_step(&sp->p, sp->u.step);
-         rc = rcmerge(rc, nrc);
-       }
-       if (rc != PGEN_FAIL)
-         goto done;
-      }
-    done:
-      mp_drop(ev->m);
-      ev->m = MP_COPY(ss->v[0].p.m);
-      break;
-    case PGEN_DONE:
-      for (i = 0; i < ss->n; i++) {
-       sp = &ss->v[i];
-       if (sp->f & PGENF_JUMP) {
-         pfilt_destroy(sp->u.jump);
-         xfree(sp->u.jump);
-       }
-       if (sp->f & PGENF_KEEP)
-         sp->u.x = MP_COPY(sp->p.m);
-       pfilt_destroy(&sp->p);
-      }
-      rc = PGEN_DONE;
-      break;
-  }
-  return (rc);
-}
-
-/* --- @pgen_simultest@ --- *
- *
- * Test a collection of numbers simultaneously.
- */
-
-int pgen_simultest(int rq, pgen_event *ev, void *p)
-{
-  pgen_simulctx *ss = p;
-  pgen_simulprime *sp;
-  int rc;
-  unsigned i;
-  mp *m;
-
-  assert(ss->n);
-  switch (rq) {
-    case PGEN_BEGIN:
-      for (i = 0; i < ss->n; i++)
-       rabin_create(&ss->v[i].r, ss->v[i].p.m);
-      rc = PGEN_TRY;
-      break;
-    case PGEN_TRY:
-      m = MP_NEW;
-      for (i = 0; i < ss->n; i++) {
-       sp = &ss->v[i];
-       m = mprand_range(m, sp->p.m, ev->r, 0);
-       rc = rabin_test(&sp->r, m);
-       if (rc != PGEN_PASS)
-         break;
-      }
-      mp_drop(m);
-      break;
-    case PGEN_DONE:
-      for (i = 0; i < ss->n; i++)
-       rabin_destroy(&ss->v[i].r);
-      rc = PGEN_DONE;
-      break;
-  }
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/pgen-stdev.c b/pgen-stdev.c
deleted file mode 100644 (file)
index c917998..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*-c-*-
- *
- * $Id: pgen-stdev.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Standard event handlers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "pgen.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @pgen_evspin@ --- *
- *
- * Displays a spinning baton to show progress.
- */
-
-int pgen_evspin(int rq, pgen_event *ev, void *p)
-{
-  static char spinner[] = "/-\\|";
-  static char *q = spinner;
-
-  switch (rq) {
-    case PGEN_PASS:
-    case PGEN_FAIL:
-      putchar(*q++);
-      putchar('\b');
-      fflush(stdout);
-      if (!*q)
-       q = spinner;
-      break;
-    case PGEN_DONE:
-    case PGEN_ABORT:
-      putchar(' ');
-      putchar('\b');
-      fflush(stdout);
-      break;
-  }
-  return (0);
-}
-
-/* --- @pgen_ev@ --- *
- *
- * Traditional event handler, shows dots for each test.
- */
-
-int pgen_ev(int rq, pgen_event *ev, void *p)
-{
-  switch (rq) {
-    case PGEN_BEGIN:
-      printf("Searching for %s: ", ev->name);
-      fflush(stdout);
-      break;
-    case PGEN_FAIL:
-      putchar('.');
-      fflush(stdout);
-      break;
-    case PGEN_PASS:
-      putchar('+');
-      fflush(stdout);
-      break;
-    case PGEN_DONE:
-      puts("+ ok");
-      break;
-    case PGEN_ABORT:
-      puts(" failed");
-      break;
-  }
-  return (0);
-}
-
-/* --- @pgen_subev@ --- *
- *
- * Subsidiary event handler, mainly for Lim-Lee searches and so on.
- */
-
-int pgen_subev(int rq, pgen_event *ev, void *p)
-{
-  switch (rq) {
-    case PGEN_BEGIN:
-      printf("[%s: ", ev->name);
-      fflush(stdout);
-      break;
-    case PGEN_FAIL:
-      putchar('.');
-      fflush(stdout);
-      break;
-    case PGEN_PASS:
-      putchar('+');
-      fflush(stdout);
-      break;
-    case PGEN_DONE:
-      fputs("+]", stdout);
-      fflush(stdout);
-      break;
-    case PGEN_ABORT:
-      fputs(" failed]", stdout);
-      fflush(stdout);
-      break;
-  }
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/pgen.c b/pgen.c
deleted file mode 100644 (file)
index 1a2a8ac..0000000
--- a/pgen.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Prime generation glue
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "fibrand.h"
-#include "grand.h"
-#include "mp.h"
-#include "mprand.h"
-#include "pgen.h"
-#include "pfilt.h"
-#include "rabin.h"
-
-/*----- Standard prime filter ---------------------------------------------*/
-
-/* --- @pgen_filter@ --- */
-
-int pgen_filter(int rq, pgen_event *ev, void *p)
-{
-  pgen_filterctx *f = p;
-  int rc = PGEN_FAIL;
-
-  switch (rq) {
-    case PGEN_BEGIN:
-      rc = pfilt_create(&f->f, ev->m);
-      mp_drop(ev->m);
-      break;
-    case PGEN_TRY:
-      mp_drop(ev->m);
-      break;
-    case PGEN_DONE:
-      pfilt_destroy(&f->f);
-      return (PGEN_DONE);
-    default:
-      rc = PGEN_ABORT;
-      break;
-  }
-
-  if (rc == PGEN_FAIL && !((f->step | f->f.m->v[0]) & 1))
-    rc = pfilt_step(&f->f, 1);
-  while (rc == PGEN_FAIL)
-    rc = pfilt_step(&f->f, f->step);
-  ev->m = MP_COPY(f->f.m);
-  return (rc);
-}
-
-/* --- @pgen_jump@ --- *
- *
- * Similar to the standard @pgen_filter@, but jumps in large steps rather
- * than small ones.
- */
-
-int pgen_jump(int rq, pgen_event *ev, void *p)
-{
-  pgen_jumpctx *f = p;
-  int rc = PGEN_ABORT;
-
-  switch (rq) {
-    case PGEN_BEGIN: {
-      mp *g = MP_NEW;
-      mp_gcd(&g, 0, 0, ev->m, f->j->m);
-      if (MP_CMP(g, >, MP_ONE)) {
-       mp_drop(g);
-       return (PGEN_ABORT);
-      }
-      mp_drop(g);
-      rc = pfilt_create(&f->f, ev->m);
-      mp_drop(ev->m);
-    } break;
-    case PGEN_TRY:
-      mp_drop(ev->m);
-      rc = pfilt_jump(&f->f, f->j);
-      break;
-    case PGEN_DONE:
-      pfilt_destroy(&f->f);
-      return (PGEN_DONE);
-  }
-
-  while (rc == PGEN_FAIL)
-    rc = pfilt_jump(&f->f, f->j);
-  ev->m = MP_COPY(f->f.m);
-  return (rc);
-}
-
-/*----- Standard prime test -----------------------------------------------*/
-
-/* --- @pgen_test@ --- */
-
-int pgen_test(int rq, pgen_event *ev, void *p)
-{
-  rabin *r = p;
-  int rc = PGEN_ABORT;
-
-  switch (rq) {
-    case PGEN_BEGIN:
-      rabin_create(r, ev->m);
-      rc = PGEN_TRY;
-      break;
-    case PGEN_TRY:
-      if (!ev->tests)
-       rc = rabin_rtest(r, MP_TWO);
-      else {
-       mp *a = mprand_range(MP_NEW, ev->m, ev->r, 0);
-       rc = rabin_rtest(r, a);
-       mp_drop(a);
-      }
-      break;
-    case PGEN_DONE:
-      rabin_destroy(r);
-      rc = PGEN_DONE;
-      break;
-  }
-
-  return (rc);
-}
-
-/*----- The main driver ---------------------------------------------------*/
-
-/* --- @pgen@ --- *
- *
- * Arguments:  @const char *name@ = name of the value being searched for
- *             @mp *d@ = destination for the result integer
- *             @mp *m@ = start value to pass to stepper
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = context argument for event andler
- *             @unsigned steps@ = number of steps to take in search
- *             @pgen_proc *step@ = stepper function to use
- *             @void *sctx@ = context argument for stepper
- *             @unsigned tests@ = number of tests to make
- *             @pgen_proc *test@ = tester function to use
- *             @void *tctx@ = context argument for tester
- *
- * Returns:    Pointer to final result, or null.
- *
- * Use:                A generalized prime-number search skeleton.  Yes, that's a
- *             scary number of arguments.
- */
-
-mp *pgen(const char *name, mp *d, mp *m, pgen_proc *event, void *ectx,
-        unsigned steps, pgen_proc *step, void *sctx,
-        unsigned tests, pgen_proc *test, void *tctx)
-{
-  pgen_event ev;
-  int rq, rc;
-  pgen_proc *proc;
-  void *ctx;
-  int p;
-
-  enum { P_STEP, P_TEST };
-
-  /* --- Set up the initial event block --- */
-
-  ev.name = name;
-  if (m)
-    ev.m = MP_COPY(m);
-  else
-    ev.m = 0;
-  ev.steps = 0;
-  ev.tests = 0;
-  ev.r = fibrand_create(0);
-
-  /* --- Tell the event handler we're under way --- */
-
-  if (event && event(PGEN_BEGIN, &ev, ectx) == PGEN_ABORT) {
-    ev.r->ops->destroy(ev.r);
-    return (0);
-  }
-
-  /* --- Set up for the initial call --- */
-
-  proc = step; ctx = sctx; p = P_STEP; rq = PGEN_BEGIN;
-
-  /* --- Enter the great maelstrom of state transitions --- */
-
-  for (;;) {
-    unsigned act = 0;
-
-#define A_STEP 1u
-#define A_TEST 2u
-#define A_EVENT 4u
-#define A_ENDTEST 8u
-#define A_ENDSTEP 16u
-#define A_DONE 32u
-
-    /* --- Call the procedure and decide what to do next --- */
-
-    rc = proc(rq, &ev, ctx);
-    switch (rc) {
-      case PGEN_TRY:
-       if (p == P_TEST)
-         rq = PGEN_TRY;
-       else {
-         act |= A_EVENT;
-         proc = test; ctx = tctx; p = P_TEST;
-         rq = PGEN_BEGIN;
-       }
-       break;
-      case PGEN_PASS:
-       act |= A_TEST | A_EVENT;
-       if (p == P_TEST)
-         rq = PGEN_TRY;
-       else {
-         proc = test; ctx = tctx; p = P_TEST;
-         rq = PGEN_BEGIN;
-       }
-       break;
-      case PGEN_FAIL:
-       act |= A_STEP;
-       if (p == P_TEST) {
-         act |= A_ENDTEST | A_EVENT;
-         proc = step; ctx = sctx; p = P_STEP;
-       }
-       rq = PGEN_TRY;
-       break;
-      case PGEN_DONE:
-       act |= A_EVENT | A_DONE | A_ENDSTEP;
-       if (p == P_TEST)
-         act |= A_ENDTEST;
-       break;
-      case PGEN_ABORT:
-       act |= A_EVENT | A_DONE;
-       if (p == P_TEST || rq == PGEN_TRY)
-         act |= A_ENDSTEP;
-       if (p == P_TEST && rq != PGEN_BEGIN)
-         act |= A_ENDTEST;
-       break;
-      default:
-       assert(((void)"Invalid response from function", 0));
-       break;
-    }
-
-    /* --- If decrementing counters is requested, do that --- */
-
-    if ((act & A_STEP) && steps) {
-      ev.steps++;
-      if (ev.steps == steps) {
-       act |= A_EVENT | A_ENDSTEP | A_DONE;
-       rc = PGEN_ABORT;
-      }
-      ev.tests = 0;
-    }
-
-    if ((act & A_TEST) && tests) {
-      ev.tests++;
-      if (ev.tests == tests) {
-       act |= A_ENDTEST | A_ENDSTEP | A_DONE;
-       rc = PGEN_DONE;
-      }
-    }
-
-    /* --- Report an event if so directed --- */
-
-    if ((act & A_EVENT) && event && event(rc, &ev, ectx) == PGEN_ABORT) {
-      rc = PGEN_ABORT;
-      if (!(act & A_DONE)) {
-       act |= A_ENDSTEP | A_DONE;
-       if (p == P_TEST)
-         act |= A_ENDTEST;
-      }
-    }
-
-    /* --- Close down tester and stepper functions --- */
-
-    if (act & A_ENDTEST)
-      test(PGEN_DONE, &ev, tctx);
-    if (act & A_ENDSTEP)
-      step(PGEN_DONE, &ev, sctx);
-
-    /* --- Stop the entire test if necessary --- */
-
-    if (act & A_DONE)
-      break;
-  }
-
-  /* --- Tidy up and return --- */
-
-  if (rc == PGEN_ABORT) {
-    mp_drop(ev.m);
-    ev.m = 0;
-  }
-  ev.r->ops->destroy(ev.r);
-  mp_drop(d);
-
-  return (ev.m);
-}
-
-/* --- @pgen_primep@ --- *
- *
- * Arguments:  @mp *p@ = a number to check
- *             @grand *gr@ = a random number source
- *
- * Returns:    Nonzero if @p@ is really prime.
- */
-
-int pgen_primep(mp *p, grand *gr)
-{
-  int i;
-  rabin r;
-  mp *x = MP_NEW;
-
-  if (MP_NEGP(p)) return (0);
-  switch (pfilt_smallfactor(p)) {
-    case PGEN_DONE: return (1);
-    case PGEN_FAIL: return (0);
-  }
-  rabin_create(&r, p);
-  for (i = 32; i; i--) {
-    x = mprand_range(x, p, gr, 0);
-    if (rabin_rtest(&r, x) == PGEN_FAIL)
-      break;
-  }
-  MP_DROP(x);
-  rabin_destroy(&r);
-  return (!i);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/testrig.h>
-
-static int t_primep(dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  int e = *(int *)v[1].buf;
-  int r;
-  grand *rng;
-  int ok = 1;
-
-  rng = fibrand_create(0);
-  r = pgen_primep(m, rng);
-  GR_DESTROY(rng);
-  if (e != r) {
-    fputs("\n*** primep failed", stderr);
-    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
-    fprintf(stderr, "\nexpected %d", e);
-    fprintf(stderr, "\nreported %d", r);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(m);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int verify(dstr *v)
-{
-  mp *m = *(mp **)v[0].buf;
-  mp *q = *(mp **)v[1].buf;
-  mp *p;
-  int ok = 1;
-
-  pgen_filterctx pf;
-  rabin r;
-
-  pf.step = 2;
-  p = pgen("p", MP_NEW, m, pgen_evspin, 0, 0, pgen_filter, &pf,
-          rabin_iters(mp_bits(m)), pgen_test, &r);
-  if (!p || !MP_EQ(p, q)) {
-    fputs("\n*** pgen failed", stderr);
-    fputs("\nm = ", stderr); mp_writefile(m, stderr, 10);
-    fputs("\np = ", stderr); mp_writefile(p, stderr, 10);
-    fputs("\nq = ", stderr); mp_writefile(q, stderr, 10);
-    fputc('\n', stderr);
-    ok = 0;
-  }
-
-  mp_drop(m);
-  mp_drop(q);
-  mp_drop(p);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "pgen", verify, { &type_mp, &type_mp, 0 } },
-  { "primep", t_primep, { &type_mp, &type_int, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  test_run(argc, argv, tests, SRCDIR "/tests/pgen");
-  return (0);
-}
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/pgen.h b/pgen.h
deleted file mode 100644 (file)
index a066e28..0000000
--- a/pgen.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Prime generation glue
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_PGEN_H
-#define CATACOMB_PGEN_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_PFILT_H
-#  include "pfilt.h"
-#endif
-
-#ifndef CATACOMB_RABIN_H
-#  include "rabin.h"
-#endif
-
-/*----- Event handling ----------------------------------------------------*
- *
- * Different programs and architectures will want to show progress of prime
- * searches and similar processes in different ways.  Of course, for simple
- * searches, it's possible to use the @pfilt@ and @rabin@ functions and
- * maintain control over the general control flow throughout the search.
- *
- * For more complex cases, this sort of control is undesirable.  It's
- * possible to specify an event handler which is informed in abstract about
- * the search.  The event handler can also request the search be aborted.
- */
-
-/* --- Event code constants --- *
- *
- * You're allowed to rely on the values of @PGEN_DONE@ and @PGEN_ABORT@.
- */
-
-enum {
-  PGEN_BEGIN = 1,                      /* Search for value begins */
-  PGEN_TRY,                            /* A new candidate has appeared */
-  PGEN_FAIL,                           /* The candidate failed the test */
-  PGEN_PASS,                           /* The candidate passed a test */
-  PGEN_DONE = 0,                       /* A good value has been found */
-  PGEN_ABORT = -1                      /* The search has been aborted */
-};
-
-/* --- Event information --- *
- *
- * Note that the pseudorandom number generator supplied is not
- * cryptographically strong.
- */
-
-typedef struct pgen_event {
-  const char *name;                    /* Which quantity is being found */
-  mp *m;                               /* Current value under test */
-  unsigned steps;                      /* Number of candidates left */
-  unsigned tests;                      /* Tests left before passing */
-  grand *r;                            /* Source of random numbers */
-} pgen_event;
-
-/*----- Prime search parameters -------------------------------------------*
- *
- * The prime search is parameterized in a large number of ways, although this
- * isn't so much of a surprise given the different sorts of properties
- * required from prime numbers in cryptographic applications.
- *
- * There are two main things which need to be configured: stepping, and
- * testing.  (Filtering is done as part of stepping.)
- *
- * The functions here provide a toolkit for constructing stepping and testing
- * routines.  In a lot of cases, the functions can be used directly; in
- * others, simple bits of glue need be written.
- *
- * Two types of functions are defined: steppers and testers, but their
- * interfaces are substantially similar.  Each is given a request code, a
- * context block and an event block.  It is meant to update its context and
- * the event block and return an event code.
- *
- * A call with a request of @PGEN_BEGIN@ asks the stepper or tester to
- * initialize itself using the information in its event block and context.  A
- * return of @PGEN_FAIL@ reports an immediate failure; @PGEN_ABORT@ reports a
- * fatal problem; @PGEN_DONE@ reports immediate success.  @PGEN_TRY@ reports
- * successful initialization and requests test iterations.
- *
- * A call to a stepper with a request of @PGEN_TRY@ asks it to step to the
- * next possible candidate, replacing the value @m@ in the event block with
- * the new candidate.  A call to a tester with a request of @PGEN_TRY@
- * runs one pass of the test.  It should return @PGEN_FAIL@ to report a
- * failure, @PGEN_PASS@ to report a success and request another iteration,
- * @PGEN_DONE@ to report final acceptance and @PGEN_ABORT@ to terminate the
- * search unsuccessfully.  Note that even if the search is aborted, a
- * shutdown request is still made.
- *
- * A call with a request of @PGEN_DONE@ closes down the stepper or tester.
- * After a successful initialization (i.e., a return of something other than
- * @PGEN_ABORT@), a shutdown call is guaranteed.  The return code is ignored.
- */
-
-typedef int pgen_proc(int /*rq*/, pgen_event */*ev*/, void */*p*/);
-
-/*----- Simple handler functions ------------------------------------------*/
-
-/* --- @pgen_filter@ --- *
- *
- * A prime generation context contains the information required for the
- * simple prime filter and tester presented here.
- */
-
-typedef struct pgen_filterctx {
-  unsigned step;                       /* Step size (set by client) */
-  pfilt f;                             /* The rapid prime filter */
-} pgen_filterctx;
-
-extern pgen_proc pgen_filter;
-
-/* --- @pgen_jump@ --- *
- *
- * Similar to the standard @pgen_filter@, but jumps in large steps rather
- * than small ones.
- */
-
-typedef struct pgen_jumpctx {
-  const pfilt *j;
-  pfilt f;
-} pgen_jumpctx;
-
-extern pgen_proc pgen_jump;
-
-/* --- @pgen_test@ --- *
- *
- * Runs the Rabin-Miller primality test.  The context block is simply a
- * @rabin@ context.
- */
-
-extern pgen_proc pgen_test;
-
-/*----- Simultaneous primality checking -----------------------------------*/
-
-typedef struct pgen_simulprime {
-  mp *mul, *add;                       /* Arguments from the client */
-  unsigned f;                          /* Flags, set by client, changed */
-#define PGENF_KEEP 1u                  /*   Keep this prime's value */
-#define PGENF_JUMP 8u                  /*   Use jump table, not stepping */
-  pfilt p;                             /* This prime's filter */
-  rabin r;                             /* Rabin testing context */
-  union {
-    mpw step;                          /* The simple step to use */
-    pfilt *jump;                       /* The jump to move by */
-    mp *x;                             /* The result, if wanted */
-  } u;
-} pgen_simulprime;
-
-typedef struct pgen_simulctx {
-  pgen_simulprime *v;                  /* Vector of related primes */
-  unsigned n;                          /* Size of the vector */
-  mp *step;                            /* Basic stepping value */
-} pgen_simulctx;
-
-/* --- @pgen_simulstep@ --- *
- *
- * Step a collection of numbers simultaneously.
- */
-
-extern pgen_proc pgen_simulstep;
-
-/* --- @pgen_simultest@ --- *
- *
- * Test a collection of numbers simultaneously.
- */
-
-extern pgen_proc pgen_simultest;
-
-/*----- Miscellaneous steppers and testers --------------------------------*/
-
-typedef struct pgen_gcdstepctx {
-  pfilt p, jp;                         /* Prime filter and step filter */
-  mp *q, *jq;                          /* %$p - 1$%, and a step value*/
-  mp *r;                               /* Other argument for GCD */
-  mp *g;                               /* GCD output (must be inited) */
-  mp *max;                             /* Maximum permissible GCD */
-} pgen_gcdstepctx;
-
-/* --- @pgen_gcdstep@ --- *
- *
- * Steps @p@ and @q@, until @p@ has no small factors, and
- * %$\gcd(p, r) \le max$%.
- */
-
-extern pgen_proc pgen_gcdstep;
-
-/*----- Standard event handlers -------------------------------------------*/
-
-/* --- @pgen_evspin@ --- *
- *
- * Displays a spinning baton to show progress.
- */
-
-extern pgen_proc pgen_evspin;
-
-/* --- @pgen_ev@ --- *
- *
- * Traditional event handler, shows dots for each test.
- */
-
-extern pgen_proc pgen_ev;
-
-/* --- @pgen_subev@ --- *
- *
- * Subsidiary event handler, mainly for Lim-Lee searches and so on.
- */
-
-extern pgen_proc pgen_subev;
-
-/*----- The main driver ---------------------------------------------------*/
-
-/* --- @pgen@ --- *
- *
- * Arguments:  @const char *name@ = name of the value being searched for
- *             @mp *d@ = destination for resulting integer
- *             @mp *m@ = start value to pass to stepper
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = context argument for event andler
- *             @unsigned steps@ = number of steps to take in search
- *             @pgen_proc *step@ = stepper function to use
- *             @void *sctx@ = context argument for stepper
- *             @unsigned tests@ = number of tests to make
- *             @pgen_proc *test@ = tester function to use
- *             @void *tctx@ = context argument for tester
- *
- * Returns:    The resulting value, or null.
- *
- * Use:                A generalized prime-number search skeleton.  Yes, that's a
- *             scary number of arguments.
- */
-
-extern mp *pgen(const char */*name*/, mp */*d*/, mp */*m*/,
-               pgen_proc */*event*/, void */*ectx*/,
-               unsigned /*steps*/, pgen_proc */*step*/, void */*sctx*/,
-               unsigned /*tests*/, pgen_proc */*test*/, void */*tctx*/);
-
-/* --- @pgen_primep@ --- *
- *
- * Arguments:  @mp *p@ = a number to check
- *             @grand *gr@ = a random number source
- *
- * Returns:    Nonzero if @p@ is really prime.
- */
-
-extern int pgen_primep(mp */*p*/, grand */*gr*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/pixie-common.c b/pixie-common.c
deleted file mode 100644 (file)
index fbb7f11..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Common code for Pixie client and server (Unix-specific)
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <pwd.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/str.h>
-
-#include "pixie.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @pixie_address@ --- *
- *
- * Arguments:  @const char *sock@ = pointer to socket name
- *             @size_t *psz@ = where to write the address size
- *
- * Returns:    Pointer to filled-in Unix-domain socket address.
- *
- * Use:                Returns a Unix-domain socket address to use to find the
- *             passphrase pixie.
- */
-
-struct sockaddr_un *pixie_address(const char *sock, size_t *psz)
-{
-  dstr d = DSTR_INIT;
-
-  /* --- Get the default socket path if none specified --- */
-
-  if (!sock)
-    sock = getenv("CATACOMB_PIXIE_SOCKET");
-  if (!sock)
-    sock = "%h/.catacomb/pixie";
-
-  /* --- Substitute interesting sequences in the path --- */
-
-  {
-    const char *q, *qq;
-
-    q = sock;
-    for (;;) {
-      qq = strchr(q, '%');
-      if (!qq || !qq[1]) {
-       DPUTS(&d, q);
-       break;
-      }
-      DPUTM(&d, q, qq - q);
-      q = qq + 1;
-      switch (*q) {
-       case 'u':
-         qq = getenv("USER");
-         if (!qq)
-           qq = getenv("LOGNAME");
-         if (!qq) {
-           struct passwd *pw = getpwuid(getuid());
-           if (pw)
-             qq = pw->pw_name;
-           else
-             qq = "<unknown>";
-         }
-         DPUTS(&d, qq);
-         break;
-       case 'h':
-         qq = getenv("HOME");
-         if (!qq) {
-           struct passwd *pw = getpwuid(getuid());
-           if (pw)
-             qq = pw->pw_dir;
-           else
-             qq = "<unknown>";
-         }
-         DPUTS(&d, qq);
-         break;
-       default:
-         DPUTC(&d, '%');
-         DPUTC(&d, *q);
-         break;
-      }
-      q++;
-    }
-    DPUTZ(&d);
-  }
-
-  /* --- Allocate and initialize the socket address --- */
-
-  {
-    struct sockaddr_un *sun;
-    size_t bsz = offsetof(struct sockaddr_un, sun_path);
-    *psz = bsz + d.len + 1;
-    sun = xmalloc(bsz + d.len + 1);
-    memset(sun, 0, bsz);
-    sun->sun_family = AF_UNIX;
-    memcpy(sun->sun_path, d.buf, d.len + 1);
-    dstr_destroy(&d);
-    return (sun);
-  }
-}
-
-/* --- @pixie_fdline@ --- *
- *
- * Arguments:  @int fd@ = file descriptor to read from
- *             @char *buf@ = pointer to buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    ---
- *
- * Use:                Reads a line from a file descriptor.  The read is done one
- *             character at a time.  If the entire line won't fit, the end
- *             is truncated.  The line is null terminated.
- */
-
-void pixie_fdline(int fd, char *buf, size_t sz)
-{
-  char *p = buf;
-  char *q = p + sz - 1;
-
-  for (;;) {
-    char c;
-    if (read(fd, &c, 1) < 1)
-      break;
-    if (c == '\n')
-      break;
-    if (p < q)
-      *p++ = c;
-  }
-  *p = 0;
-}
-
-/* --- @pixie_getpass@ --- *
- *
- * Arguments:  @const char *prompt@ = pointer to prompt string
- *             @char *buf@ = pointer to buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    Zero if it worked OK, nonzero otherwise.
- *
- * Use:                Reads a passphrase from the terminal or some other requested
- *             source.
- */
-
-int pixie_getpass(const char *prompt, char *buf, size_t sz)
-{
-  const char *pfd = getenv("CATACOMB_PASSPHRASE_FD");
-  int fd = 0;
-
-  /* --- See whether a terminal is what's wanted --- */
-
-  if (pfd) {
-    fd = atoi(pfd);
-    pixie_fdline(fd, buf, sz);
-  } else {
-    struct termios ta;
-    struct termios ota;
-    char nl = '\n';
-
-    if ((fd = open("/dev/tty", O_RDWR)) < 0)
-      goto fail_0;
-    if (tcgetattr(fd, &ta) < 0)
-      goto fail_1;
-    ota = ta;
-    ta.c_lflag &= ~(ECHO | ISIG);
-    if (tcsetattr(fd, TCSAFLUSH, &ta))
-      goto fail_1;
-    write(fd, prompt, strlen(prompt));
-    pixie_fdline(fd, buf, sz);
-    tcsetattr(fd, TCSAFLUSH, &ota);
-    write(fd, &nl, 1);
-    close(fd);
-  }
-  return (0);
-
-  /* --- Tidy up if things went wrong --- */
-
-fail_1:
-  close(fd);
-fail_0:
-  return (-1);
-}
-
-/* --- @pixie_open@ --- *
- *
- * Arguments:  @const char *sock@ = path to pixie socket
- *
- * Returns:    Less than zero if it failed, or file descriptor.
- *
- * Use:                Opens a connection to a passphrase pixie.
- */
-
-int pixie_open(const char *sock)
-{
-  struct sockaddr_un *sun;
-  size_t sz;
-  int fd;
-
-  /* --- Open the connection --- */
-
-  if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
-    goto fail_0;
-  sun = pixie_address(sock, &sz);
-  if (connect(fd, (struct sockaddr *)sun, sz))
-    goto fail_1;
-  xfree(sun);
-  return (fd);
-
-  /* --- Tidy up if things went wrong --- */
-
-fail_1:
-  xfree(sun);
-  close(fd);
-fail_0:
-  return (-1);
-}
-
-/* --- @pixie_read@ --- *
- *
- * Arguments:  @int fd@ = connection to passphrase pixie
- *             @const char *tag@ = pointer to tag string
- *             @unsigned mode@ = reading mode
- *             @char *buf@ = pointer to destination buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    Zero if all went well, @-1@ if the read fails, @+1@ to
- *             request the passphrase from the user.
- *
- * Use:                Reads a passphrase from the pixie.
- */
-
-int pixie_read(int fd, const char *tag, unsigned mode, char *buf, size_t sz)
-{
-  dstr d = DSTR_INIT;
-  char *p, *q;
-
-  /* --- Send the request --- */
-
-  dstr_putf(&d, "%s %s\n", mode == PMODE_READ ? "PASS" : "VERIFY", tag);
-  write(fd, d.buf, d.len);
-  dstr_destroy(&d);
-
-  /* --- Sort out the result --- */
-
-again:
-  pixie_fdline(fd, buf, sz);
-  p = buf;
-  if ((q = str_getword(&p)) == 0)
-    return (-1);
-  if (strcmp(q, "INFO") == 0)
-    goto again;
-  else if (strcmp(q, "MISSING") == 0)
-    return (+1);
-  else if (strcmp(q, "OK") != 0)
-    return (-1);
-
-  /* --- Return the final answer --- */
-
-  if (p)
-    memmove(buf, p, strlen(p) + 1);
-  else
-    *buf = 0;
-  return (0);
-}
-
-/* --- @pixie_set@ --- *
- *
- * Arguments:  @int fd@ = pixie file descriptor
- *             @const char *tag@ = pointer to tag string
- *             @const char *phrase@ = pointer to passphrase string
- *
- * Returns:    ---
- *
- * Use:                Sends a passphrase to the passphrase pixie.
- */
-
-void pixie_set(int fd, const char *tag, const char *phrase)
-{
-  dstr d = DSTR_INIT;
-  char buf[16];
-  size_t sz = strlen(phrase);
-  char nl = '\n';
-  char *p, *q;
-
-  /* --- Send the request --- *
-   *
-   * I didn't want to copy it out of the caller's buffer.  @writev@ may
-   * produce a copy, too, so I didn't do that either.
-   */
-
-  dstr_putf(&d, "SET %s -- ", tag);
-  write(fd, d.buf, d.len);
-  write(fd, phrase, sz);
-  write(fd, &nl, 1);
-  dstr_destroy(&d);
-
-  /* --- Pick up the pieces --- */
-
-again:
-  pixie_fdline(fd, buf, sizeof(buf));
-  p = buf;
-  if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0)
-    goto again;
-}
-
-/* --- @pixie_cancel@ --- *
- *
- * Arguments:  @int fd@ = pixie file descriptor
- *             @const char *tag@ = pointer to tag string
- *
- * Returns:    ---
- *
- * Use:                Cancels a passphrase if it turns out to be bogus.
- */
-
-void pixie_cancel(int fd, const char *tag)
-{
-  dstr d = DSTR_INIT;
-  char buf[16];
-  char *p, *q;
-
-  /* --- Send the request --- */
-
-  dstr_putf(&d, "FLUSH %s\n", tag);
-  write(fd, d.buf, d.len);
-  dstr_destroy(&d);
-
-  /* --- Sort out the result --- */
-
-again:
-  pixie_fdline(fd, buf, sizeof(buf));
-  p = buf;
-  if ((q = str_getword(&p)) != 0 && strcmp(q, "INFO") == 0)
-    goto again;
-}
-
-/*----- That's all, folks -------------------------------------------------*/
-
diff --git a/pixie.c b/pixie.c
deleted file mode 100644 (file)
index af6483a..0000000
--- a/pixie.c
+++ /dev/null
@@ -1,1462 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Passphrase pixie for Catacomb
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "config.h"
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <pwd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <syslog.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/fdflags.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sel.h>
-#include <mLib/selbuf.h>
-#include <mLib/sig.h>
-#include <mLib/str.h>
-#include <mLib/sub.h>
-#include <mLib/tv.h>
-
-#include "arena.h"
-#include "lmem.h"
-#include "passphrase.h"
-#include "pixie.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static unsigned long timeout = 900;
-static sel_state sel;
-static unsigned verbose = 1;
-static const char *command = 0;
-static lmem lm;
-static unsigned flags = 0;
-
-#define F_SYSLOG 1u
-#define F_FETCH 2u
-
-/*----- Event logging -----------------------------------------------------*/
-
-/* --- @log@ --- *
- *
- * Arguments:  @const char *p@ = @printf@-style format string
- *             @...@ = extra arguments to fill in
- *
- * Returns:    ---
- *
- * Use:                Writes out a timestamped log message.
- */
-
-static void log(const char *p, ...)
-{
-  dstr d = DSTR_INIT;
-  va_list ap;
-
-  if (!(flags & F_SYSLOG)) {
-    time_t t = time(0);
-    struct tm *tm = localtime(&t);
-    DENSURE(&d, 64);
-    d.len += strftime(d.buf, d.sz, "%Y-%m-%d %H:%M:%S ", tm);
-  }
-  va_start(ap, p);
-  dstr_vputf(&d, p, &ap);
-  va_end(ap);
-
-  if (flags & F_SYSLOG)
-    syslog(LOG_NOTICE, "%s", d.buf);
-  else {
-    DPUTC(&d, '\n');
-    dstr_write(&d, stderr);
-  }
-  DDESTROY(&d);
-}
-
-/*----- Passphrase management ---------------------------------------------*/
-
-/* --- Data structures --- */
-
-typedef struct phrase {
-  struct phrase *next;
-  struct phrase *prev;
-  char *tag;
-  char *p;
-  unsigned long t;
-  sel_timer timer;
-  unsigned f;
-} phrase;
-
-/* --- Variables --- */
-
-#define P_ROOT ((phrase *)&p_root)
-static struct { phrase *next; phrase *prev; } p_root = { P_ROOT, P_ROOT };
-
-/* --- @p_free@ --- *
- *
- * Arguments:  @phrase *p@ = pointer to phrase block
- *
- * Returns:    ---
- *
- * Use:                Frees a phrase block.
- */
-
-static void p_free(phrase *p)
-{
-  if (p->t)
-    sel_rmtimer(&p->timer);
-  xfree(p->tag);
-  l_free(&lm, p->p);
-  p->next->prev = p->prev;
-  p->prev->next = p->next;
-  DESTROY(p);
-}
-
-/* --- @p_timer@ --- *
- *
- * Arguments:  @struct timeval *tv@ = current time
- *             @void *p@ = pointer to phrase
- *
- * Returns:    ---
- *
- * Use:                Expires a passphrase.
- */
-
-static void p_timer(struct timeval *tv, void *p)
-{
-  phrase *pp = p;
-  if (verbose)
-    log("expiring passphrase `%s'", pp->tag);
-  p_free(pp);
-}
-
-/* --- @p_alloc@ --- *
- *
- * Arguments:  @size_t sz@ = amount of memory required
- *
- * Returns:    Pointer to allocated memory, or null.
- *
- * Use:                Allocates some locked memory, flushing old passphrases if
- *             there's not enough space.
- */
-
-static void *p_alloc(size_t sz)
-{
-  for (;;) {
-    char *p;
-    if ((p = l_alloc(&lm, sz)) != 0)
-      return (p);
-    if (P_ROOT->next == P_ROOT)
-      return (0);
-    if (verbose) {
-      log("flushing passphrase `%s' to free up needed space",
-         P_ROOT->next->tag);
-    }
-    p_free(P_ROOT->next);
-  }
-}
-
-/* --- @p_find@ --- *
- *
- * Arguments:  @const char *tag@ = pointer to tag to find
- *
- * Returns:    Pointer to passphrase block, or null.
- *
- * Use:                Finds a passphrase with a given tag.
- */
-
-static phrase *p_find(const char *tag)
-{
-  phrase *p;
-
-  for (p = P_ROOT->next; p != P_ROOT; p = p->next) {
-    if (strcmp(p->tag, tag) == 0) {
-      if (p->t) {
-       struct timeval tv;
-       sel_rmtimer(&p->timer);
-       gettimeofday(&tv, 0);
-       tv.tv_sec += p->t;
-       sel_addtimer(&sel, &p->timer, &tv, p_timer, p);
-      }
-      p->next->prev = p->prev;
-      p->prev->next = p->next;
-      p->next = P_ROOT;
-      p->prev = P_ROOT->prev;
-      P_ROOT->prev->next = p;
-      P_ROOT->prev = p;
-      return (p);
-    }
-  }
-  return (0);
-}
-
-/* --- @p_add@ --- *
- *
- * Arguments:  @const char *tag@ = pointer to tag string
- *             @const char *p@ = pointer to passphrase
- *             @unsigned long t@ = expiry timeout
- *
- * Returns:    Pointer to newly-added passphrase.
- *
- * Use:                Adds a new passphrase.  The tag must not already exist.
- */
-
-static phrase *p_add(const char *tag, const char *p, unsigned long t)
-{
-  size_t sz = strlen(p) + 1;
-  char *l = p_alloc(sz);
-  phrase *pp;
-
-  /* --- Make sure the locked memory was allocated --- */
-
-  if (!l)
-    return (0);
-
-  /* --- Fill in some other bits of the block --- */
-
-  pp = CREATE(phrase);
-  memcpy(l, p, sz);
-  pp->p = l;
-  pp->tag = xstrdup(tag);
-  pp->f = 0;
-
-  /* --- Set the timer --- */
-
-  pp->t = t;
-  if (t) {
-    struct timeval tv;
-    gettimeofday(&tv, 0);
-    tv.tv_sec += t;
-    sel_addtimer(&sel, &pp->timer, &tv, p_timer, pp);
-  }
-
-  /* --- Link the block into the chain --- */
-
-  pp->next = P_ROOT;
-  pp->prev = P_ROOT->prev;
-  P_ROOT->prev->next = pp;
-  P_ROOT->prev = pp;
-  return (pp);
-}
-
-/* --- @p_flush@ --- *
- *
- * Arguments:  @const char *tag@ = pointer to tag string, or zero for all
- *
- * Returns:    ---
- *
- * Use:                Immediately flushes either a single phrase or all of them.
- */
-
-static void p_flush(const char *tag)
-{
-  phrase *p;
-
-  if (!tag && verbose > 1)
-    log("flushing all passphrases");
-  p = P_ROOT->next;
-  while (p != P_ROOT) {
-    phrase *pp = p->next;
-    if (!tag)
-      p_free(p);
-    else if (strcmp(p->tag, tag) == 0) {
-      if (verbose > 1)
-       log("flushing passphrase `%s'", tag);
-      p_free(p);
-      break;
-    }
-    p = pp;
-  }
-}
-
-/*----- Reading passphrases -----------------------------------------------*/
-
-/* --- @p_request@ --- *
- *
- * Arguments:  @const char *msg@ = message string
- *             @const char *tag@ = pointer to tag string
- *             @char *buf@ = pointer to (locked) buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    Zero if all went well, nonzero otherwise.
- *
- * Use:                Requests a passphrase from the user.
- */
-
-static int p_request(const char *msg, const char *tag, char *buf, size_t sz)
-{
-  /* --- If there's a passphrase-fetching command, run it --- */
-
-  if (command) {
-    dstr d = DSTR_INIT;
-    const char *p;
-    int fd[2];
-    pid_t kid;
-    int r;
-    int rc;
-
-    /* --- Substitute the prompt string into the command --- */
-
-    p = command;
-    for (;;) {
-      const char *q = strchr(p, '%');
-      if (!q || !q[1]) {
-       DPUTS(&d, p);
-       break;
-      }
-      DPUTM(&d, p, q - p);
-      p = q + 1;
-      switch (*p) {
-       case 'm':
-         DPUTS(&d, msg);
-         break;
-       case 't':
-         DPUTS(&d, tag);
-         break;
-       default:
-         DPUTC(&d, '%');
-         DPUTC(&d, *p);
-         break;
-      }
-      p++;
-    }
-    DPUTZ(&d);
-
-    /* --- Create a pipe and start a child process --- */
-
-    if (pipe(fd))
-      goto fail_1;
-    if ((kid = fork()) < 0)
-      goto fail_2;
-
-    /* --- Child process --- */
-
-    fflush(0);
-    if (kid == 0) {
-      if (dup2(fd[1], STDOUT_FILENO) < 0)
-       _exit(127);
-      close(fd[0]);
-      execl("/bin/sh", "sh", "-c", d.buf, (char *)0);
-      _exit(127);
-    }
-
-    /* --- Read the data back into my buffer --- */
-
-    close(fd[1]);
-    if ((r = read(fd[0], buf, sz - 1)) >= 0) {
-      char *q = memchr(buf, '\n', r);
-      if (!q)
-       q = buf + r;
-      *q = 0;
-    }
-    close(fd[0]);
-    waitpid(kid, &rc, 0);
-    dstr_destroy(&d);
-    if (r < 0 || rc != 0)
-      goto fail_0;
-    goto ok;
-
-    /* --- Tidy up when things go wrong --- */
-
-  fail_2:
-    close(fd[0]);
-    close(fd[1]);
-  fail_1:
-    dstr_destroy(&d);
-  fail_0:
-    return (-1);
-  }
-
-  /* --- Read a passphrase from the terminal --- *
-   *
-   * Use the standard Catacomb passphrase-reading function, so it'll read the
-   * passphrase from a file descriptor or something if the appropriate
-   * environment variable is set.
-   */
-
-  {
-    dstr d = DSTR_INIT;
-    int rc;
-    dstr_putf(&d, "%s %s: ", msg, tag);
-    rc = pixie_getpass(d.buf, buf, sz);
-    dstr_destroy(&d);
-    if (rc)
-      return (rc);
-    goto ok;
-  }
-
-  /* --- Sort out the buffer --- *
-   *
-   * Strip leading spaces.
-   */
-
-ok: {
-    char *p = buf;
-    size_t len;
-    while (isspace((unsigned char)*p))
-      p++;
-    len = strlen(p);
-    memmove(buf, p, len);
-    p[len] = 0;
-  }
-
-  /* --- Done --- */
-
-  return (0);
-}
-
-/* --- @p_get@ --- *
- *
- * Arguments:  @const char **q@ = where to store the result
- *             @const char *tag@ = pointer to tag string
- *             @unsigned mode@ = reading mode (verify?)
- *             @time_t exp@ = expiry time suggestion
- *
- * Returns:    Zero if successful, @-1@ on a read failure, or @+1@ if the
- *             passphrase is missing and there is no fetcher.  (This will
- *             always happen if there is no fetcher and @mode@ is
- *             @PMODE_VERIFY@.
- *
- * Use:                Reads a passphrase from somewhere.
- */
-
-static int p_get(const char **q, const char *tag, unsigned mode, time_t exp)
-{
-#define LBUFSZ 1024
-
-  phrase *p;
-  char *pp = 0;
-
-  /* --- Write a log message --- */
-
-  if (verbose > 1)
-    log("passphrase `%s' requested", tag);
-
-  /* --- If there is no fetcher, life is simpler --- */
-
-  if (!(flags & F_FETCH)) {
-    if (mode == PMODE_VERIFY)
-      return (+1);
-    if ((p = p_find(tag)) == 0)
-      return (+1);
-    *q = p->p;
-    return (0);
-  }
-
-  /* --- Try to find the phrase --- */
-
-  if (mode == PMODE_VERIFY)
-    p_flush(tag);
-  if (mode == PMODE_VERIFY || (p = p_find(tag)) == 0) {
-    if ((pp = p_alloc(LBUFSZ)) == 0)
-      goto fail;
-    if (p_request(mode == PMODE_READ ? "Passphrase" : "New passphrase",
-                 tag, pp, LBUFSZ) < 0)
-      goto fail;
-    p = p_add(tag, pp, exp);
-    if (!p)
-      goto fail;
-  }
-
-  /* --- If verification is requested, verify the passphrase --- */
-
-  if (mode == PMODE_VERIFY) {
-    if (!pp && (pp = p_alloc(LBUFSZ)) == 0)
-      goto fail;
-    if (p_request("Verify passphrase", tag, pp, LBUFSZ) < 0)
-      goto fail;
-    if (strcmp(pp, p->p) != 0) {
-      if (verbose)
-       log("passphrases for `%s' don't match", tag);
-      p_free(p);
-      goto fail;
-    }
-  }
-
-  /* --- Tidy up and return the passphrase --- */
-
-  if (pp) {
-    memset(pp, 0, LBUFSZ);
-    l_free(&lm, pp);
-  }
-  *q = p->p;
-  return (0);
-
-  /* --- Tidy up if things went wrong --- */
-
-fail:
-  if (pp) {
-    memset(pp, 0, LBUFSZ);
-    l_free(&lm, pp);
-  }
-  return (-1);
-
-#undef LBUFSZ
-}
-
-/*----- Server command parsing --------------------------------------------*/
-
-/* --- Data structures --- */
-
-typedef struct pixserv {
-  selbuf b;
-  int fd;
-  sel_timer timer;
-  unsigned f;
-} pixserv;
-
-#define px_stdin 1u
-
-#define PIXSERV_TIMEOUT 30
-
-/* --- @pixserv_expire@ --- *
- *
- * Arguments:  @struct timeval *tv@ = pointer to current time
- *             @void *p@ = pointer to server block
- *
- * Returns:    ---
- *
- * Use:                Expires a pixie connection if the remote end decides he's not
- *             interested any more.
- */
-
-static void pixserv_expire(struct timeval *tv, void *p)
-{
-  pixserv *px = p;
-  if (px->fd != px->b.reader.fd)
-    close(px->fd);
-  selbuf_destroy(&px->b);
-  close(px->b.reader.fd);
-  DESTROY(px);
-}
-
-/* --- @pixserv_write@ --- *
- *
- * Arguments:  @pixserv *px@ = pointer to server block
- *             @const char *p@ = pointer to skeleton string
- *             @...@ = other arguments to fill in
- *
- * Returns:    ---
- *
- * Use:                Formats a string and emits it to the output file.
- */
-
-static void pixserv_write(pixserv *px, const char *p, ...)
-{
-  dstr d = DSTR_INIT;
-  va_list ap;
-
-  va_start(ap, p);
-  dstr_vputf(&d, p, &ap);
-  write(px->fd, d.buf, d.len);
-  va_end(ap);
-  dstr_destroy(&d);
-}
-
-/* --- @pixserv_timeout@ --- *
- *
- * Arguments:  @const char *p@ = pointer to timeout string
- *
- * Returns:    Timeout in seconds.
- *
- * Use:                Translates a string to a timeout value in seconds.
- */
-
-static unsigned long pixserv_timeout(const char *p)
-{
-  unsigned long t;
-  char *q;
-
-  if (!p)
-    return (timeout);
-
-  t = strtoul(p, &q, 0);
-  switch (*q) {
-    case 'd': t *= 24;
-    case 'h': t *= 60;
-    case 'm': t *= 60;
-    case 's': if (q[1] != 0)
-      default:   t = 0;
-    case 0:   break;
-  }
-  return (t);
-}
-
-/* --- @pixserv_line@ --- *
- *
- * Arguments:  @char *s@ = pointer to the line read
- *             @size_t len@ = length of the line
- *             @void *p@ = pointer to server block
- *
- * Returns:    ---
- *
- * Use:                Handles a line read from the client.
- */
-
-static void pixserv_line(char *s, size_t len, void *p)
-{
-  pixserv *px = p;
-  char *q, *qq;
-  unsigned mode;
-
-  /* --- Handle an end-of-file --- */
-
-  if (!(px->f & px_stdin))
-    sel_rmtimer(&px->timer);
-  if (!s) {
-    if (px->fd != px->b.reader.fd)
-      close(px->fd);
-    selbuf_destroy(&px->b);
-    close(px->b.reader.fd);
-    return;
-  }
-
-  /* --- Fiddle the timeout --- */
-
-  if (!(px->f & px_stdin)) {
-    struct timeval tv;
-    gettimeofday(&tv, 0);
-    tv.tv_sec += PIXSERV_TIMEOUT;
-    sel_addtimer(&sel, &px->timer, &tv, pixserv_expire, px);
-  }
-
-  /* --- Scan out the first word --- */
-
-  if ((q = str_getword(&s)) == 0)
-    return;
-  for (qq = q; *qq; qq++)
-    *qq = tolower((unsigned char)*qq);
-
-  /* --- Handle a help request --- */
-
-  if (strcmp(q, "help") == 0) {
-    pixserv_write(px, "\
-INFO Commands supported:\n\
-INFO HELP\n\
-INFO LIST\n\
-INFO PASS tag [expire]\n\
-INFO VERIFY tag [expire]\n\
-INFO FLUSH [tag]\n\
-INFO SET tag [expire] -- phrase\n\
-INFO QUIT\n\
-OK\n\
-");
-  }
-
-  /* --- List the passphrases --- */
-
-  else if (strcmp(q, "list") == 0) {
-    phrase *p;
-
-    for (p = P_ROOT->next; p != P_ROOT; p = p->next) {
-      if (!p->t)
-       pixserv_write(px, "ITEM %s no-expire\n", p->tag);
-      else {
-       struct timeval tv;
-       gettimeofday(&tv, 0);
-       TV_SUB(&tv, &p->timer.tv, &tv);
-       pixserv_write(px, "ITEM %s %i\n", p->tag, tv.tv_sec);
-      }
-    }
-    pixserv_write(px, "OK\n");
-  }
-
-  /* --- Request a passphrase --- */
-
-  else if ((mode = PMODE_READ, strcmp(q, "pass") == 0) ||
-          (mode = PMODE_VERIFY, strcmp(q, "verify") == 0)) {
-    unsigned long t;
-    const char *p;
-    int rc;
-
-    if ((q = str_getword(&s)) == 0)
-      pixserv_write(px, "FAIL missing tag\n");
-    else if ((t = pixserv_timeout(s)) == 0)
-      pixserv_write(px, "FAIL bad timeout\n");
-    else {
-      rc = p_get(&p, q, mode, t > timeout ? timeout : t);
-      switch (rc) {
-       case 0:
-         pixserv_write(px, "OK %s\n", p);
-         break;
-       case -1:
-         pixserv_write(px, "FAIL error reading passphrase\n");
-         break;
-       case +1:
-         pixserv_write(px, "MISSING\n");
-         break;
-      }
-    }
-  }
-
-  /* --- Flush existing passphrases --- */
-
-  else if (strcmp(q, "flush") == 0) {
-    q = str_getword(&s);
-    p_flush(q);
-    pixserv_write(px, "OK\n");
-  }
-
-  /* --- Set a passphrase --- */
-
-  else if (strcmp(q, "set") == 0) {
-    char *tag;
-    unsigned long t;
-    if ((tag = str_getword(&s)) == 0)
-      pixserv_write(px, "FAIL missing tag\n");
-    else if ((q = str_getword(&s)) == 0)
-      pixserv_write(px, "FAIL no passphrase\n");
-    else {
-      if (strcmp(q, "--") != 0) {
-       t = pixserv_timeout(q);
-       q = str_getword(&s);
-      } else
-       t = pixserv_timeout(0);
-      if (!q)
-       pixserv_write(px, "FAIL no passphrase\n");
-      else if (strcmp(q, "--") != 0)
-       pixserv_write(px, "FAIL rubbish found before passphrase\n");
-      else {
-       p_flush(tag);
-       p_add(tag, s, t);
-       pixserv_write(px, "OK\n");
-      }
-    }
-  }
-
-  /* --- Shut the server down --- */
-
-  else if (strcmp(q, "quit") == 0) {
-    if (verbose)
-      log("%s client requested shutdown",
-         px->f & px_stdin ? "local" : "remote");
-    pixserv_write(px, "OK\n");
-    exit(0);
-  }
-
-  /* --- Report an error for other commands --- */
-
-  else
-    pixserv_write(px, "FAIL unknown command `%s'\n", q);
-}
-
-/* --- @pixserv_create@ --- *
- *
- * Arguments:  @int fd@ = file descriptor to read from
- *             @int ofd@ = file descriptor to write to
- *
- * Returns:    Pointer to the new connection.
- *
- * Use:                Creates a new Pixie server instance for a new connection.
- */
-
-static pixserv *pixserv_create(int fd, int ofd)
-{
-  pixserv *px = CREATE(pixserv);
-  struct timeval tv;
-  fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
-  if (ofd != fd)
-    fdflags(ofd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
-  px->fd = ofd;
-  selbuf_init(&px->b, &sel, fd, pixserv_line, px);
-  px->b.b.a = arena_secure;
-  selbuf_setsize(&px->b, 1024);
-  gettimeofday(&tv, 0);
-  tv.tv_sec += PIXSERV_TIMEOUT;
-  sel_addtimer(&sel, &px->timer, &tv, pixserv_expire, px);
-  px->f = 0;
-  return (px);
-}
-
-/* --- @pixserv_accept@ --- *
- *
- * Arguments:  @int fd@ = file descriptor
- *             @unsigned mode@ = what's happened
- *             @void *p@ = an uninteresting argument
- *
- * Returns:    ---
- *
- * Use:                Accepts a new connection.
- */
-
-static void pixserv_accept(int fd, unsigned mode, void *p)
-{
-  int nfd;
-  struct sockaddr_un sun;
-  size_t sunsz = sizeof(sun);
-
-  if (mode != SEL_READ)
-    return;
-  if ((nfd = accept(fd, (struct sockaddr *)&sun, &sunsz)) < 0) {
-    if (verbose && errno != EAGAIN && errno != EWOULDBLOCK &&
-       errno != ECONNABORTED && errno != EPROTO && errno != EINTR)
-      log("new connection failed: %s", strerror(errno));
-    return;
-  }
-  pixserv_create(nfd, nfd);
-}
-
-/*----- Setting up the server ---------------------------------------------*/
-
-/* --- @unlinksocket@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    ---
- *
- * Use:                Tidies up the socket when it's finished with.
- */
-
-static char *sockpath;
-
-static void unlinksocket(void)
-{
-  unlink(sockpath);
-  l_purge(&lm);
-}
-
-/* --- @pix_sigdie@ --- *
- *
- * Arguments:  @int sig@ = signal number
- *             @void *p@ = uninteresting argument
- *
- * Returns:    ---
- *
- * Use:                Shuts down the program after a fatal signal.
- */
-
-static void pix_sigdie(int sig, void *p)
-{
-  if (verbose) {
-    char *p;
-    char buf[20];
-
-    switch (sig) {
-      case SIGTERM:    p = "SIGTERM"; break;
-      case SIGINT:     p = "SIGINT"; break;
-      default:
-       sprintf(buf, "signal %i", sig);
-       p = buf;
-       break;
-    }
-    log("shutting down on %s", p);
-  }
-  exit(0);
-}
-
-/* --- @pix_sigflush@ --- *
- *
- * Arguments:  @int sig@ = signal number
- *             @void *p@ = uninteresting argument
- *
- * Returns:    ---
- *
- * Use:                Flushes the passphrase cache on receipt of a signal.
- */
-
-static void pix_sigflush(int sig, void *p)
-{
-  if (verbose) {
-    char *p;
-    char buf[20];
-
-    switch (sig) {
-      case SIGHUP:     p = "SIGHUP"; break;
-      case SIGQUIT:    p = "SIGQUIT"; break;
-      default:
-       sprintf(buf, "signal %i", sig);
-       p = buf;
-       break;
-    }
-    log("received %s; flushing passphrases", p);
-  }
-  p_flush(0);
-}
-
-/* --- @pix_setup@ --- *
- *
- * Arguments:  @struct sockaddr_un *sun@ = pointer to address to use
- *             @size_t sz@ = size of socket address
- *
- * Returns:    ---
- *
- * Use:                Sets up the pixie's Unix-domain socket.
- */
-
-static void pix_setup(struct sockaddr_un *sun, size_t sz)
-{
-  int fd;
-
-  /* --- Set up the parent directory --- */
-
-  {
-    char *p = sun->sun_path;
-    char *q = strrchr(p, '/');
-
-    if (q) {
-      dstr d = DSTR_INIT;
-      struct stat st;
-
-      DPUTM(&d, p, q - p);
-      DPUTZ(&d);
-
-      mkdir(d.buf, 0700);
-      if (stat(d.buf, &st))
-       die(1, "couldn't stat `%s': %s", d.buf, strerror(errno));
-      if (!S_ISDIR(st.st_mode))
-       die(1, "object `%s' isn't a directory", d.buf);
-      if (st.st_mode & 0077)
-       die(1, "parent directory `%s' has group or world access", d.buf);
-      dstr_destroy(&d);
-    }
-  }
-
-  /* --- Initialize the socket --- */
-
-  {
-    int n = 5;
-    int e;
-
-    umask(0077);
-  again:
-    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
-      die(1, "couldn't create socket: %s", strerror(errno));
-    if (bind(fd, (struct sockaddr *)sun, sz) < 0) {
-      e = errno;
-      if (errno != EADDRINUSE)
-       die(1, "couldn't bind to address: %s", strerror(e));
-      if (!n)
-       die(1, "too many retries; giving up");
-      n--;
-      if (connect(fd, (struct sockaddr *)sun, sz)) {
-       struct stat st;
-       if (errno != ECONNREFUSED)
-         die(1, "couldn't bind to address: %s", strerror(e));
-       if (stat(sun->sun_path, &st))
-         die(1, "couldn't stat `%s': %s", sun->sun_path, strerror(errno));
-       if (!S_ISSOCK(st.st_mode))
-         die(1, "object `%s' isn't a socket", sun->sun_path);
-       if (verbose)
-         log("stale socket found; removing it");
-       unlink(sun->sun_path);
-       close(fd);
-      } else {
-       if (verbose)
-         log("server already running; shutting it down");
-       write(fd, "QUIT\n", 5);
-       sleep(1);
-       close(fd);
-      }
-      goto again;
-    }
-    chmod(sun->sun_path, 0600);
-    fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
-    if (listen(fd, 5))
-      die(1, "couldn't listen on socket: %s", strerror(errno));
-  }
-
-  /* --- Set up the rest of the server --- */
-
-  {
-    static sel_file serv;
-    sockpath = sun->sun_path;
-    atexit(unlinksocket);
-    sel_initfile(&sel, &serv, fd, SEL_READ, pixserv_accept, 0);
-    sel_addfile(&serv);
-  }
-}
-
-/*----- Client support code -----------------------------------------------*/
-
-/* --- Variables --- */
-
-static selbuf c_server, c_client;
-static unsigned c_flags = 0;
-
-#define cf_uclose 1u
-#define cf_sclose 2u
-#define cf_cooked 4u
-
-/* --- Line handler functions --- */
-
-static void c_uline(char *s, size_t len, void *p)
-{
-  if (!s) {
-    selbuf_destroy(&c_client);
-    shutdown(c_server.reader.fd, 1);
-    c_flags |= cf_uclose;
-  } else {
-    s[len++] = '\n';
-    write(c_server.reader.fd, s, len);
-  }
-}
-
-static void c_sline(char *s, size_t len, void *p)
-{
-  if (!s) {
-    selbuf_destroy(&c_server);
-    if (!(c_flags & cf_uclose)) {
-      moan("server closed the connection");
-      selbuf_destroy(&c_client);
-    }
-    exit(0);
-  }
-  if (!(c_flags & cf_cooked))
-    puts(s);
-  else {
-    char *q = str_getword(&s);
-    if (strcmp(q, "FAIL") == 0)
-      die(1, "%s", s);
-    else if (strcmp(q, "INFO") == 0 ||
-            strcmp(q, "ITEM") == 0)
-      puts(s);
-    else if (strcmp(q, "OK") == 0) {
-      if (s && *s) puts(s);
-    } else if (strcmp(q, "MISSING") == 0)
-      ;
-    else
-      moan("unexpected output: %s %s", q, s);
-  }
-}
-
-/* --- @pix_client@ --- *
- *
- * Arguments:  @struct sockaddr_un *sun@ = pointer to socket address
- *             @size_t sz@ = size of socket address
- *             @char *argv[]@ = pointer to arguments to send
- *
- * Returns:    ---
- *
- * Use:                Performs client-side actions for the passphrase pixie.
- */
-
-static void pix_client(struct sockaddr_un *sun, size_t sz, char *argv[])
-{
-  int fd;
-
-  /* --- Dispose of locked memory --- */
-
-  l_destroy(&lm);
-
-  /* --- Open the socket --- */
-
-  if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
-    die(1, "couldn't create socket: %s", strerror(errno));
-  if (connect(fd, (struct sockaddr *)sun, sz))
-    die(1, "couldn't connect to server: %s", strerror(errno));
-  selbuf_init(&c_server, &sel, fd, c_sline, 0);
-
-  /* --- If there are any arguments, turn them into a string --- */
-
-  if (!*argv)
-    selbuf_init(&c_client, &sel, STDIN_FILENO, c_uline, 0);
-  else {
-    dstr d = DSTR_INIT;
-    DPUTS(&d, *argv++);
-    while (*argv) {
-      DPUTC(&d, ' ');
-      DPUTS(&d, *argv++);
-    }
-    DPUTC(&d, '\n');
-    write(fd, d.buf, d.len);
-    shutdown(fd, 1);
-    c_flags |= cf_uclose | cf_cooked;
-    dstr_destroy(&d);
-  }
-
-  /* --- And repeat --- */
-
-  for (;;) {
-    if (sel_select(&sel))
-      die(EXIT_FAILURE, "select error: %s", strerror(errno));
-  }
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @help@, @version@, @usage@ --- *
- *
- * Arguments:  @FILE *fp@ = stream to write on
- *
- * Returns:    ---
- *
- * Use:                Emit helpful messages.
- */
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "\
-Usage:\n\
-       $ [-qvfidl] [-c COMMAND] [-t TIMEOUT] [-s SOCKET]\n\
-       $ [-s SOCKET] -C [COMMAND ARGS...]\n\
-       $ [-s SOCKET] -P[P] TAG\n\
-");
-}
-
-static void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-static void help(FILE *fp)
-{
-  version(fp);
-  fputc('\n', fp);
-  usage(fp);
-  pquis(fp, "\n\
-The Catacomb passphrase pixie collects and caches passphrases used to\n\
-protect important keys.  Options provided:\n\
-\n\
--h, --help             Show this help text.\n\
--V, --version          Show the program's version number.\n\
--u, --usage            Show a (very) terse usage summary.\n\
-\n\
--C, --client           Connect to a running pixie as a client.\n\
--P, --passphrase       Request passphrase TAG and print to stdout.\n\
--PP, --verify-passphrase\n\
-                       Verify passphrase TAG and print to stdout.\n\
-\n\
--q, --quiet            Emit fewer log messages.\n\
--v, --version          Emit more log messages.\n\
--s, --socket=FILE      Name the pixie's socket.\n\
--c, --command=COMMAND  Shell command to read a passphrase.\n\
--f, --fetch            Fetch passphrases from the terminal.\n\
--t, --timeout=TIMEOUT  Length of time to retain a passphrase in memory.\n\
--i, --interactive      Allow commands to be typed interactively.\n\
--d, --daemon           Fork into the background after initialization.\n\
--l, --syslog           Emit log messages to the system log.\n\
-\n\
-The COMMAND may contain `%m' and `%t' markers which are replaced by a\n\
-prompt message and the passphrase tag respectively.  The TIMEOUT is an\n\
-integer, optionally followed by `d', `h', `m' or `s' to specify units of\n\
-days, hours, minutes or seconds respectively.\n\
-\n\
-In client mode, if a command is specified on the command line, it is sent\n\
-to the running server; otherwise the program reads requests from stdin.\n\
-Responses from the pixie are written to stdout.  Send a HELP request for\n\
-a quick summary of the pixie communication protocol.\n\
-");
-}
-
-/* --- @main@ --- *
- *
- * Arguments:  @int argc@ = number of arguments
- *             @char *argv[]@ = vector of argument values
- *
- * Returns:    Zero if OK.
- *
- * Use:                Main program.  Listens on a socket and responds with a PGP
- *             passphrase when asked.
- */
-
-int main(int argc, char *argv[])
-{
-  char *path = 0;
-  struct sockaddr_un *sun;
-  size_t sz;
-  unsigned f = 0;
-
-#define f_bogus 1u
-#define f_client 2u
-#define f_stdin 4u
-#define f_daemon 8u
-#define f_syslog 16u
-#define f_fetch 32u
-#define f_verify 64u
-
-  /* --- Initialize libraries --- */
-
-  ego(argv[0]);
-  sub_init();
-
-  /* --- Set up the locked memory area --- */
-
-  l_init(&lm, 16384);
-  setuid(getuid());
-
-  /* --- Parse command line arguments --- */
-
-  for (;;) {
-    static struct option opts[] = {
-
-      /* --- Standard GNUy help options --- */
-
-      { "help",                0,              0,      'h' },
-      { "version",     0,              0,      'V' },
-      { "usage",       0,              0,      'u' },
-
-      /* --- Other options --- */
-
-      { "quiet",       0,              0,      'q' },
-      { "verbose",     0,              0,      'v' },
-      { "client",      0,              0,      'C' },
-      { "passphrase",  0,              0,      'P' },
-      { "verify-passphrase",   0,      0,      '+' },
-      { "socket",      OPTF_ARGREQ,    0,      's' },
-      { "command",     OPTF_ARGREQ,    0,      'c' },
-      { "fetch",       0,              0,      'f' },
-      { "timeout",     OPTF_ARGREQ,    0,      't' },
-      { "interactive", 0,              0,      'i' },
-      { "stdin",       0,              0,      'i' },
-      { "daemon",      0,              0,      'd' },
-      { "log",         0,              0,      'l' },
-      { "syslog",      0,              0,      'l' },
-
-      /* --- Magic terminator --- */
-
-      { 0,             0,              0,      0 }
-    };
-
-    int i = mdwopt(argc, argv, "hVuqvCPs:c:ft:idl", opts, 0, 0, 0);
-    if (i < 0)
-      break;
-
-    switch (i) {
-
-      /* --- GNUy help options --- */
-
-      case 'h':
-       help(stdout);
-       exit(0);
-      case 'V':
-       version(stdout);
-       exit(0);
-      case 'u':
-       usage(stdout);
-       exit(0);
-
-      /* --- Other interesting things --- */
-
-      case 'q':
-       if (verbose)
-         verbose--;
-       break;
-      case 'v':
-       verbose++;
-       break;
-      case 'C':
-       f |= f_client;
-       f &= ~f_fetch;
-       break;
-      case 'P':
-       if (!(f & f_fetch))
-         f |= f_fetch;
-       else
-         f |= f_verify;
-       break;
-      case '+':
-       f |= f_fetch | f_verify;
-       f &= ~f_client;
-       break;
-      case 's':
-       path = optarg;
-       break;
-      case 't':
-       if ((timeout = pixserv_timeout(optarg)) == 0)
-         die(1, "bad timeout `%s'", optarg);
-       break;
-      case 'c':
-       command = optarg;
-       flags |= F_FETCH;
-       break;
-      case 'f':
-       flags |= F_FETCH;
-       break;
-      case 'i':
-       f |= f_stdin;
-       break;
-      case 'd':
-       f |= f_daemon;
-       break;
-      case 'l':
-       f |= f_syslog;
-       break;
-
-      /* --- Something else --- */
-
-      default:
-       f |= f_bogus;
-       break;
-    }
-  }
-
-  if (f & f_bogus ||
-      (optind < argc && !(f & (f_client|f_fetch))) ||
-      ((f & f_fetch) && optind != argc - 1)) {
-    usage(stderr);
-    exit(1);
-  }
-
-  /* --- Handle request for a passphrase --- */
-
-  if (f & f_fetch) {
-    char *buf = l_alloc(&lm, 1024);
-    passphrase_connect(path);
-    if (passphrase_read(argv[optind],
-                       (f & f_verify) ? PMODE_VERIFY : PMODE_READ,
-                       buf, 1024))
-      die(1, "failed to read passphrase: %s", strerror(errno));
-    puts(buf);
-    return (0);
-  }
-
-  /* --- Set up the socket address --- */
-
-  sun = pixie_address(path, &sz);
-
-  /* --- Initialize selectory --- */
-
-  sel_init(&sel);
-  signal(SIGPIPE, SIG_IGN);
-
-  /* --- Be a client if a client's wanted --- */
-
-  if (f & f_client)
-    pix_client(sun, sz, argv + optind);
-
-  /* --- Open the syslog if requested --- */
-
-  if (f & f_syslog) {
-    flags |= F_SYSLOG;
-    openlog(QUIS, 0, LOG_DAEMON);
-  }
-
-  /* --- Check on the locked memory area --- */
-
-  {
-    dstr d = DSTR_INIT;
-    int rc = l_report(&lm, &d);
-    if (rc < 0)
-      die(EXIT_FAILURE, d.buf);
-    else if (rc && verbose) {
-      log(d.buf);
-      log("couldn't lock passphrase buffer");
-    }
-    dstr_destroy(&d);
-    arena_setsecure(&lm.a);
-  }
-
-  /* --- Set signal behaviours --- */
-
-  {
-    static sig sigint, sigterm, sigquit, sighup;
-    struct sigaction sa;
-    sig_init(&sel);
-    sigaction(SIGINT, 0, &sa);
-    if (sa.sa_handler != SIG_IGN)
-      sig_add(&sigint, SIGINT, pix_sigdie, 0);
-    sig_add(&sigterm, SIGTERM, pix_sigdie, 0);
-    sig_add(&sigquit, SIGQUIT, pix_sigflush, 0);
-    sig_add(&sighup, SIGHUP, pix_sigflush, 0);
-  }
-
-  /* --- Set up the server --- */
-
-  pix_setup(sun, sz);
-  if (f & f_stdin) {
-    pixserv *px = pixserv_create(STDIN_FILENO, STDOUT_FILENO);
-    sel_rmtimer(&px->timer);
-    px->f |= px_stdin;
-  }
-
-  /* --- Fork into the background if requested --- */
-
-  if (f & f_daemon) {
-    pid_t kid;
-
-    if (((f & f_stdin) &&
-        (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO))) ||
-       (!command && (flags & F_FETCH)))
-      die(1, "can't become a daemon if terminal required");
-
-    if ((kid = fork()) < 0)
-      die(1, "fork failed: %s", strerror(errno));
-    if (kid)
-      _exit(0);
-#ifdef TIOCNOTTY
-    {
-      int fd;
-      if ((fd = open("/dev/tty", O_RDONLY)) >= 0) {
-       ioctl(fd, TIOCNOTTY);
-       close(fd);
-      }
-    }
-#endif
-    chdir("/");
-    setsid();
-
-    if (fork() != 0)
-      _exit(0);
-  }
-
-  if (verbose)
-    log("initialized ok");
-
-  {
-    int selerr = 0;
-    for (;;) {
-      if (!sel_select(&sel))
-       selerr = 0;
-      else if (errno != EINTR && errno != EAGAIN) {
-       log("error from select: %s", strerror(errno));
-       selerr++;
-       if (selerr > 8) {
-         log("too many consecutive select errors: bailing out");
-         exit(EXIT_FAILURE);
-       }
-      }
-    }
-  }
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/pixie.h b/pixie.h
deleted file mode 100644 (file)
index a5bc171..0000000
--- a/pixie.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/* -*-c-*-
- *
- * $Id: pixie.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Passphrase pixie definitions (Unix-specific)
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_PIXIE_H
-#define CATACOMB_PIXIE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#ifndef CATACOMB_PASSPHRASE_H
-#  include "passphrase.h"
-#endif
-
-/*----- Protocol definition -----------------------------------------------*
- *
- * The protocol is simple and text-based.  The client connects to the
- * server's socket and sends `request lines', each of which elicits one or
- * more `response lines' from the server.  Request and response lines contain
- * whitespace-separated fields, and are terminated by a single linefeed.  The
- * final field on a line may contain whitespace.  The first field describes
- * the type of the line.  The type field is not case-sensitive, although
- * writing them in uppercase is conventional.
- *
- * The requests are:
- *
- * HELP
- *     Provide (very) brief help with the pixie protocol.
- *
- * LIST
- *     Return a list of passphrases currently stored, together with expiry
- *     information.
- *
- * PASS tag [expire]
- *     Request the passphrase named `tag' from the pixie.
- *
- * VERIFY tag [expire]
- *     Request a new passphrase, which therefore requires verification.
- *
- * SET tag [expire] -- phrase
- *     Set the value of passphrase `tag'.  This will usually be a follow-up
- *     to a MISSING response.
- *
- * FLUSH [tag]
- *     Flush the passphrase named `tag', or all passphrases, from memory.
- *
- * QUIT
- *     Requests that the pixie close down.
- *
- * Response lines are as follows:
- *
- * OK [phrase]
- *     Request completed successfully.  If a passphrase was requested, it is
- *     returned by the pixie.  This is the final response to a request.
- *
- * MISSING
- *     The passphrase requested is not known, and no requester mechanism is
- *     present.  The client should request the passphrase itself and pass it
- *     back to the pixie.  This is the final response to a request.
- *
- * FAIL error
- *     Reports an error.  The message given is intended to be
- *     human-readable.  This is the final response to a request.
- *
- * INFO message
- *     Reports a human-readable informational message.  Further responses
- *     follow.
- *
- * ITEM tag expires
- *     Reports a passphrase in response to a LIST request.  One ITEM
- *     response is given for each passphrase currently in memory.  An OK or
- *     FAIL response follows the last ITEM.
- *
- * Expiry times in requests may be given in any format acceptable to
- * `getdate'.  Expiry times in responses are returned in ISO format
- * (YYYY-MM-DD HH:MM:SS ZZZ) and are expressed relative to local time.
- */
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @pixie_open@ --- *
- *
- * Arguments:  @const char *sock@ = path to pixie socket
- *
- * Returns:    Less than zero if it failed, or file descriptor.
- *
- * Use:                Opens a connection to a passphrase pixie.
- */
-
-extern int pixie_open(const char */*sock*/);
-
-/* --- @pixie_read@ --- *
- *
- * Arguments:  @int fd@ = connection to passphrase pixie
- *             @const char *tag@ = pointer to tag string
- *             @unsigned mode@ = reading mode
- *             @char *buf@ = pointer to destination buffer
- *             @size_t sz@ = size of the buffer
- *
- * Returns:    Zero if all went well, @-1@ if the read fails, @+1@ to
- *             request the passphrase from the user.
- *
- * Use:                Reads a passphrase from the pixie.
- */
-
-extern int pixie_read(int /*fd*/, const char */*tag*/, unsigned /*mode*/,
-                     char */*buf*/, size_t /*sz*/);
-
-/* --- @pixie_set@ --- *
- *
- * Arguments:  @int fd@ = pixie file descriptor
- *             @const char *tag@ = pointer to tag string
- *             @const char *phrase@ = pointer to passphrase string
- *
- * Returns:    ---
- *
- * Use:                Sends a passphrase to the passphrase pixie.
- */
-
-extern void pixie_set(int /*fd*/, const char */*tag*/,
-                     const char */*phrase*/);
-
-/* --- @pixie_cancel@ --- *
- *
- * Arguments:  @int fd@ = pixie file descriptor
- *             @const char *tag@ = pointer to tag string
- *
- * Returns:    ---
- *
- * Use:                Cancels a passphrase if it turns out to be bogus.
- */
-
-extern void pixie_cancel(int /*fd*/, const char */*tag*/);
-
-/* --- @pixie_address@ --- *
- *
- * Arguments:  @const char *sock@ = pointer to socket name
- *             @size_t *psz@ = where to write the address size
- *
- * Returns:    Pointer to filled-in Unix-domain socket address.
- *
- * Use:                Returns a Unix-domain socket address to use to find the
- *             passphrase pixie.
- */
-
-extern struct sockaddr_un *pixie_address(const char */*sock*/,
-                                        size_t */*psz*/);
-
-/* --- @pixie_fdline@ --- *
- *
- * Arguments:  @int fd@ = file descriptor to read from
- *             @char *buf@ = pointer to buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    ---
- *
- * Use:                Reads a line from a file descriptor.  The read is done one
- *             character at a time.  If the entire line won't fit, the end
- *             is truncated.  The line is null terminated.
- */
-
-extern void pixie_fdline(int /*fd*/, char */*buf*/, size_t /*sz*/);
-
-/* --- @pixie_getpass@ --- *
- *
- * Arguments:  @const char *prompt@ = pointer to prompt string
- *             @char *buf@ = pointer to buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    Zero if it worked OK, nonzero otherwise.
- *
- * Use:                Reads a passphrase from the terminal or some other requested
- *             source.
- */
-
-extern int pixie_getpass(const char */*prompt*/,
-                        char */*buf*/, size_t /*sz*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/pkcs1.c b/pkcs1.c
deleted file mode 100644 (file)
index 47c135f..0000000
--- a/pkcs1.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/* -*-c-*-
- *
- * $Id: pkcs1.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * PKCS#1 1.5 packing
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-
-#include "ct.h"
-#include "grand.h"
-#include "rsa.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @pkcs1_cryptencode@ --- *
- *
- * Arguments:  @mp *d@ = where to put the answer
- *             @const void *m@ = pointer to message data
- *             @size_t msz@ = size of message data
- *             @octet *b@ = spare buffer
- *             @size_t sz@ = size of the buffer (big enough)
- *             @unsigned long nbits@ = length of bits of @n@
- *             @void *p@ = pointer to PKCS1 parameter block
- *
- * Returns:    The encoded result, or null.
- *
- * Use:                Implements the operation @EME-PKCS1-V1_5-ENCODE@, as defined
- *             in PKCS#1 v. 2.0 (RFC2437).
- */
-
-mp *pkcs1_cryptencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
-                     unsigned long nbits, void *p)
-{
-  pkcs1 *pp = p;
-  grand *r = pp->r;
-  octet *q;
-  size_t i, n;
-
-  /* --- Ensure that the buffer is sensibly sized --- */
-
-  if (pp->epsz + msz + 11 > sz)
-    return (0);
-
-  /* --- Allocate the buffer and fill it in --- */
-
-  q = b;
-  *q++ = 0x00;
-  *q++ = 0x02;
-  n = sz - msz - pp->epsz - 3;
-  GR_FILL(r, q, n);
-  for (i = 0; i < n; i++) {
-    if (*q == 0)
-      *q = r->ops->range(r, 255) + 1;
-    q++;
-  }
-  *q++ = 0;
-  if (pp->ep) {
-    memcpy(q, pp->ep, pp->epsz);
-    q += pp->epsz;
-  }
-  memcpy(q, m, msz);
-  q += msz;
-  assert(q == b + sz);
-
-  /* --- Collect the result --- */
-
-  return (mp_loadb(d, b, sz));
-}
-
-/* --- @pkcs1_cryptdecode@ --- *
- *
- * Arguments:  @mp *m@ = the decrypted message
- *             @octet *b@ = pointer to a buffer to work in
- *             @size_t sz@ = the size of the buffer (big enough)
- *             @unsigned long nbits@ = the number of bits in @n@
- *             @void *p@ = pointer to PKCS1 parameter block
- *
- * Returns:    The length of the output string if successful, negative on
- *             failure.
- *
- * Use:                Implements the operation @EME-PKCS1-V1_5-DECODE@, as defined
- *             in PKCS#1 v. 2.0 (RFC2437).
- */
-
-int pkcs1_cryptdecode(mp *m, octet *b, size_t sz,
-                     unsigned long nbits, void *p)
-{
-  pkcs1 *pp = p;
-  const octet *q, *qq;
-  size_t n, i;
-  uint32 goodp = 1;
-
-  /* --- Check the size of the block looks sane --- */
-
-  if (pp->epsz + 11 > sz)              /* OK: independent of ciphertext */
-    return (-1);
-  mp_storeb(m, b, sz);
-  q = b;
-  qq = q + sz;
-
-  /* --- Ensure that the block looks OK --- */
-
-  goodp &= ct_inteq(*q++, 0);
-  goodp &= ct_inteq(*q++, 2);
-
-  /* --- Check the nonzero padding --- */
-
-  i = 0;
-  while (*q != 0 && q < qq)
-    i++, q++;
-  goodp &= ct_intle(8, i);
-  goodp &= ~ct_intle(qq - q, pp->epsz + 1);
-  q++;
-
-  /* --- Check the encoding parameters --- */
-
-  if (pp->ep)
-    goodp &= ct_memeq(b + ct_pick(goodp, 0, q - b), pp->ep, pp->epsz);
-  q += pp->epsz;
-
-  /* --- Done --- */
-
-  n = qq - q;
-  memmove(b, b + ct_pick(goodp, 1, q - b), n);
-  return (goodp ? n : -1);
-}
-
-/* --- @pkcs1_sigencode@ --- *
- *
- * Arguments:  @mp *d@ = where to put the answer
- *             @const void *m@ = pointer to message data
- *             @size_t msz@ = size of message data
- *             @octet *b@ = spare buffer
- *             @size_t sz@ = size of the buffer (big enough)
- *             @unsigned long nbits@ = length of bits of @n@
- *             @void *p@ = pointer to PKCS1 parameter block
- *
- * Returns:    The encoded message representative, or null.
- *
- * Use:                Implements the operation @EMSA-PKCS1-V1_5-ENCODE@, as defined
- *             in PKCS#1 v. 2.0 (RFC2437).
- */
-
-mp *pkcs1_sigencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
-                   unsigned long nbits, void *p)
-{
-  pkcs1 *pp = p;
-  octet *q;
-  size_t n;
-
-  /* --- Ensure that the buffer is sensibly sized --- */
-
-  if (pp->epsz + msz + 11 > sz)
-    return (0);
-
-  /* --- Fill in the buffer --- */
-
-  q = b;
-  *q++ = 0x00;
-  *q++ = 0x01;
-  n = sz - msz - pp->epsz - 3;
-  memset(q, 0xff, n);
-  q += n;
-  *q++ = 0;
-  if (pp->ep) {
-    memcpy(q, pp->ep, pp->epsz);
-    q += pp->epsz;
-  }
-  memcpy(q, m, msz);
-  q += msz;
-  assert(q == b + sz);
-  return (mp_loadb(d, b, sz));
-}
-
-/* --- @pkcs1_sigdecode@ --- *
- *
- * Arguments:  @mp *s@ = the message representative
- *             @const void *m@ = the original message, or null (ignored)
- *             @size_t msz@ = the message size (ignored)
- *             @octet *b@ = a scratch buffer
- *             @size_t sz@ = size of the buffer (large enough)
- *             @unsigned long nbits@ = number of bits in @n@
- *             @void *p@ = pointer to PKCS1 parameters
- *
- * Returns:    The length of the output string if successful, negative on
- *             failure.
- *
- * Use:                Implements the operation @EMSA-PKCS1-V1_5-DECODE@, as defined
- *             in PKCS#1 v. 2.0 (RFC2437).
- */
-
-int pkcs1_sigdecode(mp *s, const void *m, size_t msz, octet *b, size_t sz,
-                   unsigned long nbits, void *p)
-{
-  pkcs1 *pp = p;
-  const octet *q, *qq;
-  size_t i, n;
-
-  /* --- Check the size of the block looks sane --- */
-
-  if (pp->epsz + 10 > sz)
-    return (-1);
-  mp_storeb(s, b, sz);
-  q = b;
-  qq = q + sz;
-
-  /* --- Ensure that the block looks OK --- */
-
-  if (*q++ != 0x00 || *q++ != 0x01)
-    return (-1);
-
-  /* --- Check the padding --- */
-
-  i = 0;
-  while (*q == 0xff && q < qq)
-    i++, q++;
-  if (i < 8 || qq - q < pp->epsz + 1 || *q++ != 0)
-    return (-1);
-
-  /* --- Check the encoding parameters --- */
-
-  if (pp->ep && memcmp(q, pp->ep, pp->epsz) != 0)
-    return (-1);
-  q += pp->epsz;
-
-  /* --- Done --- */
-
-  n = qq - q;
-  memmove(b, q, n);
-  return (n);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/prim.c b/prim.c
deleted file mode 100644 (file)
index 4767912..0000000
--- a/prim.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -*-c-*-
- *
- * $Id: prim.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Finding primitive elements
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpint.h"
-#include "mpmont.h"
-#include "mprand.h"
-#include "pgen.h"
-#include "prim.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @prim_test@ --- */
-
-int prim_test(int rq, pgen_event *ev, void *p)
-{
-  prim_ctx *c = p;
-  int rc = rq;
-
-  switch (rq) {
-    case PGEN_BEGIN:
-      return (PGEN_TRY);
-    case PGEN_TRY: {
-      mp *x;
-      rc = PGEN_FAIL;
-
-      if (!c->exp)
-       x = mp_copy(ev->m);
-      else {
-       x = mpmont_exp(&c->mm, MP_NEW, ev->m, c->exp);
-       if (MP_EQ(x, MP_ONE))
-         goto done;
-      }
-      if (c->n == 0)
-       goto ok;
-      else {
-       size_t n = c->n;
-       mp **f = c->f;
-       mp *y = MP_NEW;
-       while (n) {
-         y = mpmont_exp(&c->mm, y, x, *f);
-         if (MP_EQ(y, MP_ONE)) {
-           mp_drop(y);
-           goto done;
-         }
-         n--; f++;
-       }
-       mp_drop(y);
-      }
-    ok:
-      rc = PGEN_DONE;
-      mp_drop(ev->m);
-      ev->m = x;
-      break;
-    done:
-      mp_drop(x);
-    } break;
-  }
-
-  return (rc);
-}
-
-/* --- Trivial stepping functions -----------------------------------------*/
-
-/* --- @prim_step@ --- */
-
-int prim_step(int rq, pgen_event *ev, void *p)
-{
-  unsigned *i = p;
-  switch (rq) {
-    case PGEN_BEGIN:
-    case PGEN_TRY:
-      if (*i >= NPRIME)
-       return PGEN_FAIL;
-      ev->m = mp_fromint(ev->m, primetab[(*i)++]);
-      return (PGEN_TRY);
-  }
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/prim.h b/prim.h
deleted file mode 100644 (file)
index 1df2ed6..0000000
--- a/prim.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*-c-*-
- *
- * $Id: prim.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Finding primitive elements
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_PRIM_H
-#define CATACOMB_PRIM_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_MPMONT_H
-#  include "mpmont.h"
-#endif
-
-#ifndef CATACOMB_PGEN_H
-#  include "pgen.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- @prim_ctx@ --- *
- *
- * All fields must be configured by the client.  Set @n@ to zero to discover
- * generators of the subgroup of order %$m / f$%.
- *
- * Let %$p = \prod q_i + 1$% be a prime number.  In order to find an element
- * %$g$% with order %$o$%, we choose elements %$h_j$% from %$\gf{p}^*$%,
- * compute $%g_j = h_j^{p/o}$%, rejecting %$h_j$% where %$g_j = 1$%, and then
- * for each proper prime factor %$q_i$% of %$p/o$% we check that
- * %$g^{f_i} \ne 1$%, where the %$f_i$% are cofactors of the %$q_i$%
- * (%$f_i q_i = p/o$%).
- */
-
-typedef struct prim_ctx {
-  mpmont mm;                           /* Montgomery context for modulus */
-  mp *exp;                             /* Exponent (%$p/o$%; may be zero) */
-  size_t n;                            /* Number of cofactors */
-  mp **f;                              /* Array of cofactors */
-} prim_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @prim_test@ --- */
-
-extern pgen_proc prim_test;
-
-/* --- @prim_step@ --- */
-
-extern pgen_proc prim_step;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/primeiter.c b/primeiter.c
deleted file mode 100644 (file)
index d7126ba..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/* -*-c-*-
- *
- * Iterate over small primes efficiently
- *
- * (c) 2007 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "fibrand.h"
-#include "mp.h"
-#include "pgen.h"
-#include "primeiter.h"
-#include "primetab.h"
-#include "wheel.h"
-
-/*----- Theory ------------------------------------------------------------*
- *
- * For small primes, we can just pluck them out of the small primes table.
- * For larger primes, we can test them individually, or build a sieve or
- * something, but since we don't know when to stop, that could be tricky.
- *
- * We've built a `wheel', as follows.  Let %$m$% be the product of the first
- * %$n$% primes.  There are %$\phi(m)$% integers %$n_i$%, with %$0 < n_i <
- * m$% coprime to %$m$%, and any integer %$j > n$% must be congruent to some
- * %$n_i$% modulo %$m$%.  The wheel itself doesn't list the %$n_i$%, but
- * rather the differences %$\delta_i = n_i - n_{i-1}$% (wrapping around
- * appropriately at the ends), so you can just add simple offsets to step
- * onwards.  The wheel assumes you start at 1 and move on round.
- */
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @wheelsync@ --- *
- *
- * Arguments:  @primeiter *pi@ = iterator to synchronize
- *             @mp *where@ = value to synchronize
- *
- * Returns:    ---
- *
- * Use:                Sets up the wheel index to match the given integer.  After
- *             this, we can step along the wheel to find candidate primes.
- */
-
-static void wheelsync(primeiter *pi, mp *where)
-{
-  mpw w;
-  mp t;
-  mpw rr;
-  mp *r = MP_NEW;
-  unsigned i, n;
-
-  w = WHEELMOD;
-  mp_build(&t, &w, &w + 1);
-  mp_div(0, &r, where, &t);
-  rr = MP_ZEROP(r) ? 0 : r->v[0];
-
-  for (i = 0, n = 1; rr > n; n += wheel[i], i++);
-  w = n - rr;
-  pi->p = mp_add(MP_NEW, where, &t);
-  pi->i = i;
-  pi->r = fibrand_create(0);
-  MP_DROP(r);
-}
-
-/* --- @primeiter_create@ --- *
- *
- * Arguments:  @primeiter *pi@ = pointer to an iterator structure
- *             @mp *start@ = where to start
- *
- * Returns:    ---
- *
- * Use:                Initializes a prime iterator.  The first output will be the
- *             smallest prime not less than @start@.
- */
-
-void primeiter_create(primeiter *pi, mp *start)
-{
-  mpw n;
-  unsigned l, h, m;
-
-  if (!start || MP_CMP(start, <=, MP_TWO))
-    start = MP_TWO;
-
-  if (MP_LEN(start) <= 1) {
-    n = start->v[0];
-    if (n <= MAXPRIME) {
-      l = 0;
-      h = NPRIME;
-      for (;;) {
-       m = l + (h - l)/2;
-       if (primetab[m] == n) break;
-       else if (m == l) { m++; break; }
-       else if (primetab[m] < n) l = m;
-       else h = m;
-      }
-      pi->i = m;
-      pi->mode = PIMODE_PTAB;
-      mp_build(&pi->pp, &pi->w, &pi->w + 1);
-      pi->p = &pi->pp;
-      return;
-    }
-  }
-
-  wheelsync(pi, start);
-  pi->mode = PIMODE_STALL;
-}
-
-/* --- @primeiter_destroy@ --- *
- *
- * Arguments:  @primeiter *pi@ = pointer to iterator structure
- *
- * Returns:    ---
- *
- * Use:                Frees up an iterator structure when it's no longer wanted.
- */
-
-void primeiter_destroy(primeiter *pi)
-{
-  switch (pi->mode) {
-    case PIMODE_PTAB:
-      break;
-    case PIMODE_STALL:
-    case PIMODE_WHEEL:
-      MP_DROP(pi->p);
-      GR_DESTROY(pi->r);
-      break;
-    default:
-      abort();
-  }
-}
-
-/* --- @primeiter_next@ --- *
- *
- * Arguments:  @primeiter *pi@ = pointer to an iterator structure
- *             @mp *d@ = fake destination
- *
- * Returns:    The next prime number from the iterator.
- *
- * Use:                Returns a new prime number.
- */
-
-mp *primeiter_next(primeiter *pi, mp *d)
-{
-  mp *p;
-
-  switch (pi->mode) {
-    case PIMODE_PTAB:
-      pi->w = primetab[pi->i++];
-      if (pi->i >= NPRIME) {
-       wheelsync(pi, pi->p);
-       pi->mode = PIMODE_WHEEL;
-      }
-      p = MP_COPY(pi->p);
-      MP_SPLIT(p);
-      break;
-    case PIMODE_STALL:
-      pi->mode = PIMODE_WHEEL;
-      goto loop;
-    case PIMODE_WHEEL:
-      do {
-       MP_DEST(pi->p, MP_LEN(pi->p) + 1, pi->p->f);
-       MPX_UADDN(pi->p->v, pi->p->vl, wheel[pi->i++]);
-       MP_SHRINK(pi->p);
-       if (pi->i >= WHEELN) pi->i = 0;
-      loop:;
-      } while (!pgen_primep(pi->p, pi->r));
-      p = MP_COPY(pi->p);
-      break;
-    default:
-      abort();
-  }
-  if (d) MP_DROP(d);
-  return (p);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <mLib/macros.h>
-#include <mLib/testrig.h>
-
-static int test(dstr *v)
-{
-  mp *start = *(mp **)v[0].buf;
-  mp *pp[5], *ret[5];
-  int i;
-  primeiter pi;
-  int ok = 1;
-
-  for (i = 0; i < N(pp); i++)
-    pp[i] = *(mp **)v[i + 1].buf;
-  primeiter_create(&pi, start);
-  for (i = 0; i < N(pp); i++) {
-    ret[i] = primeiter_next(&pi, MP_NEW);
-    if (!MP_EQ(ret[i], pp[i])) ok = 0;
-  }
-  if (!ok) {
-    fprintf(stderr, "\n*** primeiter test failure:\n***   start = ");
-    mp_writefile(start, stderr, 10);
-    for (i = 0; i < N(pp); i++) {
-      fprintf(stderr, "\n***   p[%d] = ", i);
-      mp_writefile(ret[i], stderr, 10);
-      fprintf(stderr, " %s ", MP_EQ(ret[i], pp[i]) ? "==" : "!=");
-      mp_writefile(pp[i], stderr, 10);
-    }
-    fputc('\n', stderr);
-  }
-  for (i = 0; i < N(pp); i++) {
-    MP_DROP(pp[i]);
-    MP_DROP(ret[i]);
-  }
-  primeiter_destroy(&pi);
-  MP_DROP(start);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static test_chunk tests[] = {
-  { "primeiter", test,
-    { &type_mp,  &type_mp, &type_mp, &type_mp, &type_mp, &type_mp, } },
-  { 0 }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, tests, SRCDIR "/tests/pgen");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/progs/Makefile.am b/progs/Makefile.am
new file mode 100644 (file)
index 0000000..4d1dbd9
--- /dev/null
@@ -0,0 +1,109 @@
+### -*-makefile-*-
+###
+### Build script for utility programs
+###
+### (c) 2013 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.
+
+include $(top_srcdir)/vars.am
+
+bin_PROGRAMS            =
+dist_man_MANS           =
+
+UTILS_LIBS              = \
+       libcatcrypt.la $(top_builddir)/libcatacomb.la \
+       $(mLib_LIBS) $(LIBS)
+
+LDADD                   = $(UTILS_LIBS)
+
+###--------------------------------------------------------------------------
+### The `catcrypt' library.
+
+noinst_LTLIBRARIES      = libcatcrypt.la
+libcatcrypt_la_SOURCES  =
+
+## The main library.
+libcatcrypt_la_SOURCES += cc.h
+libcatcrypt_la_SOURCES += cc-enc.c
+libcatcrypt_la_SOURCES += cc-hash.c
+libcatcrypt_la_SOURCES += cc-kem.c
+libcatcrypt_la_SOURCES += cc-list.c
+libcatcrypt_la_SOURCES += cc-progress.c
+libcatcrypt_la_SOURCES += cc-sig.c
+libcatcrypt_la_SOURCES += cc-subcmd.c
+
+## Date parsing.
+libcatcrypt_la_SOURCES += getdate.h
+libcatcrypt_la_SOURCES += getdate.y
+
+###--------------------------------------------------------------------------
+### Utility programs.
+
+## Generate and verify datestamped cookies.
+bin_PROGRAMS           += cookie
+dist_man_MANS          += cookie.1
+
+## Asymmetric message encryption and decryption with deniable authentication.
+bin_PROGRAMS           += catcrypt
+dist_man_MANS          += catcrypt.1
+
+## Signing and verifying files.
+bin_PROGRAMS           += catsign
+dist_man_MANS          += catsign.1
+
+## Issue and verify signatures on directory trees.
+bin_PROGRAMS           += dsig
+dist_man_MANS          += dsig.1
+
+## Compute factorials to arbitrary precision.
+bin_PROGRAMS           += factorial
+
+## Compute Fibonacci numbers to arbitrary precision.
+bin_PROGRAMS           += fibonacci
+
+## Compute hashes of files.
+bin_PROGRAMS           += hashsum
+dist_man_MANS          += hashsum.1
+
+## Key management utility.
+bin_PROGRAMS           += key
+key_SOURCES             = key.c
+dist_man_MANS          += key.1 keyring.5
+
+## Generate passphrases with given entropy using wordlists and Markov models.
+bin_PROGRAMS           += mkphrase
+dist_man_MANS          += mkphrase.1
+
+## Performance testing.
+bin_PROGRAMS           += perftest
+
+## Remember passphrases for limited periods of time.
+bin_PROGRAMS           += pixie
+pixie_SOURCES           = pixie.c
+pixie_LDADD             = $(UTILS_LIBS) $(PIXIE_LIBS)
+dist_man_MANS          += pixie.1
+EXTRA_DIST             += xpixie
+
+## Generate random data.
+bin_PROGRAMS           += rspit
+
+###----- That's all, folks --------------------------------------------------
similarity index 100%
rename from catcrypt.1
rename to progs/catcrypt.1
diff --git a/progs/catcrypt.c b/progs/catcrypt.c
new file mode 100644 (file)
index 0000000..6e0db1d
--- /dev/null
@@ -0,0 +1,769 @@
+/* -*-c-*-
+ *
+ * Command-line encryption tool
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/base64.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include "buf.h"
+#include "rand.h"
+#include "noise.h"
+#include "mprand.h"
+#include "key.h"
+#include "cc.h"
+
+#include "ectab.h"
+#include "ptab.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static const char *keyring = "keyring";
+
+/*----- Data format -------------------------------------------------------*/
+
+/* --- Overview --- *
+ *
+ * The encrypted message is divided into chunks, each preceded by a two-octet
+ * length.  The chunks don't need to be large -- the idea is that we can
+ * stream the chunks in and out.
+ *
+ * The first chunk is a header.  It contains the decryption key-id, and maybe
+ * the verification key-id if the message is signed.
+ *
+ * Next comes the key-encapsulation chunk.  This is decrypted in some
+ * KEM-specific way to yield a secret hash.  The hash is expanded using an
+ * MGF (or similar) to make a symmetric encryption and MAC key.
+ *
+ * If the message is signed, there comes a signature chunk.  The signature is
+ * on the header and key-encapsulation chunks, and further output of the MGF.
+ * This means that the recipient can modify the message and still have a
+ * valid signature, so it's not useful for proving things to other people;
+ * but it also means that the recipient knows that the message is from
+ * someone who knows the hash, which limits the possiblities to (a) whoever
+ * encrypted the message (good!) and (b) whoever knows the recipient's
+ * private key.
+ *
+ * Then come message chunks.  Each one begins with a MAC over an implicit
+ * sequence number and the ciphertext.  The final chunk's ciphertext is
+ * empty; no other chunk is empty.  Thus can the correct end-of-file be
+ * discerned.
+ */
+
+/*----- Chunk I/O ---------------------------------------------------------*/
+
+static void chunk_write(enc *e, buf *b)
+{
+  octet l[2];
+  size_t n = BLEN(b);
+  assert(n <= MASK16);
+  STORE16(l, n);
+  if (e->ops->write(e, l, 2) ||
+      e->ops->write(e, BBASE(b), BLEN(b)))
+    die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+}
+
+static void chunk_read(enc *e, dstr *d, buf *b)
+{
+  octet l[2];
+  size_t n;
+
+  dstr_reset(d);
+  errno = 0;
+  if (e->ops->read(e, l, 2) != 2)
+    goto err;
+  n = LOAD16(l);
+  dstr_ensure(d, n);
+  if (e->ops->read(e, d->buf, n) != n)
+    goto err;
+  d->len = n;
+  buf_init(b, d->buf, d->len);
+  return;
+
+err:
+  if (!errno) die(EXIT_FAILURE, "unexpected end-of-file on input");
+  else die(EXIT_FAILURE, "error reading input: %s", strerror(errno));
+}
+
+/*----- Encryption --------------------------------------------------------*/
+
+static int encrypt(int argc, char *argv[])
+{
+  const char *fn, *of = 0, *kn = "ccrypt", *skn = 0;
+  FILE *ofp = 0;
+  FILE *fp = 0;
+  const char *ef = "binary";
+  fprogress ff;
+  const char *err;
+  int i;
+  int en;
+  size_t n, chsz;
+  dstr d = DSTR_INIT;
+  octet *tag, *ct;
+  buf b;
+  size_t seq;
+  char bb[65536];
+  unsigned f = 0;
+  key_file kf;
+  key *k;
+  key *sk = 0;
+  kem *km;
+  sig *s = 0;
+  gcipher *cx, *c;
+  gmac *m;
+  ghash *h;
+  const encops *eo;
+  enc *e;
+
+#define f_bogus 1u
+#define f_nocheck 2u
+#define f_progress 4u
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "key",         OPTF_ARGREQ,    0,      'k' },
+      { "sign-key",    OPTF_ARGREQ,    0,      's' },
+      { "armour",      0,              0,      'a' },
+      { "armor",       0,              0,      'a' },
+      { "format",      OPTF_ARGREQ,    0,      'f' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "progress",    0,              0,      'p' },
+      { "nocheck",     0,              0,      'C' },
+      { 0,             0,              0,      0 }
+    };
+    i = mdwopt(argc, argv, "k:s:af:o:pC", opt, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'k': kn = optarg; break;
+      case 's': skn = optarg; break;
+      case 'a': ef = "pem"; break;
+      case 'f': ef = optarg; break;
+      case 'o': of = optarg; break;
+      case 'p': f |= f_progress; break;
+      case 'C': f |= f_nocheck; break;
+      default: f |= f_bogus; break;
+    }
+  }
+  if (argc - optind > 1 || (f & f_bogus))
+    die(EXIT_FAILURE, "Usage: encrypt [-OPTIONS] [FILE]");
+
+  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
+    die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
+  if ((k = key_bytag(&kf, kn)) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", kn);
+  if (skn && (sk = key_bytag(&kf, skn)) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", skn);
+
+  if ((eo = getenc(ef)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+  fn = optind < argc ? argv[optind++] : "-";
+  if (strcmp(fn, "-") == 0)
+    fp = stdin;
+  else if ((fp = fopen(fn, "rb")) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s': %s",
+       fn, strerror(errno));
+  }
+
+  if (!of || strcmp(of, "-") == 0)
+    ofp = stdout;
+  else if ((ofp = fopen(of, eo->wmode)) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+       ofp, strerror(errno));
+  }
+
+  dstr_reset(&d);
+  key_fulltag(k, &d);
+  e = initenc(eo, ofp, "CATCRYPT ENCRYPTED MESSAGE");
+  km = getkem(k, "cckem", 0);
+  if (!(f & f_nocheck) && (err = km->ops->check(km)) != 0)
+    moan("key %s fails check: %s", d.buf, err);
+  if (sk) {
+    dstr_reset(&d);
+    key_fulltag(sk, &d);
+    s = getsig(sk, "ccsig", 1);
+    if ((err = s->ops->check(s)) != 0)
+      moan("key %s fails check: %s", d.buf, err);
+  }
+
+  /* --- Build the header chunk --- */
+
+  dstr_reset(&d);
+  dstr_ensure(&d, 256);
+  buf_init(&b, d.buf, 256);
+  buf_putu32(&b, k->id);
+  if (sk) buf_putu32(&b, sk->id);
+  assert(BOK(&b));
+  if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b));
+  chunk_write(e, &b);
+
+  /* --- Build the KEM chunk --- */
+
+  dstr_reset(&d);
+  if (setupkem(km, &d, &cx, &c, &m))
+    die(EXIT_FAILURE, "failed to encapsulate key");
+  buf_init(&b, d.buf, d.len);
+  BSTEP(&b, d.len);
+  if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b));
+  chunk_write(e, &b);
+
+  /* --- Write the signature chunk --- */
+
+  if (s) {
+    GC_ENCRYPT(cx, 0, bb, 1024);
+    GH_HASH(s->h, bb, 1024);
+    dstr_reset(&d);
+    if ((en = s->ops->doit(s, &d)) != 0)
+      die(EXIT_FAILURE, "error creating signature: %s", key_strerror(en));
+    buf_init(&b, d.buf, d.len);
+    BSTEP(&b, d.len);
+    chunk_write(e, &b);
+  }
+
+  /* --- Now do the main crypto --- */
+
+  if (f & f_progress) {
+    if (fprogress_init(&ff, fn, fp)) {
+      die(EXIT_FAILURE, "failed to initialize progress display: %s",
+         strerror(errno));
+    }
+  }
+
+  assert(GC_CLASS(c)->blksz <= sizeof(bb));
+  dstr_ensure(&d, sizeof(bb) + GM_CLASS(m)->hashsz);
+  seq = 0;
+  chsz = MASK16 - GM_CLASS(m)->hashsz;
+  for (;;) {
+    h = GM_INIT(m);
+    GH_HASHU32(h, seq);
+    seq++;
+    if (GC_CLASS(c)->blksz) {
+      GC_ENCRYPT(cx, 0, bb, GC_CLASS(c)->blksz);
+      GC_SETIV(c, bb);
+    }
+    n = fread(bb, 1, chsz, fp);
+    if (!n) break;
+    if (f & f_progress) fprogress_update(&ff, n);
+    buf_init(&b, d.buf, d.sz);
+    tag = buf_get(&b, GM_CLASS(m)->hashsz);
+    ct = buf_get(&b, n);
+    assert(tag); assert(ct);
+    GC_ENCRYPT(c, bb, ct, n);
+    GH_HASH(h, ct, n);
+    GH_DONE(h, tag);
+    GH_DESTROY(h);
+    chunk_write(e, &b);
+  }
+
+  /* --- Final terminator packet --- */
+
+  buf_init(&b, d.buf, d.sz);
+  tag = buf_get(&b, GM_CLASS(m)->hashsz);
+  assert(tag);
+  GH_DONE(h, tag);
+  GH_DESTROY(h);
+  chunk_write(e, &b);
+
+  /* --- All done --- */
+
+  if (f & f_progress) fprogress_done(&ff);
+  e->ops->encdone(e);
+  GM_DESTROY(m);
+  GC_DESTROY(c);
+  GC_DESTROY(cx);
+  freeenc(e);
+  if (s) freesig(s);
+  freekem(km);
+  if (fp != stdin) fclose(fp);
+  if (of) fclose(ofp);
+  key_close(&kf);
+  dstr_destroy(&d);
+  return (0);
+
+#undef f_bogus
+#undef f_nocheck
+#undef f_progress
+}
+
+/*---- Decryption ---------------------------------------------------------*/
+
+static int decrypt(int argc, char *argv[])
+{
+  const char *fn, *of = 0;
+  FILE *ofp = 0, *rfp = 0;
+  FILE *fp = 0;
+  const char *ef = "binary";
+  fprogress ff;
+  int i;
+  size_t n;
+  dstr d = DSTR_INIT;
+  buf b;
+  key_file kf;
+  size_t seq;
+  uint32 id;
+  key *k;
+  key *sk = 0;
+  kem *km;
+  sig *s = 0;
+  gcipher *cx;
+  gcipher *c;
+  ghash *h;
+  gmac *m;
+  octet *tag;
+  unsigned f = 0;
+  const encops *eo;
+  const char *err;
+  int verb = 1;
+  enc *e;
+
+#define f_bogus 1u
+#define f_buffer 2u
+#define f_nocheck 4u
+#define f_progress 8u
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "armour",      0,              0,      'a' },
+      { "armor",       0,              0,      'a' },
+      { "buffer",      0,              0,      'b' },
+      { "verbose",     0,              0,      'v' },
+      { "quiet",       0,              0,      'q' },
+      { "nocheck",     0,              0,      'C' },
+      { "format",      OPTF_ARGREQ,    0,      'f' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "progress",    0,              0,      'p' },
+      { 0,             0,              0,      0 }
+    };
+    i = mdwopt(argc, argv, "abf:o:pqvC", opt, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'a': ef = "pem"; break;
+      case 'b': f |= f_buffer; break;
+      case 'v': verb++; break;
+      case 'q': if (verb) verb--; break;
+      case 'C': f |= f_nocheck; break;
+      case 'f': ef = optarg; break;
+      case 'o': of = optarg; break;
+      case 'p': f |= f_progress; break;
+      default: f |= f_bogus; break;
+    }
+  }
+  if (argc - optind > 1 || (f & f_bogus))
+    die(EXIT_FAILURE, "Usage: decrypt [-OPTIONS] [FILE]");
+
+  if ((eo = getenc(ef)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+  fn = optind < argc ? argv[optind++] : "-";
+  if (strcmp(fn, "-") == 0)
+    fp = stdin;
+  else if ((fp = fopen(fn, eo->rmode)) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s': %s",
+       fn, strerror(errno));
+  }
+
+  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
+    die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
+
+  e = initdec(eo, fp, checkbdry, "CATCRYPT ENCRYPTED MESSAGE");
+
+  if (f & f_progress) {
+    if (fprogress_init(&ff, fn, fp)) {
+      die(EXIT_FAILURE, "failed to initialize progress display: %s",
+         strerror(errno));
+    }
+  }
+
+  /* --- Read the header chunk --- */
+
+  chunk_read(e, &d, &b);
+  if (f & f_progress)
+    fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
+  if (buf_getu32(&b, &id)) {
+    if (f & f_progress) fprogress_done(&ff);
+    if (verb) printf("FAIL malformed header: missing keyid\n");
+    exit(EXIT_FAILURE);
+  }
+  if ((k = key_byid(&kf, id)) == 0) {
+    if (f & f_progress) fprogress_done(&ff);
+    if (verb) printf("FAIL key id %08lx not found\n", (unsigned long)id);
+    exit(EXIT_FAILURE);
+  }
+  if (BLEFT(&b)) {
+    if (buf_getu32(&b, &id)) {
+      if (f & f_progress) fprogress_done(&ff);
+      if (verb) printf("FAIL malformed header: missing signature keyid\n");
+      exit(EXIT_FAILURE);
+    }
+    if ((sk = key_byid(&kf, id)) == 0) {
+      if (f & f_progress) fprogress_done(&ff);
+      if (verb) printf("FAIL key id %08lx not found\n", (unsigned long)id);
+      exit(EXIT_FAILURE);
+    }
+  }
+  if (BLEFT(&b)) {
+    if (f & f_progress) fprogress_done(&ff);
+    if (verb) printf("FAIL malformed header: junk at end\n");
+    exit(EXIT_FAILURE);
+  }
+  if (sk) {
+    s = getsig(sk, "ccsig", 0);
+    if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0) {
+      dstr_reset(&d);
+      key_fulltag(sk, &d);
+      printf("WARN verification key %s fails check: %s\n", d.buf, err);
+    }
+    GH_HASHBUF16(s->h, BBASE(&b), BSZ(&b));
+  }
+
+  /* --- Find the key --- */
+
+  km = getkem(k, "cckem", 1);
+
+  /* --- Read the KEM chunk --- */
+
+  chunk_read(e, &d, &b);
+  if (f & f_progress)
+    fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
+  if (setupkem(km, &d, &cx, &c, &m)) {
+    if (f & f_progress) fprogress_done(&ff);
+    if (verb) printf("FAIL failed to decapsulate key\n");
+    exit(EXIT_FAILURE);
+  }
+  if (s) GH_HASHBUF16(s->h, d.buf, d.len);
+
+  /* --- Verify the signature, if there is one --- */
+
+  if (sk) {
+    dstr_reset(&d);
+    dstr_ensure(&d, 1024);
+    GC_ENCRYPT(cx, 0, d.buf, 1024);
+    GH_HASH(s->h, d.buf, 1024);
+    chunk_read(e, &d, &b);
+    if (f & f_progress)
+      fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
+    if (s->ops->doit(s, &d)) {
+      if (f & f_progress) fprogress_done(&ff);
+      if (verb) printf("FAIL signature verification failed\n");
+      exit(EXIT_FAILURE);
+    }
+    if (verb) {
+      dstr_reset(&d);
+      key_fulltag(sk, &d);
+      if (f & f_progress) fprogress_clear(&ff);
+      printf("INFO good-signature %s\n", d.buf);
+    }
+    freesig(s);
+  } else if (verb) {
+    if (f & f_progress) fprogress_clear(&ff);
+    printf("INFO no-signature\n");
+  }
+
+  /* --- Now decrypt the main body --- */
+
+  if (!of || strcmp(of, "-") == 0) {
+    ofp = stdout;
+    f |= f_buffer;
+  }
+  if (!(f & f_buffer)) {
+    if ((ofp = fopen(of, "wb")) == 0) {
+      if (f & f_progress) fprogress_done(&ff);
+      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+         ofp, strerror(errno));
+    }
+    rfp = ofp;
+  } else if ((rfp = tmpfile()) == 0) {
+    if (f & f_progress) fprogress_done(&ff);
+    die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno));
+  }
+
+  seq = 0;
+  dstr_ensure(&d, GC_CLASS(c)->blksz);
+  dstr_ensure(&d, 4);
+  for (;;) {
+    if (GC_CLASS(c)->blksz) {
+      GC_ENCRYPT(cx, 0, d.buf, GC_CLASS(c)->blksz);
+      GC_SETIV(c, d.buf);
+    }
+    h = GM_INIT(m);
+    GH_HASHU32(h, seq);
+    seq++;
+    chunk_read(e, &d, &b);
+    if (f & f_progress)
+      fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
+    if ((tag = buf_get(&b, GM_CLASS(m)->hashsz)) == 0) {
+      if (f & f_progress) fprogress_done(&ff);
+      if (verb) printf("FAIL bad ciphertext chunk: no tag\n");
+      exit(EXIT_FAILURE);
+    }
+    GH_HASH(h, BCUR(&b), BLEFT(&b));
+    if (memcmp(tag, GH_DONE(h, 0), GM_CLASS(m)->hashsz) != 0) {
+      if (f & f_progress) fprogress_done(&ff);
+      if (verb)
+       printf("FAIL bad ciphertext chunk: authentication failure\n");
+      exit(EXIT_FAILURE);
+    }
+    GH_DESTROY(h);
+    if (!BLEFT(&b))
+      break;
+    GC_DECRYPT(c, BCUR(&b), BCUR(&b), BLEFT(&b));
+    if (fwrite(BCUR(&b), 1, BLEFT(&b), rfp) != BLEFT(&b)) {
+      if (f & f_progress) fprogress_done(&ff);
+      if (verb) printf("FAIL error writing output: %s\n", strerror(errno));
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  if (f & f_progress) fprogress_done(&ff);
+  if (fflush(rfp) || ferror(rfp)) {
+    if (verb) printf("FAIL error writing output: %s\n", strerror(errno));
+    exit(EXIT_FAILURE);
+  }
+  if (f & f_buffer) {
+    if (!ofp && (ofp = fopen(of, "wb")) == 0) {
+      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+         of, strerror(errno));
+    }
+    rewind(rfp);
+    if (f & f_progress) fprogress_init(&ff, "copying buffer", rfp);
+    dstr_reset(&d);
+    dstr_ensure(&d, 65536);
+    if (verb && ofp == stdout) printf("DATA\n");
+    for (;;) {
+      n = fread(d.buf, 1, d.sz, rfp);
+      if (!n) break;
+      if (f & f_progress) fprogress_update(&ff, n);
+      if (fwrite(d.buf, 1, n, ofp) < n) {
+       if (f & f_progress) fprogress_done(&ff);
+       die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+      }
+    }
+    if (f & f_progress) fprogress_done(&ff);
+    if (ferror(rfp) || fclose(rfp))
+      die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno));
+  }
+
+  e->ops->decdone(e);
+  if (verb && ofp != stdout)
+    printf("OK decrypted successfully\n");
+  if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
+      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+  freeenc(e);
+  GC_DESTROY(c);
+  GC_DESTROY(cx);
+  GM_DESTROY(m);
+  freekem(km);
+  if (fp != stdin) fclose(fp);
+  key_close(&kf);
+  dstr_destroy(&d);
+  return (0);
+
+#undef f_bogus
+#undef f_buffer
+#undef f_nocheck
+#undef f_progress
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+#define LISTS(LI)                                                      \
+  LI("Lists", list,                                                    \
+     listtab[i].name, listtab[i].name)                                 \
+  LI("Key-encapsulation mechanisms", kem,                              \
+     kemtab[i].name, kemtab[i].name)                                   \
+  LI("Signature schemes", sig,                                         \
+     sigtab[i].name, sigtab[i].name)                                   \
+  LI("Encodings", enc,                                                 \
+     enctab[i].name, enctab[i].name)                                   \
+  LI("Symmetric encryption algorithms", cipher,                                \
+     gciphertab[i], gciphertab[i]->name)                               \
+  LI("Hash functions", hash,                                           \
+     ghashtab[i], ghashtab[i]->name)                                   \
+  LI("Message authentication codes", mac,                              \
+     gmactab[i], gmactab[i]->name)
+
+MAKELISTTAB(listtab, LISTS)
+
+int cmd_show(int argc, char *argv[])
+{
+  return (displaylists(listtab, argv + 1));
+}
+
+static int cmd_help(int, char **);
+
+static cmd cmdtab[] = {
+  { "help", cmd_help, "help [COMMAND...]" },
+  { "show", cmd_show, "show [ITEM...]" },
+  CMD_ENCODE,
+  CMD_DECODE,
+  { "encrypt", encrypt,
+    "encrypt [-apC] [-k TAG] [-s TAG] [-f FORMAT]\n\t\
+[-o OUTPUT] [FILE]", "\
+Options:\n\
+\n\
+-a, --armour           Same as `-f pem'.\n\
+-f, --format=FORMAT    Encode as FORMAT.\n\
+-k, --key=TAG          Use public encryption key named by TAG.\n\
+-s, --sign-key=TAG     Use private signature key named by TAG.\n\
+-o, --output=FILE      Write output to FILE.\n\
+-p, --progress         Show progress on large files.\n\
+-C, --nocheck          Don't check the public key.\n\
+" },
+  { "decrypt", decrypt,
+    "decrypt [-abpqvC] [-f FORMAT] [-o OUTPUT] [FILE]", "\
+Options:\n\
+\n\
+-a, --armour           Same as `-f pem'.\n\
+-b, --buffer           Buffer output until we're sure we have it all.\n\
+-f, --format=FORMAT    Decode as FORMAT.\n\
+-o, --output=FILE      Write output to FILE.\n\
+-p, --progress         Show progress on large files.\n\
+-q, --quiet            Produce fewer messages.\n\
+-v, --verbose          Produce more verbose messages.\n\
+-C, --nocheck          Don't check the private key.\n\
+" },
+  { 0, 0, 0 }
+};
+
+static int cmd_help(int argc, char **argv)
+{
+  sc_help(cmdtab, stdout, argv + 1);
+  return (0);
+}
+
+void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n");
+}
+
+void help_global(FILE *fp)
+{
+  usage(fp);
+  fputs("\n\
+Encrypt and decrypt files.\n\
+\n\
+Global command-line options:\n\
+\n\
+-h, --help [COMMAND...]        Show this help message, or help for COMMANDs.\n\
+-v, --version          Show program version number.\n\
+-u, --usage            Show a terse usage message.\n\
+\n\
+-k, --keyring=FILE     Read keys from FILE.\n",
+       fp);
+}
+
+/* --- @main@ --- *
+ *
+ * Arguments:  @int argc@ = number of command line arguments
+ *             @char *argv[]@ = vector of command line arguments
+ *
+ * Returns:    Zero if successful, nonzero otherwise.
+ *
+ * Use:                Encrypts or decrypts files.
+ */
+
+int main(int argc, char *argv[])
+{
+  unsigned f = 0;
+
+#define f_bogus 1u
+
+  /* --- Initialize the library --- */
+
+  ego(argv[0]);
+  sub_init();
+  rand_noisesrc(RAND_GLOBAL, &noise_source);
+  rand_seed(RAND_GLOBAL, 160);
+
+  /* --- Parse options --- */
+
+  for (;;) {
+    static struct option opts[] = {
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'v' },
+      { "usage",       0,              0,      'u' },
+      { "keyring",     OPTF_ARGREQ,    0,      'k' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'h':
+       sc_help(cmdtab, stdout, argv + optind);
+       exit(0);
+       break;
+      case 'v':
+       version(stdout);
+       exit(0);
+       break;
+      case 'u':
+       usage(stdout);
+       exit(0);
+      case 'k':
+       keyring = optarg;
+       break;
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+  optind = 0;
+  if (f & f_bogus || argc < 1) {
+    usage(stderr);
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Dispatch to the correct subcommand handler --- */
+
+  return (findcmd(cmdtab, argv[0])->cmd(argc, argv));
+
+#undef f_bogus
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from catsign.1
rename to progs/catsign.1
diff --git a/progs/catsign.c b/progs/catsign.c
new file mode 100644 (file)
index 0000000..48f8fcb
--- /dev/null
@@ -0,0 +1,1274 @@
+/* -*-c-*-
+ *
+ * Sign files
+ *
+ * (c) 2005 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include "config.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <mLib/base64.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include "buf.h"
+#include "rand.h"
+#include "noise.h"
+#include "mprand.h"
+#include "key.h"
+#include "getdate.h"
+#include "cc.h"
+
+#include "ectab.h"
+#include "ptab.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static const char *keyring = "keyring";
+
+/*----- Data formats ------------------------------------------------------*
+ *
+ * Our crypto stuff is split into three parts: a header describing the key,
+ * the message itself, and the signature.  In a detached signature, the
+ * message is separate, and the header and signature are combined into one
+ * encoded chunk.  In an attached signature, the message is included.  There
+ * are two forms of message: binary and text.  Binary messages are divided
+ * into chunks, each preceded by a 2-octet length, and terminated by a
+ * zero-length chunk.  Text messages are byte-stuffed, as for RFC821, and
+ * trailing whitespace before a newline is ignored.
+ */
+
+typedef struct sigmsg {
+  unsigned f;                          /* Flags */
+#define F_DETACH 1u
+#define F_BINARY 2u
+#define F_SIGMASK 3u
+#define F_HASHMASK (F_BINARY)
+  uint32 keyid;                                /* Key identifier */
+  time_t t;                            /* When the signature was made */
+  dstr kh;                             /* Key fingerprint (sanity check) */
+  dstr sig;                            /* Signature */
+  sig *s;                              /* Signature algorithm */
+} sigmsg;
+
+#define F_MIDLINE 16u
+#define F_EOF 32u
+#define F_NOCLOSE 64u
+#define F_BOGUS 128u
+#define F_BUFFER 256u
+#define F_UTC 512u
+#define F_NOCHECK 1024u
+#define F_PROGRESS 2048u
+
+/*----- Chunk I/O ---------------------------------------------------------*/
+
+static void chunk_write(enc *e, const void *p, size_t n)
+{
+  octet b[2];
+
+  assert(n <= 0xffff);
+  STORE16(b, n);
+  if (e->ops->write(e, b, 2) || e->ops->write(e, p, n))
+    die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+}
+
+static size_t chunk_read(enc *e, void *p)
+{
+  octet b[2];
+  size_t n;
+
+  if (e->ops->read(e, b, 2) != 2)
+    goto err;
+  n = LOAD16(b);
+  if (n && e->ops->read(e, p, n) != n)
+    goto err;
+  return (n);
+
+err:
+  if (!errno) die(EXIT_FAILURE, "unexpected end-of-file on input");
+  else die(EXIT_FAILURE, "error reading input: %s", strerror(errno));
+  return (0);
+}
+
+/*----- Message canonification --------------------------------------------*/
+
+#define MSGBUFSZ 65536
+#define MSGBUFTHRESH 32768
+
+typedef struct msgcanon {
+  unsigned f;
+  FILE *fp;
+  enc *e;
+  fprogress ff;
+  size_t (*read)(struct msgcanon *, void *);
+  void (*write)(struct msgcanon *, const void *, size_t);
+  void (*close)(struct msgcanon *);
+} msgcanon;
+
+#define MC_INIT { 0 }
+
+static size_t textread(msgcanon *m, void *bp)
+{
+  size_t n = 0, nsp = 0;
+  int ch;
+  char *b = bp;
+  unsigned f = m->f;
+
+  if (f & F_EOF) return (0);
+  for (;;) {
+    if ((ch = getc(m->fp)) == EOF) goto eof;
+    if (!(f & (F_DETACH | F_MIDLINE)) && ch == '.') {
+      ch = getc(m->fp);
+      if (ch == '\n') goto eof;
+    }
+    if (ch == '\n') {
+      n -= nsp; nsp = 0;
+      if (n >= MSGBUFTHRESH) goto full;
+      b[n++] = ch;
+      f &= ~F_MIDLINE;
+    } else if (isspace(ch)) {
+      f |= F_MIDLINE;
+      if (n >= MSGBUFSZ) goto full;
+      b[n++] = ch; nsp++;
+    } else {
+      f |= F_MIDLINE;
+      nsp = 0;
+      if (n >= MSGBUFTHRESH) goto full;
+      b[n++] = ch;
+    }
+  }
+eof:
+  f |= F_EOF;
+  goto done;
+full:
+  ungetc(ch, m->fp);
+done:
+  m->f = f;
+  if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
+  return (n);
+}
+
+static void textwrite(msgcanon *m, const void *bp, size_t n)
+{
+  const char *p = bp, *l = p + n;
+  unsigned f = m->f;
+
+  while (p < l) {
+    if (!(f & (F_MIDLINE | F_DETACH)) &&
+       (*p == '.' || *p == '-'))
+      putc('.', m->fp);
+    if (*p == '\n') f &= ~F_MIDLINE;
+    else f |= F_MIDLINE;
+    putc(*p, m->fp);
+    p++;
+  }
+  m->f = f;
+}
+
+static size_t binreadembed(msgcanon *m, void *bp)
+{
+  size_t n = chunk_read(m->e, bp);
+  if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
+  return (n);
+}
+
+static size_t binreaddetach(msgcanon *m, void *bp)
+{
+  size_t n = fread(bp, 1, MSGBUFSZ - 1, m->fp);
+  if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
+  return (n);
+}
+
+static void binwriteembed(msgcanon *m, const void *bp, size_t n)
+  { chunk_write(m->e, bp, n); }
+
+static void nullwrite(msgcanon *m, const void *bp, size_t n) { ; }
+
+static void mcsetup_readfile(msgcanon *m, unsigned f, const char *fn)
+{
+  m->f = F_DETACH | (f & (F_BINARY | F_PROGRESS));
+  if (!fn || strcmp(fn, "-") == 0) {
+    m->fp = stdin;
+    m->f |= F_NOCLOSE;
+  } else if ((m->fp = fopen(fn, (f & F_BINARY) ? "rb" : "r")) == 0)
+    die(EXIT_FAILURE, "couldn't open file `%s': %s", fn, strerror(errno));
+  if (m->f & F_PROGRESS) {
+    if (fprogress_init(&m->ff, fn, m->fp)) {
+      die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+         strerror(errno));
+    }
+  }
+  m->read = (f & F_BINARY) ? binreaddetach : textread;
+}
+
+static void mcsetup_writenull(msgcanon *m) { m->write = nullwrite; }
+
+static void mcsetup_read(msgcanon *m, unsigned f, enc **ee,
+                        const char *fn, const char *dfn)
+{
+  enc *e = *ee;
+
+  m->f = f | F_NOCLOSE;
+
+  if (dfn && !(f & F_DETACH)) die(EXIT_FAILURE, "signature is not detached");
+  if (f & F_BINARY) {
+    if (!(f & F_DETACH)) {
+      m->e = e;
+      *ee = 0;
+      m->fp = e->fp;
+      m->read = binreadembed;
+      if (m->f & F_PROGRESS) {
+       if (fprogress_init(&m->ff, fn, m->fp)) {
+         die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+             strerror(errno));
+       }
+      }
+    } else {
+      m->read = binreaddetach;
+      if (!dfn || strcmp(dfn, "-") == 0)
+       m->fp = stdin;
+      else if ((m->fp = fopen(dfn, "rb")) == 0)
+       die(EXIT_FAILURE, "can't open `%s': %s", dfn, strerror(errno));
+      else
+       m->f &= ~F_NOCLOSE;
+      if (m->f & F_PROGRESS) {
+       if (fprogress_init(&m->ff, dfn, m->fp)) {
+         die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+             strerror(errno));
+       }
+      }
+    }
+  } else {
+    m->read = textread;
+    if (!(f & F_DETACH)) {
+      if (e->ops->decdone(e) || ferror(e->fp))
+       die(EXIT_FAILURE, "error at end of signature header");
+      m->fp = e->fp;
+      e->ops->destroy(e);
+      *ee = 0;
+      if (m->f & F_PROGRESS) {
+       if (fprogress_init(&m->ff, fn, m->fp)) {
+         die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+             strerror(errno));
+       }
+      }
+    } else {
+      if (!dfn || strcmp(dfn, "-") == 0)
+       m->fp = stdin;
+      else if ((m->fp = fopen(dfn, "r")) == 0)
+       die(EXIT_FAILURE, "can't read file `%s': %s", dfn, strerror(errno));
+      else
+       m->f &= ~F_NOCLOSE;
+      if (m->f & F_PROGRESS) {
+       if (fprogress_init(&m->ff, dfn, m->fp)) {
+         die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+             strerror(errno));
+       }
+      }
+    }
+  }
+}
+
+static void mcsetup_write(msgcanon *m, unsigned f, enc **ee)
+{
+  enc *e = *ee;
+
+  m->f = f | F_NOCLOSE;
+
+  if (f & F_DETACH)
+    m->write = nullwrite;
+  else if (f & F_BINARY) {
+    m->e = e;
+    *ee = 0;
+    m->fp = e->fp;
+    m->write = binwriteembed;
+  } else {
+    if (e->ops->encdone(e) || ferror(e->fp))
+      die(EXIT_FAILURE, "error at end of signature header");
+    m->fp = e->fp;
+    e->ops->destroy(e);
+    *ee = 0;
+    m->write = textwrite;
+  }
+}
+
+static void mc_endread(msgcanon *m, const encops *eops, enc **ee)
+{
+  if (!(m->f & F_DETACH)) {
+    if (m->f & F_BINARY)
+      *ee = m->e;
+    else
+      *ee = initdec(eops, m->fp, checkbdry, "CATSIGN SIGNATURE");
+  }
+  if (m->fp && !(m->f & F_NOCLOSE)) {
+    if (ferror(m->fp) || fclose(m->fp))
+      die(EXIT_FAILURE, "error closing message file: %s", strerror(errno));
+  }
+  if (m->f & F_PROGRESS) fprogress_done(&m->ff);
+}
+
+static void mc_endwrite(msgcanon *m, const encops *eops, enc **ee)
+{
+  if (!(m->f & F_BINARY)) {
+    if (m->f & F_MIDLINE) putc('\n', m->fp);
+    if (!(m->f & F_DETACH)) {
+      putc('.', m->fp); putc('\n', m->fp);
+      *ee = initenc(eops, m->fp, "CATSIGN SIGNATURE");
+    }
+  } else if (!(m->f & F_DETACH)) {
+    chunk_write(m->e, 0, 0);
+    *ee = m->e;
+  }
+  if (m->fp && !(m->f & F_NOCLOSE)) {
+    if (fflush(m->fp) || ferror(m->fp) || fclose(m->fp))
+      die(EXIT_FAILURE, "error closing message file: %s", strerror(errno));
+  }
+}
+
+/*----- Signature reading and writing -------------------------------------*/
+
+static void sig_init(sigmsg *s, unsigned f, uint32 keyid)
+{
+  s->f = f & F_SIGMASK;
+  s->keyid = keyid;
+  time(&s->t);
+  s->s = 0;
+  dstr_create(&s->kh);
+  dstr_create(&s->sig);
+}
+
+static void sig_destroy(sigmsg *s)
+{
+  dstr_destroy(&s->kh);
+  dstr_destroy(&s->sig);
+  if (s->s) freesig(s->s);
+}
+
+static void sigtobuffer(sigmsg *s, buf *b, int hashp)
+{
+  kludge64 t;
+
+  ASSIGN64(t, s->t);
+  if (hashp) buf_putu16(b, s->f & F_HASHMASK);
+  else buf_putu16(b, s->f & F_SIGMASK);
+  buf_putu32(b, s->keyid);
+  buf_putu32(b, HI64(t));
+  buf_putu32(b, LO64(t));
+  buf_putdstr16(b, &s->kh);
+  assert(BOK(b));
+}
+
+static void dohash(ghash *h, const void *p, size_t n)
+{
+/*   trace_block(1, "hashing", p, n); */
+  GH_HASH(h, p, n);
+}
+
+static void sig_hash(sigmsg *s)
+{
+  octet bb[16384];
+  buf b;
+
+  buf_init(&b, bb, sizeof(bb));
+  sigtobuffer(s, &b, 1);
+  dohash(s->s->h, BBASE(&b), BLEN(&b));
+}
+
+static void keyhash(key *k, sig *s, dstr *d)
+{
+  ghash *h;
+  key_filter kf;
+
+  h = GH_INIT(s->ch);
+  kf.f = KCAT_PUB;
+  kf.m = KF_CATMASK;
+  key_fingerprint(k, h, &kf);
+  dstr_ensure(d, GH_CLASS(h)->hashsz);
+  GH_DONE(h, d->buf + d->len);
+  d->len += GH_CLASS(h)->hashsz;
+  GH_DESTROY(h);
+}
+
+static void sig_writeheader(enc *e, sigmsg *s)
+{
+  octet bb[16384];
+  buf b;
+
+  buf_init(&b, bb, sizeof(bb));
+  sigtobuffer(s, &b, 0);
+  chunk_write(e, BBASE(&b), BLEN(&b));
+}
+
+static void sig_writesig(enc *e, sigmsg *s)
+  { chunk_write(e, s->sig.buf, s->sig.len); }
+
+static void diechoke(const char *m, void *p)
+  { die(EXIT_FAILURE, "%s%s%s", p, p ? ": " : "", m); }
+
+static void sig_readheader(enc *e, sigmsg *s,
+                          void (*choke)(const char *, void *), void *p)
+{
+  uint16 f;
+  octet bb[MSGBUFSZ];
+  uint32 x, y;
+  kludge64 t;
+  buf b;
+  size_t n;
+
+  n = chunk_read(e, bb);
+  buf_init(&b, bb, n);
+  if (buf_getu16(&b, &f)) choke("missing flags", p);
+  if (buf_getu32(&b, &x)) choke("missing keyid", p);
+  sig_init(s, f, x);
+  if (buf_getu32(&b, &x) || buf_getu32(&b, &y))
+    choke("missing datestamp", p);
+  SET64(t, x, y); s->t = GET64(time_t, t);
+  if (buf_getdstr16(&b, &s->kh))
+    choke("missing key hash", p);
+  if (BLEFT(&b))
+    choke("junk at end", p);
+}
+
+static void sig_readsig(enc *e, sigmsg *s)
+{
+  octet bb[MSGBUFSZ];
+  size_t n;
+
+  n = chunk_read(e, bb);
+  dstr_putm(&s->sig, bb, n);
+}
+
+/*----- Signing -----------------------------------------------------------*/
+
+static int sign(int argc, char *argv[])
+{
+  const char *ef = "binary", *fn = 0, *of = 0, *kn = "ccsig", *err;
+  unsigned f = 0;
+  key_file kf;
+  key *k;
+  sigmsg s;
+  FILE *ofp = 0;
+  int i;
+  char bb[MSGBUFSZ];
+  size_t n;
+  dstr d = DSTR_INIT;
+  const encops *eo;
+  msgcanon mc_in = MC_INIT, mc_out = MC_INIT;
+  enc *e;
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "armour",      0,              0,      'a' },
+      { "armor",       0,              0,      'a' },
+      { "binary",      0,              0,      'b' },
+      { "detach",      0,              0,      'd' },
+      { "key",         OPTF_ARGREQ,    0,      'k' },
+      { "format",      OPTF_ARGREQ,    0,      'f' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "progress",    0,              0,      'p' },
+      { "text",                0,              0,      't' },
+      { "nocheck",     0,              0,      'C' },
+      { 0,             0,              0,      0 }
+    };
+    i = mdwopt(argc, argv, "k:f:o:abdptC", opt, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'k': kn = optarg; break;
+      case 'f': ef = optarg; break;
+      case 'o': of = optarg; break;
+      case 'a': ef = "pem"; break;
+      case 't': f &= ~F_BINARY; break;
+      case 'b': f |= F_BINARY; break;
+      case 'd': f |= F_DETACH; break;
+      case 'C': f |= F_NOCHECK; break;
+      case 'p': f |= F_PROGRESS; break;
+      default: f |= F_BOGUS; break;
+    }
+  }
+  if (argc - optind > 1 || (f & F_BOGUS))
+    die(EXIT_FAILURE, "Usage: sign [-OPTIONS] [FILE]");
+
+  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
+    die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
+  if ((k = key_bytag(&kf, kn)) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", kn);
+
+  if ((eo = getenc(ef)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+  fn = (optind >= argc) ? 0 : argv[optind++];
+
+  if (!of || strcmp(of, "-") == 0)
+    ofp = stdout;
+  else if ((ofp = fopen(of, eo->wmode)) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+       ofp, strerror(errno));
+  }
+
+  /* --- Start the work --- */
+
+  sig_init(&s, f, k->id);
+  dstr_reset(&d);
+  key_fulltag(k, &d);
+  s.s = getsig(k, "ccsig", 1);
+  if (!(f & F_NOCHECK) && (err = s.s->ops->check(s.s)) != 0)
+    moan("key %s fails check: %s", d.buf, err);
+  keyhash(k, s.s, &s.kh);
+  e = initenc(eo, ofp,
+             (f & F_DETACH) ? "CATSIGN SIGNATURE" :
+             (f & F_BINARY) ? "CATSIGN MESSAGE" :
+             "CATSIGN MESSAGE HEADER");
+  sig_writeheader(e, &s);
+
+  /* --- Hash the message --- */
+
+  mcsetup_readfile(&mc_in, f, fn);
+  mcsetup_write(&mc_out, f, &e);
+  sig_hash(&s);
+  for (;;) {
+    n = mc_in.read(&mc_in, bb);
+    if (!n) break;
+    dohash(s.s->h, bb, n);
+    mc_out.write(&mc_out, bb, n);
+  }
+  mc_endread(&mc_in, 0, 0);
+  mc_endwrite(&mc_out, eo, &e);
+
+  /* --- Write the signature --- */
+
+  if (s.s->ops->doit(s.s, &s.sig))
+    die(EXIT_FAILURE, "signature failed");
+  sig_writesig(e, &s);
+  e->ops->encdone(e);
+  if (fflush(ofp) || ferror(ofp) || fclose(ofp))
+    die(EXIT_FAILURE, "error writing signature: %s", strerror(errno));
+
+  /* --- All done --- */
+
+  freeenc(e);
+  key_close(&kf);
+  sig_destroy(&s);
+  dstr_destroy(&d);
+  return (0);
+}
+
+/*----- Verifying ---------------------------------------------------------*/
+
+typedef struct vrfctx {
+  unsigned f, m;
+  int verb;
+  const char *what;
+} vrfctx;
+
+static int vrfbdry(const char *b, void *p)
+{
+  vrfctx *v = p;
+
+  if (strcmp(b, "CATSIGN MESSAGE") == 0) {
+    v->f |= F_BINARY;
+    v->m |= F_BINARY | F_DETACH;
+    return (1);
+  } else if (strcmp(b, "CATSIGN MESSAGE HEADER") == 0) {
+    v->m |= F_BINARY | F_DETACH;
+    return (1);
+  } else if (strcmp(b, "CATSIGN SIGNATURE") == 0) {
+    v->f |= F_DETACH;
+    v->m |= F_DETACH;
+    return (1);
+  } else
+    return (0);
+}
+
+static void vrfchoke(const char *m, void *p)
+{
+  vrfctx *v = p;
+  if (v->verb) printf("FAIL %s: %s\n", v->what, m);
+  exit(EXIT_FAILURE);
+}
+
+static int verify(int argc, char *argv[])
+{
+  const char *ef = "binary", *of = 0, *fn, *dfn = 0, *kn = 0, *err;
+  vrfctx v = { 0, 0, 1 };
+  key_file kf;
+  key *k, *kk = 0;
+  sigmsg s;
+  FILE *fp, *ofp = 0, *rfp = 0;
+  fprogress ff;
+  struct tm *tm;
+  int i;
+  char bb[MSGBUFSZ];
+  size_t n;
+  time_t t_fresh = 0;
+  dstr d = DSTR_INIT, dd = DSTR_INIT;
+  const encops *eo;
+  msgcanon mc_in = MC_INIT;
+  enc *e;
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "armour",      0,              0,      'a' },
+      { "armor",       0,              0,      'a' },
+      { "buffer",      0,              0,      'b' },
+      { "key",         OPTF_ARGREQ,    0,      'k' },
+      { "format",      OPTF_ARGREQ,    0,      'f' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "progress",    0,              0,      'p' },
+      { "quiet",       0,              0,      'q' },
+      { "utc",         0,              0,      'u' },
+      { "fresh-time",  0,              0,      't' },
+      { "gmt",         0,              0,      'u' },
+      { "verbose",     0,              0,      'v' },
+      { "nocheck",     0,              0,      'C' },
+      { 0,             0,              0,      0 }
+    };
+    i = mdwopt(argc, argv, "k:f:o:abpqt:uvC", opt, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'a': ef = "pem"; break;
+      case 'b': v.f |= F_BUFFER; break;
+      case 'k': kn = optarg; break;
+      case 'f': ef = optarg; break;
+      case 'o': of = optarg; break;
+      case 'u': v.f |= F_UTC; break;
+      case 'C': v.f |= F_NOCHECK; break;
+      case 't':
+       if (strcmp(optarg, "always") == 0) t_fresh = 0;
+       else if ((t_fresh = get_date(optarg, 0)) < 0)
+         die(EXIT_FAILURE, "bad freshness time");
+       break;
+      case 'q': if (v.verb > 0) v.verb--; break;
+      case 'v': if (v.verb < 10) v.verb++; break;
+      case 'p': v.f |= F_PROGRESS; break;
+      default: v.f |= F_BOGUS; break;
+    }
+  }
+  if (argc - optind > 2 || (v.f & F_BOGUS))
+    die(EXIT_FAILURE, "Usage: verify [-OPTIONS] [FILE [MESSAGE]]");
+
+  if ((eo = getenc(ef)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+  fn = optind < argc ? argv[optind++] : "-";
+  if (strcmp(fn, "-") == 0)
+    fp = stdin;
+  else if ((fp = fopen(fn, eo->rmode)) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s': %s",
+       fn, strerror(errno));
+  }
+
+  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
+    die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
+  if (kn && (kk = key_bytag(&kf, kn)) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", kn);
+
+  e = initdec(eo, fp, vrfbdry, &v);
+
+  /* --- Read the header chunk --- */
+
+  v.what = "malformed header";
+  sig_readheader(e, &s, vrfchoke, &v);
+
+  if (((s.f ^ v.f) & v.m) != 0) {
+    if (v.verb) printf("FAIL boundary string inconsistent with contents\n");
+    exit(EXIT_FAILURE);
+  }
+  v.f |= s.f;
+
+  if ((k = key_byid(&kf, s.keyid)) == 0) {
+    if (v.verb) printf("FAIL key id %08lx not found\n",
+                      (unsigned long)s.keyid);
+    exit(EXIT_FAILURE);
+  }
+  if (kk && k->id != kk->id) {
+    if (v.verb) {
+      dstr_reset(&d); key_fulltag(k, &d);
+      dstr_reset(&dd); key_fulltag(kk, &dd);
+      printf("FAIL signing key is %s; expected key %s\n", d.buf, dd.buf);
+    }
+    exit(EXIT_FAILURE);
+  }
+
+  s.s = getsig(k, "ccsig", 0);
+  dstr_reset(&d); key_fulltag(k, &d);
+  if (!(v.f & F_NOCHECK) && v.verb && (err = s.s->ops->check(s.s)) != 0)
+    printf("WARN verification key %s fails check: %s\n", d.buf, err);
+
+  dstr_reset(&dd); keyhash(k, s.s, &dd);
+  if (dd.len != s.kh.len || memcmp(dd.buf, s.kh.buf, dd.len) != 0) {
+    if (v.verb) printf("FAIL key hash mismatch\n");
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Now a merry dance --- */
+
+  if (v.f & F_DETACH)
+    sig_readsig(e, &s);
+  if (optind < argc)
+    dfn = argv[optind++];
+  mcsetup_read(&mc_in, v.f, &e, fn, dfn);
+
+  if (!of && (v.f & F_DETACH)) {
+    rfp = ofp = 0;
+    v.f &= ~F_BUFFER;
+  } else if (!of || strcmp(of, "-") == 0) {
+    v.f |= F_BUFFER;
+    ofp = stdout;
+  }
+  if (of && !(v.f & F_BUFFER)) {
+    if ((ofp = fopen(of, (v.f & F_BINARY) ? "wb" : "w")) == 0) {
+      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+         of, strerror(errno));
+    }
+    rfp = ofp;
+  } else if ((rfp = tmpfile()) == 0)
+    die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno));
+
+  /* --- Read the message and verify the signature --- */
+
+  sig_hash(&s);
+  for (;;) {
+    n = mc_in.read(&mc_in, bb);
+    if (!n) break;
+    dohash(s.s->h, bb, n);
+    if (rfp) fwrite(bb, 1, n, rfp);
+  }
+  mc_endread(&mc_in, eo, &e);
+  if (!(v.f & F_DETACH))
+    sig_readsig(e, &s);
+  if (rfp && (ferror(rfp) || fflush(rfp))) {
+    if (v.verb) printf("FAIL error writing message: %s\n", strerror(errno));
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Check the signature --- */
+
+  if (s.s->ops->doit(s.s, &s.sig)) {
+    if (v.verb) printf("FAIL signature verification failed\n");
+    exit(EXIT_FAILURE);
+  }
+  if (t_fresh && s.t < t_fresh) {
+    if (v.verb) printf("FAIL signature is stale\n");
+    exit(EXIT_FAILURE);
+  }
+  if (s.t > time(0)) {
+    if (v.verb) printf("FAIL signature timestamp in the future\n");
+    exit(EXIT_FAILURE);
+  }
+  if (v.verb) {
+    tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t);
+    strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm);
+    printf("INFO good-signature %s\n", d.buf);
+    printf("INFO date %s\n", bb);
+  }
+
+  /* --- Unbuffer buffered input --- */
+
+  if (v.f & F_BUFFER) {
+    if (!ofp && (ofp = fopen(of, "wb")) == 0) {
+      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+         of, strerror(errno));
+    }
+    rewind(rfp);
+    if (v.f & F_PROGRESS) fprogress_init(&ff, "copying buffer", rfp);
+    if (v.verb && ofp == stdout) printf("DATA\n");
+    for (;;) {
+      n = fread(bb, 1, sizeof(bb), rfp);
+      if (!n) break;
+      if (v.f & F_PROGRESS) fprogress_update(&ff, n);
+      if (fwrite(bb, 1, n, ofp) < n) {
+       if (v.f & F_PROGRESS) fprogress_done(&ff);
+       die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+      }
+    }
+    if (v.f & F_PROGRESS) fprogress_done(&ff);
+    if (ferror(rfp) || fclose(rfp))
+      die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno));
+  }
+  if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
+      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+
+  /* --- Tidy up --- */
+
+  e->ops->decdone(e);
+  if (v.verb && ofp != stdout)
+    printf("OK verified successfully\n");
+  freeenc(e);
+  key_close(&kf);
+  sig_destroy(&s);
+  dstr_destroy(&d);
+  dstr_destroy(&dd);
+  return (0);
+}
+
+/*----- Reformatting ------------------------------------------------------*/
+
+static int format(int argc, char *argv[])
+{
+  const char *ief = "binary", *oef = "binary";
+  const char *fn, *dfn = 0, *of = 0, *mf = 0;
+  sigmsg s;
+  FILE *fp, *ofp = 0, *mfp = 0;
+  int i;
+  size_t n;
+  msgcanon mc_in = MC_INIT, mc_out = MC_INIT;
+  char bb[MSGBUFSZ];
+  vrfctx v = { 0, 0, 1 };
+  unsigned f = 0, fm = ~F_SIGMASK, sf;
+  const encops *ieo, *oeo;
+  enc *ie, *oe;
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "armour-in",   0,              0,      'a' },
+      { "armor-in",    0,              0,      'a' },
+      { "armour-out",  0,              0,      'A' },
+      { "armor-out",   0,              0,      'A' },
+      { "detach",      0,              0,      'D' },
+      { "embed",       0,              0,      'E' },
+      { "format-in",   OPTF_ARGREQ,    0,      'f' },
+      { "format-out",  OPTF_ARGREQ,    0,      'F' },
+      { "message",     OPTF_ARGREQ,    0,      'm' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "progress",    0,              0,      'p' },
+      { 0,             0,              0,      0 }
+    };
+    i = mdwopt(argc, argv, "f:F:m:o:apADE", opt, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'a': ief = "pem"; break;
+      case 'A': oef = "pem"; break;
+      case 'f': ief = optarg; break;
+      case 'F': oef = optarg; break;
+      case 'D': f |= F_DETACH; fm |= F_DETACH; break;
+      case 'E': f &= ~F_DETACH; fm |= F_DETACH; break;
+      case 'm': mf = optarg; break;
+      case 'o': of = optarg; break;
+      case 'p': f |= F_PROGRESS; break;
+      default: f |= F_BOGUS; break;
+    }
+  }
+
+  if (argc - optind > 2 || (f & F_BOGUS))
+    die(EXIT_FAILURE, "Usage: format [-OPTIONS] [FILE [MESSAGE]]");
+
+  if ((ieo = getenc(ief)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", ief);
+  if ((oeo = getenc(oef)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", oef);
+
+  fn = optind < argc ? argv[optind++] : "-";
+  if (strcmp(fn, "-") == 0)
+    fp = stdin;
+  else if ((fp = fopen(fn, ieo->rmode)) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s': %s",
+       fn, strerror(errno));
+  }
+
+  if (optind < argc)
+    dfn = argv[optind++];
+
+  ie = initdec(ieo, fp, vrfbdry, &v);
+
+  /* --- Read the header chunk --- */
+
+  sig_readheader(ie, &s, diechoke, "malformed header");
+
+  if (((s.f ^ v.f) & v.m) != 0)
+    moan("boundary string inconsistent with contents (ignoring)");
+
+  mcsetup_read(&mc_in, s.f, &ie, fn, dfn);
+
+  /* --- Prepare the output stuff --- */
+
+  if (!of && !mf) of = "-";
+  sf = s.f;
+  f = (f & fm) | (s.f & ~fm);
+  s.f = f & F_SIGMASK;
+
+  if (sf & F_DETACH)
+    sig_readsig(ie, &s);
+
+  if (!of)
+    mcsetup_writenull(&mc_out);
+  else {
+    if (strcmp(of, "-") == 0)
+      ofp = stdout;
+    else if ((ofp = fopen(of, oeo->wmode)) == 0) {
+      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+         of, strerror(errno));
+    }
+    oe = initenc(oeo, ofp,
+                (f & F_DETACH) ? "CATSIGN SIGNATURE" :
+                (f & F_BINARY) ? "CATSIGN MESSAGE" :
+                "CATSIGN MESSAGE HEADER");
+    sig_writeheader(oe, &s);
+    mcsetup_write(&mc_out, f, &oe);
+  }
+
+  if (mf) {
+    if (strcmp(mf, "-") == 0)
+      mfp = stdout;
+    else if ((mfp = fopen(mf, (f & F_BINARY) ? "wb" : "w")) == 0) {
+      die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+         mf, strerror(errno));
+    }
+  }
+
+  /* --- Wade through the message body --- */
+
+  for (;;) {
+    n = mc_in.read(&mc_in, bb);
+    if (!n) break;
+    mc_out.write(&mc_out, bb, n);
+    if (mfp) fwrite(bb, 1, n, mfp);
+  }
+  mc_endread(&mc_in, ieo, &ie);
+  if (of) mc_endwrite(&mc_out, oeo, &oe);
+
+  /* --- Write the signature --- */
+
+  if (!(sf & F_DETACH))
+    sig_readsig(ie, &s);
+  if (of) {
+    sig_writesig(oe, &s);
+    oe->ops->encdone(oe);
+  }
+
+  /* --- All done --- */
+
+  ie->ops->decdone(ie);
+  if (ferror(fp) || fclose(fp))
+    die(EXIT_FAILURE, "error reading input signature: %s", strerror(errno));
+  if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
+    die(EXIT_FAILURE, "error writing output signature: %s", strerror(errno));
+  if (mfp && (fflush(mfp) || ferror(mfp) || fclose(mfp)))
+    die(EXIT_FAILURE, "error writing output message: %s", strerror(errno));
+  freeenc(ie);
+  if (of) freeenc(oe);
+  sig_destroy(&s);
+  return (0);
+}
+
+static void infochoke(const char *m, void *p)
+{
+  vrfctx *v = p;
+  printf("BAD %s: %s\n", v->what, m);
+  exit(EXIT_FAILURE);
+}
+
+static void infokeyreport(const char *file, int line,
+                         const char *err, void *p)
+{ /*whatever*/; }
+
+static int info(int argc, char *argv[])
+{
+  const char *ef = "binary";
+  vrfctx v = { 0, 0, 1 };
+  key_file kf;
+  key *k;
+  sigmsg s;
+  FILE *fp;
+  int i;
+  struct tm *tm;
+  char bb[256];
+  dstr d = DSTR_INIT;
+  const encops *eo;
+  enc *e;
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "armour",      0,              0,      'a' },
+      { "armor",       0,              0,      'a' },
+      { "format",      OPTF_ARGREQ,    0,      'f' },
+      { "gmt",         0,              0,      'u' },
+      { "utc",         0,              0,      'u' },
+      { 0,             0,              0,      0 }
+    };
+    i = mdwopt(argc, argv, "f:au", opt, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'a': ef = "pem"; break;
+      case 'f': ef = optarg; break;
+      case 'u': v.f |= F_UTC; break;
+      default: v.f |= F_BOGUS; break;
+    }
+  }
+  if (argc - optind > 1 || (v.f & F_BOGUS))
+    die(EXIT_FAILURE, "Usage: info [-OPTIONS] [FILE]");
+
+  if ((eo = getenc(ef)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+  if (optind >= argc)
+    fp = stdin;
+  else if (strcmp(argv[optind], "-") == 0) {
+    fp = stdin;
+    optind++;
+  } else if ((fp = fopen(argv[optind], eo->rmode)) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s': %s",
+       argv[optind], strerror(errno));
+  } else
+    optind++;
+
+  if (key_open(&kf, keyring, KOPEN_READ, infokeyreport, 0)) {
+    printf("NOTE can't open keyring `%s'\n", keyring);
+    keyring = 0;
+  }
+  e = initdec(eo, fp, vrfbdry, &v);
+
+  v.what = "malformed header";
+  sig_readheader(e, &s, infochoke, &v);
+
+  printf("INFO flags %sdetach %sbinary\n",
+        (s.f & F_DETACH) ? "" : "!",
+        (s.f & F_BINARY) ? "" : "!");
+
+  if (((s.f ^ v.f) & v.m) != 0) {
+    printf("WARN boundary string inconsistent with contents\n");
+    printf("INFO expected-flags");
+    if (v.m & F_DETACH) printf(" %sdetach", (v.f & F_DETACH) ? "" : "!");
+    if (v.m & F_BINARY) printf(" %sbinary", (v.f & F_BINARY) ? "" : "!");
+    putchar('\n');
+  }
+  v.f |= s.f;
+
+  tm = (v.f & F_UTC) ? gmtime(&s.t) : localtime(&s.t);
+  strftime(bb, sizeof(bb), "%Y-%m-%d %H:%M:%S %Z", tm);
+  printf("INFO date %s\n", bb);
+
+  if (keyring && (k = key_byid(&kf, s.keyid)) != 0) {
+    dstr_reset(&d); key_fulltag(k, &d);
+    printf("INFO key %s\n", d.buf);
+  } else
+    printf("INFO unknown-key %08lx\n", (unsigned long)s.keyid);
+
+  if (keyring) key_close(&kf);
+  dstr_destroy(&d);
+  sig_destroy(&s);
+  return (0);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+#define LISTS(LI)                                                      \
+  LI("Lists", list,                                                    \
+     listtab[i].name, listtab[i].name)                                 \
+  LI("Signature schemes", sig,                                         \
+     sigtab[i].name, sigtab[i].name)                                   \
+  LI("Encodings", enc,                                                 \
+     enctab[i].name, enctab[i].name)                                   \
+  LI("Hash functions", hash,                                           \
+     ghashtab[i], ghashtab[i]->name)
+
+MAKELISTTAB(listtab, LISTS)
+
+int cmd_show(int argc, char *argv[])
+{
+  return (displaylists(listtab, argv + 1));
+}
+
+static int cmd_help(int, char **);
+
+static cmd cmdtab[] = {
+  { "help", cmd_help, "help [COMMAND...]" },
+  { "show", cmd_show, "show [ITEM...]" },
+  CMD_ENCODE,
+  CMD_DECODE,
+  { "sign", sign,
+    "sign [-adptC] [-k TAG] [-f FORMAT] [-o OUTPUT] [FILE]", "\
+Options:\n\
+\n\
+-a, --armour           Same as `-f pem'.\n\
+-b, --binary           Treat the input message as binary data.\n\
+-d, --detach           Produce a detached signature.\n\
+-f, --format=FORMAT    Encode as FORMAT.\n\
+-k, --key=TAG          Use public encryption key named by TAG.\n\
+-o, --output=FILE      Write output to FILE.\n\
+-p, --progress         Show progress on large files.\n\
+-t, --text             Canonify input message as a text file.\n\
+-C, --nocheck          Don't check the private key.\n\
+" },
+  { "verify", verify,
+    "verify [-abpquvC] [-f FORMAT] [-k TAG] [-o OUTPUT]\n\t\
+[FILE [MESSAGE]]", "\
+Options:\n\
+\n\
+-a, --armour           Same as `-f pem'.\n\
+-b, --buffer           Buffer message until signature is verified.\n\
+-f, --format=FORMAT    Decode as FORMAT.\n\
+-k, --key=TAG          Require that the message be signed by key TAG.\n\
+-o, --output=FILE      Write message to FILE.\n\
+-p, --progress         Show progress on large files.\n\
+-q, --quiet            Produce fewer messages.\n\
+-t, --freshtime=TIME   Only accept signatures made after this time.\n\
+-u, --utc              Show dates in UTC rather than local time.\n\
+-v, --verbose          Produce more verbose messages.\n\
+-C, --nocheck          Don't check the public key.\n\
+" },
+  { "info", info,
+    "info [-au] [-f FORMAT] [FILE]", "\
+Options:\n\
+\n\
+-a, --armour           Same as `-f pem'.\n\
+-f, --format=FORMAT    Decode as FORMAT.\n\
+-u, --utc              Show dates in UTC rather than local time.\n\
+"},
+  { "format", format,
+    "format [-apuADE] [-f FORMAT] [-F format] [-m FILE] [-o FILE]\n\t\
+[FILE [MESSAGE]]", "\
+Options:\n\
+\n\
+-a, --armour-in                Same as `-f pem'.\n\
+-A, --armour-out       Same as `-F pem'.\n\
+-D, --detach           Create detached signature.\n\
+-E, --embed            Create signature with embedded message.\n\
+-f, --format-in=FORMAT Decode input as FORMAT.\n\
+-F, --format-out=FORMAT        Encode output as FORMAT.\n\
+-m, --message=FILE     Write message to FILE.\n\
+-o, --output=FILE      Write new signature to FILE.\n\
+-p, --progress         Show progress on large files.\n\
+"},
+  { 0, 0, 0 }
+}; /* " Emacs seems confused. */
+
+static int cmd_help(int argc, char **argv)
+{
+  sc_help(cmdtab, stdout, argv + 1);
+  return (0);
+}
+
+void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n");
+}
+
+void help_global(FILE *fp)
+{
+  usage(fp);
+  fputs("\n\
+Sign and verify data.\n\
+\n\
+Global command-line options:\n\
+\n\
+-h, --help [COMMAND...]        Show this help message, or help for COMMANDs.\n\
+-v, --version          Show program version number.\n\
+-u, --usage            Show a terse usage message.\n\
+\n\
+-k, --keyring=FILE     Read keys from FILE.\n",
+       fp);
+}
+
+/* --- @main@ --- *
+ *
+ * Arguments:  @int argc@ = number of command line arguments
+ *             @char *argv[]@ = vector of command line arguments
+ *
+ * Returns:    Zero if successful, nonzero otherwise.
+ *
+ * Use:                Encrypts or decrypts files.
+ */
+
+int main(int argc, char *argv[])
+{
+  unsigned f = 0;
+
+#define f_bogus 1u
+
+  /* --- Initialize the library --- */
+
+  ego(argv[0]);
+  sub_init();
+  rand_noisesrc(RAND_GLOBAL, &noise_source);
+  rand_seed(RAND_GLOBAL, 160);
+/*   trace_on(stderr, 1); */
+
+  /* --- Parse options --- */
+
+  for (;;) {
+    static struct option opts[] = {
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'v' },
+      { "usage",       0,              0,      'u' },
+      { "keyring",     OPTF_ARGREQ,    0,      'k' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'h':
+       sc_help(cmdtab, stdout, argv + optind);
+       exit(0);
+       break;
+      case 'v':
+       version(stdout);
+       exit(0);
+       break;
+      case 'u':
+       usage(stdout);
+       exit(0);
+      case 'k':
+       keyring = optarg;
+       break;
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+  optind = 0;
+  if (f & f_bogus || argc < 1) {
+    usage(stderr);
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Dispatch to the correct subcommand handler --- */
+
+  return (findcmd(cmdtab, argv[0])->cmd(argc, argv));
+
+#undef f_bogus
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/progs/cc-enc.c b/progs/cc-enc.c
new file mode 100644 (file)
index 0000000..61d9805
--- /dev/null
@@ -0,0 +1,528 @@
+/* -*-c-*-
+ *
+ * Catcrypt data encoding
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <mLib/alloc.h>
+#include <mLib/base64.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include "cc.h"
+
+typedef int encbdryp(const char *, void *);
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Binary --- */
+
+static enc *bin_encinit(FILE *fp, const char *msg)
+  { enc *e = CREATE(enc); return (e); }
+static enc *bin_decinit(FILE *fp, encbdryp *func, void *p)
+  { enc *e = CREATE(enc); return (e); }
+
+static int bin_read(enc *e, void *p, size_t sz)
+{
+  size_t n;
+
+  if (!sz) return (0);
+  n = fread(p, 1, sz, e->fp);
+  if (!n || ferror(e->fp)) return (-1);
+  return (n);
+}
+
+static int bin_write(enc *e, const void *p, size_t sz)
+  { if (sz && fwrite(p, 1, sz, e->fp) < sz) return (-1); return (0); }
+
+static int bin_done(enc *e) { return (0); }
+
+static void bin_destroy(enc *e) { DESTROY(e); }
+
+/* --- PEM --- */
+
+typedef struct pem_encctx {
+  enc e;
+  char *msg;
+  unsigned f;
+  base64_ctx b;
+  dstr d;
+  size_t n;
+#define PEMF_NL 1u
+#define PEMF_EOF 2u
+} pem_encctx;
+
+static enc *pem_encinit(FILE *fp, const char *msg)
+{
+  pem_encctx *pe = CREATE(pem_encctx);
+  base64_init(&pe->b);
+  fprintf(fp, "-----BEGIN %s-----\n", msg);
+  pe->msg = xstrdup(msg);
+  dstr_create(&pe->d);
+  pe->n = 0;
+  pe->f = 0;
+  return (&pe->e);
+}
+
+int checkbdry(const char *b, void *p) { return (!p || strcmp(b, p) == 0); }
+
+static enc *pem_decinit(FILE *fp, encbdryp *func, void *p)
+{
+  char buf[128];
+  int i, d;
+  pem_encctx *pe;
+  int ch;
+
+  /* --- Go until I find a newline and `-----' --- */
+
+top:
+  d = 0;
+  for (;;) {
+    if ((ch = getc(fp)) == EOF) goto fail;
+    switch (ch) {
+      case '\n': d = 0; break;
+      case '-': if (d >= 0) { d++; if (d == 5) goto banner; }; break;
+      default: d = -1; break;
+    }
+  }
+
+  /* --- See what the banner looks like --- */
+
+banner:
+  i = d = 0;
+  for (;;) {
+    if ((ch = getc(fp)) == EOF) goto fail;
+    if (ch == '-') { d++; continue; }
+    if (ch == '\n') break;
+    if (i + d + 1 >= sizeof(buf)) goto top;
+    while (d) { buf[i++] = '-'; d--; }
+    buf[i++] = ch;
+  }
+  buf[i] = 0;
+
+  /* --- Check we have the right framing --- */
+
+  if (d != 5) goto top;
+  if (strncmp(buf, "BEGIN ", 6) != 0 || (func && !func(buf + 6, p)))
+    goto top;
+
+  /* --- Ready --- */
+
+  pe = CREATE(pem_encctx);
+  base64_init(&pe->b);
+  pe->msg = xstrdup(buf + 6);
+  dstr_create(&pe->d);
+  pe->n = 0;
+  pe->f = PEMF_NL;
+  return (&pe->e);
+
+  /* --- Failed --- */
+
+fail:
+  die(EXIT_FAILURE, "initial encapsulation boundary not found");
+  return (0);
+}
+
+#define PEM_CHUNKSZ 4096
+
+static int pem_read(enc *e, void *p, size_t sz)
+{
+  pem_encctx *pe = (pem_encctx *)e;
+  char buf[PEM_CHUNKSZ];
+  char *pp = p;
+  int ch;
+  size_t n;
+  int rc = 0;
+
+  for (;;) {
+    n = pe->d.len - pe->n;
+    if (n > sz) n = sz;
+    memcpy(pp, pe->d.buf + pe->n, n);
+    pe->n += n;
+    pp += n;
+    rc += n;
+    sz -= n;
+    if (!sz) break;
+    if (pe->f & PEMF_EOF) return (rc ? rc : -1);
+    dstr_reset(&pe->d);
+    n = 0;
+    for (;;) {
+      if ((ch = getc(pe->e.fp)) == EOF) return (-1);
+      if ((pe->f & PEMF_NL) && ch == '-') {
+       ungetc(ch, pe->e.fp);
+       pe->f |= PEMF_EOF;
+       break;
+      }
+      if (ch == '\n') { pe->f |= PEMF_NL; continue; }
+      pe->f &= ~PEMF_NL;
+      buf[n++] = ch;
+      if (n >= PEM_CHUNKSZ) break;
+    }
+    if (n)
+      base64_decode(&pe->b, buf, n, &pe->d);
+    if (pe->f & PEMF_EOF)
+      base64_decode(&pe->b, 0, 0, &pe->d);
+    pe->n = 0;
+  }
+  return (rc);
+}
+
+static int pem_write(enc *e, const void *p, size_t sz)
+{
+  pem_encctx *pe = (pem_encctx *)e;
+  const char *pp = p;
+  size_t n;
+
+  while (sz) {
+    n = PEM_CHUNKSZ;
+    if (n > sz) n = sz;
+    dstr_reset(&pe->d);
+    base64_encode(&pe->b, pp, n, &pe->d);
+    if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len)
+      return (-1);
+    pp += n;
+    sz -= n;
+  }
+  return (0);
+}
+
+static int pem_encdone(enc *e)
+{
+  pem_encctx *pe = (pem_encctx *)e;
+  dstr_reset(&pe->d);
+  base64_encode(&pe->b, 0, 0, &pe->d);
+  if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len)
+    return (-1);
+  if (pe->b.lnlen) fputc('\n', pe->e.fp);
+  fprintf(pe->e.fp, "-----END %s-----\n", pe->msg);
+  return (0);
+}
+
+static int pem_decdone(enc *e)
+{
+  pem_encctx *pe = (pem_encctx *)e;
+  char buf[128];
+  int i, d;
+  int ch;
+
+  for (d = 0; d < 5; d++)
+    if ((ch = getc(pe->e.fp)) != '-') goto fail;
+  i = d = 0;
+  for (;;) {
+    if ((ch = getc(pe->e.fp)) == EOF) goto fail;
+    if (ch == '-') { d++; continue; }
+    if (ch == '\n') break;
+    if (i + d + 1 >= sizeof(buf)) goto fail;
+    while (d) { buf[i++] = '-'; d--; }
+    buf[i++] = ch;
+  }
+  if (d != 5) goto fail;
+  buf[i] = 0;
+  if (strncmp(buf, "END ", 4) != 0 || strcmp(buf + 4, pe->msg) != 0)
+    goto fail;
+  return (0);
+
+fail:
+  die(EXIT_FAILURE, "final encapsulation boundary not found");
+  return (-1);
+}
+
+static void pem_destroy(enc *e)
+{
+  pem_encctx *pe = (pem_encctx *)e;
+  dstr_destroy(&pe->d);
+  xfree(pe->msg);
+  DESTROY(pe);
+}
+
+/* --- Encoder table --- */
+
+const encops enctab[] = {
+  { "binary", "rb", "wb", 1, 1,
+    bin_encinit, bin_decinit,
+    bin_read, bin_write,
+    bin_done, bin_done,
+    bin_destroy },
+  { "pem", "r", "w", 3, 4,
+    pem_encinit, pem_decinit,
+    pem_read, pem_write,
+    pem_encdone, pem_decdone,
+    pem_destroy },
+  { 0 }
+};
+
+/* --- @getenc@ --- *
+ *
+ * Arguments:  @const char *enc@ = name of wanted encoding
+ *
+ * Returns:    Pointer to encoder operations.
+ *
+ * Use:                Finds a named encoder or decoder.
+ */
+
+const encops *getenc(const char *enc)
+{
+  const encops *eo;
+
+  for (eo = enctab; eo->name; eo++) {
+    if (strcmp(eo->name, enc) == 0)
+      goto e_found;
+  }
+  die(EXIT_FAILURE, "couldn't find encoding `%s'", enc);
+e_found:
+  return (eo);
+}
+
+/* --- @initenc@ --- *
+ *
+ * Arguments:  @const encops *eo@ = operations (from @getenc@)
+ *             @FILE *fp@ = file handle to attach
+ *             @const char *msg@ = banner message
+ *
+ * Returns:    The encoder object.
+ *
+ * Use:                Initializes an encoder.
+ */
+
+enc *initenc(const encops *eo, FILE *fp, const char *msg)
+{
+  enc *e = eo->initenc(fp, msg);
+  e->ops = eo;
+  e->fp = fp;
+  return (e);
+}
+
+/* --- @initdec@ --- *
+ *
+ * Arguments:  @const encops *eo@ = operations (from @getenc@)
+ *             @FILE *fp@ = file handle to attach
+ *             @int (*func)(const char *, void *)@ = banner check function
+ *             @void *p@ = argument for @func@
+ *
+ * Returns:    The encoder object.
+ *
+ * Use:                Initializes an encoder.
+ */
+
+enc *initdec(const encops *eo, FILE *fp,
+            int (*func)(const char *, void *), void *p)
+{
+  enc *e = eo->initdec(fp, func, p);
+  e->ops = eo;
+  e->fp = fp;
+  return (e);
+}
+
+/* --- @freeenc@ --- *
+ *
+ * Arguments:  @enc *e@ = encoder object
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an encoder object.
+ */
+
+void freeenc(enc *e) { e->ops->destroy(e); }
+
+/*----- Encoding and decoding commands ------------------------------------*/
+
+int cmd_encode(int argc, char *argv[])
+{
+  const char *fn, *of = 0;
+  FILE *ofp = 0;
+  FILE *fp = 0;
+  const char *ef = "binary";
+  const char *bd = "MESSAGE";
+  fprogress ff;
+  int i;
+  size_t n;
+  char buf[4096];
+  unsigned f = 0;
+  const encops *eo;
+  enc *e;
+
+#define f_bogus 1u
+#define f_progress 2u
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "format",      OPTF_ARGREQ,    0,      'f' },
+      { "boundary",    OPTF_ARGREQ,    0,      'b' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "progress",    0,              0,      'p' },
+      { 0,             0,              0,      0 }
+    };
+    i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'f': ef = optarg; break;
+      case 'b': bd = optarg; break;
+      case 'o': of = optarg; break;
+      case 'p': f |= f_progress; break;
+      default: f |= f_bogus; break;
+    }
+  }
+  if (argc - optind > 1 || (f & f_bogus))
+    die(EXIT_FAILURE, "Usage: encode [-OPTIONS] [FILE]");
+
+  if ((eo = getenc(ef)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+  fn = optind < argc ? argv[optind++] : "-";
+  if (strcmp(fn, "-") == 0)
+    fp = stdin;
+  else if ((fp = fopen(fn, "rb")) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s': %s",
+       fn, strerror(errno));
+  }
+
+  if (!of || strcmp(of, "-") == 0)
+    ofp = stdout;
+  else if ((ofp = fopen(of, eo->wmode)) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+       ofp, strerror(errno));
+  }
+
+  e = initenc(eo, ofp, bd);
+
+  if (f & f_progress) {
+    if (fprogress_init(&ff, fn, fp)) {
+      die(EXIT_FAILURE, "failed to initialize progress display: %s",
+         strerror(errno));
+    }
+  }
+
+  do {
+    n = fread(buf, 1, sizeof(buf), fp);
+    if (f & f_progress) fprogress_update(&ff, n);
+    if (e->ops->write(e, buf, n)) {
+      if (f & f_progress) fprogress_done(&ff);
+      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+    }
+  } while (n == sizeof(buf));
+  if (f & f_progress) fprogress_done(&ff);
+  e->ops->encdone(e);
+  freeenc(e);
+  return (0);
+
+#undef f_bogus
+#undef f_progress
+}
+
+int cmd_decode(int argc, char *argv[])
+{
+  const char *fn, *of = 0;
+  FILE *ofp = 0;
+  FILE *fp = 0;
+  const char *ef = "binary";
+  const char *bd = 0;
+  fprogress ff;
+  int i;
+  char buf[4096];
+  unsigned f = 0;
+  const encops *eo;
+  enc *e;
+
+#define f_bogus 1u
+#define f_progress 2u
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "format",      OPTF_ARGREQ,    0,      'f' },
+      { "boundary",    OPTF_ARGREQ,    0,      'b' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "progress",    0,              0,      'p' },
+      { 0,             0,              0,      0 }
+    };
+    i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'f': ef = optarg; break;
+      case 'b': bd = optarg; break;
+      case 'o': of = optarg; break;
+      case 'p': f |= f_progress; break;
+      default: f |= f_bogus; break;
+    }
+  }
+  if (argc - optind > 1 || (f & f_bogus))
+    die(EXIT_FAILURE, "Usage: decode [-OPTIONS] [FILE]");
+
+  if ((eo = getenc(ef)) == 0)
+    die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+  fn = optind < argc ? argv[optind++] : "-";
+  if (strcmp(fn, "-") == 0)
+    fp = stdin;
+  else if ((fp = fopen(fn, eo->rmode)) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s': %s",
+       fn, strerror(errno));
+  }
+
+  if (!of || strcmp(of, "-") == 0)
+    ofp = stdout;
+  else if ((ofp = fopen(of, "wb")) == 0) {
+    die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+       ofp, strerror(errno));
+  }
+
+  e = initdec(eo, fp, checkbdry, (/*unconst*/ void *)bd);
+
+  if (f & f_progress) {
+    if (fprogress_init(&ff, fn, fp)) {
+      die(EXIT_FAILURE, "failed to initialize progress display: %s",
+         strerror(errno));
+    }
+  }
+
+  do {
+    if ((i = e->ops->read(e, buf, sizeof(buf))) < 0) {
+      if (f & f_progress) fprogress_done(&ff);
+      die(EXIT_FAILURE, "error reading input: %s", strerror(errno));
+    }
+    if (f & f_progress)
+      fprogress_update(&ff, i*e->ops->ncook/e->ops->nraw);
+    if (fwrite(buf, 1, i, ofp) < i) {
+      if (f & f_progress) fprogress_done(&ff);
+      die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+    }
+  } while (i == sizeof(buf));
+  e->ops->decdone(e);
+  if (f & f_progress) fprogress_done(&ff);
+  freeenc(e);
+  return (0);
+
+#undef f_bogus
+#undef f_progress
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from cc-hash.c
rename to progs/cc-hash.c
diff --git a/progs/cc-kem.c b/progs/cc-kem.c
new file mode 100644 (file)
index 0000000..e165389
--- /dev/null
@@ -0,0 +1,627 @@
+/* -*-c-*-
+ *
+ * Catcrypt key-encapsulation
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include <stdlib.h>
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include "mprand.h"
+#include "rand.h"
+
+#include "ec.h"
+#include "ec-keys.h"
+#include "dh.h"
+#include "rsa.h"
+
+#include "rmd160.h"
+#include "blowfish-cbc.h"
+
+#include "cc.h"
+
+/*----- Key encapsulation -------------------------------------------------*/
+
+/* --- RSA --- */
+
+typedef struct rsa_encctx {
+  kem k;
+  rsa_pubctx rp;
+} rsa_encctx;
+
+static kem *rsa_encinit(key *k, void *kd)
+{
+  rsa_encctx *re = CREATE(rsa_encctx);
+  rsa_pubcreate(&re->rp, kd);
+  return (&re->k);
+}
+
+static int rsa_encdoit(kem *k, dstr *d, ghash *h)
+{
+  rsa_encctx *re = (rsa_encctx *)k;
+  mp *x = mprand_range(MP_NEW, re->rp.rp->n, &rand_global, 0);
+  mp *y = rsa_pubop(&re->rp, MP_NEW, x);
+  size_t n = mp_octets(re->rp.rp->n);
+  dstr_ensure(d, n);
+  mp_storeb(x, d->buf, n);
+  GH_HASH(h, d->buf, n);
+  mp_storeb(y, d->buf, n);
+  d->len += n;
+  mp_drop(x);
+  mp_drop(y);
+  return (0);
+}
+
+static const char *rsa_lengthcheck(mp *n)
+{
+  if (mp_bits(n) < 1020) return ("key too short");
+  return (0);
+}
+
+static const char *rsa_enccheck(kem *k)
+{
+  rsa_encctx *re = (rsa_encctx *)k;
+  const char *e;
+  if ((e = rsa_lengthcheck(re->rp.rp->n)) != 0) return (e);
+  return (0);
+}
+
+static void rsa_encdestroy(kem *k)
+{
+  rsa_encctx *re = (rsa_encctx *)k;
+  rsa_pubdestroy(&re->rp);
+  DESTROY(re);
+}
+
+static const kemops rsa_encops = {
+  rsa_pubfetch, sizeof(rsa_pub),
+  rsa_encinit, rsa_encdoit, rsa_enccheck, rsa_encdestroy
+};
+
+typedef struct rsa_decctx {
+  kem k;
+  rsa_privctx rp;
+} rsa_decctx;
+
+static kem *rsa_decinit(key *k, void *kd)
+{
+  rsa_decctx *rd = CREATE(rsa_decctx);
+  rsa_privcreate(&rd->rp, kd, &rand_global);
+  return (&rd->k);
+}
+
+static int rsa_decdoit(kem *k, dstr *d, ghash *h)
+{
+  rsa_decctx *rd = (rsa_decctx *)k;
+  mp *x = mp_loadb(MP_NEW, d->buf, d->len);
+  size_t n;
+  char *p;
+
+  if (MP_CMP(x, >=, rd->rp.rp->n)) {
+    mp_drop(x);
+    return (-1);
+  }
+  n = mp_octets(rd->rp.rp->n);
+  p = xmalloc(n);
+  x = rsa_privop(&rd->rp, x, x);
+  mp_storeb(x, p, n);
+  GH_HASH(h, p, n);
+  mp_drop(x);
+  xfree(p);
+  return (0);
+}
+
+static const char *rsa_deccheck(kem *k)
+{
+  rsa_decctx *rd = (rsa_decctx *)k;
+  const char *e;
+  if ((e = rsa_lengthcheck(rd->rp.rp->n)) != 0) return (e);
+  return (0);
+}
+
+static void rsa_decdestroy(kem *k)
+{
+  rsa_decctx *rd = (rsa_decctx *)k;
+  rsa_privdestroy(&rd->rp);
+  DESTROY(rd);
+}
+
+static const kemops rsa_decops = {
+  rsa_privfetch, sizeof(rsa_priv),
+  rsa_decinit, rsa_decdoit, rsa_deccheck, rsa_decdestroy
+};
+
+/* --- DH and EC --- */
+
+typedef struct dh_encctx {
+  kem k;
+  group *g;
+  mp *x;
+  ge *y;
+} dh_encctx;
+
+static dh_encctx *dh_doinit(key *k, const gprime_param *gp, mp *y,
+                           group *(*makegroup)(const gprime_param *),
+                           const char *what)
+{
+  dh_encctx *de = CREATE(dh_encctx);
+  dstr t = DSTR_INIT;
+
+  key_fulltag(k, &t);
+  if ((de->g = makegroup(gp)) == 0)
+    die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf);
+  de->x = MP_NEW;
+  de->y = G_CREATE(de->g);
+  if (G_FROMINT(de->g, de->y, y))
+    die(EXIT_FAILURE, "bad public key `%s'", t.buf);
+  dstr_destroy(&t);
+  return (de);
+}
+
+static dh_encctx *ec_doinit(key *k, const char *cstr, const ec *y)
+{
+  dh_encctx *de = CREATE(dh_encctx);
+  ec_info ei;
+  const char *e;
+  dstr t = DSTR_INIT;
+
+  key_fulltag(k, &t);
+  if ((e = ec_getinfo(&ei, cstr)) != 0 ||
+      (de->g = group_ec(&ei)) == 0)
+    die(EXIT_FAILURE, "bad elliptic curve spec in key `%s': %s", t.buf, e);
+  de->x = MP_NEW;
+  de->y = G_CREATE(de->g);
+  if (G_FROMEC(de->g, de->y, y))
+    die(EXIT_FAILURE, "bad public curve point `%s'", t.buf);
+  dstr_destroy(&t);
+  return (de);
+}
+
+static kem *dh_encinit(key *k, void *kd)
+{
+  dh_pub *dp = kd;
+  dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime");
+  return (&de->k);
+}
+
+static kem *bindh_encinit(key *k, void *kd)
+{
+  dh_pub *dp = kd;
+  dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary");
+  return (&de->k);
+}
+
+static kem *ec_encinit(key *k, void *kd)
+{
+  ec_pub *ep = kd;
+  dh_encctx *de = ec_doinit(k, ep->cstr, &ep->p);
+  return (&de->k);
+}
+
+static int dh_encdoit(kem *k, dstr *d, ghash *h)
+{
+  dh_encctx *de = (dh_encctx *)k;
+  mp *r = mprand_range(MP_NEW, de->g->r, &rand_global, 0);
+  ge *x = G_CREATE(de->g);
+  ge *y = G_CREATE(de->g);
+  size_t n = de->g->noctets;
+  buf b;
+
+  G_EXP(de->g, x, de->g->g, r);
+  G_EXP(de->g, y, de->y, r);
+  dstr_ensure(d, n);
+  buf_init(&b, d->buf, n);
+  G_TORAW(de->g, &b, y);
+  GH_HASH(h, BBASE(&b), BLEN(&b));
+  buf_init(&b, d->buf, n);
+  G_TORAW(de->g, &b, x);
+  GH_HASH(h, BBASE(&b), BLEN(&b));
+  d->len += BLEN(&b);
+  mp_drop(r);
+  G_DESTROY(de->g, x);
+  G_DESTROY(de->g, y);
+  return (0);
+}
+
+static const char *dh_enccheck(kem *k)
+{
+  dh_encctx *de = (dh_encctx *)k;
+  const char *e;
+  if ((e = G_CHECK(de->g, &rand_global)) != 0)
+    return (0);
+  if (group_check(de->g, de->y))
+    return ("public key not in subgroup");
+  return (0);
+}
+
+static void dh_encdestroy(kem *k)
+{
+  dh_encctx *de = (dh_encctx *)k;
+  G_DESTROY(de->g, de->y);
+  mp_drop(de->x);
+  G_DESTROYGROUP(de->g);
+  DESTROY(de);
+}
+
+static const kemops dh_encops = {
+  dh_pubfetch, sizeof(dh_pub),
+  dh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy
+};
+
+static const kemops bindh_encops = {
+  dh_pubfetch, sizeof(dh_pub),
+  bindh_encinit, dh_encdoit, dh_enccheck, dh_encdestroy
+};
+
+static const kemops ec_encops = {
+  ec_pubfetch, sizeof(ec_pub),
+  ec_encinit, dh_encdoit, dh_enccheck, dh_encdestroy
+};
+
+static kem *dh_decinit(key *k, void *kd)
+{
+  dh_priv *dp = kd;
+  dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_prime, "prime");
+  de->x = MP_COPY(dp->x);
+  return (&de->k);
+}
+
+static kem *bindh_decinit(key *k, void *kd)
+{
+  dh_priv *dp = kd;
+  dh_encctx *de = dh_doinit(k, &dp->dp, dp->y, group_binary, "binary");
+  de->x = MP_COPY(dp->x);
+  return (&de->k);
+}
+
+static kem *ec_decinit(key *k, void *kd)
+{
+  ec_priv *ep = kd;
+  dh_encctx *de = ec_doinit(k, ep->cstr, &ep->p);
+  de->x = MP_COPY(ep->x);
+  return (&de->k);
+}
+
+static int dh_decdoit(kem *k, dstr *d, ghash *h)
+{
+  dh_encctx *de = (dh_encctx *)k;
+  ge *x = G_CREATE(de->g);
+  size_t n = de->g->noctets;
+  void *p = xmalloc(n);
+  buf b;
+  int rc = -1;
+
+  buf_init(&b, d->buf, d->len);
+  if (G_FROMRAW(de->g, &b, x) || group_check(de->g, x))
+    goto done;
+  G_EXP(de->g, x, x, de->x);
+  buf_init(&b, p, n);
+  G_TORAW(de->g, &b, x);
+  GH_HASH(h, BBASE(&b), BLEN(&b));
+  GH_HASH(h, d->buf, d->len);
+  rc = 0;
+done:
+  G_DESTROY(de->g, x);
+  xfree(p);
+  return (rc);
+}
+
+static const kemops dh_decops = {
+  dh_privfetch, sizeof(dh_priv),
+  dh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy
+};
+
+static const kemops bindh_decops = {
+  dh_privfetch, sizeof(dh_priv),
+  bindh_decinit, dh_decdoit, dh_enccheck, dh_encdestroy
+};
+
+static const kemops ec_decops = {
+  ec_privfetch, sizeof(ec_priv),
+  ec_decinit, dh_decdoit, dh_enccheck, dh_encdestroy
+};
+
+/* --- Symmetric --- */
+
+typedef struct symm_ctx {
+  kem k;
+  key_packdef kp;
+  key_bin kb;
+} symm_ctx;
+
+static kem *symm_init(key *k, void *kd)
+{
+  symm_ctx *s;
+  dstr d = DSTR_INIT;
+  int err;
+
+  s = CREATE(symm_ctx);
+
+  key_fulltag(k, &d);
+  s->kp.e = KENC_BINARY;
+  s->kp.p = &s->kb;
+  s->kp.kd = 0;
+
+  if ((err = key_unpack(&s->kp, kd, &d)) != 0) {
+    die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s",
+       d.buf, key_strerror(err));
+  }
+  dstr_destroy(&d);
+  return (&s->k);
+}
+
+static int symm_decdoit(kem *k, dstr *d, ghash *h)
+{
+  symm_ctx *s = (symm_ctx *)k;
+
+  GH_HASH(h, s->kb.k, s->kb.sz);
+  GH_HASH(h, d->buf, d->len);
+  return (0);
+}
+
+static int symm_encdoit(kem *k, dstr *d, ghash *h)
+{
+  dstr_ensure(d, h->ops->c->hashsz);
+  d->len += h->ops->c->hashsz;
+  rand_get(RAND_GLOBAL, d->buf, d->len);
+  return (symm_decdoit(k, d, h));
+}
+
+static const char *symm_check(kem *k) { return (0); }
+
+static void symm_destroy(kem *k)
+  { symm_ctx *s = (symm_ctx *)k; key_unpackdone(&s->kp); }
+
+static const kemops symm_encops = {
+  0, 0,
+  symm_init, symm_encdoit, symm_check, symm_destroy
+};
+
+static const kemops symm_decops = {
+  0, 0,
+  symm_init, symm_decdoit, symm_check, symm_destroy
+};
+
+/* --- The switch table --- */
+
+const struct kemtab kemtab[] = {
+  { "rsa",     &rsa_encops,    &rsa_decops },
+  { "dh",      &dh_encops,     &dh_decops },
+  { "bindh",   &bindh_encops,  &bindh_decops },
+  { "ec",      &ec_encops,     &ec_decops },
+  { "symm",    &symm_encops,   &symm_decops },
+  { 0,         0,              0 }
+};
+
+/* --- @getkem@ --- *
+ *
+ * Arguments:  @key *k@ = the key to load
+ *             @const char *app@ = application name
+ *             @int wantpriv@ = nonzero if we want to decrypt
+ *
+ * Returns:    A key-encapsulating thing.
+ *
+ * Use:                Loads a key.
+ */
+
+kem *getkem(key *k, const char *app, int wantpriv)
+{
+  const char *kalg, *halg = 0, *calg = 0;
+  dstr d = DSTR_INIT;
+  dstr t = DSTR_INIT;
+  size_t n;
+  char *p = 0;
+  const char *q;
+  kem *kk;
+  const struct kemtab *kt;
+  const kemops *ko;
+  void *kd;
+  int e;
+  key_packdef *kp;
+
+  /* --- Setup stuff --- */
+
+  key_fulltag(k, &t);
+
+  /* --- Get the KEM name --- *
+   *
+   * Take the attribute if it's there; otherwise use the key type.
+   */
+
+  n = strlen(app);
+  if ((q = key_getattr(0, k, "kem")) != 0) {
+    dstr_puts(&d, q);
+    p = d.buf;
+  } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') {
+    dstr_puts(&d, k->type);
+    p = d.buf + n + 1;
+  } else
+    die(EXIT_FAILURE, "no KEM for key `%s'", t.buf);
+  kalg = p;
+
+  /* --- Grab the encryption scheme --- *
+   *
+   * Grab it from the KEM if it's there, but override it from the attribute.
+   */
+
+  if (p && (p = strchr(p, '/')) != 0) {
+    *p++ = 0;
+    calg = p;
+  }
+  if ((q = key_getattr(0, k, "cipher")) != 0)
+    calg = q;
+
+  /* --- Grab the hash function --- */
+
+  if (p && (p = strchr(p, '/')) != 0) {
+    *p++ = 0;
+    halg = p;
+  }
+  if ((q = key_getattr(0, k, "hash")) != 0)
+    halg = q;
+
+  /* --- Instantiate the KEM --- */
+
+  for (kt = kemtab; kt->name; kt++) {
+    if (strcmp(kt->name, kalg) == 0)
+      goto k_found;
+  }
+  die(EXIT_FAILURE, "key encapsulation mechanism `%s' not found in key `%s'",
+      kalg, t.buf);
+k_found:;
+  ko = wantpriv ? kt->decops : kt->encops;
+  if (!ko->kf) {
+    kd = k->k;
+    key_incref(kd);
+    kp = 0;
+  } else {
+    kd = xmalloc(ko->kdsz);
+    kp = key_fetchinit(ko->kf, 0, kd);
+    if ((e = key_fetch(kp, k)) != 0) {
+      die(EXIT_FAILURE, "error fetching key `%s': %s",
+         t.buf, key_strerror(e));
+    }
+  }
+  kk = ko->init(k, kd);
+  kk->kp = kp;
+  kk->ops = ko;
+  kk->kd = kd;
+
+  /* --- Set up the algorithms --- */
+
+  if (!halg)
+    kk->h = &rmd160;
+  else if ((kk->h = ghash_byname(halg)) == 0) {
+    die(EXIT_FAILURE, "hash algorithm `%s' not found in key `%s'",
+       halg, t.buf);
+  }
+
+  if (!calg)
+    kk->c = &blowfish_cbc;
+  else if ((kk->c = gcipher_byname(calg)) == 0) {
+    die(EXIT_FAILURE, "encryption scheme `%s' not found in key `%s'",
+       calg, t.buf);
+  }
+
+  dstr_reset(&d);
+  if ((q = key_getattr(0, k, "kdf")) == 0) {
+    dstr_putf(&d, "%s-mgf", kk->h->name);
+    q = d.buf;
+  }
+  if ((kk->cx = gcipher_byname(q)) == 0) {
+    die(EXIT_FAILURE, "encryption scheme (KDF) `%s' not found in key `%s'",
+       q, t.buf);
+  }
+
+  dstr_reset(&d);
+  if ((q = key_getattr(0, k, "mac")) == 0) {
+    dstr_putf(&d, "%s-hmac", kk->h->name);
+    q = d.buf;
+  }
+  if ((kk->m = gmac_byname(q)) == 0) {
+    die(EXIT_FAILURE,
+       "message authentication code `%s' not found in key `%s'",
+       q, t.buf);
+  }
+
+  /* --- Tidy up --- */
+
+  dstr_destroy(&d);
+  dstr_destroy(&t);
+  return (kk);
+}
+
+/* --- @setupkem@ --- *
+ *
+ * Arguments:  @kem *k@ = key-encapsulation thing
+ *             @dstr *d@ = key-encapsulation data
+ *             @gcipher **cx@ = key-expansion function (for IVs)
+ *             @gcipher **c@ = where to put initialized encryption scheme
+ *             @gmac **m@ = where to put initialized MAC
+ *
+ * Returns:    Zero on success, nonzero on failure.
+ *
+ * Use:                Initializes all the various symmetric things from a KEM.
+ */
+
+int setupkem(kem *k, dstr *d, gcipher **cx, gcipher **c, gmac **m)
+{
+  octet *kd;
+  size_t n, cn, mn;
+  ghash *h;
+  int rc = -1;
+
+  h = GH_INIT(k->h);
+  if (k->ops->doit(k, d, h))
+    goto done;
+  n = keysz(GH_CLASS(h)->hashsz, k->cx->keysz);
+  if (!n)
+    goto done;
+  kd = GH_DONE(h, 0);
+  *cx = GC_INIT(k->cx, kd, n);
+
+  cn = keysz(0, k->c->keysz); n = cn;
+  mn = keysz(0, k->m->keysz); if (mn > n) n = mn;
+  kd = xmalloc(n);
+  GC_ENCRYPT(*cx, 0, kd, cn);
+  *c = GC_INIT(k->c, kd, cn);
+  GC_ENCRYPT(*cx, 0, kd, mn);
+  *m = GM_KEY(k->m, kd, mn);
+  xfree(kd);
+
+  rc = 0;
+done:
+  GH_DESTROY(h);
+  return (rc);
+}
+
+/* --- @freekem@ --- *
+ *
+ * Arguments:  @kem *k@ = key-encapsulation thing
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees up a key-encapsulation thing.
+ */
+
+void freekem(kem *k)
+{
+  if (!k->ops->kf)
+    key_drop(k->kd);
+  else {
+    key_fetchdone(k->kp);
+    xfree(k->kd);
+  }
+  k->ops->destroy(k);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/progs/cc-list.c b/progs/cc-list.c
new file mode 100644 (file)
index 0000000..8bc2219
--- /dev/null
@@ -0,0 +1,73 @@
+/* -*-c-*-
+ *
+ * Emit lists of things in tables
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include <mLib/report.h>
+
+#include "cc.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @displaylists@ --- *
+ *
+ * Arguments:  @const struct listent *listtab@ = table of lists to show
+ *             @char *const argv[]@ = list of lists to show
+ *
+ * Returns:    Nonzero if anything failed.
+ *
+ * Use:                Dumps the named lists, or all of them.
+ */
+
+int displaylists(const struct listent *listtab, char *const argv[])
+{
+  const struct listent *li;
+  int i;
+  int rc = 0;
+
+  if (!argv || !*argv) {
+    for (li = listtab; li->name; li++)
+      li->list();
+  } else {
+    for (i = 0; argv[i]; i++) {
+      for (li = listtab; li->name; li++) {
+       if (strcmp(li->name, argv[i]) == 0) {
+         li->list();
+         goto cool;
+       }
+      }
+      moan("unknown list `%s'", argv[i]);
+      rc = 1;
+    cool:;
+    }
+  }
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from cc-progress.c
rename to progs/cc-progress.c
diff --git a/progs/cc-sig.c b/progs/cc-sig.c
new file mode 100644 (file)
index 0000000..35f1701
--- /dev/null
@@ -0,0 +1,804 @@
+/* -*-c-*-
+ *
+ * Catcrypt signatures
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include <stdlib.h>
+
+#include <mLib/report.h>
+
+#include "rand.h"
+#include "sha.h"
+#include "has160.h"
+
+#include "ec.h"
+#include "ec-keys.h"
+#include "dh.h"
+#include "gdsa.h"
+#include "gkcdsa.h"
+#include "rsa.h"
+
+#include "cc.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- RSA PKCS1 --- */
+
+typedef struct rsap1_sigctx {
+  sig s;
+  rsa_privctx rp;
+  pkcs1 p1;
+} rsap1_sigctx;
+
+static sig *rsap1_siginit(key *k, void *kd, const gchash *hc)
+{
+  rsap1_sigctx *rs = CREATE(rsap1_sigctx);
+  rsa_privcreate(&rs->rp, kd, &rand_global);
+  rs->p1.r = &rand_global;
+  rs->p1.ep = hc->name;
+  rs->p1.epsz = strlen(hc->name) + 1;
+  rs->s.h = 0;
+  return (&rs->s);
+}
+
+static int rsap1_sigdoit(sig *s, dstr *d)
+{
+  rsap1_sigctx *rs = (rsap1_sigctx *)s;
+  size_t n;
+  mp *m = rsa_sign(&rs->rp, MP_NEW,
+                  GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
+                  pkcs1_sigencode, &rs->p1);
+  if (!m) return (-1);
+  n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n);
+  d->len += n; mp_drop(m);
+  return (0);
+}
+
+static const char *rsa_lengthcheck(mp *n)
+{
+  if (mp_bits(n) < 1024) return ("key too short");
+  return (0);
+}
+
+static const char *rsap1_sigcheck(sig *s)
+{
+  rsap1_sigctx *rs = (rsap1_sigctx *)s;
+  const char *e;
+  if ((e = rsa_lengthcheck(rs->rp.rp->n)) != 0) return (e);
+  return (0);
+}
+
+static void rsap1_sigdestroy(sig *s)
+{
+  rsap1_sigctx *rs = (rsap1_sigctx *)s;
+  rsa_privdestroy(&rs->rp);
+  DESTROY(rs);
+}
+
+static const sigops rsap1_sig = {
+  rsa_privfetch, sizeof(rsa_priv),
+  rsap1_siginit, rsap1_sigdoit, rsap1_sigcheck, rsap1_sigdestroy
+};
+
+typedef struct rsap1_vrfctx {
+  sig s;
+  rsa_pubctx rp;
+  pkcs1 p1;
+} rsap1_vrfctx;
+
+static sig *rsap1_vrfinit(key *k, void *kd, const gchash *hc)
+{
+  rsap1_vrfctx *rv = CREATE(rsap1_vrfctx);
+  rsa_pubcreate(&rv->rp, kd);
+  rv->p1.r = &rand_global;
+  rv->p1.ep = hc->name;
+  rv->p1.epsz = strlen(hc->name) + 1;
+  rv->s.h = 0;
+  return (&rv->s);
+}
+
+static int rsap1_vrfdoit(sig *s, dstr *d)
+{
+  rsap1_vrfctx *rv = (rsap1_vrfctx *)s;
+  mp *m = mp_loadb(MP_NEW, d->buf, d->len);
+  int rc = rsa_verify(&rv->rp, m,
+                     GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
+                     0, pkcs1_sigdecode, &rv->p1);
+  mp_drop(m);
+  return (rc);
+}
+
+static const char *rsap1_vrfcheck(sig *s)
+{
+  rsap1_vrfctx *rv = (rsap1_vrfctx *)s;
+  const char *e;
+  if ((e = rsa_lengthcheck(rv->rp.rp->n)) != 0) return (e);
+  return (0);
+}
+
+static void rsap1_vrfdestroy(sig *s)
+{
+  rsap1_vrfctx *rv = (rsap1_vrfctx *)s;
+  rsa_pubdestroy(&rv->rp);
+  DESTROY(rv);
+}
+
+static const sigops rsap1_vrf = {
+  rsa_pubfetch, sizeof(rsa_pub),
+  rsap1_vrfinit, rsap1_vrfdoit, rsap1_vrfcheck, rsap1_vrfdestroy
+};
+
+/* --- RSA PSS --- */
+
+static const gccipher *getmgf(key *k, const gchash *hc)
+{
+  dstr d = DSTR_INIT;
+  const gccipher *gc;
+  const char *mm;
+
+  if ((mm = key_getattr(0, k, "mgf")) == 0) {
+    dstr_putf(&d, "%s-mgf", hc->name);
+    mm = d.buf;
+  }
+  if ((gc = gcipher_byname(mm)) == 0)
+    die(EXIT_FAILURE, "unknown encryption scheme `%s'", mm);
+  dstr_destroy(&d);
+  return (gc);
+}
+
+typedef struct rsapss_sigctx {
+  sig s;
+  rsa_privctx rp;
+  pss p;
+} rsapss_sigctx;
+
+static sig *rsapss_siginit(key *k, void *kd, const gchash *hc)
+{
+  rsapss_sigctx *rs = CREATE(rsapss_sigctx);
+  rsa_privcreate(&rs->rp, kd, &rand_global);
+  rs->p.r = &rand_global;
+  rs->p.cc = getmgf(k, hc);
+  rs->p.ch = hc;
+  rs->p.ssz = hc->hashsz;
+  rsa_privdestroy(&rs->rp);
+  return (&rs->s);
+}
+
+static int rsapss_sigdoit(sig *s, dstr *d)
+{
+  rsapss_sigctx *rs = (rsapss_sigctx *)s;
+  size_t n;
+  mp *m = rsa_sign(&rs->rp, MP_NEW,
+                  GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
+                  pss_encode, &rs->p);
+  if (!m) return (-1);
+  n = mp_octets(rs->rp.rp->n); dstr_ensure(d, n); mp_storeb(m, d->buf, n);
+  d->len += n; mp_drop(m);
+  return (0);
+}
+
+static const char *rsapss_sigcheck(sig *s)
+{
+  rsapss_sigctx *rs = (rsapss_sigctx *)s;
+  const char *e;
+  if ((e = rsa_lengthcheck(rs->rp.rp->n)) != 0) return (e);
+  return (0);
+}
+
+static void rsapss_sigdestroy(sig *s)
+{
+  rsapss_sigctx *rs = (rsapss_sigctx *)s;
+  rsa_privdestroy(&rs->rp);
+  DESTROY(rs);
+}
+
+static const sigops rsapss_sig = {
+  rsa_privfetch, sizeof(rsa_priv),
+  rsapss_siginit, rsapss_sigdoit, rsapss_sigcheck, rsapss_sigdestroy
+};
+
+typedef struct rsapss_vrfctx {
+  sig s;
+  rsa_pubctx rp;
+  pss p;
+} rsapss_vrfctx;
+
+static sig *rsapss_vrfinit(key *k, void *kd, const gchash *hc)
+{
+  rsapss_vrfctx *rv = CREATE(rsapss_vrfctx);
+  rsa_pubcreate(&rv->rp, kd);
+  rv->p.r = &rand_global;
+  rv->p.cc = getmgf(k, hc);
+  rv->p.ch = hc;
+  rv->p.ssz = hc->hashsz;
+  return (&rv->s);
+}
+
+static int rsapss_vrfdoit(sig *s, dstr *d)
+{
+  rsapss_vrfctx *rv = (rsapss_vrfctx *)s;
+  mp *m = mp_loadb(MP_NEW, d->buf, d->len);
+  int rc = rsa_verify(&rv->rp, m,
+                     GH_DONE(s->h, 0), GH_CLASS(s->h)->hashsz,
+                     0, pss_decode, &rv->p);
+  mp_drop(m);
+  return (rc);
+}
+
+static const char *rsapss_vrfcheck(sig *s)
+{
+  rsapss_vrfctx *rv = (rsapss_vrfctx *)s;
+  const char *e;
+  if ((e = rsa_lengthcheck(rv->rp.rp->n)) != 0) return (e);
+  return (0);
+}
+
+static void rsapss_vrfdestroy(sig *s)
+{
+  rsapss_vrfctx *rv = (rsapss_vrfctx *)s;
+  rsa_pubdestroy(&rv->rp);
+  DESTROY(rv);
+}
+
+static const sigops rsapss_vrf = {
+  rsa_pubfetch, sizeof(rsa_pub),
+  rsapss_vrfinit, rsapss_vrfdoit, rsapss_vrfcheck, rsapss_vrfdestroy
+};
+
+/* --- DSA and ECDSA --- */
+
+typedef struct dsa_sigctx {
+  sig s;
+  gdsa g;
+} dsa_sigctx;
+
+static void dsa_initcommon(dsa_sigctx *ds, const gchash *hc,
+                          const char *ktag)
+{
+  ds->g.r = &rand_global;
+  ds->g.h = hc;
+  ds->g.u = MP_NEW;
+  ds->s.h = 0;
+}
+
+static dsa_sigctx *dsa_doinit(key *k, const gprime_param *gp,
+                             mp *y, const gchash *hc,
+                             group *(*makegroup)(const gprime_param *),
+                             const char *what)
+{
+  dsa_sigctx *ds = CREATE(dsa_sigctx);
+  dstr t = DSTR_INIT;
+
+  key_fulltag(k, &t);
+  if ((ds->g.g = makegroup(gp)) == 0)
+    die(EXIT_FAILURE, "bad %s group in key `%s'", what, t.buf);
+  ds->g.p = G_CREATE(ds->g.g);
+  if (G_FROMINT(ds->g.g, ds->g.p, y))
+    die(EXIT_FAILURE, "bad public key in key `%s'", t.buf);
+  dsa_initcommon(ds, hc, t.buf);
+  dstr_destroy(&t);
+  return (ds);
+}
+
+static dsa_sigctx *ecdsa_doinit(key *k, const char *cstr,
+                               ec *y, const gchash *hc)
+{
+  dsa_sigctx *ds = CREATE(dsa_sigctx);
+  ec_info ei;
+  const char *e;
+  dstr t = DSTR_INIT;
+
+  key_fulltag(k, &t);
+  if ((e = ec_getinfo(&ei, cstr)) != 0)
+    die(EXIT_FAILURE, "bad curve in key `%s': %s", t.buf, e);
+  ds->g.g = group_ec(&ei);
+  ds->g.p = G_CREATE(ds->g.g);
+  if (G_FROMEC(ds->g.g, ds->g.p, y))
+    die(EXIT_FAILURE, "bad public key in key `%s'", t.buf);
+  dsa_initcommon(ds, hc, t.buf);
+  dstr_destroy(&t);
+  return (ds);
+}
+
+static sig *dsa_siginit(key *k, void *kd, const gchash *hc)
+{
+  dh_priv *dp = kd;
+  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime");
+  ds->g.u = MP_COPY(dp->x);
+  return (&ds->s);
+}
+
+static sig *bindsa_siginit(key *k, void *kd, const gchash *hc)
+{
+  dh_priv *dp = kd;
+  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary");
+  ds->g.u = MP_COPY(dp->x);
+  return (&ds->s);
+}
+
+static sig *ecdsa_siginit(key *k, void *kd, const gchash *hc)
+{
+  ec_priv *ep = kd;
+  dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc);
+  ds->g.u = MP_COPY(ep->x);
+  return (&ds->s);
+}
+
+static int dsa_sigdoit(sig *s, dstr *d)
+{
+  dsa_sigctx *ds = (dsa_sigctx *)s;
+  gdsa_sig ss = GDSA_SIG_INIT;
+  size_t n = mp_octets(ds->g.g->r);
+
+  gdsa_sign(&ds->g, &ss, GH_DONE(ds->s.h, 0), 0);
+  dstr_ensure(d, 2 * n);
+  mp_storeb(ss.r, d->buf, n);
+  mp_storeb(ss.s, d->buf + n, n);
+  d->len += 2 * n;
+  mp_drop(ss.r); mp_drop(ss.s);
+  return (0);
+}
+
+static const char *dsa_sigcheck(sig *s)
+{
+  dsa_sigctx *ds = (dsa_sigctx *)s;
+  const char *e;
+  if ((e = G_CHECK(ds->g.g, &rand_global)) != 0)
+    return (0);
+  if (group_check(ds->g.g, ds->g.p))
+    return ("public key not in subgroup");
+  return (0);
+}
+
+static void dsa_sigdestroy(sig *s)
+{
+  dsa_sigctx *ds = (dsa_sigctx *)s;
+  G_DESTROY(ds->g.g, ds->g.p);
+  mp_drop(ds->g.u);
+  G_DESTROYGROUP(ds->g.g);
+  DESTROY(ds);
+}
+
+static const sigops dsa_sig = {
+  dh_privfetch, sizeof(dh_priv),
+  dsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static const sigops bindsa_sig = {
+  dh_privfetch, sizeof(dh_priv),
+  bindsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static const sigops ecdsa_sig = {
+  ec_privfetch, sizeof(ec_priv),
+  ecdsa_siginit, dsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static sig *dsa_vrfinit(key *k, void *kd, const gchash *hc)
+{
+  dh_pub *dp = kd;
+  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime");
+  return (&ds->s);
+}
+
+static sig *bindsa_vrfinit(key *k, void *kd, const gchash *hc)
+{
+  dh_pub *dp = kd;
+  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary");
+  return (&ds->s);
+}
+
+static sig *ecdsa_vrfinit(key *k, void *kd, const gchash *hc)
+{
+  ec_pub *ep = kd;
+  dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc);
+  return (&ds->s);
+}
+
+static int dsa_vrfdoit(sig *s, dstr *d)
+{
+  dsa_sigctx *ds = (dsa_sigctx *)s;
+  gdsa_sig ss;
+  size_t n = d->len/2;
+  int rc;
+
+  ss.r = mp_loadb(MP_NEW, d->buf, n);
+  ss.s = mp_loadb(MP_NEW, d->buf + n, d->len - n);
+  rc = gdsa_verify(&ds->g, &ss, GH_DONE(ds->s.h, 0));
+  mp_drop(ss.r); mp_drop(ss.s);
+  return (rc);
+}
+
+static const sigops dsa_vrf = {
+  dh_pubfetch, sizeof(dh_pub),
+  dsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static const sigops bindsa_vrf = {
+  dh_pubfetch, sizeof(dh_pub),
+  bindsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static const sigops ecdsa_vrf = {
+  ec_pubfetch, sizeof(ec_pub),
+  ecdsa_vrfinit, dsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+/* --- KCDSA and ECKCDSA --- */
+
+static void kcdsa_privkey(dsa_sigctx *ds, mp *x)
+  { ds->g.u = mp_modinv(MP_NEW, x, ds->g.g->r); }
+
+static void kcdsa_sethash(dsa_sigctx *ds, const gchash *hc)
+  { ds->s.h = gkcdsa_beginhash(&ds->g); }
+
+static sig *kcdsa_siginit(key *k, void *kd, const gchash *hc)
+{
+  dh_priv *dp = kd;
+  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime");
+  kcdsa_privkey(ds, dp->x);
+  kcdsa_sethash(ds, hc);
+  return (&ds->s);
+}
+
+static sig *binkcdsa_siginit(key *k, void *kd, const gchash *hc)
+{
+  dh_priv *dp = kd;
+  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary");
+  kcdsa_privkey(ds, dp->x);
+  kcdsa_sethash(ds, hc);
+  return (&ds->s);
+}
+
+static sig *eckcdsa_siginit(key *k, void *kd, const gchash *hc)
+{
+  ec_priv *ep = kd;
+  dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc);
+  kcdsa_privkey(ds, ep->x);
+  kcdsa_sethash(ds, hc);
+  return (&ds->s);
+}
+
+static int kcdsa_sigdoit(sig *s, dstr *d)
+{
+  dsa_sigctx *ds = (dsa_sigctx *)s;
+  gkcdsa_sig ss = GKCDSA_SIG_INIT;
+  size_t hsz = ds->g.h->hashsz, n = mp_octets(ds->g.g->r);
+
+  gkcdsa_sign(&ds->g, &ss, GH_DONE(ds->s.h, 0), 0);
+  dstr_ensure(d, hsz + n);
+  memcpy(d->buf, ss.r, hsz);
+  mp_storeb(ss.s, d->buf + hsz, n);
+  d->len += hsz + n;
+  xfree(ss.r); mp_drop(ss.s);
+  return (0);
+}
+
+static const sigops kcdsa_sig = {
+  dh_privfetch, sizeof(dh_priv),
+  kcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static const sigops binkcdsa_sig = {
+  dh_privfetch, sizeof(dh_priv),
+  binkcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static const sigops eckcdsa_sig = {
+  ec_privfetch, sizeof(ec_priv),
+  eckcdsa_siginit, kcdsa_sigdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static sig *kcdsa_vrfinit(key *k, void *kd, const gchash *hc)
+{
+  dh_pub *dp = kd;
+  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_prime, "prime");
+  kcdsa_sethash(ds, hc);
+  return (&ds->s);
+}
+
+static sig *binkcdsa_vrfinit(key *k, void *kd, const gchash *hc)
+{
+  dh_pub *dp = kd;
+  dsa_sigctx *ds = dsa_doinit(k, &dp->dp, dp->y, hc, group_binary, "binary");
+  kcdsa_sethash(ds, hc);
+  return (&ds->s);
+}
+
+static sig *eckcdsa_vrfinit(key *k, void *kd, const gchash *hc)
+{
+  ec_pub *ep = kd;
+  dsa_sigctx *ds = ecdsa_doinit(k, ep->cstr, &ep->p, hc);
+  kcdsa_sethash(ds, hc);
+  return (&ds->s);
+}
+
+static int kcdsa_vrfdoit(sig *s, dstr *d)
+{
+  dsa_sigctx *ds = (dsa_sigctx *)s;
+  gkcdsa_sig ss;
+  size_t hsz = ds->g.h->hashsz, n = d->len - hsz;
+  int rc;
+
+  if (d->len < hsz)
+    return (-1);
+  ss.r = (octet *)d->buf;
+  ss.s = mp_loadb(MP_NEW, d->buf + hsz, n);
+  rc = gkcdsa_verify(&ds->g, &ss, GH_DONE(ds->s.h, 0));
+  mp_drop(ss.s);
+  return (rc);
+}
+
+static const sigops kcdsa_vrf = {
+  dh_pubfetch, sizeof(dh_pub),
+  kcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static const sigops binkcdsa_vrf = {
+  dh_pubfetch, sizeof(dh_pub),
+  binkcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+static const sigops eckcdsa_vrf = {
+  ec_pubfetch, sizeof(ec_pub),
+  eckcdsa_vrfinit, kcdsa_vrfdoit, dsa_sigcheck, dsa_sigdestroy
+};
+
+/* --- Symmetric message authentication --- */
+
+typedef struct mac_ctx {
+  sig s;
+  const gcmac *mc;
+  gmac *m;
+  key_packdef kp;
+  key_bin kb;
+} mac_ctx;
+
+static sig *mac_init(key *k, void *kd, const gchash *hc)
+{
+  mac_ctx *m;
+  dstr d = DSTR_INIT;
+  int err;
+  const char *mm;
+
+  m = CREATE(mac_ctx);
+
+  key_fulltag(k, &d);
+  m->kp.e = KENC_BINARY;
+  m->kp.p = &m->kb;
+  m->kp.kd = 0;
+
+  if ((mm = key_getattr(0 /*yik*/, k, "mac")) == 0) {
+    dstr_putf(&d, "%s-hmac", hc->name);
+    mm = d.buf;
+  }
+  if ((m->mc = gmac_byname(mm)) == 0)
+    die(EXIT_FAILURE, "unknown message authentication scheme `%s'", mm);
+  dstr_reset(&d);
+
+  if ((err = key_unpack(&m->kp, kd, &d)) != 0) {
+    die(EXIT_FAILURE, "failed to unpack symmetric key `%s': %s",
+       d.buf, key_strerror(err));
+  }
+  dstr_destroy(&d);
+
+  if (keysz(m->kb.sz, m->mc->keysz) != m->kb.sz) {
+    die(EXIT_FAILURE, "bad key size %lu for `%s'",
+       (unsigned long)m->kb.sz, m->mc->name);
+  }
+  m->m = GM_KEY(m->mc, m->kb.k, m->kb.sz);
+  m->s.h = GM_INIT(m->m);
+  return (&m->s);
+}
+
+static int mac_sigdoit(sig *s, dstr *d)
+{
+  mac_ctx *m = (mac_ctx *)s;
+
+  dstr_ensure(d, m->mc->hashsz);
+  GH_DONE(m->s.h, d->buf);
+  d->len += m->mc->hashsz;
+  return (0);
+}
+
+static int mac_vrfdoit(sig *s, dstr *d)
+{
+  mac_ctx *m = (mac_ctx *)s;
+  const octet *t;
+
+  t = GH_DONE(m->s.h, 0);
+  if (d->len != m->mc->hashsz || memcmp(d->buf, t, d->len) != 0)
+    return (-1);
+  return (0);
+}
+
+static const char *mac_check(sig *s) { return (0); }
+
+static void mac_destroy(sig *s)
+{
+  mac_ctx *m = (mac_ctx *)s;
+  GM_DESTROY(m->m);
+  key_unpackdone(&m->kp);
+}
+
+static const sigops mac_sig = {
+  0, 0,
+  mac_init, mac_sigdoit, mac_check, mac_destroy
+};
+
+static const sigops mac_vrf = {
+  0, 0,
+  mac_init, mac_vrfdoit, mac_check, mac_destroy
+};
+
+/* --- The switch table --- */
+
+const struct sigtab sigtab[] = {
+  { "rsapkcs1",        &rsap1_sig,     &rsap1_vrf,     &sha },
+  { "rsapss",  &rsapss_sig,    &rsapss_vrf,    &sha },
+  { "dsa",     &dsa_sig,       &dsa_vrf,       &sha },
+  { "bindsa",  &bindsa_sig,    &bindsa_vrf,    &sha },
+  { "ecdsa",   &ecdsa_sig,     &ecdsa_vrf,     &sha },
+  { "kcdsa",   &kcdsa_sig,     &kcdsa_vrf,     &has160 },
+  { "binkcdsa",        &binkcdsa_sig,  &binkcdsa_vrf,  &has160 },
+  { "eckcdsa", &eckcdsa_sig,   &eckcdsa_vrf,   &has160 },
+  { "mac",     &mac_sig,       &mac_vrf,       &rmd160 },
+  { 0,         0,              0 }
+};
+
+/* --- @getsig@ --- *
+ *
+ * Arguments:  @key *k@ = the key to load
+ *             @const char *app@ = application name
+ *             @int wantpriv@ = nonzero if we want to sign
+ *
+ * Returns:    A signature-making thing.
+ *
+ * Use:                Loads a key and starts hashing.
+ */
+
+sig *getsig(key *k, const char *app, int wantpriv)
+{
+  const char *salg, *halg = 0;
+  dstr d = DSTR_INIT;
+  dstr t = DSTR_INIT;
+  char *p = 0;
+  const char *q;
+  sig *s;
+  size_t n;
+  const struct sigtab *st;
+  const sigops *so;
+  const gchash *ch;
+  void *kd;
+  int e;
+  key_packdef *kp;
+
+  /* --- Setup stuff --- */
+
+  key_fulltag(k, &t);
+
+  /* --- Get the signature algorithm --- *
+   *
+   * Take the attribute if it's there; otherwise use the key type.
+   */
+
+  n = strlen(app);
+  if ((q = key_getattr(0, k, "sig")) != 0) {
+    dstr_puts(&d, q);
+    p = d.buf;
+  } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') {
+    dstr_puts(&d, k->type);
+    p = d.buf + n + 1;
+  } else
+    die(EXIT_FAILURE, "no signature algorithm for key `%s'", t.buf);
+
+  /* --- Grab the hash algorithm --- *
+   *
+   * Grab it from the signature algorithm if it's there.  But override that
+   * from the attribute.
+   */
+
+  salg = p;
+  if ((p = strchr(p, '/')) != 0) {
+    *p++ = 0;
+    halg = p;
+  }
+  if ((q = key_getattr(0, k, "hash")) != 0)
+    halg = q;
+
+  /* --- Look up the algorithms in the table --- */
+
+  for (st = sigtab; st->name; st++) {
+    if (strcmp(st->name, salg) == 0)
+      goto s_found;
+  }
+  die(EXIT_FAILURE, "signature algorithm `%s' not found in key `%s'",
+      salg, t.buf);
+s_found:;
+  if (!halg)
+    ch = st->ch;
+  else {
+    if ((ch = ghash_byname(halg)) == 0) {
+      die(EXIT_FAILURE, "hash algorithm `%s' not found in key `%s'",
+         halg, t.buf);
+    }
+  }
+  so = wantpriv ? st->signops : st->verifyops;
+
+  /* --- Load the key --- */
+
+  if (!so->kf) {
+    kd = k->k;
+    key_incref(kd);
+    kp = 0;
+  } else {
+    kd = xmalloc(so->kdsz);
+    kp = key_fetchinit(so->kf, 0, kd);
+    if ((e = key_fetch(kp, k)) != 0) {
+      die(EXIT_FAILURE, "error fetching key `%s': %s",
+         t.buf, key_strerror(e));
+    }
+  }
+  s = so->init(k, kd, ch);
+  if (!s->h)
+    s->h = GH_INIT(ch);
+  s->kp = kp;
+  s->ops = so;
+  s->kd = kd;
+  s->ch = ch;
+
+  /* --- Free stuff up --- */
+
+  dstr_destroy(&d);
+  dstr_destroy(&t);
+  return (s);
+}
+
+/* --- @freesig@ --- *
+ *
+ * Arguments:  @sig *s@ = signature-making thing
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees up a signature-making thing
+ */
+
+void freesig(sig *s)
+{
+  GH_DESTROY(s->h);
+  if (!s->ops->kf)
+    key_drop(s->kd);
+  else {
+    key_fetchdone(s->kp);
+    xfree(s->kd);
+  }
+  s->ops->destroy(s);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/progs/cc-subcmd.c b/progs/cc-subcmd.c
new file mode 100644 (file)
index 0000000..83c4a78
--- /dev/null
@@ -0,0 +1,109 @@
+/* -*-c-*-
+ *
+ * Subcommand infrastructure
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include <mLib/quis.h>
+#include <mLib/report.h>
+
+#include "cc.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @findcmd@ --- *
+ *
+ * Arguments:  @const cmd *cmds@ = pointer to command table
+ *             @const char *name@ = a command name
+ *
+ * Returns:    Pointer to the command structure.
+ *
+ * Use:                Looks up a command by name.  If the command isn't found, an
+ *             error is reported and the program is terminated.
+ */
+
+const cmd *findcmd(const cmd *cmds, const char *name)
+{
+  const cmd *c, *chosen = 0;
+  size_t sz = strlen(name);
+
+  for (c = cmds; c->name; c++) {
+    if (strncmp(name, c->name, sz) == 0) {
+      if (c->name[sz] == 0) {
+       chosen = c;
+       break;
+      } else if (chosen)
+       die(EXIT_FAILURE, "ambiguous command name `%s'", name);
+      else
+       chosen = c;
+    }
+  }
+  if (!chosen)
+    die(EXIT_FAILURE, "unknown command name `%s'", name);
+  return (chosen);
+}
+
+/* --- @sc_help@ --- *
+ *
+ * Arguments:  @const cmd *cmds@ = pointer to command table
+ *             @FILE *fp@ = output file handle
+ *             @char *const *argv@ = remaining arguments
+ *
+ * Returns:    ---
+ *
+ * Use:                Prints a help message, maybe with help about subcommands.
+ */
+
+void sc_help(const cmd *cmds, FILE *fp, char *const *argv)
+{
+  const cmd *c;
+
+  version(fp);
+  fputc('\n', fp);
+  if (!*argv) {
+    help_global(fp);
+    fputs("\n\
+The following commands are understood:\n\n",
+         fp);
+    for (c = cmds; c->name; c++)
+      fprintf(fp, "%s\n", c->usage);
+  } else {
+    while (*argv) {
+      c = findcmd(cmds, *argv);
+      fprintf(fp, "Usage: %s [-OPTIONS] %s\n", QUIS, c->usage);
+      if (c->help) {
+       fputc('\n', fp);
+       pquis(fp, c->help);
+      }
+      argv++;
+      if (*argv) fputc('\n', fp);
+    }
+  }
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/progs/cc.h b/progs/cc.h
new file mode 100644 (file)
index 0000000..610a765
--- /dev/null
@@ -0,0 +1,657 @@
+/* -*-c-*-
+ *
+ * Catcrypt common stuff
+ *
+ * (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.
+ */
+
+#ifndef CATACOMB_CC_H
+#define CATACOMB_CC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#if _FILE_OFFSET_BITS != 64
+#  error "Must set _FILE_OFFSET_BITS to 64."
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <mLib/dstr.h>
+
+#include "key.h"
+#include "gcipher.h"
+#include "ghash.h"
+#include "gmac.h"
+
+/*----- Cryptographic object tables ---------------------------------------*/
+
+/* --- Key encapsulation --- */
+
+typedef struct kem {
+  const struct kemops *ops;
+  key_packdef *kp;
+  void *kd;
+  const gchash *h;
+  const gccipher *c, *cx;
+  const gcmac *m;
+} kem;
+
+typedef struct kemops {
+  const key_fetchdef *kf;              /* Key fetching structure */
+  size_t kdsz;                         /* Size of the key-data structure */
+  kem *(*init)(key */*k*/, void */*kd*/);
+  int (*doit)(kem */*k*/, dstr */*d*/, ghash */*h*/);
+  const char *(*check)(kem */*k*/);
+  void (*destroy)(kem */*k*/);
+} kemops;
+
+struct kemtab {
+  const char *name;
+  const kemops *encops;
+  const kemops *decops;
+};
+
+extern const struct kemtab kemtab[];
+
+/* --- @getkem@ --- *
+ *
+ * Arguments:  @key *k@ = the key to load
+ *             @const char *app@ = application name
+ *             @int wantpriv@ = nonzero if we want to decrypt
+ *
+ * Returns:    A key-encapsulating thing.
+ *
+ * Use:                Loads a key.
+ */
+
+extern kem *getkem(key */*k*/, const char */*app*/, int /*wantpriv*/);
+
+/* --- @setupkem@ --- *
+ *
+ * Arguments:  @kem *k@ = key-encapsulation thing
+ *             @dstr *d@ = key-encapsulation data
+ *             @gcipher **cx@ = key-expansion function (for IVs)
+ *             @gcipher **c@ = where to put initialized encryption scheme
+ *             @gmac **m@ = where to put initialized MAC
+ *
+ * Returns:    Zero for success, nonzero on faliure.
+ *
+ * Use:                Initializes all the various symmetric things from a KEM.
+ */
+
+extern int setupkem(kem */*k*/, dstr */*d*/,
+                   gcipher **/*cx*/, gcipher **/*c*/, gmac **/*m*/);
+
+/* --- @freekem@ --- *
+ *
+ * Arguments:  @kem *k@ = key-encapsulation thing
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees up a key-encapsulation thing.
+ */
+
+extern void freekem(kem */*k*/);
+
+/* --- Signing --- */
+
+typedef struct sig {
+  const struct sigops *ops;
+  key_packdef *kp;
+  void *kd;
+  const gchash *ch;
+  ghash *h;
+} sig;
+
+typedef struct sigops {
+  const key_fetchdef *kf;              /* Key fetching structure */
+  size_t kdsz;                         /* Size of the key-data structure */
+  sig *(*init)(key */*k*/, void */*kd*/, const gchash */*hc*/);
+  int (*doit)(sig */*s*/, dstr */*d*/);
+  const char *(*check)(sig */*s*/);
+  void (*destroy)(sig */*s*/);
+} sigops;
+
+struct sigtab {
+  const char *name;
+  const sigops *signops;
+  const sigops *verifyops;
+  const gchash *ch;
+};
+
+extern const struct sigtab sigtab[];
+
+/* --- @getsig@ --- *
+ *
+ * Arguments:  @key *k@ = the key to load
+ *             @const char *app@ = application name
+ *             @int wantpriv@ = nonzero if we want to sign
+ *
+ * Returns:    A signature-making thing.
+ *
+ * Use:                Loads a key and starts hashing.
+ */
+
+extern sig *getsig(key */*k*/, const char */*app*/, int /*wantpriv*/);
+
+/* --- @freesig@ --- *
+ *
+ * Arguments:  @sig *s@ = signature-making thing
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees up a signature-making thing
+ */
+
+extern void freesig(sig */*s*/);
+
+/*----- File encodings ----------------------------------------------------*/
+
+/* --- Data encoding --- */
+
+typedef struct enc {
+  const struct encops *ops;
+  FILE *fp;
+} enc;
+
+typedef struct encops {
+  const char *name;
+  const char *rmode, *wmode;
+  int nraw, ncook;
+  enc *(*initenc)(FILE */*fp*/, const char */*msg*/);
+  enc *(*initdec)(FILE */*fp*/,
+                 int (*/*func*/)(const char *, void *), void */*p*/);
+  int (*read)(enc */*e*/, void */*p*/, size_t /*sz*/);
+  int (*write)(enc */*e*/, const void */*p*/, size_t /*sz*/);
+  int (*encdone)(enc */*e*/);
+  int (*decdone)(enc */*e*/);
+  void (*destroy)(enc */*e*/);
+} encops;
+
+extern const encops enctab[];
+
+/* --- @getenc@ --- *
+ *
+ * Arguments:  @const char *enc@ = name of wanted encoding
+ *
+ * Returns:    Pointer to encoder operations.
+ *
+ * Use:                Finds a named encoder or decoder.
+ */
+
+extern const encops *getenc(const char */*enc*/);
+
+/* --- @checkbdry@ --- *
+ *
+ * Arguments:  @const char *b@ = boundary string found
+ *             @void *p@ = boundary string wanted
+ *
+ * Returns:    Nonzero if the boundary string is the one we wanted.
+ *
+ * Use:                Pass as @func@ to @initdec@ if you just want a simple life.
+ */
+
+extern int checkbdry(const char */*b*/, void */*p*/);
+
+/* --- @initenc@ --- *
+ *
+ * Arguments:  @const encops *eo@ = operations (from @getenc@)
+ *             @FILE *fp@ = file handle to attach
+ *             @const char *msg@ = banner message
+ *
+ * Returns:    The encoder object.
+ *
+ * Use:                Initializes an encoder.
+ */
+
+extern enc *initenc(const encops */*eo*/, FILE */*fp*/, const char */*msg*/);
+
+/* --- @initdec@ --- *
+ *
+ * Arguments:  @const encops *eo@ = operations (from @getenc@)
+ *             @FILE *fp@ = file handle to attach
+ *             @int (*func)(const char *, void *)@ = banner check function
+ *             @void *p@ = argument for @func@
+ *
+ * Returns:    The encoder object.
+ *
+ * Use:                Initializes an encoder.
+ */
+
+extern enc *initdec(const encops */*eo*/, FILE */*fp*/,
+                   int (*/*func*/)(const char *, void *), void */*p*/);
+
+/* --- @freeenc@ --- *
+ *
+ * Arguments:  @enc *e@ = encoder object
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an encoder object.
+ */
+
+extern void freeenc(enc */*e*/);
+
+/* --- @cmd_encode@, @cmd_decode@ --- */
+
+#define CMD_ENCODE {                                                   \
+  "encode", cmd_encode,                                                        \
+    "encode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]",           \
+    "\
+Options:\n\
+\n\
+-f, --format=FORMAT    Encode to FORMAT.\n\
+-b, --boundary=LABEL   PEM boundary is LABEL.\n\
+-o, --output=FILE      Write output to FILE.\n\
+-p, --progress         Show progress on large files.\n\
+" }
+
+#define CMD_DECODE {                                                   \
+  "decode", cmd_decode,                                                        \
+    "decode [-p] [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]",           \
+    "\
+Options:\n\
+\n\
+-f, --format=FORMAT    Decode from FORMAT.\n\
+-b, --boundary=LABEL   PEM boundary is LABEL.\n\
+-o, --output=FILE      Write output to FILE.\n\
+-p, --progress         Show progress on large files.\n\
+" }
+
+extern int cmd_encode(int /*argc*/, char */*argv*/[]);
+extern int cmd_decode(int /*argc*/, char */*argv*/[]);
+
+/*----- Hash encoding functions -------------------------------------------*/
+
+/* --- Table --- */
+
+#define ENCODINGS(_)                                                   \
+  _(HEX, hex)                                                          \
+  _(BASE64, base64)                                                    \
+  _(BASE32, base32)
+
+enum {
+#define ENUM(tag, name) ENC_##tag,
+  ENCODINGS(ENUM)
+#undef ENUM
+  ENC_LIMIT
+};
+
+typedef struct encodeops {
+  const char *name;
+  void (*put)(const octet *, size_t, FILE *);
+  size_t (*get)(const char *, octet *, size_t, char **);
+} encodeops;
+
+extern const encodeops encodingtab[];
+
+/* --- @getencoding@ --- *
+ *
+ * Arguments:  @const char *ename@ = encoding name
+ *
+ * Returns:    Pointer to encoding table entry, or null.
+ *
+ * Use:                Finds an encoding entry given its name.
+ */
+
+extern const encodeops *getencoding(const char */*ename*/);
+
+/*----- File hashing ------------------------------------------------------*/
+
+typedef struct fhashstate {
+  const gchash *gch;
+  unsigned f;
+  struct fhent *ents;
+} fhashstate;
+
+#define FHF_BINARY 0x100u
+#define FHF_PROGRESS 0x200u
+#define FHF_JUNK 0x400u
+
+#define FHF_MASK 0xff00u
+
+/* --- @gethash@ --- *
+ *
+ * Arguments:  @const char *name@ = pointer to name string
+ *
+ * Returns:    Pointer to appropriate hash class.
+ *
+ * Use:                Chooses a hash function by name.
+ */
+
+extern const gchash *gethash(const char */*name*/);
+
+/* --- @describefile@ --- *
+ *
+ * Arguments:  @const struct stat *st@ = pointer to file state
+ *
+ * Returns:    A snappy one-word description of the file.
+ */
+
+extern const char *describefile(const struct stat */*st*/);
+
+/* --- @fhash_init@ ---*
+ *
+ * Arguments:  @fhashstate *fh@ = pointer to fhash state to initialize
+ *             @const gchash *gch@ = hash class to set
+ *             @unsigned f@ initial flags to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an @fhashstate@ structure.
+ */
+
+extern void fhash_init(fhashstate */*fh*/,
+                      const gchash */*gch*/, unsigned /*f*/);
+
+/* --- @fhash_free@ --- *
+ *
+ * Arguments:  @fhashstate *fh@ = pointer to fhash state to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an fhash state.
+ */
+
+extern void fhash_free(fhashstate */*fh*/);
+
+/* --- @fhash@ --- *
+ *
+ * Arguments:  @fhashstate *fh@ = pointer to fhash state
+ *             @const char *file@ = file name to be hashed (null for stdin)
+ *             @void *buf@ = pointer to hash output buffer
+ *
+ * Returns:    Zero if it worked, nonzero on error.
+ *
+ * Use:                Hashes a file.
+ */
+
+extern int fhash(fhashstate */*fh*/, const char */*file*/, void */*buf*/);
+
+/* --- @fhash_junk@ --- *
+ *
+ * Arguments:  @fhashstate *fh@ = pointer to fhash state
+ *             @void (*func)(const char *, const struct stat *, void *)@
+ *             @void *p@ = pointer to pass to function
+ *
+ * Returns:    Positive if any junk was found, negative on error, zero if
+ *             everything was fine.
+ *
+ * Use:                Reports junk files in any directories covered by the hash
+ *             state.
+ */
+
+extern int fhash_junk(fhashstate */*fh*/,
+                     int (*/*func*/)(const char *,
+                                     const struct stat *,
+                                     void *),
+                     void */*p*/);
+
+/* --- @hfparse@ --- *
+ *
+ * Arguments:  @hfpctx *hfp@ = pointer to the context structure
+ *
+ * Returns:    A code indicating what happened.
+ *
+ * Use:                Parses a line from the input file.
+ */
+
+enum {                                 /* Meaning and members set */
+  HF_FILE,                             /* File hash: @dline@ and @hbuf@ */
+  HF_ENC,                              /* Encoding: @ee@ */
+  HF_HASH,                             /* Hash function: @gch@ */
+  HF_ESC,                              /* Name escape: @f@ */
+  HF_EOF,                              /* End of file */
+  HF_BAD                               /* Unrecognized line */
+};
+
+typedef struct hfpctx {
+  unsigned f;                          /* Flags to read */
+#define HFF_ESCAPE 1u                  /*   File names are escaped */
+  FILE *fp;                            /* Input file to read */
+  dstr *dline;                         /* Line contents, corrupted */
+  const gchash *gch;                   /* Hash function to use */
+  const encodeops *ee;                 /* Encoding to apply to hashes */
+  dstr *dfile;                         /* File name for @HF_FILE@ lines */
+  octet *hbuf;                         /* Output buffer for hash data */
+} hfpctx;
+
+extern int hfparse(hfpctx */*hfp*/);
+
+/*----- String I/O --------------------------------------------------------*/
+
+#define GSF_RAW 4096u
+#define GSF_FILE 0u
+#define GSF_STRING 8192u
+
+#define GSF_MASK 61440u
+
+/* --- @getstring@ --- *
+ *
+ * Arguments:  @void *in@ = input source
+ *             @dstr *d@ = destination string
+ *             @unsigned f@ = input flags
+ *
+ * Returns:    Zero if OK, nonzero on end-of-file.
+ *
+ * Use:                Reads a filename (or something similar) from a stream.
+ */
+
+extern int getstring(void */*in*/, dstr */*d*/, unsigned /*f*/);
+
+/* --- @putstring@ --- *
+ *
+ * Arguments:  @FILE *fp@ = stream to write on
+ *             @const char *p@ = pointer to text
+ *             @unsigned f@ = output flags
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits a string to a stream.
+ */
+
+extern void putstring(FILE */*fp*/, const char */*p*/, unsigned /*f*/);
+
+/*----- Lists of things ---------------------------------------------------*/
+
+/* --- @LIST(STRING, FP, END-TEST, NAME-EXPR)@ --- *
+ *
+ * Produce list of things.  Requires @i@ and @w@ variables in scope.
+ * END-TEST and NAME-EXPR are in terms of @i@.
+ */
+
+#define LIST(what, fp, end, name) do {                                 \
+  fputs(what ":\n  ", fp);                                             \
+  w = 2;                                                               \
+  for (i = 0; end; i++) {                                              \
+    if (w == 2)                                                                \
+      w += strlen(name);                                               \
+    else {                                                             \
+      if (strlen(name) + w > 76) {                                     \
+       fputs("\n  ", fp);                                              \
+       w = 2 + strlen(name);                                           \
+      } else {                                                         \
+       fputc(' ', fp);                                                 \
+       w += strlen(name) + 1;                                          \
+      }                                                                        \
+    }                                                                  \
+    fputs(name, fp);                                                   \
+  }                                                                    \
+  fputc('\n', fp);                                                     \
+} while (0)
+
+#define STDLISTS(LI)                                                   \
+  LI("Hash functions", hash,                                           \
+     ghashtab[i], ghashtab[i]->name)                                   \
+  LI("Encryption schemes", enc,                                                \
+     gciphertab[i], gciphertab[i]->name)                               \
+  LI("Message authentication schemes", mac,                            \
+     gmactab[i], gmactab[i]->name)                                     \
+  LI("Elliptic curves", ec,                                            \
+     ectab[i].name, ectab[i].name)                                     \
+  LI("Diffie-Hellman groups", dh,                                      \
+     ptab[i].name, ptab[i].name)
+
+#define LIDECL(text, tag, test, name)                                  \
+  static void show_##tag(void);
+
+#define LIDEF(text, tag, test, name)                                   \
+  static void show_##tag(void)                                         \
+  {                                                                    \
+    unsigned i, w;                                                     \
+    LIST(text, stdout, test, name);                                    \
+  }
+
+#define LIENT(text, tag, test, name)                                   \
+  { #tag, show_##tag },
+
+struct listent {
+  const char *name;
+  void (*list)(void);
+};
+
+#define MAKELISTTAB(listtab, LISTS)                                    \
+  LISTS(LIDECL)                                                                \
+  static const struct listent listtab[] = {                            \
+    LISTS(LIENT)                                                       \
+    { 0, 0 }                                                           \
+  };                                                                   \
+  LISTS(LIDEF)
+
+extern int displaylists(const struct listent */*listtab*/,
+                       char *const /*argv*/[]);
+
+/*----- Progress indicators -----------------------------------------------*/
+
+typedef struct fprogress {
+  const char *bp;
+  off_t o, sz, olast;
+  time_t start, last;
+  char name[24];
+} fprogress;
+
+/* --- @fprogress_init@ --- *
+ *
+ * Arguments:  @fprogress *f@ = progress context to be initialized
+ *             @const char *name@ = file name string to show
+ *             @FILE *fp@ = file we're reading from
+ *
+ * Returns:    Zero on success, nonzero if the file's state is now broken.
+ *
+ * Use:                Initializes a progress context.  Nothing is actually
+ *             displayed yet.
+ */
+
+extern int fprogress_init(fprogress */*f*/,
+                         const char */*name*/, FILE */*fp*/);
+
+/* --- @fprogress_update@ --- *
+ *
+ * Arguments:  @fprogress *f@ = progress context
+ *             @size_t n@ = how much progress has been made
+ *
+ * Returns:    ---
+ *
+ * Use:                Maybe updates the display to show that some progress has been
+ *             made.
+ */
+
+extern void fprogress_update(fprogress */*f*/, size_t /*n*/);
+
+/* --- @fprogress_clear@ --- *
+ *
+ * Arguments:  @fprogress *f@ = progress context
+ *
+ * Returns:    ---
+ *
+ * Use:                Clears the progress display from the screen.
+ */
+
+extern void fprogress_clear(fprogress */*f*/);
+
+/* --- @fprogress_done@ --- *
+ *
+ * Arguments:  @fprogress *f@ = progress context
+ *
+ * Returns:    ---
+ *
+ * Use:                Clear up the progress context and removes any display.
+ */
+
+extern void fprogress_done(fprogress */*f*/);
+
+/*----- Subcommand dispatch -----------------------------------------------*/
+
+typedef struct cmd {
+  const char *name;
+  int (*cmd)(int /*argc*/, char */*argv*/[]);
+  const char *usage;
+  const char *help;
+} cmd;
+
+extern void version(FILE */*fp*/);
+extern void help_global(FILE */*fp*/);
+
+/* --- @findcmd@ --- *
+ *
+ * Arguments:  @const cmd *cmds@ = pointer to command table
+ *             @const char *name@ = a command name
+ *
+ * Returns:    Pointer to the command structure.
+ *
+ * Use:                Looks up a command by name.  If the command isn't found, an
+ *             error is reported and the program is terminated.
+ */
+
+const cmd *findcmd(const cmd */*cmds*/, const char */*name*/);
+
+/* --- @sc_help@ --- *
+ *
+ * Arguments:  @const cmd *cmds@ = pointer to command table
+ *             @FILE *fp@ = output file handle
+ *             @char *const *argv@ = remaining arguments
+ *
+ * Returns:    ---
+ *
+ * Use:                Prints a help message, maybe with help about subcommands.
+ */
+
+extern void sc_help(const cmd */*cmds*/, FILE */*fp*/,
+                   char *const */*argv*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
similarity index 100%
rename from cookie.1
rename to progs/cookie.1
diff --git a/progs/cookie.c b/progs/cookie.c
new file mode 100644 (file)
index 0000000..56849e5
--- /dev/null
@@ -0,0 +1,692 @@
+/* -*-c-*-
+ *
+ * Generate and validate cryptographic cookies
+ *
+ * (c) 1999 Mark Wooding
+ */
+
+/*----- 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <mLib/base64.h>
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include "cc.h"
+#include "key.h"
+#include "gmac.h"
+#include "getdate.h"
+
+/*----- Handy global state ------------------------------------------------*/
+
+static const char *keyfile = "keyring";
+
+/*----- Cookie format -----------------------------------------------------*/
+
+/* --- Cookie header structure (unpacked) --- */
+
+typedef struct cookie {
+  uint32 k;
+  time_t exp;
+} cookie;
+
+/* --- Size of a cookie header (packed) --- */
+
+#define COOKIE_SZ (4 + 8)
+
+/* --- @COOKIE_PACK@ --- *
+ *
+ * Arguments:  @p@ = pointer to destination buffer
+ *             @c@ = pointer to source cookie header block
+ *
+ * Use:                Packs a cookie header into an octet buffer in a machine-
+ *             independent way.
+ */
+
+#define COOKIE_PACK(p, c) do {                                         \
+  octet *_p = (octet *)(p);                                            \
+  const cookie *_c = (c);                                              \
+  STORE32(_p + 0, _c->k);                                              \
+  STORE32(_p + 4, ((_c->exp & ~MASK32) >> 16) >> 16);                  \
+  STORE32(_p + 8, _c->exp);                                            \
+} while (0)
+
+/* --- @COOKIE_UNPACK@ --- *
+ *
+ * Arguments:  @c@ = pointer to destination cookie header
+ *             @p@ = pointer to source buffer
+ *
+ * Use:                Unpacks a cookie header from an octet buffer into a
+ *             machine-specific but comprehensible structure.
+ */
+
+#define COOKIE_UNPACK(c, p) do {                                       \
+  cookie *_c = (c);                                                    \
+  const octet *_p = (const octet *)(p);                                        \
+  _c->k = LOAD32(_p + 0);                                              \
+  _c->exp = ((time_t)(((LOAD32(_p + 4) << 16) << 16) & ~MASK32) |      \
+            (time_t)LOAD32(_p + 8));                                   \
+} while (0)
+
+/*----- Useful shared functions -------------------------------------------*/
+
+/* --- @doopen@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *             @unsigned how@ = method to open file with
+ *
+ * Returns:    ---
+ *
+ * Use:                Opens a key file and handles errors by panicking
+ *             appropriately.
+ */
+
+static void doopen(key_file *f, unsigned how)
+{
+  if (key_open(f, keyfile, how, key_moan, 0)) {
+    die(EXIT_FAILURE, "couldn't open file `%s': %s",
+       keyfile, strerror(errno));
+  }
+}
+
+/* --- @doclose@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *
+ * Returns:    ---
+ *
+ * Use:                Closes a key file and handles errors by panicking
+ *             appropriately.
+ */
+
+static void doclose(key_file *f)
+{
+  switch (key_close(f)) {
+    case KWRITE_FAIL:
+      die(EXIT_FAILURE, "couldn't write file `%s': %s",
+         keyfile, strerror(errno));
+    case KWRITE_BROKEN:
+      die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)",
+         keyfile, strerror(errno));
+  }
+}
+
+/* --- @getmac@ --- *
+ *
+ * Arguments:  @key *k@ = key to use
+ *             @const char *app@ = application name
+ *
+ * Returns:    The MAC to use.
+ *
+ * Use:                Finds the right MAC for the given key.
+ */
+
+static gmac *getmac(key *k, const char *app)
+{
+  dstr t = DSTR_INIT;
+  dstr d = DSTR_INIT;
+  char *p = 0;
+  const char *q;
+  size_t n;
+  key_bin kb;
+  key_packdef kp;
+  const gcmac *cm;
+  int e;
+  gmac *m;
+
+  /* --- Set up --- */
+
+  key_fulltag(k, &t);
+
+  /* --- Pick out the right MAC --- */
+
+  n = strlen(app);
+  if ((q = key_getattr(0, k, "mac")) != 0) {
+    dstr_puts(&d, q);
+    p = d.buf;
+  } else if (strncmp(k->type, app, n) == 0 && k->type[n] == '-') {
+    dstr_puts(&d, k->type);
+    p = d.buf + n + 1;
+  } else
+    die(EXIT_FAILURE, "no MAC algorithm for key `%s'", t.buf);
+  if ((cm = gmac_byname(p)) == 0) {
+    die(EXIT_FAILURE, "MAC algorithm `%s' not found in key `%s'",
+       p, t.buf);
+  }
+
+  /* --- Unlock the key --- */
+
+  kp.e = KENC_BINARY;
+  kp.p = &kb;
+  if ((e = key_unpack(&kp, k->k, &t)) != 0) {
+    die(EXIT_FAILURE, "error unpacking key `%s': %s",
+       t.buf, key_strerror(e));
+  }
+
+  /* --- Make the MAC object --- */
+
+  if (keysz(kb.sz, cm->keysz) != kb.sz)
+    die(EXIT_FAILURE, "key %s has bad length (%lu) for MAC %s",
+       t.buf, (unsigned long)kb.sz, cm->name);
+  m = cm->key(kb.k, kb.sz);
+  key_unpackdone(&kp);
+  return (m);
+}
+
+/*----- Command implementation --------------------------------------------*/
+
+/* --- @cmd_gen@ --- */
+
+static int cmd_gen(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  gmac *m;
+  ghash *h;
+  const char *tag = "cookie";
+  int err;
+  cookie c = { 0, KEXP_EXPIRE };
+  unsigned fl = 0;
+  int bits = 32;
+  const octet *t;
+  dstr d = DSTR_INIT;
+  octet buf[COOKIE_SZ];
+  base64_ctx b;
+
+  /* --- Various useful flag bits --- */
+
+#define f_bogus 1u
+
+  /* --- Parse options for the subcommand --- */
+
+  for (;;) {
+    static struct option opt[] = {
+      { "bits",                OPTF_ARGREQ,    0,      'b' },
+      { "expire",      OPTF_ARGREQ,    0,      'e' },
+      { "key",         OPTF_ARGREQ,    0,      'k' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+b:e:i:t:", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+
+    /* --- Handle the various options --- */
+
+    switch (i) {
+
+      /* --- Fetch a size in bits --- */
+
+      case 'b':
+       if (!(bits = atoi(optarg)) || bits % 8)
+         die(EXIT_FAILURE, "bad number of bits: `%s'", optarg);
+       break;
+
+      /* --- Fetch an expiry time --- */
+
+      case 'e':
+       if (strcmp(optarg, "forever") == 0)
+         c.exp = KEXP_FOREVER;
+       else if ((c.exp = get_date(optarg, 0)) == -1)
+         die(EXIT_FAILURE, "bad expiry date: `%s'", optarg);
+       break;
+
+      /* --- Fetch a key type --- */
+
+      case 'k':
+       tag = optarg;
+       break;
+
+      /* --- Other things are bogus --- */
+
+      default:
+       fl |= f_bogus;
+       break;
+    }
+  }
+
+  /* --- Various sorts of bogosity --- */
+
+  if (fl & f_bogus || optind + 1 < argc)
+    die(EXIT_FAILURE,
+       "Usage: generate [-b BITS] [-e TIME] [-k TAG] [DATA]");
+
+  /* --- Choose a default expiry time --- */
+
+  if (c.exp == KEXP_EXPIRE)
+    c.exp = time(0) + 7 * 24 * 60 * 60;
+
+  /* --- Open the key file and get the key --- */
+
+  doopen(&f, KOPEN_WRITE);
+  if ((k = key_bytag(&f, tag)) == 0) {
+    die(EXIT_FAILURE, "no key with tag `%s' in keyring `%s'",
+       tag, keyfile);
+  }
+
+  c.k = k->id;
+  if ((err = key_used(&f, k, c.exp)) != 0)
+    die(EXIT_FAILURE, "can't generate cookie: %s", key_strerror(err));
+  m = getmac(k, "cookie");
+  if (bits/8 > GM_CLASS(m)->hashsz) {
+    die(EXIT_FAILURE, "inapproriate bit length for `%s' MACs",
+       GM_CLASS(m)->name);
+  }
+
+  /* --- Store and MAC the cookie --- */
+
+  COOKIE_PACK(buf, &c);
+
+  h = GM_INIT(m);
+  GH_HASH(h, buf, sizeof(buf));
+  if (argv[optind])
+    GH_HASH(h, argv[optind], strlen(argv[optind]));
+  t = GH_DONE(h, 0);
+
+  /* --- Encode and emit the finished cookie --- */
+
+  base64_init(&b);
+  b.indent = "";
+  base64_encode(&b, buf, sizeof(buf), &d);
+  base64_encode(&b, t, bits/8, &d);
+  base64_encode(&b, 0, 0, &d);
+  DWRITE(&d, stdout);
+  fputc('\n', stdout);
+  DDESTROY(&d);
+  GH_DESTROY(h);
+  GM_DESTROY(m);
+
+  doclose(&f);
+  return (0);
+
+#undef f_bogus
+}
+
+/* --- @cmd_verify@ --- */
+
+static int cmd_verify(int argc, char *argv[])
+{
+  key_file f;
+  dstr d = DSTR_INIT;
+  unsigned fl = 0;
+  int bits = -1, minbits = 32;
+  int v = 1;
+  base64_ctx b;
+  gmac *m;
+  ghash *h;
+  cookie c;
+  key *k;
+  int cbits;
+  const octet *t;
+  time_t now = time(0);
+
+  /* --- Various useful flag bits --- */
+
+#define f_bogus 1u
+#define f_forever 2u
+#define f_utc 4u
+
+  /* --- Parse options for the subcommand --- */
+
+  for (;;) {
+    static struct option opt[] = {
+      { "bits",                OPTF_ARGREQ,    0,      'b' },
+      { "min-bits",    OPTF_ARGREQ,    0,      'm' },
+      { "forever",     0,              0,      'f' },
+      { "quiet",       0,              0,      'q' },
+      { "verbose",     0,              0,      'v' },
+      { "utc",         0,              0,      'u' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+b:m:fqvu", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+
+    /* --- Handle the various options --- */
+
+    switch (i) {
+
+      /* --- Fetch a size in bits --- */
+
+      case 'b':
+       if (!(bits = atoi(optarg)) || bits % 8)
+         die(EXIT_FAILURE, "bad number of bits: `%s'", optarg);
+       break;
+      case 'm':
+       if (!(minbits = atoi(optarg)) || minbits % 8)
+         die(EXIT_FAILURE, "bad number of bits: `%s'", optarg);
+       break;
+
+      /* --- Miscellaneous flags --- */
+
+      case 'f':
+       fl |= f_forever;
+       break;
+      case 'u':
+       fl |= f_utc;
+       break;
+      case 'q':
+       if (v > 0) v--;
+       break;
+      case 'v':
+       v++;
+       break;
+
+      /* --- Other things are bogus --- */
+
+      default:
+       fl |= f_bogus;
+       break;
+    }
+  }
+
+  /* --- Various sorts of bogosity --- */
+
+  if (fl & f_bogus || optind == argc || optind + 2 < argc) {
+    die(EXIT_FAILURE,
+       "Usage: verify [-fuqv] [-b BITS] [-m BITS] COOKIE [DATA]");
+  }
+  doopen(&f, KOPEN_READ);
+
+  /* --- Decode the base64 wrapping --- */
+
+  base64_init(&b);
+  base64_decode(&b, argv[optind], strlen(argv[optind]), &d);
+  base64_decode(&b, 0, 0, &d);
+
+  if (d.len < COOKIE_SZ + 1) {
+    if (v) printf("FAIL cookie too small\n");
+    goto fail;
+  }
+
+  /* --- Extract the relevant details --- */
+
+  COOKIE_UNPACK(&c, d.buf);
+
+  if (v > 1) {
+    char buf[64];
+    if (c.exp == KEXP_FOREVER)
+      strcpy(buf, "forever");
+    else {
+      struct tm *tm;
+      const char *fmt;
+
+      if (fl & f_utc) {
+       tm = gmtime(&c.exp);
+       fmt = "%Y-%m-%d %H:%M:%S UTC";
+      } else {
+       tm = localtime(&c.exp);
+       fmt = "%Y-%m-%d %H:%M:%S %Z";
+      }
+      strftime(buf, sizeof(buf), fmt, tm);
+    }
+    printf("INFO keyid = %08lx; expiry = %s\n", (unsigned long)c.k, buf);
+  }
+
+  /* --- Check the authentication token width --- */
+
+  cbits = (d.len - COOKIE_SZ) * 8;
+  if (v > 2) printf("INFO authentication token width = %i bits\n", cbits);
+  if (bits == -1) {
+    if (cbits < minbits) {
+      if (v) printf("FAIL authentication token too narrow\n");
+      goto fail;
+    }
+  } else {
+    if (cbits != bits) {
+      if (v) printf("FAIL authentication token width doesn't match\n");
+      goto fail;
+    }
+  }
+  /* --- Get the key --- */
+
+  if ((k = key_byid(&f, c.k)) == 0) {
+    if (v) printf("FAIL keyid %08lx unavailable\n", (unsigned long)c.k);
+    goto fail;
+  }
+
+  /* --- Check that the cookie authenticates OK --- */
+
+  m = getmac(k, "cookie");
+  h = GM_INIT(m);
+  GH_HASH(h, d.buf, COOKIE_SZ);
+  if (argv[optind + 1])
+    GH_HASH(h, argv[optind + 1], strlen(argv[optind + 1]));
+  t = GH_DONE(h, 0);
+
+  if (memcmp(t, d.buf + COOKIE_SZ, cbits / 8) != 0) {
+    if (v) printf("FAIL bad authentication token\n");
+    goto fail;
+  }
+
+  /* --- See whether the cookie has expired --- */
+
+  if (c.exp == KEXP_FOREVER) {
+    if (!(fl & f_forever)) {
+      if (v) printf("FAIL forever cookies not allowed\n");
+      goto fail;
+    }
+    if (k->exp != KEXP_FOREVER) {
+      if (v) printf("FAIL cookie lasts forever but key will expire\n");
+      goto fail;
+    }
+  } else if (c.exp < now) {
+    if (v) printf("FAIL cookie has expired\n");
+    goto fail;
+  }
+
+  if (v) printf("OK\n");
+  key_close(&f);
+  GM_DESTROY(m);
+  GH_DESTROY(h);
+  dstr_destroy(&d);
+  return (0);
+
+fail:
+  key_close(&f);
+  dstr_destroy(&d);
+  return (1);
+
+#undef f_bogus
+#undef f_forever
+#undef f_utc
+}
+
+/*----- Main command table ------------------------------------------------*/
+
+static int cmd_help(int, char **);
+
+#define LISTS(LI)                                                      \
+  LI("Lists", list,                                                    \
+     listtab[i].name, listtab[i].name)                                 \
+  LI("Message authentication algorithms", mac,                         \
+     gmactab[i], gmactab[i]->name)
+
+MAKELISTTAB(listtab, LISTS)
+
+static int cmd_show(int argc, char *argv[])
+{
+  return (displaylists(listtab, argv + 1));
+}
+
+static cmd cmds[] = {
+  { "help", cmd_help, "help [COMMAND...]" },
+  { "show", cmd_show, "show [ITEM...]" },
+  { "generate", cmd_gen,
+    "generate [-b BITS] [-e TIME] [-k TAG] [DATA]", "\
+Options:\n\
+\n\
+-b, --bits=N           Use an N-bit token in the cookie.\n\
+-e, --expire=TIME      Make the cookie expire after TIME.\n\
+-k, --key=TAG          Use key TAG to create the token.\n\
+" },
+  { "verify", cmd_verify,
+    "verify [-fuqv] [-b BITS] [-m BITS] COOKIE [DATA]", "\
+Options:\n\
+\n\
+-b, --bits=N           Accept tokens exactly N bits long only.\n\
+-m, --min-bits=N       Accept tokens N bits long or more.\n\
+-f, --forever          Accept cookies which never expire.\n\
+-u, --utc              Output cookie expiry dates in UTC.\n\
+-q, --quiet            Produce less output while checking cookies.\n\
+-v, --verbose          Produce more output while checking cookies.\n\
+" },
+  { 0, 0, 0 }
+};
+
+static int cmd_help(int argc, char *argv[])
+{
+  sc_help(cmds, stdout, argv + 1);
+  return (0);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Helpful GNUy functions --- */
+
+static void usage(FILE *fp)
+{
+  fprintf(fp, "Usage: %s [-k KEYRING] COMMAND [ARGS]\n", QUIS);
+}
+
+void version(FILE *fp)
+{
+  fprintf(fp, "%s, Catacomb version " VERSION "\n", QUIS);
+}
+
+void help_global(FILE *fp)
+{
+  usage(fp);
+  fputs("\n\
+Generates and validates cryptographic cookies.  Command line options\n\
+recognized are:\n\
+\n\
+-h, --help [COMMAND]   Display this help text (or help for COMMAND).\n\
+-v, --version          Display version number.\n\
+-u, --usage            Display short usage summary.\n\
+\n\
+-k, --key-file=FILE    Read and write keys in FILE.\n",
+       fp);
+}
+
+/* --- @main@ --- *
+ *
+ * Arguments:  @int argc@ = number of command line arguments
+ *             @char *argv[]@ = array of arguments
+ *
+ * Returns:    Zero if OK, nonzero if not.
+ *
+ * Use:                Generates and validates cryptographic cookies.
+ */
+
+int main(int argc, char *argv[])
+{
+  unsigned f = 0;
+
+#define f_bogus 1u
+#define f_forever 2u
+
+  /* --- Initialize the library --- */
+
+  ego(argv[0]);
+  sub_init();
+
+  /* --- Options parsing --- */
+
+  for (;;) {
+    static struct option opt[] = {
+
+      /* --- Standard GNUy help options --- */
+
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'v' },
+      { "usage",       0,              0,      'u' },
+
+      /* --- Actual relevant options --- */
+
+      { "keyring",     OPTF_ARGREQ,    0,      'k' },
+
+      /* --- Magic terminator --- */
+
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+hvu k:", opt, 0, 0, 0);
+
+    if (i < 0)
+      break;
+    switch (i) {
+
+      /* --- Helpful GNUs --- */
+
+      case 'u':
+       usage(stdout);
+       exit(0);
+      case 'v':
+       version(stdout);
+       exit(0);
+      case 'h':
+       sc_help(cmds, stdout, argv + optind);
+       exit(0);
+
+      /* --- Real genuine useful options --- */
+
+      case 'k':
+       keyfile = optarg;
+       break;
+
+      /* --- Bogus things --- */
+
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+
+  if ((f & f_bogus) || optind == argc) {
+    usage(stderr);
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Dispatch to appropriate command handler --- */
+
+  argc -= optind;
+  argv += optind;
+  optind = 0;
+  return (findcmd(cmds, argv[0])->cmd(argc, argv));
+
+#undef f_bogus
+#undef f_forever
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from dsig.1
rename to progs/dsig.1
diff --git a/progs/dsig.c b/progs/dsig.c
new file mode 100644 (file)
index 0000000..5e5a3cf
--- /dev/null
@@ -0,0 +1,1124 @@
+/* -*-c-*-
+ *
+ * Verify signatures on distribuitions of files
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include "config.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/base64.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include "getdate.h"
+#include "rand.h"
+#include "ghash.h"
+#include "key.h"
+#include "key-data.h"
+#include "noise.h"
+#include "cc.h"
+
+/*----- Data formatting ---------------------------------------------------*/
+
+/* --- Binary data structure --- *
+ *
+ * The binary format, which is used for hashing and for the optional binary
+ * output, consists of a sequence of tagged blocks.  The tag describes the
+ * format and meaining of the following data.
+ */
+
+enum {
+  /* --- Block tags --- */
+
+  T_IDENT = 0,                         /* An identifying marker */
+  T_KEYID,                             /* Key identifier */
+  T_BEGIN,                             /* Begin hashing here */
+  T_COMMENT = T_BEGIN,                 /* A textual comment */
+  T_DATE,                              /* Creation date of signature */
+  T_EXPIRE,                            /* Expiry date of signature */
+  T_FILE,                              /* File and corresponding hash */
+  T_SIGNATURE,                         /* Final signature block */
+
+  /* --- Error messages --- */
+
+  E_EOF = -1,
+  E_BIN = -2,
+  E_TAG = -3,
+  E_DATE = -4
+};
+
+/* --- Name translation table --- */
+
+static const char *tagtab[] = {
+  "ident:", "keyid:",
+  "comment:", "date:", "expires:", "file:",
+  "signature:",
+  0
+};
+
+static const char *errtab[] = {
+  "Off-by-one bug",
+  "Unexpected end-of-file",
+  "Binary object too large",
+  "Unrecognized tag",
+  "Bad date string"
+};
+
+/* --- Memory representation of block types --- */
+
+typedef struct block {
+  int tag;                             /* Type tag */
+  dstr d;                              /* String data */
+  dstr b;                              /* Binary data */
+  time_t t;                            /* Timestamp */
+  uint32 k;                            /* Keyid */
+} block;
+
+/* --- @timestring@ --- *
+ *
+ * Arguments:  @time_t t@ = a timestamp
+ *             @dstr *d@ = a string to write on
+ *
+ * Returns:    ---
+ *
+ * Use:                Writes a textual representation of the timestamp to the
+ *             string.
+ */
+
+static void timestring(time_t t, dstr *d)
+{
+  if (t == KEXP_FOREVER)
+    DPUTS(d, "forever");
+  else {
+    struct tm *tm = localtime(&t);
+    DENSURE(d, 32);
+    d->len += strftime(d->buf + d->len, 32, "%Y-%m-%d %H:%M:%S %Z", tm);
+    DPUTZ(d);
+  }
+}
+
+/* --- @breset@ --- *
+ *
+ * Arguments:  @block *b@ = block to reset
+ *
+ * Returns:    ---
+ *
+ * Use:                Resets a block so that more stuff can be put in it.
+ */
+
+static void breset(block *b)
+{
+  b->tag = 0;
+  DRESET(&b->d);
+  DRESET(&b->b);
+  b->k = 0;
+  b->t = KEXP_EXPIRE;
+}
+
+/* --- @binit@ --- *
+ *
+ * Arguments:  @block *b@ = block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a block as something to read into.
+ */
+
+static void binit(block *b)
+{
+  dstr_create(&b->d);
+  dstr_create(&b->b);
+  breset(b);
+}
+
+/* --- @bdestroy@ --- *
+ *
+ * Arguments:  @block *b@ = block to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a block's contents.
+ */
+
+static void bdestroy(block *b)
+{
+  dstr_destroy(&b->d);
+  dstr_destroy(&b->b);
+}
+
+/* --- @bget@ --- *
+ *
+ * Arguments:  @block *b@ = pointer to block
+ *             @FILE *fp@ = stream to read from
+ *             @unsigned bin@ = binary switch
+ *
+ * Returns:    Tag of block, or an error tag.
+ *
+ * Use:                Reads a block from a stream.
+ */
+
+static int bget(block *b, FILE *fp, unsigned bin)
+{
+  int tag;
+
+  /* --- Read the tag --- */
+
+  if (bin)
+    tag = getc(fp);
+  else {
+    dstr d = DSTR_INIT;
+    if (getstring(fp, &d, GSF_FILE))
+      return (E_EOF);
+    for (tag = 0; tagtab[tag]; tag++) {
+      if (strcmp(tagtab[tag], d.buf) == 0)
+       goto done;
+    }
+    return (E_TAG);
+  done:;
+  }
+
+  /* --- Decide what to do next --- */
+
+  breset(b);
+  b->tag = tag;
+  switch (tag) {
+
+    /* --- Reading of strings --- */
+
+    case T_IDENT:
+    case T_COMMENT:
+      if (getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0)))
+       return (E_EOF);
+      break;
+
+    /* --- Timestamps --- */
+
+    case T_DATE:
+    case T_EXPIRE:
+      if (bin) {
+       octet buf[8];
+       if (fread(buf, sizeof(buf), 1, fp) < 1)
+         return (E_EOF);
+       b->t = ((time_t)(((LOAD32(buf + 0) << 16) << 16) & ~MASK32) |
+               (time_t)LOAD32(buf + 4));
+      } else {
+       if (getstring(fp, &b->d, GSF_FILE))
+         return (E_EOF);
+       if (strcmp(b->d.buf, "forever") == 0)
+         b->t = KEXP_FOREVER;
+       else if ((b->t = get_date(b->d.buf, 0)) == -1)
+         return (E_DATE);
+      }
+      break;
+
+    /* --- Key ids --- */
+
+    case T_KEYID:
+      if (bin) {
+       octet buf[4];
+       if (fread(buf, sizeof(buf), 1, fp) < 1)
+         return (E_EOF);
+       b->k = LOAD32(buf);
+      } else {
+       if (getstring(fp, &b->d, GSF_FILE))
+         return (E_EOF);
+       b->k = strtoul(b->d.buf, 0, 16);
+      }
+      break;
+
+    /* --- Reading of binary data --- */
+
+    case T_FILE:
+    case T_SIGNATURE:
+      if (bin) {
+       octet buf[2];
+       uint32 sz;
+       if (fread(buf, sizeof(buf), 1, fp) < 1)
+         return (E_EOF);
+       sz = LOAD16(buf);
+       if (sz > 4096)
+         return (E_BIN);
+       DENSURE(&b->b, sz);
+       if (fread(b->b.buf + b->b.len, 1, sz, fp) < sz)
+         return (E_EOF);
+       b->b.len += sz;
+      } else {
+       base64_ctx b64;
+       if (getstring(fp, &b->d, GSF_FILE))
+         return (E_EOF);
+       base64_init(&b64);
+       base64_decode(&b64, b->d.buf, b->d.len, &b->b);
+       base64_decode(&b64, 0, 0, &b->b);
+       DRESET(&b->d);
+      }
+      if (tag == T_FILE &&
+         getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0)))
+       return (E_EOF);
+      break;
+
+      /* --- Anything else --- */
+
+    default:
+      return (E_TAG);
+  }
+
+  return (tag);
+}
+
+/* --- @blob@ --- *
+ *
+ * Arguments:  @block *b@ = pointer to block to emit
+ *             @dstr *d@ = output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Encodes a block in a binary format.
+ */
+
+static void blob(block *b, dstr *d)
+{
+  DPUTC(d, b->tag);
+  switch (b->tag) {
+    case T_IDENT:
+    case T_COMMENT:
+      DPUTD(d, &b->d);
+      DPUTC(d, 0);
+      break;
+    case T_DATE:
+    case T_EXPIRE:
+      DENSURE(d, 8);
+      if (b->t == KEXP_FOREVER) {
+       STORE32(d->buf + d->len, 0xffffffff);
+       STORE32(d->buf + d->len + 4, 0xffffffff);
+      } else {
+       STORE32(d->buf + d->len, ((b->t & ~MASK32) >> 16) >> 16);
+       STORE32(d->buf + d->len + 4, b->t);
+      }
+      d->len += 8;
+      break;
+    case T_KEYID:
+      DENSURE(d, 4);
+      STORE32(d->buf + d->len, b->k);
+      d->len += 4;
+      break;
+    case T_FILE:
+    case T_SIGNATURE:
+      DENSURE(d, 2);
+      STORE16(d->buf + d->len, b->b.len);
+      d->len += 2;
+      DPUTD(d, &b->b);
+      if (b->tag == T_FILE) {
+       DPUTD(d, &b->d);
+       DPUTC(d, 0);
+      }
+      break;
+  }
+}
+
+/* --- @bwrite@ --- *
+ *
+ * Arguments:  @block *b@ = pointer to block to write
+ *             @FILE *fp@ = stream to write on
+ *
+ * Returns:    ---
+ *
+ * Use:                Writes a block on a stream in a textual format.
+ */
+
+static void bwrite(block *b, FILE *fp)
+{
+  fputs(tagtab[b->tag], fp);
+  putc(' ', fp);
+  switch (b->tag) {
+    case T_IDENT:
+    case T_COMMENT:
+      putstring(fp, b->d.buf, 0);
+      break;
+    case T_DATE:
+    case T_EXPIRE: {
+      dstr d = DSTR_INIT;
+      timestring(b->t, &d);
+      putstring(fp, d.buf, 0);
+      dstr_destroy(&d);
+    } break;
+    case T_KEYID:
+      fprintf(fp, "%08lx", (unsigned long)b->k);
+      break;
+    case T_FILE:
+    case T_SIGNATURE: {
+      dstr d = DSTR_INIT;
+      base64_ctx b64;
+      base64_init(&b64);
+      b64.maxline = 0;
+      base64_encode(&b64, b->b.buf, b->b.len, &d);
+      base64_encode(&b64, 0, 0, &d);
+      dstr_write(&d, fp);
+      if (b->tag == T_FILE) {
+       putc(' ', fp);
+       putstring(fp, b->d.buf, 0);
+      }
+    } break;
+  }
+  putc('\n', fp);
+}
+
+/* --- @bemit@ --- *
+ *
+ * Arguments:  @block *b@ = pointer to block to write
+ *             @FILE *fp@ = file to write on
+ *             @ghash *h@ = pointer to hash function
+ *             @unsigned bin@ = binary/text flag
+ *
+ * Returns:    ---
+ *
+ * Use:                Spits out a block properly.
+ */
+
+static void bemit(block *b, FILE *fp, ghash *h, unsigned bin)
+{
+  if (h || (fp && bin)) {
+    dstr d = DSTR_INIT;
+    blob(b, &d);
+    if (h)
+      GH_HASH(h, d.buf, d.len);
+    if (fp && bin)
+      fwrite(d.buf, d.len, 1, fp);
+  }
+  if (fp && !bin)
+    bwrite(b, fp);
+}
+
+/*----- Static variables --------------------------------------------------*/
+
+static const char *keyring = "keyring";
+
+/*----- Other shared functions --------------------------------------------*/
+
+/* --- @fhex@ --- *
+ *
+ * Arguments:  @FILE *fp@ = file to write on
+ *             @const void *p@ = pointer to data to be written
+ *             @size_t sz@ = size of the data to write
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits a hex dump to a stream.
+ */
+
+static void fhex(FILE *fp, const void *p, size_t sz)
+{
+  const octet *q = p;
+  if (!sz)
+    return;
+  for (;;) {
+    fprintf(fp, "%02x", *q++);
+    sz--;
+    if (!sz)
+      break;
+  }
+}
+
+/*----- Signature generation ----------------------------------------------*/
+
+static int sign(int argc, char *argv[])
+{
+#define f_bogus 1u
+#define f_bin 2u
+#define f_nocheck 4u
+
+  unsigned f = 0;
+  const char *ki = "dsig";
+  key_file kf;
+  key *k;
+  sig *s;
+  fhashstate fh;
+  time_t exp = KEXP_EXPIRE;
+  unsigned verb = 0;
+  const char *ifile = 0, *hfile = 0;
+  const char *ofile = 0;
+  const char *c = 0;
+  const char *err;
+  FILE *ifp, *ofp;
+  dstr d = DSTR_INIT;
+  hfpctx hfp;
+  block b;
+  int e, hf, n;
+
+  for (;;) {
+    static struct option opts[] = {
+      { "null",                0,              0,      '0' },
+      { "binary",      0,              0,      'b' },
+      { "verbose",     0,              0,      'v' },
+      { "progress",    0,              0,      'p' },
+      { "quiet",       0,              0,      'q' },
+      { "comment",     OPTF_ARGREQ,    0,      'c' },
+      { "file",                OPTF_ARGREQ,    0,      'f' },
+      { "hashes",      OPTF_ARGREQ,    0,      'h' },
+      { "output",      OPTF_ARGREQ,    0,      'o' },
+      { "key",         OPTF_ARGREQ,    0,      'k' },
+      { "expire",      OPTF_ARGREQ,    0,      'e' },
+      { "nocheck",     OPTF_ARGREQ,    0,      'C' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+0vpqbC" "c:" "f:h:o:" "k:e:",
+                  opts, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case '0':
+       f |= GSF_RAW;
+       break;
+      case 'b':
+       f |= f_bin;
+       break;
+      case 'v':
+       verb++;
+       break;
+      case 'p':
+       f |= FHF_PROGRESS;
+       break;
+      case 'q':
+       if (verb > 0)
+         verb--;
+       break;
+      case 'C':
+       f |= f_nocheck;
+       break;
+      case 'c':
+       c = optarg;
+       break;
+      case 'f':
+       ifile = optarg;
+       break;
+      case 'h':
+       hfile = optarg;
+       break;
+      case 'o':
+       ofile = optarg;
+       break;
+      case 'k':
+       ki = optarg;
+       break;
+      case 'e':
+       if (strcmp(optarg, "forever") == 0)
+         exp = KEXP_FOREVER;
+       else if ((exp = get_date(optarg, 0)) == -1)
+         die(EXIT_FAILURE, "bad expiry time");
+       break;
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+  if (optind != argc || (f & f_bogus))
+    die(EXIT_FAILURE, "Usage: sign [-OPTIONS]");
+  if (hfile && ifile)
+    die(EXIT_FAILURE, "Inconsistent options `-h' and `-f'");
+
+  /* --- Locate the signing key --- */
+
+  if (key_open(&kf, keyring, KOPEN_WRITE, key_moan, 0))
+    die(EXIT_FAILURE, "couldn't open keyring `%s'", keyring);
+  if ((k = key_bytag(&kf, ki)) == 0)
+    die(EXIT_FAILURE, "couldn't find key `%s'", ki);
+  key_fulltag(k, &d);
+  if (exp == KEXP_FOREVER && k->exp != KEXP_FOREVER) {
+    die(EXIT_FAILURE, "key `%s' expires: can't create nonexpiring signature",
+       d.buf);
+  }
+  s = getsig(k, "dsig", 1);
+
+  /* --- Check the key --- */
+
+  if (!(f & f_nocheck) && (err = s->ops->check(s)) != 0)
+    moan("key `%s' fails check: %s", d.buf, err);
+
+  /* --- Open files --- */
+
+  if (hfile) ifile = hfile;
+  if (!ifile || strcmp(ifile, "-") == 0)
+    ifp = stdin;
+  else if ((ifp = fopen(ifile, (f & f_bin) ? "rb" : "r")) == 0) {
+    die(EXIT_FAILURE, "couldn't open input file `%s': %s",
+       ifile, strerror(errno));
+  }
+
+  if (!ofile || strcmp(ofile, "-") == 0)
+    ofp = stdout;
+  else if ((ofp = fopen(ofile, (f & f_bin) ? "wb" : "w")) == 0) {
+    die(EXIT_FAILURE, "couldn't open output file `%s': %s",
+       ofile, strerror(errno));
+  }
+
+  /* --- Emit the start of the output --- */
+
+  binit(&b); b.tag = T_IDENT;
+  dstr_putf(&b.d, "%s, Catacomb version " VERSION, QUIS);
+  bemit(&b, ofp, 0, f & f_bin);
+
+  breset(&b); b.tag = T_KEYID; b.k = k->id;
+  bemit(&b, ofp, 0, f & f_bin);
+
+  /* --- Start hashing, and emit the datestamps and things --- */
+
+  {
+    time_t now = time(0);
+
+    breset(&b); b.tag = T_DATE; b.t = now; bemit(&b, ofp, s->h, f & f_bin);
+    if (exp == KEXP_EXPIRE)
+      exp = now + 86400 * 28;
+    breset(&b); b.tag = T_EXPIRE; b.t = exp; bemit(&b, ofp, s->h, f & f_bin);
+    if (c) {
+      breset(&b); b.tag = T_COMMENT; DPUTS(&b.d, c);
+      bemit(&b, ofp, s->h, f & f_bin);
+    }
+
+    if (!(f & f_bin))
+      putc('\n', ofp);
+  }
+
+  /* --- Now hash the various files --- */
+
+  if (hfile) {
+    hfp.f = f;
+    hfp.fp = ifp;
+    hfp.ee = &encodingtab[ENC_HEX];
+    hfp.gch = GH_CLASS(s->h);
+    hfp.dline = &d;
+    hfp.dfile = &b.d;
+
+    n = 0;
+    for (;;) {
+      breset(&b);
+      DENSURE(&b.b, hfp.gch->hashsz);
+      hfp.hbuf = (octet *)b.b.buf;
+      if (ferror(ofp)) { f |= f_bogus; break; }
+      if ((hf = hfparse(&hfp)) == HF_EOF) break;
+      n++;
+
+      switch (hf) {
+       case HF_HASH:
+         if (hfp.gch != GH_CLASS(s->h)) {
+           moan("%s:%d: incorrect hash function `%s' (should be `%s')",
+                hfile, n, hfp.gch->name, GH_CLASS(s->h)->name);
+           f |= f_bogus;
+         }
+         break;
+       case HF_BAD:
+         moan("%s:%d: invalid hash-file line", hfile, n);
+         f |= f_bogus;
+         break;
+       case HF_FILE:
+         b.tag = T_FILE;
+         b.b.len += hfp.gch->hashsz;
+         bemit(&b, ofp, s->h, f & f_bin);
+         break;
+      }
+    }
+  } else {
+    for (;;) {
+
+      /* --- Stop on an output error --- */
+
+      if (ferror(ofp)) {
+       f |= f_bogus;
+       break;
+      }
+
+      /* --- Read the next filename to hash --- */
+
+      fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY);
+      breset(&b);
+      if (getstring(ifp, &b.d, GSF_FILE | f))
+       break;
+      b.tag = T_FILE;
+      DENSURE(&b.b, GH_CLASS(s->h)->hashsz);
+      if (fhash(&fh, b.d.buf, b.b.buf)) {
+       moan("error reading `%s': %s", b.d.buf, strerror(errno));
+       f |= f_bogus;
+      } else {
+       b.b.len += GH_CLASS(s->h)->hashsz;
+       if (verb) {
+         fhex(stderr, b.b.buf, b.b.len);
+         fprintf(stderr, " %s\n", b.d.buf);
+       }
+       bemit(&b, ofp, s->h, f & f_bin);
+      }
+      fhash_free(&fh);
+    }
+  }
+
+  /* --- Create the signature --- */
+
+  if (!(f & f_bogus)) {
+    breset(&b);
+    b.tag = T_SIGNATURE;
+    if ((e = s->ops->doit(s, &b.b)) != 0) {
+      moan("error creating signature: %s", key_strerror(e));
+      f |= f_bogus;
+    }
+    if (!(f & f_bogus)) {
+      bemit(&b, ofp, 0, f & f_bin);
+      key_used(&kf, k, exp);
+    }
+  }
+
+  /* --- Tidy up at the end --- */
+
+  freesig(s);
+  bdestroy(&b);
+  if (ifile)
+    fclose(ifp);
+  if (ofile) {
+    if (fclose(ofp))
+      f |= f_bogus;
+  } else {
+    if (fflush(ofp))
+      f |= f_bogus;
+  }
+  if ((e = key_close(&kf)) != 0) {
+    switch (e) {
+      case KWRITE_FAIL:
+       die(EXIT_FAILURE, "couldn't write file `%s': %s",
+           keyring, strerror(errno));
+      case KWRITE_BROKEN:
+       die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)",
+           keyring, strerror(errno));
+    }
+  }
+  if (f & f_bogus)
+    die(EXIT_FAILURE, "error(s) occurred while creating signature");
+  return (EXIT_SUCCESS);
+
+#undef f_bin
+#undef f_bogus
+#undef f_nocheck
+}
+
+/*----- Signature verification --------------------------------------------*/
+
+static int checkjunk(const char *path, const struct stat *st, void *p)
+{
+  if (!st) printf("JUNK (error %s) %s\n", strerror(errno), path);
+  else printf("JUNK %s %s\n", describefile(st), path);
+  return (0);
+}
+
+static int verify(int argc, char *argv[])
+{
+#define f_bogus 1u
+#define f_bin 2u
+#define f_ok 4u
+#define f_nocheck 8u
+
+  unsigned f = 0;
+  unsigned verb = 1;
+  key_file kf;
+  key *k = 0;
+  sig *s;
+  dstr d = DSTR_INIT;
+  const char *err;
+  fhashstate fh;
+  FILE *fp;
+  block b;
+  int e;
+
+  /* --- Parse the options --- */
+
+  for (;;) {
+    static struct option opts[] = {
+      { "verbose",     0,              0,      'v' },
+      { "progress",    0,              0,      'p' },
+      { "quiet",       0,              0,      'q' },
+      { "nocheck",     0,              0,      'C' },
+      { "junk",                0,              0,      'j' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+vpqCj", opts, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'v':
+       verb++;
+       break;
+      case 'p':
+       f |= FHF_PROGRESS;
+       break;
+      case 'q':
+       if (verb)
+         verb--;
+       break;
+      case 'C':
+       f |= f_nocheck;
+       break;
+      case 'j':
+       f |= FHF_JUNK;
+       break;
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+  argc -= optind;
+  argv += optind;
+  if ((f & f_bogus) || argc > 1)
+    die(EXIT_FAILURE, "Usage: verify [-qvC] [FILE]");
+
+  /* --- Open the key file, and start reading the input file --- */
+
+  if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
+    die(EXIT_FAILURE, "couldn't open keyring `%s'\n", keyring);
+  if (argc < 1)
+    fp = stdin;
+  else {
+    if ((fp = fopen(argv[0], "rb")) == 0) {
+      die(EXIT_FAILURE, "couldn't open file `%s': %s\n",
+             argv[0], strerror(errno));
+    }
+    if (getc(fp) == 0) {
+      ungetc(0, fp);
+      f |= f_bin;
+    } else {
+      fclose(fp);
+      if ((fp = fopen(argv[0], "r")) == 0) {
+       die(EXIT_FAILURE, "couldn't open file `%s': %s\n",
+               argv[0], strerror(errno));
+      }
+    }
+  }
+
+  /* --- Read the introductory matter --- */
+
+  binit(&b);
+  for (;;) {
+    breset(&b);
+    e = bget(&b, fp, f & f_bin);
+    if (e < 0)
+      die(EXIT_FAILURE, "error reading packet: %s", errtab[-e]);
+    if (e >= T_BEGIN)
+      break;
+    switch (e) {
+      case T_IDENT:
+       if (verb > 2)
+         printf("INFO ident: `%s'\n", b.d.buf);
+       break;
+      case T_KEYID:
+       if ((k = key_byid(&kf, b.k)) == 0) {
+         if (verb)
+           printf("FAIL key %08lx not found\n", (unsigned long)b.k);
+         exit(EXIT_FAILURE);
+       }
+       if (verb > 2) {
+         DRESET(&b.d);
+         key_fulltag(k, &b.d);
+         printf("INFO key: %s\n", b.d.buf);
+       }
+       break;
+      default:
+       die(EXIT_FAILURE, "(internal) unknown packet type\n");
+       break;
+    }
+  }
+
+  /* --- Initialize the hash function and start reading hashed packets --- */
+
+  if (!k) {
+    if (verb)
+      puts("FAIL no keyid packet found");
+    exit(EXIT_FAILURE);
+  }
+
+  s = getsig(k, "dsig", 0);
+  if (!(f & f_nocheck) && verb && (err = s->ops->check(s)) != 0)
+    printf("WARN public key fails check: %s", err);
+
+  fhash_init(&fh, GH_CLASS(s->h), f | FHF_BINARY);
+  for (;;) {
+    switch (e) {
+      case T_COMMENT:
+       if (verb > 1)
+         printf("INFO comment: `%s'\n", b.d.buf);
+       bemit(&b, 0, s->h, 0);
+       break;
+      case T_DATE:
+       if (verb > 2) {
+         DRESET(&b.d);
+         timestring(b.t, &b.d);
+         printf("INFO date: %s\n", b.d.buf);
+       }
+       bemit(&b, 0, s->h, 0);
+       break;
+      case T_EXPIRE: {
+       time_t now = time(0);
+       if (b.t != KEXP_FOREVER && b.t < now) {
+         if (verb > 1)
+           puts("BAD signature has expired");
+         f |= f_bogus;
+       }
+       if (verb > 2) {
+         DRESET(&b.d);
+         timestring(b.t, &b.d);
+         printf("INFO expires: %s\n", b.d.buf);
+       }
+       bemit(&b, 0, s->h, 0);
+      }        break;
+      case T_FILE:
+       DRESET(&d);
+       DENSURE(&d, GH_CLASS(s->h)->hashsz);
+       if (fhash(&fh, b.d.buf, d.buf)) {
+         if (verb > 1) {
+           printf("BAD error reading file `%s': %s\n",
+                   b.d.buf, strerror(errno));
+         }
+         f |= f_bogus;
+       } else if (b.b.len != GH_CLASS(s->h)->hashsz ||
+                  memcmp(d.buf, b.b.buf, b.b.len) != 0) {
+         if (verb > 1)
+           printf("BAD file `%s' has incorrect hash\n", b.d.buf);
+         f |= f_bogus;
+       } else if (verb > 3) {
+         fputs("INFO hash: ", stdout);
+         fhex(stdout, b.b.buf, b.b.len);
+         printf(" %s\n", b.d.buf);
+       }
+       bemit(&b, 0, s->h, 0);
+       break;
+      case T_SIGNATURE:
+       if (s->ops->doit(s, &b.b)) {
+         if (verb > 1)
+           puts("BAD bad signature");
+         f |= f_bogus;
+       } else if (verb > 2)
+         puts("INFO good signature");
+       goto done;
+      default:
+       if (verb)
+         printf("FAIL invalid packet type %i\n", e);
+       exit(EXIT_FAILURE);
+       break;
+    }
+    breset(&b);
+    e = bget(&b, fp, f & f_bin);
+    if (e < 0) {
+      if (verb)
+       printf("FAIL error reading packet: %s\n", errtab[-e]);
+      exit(EXIT_FAILURE);
+    }
+  }
+done:
+  if ((f & FHF_JUNK) && fhash_junk(&fh, checkjunk, 0))
+    f |= f_bogus;
+  fhash_free(&fh);
+  bdestroy(&b);
+  dstr_destroy(&d);
+  freesig(s);
+  key_close(&kf);
+  if (fp != stdin)
+    fclose(fp);
+  if (verb) {
+    if (f & f_bogus)
+      puts("FAIL signature invalid");
+    else
+      puts("OK signature verified");
+  }
+  return (f & f_bogus ? EXIT_FAILURE : EXIT_SUCCESS);
+
+#undef f_bogus
+#undef f_bin
+#undef f_ok
+#undef f_nocheck
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+#define LISTS(LI)                                                      \
+  LI("Lists", list,                                                    \
+     listtab[i].name, listtab[i].name)                                 \
+  LI("Signature schemes", sig,                                         \
+     sigtab[i].name, sigtab[i].name)                                   \
+  LI("Hash functions", hash,                                           \
+     ghashtab[i], ghashtab[i]->name)
+
+MAKELISTTAB(listtab, LISTS)
+
+int cmd_show(int argc, char *argv[])
+{
+  return (displaylists(listtab, argv + 1));
+}
+
+static int cmd_help(int, char **);
+
+static cmd cmdtab[] = {
+  { "help", cmd_help, "help [COMMAND...]" },
+  { "show", cmd_show, "show [ITEM...]" },
+  { "sign", sign,
+    "sign [-0bpqvC] [-c COMMENT] [-k TAG] [-e EXPIRE]\n\t\
+[-f FILE] [-h FILE] [-o OUTPUT]",
+    "\
+Options:\n\
+\n\
+-0, --null             Read null-terminated filenames from stdin.\n\
+-b, --binary           Produce a binary output file.\n\
+-q, --quiet            Produce fewer messages while working.\n\
+-v, --verbose          Produce more messages while working.\n\
+-p, --progress         Show progress on large files.\n\
+-C, --nocheck          Don't check the private key.\n\
+-c, --comment=COMMENT  Include COMMENT in the output file.\n\
+-f, --file=FILE                Read filenames to hash from FILE.\n\
+-h, --hashes=FILE      Read precomputed hashes from FILE.\n\
+-o, --output=FILE      Write the signed result to FILE.\n\
+-k, --key=TAG          Use a key named by TAG.\n\
+-e, --expire=TIME      The signature should expire after TIME.\n\
+" },
+  { "verify", verify,
+    "verify [-pqvC] [FILE]", "\
+Options:\n\
+\n\
+-q, --quiet            Produce fewer messages while working.\n\
+-v, --verbose          Produce more messages while working.\n\
+-p, --progress         Show progress on large files.\n\
+-C, --nocheck          Don't check the public key.\n\
+" },
+  { 0, 0, 0 }
+};
+
+static int cmd_help(int argc, char **argv)
+{
+  sc_help(cmdtab, stdout, argv + 1);
+  return (0);
+}
+
+void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n");
+}
+
+void help_global(FILE *fp)
+{
+  usage(fp);
+  fputs("\n\
+Create and verify signatures on lists of files.\n\
+\n\
+Global command-line options:\n\
+\n\
+-h, --help [COMMAND...]        Show this help message, or help for COMMANDs.\n\
+-v, --version          Show program version number.\n\
+-u, --usage            Show a terse usage message.\n\
+\n\
+-k, --keyring=FILE     Read keys from FILE.\n",
+       fp);
+}
+
+/* --- @main@ --- *
+ *
+ * Arguments:  @int argc@ = number of command line arguments
+ *             @char *argv[]@ = vector of command line arguments
+ *
+ * Returns:    Zero if successful, nonzero otherwise.
+ *
+ * Use:                Signs or verifies signatures on lists of files.  Useful for
+ *             ensuring that a distribution is unmolested.
+ */
+
+int main(int argc, char *argv[])
+{
+  unsigned f = 0;
+
+#define f_bogus 1u
+
+  /* --- Initialize the library --- */
+
+  ego(argv[0]);
+  sub_init();
+  rand_noisesrc(RAND_GLOBAL, &noise_source);
+  rand_seed(RAND_GLOBAL, 160);
+
+  /* --- Parse options --- */
+
+  for (;;) {
+    static struct option opts[] = {
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'v' },
+      { "usage",       0,              0,      'u' },
+      { "keyring",     OPTF_ARGREQ,    0,      'k' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+hvu k:", opts, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'h':
+       sc_help(cmdtab, stdout, argv + optind);
+       exit(0);
+       break;
+      case 'v':
+       version(stdout);
+       exit(0);
+       break;
+      case 'u':
+       usage(stdout);
+       exit(0);
+      case 'k':
+       keyring = optarg;
+       break;
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+  optind = 0;
+  if (f & f_bogus || argc < 1) {
+    usage(stderr);
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Dispatch to the correct subcommand handler --- */
+
+  return (findcmd(cmdtab, argv[0])->cmd(argc, argv));
+
+#undef f_bogus
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/progs/factorial.c b/progs/factorial.c
new file mode 100644 (file)
index 0000000..a46debd
--- /dev/null
@@ -0,0 +1,150 @@
+/* -*-c-*-
+ *
+ * Example factorial computation
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+
+#include "mpint.h"
+#include "mpmul.h"
+#include "mptext.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "Usage: $ [-r RADIX] INTEGER\n");
+}
+
+static void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+static void help(FILE *fp)
+{
+  version(fp);
+  putc('\n', fp);
+  usage(fp);
+  fputs("\n\
+Prints the factorial of the given integer on its output.  Input may be\n\
+in decimal (the default), octal with preceding zero, hex with preceding\n\
+`0x', or any base N between 2 and 62 inclusive with preceding `N_'.\n\
+Output may be in any base between 2 and 62; the default is base 10.  For\n\
+bases between 11 and 36 inclusive, lowercase letters of either case are\n\
+used as additional digits with values 10 upwards; lowercase is always\n\
+used for output.  For bases between 37 and 62 inclusive, lowercase letters\n\
+have lower value than uppercase; hence `a' has the value 10, while `A' has\n\
+the value 36.\n\
+\n\
+Options provided:\n\
+\n\
+-h, --help             Display this help message.\n\
+-v, --version          Display the version number.\n\
+-u, --usage            Display a usage message.\n\
+\n\
+-r, --radix=N          Write output in base N.\n\
+", fp);
+}
+
+int main(int argc, char *argv[])
+{
+  unsigned long x;
+  int r = 10;
+  char *p;
+  mp *f, *ulmax, *xx;
+  unsigned fl = 0;
+
+#define f_bogus 1u
+
+  ego(argv[0]);
+
+  for (;;) {
+    static const struct option opt[] = {
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'v' },
+      { "usage",       0,              0,      'u' },
+      { "radix",       OPTF_ARGREQ,    0,      'r' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "hvur:", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'h':
+       help(stdout);
+       exit(0);
+      case 'v':
+       version(stdout);
+       exit(0);
+      case 'u':
+       usage(stdout);
+       exit(0);
+      case 'r':
+       r = atoi(optarg);
+       if (r < 2 || r > 62)
+         die(EXIT_FAILURE, "bad radix `%s'", optarg);
+       break;
+      default:
+       fl |= f_bogus;
+       break;
+    }
+  }
+
+  if (optind + 1 != argc || (fl & f_bogus)) {
+    usage(stderr);
+    exit(EXIT_FAILURE);
+  }
+  ulmax = mp_fromulong(MP_NEW, ULONG_MAX);
+  p = argv[optind];
+  while (isspace((unsigned char)*p))
+    p++;
+  xx = mp_readstring(MP_NEW, argv[optind], &p, 0);
+  while (isspace((unsigned char)*p))
+    p++;
+  if (!xx || *p || MP_CMP(xx, >, ulmax))
+    die(EXIT_FAILURE, "bad integer `%s'", argv[optind]);
+  x = mp_toulong(xx);
+  mp_drop(xx);
+  mp_drop(ulmax);
+  f = mp_factorial(x);
+  mp_writefile(f, stdout, r);
+  fputc('\n', stdout);
+  mp_drop(f);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from fibonacci.c
rename to progs/fibonacci.c
similarity index 100%
rename from hashsum.1
rename to progs/hashsum.1
diff --git a/progs/hashsum.c b/progs/hashsum.c
new file mode 100644 (file)
index 0000000..8cc1926
--- /dev/null
@@ -0,0 +1,410 @@
+/* -*-c-*-
+ *
+ * Hash files using some secure hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include "ghash.h"
+#include "cc.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+#define f_bogus 1u
+#define f_verbose 2u
+#define f_check 4u
+#define f_files 8u
+#define f_oddhash 16u
+#define f_escape 32u
+#define f_oddenc 64u
+
+/*----- Guts --------------------------------------------------------------*/
+
+static int checkjunk(const char *path, const struct stat *st, void *p)
+{
+  const char *what;
+  fhashstate *fh = p;
+
+  if (!st) {
+    if (fh->f & f_verbose)
+      fprintf(stderr, "JUNK (error %s) %s\n", strerror(errno), path);
+    else
+      moan("couldn't stat junk file `%s': %s", path, strerror(errno));
+  } else {
+    what = describefile(st);
+    if (fh->f & f_verbose)
+      fprintf(stderr, "JUNK %s %s\n", what, path);
+    else
+      moan("found junk %s `%s'", what, path);
+  }
+  return (0);
+}
+
+static int warnjunk(const char *path, const struct stat *st, void *p)
+{
+  if (st)
+    moan("unexpected %s `%s'", describefile(st), path);
+  else
+    moan("couldn't stat unexpected file `%s': %s", path, strerror(errno));
+  return (0);
+}
+
+static int checkhash(fhashstate *fh, const char *file, const encodeops *e)
+{
+  int rc;
+  hfpctx hfp;
+  dstr dl = DSTR_INIT;
+  dstr df = DSTR_INIT;
+  unsigned long n = 0, nfail = 0;
+  int hf;
+
+  if (!file || strcmp(file, "-") == 0)
+    hfp.fp = stdin;
+  else if ((hfp.fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) {
+    moan("couldn't open `%s': %s", file, strerror(errno));
+    return (EXIT_FAILURE);
+  }
+
+  hfp.dline = &dl;
+  hfp.dfile = &df;
+  hfp.hbuf = xmalloc(2 * fh->gch->hashsz);
+  hfp.gch = fh->gch;
+  hfp.ee = e;
+  hfp.f = fh->f;
+
+  while ((hf = hfparse(&hfp)) != HF_EOF) {
+    switch (hf) {
+      case HF_HASH:
+       xfree(hfp.hbuf);
+       hfp.hbuf = xmalloc(2 * hfp.gch->hashsz);
+       break;
+      case HF_FILE:
+       if (fhash(fh, df.buf, hfp.hbuf + hfp.gch->hashsz)) {
+         moan("couldn't read `%s': %s", df.buf, strerror(errno));
+         rc = EXIT_FAILURE;
+         continue;
+       }
+       if (memcmp(hfp.hbuf, hfp.hbuf + hfp.gch->hashsz,
+                  hfp.gch->hashsz) != 0) {
+         if (hfp.f & f_verbose)
+           fprintf(stderr, "FAIL %s\n", df.buf);
+         else
+           moan("%s check failed for `%s'", hfp.gch->name, df.buf);
+         nfail++;
+         rc = EXIT_FAILURE;
+       } else {
+         if (hfp.f & f_verbose)
+           fprintf(stderr, "OK %s\n", df.buf);
+       }
+       n++;
+    }
+  }
+
+  if (ferror(hfp.fp)) {
+    moan("error reading input `%s': %s",
+        file ? file : "<stdin>", strerror(errno));
+    rc = EXIT_FAILURE;
+  }
+  dstr_destroy(&dl);
+  dstr_destroy(&df);
+  xfree(hfp.hbuf);
+  if ((fh->f & f_verbose) && nfail)
+    moan("%lu of %lu file(s) failed %s check", nfail, n, hfp.gch->name);
+  else if (!n)
+    moan("no files checked");
+  return (rc);
+}
+
+static int dohash(fhashstate *fh, const char *file, const encodeops *e)
+{
+  int rc = 0;
+  octet *p = xmalloc(fh->gch->hashsz);
+
+  if (fhash(fh, file, p)) {
+    moan("couldn't read `%s': %s", file ? file : "<stdin>", strerror(errno));
+    rc = EXIT_FAILURE;
+  } else {
+    e->put(p, fh->gch->hashsz, stdout);
+    if (file) {
+      fputc(' ', stdout);
+      fputc(fh->f & FHF_BINARY ? '*' : ' ', stdout);
+      if (fh->f & f_escape)
+       putstring(stdout, file, 0);
+      else
+       fputs(file, stdout);
+    }
+    fputc('\n', stdout);
+  }
+
+  xfree(p);
+  return (rc);
+}
+
+static int dofile(fhashstate *fh, const char *file, const encodeops *e)
+  { return (fh->f & f_check ? checkhash : dohash)(fh, file, e); }
+
+static int hashfiles(fhashstate *fh, const char *file, const encodeops *e)
+{
+  FILE *fp;
+  dstr d = DSTR_INIT;
+  int rc = 0;
+  int rrc;
+
+  if (!file || strcmp(file, "-") == 0)
+    fp = stdin;
+  else if ((fp = fopen(file, fh->f & GSF_RAW ? "r" : "rb")) == 0) {
+    moan("couldn't open `%s': %s", file, strerror(errno));
+    return (EXIT_FAILURE);
+  }
+
+  for (;;) {
+    DRESET(&d);
+    if (getstring(fp, &d, GSF_FILE | fh->f))
+      break;
+    if ((rrc = dofile(fh, d.buf, e)) != 0)
+      rc = rrc;
+  }
+
+  return (rc);
+}
+
+static int hashsum(fhashstate *fh, const char *file, const encodeops *e)
+  { return (fh->f & f_files ? hashfiles : dofile)(fh, file, e); }
+
+/*----- Main driver -------------------------------------------------------*/
+
+void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "Usage: $ [-f0ebcv] [-a ALGORITHM] [-E ENC] [FILES...]\n");
+}
+
+static void help(FILE *fp, const gchash *gch)
+{
+  version(fp);
+  fputc('\n', fp);
+  usage(fp);
+  pquis(fp, "\n\
+Generates or checks message digests on files.  Options available:\n\
+\n\
+-h, --help             Display this help message.\n\
+-V, --version          Display program's version number.\n\
+-u, --usage            Display a terse usage message.\n\
+-l, --list [ITEM...]   Show known hash functions and/or encodings.\n\
+\n\
+-a, --algorithm=ALG    Use the message digest algorithm ALG.\n\
+-E, --encoding=ENC     Represent hashes using encoding ENC.\n\
+\n\
+-f, --files            Read a list of file names from standard input.\n\
+-0, --null             File names are null terminated, not plain text.\n\
+\n\
+-e, --escape           Escape funny characters in filenames.\n\
+-c, --check            Check message digests rather than emitting them.\n\
+-b, --binary           When reading files, treat them as binary.\n\
+-p, --progress         Show a progress indicator for large files.\n\
+-v, --verbose          Be verbose when checking digests.\n\
+\n\
+For a list of hashing algorithms and encodings, type `$ --list'.\n\
+");
+  if (gch)
+    fprintf(fp, "The default message digest algorithm is %s.\n", gch->name);
+}
+
+#define LISTS(LI)                                                      \
+  LI("Lists", list, listtab[i].name, listtab[i].name)                  \
+  LI("Hash functions", hash, ghashtab[i], ghashtab[i]->name)           \
+  LI("Encodings", enc, encodingtab[i].name, encodingtab[i].name)
+
+MAKELISTTAB(listtab, LISTS)
+
+int main(int argc, char *argv[])
+{
+  fhashstate fh;
+  const encodeops *e = &encodingtab[ENC_HEX];
+  int rc;
+
+  /* --- Initialization --- */
+
+  ego(argv[0]);
+  sub_init();
+  fhash_init(&fh, 0, 0);
+
+  /* --- Choose a hash function from the name --- */
+
+  {
+    char *q = xstrdup(QUIS);
+    size_t len = strlen(q);
+    if (len > 3 && strcmp(q + len - 3, "sum") == 0) {
+      q[len - 3] = 0;
+      fh.gch = gethash(q);
+    }
+    if (!fh.gch)
+      fh.gch = gethash("md5");
+    xfree(q);
+  }
+
+  /* --- Read options --- */
+
+  for (;;) {
+    static struct option opts[] = {
+      { "help",                0,              0,      'h' },
+      { "verbose",     0,              0,      'V' },
+      { "usage",       0,              0,      'u' },
+
+      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
+      { "hash",                OPTF_ARGREQ,    0,      'a' },
+      { "encoding",    OPTF_ARGREQ,    0,      'E' },
+      { "list",                0,              0,      'l' },
+
+      { "files",       0,              0,      'f' },
+      { "find",                0,              0,      'f' },
+      { "null",                0,              0,      '0' },
+
+      { "escape",      0,              0,      'e' },
+      { "check",       0,              0,      'c' },
+      { "junk",                0,              0,      'j' },
+      { "binary",      0,              0,      'b' },
+      { "verbose",     0,              0,      'v' },
+      { "progress",    0,              0,      'p' },
+
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "hVu a:E:l f0 ecjbvp", opts, 0, 0, 0);
+    if (i < 0)
+      break;
+
+    switch (i) {
+      case 'h':
+       help(stdout, fh.gch);
+       exit(0);
+      case 'V':
+       version(stdout);
+       exit(0);
+      case 'u':
+       usage(stdout);
+       exit(0);
+      case 'l':
+       exit(displaylists(listtab, argv + optind));
+      case 'a':
+       if ((fh.gch = gethash(optarg)) == 0)
+         die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg);
+       fh.f |= f_oddhash;
+       break;
+      case 'E':
+       if ((e = getencoding(optarg)) == 0)
+         die(EXIT_FAILURE, "unknown encoding `%s'", optarg);
+       fh.f |= f_oddenc;
+       break;
+      case 'f':
+       fh.f |= f_files;
+       break;
+      case '0':
+       fh.f |= GSF_RAW;
+       break;
+      case 'e':
+       fh.f |= f_escape;
+       break;
+      case 'c':
+       fh.f |= f_check;
+       break;
+      case 'j':
+       fh.f |= FHF_JUNK;
+       break;
+      case 'b':
+       fh.f |= FHF_BINARY;
+       break;
+      case 'v':
+       fh.f |= f_verbose;
+       break;
+      case 'p':
+       fh.f |= FHF_PROGRESS;
+       break;
+      default:
+       fh.f |= f_bogus;
+       break;
+    }
+  }
+
+  if (fh.f & f_bogus) {
+    usage(stderr);
+    exit(EXIT_FAILURE);
+  }
+  argv += optind;
+  argc -= optind;
+
+  /* --- Generate output --- */
+
+  if (!(fh.f & f_check) && (argc || (fh.f & f_files))) {
+    if (fh.f & f_oddhash) printf("#hash %s\n", fh.gch->name);
+    if (fh.f & f_oddenc) printf("#encoding %s\n", e->name);
+    if (fh.f & f_escape) fputs("#escape\n", stdout);
+  }
+  if (!argc)
+    rc = hashsum(&fh, 0, e);
+  else {
+    int i;
+    int rrc;
+
+    rc = 0;
+    for (i = 0; i < argc; i++) {
+      if ((rrc = hashsum(&fh, argv[i], e)) != 0)
+       rc = rrc;
+    }
+  }
+
+  if (fh.f & FHF_JUNK) {
+    if (fh.f & f_check) {
+      if (fhash_junk(&fh, checkjunk, &fh)) rc = EXIT_FAILURE;
+    } else {
+      if (fhash_junk(&fh, warnjunk, 0) < 0) rc = EXIT_FAILURE;
+    }
+  }
+  fhash_free(&fh);
+
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from key.1
rename to progs/key.1
diff --git a/progs/key.c b/progs/key.c
new file mode 100644 (file)
index 0000000..f263aaf
--- /dev/null
@@ -0,0 +1,2306 @@
+/* -*-c-*-
+ *
+ * Simple key manager program
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include "config.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <mLib/base64.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include <noise.h>
+#include <rand.h>
+
+#include "bintab.h"
+#include "bbs.h"
+#include "dh.h"
+#include "dsa.h"
+#include "dsarand.h"
+#include "ec.h"
+#include "ec-keys.h"
+#include "ectab.h"
+#include "fibrand.h"
+#include "getdate.h"
+#include "gfreduce.h"
+#include "key.h"
+#include "mp.h"
+#include "mpmont.h"
+#include "mprand.h"
+#include "mptext.h"
+#include "pgen.h"
+#include "ptab.h"
+#include "rsa.h"
+
+#include "cc.h"
+#include "sha-mgf.h"
+#include "sha256-mgf.h"
+#include "sha224-mgf.h"
+#include "sha384-mgf.h"
+#include "sha512-mgf.h"
+#include "tiger-mgf.h"
+#include "rmd128-mgf.h"
+#include "rmd160-mgf.h"
+#include "rmd256-mgf.h"
+#include "rmd320-mgf.h"
+#include "md5-mgf.h"
+#include "dsarand.h"
+
+/*----- Handy global state ------------------------------------------------*/
+
+static const char *keyfile = "keyring";
+
+/*----- Useful shared functions -------------------------------------------*/
+
+/* --- @doopen@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *             @unsigned how@ = method to open file with
+ *
+ * Returns:    ---
+ *
+ * Use:                Opens a key file and handles errors by panicking
+ *             appropriately.
+ */
+
+static void doopen(key_file *f, unsigned how)
+{
+  if (key_open(f, keyfile, how, key_moan, 0))
+    die(1, "couldn't open keyring `%s': %s", keyfile, strerror(errno));
+}
+
+/* --- @doclose@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *
+ * Returns:    ---
+ *
+ * Use:                Closes a key file and handles errors by panicking
+ *             appropriately.
+ */
+
+static void doclose(key_file *f)
+{
+  switch (key_close(f)) {
+    case KWRITE_FAIL:
+      die(EXIT_FAILURE, "couldn't write file `%s': %s",
+         keyfile, strerror(errno));
+    case KWRITE_BROKEN:
+      die(EXIT_FAILURE, "keyring file `%s' broken: %s (repair manually)",
+         keyfile, strerror(errno));
+  }
+}
+
+/* --- @setattr@ --- *
+ *
+ * Arguments:  @key_file *f@ = pointer to key file block
+ *             @key *k@ = pointer to key block
+ *             @char *v[]@ = array of assignments (overwritten!)
+ *
+ * Returns:    ---
+ *
+ * Use:                Applies the attribute assignments to the key.
+ */
+
+static void setattr(key_file *f, key *k, char *v[])
+{
+  while (*v) {
+    int err;
+    char *p = *v;
+    size_t eq = strcspn(p, "=");
+    if (!p[eq]) {
+      moan("invalid assignment: `%s' (ignored)", p);
+      v++;
+      continue;
+    }
+    p[eq] = 0;
+    p += eq + 1;
+    if ((err = key_putattr(f, k, *v, *p ? p : 0)) != 0)
+      die(EXIT_FAILURE, "couldn't set attributes: %s", key_strerror(err));
+    v++;
+  }
+}
+
+/*----- Seeding -----------------------------------------------------------*/
+
+const struct seedalg { const char *p; grand *(*gen)(const void *, size_t); }
+seedtab[] = {
+  { "dsarand", dsarand_create },
+  { "rmd128-mgf", rmd128_mgfrand },
+  { "rmd160-mgf", rmd160_mgfrand },
+  { "rmd256-mgf", rmd256_mgfrand },
+  { "rmd320-mgf", rmd320_mgfrand },
+  { "sha-mgf", sha_mgfrand },
+  { "sha224-mgf", sha224_mgfrand },
+  { "sha256-mgf", sha256_mgfrand },
+  { "sha384-mgf", sha384_mgfrand },
+  { "sha512-mgf", sha512_mgfrand },
+  { "tiger-mgf", tiger_mgfrand },
+  { 0, 0 }
+};
+
+#define SEEDALG_DEFAULT (seedtab + 2)
+
+/*----- Key generation ----------------------------------------------------*/
+
+/* --- Key generation parameters --- */
+
+typedef struct keyopts {
+  key_file *kf;                                /* Pointer to key file */
+  key *k;                              /* Pointer to the actual key */
+  dstr tag;                            /* Full tag name for the key */
+  unsigned f;                          /* Flags for the new key */
+  unsigned bits, qbits;                        /* Bit length for the new key */
+  const char *curve;                   /* Elliptic curve name/info */
+  grand *r;                            /* Random number source */
+  key *p;                              /* Parameters key-data */
+} keyopts;
+
+#define f_bogus 1u                     /* Error in parsing */
+#define f_lock 2u                      /* Passphrase-lock private key */
+#define f_quiet 4u                     /* Don't show a progress indicator */
+#define f_limlee 8u                    /* Generate Lim-Lee primes */
+#define f_subgroup 16u                 /* Generate a subgroup */
+#define f_retag 32u                    /* Remove any existing tag */
+#define f_kcdsa 64u                    /* Generate KCDSA primes */
+
+/* --- @dolock@ --- *
+ *
+ * Arguments:  @keyopts *k@ = key generation options
+ *             @key_data **kd@ = pointer to key data to lock
+ *             @const char *t@ = tag suffix or null
+ *
+ * Returns:    ---
+ *
+ * Use:                Does passphrase locking on new keys.
+ */
+
+static void dolock(keyopts *k, key_data **kd, const char *t)
+{
+  if (!(k->f & f_lock))
+    return;
+  if (t)
+    dstr_putf(&k->tag, ".%s", t);
+  if (key_plock(kd, 0, k->tag.buf))
+    die(EXIT_FAILURE, "couldn't lock key");
+}
+
+/* --- @copyparam@ --- *
+ *
+ * Arguments:  @keyopts *k@ = pointer to key options
+ *             @const char **pp@ = checklist of parameters
+ *
+ * Returns:    Nonzero if parameters copied; zero if you have to generate
+ *             them.
+ *
+ * Use:                Copies parameters from a source key to the current one.
+ */
+
+static int copyparam(keyopts *k, const char **pp)
+{
+  key_filter kf;
+  key_attriter i;
+  key_data *kd;
+  const char *n, *v;
+
+  kf.f = KCAT_SHARE;
+  kf.m = KF_CATMASK;
+
+  /* --- Quick check if no parameters supplied --- */
+
+  if (!k->p)
+    return (0);
+
+  /* --- Run through the checklist --- */
+
+  while (*pp) {
+    key_data *kd = key_structfind(k->p->k, *pp);
+    if (!kd)
+      die(EXIT_FAILURE, "bad parameter key: parameter `%s' not found", *pp);
+    if (!KEY_MATCH(kd, &kf))
+      die(EXIT_FAILURE, "bad parameter key: subkey `%s' is not shared", *pp);
+    pp++;
+  }
+
+  /* --- Copy over the parameters --- */
+
+  kd = key_copydata(k->p->k, &kf);
+  assert(kd);
+  key_setkeydata(k->kf, k->k, kd);
+  key_drop(kd);
+
+  /* --- Copy over attributes --- */
+
+  for (key_mkattriter(&i, k->p); key_nextattr(&i, &n, &v); )
+    key_putattr(k->kf, k->k, n, v);
+
+  /* --- Done --- */
+
+  return (1);
+}
+
+/* --- @getmp@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const char *tag@ = tag string to use
+ *
+ * Returns:    Pointer to multiprecision integer key item.
+ *
+ * Use:                Fetches an MP key component.
+ */
+
+static mp *getmp(key_data *k, const char *tag)
+{
+  k = key_structfind(k, tag);
+  if (!k)
+    die(EXIT_FAILURE, "unexpected failure looking up subkey `%s'", tag);
+  if ((k->e & KF_ENCMASK) != KENC_MP)
+    die(EXIT_FAILURE, "subkey `%s' has an incompatible type");
+  return (k->u.m);
+}
+
+/* --- @keyrand@ --- *
+ *
+ * Arguments:  @key_file *kf@ = pointer to key file
+ *             @const char *id@ = pointer to key id (or null)
+ *
+ * Returns:    ---
+ *
+ * Use:                Keys the random number generator.
+ */
+
+static void keyrand(key_file *kf, const char *id)
+{
+  key *k;
+
+  /* --- Find the key --- */
+
+  if (id) {
+    if ((k = key_bytag(kf, id)) == 0)
+      die(EXIT_FAILURE, "key `%s' not found", id);
+  } else
+    k = key_bytype(kf, "catacomb-rand");
+
+  if (k) {
+    key_data *kd = k->k, *kkd;
+    key_incref(kd);
+
+  again:
+    switch (kd->e & KF_ENCMASK) {
+      case KENC_BINARY:
+       break;
+      case KENC_ENCRYPT: {
+       dstr d = DSTR_INIT;
+       key_fulltag(k, &d);
+       if (key_punlock(&kkd, kd, d.buf))
+         die(EXIT_FAILURE, "error unlocking key `%s'", d.buf);
+       dstr_destroy(&d);
+       key_drop(kd);
+       kd = kkd;
+      } goto again;
+      default: {
+       dstr d = DSTR_INIT;
+       key_fulltag(k, &d);
+       die(EXIT_FAILURE, "bad encoding type for key `%s'", d.buf);
+      } break;
+    }
+
+    /* --- Key the generator --- */
+
+    rand_key(RAND_GLOBAL, kd->u.k.k, kd->u.k.sz);
+    key_drop(kd);
+  }
+}
+
+/* --- Key generation algorithms --- */
+
+static void alg_binary(keyopts *k)
+{
+  unsigned sz;
+  unsigned m;
+  key_data *kd;
+  octet *p;
+
+  if (!k->bits)
+    k->bits = 128;
+  if (k->p)
+    die(EXIT_FAILURE, "no shared parameters for binary keys");
+
+  sz = (k->bits + 7) >> 3;
+  p = sub_alloc(sz);
+  m = (1 << (((k->bits - 1) & 7) + 1)) - 1;
+  k->r->ops->fill(k->r, p, sz);
+  *p &= m;
+  kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz);
+  memset(p, 0, sz);
+  dolock(k, &kd, 0);
+  key_setkeydata(k->kf, k->k, kd);
+  key_drop(kd);
+  sub_free(p, sz);
+}
+
+static void alg_des(keyopts *k)
+{
+  unsigned sz;
+  octet *p;
+  key_data *kd;
+  int i;
+
+  if (!k->bits)
+    k->bits = 168;
+  if (k->p)
+    die(EXIT_FAILURE, "no shared parameters for DES keys");
+  if (k->bits % 56 || k->bits > 168)
+    die(EXIT_FAILURE, "DES keys must be 56, 112 or 168 bits long");
+
+  sz = k->bits / 7;
+  p = sub_alloc(sz);
+  k->r->ops->fill(k->r, p, sz);
+  for (i = 0; i < sz; i++) {
+    octet x = p[i] | 0x01;
+    x = x ^ (x >> 4);
+    x = x ^ (x >> 2);
+    x = x ^ (x >> 1);
+    p[i] = (p[i] & 0xfe) | (x & 0x01);
+  }
+  kd = key_newbinary(KCAT_SYMM | KF_BURN, p, sz);
+  memset(p, 0, sz);
+  dolock(k, &kd, 0);
+  key_setkeydata(k->kf, k->k, kd);
+  key_drop(kd);
+  sub_free(p, sz);
+}
+
+static void alg_rsa(keyopts *k)
+{
+  rsa_priv rp;
+  key_data *kd, *kkd;
+
+  /* --- Sanity checking --- */
+
+  if (k->p)
+    die(EXIT_FAILURE, "no shared parameters for RSA keys");
+  if (!k->bits)
+    k->bits = 1024;
+
+  /* --- Generate the RSA parameters --- */
+
+  if (rsa_gen(&rp, k->bits, k->r, 0,
+             (k->f & f_quiet) ? 0 : pgen_ev, 0))
+    die(EXIT_FAILURE, "RSA key generation failed");
+
+  /* --- Run a test encryption --- */
+
+  {
+    grand *g = fibrand_create(k->r->ops->word(k->r));
+    rsa_pub rpp;
+    mp *m = mprand_range(MP_NEW, rp.n, g, 0);
+    mp *c;
+
+    rpp.n = rp.n;
+    rpp.e = rp.e;
+    c = rsa_qpubop(&rpp, MP_NEW, m);
+    c = rsa_qprivop(&rp, c, c, g);
+
+    if (!MP_EQ(c, m))
+      die(EXIT_FAILURE, "test encryption failed");
+    mp_drop(c);
+    mp_drop(m);
+    g->ops->destroy(g);
+  }
+
+  /* --- Allrighty then --- */
+
+  kd = key_newstruct();
+  key_structsteal(kd, "n", key_newmp(KCAT_PUB, rp.n));
+  key_structsteal(kd, "e", key_newmp(KCAT_PUB, rp.e));
+
+  kkd = key_newstruct();
+  key_structsteal(kkd, "d", key_newmp(KCAT_PRIV | KF_BURN, rp.d));
+  key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, rp.p));
+  key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, rp.q));
+  key_structsteal(kkd, "q-inv", key_newmp(KCAT_PRIV | KF_BURN, rp.q_inv));
+  key_structsteal(kkd, "d-mod-p", key_newmp(KCAT_PRIV | KF_BURN, rp.dp));
+  key_structsteal(kkd, "d-mod-q", key_newmp(KCAT_PRIV | KF_BURN, rp.dq));
+  dolock(k, &kkd, "private");
+  key_structsteal(kd, "private", kkd);
+  key_setkeydata(k->kf, k->k, kd);
+  key_drop(kd);
+  rsa_privfree(&rp);
+}
+
+static void alg_dsaparam(keyopts *k)
+{
+  static const char *pl[] = { "q", "p", "g", 0 };
+  if (!copyparam(k, pl)) {
+    dsa_param dp;
+    octet *p;
+    size_t sz;
+    dstr d = DSTR_INIT;
+    base64_ctx c;
+    key_data *kd;
+    dsa_seed ds;
+
+    /* --- Choose appropriate bit lengths if necessary --- */
+
+    if (!k->qbits)
+      k->qbits = 160;
+    if (!k->bits)
+      k->bits = 1024;
+
+    /* --- Allocate a seed block --- */
+
+    sz = (k->qbits + 7) >> 3;
+    p = sub_alloc(sz);
+    k->r->ops->fill(k->r, p, sz);
+
+    /* --- Allocate the parameters --- */
+
+    if (dsa_gen(&dp, k->qbits, k->bits, 0, p, sz, &ds,
+               (k->f & f_quiet) ? 0 : pgen_ev, 0))
+      die(EXIT_FAILURE, "DSA parameter generation failed");
+
+    /* --- Store the parameters --- */
+
+    kd = key_newstruct();
+    key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q));
+    key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p));
+    key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g));
+    mp_drop(dp.q);
+    mp_drop(dp.p);
+    mp_drop(dp.g);
+    key_setkeydata(k->kf, k->k, kd);
+    key_drop(kd);
+
+    /* --- Store the seed for future verification --- */
+
+    base64_init(&c);
+    c.maxline = 0;
+    c.indent = "";
+    base64_encode(&c, ds.p, ds.sz, &d);
+    base64_encode(&c, 0, 0, &d);
+    DPUTZ(&d);
+    key_putattr(k->kf, k->k, "seed", d.buf);
+    DRESET(&d);
+    dstr_putf(&d, "%u", ds.count);
+    key_putattr(k->kf, k->k, "count", d.buf);
+    xfree(ds.p);
+    sub_free(p, sz);
+    dstr_destroy(&d);
+  }
+}
+
+static void alg_dsa(keyopts *k)
+{
+  mp *q, *p, *g;
+  mp *x, *y;
+  mpmont mm;
+  key_data *kd, *kkd;
+
+  /* --- Get the shared parameters --- */
+
+  alg_dsaparam(k);
+  key_split(&k->k->k); kd = k->k->k;
+  q = getmp(kd, "q");
+  p = getmp(kd, "p");
+  g = getmp(kd, "g");
+
+  /* --- Choose a private key --- */
+
+  x = mprand_range(MP_NEWSEC, q, k->r, 0);
+  mpmont_create(&mm, p);
+  y = mpmont_exp(&mm, MP_NEW, g, x);
+
+  /* --- Store everything away --- */
+
+  key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
+
+  kkd = key_newstruct();
+  key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
+  dolock(k, &kkd, "private");
+  key_structsteal(kd, "private", kkd);
+
+  mp_drop(x); mp_drop(y);
+}
+
+static void alg_dhparam(keyopts *k)
+{
+  static const char *pl[] = { "p", "q", "g", 0 };
+  key_data *kd;
+  if (!copyparam(k, pl)) {
+    dh_param dp;
+    int rc;
+
+    if (k->curve) {
+      qd_parse qd;
+      group *g;
+      const char *e;
+
+      if (strcmp(k->curve, "list") == 0) {
+       unsigned i, w;
+       LIST("Built-in prime fields", stdout, ptab[i].name, ptab[i].name);
+       exit(0);
+      }
+      qd.p = k->curve;
+      if (dh_parse(&qd, &dp))
+       die(EXIT_FAILURE, "error in field spec: %s", qd.e);
+      if (!qd_eofp(&qd))
+       die(EXIT_FAILURE, "junk at end of field spec");
+      if ((g = group_prime(&dp)) == 0)
+       die(EXIT_FAILURE, "invalid prime field");
+      if (!(k->f & f_quiet) && (e = G_CHECK(g, &rand_global)) != 0)
+       moan("WARNING!  group check failed: %s", e);
+      G_DESTROYGROUP(g);
+      goto done;
+    }
+
+    if (!k->bits)
+      k->bits = 1024;
+
+    /* --- Choose a large safe prime number --- */
+
+    if (k->f & f_limlee) {
+      mp **f;
+      size_t nf;
+      if (!k->qbits)
+       k->qbits = 256;
+      rc = dh_limlee(&dp, k->qbits, k->bits,
+                    (k->f & f_subgroup) ? DH_SUBGROUP : 0,
+                    0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0,
+                    (k->f & f_quiet) ? 0 : pgen_evspin, 0, &nf, &f);
+      if (!rc) {
+       dstr d = DSTR_INIT;
+       size_t i;
+       for (i = 0; i < nf; i++) {
+         if (i)
+           dstr_puts(&d, ", ");
+         mp_writedstr(f[i], &d, 10);
+         mp_drop(f[i]);
+       }
+       key_putattr(k->kf, k->k, "factors", d.buf);
+       dstr_destroy(&d);
+      }
+    } else if (k->f & f_kcdsa) {
+      if (!k->qbits)
+       k->qbits = 256;
+      rc = dh_kcdsagen(&dp, k->qbits, k->bits, 0,
+                      0, k->r, (k->f & f_quiet) ? 0 : pgen_ev, 0);
+      if (!rc) {
+       dstr d = DSTR_INIT;
+       mp *v = MP_NEW;
+
+       mp_writedstr(dp.q, &d, 10);
+       mp_div(&v, 0, dp.p, dp.q);
+       v = mp_lsr(v, v, 1);
+       dstr_puts(&d, ", ");
+       mp_writedstr(v, &d, 10);
+       mp_drop(v);
+       key_putattr(k->kf, k->k, "factors", d.buf);
+       dstr_destroy(&d);
+      }
+    } else
+      rc = dh_gen(&dp, k->qbits, k->bits, 0, k->r,
+                 (k->f & f_quiet) ? 0 : pgen_ev, 0);
+
+    if (rc)
+      die(EXIT_FAILURE, "Diffie-Hellman parameter generation failed");
+
+  done:
+    kd = key_newstruct();
+    key_structsteal(kd, "p", key_newmp(KCAT_SHARE, dp.p));
+    key_structsteal(kd, "q", key_newmp(KCAT_SHARE, dp.q));
+    key_structsteal(kd, "g", key_newmp(KCAT_SHARE, dp.g));
+    mp_drop(dp.q);
+    mp_drop(dp.p);
+    mp_drop(dp.g);
+    key_setkeydata(k->kf, k->k, kd);
+    key_drop(kd);
+  }
+}
+
+static void alg_dh(keyopts *k)
+{
+  mp *x, *y;
+  mp *p, *q, *g;
+  mpmont mm;
+  key_data *kd, *kkd;
+
+  /* --- Get the shared parameters --- */
+
+  alg_dhparam(k);
+  key_split(&k->k->k); kd = k->k->k;
+  p = getmp(kd, "p");
+  q = getmp(kd, "q");
+  g = getmp(kd, "g");
+
+  /* --- Choose a suitable private key --- *
+   *
+   * Since %$g$% has order %$q$%, choose %$x < q$%.
+   */
+
+  x = mprand_range(MP_NEWSEC, q, k->r, 0);
+
+  /* --- Compute the public key %$y = g^x \bmod p$% --- */
+
+  mpmont_create(&mm, p);
+  y = mpmont_exp(&mm, MP_NEW, g, x);
+  mpmont_destroy(&mm);
+
+  /* --- Store everything away --- */
+
+  key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
+
+  kkd = key_newstruct();
+  key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
+  dolock(k, &kkd, "private");
+  key_structsteal(kd, "private", kkd);
+
+  mp_drop(x); mp_drop(y);
+}
+
+static void alg_bbs(keyopts *k)
+{
+  bbs_priv bp;
+  key_data *kd, *kkd;
+
+  /* --- Sanity checking --- */
+
+  if (k->p)
+    die(EXIT_FAILURE, "no shared parameters for Blum-Blum-Shub keys");
+  if (!k->bits)
+    k->bits = 1024;
+
+  /* --- Generate the BBS parameters --- */
+
+  if (bbs_gen(&bp, k->bits, k->r, 0,
+             (k->f & f_quiet) ? 0 : pgen_ev, 0))
+    die(EXIT_FAILURE, "Blum-Blum-Shub key generation failed");
+
+  /* --- Allrighty then --- */
+
+  kd = key_newstruct();
+  key_structsteal(kd, "n", key_newmp(KCAT_PUB, bp.n));
+
+  kkd = key_newstruct();
+  key_structsteal(kkd, "p", key_newmp(KCAT_PRIV | KF_BURN, bp.p));
+  key_structsteal(kkd, "q", key_newmp(KCAT_PRIV | KF_BURN, bp.q));
+  dolock(k, &kkd, "private");
+  key_structsteal(kd, "private", kkd);
+  key_setkeydata(k->kf, k->k, kd);
+  key_drop(kd);
+
+  bbs_privfree(&bp);
+}
+
+static void alg_binparam(keyopts *k)
+{
+  static const char *pl[] = { "p", "q", "g", 0 };
+  if (!copyparam(k, pl)) {
+    gbin_param gb;
+    qd_parse qd;
+    group *g;
+    const char *e;
+    key_data *kd;
+
+    /* --- Decide on a field --- */
+
+    if (!k->bits) k->bits = 128;
+    if (k->curve && strcmp(k->curve, "list") == 0) {
+      unsigned i, w;
+      LIST("Built-in binary fields", stdout,
+          bintab[i].name, bintab[i].name);
+      exit(0);
+    }
+    if (!k->curve) {
+      if (k->bits <= 40) k->curve = "p1363-40";
+      else if (k->bits <= 56) k->curve = "p1363-56";
+      else if (k->bits <= 64) k->curve = "p1363-64";
+      else if (k->bits <= 80) k->curve = "p1363-80";
+      else if (k->bits <= 112) k->curve = "p1363-112";
+      else if (k->bits <= 128) k->curve = "p1363-128";
+      else {
+       die(EXIT_FAILURE,
+           "no built-in binary fields provide %u-bit security",
+           k->bits);
+      }
+    }
+
+    /* --- Check it --- */
+
+    qd.e = 0;
+    qd.p = k->curve;
+    if (dhbin_parse(&qd, &gb))
+      die(EXIT_FAILURE, "error in field spec: %s", qd.e);
+    if (!qd_eofp(&qd))
+      die(EXIT_FAILURE, "junk at end of field spec");
+    if ((g = group_binary(&gb)) == 0)
+      die(EXIT_FAILURE, "invalid binary field");
+    if (!(k->f & f_quiet) && (e = G_CHECK(g, &rand_global)) != 0)
+      moan("WARNING!  group check failed: %s", e);
+    G_DESTROYGROUP(g);
+
+    /* --- Write out the answer --- */
+
+    kd = key_newstruct();
+    key_structsteal(kd, "p", key_newmp(KCAT_SHARE, gb.p));
+    key_structsteal(kd, "q", key_newmp(KCAT_SHARE, gb.q));
+    key_structsteal(kd, "g", key_newmp(KCAT_SHARE, gb.g));
+    mp_drop(gb.q);
+    mp_drop(gb.p);
+    mp_drop(gb.g);
+    key_setkeydata(k->kf, k->k, kd);
+    key_drop(kd);
+  }
+}
+
+static void alg_bin(keyopts *k)
+{
+  mp *x, *y;
+  mp *p, *q, *g;
+  gfreduce r;
+  key_data *kd, *kkd;
+
+  /* --- Get the shared parameters --- */
+
+  alg_binparam(k);
+  key_split(&k->k->k); kd = k->k->k;
+  p = getmp(kd, "p");
+  q = getmp(kd, "q");
+  g = getmp(kd, "g");
+
+  /* --- Choose a suitable private key --- *
+   *
+   * Since %$g$% has order %$q$%, choose %$x < q$%.
+   */
+
+  x = mprand_range(MP_NEWSEC, q, k->r, 0);
+
+  /* --- Compute the public key %$y = g^x \bmod p$% --- */
+
+  gfreduce_create(&r, p);
+  y = gfreduce_exp(&r, MP_NEW, g, x);
+  gfreduce_destroy(&r);
+
+  /* --- Store everything away --- */
+
+  key_structsteal(kd, "y", key_newmp(KCAT_PUB, y));
+
+  kkd = key_newstruct();
+  key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
+  dolock(k, &kkd, "private");
+  key_structsteal(kd, "private", kkd);
+
+  mp_drop(x); mp_drop(y);
+}
+
+static void alg_ecparam(keyopts *k)
+{
+  static const char *pl[] = { "curve", 0 };
+  if (!copyparam(k, pl)) {
+    ec_info ei;
+    const char *e;
+    key_data *kd;
+
+    /* --- Decide on a curve --- */
+
+    if (!k->bits) k->bits = 256;
+    if (k->curve && strcmp(k->curve, "list") == 0) {
+      unsigned i, w;
+      LIST("Built-in elliptic curves", stdout,
+          ectab[i].name, ectab[i].name);
+      exit(0);
+    }
+    if (!k->curve) {
+      if (k->bits <= 56) k->curve = "secp112r1";
+      else if (k->bits <= 64) k->curve = "secp128r1";
+      else if (k->bits <= 80) k->curve = "secp160r1";
+      else if (k->bits <= 96) k->curve = "secp192r1";
+      else if (k->bits <= 112) k->curve = "secp224r1";
+      else if (k->bits <= 128) k->curve = "secp256r1";
+      else if (k->bits <= 192) k->curve = "secp384r1";
+      else if (k->bits <= 256) k->curve = "secp521r1";
+      else
+       die(EXIT_FAILURE, "no built-in curves provide %u-bit security",
+           k->bits);
+    }
+
+    /* --- Check it --- */
+
+    if ((e = ec_getinfo(&ei, k->curve)) != 0)
+      die(EXIT_FAILURE, "error in curve spec: %s", e);
+    if (!(k->f & f_quiet) && (e = ec_checkinfo(&ei, k->r)) != 0)
+      moan("WARNING!  curve check failed: %s", e);
+    ec_freeinfo(&ei);
+
+    /* --- Write out the answer --- */
+
+    kd = key_newstruct();
+    key_structsteal(kd, "curve", key_newstring(KCAT_SHARE, k->curve));
+    key_setkeydata(k->kf, k->k, kd);
+    key_drop(kd);
+  }
+}
+
+static void alg_ec(keyopts *k)
+{
+  key_data *kd;
+  key_data *kkd;
+  mp *x = MP_NEW;
+  ec p = EC_INIT;
+  const char *e;
+  ec_info ei;
+
+  /* --- Get the curve --- */
+
+  alg_ecparam(k);
+  key_split(&k->k->k); kd = k->k->k;
+  if ((kkd = key_structfind(kd, "curve")) == 0)
+    die(EXIT_FAILURE, "unexpected failure looking up subkey `curve')");
+  if ((kkd->e & KF_ENCMASK) != KENC_STRING)
+    die(EXIT_FAILURE, "subkey `curve' is not a string");
+  if ((e = ec_getinfo(&ei, kkd->u.p)) != 0)
+    die(EXIT_FAILURE, "error in curve spec: %s", e);
+
+  /* --- Invent a private exponent and compute the public key --- */
+
+  x = mprand_range(MP_NEWSEC, ei.r, k->r, 0);
+  ec_mul(ei.c, &p, &ei.g, x);
+
+  /* --- Store everything away --- */
+
+  key_structsteal(kd, "p", key_newec(KCAT_PUB, &p));
+
+  kkd = key_newstruct();
+  key_structsteal(kkd, "x", key_newmp(KCAT_PRIV | KF_BURN, x));
+  dolock(k, &kkd, "private");
+  key_structsteal(kd, "private", kkd);
+
+  /* --- Done --- */
+
+  ec_freeinfo(&ei);
+  mp_drop(x);
+}
+
+/* --- The algorithm tables --- */
+
+typedef struct keyalg {
+  const char *name;
+  void (*proc)(keyopts *o);
+  const char *help;
+} keyalg;
+
+static keyalg algtab[] = {
+  { "binary",          alg_binary,     "Plain binary data" },
+  { "des",             alg_des,        "Binary with DES-style parity" },
+  { "rsa",             alg_rsa,        "RSA public-key encryption" },
+  { "bbs",             alg_bbs,        "Blum-Blum-Shub generator" },
+  { "dsa",             alg_dsa,        "DSA digital signatures" },
+  { "dsa-param",       alg_dsaparam,   "DSA shared parameters" },
+  { "dh",              alg_dh,         "Diffie-Hellman key exchange" },
+  { "dh-param",                alg_dhparam,    "Diffie-Hellman parameters" },
+  { "bindh",           alg_bin,        "DH over a binary field" },
+  { "bindh-param",     alg_binparam,   "Binary-field DH parameters" },
+  { "ec-param",                alg_ecparam,    "Elliptic curve parameters" },
+  { "ec",              alg_ec,         "Elliptic curve crypto" },
+  { 0,                 0 }
+};
+
+/* --- @cmd_add@ --- */
+
+static int cmd_add(int argc, char *argv[])
+{
+  key_file f;
+  time_t exp = KEXP_EXPIRE;
+  uint32 kid = rand_global.ops->word(&rand_global);
+  const char *tag = 0, *ptag = 0;
+  const char *c = 0;
+  keyalg *alg = algtab;
+  const char *rtag = 0;
+  const struct seedalg *sa = SEEDALG_DEFAULT;
+  keyopts k = { 0, 0, DSTR_INIT, 0, 0, 0, 0, 0 };
+  const char *seed = 0;
+  k.r = &rand_global;
+
+  /* --- Parse options for the subcommand --- */
+
+  for (;;) {
+    static struct option opt[] = {
+      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
+      { "bits",                OPTF_ARGREQ,    0,      'b' },
+      { "qbits",       OPTF_ARGREQ,    0,      'B' },
+      { "parameters",  OPTF_ARGREQ,    0,      'p' },
+      { "expire",      OPTF_ARGREQ,    0,      'e' },
+      { "comment",     OPTF_ARGREQ,    0,      'c' },
+      { "tag",         OPTF_ARGREQ,    0,      't' },
+      { "rand-id",     OPTF_ARGREQ,    0,      'R' },
+      { "key-id",      OPTF_ARGREQ,    0,      'I' },
+      { "curve",       OPTF_ARGREQ,    0,      'C' },
+      { "seedalg",     OPTF_ARGREQ,    0,      'A' },
+      { "seed",                OPTF_ARGREQ,    0,      's' },
+      { "newseed",     OPTF_ARGREQ,    0,      'n' },
+      { "lock",                0,              0,      'l' },
+      { "quiet",       0,              0,      'q' },
+      { "lim-lee",     0,              0,      'L' },
+      { "subgroup",    0,              0,      'S' },
+      { "kcdsa",       0,              0,      'K' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+a:b:B:p:e:c:t:R:I:C:A:s:n:lqrLKS",
+                  opt, 0, 0, 0);
+    if (i < 0)
+      break;
+
+    /* --- Handle the various options --- */
+
+    switch (i) {
+
+      /* --- Read an algorithm name --- */
+
+      case 'a': {
+       keyalg *a;
+       size_t sz = strlen(optarg);
+
+       if (strcmp(optarg, "list") == 0) {
+         for (a = algtab; a->name; a++)
+           printf("%-10s %s\n", a->name, a->help);
+         return (0);
+       }
+
+       alg = 0;
+       for (a = algtab; a->name; a++) {
+         if (strncmp(optarg, a->name, sz) == 0) {
+           if (a->name[sz] == 0) {
+             alg = a;
+             break;
+           } else if (alg)
+             die(EXIT_FAILURE, "ambiguous algorithm name `%s'", optarg);
+           else
+             alg = a;
+         }
+       }
+       if (!alg)
+         die(EXIT_FAILURE, "unknown algorithm name `%s'", optarg);
+      } break;
+
+      /* --- Bits must be nonzero and a multiple of 8 --- */
+
+      case 'b': {
+       char *p;
+       k.bits = strtoul(optarg, &p, 0);
+       if (k.bits == 0 || *p != 0)
+         die(EXIT_FAILURE, "bad bitlength `%s'", optarg);
+      } break;
+
+      case 'B': {
+       char *p;
+       k.qbits = strtoul(optarg, &p, 0);
+       if (k.qbits == 0 || *p != 0)
+         die(EXIT_FAILURE, "bad bitlength `%s'", optarg);
+      } break;
+
+      /* --- Parameter selection --- */
+
+      case 'p':
+       ptag = optarg;
+       break;
+
+      /* --- Expiry dates get passed to @get_date@ for parsing --- */
+
+      case 'e':
+       if (strcmp(optarg, "forever") == 0)
+         exp = KEXP_FOREVER;
+       else {
+         exp = get_date(optarg, 0);
+         if (exp == -1)
+           die(EXIT_FAILURE, "bad expiry date `%s'", optarg);
+       }
+       break;
+
+      /* --- Store comments without interpretation --- */
+
+      case 'c':
+       if (key_chkcomment(optarg))
+         die(EXIT_FAILURE, "bad comment string `%s'", optarg);
+       c = optarg;
+       break;
+
+      /* --- Elliptic curve parameters --- */
+
+      case 'C':
+       k.curve = optarg;
+       break;
+
+      /* --- Store tags --- */
+
+      case 't':
+       if (key_chkident(optarg))
+         die(EXIT_FAILURE, "bad tag string `%s'", optarg);
+       tag = optarg;
+       break;
+      case 'r':
+       k.f |= f_retag;
+       break;
+
+      /* --- Seeding --- */
+
+      case 'A': {
+       const struct seedalg *ss;
+       if (strcmp(optarg, "list") == 0) {
+         printf("Seed algorithms:\n");
+         for (ss = seedtab; ss->p; ss++)
+           printf("  %s\n", ss->p);
+         exit(0);
+       }
+       if (seed) die(EXIT_FAILURE, "seed already set -- put -A first");
+       sa = 0;
+       for (ss = seedtab; ss->p; ss++) {
+         if (strcmp(optarg, ss->p) == 0)
+           sa = ss;
+       }
+       if (!sa)
+         die(EXIT_FAILURE, "seed algorithm `%s' not known", optarg);
+      } break;
+
+      case 's': {
+       base64_ctx b;
+       dstr d = DSTR_INIT;
+       if (seed) die(EXIT_FAILURE, "seed already set");
+       base64_init(&b);
+       base64_decode(&b, optarg, strlen(optarg), &d);
+       base64_decode(&b, 0, 0, &d);
+       k.r = sa->gen(d.buf, d.len);
+       seed = optarg;
+       dstr_destroy(&d);
+      } break;
+
+      case 'n': {
+       base64_ctx b;
+       dstr d = DSTR_INIT;
+       char *p;
+       unsigned n = strtoul(optarg, &p, 0);
+       if (n == 0 || *p != 0 || n % 8 != 0)
+         die(EXIT_FAILURE, "bad seed length `%s'", optarg);
+       if (seed) die(EXIT_FAILURE, "seed already set");
+       n /= 8;
+       p = xmalloc(n);
+       rand_get(RAND_GLOBAL, p, n);
+       base64_init(&b);
+       base64_encode(&b, p, n, &d);
+       base64_encode(&b, 0, 0, &d);
+       seed = d.buf;
+       k.r = sa->gen(p, n);
+      } break;
+
+      /* --- Key id --- */
+
+      case 'I': {
+       char *p;
+       unsigned long id;
+
+       errno = 0;
+       id = strtoul(optarg, &p, 16);
+       if (errno || *p || id > MASK32)
+         die(EXIT_FAILURE, "bad key-id `%s'", optarg);
+       kid = id;
+      } break;
+
+      /* --- Other flags --- */
+
+      case 'R':
+       rtag = optarg;
+       break;
+      case 'l':
+       k.f |= f_lock;
+       break;
+      case 'q':
+       k.f |= f_quiet;
+       break;
+      case 'L':
+       k.f |= f_limlee;
+       break;
+      case 'K':
+       k.f |= f_kcdsa;
+       break;
+      case 'S':
+       k.f |= f_subgroup;
+       break;
+
+      /* --- Other things are bogus --- */
+
+      default:
+       k.f |= f_bogus;
+       break;
+    }
+  }
+
+  /* --- Various sorts of bogosity --- */
+
+  if ((k.f & f_bogus) || optind + 1 > argc) {
+    die(EXIT_FAILURE,
+       "Usage: add [OPTIONS] TYPE [ATTR...]");
+  }
+  if (key_chkident(argv[optind]))
+    die(EXIT_FAILURE, "bad key type `%s'", argv[optind]);
+
+  /* --- Set up various bits of the state --- */
+
+  if (exp == KEXP_EXPIRE)
+    exp = time(0) + 14 * 24 * 60 * 60;
+
+  /* --- Open the file and create the basic key block --- *
+   *
+   * Keep on generating keyids until one of them doesn't collide.
+   */
+
+  doopen(&f, KOPEN_WRITE);
+  k.kf = &f;
+
+  /* --- Key the generator --- */
+
+  keyrand(&f, rtag);
+
+  for (;;) {
+    int err;
+    if ((err = key_new(&f, kid, argv[optind], exp, &k.k)) == 0)
+      break;
+    else if (err != KERR_DUPID)
+      die(EXIT_FAILURE, "error adding new key: %s", key_strerror(err));
+  }
+
+  /* --- Set various simple attributes --- */
+
+  if (tag) {
+    int err;
+    key *kk;
+    if (k.f & f_retag) {
+      if ((kk = key_bytag(&f, tag)) != 0 &&
+         kk->tag &&
+         strcmp(kk->tag, tag) == 0)
+       key_settag(&f, kk, 0);
+    }
+    if ((err = key_settag(&f, k.k, tag)) != 0)
+      die(EXIT_FAILURE, "error setting key tag: %s", key_strerror(err));
+  }
+
+  if (c) {
+    int err = key_setcomment(&f, k.k, c);
+    if (err)
+      die(EXIT_FAILURE, "error setting key comment: %s", key_strerror(err));
+  }
+
+  setattr(&f, k.k, argv + optind + 1);
+  if (seed) {
+    key_putattr(&f, k.k, "genseed", seed);
+    key_putattr(&f, k.k, "seedalg", sa->p);
+  }
+
+  key_fulltag(k.k, &k.tag);
+
+  /* --- Find the parameter key --- */
+
+  if (ptag) {
+    if ((k.p = key_bytag(&f, ptag)) == 0)
+      die(EXIT_FAILURE, "parameter key `%s' not found", ptag);
+    if ((k.p->k->e & KF_ENCMASK) != KENC_STRUCT)
+      die(EXIT_FAILURE, "parameter key `%s' is not structured", ptag);
+  }
+
+  /* --- Now generate the actual key data --- */
+
+  alg->proc(&k);
+
+  /* --- Done --- */
+
+  dstr_destroy(&k.tag);
+  doclose(&f);
+  return (0);
+}
+
+/*----- Key listing -------------------------------------------------------*/
+
+/* --- Listing options --- */
+
+typedef struct listopts {
+  const char *tfmt;                    /* Date format (@strftime@-style) */
+  int v;                               /* Verbosity level */
+  unsigned f;                          /* Various flags */
+  time_t t;                            /* Time now (for key expiry) */
+  key_filter kf;                       /* Filter for matching keys */
+} listopts;
+
+/* --- Listing flags --- */
+
+#define f_newline 2u                   /* Write newline before next entry */
+#define f_attr 4u                      /* Written at least one attribute */
+#define f_utc 8u                       /* Emit UTC time, not local time */
+
+/* --- @showkeydata@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key to write
+ *             @int ind@ = indentation level
+ *             @listopts *o@ = listing options
+ *             @dstr *d@ = tag string for this subkey
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits a piece of key data in a human-readable format.
+ */
+
+static void showkeydata(key_data *k, int ind, listopts *o, dstr *d)
+{
+#define INDENT(i) do {                                                 \
+  int _i;                                                              \
+  for (_i = 0; _i < (i); _i++) {                                       \
+    putchar(' ');                                                      \
+  }                                                                    \
+} while (0)
+
+  switch (k->e & KF_ENCMASK) {
+
+    /* --- Binary key data --- *
+     *
+     * Emit as a simple hex dump.
+     */
+
+    case KENC_BINARY: {
+      const octet *p = k->u.k.k;
+      const octet *l = p + k->u.k.sz;
+      size_t sz = 0;
+
+      fputs(" {", stdout);
+      while (p < l) {
+       if (sz % 16 == 0) {
+         putchar('\n');
+         INDENT(ind + 2);
+       } else if (sz % 8 == 0)
+         fputs("  ", stdout);
+       else
+         putc(' ', stdout);
+       printf("%02x", *p++);
+       sz++;
+      }
+      putchar('\n');
+      INDENT(ind);
+      fputs("}\n", stdout);
+    } break;
+
+    /* --- Encrypted data --- *
+     *
+     * If the user is sufficiently keen, ask for a passphrase and decrypt the
+     * key.  Otherwise just say that it's encrypted and move on.
+     */
+
+    case KENC_ENCRYPT:
+      if (o->v <= 3)
+       fputs(" encrypted\n", stdout);
+      else {
+       key_data *kd;
+       if (key_punlock(&kd, k, d->buf))
+         printf(" <failed to unlock %s>\n", d->buf);
+       else {
+         fputs(" encrypted", stdout);
+         showkeydata(kd, ind, o, d);
+         key_drop(kd);
+       }
+      }
+      break;
+
+    /* --- Integer keys --- *
+     *
+     * Emit as a large integer in decimal.  This makes using the key in
+     * `calc' or whatever easier.
+     */
+
+    case KENC_MP:
+      putchar(' ');
+      mp_writefile(k->u.m, stdout, 10);
+      putchar('\n');
+      break;
+
+    /* --- Strings --- */
+
+    case KENC_STRING:
+      printf(" `%s'\n", k->u.p);
+      break;
+
+    /* --- Elliptic curve points --- */
+
+    case KENC_EC:
+      if (EC_ATINF(&k->u.e))
+       fputs(" inf\n", stdout);
+      else {
+       fputs(" 0x", stdout); mp_writefile(k->u.e.x, stdout, 16);
+       fputs(", 0x", stdout); mp_writefile(k->u.e.y, stdout, 16);
+       putchar('\n');
+      }
+      break;
+
+    /* --- Structured keys --- *
+     *
+     * Just iterate over the subkeys.
+     */
+
+    case KENC_STRUCT: {
+      key_subkeyiter i;
+      const char *tag;
+      size_t n = d->len;
+
+      fputs(" {\n", stdout);
+      for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &k); ) {
+       if (!key_match(k, &o->kf))
+         continue;
+       INDENT(ind + 2);
+       printf("%s =", tag);
+       d->len = n;
+       dstr_putf(d, ".%s", tag);
+       showkeydata(k, ind + 2, o, d);
+      }
+      INDENT(ind);
+      fputs("}\n", stdout);
+    } break;
+  }
+
+#undef INDENT
+}
+
+/* --- @showkey@ --- *
+ *
+ * Arguments:  @key *k@ = pointer to key to show
+ *             @listopts *o@ = pointer to listing options
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits a listing of a particular key.
+ */
+
+static void showkey(key *k, listopts *o)
+{
+  char ebuf[24], dbuf[24];
+  struct tm *tm;
+
+  /* --- Skip the key if the filter doesn't match --- */
+
+  if (!key_match(k->k, &o->kf))
+    return;
+
+  /* --- Sort out the expiry and deletion times --- */
+
+  if (KEY_EXPIRED(o->t, k->exp))
+    strcpy(ebuf, "expired");
+  else if (k->exp == KEXP_FOREVER)
+    strcpy(ebuf, "forever");
+  else {
+    tm = (o->f & f_utc) ? gmtime(&k->exp) : localtime(&k->exp);
+    strftime(ebuf, sizeof(ebuf), o->tfmt, tm);
+  }
+
+  if (KEY_EXPIRED(o->t, k->del))
+    strcpy(dbuf, "deleted");
+  else if (k->del == KEXP_FOREVER)
+    strcpy(dbuf, "forever");
+  else {
+    tm = (o->f & f_utc) ? gmtime(&k->del) : localtime(&k->del);
+    strftime(dbuf, sizeof(dbuf), o->tfmt, tm);
+  }
+
+  /* --- If in compact format, just display and quit --- */
+
+  if (!o->v) {
+    if (!(o->f & f_newline)) {
+      printf("%8s  %-20s  %-20s  %-10s  %s\n",
+            "Id", "Tag", "Type", "Expire", "Delete");
+    }
+    printf("%08lx  %-20s  %-20s  %-10s  %s\n",
+          (unsigned long)k->id, k->tag ? k->tag : "<none>",
+          k->type, ebuf, dbuf);
+    o->f |= f_newline;
+    return;
+  }
+
+  /* --- Display the standard header --- */
+
+  if (o->f & f_newline)
+    fputc('\n', stdout);
+  printf("keyid: %08lx\n", (unsigned long)k->id);
+  printf("tag: %s\n", k->tag ? k->tag : "<none>");
+  printf("type: %s\n", k->type);
+  printf("expiry: %s\n", ebuf);
+  printf("delete: %s\n", dbuf);
+  printf("comment: %s\n", k->c ? k->c : "<none>");
+
+  /* --- Display the attributes --- */
+
+  if (o->v > 1) {
+    key_attriter i;
+    const char *av, *an;
+
+    o->f &= ~f_attr;
+    printf("attributes:");
+    for (key_mkattriter(&i, k); key_nextattr(&i, &an, &av); ) {
+      printf("\n  %s = %s", an, av);
+      o->f |= f_attr;
+    }
+    if (o->f & f_attr)
+      fputc('\n', stdout);
+    else
+      puts(" <none>");
+  }
+
+  /* --- If dumping requested, dump the raw key data --- */
+
+  if (o->v > 2) {
+    dstr d = DSTR_INIT;
+    fputs("key:", stdout);
+    key_fulltag(k, &d);
+    showkeydata(k->k, 0, o, &d);
+    dstr_destroy(&d);
+  }
+
+  o->f |= f_newline;
+}
+
+/* --- @cmd_list@ --- */
+
+static int cmd_list(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  listopts o = { 0, 0, 0, 0, { 0, 0 } };
+
+  /* --- Parse subcommand options --- */
+
+  for (;;) {
+    static struct option opt[] = {
+      { "quiet",       0,              0,      'q' },
+      { "verbose",     0,              0,      'v' },
+      { "utc",         0,              0,      'u' },
+      { "filter",      OPTF_ARGREQ,    0,      'f' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+uqvf:", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+
+    switch (i) {
+      case 'u':
+       o.f |= f_utc;
+       break;
+      case 'q':
+       if (o.v)
+         o.v--;
+       break;
+      case 'v':
+       o.v++;
+       break;
+      case 'f': {
+       char *p;
+       int e = key_readflags(optarg, &p, &o.kf.f, &o.kf.m);
+       if (e || *p)
+         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
+      } break;
+      default:
+       o.f |= f_bogus;
+       break;
+    }
+  }
+
+  if (o.f & f_bogus)
+    die(EXIT_FAILURE, "Usage: list [-uqv] [-f FILTER] [TAG...]");
+
+  /* --- Open the key file --- */
+
+  doopen(&f, KOPEN_READ);
+  o.t = time(0);
+
+  /* --- Set up the time format --- */
+
+  if (!o.v)
+    o.tfmt = "%Y-%m-%d";
+  else if (o.f & f_utc)
+    o.tfmt = "%Y-%m-%d %H:%M:%S UTC";
+  else
+    o.tfmt = "%Y-%m-%d %H:%M:%S %Z";
+
+  /* --- If specific keys were requested use them, otherwise do all --- *
+   *
+   * Some day, this might turn into a wildcard match.
+   */
+
+  if (optind < argc) {
+    do {
+      if ((k = key_bytag(&f, argv[optind])) != 0)
+       showkey(k, &o);
+      else {
+       moan("key `%s' not found", argv[optind]);
+       o.f |= f_bogus;
+      }
+      optind++;
+    } while (optind < argc);
+  } else {
+    key_iter i;
+    for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; )
+      showkey(k, &o);
+  }
+
+  /* --- Done --- */
+
+  doclose(&f);
+  if (o.f & f_bogus)
+    return (EXIT_FAILURE);
+  else
+    return (0);
+}
+
+/*----- Command implementation --------------------------------------------*/
+
+/* --- @cmd_expire@ --- */
+
+static int cmd_expire(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  int i;
+  int rc = 0;
+
+  if (argc < 2)
+    die(EXIT_FAILURE, "Usage: expire TAG...");
+  doopen(&f, KOPEN_WRITE);
+  for (i = 1; i < argc; i++) {
+    if ((k = key_bytag(&f, argv[i])) != 0)
+      key_expire(&f, k);
+    else {
+      moan("key `%s' not found", argv[i]);
+      rc = 1;
+    }
+  }
+  doclose(&f);
+  return (rc);
+}
+
+/* --- @cmd_delete@ --- */
+
+static int cmd_delete(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  int i;
+  int rc = 0;
+
+  if (argc < 2)
+    die(EXIT_FAILURE, "Usage: delete TAG...");
+  doopen(&f, KOPEN_WRITE);
+  for (i = 1; i < argc; i++) {
+    if ((k = key_bytag(&f, argv[i])) != 0)
+      key_delete(&f, k);
+    else {
+      moan("key `%s' not found", argv[i]);
+      rc = 1;
+    }
+  }
+  doclose(&f);
+  return (rc);
+}
+
+/* --- @cmd_setattr@ --- */
+
+static int cmd_setattr(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+
+  if (argc < 3)
+    die(EXIT_FAILURE, "Usage: setattr TAG ATTR...");
+  doopen(&f, KOPEN_WRITE);
+  if ((k = key_bytag(&f, argv[1])) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
+  setattr(&f, k, argv + 2);
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_getattr@ --- */
+
+static int cmd_getattr(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  dstr d = DSTR_INIT;
+  const char *p;
+
+  if (argc != 3)
+    die(EXIT_FAILURE, "Usage: getattr TAG ATTR");
+  doopen(&f, KOPEN_READ);
+  if ((k = key_bytag(&f, argv[1])) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
+  key_fulltag(k, &d);
+  if ((p = key_getattr(&f, k, argv[2])) == 0)
+    die(EXIT_FAILURE, "no attribute `%s' for key `%s'", argv[2], d.buf);
+  puts(p);
+  dstr_destroy(&d);
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_finger@ --- */
+
+static void fingerprint(key *k, const gchash *ch, const key_filter *kf)
+{
+  ghash *h;
+  dstr d = DSTR_INIT;
+  const octet *p;
+  size_t i;
+
+  h = GH_INIT(ch);
+  if (key_fingerprint(k, h, kf)) {
+    p = GH_DONE(h, 0);
+    key_fulltag(k, &d);
+    for (i = 0; i < ch->hashsz; i++) {
+      if (i && i % 4 == 0)
+       putchar('-');
+      printf("%02x", p[i]);
+    }
+    printf(" %s\n", d.buf);
+  }
+  dstr_destroy(&d);
+  GH_DESTROY(h);
+}
+
+static int cmd_finger(int argc, char *argv[])
+{
+  key_file f;
+  int rc = 0;
+  const gchash *ch = &rmd160;
+  key_filter kf = { KF_NONSECRET, KF_NONSECRET };
+
+  for (;;) {
+    static struct option opt[] = {
+      { "filter",      OPTF_ARGREQ,    0,      'f' },
+      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'f': {
+       char *p;
+       int err = key_readflags(optarg, &p, &kf.f, &kf.m);
+       if (err || *p)
+         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
+      } break;
+      case 'a':
+       if ((ch = ghash_byname(optarg)) == 0)
+         die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg);
+       break;
+      default:
+       rc = 1;
+       break;
+    }
+  }
+
+  argv += optind; argc -= optind;
+  if (rc)
+    die(EXIT_FAILURE, "Usage: fingerprint [-f FILTER] [TAG...]");
+
+  doopen(&f, KOPEN_READ);
+
+  if (argc) {
+    int i;
+    for (i = 0; i < argc; i++) {
+      key *k = key_bytag(&f, argv[i]);
+      if (k)
+       fingerprint(k, ch, &kf);
+      else {
+       rc = 1;
+       moan("key `%s' not found", argv[i]);
+      }
+    }
+  } else {
+    key_iter i;
+    key *k;
+    for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; )
+      fingerprint(k, ch, &kf);
+  }
+  return (rc);
+}
+
+/* --- @cmd_verify@ --- */
+
+static unsigned xdigit(char c)
+{
+  if ('A' <= c && c <= 'Z') return (c + 10 - 'A');
+  if ('a' <= c && c <= 'z') return (c + 10 - 'a');
+  if ('0' <= c && c <= '9') return (c - '0');
+  return (~0u);
+}
+
+static void unhexify(octet *q, char *p, size_t n)
+{
+  unsigned a = 0;
+  int i = 0;
+
+  for (;;) {
+    if (*p == '-' || *p == ':' || isspace((unsigned char)*p)) {
+      p++;
+      continue;
+    }
+    if (!n && !*p)
+      break;
+    if (!*p)
+      die(EXIT_FAILURE, "hex string too short");
+    if (!isxdigit((unsigned char)*p))
+      die(EXIT_FAILURE, "bad hex string");
+    if (!n)
+      die(EXIT_FAILURE, "hex string too long");
+    a = (a << 4) | xdigit(*p++);
+    i++;
+    if (i == 2) {
+      *q++ = U8(a);
+      a = 0;
+      i = 0;
+      n--;
+    }
+  }
+}
+
+static int cmd_verify(int argc, char *argv[])
+{
+  key_file f;
+  int rc = 0;
+  const gchash *ch = &rmd160;
+  ghash *h;
+  key *k;
+  octet *buf;
+  const octet *fpr;
+  key_filter kf = { KF_NONSECRET, KF_NONSECRET };
+
+  for (;;) {
+    static struct option opt[] = {
+      { "filter",      OPTF_ARGREQ,    0,      'f' },
+      { "algorithm",   OPTF_ARGREQ,    0,      'a' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+f:a:", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'f': {
+       char *p;
+       int err = key_readflags(optarg, &p, &kf.f, &kf.m);
+       if (err || *p)
+         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
+      } break;
+      case 'a':
+       if ((ch = ghash_byname(optarg)) == 0)
+         die(EXIT_FAILURE, "unknown hash algorithm `%s'", optarg);
+       break;
+      default:
+       rc = 1;
+       break;
+    }
+  }
+
+  argv += optind; argc -= optind;
+  if (rc || argc != 2)
+    die(EXIT_FAILURE, "Usage: verify [-f FILTER] TAG FINGERPRINT");
+
+  doopen(&f, KOPEN_READ);
+
+  if ((k = key_bytag(&f, argv[0])) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", argv[0]);
+  buf = xmalloc(ch->hashsz);
+  unhexify(buf, argv[1], ch->hashsz);
+  h = GH_INIT(ch);
+  if (!key_fingerprint(k, h, &kf))
+    die(EXIT_FAILURE, "key has no fingerprintable components (as filtered)");
+  fpr = GH_DONE(h, 0);
+  if (memcmp(fpr, buf, ch->hashsz) != 0)
+    die(EXIT_FAILURE, "key fingerprint mismatch");
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_comment@ --- */
+
+static int cmd_comment(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  int err;
+
+  if (argc < 2 || argc > 3)
+    die(EXIT_FAILURE, "Usage: comment TAG [COMMENT]");
+  doopen(&f, KOPEN_WRITE);
+  if ((k = key_bytag(&f, argv[1])) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
+  if ((err = key_setcomment(&f, k, argv[2])) != 0)
+    die(EXIT_FAILURE, "bad comment `%s': %s", argv[2], key_strerror(err));
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_tag@ --- */
+
+static int cmd_tag(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  int err;
+  unsigned flags = 0;
+  int rc = 0;
+
+  for (;;) {
+    static struct option opt[] = {
+      { "retag",       0,              0,      'r' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+r", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'r':
+       flags |= f_retag;
+       break;
+      default:
+       rc = 1;
+       break;
+    }
+  }
+
+  argv += optind; argc -= optind;
+  if (argc < 1 || argc > 2 || rc)
+    die(EXIT_FAILURE, "Usage: tag [-r] TAG [NEW-TAG]");
+  doopen(&f, KOPEN_WRITE);
+  if (flags & f_retag) {
+    if ((k = key_bytag(&f, argv[1])) != 0 && strcmp(k->tag, argv[1]) == 0)
+      key_settag(&f, k, 0);
+  }
+  if ((k = key_bytag(&f, argv[0])) == 0)
+    die(EXIT_FAILURE, "key `%s' not found", argv[0]);
+  if ((err = key_settag(&f, k, argv[1])) != 0)
+    die(EXIT_FAILURE, "bad tag `%s': %s", argv[1], key_strerror(err));
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_lock@ --- */
+
+static int cmd_lock(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  key_data **kd;
+  dstr d = DSTR_INIT;
+
+  if (argc != 2)
+    die(EXIT_FAILURE, "Usage: lock QTAG");
+  doopen(&f, KOPEN_WRITE);
+  if (key_qtag(&f, argv[1], &d, &k, &kd))
+    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
+  if ((*kd)->e == KENC_ENCRYPT && key_punlock(kd, 0, d.buf))
+    die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf);
+  if (key_plock(kd, 0, d.buf))
+    die(EXIT_FAILURE, "failed to lock key `%s'", d.buf);
+  f.f |= KF_MODIFIED;
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_unlock@ --- */
+
+static int cmd_unlock(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  key_data **kd;
+  dstr d = DSTR_INIT;
+
+  if (argc != 2)
+    die(EXIT_FAILURE, "Usage: unlock QTAG");
+  doopen(&f, KOPEN_WRITE);
+  if (key_qtag(&f, argv[1], &d, &k, &kd))
+    die(EXIT_FAILURE, "key `%s' not found", argv[1]);
+  if ((*kd)->e != KENC_ENCRYPT)
+    die(EXIT_FAILURE, "key `%s' is not encrypted", d.buf);
+  if (key_punlock(kd, 0, d.buf))
+    die(EXIT_FAILURE, "couldn't unlock key `%s'", d.buf);
+  f.f |= KF_MODIFIED;
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_extract@ --- */
+
+static int cmd_extract(int argc, char *argv[])
+{
+  key_file f;
+  key *k;
+  int i;
+  int rc = 0;
+  key_filter kf = { 0, 0 };
+  dstr d = DSTR_INIT;
+  const char *outfile = 0;
+  FILE *fp;
+
+  for (;;) {
+    static struct option opt[] = {
+      { "filter",      OPTF_ARGREQ,    0,      'f' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "f:", opt, 0, 0, 0);
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'f': {
+       char *p;
+       int err = key_readflags(optarg, &p, &kf.f, &kf.m);
+       if (err || *p)
+         die(EXIT_FAILURE, "bad filter string `%s'", optarg);
+      } break;
+      default:
+       rc = 1;
+       break;
+    }
+  }
+
+  argv += optind; argc -= optind;
+  if (rc || argc < 1)
+    die(EXIT_FAILURE, "Usage: extract [-f FILTER] FILE [TAG...]");
+  if (strcmp(*argv, "-") == 0)
+    fp = stdout;
+  else {
+    outfile = *argv;
+    dstr_putf(&d, "%s.new", outfile);
+    if (!(fp = fopen(d.buf, "w"))) {
+      die(EXIT_FAILURE, "couldn't open `%s' for writing: %s",
+         d.buf, strerror(errno));
+    }
+  }
+
+  doopen(&f, KOPEN_READ);
+  if (argc < 2) {
+    key_iter i;
+    key *k;
+    for (key_mkiter(&i, &f); (k = key_next(&i)) != 0; )
+      key_extract(&f, k, fp, &kf);
+  } else {
+    for (i = 1; i < argc; i++) {
+      if ((k = key_bytag(&f, argv[i])) != 0)
+       key_extract(&f, k, fp, &kf);
+      else {
+       moan("key `%s' not found", argv[i]);
+       rc = 1;
+      }
+    }
+  }
+  if (fclose(fp) || (outfile && rename(d.buf, outfile)))
+    die(EXIT_FAILURE, "error writing file: %s", strerror(errno));
+  dstr_destroy(&d);
+  doclose(&f);
+  return (rc);
+}
+
+/* --- @cmd_tidy@ --- */
+
+static int cmd_tidy(int argc, char *argv[])
+{
+  key_file f;
+  if (argc != 1)
+    die(EXIT_FAILURE, "Usage: tidy");
+  doopen(&f, KOPEN_WRITE);
+  f.f |= KF_MODIFIED; /* Nasty hack */
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_merge@ --- */
+
+static int cmd_merge(int argc, char *argv[])
+{
+  key_file f;
+  FILE *fp;
+
+  if (argc != 2)
+    die(EXIT_FAILURE, "Usage: merge FILE");
+  if (strcmp(argv[1], "-") == 0)
+    fp = stdin;
+  else if (!(fp = fopen(argv[1], "r"))) {
+    die(EXIT_FAILURE, "couldn't open `%s' for reading: %s",
+       argv[1], strerror(errno));
+  }
+
+  doopen(&f, KOPEN_WRITE);
+  key_merge(&f, argv[1], fp, key_moan, 0);
+  doclose(&f);
+  return (0);
+}
+
+/* --- @cmd_show@ --- */
+
+#define LISTS(LI)                                                      \
+  LI("Lists", list,                                                    \
+     listtab[i].name, listtab[i].name)                                 \
+  LI("Hash functions", hash,                                           \
+     ghashtab[i], ghashtab[i]->name)                                   \
+  LI("Elliptic curves", ec,                                            \
+     ectab[i].name, ectab[i].name)                                     \
+  LI("Prime Diffie-Hellman groups", dh,                                        \
+     ptab[i].name, ptab[i].name)                                       \
+  LI("Binary Diffie-Hellman groups", bindh,                            \
+     bintab[i].name, bintab[i].name)                                   \
+  LI("Key-generation algorithms", keygen,                              \
+     algtab[i].name, algtab[i].name)                                   \
+  LI("Random seeding algorithms", seed,                                        \
+     seedtab[i].p, seedtab[i].p)
+
+MAKELISTTAB(listtab, LISTS)
+
+static int cmd_show(int argc, char *argv[])
+{
+  return (displaylists(listtab, argv + 1));
+}
+
+/*----- Main command table ------------------------------------------------*/
+
+static int cmd_help(int argc, char *argv[]);
+
+static cmd cmds[] = {
+  { "help", cmd_help, "help [COMMAND...]" },
+  { "show", cmd_show, "show [ITEM...]" },
+  { "list", cmd_list, "list [-uqv] [-f FILTER] [TAG...]", "\
+Options:\n\
+\n\
+-u, --utc              Display expiry times etc. in UTC, not local time.\n\
+-q, --quiet            Show less information.\n\
+-v, --verbose          Show more information.\n\
+" },
+  { "fingerprint", cmd_finger, "fingerprint [-f FILTER] [TAG...]", "\
+Options:\n\
+\n\
+-f, --filter=FILT      Only hash key components matching FILT.\n\
+-a, --algorithm=HASH   Use the named HASH algorithm.\n\
+                         ($ show hash for list.)\n\
+" },
+  { "verify", cmd_verify, "verify [-f FILTER] TAG FINGERPRINT", "\
+Options:\n\
+\n\
+-f, --filter=FILT      Only hash key components matching FILT.\n\
+-a, --algorithm=HASH   Use the named HASH algorithm.\n\
+                         ($ show hash for list.)\n\
+" },
+  { "extract", cmd_extract, "extract [-f FILTER] FILE [TAG...]", "\
+Options:\n\
+\n\
+-f, --filter=FILT      Only extract key components matching FILT.\n\
+" },
+  { "merge", cmd_merge, "merge FILE" },
+  { "expire", cmd_expire, "expire TAG..." },
+  { "delete", cmd_delete, "delete TAG..." },
+  { "setattr", cmd_setattr, "setattr TAG ATTR..." },
+  { "getattr", cmd_getattr, "getattr TAG ATTR" },
+  { "comment", cmd_comment, "comment TAG [COMMENT]" },
+  { "lock", cmd_lock, "lock QTAG" },
+  { "unlock", cmd_unlock, "unlock QTAG" },
+  { "tag", cmd_tag, "tag [-r] TAG [NEW-TAG]", "\
+Options:\n\
+\n\
+-r, --retag            Untag any key currently called new-tag.\n\
+" },
+  { "tidy", cmd_tidy, "tidy" },
+  { "add", cmd_add,
+    "add [-OPTIONS] TYPE [ATTR...]\n\
+       Options: [-lqrLKS] [-a ALG] [-bB BITS] [-p PARAM] [-R TAG]\n\
+                [-A SEEDALG] [-s SEED] [-n BITS] [-I KEYID]\n\
+                [-e EXPIRE] [-t TAG] [-c COMMENT]", "\
+Options:\n\
+\n\
+-a, --algorithm=ALG    Generate keys suitable for ALG.\n\
+                         ($ show keygen for list.)\n\
+-b, --bits=N           Generate an N-bit key.\n\
+-B, --qbits=N          Use an N-bit subgroup or factors.\n\
+-p, --parameters=TAG   Get group parameters from TAG.\n\
+-C, --curve=NAME       Use elliptic curve or DH group NAME.\n\
+                         ($ show ec or $ show dh for list.)\n\
+-A, --seedalg=ALG      Use pseudorandom generator ALG to generate key.\n\
+                         ($ show seed for list.)\n\
+-s, --seed=BASE64      Use Base64-encoded string BASE64 as seed.\n\
+-n, --newseed=COUNT    Generate new COUNT-bit seed.\n\
+-e, --expire=TIME      Make the key expire after TIME.\n\
+-c, --comment=STRING   Attach the command STRING to the key.\n\
+-t, --tag=TAG          Tag the key with the name TAG.\n\
+-r, --retag            Untag any key currently with that tag.\n\
+-R, --rand-id=TAG      Use key named TAG for the random number generator.\n\
+-I, --key-id=ID                Force the key-id for the new key.\n\
+-l, --lock             Lock the generated key with a passphrase.\n\
+-q, --quiet            Don't give progress indicators while working.\n\
+-L, --lim-lee          Generate Lim-Lee primes for Diffie-Hellman groups.\n\
+-K, --kcdsa            Generate KCDSA-style Lim-Lee primes for DH groups.\n\
+-S, --subgroup         Use a prime-order subgroup for Diffie-Hellman.\n\
+" },
+  { 0, 0, 0 }
+};
+
+static int cmd_help(int argc, char *argv[])
+{
+  sc_help(cmds, stdout, argv + 1);
+  return (0);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- Helpful GNUy functions --- */
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "Usage: $ [-k KEYRING] COMMAND [ARGS]\n");
+}
+
+void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+void help_global(FILE *fp)
+{
+  usage(fp);
+  fputs("\n\
+Performs various simple key management operations.\n\
+\n\
+Global command line options:\n\
+\n\
+-h, --help [COMMAND...]        Display this help text (or help for COMMANDs).\n\
+-v, --version          Display version number.\n\
+-u, --usage            Display short usage summary.\n\
+\n\
+-k, --keyring=FILE     Read and write keys in FILE.\n",
+       fp);
+}
+
+/* --- @main@ --- *
+ *
+ * Arguments:  @int argc@ = number of command line arguments
+ *             @char *argv[]@ = array of command line arguments
+ *
+ * Returns:    Nonzero on failure.
+ *
+ * Use:                Main program.  Performs simple key management functions.
+ */
+
+int main(int argc, char *argv[])
+{
+  unsigned f = 0;
+
+#define f_bogus 1u
+
+  /* --- Initialization --- */
+
+  ego(argv[0]);
+  sub_init();
+
+  /* --- Parse command line options --- */
+
+  for (;;) {
+    static struct option opt[] = {
+
+      /* --- Standard GNUy help options --- */
+
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'v' },
+      { "usage",       0,              0,      'u' },
+
+      /* --- Real live useful options --- */
+
+      { "keyring",     OPTF_ARGREQ,    0,      'k' },
+
+      /* --- Magic terminator --- */
+
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "+hvu k:", opt, 0, 0, 0);
+
+    if (i < 0)
+      break;
+    switch (i) {
+
+      /* --- GNU help options --- */
+
+      case 'h':
+       sc_help(cmds, stdout, argv + optind);
+       exit(0);
+      case 'v':
+       version(stdout);
+       exit(0);
+      case 'u':
+       usage(stdout);
+       exit(0);
+
+      /* --- Real useful options --- */
+
+      case 'k':
+       keyfile = optarg;
+       break;
+
+      /* --- Bogosity --- */
+
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+
+  /* --- Complain about excessive bogons --- */
+
+  if (f & f_bogus || optind == argc) {
+    usage(stderr);
+    exit(1);
+  }
+
+  /* --- Initialize the Catacomb random number generator --- */
+
+  rand_noisesrc(RAND_GLOBAL, &noise_source);
+  rand_seed(RAND_GLOBAL, 160);
+
+  /* --- Dispatch to appropriate command handler --- */
+
+  argc -= optind;
+  argv += optind;
+  optind = 0;
+  return (findcmd(cmds, argv[0])->cmd(argc, argv));
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from keyring.5
rename to progs/keyring.5
similarity index 100%
rename from mkphrase.1
rename to progs/mkphrase.1
diff --git a/progs/mkphrase.c b/progs/mkphrase.c
new file mode 100644 (file)
index 0000000..17fcb9c
--- /dev/null
@@ -0,0 +1,456 @@
+/* -*-c-*-
+ *
+ * Generate passphrases from word lists
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+#include <mLib/darray.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sym.h>
+
+#include "grand.h"
+#include "noise.h"
+#include "rand.h"
+
+/*----- Global state ------------------------------------------------------*/
+
+static unsigned min = 0, max = 256;    /* Word length bounds */
+static unsigned minbits = 128, maxbits = UINT_MAX; /* Acceptable entropy */
+static unsigned count = 1;             /* How many passphrases to make */
+
+static const char wchars[] = "abcdefghijklmnopqrstuvwxyz'";
+
+typedef struct ppgen_ops {
+  const char *name;                    /* Name of the generator */
+  void *(*init)(void);                 /* Initialize generator */
+  void (*scan)(FILE */*fp*/, void */*p*/); /* Scan an input word list */
+  void (*endscan)(void */*p*/);                /* Scanning phase completed */
+  double (*gen)(dstr */*d*/, grand */*r*/, void */*p*/);
+                                       /* Emit word and return entropy */
+  void (*done)(void */*p*/);           /* Close down generator */
+} ppgen_ops;
+
+/*----- Word list ---------------------------------------------------------*/
+
+#ifndef STRING_V
+#  define STRING_V
+   DA_DECL(string_v, char *);
+#endif
+
+typedef struct wlist {
+  string_v sv;
+  sym_table tab;
+  char *buf;
+  double logp;
+} wlist;
+
+static void *wordlist_init(void)
+{
+  wlist *w = xmalloc(sizeof(wlist));
+  sym_create(&w->tab);
+  w->logp = 0;
+  return (w);
+}
+
+static void wordlist_scan(FILE *fp, void *p)
+{
+  wlist *w = p;
+  dstr d = DSTR_INIT;
+  unsigned f = 0;
+
+  for (;;) {
+    int ch = getc(fp);
+    if (ch == EOF || isspace(ch)) {
+      DPUTZ(&d);
+      if (f && d.len >= min && d.len <= max)
+       sym_find(&w->tab, d.buf, d.len + 1, sizeof(sym_base), 0);
+      f = 0;
+      DRESET(&d);
+      if (ch == EOF)
+       break;
+      continue;
+    }
+    ch = tolower(ch);
+    if (strchr(wchars, ch)) {
+      DPUTC(&d, ch);
+      f = 1;
+    }
+  }
+
+  dstr_destroy(&d);
+}
+
+static void wordlist_endscan(void *p)
+{
+  wlist *w = p;
+  size_t buflen = 0;
+  sym_iter i;
+  sym_base *b;
+  char *q;
+
+  for (sym_mkiter(&i, &w->tab); (b = sym_next(&i)) != 0; )
+    buflen += b->len;
+  w->buf = xmalloc(buflen);
+  q = w->buf;
+  DA_CREATE(&w->sv);
+  for (sym_mkiter(&i, &w->tab); (b = sym_next(&i)) != 0; ) {
+    memcpy(q, SYM_NAME(b), b->len);
+    DA_PUSH(&w->sv, q);
+    q += b->len;
+  }
+  sym_destroy(&w->tab);
+  w->logp = log(DA_LEN(&w->sv))/log(2);
+}
+
+static double wordlist_gen(dstr *d, grand *r, void *p)
+{
+  wlist *w = p;
+  uint32 i = r->ops->range(r, DA_LEN(&w->sv));
+  DPUTS(d, DA(&w->sv)[i]);
+  return (w->logp);
+}
+
+static void wordlist_done(void *p)
+{
+  wlist *w = p;
+  xfree(w->buf);
+  DA_DESTROY(&w->sv);
+  xfree(w);
+}
+
+static ppgen_ops wordlist_ops = {
+  "wordlist",
+  wordlist_init, wordlist_scan, wordlist_endscan, wordlist_gen, wordlist_done
+};
+
+/*----- Markov word model -------------------------------------------------*/
+
+enum {
+  C_START = 27,
+  C_END,
+  VECSZ
+};
+
+typedef struct node {
+  uint32 count;
+  uint32 p[VECSZ];
+} node;
+
+static void *markov_init(void)
+{
+  node (*model)[VECSZ][VECSZ][VECSZ] = xmalloc(sizeof(*model));
+  unsigned i, j, k, l;
+
+  for (i = 0; i < VECSZ; i++) {
+    for (j = 0; j < VECSZ; j++) {
+      for (k = 0; k < VECSZ; k++) {
+       node *n = &(*model)[i][j][k];
+       n->count = 0;
+       for (l = 0; l < VECSZ; l++)
+         n->p[l] = 0;
+      }
+    }
+  }
+
+  return (model);
+}
+
+static void markov_scan(FILE *fp, void *p)
+{
+  node (*model)[VECSZ][VECSZ][VECSZ] = p;
+  unsigned i = C_START, j = C_START, k = C_START, l = C_END;
+
+  for (;;) {
+    int ch = getc(fp);
+    const char *q;
+    node *n = &(*model)[i][j][k];
+
+    if (ch == EOF || isspace(ch)) {
+      if (l != C_END) {
+       l = C_END;
+       n->count++;
+       n->p[l]++;
+       i = j = k = C_START;
+      }
+      if (ch == EOF)
+       break;
+      continue;
+    }
+
+    if ((q = strchr(wchars, tolower(ch))) == 0)
+      continue;
+    l = q - wchars;
+    n->count++;
+    n->p[l]++;
+    i = j; j = k; k = l;
+  }
+}
+
+static double markov_gen(dstr *d, grand *r, void *p)
+{
+  node (*model)[VECSZ][VECSZ][VECSZ] = p;
+  unsigned i = C_START, j = C_START, k = C_START, l;
+  double logp = 0;
+  double log2 = log(2);
+
+  for (;;) {
+    node *n = &(*model)[i][j][k];
+    uint32 z = r->ops->range(r, n->count);
+    for (l = 0; z >= n->p[l]; z -= n->p[l++])
+      ;
+    logp -= log((double)n->p[l]/(double)n->count)/log2;
+    if (l == C_END)
+      break;
+    DPUTC(d, wchars[l]);
+    i = j; j = k; k = l;
+  }
+
+  return (logp);
+}
+
+static void markov_done(void *p)
+{
+  node (*model)[VECSZ][VECSZ][VECSZ] = p;
+  xfree(model);
+}
+
+static ppgen_ops markov_ops = {
+  "markov",
+  markov_init, markov_scan, 0, markov_gen, markov_done
+};
+
+/*----- Main code ---------------------------------------------------------*/
+
+static ppgen_ops *ppgentab[] = {
+  &markov_ops,
+  &wordlist_ops,
+  0
+};
+
+static void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "\
+Usage: $ [-p] [-b MIN[-MAX]] [-g GEN] [-n COUNT]\n\
+\t[-r [MIN-]MAX] WORDLIST...\n                   \
+");
+}
+
+static void help(FILE *fp)
+{
+  ppgen_ops **ops;
+  version(fp);
+  fputc('\n', fp);
+  usage(fp);
+  pquis(fp, "\n\
+Generates random passphrases with the requested level of entropy.  Options\n\
+supported are:\n\
+\n\
+-h, --help             Show this help text.\n\
+-v, --version          Show the program's version number.\n\
+-u, --usage            Show a terse usage summary.\n\
+-b, --bits=MIN[-MAX]   Minimum and maximum bits of entropy.\n\
+-g, --generator=GEN    Use passphrase generator GEN.\n\
+-n, --count=COUNT      Generate COUNT passphrases.\n\
+-p, --probability      Show -log_2 of probability for each phrase.\n\
+-r, --range=[MIN-]MAX  Supply minimum and maximum word lengths.\n\
+\n\
+Generators currently available:");
+  for (ops = ppgentab; *ops; ops++)
+    fprintf(fp, " %s", (*ops)->name);
+  fputc('\n', fp);
+}
+
+int main(int argc, char *argv[])
+{
+  ppgen_ops *ops = ppgentab[0];
+  unsigned f = 0;
+  void *ctx;
+  dstr d = DSTR_INIT;
+  dstr dd = DSTR_INIT;
+  unsigned i;
+
+#define f_bogus 1u
+#define f_showp 2u
+
+  ego(argv[0]);
+  for (;;) {
+    static struct option opts[] = {
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'v' },
+      { "usage",       0,              0,      'u' },
+      { "bits",                OPTF_ARGREQ,    0,      'b' },
+      { "generator",   OPTF_ARGREQ,    0,      'g' },
+      { "count",       OPTF_ARGREQ,    0,      'n' },
+      { "probability", 0,              0,      'p' },
+      { "range",       OPTF_ARGREQ,    0,      'r' },
+      { 0,             0,              0,      0 }
+    };
+    int i = mdwopt(argc, argv, "hvu b:g:n:pr:", opts, 0, 0, 0);
+
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'h':
+       help(stdout);
+       exit(0);
+      case 'v':
+       version(stdout);
+       exit(0);
+      case 'u':
+       usage(stdout);
+       exit(0);
+      case 'b': {
+       char *p;
+       minbits = strtoul(optarg, &p, 0);
+       if (*p == '-')
+         maxbits = strtoul(p + 1, &p, 0);
+       else
+         maxbits = UINT_MAX;
+       if (*p || minbits > maxbits)
+         die(EXIT_FAILURE, "bad entropy range `%s'", optarg);
+      } break;
+      case 'g': {
+       ppgen_ops **p;
+       size_t n = strlen(optarg);
+       ops = 0;
+       for (p = ppgentab; *p; p++) {
+         if (strncmp(optarg, (*p)->name, n) == 0) {
+           if (!(*p)->name[n]) {
+             ops = *p;
+             break;
+           } else if (ops)
+             die(EXIT_FAILURE, "ambiguous generator name `%s'", optarg);
+           ops = *p;
+         }
+       }
+       if (!ops)
+         die(EXIT_FAILURE, "unknown generator name `%s'", optarg);
+      } break;
+      case 'n': {
+       char *p;
+       unsigned long n = strtoul(optarg, &p, 0);
+       if (*p)
+         die(EXIT_FAILURE, "bad integer `%s'", optarg);
+       count = n;
+      } break;
+      case 'p':
+       f |= f_showp;
+       break;
+      case 'r': {
+       char *p;
+       unsigned long n = min, nn = max;
+       nn = strtoul(optarg, &p, 0);
+       if (*p == '-') {
+         n = nn;
+         nn = strtoul(p + 1, &p, 0);
+       }
+       if (*p || min > max)
+         die(EXIT_FAILURE, "bad range string `%s'", optarg);
+       min = n; max = nn;
+      } break;
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+  if ((f & f_bogus) || !argc) {
+    usage(stderr);
+    exit(EXIT_FAILURE);
+  }
+
+  rand_noisesrc(RAND_GLOBAL, &noise_source);
+  rand_seed(RAND_GLOBAL, 160);
+
+  ctx = ops->init();
+  while (*argv) {
+    if (strcmp(*argv, "-") == 0)
+      ops->scan(stdin, ctx);
+    else {
+      FILE *fp = fopen(*argv, "r");
+      if (!fp) {
+       die(EXIT_FAILURE, "error opening file `%s': %s",
+           *argv, strerror(errno));
+      }
+      ops->scan(fp, ctx);
+      fclose(fp);
+    }
+    argv++;
+  }
+  if (ops->endscan)
+    ops->endscan(ctx);
+
+  for (i = 0; !count || i < count; ) {
+    double logp = 0;
+    DRESET(&d);
+    while (logp < minbits) {
+      double pp;
+      DRESET(&dd);
+      pp = ops->gen(&dd, &rand_global, ctx);
+      if (!pp || dd.len < min || dd.len > max)
+       continue;
+      if (logp)
+       DPUTC(&d, ' ');
+      DPUTD(&d, &dd);
+      logp += pp;
+    }
+    if (logp >= (double)maxbits + 1)
+      continue;
+    dstr_write(&d, stdout);
+    if (f & f_showp)
+      printf(" [%g]", logp);
+    fputc('\n', stdout);
+    i++;
+  }
+
+  ops->done(ctx);
+  dstr_destroy(&d);
+  dstr_destroy(&dd);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/progs/perftest.c b/progs/perftest.c
new file mode 100644 (file)
index 0000000..97a2e0f
--- /dev/null
@@ -0,0 +1,614 @@
+/* -*-c-*-
+ *
+ * Measure performance of various operations (Unix-specific)
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include "config.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+#include <mLib/tv.h>
+
+#include "rand.h"
+#include "mp.h"
+#include "mprand.h"
+#include "fibrand.h"
+#include "rsa.h"
+#include "mpmont.h"
+#include "mpbarrett.h"
+#include "dh.h"
+#include "pgen.h"
+#include "ec.h"
+#include "group.h"
+
+#include "cc.h"
+#include "gcipher.h"
+#include "ghash.h"
+#include "gmac.h"
+#include "ectab.h"
+#include "ptab.h"
+
+/*----- Options -----------------------------------------------------------*/
+
+typedef struct opts {
+  const char *name;                    /* Pre-configured named thing */
+  unsigned fbits;                      /* Field size bits */
+  unsigned gbits;                      /* Group size bits */
+  unsigned n;                          /* Number of factors */
+  unsigned i;                          /* Number of intervals (or zero) */
+  double t;                            /* Time for each interval (secs) */
+  unsigned f;                          /* Flags */
+#define OF_NOCHECK 1u                  /*   Don't do group checking */
+} opts;
+
+/*----- Job switch --------------------------------------------------------*/
+
+/* --- Barrett exponentiation --- */
+
+typedef struct bar_ctx {
+  size_t n;
+  mpbarrett b;
+  mp_expfactor *e;
+} bar_ctx;
+
+static void *bar_init(opts *o)
+{
+  bar_ctx *c = CREATE(bar_ctx);
+  gprime_param gp;
+  qd_parse qd;
+  size_t i;
+
+  if (o->name) {
+    qd.p = o->name;
+    if (dh_parse(&qd, &gp))
+      die(1, "bad prime group: %s", qd.e);
+  } else {
+    if (!o->fbits) o->fbits = 1024;
+    dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0);
+  }
+  mpbarrett_create(&c->b, gp.p);
+  if (!o->n) o->n = 1;
+  c->n = o->n;
+  c->e = xmalloc(c->n * sizeof(group_expfactor));
+  for (i = 0; i < c->n; i++) {
+    c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0);
+    c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0);
+  }
+  dh_paramfree(&gp);
+  return (c);
+}
+
+static void bar_run(void *cc)
+{
+  bar_ctx *c = cc;
+  mp *d = mpbarrett_exp(&c->b, MP_NEW, c->e[0].base, c->e[0].exp);
+  MP_DROP(d);
+}
+
+static void barsim_run(void *cc)
+{
+  bar_ctx *c = cc;
+  mp *d = mpbarrett_mexp(&c->b, MP_NEW, c->e, c->n);
+  MP_DROP(d);
+}
+
+/* --- Montgomery exponentiation --- */
+
+typedef struct mont_ctx {
+  size_t n;
+  mpmont m;
+  mp_expfactor *e;
+} mont_ctx;
+
+static void *mont_init(opts *o)
+{
+  mont_ctx *c = CREATE(mont_ctx);
+  gprime_param gp;
+  qd_parse qd;
+  size_t i;
+
+  if (o->name) {
+    qd.p = o->name;
+    if (dh_parse(&qd, &gp))
+      die(1, "bad prime group: %s", qd.e);
+  } else {
+    if (!o->fbits) o->fbits = 1024;
+    dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0);
+  }
+  mpmont_create(&c->m, gp.p);
+  if (!o->n) o->n = 1;
+  c->n = o->n;
+  c->e = xmalloc(c->n * sizeof(mp_expfactor));
+  for (i = 0; i < c->n; i++) {
+    c->e[i].base = mprand_range(MP_NEW, gp.p, &rand_global, 0);
+    c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0);
+  }
+  dh_paramfree(&gp);
+  return (c);
+}
+
+static void mont_run(void *cc)
+{
+  mont_ctx *c = cc;
+  mp *d = mpmont_expr(&c->m, MP_NEW, c->e[0].base, c->e[0].exp);
+  MP_DROP(d);
+}
+
+static void montsim_run(void *cc)
+{
+  mont_ctx *c = cc;
+  mp *d = mpmont_mexpr(&c->m, MP_NEW, c->e, c->n);
+  MP_DROP(d);
+}
+
+/* --- Group exponentiation --- */
+
+typedef struct gr_ctx {
+  size_t n;
+  group *g;
+  group_expfactor *e;
+} gr_ctx;
+
+static void *grp_init(opts *o)
+{
+  gr_ctx *c = CREATE(gr_ctx);
+  const char *e;
+  gprime_param gp;
+  qd_parse qd;
+  size_t i;
+
+  if (o->name) {
+    qd.p = o->name;
+    if (dh_parse(&qd, &gp))
+      die(1, "bad prime group: %s", qd.e);
+  } else {
+    if (!o->fbits) o->fbits = 1024;
+    dh_gen(&gp, o->gbits, o->fbits, 0, &rand_global, pgen_evspin, 0);
+  }
+  c->g = group_prime(&gp);
+  if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0)
+    die(1, "bad group: %s", e);
+  if (!o->n) o->n = 1;
+  c->n = o->n;
+  c->e = xmalloc(c->n * sizeof(group_expfactor));
+  for (i = 0; i < c->n; i++) {
+    c->e[i].base = G_CREATE(c->g);
+    G_FROMINT(c->g, c->e[i].base,
+             mprand_range(MP_NEW, gp.p, &rand_global, 0));
+    c->e[i].exp = mprand_range(MP_NEW, gp.q, &rand_global, 0);
+  }
+  dh_paramfree(&gp);
+  return (c);
+}
+
+static void *grec_init(opts *o)
+{
+  gr_ctx *c = CREATE(gr_ctx);
+  const char *e;
+  ec_info ei;
+  ec p = EC_INIT;
+  size_t i;
+
+  if (!o->name)
+    die(1, "can't generate elliptic curves");
+  if ((e = ec_getinfo(&ei, o->name)) != 0)
+    die(1, "bad curve: %s", e);
+  c->g = group_ec(&ei);
+  if (!(o->f & OF_NOCHECK) && (e = G_CHECK(c->g, &rand_global)) != 0)
+    die(1, "bad group: %s", e);
+  if (!o->n) o->n = 1;
+  c->n = o->n;
+  c->e = xmalloc(c->n * sizeof(group_expfactor));
+  for (i = 0; i < c->n; i++) {
+    c->e[i].base = G_CREATE(c->g);
+    ec_rand(ei.c, &p, &rand_global);
+    G_FROMEC(c->g, c->e[i].base, &p);
+    c->e[i].exp = mprand_range(MP_NEW, ei.r, &rand_global, 0);
+  }
+  EC_DESTROY(&p);
+  return (c);
+}
+
+static void gr_run(void *cc)
+{
+  gr_ctx *c = cc;
+  ge *x = G_CREATE(c->g);
+  G_EXP(c->g, x, c->e[0].base, c->e[0].exp);
+  G_DESTROY(c->g, x);
+}
+
+static void grsim_run(void *cc)
+{
+  gr_ctx *c = cc;
+  ge *x = G_CREATE(c->g);
+  G_MEXP(c->g, x, c->e, c->n);
+  G_DESTROY(c->g, x);
+}
+
+/* --- RSA --- */
+
+typedef struct rsapriv_ctx {
+  rsa_priv rp;
+  rsa_privctx rpc;
+  mp *m;
+} rsapriv_ctx;
+
+static void *rsapriv_init(opts *o)
+{
+  rsapriv_ctx *c = CREATE(rsapriv_ctx);
+
+  if (!o->fbits) o->fbits = 1024;
+  rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0);
+  rsa_privcreate(&c->rpc, &c->rp, 0);
+  c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0);
+  return (c);
+}
+
+static void *rsaprivblind_init(opts *o)
+{
+  rsapriv_ctx *c = CREATE(rsapriv_ctx);
+
+  if (!o->fbits) o->fbits = 1024;
+  rsa_gen(&c->rp, o->fbits, &rand_global, 0, pgen_evspin, 0);
+  rsa_privcreate(&c->rpc, &c->rp, fibrand_create(0));
+  c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0);
+  return (c);
+}
+
+static void rsapriv_run(void *cc)
+{
+  rsapriv_ctx *c = cc;
+  mp *d = rsa_privop(&c->rpc, MP_NEW, c->m);
+  MP_DROP(d);
+}
+
+typedef struct rsapub_ctx {
+  rsa_pub rp;
+  rsa_pubctx rpc;
+  mp *m;
+} rsapub_ctx;
+
+static void *rsapub_init(opts *o)
+{
+  rsapub_ctx *c = CREATE(rsapub_ctx);
+  rsa_priv rp;
+
+  if (!o->fbits) o->fbits = 1024;
+  rsa_gen(&rp, o->fbits, &rand_global, 0, pgen_evspin, 0);
+  c->rp.n = MP_COPY(rp.n);
+  c->rp.e = MP_COPY(rp.e);
+  rsa_privfree(&rp);
+  rsa_pubcreate(&c->rpc, &c->rp);
+  c->m = mprand_range(MP_NEW, c->rp.n, &rand_global, 0);
+  return (c);
+}
+
+static void rsapub_run(void *cc)
+{
+  rsapub_ctx *c = cc;
+  mp *d = rsa_pubop(&c->rpc, MP_NEW, c->m);
+  MP_DROP(d);
+}
+
+/* --- Symmetric encryption --- */
+
+typedef struct ksched_ctx {
+  const gccipher *c;
+  octet *k;
+  size_t ksz;
+} ksched_ctx;
+
+static void *ksched_init(opts *o)
+{
+  ksched_ctx *c = CREATE(ksched_ctx);
+  if (!o->name)
+    die(1, "must specify encryption scheme name");
+  if ((c->c = gcipher_byname(o->name)) == 0)
+    die(1, "encryption scheme `%s' not known", o->name);
+  c->ksz = keysz(o->gbits/8, c->c->keysz);
+  c->k = xmalloc(c->ksz);
+  rand_get(RAND_GLOBAL, c->k, c->ksz);
+  return (c);
+}
+
+static void ksched_run(void *cc)
+{
+  ksched_ctx *c = cc;
+  gcipher *gc = GC_INIT(c->c, c->k, c->ksz);
+  GC_DESTROY(gc);
+}
+
+typedef struct enc_ctx {
+  gcipher *c;
+  octet *m;
+  size_t sz;
+  size_t n;
+} enc_ctx;
+
+static void *enc_init(opts *o)
+{
+  enc_ctx *c = CREATE(enc_ctx);
+  const gccipher *cc;
+  size_t ksz;
+  octet *k;
+  if (!o->name)
+    die(1, "must specify encryption scheme name");
+  if ((cc = gcipher_byname(o->name)) == 0)
+    die(1, "encryption scheme `%s' not known", o->name);
+  ksz = keysz(0, cc->keysz);
+  k = xmalloc(ksz);
+  rand_get(RAND_GLOBAL, k, ksz);
+  c->c = GC_INIT(cc, k, ksz);
+  xfree(k);
+  c->sz = o->gbits ? o->gbits : 65536;
+  c->n = o->n ? o->n : 16;
+  c->m = xmalloc(c->sz);
+  return (c);
+}
+
+static void enc_run(void *cc)
+{
+  enc_ctx *c = cc;
+  size_t i;
+  for (i = 0; i < c->n; i++)
+    GC_ENCRYPT(c->c, c->m, c->m, c->sz);
+}
+
+/* --- Hashing --- */
+
+typedef struct hash_ctx {
+  const gchash *h;
+  octet *m;
+  size_t sz;
+  size_t n;
+} hash_ctx;
+
+static void *hash_init(opts *o)
+{
+  hash_ctx *c = CREATE(hash_ctx);
+  if (!o->name)
+    die(1, "must specify hash function name");
+  if ((c->h = ghash_byname(o->name)) == 0)
+    die(1, "hash function `%s' not known", o->name);
+  c->sz = o->gbits ? o->gbits : 65536;
+  c->n = o->n ? o->n : 16;
+  c->m = xmalloc(c->sz);
+  return (c);
+}
+
+static void hash_run(void *cc)
+{
+  hash_ctx *c = cc;
+  size_t i;
+  ghash *h = GH_INIT(c->h);
+  for (i = 0; i < c->n; i++)
+    GH_HASH(h, c->m, c->sz);
+  GH_DONE(h, 0);
+  GH_DESTROY(h);
+}
+
+/* --- Job table --- */
+
+typedef struct jobops {
+  const char *name;
+  void *(*init)(opts *);
+  void (*run)(void *);
+} jobops;
+
+static const jobops jobtab[] = {
+  { "g-prime-exp",             grp_init,               gr_run },
+  { "g-ec-mul",                        grec_init,              gr_run },
+  { "g-prime-exp-sim",         grp_init,               grsim_run },
+  { "g-ec-mul-sim",            grec_init,              grsim_run },
+  { "barrett-exp",             bar_init,               bar_run },
+  { "barrett-exp-sim",         bar_init,               barsim_run },
+  { "mont-exp",                        mont_init,              mont_run },
+  { "mont-exp-sim",            mont_init,              montsim_run },
+  { "rsa-priv",                        rsapriv_init,           rsapriv_run },
+  { "rsa-priv-blind",          rsaprivblind_init,      rsapriv_run },
+  { "rsa-pub",                 rsapub_init,            rsapub_run },
+  { "ksched",                  ksched_init,            ksched_run },
+  { "enc",                     enc_init,               enc_run },
+  { "hash",                    hash_init,              hash_run },
+  { 0,                         0,                      0 }
+};
+
+/*----- Main code ---------------------------------------------------------*/
+
+void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb " VERSION "\n");
+}
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "Usage: $ [-options] job\n");
+}
+
+static void help(FILE *fp)
+{
+  version(fp);
+  putc('\n', fp);
+  usage(fp);
+  pquis(fp, "\n\
+Various performance tests.\n\
+\n\
+Options:\n\
+\n\
+-h, --help             Show this help text.\n\
+-v, --version          Show program version number.\n\
+-u, --usage            Show terse usage message.\n\
+-l, --list [ITEM...]   List all the various names of things.\n\
+\n\
+-C, --name=NAME                Select curve/DH-group/enc/hash name.\n\
+-b, --field-bits       Field size for g-prime and rsa.\n\
+-q, --no-check         Don't check field/group for validity.\n\
+-B, --group-bits       Group size for g-prime; key size for ksched;\n\
+                         data size for enc and hash.\n\
+-n, --factors=COUNT    Number of factors for {exp,mul}-sim.\n\
+-i, --intervals=COUNT  Number of intervals to run for.  [0; forever]\n\
+-t, --time=TIME                Length of an interval in seconds.  [1]\n\
+");
+}
+
+#define LISTS(LI)                                                      \
+  LI("Lists", list,                                                    \
+     listtab[i].name, listtab[i].name)                                 \
+  LI("Jobs", job,                                                      \
+     jobtab[i].name, jobtab[i].name)                                   \
+  LI("Elliptic curves", ec,                                            \
+     ectab[i].name, ectab[i].name)                                     \
+  LI("Diffie-Hellman groups", dh,                                      \
+     ptab[i].name, ptab[i].name)                                       \
+  LI("Encryption algorithms", cipher,                                  \
+     gciphertab[i], gciphertab[i]->name)                               \
+  LI("Hash functions", hash,                                           \
+     ghashtab[i], ghashtab[i]->name)
+
+MAKELISTTAB(listtab, LISTS)
+
+static unsigned uarg(const char *what, const char *p)
+{
+  char *q;
+  unsigned long u;
+  errno = 0;
+  u = strtoul(p, &q, 0);
+  if (*q || u > UINT_MAX || q == p || errno)
+    die(1, "bad %s `%s'", what, p);
+  return (u);
+}
+
+static double farg(const char *what, const char *p)
+{
+  char *q;
+  double f;
+  errno = 0;
+  f = strtod(p, &q);
+  if (*q || q == p || errno)
+    die(1, "bad %s `%s'", what, p);
+  return (f);
+}
+
+int main(int argc, char *argv[])
+{
+  int i;
+  opts o = { 0 };
+  const jobops *j;
+  struct timeval tv_next, tv_now;
+  double t, ttot;
+  unsigned n;
+  unsigned long ii;
+  clock_t c_start, c_stop;
+  double itot;
+  void *p;
+
+  ego(argv[0]);
+  o.t = 1;
+  for (;;) {
+    static const struct option opts[] = {
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'v' },
+      { "usage",       0,              0,      'u' },
+      { "list",                0,              0,      'l' },
+      { "name",                OPTF_ARGREQ,    0,      'C' },
+      { "field-bits",  OPTF_ARGREQ,    0,      'b' },
+      { "group-bits",  OPTF_ARGREQ,    0,      'B' },
+      { "factors",     OPTF_ARGREQ,    0,      'n' },
+      { "intervals",   OPTF_ARGREQ,    0,      'i' },
+      { "time",                OPTF_ARGREQ,    0,      't' },
+      { "no-check",    0,              0,      'q' },
+      { 0,             0,              0,      0 }
+    };
+
+    i = mdwopt(argc, argv, "hvulC:b:B:n:i:t:q", opts, 0, 0, 0);
+    if (i < 0) break;
+    switch (i) {
+      case 'h': help(stdout); exit(0);
+      case 'v': version(stdout); exit(0);
+      case 'u': usage(stdout); exit(0);
+      case 'l': exit(displaylists(listtab, argv + optind));
+      case 'C': o.name = optarg; break;
+      case 'b': o.fbits = uarg("field bits", optarg); break;
+      case 'B': o.gbits = uarg("subgroup bits", optarg); break;
+      case 'n': o.n = uarg("factor count", optarg); break;
+      case 'i': o.i = uarg("interval count", optarg); break;
+      case 't': o.t = farg("interval length", optarg); break;
+      case 'q': o.f |= OF_NOCHECK; break;
+      default: usage(stderr); exit(1);
+    }
+  }
+  if (optind + 1 != argc) { usage(stderr); exit(1); }
+
+  for (j = jobtab; j->name; j++)
+    if (strcmp(j->name, argv[optind]) == 0) break;
+  if (!j->name) die(1, "unknown job type `%s'", argv[optind]);
+  p = j->init(&o);
+
+  n = 0;
+  ttot = itot =         0;
+  gettimeofday(&tv_now, 0);
+  do {
+    tv_addl(&tv_next, &tv_now, o.t, fmod(o.t * MILLION, MILLION));
+    ii = 0;
+    c_start = clock();
+    do {
+      j->run(p);
+      ii++;
+      gettimeofday(&tv_now, 0);
+    } while (TV_CMP(&tv_now, <, &tv_next));
+    c_stop = clock();
+    t = (double)(c_stop - c_start)/CLOCKS_PER_SEC;
+    itot += ii;
+    ttot += t;
+    printf("%5u: did = %5lu; /sec = %5f; avg /sec = %5f\n",
+          n, ii, ii/t, itot/ttot);
+    fflush(stdout);
+    n++;
+  } while (!o.i || n < o.i);
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from pixie.1
rename to progs/pixie.1
diff --git a/progs/pixie.c b/progs/pixie.c
new file mode 100644 (file)
index 0000000..4a5e9ab
--- /dev/null
@@ -0,0 +1,1460 @@
+/* -*-c-*-
+ *
+ * Passphrase pixie for Catacomb
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <syslog.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/fdflags.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sel.h>
+#include <mLib/selbuf.h>
+#include <mLib/sig.h>
+#include <mLib/str.h>
+#include <mLib/sub.h>
+#include <mLib/tv.h>
+
+#include "arena.h"
+#include "lmem.h"
+#include "passphrase.h"
+#include "pixie.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static unsigned long timeout = 900;
+static sel_state sel;
+static unsigned verbose = 1;
+static const char *command = 0;
+static lmem lm;
+static unsigned flags = 0;
+
+#define F_SYSLOG 1u
+#define F_FETCH 2u
+
+/*----- Event logging -----------------------------------------------------*/
+
+/* --- @log@ --- *
+ *
+ * Arguments:  @const char *p@ = @printf@-style format string
+ *             @...@ = extra arguments to fill in
+ *
+ * Returns:    ---
+ *
+ * Use:                Writes out a timestamped log message.
+ */
+
+static void log(const char *p, ...)
+{
+  dstr d = DSTR_INIT;
+  va_list ap;
+
+  if (!(flags & F_SYSLOG)) {
+    time_t t = time(0);
+    struct tm *tm = localtime(&t);
+    DENSURE(&d, 64);
+    d.len += strftime(d.buf, d.sz, "%Y-%m-%d %H:%M:%S ", tm);
+  }
+  va_start(ap, p);
+  dstr_vputf(&d, p, &ap);
+  va_end(ap);
+
+  if (flags & F_SYSLOG)
+    syslog(LOG_NOTICE, "%s", d.buf);
+  else {
+    DPUTC(&d, '\n');
+    dstr_write(&d, stderr);
+  }
+  DDESTROY(&d);
+}
+
+/*----- Passphrase management ---------------------------------------------*/
+
+/* --- Data structures --- */
+
+typedef struct phrase {
+  struct phrase *next;
+  struct phrase *prev;
+  char *tag;
+  char *p;
+  unsigned long t;
+  sel_timer timer;
+  unsigned f;
+} phrase;
+
+/* --- Variables --- */
+
+#define P_ROOT ((phrase *)&p_root)
+static struct { phrase *next; phrase *prev; } p_root = { P_ROOT, P_ROOT };
+
+/* --- @p_free@ --- *
+ *
+ * Arguments:  @phrase *p@ = pointer to phrase block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a phrase block.
+ */
+
+static void p_free(phrase *p)
+{
+  if (p->t)
+    sel_rmtimer(&p->timer);
+  xfree(p->tag);
+  l_free(&lm, p->p);
+  p->next->prev = p->prev;
+  p->prev->next = p->next;
+  DESTROY(p);
+}
+
+/* --- @p_timer@ --- *
+ *
+ * Arguments:  @struct timeval *tv@ = current time
+ *             @void *p@ = pointer to phrase
+ *
+ * Returns:    ---
+ *
+ * Use:                Expires a passphrase.
+ */
+
+static void p_timer(struct timeval *tv, void *p)
+{
+  phrase *pp = p;
+  if (verbose)
+    log("expiring passphrase `%s'", pp->tag);
+  p_free(pp);
+}
+
+/* --- @p_alloc@ --- *
+ *
+ * Arguments:  @size_t sz@ = amount of memory required
+ *
+ * Returns:    Pointer to allocated memory, or null.
+ *
+ * Use:                Allocates some locked memory, flushing old passphrases if
+ *             there's not enough space.
+ */
+
+static void *p_alloc(size_t sz)
+{
+  for (;;) {
+    char *p;
+    if ((p = l_alloc(&lm, sz)) != 0)
+      return (p);
+    if (P_ROOT->next == P_ROOT)
+      return (0);
+    if (verbose) {
+      log("flushing passphrase `%s' to free up needed space",
+         P_ROOT->next->tag);
+    }
+    p_free(P_ROOT->next);
+  }
+}
+
+/* --- @p_find@ --- *
+ *
+ * Arguments:  @const char *tag@ = pointer to tag to find
+ *
+ * Returns:    Pointer to passphrase block, or null.
+ *
+ * Use:                Finds a passphrase with a given tag.
+ */
+
+static phrase *p_find(const char *tag)
+{
+  phrase *p;
+
+  for (p = P_ROOT->next; p != P_ROOT; p = p->next) {
+    if (strcmp(p->tag, tag) == 0) {
+      if (p->t) {
+       struct timeval tv;
+       sel_rmtimer(&p->timer);
+       gettimeofday(&tv, 0);
+       tv.tv_sec += p->t;
+       sel_addtimer(&sel, &p->timer, &tv, p_timer, p);
+      }
+      p->next->prev = p->prev;
+      p->prev->next = p->next;
+      p->next = P_ROOT;
+      p->prev = P_ROOT->prev;
+      P_ROOT->prev->next = p;
+      P_ROOT->prev = p;
+      return (p);
+    }
+  }
+  return (0);
+}
+
+/* --- @p_add@ --- *
+ *
+ * Arguments:  @const char *tag@ = pointer to tag string
+ *             @const char *p@ = pointer to passphrase
+ *             @unsigned long t@ = expiry timeout
+ *
+ * Returns:    Pointer to newly-added passphrase.
+ *
+ * Use:                Adds a new passphrase.  The tag must not already exist.
+ */
+
+static phrase *p_add(const char *tag, const char *p, unsigned long t)
+{
+  size_t sz = strlen(p) + 1;
+  char *l = p_alloc(sz);
+  phrase *pp;
+
+  /* --- Make sure the locked memory was allocated --- */
+
+  if (!l)
+    return (0);
+
+  /* --- Fill in some other bits of the block --- */
+
+  pp = CREATE(phrase);
+  memcpy(l, p, sz);
+  pp->p = l;
+  pp->tag = xstrdup(tag);
+  pp->f = 0;
+
+  /* --- Set the timer --- */
+
+  pp->t = t;
+  if (t) {
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    tv.tv_sec += t;
+    sel_addtimer(&sel, &pp->timer, &tv, p_timer, pp);
+  }
+
+  /* --- Link the block into the chain --- */
+
+  pp->next = P_ROOT;
+  pp->prev = P_ROOT->prev;
+  P_ROOT->prev->next = pp;
+  P_ROOT->prev = pp;
+  return (pp);
+}
+
+/* --- @p_flush@ --- *
+ *
+ * Arguments:  @const char *tag@ = pointer to tag string, or zero for all
+ *
+ * Returns:    ---
+ *
+ * Use:                Immediately flushes either a single phrase or all of them.
+ */
+
+static void p_flush(const char *tag)
+{
+  phrase *p;
+
+  if (!tag && verbose > 1)
+    log("flushing all passphrases");
+  p = P_ROOT->next;
+  while (p != P_ROOT) {
+    phrase *pp = p->next;
+    if (!tag)
+      p_free(p);
+    else if (strcmp(p->tag, tag) == 0) {
+      if (verbose > 1)
+       log("flushing passphrase `%s'", tag);
+      p_free(p);
+      break;
+    }
+    p = pp;
+  }
+}
+
+/*----- Reading passphrases -----------------------------------------------*/
+
+/* --- @p_request@ --- *
+ *
+ * Arguments:  @const char *msg@ = message string
+ *             @const char *tag@ = pointer to tag string
+ *             @char *buf@ = pointer to (locked) buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    Zero if all went well, nonzero otherwise.
+ *
+ * Use:                Requests a passphrase from the user.
+ */
+
+static int p_request(const char *msg, const char *tag, char *buf, size_t sz)
+{
+  /* --- If there's a passphrase-fetching command, run it --- */
+
+  if (command) {
+    dstr d = DSTR_INIT;
+    const char *p;
+    int fd[2];
+    pid_t kid;
+    int r;
+    int rc;
+
+    /* --- Substitute the prompt string into the command --- */
+
+    p = command;
+    for (;;) {
+      const char *q = strchr(p, '%');
+      if (!q || !q[1]) {
+       DPUTS(&d, p);
+       break;
+      }
+      DPUTM(&d, p, q - p);
+      p = q + 1;
+      switch (*p) {
+       case 'm':
+         DPUTS(&d, msg);
+         break;
+       case 't':
+         DPUTS(&d, tag);
+         break;
+       default:
+         DPUTC(&d, '%');
+         DPUTC(&d, *p);
+         break;
+      }
+      p++;
+    }
+    DPUTZ(&d);
+
+    /* --- Create a pipe and start a child process --- */
+
+    if (pipe(fd))
+      goto fail_1;
+    if ((kid = fork()) < 0)
+      goto fail_2;
+
+    /* --- Child process --- */
+
+    fflush(0);
+    if (kid == 0) {
+      if (dup2(fd[1], STDOUT_FILENO) < 0)
+       _exit(127);
+      close(fd[0]);
+      execl("/bin/sh", "sh", "-c", d.buf, (char *)0);
+      _exit(127);
+    }
+
+    /* --- Read the data back into my buffer --- */
+
+    close(fd[1]);
+    if ((r = read(fd[0], buf, sz - 1)) >= 0) {
+      char *q = memchr(buf, '\n', r);
+      if (!q)
+       q = buf + r;
+      *q = 0;
+    }
+    close(fd[0]);
+    waitpid(kid, &rc, 0);
+    dstr_destroy(&d);
+    if (r < 0 || rc != 0)
+      goto fail_0;
+    goto ok;
+
+    /* --- Tidy up when things go wrong --- */
+
+  fail_2:
+    close(fd[0]);
+    close(fd[1]);
+  fail_1:
+    dstr_destroy(&d);
+  fail_0:
+    return (-1);
+  }
+
+  /* --- Read a passphrase from the terminal --- *
+   *
+   * Use the standard Catacomb passphrase-reading function, so it'll read the
+   * passphrase from a file descriptor or something if the appropriate
+   * environment variable is set.
+   */
+
+  {
+    dstr d = DSTR_INIT;
+    int rc;
+    dstr_putf(&d, "%s %s: ", msg, tag);
+    rc = pixie_getpass(d.buf, buf, sz);
+    dstr_destroy(&d);
+    if (rc)
+      return (rc);
+    goto ok;
+  }
+
+  /* --- Sort out the buffer --- *
+   *
+   * Strip leading spaces.
+   */
+
+ok: {
+    char *p = buf;
+    size_t len;
+    while (isspace((unsigned char)*p))
+      p++;
+    len = strlen(p);
+    memmove(buf, p, len);
+    p[len] = 0;
+  }
+
+  /* --- Done --- */
+
+  return (0);
+}
+
+/* --- @p_get@ --- *
+ *
+ * Arguments:  @const char **q@ = where to store the result
+ *             @const char *tag@ = pointer to tag string
+ *             @unsigned mode@ = reading mode (verify?)
+ *             @time_t exp@ = expiry time suggestion
+ *
+ * Returns:    Zero if successful, @-1@ on a read failure, or @+1@ if the
+ *             passphrase is missing and there is no fetcher.  (This will
+ *             always happen if there is no fetcher and @mode@ is
+ *             @PMODE_VERIFY@.
+ *
+ * Use:                Reads a passphrase from somewhere.
+ */
+
+static int p_get(const char **q, const char *tag, unsigned mode, time_t exp)
+{
+#define LBUFSZ 1024
+
+  phrase *p;
+  char *pp = 0;
+
+  /* --- Write a log message --- */
+
+  if (verbose > 1)
+    log("passphrase `%s' requested", tag);
+
+  /* --- If there is no fetcher, life is simpler --- */
+
+  if (!(flags & F_FETCH)) {
+    if (mode == PMODE_VERIFY)
+      return (+1);
+    if ((p = p_find(tag)) == 0)
+      return (+1);
+    *q = p->p;
+    return (0);
+  }
+
+  /* --- Try to find the phrase --- */
+
+  if (mode == PMODE_VERIFY)
+    p_flush(tag);
+  if (mode == PMODE_VERIFY || (p = p_find(tag)) == 0) {
+    if ((pp = p_alloc(LBUFSZ)) == 0)
+      goto fail;
+    if (p_request(mode == PMODE_READ ? "Passphrase" : "New passphrase",
+                 tag, pp, LBUFSZ) < 0)
+      goto fail;
+    p = p_add(tag, pp, exp);
+    if (!p)
+      goto fail;
+  }
+
+  /* --- If verification is requested, verify the passphrase --- */
+
+  if (mode == PMODE_VERIFY) {
+    if (!pp && (pp = p_alloc(LBUFSZ)) == 0)
+      goto fail;
+    if (p_request("Verify passphrase", tag, pp, LBUFSZ) < 0)
+      goto fail;
+    if (strcmp(pp, p->p) != 0) {
+      if (verbose)
+       log("passphrases for `%s' don't match", tag);
+      p_free(p);
+      goto fail;
+    }
+  }
+
+  /* --- Tidy up and return the passphrase --- */
+
+  if (pp) {
+    memset(pp, 0, LBUFSZ);
+    l_free(&lm, pp);
+  }
+  *q = p->p;
+  return (0);
+
+  /* --- Tidy up if things went wrong --- */
+
+fail:
+  if (pp) {
+    memset(pp, 0, LBUFSZ);
+    l_free(&lm, pp);
+  }
+  return (-1);
+
+#undef LBUFSZ
+}
+
+/*----- Server command parsing --------------------------------------------*/
+
+/* --- Data structures --- */
+
+typedef struct pixserv {
+  selbuf b;
+  int fd;
+  sel_timer timer;
+  unsigned f;
+} pixserv;
+
+#define px_stdin 1u
+
+#define PIXSERV_TIMEOUT 30
+
+/* --- @pixserv_expire@ --- *
+ *
+ * Arguments:  @struct timeval *tv@ = pointer to current time
+ *             @void *p@ = pointer to server block
+ *
+ * Returns:    ---
+ *
+ * Use:                Expires a pixie connection if the remote end decides he's not
+ *             interested any more.
+ */
+
+static void pixserv_expire(struct timeval *tv, void *p)
+{
+  pixserv *px = p;
+  if (px->fd != px->b.reader.fd)
+    close(px->fd);
+  selbuf_destroy(&px->b);
+  close(px->b.reader.fd);
+  DESTROY(px);
+}
+
+/* --- @pixserv_write@ --- *
+ *
+ * Arguments:  @pixserv *px@ = pointer to server block
+ *             @const char *p@ = pointer to skeleton string
+ *             @...@ = other arguments to fill in
+ *
+ * Returns:    ---
+ *
+ * Use:                Formats a string and emits it to the output file.
+ */
+
+static void pixserv_write(pixserv *px, const char *p, ...)
+{
+  dstr d = DSTR_INIT;
+  va_list ap;
+
+  va_start(ap, p);
+  dstr_vputf(&d, p, &ap);
+  write(px->fd, d.buf, d.len);
+  va_end(ap);
+  dstr_destroy(&d);
+}
+
+/* --- @pixserv_timeout@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to timeout string
+ *
+ * Returns:    Timeout in seconds.
+ *
+ * Use:                Translates a string to a timeout value in seconds.
+ */
+
+static unsigned long pixserv_timeout(const char *p)
+{
+  unsigned long t;
+  char *q;
+
+  if (!p)
+    return (timeout);
+
+  t = strtoul(p, &q, 0);
+  switch (*q) {
+    case 'd': t *= 24;
+    case 'h': t *= 60;
+    case 'm': t *= 60;
+    case 's': if (q[1] != 0)
+      default:   t = 0;
+    case 0:   break;
+  }
+  return (t);
+}
+
+/* --- @pixserv_line@ --- *
+ *
+ * Arguments:  @char *s@ = pointer to the line read
+ *             @size_t len@ = length of the line
+ *             @void *p@ = pointer to server block
+ *
+ * Returns:    ---
+ *
+ * Use:                Handles a line read from the client.
+ */
+
+static void pixserv_line(char *s, size_t len, void *p)
+{
+  pixserv *px = p;
+  char *q, *qq;
+  unsigned mode;
+
+  /* --- Handle an end-of-file --- */
+
+  if (!(px->f & px_stdin))
+    sel_rmtimer(&px->timer);
+  if (!s) {
+    if (px->fd != px->b.reader.fd)
+      close(px->fd);
+    selbuf_destroy(&px->b);
+    close(px->b.reader.fd);
+    return;
+  }
+
+  /* --- Fiddle the timeout --- */
+
+  if (!(px->f & px_stdin)) {
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    tv.tv_sec += PIXSERV_TIMEOUT;
+    sel_addtimer(&sel, &px->timer, &tv, pixserv_expire, px);
+  }
+
+  /* --- Scan out the first word --- */
+
+  if ((q = str_getword(&s)) == 0)
+    return;
+  for (qq = q; *qq; qq++)
+    *qq = tolower((unsigned char)*qq);
+
+  /* --- Handle a help request --- */
+
+  if (strcmp(q, "help") == 0) {
+    pixserv_write(px, "\
+INFO Commands supported:\n\
+INFO HELP\n\
+INFO LIST\n\
+INFO PASS tag [expire]\n\
+INFO VERIFY tag [expire]\n\
+INFO FLUSH [tag]\n\
+INFO SET tag [expire] -- phrase\n\
+INFO QUIT\n\
+OK\n\
+");
+  }
+
+  /* --- List the passphrases --- */
+
+  else if (strcmp(q, "list") == 0) {
+    phrase *p;
+
+    for (p = P_ROOT->next; p != P_ROOT; p = p->next) {
+      if (!p->t)
+       pixserv_write(px, "ITEM %s no-expire\n", p->tag);
+      else {
+       struct timeval tv;
+       gettimeofday(&tv, 0);
+       TV_SUB(&tv, &p->timer.tv, &tv);
+       pixserv_write(px, "ITEM %s %i\n", p->tag, tv.tv_sec);
+      }
+    }
+    pixserv_write(px, "OK\n");
+  }
+
+  /* --- Request a passphrase --- */
+
+  else if ((mode = PMODE_READ, strcmp(q, "pass") == 0) ||
+          (mode = PMODE_VERIFY, strcmp(q, "verify") == 0)) {
+    unsigned long t;
+    const char *p;
+    int rc;
+
+    if ((q = str_getword(&s)) == 0)
+      pixserv_write(px, "FAIL missing tag\n");
+    else if ((t = pixserv_timeout(s)) == 0)
+      pixserv_write(px, "FAIL bad timeout\n");
+    else {
+      rc = p_get(&p, q, mode, t > timeout ? timeout : t);
+      switch (rc) {
+       case 0:
+         pixserv_write(px, "OK %s\n", p);
+         break;
+       case -1:
+         pixserv_write(px, "FAIL error reading passphrase\n");
+         break;
+       case +1:
+         pixserv_write(px, "MISSING\n");
+         break;
+      }
+    }
+  }
+
+  /* --- Flush existing passphrases --- */
+
+  else if (strcmp(q, "flush") == 0) {
+    q = str_getword(&s);
+    p_flush(q);
+    pixserv_write(px, "OK\n");
+  }
+
+  /* --- Set a passphrase --- */
+
+  else if (strcmp(q, "set") == 0) {
+    char *tag;
+    unsigned long t;
+    if ((tag = str_getword(&s)) == 0)
+      pixserv_write(px, "FAIL missing tag\n");
+    else if ((q = str_getword(&s)) == 0)
+      pixserv_write(px, "FAIL no passphrase\n");
+    else {
+      if (strcmp(q, "--") != 0) {
+       t = pixserv_timeout(q);
+       q = str_getword(&s);
+      } else
+       t = pixserv_timeout(0);
+      if (!q)
+       pixserv_write(px, "FAIL no passphrase\n");
+      else if (strcmp(q, "--") != 0)
+       pixserv_write(px, "FAIL rubbish found before passphrase\n");
+      else {
+       p_flush(tag);
+       p_add(tag, s, t);
+       pixserv_write(px, "OK\n");
+      }
+    }
+  }
+
+  /* --- Shut the server down --- */
+
+  else if (strcmp(q, "quit") == 0) {
+    if (verbose)
+      log("%s client requested shutdown",
+         px->f & px_stdin ? "local" : "remote");
+    pixserv_write(px, "OK\n");
+    exit(0);
+  }
+
+  /* --- Report an error for other commands --- */
+
+  else
+    pixserv_write(px, "FAIL unknown command `%s'\n", q);
+}
+
+/* --- @pixserv_create@ --- *
+ *
+ * Arguments:  @int fd@ = file descriptor to read from
+ *             @int ofd@ = file descriptor to write to
+ *
+ * Returns:    Pointer to the new connection.
+ *
+ * Use:                Creates a new Pixie server instance for a new connection.
+ */
+
+static pixserv *pixserv_create(int fd, int ofd)
+{
+  pixserv *px = CREATE(pixserv);
+  struct timeval tv;
+  fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+  if (ofd != fd)
+    fdflags(ofd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+  px->fd = ofd;
+  selbuf_init(&px->b, &sel, fd, pixserv_line, px);
+  px->b.b.a = arena_secure;
+  selbuf_setsize(&px->b, 1024);
+  gettimeofday(&tv, 0);
+  tv.tv_sec += PIXSERV_TIMEOUT;
+  sel_addtimer(&sel, &px->timer, &tv, pixserv_expire, px);
+  px->f = 0;
+  return (px);
+}
+
+/* --- @pixserv_accept@ --- *
+ *
+ * Arguments:  @int fd@ = file descriptor
+ *             @unsigned mode@ = what's happened
+ *             @void *p@ = an uninteresting argument
+ *
+ * Returns:    ---
+ *
+ * Use:                Accepts a new connection.
+ */
+
+static void pixserv_accept(int fd, unsigned mode, void *p)
+{
+  int nfd;
+  struct sockaddr_un sun;
+  size_t sunsz = sizeof(sun);
+
+  if (mode != SEL_READ)
+    return;
+  if ((nfd = accept(fd, (struct sockaddr *)&sun, &sunsz)) < 0) {
+    if (verbose && errno != EAGAIN && errno != EWOULDBLOCK &&
+       errno != ECONNABORTED && errno != EPROTO && errno != EINTR)
+      log("new connection failed: %s", strerror(errno));
+    return;
+  }
+  pixserv_create(nfd, nfd);
+}
+
+/*----- Setting up the server ---------------------------------------------*/
+
+/* --- @unlinksocket@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    ---
+ *
+ * Use:                Tidies up the socket when it's finished with.
+ */
+
+static char *sockpath;
+
+static void unlinksocket(void)
+{
+  unlink(sockpath);
+  l_purge(&lm);
+}
+
+/* --- @pix_sigdie@ --- *
+ *
+ * Arguments:  @int sig@ = signal number
+ *             @void *p@ = uninteresting argument
+ *
+ * Returns:    ---
+ *
+ * Use:                Shuts down the program after a fatal signal.
+ */
+
+static void pix_sigdie(int sig, void *p)
+{
+  if (verbose) {
+    char *p;
+    char buf[20];
+
+    switch (sig) {
+      case SIGTERM:    p = "SIGTERM"; break;
+      case SIGINT:     p = "SIGINT"; break;
+      default:
+       sprintf(buf, "signal %i", sig);
+       p = buf;
+       break;
+    }
+    log("shutting down on %s", p);
+  }
+  exit(0);
+}
+
+/* --- @pix_sigflush@ --- *
+ *
+ * Arguments:  @int sig@ = signal number
+ *             @void *p@ = uninteresting argument
+ *
+ * Returns:    ---
+ *
+ * Use:                Flushes the passphrase cache on receipt of a signal.
+ */
+
+static void pix_sigflush(int sig, void *p)
+{
+  if (verbose) {
+    char *p;
+    char buf[20];
+
+    switch (sig) {
+      case SIGHUP:     p = "SIGHUP"; break;
+      case SIGQUIT:    p = "SIGQUIT"; break;
+      default:
+       sprintf(buf, "signal %i", sig);
+       p = buf;
+       break;
+    }
+    log("received %s; flushing passphrases", p);
+  }
+  p_flush(0);
+}
+
+/* --- @pix_setup@ --- *
+ *
+ * Arguments:  @struct sockaddr_un *sun@ = pointer to address to use
+ *             @size_t sz@ = size of socket address
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets up the pixie's Unix-domain socket.
+ */
+
+static void pix_setup(struct sockaddr_un *sun, size_t sz)
+{
+  int fd;
+
+  /* --- Set up the parent directory --- */
+
+  {
+    char *p = sun->sun_path;
+    char *q = strrchr(p, '/');
+
+    if (q) {
+      dstr d = DSTR_INIT;
+      struct stat st;
+
+      DPUTM(&d, p, q - p);
+      DPUTZ(&d);
+
+      mkdir(d.buf, 0700);
+      if (stat(d.buf, &st))
+       die(1, "couldn't stat `%s': %s", d.buf, strerror(errno));
+      if (!S_ISDIR(st.st_mode))
+       die(1, "object `%s' isn't a directory", d.buf);
+      if (st.st_mode & 0077)
+       die(1, "parent directory `%s' has group or world access", d.buf);
+      dstr_destroy(&d);
+    }
+  }
+
+  /* --- Initialize the socket --- */
+
+  {
+    int n = 5;
+    int e;
+
+    umask(0077);
+  again:
+    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+      die(1, "couldn't create socket: %s", strerror(errno));
+    if (bind(fd, (struct sockaddr *)sun, sz) < 0) {
+      e = errno;
+      if (errno != EADDRINUSE)
+       die(1, "couldn't bind to address: %s", strerror(e));
+      if (!n)
+       die(1, "too many retries; giving up");
+      n--;
+      if (connect(fd, (struct sockaddr *)sun, sz)) {
+       struct stat st;
+       if (errno != ECONNREFUSED)
+         die(1, "couldn't bind to address: %s", strerror(e));
+       if (stat(sun->sun_path, &st))
+         die(1, "couldn't stat `%s': %s", sun->sun_path, strerror(errno));
+       if (!S_ISSOCK(st.st_mode))
+         die(1, "object `%s' isn't a socket", sun->sun_path);
+       if (verbose)
+         log("stale socket found; removing it");
+       unlink(sun->sun_path);
+       close(fd);
+      } else {
+       if (verbose)
+         log("server already running; shutting it down");
+       write(fd, "QUIT\n", 5);
+       sleep(1);
+       close(fd);
+      }
+      goto again;
+    }
+    chmod(sun->sun_path, 0600);
+    fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+    if (listen(fd, 5))
+      die(1, "couldn't listen on socket: %s", strerror(errno));
+  }
+
+  /* --- Set up the rest of the server --- */
+
+  {
+    static sel_file serv;
+    sockpath = sun->sun_path;
+    atexit(unlinksocket);
+    sel_initfile(&sel, &serv, fd, SEL_READ, pixserv_accept, 0);
+    sel_addfile(&serv);
+  }
+}
+
+/*----- Client support code -----------------------------------------------*/
+
+/* --- Variables --- */
+
+static selbuf c_server, c_client;
+static unsigned c_flags = 0;
+
+#define cf_uclose 1u
+#define cf_sclose 2u
+#define cf_cooked 4u
+
+/* --- Line handler functions --- */
+
+static void c_uline(char *s, size_t len, void *p)
+{
+  if (!s) {
+    selbuf_destroy(&c_client);
+    shutdown(c_server.reader.fd, 1);
+    c_flags |= cf_uclose;
+  } else {
+    s[len++] = '\n';
+    write(c_server.reader.fd, s, len);
+  }
+}
+
+static void c_sline(char *s, size_t len, void *p)
+{
+  if (!s) {
+    selbuf_destroy(&c_server);
+    if (!(c_flags & cf_uclose)) {
+      moan("server closed the connection");
+      selbuf_destroy(&c_client);
+    }
+    exit(0);
+  }
+  if (!(c_flags & cf_cooked))
+    puts(s);
+  else {
+    char *q = str_getword(&s);
+    if (strcmp(q, "FAIL") == 0)
+      die(1, "%s", s);
+    else if (strcmp(q, "INFO") == 0 ||
+            strcmp(q, "ITEM") == 0)
+      puts(s);
+    else if (strcmp(q, "OK") == 0) {
+      if (s && *s) puts(s);
+    } else if (strcmp(q, "MISSING") == 0)
+      ;
+    else
+      moan("unexpected output: %s %s", q, s);
+  }
+}
+
+/* --- @pix_client@ --- *
+ *
+ * Arguments:  @struct sockaddr_un *sun@ = pointer to socket address
+ *             @size_t sz@ = size of socket address
+ *             @char *argv[]@ = pointer to arguments to send
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs client-side actions for the passphrase pixie.
+ */
+
+static void pix_client(struct sockaddr_un *sun, size_t sz, char *argv[])
+{
+  int fd;
+
+  /* --- Dispose of locked memory --- */
+
+  l_destroy(&lm);
+
+  /* --- Open the socket --- */
+
+  if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+    die(1, "couldn't create socket: %s", strerror(errno));
+  if (connect(fd, (struct sockaddr *)sun, sz))
+    die(1, "couldn't connect to server: %s", strerror(errno));
+  selbuf_init(&c_server, &sel, fd, c_sline, 0);
+
+  /* --- If there are any arguments, turn them into a string --- */
+
+  if (!*argv)
+    selbuf_init(&c_client, &sel, STDIN_FILENO, c_uline, 0);
+  else {
+    dstr d = DSTR_INIT;
+    DPUTS(&d, *argv++);
+    while (*argv) {
+      DPUTC(&d, ' ');
+      DPUTS(&d, *argv++);
+    }
+    DPUTC(&d, '\n');
+    write(fd, d.buf, d.len);
+    shutdown(fd, 1);
+    c_flags |= cf_uclose | cf_cooked;
+    dstr_destroy(&d);
+  }
+
+  /* --- And repeat --- */
+
+  for (;;) {
+    if (sel_select(&sel))
+      die(EXIT_FAILURE, "select error: %s", strerror(errno));
+  }
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @help@, @version@, @usage@ --- *
+ *
+ * Arguments:  @FILE *fp@ = stream to write on
+ *
+ * Returns:    ---
+ *
+ * Use:                Emit helpful messages.
+ */
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "\
+Usage:\n\
+       $ [-qvfidl] [-c COMMAND] [-t TIMEOUT] [-s SOCKET]\n\
+       $ [-s SOCKET] -C [COMMAND ARGS...]\n\
+       $ [-s SOCKET] -P[P] TAG\n\
+");
+}
+
+static void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+static void help(FILE *fp)
+{
+  version(fp);
+  fputc('\n', fp);
+  usage(fp);
+  pquis(fp, "\n\
+The Catacomb passphrase pixie collects and caches passphrases used to\n\
+protect important keys.  Options provided:\n\
+\n\
+-h, --help             Show this help text.\n\
+-V, --version          Show the program's version number.\n\
+-u, --usage            Show a (very) terse usage summary.\n\
+\n\
+-C, --client           Connect to a running pixie as a client.\n\
+-P, --passphrase       Request passphrase TAG and print to stdout.\n\
+-PP, --verify-passphrase\n\
+                       Verify passphrase TAG and print to stdout.\n\
+\n\
+-q, --quiet            Emit fewer log messages.\n\
+-v, --version          Emit more log messages.\n\
+-s, --socket=FILE      Name the pixie's socket.\n\
+-c, --command=COMMAND  Shell command to read a passphrase.\n\
+-f, --fetch            Fetch passphrases from the terminal.\n\
+-t, --timeout=TIMEOUT  Length of time to retain a passphrase in memory.\n\
+-i, --interactive      Allow commands to be typed interactively.\n\
+-d, --daemon           Fork into the background after initialization.\n\
+-l, --syslog           Emit log messages to the system log.\n\
+\n\
+The COMMAND may contain `%m' and `%t' markers which are replaced by a\n\
+prompt message and the passphrase tag respectively.  The TIMEOUT is an\n\
+integer, optionally followed by `d', `h', `m' or `s' to specify units of\n\
+days, hours, minutes or seconds respectively.\n\
+\n\
+In client mode, if a command is specified on the command line, it is sent\n\
+to the running server; otherwise the program reads requests from stdin.\n\
+Responses from the pixie are written to stdout.  Send a HELP request for\n\
+a quick summary of the pixie communication protocol.\n\
+");
+}
+
+/* --- @main@ --- *
+ *
+ * Arguments:  @int argc@ = number of arguments
+ *             @char *argv[]@ = vector of argument values
+ *
+ * Returns:    Zero if OK.
+ *
+ * Use:                Main program.  Listens on a socket and responds with a PGP
+ *             passphrase when asked.
+ */
+
+int main(int argc, char *argv[])
+{
+  char *path = 0;
+  struct sockaddr_un *sun;
+  size_t sz;
+  unsigned f = 0;
+
+#define f_bogus 1u
+#define f_client 2u
+#define f_stdin 4u
+#define f_daemon 8u
+#define f_syslog 16u
+#define f_fetch 32u
+#define f_verify 64u
+
+  /* --- Initialize libraries --- */
+
+  ego(argv[0]);
+  sub_init();
+
+  /* --- Set up the locked memory area --- */
+
+  l_init(&lm, 16384);
+  setuid(getuid());
+
+  /* --- Parse command line arguments --- */
+
+  for (;;) {
+    static struct option opts[] = {
+
+      /* --- Standard GNUy help options --- */
+
+      { "help",                0,              0,      'h' },
+      { "version",     0,              0,      'V' },
+      { "usage",       0,              0,      'u' },
+
+      /* --- Other options --- */
+
+      { "quiet",       0,              0,      'q' },
+      { "verbose",     0,              0,      'v' },
+      { "client",      0,              0,      'C' },
+      { "passphrase",  0,              0,      'P' },
+      { "verify-passphrase",   0,      0,      '+' },
+      { "socket",      OPTF_ARGREQ,    0,      's' },
+      { "command",     OPTF_ARGREQ,    0,      'c' },
+      { "fetch",       0,              0,      'f' },
+      { "timeout",     OPTF_ARGREQ,    0,      't' },
+      { "interactive", 0,              0,      'i' },
+      { "stdin",       0,              0,      'i' },
+      { "daemon",      0,              0,      'd' },
+      { "log",         0,              0,      'l' },
+      { "syslog",      0,              0,      'l' },
+
+      /* --- Magic terminator --- */
+
+      { 0,             0,              0,      0 }
+    };
+
+    int i = mdwopt(argc, argv, "hVuqvCPs:c:ft:idl", opts, 0, 0, 0);
+    if (i < 0)
+      break;
+
+    switch (i) {
+
+      /* --- GNUy help options --- */
+
+      case 'h':
+       help(stdout);
+       exit(0);
+      case 'V':
+       version(stdout);
+       exit(0);
+      case 'u':
+       usage(stdout);
+       exit(0);
+
+      /* --- Other interesting things --- */
+
+      case 'q':
+       if (verbose)
+         verbose--;
+       break;
+      case 'v':
+       verbose++;
+       break;
+      case 'C':
+       f |= f_client;
+       f &= ~f_fetch;
+       break;
+      case 'P':
+       if (!(f & f_fetch))
+         f |= f_fetch;
+       else
+         f |= f_verify;
+       break;
+      case '+':
+       f |= f_fetch | f_verify;
+       f &= ~f_client;
+       break;
+      case 's':
+       path = optarg;
+       break;
+      case 't':
+       if ((timeout = pixserv_timeout(optarg)) == 0)
+         die(1, "bad timeout `%s'", optarg);
+       break;
+      case 'c':
+       command = optarg;
+       flags |= F_FETCH;
+       break;
+      case 'f':
+       flags |= F_FETCH;
+       break;
+      case 'i':
+       f |= f_stdin;
+       break;
+      case 'd':
+       f |= f_daemon;
+       break;
+      case 'l':
+       f |= f_syslog;
+       break;
+
+      /* --- Something else --- */
+
+      default:
+       f |= f_bogus;
+       break;
+    }
+  }
+
+  if (f & f_bogus ||
+      (optind < argc && !(f & (f_client|f_fetch))) ||
+      ((f & f_fetch) && optind != argc - 1)) {
+    usage(stderr);
+    exit(1);
+  }
+
+  /* --- Handle request for a passphrase --- */
+
+  if (f & f_fetch) {
+    char *buf = l_alloc(&lm, 1024);
+    passphrase_connect(path);
+    if (passphrase_read(argv[optind],
+                       (f & f_verify) ? PMODE_VERIFY : PMODE_READ,
+                       buf, 1024))
+      die(1, "failed to read passphrase: %s", strerror(errno));
+    puts(buf);
+    return (0);
+  }
+
+  /* --- Set up the socket address --- */
+
+  sun = pixie_address(path, &sz);
+
+  /* --- Initialize selectory --- */
+
+  sel_init(&sel);
+  signal(SIGPIPE, SIG_IGN);
+
+  /* --- Be a client if a client's wanted --- */
+
+  if (f & f_client)
+    pix_client(sun, sz, argv + optind);
+
+  /* --- Open the syslog if requested --- */
+
+  if (f & f_syslog) {
+    flags |= F_SYSLOG;
+    openlog(QUIS, 0, LOG_DAEMON);
+  }
+
+  /* --- Check on the locked memory area --- */
+
+  {
+    dstr d = DSTR_INIT;
+    int rc = l_report(&lm, &d);
+    if (rc < 0)
+      die(EXIT_FAILURE, d.buf);
+    else if (rc && verbose) {
+      log(d.buf);
+      log("couldn't lock passphrase buffer");
+    }
+    dstr_destroy(&d);
+    arena_setsecure(&lm.a);
+  }
+
+  /* --- Set signal behaviours --- */
+
+  {
+    static sig sigint, sigterm, sigquit, sighup;
+    struct sigaction sa;
+    sig_init(&sel);
+    sigaction(SIGINT, 0, &sa);
+    if (sa.sa_handler != SIG_IGN)
+      sig_add(&sigint, SIGINT, pix_sigdie, 0);
+    sig_add(&sigterm, SIGTERM, pix_sigdie, 0);
+    sig_add(&sigquit, SIGQUIT, pix_sigflush, 0);
+    sig_add(&sighup, SIGHUP, pix_sigflush, 0);
+  }
+
+  /* --- Set up the server --- */
+
+  pix_setup(sun, sz);
+  if (f & f_stdin) {
+    pixserv *px = pixserv_create(STDIN_FILENO, STDOUT_FILENO);
+    sel_rmtimer(&px->timer);
+    px->f |= px_stdin;
+  }
+
+  /* --- Fork into the background if requested --- */
+
+  if (f & f_daemon) {
+    pid_t kid;
+
+    if (((f & f_stdin) &&
+        (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO))) ||
+       (!command && (flags & F_FETCH)))
+      die(1, "can't become a daemon if terminal required");
+
+    if ((kid = fork()) < 0)
+      die(1, "fork failed: %s", strerror(errno));
+    if (kid)
+      _exit(0);
+#ifdef TIOCNOTTY
+    {
+      int fd;
+      if ((fd = open("/dev/tty", O_RDONLY)) >= 0) {
+       ioctl(fd, TIOCNOTTY);
+       close(fd);
+      }
+    }
+#endif
+    chdir("/");
+    setsid();
+
+    if (fork() != 0)
+      _exit(0);
+  }
+
+  if (verbose)
+    log("initialized ok");
+
+  {
+    int selerr = 0;
+    for (;;) {
+      if (!sel_select(&sel))
+       selerr = 0;
+      else if (errno != EINTR && errno != EAGAIN) {
+       log("error from select: %s", strerror(errno));
+       selerr++;
+       if (selerr > 8) {
+         log("too many consecutive select errors: bailing out");
+         exit(EXIT_FAILURE);
+       }
+      }
+    }
+  }
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/progs/rspit.c b/progs/rspit.c
new file mode 100644 (file)
index 0000000..1819a61
--- /dev/null
@@ -0,0 +1,1400 @@
+/* -*-c-*-
+ *
+ * Spit out random numbers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef PORTABLE
+#  include <unistd.h>
+#endif
+
+#include <mLib/darray.h>
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+#include <mLib/sub.h>
+
+#include "fipstest.h"
+#include "grand.h"
+#include "maurer.h"
+#include "key.h"
+
+#include "lcrand.h"
+#include "fibrand.h"
+#include "rand.h"
+#include "noise.h"
+
+#include "bbs.h"
+#include "mprand.h"
+
+#include "rc4.h"
+#include "seal.h"
+
+#include "des-ofb.h"
+#include "des3-ofb.h"
+#include "rc2-ofb.h"
+#include "rc5-ofb.h"
+#include "mars-ofb.h"
+#include "skipjack-ofb.h"
+#include "tea-ofb.h"
+#include "xtea-ofb.h"
+#include "blowfish-ofb.h"
+#include "twofish-ofb.h"
+#include "idea-ofb.h"
+#include "cast128-ofb.h"
+#include "cast256-ofb.h"
+#include "noekeon-ofb.h"
+#include "rijndael-ofb.h"
+#include "rijndael192-ofb.h"
+#include "rijndael256-ofb.h"
+#include "safer-ofb.h"
+#include "safersk-ofb.h"
+#include "square-ofb.h"
+#include "serpent-ofb.h"
+
+#include "des-counter.h"
+#include "des3-counter.h"
+#include "rc2-counter.h"
+#include "rc5-counter.h"
+#include "mars-counter.h"
+#include "skipjack-counter.h"
+#include "tea-counter.h"
+#include "xtea-counter.h"
+#include "blowfish-counter.h"
+#include "twofish-counter.h"
+#include "idea-counter.h"
+#include "cast128-counter.h"
+#include "cast256-counter.h"
+#include "noekeon-counter.h"
+#include "rijndael-counter.h"
+#include "rijndael192-counter.h"
+#include "rijndael256-counter.h"
+#include "safer-counter.h"
+#include "safersk-counter.h"
+#include "square-counter.h"
+#include "serpent-counter.h"
+
+#include "md2-mgf.h"
+#include "md4-mgf.h"
+#include "md5-mgf.h"
+#include "sha-mgf.h"
+#include "tiger-mgf.h"
+#include "rmd128-mgf.h"
+#include "rmd160-mgf.h"
+#include "rmd256-mgf.h"
+#include "rmd320-mgf.h"
+
+#include "rmd160.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct gen {
+  const char *name;
+  grand *(*seed)(unsigned /*i*/);
+  unsigned i;
+  const char *help;
+} gen;
+
+extern gen generators[];
+
+#define CIPHERS                                                                \
+  E(DES, des)                                                          \
+  E(DES3, des3)                                                                \
+  E(RC2, rc2)                                                          \
+  E(RC5, rc5)                                                          \
+  E(MARS, mars)                                                                \
+  E(SKIPJACK, skipjack)                                                        \
+  E(TEA, tea)                                                          \
+  E(XTEA, xtea)                                                                \
+  E(BLOWFISH, blowfish)                                                        \
+  E(TWOFISH, twofish)                                                  \
+  E(IDEA, idea)                                                                \
+  E(CAST128, cast128)                                                  \
+  E(CAST256, cast256)                                                  \
+  E(SQUARE, square)                                                    \
+  E(SAFER, safer)                                                      \
+  E(SAFERSK, safersk)                                                  \
+  E(NOEKEON, noekeon)                                                  \
+  E(RIJNDAEL, rijndael)                                                        \
+  E(RIJNDAEL192, rijndael192)                                          \
+  E(RIJNDAEL256, rijndael256)                                          \
+  E(SERPENT, serpent)
+
+#define HASHES                                                         \
+  E(MD2, md2)                                                          \
+  E(MD4, md4)                                                          \
+  E(MD5, md5)                                                          \
+  E(SHA, sha)                                                          \
+  E(TIGER, tiger)                                                      \
+  E(RMD128, rmd128)                                                    \
+  E(RMD160, rmd160)                                                    \
+  E(RMD256, rmd256)                                                    \
+  E(RMD320, rmd320)
+
+#define E(PRE, pre) CIPHER_##PRE,
+enum { CIPHERS CIPHER__bogus };
+#undef E
+
+#define E(PRE, pre) HASH_##PRE,
+enum { HASHES HASH__bogus };
+#undef E
+
+static struct {
+  const octet *keysz;
+  size_t blksz;
+  grand *(*ofb)(const void */*k*/, size_t /*sz*/);
+  grand *(*counter)(const void */*k*/, size_t /*sz*/);
+} ciphertab[] = {
+#define E(PRE, pre)                                                    \
+  { pre##_keysz, PRE##_BLKSZ, pre##_ofbrand, pre##_counterrand },
+  CIPHERS
+#undef E
+};
+
+static struct {
+  const gchash *h;
+  const octet *keysz;
+  grand *(*mgf)(const void */*k*/, size_t /*sz*/);
+} hashtab[] = {
+#define E(PRE, pre)                                                    \
+  { &pre, pre##_mgfkeysz, pre##_mgfrand },
+  HASHES
+#undef E
+};
+
+/*----- Miscellaneous static data -----------------------------------------*/
+
+static FILE *outfp;
+static size_t outsz = 0;
+static unsigned maurer_lo = 5, maurer_hi = 8;
+
+static int argc;
+static char **argv;
+
+static unsigned flags = 0;
+
+#define f_progress 1u
+#define f_file 2u
+#define f_fips 4u
+#define f_maurer 8u
+#define f_timer 16u
+#define f_discard 32u
+
+/*----- Help options ------------------------------------------------------*/
+
+static void usage(FILE *fp)
+{
+  pquis(fp, "Usage: $ generator [options]\n");
+}
+
+static void version(FILE *fp)
+{
+  pquis(fp, "$, Catacomb version " VERSION "\n");
+}
+
+static void help(FILE *fp)
+{
+  version(fp);
+  fputc('\n', fp);
+  usage(fp);
+  pquis(fp, "\n\
+Emits a stream of random bytes suitable for, well, all sorts of things.\n\
+The primary objective is to be able to generate streams of input for\n\
+statistical tests, such as Diehard.\n\
+\n\
+Options are specific to the particular generator, although there's a\n\
+common core set:\n\
+\n\
+-h, --help             Display this help message.\n\
+-v, --version          Display the program's version number.\n\
+-u, --usage            Display a useless usage message.\n\
+\n\
+-l, --list             Show a list of the supported generators, with\n\
+                       their options.\n\
+-f, --fipstest         Run the FIPS 140-1 randomness test.\n\
+-m, --maurer[=LO-HI]   Run Maurer's universal statistical test.\n\
+-o, --output FILE      Write output to FILE, not stdout.\n\
+-z, --size SIZE                Emit SIZE bytes, not an unlimited number.\n\
+-p, --progress         Show a little progress meter (on stderr).\n\
+-T, --timer            Keep track of the CPU time used by the generator.\n\
+-d, --discard          Discard the generated output.\n\
+\n\
+(A SIZE may be followed by `g' for gigabytes, `m' for megabytes, or\n\
+`k' for kilobytes.  If unqualified, an amount in bytes is assumed.)\n\
+");
+}
+
+/*----- Main options parser -----------------------------------------------*/
+
+static struct option opts[] = {
+
+  /* --- Standard GNU help options --- */
+
+  { "help",    0,              0,      'h' },
+  { "version", 0,              0,      'v' },
+  { "usage",   0,              0,      'u' },
+
+  /* --- Other useful things --- */
+
+  { "list",    0,              0,      'l' },
+  { "fipstest",        0,              0,      'f' },
+  { "maurer",  OPTF_ARGOPT,    0,      'm' },
+  { "output",  OPTF_ARGREQ,    0,      'o' },
+  { "size",    OPTF_ARGREQ,    0,      'z' },
+  { "progress",        0,              0,      'p' },
+  { "timer",   0,              0,      'T' },
+  { "discard", 0,              0,      'd' },
+
+  /* --- End of main table --- */
+
+  { 0,         0,              0,      0 }
+};
+
+static const char *sopts = "hvu lfm::o:z:pTd";
+
+#ifndef OPTION_V
+   DA_DECL(option_v, struct option);
+#  define OPTION_V
+#endif
+
+static option_v optv = DA_INIT;
+static dstr optd = DSTR_INIT;
+
+/* --- @addopts@ --- *
+ *
+ * Arguments:  @const char *s@ = pointer to short options
+ *             @struct option *l@ = pointer to long options
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds a collection of options to the table.
+ */
+
+static void addopts(const char *s, struct option *l)
+{
+  dstr_puts(&optd, s);
+  if (DA_LEN(&optv))
+    DA_SHRINK(&optv, 1);
+  while (l->name)
+    DA_PUSH(&optv, *l++);
+  DA_PUSH(&optv, *l);
+}
+
+/* --- @opt@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    Next option from argument array.
+ *
+ * Use:                Fetches options, handling the standard ones.
+ */
+
+static int opt(void)
+{
+  for (;;) {
+    int i = mdwopt(argc, argv, optd.buf, DA(&optv), 0, 0, 0);
+    switch (i) {
+      case 'h':
+       help(stdout);
+       exit(0);
+      case 'v':
+       version(stdout);
+       exit(0);
+      case 'u':
+       usage(stdout);
+       exit(0);
+      case 'l': {
+       gen *g;
+       puts("Generators supported:");
+       for (g = generators; g->name; g++)
+         printf("  %s %s\n", g->name, g->help);
+       exit(0);
+      } break;
+      case 'f':
+       flags |= f_fips;
+       break;
+      case 'm':
+       flags |= f_maurer;
+       if (optarg) {
+         char *p;
+         unsigned long lo, hi;
+         lo = strtoul(optarg, &p, 0);
+         if (*p == '-' || *p == ',')
+           hi = strtoul(p + 1, &p, 0);
+         else
+           hi = lo;
+         if (*p != 0 || hi < lo || lo == 0)
+           die(EXIT_FAILURE, "bad bit range `%s'", optarg);
+         maurer_lo = lo;
+         maurer_hi = hi;
+       }
+       break;
+      case 'o':
+       if (flags & f_file)
+         die(EXIT_FAILURE, "already set an output file");
+       if (strcmp(optarg, "-") == 0)
+         outfp = stdout;
+       else {
+         outfp = fopen(optarg, "w");
+         if (!outfp) {
+           die(EXIT_FAILURE, "couldn't open output file `%s': %s",
+               optarg, strerror(errno));
+         }
+       }
+       flags |= f_file;
+       break;
+      case 'z': {
+       char *p;
+       outsz = strtoul(optarg, &p, 0);
+       if (!outsz)
+         die(EXIT_FAILURE, "bad number `%s'", optarg);
+       switch (*p) {
+         case 'G': case 'g': outsz *= 1024;
+         case 'M': case 'm': outsz *= 1024;
+         case 'K': case 'k': outsz *= 1024;
+         case 0:
+           break;
+         default:
+           die(EXIT_FAILURE, "bad suffix `%s'", p);
+           break;
+       }
+       if (*p && p[1] != 0)
+         die(EXIT_FAILURE, "bad suffix `%s'", p);
+      } break;
+      case 'p':
+       flags |= f_progress;
+       break;
+      case 'T':
+       flags |= f_timer;
+       break;
+      case 'd':
+       flags |= f_discard;
+       break;
+      default:
+       return (i);
+    }
+  }
+}
+
+/*----- Manglers for seed strings -----------------------------------------*/
+
+/* --- @unhex@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to input string
+ *             @char **end@ = where the end goes
+ *             @dstr *d@ = output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Transforms a hex string into a chunk of binary data.
+ */
+
+static void unhex(const char *p, char **end, dstr *d)
+{
+  while (p[0] && p[1]) {
+    int x = p[0], y = p[1];
+    if ('0' <= x && x <= '9') x -= '0';
+    else if ('A' <= x && x <= 'F') x -= 'A' - 10;
+    else if ('a' <= x && x <= 'f') x -= 'a' - 10;
+    else x = 0;
+    if ('0' <= y && y <= '9') y -= '0';
+    else if ('A' <= y && y <= 'F') y -= 'A' - 10;
+    else if ('a' <= y && y <= 'f') y -= 'a' - 10;
+    else y = 0;
+    DPUTC(d, (x << 4) + y);
+    p += 2;
+  }
+  *end = (char *)p;
+}
+
+/* --- Generate a key --- */
+
+static void textkey(dstr *d, const char *p, const octet *ksz)
+{
+  size_t sz = strlen(p);
+
+  if (!sz)
+    die(EXIT_FAILURE, "zero-length key string");
+  if (keysz(sz, ksz) != sz)
+    DPUTM(d, p, sz);
+  else {
+    rmd160_mgfctx g;
+    rmd160_mgfinit(&g, p, sz);
+    sz = keysz(0, ksz);
+    dstr_ensure(d, sz);
+    rmd160_mgfencrypt(&g, 0, d->buf, sz);
+    d->len += sz;
+  }
+  assert(((void)"I can't seem to choose a good key size",
+         keysz(d->len, ksz) == d->len));
+}
+
+static void hexkey(dstr *d, const char *p, const octet *ksz)
+{
+  char *q;
+  unhex(optarg, &q, d);
+  if (*q)
+    die(EXIT_FAILURE, "bad hex key `%s'", p);
+  if (keysz(d->len, ksz) != d->len)
+    die(EXIT_FAILURE, "bad key length");
+}
+
+static void randkey(dstr *d, const octet *ksz)
+{
+  size_t sz = keysz(0, ksz);
+  dstr_ensure(d, sz);
+  rand_get(RAND_GLOBAL, d->buf, sz);
+  d->len += sz;
+}
+
+/*----- Generators --------------------------------------------------------*/
+
+/* --- Blum-Blum-Shub strong generator --- */
+
+static grand *gen_bbs(unsigned i)
+{
+  /* --- Default modulus --- *
+   *
+   * The factors of this number are
+   *
+   *  @p = 1229936431484295969649886203367009966370895964206162032259292413@
+   *     @7754313537966036459299022912838407755462506416274551744201653277@
+   *     @313130311731673973886822067@
+   *
+   *  @q = 9798171783943489959487301695884963889684294764514008432498259742@
+   *     @5374320073594018817245784145742769603334292182227671519041431067@
+   *     @61344781426317516045890159@
+   *
+   * Both %$p$% and %$q$% are prime; %$(p - 1)/2$% and %$(q - 1)/2$% have no
+   * common factors.  They were found using this program, with random
+   * starting points.
+   *
+   * I hope that, by publishing these factors, I'll dissuade people from
+   * actually using this modulus in an attempt to attain real security.  The
+   * program is quite quick at finding Blum numbers, so there's no excuse for
+   * not generating your own.
+   */
+
+  const char *mt =
+    "12051128439013574251357214209433471144307319411973256935382082"
+    "84356405274180923922403660880355098909699130818163691602989614"
+    "90135716255689660470370755013177656905237112577648090277537209"
+    "93607817155427455344810369808478266925293635284364998010510985"
+    "0503830397166360721262431179505917248447259735253684659338653";
+
+  /* --- Other things --- */
+
+  grand *r;
+  const char *xt = 0;
+  unsigned bits = 1024;
+  mp *m, *x;
+  unsigned show = 0;
+  const char *kfile = 0, *id = 0, *ktype = 0;
+
+  /* --- Parse options --- */
+
+  static struct option opts[] = {
+    { "modulus",       OPTF_ARGREQ,    0,      'M' },
+    { "generate",      0,              0,      'g' },
+    { "seed",          OPTF_ARGREQ,    0,      's' },
+    { "bits",          OPTF_ARGREQ,    0,      'b' },
+    { "show",          0,              0,      'S' },
+    { "keyring",       OPTF_ARGREQ,    0,      'k' },
+    { "id",            OPTF_ARGREQ,    0,      'i' },
+    { "type",          OPTF_ARGREQ,    0,      't' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("M:gs:b:Sk:i:t:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'M':
+       mt = optarg;
+       break;
+      case 'g':
+       mt = 0;
+       break;
+      case 's':
+       xt = optarg;
+       break;
+      case 'b':
+       bits = strtoul(optarg, 0, 0);
+       if (bits == 0)
+         die(EXIT_FAILURE, "bad number of bits `%s'", optarg);
+       break;
+      case 'S':
+       show = 1;
+       break;
+      case 'k':
+       kfile = optarg;
+       mt = 0;
+       break;
+      case 'i':
+       id = optarg;
+       mt = 0;
+       break;
+      case 't':
+       ktype = optarg;
+       mt = 0;
+       break;
+      default:
+       return (0);
+    }
+  }
+
+  /* --- Generate a modulus if one is requested --- */
+
+  if (mt) {
+    char *p;
+    m = mp_readstring(MP_NEW, mt, &p, 0);
+    if (!m || *p || (m->v[0] & 3) != 1)
+      die(EXIT_FAILURE, "bad modulus `%s'", mt);
+    /* Unfortunately I don't know how to test for a Blum integer */
+  } else if (kfile || id || ktype) {
+    key_file kf;
+    key *kk;
+    key_data *kd;
+
+    /* --- Open the key file --- */
+
+    if (!kfile)
+      kfile = "keyring";
+    if (key_open(&kf, kfile, KOPEN_READ, key_moan, 0)) {
+      die(EXIT_FAILURE, "error opening key file `%s': %s",
+         kfile, strerror(errno));
+    }
+
+    /* --- Find the key --- */
+
+    if (id) {
+      if ((kk = key_bytag(&kf, id)) == 0)
+       die(EXIT_FAILURE, "key `%s' not found", id);
+    } else {
+      if (!ktype)
+       ktype = "bbs";
+      if ((kk = key_bytype(&kf, ktype)) == 0)
+       die(EXIT_FAILURE, "no suitable key with type `%s' found", ktype);
+    }
+
+    /* --- Read the key data --- */
+
+    if ((kk->k->e & KF_ENCMASK) != KENC_STRUCT)
+      die(EXIT_FAILURE, "key is not structured");
+    if ((kd = key_structfind(kk->k, "n")) == 0)
+      die(EXIT_FAILURE, "key has no subkey `n'");
+    if ((kd->e & KF_ENCMASK) != KENC_MP)
+      die(EXIT_FAILURE, "incompatible subkey encoding");
+    m = MP_COPY(kd->u.m);
+    key_close(&kf);
+  } else {
+    bbs_priv bp;
+
+    if (bbs_gen(&bp, bits, &rand_global, 0,
+               (flags & f_progress) ? pgen_ev : 0, 0))
+      die(EXIT_FAILURE, "modulus generation failed");
+    m = bp.n;
+
+    if (show) {
+      fputs("p = ", stderr);
+      mp_writefile(bp.p, stderr, 10);
+      fputs("\nq = ", stderr);
+      mp_writefile(bp.q, stderr, 10);
+      fputs("\nn = ", stderr);
+      mp_writefile(bp.n, stderr, 10);
+      fputc('\n', stderr);
+    }
+
+    mp_drop(bp.p);
+    mp_drop(bp.q);
+  }
+
+  /* --- Set up a seed --- */
+
+  if (!xt)
+    x = mprand(MP_NEW, mp_bits(m) - 1, &rand_global, 1);
+  else {
+    char *p;
+    x = mp_readstring(MP_NEW, xt, &p, 0);
+    if (*p)
+      die(EXIT_FAILURE, "bad modulus `%s'", xt);
+  }
+
+  /* --- Right --- */
+
+  r = bbs_rand(m, x);
+
+  mp_drop(m);
+  mp_drop(x);
+  return (r);
+}
+
+/* --- Catacomb's random number generator --- */
+
+static grand *gen_rand(unsigned i)
+{
+  grand *r = rand_create();
+  dstr d = DSTR_INIT;
+
+  static struct option opts[] = {
+    { "key",           OPTF_ARGREQ,    0,      'k' },
+    { "text",          OPTF_ARGREQ,    0,      't' },
+    { "hex",           OPTF_ARGREQ,    0,      'H' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("k:t:H:n", opts);
+
+  r->ops->misc(r, RAND_NOISESRC, &noise_source);
+  r->ops->misc(r, RAND_SEED, 160);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'k':
+       DRESET(&d);
+       textkey(&d, optarg, rmd160_hmackeysz);
+       r->ops->misc(r, RAND_KEY, d.buf, d.len);
+       break;
+      case 't':
+       r->ops->misc(r, GRAND_SEEDBLOCK, optarg, strlen(optarg));
+       break;
+      case 'H':
+       DRESET(&d);
+       hexkey(&d, optarg, rmd160_hmackeysz);
+       r->ops->misc(r, GRAND_SEEDBLOCK, d.buf, d.len);
+       break;
+    }
+  }
+
+  dstr_destroy(&d);
+  return (r);
+}
+
+/* --- RC4 output --- */
+
+static grand *gen_rc4(unsigned i)
+{
+  grand *r;
+  dstr d = DSTR_INIT;
+
+  static struct option opts[] = {
+    { "key",           OPTF_ARGREQ,    0,      'k' },
+    { "hex",           OPTF_ARGREQ,    0,      'H' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("k:H:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'k':
+       DRESET(&d);
+       textkey(&d, optarg, rc4_keysz);
+       break;
+      case 'H':
+       DRESET(&d);
+       hexkey(&d, optarg, rc4_keysz);
+       break;
+      default:
+       return (0);
+    }
+  }
+
+  if (!d.len)
+    randkey(&d, rc4_keysz);
+  r = rc4_rand(d.buf, d.len);
+  dstr_destroy(&d);
+  return (r);
+}
+
+/* --- SEAL output --- */
+
+static grand *gen_seal(unsigned i)
+{
+  grand *r;
+  dstr d = DSTR_INIT;
+  uint32 n = 0;
+
+  static struct option opts[] = {
+    { "key",           OPTF_ARGREQ,    0,      'k' },
+    { "hex",           OPTF_ARGREQ,    0,      'H' },
+    { "sequence",      OPTF_ARGREQ,    0,      'n' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("k:H:n:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'k':
+       DRESET(&d);
+       textkey(&d, optarg, seal_keysz);
+       break;
+      case 'H':
+       DRESET(&d);
+       hexkey(&d, optarg, seal_keysz);
+       break;
+      case 'n': {
+       char *p;
+       n = strtoul(optarg, &p, 0);
+       if (*p)
+         die(EXIT_FAILURE, "bad number `%s'", optarg);
+      } break;
+      default:
+       return (0);
+    }
+  }
+
+  if (!d.len)
+    randkey(&d, seal_keysz);
+  r = seal_rand(d.buf, d.len, n);
+  dstr_destroy(&d);
+  return (r);
+}
+
+/* --- Output feedback generators --- */
+
+static grand *gen_ofb(unsigned i)
+{
+  grand *r;
+  dstr d = DSTR_INIT;
+  dstr iv = DSTR_INIT;
+
+  static struct option opts[] = {
+    { "key",           OPTF_ARGREQ,    0,      'k' },
+    { "hex",           OPTF_ARGREQ,    0,      'H' },
+    { "iv",            OPTF_ARGREQ,    0,      'i' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("k:H:i:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'k':
+       DRESET(&d);
+       textkey(&d, optarg, ciphertab[i].keysz);
+       break;
+      case 'H':
+       DRESET(&d);
+       hexkey(&d, optarg, ciphertab[i].keysz);
+       break;
+      case 'i': {
+       char *p;
+       unhex(optarg, &p, &iv);
+       if (*p)
+         die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
+      } break;
+      default:
+       return (0);
+    }
+  }
+
+  if (!d.len)
+    randkey(&d, ciphertab[i].keysz);
+  r = ciphertab[i].ofb(d.buf, d.len);
+  if (iv.len) {
+    if (iv.len != ciphertab[i].blksz) {
+      die(EXIT_FAILURE, "bad IV length %lu (must be %lu)",
+         (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz);
+    }
+    r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf);
+  }
+
+  dstr_destroy(&d);
+  dstr_destroy(&iv);
+  return (r);
+}
+
+/* --- Counter generators --- */
+
+static grand *gen_counter(unsigned i)
+{
+  grand *r;
+  dstr d = DSTR_INIT;
+  dstr iv = DSTR_INIT;
+
+  static struct option opts[] = {
+    { "key",           OPTF_ARGREQ,    0,      'k' },
+    { "hex",           OPTF_ARGREQ,    0,      'H' },
+    { "iv",            OPTF_ARGREQ,    0,      'i' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("k:H:i:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'k':
+       DRESET(&d);
+       textkey(&d, optarg, ciphertab[i].keysz);
+       break;
+      case 'H':
+       DRESET(&d);
+       hexkey(&d, optarg, ciphertab[i].keysz);
+       break;
+      case 'i': {
+       char *p;
+       unhex(optarg, &p, &iv);
+       if (*p)
+         die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
+      } break;
+      default:
+       return (0);
+    }
+  }
+
+  if (!d.len)
+    randkey(&d, ciphertab[i].keysz);
+  r = ciphertab[i].counter(d.buf, d.len);
+  if (iv.len) {
+    if (iv.len != ciphertab[i].blksz) {
+      die(EXIT_FAILURE, "bad IV length %lu (must be %lu)",
+         (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz);
+    }
+    r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf);
+  }
+
+  dstr_destroy(&d);
+  dstr_destroy(&iv);
+  return (r);
+}
+
+/* --- Mask generators --- */
+
+static grand *gen_mgf(unsigned i)
+{
+  grand *r;
+  dstr d = DSTR_INIT;
+  uint32 c = 0;
+
+  static struct option opts[] = {
+    { "key",           OPTF_ARGREQ,    0,      'k' },
+    { "hex",           OPTF_ARGREQ,    0,      'H' },
+    { "index",         OPTF_ARGREQ,    0,      'i' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("k:H:i:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'k':
+       DRESET(&d);
+       textkey(&d, optarg, hashtab[i].keysz);
+       break;
+      case 'H':
+       DRESET(&d);
+       hexkey(&d, optarg, hashtab[i].keysz);
+       break;
+      case 'i': {
+       char *p;
+       c = strtoul(optarg, &p, 0);
+       if (*p)
+         die(EXIT_FAILURE, "bad index `%s'", optarg);
+      } break;
+      default:
+       return (0);
+    }
+  }
+
+  if (!d.len)
+    randkey(&d, hashtab[i].keysz);
+
+  r = hashtab[i].mgf(d.buf, d.len);
+  if (c)
+    r->ops->misc(r, GRAND_SEEDUINT32, c);
+
+  dstr_destroy(&d);
+  return (r);
+}
+
+/* --- Fibonacci generator --- */
+
+static grand *gen_fib(unsigned i)
+{
+  grand *r;
+  uint32 s = 0;
+  char *p;
+  unsigned set = 0;
+
+  static struct option opts[] = {
+    { "seed",          OPTF_ARGREQ,    0,      's' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("s:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 's':
+       s = strtoul(optarg, &p, 0);
+       if (*p)
+         die(EXIT_FAILURE, "bad integer `%s'", optarg);
+       set = 1;
+       break;
+      default:
+       return (0);
+    }
+  }
+  r = fibrand_create(s);
+  if (!set)
+    r->ops->misc(r, GRAND_SEEDRAND, &rand_global);
+  return (r);
+}
+
+/* --- LC generator --- */
+
+static grand *gen_lc(unsigned i)
+{
+  uint32 s = 0;
+  char *p;
+  unsigned set = 0;
+
+  static struct option opts[] = {
+    { "seed",          OPTF_ARGREQ,    0,      's' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("s:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 's':
+       s = strtoul(optarg, &p, 0);
+       if (*p)
+         die(EXIT_FAILURE, "bad integer `%s'", optarg);
+       set = 1;
+       break;
+      default:
+       return (0);
+    }
+  }
+  if (!set) {
+    do
+      s = rand_global.ops->range(&rand_global, LCRAND_P);
+    while (s == LCRAND_FIXEDPT);
+  }
+  return (lcrand_create(s));
+}
+
+/* --- Basic options parser -- can't generate output --- */
+
+static grand *gen_opts(unsigned i)
+{
+  while (opt() >= 0)
+    ;
+  return (0);
+}
+
+/*----- Generators table --------------------------------------------------*/
+
+gen generators[] = {
+  { "fibonacci",       gen_fib,        0,
+    "[-s SEED]" },
+  { "lc",              gen_lc,         0,
+    "[-s SEED]" },
+#define E(PRE, pre)                                                    \
+  { #pre "-ofb",       gen_ofb,        CIPHER_##PRE,                   \
+    "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
+  CIPHERS
+#undef E
+#define E(PRE, pre)                                                    \
+  { #pre "-counter",   gen_counter,    CIPHER_##PRE,                   \
+    "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
+  CIPHERS
+#undef E
+#define E(PRE, pre)                                                    \
+  { #pre "-mgf",       gen_mgf,        HASH_##PRE,                     \
+    "[-k KEY-PHRASE] [-H HEX-KEY] [-i INDEX]" },
+  HASHES
+#undef E
+  { "rc4",             gen_rc4,        0,
+    "[-k KEY-PHRASE] [-H HEX-KEY]" },
+  { "seal",            gen_seal,       0,
+    "[-k KEY-PHRASE] [-H HEX-KEY] [-n SEQ]" },
+  { "rand",            gen_rand,       0,
+    "[-n] [-k KEY-PHRASE] [-t TEXT-BLOCK] [-H HEX-BLOCK]" },
+  { "bbs",             gen_bbs,        0,
+    "[-gS] [-s SEED] [-M MODULUS] [-b BITS] [-k KEYRING] [-i TAG] [-t TYPE]"
+  },
+  { 0,                 0,              0, 0 },
+};
+
+static gen optsg = { "options", gen_opts, 0,
+                    "This message shouldn't be printed." };
+
+/*----- Random number generation ------------------------------------------*/
+
+static int genfile(const void *buf, size_t sz, void *p)
+{
+  FILE *fp = p;
+  if (fwrite(buf, 1, sz, fp) != sz)
+    die(EXIT_FAILURE, "error writing to file: %s", strerror(errno));
+  return (0);
+}
+
+static int genbuf(const void *buf, size_t sz, void *p)
+{
+  octet **pp = p;
+  memcpy(*pp, buf, sz);
+  *pp += sz;
+  return (0);
+}
+
+typedef struct genmaurer_ctx {
+  size_t n;
+  maurer_ctx *m;
+} genmaurer_ctx;
+
+static int genmaurer(const void *buf, size_t sz, void *p)
+{
+  genmaurer_ctx *g = p;
+  size_t i;
+
+  for (i = 0; i < g->n; i++)
+    maurer_test(&g->m[i], buf, sz);
+  return (0);
+}
+
+static int generate(grand *r, size_t outsz,
+                   int (*func)(const void *buf, size_t sz, void *p),
+                   void *p)
+{
+  static char kmg[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 };
+
+  unsigned percent = 0;
+  size_t kb = 0;
+  time_t last;
+  static char baton[] = "-\\|/";
+  char *bp;
+  int rc;
+  clock_t clk = 0;
+
+  /* --- Spit out random data --- */
+
+  last = time(0);
+  bp = baton;
+  if (flags & f_progress) {
+    char *errbuf = xmalloc(BUFSIZ);
+    setvbuf(stderr, errbuf, _IOLBF, BUFSIZ);
+    if (outsz)
+      fprintf(stderr, "[%*s]   0%%    0\r[/\b", 50, "");
+    else
+      fputs("[ ]    0\r[/\b", stderr);
+    fflush(stderr);
+  }
+
+#ifdef SIGPIPE
+  signal(SIGPIPE, SIG_IGN);
+#endif
+
+  do {
+    octet buf[BUFSIZ];
+    size_t sz = sizeof(buf);
+    clock_t c_start, c_stop;
+
+    /* --- Emit a bufferful (or less) of data --- */
+
+    if (outsz) {
+      if (sz > outsz - kb)
+       sz = outsz - kb;
+    }
+    c_start = clock();
+    r->ops->fill(r, buf, sz);
+    c_stop = clock();
+    clk += c_stop - c_start;
+    if (func && (rc = func(buf, sz, p)) != 0)
+      return (rc);
+    kb += sz;
+
+    /* --- Update the display --- */
+
+    if (flags & f_progress) {
+      time_t t = time(0);
+      unsigned up = 0;
+
+      if (percent > 100)
+       up = 1;
+
+      if (!outsz) {
+       if (difftime(t, last) > 1.0) {
+         up = 1;
+       }
+       if (up)
+         fputs(" ] ", stderr);
+      } else {
+       unsigned pc = kb * 100.0 / outsz;
+       if (pc > percent || percent > 100 || difftime(t, last) > 1.0) {
+         if (percent > 100)
+           percent = 0;
+         percent &= ~1;
+         for (; percent < (pc & ~1); percent += 2)
+           putc('.', stderr);
+         percent = pc;
+         for (; pc < 100; pc += 2)
+           putc(' ', stderr);
+         fprintf(stderr, "] %3i%% ", percent);
+         up = 1;
+       }
+      }
+
+      if (up) {
+       size_t q = kb;
+       char *kk = kmg;
+       while (q > 8192 && kk[1]) {
+         q >>= 10;
+         kk++;
+       }
+       fprintf(stderr, "%4i%c\r[", q, *kk);
+       if (outsz) {
+         unsigned pc;
+         for (pc = 0; pc < (percent & ~1); pc += 2)
+           putc('.', stderr);
+       }
+       last = t;
+      }
+
+      if (percent > 100)
+       percent = 0;
+
+      if (percent < 100) {
+       putc(*bp++, stderr);
+       putc('\b', stderr);
+       if (!*bp)
+         bp = baton;
+      }
+      fflush(stderr);
+    }
+
+    /* --- Terminate the loop --- */
+
+  } while (!outsz || kb < outsz);
+
+  if (flags & f_progress)
+    fputc('\n', stderr);
+  if (flags & f_timer) {
+    fprintf(stderr, "generated %lu bytes ", (unsigned long)outsz);
+    if (!clk)
+      fputs("too quickly to measure\n", stderr);
+    else {
+      char *kk;
+      double sec = (double)clk/CLOCKS_PER_SEC;
+      double bps = (outsz << 3)/sec;
+      for (kk = kmg; bps > 1024 && kk[1]; kk++, bps /= 1024)
+       ;
+      fprintf(stderr, "in %g secs (%g %cb/s)\n", sec, bps, *kk);
+    }
+  }
+  return (0);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int ac, char *av[])
+{
+  gen *g = &optsg;
+  grand *r;
+
+  /* --- Initialize mLib --- */
+
+  ego(av[0]);
+  sub_init();
+
+  /* --- Set up the main Catacomb generator --- */
+
+  rand_noisesrc(RAND_GLOBAL, &noise_source);
+  rand_seed(RAND_GLOBAL, 160);
+
+  /* --- Initialize the options table --- */
+
+  addopts(sopts, opts);
+  argc = ac;
+  argv = av;
+  outfp = stdout;
+
+  /* --- Read the generator out of the first argument --- */
+
+  if (argc > 1 && *argv[1] != '-') {
+    const char *arg = av[1];
+    size_t sz = strlen(arg);
+    gen *gg;
+
+    g = 0;
+    for (gg = generators; gg->name; gg++) {
+      if (strncmp(arg, gg->name, sz) == 0) {
+       if (gg->name[sz] == 0) {
+         g = gg;
+         break;
+       } else if (g)
+         die(EXIT_FAILURE, "ambiguous generator name `%s'", arg);
+       else
+         g = gg;
+      }
+    }
+    if (!g)
+      die(EXIT_FAILURE, "unknown generator name `%s'", arg);
+    argc--;
+    argv++;
+  }
+
+  /* --- Get a generic random number generator --- */
+
+  r = g->seed(g->i);
+  if (!r || optind != ac - 1) {
+    usage(stderr);
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Do the FIPS test --- */
+
+  if (flags & f_fips) {
+    octet buf[FIPSTEST_BUFSZ];
+    unsigned rc;
+    octet *p = buf;
+
+    generate(r, sizeof(buf), genbuf, &p);
+    rc = fipstest(buf);
+    if (rc & FIPSTEST_MONOBIT)
+      moan("failed monobit test");
+    if (rc & FIPSTEST_POKER)
+      moan("failed poker test");
+    if (rc & FIPSTEST_RUNS)
+      moan("failed runs test");
+    if (rc & FIPSTEST_LONGRUNS)
+      moan("failed long runs test");
+    if (!rc && (flags & f_progress))
+      fputs("test passed\n", stderr);
+    return (rc ? EXIT_FAILURE : 0);
+  }
+
+  /* --- Do Maurer's test --- */
+
+  if (flags & f_maurer) {
+    size_t bufsz;
+    unsigned i;
+    unsigned rc = 0;
+    genmaurer_ctx g;
+
+    static struct { double x; const char *sig; } sigtab[] = {
+      { 3.2905, "1e-3" },
+      { 3.0902, "2e-3" },
+      { 2.8070, "5e-3" },
+      { 2.5758, "1e-2" },
+      { 0     , 0      }
+    };
+
+    g.n = maurer_hi - maurer_lo + 1;
+    g.m = xmalloc(g.n * sizeof(maurer_ctx));
+    for (i = 0; i < g.n; i++)
+      maurer_init(&g.m[i], i + maurer_lo);
+    bufsz = (100 * maurer_hi) << maurer_hi;
+
+    generate(r, bufsz, genmaurer, &g);
+
+    for (i = maurer_lo; i <= maurer_hi; i++) {
+      double z = maurer_done(&g.m[i - maurer_lo]);
+      double zz = fabs(z);
+      unsigned j;
+
+      for (j = 0; sigtab[j].sig; j++) {
+       if (zz > sigtab[j].x) {
+         rc = EXIT_FAILURE;
+         moan("failed, bits = %u, sig = %s, Z_u = %g",
+              i, sigtab[j].sig, z);
+         break;
+       }
+      }
+      if (flags & f_progress)
+       fprintf(stderr, "bits = %u, Z_u = %g\n", i, z);
+    }
+
+    xfree(g.m);
+    return (rc);
+  }
+
+  /* --- Discard --- */
+
+  if (flags & f_discard) {
+    generate(r, outsz, 0, 0);
+    return (0);
+  }
+
+  /* --- Write to a file --- */
+
+#ifndef PORTABLE
+  if (!(flags & f_file) && isatty(STDOUT_FILENO))
+    die(EXIT_FAILURE, "writing output to a terminal is a bad idea");
+#endif
+
+  generate(r, outsz, genfile, outfp);
+
+  /* --- Done --- */
+
+  r->ops->destroy(r);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from xpixie
rename to progs/xpixie
diff --git a/pss.c b/pss.c
deleted file mode 100644 (file)
index b4771db..0000000
--- a/pss.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/* -*-c-*-
- *
- * $Id: pss.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Probabistic signature scheme
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-
-#include "gcipher.h"
-#include "ghash.h"
-#include "grand.h"
-#include "rsa.h"
-
-/*----- Magic statics -----------------------------------------------------*/
-
-static const octet z8[8] = { 0 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @pss_encode@ --- *
- *
- * Arguments:  @mp *d@ = where to put the answer
- *             @const void *m@ = pointer to the message hash
- *             @size_t msz@ = the size of the message hash
- *             @octet *b@ = scratch buffer
- *             @size_t sz@ = sizeo of the buffer (large enough)
- *             @unsigned long nbits@ = size in bits of @n@
- *             @void *p@ = pointer to the PSS parameters
- *
- * Returns:    Encoded message representative, or null on error.
- *
- * Use:                Implements the operation @EMSA-PSS-ENCODE@, as defined in
- *             PKCS#1 v. 2.1 (RFC3447).
- */
-
-mp *pss_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
-              unsigned long nbits, void *p)
-{
-  pss *pp = p;
-  octet *s, *r;
-  ghash *h;
-  gcipher *c;
-  unsigned mask;
-  size_t pssz, hsz = pp->ch->hashsz;
-
-  /* --- Check the message length --- */
-
-  nbits--;
-  sz = (nbits + 7)/8;
-  mask = (1 << nbits%8) - 1;
-  if (!mask) mask = 0xff;
-  if (hsz + pp->ssz + 2 > sz)
-    return (0);
-
-  /* --- Generate a random salt --- */
-
-  pssz = sz - pp->ssz - hsz - 2;
-  memset(b, 0, pssz);
-  b[pssz] = 0x01;
-  s = b + pssz + 1;
-  r = s + pp->ssz;
-  GR_FILL(pp->r, s, pp->ssz);
-
-  /* --- Compute the salted hash --- */
-
-  h = GH_INIT(pp->ch);
-  GH_HASH(h, z8, 8);
-  GH_HASH(h, m, msz);
-  GH_HASH(h, s, pp->ssz);
-  GH_DONE(h, r);
-  r[hsz] = 0xbc;
-
-  /* --- Do the masking --- */
-
-  c = GC_INIT(pp->cc, r, hsz);
-  GC_ENCRYPT(c, b, b, pssz + pp->ssz + 1);
-  GC_DESTROY(c);
-  b[0] &= mask;
-  return (mp_loadb(d, b, sz));
-}
-
-/* --- @pss_decode@ --- *
- *
- * Arguments:  @mp *s@ = the message representative
- *             @const void *m@ = the original message
- *             @size_t msz@ = the message size
- *             @octet *b@ = a scratch buffer
- *             @size_t sz@ = size of the buffer (large enough)
- *             @unsigned long nbits@ = number of bits in @n@
- *             @void *p@ = pointer to PKCS1 parameters
- *
- * Returns:    The length of the output string if successful, negative on
- *             failure.
- *
- * Use:                Implements the operation @EMSA_PSS_VERIFY@, as defined in
- *             PCSK#1 v. 2.1 (RFC3447).
- */
-
-int pss_decode(mp *mi, const void *m, size_t msz, octet *b, size_t sz,
-              unsigned long nbits, void *p)
-{
-  pss *pp = p;
-  octet *s, *r;
-  ghash *h;
-  gcipher *c;
-  unsigned mask;
-  size_t pssz, hsz = pp->ch->hashsz, i;
-  int rc;
-
-  /* --- Check the message length --- */
-
-  nbits--;
-  sz = (nbits + 7)/8;
-  if (mp_octets(mi) > sz)
-    return (-1);
-  mask = (1 << nbits%8) - 1;
-  if (!mask) mask = 0xff;
-  if (hsz + pp->ssz + 2 > sz)
-    return (-1);
-  mp_storeb(mi, b, sz);
-
-  /* --- Split up the buffer --- */
-
-  pssz = sz - hsz - pp->ssz - 2;
-  s = b + pssz + 1;
-  r = s + pp->ssz;
-  if (r[hsz] != 0xbc)
-    return (-1);
-
-  /* --- Decode the seed --- */
-
-  if (b[0] & ~mask)
-    return (-1);
-  c = GC_INIT(pp->cc, r, hsz);
-  GC_DECRYPT(c, b, b, pssz + pp->ssz + 1);
-  GC_DESTROY(c);
-  b[0] &= mask;
-  for (i = 0; i < pssz; i++)
-    if (b[i]) return (-1);
-  if (b[pssz] != 0x01)
-    return (-1);
-
-  /* --- Hash the message --- */
-
-  h = GH_INIT(pp->ch);
-  GH_HASH(h, z8, 8);
-  GH_HASH(h, m, msz);
-  GH_HASH(h, s, pp->ssz);
-  s = GH_DONE(h, 0);
-  rc = !memcmp(s, r, hsz);
-  GH_DESTROY(h);
-  if (!rc) return (-1);
-
-  /* --- Done --- */
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/ptab.h b/ptab.h
deleted file mode 100644 (file)
index 1e9af6e..0000000
--- a/ptab.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*-c-*-
- *
- * $Id: ptab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Table of standard prime groups
- *
- * (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.
- */
-
-#ifndef CATACOMB_PTAB_H
-#define CATACOMB_PTAB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct pdata {
-  mp p;                                        /* The modulus */
-  mp q;                                        /* The group order */
-  mp g;                                        /* The generator */
-} pdata;
-
-typedef struct pentry {
-  const char *name;
-  pdata *data;
-} pentry;
-
-/*----- Global variables --------------------------------------------------*/
-
-extern const pentry ptab[];
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/ptab.in b/ptab.in
deleted file mode 100644 (file)
index 24151f9..0000000
--- a/ptab.in
+++ /dev/null
@@ -1,219 +0,0 @@
-# $Id$
-#
-# Standard prime groups
-
-#----- Groups from Oakley (RFC2412) -----------------------------------------
-
-group oakley768
-  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff
-  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff
-  g 2
-
-group oakley1024
-  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff
-  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f67329c0ffffffffffffffff
-  g 2
-
-group oakley1536
-  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff
-  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba36046511b993ffffffffffffffff
-  g 2
-
-#----- Groups from RFC3526 --------------------------------------------------
-
-group oakley2048
-  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff
-  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba36046511b993ffffffffffffffff
-  g 2
-
-group oakley3072
-  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff
-  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549d69657fffffffffffffff
-  g 2
-
-group oakley4096
-  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff
-  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0318ccffffffffffffffff
-  g 2
-
-group oakley6144
-  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff
-  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f617794b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36e620127fffffffffffffff
-  g 2
-
-group oakley8192
-  p 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff
-  q 0x7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538abae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f617794b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36df08acba51c937897f72f21c3bbe5b54996fc66c5f626839dc98dd1de4195b46cee9803a0fd3dfc57e23f692bb7b49b5d212331d55b1ce2d727ab41a11da3a15f8e4bc11c78b65f1ceb296f1fedc5f7e42456c911117025201be0389f5abd40d11f8639a39fe3236751835a5e5e44317c1c2eefd4ea5bfd16043f43cb41981f6adee9d03159e7ad9d13c53369509fc1fa27c16ef9887703a55b51b22cbf44cd012aee0b2798e628423428efcd5a40caef6bf50d8ea885ebf73a6b9fd79b5e18f67d1341ac8237a75c3cfc92004a1c5a40e366bc44d00176af71c15e48c86d37e013723caac7223ab3bf4d54f1828713b2b4a6fe40fab74405cb738b064c06ecc76e9efffffffffffffffff
-  g 2
-
-#----- Lim-Lee groups generated by hand -------------------------------------
-#
-# I generated these using utils/genpgroups.  It took a rather long time.
-
-# --- catacomb-ll-128-512 ---
-#
-# keyid = 3db35e07
-# seed = PbNeB774QFw0xJvLDEn3bUx6hJw=
-# fingerprint = fb47344e-9bfcd0e-e986c772-48edc231-861cb5fb
-
-group catacomb-ll-128-512
-  p 9749248307666198278625282069621029423614285873414870747628872221551255623823205551438908261067675576856742534707535779666498916029617598868013496631088223
-  q 271499434142083095503643289076442321059
-  g 572938290446952786361356734705597783874760982871814854106633812061613480394314443743197177265739535298268868306029572450131746639710824513310586144336987
-#:factor 271499434142083095503643289076442321059
-#:factor 251174382438405784142034780246853570853
-#:factor 259658226261043076610234546745792177763
-#:factor 275292752516630714214627215608643381611
-
-# --- catacomb-ll-160-1024 ---
-#
-# keyid = 98f62cc8
-# seed = mPYsyKXF6PoNTkl5uZE64gKEf20=
-# fingerprint = 6ab1f087-5614561c-5d388443-b1f02eac-38248fe6
-
-group catacomb-ll-160-1024
-  p 69775951038073580217048751187698556149910661999359201823421066000439190288124938297116840422332973903349265313226189724474672148172906743149961449018143681316055777549225333684417216672046201528908637006946721694566251047975893301628540057123962444434130461052652526277961662241061299058137499738575071867183
-  q 741802303617786660769426556982216255271020758647
-  g 24031880137812767104513348688448999056754549625670167617628008814539123937598464069755252337842705625768270002772600104095116713027947418314704258588569425678035630653993833866258334547988915311887541947589468379164053328339235797437698686107421712042993209960764868024283667188725341401853595169622553906137
-#:factor 741802303617786660769426556982216255271020758647
-#:factor 1436145082693042410533997633791272917636904431479
-#:factor 1053371763883815722032496338163704236230178616951
-#:factor 1215995718665420681503927009463070333378310191827
-#:factor 1448192360714741582009673893725822727433041298541
-#:factor 17654251325616983743094122151298023764308424678047987263690296014551
-
-# --- catacomb-ll-192-1536 ---
-#
-# keyid = 7efe5c2c
-# seed = fv5cLMXgGO2voYGTQ5K525Xtf9E=
-# fingerprint = ae9d47b9-e303daa5-9677023d-764b338b-53f03c4e
-
-group catacomb-ll-192-1536
-  p 271163844483056215974969265313967454661676256266511940924304321373021958106999031565631233996938091358447023677706317722695337026864685384345663120704730255257202847527192911265950638087504732115876440997750045081880863038141607482083211725689822517898206821836185159703555104632867971994304356879518337226475272092974597967943366038800089283400183985773753490774687966167193456249452974119129018696293050595073100284829925638444204379135326678813960293114732959
-  q 3265942811645946563242629602041107481841853511350443184197
-  g 216185318413290469366405581500018842001794769819261149347277739848511992115259660705539911431188902360038442052949313200461450240469139278699145891151900315976816130082310914969548643710915174155521909660265659882527478738966654443422798664706090262812802264667406360583964285545011889176706871228354070760597031811706100156760441692822039947686308668974200473374152063439445019790248156400822413220452383963514887723177708643429977392740800552485785350546387634
-#:factor 3265942811645946563242629602041107481841853511350443184197
-#:factor 4203281750074745560664516895168522022509720946720609480259
-#:factor 5008750505930402098755083797499946811957880698185704286517
-#:factor 5437815993255342021982036827752826453901545498474314278259
-#:factor 3856915640937851719940744630159301063173277801391043813291
-#:factor 6054082443893470116716978196535076127652382149483455623509
-#:factor 4527580176039500642864307604310793340910014541817043735439
-#:factor 3430016280837410693307976287901159907499384818919106315351
-
-# --- catacomb-ll-224-2048 ---
-#
-# keyid = e2824699
-# seed = 4oJGmZFnxNgns4UExrPWJXJDQYY=
-# fingerprint = 5b3631f1-f388bca-554c1df1-3774fee9-cd46747c
-
-group catacomb-ll-224-2048
-  p 3113844893182469436423817481922802329154474934213986369565700235348098440269001480103560846535113493144522446351379349356211385191632945710341444495577638160076546999114567117877732507854868463110804063964212132228977417231690350182211790515961798314443291574015832300281633156990779527484905381392680532643288437519954295652416759988107781937077836044809781096660654460207183523575424301901443740349094152501352983589721328225459512044516684078781305909247963063040562914192132284695886353707336911126238203292592145886841905764429235683487108646920559740458905874135798982283901137307047131586817745416509850061963
-  q 18749474022970964965792505501868745784157349746475161167020805104727
-  g 1018599075350815414286530684646967825916370747779291600517646276513566802791874935821816063520500873842729343817973803895278528701892043836290994612088035311589900475691176610297248816678701309707300454643927577686742011376684351525767933769045470869869290385506108485669189456183746644562327923152628958690988304340204333382573235567919004822811151873260798098816157572583867825397056414990908538555039226503662448878536483457742053639607062687899859473980884756925814541061907505350254827583321961201313954703462583072253230646667723110441238195386606218014837851495231172030604130800244334912972408067680590879980
-#:factor 18749474022970964965792505501868745784157349746475161167020805104727
-#:factor 26459793266106143518700371316953986751950547842631163615799385478033
-#:factor 23385205652191135191327958583020476187937251160152256504448581299573
-#:factor 17287418736358368314036906794523064561326146990020019216549187737103
-#:factor 16800288948485454351848726052252844830400274721321174607061304165751
-#:factor 14817124042645057452868896146782513905071983176482538876644503596827
-#:factor 24089412810223523640445605527780074479098235298741910558499656689361
-#:factor 18919386933765812741111621380736732547216460099506859126765656541087
-#:factor 68423637472150676252123752731403397187923476268634988015857219241126016100451
-
-# --- catacomb-ll-256-3072 ---
-#
-# keyid = e6a15ce1
-# seed = 5qFc4fL01gTjyvNMZH5BvwETZco=
-# fingerprint = 904df4e7-74941baa-40d589c8-fecad932-2b3b7c8d
-
-group catacomb-ll-256-3072
-  p 635937223373484887991140560420669529960468634418212194527199243018802509220923645480563049852948379631872315326364181219863391536284352632127476573990043945919830000350264391397346335414535975554209931971547284463207275833747975949070870172306582775948778222246682185331862354083029804303222690541851195763223409045953191584611635790362191424339883737168342809190665629632289528654983812904611647818546832860081714363504512892885600580448186423533085059295328609139522690627823102925150246378111221377628009667319528150747320084312110336288028683700603719073769314245952464113622780032073817850603131463761017417455806035107984621889773217138911836476354442521466189648565925624512100087534918369360007697883847802211797655614684090408428715299537509886614640500137409891381649298835563011151796284848165977247286439820050405175697064122759870661294968492275655767983096727976056361878300352234381528837008128941375285251387
-  q 89271282791461757245617785540129155142212959423277129581512553253419075634703
-  g 293025651734044707050351995205142657657141955131408425452312245943331353163428637443799381119408990271553007202915223601376791534187122912295000993316207089139736477148501917083144416322685925261624358336253378688806309805096283386698409139605996997308008266491782991490291726095895573563845937760385377670846794792328581579165150512160132493375389995617711312966986681865792948443127326586291576561351005982500369077653940283008076332825908419690031303502192009860824429031526378047535596212801179578879818504990773143072529887215206211778546705082334239130823956177702608427222251531070457604183947814624087379251368161182770323100074409926426428526795865215674068539423364010352920515052672366811052717283396264950182005583498061313136436293898863077084485762289185337928869086731032780517039420605615746259170222257438835029958473402842467194409561307509136616954789698181252705567549441508247668319257495617674881793988
-#:factor 89271282791461757245617785540129155142212959423277129581512553253419075634703
-#:factor 85831054040144766435760746678768685031101307134949905606966042252247846736739
-#:factor 106974241938861083915762659525277908624697359844432666343676471334975764276049
-#:factor 74188558205228235051388929541366735789893711666871143431413381703129034070571
-#:factor 64157908398727096384500697645883202842334928055247546726538359334678953374533
-#:factor 91888021786522811643506031866522514605588426773858897142365239694153824388723
-#:factor 86202112980065410413258705060295663522206392211838714986438313175672540034679
-#:factor 101718718485667336124248700072690338405530751717394437871691123315096947983183
-#:factor 86666452227843804499517643692692014159268339780015078349842908985056208435853
-#:factor 107755126504421076829573915729759110231793946298489260169446357640494497518059
-#:factor 106001951238340530179427922980522671485637210826387486585015951056665476348869
-#:factor 102183593360154313236939029184315018977616435836107396944951781361526011480879
-
-# --- catacomb-ll-384-7680 ---
-#
-# keyid = 5269085d
-# seed = UmkIXe0NUh9EHPOO8u8wF8mhLQE=
-# fingerprint = 79071929-98fc59d-90b7743e-c5c2b654-9bb79c2f
-
-group catacomb-ll-384-7680
-  p 216559231449171871041190135626382624797124950735238103903411263023444445882521628396323446917201544947387362748232352479621010825720892522010264595137021526116731147020276163999389935515909942333859243831227670403913428432731504427389273023004939424753052775358161721558889434984752937404659922107755872908503276779890720154023419646466364753857461405783464469564625360217138090672724105361675896756808274354930058114085554600822147968649870032508764648998263671769796991884663568970203225077040350146289614179408735323764473153776149414398483161820946251418283039309221276673125231280207218356527486085198155052448482264858753938528034551335541575510835605019724293894867922725429018142837363943168309374088743910487619039647758175469460668571266467909654776838430687432194443218576000354284573578578313918222270250431668826898042163427173702446261012188950489694384130788197898956349943432660613123480611964086340909829616693038723512697569973817087806925553170590595578662024721424212829104524679861074838515062614572669868082762235959143570965134389478420007029121452023331460602894158087970348076496609174310151629106271427215947168306439928345126945165118709319486831988505313790613950433545275492703644799196726129007271379101141097250063655345163597099147393517021524375283410477077887674889864364373504345856902602031627659096612965600880097793678105801528551273968273016116586602655943987294387646704481664853571904789295943497201543689680443816576374462034616478062083674538453821741357423160686683957869164976227205380757021506255070600142017516211729170052461889059117212201165174680435195480761191462787291840078314124775690821420091760461597315155088442641783854597704388729214697745034805817520117506496545607796864049406793174516710815917428415700817370248228453077064519820749224220930454265603643316849024708084260878037824529368824330161019279087245044637182254878850971615729695143996520927935652887799292993748602455597137301552603377186175439256163850872771856775561289081476860168359000521640192117573827877302113899996287468260783657370603418752653187994927154468272901154316379212588059218864942163650290968975838491996852452140839172227541162524444316754170785930872965059072588210184084993896704348797801907146398460530513820150529386362374102968643080903455218783795163739396580563
-  q 33126499307317576797871833023217004335728314922050873541842362900543256622519036793987373377351818708943025119171013
-  g 96859294361547047642162231787698695293269170366381491039992704638487946870512955047635144422727688206850890592577601738386271033615655069759857614095318767501569475658225621379418176050399654722867097565799361229947796756782330159878485797280010527792372818398073347477883450716624241650342576251700830368197267161507895940250335059430229713885285808307538641824823453590259949699610056770268667527819173674245700546468626735701216914339359142650715456068873883323510582206093162545301581421872580614739960541059105320799303366751068487975658774037067271201124075671594347915071804828018801863090776942278748696864666275555399479604564578677796647983816263014540144519577131864786690922226752900095101570448042330169808811588582992274222974333043374060077106932770817928804830739464113061207244668378493315384242428432594357567083170258903374723309088233501818385465347016865045003737737429798873421728939731524368763227995005635265743181878570394577251864081145075962862658667595276249717296728684048617249986325764929873684993115348889870151843083280953797610712542442651569528403369291638278579344023829005801861314384307223035852089456550106858884145475380292972702972023699980804060437666725813022897101316874650121913713231347979141680903702045096621935190730276560295174524297300767314797689155407477601193107232938299830541221417725759368288595613473097104008577963940594171976537149511040148774289702490489315160512871522386217608881824304091006999472822494018964857391111674528315676869116824677355671824612095554583261258648450847127015033139359148253652027620146044628375304786435643476708542206375787159378427699020092463186472971399347599749181816424274424067915825882710114752513444732397713670497772986582958901510359579133132479016445445133604454907255125008080844594331635493230874836372234145675198053154029087315214747182882002718722228763467363382722967777319004806095376893995711476881150741027724250087088999020456989167082293444606242846362570237792721708356293491203816603574491100293039203889820292140596922368098350519693304511861932465759110608906269402554390780611082681465359527185555358515709411662470414648813606479086286524570875988991968332315775966514438221552899748093614170849525785168229994381907745855683962639488177828929551456219770877454135407893035439949325975780350
-#:factor 33126499307317576797871833023217004335728314922050873541842362900543256622519036793987373377351818708943025119171013
-#:factor 39355538213779465581327905402419970362362827155309917911796788256581129259700838386618633466328785307910060598484089
-#:factor 24990988056514685939227489925894893740599480412356885556635114159485308445876939770393364881549529860169928180358751
-#:factor 29710393998736802825004025579677917729092552502321819764111039726208854433428942095508492913578932136133436765710137
-#:factor 30739990822741028562742164007270587796692423847729505877569973917995737943042778723217469119645159801429991709987411
-#:factor 38467104071408925475553899301420008676544897864238119086844380566779548268491996551153519861871328607592273248640063
-#:factor 26249202441547885968346939762119297860863007366370739789532392353072352597721946778221716140197625626869457398407943
-#:factor 35113510884533077462576668870689443131037411172656549819745724383911555364605887073198680214468558440325573744139273
-#:factor 22799521027155572453510717469170377645186972219918245680012037643676230864376926993221681405925996643835629140041553
-#:factor 35237903572957790995889936270089932531166269466107290813994448142778414605138387309936585467385466822473088271031989
-#:factor 27428052831286394078655137717030752972732374814011687175621160166365055343004612251793080304507732432129056200291727
-#:factor 20653805003557030567582482355924457431196786739428479408853799555350943953733271029133593962324338862058432369521581
-#:factor 20826184829221859923080357759745090302065026449606341016497732724141145977802307612276509411486570418197846062995143
-#:factor 26186565771074398017481590713676896769947111595943534554546789381717976098676902111563130714755073678247235508588839
-#:factor 25062273677906610062620640227124848504281876654137470308684277968100792708156285085199790540571827305085913619650939
-#:factor 28620246516918127020366359691491908359742867622666550018522929993024502416569436771205673472786682579926850748107811
-#:factor 37856943506407240881326721106883344091018942980536189030625919515240362253893275735656123073145875668656864714642553
-#:factor 22067087486134964177557541373312161142485654981859077450341811542291069526079170766664489890765256439946132722899891
-#:factor 23098926790257626751285008739153477597734517594763012574497649607286859624287080618144594023194033634778511868647877
-#:factor 29874082012645596638985309976826212131328113612069017684649166404247820505933961130580996098120522635385267888074961
-
-# --- catacomb-ll-512-15360 ---
-#
-# keyid = eb8239f8
-# seed = 64I5+NMQg5J7WZeXPpo7dsXLiAs=
-# fingerprint = c9addb82-dd632399-3dc1de81-40bf1c07-8ca10f5f
-
-group catacomb-ll-512-15360
-  p 267737496760767722068079882470300794033605836807622482067410964171393411520919176256914869964612479175351332823409449521645606004586415623871847948375817498161847543702485018137658512658395575254789459353699345744602369381934625059696198589413369531883820496222659510755499199435844896264025524352060302680951373940575374076136832975200291005032514098640691398905405952695332479714616633295008654736506041813997134163987333741695846413097366684661344684616003601739167823328153896592432168889551779922529269033348086812310042261625165919052730860791202842844956446296689792441147970214424901342118997798159010536443797638756041327664696059380444566468860999953138675880647585649322318597258428498912095373426547986582540102395757192981849426353427220562438871461011279156327503538285028350335365137967747204548916792891345433172565689300894798309981237564346356082832141951952353587270953547648554401212070076679138112680602893278933373210074307452631417834131238872904464712762382727721405307974548332455937227001307804713345124421010621912271858653169426612004330651882144263970965845286327430353225544353979151213153918381850147302137013870443565447267408929820734324527586605299075224612369180273167439366180804630758969753426630886643792237194705165542753979443278245006454216061793688914453452033873682552924255069369382991399006219888447629091144761962816311838278453426744318329244891747907726689490072483441687762777514940810025483492250932938902924371182177616985098416863622505393245791898509271049937545780547703178646787153221220148776603371623990916784487761937997154509142207118563842540149656720890488789518041789234252783231203642923485126118874925205605743388337049290048102619379144553450612454492744292824661671019548713713568495220254740410669480812494122553523238166010275744321977341774600646768663036548131650974040647199495585196626323527740836162430085342052052727637724463434046775500298250476314587684591403987781101547180153540252142742428325763088665202774890061858211471865412555929191623058633649510807447665649697908545538433271811034260583364231115893882106660460362988412359863944207083315791203817813275002751650497247445133621959259165882426036642183903263726738720790482023621515505915532731458799675555130983697925269194130788271555917528320139537585237789448433361057472038619150612530155365282694361060208517945072413778375766282508764808188838406430261098030072276397680381934641479775177012533402001805227189560517281847643477431969193260714721511089510106902236389858739200666246366584470443084819740458839115330024642751710950508392249199171525940200641812690856715538273687610654143705053231753228288281925749573248819830807718047751291456635357252049651851428004843642993442708365926756086784864901619631645046021861362898457472437142021009316121209673296032419273205690055243737394068612057117222448137828274568145532165778912543711623225896980785464025683101674037519994362712933363700839222229325067956938417486554365785132752607665421070796369679950679278370647133471481601224482043380412158088958751348091674065435762606782309017939064656880665108380755999804750464216396676060064634049102602879726529064753147592949810279608808566906092860843406668537037778792512924649747927350781700804454803517161392276648064085521072720776995493746790698252658256127300427299712765912635964190588872362794322452414626926829451697570056145597909237733397993006318713907266282999209757835954408527578538863449022305050578740139814278853085620493082736691092281414370903171187358162080568284465302364244005694005210033241390491480461570699307912480038911233821105644446152512328525805707483171601688919032664561976430006629718308661207667153016502452884195148963125673969191706827403727809879672157011607257925720399770233625156155404482591336975116607711326594730647784392952199755924399936290034962258677008541859799419880022170446493041811273344503041707889648677394173861246482375736320283850849220544488123549088485079584855817373424359266678858651199243166073560382077730099987468377705636637242565948949985751205620857554830109239961545967537041510571588045286127240744618124771659845616409968497542978672000492769104999131872897737410994487787465125717465733543538344980281077012185860886320520255782307357238375948751409954873680258342250057671086544607706855079362474966284884466968233383764211808745671425930931575698296989086335739534025778159969392356967742191929914522690322438276604838230279525053780117636662663017876019549874233270026169569062088907790243918806941605480559016625665402398248013040463246716327424411605332836931485156524858341673845209004633198457099
-  q 10571951456907669779892620647342646690819262609396359690524502534177633120229168340667942575812279188027386527234551758107216468763903236115143427787743501
-  g 128598894907195188417229808251635947329739807715046258519185506584473330204570377688022234101083503575628247088869022751684161661116289139941422707052770784716284088672813457818076409289020116060576402861848262767893027233018967673188177319672220467630868456703363498829958429433052255385200803148036151824908127072135772477213206484282052574102804738136991255543544214210006836913841655431369354618035834267490750490209475650037611036969604510775085809840648347935149597993597050657382149424122551607765060905481452516927446598515527477247171478999535528834297030357374539135945862618225434749983777290822601640168801388457093291990583760394365529485898194260738109655976435021259260994433703250576566622543068851481307975157566559105117105696734982421364733215553702481282493676675415951561410801018648748202526310066348347675957920894052908634114299749835690825285958913309859395516637946391466247723186108045362984213928977339986546180336619120165000686737182828914686039307870836014970214762767616169050313307016785283407848979763838796901889533929991249262241241357085858440003100578599589303213283823231174826022087580289633445725655404503623057795603361275581688344479184031083934546255260431689248986625244613768138643274300512818504921212079442823382330541009102805040432664579664706843475903526712081265964789883073385412340566450530204050902742402634241295067292054198743776821135490852456571373786221834566840691504860631528594003016940806795952907191256706618335919348660172917691296581810487025804834121410117485699086165420315964836248122689453219355409068053887775439819365185836341867035959423656535221657069676936301160422526984733243805036094607065902991385803575050051402498313584896099087939918378394590246964040554542516556529955127714323667109459918696040305338316628605973670322139489914621903381403168134305230387553206034949296665589019458435333656497975595505186840554679289490725712215379119708936656398805481443817609780446044759428279250269061044353577054755809478942400511447476504959503019924384501854940670343756700595741830432409860516378561836547983052719529231317929703619794317736666240984610506873930809661048521360303804091987776920298335472932445807825891843426486417538296088228895526448505937443508396033850769937257926518277775854316505029339507246170910597358345642816471561799639718384521695469006324992746905242127842686811730217295508863843618253667094515294426385046337302700840651870607339402514793220932482394311605909804968180513732290422195401488734272875219573971965851758260974945420620612963750578280530090049561109078297429042230921153112538935821627493853510065306244811588574295137834903557863723543417221594934011392570967713979066781470665113263579679078346927299350593423807794432345965954214411279192997560913500420482135209761870894770590428753377060355446520714577823849327411455211803153798853005451969647921330963739815383804967938950844708859220970746343764387380686978388124365668599015606571832777646186264005031394838487124138566127931419400765659300590631175744824203747372760896426041038824093171455170878742081716134501047540584551546098074082811645710233649110893608312835114875022232159365133137870471783950558791394747886849817239478618258433146217414467845273035067690658728958244690182678308246002614307639728716544214919926387449699076757255860035522872191741413862595318802625699582434142963070125555096411118677017567085204173949296857347553686296332447084040218420742023614270285859547357310153777066869597179554114216347704995773693933927290606278271631839500986041846119745101489053876898923820486679517034985529967206488771012442386273647914758788794352696546007225147463040960836917540476556158171204978341050270842436674153236983839541594662370682859252061101201529771658391958638069866925173982823135401442054529882771497178435812973944610940759337374490667655762675502138898683030596178493879840530527200986100162672072577140966652435656059897085134772326082774218777784721364471952331014224241827859689552691557210912017591834455185827870287610792949837996937421382409243563221525985357912277040622211893182331275112628740300448802121194783069108322399073099060064264166221152635853834406853391568903009131371873111346754163371271208724745835028574196362705248110621990890004232459546556494832519339269358637289654972986665902221815201810894863582325166306449650465453223955176919686048223394344108072515484536428726902347665256053780647893633252440024422896973060032376625419596170725316577542832012274755089837231069989343909974684844834831911679673118788567527167638795212119760473587068197787346864147296908951760670987133395
-#:factor 10571951456907669779892620647342646690819262609396359690524502534177633120229168340667942575812279188027386527234551758107216468763903236115143427787743501
-#:factor 9012440645643314246834973626922261248430582884321541587438489180023988737512032104254581442848613136311423618140795155753411152808972231131191495364696113
-#:factor 11664407479888990184202139277551028676651013424643181979060212470678705307128063234525963058666093887020686441365922823734852909082402446828730382752979229
-#:factor 9087876611156307298284101521955646383324933273215705601366986444355710006473522774817841755272381080750837076062838195845188516807677339637355892566997161
-#:factor 7850875653648084112022472229380028253695299668265516016947697170686003077850514907765524197019907612330445487029463301633628025237963893050671557196181037
-#:factor 9811668747595937862696556986818901047696541620978343479470960055182987731849807766456487932153408355304918692734270804755894967739728440775732045253975867
-#:factor 6850528828310882434413759447618080765577150578105428774266564959349750426580886713871673166366380181300391220234049862529092166014652885149727426581950889
-#:factor 6821638102376526854453397172384749542254164092866952888824098621712040405559147454526516007481215285840029382069182522430838260284493396455708010177523951
-#:factor 9678671090017306504471193471606002503207329774194080688795341865275315066168913972420992866933767238945244749299859823721414058505077146271463652017042439
-#:factor 11393931156044806890317196442201195583808258792085050704419049073069764825659064050709401048990965128349659629815212528487569661791997378607235211682046767
-#:factor 9017010040179947675396805634091838536572796142622751259821087175550548949037522734269840576513891007984351108919567391192649737362028379518075599077332061
-#:factor 8471151817163912127252174076707115691748601873337141861143247343372659043906393812132481208054508793108003038614600545971718635646265794386795278691754067
-#:factor 13197493938382376428309109637837242582358905975783852842417135134626200360303237020546312789639222633029539785097700295596040150049781404432593082545583687
-#:factor 8575974070132361564362415034026161716899096825228901868850832979622821929082521380113628505749265007300639809003377137159593961387754096563405572654530453
-#:factor 10685309091824418682668636366538457951831463604934567645475353414106697701363236027779367582469465499678424648685247868794321185827903765405464064983847047
-#:factor 7832579167103862778682606390694147440819353518240318233355101493037014682039100415001767021498559727856779744520541030712369584582339760294936511514528613
-#:factor 11443136038500921044854720404653372565248054144656073888671297768218410197327711069816877279851418893039887799451033119855767890079711768713385653679344477
-#:factor 11688409215583921110956357044321797822832780718093563289058981511879157867538826225803418406379935887495839460956831051786990678735417867002006878510530001
-#:factor 8269373232168928931276034385529570570419130675409379232099124396037402056853784630410470739109999093193671624909979089535332341276117302614326085797220209
-#:factor 9186395703395988275207810642702730047142932136743815395858445937000755684133671310159954341948067614705752787518132853542049279332346920436340054839993081
-#:factor 6795425485592182949378541037739159131046423659599522629955532628051588695375698396588579193598504741404656736703919260744390720003440892800061391975968543
-#:factor 10396118888753141861444655191592919753341123585411878553552147287212817173935858961195926696707128865851883589958560492545922923504442555855283863684690883
-#:factor 9200414943820306382018413241324240995480578531923453792659897506893121059804164387167396258851931504929883516095987516319887977740512884087194394964391023
-#:factor 12530634260640146540037552613265173527563597551474945252217132553909981324169848692185513076985582524700624840690045385961239986165286808674599194021249909
-#:factor 11777196311833624813129143516165715650218942159782423895657055945748378658698548936802659687190537166673298770529607439929019151210938035218664232208577273
-#:factor 7348262210091125168844276092746402631926760996426639974638799774896265368458530624040379440531440039323922186709965290812433008147988187233036235954446539
-#:factor 7495895476596043082228459599736776072884975040533651752897223545444099013720437774241963953093854938504409948988231217421899198126781802901186687835439671
-#:factor 7552446094981741253426497231778914956993354256770700433779133501020398264257537810327407638749096379083785811976115762275583243733103646262540268854635459
-#:factor 11876032185719044257059947481606348236079583968867505900797840767914468036111126560459281957584518925180041310466390015937147792402479266081314053413722009
-#:factor 9583540052593144013269177059658457027998433819569867982260511279574493019496581755069425156501941108339618548765191994601041609651011729970172839875903479
-
-#----- That's all, folks ----------------------------------------------------
diff --git a/pub/Makefile.am b/pub/Makefile.am
new file mode 100644 (file)
index 0000000..d919edf
--- /dev/null
@@ -0,0 +1,101 @@
+### -*-makefile-*-
+###
+### Build script for public-key cryptography
+###
+### (c) 2013 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.
+
+include $(top_srcdir)/vars.am
+
+noinst_LTLIBRARIES      = libpub.la
+libpub_la_SOURCES       =
+
+TEST_LIBS               = libpub.la
+
+###--------------------------------------------------------------------------
+### Component files.
+
+## The Blum--Blum--Shub random-bit generator.
+pkginclude_HEADERS     += bbs.h
+libpub_la_SOURCES      += bbs-fetch.c
+libpub_la_SOURCES      += bbs-gen.c
+libpub_la_SOURCES      += bbs-jump.c
+TESTS                  += bbs-jump.$t
+libpub_la_SOURCES      += bbs-rand.c
+TESTS                  += bbs-rand.$t
+EXTRA_DIST             += t/bbs
+
+## Plain Diffie--Hellman, in Schorr groups.
+pkginclude_HEADERS     += dh.h
+libpub_la_SOURCES      += dh-check.c
+libpub_la_SOURCES      += dh-fetch.c
+libpub_la_SOURCES      += dh-gen.c
+libpub_la_SOURCES      += dh-kcdsa.c
+libpub_la_SOURCES      += dh-limlee.c
+libpub_la_SOURCES      += dh-param.c
+TESTS                  += dh-param.$t
+
+## The National Security Agency's Digital Signature Algorithm.
+pkginclude_HEADERS     += dsa.h
+libpub_la_SOURCES      += dsa-gen.c
+TESTS                  += dsa-gen.$t
+libpub_la_SOURCES      += dsa-misc.c
+libpub_la_SOURCES      += dsa-sign.c
+TESTS                  += dsa-sign.$t
+libpub_la_SOURCES      += dsa-verify.c
+TESTS                  += dsa-verify.$t
+libpub_la_SOURCES      += dsa-check.c
+EXTRA_DIST             += t/dsa
+
+## Generalization of DSA to arbitrary cyclic groups.
+pkginclude_HEADERS     += gdsa.h
+libpub_la_SOURCES      += gdsa.c
+TESTS                  += gdsa.$t
+EXTRA_DIST             += t/gdsa
+
+## KISA `KCDSA', generalized to arbitrary cyclic groups.
+pkginclude_HEADERS     += gkcdsa.h
+libpub_la_SOURCES      += gkcdsa.c
+TESTS                  += gkcdsa.$t
+EXTRA_DIST             += t/gkcdsa
+
+## General key validity checking machinery.
+pkginclude_HEADERS     += keycheck.h
+libpub_la_SOURCES      += keycheck.c
+libpub_la_SOURCES      += keycheck-mp.c
+libpub_la_SOURCES      += keycheck-report.c
+
+## The Rivest--Shamir--Adleman trapdoor one-way function.
+pkginclude_HEADERS     += rsa.h
+libpub_la_SOURCES      += rsa-fetch.c
+libpub_la_SOURCES      += rsa-gen.c
+libpub_la_SOURCES      += rsa-priv.c
+libpub_la_SOURCES      += rsa-pub.c
+libpub_la_SOURCES      += rsa-recover.c
+libpub_la_SOURCES      += oaep.c
+libpub_la_SOURCES      += pkcs1.c
+libpub_la_SOURCES      += pss.c
+EXTRA_DIST             += rsa-test.c
+TESTS                  += rsa-test.$t
+EXTRA_DIST             += t/rsa
+
+###----- That's all, folks --------------------------------------------------
diff --git a/pub/bbs-fetch.c b/pub/bbs-fetch.c
new file mode 100644 (file)
index 0000000..939aecb
--- /dev/null
@@ -0,0 +1,73 @@
+/* -*-c-*-
+ *
+ * Key fetching for BBS public and private keys
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "bbs.h"
+#include "key.h"
+
+/*----- Key fetching ------------------------------------------------------*/
+
+const key_fetchdef bbs_pubfetch[] = {
+  { "n",       offsetof(bbs_pub, n),           KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+static const key_fetchdef priv[] = {
+  { "p",       offsetof(bbs_priv, p),          KENC_MP,        0 },
+  { "q",       offsetof(bbs_priv, q),          KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+const key_fetchdef bbs_privfetch[] = {
+  { "n",       offsetof(bbs_priv, n),          KENC_MP,        0 },
+  { "private", 0,                              KENC_STRUCT,    priv },
+  { 0,         0,                              0,              0 }
+};
+
+/* --- @bbs_pubfree@, @bbs_privfree@ --- *
+ *
+ * Arguments:  @bbs_pub *bp@, @bbs_priv *bp@ = pointer to key block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an RSA key block.
+ */
+
+void bbs_pubfree(bbs_pub *bp)
+{
+  mp_drop(bp->n);
+}
+
+void bbs_privfree(bbs_priv *bp)
+{
+  mp_drop(bp->n);
+  mp_drop(bp->p);
+  mp_drop(bp->q);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/bbs-gen.c b/pub/bbs-gen.c
new file mode 100644 (file)
index 0000000..e9e6922
--- /dev/null
@@ -0,0 +1,124 @@
+/* -*-c-*-
+ *
+ * Generate Blum integers
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bbs.h"
+#include "mp.h"
+#include "mprand.h"
+#include "pgen.h"
+#include "strongprime.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @bbs_gen@ --- *
+ *
+ * Arguments:  @bbs_priv *bp@ = pointer to parameter block
+ *             @unsigned nbits@ = number of bits in the modulus
+ *             @grand *r@ = pointer to random number source
+ *             @unsigned n@ = number of attempts to make
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for event handler
+ *
+ * Returns:    If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@.
+ *
+ * Use:                Finds two prime numbers %$p'$% and %$q'$% such that both are
+ *             congruent to %$3 \bmod 4$%, and  $(p - 1)/2$% and
+ *             %$(q - 1)/2$% have no common factors.  The product %$n = pq$%
+ *             is eminently suitable for use as a modulus in a Blum-Blum-
+ *             Shub pseudorandom bit generator.
+ */
+
+int bbs_gen(bbs_priv *bp, unsigned nbits, grand *r, unsigned n,
+           pgen_proc *event, void *ectx)
+{
+  rabin rb;
+  pfilt jp;
+  pgen_jumpctx j;
+  pgen_gcdstepctx g;
+  unsigned nb = nbits/2;
+  mp *x = MP_NEW;
+
+  /* --- Generate @p@ --- */
+
+again:
+  if ((x = strongprime_setup("p", x, &jp, nb, r, n, event, ectx)) == 0)
+    goto fail_x;
+  j.j = &jp;
+  bp->p = pgen("p", MP_NEW, x, event, ectx, n, pgen_jump, &j,
+              rabin_iters(nb), pgen_test, &rb);
+  pfilt_destroy(&jp);
+  if (!bp->p) {
+    if (n)
+      goto fail_p;
+    goto again;
+  }
+
+  /* --- Generate @q@ --- */
+
+  nb = nbits - nb;
+  if ((x = strongprime_setup("q", x, &g.jp, nb, r, n, event, ectx)) == 0)
+    goto fail_q;
+  if ((x->v[0] & 3) != 3)
+    x = mp_add(x, x, g.jp.m);
+  pfilt_muladd(&g.jp, &g.jp, 2, 0);
+  g.r = mp_lsr(MP_NEW, bp->p, 1);
+  g.g = MP_NEW;
+  g.max = MP_ONE;
+  bp->q = pgen("q", MP_NEW, x, event, ectx, n, pgen_gcdstep, &g,
+              rabin_iters(nb), pgen_test, &rb);
+  pfilt_destroy(&g.jp);
+  mp_drop(g.r);
+  mp_drop(g.g);
+  if (!bp->q) {
+    if (n)
+      goto fail_q;
+    mp_drop(bp->p);
+    goto again;
+  }
+
+  /* --- Compute @n@ --- */
+
+  bp->n = mp_mul(MP_NEW, bp->p, bp->q);
+  mp_drop(x);
+  return (PGEN_DONE);
+
+  /* --- Tidy up if things went wrong --- */
+
+fail_q:
+  mp_drop(bp->p);
+fail_p:
+  mp_drop(x);
+fail_x:
+  return (PGEN_ABORT);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/bbs-jump.c b/pub/bbs-jump.c
new file mode 100644 (file)
index 0000000..dd41d6f
--- /dev/null
@@ -0,0 +1,294 @@
+/* -*-c-*-
+ *
+ * Jumping around a BBS sequence
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "bbs.h"
+#include "mp.h"
+#include "mpbarrett.h"
+#include "mpcrt.h"
+#include "mpint.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @jump@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator context
+ *             @const bbs_priv *bp@ = pointer to BBS modulus factors
+ *             @mp *n@ = number of steps to move
+ *             @mp *px@ = exponent mod @p@ for a one-step jump
+ *             @mp *qx@ = exponent mod @q@ for a one-step jump
+ *
+ * Returns:    ---
+ *
+ * Use:                Jumps a BBS context a certain number of places (assuming the
+ *             arguments are right).
+ *
+ *             Let the BBS modulus be %$n = pq$% and the current residue be
+ *             %$x$%.  Then the computations performed are:
+ *
+ *               * Calculate %$x_p = x \bmod p$% and %$x_q = x \bmod q$%.
+ *
+ *               * Determine %$e_p = px^n \bmod (p - 1)$% and similarly
+ *                 %$e_q = qx^n \bmod (p - 1)$%.
+ *
+ *               * Calculate %$x_p' = x_p^{e_p} \bmod p$% and
+ *                 %$x_q' = x_q^{e_q} \bmod q$%.
+ *
+ *               * Combine %$x_p'$% and %$x_q'$% using the Chinese Remainder
+ *                 Theorem.
+ *
+ *             If you want to step the generator forwards, simply set
+ *             %$px = qx = 2$%.  If you want to step backwards, make
+ *             %$px = (p + 1)/4$% and %$qx = (q + 1)/4$%.  Note that, if
+ *             %$x$% is a quadratic residue mod $%p$%, then
+ *
+ *             %$(x^2) ^ {(p + 1)/4}$%
+ *               %${} = x^{(p + 1)/2}$%
+ *               %${} = x \cdot x^{(p - 1)/2}$%
+ *               %${} = x$%
+ *
+ *             Simple, no?  (Note that the division works because
+ *             %$p \equiv 3 \pmod 4$%.)
+ */
+
+static void jump(bbs *b, const bbs_priv *bp, mp *n,
+                mp *px, mp *qx)
+{
+  mp *ep, *eq;
+  mp *v[2] = { MP_NEW, MP_NEW };
+
+  /* --- First work out the exponents --- */
+
+  {
+    mpbarrett mb;
+    mp *m;
+
+    m = mp_sub(MP_NEW, bp->p, MP_ONE);
+    mpbarrett_create(&mb, m);
+    ep = mpbarrett_exp(&mb, MP_NEW, px, n);
+    mpbarrett_destroy(&mb);
+    if (qx == px)
+      eq = MP_COPY(ep);
+    else {
+      m = mp_sub(m, bp->q, MP_ONE);
+      mpbarrett_create(&mb, m);
+      eq = mpbarrett_exp(&mb, MP_NEW, qx, n);
+      mpbarrett_destroy(&mb);
+    }
+
+    mp_drop(m);
+  }
+
+  /* --- Now calculate the residues of @x@ --- */
+
+  mp_div(0, &v[0], b->x, bp->p);
+  mp_div(0, &v[1], b->x, bp->q);
+
+  /* --- Exponentiate --- */
+
+  {
+    mpbarrett mb;
+
+    mpbarrett_create(&mb, bp->p);
+    v[0] = mpbarrett_exp(&mb, v[0], v[0], ep);
+    mpbarrett_destroy(&mb);
+
+    mpbarrett_create(&mb, bp->q);
+    v[1] = mpbarrett_exp(&mb, v[1], v[1], eq);
+    mpbarrett_destroy(&mb);
+
+    mp_drop(ep);
+    mp_drop(eq);
+  }
+
+  /* --- Sort out the result using the Chinese Remainder Theorem --- */
+
+  {
+    mpcrt_mod mv[2];
+    mpcrt c;
+    int i;
+
+    mv[0].m = MP_COPY(bp->p);
+    mv[1].m = MP_COPY(bp->q);
+    for (i = 0; i < 2; i++)
+      mv[i].n = mv[i].ni = mv[i].nni = MP_NEW;
+    mpcrt_create(&c, mv, 2, b->mb.m);
+    b->x = mpcrt_solve(&c, b->x, v);
+    mpcrt_destroy(&c);
+  }
+
+  /* --- Tidy away --- */
+
+  mp_drop(v[0]);
+  mp_drop(v[1]);
+  b->r = b->x->v[0];
+  b->b = b->k;
+}
+
+/* --- @bbs_{ff,rew}{,n}@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to a BBS generator state
+ *             @const bbs_priv *bp@ = pointer to BBS modulus factors
+ *             @mp *n@, @unsigned long n@ = number of steps to make
+ *
+ * Returns:    ---
+ *
+ * Use:                `Fast-forwards' or rewinds a Blum-Blum-Shub generator by @n@
+ *             steps.  The @...n@ versions take an @unsigned long@ argument;
+ *             the non-@...n@ versions a multiprecision integer.  If @n@ is
+ *             negative then the generator is stepped in the reverse
+ *             direction.
+ */
+
+static void ff(bbs *b, const bbs_priv *bp, mp *n)
+  { jump(b, bp, n, MP_TWO, MP_TWO); }
+
+static void rew(bbs *b, const bbs_priv *bp, mp *n)
+{
+  mp *px = mp_lsr(MP_NEW, bp->p, 2);
+  mp *qx = mp_lsr(MP_NEW, bp->q, 2);
+  px = mp_add(px, px, MP_ONE);
+  qx = mp_add(qx, qx, MP_ONE);
+  jump(b, bp, n, px, qx);
+  mp_drop(px);
+  mp_drop(qx);
+}
+
+void bbs_ff(bbs *b, const bbs_priv *bp, mp *n)
+{
+  if (!MP_NEGP(n))
+    ff(b, bp, n);
+  else {
+    n = mp_neg(MP_NEW, n);
+    rew(b, bp, n);
+    mp_drop(n);
+  }
+}
+
+void bbs_ffn(bbs *b, const bbs_priv *bp, unsigned long n)
+  { mp *nn = mp_fromulong(MP_NEW, n); ff(b, bp, nn); mp_drop(nn); }
+
+void bbs_rew(bbs *b, const bbs_priv *bp, mp *n)
+{
+  if (!MP_NEGP(n))
+    rew(b, bp, n);
+  else {
+    n = mp_neg(MP_NEW, n);
+    ff(b, bp, n);
+    mp_drop(n);
+  }
+}
+
+void bbs_rewn(bbs *b, const bbs_priv *bp, unsigned long n)
+  { mp *nn = mp_fromulong(MP_NEW, n); bbs_rew(b, bp, nn); mp_drop(nn); }
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int verify(dstr *v)
+{
+  bbs_priv bp;
+  bbs b;
+  mp *x;
+  unsigned long n;
+  int ok = 1;
+  uint32 p, q, r;
+  int i;
+
+  bp.p = *(mp **)v[0].buf;
+  bp.q = *(mp **)v[1].buf;
+  bp.n = mp_mul(MP_NEW, bp.p, bp.q);
+  x = *(mp **)v[2].buf;
+  n = *(unsigned long *)v[3].buf;
+
+  bbs_create(&b, bp.n, x);
+  p = bbs_bits(&b, 32);
+
+  bbs_seed(&b, x);
+  for (i = 0; i < n; i++)
+    bbs_step(&b);
+  q = bbs_bits(&b, 32);
+  bbs_wrap(&b);
+
+  bbs_rewn(&b, &bp, n + (32 + b.k - 1) / b.k);
+  r = bbs_bits(&b, 32);
+
+  if (r != p) {
+    fputs("\n*** bbs rewind failure\n", stderr);
+    fputs("p = ", stderr); mp_writefile(bp.p, stderr, 10); fputc('\n', stderr);
+    fputs("q = ", stderr); mp_writefile(bp.q, stderr, 10); fputc('\n', stderr);
+    fputs("n = ", stderr); mp_writefile(bp.n, stderr, 10); fputc('\n', stderr);
+    fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr);
+    fprintf(stderr, "stepped %lu back\n", n + (32 + b.k - 1) / b.k);
+    fprintf(stderr, "expected output = %08lx, found %08lx\n",
+           (unsigned long)p, (unsigned long)r);
+    ok = 0;
+  }
+
+  bbs_seed(&b, x);
+  bbs_ffn(&b, &bp, n);
+  r = bbs_bits(&b, 32);
+
+  if (q != r) {
+    fputs("\n*** bbs fastforward failure\n", stderr);
+    fputs("p = ", stderr); mp_writefile(bp.p, stderr, 10); fputc('\n', stderr);
+    fputs("q = ", stderr); mp_writefile(bp.q, stderr, 10); fputc('\n', stderr);
+    fputs("n = ", stderr); mp_writefile(bp.n, stderr, 10); fputc('\n', stderr);
+    fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr);
+    fprintf(stderr, "stepped %lu back\n", n + (32 + b.k - 1) / b.k);
+    fprintf(stderr, "expected output = %08lx, found %08lx\n",
+           (unsigned long)q, (unsigned long)r);
+    ok = 0;
+  }
+
+  bbs_destroy(&b);
+  mp_drop(bp.p);
+  mp_drop(bp.q);
+  mp_drop(bp.n);
+  mp_drop(x);
+
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "bbs-jump", verify, { &type_mp, &type_mp, &type_mp, &type_ulong, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/bbs");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/bbs-rand.c b/pub/bbs-rand.c
new file mode 100644 (file)
index 0000000..58b62b1
--- /dev/null
@@ -0,0 +1,421 @@
+/* -*-c-*-
+ *
+ * Blum-Blum-Shub secure random number generator
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#include "arena.h"
+#include "bbs.h"
+#include "grand.h"
+#include "mp.h"
+#include "mpbarrett.h"
+#include "mpint.h"
+#include "mprand.h"
+#include "paranoia.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @bbs_create@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state to initialize
+ *             @mp *m@ = modulus (must be a Blum integer)
+ *             @mp *x@ = initial seed for generator
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a BBS generator.  The generator is stepped once
+ *             after initialization, as for @bbs_seed@.
+ */
+
+void bbs_create(bbs *b, mp *m, mp *x)
+{
+  mpw kw;
+  mp k;
+
+  mpbarrett_create(&b->mb, m);
+  kw = mp_bits(m) - 1;
+  mp_build(&k, &kw, &kw + 1);
+  b->k = mp_bits(&k) - 1;
+  b->x = 0;
+  bbs_seed(b, x);
+}
+
+/* --- @bbs_destroy@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a generator state when it's no longer wanted.
+ */
+
+void bbs_destroy(bbs *b)
+{
+  mp_drop(b->x);
+  mpbarrett_destroy(&b->mb);
+}
+
+/* --- @bbs_step@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *
+ * Returns:    ---
+ *
+ * Use:                Steps the generator once.  This isn't too useful in client
+ *             code.
+ */
+
+void bbs_step(bbs *b)
+{
+  mp *x = b->x;
+  x = mp_sqr(x, x);
+  x = mpbarrett_reduce(&b->mb, x, x);
+  b->x = x;
+  b->b = b->k;
+  b->r = b->x->v[0];
+}
+
+/* --- @bbs_set@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *             @mp *x@ = new residue to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets a new quadratic residue.  The generator is stepped once.
+ */
+
+void bbs_set(bbs *b, mp *x)
+{
+  mp_drop(b->x);
+  b->x = MP_COPY(x);
+  bbs_step(b);
+}
+
+/* --- @bbs_seed@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *             @mp *x@ = new seed to set
+ *
+ * Returns     ---
+ *
+ * Use:                Sets a new seed.  The generator is stepped until the residue
+ *             has clearly wrapped around.
+ */
+
+void bbs_seed(bbs *b, mp *x)
+{
+  mp *y;
+  x = MP_COPY(x);
+  for (;;) {
+    y = mp_sqr(MP_NEW, x);
+    y = mpbarrett_reduce(&b->mb, y, y);
+    if (MP_CMP(y, <, x))
+      break;
+    mp_drop(x);
+    x = y;
+  }
+  mp_drop(x);
+  bbs_set(b, y);
+  mp_drop(y);
+}
+
+/* --- @bbs_bits@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *             @unsigned bits@ = number of bits wanted
+ *
+ * Returns:    Bits extracted from the BBS generator.
+ *
+ * Use:                Extracts a requested number of bits from the BBS generator.
+ */
+
+uint32 bbs_bits(bbs *b, unsigned bits)
+{
+  uint32 x = 0;
+  mpw m;
+
+  /* --- Keep turning the handle until there's enough in the reservoir --- */
+
+  while (bits >= b->b) {
+    bits -= b->b;
+    m = (1 << b->b) - 1;
+    x |= (b->r & m) << bits;
+    bbs_step(b);
+  }
+
+  /* --- Extract the last few bits needed --- */
+
+  if (bits) {
+    m = (1 << bits) - 1;
+    b->b -= bits;
+    x |= (b->r >> b->b) & m;
+  }
+
+  /* --- Done --- */
+
+  return (x);
+}
+
+/* --- @bbs_wrap@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *
+ * Returns:    ---
+ *
+ * Use:                Steps the generator if any of the reservoir bits are used.
+ *             This can be used to `wrap up' after a Blum-Goldwasser
+ *             encryption, for example, producing the final value to be sent
+ *             along with the ciphertext.
+ *
+ *             If a generator is seeded, %$b$% bits are extracted, and then
+ *             @bbs_wrap@ is called, the generator will have been stepped
+ *             %$\lceil b/k \rceil$% times.
+ */
+
+void bbs_wrap(bbs *b)
+{
+  if (b->b < b->k)
+    bbs_step(b);
+}
+
+/*----- Generic random number generator interface -------------------------*/
+
+typedef struct gctx {
+  grand r;
+  bbs b;
+} gctx;
+
+static void gdestroy(grand *r)
+{
+  gctx *g = (gctx *)r;
+  bbs_destroy(&g->b);
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static int gmisc(grand *r, unsigned op, ...)
+{
+  gctx *g = (gctx *)r;
+  va_list ap;
+  int rc = 0;
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDMP:
+       case GRAND_SEEDRAND:
+       case BBS_SET:
+       case BBS_STEP:
+       case BBS_STEPSZ:
+       case BBS_BITS:
+       case BBS_WRAP:
+       case BBS_FF:
+       case BBS_FFN:
+       case BBS_REW:
+       case BBS_REWN:
+       case BBS_MOD:
+       case BBS_STATE:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT: {
+      mp *x = mp_fromuint(MP_NEW, va_arg(ap, unsigned));
+      bbs_seed(&g->b, x);
+      mp_drop(x);
+    } break;
+    case GRAND_SEEDUINT32: {
+      mp *x = mp_fromuint32(MP_NEW, va_arg(ap, uint32));
+      bbs_seed(&g->b, x);
+      mp_drop(x);
+    } break;
+    case GRAND_SEEDMP:
+      bbs_seed(&g->b, va_arg(ap, mp *));
+      break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      mp *m = mprand(MP_NEW, mp_bits(g->b.mb.m) - 1, rr, 0);
+      bbs_seed(&g->b, m);
+      mp_drop(m);
+    } break;
+    case BBS_SET:
+      bbs_set(&g->b, va_arg(ap, mp *));
+      break;
+    case BBS_STEP:
+      bbs_step(&g->b);
+      break;
+    case BBS_STEPSZ:
+      rc = g->b.k;
+      break;
+    case BBS_BITS: {
+      unsigned nb = va_arg(ap, unsigned);
+      uint32 *w = va_arg(ap, uint32 *);
+      *w = bbs_bits(&g->b, nb);
+    } break;
+    case BBS_WRAP:
+      bbs_wrap(&g->b);
+      break;
+    case BBS_FF: {
+      const bbs_priv *bp = va_arg(ap, const bbs_priv *);
+      mp *n = va_arg(ap, mp *);
+      bbs_ff(&g->b, bp, n);
+    } break;
+    case BBS_FFN: {
+      const bbs_priv *bp = va_arg(ap, const bbs_priv *);
+      unsigned long n = va_arg(ap, unsigned long);
+      bbs_ffn(&g->b, bp, n);
+    } break;
+    case BBS_REW: {
+      const bbs_priv *bp = va_arg(ap, const bbs_priv *);
+      mp *n = va_arg(ap, mp *);
+      bbs_rew(&g->b, bp, n);
+    } break;
+    case BBS_REWN: {
+      const bbs_priv *bp = va_arg(ap, const bbs_priv *);
+      unsigned long n = va_arg(ap, unsigned long);
+      bbs_rewn(&g->b, bp, n);
+    } break;
+    case BBS_MOD: {
+      mp **n = va_arg(ap, mp **);
+      if (*n) MP_DROP(*n);
+      *n = MP_COPY(g->b.mb.m);
+    } break;
+    case BBS_STATE: {
+      mp **n = va_arg(ap, mp **);
+      if (*n) MP_DROP(*n);
+      *n = MP_COPY(g->b.x);
+    } break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static octet gbyte(grand *r)
+{
+  gctx *g = (gctx *)r;
+  return (bbs_bits(&g->b, 8));
+}
+
+static uint32 gword(grand *r)
+{
+  gctx *g = (gctx *)r;
+  return (bbs_bits(&g->b, 32));
+}
+
+static const grand_ops gops = {
+  "bbs",
+  GRAND_CRYPTO, 0,
+  gmisc, gdestroy,
+  gword, gbyte, gword, grand_range, grand_fill
+};
+
+/* --- @bbs_rand@ --- *
+ *
+ * Arguments:  @mp *m@ = modulus
+ *             @mp *x@ = initial seed
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a
+ *             Blum-Blum-Shub generator.
+ */
+
+grand *bbs_rand(mp *m, mp *x)
+{
+  gctx *g = S_CREATE(gctx);
+  g->r.ops = &gops;
+  bbs_create(&g->b, m, x);
+  return (&g->r);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int verify(dstr *v)
+{
+  mp *n = *(mp **)v[0].buf;
+  mp *x = *(mp **)v[1].buf;
+  grand *b = bbs_rand(n, x);
+  dstr d = DSTR_INIT;
+  int ok = 1;
+
+  dstr_ensure(&d, v[2].len);
+  b->ops->fill(b, d.buf, v[2].len);
+  d.len = v[2].len;
+  if (memcmp(d.buf, v[2].buf, v[2].len) != 0) {
+    fputs("\n*** bbs failure\n", stderr);
+    fputs("n = ", stderr); mp_writefile(n, stderr, 10); fputc('\n', stderr);
+    fputs("x = ", stderr); mp_writefile(x, stderr, 10); fputc('\n', stderr);
+    fputs("expected = ", stderr); type_hex.dump(&v[2], stderr);
+    fputc('\n', stderr);
+    fputs("   found = ", stderr); type_hex.dump(&d, stderr);
+    fputc('\n', stderr);
+    fprintf(stderr, "k = %u\n", ((gctx *)b)->b.k);
+    ok = 0;
+  }
+  b->ops->destroy(b);
+  mp_drop(x);
+  mp_drop(n);
+  dstr_destroy(&d);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "bbs", verify, { &type_mp, &type_mp, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/bbs");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/bbs.h b/pub/bbs.h
new file mode 100644 (file)
index 0000000..4eb48d7
--- /dev/null
+++ b/pub/bbs.h
@@ -0,0 +1,294 @@
+/* -*-c-*-
+ *
+ * The Blum-Blum-Shub random bit generator
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on the BBS generator ----------------------------------------*
+ *
+ * The Blum-Blum-Shub generator takes the least significant bits from the
+ * sequence %$x_i = x_{i - 1}^2 \bmod n$%, where %$n = pq$% is the product of
+ * two primes %$p$% and %$q$%, each of which are congruent to %$3 \bmod 4$%.
+ * For maximum period of the generator, %$(p - 1)/2$% and %$(q - 1)/1$%
+ * should be coprime.  It is safe to use the least significant
+ * %$\log \log n$% bits of each step in the sequence -- an adversary must
+ * factor the modulus before being able to work forwards or backwards.  The
+ * output of the generator cannot be distinguished from a (uniform,
+ * independent) random sequence of bits using any polynomial-time test.  This
+ * is by far the strongest pseudorandom number generator provided in
+ * Catacomb, and by far the slowest too.  For normal use, the standard
+ * Catacomb @rand@ generator should be more than adequate.
+ */
+
+#ifndef CATACOMB_BBS_H
+#define CATACOMB_BBS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_KEY_H
+#  include "key.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_MPBARRETT_H
+#  include "mpbarrett.h"
+#endif
+
+#ifndef CATACOMB_PGEN_H
+#  include "pgen.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- Basic generator state --- */
+
+typedef struct bbs {
+  mpbarrett mb;                                /* Barrett reduction context */
+  mp *x;                               /* Current quadratic residue */
+  unsigned k;                          /* Number of bits from each step */
+  unsigned b;                          /* Number of bits in reservoir */
+  mpw r;                               /* Reservoir of output bits */
+} bbs;
+
+/* --- Parameters --- */
+
+typedef struct bbs_pub {
+  mp *n;
+} bbs_pub;
+
+typedef struct bbs_priv {
+  mp *p, *q;                           /* Prime factors (3 mod 4) */
+  mp *n;                               /* Product @pq@ -- a Blum integer */
+} bbs_priv;
+
+/*----- Key fetching ------------------------------------------------------*/
+
+extern const key_fetchdef bbs_pubfetch[];
+#define BBS_PUBFETCHSZ 3
+
+extern const key_fetchdef bbs_privfetch[];
+#define BBS_PRIVFETCHSZ 7
+
+/* --- @bbs_pubfree@, @bbs_privfree@ --- *
+ *
+ * Arguments:  @bbs_pub *bp@, @bbs_priv *bp@ = pointer to key block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a BBS key block.
+ */
+
+extern void bbs_pubfree(bbs_pub */*bp*/);
+extern void bbs_privfree(bbs_priv */*bp*/);
+
+/*----- The basic generator -----------------------------------------------*/
+
+/* --- @bbs_create@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state to initialize
+ *             @mp *m@ = modulus (must be a Blum integer)
+ *             @mp *x@ = initial seed for generator
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a BBS generator.  The generator is stepped once
+ *             after initialization, as for @bbs_seed@.
+ */
+
+extern void bbs_create(bbs */*b*/, mp */*m*/, mp */*x*/);
+
+/* --- @bbs_destroy@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a generator state when it's no longer wanted.
+ */
+
+extern void bbs_destroy(bbs */*b*/);
+
+/* --- @bbs_step@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *
+ * Returns:    ---
+ *
+ * Use:                Steps the generator once.  This isn't too useful in client
+ *             code.
+ */
+
+extern void bbs_step(bbs */*b*/);
+
+/* --- @bbs_set@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *             @mp *x@ = new residue to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets a new quadratic residue.  The generator is stepped once.
+ */
+
+extern void bbs_set(bbs */*b*/, mp */*x*/);
+
+/* --- @bbs_seed@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *             @mp *x@ = new seed to set
+ *
+ * Returns     ---
+ *
+ * Use:                Sets a new seed.  The generator is stepped until the residue
+ *             has clearly wrapped around.
+ */
+
+extern void bbs_seed(bbs */*b*/, mp */*x*/);
+
+/* --- @bbs_bits@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *             @unsigned bits@ = number of bits wanted
+ *
+ * Returns:    Bits extracted from the BBS generator.
+ *
+ * Use:                Extracts a requested number of bits from the BBS generator.
+ */
+
+extern uint32 bbs_bits(bbs */*b*/, unsigned /*bits*/);
+
+/* --- @bbs_wrap@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to BBS generator state
+ *
+ * Returns:    ---
+ *
+ * Use:                Steps the generator if any of the reservoir bits are used.
+ *             This can be used to `wrap up' after a Blum-Goldwasser
+ *             encryption, for example, producing the final value to be sent
+ *             along with the ciphertext.
+ *
+ *             If a generator is seeded, %$b$% bits are extracted, and then
+ *             @bbs_wrap@ is called, the generator will have been stepped
+ *             %$\lceil b/k \rceil$% times.
+ */
+
+extern void bbs_wrap(bbs */*b*/);
+
+/*----- Large forwards and backwards jumps --------------------------------*/
+
+/* --- @bbs_{ff,rew}{,n}@ --- *
+ *
+ * Arguments:  @bbs *b@ = pointer to a BBS generator state
+ *             @const bbs_priv *bp@ = pointer to BBS modulus factors
+ *             @mp *n@, @unsigned long n@ = number of steps to make
+ *
+ * Returns:    ---
+ *
+ * Use:                `Fast-forwards' or rewinds a Blum-Blum-Shub generator by @n@
+ *             steps.  The @...n@ versions take an @unsigned long@ argument;
+ *             the non-@...n@ versions a multiprecision integer.  If @n@ is
+ *             negative then the generator is stepped in the reverse
+ *             direction.
+ */
+
+extern void bbs_ff(bbs */*b*/, const bbs_priv */*bp*/, mp */*n*/);
+extern void bbs_ffn(bbs */*b*/, const bbs_priv */*bp*/, unsigned long /*n*/);
+extern void bbs_rew(bbs */*b*/, const bbs_priv */*bp*/, mp */*n*/);
+extern void bbs_rewn(bbs */*b*/, const bbs_priv */*bp*/, unsigned long /*n*/);
+
+/*----- Parameter generation ----------------------------------------------*/
+
+/* --- @bbs_gen@ --- *
+ *
+ * Arguments:  @bbs_priv *bp@ = pointer to parameter block
+ *             @unsigned nbits@ = number of bits in the modulus
+ *             @grand *r@ = pointer to random number source
+ *             @unsigned n@ = number of attempts to make
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for event handler
+ *
+ * Returns:    If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@.
+ *
+ * Use:                Finds two prime numbers %$p'$% and %$q'$% such that both are
+ *             congruent to %$3 \bmod 4$%, and  $(p - 1)/2$% and
+ *             %$(q - 1)/2$% have no common factors.  The product %$n = pq$%
+ *             is eminently suitable for use as a modulus in a Blum-Blum-
+ *             Shub pseudorandom bit generator.
+ */
+
+extern int bbs_gen(bbs_priv */*bp*/, unsigned /*nbits*/, grand */*r*/,
+                  unsigned /*n*/, pgen_proc */*event*/, void */*ectx*/);
+
+/*----- Generic random number generator interface -------------------------*/
+
+/* --- @bbs_rand@ --- *
+ *
+ * Arguments:  @mp *m@ = modulus
+ *             @mp *x@ = initial seed
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a
+ *             Blum-Blum-Shub generator.
+ */
+
+extern grand *bbs_rand(mp */*m*/, mp */*x*/);
+
+/* --- Blum-Blum-Shub-specific misc op codes --- */
+
+enum {
+  BBS_SET = GRAND_SPECIFIC('B'),       /* @mp *x@ */
+  BBS_STEP,                            /* @void@ */
+  BBS_STEPSZ,                          /* @void@ */
+  BBS_BITS,                            /* @unsigned bits, uint32 *w@ */
+  BBS_WRAP,                            /* @void@ */
+  BBS_FF,                              /* @bbs_priv *p, mp *n@ */
+  BBS_FFN,                             /* @bbs_priv *p, unsigned long n@ */
+  BBS_REW,                             /* @bbs_priv *p, mp *n@ */
+  BBS_REWN,                            /* @bbs_priv *p, unsigned long n@ */
+  BBS_MOD,                             /* @mp **n@ */
+  BBS_STATE                            /* @mp **x@ */
+};
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/pub/dh-check.c b/pub/dh-check.c
new file mode 100644 (file)
index 0000000..06f02ae
--- /dev/null
@@ -0,0 +1,170 @@
+/* -*-c-*-
+ *
+ * Checks Diffie-Hellman group parameters
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "dh.h"
+#include "keycheck.h"
+#include "mp.h"
+#include "mpmont.h"
+#include "mpmul.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @dh_checkparam@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = keycheck state
+ *             @const dh_param *dp@ = pointer to the parameter set
+ *             @mp **v@ = optional vector of factors
+ *             @size_t n@ = size of vector
+ *
+ * Returns:    Zero if all OK, or return status from function.
+ *
+ * Use:                Checks a set of Diffie-Hellman parameters for consistency and
+ *             security.
+ */
+
+int dh_checkparam(keycheck *kc, const dh_param *dp, mp **v, size_t n)
+{
+  int rc = 0;
+  mpmont mm;
+  mp *pm1 = MP_NEW;
+  mp *q = MP_NEW;
+  mp *x;
+  mpmul mu;
+  size_t i;
+
+  /* --- Check that the numbers which are supposed to be prime are --- */
+
+  if ((!v && keycheck_prime(kc, KCSEV_WARN, dp->q, "q")) ||
+      keycheck_prime(kc, KCSEV_ERR, dp->p, "p"))
+    goto fail;
+
+  /* --- Ensure that %$q$% is a sensible choice of number --- */
+
+  pm1 = mp_sub(pm1, dp->p, MP_ONE);
+  mp_div(0, &q, pm1, dp->q);
+  if (!mp_eq(q, MP_ZERO) &&
+      keycheck_report(kc, KCSEV_ERR, "q not a factor of p - 1"))
+    goto fail;
+
+  /* --- Check that %$g$% is actually right --- *
+   *
+   * This isn't perfect.  If %$q$% is composite and we don't have the factors
+   * of %$p - 1$% then the order of %$g$% may be some factor of %$q$% which
+   * we can't find.  (If we do have the factors, we check them all lower
+   * down.)  We do strip out powers of two from %$q$% before testing, though.
+   */
+
+  if ((mp_eq(dp->g, MP_ONE) || mp_eq(dp->g, pm1)) &&
+      keycheck_report(kc, KCSEV_ERR, "g is degenerate (+/-1 mod p)"))
+    goto fail;
+  q = mp_odd(q, dp->q, &i);
+  mpmont_create(&mm, dp->p);
+  x = mpmont_mul(&mm, MP_NEW, dp->g, mm.r2);
+  q = mpmont_expr(&mm, q, x, q);
+  mp_drop(x);
+  do {
+    if (mp_eq(q, mm.r) != !i) {
+      if (keycheck_report(kc, KCSEV_ERR, "order of g != q")) {
+       mpmont_destroy(&mm);
+       goto fail;
+      }
+      break;
+    }
+    if (i) {
+      q = mp_sqr(q, q);
+      q = mpmont_reduce(&mm, q, q);
+    }
+  } while (i--);
+
+  /* --- Check Lim-Lee primes more carefully --- *
+   *
+   * In this case, we really can be sure whether the order of %$g$% is
+   * actually %$q$% as advertised.  Also ensure that the individual primes
+   * are really prime, and that their product is correct.
+   */
+
+  if (!v)
+    mpmont_destroy(&mm);
+  else {
+    dstr d = DSTR_INIT;
+    mp *r = MP_NEW;
+
+    mpmul_init(&mu);
+    for (i = 0; i < n; i++) {
+      DRESET(&d);
+      dstr_putf(&d, "factor f_%lu of p", (unsigned long)i);
+      if ((rc = keycheck_prime(kc, KCSEV_ERR, v[i], d.buf)) != 0)
+       break;
+      mp_div(&q, &r, dp->q, v[i]);
+      if (mp_eq(r, MP_ZERO) && !mp_eq(q, MP_ONE)) {
+       q = mpmont_exp(&mm, q, dp->g, q);
+       if (mp_eq(q, MP_ONE) &&
+           (rc = keycheck_report(kc, KCSEV_ERR,
+                                 "order of g is proper divisor of q")) != 0)
+         break;
+      }
+      mpmul_add(&mu, v[i]);
+    }
+    mp_drop(q);
+    mp_drop(r);
+    q = mpmul_done(&mu);
+    mpmont_destroy(&mm);
+    dstr_destroy(&d);
+    if (rc)
+      goto fail;
+    q = mp_lsl(q, q, 1);
+    if (!mp_eq(q, pm1) &&
+       keycheck_report(kc, KCSEV_ERR, "product of f_i != (p - 1)/2"))
+      goto fail;
+  }
+
+  /* --- Finally, check the key sizes --- */
+
+  if ((mp_bits(dp->p) < 1024 &&
+       keycheck_report(kc, KCSEV_WARN,
+                      "p too small to resist index calculus attacks")) ||
+      (mp_bits(dp->q) < 160 &&
+       keycheck_report(kc, KCSEV_WARN,
+                      "q too small to resist collision-finding attacks")))
+    goto fail;
+
+  /* --- Done --- */
+
+tidy:
+  mp_drop(q);
+  mp_drop(pm1);
+  return (rc);
+fail:
+  rc = -1;
+  goto tidy;
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dh-fetch.c b/pub/dh-fetch.c
new file mode 100644 (file)
index 0000000..ddb3ce2
--- /dev/null
@@ -0,0 +1,98 @@
+/* -*-c-*-
+ *
+ * Key fetching for Diffie-Hellman public and private keys
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "dh.h"
+#include "key.h"
+
+/*----- Key fetching ------------------------------------------------------*/
+
+const key_fetchdef dh_paramfetch[] = {
+  { "p",       offsetof(dh_param, p),          KENC_MP,        0 },
+  { "q",       offsetof(dh_param, q),          KENC_MP,        0 },
+  { "g",       offsetof(dh_param, g),          KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+const key_fetchdef dh_pubfetch[] = {
+  { "p",       offsetof(dh_pub, dp.p),         KENC_MP,        0 },
+  { "q",       offsetof(dh_pub, dp.q),         KENC_MP,        0 },
+  { "g",       offsetof(dh_pub, dp.g),         KENC_MP,        0 },
+  { "y",       offsetof(dh_pub, y),            KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+static const key_fetchdef priv[] = {
+  { "x",       offsetof(dh_priv, x),           KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+const key_fetchdef dh_privfetch[] = {
+  { "p",       offsetof(dh_priv, dp.p),        KENC_MP,        0 },
+  { "q",       offsetof(dh_priv, dp.q),        KENC_MP,        0 },
+  { "g",       offsetof(dh_priv, dp.g),        KENC_MP,        0 },
+  { "y",       offsetof(dh_priv, y),           KENC_MP,        0 },
+  { "private", 0,                              KENC_STRUCT,    priv },
+  { 0,         0,                              0,              0 }
+};
+
+/* --- @dh_paramfree@, @dh_pubfree@, @dh_privfree@ --- *
+ *
+ * Arguments:  @dh_param *dp@, @dh_pub *dp@, @dh_priv *dp@ = pointer
+ *                     to key block to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a Diffie-Hellman key block.
+ */
+
+void dh_paramfree(dh_param *dp)
+{
+  mp_drop(dp->p);
+  mp_drop(dp->q);
+  mp_drop(dp->g);
+}
+
+void dh_pubfree(dh_pub *dp)
+{
+  mp_drop(dp->dp.p);
+  mp_drop(dp->dp.q);
+  mp_drop(dp->dp.g);
+  mp_drop(dp->y);
+}
+
+void dh_privfree(dh_priv *dp)
+{
+  mp_drop(dp->dp.p);
+  mp_drop(dp->dp.q);
+  mp_drop(dp->dp.g);
+  mp_drop(dp->y);
+  mp_drop(dp->x);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dh-gen.c b/pub/dh-gen.c
new file mode 100644 (file)
index 0000000..17b34f6
--- /dev/null
@@ -0,0 +1,161 @@
+/* -*-c-*-
+ *
+ * Generate Diffie-Hellman parameters
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/macros.h>
+
+#include "dh.h"
+#include "grand.h"
+#include "mp.h"
+#include "mpmont.h"
+#include "mprand.h"
+#include "pfilt.h"
+#include "pgen.h"
+#include "prim.h"
+#include "rabin.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @dh_gen@ --- *
+ *
+ * Arguments:  @dh_param *dp@ = pointer to output parameter block
+ *             @unsigned ql@ = length of %$q$% in bits, or zero
+ *             @unsigned pl@ = length of %$p$% in bits
+ *             @unsigned steps@ = number of steps to go
+ *             @grand *r@ = random number source
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for the event handler
+ *
+ * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't.
+ *
+ * Use:                Generates Diffie-Hellman parameters.
+ *
+ *             The parameters are a prime %$q$%, relatively small, and a
+ *             large prime %$p = kq + 1$% for some %$k$%, together with a
+ *             generator %$g$% of the cyclic subgroup of order %$q$%.  These
+ *             are actually the same as the DSA parameter set, but the
+ *             generation algorithm is different.  Also, if @ql@ is zero,
+ *             this algorithm forces %$k = 2$%, and chooses %$g = 4$%.  Make
+ *             sure you have something interesting to do if you choose this
+ *             option.
+ */
+
+int dh_gen(dh_param *dp, unsigned ql, unsigned pl, unsigned steps, grand *r,
+          pgen_proc *event, void *ectx)
+{
+  /* --- If @ql@ is zero, do the time consuming safe-prime thing --- */
+
+  if (!ql) {
+    pgen_simulprime sp[2];
+    pgen_simulctx ss;
+
+    mp *m = mprand(MP_NEW, pl - 1, r, 1);
+    ss.step = MP_TWO;
+    sp[0].mul = MP_ONE; sp[0].add = MP_ZERO; sp[0].f = 0;
+    sp[1].mul = MP_TWO; sp[1].add = MP_ONE; sp[1].f = PGENF_KEEP;
+    ss.v = sp; ss.n = N(sp);
+    dp->q = pgen("p", MP_NEW, m, event, ectx, steps, pgen_simulstep, &ss,
+                rabin_iters(pl), pgen_simultest, &ss);
+    mp_drop(m);
+    if (!dp->q) {
+      mp_drop(sp[1].u.x);
+      return (PGEN_ABORT);
+    }
+    dp->p = sp[1].u.x;
+    dp->g = MP_FOUR;
+    return (PGEN_DONE);
+  }
+
+  /* --- Otherwise the job is much simpler --- *
+   *
+   * But doesn't look it...
+   */
+
+  else {
+    pgen_filterctx c;
+    pgen_jumpctx j;
+    rabin rb;
+    prim_ctx p;
+    int i;
+    mp *m = MP_NEW;
+    mp *x, *y;
+
+    /* --- Generate @q@ first --- */
+
+    c.step = 2;
+    m = mprand(MP_NEW, ql, r, 1);
+    dp->q = pgen("q", MP_NEW, m, event, ectx, steps, pgen_filter, &c,
+                rabin_iters(ql), pgen_test, &rb);
+    if (!dp->q)
+      goto fail_q;
+
+    /* --- Now pick a suitable @p@ --- */
+
+    m = mp_lsl(m, dp->q, 1);
+    x = mprand(MP_NEW, pl, r, 0);
+    y = MP_NEW; mp_div(0, &y, x, m);
+    x = mp_sub(x, x, y);
+    x = mp_add(x, x, MP_ONE);
+    mp_drop(y);
+    pfilt_create(&c.f, m);
+    j.j = &c.f;
+    dp->p = pgen("p", MP_NEW, x, event, ectx, steps, pgen_jump, &j,
+                rabin_iters(pl), pgen_test, &rb);
+    pfilt_destroy(&c.f);
+    mp_drop(x);
+    if (!dp->p)
+      goto fail_p;
+
+    /* --- And finally a suitable @g@ --- */
+
+    mpmont_create(&p.mm, dp->p);
+    mp_div(&m, 0, dp->p, dp->q);
+    i = 0;
+    p.exp = m;
+    p.n = 0;
+    dp->g = pgen("g", MP_NEW, MP_NEW, event, ectx, 0, prim_step, &i,
+                1, prim_test, &p);
+    mpmont_destroy(&p.mm);
+    if (!dp->g)
+      goto fail_g;
+    mp_drop(m);
+    return (PGEN_DONE);
+
+    /* --- Tidy up --- */
+
+  fail_g:
+    mp_drop(dp->q);
+  fail_q:
+    mp_drop(dp->p);
+  fail_p:
+    mp_drop(m);
+    return (PGEN_ABORT);
+  }
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dh-kcdsa.c b/pub/dh-kcdsa.c
new file mode 100644 (file)
index 0000000..e773309
--- /dev/null
@@ -0,0 +1,123 @@
+/* -*-c-*-
+ *
+ * Generate KCDSA prime groups
+ *
+ * (c) 2006 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/macros.h>
+
+#include "dh.h"
+#include "mprand.h"
+#include "pgen.h"
+#include "prim.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @dh_kcdsagen@ --- *
+ *
+ * Arguments:  @dh_param *dp@ = pointer to output parameter block
+ *             @unsigned ql@ = size of small factor of %$(p - 1)/2$%
+ *             @unsigned pl@ = size of %$p$% in bits
+ *             @unsigned flags@ = other generation flags
+ *             @unsigned steps@ = number of steps to go
+ *             @grand *r@ = random number source
+ *             @pgen_proc *ev@ = event handler function
+ *             @void *ec@ = context for the event handler
+ *
+ * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed.
+ *
+ * Use:                Generates a KCDSA prime group.  That is, it chooses a prime
+ *             %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and
+ *             %$v$%.  The actual group of interest is the subgroup of order
+ *             %$q$%.
+ */
+
+int dh_kcdsagen(dh_param *dp, unsigned ql, unsigned pl,
+               unsigned flags, unsigned steps, grand *r,
+               pgen_proc *ev, void *ec)
+{
+  pgen_filterctx pf;
+  pgen_simulprime sp[2];
+  pgen_simulctx ss;
+  prim_ctx pc;
+  rabin rb;
+  int rc = PGEN_ABORT;
+  int i;
+  mp *x;
+
+  /* --- First trick: find %$q$% --- */
+
+  pf.step = 2;
+  x = mprand(MP_NEW, pl - ql, r, 1);
+  x = pgen("v", x, x, ev, ec,
+          steps, pgen_filter, &pf,
+          rabin_iters(pl - ql), pgen_test, &rb);
+  if (!x)
+    goto fail_0;
+
+  /* --- Second trick: find %$p$% and %$v$% --- */
+
+  x = mp_lsl(x, x, 1);
+  sp[0].add = MP_ZERO; sp[0].mul = MP_ONE; sp[0].f = 0;
+  sp[1].add = MP_ONE; sp[1].mul = x; sp[1].f = PGENF_KEEP;
+  ss.step = MP_TWO; ss.v = sp; ss.n = N(sp);
+  x = mprand(MP_NEW, ql, r, 1);
+  dp->q = pgen("p", MP_NEW, x, ev, ec,
+              steps, pgen_simulstep, &ss,
+              rabin_iters(ql), pgen_simultest, &ss);
+  mp_drop(sp[0].mul);
+  if (!dp->q)
+    goto fail_1;
+  dp->p = sp[1].u.x;
+
+  /* --- Third trick: find a generator --- */
+
+  mpmont_create(&pc.mm, dp->p);
+  mp_div(&x, 0, dp->p, dp->q);
+  i = 0;
+  pc.exp = x;
+  pc.n = 0;
+  dp->g = pgen("g", MP_NEW, MP_NEW, ev, ec,
+              0, prim_step, &i, 1, prim_test, &pc);
+  mpmont_destroy(&pc.mm);
+  if (!dp->g)
+    goto fail_2;
+
+  rc = PGEN_DONE;
+  goto done;
+
+  /* --- Tidying up and going home --- */
+
+fail_2:
+  mp_drop(dp->p);
+fail_1:
+fail_0:
+done:
+  mp_drop(x);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dh-limlee.c b/pub/dh-limlee.c
new file mode 100644 (file)
index 0000000..cdcebe2
--- /dev/null
@@ -0,0 +1,138 @@
+/* -*-c-*-
+ *
+ * Generate Diffie-Hellman parameters from Lim-Lee primes
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "dh.h"
+#include "limlee.h"
+#include "mpmont.h"
+#include "prim.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @dh_limlee@ --- *
+ *
+ * Arguments:  @dh_param *dp@ = pointer to output parameter block
+ *             @unsigned ql@ = length of smallest factor of %$(p - 1)/2$%
+ *             @unsigned pl@ = length of %$p$% in bits
+ *             @unsigned flags@ = other generation flags
+ *             @unsigned steps@ = number of steps to go
+ *             @grand *r@ = random number source
+ *             @pgen_proc *oev@ = outer event handler function
+ *             @void *oec@ = argument for the outer event handler
+ *             @pgen_proc *iev@ = inner event handler function
+ *             @void *iec@ = argument for the inner event handler
+ *             @size_t *nf@, @mp ***f@ = output array for factors
+ *
+ * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't.
+ *
+ * Use:                Generates Diffie-Hellman parameters based on a Lim-Lee prime.
+ *
+ *             The modulus is a large prime %$p = 2 \prod q_i + 1$%, @pl@
+ *             bits long, where the %$q_i$% are smaller primes each at least
+ *             @ql@ bits long.  It is safe to set @nf@ and @f@ to zero if
+ *             you're not interested in the factor values.
+ *
+ *             The returned %$g$% generates a subgroup of order %$q_0$% (the
+ *             first factor, returned as @f[0]@), if the flag @DH_SUBGROUP@
+ *             is set on entry; otherwise %$g$% will have order
+ *             %$(p - 1)/2$%.
+ */
+
+int dh_limlee(dh_param *dp, unsigned ql, unsigned pl,
+             unsigned flags, unsigned steps, grand *r,
+             pgen_proc *oev, void *oec, pgen_proc *iev,
+             void *iec, size_t *nf, mp ***f)
+{
+  mp **ff;
+  size_t nff;
+  prim_ctx pc;
+  size_t i;
+  int j;
+  mp *pp;
+
+  /* --- Generate the Lim-Lee prime --- */
+
+  if ((dp->p = limlee("p", MP_NEW, MP_NEW, ql, pl,
+                     r, steps, oev, oec, iev, iec, &nff, &ff)) == 0)
+    return (PGEN_ABORT);
+
+  /* --- Now find a primitive element --- */
+
+  mpmont_create(&pc.mm, dp->p);
+  pp = mp_sub(MP_NEW, dp->p, MP_ONE);
+  if (flags & DH_SUBGROUP) {
+    dp->q = mp_copy(ff[0]);
+    pc.exp = MP_NEW;
+    mp_div(&pc.exp, 0, pp, dp->q);
+    pc.n = 0;
+    pc.f = 0;
+  } else {
+    dp->q = mp_lsr(MP_NEW, dp->p, 1);
+    pc.exp = MP_TWO;
+    pc.n = nff;
+    pc.f = xmalloc(nff * sizeof(mp *));
+    for (i = 0; i < nff; i++) {
+      pc.f[i] = MP_NEW;
+      mp_div(&pc.f[i], 0, pp, ff[i]);
+    }
+  }
+
+  j = 0;
+  dp->g = pgen("g", MP_NEW, MP_NEW, oev, oec,
+              0, prim_step, &j, 1, prim_test, &pc);
+
+  mp_drop(pp);
+  if (pc.f) {
+    for (i = 0; i < pc.n; i++)
+      mp_drop(pc.f[i]);
+    xfree(pc.f);
+  }
+  mpmont_destroy(&pc.mm);
+
+  /* --- Do something sensible with the list of primes --- */
+
+  if (dp->g && f) {
+    *f = ff;
+    *nf = nff;
+  } else {
+    for (i = 0; i < nff; i++)
+      mp_drop(ff[i]);
+    xfree(ff);
+  }
+
+  /* --- Tidy up and return --- */
+
+  if (!dp->g) {
+    mp_drop(dp->p);
+    mp_drop(dp->q);
+    return (PGEN_ABORT);
+  }
+  return (PGEN_DONE);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dh-param.c b/pub/dh-param.c
new file mode 100644 (file)
index 0000000..b593fb8
--- /dev/null
@@ -0,0 +1,170 @@
+/* -*-c-*-
+ *
+ * Reading Diffie-Hellman parameters
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "dh.h"
+#include "ptab.h"
+#include "bintab.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* ---- @dh_infofromdata@ --- *
+ *
+ * Arguments:  @dh_param *dp@ = parameters to fill in
+ *             @pdata *pd@ = packed data structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Fills in a parameters structure from a packed data block.
+ */
+
+void dh_infofromdata(dh_param *dp, pdata *pd)
+  { dp->p = &pd->p; dp->q = &pd->q; dp->g = &pd->g; }
+
+/* --- @dh_parse@, @dhbin_parse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *             @dh_param *dp@ = parameters to fill in
+ *
+ * Returns:    Zero if OK, nonzero on error.
+ *
+ * Use:                Parses a prime group string.  This is either one of the
+ *             standard group strings, or a %$p$%, %$q$%, %$g$% triple
+ *             separated by commas.
+ */
+
+static int parse(qd_parse *qd, gprime_param *dp)
+{
+  mp *p = MP_NEW, *q = MP_NEW, *g = MP_NEW;
+
+  if ((p = qd_getmp(qd)) == 0) goto fail;
+  qd_delim(qd, ','); if ((q = qd_getmp(qd)) == 0) goto fail;
+  qd_delim(qd, ','); if ((g = qd_getmp(qd)) == 0) goto fail;
+  dp->p = p; dp->q = q; dp->g = g;
+  return (0);
+fail:
+  mp_drop(p); mp_drop(q); mp_drop(g);
+  return (-1);
+}
+
+int dh_parse(qd_parse *qd, dh_param *dp)
+{
+  const pentry *pe;
+
+  for (pe = ptab; pe->name; pe++) {
+    if (qd_enum(qd, pe->name) >= 0) {
+      dh_infofromdata(dp, pe->data);
+      goto found;
+    }
+  }
+  if (parse(qd, dp))
+    return (-1);
+found:
+  return (0);
+}
+
+int dhbin_parse(qd_parse *qd, gbin_param *gb)
+{
+  const binentry *be;
+
+  for (be = bintab; be->name; be++) {
+    if (qd_enum(qd, be->name) >= 0) {
+      dh_infofromdata(gb, be->data);
+      goto found;
+    }
+  }
+  if (parse(qd, gb))
+    return (-1);
+found:
+  return (0);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include "fibrand.h"
+
+int main(int argc, char *argv[])
+{
+  const pentry *pe;
+  const binentry *be;
+  const char *e;
+  int ok = 1, aok = 1;
+  grand *gr;
+
+  gr = fibrand_create(0);
+  fputs("checking standard prime groups:", stdout);
+  fflush(stdout);
+  for (pe = ptab; pe->name; pe++) {
+    dh_param dp;
+    group *g;
+    dh_infofromdata(&dp, pe->data);
+    g = group_prime(&dp);
+    if (mp_bits(dp.p) > 2048 &&
+       (!argv[1] || strcmp(argv[1], "keen") != 0)) {
+      printf(" [%s skipped]", pe->name);
+      fflush(stdout);
+      continue;
+    }
+    e = G_CHECK(g, gr);
+    G_DESTROYGROUP(g);
+    dh_paramfree(&dp);
+    if (e) {
+      printf(" [%s failed: %s]", pe->name, e);
+      ok = aok = 0;
+    } else
+      printf(" %s", pe->name);
+    fflush(stdout);
+  }
+  fputs(ok ? " ok\n" : " failed\n", stdout);
+  ok = 1;
+  fputs("checking standard binary groups:", stdout);
+  for (be = bintab; be->name; be++) {
+    gbin_param gb;
+    group *g;
+    dh_infofromdata(&gb, be->data);
+    g = group_binary(&gb);
+    e = G_CHECK(g, gr);
+    G_DESTROYGROUP(g);
+    dh_paramfree(&gb);
+    if (e) {
+      printf(" [%s failed: %s]", be->name, e);
+      ok = aok = 0;
+    } else
+      printf(" %s", be->name);
+    fflush(stdout);
+  }
+  fputs(ok ? " ok\n" : " failed\n", stdout);
+  gr->ops->destroy(gr);
+  return (!aok);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dh.h b/pub/dh.h
new file mode 100644 (file)
index 0000000..32ed522
--- /dev/null
+++ b/pub/dh.h
@@ -0,0 +1,240 @@
+/* -*-c-*-
+ *
+ * Diffie-Hellman and related public-key systems
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_DH_H
+#define CATACOMB_DH_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GROUP_H
+#  include "group.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_KEY_H
+#  include "key.h"
+#endif
+
+#ifndef CATACOMB_KEYCHECK_H
+#  include "keycheck.h"
+#endif
+
+#ifndef CATACOMB_PGEN_H
+#  include "pgen.h"
+#endif
+
+#ifndef CATACOMB_QDPARSE_H
+#  include "qdparse.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef gprime_param dh_param;         /* Group parameters */
+
+typedef struct dh_pub {
+  dh_param dp;                         /* Shared parameters */
+  mp *y;                               /* Public key */
+} dh_pub;
+
+typedef struct dh_priv {
+  dh_param dp;                         /* Shared parameters */
+  mp *x;                               /* Private key */
+  mp *y;                               /* %$y \equiv g^x \pmod{p}$% */
+} dh_priv;
+
+/*----- Key fetching ------------------------------------------------------*/
+
+extern const key_fetchdef dh_paramfetch[];
+#define DH_PARAMFETCHSZ 5
+
+extern const key_fetchdef dh_pubfetch[];
+#define DH_PUBFETCHSZ 6
+
+extern const key_fetchdef dh_privfetch[];
+#define DH_PRIVFETCHSZ 9
+
+/* --- @dh_paramfree@, @dh_pubfree@, @dh_privfree@ --- *
+ *
+ * Arguments:  @dh_param *dp@, @dh_pub *dp@, @dh_priv *dp@ = pointer to
+ *                     key block to free
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a Diffie-Hellman key block.
+ */
+
+extern void dh_paramfree(dh_param */*dp*/);
+extern void dh_pubfree(dh_pub */*dp*/);
+extern void dh_privfree(dh_priv */*dp*/);
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @dh_gen@ --- *
+ *
+ * Arguments:  @dh_param *dp@ = pointer to output parameter block
+ *             @unsigned ql@ = length of %$q$% in bits, or zero
+ *             @unsigned pl@ = length of %$p$% in bits
+ *             @unsigned steps@ = number of steps to go
+ *             @grand *r@ = random number source
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for the event handler
+ *
+ * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't.
+ *
+ * Use:                Generates Diffie-Hellman parameters.
+ *
+ *             The parameters are a prime %$q$%, relatively small, and a
+ *             large prime %$p = kq + 1$% for some %$k$%, together with a
+ *             generator %$g$% of the cyclic subgroup of order %$q$%.  These
+ *             are actually the same as the DSA parameter set, but the
+ *             generation algorithm is different.  Also, if @ql@ is zero,
+ *             this algorithm forces %$k = 2$%, and chooses %$g = 4$%.  Make
+ *             sure you have something interesting to do if you choose this
+ *             option.
+ */
+
+extern int dh_gen(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/,
+                 unsigned /*steps*/, grand */*r*/, pgen_proc */*event*/,
+                 void */*ectx*/);
+
+/* --- @dh_limlee@ --- *
+ *
+ * Arguments:  @dh_param *dp@ = pointer to output parameter block
+ *             @unsigned ql@ = length of smallest factor of %$(p - 1)/2$%
+ *             @unsigned pl@ = length of %$p$% in bits
+ *             @unsigned flags@ = other generation flags
+ *             @unsigned steps@ = number of steps to go
+ *             @grand *r@ = random number source
+ *             @pgen_proc *oev@ = outer event handler function
+ *             @void *oec@ = argument for the outer event handler
+ *             @pgen_proc *iev@ = inner event handler function
+ *             @void *iec@ = argument for the inner event handler
+ *             @size_t *nf@, @mp ***f@ = output array for factors
+ *
+ * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it didn't.
+ *
+ * Use:                Generates Diffie-Hellman parameters based on a Lim-Lee prime.
+ *
+ *             The modulus is a large prime %$p = 2 \prod q_i + 1$%, @pl@
+ *             bits long, where the %$q_i$% are smaller primes each at least
+ *             @ql@ bits long.  It is safe to set @nf@ and @f@ to zero if
+ *             you're not interested in the factor values.
+ *
+ *             The returned %$g$% generates a subgroup of order %$q_0$% (the
+ *             first factor, returned as @f[0]@), if the flag @DH_SUBGROUP@
+ *             is set on entry; otherwise %$g$% will have order
+ *             %$(p - 1)/2$%.
+ */
+
+#define DH_SUBGROUP 1u
+
+extern int dh_limlee(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/,
+                    unsigned /*flags*/, unsigned /*steps*/, grand */*r*/,
+                    pgen_proc */*oev*/, void */*oec*/, pgen_proc */*iev*/,
+                    void */*iec*/, size_t */*nf*/, mp ***/*f*/);
+
+/* --- @dh_kcdsagen@ --- *
+ *
+ * Arguments:  @dh_param *dp@ = pointer to output parameter block
+ *             @unsigned ql@ = size of small factor of %$(p - 1)/2$%
+ *             @unsigned pl@ = size of %$p$% in bits
+ *             @unsigned flags@ = other generation flags (none defined)
+ *             @unsigned steps@ = number of steps to go
+ *             @grand *r@ = random number source
+ *             @pgen_proc *ev@ = event handler function
+ *             @void *ec@ = context for the event handler
+ *
+ * Returns:    @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed.
+ *
+ * Use:                Generates a KCDSA prime group.  That is, it chooses a prime
+ *             %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and
+ *             %$v$%.  The actual group of interest is the subgroup of order
+ *             %$q$%.
+ */
+
+extern int dh_kcdsagen(dh_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/,
+                      unsigned /*flags*/, unsigned /*steps*/, grand */*r*/,
+                      pgen_proc */*ev*/, void */*ec*/);
+
+/* --- @dh_checkparam@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = keycheck state
+ *             @const dh_param *dp@ = pointer to the parameter set
+ *             @mp **v@ = optional vector of factors
+ *             @size_t n@ = size of vector
+ *
+ * Returns:    Zero if all OK, or return status from function.
+ *
+ * Use:                Checks a set of Diffie-Hellman parameters for consistency and
+ *             security.
+ */
+
+extern int dh_checkparam(keycheck */*kc*/, const dh_param */*dp*/,
+                        mp **/*v*/, size_t /*n*/);
+
+/* ---- @dh_infofromdata@ --- *
+ *
+ * Arguments:  @dh_param *dp@ = parameters to fill in
+ *             @pdata *pd@ = packed data structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Fills in a parameters structure from a packed data block.
+ */
+
+struct pdata;
+extern void dh_infofromdata(dh_param */*dp*/, struct pdata */*pd*/);
+
+/* --- @dh_parse@, @dhbin_parse@ --- *
+ *
+ * Arguments:  @qd_parse *qd@ = parser context
+ *             @dh_param *dp@ = parameters to fill in
+ *
+ * Returns:    Zero if OK, nonzero on error.
+ *
+ * Use:                Parses a prime/binary group string.  This is either one of
+ *             the standard group strings, or a %$p$%, %$q$%, %$g$% triple
+ *             separated by commas.
+ */
+
+extern int dh_parse(qd_parse */*qd*/, dh_param */*dp*/);
+extern int dhbin_parse(qd_parse */*qd*/, gbin_param */*gb*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/pub/dsa-check.c b/pub/dsa-check.c
new file mode 100644 (file)
index 0000000..4d42ff2
--- /dev/null
@@ -0,0 +1,87 @@
+/* -*-c-*-
+ *
+ * Consistency checking for DSA keys
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "dh.h"
+#include "dsa.h"
+#include "dsarand.h"
+#include "grand.h"
+#include "keycheck.h"
+#include "mp.h"
+#include "mprand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @dsa_checkparam@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = keycheck state
+ *             @const dsa_param *dp@ = pointer to the parameter set
+ *             @const dsa_seed *ds@ = pointer to seed information
+ *
+ * Returns:    Zero if all OK, or return status from function.
+ *
+ * Use:                Checks a set of DSA parameters for consistency and security.
+ */
+
+int dsa_checkparam(keycheck *kc, const dsa_param *dp, const dsa_seed *ds)
+{
+  if (ds) {
+    grand *r = dsarand_create(ds->p, ds->sz);
+    mp *p = MP_NEW, *q = MP_NEW;
+    int rc = 0;
+    unsigned i;
+    unsigned long n;
+
+    r->ops->misc(r, DSARAND_PASSES, 2);
+    q = mprand(q, mp_bits(dp->q), r, 1);
+    if (!mp_eq(q, dp->q) &&
+       keycheck_report(kc, KCSEV_ERR, "q doesn't match seed provided"))
+      rc = -1;
+    else {
+      n = mp_bits(dp->p);
+      r->ops->misc(r, DSARAND_PASSES, 1);
+      for (i = 0; i <= ds->count; i++)
+       p = mprand(p, n, r, 0);
+      q = mp_lsl(q, q, 1);
+      mp_div(0, &q, p, q);
+      p = mp_sub(p, p, q);
+      p->v[0] |= 1;
+      if (!mp_eq(p, dp->p) &&
+         keycheck_report(kc, KCSEV_ERR, "p doesn't match seed provided"))
+       rc = -1;
+    }
+    mp_drop(p);
+    mp_drop(q);
+    r->ops->destroy(r);
+    if (rc)
+      return (rc);
+  }
+  return (dh_checkparam(kc, dp, 0, 0));
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dsa-gen.c b/pub/dsa-gen.c
new file mode 100644 (file)
index 0000000..7c6c3ba
--- /dev/null
@@ -0,0 +1,299 @@
+/* -*-c-*-
+ *
+ * Generate DSA shared parameters
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dsa.h"
+#include "dsarand.h"
+#include "fibrand.h"
+#include "mp.h"
+#include "mprand.h"
+#include "pgen.h"
+#include "prim.h"
+#include "sha.h"
+
+/*----- The DSA stepper ---------------------------------------------------*/
+
+/* --- @next@ --- *
+ *
+ * Arguments:  @pgen_event *ev@ = pointer to event block
+ *             @dsa_stepctx *d@ = pointer to stepping context
+ *
+ * Returns:    A @PGEN@ result code.
+ *
+ * Use:                Steps the generator once, reads the result, and tests it.
+ */
+
+static int next(pgen_event *ev, dsa_stepctx *d)
+{
+  mp *m;
+  int rc;
+
+  /* --- Load the new candidate --- */
+
+  if (d->seedbuf)
+    d->r->ops->misc(d->r, DSARAND_GETSEED, d->seedbuf);
+  m = mprand(ev->m, d->bits, d->r, 0);
+
+  /* --- Force to be a multiple of @q@ --- */
+
+  if (d->q) {
+    mp *r = MP_NEW;
+    mp_div(0, &r, m, d->q);
+    m = mp_sub(m, m, r);
+    mp_drop(r);
+  }
+  m->v[0] |= d->or;
+  ev->m = m;
+
+  /* --- Do the trial division --- */
+
+  rc = pfilt_smallfactor(m);
+  d->count++;
+
+  /* --- Return the result --- */
+
+  return (rc);
+}
+
+/* --- @dsa_step@ --- */
+
+int dsa_step(int rq, pgen_event *ev, void *p)
+{
+  dsa_stepctx *d = p;
+
+  switch (rq) {
+    case PGEN_BEGIN:
+    case PGEN_TRY:
+      return (next(ev, d));
+    case PGEN_DONE:
+      return (PGEN_DONE);
+  }
+  return (PGEN_ABORT);
+}
+
+/*----- Glue code ---------------------------------------------------------*/
+
+/* --- @dsa_gen@ --- *
+ *
+ * Arguments:  @dsa_param *dp@ = where to store parameters
+ *             @unsigned ql@ = length of @q@ in bits
+ *             @unsigned pl@ = length of @p@ in bits
+ *             @unsigned steps@ = number of steps to find @q@
+ *             @const void *k@ = pointer to key material
+ *             @size_t sz@ = size of key material
+ *             @dsa_seed *ds@ = optional pointer for output seed information
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for event handler
+ *
+ * Returns:    @PGEN_DONE@ if everything worked ok; @PGEN_ABORT@ otherwise.
+ *
+ * Use:                Generates the DSA shared parameters from a given seed value.
+ *
+ *             The parameters are a prime %$q$%, relatively small, and a
+ *             large prime %$p = kq + 1$% for some %$k$%, together with a
+ *             generator %$g$% of the cyclic subgroup of order %$q$%.  These
+ *             are actually the same as the Diffie-Hellman parameter set,
+ *             but the generation algorithm is different.
+ *
+ *             The algorithm used is a compatible extension of the method
+ *             described in the DSA standard, FIPS 186.  The standard
+ *             requires that %$q$% be 160 bits in size (i.e., @ql == 160@)
+ *             and that the length of %$p$% be %$L = 512 + 64l$% for some
+ *             %$l$%.  Neither limitation applies to this implementation.
+ */
+
+int dsa_gen(dsa_param *dp, unsigned ql, unsigned pl, unsigned steps,
+           const void *k, size_t sz, dsa_seed *ds,
+           pgen_proc *event, void *ectx)
+{
+  dsa_stepctx s;
+  prim_ctx p;
+  int i;
+  rabin r;
+  mp *qc;
+
+  /* --- Initialize the stepping context --- */
+
+  s.r = dsarand_create(k, sz);
+
+  /* --- Find @q@ --- */
+
+  s.q = 0;
+  s.r->ops->misc(s.r, DSARAND_PASSES, 2);
+  s.bits = ql;
+  s.count = 0;
+  s.or = 1;
+  if (!ds)
+    s.seedbuf = 0;
+  else {
+    ds->sz = sz;
+    ds->p = s.seedbuf = xmalloc(sz);
+  }
+  if ((dp->q = pgen("q", MP_NEW, MP_NEW, event, ectx, steps, dsa_step, &s,
+                   rabin_iters(ql), pgen_test, &r)) == 0)
+    goto fail_q;
+
+  /* --- Find @p@ --- */
+
+  s.count = ~0;
+  s.q = mp_lsl(MP_NEW, dp->q, 1);
+  s.r->ops->misc(s.r, DSARAND_PASSES, 1);
+  s.bits = pl;
+  s.seedbuf = 0;
+  if ((dp->p = pgen("p", MP_NEW, MP_NEW, event, ectx, 4096, dsa_step, &s,
+                   rabin_iters(pl), pgen_test, &r)) == 0)
+    goto fail_p;
+  mp_drop(s.q);
+  if (ds)
+    ds->count = s.count;
+
+  /* --- Find @g@ --- *
+   *
+   * The division returns remainder 1.  This doesn't matter.
+   */
+
+  mpmont_create(&p.mm, dp->p);
+  qc = MP_NEW; mp_div(&qc, 0, dp->p, dp->q);
+  i = 0;
+  p.exp = qc;
+  p.n = 0;
+  if ((dp->g = pgen("g", MP_NEW, MP_NEW, event, ectx, 0, prim_step, &i,
+                   1, prim_test, &p)) == 0)
+    goto fail_g;
+
+  /* --- Done --- */
+
+  mp_drop(qc);
+  mpmont_destroy(&p.mm);
+  s.r->ops->destroy(s.r);
+  return (PGEN_DONE);
+
+  /* --- Tidy up when things go wrong --- */
+
+fail_g:
+  mp_drop(qc);
+  mpmont_destroy(&p.mm);
+fail_p:
+  mp_drop(dp->q);
+  mp_drop(s.q);
+fail_q:
+  s.r->ops->destroy(s.r);
+  if (ds)
+    xfree(ds->p);
+  return (PGEN_ABORT);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static int verify(dstr *v)
+{
+  mp *q = *(mp **)v[4].buf;
+  mp *p = *(mp **)v[5].buf;
+  mp *g = *(mp **)v[6].buf;
+  dsa_param dp;
+  dsa_seed ds;
+  unsigned long l = *(unsigned long *)v[1].buf;
+  unsigned long n = *(unsigned long *)v[3].buf;
+  int ok = 1;
+  int rc;
+  keycheck kc;
+  keycheck_reportctx kcr;
+
+  rc = dsa_gen(&dp, 160, l, 16, v[0].buf, v[0].len, &ds, pgen_evspin, 0);
+  if (rc || ds.count != n || ds.sz != v[2].len ||
+      memcmp(ds.p, v[2].buf, v[2].len) != 0 ||
+      !MP_EQ(q, dp.q) || !MP_EQ(p, dp.p) || !MP_EQ(g, dp.g)) {
+    fputs("\n*** gen failed", stderr);
+    fputs("\nseed_in = ", stderr); type_hex.dump(&v[0], stderr);
+    fprintf(stderr, "\nl = %lu", l);
+    fputs("\nseed_out = ", stderr); type_hex.dump(&v[2], stderr);
+    fprintf(stderr, "\ncount = %lu", n);
+    fputs("\n  q = ", stderr); mp_writefile(q, stderr, 16);
+    fputs("\n  p = ", stderr); mp_writefile(p, stderr, 16);
+    fputs("\n  g = ", stderr); mp_writefile(g, stderr, 16);
+    if (!rc) {
+      dstr d;
+      d.buf = ds.p; d.len = ds.sz;
+      fputs("\nds.seed = ", stderr); type_hex.dump(&d, stderr);
+      fprintf(stderr, "\nds.count = %u", ds.count);
+      fputs("\ndp.q = ", stderr); mp_writefile(dp.q, stderr, 16);
+      fputs("\ndp.p = ", stderr); mp_writefile(dp.p, stderr, 16);
+      fputs("\ndp.g = ", stderr); mp_writefile(dp.g, stderr, 16);
+    }
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  kcr.fp = stderr;
+  kcr.sev = KCSEV_ERR;
+  keycheck_init(&kc, keycheck_stdreport, &kcr);
+  if (!rc)
+    dsa_checkparam(&kc, &dp, &ds);
+  if (!keycheck_allclear(&kc, KCSEV_ERR)) {
+    fputs("\n*** gen failed check", stderr);
+    fputs("\nseed_in = ", stderr); type_hex.dump(&v[0], stderr);
+    fprintf(stderr, "\nl = %lu", l);
+    fputs("\nseed_out = ", stderr); type_hex.dump(&v[2], stderr);
+    fprintf(stderr, "\ncount = %lu", n);
+    fputs("\n  q = ", stderr); mp_writefile(q, stderr, 16);
+    fputs("\n  p = ", stderr); mp_writefile(p, stderr, 16);
+    fputs("\n  g = ", stderr); mp_writefile(g, stderr, 16);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(q); mp_drop(p); mp_drop(g);
+  if (!rc) {
+    mp_drop(dp.q); mp_drop(dp.p); mp_drop(dp.g); xfree(ds.p);
+  }
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "gen", verify,
+    { &type_hex, &type_ulong, &type_hex, &type_ulong,
+      &type_mp, &type_mp, &type_mp, 0 }         },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/dsa");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
similarity index 100%
rename from dsa-misc.c
rename to pub/dsa-misc.c
diff --git a/pub/dsa-sign.c b/pub/dsa-sign.c
new file mode 100644 (file)
index 0000000..23bbf7f
--- /dev/null
@@ -0,0 +1,198 @@
+/* -*-c-*-
+ *
+ * DSA signing operation
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "dsa.h"
+#include "mp.h"
+#include "mpbarrett.h"
+#include "mpmont.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @dsa_mksig@ --- *
+ *
+ * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
+ *             @mp *a@ = secret signing key
+ *             @mp *m@ = message to be signed
+ *             @mp *k@ = random data
+ *             @mp **rr, **ss@ = where to put output parameters
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes a DSA signature of a message.
+ */
+
+void dsa_mksig(const dsa_param *dp, mp *a, mp *m, mp *k, mp **rr, mp **ss)
+{
+  mpmont pm;
+  mpbarrett qb;
+  mp *k1, *r;
+  mp *ar;
+
+  /* --- Compute %$r = (g^k \bmod p) \bmod q$% --- */
+
+  mpmont_create(&pm, dp->p);
+  r = mpmont_exp(&pm, MP_NEW, dp->g, k);
+  mpmont_destroy(&pm);
+  mp_div(0, &r, r, dp->q);
+
+  /* --- Compute %$k^{-1} \bmod q$% --- */
+
+  k1 = mp_modinv(MP_NEW, k, dp->q);
+
+  /* --- Now for %$k^{-1}(m + ar)$% --- */
+
+  mpbarrett_create(&qb, dp->q);
+  ar = mp_mul(MP_NEW, a, r);
+  ar = mp_add(ar, ar, m);
+  ar = mpbarrett_reduce(&qb, ar, ar);
+  ar = mp_mul(ar, ar, k1);
+  ar = mpbarrett_reduce(&qb, ar, ar);
+  mpbarrett_destroy(&qb);
+  MP_DROP(k1);
+  if (*rr) MP_DROP(*rr);
+  if (*ss) MP_DROP(*ss);
+  *rr = r;
+  *ss = ar;
+}
+
+/* --- @dsa_sign@ --- *
+ *
+ * Arguments:  @dsa_param *dp@ = pointer to DSA parameters
+ *             @mp *a@ = pointer to secret signing key
+ *             @const void *m@ = pointer to message
+ *             @size_t msz@ = size of the message
+ *             @const void *k@ = secret random data for securing signature
+ *             @size_t ksz@ = size of secret data
+ *             @void *r@ = pointer to output space for @r@
+ *             @size_t rsz@ = size of output space for @r@
+ *             @void *s@ = pointer to output space for @s@
+ *             @size_t ssz@ = size of output space for @s@
+ *
+ * Returns:    ---
+ *
+ * Use:                Signs a message, storing the results in a big-endian binary
+ *             form.
+ */
+
+void dsa_sign(dsa_param *dp, mp *a,
+             const void *m, size_t msz, const void *k, size_t ksz,
+             void *r, size_t rsz, void *s, size_t ssz)
+{
+  mp *mm = dsa_h2n(MP_NEW, dp->q, m, msz);
+  mp *km = mp_loadb(MP_NEW, k, ksz);
+  mp *rm = MP_NEW, *sm = MP_NEW;
+  dsa_mksig(dp, a, mm, km, &rm, &sm);
+  mp_storeb(rm, r, rsz);
+  mp_storeb(sm, s, ssz);
+  mp_drop(mm); mp_drop(km);
+  mp_drop(rm); mp_drop(sm);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+#include "sha.h"
+
+static int verify(dstr *v)
+{
+  dsa_param dp;
+  mp *x;
+  sha_ctx c;
+  octet hash[SHA_HASHSZ];
+  dsa_sig s;
+  int ok = 1;
+
+  dp.q = *(mp **)v[0].buf;
+  dp.p = *(mp **)v[1].buf;
+  dp.g = *(mp **)v[2].buf;
+  x = *(mp **)v[3].buf;
+
+  sha_init(&c);
+  sha_hash(&c, v[4].buf, v[4].len);
+  sha_done(&c, hash);
+
+  dsa_sign(&dp, x, hash, sizeof(hash), v[5].buf, v[5].len,
+          s.r, sizeof(s.r), s.s, sizeof(s.s));
+
+  if (v[6].len != sizeof(s.r) || v[7].len != sizeof(s.s) ||
+      memcmp(s.r, v[6].buf, sizeof(s.r)) != 0 ||
+      memcmp(s.s, v[7].buf, sizeof(s.s)) != 0) {
+    fputs("\n*** signature failed", stderr);
+    fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16);
+    fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16);
+    fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16);
+    fputs("\nx = ", stderr); mp_writefile(x, stderr, 16);
+    fprintf(stderr, "\nmessage = `%s'", v[4].buf);
+    fputs("\nk = ", stderr); type_hex.dump(&v[5], stderr);
+    fputs("\nR = ", stderr); type_hex.dump(&v[6], stderr);
+    fputs("\nS = ", stderr); type_hex.dump(&v[7], stderr);
+
+    {
+      mp *m = MP_NEW;
+      m = mp_loadb(m, hash, sizeof(hash));
+      fputs("\nm = ", stderr); mp_writefile(m, stderr, 16);
+      m = mp_loadb(m, s.r, sizeof(s.r));
+      fputs("\nr = ", stderr); mp_writefile(m, stderr, 16);
+      m = mp_loadb(m, s.s, sizeof(s.s));
+      fputs("\ns = ", stderr); mp_writefile(m, stderr, 16);
+      mp_drop(m);
+    }
+
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(dp.p);
+  mp_drop(dp.q);
+  mp_drop(dp.g);
+  mp_drop(x);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "sign", verify,
+    { &type_mp, &type_mp, &type_mp, &type_mp,
+      &type_string, &type_hex, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/dsa");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dsa-verify.c b/pub/dsa-verify.c
new file mode 100644 (file)
index 0000000..5a6bd4e
--- /dev/null
@@ -0,0 +1,205 @@
+/* -*-c-*-
+ *
+ * DSA signature verification
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "dsa.h"
+#include "mp.h"
+#include "mpmont.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @dsa_vrfy@ --- *
+ *
+ * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
+ *             @mp *y@ = public verification key
+ *             @mp *m@ = message which was signed
+ *             @mp *r, *s@ = the signature
+ *
+ * Returns:    Zero if the signature is a forgery, nonzero if it's valid.
+ *
+ * Use:                Verifies a DSA digital signature.
+ */
+
+int dsa_vrfy(const dsa_param *dp, mp *y, mp *m, mp *r, mp *s)
+{
+  mpmont pm, qm;
+  mp *w;
+  mp_expfactor f[2];
+  int ok;
+
+  /* --- Ensure that all of the signature bits are in range --- */
+
+  if ((r->f | s->f) & MP_NEG)
+    return (0);
+  if (MP_CMP(r, >=, dp->q) || MP_CMP(s, >=, dp->q))
+    return (0);
+
+  /* --- Set up Montgomery contexts --- */
+
+  mpmont_create(&pm, dp->p);
+  mpmont_create(&qm, dp->q);
+
+  /* --- Compute %$w = s^{-1} \bmod q$% --- */
+
+  {
+    mp *z = mp_modinv(MP_NEW, s, dp->q);
+    w = mpmont_mul(&qm, MP_NEW, z, qm.r2);
+    mp_drop(z);
+  }
+
+  /* --- Compute %$wr$% and %$wm$% --- */
+
+  f[0].exp = mpmont_mul(&qm, MP_NEW, w, m);
+  f[1].exp = mpmont_mul(&qm, MP_NEW, w, r);
+  mp_drop(w);
+  mpmont_destroy(&qm);
+
+  /* --- Do the exponentiation and take residue mod @q@ --- */
+
+  f[0].base = dp->g;
+  f[1].base = y;
+  w = mpmont_mexp(&pm, MP_NEW, f, 2);
+  mp_div(0, &w, w, dp->q);
+  ok = MP_EQ(w, r);
+
+  /* --- Tidy up --- */
+
+  mp_drop(w);
+  mp_drop(f[0].exp);
+  mp_drop(f[1].exp);
+  mpmont_destroy(&pm);
+  return (ok);
+}
+
+/* --- @dsa_verify@ --- *
+ *
+ * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
+ *             @mp *y@ = public verification key
+ *             @const void *m@ = pointer to message block
+ *             @size_t msz@ = size of message block
+ *             @const void *r@ = pointer to @r@ signature half
+ *             @size_t rsz@ = size of @r@
+ *             @const void *s@ = pointer to @s@ signature half
+ *             @size_t ssz@ = size of @s@
+ *
+ * Returns:    Zero if the signature is a forgery, nonzero if it's valid.
+ *
+ * Use:                Verifies a DSA digital signature.
+ */
+
+int dsa_verify(const dsa_param *dp, mp *y,
+              const void *m, size_t msz,
+              const void *r, size_t rsz,
+              const void *s, size_t ssz)
+{
+  mp *mm = dsa_h2n(MP_NEW, dp->q, m, msz);
+  mp *rm = mp_loadb(MP_NEW, r, rsz);
+  mp *sm = mp_loadb(MP_NEW, s, ssz);
+  int ok = dsa_vrfy(dp, y, mm, rm, sm);
+  mp_drop(mm);
+  mp_drop(rm);
+  mp_drop(sm);
+  return (ok);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+#include "sha.h"
+
+static int verify(int good, dstr *v)
+{
+  dsa_param dp;
+  mp *y;
+  sha_ctx c;
+  octet hash[SHA_HASHSZ];
+  int ok = 1;
+  int rc;
+
+  dp.q = *(mp **)v[0].buf;
+  dp.p = *(mp **)v[1].buf;
+  dp.g = *(mp **)v[2].buf;
+  y = *(mp **)v[3].buf;
+
+  sha_init(&c);
+  sha_hash(&c, v[4].buf, v[4].len);
+  sha_done(&c, hash);
+
+  rc = dsa_verify(&dp, y, hash, sizeof(hash),
+                 v[5].buf, v[5].len, v[6].buf, v[6].len);
+
+  if (!rc != !good) {
+    if (good)
+      fputs("\n*** verification failed", stderr);
+    else
+      fputs("\n*** verification succeeded", stderr);
+    fputs("\nq = ", stderr); mp_writefile(dp.q, stderr, 16);
+    fputs("\np = ", stderr); mp_writefile(dp.p, stderr, 16);
+    fputs("\ng = ", stderr); mp_writefile(dp.g, stderr, 16);
+    fputs("\ny = ", stderr); mp_writefile(y, stderr, 16);
+    fprintf(stderr, "\nmessage = `%s'", v[4].buf);
+    fputs("\nr = ", stderr); type_hex.dump(&v[5], stderr);
+    fputs("\ns = ", stderr); type_hex.dump(&v[6], stderr);
+    fputc('\n', stderr);
+    ok = 0;
+  }
+
+  mp_drop(dp.p);
+  mp_drop(dp.q);
+  mp_drop(dp.g);
+  mp_drop(y);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int vgood(dstr *v) { return verify(1, v); }
+static int vbad(dstr *v) { return verify(0, v); }
+
+static test_chunk tests[] = {
+  { "verify-good", vgood,
+    { &type_mp, &type_mp, &type_mp, &type_mp,
+      &type_string, &type_hex, &type_hex, 0 } },
+  { "verify-bad", vbad,
+    { &type_mp, &type_mp, &type_mp, &type_mp,
+      &type_string, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/t/dsa");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/dsa.h b/pub/dsa.h
new file mode 100644 (file)
index 0000000..3b93d93
--- /dev/null
+++ b/pub/dsa.h
@@ -0,0 +1,277 @@
+/* -*-c-*-
+ *
+ * Digital Signature Algorithm
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_DSA_H
+#define CATACOMB_DSA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Notes on the Digital Signature Algorithm --------------------------*
+ *
+ * The Digital Signature Algorithm was designed by the NSA for US Government
+ * use.  It's defined in FIPS 186-1.  Whether it's covered by patents is
+ * under dispute, although it looks relatively clear.  It produces compact
+ * signatures, and is relatively easy to compute.  It seems strong, if
+ * appropriate parameters are chosen.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_DH_H
+#  include "dh.h"
+#endif
+
+#ifndef CATACOMB_KEY_H
+#  include "key.h"
+#endif
+
+#ifndef CATACOMB_KEYCHECK_H
+#  include "keycheck.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_PGEN_H
+#  include "pgen.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- The parameters and keys are the same as for Diffie-Hellman --- */
+
+typedef dh_param dsa_param;
+typedef dh_pub dsa_pub;
+typedef dh_priv dsa_priv;
+
+/* --- DSA key seed structure --- */
+
+typedef struct dsa_seed {
+  void *p;                             /* Pointer to seed material */
+  size_t sz;                           /* Size of seed material */
+  unsigned count;                      /* Iterations to find @p@ */
+} dsa_seed;
+
+/* --- DSA signature structure --- *
+ *
+ * This is the recommended structure for a DSA signature.  The actual signing
+ * function can cope with arbitrary-sized objects given appropriate
+ * parameters, however.
+ */
+
+#define DSA_SIGLEN 20
+
+typedef struct dsa_sig {
+  octet r[DSA_SIGLEN];                 /* 160-bit @r@ value */
+  octet s[DSA_SIGLEN];                 /* 160-bit @s@ value */
+} dsa_sig;
+
+/*----- Key fetching ------------------------------------------------------*/
+
+#define dsa_paramfetch dh_paramfetch
+#define dsa_pubfetch dh_pubfetch
+#define dsa_privfetch dh_privfetch
+
+#define DSA_PARAMFETCHSZ DH_PARAMFETCHSZ
+#define DSA_PUBFETCHSZ DH_PUBFETCHSZ
+#define DSA_PRIVFETCHSZ DH_PRIVFETCHSZ
+
+#define dsa_paramfree dh_paramfree
+#define dsa_pubfree dh_pubfree
+#define dsa_privfree dh_privfree
+
+/*----- DSA stepper -------------------------------------------------------*/
+
+typedef struct dsa_stepctx {
+
+  /* --- To be initialized by the client --- */
+
+  grand *r;                            /* Random number generator */
+  mp *q;                               /* Force @p@ to be a multiple */
+  size_t bits;                         /* Number of bits in the result */
+  unsigned or;                         /* OR mask for low order bits */
+  unsigned count;                      /* Counts the number of steps made */
+  void *seedbuf;                       /* Pointer to seed buffer */
+} dsa_stepctx;
+
+/* --- @dsa_step@ --- *
+ *
+ * The stepper chooses random integers, ensures that they are a multiple of
+ * @q@ (if specified), sets the low-order bits, and then tests for
+ * divisibility by small primes.
+ */
+
+extern pgen_proc dsa_step;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @dsa_gen@ --- *
+ *
+ * Arguments:  @dsa_param *dp@ = where to store parameters
+ *             @unsigned ql@ = length of @q@ in bits
+ *             @unsigned pl@ = length of @p@ in bits
+ *             @unsigned steps@ = number of steps to find @q@
+ *             @const void *k@ = pointer to key material
+ *             @size_t sz@ = size of key material
+ *             @dsa_seed *sd@ = optional pointer for output seed information
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for event handler
+ *
+ * Returns:    @PGEN_DONE@ if everything worked ok; @PGEN_ABORT@ otherwise.
+ *
+ * Use:                Generates the DSA shared parameters from a given seed value.
+ *             This can take quite a long time.
+ *
+ *             The algorithm used is a compatible extension of the method
+ *             described in the DSA standard, FIPS 186.  The standard
+ *             requires that %$q$% be 160 bits in size (i.e., @ql == 160@)
+ *             and that the length of %$p$% be %$L = 512 + 64l$% for some
+ *             %$l$%.  Neither limitation applies to this implementation.
+ */
+
+extern int dsa_gen(dsa_param */*dp*/, unsigned /*ql*/, unsigned /*pl*/,
+                  unsigned /*steps*/, const void */*k*/, size_t /*sz*/,
+                  dsa_seed */*sd*/, pgen_proc */*event*/, void */*ectx*/);
+
+/* --- @dsa_checkparam@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = keycheck state
+ *             @const dsa_param *dp@ = pointer to the parameter set
+ *             @const dsa_seed *ds@ = pointer to seed information
+ *
+ * Returns:    Zero if all OK, or return status from function.
+ *
+ * Use:                Checks a set of DSA parameters for consistency and security.
+ */
+
+extern int dsa_checkparam(keycheck */*kc*/, const dsa_param */*dp*/,
+                         const dsa_seed */*ds*/);
+
+/* --- @dsa_h2n@ --- *
+ *
+ * Arguments:  @mp *d@ = destination integer
+ *             @mp *r@ = order of the DSA group
+ *             @const void *h@ = pointer to message hash
+ *             @size_t hsz@ = size (in bytes) of the hash output
+ *
+ * Returns:    Resulting integer.
+ *
+ * Use:                Converts a hash to an integer in the demented way necessary
+ *             for DSA/ECDSA.  This is, of course, completely insane, but
+ *             there you go.
+ */
+
+extern mp *dsa_h2n(mp */*d*/, mp */*r*/, const void */*h*/, size_t /*hsz*/);
+
+/* --- @dsa_mksig@ --- *
+ *
+ * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
+ *             @mp *a@ = secret signing key
+ *             @mp *m@ = message to be signed
+ *             @mp *k@ = random data
+ *             @mp **rr, **ss@ = where to put output parameters
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes a DSA signature of a message.
+ */
+
+extern void dsa_mksig(const dsa_param */*dp*/, mp */*a*/,
+                     mp */*m*/, mp */*k*/,
+                     mp **/*rr*/, mp **/*ss*/);
+
+/* --- @dsa_sign@ --- *
+ *
+ * Arguments:  @dsa_param *dp@ = pointer to DSA parameters
+ *             @mp *a@ = pointer to secret signing key
+ *             @const void *m@ = pointer to message
+ *             @size_t msz@ = size of the message
+ *             @const void *k@ = secret random data for securing signature
+ *             @size_t ksz@ = size of secret data
+ *             @void *r@ = pointer to output space for @r@
+ *             @size_t rsz@ = size of output space for @r@
+ *             @void *s@ = pointer to output space for @s@
+ *             @size_t ssz@ = size of output space for @s@
+ *
+ * Returns:    ---
+ *
+ * Use:                Signs a message, storing the results in a big-endian binary
+ *             form.
+ */
+
+extern void dsa_sign(dsa_param */*dp*/, mp */*a*/,
+                    const void */*m*/, size_t /*msz*/,
+                    const void */*k*/, size_t /*ksz*/,
+                    void */*r*/, size_t /*rsz*/,
+                    void */*s*/, size_t /*ssz*/);
+
+/* --- @dsa_vrfy@ --- *
+ *
+ * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
+ *             @mp *y@ = public verification key
+ *             @mp *m@ = message which was signed
+ *             @mp *r, *s@ = the signature
+ *
+ * Returns:    Zero if the signature is a forgery, nonzero if it's valid.
+ *
+ * Use:                Verifies a DSA digital signature.
+ */
+
+extern int dsa_vrfy(const dsa_param */*dp*/, mp */*y*/,
+                   mp */*m*/, mp */*r*/, mp */*s*/);
+
+/* --- @dsa_verify@ --- *
+ *
+ * Arguments:  @const dsa_param *dp@ = pointer to DSA parameters
+ *             @mp *y@ = public verification key
+ *             @const void *m@ = pointer to message block
+ *             @size_t msz@ = size of message block
+ *             @const void *r@ = pointer to @r@ signature half
+ *             @size_t rsz@ = size of @r@
+ *             @const void *s@ = pointer to @s@ signature half
+ *             @size_t ssz@ = size of @s@
+ *
+ * Returns:    Zero if the signature is a forgery, nonzero if it's valid.
+ *
+ * Use:                Verifies a DSA digital signature.
+ */
+
+extern int dsa_verify(const dsa_param */*dp*/, mp */*y*/,
+                     const void */*m*/, size_t /*msz*/,
+                     const void */*r*/, size_t /*rsz*/,
+                     const void */*s*/, size_t /*ssz*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/pub/gdsa.c b/pub/gdsa.c
new file mode 100644 (file)
index 0000000..6fea5f4
--- /dev/null
@@ -0,0 +1,255 @@
+/* -*-c-*-
+ *
+ * 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "dsa.h"
+#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(const 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 = dsa_h2n(MP_NEW, g->r, 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_ZEROP(k)) goto new_k;
+  G_EXP(g, z, g->g, k);
+  sr = G_TOINT(g, sr, z); assert(sr);
+  if (MP_ZEROP(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);
+  k = mp_modinv(k, k, g->r);
+  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, *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); h = mp_modinv(MP_NEW, s->s, g->r);
+  e[0].base = g->g; e[1].base = c->p;
+  t = dsa_h2n(MP_NEW, g->r, 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 "/t/gdsa");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/gdsa.h b/pub/gdsa.h
new file mode 100644 (file)
index 0000000..df41632
--- /dev/null
@@ -0,0 +1,130 @@
+/* -*-c-*-
+ *
+ * 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.
+ */
+
+#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(const 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
diff --git a/pub/gkcdsa.c b/pub/gkcdsa.c
new file mode 100644 (file)
index 0000000..eb5a3de
--- /dev/null
@@ -0,0 +1,309 @@
+/* -*-c-*-
+ *
+ * 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "gkcdsa.h"
+#include "group.h"
+#include "ghash.h"
+#include "mpbarrett.h"
+#include "mprand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gkcdsa_beginhash@ --- *
+ *
+ * Arguments:  @const gkcdsa *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(const 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_ZEROP(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_modinv(MP_NEW, c.u, c.g->r);
+  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 "/t/gkcdsa");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/gkcdsa.h b/pub/gkcdsa.h
new file mode 100644 (file)
index 0000000..d8e44c3
--- /dev/null
@@ -0,0 +1,130 @@
+/* -*-c-*-
+ *
+ * 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.
+ */
+
+#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 ------------------------------------------------*/
+
+/* --- @gkcdsa_beginhash@ --- *
+ *
+ * Arguments:  @const gkcdsa *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(const 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/pub/keycheck-mp.c b/pub/keycheck-mp.c
new file mode 100644 (file)
index 0000000..c5779a4
--- /dev/null
@@ -0,0 +1,86 @@
+/* -*-c-*-
+ *
+ * Key consistency checking tools for large integers
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "fibrand.h"
+#include "grand.h"
+#include "keycheck.h"
+#include "mp.h"
+#include "mprand.h"
+#include "pfilt.h"
+#include "pgen.h"
+#include "rabin.h"
+#include "rand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @keycheck_prime@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = keycheck state
+ *             @unsigned sev@ = severity if not prime
+ *             @mp *m@ = a number to check for primality
+ *             @const char *name@ = name of this number
+ *
+ * Returns:    Zero if OK, or return status from function.
+ *
+ * Use:                Checks that a number is prime.
+ */
+
+int keycheck_prime(keycheck *kc, unsigned sev, mp *m, const char *name)
+{
+  int rc;
+
+  rc = pfilt_smallfactor(m);
+  if (rc == PGEN_TRY) {
+    rabin rn;
+    grand *r = fibrand_create(0);
+    unsigned n;
+    mp *x = MP_NEW;
+
+    r->ops->misc(r, GRAND_SEEDRAND, &rand_global);
+    n = rabin_iters(mp_bits(m));
+    rabin_create(&rn, m);
+    do {
+      x = mprand_range(x, m, r, 0);
+      rc = rabin_test(&rn, x);
+      n--;
+    } while (n && rc == PGEN_PASS);
+    rabin_destroy(&rn);
+    mp_drop(x);
+    r->ops->destroy(r);
+  }
+  if (rc != PGEN_FAIL)
+    rc = 0;
+  else
+    rc = keycheck_report(kc, sev, "%s not prime", name);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/keycheck-report.c b/pub/keycheck-report.c
new file mode 100644 (file)
index 0000000..4270cfc
--- /dev/null
@@ -0,0 +1,59 @@
+/* -*-c-*-
+ *
+ * A standard reporter function
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+
+#include "keycheck.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @keycheck_stdreport@ --- *
+ *
+ * Arguments:  @unsigned sev@ = problem severity
+ *             @const char *msg@ = message to report
+ *             @void *p@ = an uninteresting pointer
+ *
+ * Returns:    Zero.
+ *
+ * Use:                Reports a message to stderr.
+ */
+
+int keycheck_stdreport(unsigned sev, const char *msg, void *p)
+{
+  static const char *const sevtab[] = {
+    "informational", "warning", "error"
+  };
+  keycheck_reportctx *r = p;
+  if (r && sev < r->sev)
+    return (0);
+  fprintf(r ? r->fp : stderr, "keycheck: %s: %s\n", sevtab[sev], msg);
+  return (0);
+}
+
+/*----- that's all, folks -------------------------------------------------*/
diff --git a/pub/keycheck.c b/pub/keycheck.c
new file mode 100644 (file)
index 0000000..2624c0b
--- /dev/null
@@ -0,0 +1,108 @@
+/* -*-c-*-
+ *
+ * Framework for checking consistency of keys
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+
+#include <mLib/dstr.h>
+
+#include "keycheck.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @keycheck_report@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = keycheck state
+ *             @unsigned sev@ = severity of this report
+ *             @const char *msg@ = message to send along
+ *             @...@ = things to fill the message in with
+ *
+ * Returns:    Zero to continue, or nonzero to stop and give up.
+ *
+ * Use:                Reports a message to the user function.
+ */
+
+int keycheck_report(keycheck *kc, unsigned sev, const char *msg, ...)
+{
+  int rc;
+  va_list ap;
+  dstr d = DSTR_INIT;
+
+  kc->sev[sev]++;
+  va_start(ap, msg);
+  dstr_vputf(&d, msg, &ap);
+  va_end(ap);
+  rc = kc->func ? kc->func(sev, d.buf, kc->p) : 0;
+  dstr_destroy(&d);
+  return (rc);
+}
+
+/* --- @keycheck_init@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = pointer to block to initialize
+ *             @int (*func)(unsigned sev, const char *msg, void *p)@ =
+ *                     handler function for problems
+ *             @void *p@ = pointer to give to handler
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a key checking context.
+ */
+
+void keycheck_init(keycheck *kc,
+                  int (*func)(unsigned /*sev*/,
+                              const char */*msg*/,
+                              void */*p*/),
+                  void *p)
+{
+  unsigned i;
+  kc->func = func;
+  kc->p = p;
+  for (i = 0; i < KCSEV_MAX; i++)
+    kc->sev[i] = 0;
+}
+
+/* --- @keycheck_allclear@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = pointer to keycheck context
+ *             @unsigned sev@ = minimum severity to care about
+ *
+ * Returns:    Nonzero if no problems of @sev@ or above were noticed.
+ */
+
+int keycheck_allclear(keycheck *kc, unsigned sev)
+{
+  while (sev < KCSEV_MAX) {
+    if (kc->sev[sev])
+      return (0);
+    sev++;
+  }
+  return (1);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/keycheck.h b/pub/keycheck.h
new file mode 100644 (file)
index 0000000..f6b3388
--- /dev/null
@@ -0,0 +1,146 @@
+/* -*-c-*-
+ *
+ * Framework for checking consistency of keys
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_KEYCHECK_H
+#define CATACOMB_KEYCHECK_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+enum {
+  KCSEV_ALL,
+  KCSEV_INFO = KCSEV_ALL,
+  KCSEV_WARN,
+  KCSEV_ERR,
+  KCSEV_MAX
+};
+
+typedef struct keycheck {
+  unsigned sev[KCSEV_MAX];
+  int (*func)(unsigned /*sev*/, const char */*msg*/, void */*p*/);
+  void *p;
+} keycheck;
+
+typedef struct keycheck_reportctx {
+  FILE *fp;
+  unsigned sev;
+} keycheck_reportctx;
+
+/*----- Generic functions -------------------------------------------------*/
+
+/* --- @keycheck_report@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = keycheck state
+ *             @unsigned sev@ = severity of this report
+ *             @const char *msg@ = message to send along
+ *             @...@ = things to fill the message in with
+ *
+ * Returns:    Zero to continue, or nonzero to stop and give up.
+ *
+ * Use:                Reports a message to the user function.
+ */
+
+extern int keycheck_report(keycheck */*kc*/, unsigned /*sev*/,
+                          const char */*msg*/, ...);
+
+/* --- @keycheck_init@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = pointer to block to initialize
+ *             @int (*func)(unsigned sev, const char *msg, void *p)@ =
+ *                     handler function for problems
+ *             @void *p@ = pointer to give to handler
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a key checking context.
+ */
+
+extern void keycheck_init(keycheck */*kc*/,
+                         int (*/*func*/)(unsigned /*sev*/,
+                                         const char */*msg*/,
+                                         void */*p*/),
+                         void */*p*/);
+
+/* --- @keycheck_allclear@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = pointer to keycheck context
+ *             @unsigned sev@ = minimum severity to care about
+ *
+ * Returns:    Nonzero if no problems of @sev@ or above were noticed.
+ */
+
+extern int keycheck_allclear(keycheck */*kc*/, unsigned /*sev*/);
+
+/*----- A standard report function ----------------------------------------*/
+
+/* --- @keycheck_stdreport@ --- *
+ *
+ * Arguments:  @unsigned sev@ = problem severity
+ *             @const char *msg@ = message to report
+ *             @void *p@ = pointer to a @keycheck_reportctx@ structure
+ *
+ * Returns:    Zero.
+ *
+ * Use:                Reports a message to stderr.
+ */
+
+extern int keycheck_stdreport(unsigned /*sev*/,
+                             const char */*msg*/, void */*p*/);
+
+/*----- Special support functions for large integers ----------------------*/
+
+/* --- @keycheck_prime@ --- *
+ *
+ * Arguments:  @keycheck *kc@ = keycheck state
+ *             @unsigned sev@ = severity if not prime
+ *             @mp *m@ = a number to check for primality
+ *             @const char *name@ = name of this number
+ *
+ * Returns:    Zero if OK, or return status from function.
+ *
+ * Use:                Checks that a number is prime.
+ */
+
+extern int keycheck_prime(keycheck */*kc*/, unsigned /*sev*/,
+                         mp */*m*/, const char */*name*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/pub/oaep.c b/pub/oaep.c
new file mode 100644 (file)
index 0000000..7c83416
--- /dev/null
@@ -0,0 +1,182 @@
+/* -*-c-*-
+ *
+ * Optimal asymmetric encryption packing
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+
+#include "ct.h"
+#include "gcipher.h"
+#include "ghash.h"
+#include "grand.h"
+#include "rsa.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @oaep_encode@ --- *
+ *
+ * Arguments:  @mp *d@ = where to put the answer
+ *             @const void *m@ = pointer to message data
+ *             @size_t msz@ = size of message data
+ *             @octet *b@ = spare buffer
+ *             @size_t sz@ = size of the buffer (big enough)
+ *             @unsigned long nbits@ = length of bits of @n@
+ *             @void *p@ = pointer to OAEP parameter block
+ *
+ * Returns:    The encoded plaintext, or null on failure.
+ *
+ * Use:                Implements the operation @EME-OAEP-ENCODE@, as defined in
+ *             PKCS#1 v. 2.0 (RFC2437).
+ */
+
+mp *oaep_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
+               unsigned long nbits, void *p)
+{
+  oaep *o = p;
+  size_t hsz = o->ch->hashsz;
+  ghash *h;
+  octet *q, *mq;
+  octet *pp;
+  gcipher *c;
+  size_t n;
+
+  /* --- Ensure that everything is sensibly sized --- */
+
+  if (2 * hsz + 2 + msz > sz)
+    return (0);
+
+  /* --- Make the `seed' value --- */
+
+  q = b;
+  *q++ = 0; sz--;
+  mq = q + hsz;
+  GR_FILL(o->r, q, hsz);
+
+  /* --- Fill in the rest of the buffer --- */
+
+  h = GH_INIT(o->ch);
+  GH_HASH(h, o->ep, o->epsz);
+  GH_DONE(h, mq);
+  GH_DESTROY(h);
+  pp = mq + hsz;
+  n = sz - 2 * hsz - msz - 1;
+  memset(pp, 0, n);
+  pp += n;
+  *pp++ = 1;
+  memcpy(pp, m, msz);
+
+  /* --- Do the packing --- */
+
+  n = sz - hsz;
+  c = GC_INIT(o->cc, q, hsz);
+  GC_ENCRYPT(c, mq, mq, n);
+  GC_DESTROY(c);
+
+  c = GC_INIT(o->cc, mq, n);
+  GC_ENCRYPT(c, q, q, hsz);
+  GC_DESTROY(c);
+
+  /* --- Done --- */
+
+  return (mp_loadb(d, b, sz + 1));
+}
+
+/* --- @oaep_decode@ --- *
+ *
+ * Arguments:  @mp *m@ = the decrypted message
+ *             @octet *b@ = pointer to a buffer to work in
+ *             @size_t sz@ = the size of the buffer (big enough)
+ *             @unsigned long nbits@ = the number of bits in @n@
+ *             @void *p@ = pointer to OAEP parameter block
+ *
+ * Returns:    The length of the output string if successful, negative on
+ *             failure.
+ *
+ * Use:                Implements the operation @EME-OAEP-DECODE@, as defined in
+ *             PKCS#1 v. 2.0 (RFC2437).
+ */
+
+int oaep_decode(mp *m, octet *b, size_t sz, unsigned long nbits, void *p)
+{
+  oaep *o = p;
+  gcipher *c;
+  ghash *h;
+  octet *q, *mq, *qq;
+  octet *pp;
+  uint32 goodp = 1;
+  size_t n;
+  size_t hsz = o->ch->hashsz;
+
+  /* --- Ensure that the block is large enough --- */
+
+  if (sz < 2 * hsz)                    /* Doesn't depend on ciphertext */
+    return (-1);
+
+  /* --- Decrypt the message --- */
+
+  mp_storeb(m, b, sz);
+  q = b;
+  goodp &= ct_inteq(*q, 0);
+  q++; sz--;
+  mq = q + hsz;
+  qq = q + sz;
+  n = sz - hsz;
+  c = GC_INIT(o->cc, mq, n);
+  GC_DECRYPT(c, q, q, hsz);
+  GC_DESTROY(c);
+
+  c = GC_INIT(o->cc, q, hsz);
+  GC_DECRYPT(c, mq, mq, n);
+  GC_DESTROY(c);
+  q--;
+
+  /* --- Check the hash on the encoding parameters --- */
+
+  h = GH_INIT(o->ch);
+  GH_HASH(h, o->ep, o->epsz);
+  GH_DONE(h, q);
+  GH_DESTROY(h);
+  goodp &= ct_memeq(q, mq, hsz);
+
+  /* --- Now find the start of the actual message --- */
+
+  pp = mq + hsz;
+  while (*pp == 0 && pp < qq)
+    pp++;
+  goodp &= ~ct_intle(qq - b, pp - b);
+  goodp &= ct_inteq(*pp, 1);
+  pp++;
+  n = qq - pp;
+  memmove(q, pp, n);
+  return (goodp ? n : -1);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/pkcs1.c b/pub/pkcs1.c
new file mode 100644 (file)
index 0000000..590c05e
--- /dev/null
@@ -0,0 +1,259 @@
+/* -*-c-*-
+ *
+ * PKCS#1 1.5 packing
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+
+#include "ct.h"
+#include "grand.h"
+#include "rsa.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @pkcs1_cryptencode@ --- *
+ *
+ * Arguments:  @mp *d@ = where to put the answer
+ *             @const void *m@ = pointer to message data
+ *             @size_t msz@ = size of message data
+ *             @octet *b@ = spare buffer
+ *             @size_t sz@ = size of the buffer (big enough)
+ *             @unsigned long nbits@ = length of bits of @n@
+ *             @void *p@ = pointer to PKCS1 parameter block
+ *
+ * Returns:    The encoded result, or null.
+ *
+ * Use:                Implements the operation @EME-PKCS1-V1_5-ENCODE@, as defined
+ *             in PKCS#1 v. 2.0 (RFC2437).
+ */
+
+mp *pkcs1_cryptencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
+                     unsigned long nbits, void *p)
+{
+  pkcs1 *pp = p;
+  grand *r = pp->r;
+  octet *q;
+  size_t i, n;
+
+  /* --- Ensure that the buffer is sensibly sized --- */
+
+  if (pp->epsz + msz + 11 > sz)
+    return (0);
+
+  /* --- Allocate the buffer and fill it in --- */
+
+  q = b;
+  *q++ = 0x00;
+  *q++ = 0x02;
+  n = sz - msz - pp->epsz - 3;
+  GR_FILL(r, q, n);
+  for (i = 0; i < n; i++) {
+    if (*q == 0)
+      *q = r->ops->range(r, 255) + 1;
+    q++;
+  }
+  *q++ = 0;
+  if (pp->ep) {
+    memcpy(q, pp->ep, pp->epsz);
+    q += pp->epsz;
+  }
+  memcpy(q, m, msz);
+  q += msz;
+  assert(q == b + sz);
+
+  /* --- Collect the result --- */
+
+  return (mp_loadb(d, b, sz));
+}
+
+/* --- @pkcs1_cryptdecode@ --- *
+ *
+ * Arguments:  @mp *m@ = the decrypted message
+ *             @octet *b@ = pointer to a buffer to work in
+ *             @size_t sz@ = the size of the buffer (big enough)
+ *             @unsigned long nbits@ = the number of bits in @n@
+ *             @void *p@ = pointer to PKCS1 parameter block
+ *
+ * Returns:    The length of the output string if successful, negative on
+ *             failure.
+ *
+ * Use:                Implements the operation @EME-PKCS1-V1_5-DECODE@, as defined
+ *             in PKCS#1 v. 2.0 (RFC2437).
+ */
+
+int pkcs1_cryptdecode(mp *m, octet *b, size_t sz,
+                     unsigned long nbits, void *p)
+{
+  pkcs1 *pp = p;
+  const octet *q, *qq;
+  size_t n, i;
+  uint32 goodp = 1;
+
+  /* --- Check the size of the block looks sane --- */
+
+  if (pp->epsz + 11 > sz)              /* OK: independent of ciphertext */
+    return (-1);
+  mp_storeb(m, b, sz);
+  q = b;
+  qq = q + sz;
+
+  /* --- Ensure that the block looks OK --- */
+
+  goodp &= ct_inteq(*q++, 0);
+  goodp &= ct_inteq(*q++, 2);
+
+  /* --- Check the nonzero padding --- */
+
+  i = 0;
+  while (*q != 0 && q < qq)
+    i++, q++;
+  goodp &= ct_intle(8, i);
+  goodp &= ~ct_intle(qq - q, pp->epsz + 1);
+  q++;
+
+  /* --- Check the encoding parameters --- */
+
+  if (pp->ep)
+    goodp &= ct_memeq(b + ct_pick(goodp, 0, q - b), pp->ep, pp->epsz);
+  q += pp->epsz;
+
+  /* --- Done --- */
+
+  n = qq - q;
+  memmove(b, b + ct_pick(goodp, 1, q - b), n);
+  return (goodp ? n : -1);
+}
+
+/* --- @pkcs1_sigencode@ --- *
+ *
+ * Arguments:  @mp *d@ = where to put the answer
+ *             @const void *m@ = pointer to message data
+ *             @size_t msz@ = size of message data
+ *             @octet *b@ = spare buffer
+ *             @size_t sz@ = size of the buffer (big enough)
+ *             @unsigned long nbits@ = length of bits of @n@
+ *             @void *p@ = pointer to PKCS1 parameter block
+ *
+ * Returns:    The encoded message representative, or null.
+ *
+ * Use:                Implements the operation @EMSA-PKCS1-V1_5-ENCODE@, as defined
+ *             in PKCS#1 v. 2.0 (RFC2437).
+ */
+
+mp *pkcs1_sigencode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
+                   unsigned long nbits, void *p)
+{
+  pkcs1 *pp = p;
+  octet *q;
+  size_t n;
+
+  /* --- Ensure that the buffer is sensibly sized --- */
+
+  if (pp->epsz + msz + 11 > sz)
+    return (0);
+
+  /* --- Fill in the buffer --- */
+
+  q = b;
+  *q++ = 0x00;
+  *q++ = 0x01;
+  n = sz - msz - pp->epsz - 3;
+  memset(q, 0xff, n);
+  q += n;
+  *q++ = 0;
+  if (pp->ep) {
+    memcpy(q, pp->ep, pp->epsz);
+    q += pp->epsz;
+  }
+  memcpy(q, m, msz);
+  q += msz;
+  assert(q == b + sz);
+  return (mp_loadb(d, b, sz));
+}
+
+/* --- @pkcs1_sigdecode@ --- *
+ *
+ * Arguments:  @mp *s@ = the message representative
+ *             @const void *m@ = the original message, or null (ignored)
+ *             @size_t msz@ = the message size (ignored)
+ *             @octet *b@ = a scratch buffer
+ *             @size_t sz@ = size of the buffer (large enough)
+ *             @unsigned long nbits@ = number of bits in @n@
+ *             @void *p@ = pointer to PKCS1 parameters
+ *
+ * Returns:    The length of the output string if successful, negative on
+ *             failure.
+ *
+ * Use:                Implements the operation @EMSA-PKCS1-V1_5-DECODE@, as defined
+ *             in PKCS#1 v. 2.0 (RFC2437).
+ */
+
+int pkcs1_sigdecode(mp *s, const void *m, size_t msz, octet *b, size_t sz,
+                   unsigned long nbits, void *p)
+{
+  pkcs1 *pp = p;
+  const octet *q, *qq;
+  size_t i, n;
+
+  /* --- Check the size of the block looks sane --- */
+
+  if (pp->epsz + 10 > sz)
+    return (-1);
+  mp_storeb(s, b, sz);
+  q = b;
+  qq = q + sz;
+
+  /* --- Ensure that the block looks OK --- */
+
+  if (*q++ != 0x00 || *q++ != 0x01)
+    return (-1);
+
+  /* --- Check the padding --- */
+
+  i = 0;
+  while (*q == 0xff && q < qq)
+    i++, q++;
+  if (i < 8 || qq - q < pp->epsz + 1 || *q++ != 0)
+    return (-1);
+
+  /* --- Check the encoding parameters --- */
+
+  if (pp->ep && memcmp(q, pp->ep, pp->epsz) != 0)
+    return (-1);
+  q += pp->epsz;
+
+  /* --- Done --- */
+
+  n = qq - q;
+  memmove(b, q, n);
+  return (n);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/pss.c b/pub/pss.c
new file mode 100644 (file)
index 0000000..8e77b78
--- /dev/null
+++ b/pub/pss.c
@@ -0,0 +1,186 @@
+/* -*-c-*-
+ *
+ * Probabistic signature scheme
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+
+#include "gcipher.h"
+#include "ghash.h"
+#include "grand.h"
+#include "rsa.h"
+
+/*----- Magic statics -----------------------------------------------------*/
+
+static const octet z8[8] = { 0 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @pss_encode@ --- *
+ *
+ * Arguments:  @mp *d@ = where to put the answer
+ *             @const void *m@ = pointer to the message hash
+ *             @size_t msz@ = the size of the message hash
+ *             @octet *b@ = scratch buffer
+ *             @size_t sz@ = sizeo of the buffer (large enough)
+ *             @unsigned long nbits@ = size in bits of @n@
+ *             @void *p@ = pointer to the PSS parameters
+ *
+ * Returns:    Encoded message representative, or null on error.
+ *
+ * Use:                Implements the operation @EMSA-PSS-ENCODE@, as defined in
+ *             PKCS#1 v. 2.1 (RFC3447).
+ */
+
+mp *pss_encode(mp *d, const void *m, size_t msz, octet *b, size_t sz,
+              unsigned long nbits, void *p)
+{
+  pss *pp = p;
+  octet *s, *r;
+  ghash *h;
+  gcipher *c;
+  unsigned mask;
+  size_t pssz, hsz = pp->ch->hashsz;
+
+  /* --- Check the message length --- */
+
+  nbits--;
+  sz = (nbits + 7)/8;
+  mask = (1 << nbits%8) - 1;
+  if (!mask) mask = 0xff;
+  if (hsz + pp->ssz + 2 > sz)
+    return (0);
+
+  /* --- Generate a random salt --- */
+
+  pssz = sz - pp->ssz - hsz - 2;
+  memset(b, 0, pssz);
+  b[pssz] = 0x01;
+  s = b + pssz + 1;
+  r = s + pp->ssz;
+  GR_FILL(pp->r, s, pp->ssz);
+
+  /* --- Compute the salted hash --- */
+
+  h = GH_INIT(pp->ch);
+  GH_HASH(h, z8, 8);
+  GH_HASH(h, m, msz);
+  GH_HASH(h, s, pp->ssz);
+  GH_DONE(h, r);
+  r[hsz] = 0xbc;
+
+  /* --- Do the masking --- */
+
+  c = GC_INIT(pp->cc, r, hsz);
+  GC_ENCRYPT(c, b, b, pssz + pp->ssz + 1);
+  GC_DESTROY(c);
+  b[0] &= mask;
+  return (mp_loadb(d, b, sz));
+}
+
+/* --- @pss_decode@ --- *
+ *
+ * Arguments:  @mp *s@ = the message representative
+ *             @const void *m@ = the original message
+ *             @size_t msz@ = the message size
+ *             @octet *b@ = a scratch buffer
+ *             @size_t sz@ = size of the buffer (large enough)
+ *             @unsigned long nbits@ = number of bits in @n@
+ *             @void *p@ = pointer to PKCS1 parameters
+ *
+ * Returns:    The length of the output string if successful, negative on
+ *             failure.
+ *
+ * Use:                Implements the operation @EMSA_PSS_VERIFY@, as defined in
+ *             PCSK#1 v. 2.1 (RFC3447).
+ */
+
+int pss_decode(mp *mi, const void *m, size_t msz, octet *b, size_t sz,
+              unsigned long nbits, void *p)
+{
+  pss *pp = p;
+  octet *s, *r;
+  ghash *h;
+  gcipher *c;
+  unsigned mask;
+  size_t pssz, hsz = pp->ch->hashsz, i;
+  int rc;
+
+  /* --- Check the message length --- */
+
+  nbits--;
+  sz = (nbits + 7)/8;
+  if (mp_octets(mi) > sz)
+    return (-1);
+  mask = (1 << nbits%8) - 1;
+  if (!mask) mask = 0xff;
+  if (hsz + pp->ssz + 2 > sz)
+    return (-1);
+  mp_storeb(mi, b, sz);
+
+  /* --- Split up the buffer --- */
+
+  pssz = sz - hsz - pp->ssz - 2;
+  s = b + pssz + 1;
+  r = s + pp->ssz;
+  if (r[hsz] != 0xbc)
+    return (-1);
+
+  /* --- Decode the seed --- */
+
+  if (b[0] & ~mask)
+    return (-1);
+  c = GC_INIT(pp->cc, r, hsz);
+  GC_DECRYPT(c, b, b, pssz + pp->ssz + 1);
+  GC_DESTROY(c);
+  b[0] &= mask;
+  for (i = 0; i < pssz; i++)
+    if (b[i]) return (-1);
+  if (b[pssz] != 0x01)
+    return (-1);
+
+  /* --- Hash the message --- */
+
+  h = GH_INIT(pp->ch);
+  GH_HASH(h, z8, 8);
+  GH_HASH(h, m, msz);
+  GH_HASH(h, s, pp->ssz);
+  s = GH_DONE(h, 0);
+  rc = !memcmp(s, r, hsz);
+  GH_DESTROY(h);
+  if (!rc) return (-1);
+
+  /* --- Done --- */
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/rsa-fetch.c b/pub/rsa-fetch.c
new file mode 100644 (file)
index 0000000..85356b4
--- /dev/null
@@ -0,0 +1,85 @@
+/* -*-c-*-
+ *
+ * Key fetching for RSA public and private keys
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "key.h"
+#include "rsa.h"
+
+/*----- Key fetching ------------------------------------------------------*/
+
+const key_fetchdef rsa_pubfetch[] = {
+  { "n",       offsetof(rsa_pub, n),           KENC_MP,        0 },
+  { "e",       offsetof(rsa_pub, e),           KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+static const key_fetchdef priv[] = {
+  { "p",       offsetof(rsa_priv, p),          KENC_MP,        0 },
+  { "q",       offsetof(rsa_priv, q),          KENC_MP,        0 },
+  { "q-inv",   offsetof(rsa_priv, q_inv),      KENC_MP,        0 },
+  { "d",       offsetof(rsa_priv, d),          KENC_MP,        0 },
+  { "d-mod-p", offsetof(rsa_priv, dp),         KENC_MP,        0 },
+  { "d-mod-q", offsetof(rsa_priv, dq),         KENC_MP,        0 },
+  { 0,         0,                              0,              0 }
+};
+
+const key_fetchdef rsa_privfetch[] = {
+  { "n",       offsetof(rsa_priv, n),          KENC_MP,        0 },
+  { "e",       offsetof(rsa_priv, e),          KENC_MP,        0 },
+  { "private", 0,                              KENC_STRUCT,    priv },
+  { 0,         0,                              0,              0 }
+};
+
+/* --- @rsa_pubfree@, @rsa_privfree@ --- *
+ *
+ * Arguments:  @rsa_pub *rp@, @rsa_priv *rp@ = pointer to key block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an RSA key block.
+ */
+
+void rsa_pubfree(rsa_pub *rp)
+{
+  mp_drop(rp->n);
+  mp_drop(rp->e);
+}
+
+void rsa_privfree(rsa_priv *rp)
+{
+  mp_drop(rp->n);
+  mp_drop(rp->e);
+  mp_drop(rp->p);
+  mp_drop(rp->q);
+  mp_drop(rp->q_inv);
+  mp_drop(rp->d);
+  mp_drop(rp->dp);
+  mp_drop(rp->dq);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/rsa-gen.c b/pub/rsa-gen.c
new file mode 100644 (file)
index 0000000..a7a2ca4
--- /dev/null
@@ -0,0 +1,189 @@
+/* -*-c-*-
+ *
+ * RSA parameter generation
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "grand.h"
+#include "mp.h"
+#include "mpint.h"
+#include "pgen.h"
+#include "rsa.h"
+#include "strongprime.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rsa_gen@ --- *
+ *
+ * Arguments:  @rsa_priv *rp@ = pointer to block to be filled in
+ *             @unsigned nbits@ = required modulus size in bits
+ *             @grand *r@ = random number source
+ *             @unsigned n@ = number of attempts to make
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for the event handler
+ *
+ * Returns:    Zero if all went well, nonzero otherwise.
+ *
+ * Use:                Constructs a pair of strong RSA primes and other useful RSA
+ *             parameters.  A small encryption exponent is chosen if
+ *             possible.
+ */
+
+int rsa_gen(rsa_priv *rp, unsigned nbits, grand *r, unsigned n,
+           pgen_proc *event, void *ectx)
+{
+  pgen_gcdstepctx g;
+  mp *phi = MP_NEW;
+
+  /* --- Bits of initialization --- */
+
+  rp->e = mp_fromulong(MP_NEW, 0x10001);
+  rp->d = MP_NEW;
+
+  /* --- Generate strong primes %$p$% and %$q$% --- *
+   *
+   * Constrain the GCD of @q@ to ensure that overly small private exponents
+   * are impossible.  Current results suggest that if %$d < n^{0.29}$% then
+   * it can be guessed fairly easily.  This implementation is rather more
+   * conservative about that sort of thing.
+   */
+
+again:
+  if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0)
+    goto fail_p;
+
+  /* --- Do painful fiddling with GCD steppers --- */
+
+  {
+    mp *q;
+    rabin rb;
+
+    if ((q = strongprime_setup("q", MP_NEWSEC, &g.jp, nbits / 2,
+                              r, n, event, ectx)) == 0)
+      goto fail_q;
+    g.r = mp_lsr(MP_NEW, rp->p, 1);
+    g.g = MP_NEW;
+    g.max = MP_256;
+    q = pgen("q", q, q, event, ectx, n, pgen_gcdstep, &g,
+                rabin_iters(nbits/2), pgen_test, &rb);
+    pfilt_destroy(&g.jp);
+    mp_drop(g.r);
+    if (!q) {
+      mp_drop(g.g);
+      if (n)
+       goto fail_q;
+      mp_drop(rp->p);
+      goto again;
+    }
+    rp->q = q;
+  }
+
+  /* --- Ensure that %$p > q$% --- *
+   *
+   * Also ensure that %$p$% and %$q$% are sufficiently different to deter
+   * square-root-based factoring methods.
+   */
+
+  phi = mp_sub(phi, rp->p, rp->q);
+  if (MP_LEN(phi) * 4 < MP_LEN(rp->p) * 3 ||
+      MP_LEN(phi) * 4 < MP_LEN(rp->q) * 3) {
+    mp_drop(rp->p);
+    mp_drop(g.g);
+    if (n)
+      goto fail_q;
+    mp_drop(rp->q);
+    goto again;
+  }
+
+  if (MP_NEGP(phi)) {
+    mp *z = rp->p;
+    rp->p = rp->q;
+    rp->q = z;
+  }
+
+  /* --- Work out the modulus and the CRT coefficient --- */
+
+  rp->n = mp_mul(MP_NEW, rp->p, rp->q);
+  rp->q_inv = mp_modinv(MP_NEW, rp->q, rp->p);
+
+  /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- *
+   *
+   * Save on further multiplications by noting that %$n = pq$% is known and
+   * that %$(p - 1)(q - 1) = pq - p - q + 1$%.  To minimize the size of @d@
+   * (useful for performance reasons, although not very because an overly
+   * small @d@ will be rejected for security reasons) this is then divided by
+   * %$\gcd(p - 1, q - 1)$%.
+   */
+
+  phi = mp_sub(phi, rp->n, rp->p);
+  phi = mp_sub(phi, phi, rp->q);
+  phi = mp_add(phi, phi, MP_ONE);
+  phi = mp_lsr(phi, phi, 1);
+  mp_div(&phi, 0, phi, g.g);
+
+  /* --- Decide on a public exponent --- *
+   *
+   * Simultaneously compute the private exponent.
+   */
+
+  mp_gcd(&g.g, 0, &rp->d, phi, rp->e);
+  if (!MP_EQ(g.g, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3)
+    goto fail_e;
+
+  /* --- Work out exponent residues --- */
+
+  rp->dp = MP_NEW; phi = mp_sub(phi, rp->p, MP_ONE);
+  mp_div(0, &rp->dp, rp->d, phi);
+
+  rp->dq = MP_NEW; phi = mp_sub(phi, rp->q, MP_ONE);
+  mp_div(0, &rp->dq, rp->d, phi);
+
+  /* --- Done --- */
+
+  mp_drop(phi);
+  mp_drop(g.g);
+  return (0);
+
+  /* --- Tidy up when something goes wrong --- */
+
+fail_e:
+  mp_drop(g.g);
+  mp_drop(phi);
+  mp_drop(rp->n);
+  mp_drop(rp->q_inv);
+  mp_drop(rp->q);
+fail_q:
+  mp_drop(rp->p);
+fail_p:
+  mp_drop(rp->e);
+  if (rp->d)
+    mp_drop(rp->d);
+  return (-1);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/rsa-priv.c b/pub/rsa-priv.c
new file mode 100644 (file)
index 0000000..08a8982
--- /dev/null
@@ -0,0 +1,260 @@
+/* -*-c-*-
+ *
+ * RSA private-key operations
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+
+#include "mp.h"
+#include "mpmont.h"
+#include "mprand.h"
+#include "rsa.h"
+
+/*----- Public key operations ---------------------------------------------*/
+
+/* --- @rsa_privcreate@ --- *
+ *
+ * Arguments:  @rsa_privctx *rd@ = pointer to an RSA private key context
+ *             @rsa_priv *rp@ = pointer to RSA private key
+ *             @grand *r@ = pointer to random number source for blinding
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RSA private-key context.  Keeping a context
+ *             for several decryption or signing operations provides a minor
+ *             performance benefit.
+ *
+ *             The random number source may be null if blinding is not
+ *             desired.  This improves decryption speed, at the risk of
+ *             permitting timing attacks.
+ */
+
+void rsa_privcreate(rsa_privctx *rd, rsa_priv *rp, grand *r)
+{
+  rd->rp = rp;
+  rd->r = r;
+  if (r)
+    mpmont_create(&rd->nm, rp->n);
+  mpmont_create(&rd->pm, rp->p);
+  mpmont_create(&rd->qm, rp->q);
+}
+
+/* --- @rsa_privdestroy@ --- *
+ *
+ * Arguments:  @rsa_privctx *rd@ = pointer to an RSA decryption context
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys an RSA decryption context.
+ */
+
+void rsa_privdestroy(rsa_privctx *rd)
+{
+  if (rd->r)
+    mpmont_destroy(&rd->nm);
+  mpmont_destroy(&rd->pm);
+  mpmont_destroy(&rd->qm);
+}
+
+/* --- @rsa_privop@ --- *
+ *
+ * Arguments:  @rsa_privctx *rd@ = pointer to RSA private key context
+ *             @mp *d@ = destination
+ *             @mp *c@ = input message
+ *
+ * Returns:    The transformed output message.
+ *
+ * Use:                Performs an RSA private key operation.  This function takes
+ *             advantage of knowledge of the key factors in order to speed
+ *             up decryption.  It also blinds the ciphertext prior to
+ *             decryption and unblinds it afterwards to thwart timing
+ *             attacks.
+ */
+
+mp *rsa_privop(rsa_privctx *rd, mp *d, mp *c)
+{
+  mp *ki = MP_NEW;
+  rsa_priv *rp = rd->rp;
+
+  /* --- If so desired, set up a blinding constant --- *
+   *
+   * Choose a constant %$k$% relatively prime to the modulus %$m$%.  Compute
+   * %$c' = c k^e \bmod n$%, and %$k^{-1} \bmod n$%.  Don't bother with the
+   * CRT stuff here because %$e$% is chosen to be small.
+   */
+
+  c = MP_COPY(c);
+  if (rd->r) {
+    mp *k = MP_NEWSEC, *g = MP_NEW;
+
+    do {
+      k = mprand_range(k, rp->n, rd->r, 0);
+      mp_gcd(&g, 0, &ki, rp->n, k);
+    } while (!MP_EQ(g, MP_ONE));
+    k = mpmont_mul(&rd->nm, k, k, rd->nm.r2);
+    k = mpmont_expr(&rd->nm, k, k, rp->e);
+    c = mpmont_mul(&rd->nm, c, c, k);
+    mp_drop(k);
+    mp_drop(g);
+  }
+
+  /* --- Do the actual modular exponentiation --- *
+   *
+   * Use a slightly hacked version of the Chinese Remainder Theorem stuff.
+   *
+   * Let %$q' = q^{-1} \bmod p$%.  Then note that
+   * %$c^d \equiv q (q'(c_p^{d_p} - c_q^{d_q}) \bmod p) + c_q^{d_q} \pmod n$%
+   */
+
+  {
+    mp *cp = MP_NEW, *cq = MP_NEW;
+
+    /* --- Work out the two halves of the result --- */
+
+    mp_div(0, &cp, c, rp->p);
+    cp = mpmont_exp(&rd->pm, cp, cp, rp->dp);
+
+    mp_div(0, &cq, c, rp->q);
+    cq = mpmont_exp(&rd->qm, cq, cq, rp->dq);
+
+    /* --- Combine the halves using the result above --- */
+
+    d = mp_sub(d, cp, cq);
+    mp_div(0, &d, d, rp->p);
+    d = mpmont_mul(&rd->pm, d, d, rp->q_inv);
+    d = mpmont_mul(&rd->pm, d, d, rd->pm.r2);
+
+    d = mp_mul(d, d, rp->q);
+    d = mp_add(d, d, cq);
+    if (MP_CMP(d, >=, rp->n))
+      d = mp_sub(d, d, rp->n);
+
+    /* --- Tidy away temporary variables --- */
+
+    mp_drop(cp);
+    mp_drop(cq);
+  }
+
+  /* --- Finally, possibly remove the blinding factor --- */
+
+  if (ki) {
+    d = mpmont_mul(&rd->nm, d, d, ki);
+    d = mpmont_mul(&rd->nm, d, d, rd->nm.r2);
+    mp_drop(ki);
+  }
+
+  /* --- Done --- */
+
+  mp_drop(c);
+  return (d);
+}
+
+/* --- @rsa_qprivop@ --- *
+ *
+ * Arguments:  @rsa_priv *rp@ = pointer to RSA parameters
+ *             @mp *d@ = destination
+ *             @mp *c@ = input message
+ *             @grand *r@ = pointer to random number source for blinding
+ *
+ * Returns:    Correctly transformed output message
+ *
+ * Use:                Performs an RSA private key operation, very carefully.
+ */
+
+mp *rsa_qprivop(rsa_priv *rp, mp *d, mp *c, grand *r)
+{
+  rsa_privctx rd;
+  rsa_privcreate(&rd, rp, r);
+  d = rsa_privop(&rd, d, c);
+  rsa_privdestroy(&rd);
+  return (d);
+}
+
+/*----- Operations with padding -------------------------------------------*/
+
+/* --- @rsa_sign@ --- *
+ *
+ * Arguments:  @rsa_privctx *rp@ = pointer to an RSA private key context
+ *             @mp *d@ = where to put the result
+ *             @const void *m@ = pointer to input message
+ *             @size_t msz@ = size of input message
+ *             @rsa_pad *e@ = encoding procedure
+ *             @void *earg@ = argument pointer for encoding procedure
+ *
+ * Returns:    The signature, as a multiprecision integer, or null on
+ *             failure.
+ *
+ * Use:                Computes an RSA digital signature.
+ */
+
+mp *rsa_sign(rsa_privctx *rp, mp *d, const void *m, size_t msz,
+            rsa_pad *e, void *earg)
+{
+  octet *p;
+  unsigned long nb = mp_bits(rp->rp->n);
+  size_t n = (nb + 7)/8;
+  arena *a = d && d->a ? d->a->a : arena_global;
+
+  p = x_alloc(a, n);
+  d = e(d, m, msz, p, n, nb, earg);
+  x_free(a, p);
+  return (d ? rsa_privop(rp, d, d) : 0);
+}
+
+/* --- @rsa_decrypt@ --- *
+ *
+ * Arguments:  @rsa_privctx *rp@ = pointer to an RSA private key context
+ *             @mp *m@ = encrypted message, as a multiprecision integer
+ *             @dstr *d@ = pointer to output string
+ *             @rsa_decunpad *e@ = decoding procedure
+ *             @void *earg@ = argument pointer for decoding procedure
+ *
+ * Returns:    The length of the output string if successful, negative on
+ *             failure.
+ *
+ * Use:                Does RSA decryption.
+ */
+
+int rsa_decrypt(rsa_privctx *rp, mp *m, dstr *d,
+               rsa_decunpad *e, void *earg)
+{
+  mp *p = rsa_privop(rp, MP_NEW, m);
+  unsigned long nb = mp_bits(rp->rp->n);
+  size_t n = (nb + 7)/8;
+  int rc;
+
+  dstr_ensure(d, n);
+  rc = e(p, (octet *)d->buf + d->len, n, nb, earg);
+  if (rc >= 0)
+    d->len += rc;
+  mp_drop(p);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/rsa-pub.c b/pub/rsa-pub.c
new file mode 100644 (file)
index 0000000..78793a9
--- /dev/null
@@ -0,0 +1,190 @@
+/* -*-c-*-
+ *
+ * [RSA encryption with padding *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+
+#include "mp.h"
+#include "mpmont.h"
+#include "rsa.h"
+
+/*----- Public key operations ---------------------------------------------*/
+
+/* --- @rsa_pubcreate@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
+ *             @rsa_pub *rp@ = pointer to RSA public key
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RSA public-key context.
+ */
+
+void rsa_pubcreate(rsa_pubctx *rd, rsa_pub *rp)
+{
+  rd->rp = rp;
+  mpmont_create(&rd->mm, rp->n);
+}
+
+/* --- @rsa_pubdestroy@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys an RSA public-key context.
+ */
+
+void rsa_pubdestroy(rsa_pubctx *rd)
+{
+  mpmont_destroy(&rd->mm);
+}
+
+/* --- @rsa_pubop@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
+ *             @mp *d@ = destination
+ *             @mp *p@ = input message
+ *
+ * Returns:    The transformed output message.
+ *
+ * Use:                Performs an RSA public key operation.
+ */
+
+mp *rsa_pubop(rsa_pubctx *rd, mp *d, mp *p)
+{
+  return (mpmont_exp(&rd->mm, d, p, rd->rp->e));
+}
+
+/* --- @rsa_qpubop@ --- *
+ *
+ * Arguments:  @rsa_pub *rp@ = pointer to RSA parameters
+ *             @mp *d@ = destination
+ *             @mp *p@ = input message
+ *
+ * Returns:    Correctly transformed output message.
+ *
+ * Use:                Performs an RSA public key operation.
+ */
+
+mp *rsa_qpubop(rsa_pub *rp, mp *d, mp *c)
+{
+  rsa_pubctx rd;
+  rsa_pubcreate(&rd, rp);
+  d = rsa_pubop(&rd, d, c);
+  rsa_pubdestroy(&rd);
+  return (d);
+}
+
+/*----- Operations with padding -------------------------------------------*/
+
+/* --- @rsa_encrypt@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rp@ = pointer to an RSA public key context
+ *             @mp *d@ = proposed destination integer
+ *             @const void *m@ = pointer to input message
+ *             @size_t msz@ = size of input message
+ *             @rsa_pad *e@ = encoding procedure
+ *             @void *earg@ = argument pointer for encoding procedure
+ *
+ * Returns:    The encrypted message, as a multiprecision integer, or null
+ *             on failure.
+ *
+ * Use:                Does RSA encryption.
+ */
+
+mp *rsa_encrypt(rsa_pubctx *rp, mp *d, const void *m, size_t msz,
+               rsa_pad *e, void *earg)
+{
+  octet *p;
+  unsigned long nb = mp_bits(rp->rp->n);
+  size_t n = (nb + 7)/8;
+  arena *a = d && d->a ? d->a->a : arena_global;
+
+  p = x_alloc(a, n);
+  d = e(d, m, msz, p, n, nb, earg);
+  x_free(a, p);
+  return (d ? rsa_pubop(rp, d, d) : 0);
+}
+
+/* --- @rsa_verify@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rp@ = pointer to an RSA public key contxt
+ *             @mp *s@ = the signature, as a multiprecision integer
+ *             @const void *m@ = pointer to message to verify, or null
+ *             @size_t msz@ = size of input message
+ *             @dstr *d@ = pointer to output string, or null
+ *             @rsa_vfrunpad *e@ = decoding procedure
+ *             @void *earg@ = argument pointer for decoding procedure
+ *
+ * Returns:    The length of the output string if successful (0 if no output
+ *             was wanted); negative on failure.
+ *
+ * Use:                Does RSA signature verification.  To use a signature scheme
+ *             with recovery, pass in @m == 0@ and @d != 0@: the recovered
+ *             message should appear in @d@.  To use a signature scheme with
+ *             appendix, provide @m != 0@ and @d == 0@; the result should be
+ *             zero for success.
+ */
+
+int rsa_verify(rsa_pubctx *rp, mp *s, const void *m, size_t msz,
+              dstr *d, rsa_vrfunpad *e, void *earg)
+{
+  mp *p = rsa_pubop(rp, MP_NEW, s);
+  unsigned long nb = mp_bits(rp->rp->n);
+  size_t n = (nb + 7)/8;
+  dstr dd = DSTR_INIT;
+  int rc;
+
+  /* --- Decoder protocol --- *
+   *
+   * We deal with two kinds of decoders: ones with message recovery and ones
+   * with appendix.  A decoder with recovery will leave a message in the
+   * buffer and exit nonzero: we'll check that against @m@ if provided and
+   * just leave it otherwise.  A decoder with appendix will inspect @m@ and
+   * return zero or @-1@ itself.
+   */
+
+  if (!d) d = &dd;
+  dstr_ensure(d, n);
+  rc = e(p, m, msz, (octet *)d->buf + d->len, n, nb, earg);
+  if (rc > 0 && m) {
+    if (rc != msz || memcmp(d->buf + d->len, m, msz) != 0)
+      rc = -1;
+    else
+      rc = 0;
+  }
+  if (rc > 0)
+    d->len += rc;
+  mp_drop(p);
+  dstr_destroy(&dd);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/rsa-recover.c b/pub/rsa-recover.c
new file mode 100644 (file)
index 0000000..1a7c460
--- /dev/null
@@ -0,0 +1,240 @@
+/* -*-c-*-
+ *
+ * Recover RSA parameters
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpmont.h"
+#include "rsa.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rsa_recover@ --- *
+ *
+ * Arguments:  @rsa_priv *rp@ = pointer to parameter block
+ *
+ * Returns:    Zero if all went well, nonzero if the parameters make no
+ *             sense.
+ *
+ * Use:                Derives the full set of RSA parameters given a minimal set.
+ */
+
+int rsa_recover(rsa_priv *rp)
+{
+  /* --- If there is no modulus, calculate it --- */
+
+  if (!rp->n) {
+    if (!rp->p || !rp->q)
+      return (-1);
+    rp->n = mp_mul(MP_NEW, rp->p, rp->q);
+  }
+
+  /* --- If there are no factors, compute them --- */
+
+  else if (!rp->p || !rp->q) {
+
+    /* --- If one is missing, use simple division to recover the other --- */
+
+    if (rp->p || rp->q) {
+      mp *r = MP_NEW;
+      if (rp->p)
+       mp_div(&rp->q, &r, rp->n, rp->p);
+      else
+       mp_div(&rp->p, &r, rp->n, rp->q);
+      if (!MP_EQ(r, MP_ZERO)) {
+       mp_drop(r);
+       return (-1);
+      }
+      mp_drop(r);
+    }
+
+    /* --- Otherwise use the public and private moduli --- */
+
+    else if (!rp->e || !rp->d)
+      return (-1);
+    else {
+      mp *t;
+      size_t s;
+      mp a; mpw aw;
+      mp *m1;
+      mpmont mm;
+      int i;
+      mp *z = MP_NEW;
+
+      /* --- Work out the appropriate exponent --- *
+       *
+       * I need to compute %$s$% and %$t$% such that %$2^s t = e d - 1$%, and
+       * %$t$% is odd.
+       */
+
+      t = mp_mul(MP_NEW, rp->e, rp->d);
+      t = mp_sub(t, t, MP_ONE);
+      t = mp_odd(t, t, &s);
+
+      /* --- Set up for the exponentiation --- */
+
+      mpmont_create(&mm, rp->n);
+      m1 = mp_sub(MP_NEW, rp->n, mm.r);
+
+      /* --- Now for the main loop --- *
+       *
+       * Choose candidate integers and attempt to factor the modulus.
+       */
+
+      mp_build(&a, &aw, &aw + 1);
+      i = 0;
+      for (;;) {
+      again:
+
+       /* --- Choose a random %$a$% and calculate %$z = a^t \bmod n$% --- *
+        *
+        * If %$z \equiv 1$% or %$z \equiv -1 \pmod n$% then this iteration
+        * is a failure.
+        */
+
+       aw = primetab[i++];
+       z = mpmont_mul(&mm, z, &a, mm.r2);
+       z = mpmont_expr(&mm, z, z, t);
+       if (MP_EQ(z, mm.r) || MP_EQ(z, m1))
+         continue;
+
+       /* --- Now square until something interesting happens --- *
+        *
+        * Compute %$z^{2i} \bmod n$%.  Eventually, I'll either get %$-1$% or
+        * %$1$%.  If the former, the number is uninteresting, and I need to
+        * restart.  If the latter, the previous number minus 1 has a common
+        * factor with %$n$%.
+        */
+
+       for (;;) {
+         mp *zz = mp_sqr(MP_NEW, z);
+         zz = mpmont_reduce(&mm, zz, zz);
+         if (MP_EQ(zz, mm.r)) {
+           mp_drop(zz);
+           goto done;
+         } else if (MP_EQ(zz, m1)) {
+           mp_drop(zz);
+           goto again;
+         }
+         mp_drop(z);
+         z = zz;
+       }
+      }
+
+      /* --- Do the factoring --- *
+       *
+       * Here's how it actually works.  I've found an interesting square
+       * root of %$1 \pmod n$%.  Any square root of 1 must be congruent to
+       * %$\pm 1$% modulo both %$p$% and %$q$%.  Both congruent to %$1$% is
+       * boring, as is both congruent to %$-1$%.  Subtracting one from the
+       * result makes it congruent to %$0$% modulo %$p$% or %$q$% (and
+       * nobody cares which), and hence can be extracted by a GCD
+       * operation.
+       */
+
+    done:
+      z = mpmont_reduce(&mm, z, z);
+      z = mp_sub(z, z, MP_ONE);
+      rp->p = MP_NEW;
+      mp_gcd(&rp->p, 0, 0, rp->n, z);
+      rp->q = MP_NEW;
+      mp_div(&rp->q, 0, rp->n, rp->p);
+      mp_drop(z);
+      mp_drop(t);
+      mp_drop(m1);
+      if (MP_CMP(rp->p, <, rp->q)) {
+       z = rp->p;
+       rp->p = rp->q;
+       rp->q = z;
+      }
+      mpmont_destroy(&mm);
+    }
+  }
+
+  /* --- If %$e$% or %$d$% is missing, recalculate it --- */
+
+  if (!rp->e || !rp->d) {
+    mp *phi;
+    mp *g = MP_NEW;
+    mp *p1, *q1;
+
+    /* --- Compute %$\varphi(n)$% --- */
+
+    phi = mp_sub(MP_NEW, rp->n, rp->p);
+    phi = mp_sub(phi, phi, rp->q);
+    phi = mp_add(phi, phi, MP_ONE);
+    p1 = mp_sub(MP_NEW, rp->p, MP_ONE);
+    q1 = mp_sub(MP_NEW, rp->q, MP_ONE);
+    mp_gcd(&g, 0, 0, p1, q1);
+    mp_div(&phi, 0, phi, g);
+    mp_drop(p1);
+    mp_drop(q1);
+
+    /* --- Recover the other exponent --- */
+
+    if (rp->e)
+      mp_gcd(&g, 0, &rp->d, phi, rp->e);
+    else if (rp->d)
+      mp_gcd(&g, 0, &rp->e, phi, rp->d);
+    else {
+      mp_drop(phi);
+      mp_drop(g);
+      return (-1);
+    }
+
+    mp_drop(phi);
+    if (!MP_EQ(g, MP_ONE)) {
+      mp_drop(g);
+      return (-1);
+    }
+    mp_drop(g);
+  }
+
+  /* --- Compute %$q^{-1} \bmod p$% --- */
+
+  if (!rp->q_inv)
+    mp_gcd(0, 0, &rp->q_inv, rp->p, rp->q);
+
+  /* --- Compute %$d \bmod (p - 1)$% and %$d \bmod (q - 1)$% --- */
+
+  if (!rp->dp) {
+    mp *p1 = mp_sub(MP_NEW, rp->p, MP_ONE);
+    mp_div(0, &rp->dp, rp->d, p1);
+    mp_drop(p1);
+  }
+  if (!rp->dq) {
+    mp *q1 = mp_sub(MP_NEW, rp->q, MP_ONE);
+    mp_div(0, &rp->dq, rp->d, q1);
+    mp_drop(q1);
+  }
+
+  /* --- Done --- */
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/rsa-test.c b/pub/rsa-test.c
new file mode 100644 (file)
index 0000000..34b2a1f
--- /dev/null
@@ -0,0 +1,512 @@
+/* -*-c-*-
+ *
+ * Testing RSA padding operations
+ *
+ * (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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fibrand.h"
+#include "rsa.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+static int tencpad(int nbits,
+                  dstr *p, int rc, mp *c,
+                  const char *ename, dstr *eparam, rsa_pad *e, void *earg)
+{
+  size_t n = (nbits + 7)/8;
+  void *q = xmalloc(n);
+  mp *d;
+  int ok = 1;
+
+  d = e(MP_NEW, p->buf, p->len, q, n, nbits, earg);
+  if (!d == !rc || (!rc && !MP_EQ(d, c))) {
+    ok = 0;
+    fprintf(stderr, "*** %s padding failed!\n", ename);
+    fprintf(stderr, "*** padding bits = %d\n", nbits);
+    if (eparam) {
+      fprintf(stderr, "*** encoding parameters = ");
+      type_hex.dump(eparam, stderr);
+      fputc('\n', stderr);
+    }
+    fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr);
+    if (rc)
+      fprintf(stderr, "\n*** expected failure\n");
+    else {
+      MP_EPRINTX("\n*** expected", c);
+      MP_EPRINTX("*** computed", d);
+    }
+  }
+  mp_drop(d);
+  mp_drop(c);
+  xfree(q);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+#define tsigpad tencpad
+
+#define DSTR_EQ(x, y)                                                  \
+  ((x)->len == (y)->len && !memcmp((x)->buf, (y)->buf, (x)->len))
+
+static int tdecpad(int nbits,
+                  mp *c, int rc, dstr *p,
+                  const char *ename, dstr *eparam,
+                  rsa_decunpad *e, void *earg)
+{
+  dstr d = DSTR_INIT;
+  int n = (nbits + 7)/8;
+  int ok = 1;
+
+  dstr_ensure(&d, n);
+  n = e(c, (octet *)d.buf, n, nbits, earg);
+  if (n >= 0)
+    d.len += n;
+  if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) {
+    ok = 0;
+    fprintf(stderr, "*** %s encryption unpadding failed!\n", ename);
+    fprintf(stderr, "*** padding bits = %d\n", nbits);
+    if (eparam) {
+      fprintf(stderr, "*** encoding parameters = ");
+      type_hex.dump(eparam, stderr);
+      fputc('\n', stderr);
+    }
+    MP_EPRINTX("*** input", c);
+    if (rc < 0)
+      fprintf(stderr, "*** expected failure\n");
+    else {
+      fprintf(stderr, "*** expected: %d = ", rc); type_hex.dump(p, stderr);
+      fprintf(stderr, "\n*** computed: %d = ", n); type_hex.dump(&d, stderr);
+      fprintf(stderr, "\n");
+    }
+  }
+  mp_drop(c);
+  dstr_destroy(&d);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tvrfpad(int nbits,
+                  mp *c, dstr *m, int rc, dstr *p,
+                  const char *ename, dstr *eparam,
+                  rsa_vrfunpad *e, void *earg)
+{
+  dstr d = DSTR_INIT;
+  int n = (nbits + 7)/8;
+  int ok = 1;
+
+  dstr_ensure(&d, n);
+  n = e(c, m->len ? (octet *)m->buf : 0, m->len,
+       (octet *)d.buf, n, nbits, earg);
+  if (n >= 0)
+    d.len += n;
+  if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) {
+    ok = 0;
+    fprintf(stderr, "*** %s signature unpadding failed!\n", ename);
+    fprintf(stderr, "*** padding bits = %d\n", nbits);
+    MP_EPRINTX("*** input", c);
+    if (eparam) {
+      fprintf(stderr, "*** encoding parameters = ");
+      type_hex.dump(eparam, stderr);
+      fputc('\n', stderr);
+    }
+    fprintf(stderr, "*** message = "); type_hex.dump(m, stderr);
+    if (rc < 0)
+      fprintf(stderr, "\n*** expected failure\n");
+    else {
+      fprintf(stderr, "\n*** expected = %d: ", rc); type_hex.dump(p, stderr);
+      fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr);
+      fprintf(stderr, "\n");
+    }
+  }
+  mp_drop(c);
+  dstr_destroy(&d);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tencpub(rsa_pub *rp,
+                  dstr *p, int rc, mp *c,
+                  const char *ename, dstr *eparam, rsa_pad *e, void *earg)
+{
+  mp *d;
+  rsa_pubctx rpc;
+  int ok = 1;
+
+  rsa_pubcreate(&rpc, rp);
+  d = rsa_encrypt(&rpc, MP_NEW, p->buf, p->len, e, earg);
+  if (!d == !rc || (!rc && !MP_EQ(d, c))) {
+    ok = 0;
+    fprintf(stderr, "*** encrypt with %s padding failed!\n", ename);
+    MP_EPRINTX("*** key.n", rp->n);
+    MP_EPRINTX("*** key.e", rp->e);
+    if (eparam) {
+      fprintf(stderr, "*** encoding parameters = ");
+      type_hex.dump(eparam, stderr);
+      fputc('\n', stderr);
+    }
+    fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr);
+    if (rc)
+      fprintf(stderr, "\n*** expected failure\n");
+    else {
+      MP_EPRINTX("\n*** expected", c);
+      MP_EPRINTX("*** computed", d);
+    }
+  }
+  rsa_pubdestroy(&rpc);
+  rsa_pubfree(rp);
+  mp_drop(d);
+  mp_drop(c);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tsigpriv(rsa_priv *rp,
+                   dstr *p, int rc, mp *c,
+                   const char *ename, dstr *eparam, rsa_pad *e, void *earg)
+{
+  mp *d;
+  grand *r = fibrand_create(0);
+  rsa_privctx rpc;
+  int ok = 1;
+
+  rsa_privcreate(&rpc, rp, r);
+  d = rsa_sign(&rpc, MP_NEW, p->buf, p->len, e, earg);
+  if (!d == !rc || (!rc && !MP_EQ(d, c))) {
+    ok = 0;
+    fprintf(stderr, "*** sign with %s padding failed!\n", ename);
+    MP_EPRINTX("*** key.n", rp->n);
+    MP_EPRINTX("*** key.d", rp->d);
+    MP_EPRINTX("*** key.e", rp->e);
+    if (eparam) {
+      fprintf(stderr, "*** encoding parameters = ");
+      type_hex.dump(eparam, stderr);
+      fputc('\n', stderr);
+    }
+    fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr);
+    if (rc)
+      fprintf(stderr, "\n*** expected failure\n");
+    else {
+      MP_EPRINTX("\n*** expected", c);
+      MP_EPRINTX("\n*** computed", d);
+    }
+  }
+  rsa_privdestroy(&rpc);
+  rsa_privfree(rp);
+  mp_drop(d);
+  mp_drop(c);
+  GR_DESTROY(r);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tdecpriv(rsa_priv *rp,
+                   mp *c, int rc, dstr *p,
+                   const char *ename, dstr *eparam,
+                   rsa_decunpad *e, void *earg)
+{
+  rsa_privctx rpc;
+  dstr d = DSTR_INIT;
+  grand *r = fibrand_create(0);
+  int n;
+  int ok = 1;
+
+  rsa_privcreate(&rpc, rp, r);
+  n = rsa_decrypt(&rpc, c, &d, e, earg);
+  if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) {
+    ok = 0;
+    fprintf(stderr, "*** decryption with %s padding failed!\n", ename);
+    MP_EPRINTX("*** key.n", rp->n);
+    MP_EPRINTX("*** key.d", rp->d);
+    MP_EPRINTX("*** key.e", rp->e);
+    if (eparam) {
+      fprintf(stderr, "*** encoding parameters = ");
+      type_hex.dump(eparam, stderr);
+      fputc('\n', stderr);
+    }
+    MP_EPRINTX("*** input", c);
+    if (rc < 0)
+      fprintf(stderr, "*** expected failure\n");
+    else {
+      fprintf(stderr, "*** expected = %d: ", rc); type_hex.dump(p, stderr);
+      fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr);
+      fprintf(stderr, "\n");
+    }
+  }
+  rsa_privdestroy(&rpc);
+  rsa_privfree(rp);
+  mp_drop(c);
+  dstr_destroy(&d);
+  GR_DESTROY(r);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tvrfpub(rsa_pub *rp,
+                  mp *c, dstr *m, int rc, dstr *p,
+                  const char *ename, dstr *eparam,
+                  rsa_vrfunpad *e, void *earg)
+{
+  rsa_pubctx rpc;
+  dstr d = DSTR_INIT;
+  int n;
+  int ok = 1;
+
+  rsa_pubcreate(&rpc, rp);
+  n = rsa_verify(&rpc, c, m->len ? m->buf : 0, m->len, &d, e, earg);
+  if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) {
+    ok = 0;
+    fprintf(stderr, "*** verification with %s padding failed!\n", ename);
+    MP_EPRINTX("*** key.n", rp->n);
+    MP_EPRINTX("*** key.e", rp->e);
+    if (eparam) {
+      fprintf(stderr, "*** encoding parameters = ");
+      type_hex.dump(eparam, stderr);
+      fputc('\n', stderr);
+    }
+    MP_EPRINTX("*** input", c);
+    fprintf(stderr, "*** message = "); type_hex.dump(m, stderr);
+    if (rc < 0)
+      fprintf(stderr, "\n*** expected failure\n");
+    else {
+      fprintf(stderr, "\n*** expected = %d: ", rc); type_hex.dump(p, stderr);
+      fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr);
+      fprintf(stderr, "\n");
+    }
+  }
+  rsa_pubdestroy(&rpc);
+  rsa_pubfree(rp);
+  mp_drop(c);
+  dstr_destroy(&d);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+/*----- Deep magic --------------------------------------------------------*
+ *
+ * Wahey!  Whacko macro programming on curry and lager.  There's nothing like
+ * it.
+ */
+
+#define DECL_priv                                                      \
+  rsa_priv rp = { 0 };
+#define FUNC_priv                                                      \
+  rp.n = *(mp **)v++->buf;                                             \
+  rp.e = *(mp **)v++->buf;                                             \
+  rp.d = *(mp **)v++->buf;                                             \
+  rsa_recover(&rp);
+#define ARG_priv                                                       \
+  &rp,
+#define TAB_priv                                                       \
+  &type_mp, &type_mp, &type_mp,
+
+#define DECL_pub                                                       \
+  rsa_pub rp;
+#define FUNC_pub                                                       \
+  rp.n = *(mp **)v++->buf;                                             \
+  rp.e = *(mp **)v++->buf;
+#define ARG_pub                                                                \
+  &rp,
+#define TAB_pub                                                                \
+  &type_mp, &type_mp,
+
+#define DECL_pad                                                       \
+  int nbits;
+#define FUNC_pad                                                       \
+  nbits = *(int *)v++->buf;
+#define ARG_pad                                                                \
+  nbits,
+#define TAB_pad                                                                \
+  &type_int,
+
+#define DECL_enc                                                       \
+  dstr *p;                                                             \
+  int rc;                                                              \
+  mp *c;
+#define FUNC_enc                                                       \
+  p = v++;                                                             \
+  rc = *(int *)v++->buf;                                               \
+  c = *(mp **)v++->buf;
+#define ARG_enc                                                                \
+  p, rc, c,
+#define TAB_enc                                                                \
+  &type_hex, &type_int, &type_mp,
+
+#define DECL_sig DECL_enc
+#define FUNC_sig FUNC_enc
+#define ARG_sig ARG_enc
+#define TAB_sig TAB_enc
+
+#define DECL_dec                                                       \
+  mp *c;                                                               \
+  int rc;                                                              \
+  dstr *p;
+#define FUNC_dec                                                       \
+  c = *(mp **)v++->buf;                                                        \
+  rc = *(int *)v++->buf;                                               \
+  p = v++;
+#define ARG_dec                                                                \
+  c, rc, p,
+#define TAB_dec                                                                \
+  &type_mp, &type_int, &type_hex,
+
+#define DECL_vrf                                                       \
+  mp *c;                                                               \
+  dstr *m;                                                             \
+  int rc;                                                              \
+  dstr *p;
+#define FUNC_vrf                                                       \
+  c = *(mp **)v++->buf;                                                        \
+  m = v++;                                                             \
+  rc = *(int *)v++->buf;                                               \
+  p = v++;
+#define ARG_vrf                                                                \
+  c, m, rc, p,
+#define TAB_vrf                                                                \
+  &type_mp, &type_hex, &type_int, &type_hex,
+
+#define DECL_p1enc                                                     \
+  pkcs1 p1;                                                            \
+  dstr *ep;
+#define FUNC_p1enc                                                     \
+  p1.r = fib;                                                          \
+  ep = v++;                                                            \
+  p1.ep = ep->buf;                                                     \
+  p1.epsz = ep->len;
+#define ARG_p1enc                                                      \
+  "pkcs1", ep, pkcs1_cryptencode, &p1
+#define TAB_p1enc                                                      \
+  &type_hex
+
+#define DECL_p1sig DECL_p1enc
+#define FUNC_p1sig FUNC_p1enc
+#define ARG_p1sig                                                      \
+  "pkcs1", ep, pkcs1_sigencode, &p1
+#define TAB_p1sig TAB_p1enc
+
+#define DECL_p1dec DECL_p1enc
+#define FUNC_p1dec FUNC_p1enc
+#define ARG_p1dec                                                      \
+  "pkcs1", ep, pkcs1_cryptdecode, &p1
+#define TAB_p1dec TAB_p1enc
+
+#define DECL_p1vrf DECL_p1enc
+#define FUNC_p1vrf FUNC_p1enc
+#define ARG_p1vrf                                                      \
+  "pkcs1", ep, pkcs1_sigdecode, &p1
+#define TAB_p1vrf TAB_p1enc
+
+#define DECL_oaepenc                                                   \
+  oaep o;                                                              \
+  dstr *ep;
+#define FUNC_oaepenc                                                   \
+  o.r = fib;                                                           \
+  o.cc = gcipher_byname(v++->buf);                                     \
+  o.ch = ghash_byname(v++->buf);                                       \
+  ep = v++;                                                            \
+  o.ep = ep->buf;                                                      \
+  o.epsz = ep->len;
+#define ARG_oaepenc                                                    \
+  "oaep", ep, oaep_encode, &o
+#define TAB_oaepenc                                                    \
+  &type_string, &type_string, &type_hex
+
+#define DECL_oaepdec DECL_oaepenc
+#define FUNC_oaepdec FUNC_oaepenc
+#define ARG_oaepdec                                                    \
+  "oaep", ep, oaep_decode, &o
+#define TAB_oaepdec TAB_oaepenc
+
+#define DECL_psssig                                                    \
+  pss pp;
+#define FUNC_psssig                                                    \
+  pp.r = fib;                                                          \
+  pp.cc = gcipher_byname(v++->buf);                                    \
+  pp.ch = ghash_byname(v++->buf);                                      \
+  pp.ssz = *(int *)v++->buf;
+#define ARG_psssig                                                     \
+  "pss", 0, pss_encode, &pp
+#define TAB_psssig                                                     \
+  &type_string, &type_string, &type_int
+
+#define DECL_pssvrf DECL_psssig
+#define FUNC_pssvrf FUNC_psssig
+#define ARG_pssvrf                                                     \
+  "pss", 0, pss_decode, &pp
+#define TAB_pssvrf TAB_psssig
+
+#define TESTS(DO)                                                      \
+  DO(pad, enc, p1enc)                                                  \
+  DO(pad, dec, p1dec)                                                  \
+  DO(pad, sig, p1sig)                                                  \
+  DO(pad, vrf, p1vrf)                                                  \
+  DO(pub, enc, p1enc)                                                  \
+  DO(priv, dec, p1dec)                                                 \
+  DO(priv, sig, p1sig)                                                 \
+  DO(pub, vrf, p1vrf)                                                  \
+  DO(pad, enc, oaepenc)                                                        \
+  DO(pad, dec, oaepdec)                                                        \
+  DO(pub, enc, oaepenc)                                                        \
+  DO(priv, dec, oaepdec)                                               \
+  DO(pad, sig, psssig)                                                 \
+  DO(pad, vrf, pssvrf)                                                 \
+  DO(priv, sig, psssig)                                                        \
+  DO(pub, vrf, pssvrf)
+
+#define FUNCS(key, op, enc)                                            \
+  int t_##key##_##enc(dstr *v)                                         \
+  {                                                                    \
+    DECL_##key                                                         \
+    DECL_##op                                                          \
+    DECL_##enc                                                         \
+    fib->ops->misc(fib, GRAND_SEEDINT, 14);                            \
+    FUNC_##key                                                         \
+    FUNC_##op                                                          \
+    FUNC_##enc                                                         \
+    return (t##op##key(ARG_##key ARG_##op ARG_##enc));                 \
+  }
+
+#define TAB(key, op, enc)                                              \
+  { #enc "-" #key, t_##key##_##enc, { TAB_##key TAB_##op TAB_##enc } },
+
+static grand *fib;
+
+TESTS(FUNCS)
+
+static const test_chunk tests[] = {
+  TESTS(TAB)
+  { 0 }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  fib = fibrand_create(0);
+  test_run(argc, argv, tests, SRCDIR "/t/rsa");
+  GR_DESTROY(fib);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pub/rsa.h b/pub/rsa.h
new file mode 100644 (file)
index 0000000..2fb767d
--- /dev/null
+++ b/pub/rsa.h
@@ -0,0 +1,402 @@
+/* -*-c-*-
+ *
+ * The RSA public-key cryptosystem
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_RSA_H
+#define CATACOMB_RSA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+#ifndef CATACOMB_KEY_H
+#  include "key.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+#  include "mp.h"
+#endif
+
+#ifndef CATACOMB_PGEN_H
+#  include "pgen.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- RSA private and public keys --- */
+
+typedef struct rsa_pub {
+  mp *n;
+  mp *e;
+} rsa_pub;
+
+typedef struct rsa_priv {
+  mp *n, *p, *q, *q_inv;
+  mp *e, *d, *dp, *dq;
+} rsa_priv;
+
+/* --- RSA private and public key contexts --- *
+ *
+ * These are used to store information about `active' keys which will speed
+ * up the various operations.
+ */
+
+typedef struct rsa_privctx {
+  rsa_priv *rp;
+  grand *r;
+  mpmont nm, pm, qm;
+} rsa_privctx;
+
+typedef struct rsa_pubctx {
+  mpmont mm;
+  rsa_pub *rp;
+} rsa_pubctx;
+
+/* --- Encoding and decoding function schemas --- *
+ *
+ * See `oaep.h' and `pkcs1.h' for appropriate encoding functions.
+ */
+
+typedef mp *rsa_pad(mp */*d*/, const void */*m*/, size_t /*msz*/,
+                   octet */*b*/, size_t /*sz*/,
+                   unsigned long /*nbits*/, void */*p*/);
+
+typedef int rsa_decunpad(mp */*m*/, octet */*b*/, size_t /*sz*/,
+                        unsigned long /*nbits*/, void */*p*/);
+
+typedef int rsa_vrfunpad(mp */*s*/, const void */*m*/, size_t /*msz*/,
+                        octet */*b*/, size_t /*sz*/,
+                        unsigned long /*nbits*/, void */*p*/);
+
+/*----- Key fetching ------------------------------------------------------*/
+
+extern const key_fetchdef rsa_pubfetch[];
+#define RSA_PUBFETCHSZ 4
+
+extern const key_fetchdef rsa_privfetch[];
+#define RSA_PRIVFETCHSZ 12
+
+/* --- @rsa_pubfree@, @rsa_privfree@ --- *
+ *
+ * Arguments:  @rsa_pub *rp@, @rsa_priv *rp@ = pointer to key block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees an RSA key block.
+ */
+
+extern void rsa_pubfree(rsa_pub */*rp*/);
+extern void rsa_privfree(rsa_priv */*rp*/);
+
+/*----- RSA private key operations ----------------------------------------*/
+
+/* --- @rsa_privcreate@ --- *
+ *
+ * Arguments:  @rsa_privctx *rd@ = pointer to an RSA private key context
+ *             @rsa_priv *rp@ = pointer to RSA private key
+ *             @grand *r@ = pointer to random number source for blinding
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RSA private-key context.  Keeping a context
+ *             for several decryption or signing operations provides a minor
+ *             performance benefit.
+ *
+ *             The random number source may be null if blinding is not
+ *             desired.  This improves decryption speed, at the risk of
+ *             permitting timing attacks.
+ */
+
+extern void rsa_privcreate(rsa_privctx */*rd*/, rsa_priv */*rp*/,
+                          grand */*r*/);
+
+/* --- @rsa_privdestroy@ --- *
+ *
+ * Arguments:  @rsa_privctx *rd@ = pointer to an RSA decryption context
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys an RSA decryption context.
+ */
+
+extern void rsa_privdestroy(rsa_privctx */*rd*/);
+
+/* --- @rsa_privop@ --- *
+ *
+ * Arguments:  @rsa_privctx *rd@ = pointer to RSA private key context
+ *             @mp *d@ = destination
+ *             @mp *c@ = input message
+ *
+ * Returns:    The transformed output message.
+ *
+ * Use:                Performs an RSA private key operation.  This function takes
+ *             advantage of knowledge of the key factors in order to speed
+ *             up decryption.  It also blinds the ciphertext prior to
+ *             decryption and unblinds it afterwards to thwart timing
+ *             attacks.
+ */
+
+extern mp *rsa_privop(rsa_privctx */*rd*/, mp */*d*/, mp */*c*/);
+
+/* --- @rsa_qprivop@ --- *
+ *
+ * Arguments:  @rsa_priv *rp@ = pointer to RSA parameters
+ *             @mp *d@ = destination
+ *             @mp *c@ = input message
+ *             @grand *r@ = pointer to random number source for blinding
+ *
+ * Returns:    Correctly transformed output message
+ *
+ * Use:                Performs an RSA private key operation, very carefully.
+ */
+
+extern mp *rsa_qprivop(rsa_priv */*rp*/, mp */*d*/, mp */*c*/, grand */*r*/);
+
+/* --- @rsa_sign@ --- *
+ *
+ * Arguments:  @rsa_privctx *rp@ = pointer to an RSA private key context
+ *             @mp *d@ = where to put the result
+ *             @const void *m@ = pointer to input message
+ *             @size_t msz@ = size of input message
+ *             @rsa_pad *e@ = encoding procedure
+ *             @void *earg@ = argument pointer for encoding procedure
+ *
+ * Returns:    The signature, as a multiprecision integer, or null on
+ *             failure.
+ *
+ * Use:                Computes an RSA digital signature.
+ */
+
+extern mp *rsa_sign(rsa_privctx */*rp*/, mp */*d*/,
+                   const void */*m*/, size_t /*msz*/,
+                   rsa_pad */*e*/, void */*earg*/);
+
+/* --- @rsa_decrypt@ --- *
+ *
+ * Arguments:  @rsa_privctx *rp@ = pointer to an RSA private key context
+ *             @mp *m@ = encrypted message, as a multiprecision integer
+ *             @dstr *d@ = pointer to output string
+ *             @rsa_decunpad *e@ = decoding procedure
+ *             @void *earg@ = argument pointer for decoding procedure
+ *
+ * Returns:    The length of the output string if successful, negative on
+ *             failure.
+ *
+ * Use:                Does RSA decryption.
+ */
+
+extern int rsa_decrypt(rsa_privctx */*rp*/, mp */*m*/,
+                      dstr */*d*/, rsa_decunpad */*e*/, void */*earg*/);
+
+/*----- RSA public key operations -----------------------------------------*/
+
+/* --- @rsa_pubcreate@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
+ *             @rsa_pub *rp@ = pointer to RSA public key
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RSA public-key context.
+ */
+
+extern void rsa_pubcreate(rsa_pubctx */*rd*/, rsa_pub */*rp*/);
+
+/* --- @rsa_pubdestroy@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys an RSA public-key context.
+ */
+
+extern void rsa_pubdestroy(rsa_pubctx */*rd*/);
+
+/* --- @rsa_pubop@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
+ *             @mp *d@ = destination
+ *             @mp *p@ = input message
+ *
+ * Returns:    The transformed output message.
+ *
+ * Use:                Performs an RSA public key operation.
+ */
+
+extern mp *rsa_pubop(rsa_pubctx */*rd*/, mp */*d*/, mp */*p*/);
+
+/* --- @rsa_qpubop@ --- *
+ *
+ * Arguments:  @rsa_pub *rp@ = pointer to RSA parameters
+ *             @mp *d@ = destination
+ *             @mp *p@ = input message
+ *
+ * Returns:    Correctly transformed output message.
+ *
+ * Use:                Performs an RSA public key operation.
+ */
+
+extern mp *rsa_qpubop(rsa_pub */*rp*/, mp */*d*/, mp */*c*/);
+
+/* --- @rsa_encrypt@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rp@ = pointer to an RSA public key context
+ *             @mp *d@ = proposed destination integer
+ *             @const void *m@ = pointer to input message
+ *             @size_t msz@ = size of input message
+ *             @rsa_pad *e@ = encoding procedure
+ *             @void *earg@ = argument pointer for encoding procedure
+ *
+ * Returns:    The encrypted message, as a multiprecision integer, or null
+ *             on failure.
+ *
+ * Use:                Does RSA encryption.
+ */
+
+extern mp *rsa_encrypt(rsa_pubctx */*rp*/, mp */*d*/,
+                      const void */*m*/, size_t /*msz*/,
+                      rsa_pad */*e*/, void */*earg*/);
+
+/* --- @rsa_verify@ --- *
+ *
+ * Arguments:  @rsa_pubctx *rp@ = pointer to an RSA public key contxt
+ *             @mp *s@ = the signature, as a multiprecision integer
+ *             @const void *m@ = pointer to message to verify, or null
+ *             @size_t sz@ = size of input message
+ *             @dstr *d@ = pointer to output string, or null
+ *             @rsa_vfrunpad *e@ = decoding procedure
+ *             @void *earg@ = argument pointer for decoding procedure
+ *
+ * Returns:    The length of the output string if successful (0 if no output
+ *             was wanted); negative on failure.
+ *
+ * Use:                Does RSA signature verification.  To use a signature scheme
+ *             with recovery, pass in @m == 0@ and @d != 0@: the recovered
+ *             message should appear in @d@.  To use a signature scheme with
+ *             appendix, provide @m != 0@ and @d == 0@; the result should be
+ *             zero for success.
+ */
+
+extern int rsa_verify(rsa_pubctx */*rp*/, mp */*s*/,
+                     const void */*m*/, size_t /*sz*/, dstr */*d*/,
+                     rsa_vrfunpad */*e*/, void */*earg*/);
+
+/*----- Miscellaneous operations ------------------------------------------*/
+
+/* --- @rsa_gen@ --- *
+ *
+ * Arguments:  @rsa_priv *rp@ = pointer to block to be filled in
+ *             @unsigned nbits@ = required modulus size in bits
+ *             @grand *r@ = random number source
+ *             @unsigned n@ = number of attempts to make
+ *             @pgen_proc *event@ = event handler function
+ *             @void *ectx@ = argument for the event handler
+ *
+ * Returns:    Zero if all went well, nonzero otherwise.
+ *
+ * Use:                Constructs a pair of strong RSA primes and other useful RSA
+ *             parameters.  A small encryption exponent is chosen if
+ *             possible.
+ */
+
+extern int rsa_gen(rsa_priv */*rp*/, unsigned /*nbits*/,
+                  grand */*r*/, unsigned /*n*/,
+                  pgen_proc */*event*/, void */*ectx*/);
+
+/* --- @rsa_recover@ --- *
+ *
+ * Arguments:  @rsa_priv *rp@ = pointer to parameter block
+ *
+ * Returns:    Zero if all went well, nonzero if the parameters make no
+ *             sense.
+ *
+ * Use:                Derives the full set of RSA parameters given a minimal set.
+ */
+
+extern int rsa_recover(rsa_priv */*rp*/);
+
+/*----- Padding schemes ---------------------------------------------------*/
+
+/* --- PKCS1 padding --- */
+
+typedef struct pkcs1 {
+  grand *r;                            /* Random number source */
+  const void *ep;                      /* Encoding parameters block */
+  size_t epsz;                         /* Size of the parameter block */
+} pkcs1;
+
+extern rsa_pad pkcs1_cryptencode;
+extern rsa_decunpad pkcs1_cryptdecode;
+extern rsa_pad pkcs1_sigencode;
+extern rsa_vrfunpad pkcs1_sigdecode;
+
+/* --- OAEP --- */
+
+typedef struct oaep {
+  const gccipher *cc;                  /* Cipher class for masking */
+  const gchash *ch;                    /* Hash class for parameter block */
+  grand *r;                            /* Random number source */
+  const void *ep;                      /* Encoding parameters block */
+  size_t epsz;                         /* Size of the parameter block */
+} oaep;
+
+extern rsa_pad oaep_encode;
+extern rsa_decunpad oaep_decode;
+
+/* --- PSS --- */
+
+typedef struct pss {
+  const gccipher *cc;                  /* Cipher class for masking */
+  const gchash *ch;                    /* Hash class for choosing a seed */
+  grand *r;                            /* Random number source */
+  size_t ssz;                          /* Requested salt size */
+} pss;
+
+extern rsa_pad pss_encode;
+extern rsa_vrfunpad pss_decode;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/pub/t/bbs b/pub/t/bbs
new file mode 100644 (file)
index 0000000..65bbe2c
--- /dev/null
+++ b/pub/t/bbs
@@ -0,0 +1,14 @@
+# Test vectors for Blum-Blum-Shub generator
+
+bbs {
+  58618255351802153154518076227263324405595169368832105733339611861073310668957206153928098662820028322143309562326246028101842658621324089654810023510552099428926874474919949521150122806716423750640359105584279946965449493907636556236204117444242840921432253645386399913807490661488722966090824347967771475377
+  2
+  4a488784b0b74c53fe820e3416f67fb7f238898f711a8b5d3f3ea70b0ec264120b7bfaef30f841a979cb76ca9e9c6b01415e7618b5d6c4cc30db539852ca86d23b3527d566a76910d43ed9ba2b83596f3411354ae37c53cf0c2eab7e7e13ac7c58de83cbfd8b0a6b7cdcb7bcef92bf96a48e18124c2c21e7964a9b701b5ea4ab;
+}
+
+bbs-jump {
+  10300002644323831640029548502577413794096963710947992849414516873746495715149677373680896096678934650462228369293905743592335562158905193518665447759028003
+  8901308291494485065585437130459769427950766447948540080704500059827922533698081294071192603392538957644021072601596274962775430269633339980725226130767879
+  15
+  250;
+}
diff --git a/pub/t/dsa b/pub/t/dsa
new file mode 100644 (file)
index 0000000..f263901
--- /dev/null
+++ b/pub/t/dsa
@@ -0,0 +1,119 @@
+# Test vectors for DSA
+
+# --- About the tests ---
+#
+# There's only one test vector from FIPS-186.  The others I've made up.  The
+# tests themselves are split into parameter generation, signature generation,
+# and verification.
+
+gen {
+  # --- One that I made up ---
+
+  bbac0ab63411435cb72f1f95b16ab94c92c34211 256
+  bbac0ab63411435cb72f1f95b16ab94c92c34221 10
+  0x84d192cd06ae59691897fa409da6198d5269325d
+  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
+  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e;
+
+  # --- FIPS-186 test vector ---
+
+  d5014e4b60ef2ba8b6211b4062ba3224e0427dd3 512
+  d5014e4b60ef2ba8b6211b4062ba3224e0427dd3 105
+  0xc773218c737ec8ee993b4f2ded30f48edace915f
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802;
+
+  # --- And a full-sized vector ---
+
+  d1a29e27dfe4d60124cc41a59e012ae690408acfc3266d07f4eaeefdc9f8c70d2d2a338d
+  1024
+  d1a29e27dfe4d60124cc41a59e012ae690408acfc3266d07f4eaeefdc9f8c70d2d2a338d
+  66
+  0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9
+  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
+  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014;
+}
+
+sign {
+  # --- Quick simple test ---
+
+  0x84d192cd06ae59691897fa409da6198d5269325d
+  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
+  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  0x1234 "An example message"
+  649b1058e0fe7ee849d3cb00b8ec3053ad0793b8
+  2718bf488b981992b164e664224dd00ca1ed4e1c
+  5c085679fbfa9ee806781bdbd86a67dbf14df640;
+
+  # --- The FIPS-186 test vector ---
+
+  0xc773218c737ec8ee993b4f2ded30f48edace915f
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  0x2070b3223dba372fde1c0ffc7b2e3b498b260614
+  "abc"
+  358dad571462710f50e254cf1a376b2bdeaadfbf
+  8bac1ab66410435cb7181f95b16ab97c92b341c0
+  41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
+
+  # --- 1024-bit modulus test ---
+
+  0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9
+  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
+  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
+  0x23a252f60bae4907a8ed5b6203e2b1da32848cd9
+  "A message signed with a 1024-bit DSA key."
+  12ccb231683a3d9c13dca6fe882349537eebfd03
+  2a301061ac185440fbf595f8f7d894158b8d1897
+  51aedaa73cb8d47e07281d14dda5ea8c0ddf7503;
+}
+
+verify-good {
+  # --- Simple test ----
+
+  0x84d192cd06ae59691897fa409da6198d5269325d
+  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
+  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47
+  "An example message"
+  2718bf488b981992b164e664224dd00ca1ed4e1c
+  5c085679fbfa9ee806781bdbd86a67dbf14df640;
+
+  # --- The FIPS-186 test vector ---
+
+  0xc773218c737ec8ee993b4f2ded30f48edace915f
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
+  "abc"
+  8bac1ab66410435cb7181f95b16ab97c92b341c0
+  41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
+
+  # --- 1024-bit modulus test ---
+
+  0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9
+  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
+  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
+  0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074
+  "A message signed with a 1024-bit DSA key."
+  2a301061ac185440fbf595f8f7d894158b8d1897
+  51aedaa73cb8d47e07281d14dda5ea8c0ddf7503;
+}
+
+verify-bad {
+  0xc773218c737ec8ee993b4f2ded30f48edace915f
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
+  "abd"
+  8bac1ab66410435cb7181f95b16ab97c92b341c0
+  41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
+
+  0xc773218c737ec8ee993b4f2ded30f48edace915f
+  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
+  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
+  "abc"
+  18bac1ab66410435cb7181f95b16ab97c92b341c0
+  41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
+}
diff --git a/pub/t/gdsa b/pub/t/gdsa
new file mode 100644 (file)
index 0000000..9eeb4e0
--- /dev/null
@@ -0,0 +1,240 @@
+# 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 { secp160r1 }" sha
+  0xaa374ffc3ce144e6b073307972cb6d57b2a4e982
+  "abc"
+  0x7b012db7681a3f28b9185c8b2ac5d528decd52da
+  0xce2873e5be449563391feb47ddcba2dc16379191
+  0x3480ec1371a091a464b31ce47df0cb8aa2d98b54;
+
+  "ec { sect163k1 }" sha
+  0x3a41434aa99c2ef40c8495b2ed9739cb2155a1e0d
+  "abc"
+  0xa40b301cc315c257d51d442234f5aff8189d2b6c
+  0x994d2c41aa30e52952aea8462370471b2b0a34ac
+  0x152f95ca15da1997a8c449e00cd2aa2accb988d7f;
+
+  ## This one's from P1363:
+  ##   http://grouper.ieee.org/groups/1363/P1363/testvector.txt
+  "ec { ansi-c2tnb191v1 }" sha
+  0x340562e1dda332f9d2aec168249b5696ee39d0ed4d03760f
+  "abc"
+  0x3eeace72b4919d991738d521879f787cb590aff8189d2b69
+  0x038e5a11fb55e4c65471dcd4998452b1e02d8af7099bb930
+  0x0c9a08c34468c244b4e5d6b21b3c68362807416020328b6e;
+
+  "ec { nist-p256 }" sha256
+  0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa
+  "An example message"
+  0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c
+  0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6
+  0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a;
+
+  # --- Test for over-long hash ---
+
+  "ec { sect131r1 }" sha
+  0x85bd9fd28a7e7f915891208fbb2b05c0
+  "An example message"
+  0xee98d38c001731403af6fbf77356f8ea
+  0x1cba36e768c0247d537a744b7ea62e3b9
+  0x216e5d02a0b1fb11d6d2fc4b383dcb168;
+}
+
+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 { secp160r1 }" sha
+  "0x51b4496fecc406ed0e75a24a3c03206251419dc0,
+    0xc28dcb4b73a514b468d793894f381ccc1756aa6c"
+  "abc"
+  0xce2873e5be449563391feb47ddcba2dc16379191
+  0x3480ec1371a091a464b31ce47df0cb8aa2d98b54
+  0;
+
+  "ec { sect163k1 }" sha
+  "0x037d529fa37e42195f10111127ffb2bb38644806bc,
+    0x0447026eee8b34157f3eb51be5185d2be0249ed776"
+  "abc"
+  0x994d2c41aa30e52952aea8462370471b2b0a34ac
+  0x152f95ca15da1997a8c449e00cd2aa2accb988d7f
+  0;
+
+  ## This one's from P1363:
+  ##   http://grouper.ieee.org/groups/1363/P1363/testvector.txt
+  "ec { ansi-c2tnb191v1 }" sha
+  "0x5de37e756bd55d72e3768cb396ffeb962614dea4ce28a2e7,
+    0x55c0e0e02f5fb132caf416ef85b229bbb8e1352003125ba1"
+  "abc"
+  0x038e5a11fb55e4c65471dcd4998452b1e02d8af7099bb930
+  0x0c9a08c34468c244b4e5d6b21b3c68362807416020328b6e
+  0;
+
+  "ec { nist-p256 }" sha256
+  "0xcc2aecbc5c5f6d72cd7b937279d72a732abcf880ea47e012ebec77ddbca6ed40,
+    0x90f99cd799abc0ea571d0e02bad80f8323050b1adbdbff50060b6e1e6ebd8611"
+  "An example message"
+  0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6
+  0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a
+  0;
+
+  # --- Test for over-long hash ---
+
+  "ec { sect131r1 }" sha
+  "0x2218ba2b57a7821be97c0015b797d82fe, 0x666aed14fd7a2abf867c6fa222ab26fcc"
+  "An example message"
+  0x1cba36e768c0247d537a744b7ea62e3b9
+  0x216e5d02a0b1fb11d6d2fc4b383dcb168
+  0;
+
+  "ec { sect131r1 }" sha
+  "0x2218ba2b57a7821be97c0015b797d82fe, 0x666aed14fd7a2abf867c6fa222ab26fcc"
+  "An example messag"
+  0x1cba36e768c0247d537a744b7ea62e3b9
+  0x216e5d02a0b1fb11d6d2fc4b383dcb168
+  -1;
+
+  "ec { nist-b163 }" sha512
+  "0x385a32536d1cb46d10cf3034a3dd39eb25e4f5123,
+    0x29ee1edfa37d0f306c4da17b8d883f01ce3be4d46"
+  "qpwmoeqpofaosdaspdpqoweopdoagnqornifnasd"
+  0x0231b6a807f6af1aee0598768b3fabb863d14a7f8d
+  0x01c2f638e9dffe03b562e48ca4e1a380cf8c3055f1
+  0;
+}
diff --git a/pub/t/gkcdsa b/pub/t/gkcdsa
new file mode 100644 (file)
index 0000000..0835f83
--- /dev/null
@@ -0,0 +1,57 @@
+# 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/pub/t/rsa b/pub/t/rsa
new file mode 100644 (file)
index 0000000..2b2b27a
--- /dev/null
+++ b/pub/t/rsa
@@ -0,0 +1,391 @@
+# Test vectors for the completely mad RSA infrastructure tests
+
+p1sig-pad {
+  # nbits msg rc result eparam
+  256 "616263" 0
+    0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263
+    "cc22cc";
+  129 "616263" 0 0x0001ffffffffffffffff00cc22cc616263 "cc22cc";
+  128 "616263" -1 0 "cc22cc";
+}
+
+p1sig-priv {
+  # n e d msg rc result eparam
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001
+    0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9
+    "616263" 0
+    0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26
+    "cc22cc";
+
+  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
+    0x10001
+    0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81
+    "a9993e364706816aba3e25717850c26c9cd0d89d" 0
+    0x0f642606b7aaf99ff4bb5853c51e31a02c58d8c1c33f3c584d4edc58b08a16d5dc8064b6e198edcc4dc06666171a113619d7da16dfd96cebfdb5cc5050af6fab3d9f2ca8b8d6ece1d513fabc98a11fe37892fcf0827ea2e792427a69b3523504f46c55ed8af9a1c59687ca73c4baad7235a1a3faedec14f95ddfa8d0554739a8
+     "3021300906052b0e03021a05000414";
+}
+
+p1vrf-pad {
+  # nbits sig msg rc result eparam
+  256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263
+    "" 3 "616263" "cc22cc";
+  256 0x0101ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263
+    "" -1 "" "cc22cc";
+  256 0x0002ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263
+    "" -1 "" "cc22cc";
+  256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff01cc22cc616263
+    "" -1 "" "cc22cc";
+  256 0x0001ffffffffffffffff00cc22ccffffffffffffffffffffff00cc22cc616263
+    "" 18 "ffffffffffffffffffffff00cc22cc616263" "cc22cc";
+  256 0x0001ffffffffffffff00cc22ccffffffffffffffffffffffff00cc22cc616263
+    "" -1 "" "cc22cc";
+  256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc21cc616263
+    "" -1 "" "cc22cc";
+  256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616262
+    "" 3 "616262" "cc22cc";
+  129 0x0001ffffffffffffffff00cc22cc616263 "" 3 "616263" "cc22cc";
+  128 0x0001ffffffffffffff00cc22cc616263 "" -1 "" "cc22cc";
+}
+
+p1vrf-pub {
+  # n e sig msg rc result eparam
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001
+    0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26
+    "" 3 "616263" "cc22cc";
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001
+    0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26
+    "616263" 0 "" "cc22cc";
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001
+    0x27654c24f4ffefffc3bef7be8ae469db3069407702391eeb551ce9544621b63a
+    "" 18 "ffffffffffffffffffffff00cc22cc616263" "cc22cc";
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001
+    0xd980f3047ab74bc4e7bb99eeb17fcc657f50ee26146b7f2a9f982ef2f44cba
+    "" -1 "" "cc22cc";
+
+  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
+    0x10001
+    0x0f642606b7aaf99ff4bb5853c51e31a02c58d8c1c33f3c584d4edc58b08a16d5dc8064b6e198edcc4dc06666171a113619d7da16dfd96cebfdb5cc5050af6fab3d9f2ca8b8d6ece1d513fabc98a11fe37892fcf0827ea2e792427a69b3523504f46c55ed8af9a1c59687ca73c4baad7235a1a3faedec14f95ddfa8d0554739a8
+    "" 20 "a9993e364706816aba3e25717850c26c9cd0d89d"
+     "3021300906052b0e03021a05000414";
+}
+
+p1enc-pad {
+  # nbits msg rc ct eparam
+  256 "616263" 0
+    0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 "";
+  105 "616263" 0
+    0x0002efbd98524ad6419b00616263 "";
+  104 "616263" -1 0 "";
+}
+
+p1enc-pub {
+  # n e msg rc ct eparam
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001 "616263" 0
+    0x8f20a0fc778b7c55567f41c344d39bfcdaca04fd475f2290dc05c236585a68ca "";
+
+  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
+    0x10001
+    "616263"
+    0
+    0xaf91f5abf4766348eaaff1e8e5561b10bc1e3b15b6dff221869389a70d371d649b6cf78c5444f5d03a9feac12d5741cbc340e09d112063b1486568fca7c59b4c90604f0b6243eccc18901afa9001fc5f669108ebc75d6713e28d4a081723184332d4fb2ca391e3247a76c85323e66352d60c0a6ce8240af6f0583058820b1e32
+    "";
+}
+
+p1dec-pad {
+  # nbits msg rc pt eparam
+  256 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263
+    3 "616263" "";
+  105 0x0002efbd98524ad6419b00616263
+    3 "616263" "";
+  104 0x0002efbd98524ad64100616263
+    -1 "" "";
+  256 0x0002efbdfc524ad6419b00537a59b42a4662918436d6e0e4804b6b1000616263
+    21 "537a59b42a4662918436d6e0e4804b6b1000616263" "";
+  256 0x0002efbdfc524ad6419b00537a59b42a4662918436d6e0e4804b6b1000616263
+    3 "616263" "537a59b42a4662918436d6e0e4804b6b1000";
+  256 0x0102efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263
+    -1 "" "";
+  256 0x0001efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263
+    -1 "" "";
+  256 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263
+    3 "616263" "";
+  256 0x0002efbdfc524ad6410065537a59b42a4662918436d6e0e4804b6b1000616263
+    -1 "" "";
+}
+
+p1dec-priv {
+  # p e d msg rc pt eparam
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001
+    0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9
+    0x8f20a0fc778b7c55567f41c344d39bfcdaca04fd475f2290dc05c236585a68ca
+    3 "616263" "";
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001
+    0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9
+    0x19d6408010f0c2722b44cd4d5e006b6ffaa634aa225d727fa37c7c6ec29c5155
+    21 "537a59b42a4662918436d6e0e4804b6b1000616263" "";
+  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
+    0x10001
+    0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9~
+    0x952aa4893cd2620e4942f449529ea2f7105b9d67e041a676259fb986bc507b7d
+    -1 "" "";
+
+  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
+    0x10001
+    0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81
+    0xaf91f5abf4766348eaaff1e8e5561b10bc1e3b15b6dff221869389a70d371d649b6cf78c5444f5d03a9feac12d5741cbc340e09d112063b1486568fca7c59b4c90604f0b6243eccc18901afa9001fc5f669108ebc75d6713e28d4a081723184332d4fb2ca391e3247a76c85323e66352d60c0a6ce8240af6f0583058820b1e32
+    3 "616263" "";
+}
+
+oaepenc-pad {
+  # nbits msg rc ct mgf hash eparam
+  1024 "616263" 0
+    0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffed
+    sha-mgf sha "";
+}
+
+oaepdec-pad {
+  # nbits msg rc pt mgf hash eparam
+  1024
+    0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffed
+    3 "616263" sha-mgf sha "";
+  1024
+    0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffec
+    -1 "" sha-mgf sha "";
+}
+
+oaepenc-pub {
+  # n e msg rc ct mgf hash eparam
+  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
+    0x10001
+    "616263"
+    0
+    0xa5c94083e56aeff3490a4abd63251b332a26cca0e521815af5d2915b2422fbc7e672c8e67c3dea8c355e0b999a1f8acc905cc4437a6ddc5a7d6f54489436bd24922f83d75629d2cb92a7963d010727ef8981c3c01971962f454e42d54996e74617022d7513505fef7b1f7d5dbdeccc4673594d01f943236e4439b3175c3f801b
+    sha-mgf sha "";
+}
+
+oaepdec-priv {
+  # n e d msg rc pt mgf hash eparam
+  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
+    0x10001
+    0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81
+    0x6ae9901c7c40104b38e10097bd42212afd437867ee4c72e7e81d7486b8721aeab493be40e3bd4335bef05c76bba1a2e30795e76fe04517d5f8fa87d16756002b061674594cb85c32b96c3a690e135d64923bd7551c45b6b89ebb89941377ce02d5c801feb33c20ebacf8dd6d6bd44d4f29bc2ff4dca35db52da545ef97733955
+    3 "616263" sha-mgf sha "";
+  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
+    0x10001
+    0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81
+    0x6ae9901c7c40104b38e10097bd42212afd437867ee4c72e7e81d7486b8721aeab493be40e3bd4335bef05c76bba1a2e30795e76fe04517d5f8fa87d16756002b061674594cb85c32b96c3a690e135d64923bd7551c45b6b89ebb89941377ce02d5c801feb33c20ebacf8dd6d6bd44d4f29bc2ff4dca35db52da545ef97733954
+    -1 "" sha-mgf sha "";
+}
+
+psssig-pad {
+  # nbits msg rc result mgf hash saltsz
+  256 "a9993e364706816aba3e25717850c26c9cd0d89d" 0
+    0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
+    sha-mgf sha 10;
+  256 "a9993e364706816aba3e25717850c26c9cd0d89d" -1
+    0 sha-mgf sha 20;
+  273 "a9993e364706816aba3e25717850c26c9cd0d89d" 0
+    0xb5c91e4c0c00aaaffba7d581011366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
+    sha-mgf sha 10;
+
+  1024 "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0
+    0x2d22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc
+    sha-mgf sha 20;
+  1025 "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0
+    0xad22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc
+    sha-mgf sha 20;
+  1024 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+  1025 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+  1026 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+  1027 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+  1028 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0x559bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+  1029 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+  1030 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+  1031 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0x2d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+  1032 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
+    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    sha256-mgf sha256 32;
+
+  2048 "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" 0
+    0x106373ce481fe7e268a5a66f8b281e17719e23e1fa5f9d6bdfb2da5451a3fe7afab07969d8acdb904c723830280f78124717e87edf05a58626e191281b9c82edeceb02d1fc8dfab7d3e941ef3a13ea27ea51609e47dd727a784f66dc189fb8527093060ee5f982f7072e3f8a5fac4edcadd9ff107d6c8a99e9b52680a046b6f984c323afbb194e94bf2ab014804e791af59b254c164ef24af7c726b314a127febc4d026c700cbe08076d4e63be94581f6b353adbd3c754864d314f0039b3c7cae177c8be11a426358d523a1f0c97a0626aa9d565751229d488d96e168e7305cdc3d256401e6b865c246d686f0d8a673603038c464a60753dcd2b0f2a552514bc
+    sha256-mgf sha256 32;
+}
+
+pssvrf-pad {
+  # nbits sig msg rc result mgf hash saltsz
+  256
+    0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
+    "a9993e364706816aba3e25717850c26c9cd0d89d" 0 "" sha-mgf sha 10;
+  256
+    0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
+    "a9993e364706816aba3e25717850c26c9cd0d89e" -1 "" sha-mgf sha 10;
+  256
+    0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bd
+    "a9993e364706816aba3e25717850c26c9cd0d89d" -1 "" sha-mgf sha 10;
+  256
+    0x3526a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
+    "a9993e364706816aba3e25717850c26c9cd0d89d" -1 "" sha-mgf sha 10;
+
+  1024
+    0x2d22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc
+    "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 ""
+    sha-mgf sha 20;
+  1025
+    0xad22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc
+    "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 ""
+    sha-mgf sha 20;
+  1024
+    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+  1025
+    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+  1026
+    0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+  1027
+    0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+  1028
+    0x559bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+  1029
+    0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+  1030
+    0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+  1031
+    0x2d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+  1032
+    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
+    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
+    sha256-mgf sha256 32;
+
+  768
+    0x3314e642649adf696651f34108408fab0e770a617a3f7d44d981add5ca88841dc57d531bb885075f150b93e96f6e7580e18b98e1ece12826bbfe4d92dec1bc05c2e95ea362e08dd4cbf162b4abff6a9ed26b822d986ec32bdd698d162262abbc
+    "2923be84e16cd6ae529049f1f1bbe9ebb3a6db3c" 0 ""
+    sha-mgf sha 20;
+  1024
+    0x29d14565cf1ad3966ad25ff10aa825c2adeb31cc431a9a388ee53afef2ea2bc3c40b54523fd6bec5d7eabbea2b969e25d1bd62086834ccc48f256d876a4065214ac4343dfba87091563921299adee851e9d0dfba8db14ae6972cc8ce569f32c01db77d291279a82c30220faa16d83b1740cb535aa7f594905d7c91122f67ffbc
+    "1cdbae32209a50ee407836fd124932f69e7d49dc" 0 ""
+    sha-mgf sha 20;
+  768
+    0x1de4193d961d4c2f5737656c910d9d5262b09d463a0b8c7c426f92f91ea8db83be870d68ab125af488bef0596b15fb2416b2836c08bc6af31ee3c215c817c9c17ee84d813dc712676c86d4c41e69074eb1646fdc80c8a59e4bad819af27104bc
+    "b2eac9cc53bf67d6bf14d67e2ddc8e6683ef574961ff698f61cdd11e9d9c1672" 0 ""
+    sha256-mgf sha256 32;
+  1024
+    0xb9317ad66af4a49e3d2e987c340e776ed3b7496d311813fd6374e743fd5156630453541fc82733b4c0fd44a869e8c541ede9692ea6deb7cd52dbb4fb66b0f5a9a07e84e886ee5520faadf4fc7d646f1987bf19ad3d669dd9df57eec3de510148a6d349b8626c20ffb6d95f09c0af54b276626da745502e9c2bb5496e1a29bc
+    "0515073b33821f187092da6454ceb1853e6915f8466a0496730ed9162f6768d4" 0 ""
+    sha256-mgf sha256 32;
+  1025
+    0x0a9228b191158744e277bd223ada3c227429e5d64884007a748d74abca2d55358c1bb21cdf2666589ffd6cdfd458c877620009ebace86e7fc88c6d0acb99e5432f1af5705908e332e1a071e3700f0a0310b531589e79fd40922f0780b239cdd489816be7fdee9f6353f7f9f182abf873eb32e83586011fce20ae957bc66728bc
+    "a90b87978c2ff1151d9a95c19be1c07ee9a89aa786c2b554bf9ae7d923d15590" 0 ""
+    sha256-mgf sha256 32;
+  1026
+    0x016ecc969a03557d5fb257119251316ec4d8630d66bd6c18e93bc5c69a3a1d68431cd298f92db41a5f017874f05054224da5d75c012855febdf801c77145c8067c714c5c218f555b1e335a73f3ca6228a9723fa074173c7941200526c3a8ad81bb25427c84bdf82052021590cb5fd6aa44d052734b9112d1063276995572300ebc
+    "cbc2033f4107840f1405651b2861c9c5e72c8e463608dcf3a88dfebef2eb71ff" 0 ""
+    sha256-mgf sha256 32;
+  1027
+    0x031a071405323cf4ef20cc186ca5edc492fa2a7158565275d1d7cce302dcb10853625822b6887ab61c0713c332eb188b708690dee268ecc1e8b07f34106a1437246034347340bb65f39d8f002fe6ad5d826cce3c44d121924ba2a2fe265200523940b2f60918202839190fd4c50960be706863daf99b34cf7a152f720cbd9a2bbc
+    "6653330bcba1105e4cec034c73e605b4310eaaadcfd5b0ca27ffd89d144df479" 0 ""
+    sha256-mgf sha256 32;
+  1028
+    0x032e267380b21f98eb301bfd28c95af795a29864dfd801146c6878d9755669a6a8ef0090c574d5e7b716e4bf32128787db838c1df23fa418406e124fe4c031e706e31e27982810561d0c77d391b7718a2dd12b583987fe1c3c07436d457e039c3f4a6bbc2b6e765670762138ec2f22c3b1ce84ff422c08479f90abeb39986abdbc
+    "d5cfd3a195ce5abe65272af607ada1be65a6b4c9c0693234092c4d018f1756c6" 0 ""
+    sha256-mgf sha256 32;
+  1029
+    0x034a4f060407d55bea14998785fef3dc09240b2145350d7aaa8e7b0114ba531209e8a5d9cfa1f8c364f21a94d302968a0ba7905ac188da019da0b68c27e42bf513bde915eaf96a91f300a32bbd723cdf66510f1ecb964ed807679dacf7ada3903e7234167bd3dc49e8b59749a396dcdc3f06d3751d0b58216d1ea3760fface17bc
+    "608f6e3c7bf45b628a8a8f275cf7e5874a3b329b614084c6c3b1a7304a10ee75" 0 ""
+    sha256-mgf sha256 32;
+  1030
+    0x0aab7297cc92ae458f1d4d3b275eab7b2c65af1a7ab4fde8f5ff78b21474751b3b245f9b32b3c7d22ca677ccc882957cfdf3583372a8038918c27e9efd9743e6673d935ade4d3a4c3029c81c56d9a900e3f403de752d816d2e224621db32baf716b7625598aae00a336df65970076a2421e82925b9496b45e889f3b91ff5c100bc
+    "0d2bb614ecbbb82f73e2517e7d1dd884d31f01be506b16d6432183191518982b" 0 ""
+    sha256-mgf sha256 32;
+  1031
+    0x0a1a81c6c71b542db6ce4aac600e96d5280f31dc6d91d201a0a83f3c2fb9a1baebf0d77b5aadd2358de635eca6f802a3adfe33c4e32e321276e102bb74dbb23aafcd8ca3806abd496a55c88223478a21ce0ee9946b93d0f94dcff307f0f33e41b3ab282016b7cda40bd8a3b1a909fb9396afff909f9bb6e44a3d70240e9ec9eabc
+    "f25b81a07f5ccb1d36e949740255d2ac1a0bf7a92623405ba333b9358868ade1" 0 ""
+    sha256-mgf sha256 32;
+
+# This one's WRONG!
+#  1024
+#    0x696c23c434d74b91841724d0cca8318938551593969a8c31468377335252f2e18cbc11902b09ea494297ac729872b459d852018bc0634e95f9a1e80f09b55b321a1cc3b5f5f8c66a6bc91f42f154c6b4406606f3e9dda02eefe343cd80436a09e013a6e6b1190d222279e6f790223c315f367f3a212ff6f1c838c728c7fafabc
+#    "29d7a859cc0dea26ed554e8084d92bf837b8edd57aa05c4efa9f21fc3c36858e81b07dbfeeb1e485e912078bc6ec66e2" 0 ""
+#    sha384-mgf sha384 48;
+
+  2048
+    0x7a14b3a1fbf3371d6a607e3a401b43937f77d1f0960f0caee52c3a962d097cbcf7659ee7a26d7da421bfdf650c02a275f7c839eccdb77eb8bd73e807f251a9b8dcf6c7bbde426e1cd2b05f5e0ca53d4a2e7487f56bde022384d581208489a835b0e4f23aa713497d7ad0b1ba3a0d3fdf1798e40f5add1ab96c1ca17006138941b87fa1bc7bdb93c49befa6e2e4cdf6a144e55525d14f995ebbc452f8dd31ee07ddee8935454e5d484132e3799978eeb15f66444e342e425ca456c4ed13e3504e1dfef8d29de9086e027958a0ab7975f642f8d061c94b379b2ddf8b5f5540f2c94a9f50ce509d9bc7f21c8e5cbca7c783c78b2a8235f4ec536b129e6f105d3bbc
+    "a744b33e02b80487b63022dde456dd617b6e3d8c5ce7c467bc2ff2ffc9cc0f1390a924111ead4b41e592283f62f5b8aefda9492b3151ca80ec2e451a3935aabe" 0 ""
+    sha512-mgf sha512 64;
+
+  2048
+    0x106373ce481fe7e268a5a66f8b281e17719e23e1fa5f9d6bdfb2da5451a3fe7afab07969d8acdb904c723830280f78124717e87edf05a58626e191281b9c82edeceb02d1fc8dfab7d3e941ef3a13ea27ea51609e47dd727a784f66dc189fb8527093060ee5f982f7072e3f8a5fac4edcadd9ff107d6c8a99e9b52680a046b6f984c323afbb194e94bf2ab014804e791af59b254c164ef24af7c726b314a127febc4d026c700cbe08076d4e63be94581f6b353adbd3c754864d314f0039b3c7cae177c8be11a426358d523a1f0c97a0626aa9d565751229d488d96e168e7305cdc3d256401e6b865c246d686f0d8a673603038c464a60753dcd2b0f2a552514bc
+    "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" 0 ""
+    sha256-mgf sha256 32;
+}
+
+psssig-priv {
+  # n e d msg rc sig mgf hash saltsz
+  0x6af87c8c97ae0c7668bc361ff1c358198309c80cd8a74a6d9d9cc846ea63ede9
+    0x10001
+    0x30ec4a0a5854d733a5ddc3e3584469f0a7d4b1f0cb38b8cfb04483c68b77a01
+    "a9993e364706816aba3e25717850c26c9cd0d89d" 0
+    0x2b484543397da31ca7aaf774c4b19acd69eb8bc230b6d98a2ae10798793bd53f
+    sha-mgf sha 10;
+
+  0x560e64d28a2352ab7930aeb78fede05837b4fb868f0e6920d3108bcd57c8fe019d20d5df7ccc1ba15b5b0f850282739f3c76f0f592e2120573551c0146c3cd6d165cfd3bedfdc131bed468f0b36a7f07d47caf5ec83c0790354fba9f5027394618fa1a342b752a028addc86765061ca680d748190befe34d0f4032ad5639b148d033c3b3914f0b4ef9a1a7e167bdfe22a7954a8542286f562c226c393d48a91a1b7843831f8133e7214d65a5874954ecd8b10002dfe9847f5e8061cfb77d2b5defc6ce63d553aa79d1fe75e90fab2fdb78f55d8348063717a6335367d8316070a44847a49ba53be57f44bc6d6108aecbe0efbf81a2b51cbe98407166d89e89a9
+    0x10001
+    0x27f0e74fa6a8ad5a83d59a09fd85f10dd0d131baaad40bec1dba3cc0d24129cf72efc60443e671de8ac9b162d11eddee26c0a7a6bb052d4b155407baf9eeaffe351674bc6781d2b4b576ddbbf5f1f4429c974047f4149488148e4c365c1bd063ddfcdac3a2f5eec91e4dc091689c95189c8d0edbfd23da722e25643ffa58ad94ec06f6ab21fc8805b09066ffe3849e2d5536cf8a7385e62526989605c9fefbd9092ddb51bd887ee71cababab3a150b34d7de54d01c19987438bef4672208418e51bf49cdbe1825f16e2764c58aab339afbb4f673914646d2a191fec4f7a503e512841a2cccdc8852c0f348b8aedea3123747d20c3c580c38b438ef5fde3608bf
+    "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884"
+    0
+    0x35fcbf7c5a69bd892dbf2ee88e53e40fe58ecddb4cf7c8885b228bfa9c24730ac554e20c65d82fc98d67a7805343450b1712a5f8c5ed6970c4310e06f65a9758d33e1c9dedec7178507da977a5ab76635d9f824b136abb855210caf851700bb57eb3aef7de61b217ae79ee4d6ad7c1a94279d9f8a425e06a0e4024d4c5b709ce1af6d09a26ce346f0a7eb36675fdbe1367f3d040ab7e18235b8090f91c355ee07425e3f4adf302e741be55959ac0f31075ccf1beef20e2f90693a82a30a48969c5ef32bc779ce84961b6a8d3ae0228cc520e2c644067bae96f14d90ceda2c8d00c97de3895d434a001d3cca244777fba4e0f5b5ed01c103842652c6402d2525b
+    sha256-mgf sha256 32;
+}
+
+pssvrf-pub {
+  # n e sig msg rc result mgf hash saltsz
+  0x6af87c8c97ae0c7668bc361ff1c358198309c80cd8a74a6d9d9cc846ea63ede9
+    0x10001
+    0x2b484543397da31ca7aaf774c4b19acd69eb8bc230b6d98a2ae10798793bd53f
+    "a9993e364706816aba3e25717850c26c9cd0d89d" 0 "" sha-mgf sha 10;
+
+  0x560e64d28a2352ab7930aeb78fede05837b4fb868f0e6920d3108bcd57c8fe019d20d5df7ccc1ba15b5b0f850282739f3c76f0f592e2120573551c0146c3cd6d165cfd3bedfdc131bed468f0b36a7f07d47caf5ec83c0790354fba9f5027394618fa1a342b752a028addc86765061ca680d748190befe34d0f4032ad5639b148d033c3b3914f0b4ef9a1a7e167bdfe22a7954a8542286f562c226c393d48a91a1b7843831f8133e7214d65a5874954ecd8b10002dfe9847f5e8061cfb77d2b5defc6ce63d553aa79d1fe75e90fab2fdb78f55d8348063717a6335367d8316070a44847a49ba53be57f44bc6d6108aecbe0efbf81a2b51cbe98407166d89e89a9
+    0x10001
+    0x35fcbf7c5a69bd892dbf2ee88e53e40fe58ecddb4cf7c8885b228bfa9c24730ac554e20c65d82fc98d67a7805343450b1712a5f8c5ed6970c4310e06f65a9758d33e1c9dedec7178507da977a5ab76635d9f824b136abb855210caf851700bb57eb3aef7de61b217ae79ee4d6ad7c1a94279d9f8a425e06a0e4024d4c5b709ce1af6d09a26ce346f0a7eb36675fdbe1367f3d040ab7e18235b8090f91c355ee07425e3f4adf302e741be55959ac0f31075ccf1beef20e2f90693a82a30a48969c5ef32bc779ce84961b6a8d3ae0228cc520e2c644067bae96f14d90ceda2c8d00c97de3895d434a001d3cca244777fba4e0f5b5ed01c103842652c6402d2525b
+    "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884"
+    0 ""
+    sha256-mgf sha256 32;
+}
diff --git a/qdparse.c b/qdparse.c
deleted file mode 100644 (file)
index 9615bb5..0000000
--- a/qdparse.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*-c-*-
- *
- * $Id: qdparse.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Quick-and-dirty parser
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <ctype.h>
-#include <string.h>
-
-#include "qdparse.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @qd_skipspc@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *
- * Returns:    ---
- *
- * Use:                Skips spaces in the string.  No errors.
- */
-
-void qd_skipspc(qd_parse *qd)
-{
-  while (isspace((unsigned char)*qd->p))
-    qd->p++;
-}
-
-/* --- @qd_delim@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *             @int ch@ = character to compare with
- *
- * Returns:    Nonzero if it was, zero if it wasn't.
- *
- * Use:                Checks the next (non-whitespace) character is what we
- *             expect.  If it is, the character is eaten; otherwise it's no
- *             big deal.
- */
-
-int qd_delim(qd_parse *qd, int ch)
-{
-  qd_skipspc(qd);
-  if (*qd->p != ch)
-    return (0);
-  qd->p++;
-  return (1);
-}
-
-/* --- @qd_enum@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *             @const char *e@ = list of enum strings, space separated
- *
- * Returns:    Index of the string matched, or @-1@.
- *
- * Use:                Matches a keyword.
- */
-
-int qd_enum(qd_parse *qd, const char *e)
-{
-  size_t n;
-  int i = 0;
-
-  qd_skipspc(qd);
-  for (;;) {
-    e += strspn(e, ", ");
-    if (!*e) break;
-    n = strcspn(e, ", ");
-    if (strncmp(qd->p, e, n) == 0 && !isalnum((unsigned char)qd->p[n])) {
-      qd->p += n;
-      return (i);
-    }
-    i++; e += n;
-  }
-  qd->e = "unrecognized keyword";
-  return (-1);
-}
-
-/* --- @qd_getmp@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *
- * Returns:    The integer extracted, or null.
- *
- * Use:                Parses a multiprecision integer from a string.
- */
-
-mp *qd_getmp(qd_parse *qd)
-{
-  char *q;
-  mp *m;
-
-  qd_skipspc(qd);
-  m = mp_readstring(MP_NEW, qd->p, &q, 0);
-  if (m && !isalnum((unsigned char)*q))
-    qd->p = q;
-  else {
-    mp_drop(m);
-    qd->e = "bad number";
-  }
-  return (m);
-}
-
-/* --- @qd_eofp@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *
- * Returns:    Nonzero if at EOF, zero otherwise.
- */
-
-int qd_eofp(qd_parse *qd)
-{
-  qd_skipspc(qd);
-  return (!*qd->p);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/qdparse.h b/qdparse.h
deleted file mode 100644 (file)
index f6696e4..0000000
--- a/qdparse.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* -*-c-*-
- *
- * $Id: qdparse.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Quick-and-dirty parser
- *
- * (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.
- */
-
-#ifndef CATACOMB_QDPARSE_H
-#define CATACOMB_QDPARSE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct qd_parse {
-  const char *p;                       /* Where we are right now */
-  const char *e;                       /* Error string (output) */
-} qd_parse;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @qd_skipspc@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *
- * Returns:    ---
- *
- * Use:                Skips spaces in the string.  No errors.
- */
-
-extern void qd_skipspc(qd_parse */*qd*/);
-
-/* --- @qd_delim@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *             @int ch@ = character to compare with
- *
- * Returns:    Nonzero if it was, zero if it wasn't.
- *
- * Use:                Checks the next (non-whitespace) character is what we
- *             expect.  If it is, the character is eaten; otherwise it's no
- *             big deal.
- */
-
-extern int qd_delim(qd_parse */*qd*/, int /*ch*/);
-
-/* --- @qd_enum@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *             @const char *e@ = list of enum strings, space separated
- *
- * Returns:    Index of the string matched, or @-1@.
- *
- * Use:                Matches a keyword.
- */
-
-extern int qd_enum(qd_parse */*qd*/, const char */*e*/);
-
-/* --- @qd_getmp@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *
- * Returns:    The integer extracted, or null.
- *
- * Use:                Parses a multiprecision integer from a string.
- */
-
-extern mp *qd_getmp(qd_parse */*qd*/);
-
-/* --- @qd_eofp@ --- *
- *
- * Arguments:  @qd_parse *qd@ = context
- *
- * Returns:    Nonzero if at EOF, zero otherwise.
- */
-
-extern int qd_eofp(qd_parse */*qd*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rabin.c b/rabin.c
deleted file mode 100644 (file)
index 1b1130b..0000000
--- a/rabin.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Miller-Rabin primality test
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpbarrett.h"
-#include "mpmont.h"
-#include "pgen.h"
-#include "rabin.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rabin_create@ --- *
- *
- * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
- *             @mp *m@ = pointer to number to test
- *
- * Returns:    Zero on success, nonzero on failure.
- *
- * Use:                Precomputes some useful values for performing the
- *             Miller-Rabin probabilistic primality test.
- */
-
-int rabin_create(rabin *r, mp *m)
-{
-  mp *m1 = mp_sub(MP_NEW, m, MP_ONE);
-  if (mpmont_create(&r->mm, m)) {
-    MP_DROP(m1);
-    return (-1);
-  }
-  r->r = mp_odd(MP_NEW, m1, &r->s);
-  r->m1 = mp_sub(MP_NEW, m, r->mm.r);
-  mp_drop(m1);
-  return (0);
-}
-
-/* --- @rabin_destroy@ --- *
- *
- * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
- *
- * Returns:    ---
- *
- * Use:                Disposes of a Rabin-Miller context when it's no longer
- *             needed.
- */
-
-void rabin_destroy(rabin *r)
-{
-  mp_drop(r->r);
-  mp_drop(r->m1);
-  mpmont_destroy(&r->mm);
-}
-
-/* --- @rabin_test@, @rabin_rtest@ --- *
- *
- * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
- *             @mp *g@ = base to test the number against
- *
- * Returns:    Either @PGEN_FAIL@ if the test failed, or @PGEN_PASS@
- *             if it succeeded.
- *
- * Use:                Performs a single iteration of the Rabin-Miller primality
- *             test.  The @rtest@ variant assumes that %$g$% is either
- *             already in Montgomery representation, or you don't care.
- */
-
-int rabin_rtest(rabin *r, mp *g)
-{
-  mp *y;
-  mp *dd, *spare = MP_NEW;
-  size_t j;
-  int rc = PGEN_FAIL;
-
-  /* --- Calculate %$y R = g^r R \bmod m$% --- *
-   *
-   * If %$y = 1$% or %$y = m - 1$% then %$m$% is prime.  If course, note that
-   * @y@ here has an extra factor of %$R$%.
-   */
-
-  y = mpmont_expr(&r->mm, MP_NEW, g, r->r);
-  if (MP_EQ(y, r->mm.r) || MP_EQ(y, r->m1)) {
-    rc = PGEN_PASS;
-    goto done;
-  }
-
-  /* --- Now for the main loop --- *
-   *
-   * If %$y^{2^j} \ne m - 1$% for any %$0 \le j < s$% then %$m$% is
-   * composite.  Of course, %$j = 0$% has already been tested.
-   */
-
-  for (j = 1; j < r->s; j++) {
-    dd = mp_sqr(spare, y);
-    dd = mpmont_reduce(&r->mm, dd, dd);
-    spare = y; y = dd;
-    if (MP_EQ(y, r->mm.r))
-      break;
-    if (MP_EQ(y, r->m1)) {
-      rc = PGEN_PASS;
-      break;
-    }
-  }
-
-  /* --- Done --- */
-
-done:
-  if (spare != MP_NEW)
-    MP_DROP(spare);
-  MP_DROP(y);
-  return (rc);
-}
-
-int rabin_test(rabin *r, mp *g)
-{
-  int rc;
-  g = mpmont_mul(&r->mm, MP_NEW, g, r->mm.r2);
-  rc = rabin_rtest(r, g);
-  mp_drop(g);
-  return (rc);
-}
-
-/* --- @rabin_iters@ --- *
- *
- * Arguments:  @unsigned len@ = number of bits in value
- *
- * Returns:    Number of iterations recommended.
- *
- * Use:                Returns the recommended number of iterations to ensure that a
- *             number with @len@ bits is really prime.
- */
-
-int rabin_iters(unsigned len)
-{
-  static const struct {
-    unsigned b;
-    int i;
-  } *p, *q, tab[] = {
-    { 100, 27 },
-    { 150, 18 },
-    { 200, 15 },
-    { 250, 12 },
-    { 300, 9 },
-    { 350, 8 },
-    { 400, 7 },
-    { 450, 6 },
-    { 550, 5 },
-    { 650, 4 },
-    { 850, 3 },
-    { 1300, 2 }
-  };
-
-  unsigned i;
-
-  /* --- Binary search through the table --- */
-
-  p = tab;
-  q = tab + (sizeof(tab)/sizeof(tab[0]));
-  for (;;) {
-    i = (q - p) / 2;
-    if (!i)
-      break;
-    if (len >= p[i].b && len < p[i + 1].b)
-      break;
-    if (len > p[i].b)
-      p = p + i;
-    else
-      q = p + i;
-  }
-  return (p[i].i);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rabin.h b/rabin.h
deleted file mode 100644 (file)
index a491625..0000000
--- a/rabin.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Miller-Rabin primality test
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_RABIN_H
-#define CATACOMB_RABIN_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_MPMONT_H
-#  include "mpmont.h"
-#endif
-
-#ifndef CATACOMB_PFILT_H
-#  include "pfilt.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rabin {
-  mpmont mm;                           /* Montgomery arithmetic context */
-  size_t s;                            /* %$m = 2^s r + 1$% */
-  mp *r;                               /* %$m = 2^s r + 1$% */
-  mp *m1;                              /* %$(m - 1)R \bmod m$% */
-} rabin;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rabin_create@ --- *
- *
- * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
- *             @mp *m@ = pointer to number to test
- *
- * Returns:    Zero on success, nonzero for failure.
- *
- * Use:                Precomputes some useful values for performing the
- *             Miller-Rabin probabilistic primality test.
- */
-
-extern int rabin_create(rabin */*r*/, mp */*m*/);
-
-/* --- @rabin_destroy@ --- *
- *
- * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
- *
- * Returns:    ---
- *
- * Use:                Disposes of a Rabin-Miller context when it's no longer
- *             needed.
- */
-
-extern void rabin_destroy(rabin */*r*/);
-
-/* --- @rabin_test@, @rabin_rtest@ --- *
- *
- * Arguments:  @rabin *r@ = pointer to Rabin-Miller context
- *             @mp *g@ = base to test the number against
- *
- * Returns:    Either @PGEN_FAIL@ if the test failed, or @PGEN_PASS@
- *             if it succeeded.
- *
- * Use:                Performs a single iteration of the Rabin-Miller primality
- *             test.  The @rtest@ variant assumes that %$g$% is either
- *             already in Montgomery representation, or you don't care.
- */
-
-extern int rabin_rtest(rabin */*r*/, mp */*g*/);
-extern int rabin_test(rabin */*r*/, mp */*g*/);
-
-/* --- @rabin_iters@ --- *
- *
- * Arguments:  @unsigned len@ = number of bits in value
- *
- * Returns:    Number of iterations recommended.
- *
- * Use:                Returns the recommended number of iterations to ensure that a
- *             number with @len@ bits is really prime.
- */
-
-extern int rabin_iters(unsigned /*len*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rand.c b/rand.c
deleted file mode 100644 (file)
index b004b3f..0000000
--- a/rand.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Secure random number generator
- *
- * (c) 1998 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#include "arena.h"
-#include "blowfish-cbc.h"
-#include "paranoia.h"
-#include "rand.h"
-#include "rmd160.h"
-#include "rmd160-hmac.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static const grand_ops gops;
-
-typedef struct gctx {
-  grand r;
-  rand_pool p;
-} gctx;
-
-static gctx *pool = 0;                 /* Default random pool */
-
-/*----- Macros ------------------------------------------------------------*/
-
-#define RAND_RESOLVE(r) do {                                           \
-  if ((r) == RAND_GLOBAL) {                                            \
-    if (!pool)                                                         \
-      pool = (gctx *)rand_create();                                    \
-    (r) = &pool->p;                                                    \
-  }                                                                    \
-} while (0)
-
-#define TIMER(r) do {                                                  \
-  if ((r)->s && (r)->s->timer)                                         \
-    (r)->s->timer(r);                                                  \
-} while (0)
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rand_init@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    ---
- *
- * Use:                Initializes a randomness pool.  The pool doesn't start out
- *             very random: that's your job to sort out.  A good suggestion
- *             would be to attach an appropriate noise source and call
- *             @rand_seed@.
- */
-
-void rand_init(rand_pool *r)
-{
-  RAND_RESOLVE(r);
-  memset(r->pool, 0, sizeof(r->pool));
-  memset(r->buf, 0, sizeof(r->buf));
-  r->i = 0;
-  r->irot = 0;
-  r->ibits = r->obits = 0;
-  r->o = RAND_SECSZ;
-  r->s = 0;
-  rmd160_hmacinit(&r->k, 0, 0);
-  rand_gate(r);
-}
-
-/* --- @rand_noisesrc@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @const rand_source *s@ = pointer to source definition
- *
- * Returns:    ---
- *
- * Use:                Sets a noise source for a randomness pool.  When the pool's
- *             estimate of good random bits falls to zero, the @getnoise@
- *             function is called, passing the pool handle as an argument.
- *             It is expected to increase the number of good bits by at
- *             least one, because it'll be called over and over again until
- *             there are enough bits to satisfy the caller.  The @timer@
- *             function is called frequently throughout the generator's
- *             operation.
- */
-
-void rand_noisesrc(rand_pool *r, const rand_source *s)
-{
-  RAND_RESOLVE(r);
-  r->s = s;
-}
-
-/* --- @rand_seed@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @unsigned bits@ = number of bits to ensure
- *
- * Returns:    ---
- *
- * Use:                Ensures that there are at least @bits@ good bits of entropy
- *             in the pool.  It is recommended that you call this after
- *             initializing a new pool.  Requesting @bits > RAND_IBITS@ is
- *             doomed to failure (and is an error).
- */
-
-void rand_seed(rand_pool *r, unsigned bits)
-{
-  RAND_RESOLVE(r);
-
-  assert(((void)"bits pointlessly large in rand_seed", bits <= RAND_IBITS));
-  assert(((void)"no noise source in rand_seed", r->s));
-
-  while (r->ibits < bits)
-    r->s->getnoise(r);
-  rand_gate(r);
-}
-
-/* --- @rand_key@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @const void *k@ = pointer to key data
- *             @size_t sz@ = size of key data
- *
- * Returns:    ---
- *
- * Use:                Sets the secret key for a randomness pool.  The key is used
- *             when mixing in new random bits.
- */
-
-void rand_key(rand_pool *r, const void *k, size_t sz)
-{
-  RAND_RESOLVE(r);
-  rmd160_hmacinit(&r->k, k, sz);
-}
-
-/* --- @rand_add@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @const void *p@ = pointer a buffer of data to add
- *             @size_t sz@ = size of the data buffer
- *             @unsigned goodbits@ = number of good bits estimated in buffer
- *
- * Returns:    ---
- *
- * Use:                Mixes the data in the buffer with the contents of the
- *             pool.  The estimate of the number of good bits is added to
- *             the pool's own count.  The mixing operation is not
- *             cryptographically strong.  However, data in the input pool
- *             isn't output directly, only through the one-way gating
- *             operation, so that shouldn't matter.
- */
-
-void rand_add(rand_pool *r, const void *p, size_t sz, unsigned goodbits)
-{
-  const octet *c = p;
-  int i, rot;
-
-#if RAND_POOLSZ != 128
-#  error Polynomial in rand_add is out of date.  Fix it.
-#endif
-
-  RAND_RESOLVE(r);
-
-  i = r->i; rot = r->irot;
-
-  while (sz) {
-    octet o = *c++;
-    r->pool[i] ^= (ROL8(o, rot) ^
-                  r->pool[(i + 1) % RAND_POOLSZ] ^
-                  r->pool[(i + 2) % RAND_POOLSZ] ^
-                  r->pool[(i + 7) % RAND_POOLSZ]);
-    rot = (rot + 5) & 7;
-    i++; if (i >= RAND_POOLSZ) i -= RAND_POOLSZ;
-    sz--;
-  }
-
-  r->i = i;
-  r->irot = rot;
-  r->ibits += goodbits;
-  if (r->ibits > RAND_IBITS)
-    r->ibits = RAND_IBITS;
-}
-
-/* --- @rand_goodbits@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Estimate of the number of good bits remaining in the pool.
- */
-
-unsigned rand_goodbits(rand_pool *r)
-{
-  RAND_RESOLVE(r);
-  return (r->ibits + r->obits);
-}
-
-/* --- @rand_gate@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    ---
- *
- * Use:                Mixes up the entire state of the generator in a nonreversible
- *             way.
- */
-
-void rand_gate(rand_pool *r)
-{
-  octet mac[RMD160_HASHSZ];
-
-  RAND_RESOLVE(r);
-  TIMER(r);
-
-  /* --- Hash up all the data in the pool --- */
-
-  {
-    rmd160_macctx mc;
-
-    rmd160_macinit(&mc, &r->k);
-    rmd160_machash(&mc, r->pool, sizeof(r->pool));
-    rmd160_machash(&mc, r->buf, sizeof(r->buf));
-    rmd160_macdone(&mc, mac);
-    BURN(mc);
-  }
-
-  /* --- Now mangle all of the data based on the hash --- */
-
-  {
-    blowfish_cbcctx bc;
-
-    blowfish_cbcinit(&bc, mac, sizeof(mac), 0);
-    blowfish_cbcencrypt(&bc, r->pool, r->pool, sizeof(r->pool));
-    blowfish_cbcencrypt(&bc, r->buf, r->buf, sizeof(r->buf));
-    BURN(bc);
-  }
-
-  /* --- Reset the various state variables --- */
-
-  r->o = RAND_SECSZ;
-  r->obits += r->ibits;
-  if (r->obits > RAND_OBITS) {
-    r->ibits = r->obits - r->ibits;
-    r->obits = RAND_OBITS;
-  } else
-    r->ibits = 0;
-  TIMER(r);
-}
-
-/* --- @rand_stretch@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    ---
- *
- * Use:                Stretches the contents of the output buffer by transforming
- *             it in a nonreversible way.  This doesn't add any entropy
- *             worth speaking about, but it works well enough when the
- *             caller doesn't care about that sort of thing.
- */
-
-void rand_stretch(rand_pool *r)
-{
-  octet mac[RMD160_HASHSZ];
-
-  RAND_RESOLVE(r);
-  TIMER(r);
-
-  /* --- Hash up all the data in the buffer --- */
-
-  {
-    rmd160_macctx mc;
-
-    rmd160_macinit(&mc, &r->k);
-    rmd160_machash(&mc, r->pool, sizeof(r->pool));
-    rmd160_machash(&mc, r->buf, sizeof(r->buf));
-    rmd160_macdone(&mc, mac);
-    BURN(mc);
-  }
-
-  /* --- Now mangle the buffer based on that hash --- */
-
-  {
-    blowfish_cbcctx bc;
-
-    blowfish_cbcinit(&bc, mac, sizeof(mac), 0);
-    blowfish_cbcencrypt(&bc, r->buf, r->buf, sizeof(r->buf));
-    BURN(bc);
-  }
-
-  /* --- Reset the various state variables --- */
-
-  r->o = RAND_SECSZ;
-  TIMER(r);
-}
-
-/* --- @rand_get@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @void *p@ = pointer to output buffer
- *             @size_t sz@ = size of output buffer
- *
- * Returns:    ---
- *
- * Use:                Gets random data from the pool.  The pool's contents can't be
- *             determined from the output of this function; nor can the
- *             output data be determined from a knowledge of the data input
- *             to the pool wihtout also having knowledge of the secret key.
- *             The good bits counter is decremented, although no special
- *             action is taken if it reaches zero.
- */
-
-void rand_get(rand_pool *r, void *p, size_t sz)
-{
-  octet *o = p;
-
-  RAND_RESOLVE(r);
-  TIMER(r);
-
-  if (!sz)
-    return;
-  for (;;) {
-    if (r->o + sz <= RAND_BUFSZ) {
-      memcpy(o, r->buf + r->o, sz);
-      r->o += sz;
-      break;
-    } else {
-      size_t chunk = RAND_BUFSZ - r->o;
-      if (chunk) {
-       memcpy(o, r->buf + r->o, chunk);
-       sz -= chunk;
-       o += chunk;
-      }
-      rand_stretch(r);
-    }
-  }
-
-  if (r->obits > sz * 8)
-    r->obits -= sz * 8;
-  else
-    r->obits = 0;
-}
-
-/* --- @rand_getgood@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @void *p@ = pointer to output buffer
- *             @size_t sz@ = size of output buffer
- *
- * Returns:    ---
- *
- * Use:                Gets random data from the pool, ensuring that there are
- *             enough good bits.  This interface isn't recommended: it makes
- *             the generator slow, and doesn't provide much more security
- *             than @rand_get@, assuming you've previously done a
- *             @rand_seed@.
- */
-
-void rand_getgood(rand_pool *r, void *p, size_t sz)
-{
-  octet *o = p;
-
-  RAND_RESOLVE(r);
-
-  if (!sz)
-    return;
-  if (!r->s || !r->s->getnoise) {
-    rand_get(r, p, sz);
-    return;
-  }
-  TIMER(r);
-
-  while (sz) {
-    size_t chunk = sz;
-
-    if (chunk * 8 > r->obits) {
-      if (chunk * 8 > r->ibits + r->obits)
-       do r->s->getnoise(r); while (r->ibits + r->obits < 256);
-      rand_gate(r);
-      if (chunk * 8 > r->obits)
-       chunk = r->obits / 8;
-    }
-
-    if (chunk + r->o > RAND_BUFSZ)
-      chunk = RAND_BUFSZ - r->o;
-
-    memcpy(o, r->buf + r->o, chunk);
-    r->o += chunk;
-    r->obits -= chunk * 8;
-    o += chunk;
-    sz -= chunk;
-  }
-}
-
-/*----- Generic random number generator interface -------------------------*/
-
-#define GRESOLVE(g, r) do {                                            \
-  if (r != &rand_global)                                               \
-    g = (gctx *)r;                                                     \
-  else {                                                               \
-    if (!pool)                                                         \
-      pool = (gctx *)rand_create();                                    \
-    g = pool;                                                          \
-  }                                                                    \
-} while (0)
-
-static void gdestroy(grand *r)
-{
-  gctx *g;
-  GRESOLVE(g, r);
-  if (g != pool) {
-    BURN(*g);
-    S_DESTROY(g);
-  }
-}
-
-static int gmisc(grand *r, unsigned op, ...)
-{
-  gctx *g;
-  va_list ap;
-  int rc = 0;
-  va_start(ap, op);
-
-  GRESOLVE(g, r);
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDBLOCK:
-       case GRAND_SEEDRAND:
-       case RAND_GATE:
-       case RAND_STRETCH:
-       case RAND_KEY:
-       case RAND_NOISESRC:
-       case RAND_SEED:
-       case RAND_TIMER:
-       case RAND_GOODBITS:
-       case RAND_ADD:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT: {
-      unsigned u = va_arg(ap, unsigned);
-      rand_add(&g->p, &u, sizeof(u), sizeof(u));
-    } break;
-    case GRAND_SEEDUINT32: {
-      uint32 i = va_arg(ap, uint32);
-      rand_add(&g->p, &i, sizeof(i), 4);
-    } break;
-    case GRAND_SEEDBLOCK: {
-      const void *p = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      rand_add(&g->p, p, sz, sz);
-    } break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      octet buf[16];
-      rr->ops->fill(rr, buf, sizeof(buf));
-      rand_add(&g->p, buf, sizeof(buf), 8);
-    } break;
-    case RAND_GATE:
-      rand_gate(&g->p);
-      break;
-    case RAND_STRETCH:
-      rand_stretch(&g->p);
-      break;
-    case RAND_KEY: {
-      const void *k = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      rand_key(&g->p, k, sz);
-    } break;
-    case RAND_NOISESRC:
-      rand_noisesrc(&g->p, va_arg(ap, const rand_source *));
-      break;
-    case RAND_SEED:
-      rand_seed(&g->p, va_arg(ap, unsigned));
-      break;
-    case RAND_TIMER:
-      TIMER(&g->p);
-      break;
-    case RAND_GOODBITS:
-      rc = rand_goodbits(&g->p);
-      break;
-    case RAND_ADD: {
-      const void *p = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      unsigned goodbits = va_arg(ap, unsigned);
-      rand_add(&g->p, p, sz, goodbits);
-    } break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static octet gbyte(grand *r)
-{
-  gctx *g;
-  octet o;
-  GRESOLVE(g, r);
-  rand_getgood(&g->p, &o, 1);
-  return (o);
-}
-
-static uint32 gword(grand *r)
-{
-  gctx *g;
-  octet b[4];
-  GRESOLVE(g, r);
-  rand_getgood(&g->p, &b, sizeof(b));
-  return (LOAD32(b));
-}
-
-static void gfill(grand *r, void *p, size_t sz)
-{
-  gctx *g;
-  GRESOLVE(g, r);
-  rand_get(&g->p, p, sz);
-}
-
-static const grand_ops gops = {
-  "rand",
-  GRAND_CRYPTO, 0,
-  gmisc, gdestroy,
-  gword, gbyte, gword, grand_range, gfill
-};
-
-grand rand_global = { &gops };
-
-/* --- @rand_create@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a Catacomb
- *             entropy pool generator.
- */
-
-grand *rand_create(void)
-{
-  gctx *g = S_CREATE(gctx);
-  g->r.ops = &gops;
-  rand_init(&g->p);
-  return (&g->r);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand.h b/rand.h
deleted file mode 100644 (file)
index 5d542b8..0000000
--- a/rand.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Secure random number generator
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on the random number generator ------------------------------*
- *
- * The algorithm is one of the author's own devising.  It may therefore be
- * worth a certain amount of skepticism.  However, I've thought about this
- * method for over a year before actually considering it worth implementing.
- * With a little bit of luck, it should have received some peer review by the
- * time this code is actually properly released, and it'll be worth a bit
- * more confidence.  My earlier generator was very similar in structure to
- * the Linux /dev/random device.  This generator is intended to address
- * concerns I expressed about the Linux generator in a Usenet article to
- * sci.crypt.
- *
- * The generator is divided into two parts: an input pool and an output
- * buffer.  New random data is placed into the pool in the way described
- * below, which is shamelessly stolen from the Linux /dev/random generator.
- * The only interaction that the pool has on the output buffer is through the
- * keyed `gating' operation, which mixes up and redistributes all of the
- * generator's state in an irreversible manner.  Random bytes, when
- * requested, are extracted from the output buffer in a linear fashion.
- *
- * The input pool is best seen as being eight shift registers in parallel.
- * Data is added to the pool one octet at a time.  Each bit of a new octet is
- * added to a different shift register, by adding it (mod 2) with other bits
- * according to the coefficients of a primitive polynomial.  Each new byte is
- * rotated before being added into the pool, in a half-hearted attempt to
- * protect against biases in the input data (e.g., top bits being clear on
- * ASCII text).
- *
- * The gating operation takes a keyed hash of the entire generator state,
- * uses it as the key for a symmetric cipher, and encrypts the state.  The
- * key is then discarded.  The result is that every ouptut bit of the
- * operation depends in a complex way on every input bit, but the operation
- * cannot be reversed.
- *
- * As an added wrinkle, 160 bits of the output buffer are never actually
- * output.  They are used in the gating operation only, as an extra item that
- * an adversary has to guess before predicting generator output.
- */
-
-#ifndef CATACOMB_RAND_H
-#define CATACOMB_RAND_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_RMD160_HMAC_H
-#  include "rmd160-hmac.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define RAND_POOLSZ 128                        /* Input pool size in bytes */
-#define RAND_BUFSZ 512                 /* Output buffer size in bytes */
-#define RAND_SECSZ 20                  /* Secret octets in output buffer */
-
-#define RAND_IBITS (RAND_POOLSZ * 8)
-#define RAND_OBITS (RAND_BUFSZ * 8)
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- A random number generator pool --- */
-
-typedef struct rand_pool {
-  octet pool[RAND_POOLSZ];             /* Actual contents of the pool */
-  unsigned i;                          /* Current index into pool */
-  unsigned irot;                       /* Current rotation applied */
-  unsigned ibits;                      /* Number of good bits in pool */
-  octet buf[RAND_BUFSZ];               /* Random octet output buffer */
-  unsigned o;                          /* Current index into buffer */
-  unsigned obits;                      /* Number of good bits in buffer */
-  rmd160_mackey k;                     /* Secret key for this pool */
-  const struct rand_source *s;         /* System-specific noise source */
-} rand_pool;
-
-#define RAND_GLOBAL ((rand_pool *)0)   /* The global randomness pool */
-
-/* --- A noise source --- */
-
-typedef struct rand_source {
-  void (*getnoise)(rand_pool */*r*/);  /* Acquire more noise */
-  int (*timer)(rand_pool */*r*/);      /* Get noise from current time */
-} rand_source;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rand_init@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    ---
- *
- * Use:                Initializes a randomness pool.  The pool doesn't start out
- *             very random: that's your job to sort out.
- */
-
-extern void rand_init(rand_pool */*r*/);
-
-/* --- @rand_noisesrc@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @const rand_source *s@ = pointer to source definition
- *
- * Returns:    ---
- *
- * Use:                Sets a noise source for a randomness pool.  When the pool's
- *             estimate of good random bits falls to zero, the @getnoise@
- *             function is called, passing the pool handle as an argument.
- *             It is expected to increase the number of good bits by at
- *             least one, because it'll be called over and over again until
- *             there are enough bits to satisfy the caller.  The @timer@
- *             function is called frequently throughout the generator's
- *             operation.
- */
-
-extern void rand_noisesrc(rand_pool */*r*/, const rand_source */*s*/);
-
-/* --- @rand_seed@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @unsigned bits@ = number of bits to ensure
- *
- * Returns:    ---
- *
- * Use:                Ensures that there are at least @bits@ good bits of entropy
- *             in the pool.  It is recommended that you call this after
- *             initializing a new pool.  Requesting @bits > RAND_IBITS@ is
- *             doomed to failure (and is an error).
- */
-
-extern void rand_seed(rand_pool */*r*/, unsigned /*bits*/);
-
-/* --- @rand_key@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @const void *k@ = pointer to key data
- *             @size_t sz@ = size of key data
- *
- * Returns:    ---
- *
- * Use:                Sets the secret key for a randomness pool.  The key is used
- *             when mixing in new random bits.
- */
-
-extern void rand_key(rand_pool */*r*/, const void */*k*/, size_t /*sz*/);
-
-/* --- @rand_add@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @const void *p@ = pointer a buffer of data to add
- *             @size_t sz@ = size of the data buffer
- *             @unsigned goodbits@ = number of good bits estimated in buffer
- *
- * Returns:    ---
- *
- * Use:                Mixes the data in the buffer with the contents of the
- *             pool.  The estimate of the number of good bits is added to
- *             the pool's own count.  The mixing operation is not
- *             cryptographically strong.  However, data in the input pool
- *             isn't output directly, only through the one-way gating
- *             operation, so that shouldn't matter.
- */
-
-extern void rand_add(rand_pool */*r*/,
-                    const void */*p*/, size_t /*sz*/,
-                    unsigned /*goodbits*/);
-
-/* --- @rand_goodbits@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    Estimate of the number of good bits remaining in the pool.
- */
-
-extern unsigned rand_goodbits(rand_pool */*r*/);
-
-/* --- @rand_gate@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    ---
- *
- * Use:                Mixes up the entire state of the generator in a nonreversible
- *             way.
- */
-
-extern void rand_gate(rand_pool */*r*/);
-
-/* --- @rand_stretch@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *
- * Returns:    ---
- *
- * Use:                Stretches the contents of the output buffer by transforming
- *             it in a nonreversible way.  This doesn't add any entropy
- *             worth speaking about, but it works well enough when the
- *             caller doesn't care about that sort of thing.
- */
-
-extern void rand_stretch(rand_pool */*r*/);
-
-/* --- @rand_get@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @void *p@ = pointer to output buffer
- *             @size_t sz@ = size of output buffer
- *
- * Returns:    ---
- *
- * Use:                Gets random data from the pool.  The pool's contents can't be
- *             determined from the output of this function; nor can the
- *             output data be determined from a knowledge of the data input
- *             to the pool without also having knowledge of the secret key.
- *             The good bits counter is decremented, although no special
- *             action is taken if it reaches zero.
- */
-
-extern void rand_get(rand_pool */*r*/, void */*p*/, size_t /*sz*/);
-
-/* --- @rand_getgood@ --- *
- *
- * Arguments:  @rand_pool *r@ = pointer to a randomness pool
- *             @void *p@ = pointer to output buffer
- *             @size_t sz@ = size of output buffer
- *
- * Returns:    ---
- *
- * Use:                Gets random data from the pool.  The pool's contents can't be
- *             determined from the output of this function; nor can the
- *             output data be determined from a knowledge of the data input
- *             to the pool wihtout also having knowledge of the secret key.
- *             If a noise source is attached to the pool in question, it is
- *             called to replenish the supply of good bits in the pool;
- *             otherwise this call is equivalent to @rand_get@.
- */
-
-extern void rand_getgood(rand_pool */*r*/, void */*p*/, size_t /*sz*/);
-
-/*----- Generic random number generator interface -------------------------*/
-
-/* --- Miscellaneous operations --- */
-
-enum {
-  RAND_GATE = GRAND_SPECIFIC('R'),     /* No args */
-  RAND_STRETCH,                                /* No args */
-  RAND_KEY,                            /* @const void *k, size_t sz@ */
-  RAND_NOISESRC,                       /* @const rand_source *s@ */
-  RAND_SEED,                           /* @unsigned bits@ */
-  RAND_TIMER,                          /* No args */
-  RAND_GOODBITS,                       /* No args */
-  RAND_ADD                             /* @const void *p, size_t sz,@
-                                        * @unsigned goodbits */
-};
-
-/* --- Default random number generator --- */
-
-extern grand rand_global;
-
-/* --- @rand_create@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    Pointer to a generic generator.
- *
- * Use:                Constructs a generic generator interface over a Catacomb
- *             entropy pool generator.
- */
-
-extern grand *rand_create(void);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rand/Makefile.am b/rand/Makefile.am
new file mode 100644 (file)
index 0000000..3934131
--- /dev/null
@@ -0,0 +1,83 @@
+### -*-makefile-*-
+###
+### Build script for random number generators
+###
+### (c) 2013 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.
+
+include $(top_srcdir)/vars.am
+
+noinst_LTLIBRARIES      = librand.la
+librand_la_SOURCES      =
+
+TEST_LIBS               = librand.la
+
+###--------------------------------------------------------------------------
+### Component files.
+
+## The FIPS186 generator used to generate DSA domain parameters.
+pkginclude_HEADERS     += dsarand.h
+librand_la_SOURCES     += dsarand.c
+
+## Knuth's lagged-Fibonacci generator.
+pkginclude_HEADERS     += fibrand.h
+librand_la_SOURCES     += fibrand.c
+
+## The FIPS 140--2 random number generator tests.
+pkginclude_HEADERS     += fipstest.h
+librand_la_SOURCES     += fipstest.c
+
+## Interface for generic random number sources.
+pkginclude_HEADERS     += grand.h
+librand_la_SOURCES     += grand.c
+
+## A simple linear-congruential generator.
+pkginclude_HEADERS     += lcrand.h
+librand_la_SOURCES     += lcrand.c
+TESTS                  += lcrand.$t
+EXTRA_DIST             += t/lcrand
+
+## Maurer's universal statistical test.
+pkginclude_HEADERS     += maurer.h
+librand_la_SOURCES     += maurer.c
+
+## System-specific noise acquisition.
+pkginclude_HEADERS     += noise.h
+librand_la_SOURCES     += noise.c
+
+## Cryptographic laundering for true random data generation.
+pkginclude_HEADERS     += rand.h
+librand_la_SOURCES     += rand.c
+
+## The SSL v3 pseudorandom function.
+pkginclude_HEADERS     += sslprf.h
+librand_la_SOURCES     += sslprf.c
+TESTS                  += sslprf.$t
+EXTRA_DIST             += t/sslprf
+
+## The TLS v1 pseudorandom function.
+pkginclude_HEADERS     += tlsprf.h
+librand_la_SOURCES     += tlsprf.c
+TESTS                  += tlsprf.$t
+EXTRA_DIST             += t/tlsprf
+
+###----- That's all, folks --------------------------------------------------
diff --git a/rand/dsarand.c b/rand/dsarand.c
new file mode 100644 (file)
index 0000000..9b18ab0
--- /dev/null
@@ -0,0 +1,335 @@
+/* -*-c-*-
+ *
+ * Random number generator for DSA
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#include "dsarand.h"
+#include "grand.h"
+#include "sha.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @STEP@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *
+ * Use:                Increments the buffer by one, interpreting it as a big-endian
+ *             integer.  Carries outside the integer are discarded.
+ */
+
+#define STEP(d) do {                                                   \
+  dsarand *_d = (d);                                                   \
+  octet *_p = _d->p;                                                   \
+  octet *_q = _p + _d->sz;                                             \
+  unsigned _c = 1;                                                     \
+  while (_c && _q > _p) {                                              \
+    _c += *--_q;                                                       \
+    *_q = U8(_c);                                                      \
+    _c >>= 8;                                                          \
+  }                                                                    \
+} while (0)
+
+/* --- @dsarand_init@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *             @const void *p@ = pointer to seed buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DSA random number generator.
+ */
+
+void dsarand_init(dsarand *d, const void *p, size_t sz)
+{
+  d->p = xmalloc(sz);
+  d->sz = sz;
+  d->passes = 1;
+  if (p)
+    memcpy(d->p, p, sz);
+}
+
+/* --- @dsarand_reseed@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *             @const void *p@ = pointer to seed buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DSA random number generator.
+ */
+
+void dsarand_reseed(dsarand *d, const void *p, size_t sz)
+{
+  xfree(d->p);
+  d->p = xmalloc(sz);
+  d->sz = sz;
+  d->passes = 1;
+  if (p)
+    memcpy(d->p, p, sz);
+}
+
+/* --- @dsarand_destroy@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a DSA random number generation context.
+ */
+
+void dsarand_destroy(dsarand *d)
+{
+  xfree(d->p);
+}
+
+/* --- @dsarand_fill@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *             @void *p@ = pointer to output buffer
+ *             @size_t sz@ = size of output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Fills an output buffer with pseudorandom data.
+ *
+ *             Let %$p$% be the numerical value of the input buffer, and let
+ *             %$b$% be the number of bytes required.  Let
+ *             %$z = \lceil b / 20 \rceil$% be the number of SHA outputs
+ *             required.  Then the output of pass %$n$% is
+ *
+ *               %$P_n = \sum_{0 \le i < z} 2^{160i} SHA(p + nz + i)$%
+ *                                                     %${} \bmod 2^{8b}$%
+ *
+ *             and the actual result in the output buffer is the XOR of all
+ *             of the output passes.
+ *
+ *             The DSA procedure for choosing @q@ involves two passes with
+ *             %$z = 1$%; the procedure for choosing @p@ involves one pass
+ *             with larger %$z$%.  This generalization of the DSA generation
+ *             procedure is my own invention but it seems relatively sound.
+ */
+
+void dsarand_fill(dsarand *d, void *p, size_t sz)
+{
+  octet *q = p;
+  unsigned n = d->passes;
+
+  /* --- Write out the first pass --- *
+   *
+   * This can write directly to the output buffer, so it's done differently
+   * from the latter passes.
+   */
+
+  {
+    size_t o = sz;
+
+    while (o) {
+      sha_ctx h;
+
+      /* --- Hash the input buffer --- */
+
+      sha_init(&h);
+      sha_hash(&h, d->p, d->sz);
+
+      /* --- If enough space, extract the hash output directly --- */
+
+      if (o >= SHA_HASHSZ) {
+       o -= SHA_HASHSZ;
+       sha_done(&h, q + o);
+      }
+
+      /* --- Otherwise take the hash result out of line and copy it --- */
+
+      else {
+       octet hash[SHA_HASHSZ];
+       sha_done(&h, hash);
+       memcpy(q, hash + (SHA_HASHSZ - o), o);
+       o = 0;
+      }
+
+      /* --- Step the input buffer --- */
+
+      STEP(d);
+    }
+
+    /* --- Another pass has been done --- */
+
+    n--;
+  }
+
+  /* --- Write out subsequent passes --- *
+   *
+   * The hash output has to be done offline, so this is slightly easier.
+   */
+
+  while (n) {
+    size_t o = sz;
+
+    while (o) {
+      sha_ctx h;
+      octet hash[SHA_HASHSZ];
+      size_t n;
+      octet *pp, *qq;
+
+      /* --- Hash the input buffer --- */
+
+      sha_init(&h);
+      sha_hash(&h, d->p, d->sz);
+      sha_done(&h, hash);
+
+      /* --- Work out how much output is wanted --- */
+
+      n = SHA_HASHSZ;
+      if (n > o)
+       n = o;
+      o -= n;
+
+      /* --- XOR the data out --- */
+
+      for (pp = hash + (SHA_HASHSZ - n), qq = q + o;
+          pp < hash + SHA_HASHSZ; pp++, qq++)
+       *qq ^= *pp;
+
+      /* --- Step the input buffer --- */
+
+      STEP(d);
+    }
+
+    /* --- Another pass is done --- */
+
+    n--;
+  }
+}
+
+/*----- Generic pseudorandom-number generator interface -------------------*/
+
+static const grand_ops gops;
+
+typedef struct gctx {
+  grand r;
+  dsarand d;
+} gctx;
+
+static void gdestroy(grand *r)
+{
+  gctx *g = (gctx *)r;
+  dsarand_destroy(&g->d);
+  DESTROY(g);
+}
+
+static int gmisc(grand *r, unsigned op, ...)
+{
+  gctx *g = (gctx *)r;
+  va_list ap;
+  int rc = 0;
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDBLOCK:
+       case GRAND_SEEDRAND:
+       case DSARAND_PASSES:
+       case DSARAND_SEEDSZ:
+       case DSARAND_GETSEED:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDBLOCK: {
+      const void *p = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      dsarand_reseed(&g->d, p, sz);
+    } break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      rr->ops->fill(rr, g->d.p, g->d.sz);
+    } break;
+    case DSARAND_PASSES:
+      g->d.passes = va_arg(ap, unsigned);
+      break;
+    case DSARAND_SEEDSZ:
+      rc = g->d.sz;
+      break;
+    case DSARAND_GETSEED:
+      memcpy(va_arg(ap, void *), g->d.p, g->d.sz);
+      break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static void gfill(grand *r, void *p, size_t sz)
+{
+  gctx *g = (gctx *)r;
+  dsarand_fill(&g->d, p, sz);
+}
+
+static const grand_ops gops = {
+  "dsarand",
+  0, 0,
+  gmisc, gdestroy,
+  grand_word, grand_byte, grand_word, grand_range, gfill
+};
+
+/* --- @dsarand_create@ --- *
+ *
+ * Arguments:  @const void *p@ = pointer to seed buffer
+ *             @size_t sz@ = size of seed buffer
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a Catacomb
+ *             entropy pool generator.
+ */
+
+grand *dsarand_create(const void *p, size_t sz)
+{
+  gctx *g = CREATE(gctx);
+  g->r.ops = &gops;
+  dsarand_init(&g->d, p, sz);
+  return (&g->r);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/dsarand.h b/rand/dsarand.h
new file mode 100644 (file)
index 0000000..04254aa
--- /dev/null
@@ -0,0 +1,151 @@
+/* -*-c-*-
+ *
+ * Random number generator for DSA
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_DSARAND_H
+#define CATACOMB_DSARAND_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_SHA_H
+#  include "sha.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct dsarand {
+  octet *p;                            /* Pointer to seed (modified) */
+  size_t sz;                           /* Size of the seed buffer */
+  unsigned passes;                     /* Number of passes to make */
+} dsarand;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @dsarand_init@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *             @const void *p@ = pointer to seed buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DSA random number generator.
+ */
+
+extern void dsarand_init(dsarand */*d*/, const void */*p*/, size_t /*sz*/);
+
+/* --- @dsarand_reseed@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *             @const void *p@ = pointer to seed buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DSA random number generator.
+ */
+
+extern void dsarand_reseed(dsarand */*d*/, const void */*p*/, size_t /*sz*/);
+
+/* --- @dsarand_destroy@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *
+ * Returns:    ---
+ *
+ * Use:                Disposes of a DSA random number generation context.
+ */
+
+extern void dsarand_destroy(dsarand */*d*/);
+
+/* --- @dsarand_fill@ --- *
+ *
+ * Arguments:  @dsarand *d@ = pointer to context
+ *             @void *p@ = pointer to output buffer
+ *             @size_t sz@ = size of output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Fills an output buffer with pseudorandom data.
+ *
+ *             Let %$p$% be the numerical value of the input buffer, and let
+ *             %$b$% be the number of bytes required.  Let
+ *             %$z = \lceil b / 20 \rceil$% be the number of SHA outputs
+ *             required.  Then the output of pass %$n$% is
+ *
+ *               %$P_n = \sum_{0 \le i < z} 2^{160i} SHA(p + nz + i)$%
+ *                                                     %${} \bmod 2^{8b}$%
+ *
+ *             and the actual result in the output buffer is the XOR of all
+ *             of the output passes.
+ *
+ *             The DSA procedure for choosing @q@ involves two passes with
+ *             %$z = 1$%; the procedure for choosing @p@ involves one pass
+ *             with larger %$z$%.  This generalization of the DSA generation
+ *             procedure is my own invention but it seems relatively sound.
+ */
+
+extern void dsarand_fill(dsarand */*d*/, void */*p*/, size_t /*sz*/);
+
+/*----- Generic pseudorandom-number generator interface -------------------*/
+
+/* --- Miscellaneous operations --- */
+
+enum {
+  DSARAND_PASSES = GRAND_SPECIFIC('D'),        /* @unsigned n@ */
+  DSARAND_SEEDSZ,                      /* No args */
+  DSARAND_GETSEED                      /* @void *buf@ */
+};
+
+/* --- @dsarand_create@ --- *
+ *
+ * Arguments:  @const void *p@ = pointer to seed buffer
+ *             @size_t sz@ = size of seed buffer
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface to a DSA generator.
+ */
+
+extern grand *dsarand_create(const void */*p*/, size_t /*sz*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/fibrand.c b/rand/fibrand.c
new file mode 100644 (file)
index 0000000..bc9afd8
--- /dev/null
@@ -0,0 +1,247 @@
+/* -*-c-*-
+ *
+ * Fibonacci generator
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#include "fibrand.h"
+#include "grand.h"
+#include "lcrand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @fibrand_step@ --- *
+ *
+ * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
+ *
+ * Returns:    Next output from generator.
+ *
+ * Use:                Steps the generator.  Returns
+ *             %$x_{i - 24} + x_{i - 55} \bmod 2^{32}$%.
+ */
+
+uint32 fibrand_step(fibrand *f)
+{
+  unsigned i = f->i;
+  unsigned j = i + (FIB_SZ - FIB_TAP);
+  uint32 x;
+  if (j >= FIB_SZ)
+    j -= FIB_SZ;
+  x = f->x[i] = U32(f->x[i] + f->x[j]);
+  i++;
+  if (i >= FIB_SZ)
+    i = 0;
+  f->i = i;
+  return (x);
+}
+
+/* --- @fibrand_seed@ --- *
+ *
+ * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
+ *             @grand *r@ = random number generator to extract words from
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Fibonacci generator using word outputs from the
+ *             given random number source @r@.
+ */
+
+void fibrand_seed(fibrand *f, grand *r)
+{
+  int i;
+  unsigned p = 0;
+
+  for (i = 0; i < FIB_SZ; i++)
+    p |= f->x[i] = r->ops->word(r);
+  if (!(p & 1)) {
+    i = r->ops->range(r, FIB_SZ);
+    f->x[i] |= 1;
+  }
+  f->i = 0;
+}
+
+/* --- @fibrand_lcseed@ --- *
+ *
+ * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
+ *             @uint32 seed@ = seed value
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Fibonacci generator using outputs from the
+ *             @lcrand@ generator seeded from @seed@.  This is faster than
+ *             using a generic @lcrand@-based generator and @fibrand_rseed@
+ *             because it uses raw outputs rather than uniformly distributed
+ *             32-bit words.
+ */
+
+void fibrand_lcseed(fibrand *f, uint32 seed)
+{
+  int i;
+  unsigned p = 0;
+
+  for (i = 0; i < FIB_SZ; i++)
+    p |= f->x[i] = seed = lcrand(seed);
+  if (!(p & 1)) {
+    i = lcrand_range(&seed, FIB_SZ);
+    f->x[i] |= 1;
+  }
+  f->i = 0;
+}
+
+/* --- @fibrand_range@ --- *
+ *
+ * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
+ *             @uint32 m@ = limit
+ *
+ * Returns:    A uniformly distributed pseudorandom integer in the interval
+ *             %$[0, m)$%.
+ */
+
+uint32 fibrand_range(fibrand *f, uint32 m)
+{
+  uint32 r = 0xffffffff - (0xffffffff % m);
+  uint32 x;
+
+  /* --- Now generate numbers until a good one comes along --- */
+
+  do x = fibrand_step(f); while (x >= r);
+  return (x % m);
+}
+
+/*----- Generic interface -------------------------------------------------*/
+
+typedef struct gctx {
+  grand r;
+  fibrand f;
+} gctx;
+
+static void gdestroy(grand *r)
+{
+  gctx *g = (gctx *)r;
+  DESTROY(g);
+}
+
+static int gmisc(grand *r, unsigned op, ...)
+{
+  gctx *g = (gctx *)r;
+  va_list ap;
+  int rc = 0;
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDRAND:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT:
+      fibrand_lcseed(&g->f, va_arg(ap, unsigned));
+      break;
+    case GRAND_SEEDUINT32:
+      fibrand_lcseed(&g->f, va_arg(ap, uint32));
+      break;
+    case GRAND_SEEDRAND:
+      fibrand_seed(&g->f, va_arg(ap, grand *));
+      break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static octet gbyte(grand *r)
+{
+  gctx *g = (gctx *)r;
+  return (U8(fibrand_step(&g->f)));
+}
+
+static uint32 gword(grand *r)
+{
+  gctx *g = (gctx *)r;
+  return (fibrand_step(&g->f));
+}
+
+static uint32 grange(grand *r, uint32 l)
+{
+  gctx *g = (gctx *)r;
+  return (fibrand_range(&g->f, l));
+}
+
+static void gfill(grand *r, void *p, size_t sz)
+{
+  gctx *g = (gctx *)r;
+  octet *q = p;
+  while (sz) {
+    *q++ = U8(fibrand_step(&g->f));
+    sz--;
+  }
+}
+
+static const grand_ops gops = {
+  "fibrand",
+  0, 0,
+  gmisc, gdestroy,
+  gword, gbyte, gword, grange, gfill
+};
+
+/* --- @fibrand_create@ --- *
+ *
+ * Arguments:  @uint32 seed@ = initial seed
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a Fibonacci
+ *             generator.  The generator is seeded using @fibrand_lcseed@.
+ */
+
+grand *fibrand_create(uint32 seed)
+{
+  gctx *g = CREATE(gctx);
+  g->r.ops = &gops;
+  fibrand_lcseed(&g->f, seed);
+  return (&g->r);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/fibrand.h b/rand/fibrand.h
new file mode 100644 (file)
index 0000000..bdef40b
--- /dev/null
@@ -0,0 +1,137 @@
+/* -*-c-*-
+ *
+ * Fibonacci generator
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on the Fibonacci generator ----------------------------------*
+ *
+ * The generator was originally suggested by G. J. Mitchell and D. P. Moore
+ * in 1957, and publicized by D. E. Knuth as Algorithm 3.2.2A in volume 2 of
+ * his work `The Art of Computer Programming'.  The generator is simple: at
+ * each stage it emits %$x_n = (x_{n - 55} + x_{n - 24}) \bmod 2^{32}$%.  The
+ * period is proven to be greater than %$2^{55}$%, and statistical properties
+ * appear to be good.
+ */
+
+#ifndef CATACOMB_FIBRAND_H
+#define CATACOMB_FIBRAND_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Magic constants ---------------------------------------------------*/
+
+#define FIB_SZ 55
+#define FIB_TAP 24
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct fibrand {
+  unsigned i;
+  uint32 x[FIB_SZ];
+} fibrand;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @fibrand_step@ --- *
+ *
+ * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
+ *
+ * Returns:    Next output from generator.
+ *
+ * Use:                Steps the generator.  Returns
+ *             %$x_{i - 24} + x_{i - 55} \bmod 2^{32}$%.
+ */
+
+extern uint32 fibrand_step(fibrand */*f*/);
+
+/* --- @fibrand_seed@ --- *
+ *
+ * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
+ *             @grand *r@ = random number generator to extract words from
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Fibonacci generator using word outputs from the
+ *             given random number source @r@.
+ */
+
+extern void fibrand_seed(fibrand */*f*/, grand */*r*/);
+
+/* --- @fibrand_lcseed@ --- *
+ *
+ * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
+ *             @uint32 seed@ = seed value
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Fibonacci generator using outputs from the
+ *             @lcrand@ generator seeded from @seed@.  This is faster than
+ *             using a generic @lcrand@-based generator and @fibrand_rseed@
+ *             because it uses raw outputs rather than uniformly distributed
+ *             32-bit words.
+ */
+
+extern void fibrand_lcseed(fibrand */*f*/, uint32 /*seed*/);
+
+/* --- @fibrand_range@ --- *
+ *
+ * Arguments:  @fibrand *f@ = pointer to Fibonacci generator context
+ *             @uint32 m@ = limit
+ *
+ * Returns:    A uniformly distributed pseudorandom integer in the interval
+ *             %$[0, m)$%.
+ */
+
+extern uint32 fibrand_range(fibrand */*f*/, uint32 /*m*/);
+
+/* --- @fibrand_create@ --- *
+ *
+ * Arguments:  @uint32 seed@ = initial seed
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a Fibonacci
+ *             generator.  The generator is seeded using @fibrand_lcseed@.
+ */
+
+extern grand *fibrand_create(uint32 /*seed*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/fipstest.c b/rand/fipstest.c
new file mode 100644 (file)
index 0000000..4bc9625
--- /dev/null
@@ -0,0 +1,189 @@
+/* -*-c-*-
+ *
+ * FIPS140 randomness tests
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "fipstest.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @monobit@ --- *
+ *
+ * Arguments:  @const octet *p@ = pointer to buffer
+ *
+ * Returns:    Zero if OK, @FIPSTEST_MONOBIT@ on failure.
+ *
+ * Use:                Performs the monobit test on a buffer of data.  If %$n_1$% is
+ *             the number of 1 bits in the buffer, then the monobit test is
+ *             passed when %$9654 < n_1 < 10346$%.
+ */
+
+static unsigned monobit(const octet *p)
+{
+  unsigned n1 = 0;
+  unsigned i, j;
+
+  for (i = 0; i < FIPSTEST_BUFSZ; i++) {
+    octet x = p[i];
+    for (j = 0; j < 8; j++) {
+      if (x & 1)
+       n1++;
+      x >>= 1;
+    }
+  }
+
+  if (9725 >= n1 || n1 >= 10275)
+    return (FIPSTEST_MONOBIT);
+  return (0);
+}
+
+/* --- @poker@ --- *
+ *
+ * Arguments:  @const octet *p@ = pointer to buffer
+ *
+ * Returns:    Zero if OK, @FIPSTEST_POKER@ on failure.
+ *
+ * Use:                Performs the poker test on a buffer of data.  The buffer is
+ *             divided into 4-bit nibbles %$x_i$%.  If
+ *             %$f(x) = \sum_{x_i = x} 1$% is the frequency of each nibble,
+ *             then the test is passed if
+ *             %$2.16 < 16/5000 \sum_i f(i)^2 - 5000 < 46.17$%.
+ */
+
+static unsigned poker(const octet *p)
+{
+  unsigned long f[16] = { 0 };
+  unsigned i;
+  unsigned long q = 0;
+
+  /* --- Compute the frequencies --- */
+
+  for (i = 0; i < FIPSTEST_BUFSZ; i++) {
+    octet x = p[i];
+    f[x & 0xf]++;
+    f[(x >> 4) & 0xf]++;
+  }
+
+  /* --- Now do the comparison --- *
+   *
+   * This can be simplified.  Multiply through the inequality by 5000 and
+   * we get %$5150 < 16 \sum_i f(i)^2 - 5000^2 < 287000$%.
+   */
+
+  for (i = 0; i < 16; i++)
+    q += f[i] * f[i];
+  q <<= 4;
+  q -= 5000ul * 5000ul;
+
+  if (10800 >= q || q >= 230850)
+    return (FIPSTEST_POKER);
+  return (0);
+}
+
+/* --- @runs@ --- *
+ *
+ * Arguments:  @const octet *p@ = pointer to buffer
+ *
+ * Returns:    Zero for success, @FIPSTEST_RUNS@ or @FIPSTEST_LONGRUNS@ on
+ *             failure.
+ *
+ * Use:                Performs the runs and long runs tests.  The frequency of each
+ *             `run', or sequence of equal bits, is counted and tested.
+ */
+
+static unsigned runs(const octet *p)
+{
+  unsigned rc = 0;
+  unsigned i, j;
+  unsigned r = 0;
+  unsigned bb = 0;
+  unsigned f[2][6] = { { 0 } };
+
+  /* --- Count the run lengths --- */
+
+  for (i = 0; i < FIPSTEST_BUFSZ; i++) {
+    octet x = p[i];
+    for (j = 0; j < 8; j++) {
+      unsigned b = x & 1;
+      x >>= 1;
+      if (b == bb)
+       r++;
+      else {
+       if (r) {
+         if (r >= 34)
+           rc |= FIPSTEST_LONGRUNS;
+         if (r > 6)
+           r = 6;
+         f[bb][r - 1]++;
+       }
+       r = 1;
+       bb = b;
+      }
+    }
+  }
+
+  if (r >= 26)
+    rc |= FIPSTEST_LONGRUNS;
+  if (r > 6)
+    r = 6;
+  f[bb][r - 1]++;
+
+  /* --- Check the results --- */
+
+  if (2343 > f[0][0] || f[0][0] > 2657 || 2343 > f[1][0] || f[1][0] > 2657 ||
+      1135 > f[0][1] || f[0][1] > 1365 || 1135 > f[1][1] || f[1][1] > 1365 ||
+       542 > f[0][2] || f[0][2] >  708 ||  542 > f[1][2] || f[1][2] >  708 ||
+       251 > f[0][3] || f[0][3] >  373 ||  251 > f[1][3] || f[1][3] >  373 ||
+       111 > f[0][4] || f[0][4] >  201 ||  111 > f[1][4] || f[1][4] >  201 ||
+       111 > f[0][5] || f[0][5] >  201 ||  111 > f[1][5] || f[1][5] >  201)
+    rc |= FIPSTEST_RUNS;
+
+  return (rc);
+}
+
+/* --- @fipstest@ --- *
+ *
+ * Arguments:  @const octet *p@ = pointer to a buffer of @FIPSTEST_BUFSZ@
+ *                     bytes
+ *
+ * Returns:    Zero if OK, or a bitmask of failed tests.
+ *
+ * Use:                Performs the FIPS140 randomness tests on a block of data.
+ */
+
+unsigned fipstest(const octet *p)
+{
+  unsigned rc = 0;
+  rc |= monobit(p);
+  rc |= poker(p);
+  rc |= runs(p);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/fipstest.h b/rand/fipstest.h
new file mode 100644 (file)
index 0000000..91facb2
--- /dev/null
@@ -0,0 +1,69 @@
+/* -*-c-*-
+ *
+ * FIPS140 randomness tests
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_FIPSTEST_H
+#define CATACOMB_FIPSTEST_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define FIPSTEST_BUFSZ 2500
+
+#define FIPSTEST_OK 0u
+#define FIPSTEST_MONOBIT 1u
+#define FIPSTEST_POKER 2u
+#define FIPSTEST_RUNS 4u
+#define FIPSTEST_LONGRUNS 8u
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @fipstest@ --- *
+ *
+ * Arguments:  @const octet *p@ = pointer to a buffer of @FIPSTEST_BUFSZ@
+ *                     bytes
+ *
+ * Returns:    Zero if OK, or a bitmask of failed tests.
+ *
+ * Use:                Performs the FIPS140 randomness tests on a block of data.
+ */
+
+extern unsigned fipstest(const octet */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/grand.c b/rand/grand.c
new file mode 100644 (file)
index 0000000..17d248b
--- /dev/null
@@ -0,0 +1,155 @@
+/* -*-c-*-
+ *
+ * Generic interface to random number generators
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#include "grand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @grand_byte@ --- *
+ *
+ * Arguments:  @grand *r@ = pointet to generic generator
+ *
+ * Returns:    A uniformly-distributed pseudorandom integer in the interval
+ *             %$[0, 256)$%.
+ */
+
+octet grand_byte(grand *r)
+{
+  if (r->ops->byte != grand_byte)
+    return (r->ops->byte(r));
+  else if (r->ops->word != grand_word)
+    return (r->ops->word(r) & 0xff);
+  else if (r->ops->fill != grand_fill) {
+    octet o;
+    r->ops->fill(r, &o, 1);
+    return (o);
+  } else
+    return (grand_range(r, 256));
+}
+
+/* --- @grand_word@ --- *
+ *
+ * Arguments:  @grand *r@ = pointet to generic generator
+ *
+ * Returns:    A uniformly-distributed pseudorandom integer in the interval
+ *             %$[0, 2^{32})$%.
+ */
+
+uint32 grand_word(grand *r)
+{
+  if (r->ops->word != grand_word)
+    return (r->ops->word(r));
+  else {
+    octet b[4];
+    grand_fill(r, b, sizeof(b));
+    return (LOAD32(b));
+  }
+}
+
+/* --- @grand_range@ --- *
+ *
+ * Arguments:  @grand *r@ = pointet to generic generator
+ *             @uint32 l@ = limit for acceptable results
+ *
+ * Returns:    A uniformly-distributed pseudorandom integer in the interval
+ *             %$[0, l)$%.
+ */
+
+uint32 grand_range(grand *r, uint32 l)
+{
+  if (r->ops->range != grand_range)
+    return (r->ops->range(r, l));
+  else {
+    uint32 m, z;
+    uint32 (*w)(grand */*r*/);
+    uint32 x;
+
+    /* --- Decide where to get data from --- *
+     *
+     * The choice of %$2^{32} - 1$% as a limit when using @grand_word@ isn't
+     * wonderful, but working with %$2^{32}$% is awkward and the loss of a
+     * few return values isn't significant.  The algorithm below still
+     * successfully returns uniformly distributed results.
+     */
+
+    if (r->ops->max) {
+      w = r->ops->raw;
+      m = r->ops->max;
+    } else {
+      w = grand_word;
+      m = 0xffffffff;
+    }
+
+    /* --- Work out maximum acceptable return value --- *
+     *
+     * This will be the highest multiple of @l@ less than @m@.
+     */
+
+    z = m - (m % l);
+
+    /* --- Generate numbers until something acceptable is found --- *
+     *
+     * This will require an expected number of attempts less than 2.
+     */
+
+    do x = w(r); while (x >= z);
+    return (x % l);
+  }
+}
+
+/* --- @grand_fill@ --- *
+ *
+ * Arguments:  @grand *r@ = pointet to generic generator
+ *             @void *p@ = pointer to a buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Fills a buffer with uniformly distributed pseudorandom bytes
+ *             (see @grand_byte@).
+ */
+
+void grand_fill(grand *r, void *p, size_t sz)
+{
+  if (r->ops->fill != grand_fill)
+    r->ops->fill(r, p, sz);
+  else {
+    octet *q = p;
+    while (sz) {
+      *q++ = r->ops->byte(r);
+      sz--;
+    }
+  }
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/grand.h b/rand/grand.h
new file mode 100644 (file)
index 0000000..ec11404
--- /dev/null
@@ -0,0 +1,161 @@
+/* -*-c-*-
+ *
+ * Generic interface to random number generators
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_GRAND_H
+#define CATACOMB_GRAND_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Generic random number generator interface -------------------------*/
+
+typedef struct grand {
+  const struct grand_ops *ops;
+} grand;
+
+typedef struct grand_ops {
+
+  /* --- Various important properties --- */
+
+  const char *name;                    /* Generator's name */
+  unsigned f;                          /* Various flags */
+  uint32 max;                          /* Maximum raw output */
+
+  /* --- Maintenance methods --- */
+
+  int (*misc)(grand */*r*/, unsigned /*op*/, ...); /* Miscellaneous ops */
+  void (*destroy)(grand */*r*/);       /* Destroy generator context */
+
+  /* --- Output methods --- *
+   *
+   * Only one of these operations need actually be implemented.  All the
+   * other operations may be synthesized.  Of course, performance is improved
+   * if more are provided.
+   */
+
+  uint32 (*raw)(grand */*r*/);         /* Uniform over %$[0, max)$% */
+  octet (*byte)(grand */*r*/);         /* Uniform over %$[0, 256)$% */
+  uint32 (*word)(grand */*r*/);                /* Uniform over %$[0, 2^{32})$% */
+  uint32 (*range)(grand */*r*/, uint32 /*l*/); /* Uniform over %$[0, l)$% */
+  void (*fill)(grand */*r*/, void */*p*/, size_t /*sz*/); /* Fill buffer */
+} grand_ops;
+
+#define GR_DESTROY(r)          (r)->ops->destroy((r))
+#define GR_RAW(r)              (r)->ops->raw((r))
+#define GR_WORD(r)             (r)->ops->word((r))
+#define GR_RANGE(r, l)         (r)->ops->range((r), (l))
+#define GR_FILL(r, p, sz)      (r)->ops->fill((r), (p), (sz))
+
+/* --- Flag types --- */
+
+#define GRAND_CRYPTO 1u                        /* Cryptographically strong */
+
+/* --- Operation types --- */
+
+enum {
+
+  /* --- Required operations --- */
+
+  GRAND_CHECK,                         /* @unsigned op2@ */
+
+  /* --- Standard seeding operations --- */
+
+  GRAND_SEEDINT,                       /* @int i@ */
+  GRAND_SEEDUINT32,                    /* @uint32 i@ */
+  GRAND_SEEDBLOCK,                     /* @const void *p, size_t sz@ */
+  GRAND_SEEDMP,                                /* @mp *m@ */
+  GRAND_SEEDRAND                       /* @grand *g@ */
+
+  /* --- Generator-specific operations --- */
+
+#define GRAND_SPECIFIC(ch) ((unsigned)(ch) << 8)
+};
+
+#define GRAND_BADOP assert(((void)"bad grand_misc op", 0))
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @grand_byte@ --- *
+ *
+ * Arguments:  @grand *r@ = pointet to generic generator
+ *
+ * Returns:    A uniformly-distributed pseudorandom integer in the interval
+ *             %$[0, 256)$%.
+ */
+
+extern octet grand_byte(grand */*r*/);
+
+/* --- @grand_word@ --- *
+ *
+ * Arguments:  @grand *r@ = pointet to generic generator
+ *
+ * Returns:    A uniformly-distributed pseudorandom integer in the interval
+ *             %$[0, 2^{32})$%.
+ */
+
+extern uint32 grand_word(grand */*r*/);
+
+/* --- @grand_range@ --- *
+ *
+ * Arguments:  @grand *r@ = pointet to generic generator
+ *             @uint32 l@ = limit for acceptable results
+ *
+ * Returns:    A uniformly-distributed pseudorandom integer in the interval
+ *             %$[0, l)$%.
+ */
+
+extern uint32 grand_range(grand */*r*/, uint32 /*l*/);
+
+/* --- @grand_fill@ --- *
+ *
+ * Arguments:  @grand *r@ = pointet to generic generator
+ *             @void *p@ = pointer to a buffer
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Fills a buffer with uniformly distributed pseudorandom bytes
+ *             (see @grand_byte@).
+ */
+
+extern void grand_fill(grand */*r*/, void */*p*/, size_t /*sz*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/lcrand.c b/rand/lcrand.c
new file mode 100644 (file)
index 0000000..6944a71
--- /dev/null
@@ -0,0 +1,304 @@
+/* -*-c-*-
+ *
+ * Simple linear congruential generator
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#include "grand.h"
+#include "lcrand.h"
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+/* --- The generator parameters --- */
+
+#define P LCRAND_P                     /* Modulus */
+#define A LCRAND_A                     /* Multiplier (primitive mod @p@) */
+#define C LCRAND_C                     /* Additive constant */
+
+/* --- Precomputed values for modular reduction --- */
+
+#define D 5                            /* %$p = 2^{32} - d$% */
+
+/* --- Other useful bits --- */
+
+#define P256 4294967040u               /* Highest multiple of 256 < %$p$% */
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @lcrand@ --- *
+ *
+ * Arguments:  @uint32 x@ = seed value
+ *
+ * Returns:    New state of the generator.
+ *
+ * Use:                Steps the generator.  Returns %$ax + c \bmod p$%.
+ */
+
+uint32 lcrand(uint32 x)
+{
+  uint32 a[2], xx[2];
+  uint32 yy[2];
+
+  /* --- Unpack things into the arrays --- */
+
+  a[0] = U16(A); a[1] = U16(A >> 16);
+  xx[0] = U16(x); xx[1] = U16(x >> 16);
+
+  /* --- Multiply everything together --- *
+   *
+   * This is plain old long multiplication, although it looks a bit strange.
+   * I set up the top and bottom partial products directly where they're
+   * supposed to be.  The cross terms I add together, with the low 16 bits in
+   * @q@ and the high 32 bits in @p@.  These I then add into the product.
+   */
+
+  {
+    uint32 p, q;
+
+    yy[0] = a[0] * xx[0];
+    yy[1] = a[1] * xx[1];
+
+    p = a[0] * xx[1];
+    q = p + a[1] * xx[0];
+    p = ((q < p) << 16) + (q >> 16);
+    q = U16(q) << 16;
+
+    q += yy[0];
+    if (q < yy[0])
+      p++;
+    else
+      p += (q >> 16) >> 16;
+    yy[0] = q;
+
+    yy[1] += p;
+  }
+
+  /* --- Now reduce mod p --- *
+   *
+   * I'm using shifts and adds to do the multiply step here.  This needs to
+   * be changed if @D@ ever becomes something other than 5.
+   */
+
+#if D != 5
+#  error "Change shift sequence!"
+#endif
+
+  {
+    uint32 q;
+
+    q = yy[1];
+    x = yy[0];
+
+    while (q) {
+      uint32 y, z;
+      y = q >> 30;
+      z = q << 2;
+      z += q;
+      if (z < q)
+       y++;
+      else
+       y += (q >> 16) >> 16;
+      q = y;
+      x += z;
+      if (x < z || x > P)
+       x -= P;
+    }
+  }
+
+  /* --- Now add on the constant --- */
+
+  x += C;
+  if (x < C || x >= P)
+    x -= P;
+
+  /* --- Done --- */
+
+  return (x);
+}
+
+/* --- @lcrand_range@ --- *
+ *
+ * Arguments:  @uint32 *x@ = pointer to seed value (updated)
+ *             @uint32 m@ = limit allowable
+ *
+ * Returns:    A uniformly distributed pseudorandom integer in the interval
+ *             %$[0, m)$%.
+ */
+
+uint32 lcrand_range(uint32 *x, uint32 m)
+{
+  uint32 xx = *x;
+  uint32 r = P - P % m;
+  do xx = lcrand(xx); while (xx >= r);
+  *x = xx;
+  return (xx % m);
+}
+
+/*----- Generic interface -------------------------------------------------*/
+
+typedef struct gctx {
+  grand r;
+  uint32 x;
+} gctx;
+
+static void gdestroy(grand *r)
+{
+  gctx *g = (gctx *)r;
+  DESTROY(g);
+}
+
+static int gmisc(grand *r, unsigned op, ...)
+{
+  gctx *g = (gctx *)r;
+  va_list ap;
+  int rc = 0;
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDRAND:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT:
+      g->x = va_arg(ap, unsigned);
+      break;
+    case GRAND_SEEDUINT32:
+      g->x = va_arg(ap, uint32);
+      break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      uint32 x;
+      do x = rr->ops->word(rr); while (x >= P || x == LCRAND_FIXEDPT);
+      g->x = x;
+    } break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static uint32 graw(grand *r)
+{
+  gctx *g = (gctx *)r;
+  g->x = lcrand(g->x);
+  return (g->x);
+}
+
+static octet gbyte(grand *r)
+{
+  gctx *g = (gctx *)r;
+  uint32 x = g->x;
+  do x = lcrand(x); while (x >= P256);
+  g->x = x;
+  return (x / (P256 / 256));
+}
+
+static uint32 grange(grand *r, uint32 l)
+{
+  gctx *g = (gctx *)r;
+  return (lcrand_range(&g->x, l));
+}
+
+static const grand_ops gops = {
+  "lcrand",
+  LCRAND_P, 0,
+  gmisc, gdestroy,
+  graw, gbyte, grand_word, grange, grand_fill
+};
+
+/* --- @lcrand_create@ --- *
+ *
+ * Arguments:  @uint32 x@ = initial seed
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a linear
+ *             congruential generator.
+ */
+
+grand *lcrand_create(uint32 x)
+{
+  gctx *g = CREATE(gctx);
+  g->r.ops = &gops;
+  g->x = x;
+  return (&g->r);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+static int verify(dstr *v)
+{
+  uint32 x = *(uint32 *)v[0].buf;
+  uint32 y = *(uint32 *)v[1].buf;
+  uint32 z = lcrand(x);
+  int ok = 1;
+  if (y != z) {
+    fprintf(stderr,
+           "\n*** lcrand failed.  lcrand(%lu) = %lu, expected %lu\n",
+           (unsigned long)x, (unsigned long)z, (unsigned long)y);
+    ok = 0;
+  }
+  return (ok);
+}
+
+static test_chunk tests[] = {
+  { "lcrand", verify, { &type_uint32, &type_uint32, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, tests, SRCDIR"/t/lcrand");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/lcrand.h b/rand/lcrand.h
new file mode 100644 (file)
index 0000000..9102096
--- /dev/null
@@ -0,0 +1,119 @@
+/* -*-c-*-
+ *
+ * Simple linear congruential generator
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on the linear congruential generator ------------------------*
+ *
+ * This pseudorandom number generator is simple, but has absolutely no
+ * cryptographic strength whatever.  It may be used whenever random numbers
+ * are required but cryptographic strength is not, for example when
+ * generating numbers for use in primality tests.  To be honest, it's not
+ * even particularly fast, although a certain amount of effort has been
+ * expended on making it better than awfully slow.  To put things in
+ * perspective, it can't quite spit bytes out as fast as OFB DES.  (Then
+ * again, bytes aren't its natural output format.)  Its main use is probably
+ * seeding a Fibonacci generator.
+ *
+ * There exists a fixed-point input @LCRAND_FIXEDPT@ -- when fed to the
+ * generator it comes straight back out again.  All other inputs less than
+ * the modulus are part of the same sequence of period %$p - 1$%.
+ *
+ * The generator has been tested for its statistical properties.  George
+ * Marsaglia's Diehard tests give it a reasonably clean bill of health.
+ *
+ * The modulus %$p$% is chosen as the largest prime number less than
+ * %$2^{32}$%.  The multiplier %$a$% and additive constant %$c$% are based on
+ * the decimal expansions of %$\pi$% and %$e$%, with the additional
+ * restriction that the multiplier must be a primitive element modulo %$p$%.
+ * The fixed point value is determined as %$c / (1 - a) \bmod p$%.
+ */
+
+#ifndef CATACOMB_LCRAND_H
+#define CATACOMB_LCRAND_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Constants ---------------------------------------------------------*/
+
+#define LCRAND_P 4294967291u           /* Modulus for the generator */
+#define LCRAND_A 314159265u            /* Multiplier (primitive mod @p@) */
+#define LCRAND_C 271828183u            /* Additive constant */
+
+#define LCRAND_FIXEDPT 3223959250u     /* Fixed point (only bad input) */
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @lcrand@ --- *
+ *
+ * Arguments:  @uint32 x@ = seed value
+ *
+ * Returns:    New state of the generator.
+ *
+ * Use:                Steps the generator.  Returns %$ax + c \bmod p$%.
+ */
+
+extern uint32 lcrand(uint32 /*x*/);
+
+/* --- @lcrand_range@ --- *
+ *
+ * Arguments:  @uint32 *x@ = pointer to seed value (updated)
+ *             @uint32 m@ = limit allowable
+ *
+ * Returns:    A uniformly distributed pseudorandom integer in the interval
+ *             %$[0, m)$%.
+ */
+
+extern uint32 lcrand_range(uint32 */*x*/, uint32 /*m*/);
+
+/* --- @lcrand_create@ --- *
+ *
+ * Arguments:  @uint32 x@ = initial seed
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a linear
+ *             congruential generator.
+ */
+
+extern grand *lcrand_create(uint32 /*x*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/maurer.c b/rand/maurer.c
new file mode 100644 (file)
index 0000000..d66194e
--- /dev/null
@@ -0,0 +1,233 @@
+/* -*-c-*-
+ *
+ * Maurer's universal statistical test
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+
+#include "maurer.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct bitscan {
+  const octet *p;
+  unsigned b;
+  uint32 a;
+} bitscan;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @maurer_init@ --- *
+ *
+ * Arguments:  @maurer_ctx *m@ = pointer to a context to initialize
+ *             @unsigned l@ = number of bits to take at a time
+ *
+ * Returns:    Minimum recommended amount of data to test.
+ *
+ * Use:                Initializes a Maurer testing context.  Note that @l@ values
+ *             larger than 16 are not supported, and values less than 6 can
+ *             give bizarre results.
+ */
+
+unsigned long maurer_init(maurer_ctx *m, unsigned l)
+{
+  size_t i;
+
+  assert(((void)"(maurer_init): chunks larger than 16 bits not supported",
+         0 < l && l <= 16));
+
+  m->l = l;
+  m->a = 0;
+  m->b = 0;
+  m->n = 0;
+  m->x = 0;
+
+  m->t = xmalloc(sizeof(unsigned long) << l);
+  for (i = 0; i < (1 << l); i++)
+    m->t[i] = 0;
+  return (((1000ul << l) * l + 7)/8);
+}
+
+/* --- @bits@ --- *
+ *
+ * Arguments:  @maurer_ctx *m@ = pointer to testing context
+ *             @const octet **p@ = address of a buffer pointer
+ *             @const octet *q@ = limit of the buffer pointer
+ *             @unsigned *x@ = address to store next chunk
+ *
+ * Returns:    Nonzero if some more bits arrived.
+ *
+ * Use:                Reads some bits from a buffer.
+ */
+
+static int bits(maurer_ctx *m, const octet **p, const octet *q, unsigned *x)
+{
+  while (m->b < m->l) {
+    if (*p >= q)
+      return (0);
+    m->a |= U8(*(*p)++) << m->b;
+    m->b += 8;
+  }
+  *x = m->a & ((1 << m->l) - 1);
+  m->a >>= m->l;
+  m->b -= m->l;
+  m->n++;
+  return (1);
+}
+
+/* --- @maurer_test@ --- *
+ *
+ * Arguments:  @maurer_ctx *m@ = pointer to a Maurer testing context
+ *             @const void *buf@ = pointer to a buffer of data
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Scans a buffer of data and updates the testing context.
+ */
+
+void maurer_test(maurer_ctx *m, const void *buf, size_t sz)
+{
+  const octet *p = buf, *l = p + sz;
+  unsigned long q = 10 << m->l;
+  unsigned x;
+
+  /* --- Initialize the table --- */
+
+  while (m->n < q) {
+    if (!bits(m, &p, l, &x))
+      return;
+    m->t[x] = m->n;
+  }
+
+  /* --- Update the statistic --- */
+
+  while (bits(m, &p, l, &x)) {
+    m->x += log(m->n - m->t[x]);
+    m->t[x] = m->n;
+  }
+}
+
+/* --- @maurer_done@ --- *
+ *
+ * Arguments:  @maurer_ctx *m@ = pointer to a Maurer testing context
+ *
+ * Returns:    The statistic %$Z_u = (X_u - \mu)/\sigma$%, which should be
+ *             normally distributed with a mean of 0 and variance of 1.
+ *
+ * Use:                Returns the result of Maurer's universal statistical test.
+ *             Also frees the memory allocated during initialization.
+ *
+ *             If insufficient data was received, the value @HUGE_VAL@ is
+ *             returned.
+ */
+
+double maurer_done(maurer_ctx *m)
+{
+  double x, mu, c, sigma;
+  unsigned long q = 10 << m->l, k;
+
+  /* --- Table for means and variances --- */
+
+  struct { double mu, var_1; } vtab[] = {
+    {  0.7326495, 0.690 },
+    {  1.5374383, 1.338 },
+    {  2.4016068, 1.901 },
+    {  3.3112247, 2.358 },
+    {  4.2534266, 2.705 },
+    {  5.2177052, 2.945 },
+    {  6.1962507, 3.125 },
+    {  7.1836656, 3.238 },
+    {  8.1764248, 3.311 },
+    {  9.1723243, 3.356 },
+    { 10.170032 , 3.384 },
+    { 11.168765 , 3.401 },
+    { 12.168070 , 3.410 },
+    { 13.167693 , 3.416 },
+    { 14.167488 , 3.419 },
+    { 15.167379 , 3.421 }
+  };
+
+  /* --- Check for bogus requests --- */
+
+  if (m->n < q) {
+    x = HUGE_VAL;
+    goto done;
+  }
+
+  /* --- Do the maths --- *
+   *
+   * This produces %$X_u$%, which should be normally distributed with a mean
+   * and variance we can compute.
+   */
+
+  k = m->n - q;
+  x = m->x/(k * log(2));
+
+  /* --- Now translate this into %$Z_u$% distributed as %$N(0, 1)$% --- */
+
+  mu = vtab[m->l - 1].mu;
+  c = 0.7 - 0.8/m->l + (1.6 + 12.8/m->l) * pow(k, -4.0/m->l);
+  sigma = sqrt(c * c * vtab[m->l - 1].var_1 / k);
+  x = (x - mu)/sigma;
+
+  /* --- Done (phew!) --- */
+
+done:
+  xfree(m->t);
+  return (x);
+}
+
+/* --- @maurer@ --- *
+ *
+ * Arguments:  @const octet *p@ = pointer to a buffer of data
+ *             @size_t sz@ = size of the buffer
+ *             @unsigned l@ = number of bits to take at a time
+ *
+ * Returns:    The statistic %$Z_u$%.
+ *
+ * Use:                Simple interface to Maurer's universal statistical test.  For
+ *             large %$l$% you should use the more complicated restartable
+ *             interface.
+ */
+
+double maurer(const octet *p, size_t sz, unsigned l)
+{
+  maurer_ctx m;
+
+  maurer_init(&m, l);
+  maurer_test(&m, p, sz);
+  return (maurer_done(&m));
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/maurer.h b/rand/maurer.h
new file mode 100644 (file)
index 0000000..0acfd39
--- /dev/null
@@ -0,0 +1,117 @@
+/* -*-c-*-
+ *
+ * Maurer's universal statistical test
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_MAURER_H
+#define CATACOMB_MAURER_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct maurer_ctx {
+  unsigned l;                          /* Chunk size, in bits */
+  uint32 a;                            /* Bitscanner accumulator */
+  unsigned b;                          /* Number of bits in accumulator */
+  unsigned long n;                     /* Number of chunks read so far */
+  double x;                            /* Statistic value */
+  unsigned long *t;                    /* Offset table */
+} maurer_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @maurer_init@ --- *
+ *
+ * Arguments:  @maurer_ctx *m@ = pointer to a context to initialize
+ *             @unsigned l@ = number of bits to take at a time
+ *
+ * Returns:    Minimum recommended amount of data to test.
+ *
+ * Use:                Initializes a Maurer testing context.  Note that @l@ values
+ *             larger than 16 are not supported, and values less than 6 can
+ *             give bizarre results.
+ */
+
+extern unsigned long maurer_init(maurer_ctx */*m*/, unsigned /*l*/);
+
+/* --- @maurer_test@ --- *
+ *
+ * Arguments:  @maurer_ctx *m@ = pointer to a Maurer testing context
+ *             @const void *buf@ = pointer to a buffer of data
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Scans a buffer of data and updates the testing context.
+ */
+
+extern void maurer_test(maurer_ctx */*m*/,
+                       const void */*buf*/, size_t /*sz*/);
+
+/* --- @maurer_done@ --- *
+ *
+ * Arguments:  @maurer_ctx *m@ = pointer to a Maurer testing context
+ *
+ * Returns:    The statistic %$Z_u = (X_u - \mu)/\sigma$%, which should be
+ *             normally distributed with a mean of 0 and variance of 1.
+ *
+ * Use:                Returns the result of Maurer's universal statistical test.
+ *             Also frees the memory allocated during initialization.
+ *
+ *             If insufficient data was received, the value @HUGE_VAL@ is
+ *             returned.
+ */
+
+extern double maurer_done(maurer_ctx */*m*/);
+
+/* --- @maurer@ --- *
+ *
+ * Arguments:  @const octet *p@ = pointer to a buffer of data
+ *             @size_t sz@ = size of the buffer
+ *             @unsigned l@ = number of bits to take at a time
+ *
+ * Returns:    The statistic %$Z_u$%.
+ *
+ * Use:                Simple interface to Maurer's universal statistical test.  For
+ *             large %$l$% you should use the more complicated restartable
+ *             interface.
+ */
+
+extern double maurer(const octet */*p*/, size_t /*sz*/, unsigned /*l*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/noise.c b/rand/noise.c
new file mode 100644 (file)
index 0000000..6ab1070
--- /dev/null
@@ -0,0 +1,459 @@
+/* -*-c-*-
+ *
+ * Acquisition of environmental noise (Unix-specific)
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef HAVE_SETGROUPS
+#  include <grp.h>
+#endif
+
+#include <mLib/bits.h>
+#include <mLib/tv.h>
+
+#include "noise.h"
+#include "paranoia.h"
+#include "rand.h"
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define NOISE_KIDLIFE 100000           /* @noise_filter@ child lifetime */
+#define MILLION 1000000                        /* One million */
+
+/*----- Noise source definition -------------------------------------------*/
+
+const rand_source noise_source = { noise_acquire, noise_timer };
+
+/*----- Static variables --------------------------------------------------*/
+
+/* --- Timer differences --- */
+
+static unsigned long noise_last;       /* Last time recorded */
+static unsigned long noise_diff;       /* Last first order difference */
+
+/* --- Setuid program handling --- */
+
+static uid_t noise_uid = NOISE_NOSETUID; /* Uid to set to spawn processes */
+static gid_t noise_gid = NOISE_NOSETGID; /* Gid to set to spawn processes */
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @bitcount@ --- *
+ *
+ * Arguments:  @unsigned long x@ = a word containing bits
+ *
+ * Returns:    The number of bits set in the word.
+ */
+
+static int bitcount(unsigned long x)
+{
+  char ctab[] = { 0, 1, 1, 2, 1, 2, 2, 3,
+                 1, 2, 2, 3, 2, 3, 3, 4 };
+  int count = 0;
+  while (x) {
+    count += ctab[x & 0xfu];
+    x >>= 4;
+  }
+  return (count);
+}
+
+/* --- @timer@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to randomness pool
+ *             @struct timeval *tv@ = pointer to time block
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Low-level timer contributor.
+ */
+
+static int timer(rand_pool *r, struct timeval *tv)
+{
+  unsigned long x, d, dd;
+  int de, dde;
+  int ret;
+
+  x = tv->tv_usec + MILLION * tv->tv_sec;
+  d = x ^ noise_last;
+  dd = d ^ noise_diff;
+  noise_diff = d;
+  de = bitcount(d);
+  dde = bitcount(dd);
+  rand_add(r, tv, sizeof(*tv), de <= dde ? de : dde);
+  ret = (de || dde);
+  BURN(tv); x = d = dd = de = dde = 0;
+  return (ret);
+}
+
+/* --- @noise_timer@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Contributes the current time to the randomness pool.
+ *             A guess at the number of useful bits contributed is made,
+ *             based on first and second order bit differences.  This isn't
+ *             ever-so reliable, but it's better than nothing.
+ */
+
+int noise_timer(rand_pool *r)
+{
+  struct timeval tv;
+  gettimeofday(&tv, 0);
+  return (timer(r, &tv));
+}
+
+/* --- @noise_devrandom@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Attempts to obtain some randomness from the system entropy
+ *             pool.  All bits from the device are assumed to be good.
+ */
+
+int noise_devrandom(rand_pool *r)
+{
+  int fd;
+  octet buf[RAND_POOLSZ];
+  ssize_t len;
+  int ret = 0;
+
+  /* --- Be nice to other clients of the random device --- *
+   *
+   * Attempt to open the device nonblockingly.  If that works, take up to
+   * one bufferful and then close again.  If there's no data to be read,
+   * then that's tough and we go away again, on the grounds that the device
+   * needs to get some more entropy from somewhere.
+   */
+
+  if ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
+      (fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
+      (fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) {
+    if ((len = read(fd, buf, sizeof(buf))) > 0) {
+      rand_add(r, buf, len, len * 8);
+      BURN(buf);
+      ret = 1;
+    }
+    close(fd);
+  }
+  noise_timer(r);
+  return (ret);
+}
+
+/* --- @noise_setid@ --- *
+ *
+ * Arguments:  @uid_t uid@ = uid to set
+ *             @gid_t gid@ = gid to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets the user and group ids to be used by @noise_filter@
+ *             when running child processes.  This is useful to avoid
+ *             giving shell commands (even carefully written ones) undue
+ *             privileges.  This interface is Unix-specific
+ */
+
+void noise_setid(uid_t uid, gid_t gid)
+{
+  noise_uid = uid;
+  noise_gid = gid;
+}
+
+/* --- @noise_filter@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @int good@ = number of good bits per 1024 bits
+ *             @const char *c@ = shell command to run
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Attempts to execute a shell command, and dump it into the
+ *             randomness pool.  A very rough estimate of the number of
+ *             good bits is made, based on the size of the command's output.
+ *             This function calls @waitpid@, so be careful.  Before execing
+ *             the command, the process uid and gid are set to the values
+ *             given to @noise_setid@, and an attempt is made to reset the
+ *             list of supplementary groups.  The environment passed to
+ *             the command has been severly lobotimized.  If the command
+ *             fails to complete within a short time period, it is killed.
+ *             Paranoid use of close-on-exec flags for file descriptors is
+ *             recommended.
+ *
+ *             This interface is Unix-specific.
+ */
+
+int noise_filter(rand_pool *r, int good, const char *c)
+{
+  char buf[4096];
+  pid_t kid;
+  int fd[2];
+  struct timeval dead;
+  int ret = 0;
+  const char *env[] = {
+    "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc",
+    0
+  };
+
+  /* --- Remember when this business started --- */
+
+  gettimeofday(&dead, 0);
+  timer(r, &dead);
+
+  /* --- Create a pipe --- */
+
+  if (pipe(fd))
+    return (ret);
+
+  /* --- Fork a child off --- */
+
+  fflush(0);
+  kid = fork();
+  if (kid < 0) {
+    close(fd[0]);
+    close(fd[1]);
+    return (ret);
+  }
+
+  /* --- Handle the child end of the deal --- */
+
+  if (kid == 0) {
+    int f;
+
+    /* --- Set the pipe as standard output, close standard input --- */
+
+    close(0); close(1); close(2);
+
+    if (fd[1] != 1) {
+      if (dup2(fd[1], 1) < 0) _exit(127);
+      close(fd[1]);
+    }
+
+    if ((f = open("/dev/null", O_RDONLY)) != 0 ||
+       (f = open("/dev/null", O_WRONLY)) != 2)
+      _exit(127);
+
+    /* --- Play games with uids --- */
+
+    if (noise_gid != NOISE_NOSETGID) {
+      setgid(noise_gid);
+      setegid(noise_gid);
+#ifdef HAVE_SETGROUPS
+      setgroups(1, &noise_gid);
+#endif
+    }
+
+    if (noise_uid != NOISE_NOSETUID) {
+      setuid(noise_uid);
+      seteuid(noise_uid);
+    }
+
+    /* --- Start the process up --- */
+
+    execle("/bin/sh", "-c", c, (char *)0, env);
+    _exit(127);
+  }
+
+  /* --- Sort out my end of the deal --- */
+
+  close(fd[1]);
+
+  /* --- Decide on the deadline --- */
+
+  TV_ADDL(&dead, &dead, 0, NOISE_KIDLIFE);
+
+  /* --- Now read, and think --- */
+
+  for (;;) {
+    struct timeval now, diff;
+    fd_set rd;
+
+    gettimeofday(&now, 0);
+    timer(r, &now);
+    if (TV_CMP(&now, >, &dead))
+      break;
+    TV_SUB(&diff, &dead, &now);
+
+    FD_ZERO(&rd);
+    FD_SET(fd[0], &rd);
+
+    if (select(fd[0] + 1, &rd, 0, 0, &diff) < 0)
+      break;
+    if (FD_ISSET(fd[0], &rd)) {
+      ssize_t sz;
+      int goodbits;
+
+      if ((sz = read(fd[0], buf, sizeof(buf))) <= 0)
+       break;
+      goodbits = (sz * good) / 128;
+      rand_add(r, buf, sz, goodbits);
+      ret = 1;
+    }
+  }
+
+  /* --- We've finished with it: kill the child process --- *
+   *
+   * This is morally questionable.  On the other hand, I don't want to be
+   * held up in the @waitpid@ call if I can possibly help it.  Maybe a
+   * double-fork is worth doing here.
+   */
+
+  close(fd[0]);
+  BURN(buf);
+  noise_timer(r);
+  kill(kid, SIGKILL);
+  waitpid(kid, 0, 0);
+  return (ret);
+}
+
+/* --- @noise_freewheel@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Runs a free counter for a short while as a desparate attempt
+ *             to get randomness from somewhere.  This is actually quite
+ *             effective.
+ */
+
+#ifdef USE_FREEWHEEL
+
+static jmp_buf fwjmp;
+
+static void fwalarm(int sig)
+{
+  siglongjmp(fwjmp, 1);
+}
+
+int noise_freewheel(rand_pool *r)
+{
+  void (*sigal)(int) = 0;
+  struct itimerval oitv, itv = { { 0, 0 }, { 0, 5000 } };
+  int rc = 0;
+  volatile uint32 fwcount = 0;
+
+  if (!sigsetjmp(fwjmp, 1)) {
+    if ((sigal = signal(SIGALRM, fwalarm)) == SIG_ERR)
+      return (0);
+    if (setitimer(ITIMER_REAL, &itv, &oitv))
+      goto done;
+    for (;;)
+      fwcount++;
+  } else {
+    octet buf[4];
+    STORE32(buf, fwcount);
+    rand_add(r, buf, sizeof(buf), 16);
+    rc = 1;
+  }
+
+done:
+  signal(SIGALRM, sigal);
+  if (oitv.it_value.tv_sec || oitv.it_value.tv_usec)
+    TV_SUB(&oitv.it_value, &oitv.it_value, &itv.it_value);
+  setitimer(ITIMER_REAL, &oitv, 0);
+  return (rc);
+}
+
+#else
+
+int noise_freewheel(rand_pool *r)
+{
+  return (0);
+}
+
+#endif
+
+/* --- @noise_enquire@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Runs some shell commands to enquire about the prevailing
+ *             environment.  This can gather quite a lot of low-quality
+ *             entropy.
+ */
+
+int noise_enquire(rand_pool *r)
+{
+  struct tab {
+    const char *cmd;
+    unsigned rate;
+  } tab[] = {
+    { "ps alxww || ps -elf",   16 },
+    { "netstat -n",             6 },
+    { "ifconfig -a",            8 },
+    { "df",                    20 },
+    { "w",                      6 },
+    { "ls -align /tmp/.",      10 },
+    { 0,                        0 }
+  };
+  int i;
+
+  for (i = 0; tab[i].cmd; i++)
+    noise_filter(r, tab[i].rate, tab[i].cmd);
+  return (1);
+}
+
+/* --- @noise_acquire@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    ---
+ *
+ * Use:                Acquires some randomness from somewhere.
+ */
+
+void noise_acquire(rand_pool *r)
+{
+  unsigned i;
+  for (i = 0; i < 8; i++)
+    noise_freewheel(r);
+  if (!noise_devrandom(r)) {
+    noise_enquire(r);
+    for (i = 0; i < 8; i++)
+      noise_freewheel(r);
+  }
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/noise.h b/rand/noise.h
new file mode 100644 (file)
index 0000000..ad93c7e
--- /dev/null
@@ -0,0 +1,163 @@
+/* -*-c-*-
+ *
+ * Acquisition of environmental noise (Unix-specific)
+ *
+ * (c) 1998 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.
+ */
+
+#ifndef CATACOMB_NOISE_H
+#define CATACOMB_NOISE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <sys/types.h>
+
+#ifndef CATACOMB_RAND_H
+#  include "rand.h"
+#endif
+
+/*----- Noise source definition -------------------------------------------*/
+
+extern const rand_source noise_source;
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define NOISE_NOSETUID ((uid_t)-1)
+#define NOISE_NOSETGID ((gid_t)-1)
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @noise_timer@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Contributes the current time to the randomness pool.
+ *             A guess at the number of useful bits contributed is made,
+ *             based on first and second order bit differences.  This isn't
+ *             ever-so reliable, but it's better than nothing.
+ */
+
+extern int noise_timer(rand_pool */*r*/);
+
+/* --- @noise_devrandom@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Attempts to obtain some randomness from the system entropy
+ *             pool.  All bits from the device are assumed to be good.
+ */
+
+extern int noise_devrandom(rand_pool */*r*/);
+
+/* --- @noise_setid@ --- *
+ *
+ * Arguments:  @uid_t uid@ = uid to set
+ *             @gid_t gid@ = gid to set
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets the user and group ids to be used by @noise_filter@
+ *             when running child processes.  This is useful to avoid
+ *             giving shell commands (even carefully written ones) undue
+ *             privileges.  This interface is Unix-specific.
+ */
+
+extern void noise_setid(uid_t /*uid*/, gid_t /*gid*/);
+
+/* --- @noise_filter@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @int good@ = number of good bits per 1024 bits
+ *             @const char *c@ = shell command to run
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Attempts to execute a shell command, and dump it into the
+ *             randomness pool.  A very rough estimate of the number of
+ *             good bits is made, based on the size of the command's output.
+ *             This function calls @waitpid@, so be careful.  Before execing
+ *             the command, the process uid and gid are set to the values
+ *             given to @noise_setid@, and an attempt is made to reset the
+ *             list of supplementary groups.  The environment passed to
+ *             the command has been severly lobotimized.  If the command
+ *             fails to complete within a short time period, it is killed.
+ *             Paranoid use of close-on-exec flags for file descriptors is
+ *             recommended.
+ *
+ *             This interface is Unix-specific.
+ */
+
+extern int noise_filter(rand_pool */*r*/, int /*good*/, const char */*c*/);
+
+/* --- @noise_freewheel@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Runs a free counter for a short while as a desparate attempt
+ *             to get randomness from somewhere.  This is actually quite
+ *             effective.
+ */
+
+int noise_freewheel(rand_pool */*r*/);
+
+/* --- @noise_enquire@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Nonzero if some randomness was contributed.
+ *
+ * Use:                Runs some shell commands to enquire about the prevailing
+ *             environment.  This can gather quite a lot of low-quality
+ *             entropy.
+ */
+
+extern int noise_enquire(rand_pool */*r*/);
+
+/* --- @noise_acquire@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    ---
+ *
+ * Use:                Acquires some randomness from somewhere.
+ */
+
+extern void noise_acquire(rand_pool */*r*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/rand.c b/rand/rand.c
new file mode 100644 (file)
index 0000000..fa6dab8
--- /dev/null
@@ -0,0 +1,584 @@
+/* -*-c-*-
+ *
+ * Secure random number generator
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#include "arena.h"
+#include "blowfish-cbc.h"
+#include "paranoia.h"
+#include "rand.h"
+#include "rmd160.h"
+#include "rmd160-hmac.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static const grand_ops gops;
+
+typedef struct gctx {
+  grand r;
+  rand_pool p;
+} gctx;
+
+static gctx *pool = 0;                 /* Default random pool */
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define RAND_RESOLVE(r) do {                                           \
+  if ((r) == RAND_GLOBAL) {                                            \
+    if (!pool)                                                         \
+      pool = (gctx *)rand_create();                                    \
+    (r) = &pool->p;                                                    \
+  }                                                                    \
+} while (0)
+
+#define TIMER(r) do {                                                  \
+  if ((r)->s && (r)->s->timer)                                         \
+    (r)->s->timer(r);                                                  \
+} while (0)
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rand_init@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a randomness pool.  The pool doesn't start out
+ *             very random: that's your job to sort out.  A good suggestion
+ *             would be to attach an appropriate noise source and call
+ *             @rand_seed@.
+ */
+
+void rand_init(rand_pool *r)
+{
+  RAND_RESOLVE(r);
+  memset(r->pool, 0, sizeof(r->pool));
+  memset(r->buf, 0, sizeof(r->buf));
+  r->i = 0;
+  r->irot = 0;
+  r->ibits = r->obits = 0;
+  r->o = RAND_SECSZ;
+  r->s = 0;
+  rmd160_hmacinit(&r->k, 0, 0);
+  rand_gate(r);
+}
+
+/* --- @rand_noisesrc@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @const rand_source *s@ = pointer to source definition
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets a noise source for a randomness pool.  When the pool's
+ *             estimate of good random bits falls to zero, the @getnoise@
+ *             function is called, passing the pool handle as an argument.
+ *             It is expected to increase the number of good bits by at
+ *             least one, because it'll be called over and over again until
+ *             there are enough bits to satisfy the caller.  The @timer@
+ *             function is called frequently throughout the generator's
+ *             operation.
+ */
+
+void rand_noisesrc(rand_pool *r, const rand_source *s)
+{
+  RAND_RESOLVE(r);
+  r->s = s;
+}
+
+/* --- @rand_seed@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @unsigned bits@ = number of bits to ensure
+ *
+ * Returns:    ---
+ *
+ * Use:                Ensures that there are at least @bits@ good bits of entropy
+ *             in the pool.  It is recommended that you call this after
+ *             initializing a new pool.  Requesting @bits > RAND_IBITS@ is
+ *             doomed to failure (and is an error).
+ */
+
+void rand_seed(rand_pool *r, unsigned bits)
+{
+  RAND_RESOLVE(r);
+
+  assert(((void)"bits pointlessly large in rand_seed", bits <= RAND_IBITS));
+  assert(((void)"no noise source in rand_seed", r->s));
+
+  while (r->ibits < bits)
+    r->s->getnoise(r);
+  rand_gate(r);
+}
+
+/* --- @rand_key@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @const void *k@ = pointer to key data
+ *             @size_t sz@ = size of key data
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets the secret key for a randomness pool.  The key is used
+ *             when mixing in new random bits.
+ */
+
+void rand_key(rand_pool *r, const void *k, size_t sz)
+{
+  RAND_RESOLVE(r);
+  rmd160_hmacinit(&r->k, k, sz);
+}
+
+/* --- @rand_add@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @const void *p@ = pointer a buffer of data to add
+ *             @size_t sz@ = size of the data buffer
+ *             @unsigned goodbits@ = number of good bits estimated in buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Mixes the data in the buffer with the contents of the
+ *             pool.  The estimate of the number of good bits is added to
+ *             the pool's own count.  The mixing operation is not
+ *             cryptographically strong.  However, data in the input pool
+ *             isn't output directly, only through the one-way gating
+ *             operation, so that shouldn't matter.
+ */
+
+void rand_add(rand_pool *r, const void *p, size_t sz, unsigned goodbits)
+{
+  const octet *c = p;
+  int i, rot;
+
+#if RAND_POOLSZ != 128
+#  error Polynomial in rand_add is out of date.  Fix it.
+#endif
+
+  RAND_RESOLVE(r);
+
+  i = r->i; rot = r->irot;
+
+  while (sz) {
+    octet o = *c++;
+    r->pool[i] ^= (ROL8(o, rot) ^
+                  r->pool[(i + 1) % RAND_POOLSZ] ^
+                  r->pool[(i + 2) % RAND_POOLSZ] ^
+                  r->pool[(i + 7) % RAND_POOLSZ]);
+    rot = (rot + 5) & 7;
+    i++; if (i >= RAND_POOLSZ) i -= RAND_POOLSZ;
+    sz--;
+  }
+
+  r->i = i;
+  r->irot = rot;
+  r->ibits += goodbits;
+  if (r->ibits > RAND_IBITS)
+    r->ibits = RAND_IBITS;
+}
+
+/* --- @rand_goodbits@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Estimate of the number of good bits remaining in the pool.
+ */
+
+unsigned rand_goodbits(rand_pool *r)
+{
+  RAND_RESOLVE(r);
+  return (r->ibits + r->obits);
+}
+
+/* --- @rand_gate@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    ---
+ *
+ * Use:                Mixes up the entire state of the generator in a nonreversible
+ *             way.
+ */
+
+void rand_gate(rand_pool *r)
+{
+  octet mac[RMD160_HASHSZ];
+
+  RAND_RESOLVE(r);
+  TIMER(r);
+
+  /* --- Hash up all the data in the pool --- */
+
+  {
+    rmd160_macctx mc;
+
+    rmd160_macinit(&mc, &r->k);
+    rmd160_machash(&mc, r->pool, sizeof(r->pool));
+    rmd160_machash(&mc, r->buf, sizeof(r->buf));
+    rmd160_macdone(&mc, mac);
+    BURN(mc);
+  }
+
+  /* --- Now mangle all of the data based on the hash --- */
+
+  {
+    blowfish_cbcctx bc;
+
+    blowfish_cbcinit(&bc, mac, sizeof(mac), 0);
+    blowfish_cbcencrypt(&bc, r->pool, r->pool, sizeof(r->pool));
+    blowfish_cbcencrypt(&bc, r->buf, r->buf, sizeof(r->buf));
+    BURN(bc);
+  }
+
+  /* --- Reset the various state variables --- */
+
+  r->o = RAND_SECSZ;
+  r->obits += r->ibits;
+  if (r->obits > RAND_OBITS) {
+    r->ibits = r->obits - r->ibits;
+    r->obits = RAND_OBITS;
+  } else
+    r->ibits = 0;
+  TIMER(r);
+}
+
+/* --- @rand_stretch@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    ---
+ *
+ * Use:                Stretches the contents of the output buffer by transforming
+ *             it in a nonreversible way.  This doesn't add any entropy
+ *             worth speaking about, but it works well enough when the
+ *             caller doesn't care about that sort of thing.
+ */
+
+void rand_stretch(rand_pool *r)
+{
+  octet mac[RMD160_HASHSZ];
+
+  RAND_RESOLVE(r);
+  TIMER(r);
+
+  /* --- Hash up all the data in the buffer --- */
+
+  {
+    rmd160_macctx mc;
+
+    rmd160_macinit(&mc, &r->k);
+    rmd160_machash(&mc, r->pool, sizeof(r->pool));
+    rmd160_machash(&mc, r->buf, sizeof(r->buf));
+    rmd160_macdone(&mc, mac);
+    BURN(mc);
+  }
+
+  /* --- Now mangle the buffer based on that hash --- */
+
+  {
+    blowfish_cbcctx bc;
+
+    blowfish_cbcinit(&bc, mac, sizeof(mac), 0);
+    blowfish_cbcencrypt(&bc, r->buf, r->buf, sizeof(r->buf));
+    BURN(bc);
+  }
+
+  /* --- Reset the various state variables --- */
+
+  r->o = RAND_SECSZ;
+  TIMER(r);
+}
+
+/* --- @rand_get@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @void *p@ = pointer to output buffer
+ *             @size_t sz@ = size of output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Gets random data from the pool.  The pool's contents can't be
+ *             determined from the output of this function; nor can the
+ *             output data be determined from a knowledge of the data input
+ *             to the pool wihtout also having knowledge of the secret key.
+ *             The good bits counter is decremented, although no special
+ *             action is taken if it reaches zero.
+ */
+
+void rand_get(rand_pool *r, void *p, size_t sz)
+{
+  octet *o = p;
+
+  RAND_RESOLVE(r);
+  TIMER(r);
+
+  if (!sz)
+    return;
+  for (;;) {
+    if (r->o + sz <= RAND_BUFSZ) {
+      memcpy(o, r->buf + r->o, sz);
+      r->o += sz;
+      break;
+    } else {
+      size_t chunk = RAND_BUFSZ - r->o;
+      if (chunk) {
+       memcpy(o, r->buf + r->o, chunk);
+       sz -= chunk;
+       o += chunk;
+      }
+      rand_stretch(r);
+    }
+  }
+
+  if (r->obits > sz * 8)
+    r->obits -= sz * 8;
+  else
+    r->obits = 0;
+}
+
+/* --- @rand_getgood@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @void *p@ = pointer to output buffer
+ *             @size_t sz@ = size of output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Gets random data from the pool, ensuring that there are
+ *             enough good bits.  This interface isn't recommended: it makes
+ *             the generator slow, and doesn't provide much more security
+ *             than @rand_get@, assuming you've previously done a
+ *             @rand_seed@.
+ */
+
+void rand_getgood(rand_pool *r, void *p, size_t sz)
+{
+  octet *o = p;
+
+  RAND_RESOLVE(r);
+
+  if (!sz)
+    return;
+  if (!r->s || !r->s->getnoise) {
+    rand_get(r, p, sz);
+    return;
+  }
+  TIMER(r);
+
+  while (sz) {
+    size_t chunk = sz;
+
+    if (chunk * 8 > r->obits) {
+      if (chunk * 8 > r->ibits + r->obits)
+       do r->s->getnoise(r); while (r->ibits + r->obits < 256);
+      rand_gate(r);
+      if (chunk * 8 > r->obits)
+       chunk = r->obits / 8;
+    }
+
+    if (chunk + r->o > RAND_BUFSZ)
+      chunk = RAND_BUFSZ - r->o;
+
+    memcpy(o, r->buf + r->o, chunk);
+    r->o += chunk;
+    r->obits -= chunk * 8;
+    o += chunk;
+    sz -= chunk;
+  }
+}
+
+/*----- Generic random number generator interface -------------------------*/
+
+#define GRESOLVE(g, r) do {                                            \
+  if (r != &rand_global)                                               \
+    g = (gctx *)r;                                                     \
+  else {                                                               \
+    if (!pool)                                                         \
+      pool = (gctx *)rand_create();                                    \
+    g = pool;                                                          \
+  }                                                                    \
+} while (0)
+
+static void gdestroy(grand *r)
+{
+  gctx *g;
+  GRESOLVE(g, r);
+  if (g != pool) {
+    BURN(*g);
+    S_DESTROY(g);
+  }
+}
+
+static int gmisc(grand *r, unsigned op, ...)
+{
+  gctx *g;
+  va_list ap;
+  int rc = 0;
+  va_start(ap, op);
+
+  GRESOLVE(g, r);
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDBLOCK:
+       case GRAND_SEEDRAND:
+       case RAND_GATE:
+       case RAND_STRETCH:
+       case RAND_KEY:
+       case RAND_NOISESRC:
+       case RAND_SEED:
+       case RAND_TIMER:
+       case RAND_GOODBITS:
+       case RAND_ADD:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT: {
+      unsigned u = va_arg(ap, unsigned);
+      rand_add(&g->p, &u, sizeof(u), sizeof(u));
+    } break;
+    case GRAND_SEEDUINT32: {
+      uint32 i = va_arg(ap, uint32);
+      rand_add(&g->p, &i, sizeof(i), 4);
+    } break;
+    case GRAND_SEEDBLOCK: {
+      const void *p = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      rand_add(&g->p, p, sz, sz);
+    } break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      octet buf[16];
+      rr->ops->fill(rr, buf, sizeof(buf));
+      rand_add(&g->p, buf, sizeof(buf), 8);
+    } break;
+    case RAND_GATE:
+      rand_gate(&g->p);
+      break;
+    case RAND_STRETCH:
+      rand_stretch(&g->p);
+      break;
+    case RAND_KEY: {
+      const void *k = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      rand_key(&g->p, k, sz);
+    } break;
+    case RAND_NOISESRC:
+      rand_noisesrc(&g->p, va_arg(ap, const rand_source *));
+      break;
+    case RAND_SEED:
+      rand_seed(&g->p, va_arg(ap, unsigned));
+      break;
+    case RAND_TIMER:
+      TIMER(&g->p);
+      break;
+    case RAND_GOODBITS:
+      rc = rand_goodbits(&g->p);
+      break;
+    case RAND_ADD: {
+      const void *p = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      unsigned goodbits = va_arg(ap, unsigned);
+      rand_add(&g->p, p, sz, goodbits);
+    } break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static octet gbyte(grand *r)
+{
+  gctx *g;
+  octet o;
+  GRESOLVE(g, r);
+  rand_getgood(&g->p, &o, 1);
+  return (o);
+}
+
+static uint32 gword(grand *r)
+{
+  gctx *g;
+  octet b[4];
+  GRESOLVE(g, r);
+  rand_getgood(&g->p, &b, sizeof(b));
+  return (LOAD32(b));
+}
+
+static void gfill(grand *r, void *p, size_t sz)
+{
+  gctx *g;
+  GRESOLVE(g, r);
+  rand_get(&g->p, p, sz);
+}
+
+static const grand_ops gops = {
+  "rand",
+  GRAND_CRYPTO, 0,
+  gmisc, gdestroy,
+  gword, gbyte, gword, grand_range, gfill
+};
+
+grand rand_global = { &gops };
+
+/* --- @rand_create@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a Catacomb
+ *             entropy pool generator.
+ */
+
+grand *rand_create(void)
+{
+  gctx *g = S_CREATE(gctx);
+  g->r.ops = &gops;
+  rand_init(&g->p);
+  return (&g->r);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/rand.h b/rand/rand.h
new file mode 100644 (file)
index 0000000..a024c0f
--- /dev/null
@@ -0,0 +1,313 @@
+/* -*-c-*-
+ *
+ * Secure random number generator
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on the random number generator ------------------------------*
+ *
+ * The algorithm is one of the author's own devising.  It may therefore be
+ * worth a certain amount of skepticism.  However, I've thought about this
+ * method for over a year before actually considering it worth implementing.
+ * With a little bit of luck, it should have received some peer review by the
+ * time this code is actually properly released, and it'll be worth a bit
+ * more confidence.  My earlier generator was very similar in structure to
+ * the Linux /dev/random device.  This generator is intended to address
+ * concerns I expressed about the Linux generator in a Usenet article to
+ * sci.crypt.
+ *
+ * The generator is divided into two parts: an input pool and an output
+ * buffer.  New random data is placed into the pool in the way described
+ * below, which is shamelessly stolen from the Linux /dev/random generator.
+ * The only interaction that the pool has on the output buffer is through the
+ * keyed `gating' operation, which mixes up and redistributes all of the
+ * generator's state in an irreversible manner.  Random bytes, when
+ * requested, are extracted from the output buffer in a linear fashion.
+ *
+ * The input pool is best seen as being eight shift registers in parallel.
+ * Data is added to the pool one octet at a time.  Each bit of a new octet is
+ * added to a different shift register, by adding it (mod 2) with other bits
+ * according to the coefficients of a primitive polynomial.  Each new byte is
+ * rotated before being added into the pool, in a half-hearted attempt to
+ * protect against biases in the input data (e.g., top bits being clear on
+ * ASCII text).
+ *
+ * The gating operation takes a keyed hash of the entire generator state,
+ * uses it as the key for a symmetric cipher, and encrypts the state.  The
+ * key is then discarded.  The result is that every ouptut bit of the
+ * operation depends in a complex way on every input bit, but the operation
+ * cannot be reversed.
+ *
+ * As an added wrinkle, 160 bits of the output buffer are never actually
+ * output.  They are used in the gating operation only, as an extra item that
+ * an adversary has to guess before predicting generator output.
+ */
+
+#ifndef CATACOMB_RAND_H
+#define CATACOMB_RAND_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_RMD160_HMAC_H
+#  include "rmd160-hmac.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define RAND_POOLSZ 128                        /* Input pool size in bytes */
+#define RAND_BUFSZ 512                 /* Output buffer size in bytes */
+#define RAND_SECSZ 20                  /* Secret octets in output buffer */
+
+#define RAND_IBITS (RAND_POOLSZ * 8)
+#define RAND_OBITS (RAND_BUFSZ * 8)
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- A random number generator pool --- */
+
+typedef struct rand_pool {
+  octet pool[RAND_POOLSZ];             /* Actual contents of the pool */
+  unsigned i;                          /* Current index into pool */
+  unsigned irot;                       /* Current rotation applied */
+  unsigned ibits;                      /* Number of good bits in pool */
+  octet buf[RAND_BUFSZ];               /* Random octet output buffer */
+  unsigned o;                          /* Current index into buffer */
+  unsigned obits;                      /* Number of good bits in buffer */
+  rmd160_mackey k;                     /* Secret key for this pool */
+  const struct rand_source *s;         /* System-specific noise source */
+} rand_pool;
+
+#define RAND_GLOBAL ((rand_pool *)0)   /* The global randomness pool */
+
+/* --- A noise source --- */
+
+typedef struct rand_source {
+  void (*getnoise)(rand_pool */*r*/);  /* Acquire more noise */
+  int (*timer)(rand_pool */*r*/);      /* Get noise from current time */
+} rand_source;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rand_init@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a randomness pool.  The pool doesn't start out
+ *             very random: that's your job to sort out.
+ */
+
+extern void rand_init(rand_pool */*r*/);
+
+/* --- @rand_noisesrc@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @const rand_source *s@ = pointer to source definition
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets a noise source for a randomness pool.  When the pool's
+ *             estimate of good random bits falls to zero, the @getnoise@
+ *             function is called, passing the pool handle as an argument.
+ *             It is expected to increase the number of good bits by at
+ *             least one, because it'll be called over and over again until
+ *             there are enough bits to satisfy the caller.  The @timer@
+ *             function is called frequently throughout the generator's
+ *             operation.
+ */
+
+extern void rand_noisesrc(rand_pool */*r*/, const rand_source */*s*/);
+
+/* --- @rand_seed@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @unsigned bits@ = number of bits to ensure
+ *
+ * Returns:    ---
+ *
+ * Use:                Ensures that there are at least @bits@ good bits of entropy
+ *             in the pool.  It is recommended that you call this after
+ *             initializing a new pool.  Requesting @bits > RAND_IBITS@ is
+ *             doomed to failure (and is an error).
+ */
+
+extern void rand_seed(rand_pool */*r*/, unsigned /*bits*/);
+
+/* --- @rand_key@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @const void *k@ = pointer to key data
+ *             @size_t sz@ = size of key data
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets the secret key for a randomness pool.  The key is used
+ *             when mixing in new random bits.
+ */
+
+extern void rand_key(rand_pool */*r*/, const void */*k*/, size_t /*sz*/);
+
+/* --- @rand_add@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @const void *p@ = pointer a buffer of data to add
+ *             @size_t sz@ = size of the data buffer
+ *             @unsigned goodbits@ = number of good bits estimated in buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Mixes the data in the buffer with the contents of the
+ *             pool.  The estimate of the number of good bits is added to
+ *             the pool's own count.  The mixing operation is not
+ *             cryptographically strong.  However, data in the input pool
+ *             isn't output directly, only through the one-way gating
+ *             operation, so that shouldn't matter.
+ */
+
+extern void rand_add(rand_pool */*r*/,
+                    const void */*p*/, size_t /*sz*/,
+                    unsigned /*goodbits*/);
+
+/* --- @rand_goodbits@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    Estimate of the number of good bits remaining in the pool.
+ */
+
+extern unsigned rand_goodbits(rand_pool */*r*/);
+
+/* --- @rand_gate@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    ---
+ *
+ * Use:                Mixes up the entire state of the generator in a nonreversible
+ *             way.
+ */
+
+extern void rand_gate(rand_pool */*r*/);
+
+/* --- @rand_stretch@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *
+ * Returns:    ---
+ *
+ * Use:                Stretches the contents of the output buffer by transforming
+ *             it in a nonreversible way.  This doesn't add any entropy
+ *             worth speaking about, but it works well enough when the
+ *             caller doesn't care about that sort of thing.
+ */
+
+extern void rand_stretch(rand_pool */*r*/);
+
+/* --- @rand_get@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @void *p@ = pointer to output buffer
+ *             @size_t sz@ = size of output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Gets random data from the pool.  The pool's contents can't be
+ *             determined from the output of this function; nor can the
+ *             output data be determined from a knowledge of the data input
+ *             to the pool without also having knowledge of the secret key.
+ *             The good bits counter is decremented, although no special
+ *             action is taken if it reaches zero.
+ */
+
+extern void rand_get(rand_pool */*r*/, void */*p*/, size_t /*sz*/);
+
+/* --- @rand_getgood@ --- *
+ *
+ * Arguments:  @rand_pool *r@ = pointer to a randomness pool
+ *             @void *p@ = pointer to output buffer
+ *             @size_t sz@ = size of output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Gets random data from the pool.  The pool's contents can't be
+ *             determined from the output of this function; nor can the
+ *             output data be determined from a knowledge of the data input
+ *             to the pool wihtout also having knowledge of the secret key.
+ *             If a noise source is attached to the pool in question, it is
+ *             called to replenish the supply of good bits in the pool;
+ *             otherwise this call is equivalent to @rand_get@.
+ */
+
+extern void rand_getgood(rand_pool */*r*/, void */*p*/, size_t /*sz*/);
+
+/*----- Generic random number generator interface -------------------------*/
+
+/* --- Miscellaneous operations --- */
+
+enum {
+  RAND_GATE = GRAND_SPECIFIC('R'),     /* No args */
+  RAND_STRETCH,                                /* No args */
+  RAND_KEY,                            /* @const void *k, size_t sz@ */
+  RAND_NOISESRC,                       /* @const rand_source *s@ */
+  RAND_SEED,                           /* @unsigned bits@ */
+  RAND_TIMER,                          /* No args */
+  RAND_GOODBITS,                       /* No args */
+  RAND_ADD                             /* @const void *p, size_t sz,@
+                                        * @unsigned goodbits */
+};
+
+/* --- Default random number generator --- */
+
+extern grand rand_global;
+
+/* --- @rand_create@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    Pointer to a generic generator.
+ *
+ * Use:                Constructs a generic generator interface over a Catacomb
+ *             entropy pool generator.
+ */
+
+extern grand *rand_create(void);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/sslprf.c b/rand/sslprf.c
new file mode 100644 (file)
index 0000000..83a4c84
--- /dev/null
@@ -0,0 +1,356 @@
+/* -*-c-*-
+ *
+ * The SSL pseudo-random function
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/sub.h>
+
+#include "arena.h"
+#include "ghash.h"
+#include "grand.h"
+#include "paranoia.h"
+#include "sslprf.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @step@ --- *
+ *
+ * Arguments:  @sslprf_ctx *c@ = pointer to context structure
+ *
+ * Returns:    ---
+ *
+ * Use:                Steps the generator.
+ */
+
+static void step(sslprf_ctx *c)
+{
+  octet buf[64];
+  size_t n, sz;
+  octet x;
+  ghash *h, *hh;
+  octet *p;
+
+  h = GH_INIT(c->ci);
+  x = 'A' + c->i - 1;
+  for (sz = c->i++; sz > 0; sz -= n) {
+    n = sz;
+    if (n > sizeof(buf))
+      n = sizeof(buf);
+    memset(buf, x, n);
+    GH_HASH(h, buf, n);
+  }
+  GH_HASH(h, c->k, c->ksz);
+  GH_HASH(h, c->sd, c->sdsz);
+  p = GH_DONE(h, 0);
+
+  hh = GH_INIT(c->co);
+  GH_HASH(hh, c->k, c->ksz);
+  GH_HASH(hh, p, c->ihashsz);
+  c->p = GH_DONE(hh, 0);
+  GH_DESTROY(h);
+
+  c->h = hh;
+  c->sz = c->ohashsz;
+}
+
+/* --- @sslprf_init@ --- *
+ *
+ * Arguments:  @sslprf_ctx *c@ = pointer to a context structure
+ *             @const gchash *hco, *hci@ = outer and inner hash functions
+ *             @const void *k@ = pointer to secret buffer
+ *             @size_t ksz@ = size of the secret
+ *             @const void *sd@ = pointer to seed buffer
+ *             @size_t sdsz@ = size of the seed
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an SSL generator context.
+ */
+
+void sslprf_init(sslprf_ctx *c, const gchash *hco, const gchash *hci,
+                const void *k, size_t ksz,
+                const void *sd, size_t sdsz)
+{
+  c->co = hco; c->ci = hci;
+  c->ohashsz = hco->hashsz; c->ihashsz = hci->hashsz;
+  c->k = k; c->ksz = ksz; c->sd = sd; c->sdsz = sdsz;
+  c->i = 1;
+  step(c);
+}
+
+/* --- @sslprf_encrypt@ --- *
+ *
+ * Arguments:  @sslprf_ctx *c@ = pointer to a context structure
+ *             @const void *src@ = pointer to source buffer
+ *             @void *dest@ = pointer to destination buffer
+ *             @size_t sz@ = size of the buffers
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts data using the SSL pseudo-random function.  If the
+ *             destination pointer is null, the generator is spun and no
+ *             output is produced; if the source pointer is null, raw output
+ *             from the generator is written; otherwise, the source data is
+ *             XORed with the generator output.
+ */
+
+void sslprf_encrypt(sslprf_ctx *c, const void *src, void *dest, size_t sz)
+{
+  const octet *s = src;
+  octet *d = dest;
+  size_t i, n;
+
+  while (sz) {
+    if (!c->sz) {
+      GH_DESTROY(c->h);
+      step(c);
+    }
+    n = c->sz;
+    if (n > sz)
+      n = sz;
+    if (d) {
+      if (!s)
+       memcpy(d, c->p, n);
+      else {
+       for (i = 0; i < n; i++) d[i] = s[i] ^ c->p[i];
+       s += n;
+      }
+      d += n;
+    }
+    c->p += n;
+    c->sz -= n;
+    sz -= n;
+  }
+}
+
+/* --- @sslprf_free@ --- *
+ *
+ * Arguments:  @sslprf_ctx@ = pointer to a context
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees resources held in an SSL generator context.
+ */
+
+void sslprf_free(sslprf_ctx *c)
+{
+  GH_DESTROY(c->h);
+}
+
+/* --- Generic random number generator --- */
+
+typedef struct grctx {
+  grand r;
+  grand_ops ops;
+  sslprf_ctx prf;
+} grctx;
+
+static void grdestroy(grand *r)
+{
+  grctx *g = (grctx *)r;
+  xfree((char *)g->ops.name);
+  xfree((octet *)g->prf.sd);
+  sslprf_free(&g->prf);
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static void seed(grctx *g, const void *p, size_t sz)
+{
+  octet *q;
+  xfree((octet *)g->prf.sd);
+  g->prf.sd = q = xmalloc(sz);
+  memcpy(q, p, sz);
+  g->prf.sdsz = sz;
+}
+
+static int grmisc(grand *r, unsigned op, ...)
+{
+  grctx *g = (grctx *)r;
+  va_list ap;
+  int rc = 0;
+  uint32 i;
+  octet buf[4];
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDBLOCK:
+       case GRAND_SEEDRAND:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT:
+      i = va_arg(ap, unsigned);
+      STORE32(buf, i);
+      seed(g, buf, sizeof(buf));
+      break;
+    case GRAND_SEEDUINT32:
+      i = va_arg(ap, uint32);
+      STORE32(buf, i);
+      seed(g, buf, sizeof(buf));
+      break;
+    case GRAND_SEEDBLOCK: {
+      const void *p = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      seed(g, p, sz);
+    } break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      octet buf[16];
+      rr->ops->fill(rr, buf, sizeof(buf));
+      seed(g, buf, sizeof(buf));
+    } break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static octet grbyte(grand *r)
+{
+  grctx *g = (grctx *)r;
+  octet o;
+  sslprf_encrypt(&g->prf, 0, &o, 1);
+  return (o);
+}
+
+static uint32 grword(grand *r)
+{
+  grctx *g = (grctx *)r;
+  octet b[4];
+  sslprf_encrypt(&g->prf, 0, &b, sizeof(b));
+  return (LOAD32(b));
+}
+
+static void grfill(grand *r, void *p, size_t sz)
+{
+  grctx *g = (grctx *)r;
+  sslprf_encrypt(&g->prf, 0, p, sz);
+}
+
+static const grand_ops grops = {
+  "<sslprf-dummy>",
+  GRAND_CRYPTO, 0,
+  grmisc, grdestroy,
+  grword, grbyte, grword, grand_range, grfill
+};
+
+/* ---@sslprf_rand@ --- *
+ *
+ * Arguments:  @const gchash *hco, const gchash *hci@ = hash functions
+ *             @const void *k@ = pointer to the key material
+ *             @size_t ksz@ = size of the key material
+ *             @const void *sd@ = pointer to the seed material
+ *             @size_t sdsz@ = size of the seed material
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a generic generator which does TLS data expansion.
+ */
+
+grand *sslprf_rand(const gchash *hco, const gchash *hci,
+                  const void *k, size_t ksz,
+                  const void *sd, size_t sdsz)
+{
+  grctx *g = S_CREATE(grctx);
+  dstr d = DSTR_INIT;
+  octet *q = xmalloc(sdsz);
+  memcpy(q, sd, sdsz);
+  dstr_putf(&d, "sslprf(%s,%s)", hco->name, hci->name);
+  g->ops = grops;
+  g->ops.name = xstrdup(d.buf);
+  g->r.ops = &g->ops;
+  dstr_destroy(&d);
+  sslprf_init(&g->prf, hco, hci, k, ksz, q, sdsz);
+  return (&g->r);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+#include <string.h>
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#include "sha.h"
+#include "md5.h"
+
+static int v_generate(dstr *v)
+{
+  grand *g;
+  dstr d = DSTR_INIT;
+  int ok = 1;
+
+  g = sslprf_rand(&md5, &sha, v[0].buf, v[0].len, v[1].buf, v[1].len);
+  dstr_ensure(&d, v[2].len);
+  d.len = v[2].len;
+  g->ops->fill(g, d.buf, d.len);
+  g->ops->destroy(g);
+  if (memcmp(v[2].buf, d.buf, d.len) != 0) {
+    ok = 0;
+    printf("\nfail sslprf:"
+          "\n\tkey        = ");
+    type_hex.dump(&v[0], stdout);
+    printf("\n\tseed      = "); type_hex.dump(&v[1], stdout);
+    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
+    printf("\n\tcalculated = "); type_hex.dump(&d, stdout);
+    putchar('\n');
+  }
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "sslprf", v_generate, { &type_hex, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/sslprf");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/sslprf.h b/rand/sslprf.h
new file mode 100644 (file)
index 0000000..5f5467b
--- /dev/null
@@ -0,0 +1,135 @@
+/* -*-c-*-
+ *
+ * The SSL pseudo-random function
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_SSLPRF_H
+#define CATACOMB_SSLPRF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GMAC_H
+#  include "gmac.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct sslprf_ctx {
+  const gchash *co, *ci;               /* Outer and inner hash functions */
+  size_t ohashsz, ihashsz;             /* Size of the hash outputs */
+  ghash *h;                            /* Hash context from last time */
+  const octet *k;                      /* Pointer to the secret */
+  size_t ksz;                          /* Size of the secret buffer */
+  const octet *sd;                     /* Pointer to the seed */
+  size_t sdsz;                         /* Size of the seed buffer */
+  unsigned i;                          /* Which iteration this is */
+  octet *p;                            /* Pointer to output buffer */
+  size_t sz;                           /* How many bytes are left */
+} sslprf_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @sslprf_init@ --- *
+ *
+ * Arguments:  @sslprf_ctx *c@ = pointer to a context structure
+ *             @const gchash *hco, *hci@ = outer and inner hash functions
+ *             @const void *k@ = pointer to secret buffer
+ *             @size_t ksz@ = size of the secret
+ *             @const void *sd@ = pointer to seed buffer
+ *             @size_t sdsz@ = size of the seed
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an SSL generator context.
+ */
+
+extern void sslprf_init(sslprf_ctx */*c*/,
+                       const gchash */*hco*/, const gchash */*hci*/,
+                       const void */*k*/, size_t /*ksz*/,
+                       const void */*sd*/, size_t /*sdsz*/);
+
+/* --- @sslprf_encrypt@ --- *
+ *
+ * Arguments:  @sslprf_ctx *c@ = pointer to a context structure
+ *             @const void *src@ = pointer to source buffer
+ *             @void *dest@ = pointer to destination buffer
+ *             @size_t sz@ = size of the buffers
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts data using the SSL pseudo-random function.  If the
+ *             destination pointer is null, the generator is spun and no
+ *             output is produced; if the source pointer is null, raw output
+ *             from the generator is written; otherwise, the source data is
+ *             XORed with the generator output.
+ */
+
+extern void sslprf_encrypt(sslprf_ctx */*c*/,
+                          const void */*src*/, void */*dest*/,
+                          size_t /*sz*/);
+
+/* --- @sslprf_free@ --- *
+ *
+ * Arguments:  @sslprf_ctx@ = pointer to a context
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees resources held in an SSL generator context.
+ */
+
+extern void sslprf_free(sslprf_ctx */*c*/);
+
+/* ---@sslprf_rand@ --- *
+ *
+ * Arguments:  @const gchash *hco, const gchash *hci@ = hash functions
+ *             @const void *k@ = pointer to the key material
+ *             @size_t ksz@ = size of the key material
+ *             @const void *sd@ = pointer to the seed material
+ *             @size_t sdsz@ = size of the seed material
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a generic generator which does TLS data expansion.
+ */
+
+extern grand *sslprf_rand(const gchash */*hco*/, const gchash */*hci*/,
+                         const void */*k*/, size_t /*ksz*/,
+                         const void */*sd*/, size_t /*sdsz*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rand/t/lcrand b/rand/t/lcrand
new file mode 100644 (file)
index 0000000..6cc9dce
--- /dev/null
@@ -0,0 +1,32 @@
+# Test vectors for linear congruential generator
+
+lcrand {
+  # --- Standard stuff ---
+
+  0            271828183;
+  271828183    996300340;
+  996300340    228306184;
+  228306184    1171467301;
+  1171467301   3265426054;
+  3265426054   2636049353;
+  2636049353   3799512036;
+  3799512036   2414373801;
+  2414373801   1059474234;
+  1059474234   2734911993;
+  2734911993   239668818;
+  239668818    1752802481;
+  1752802481   34386946;
+  34386946     1344553049;
+  1344553049   1121833700;
+  1121833700   636134543;
+
+  # --- Particular outputs ---
+
+  2282233179   4294967290;
+  2624567577   0;
+  2966901975   1;
+
+  # --- Fixed point ---
+
+  3223959250   3223959250;
+}
diff --git a/rand/t/sslprf b/rand/t/sslprf
new file mode 100644 (file)
index 0000000..1538684
--- /dev/null
@@ -0,0 +1,9 @@
+# SSL pseudo-random function
+
+sslprf {
+  # --- Generated using SSLeay ---
+
+  4837879a5040b1499a9cae62747e4857b090a0334683d8492d1d87933b58fa07523d4b8d0df762b62caddf7ac1304cd9 3ace3cb1ee080975da0dc748207c2bc0eb995746d0b37ab4789932a32ec5347b3ace3cb100000000b28539b8285cbc37622b65d8efcba4ad13eb42712c47d6f5 c15e3166e8a743e6b5da7d9cbcc08c2e4107887a70f2a4e16b54243276c48894569f2916c6cb610bb84b766b7283dca0a346fcce41683ec01f06c17e91758d5d31fbd1ca0a7d75b909035f04786f41efde988d20f5d1fecad337a3a23a16fde1beae5400bc3f357c;
+
+  53a82e555607a83890bfc633ff7f1d9ecc7d225f450dff3a8d46dd370033968fc456ae8b6fe3639c71fa2ba9d0f798aa 3ace3ca4ac5e36c228a5ce350f22261eadacdc48873b317843061aa679ed15e63ace3ca4000000009ba10a4a1837535a372de6784f037f6cc36c3113cdcc1465 798b2f8eee4cd6b35a220f8d446672762e8dd53bae7bd773877a1dfe0aa446b4274bafd546e94b1bbe4c2d56a6e60d06871b117a7d562859f36ce2082def1c134b1c117022fe449b2da85e6d2c8e763bec6e35889a315d8686e391c277377beb037dd91accddacd1;
+}
diff --git a/rand/t/tlsprf b/rand/t/tlsprf
new file mode 100644 (file)
index 0000000..ace9066
--- /dev/null
@@ -0,0 +1,9 @@
+# TLS pseudo-random function
+
+tlsprf {
+  # --- Generated using SSLeay ---
+
+  3bfcccfb9e0bf44585b7a5ffcc7ff3b27be9462d5190664b96613a089f21c06e6f4788e3a963683d5cddea86982682dc 7365727665722066696e697368656416da63a061e9dee1884336c7345060d39d8d5fb7cd42a6b15bdd4eda44890edc41137ffe 4975842aca48f758ede77403;
+
+  3bfcccfb9e0bf44585b7a5ffcc7ff3b27be9462d5190664b96613a089f21c06e6f4788e3a963683d5cddea86982682dc 6b657920657870616e73696f6e3acb7aca624a68136e34e262b3e813ea234662db262a2c5791986fbe101707f7201dca6e8c753a5f2d8be10a69e08577ff9d6ec92d8c3ed17be5ef40f029ad11 be41fda006e5fc3423589714c374f7de3a8bc1315610a419acdf62aee16462dcec00aa5ca4e1d615a3d0b87a4cf10bc9cfc3509f2a9a879708092ce0bd54cc12b3fa2238569a8327cbd314f779f653783f5119a81986e49750b4e300e6cbbebcc782a65cc72f302c;
+}
diff --git a/rand/tlsprf.c b/rand/tlsprf.c
new file mode 100644 (file)
index 0000000..3f055b0
--- /dev/null
@@ -0,0 +1,540 @@
+/* -*-c-*-
+ *
+ * The TLS pseudo-random function
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/alloc.h>
+#include <mLib/dstr.h>
+#include <mLib/sub.h>
+
+#include "arena.h"
+#include "gmac.h"
+#include "grand.h"
+#include "paranoia.h"
+#include "tlsprf.h"
+
+/*----- The data expansion function ---------------------------------------*/
+
+/* --- @tlsdx_init@ --- *
+ *
+ * Arguments:  @tlsdx_ctx *c@ = pointer to a context
+ *             @gmac *m@ = pointer to a generic MAC instance
+ *             @const void *sd@ = pointer to the seed block
+ *             @size_t sdsz@ = size of the seed block
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context for the TLS data expansion function.
+ *             This doesn't take ownership of the MAC instance or the seed
+ *             memory, nor does it allocate copies.
+ */
+
+void tlsdx_init(tlsdx_ctx *c, gmac *m, const void *sd, size_t sdsz)
+{
+  c->k = m;
+  c->hashsz = GM_CLASS(c->k)->hashsz;
+  c->sd = sd; c->sdsz = sdsz;
+
+  c->i = GM_INIT(c->k);
+  GH_HASH(c->i, sd, sdsz);
+  c->ai = GH_DONE(c->i, 0);
+  c->o = GM_INIT(c->k);
+  GH_HASH(c->o, c->ai, c->hashsz);
+  GH_HASH(c->o, sd, sdsz);
+  c->p = GH_DONE(c->o, 0);
+  c->sz = c->hashsz;
+}
+
+/* --- @tlsdx_encrypt@ --- *
+ *
+ * Arguments:  @tlsdx_ctx *c@ = pointer to a context
+ *             @const void *src@ = pointer to source data
+ *             @void *dest@ = pointer to destination buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts data using the TLS data expansion function.  If the
+ *             destination pointer is null, the generator is spun and no
+ *             output is produced; if the source pointer is null, raw output
+ *             from the generator is written; otherwise, the source data is
+ *             XORed with the generator output.
+ */
+
+void tlsdx_encrypt(tlsdx_ctx *c, const void *src, void *dest, size_t sz)
+{
+  const octet *s = src;
+  octet *d = dest;
+  ghash *h;
+  size_t i;
+  size_t n;
+
+  while (sz) {
+    if (c->sz)
+      n = c->sz;
+    else {
+      h = GM_INIT(c->k);
+      GH_HASH(h, c->ai, c->hashsz);
+      c->ai = GH_DONE(h, 0);
+      GH_DESTROY(c->i);
+      c->i = h;
+      GH_DESTROY(c->o);
+      h = c->o = GM_INIT(c->k);
+      GH_HASH(h, c->ai, c->hashsz);
+      GH_HASH(h, c->sd, c->sdsz);
+      c->p = GH_DONE(h, 0);
+      c->sz = n = c->hashsz;
+    }
+    if (n > sz)
+      n = sz;
+    if (d) {
+      if (!s)
+       memcpy(d, c->p, n);
+      else {
+       for (i = 0; i < n; i++) d[i] = s[i] ^ c->p[i];
+       s += n;
+      }
+      d += n;
+    }
+    c->p += n;
+    c->sz -= n;
+    sz -= n;
+  }
+}
+
+/* --- @tlsdx_free@ --- *
+ *
+ * Arguments:  @tlsdx_ctx *c@ = pointer to the context block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a context for the TLS data expansion function
+ */
+
+void tlsdx_free(tlsdx_ctx *c)
+{
+  GH_DESTROY(c->i);
+  GH_DESTROY(c->o);
+}
+
+/* --- Generic random number generator --- */
+
+typedef struct dx_grctx {
+  grand r;
+  grand_ops ops;
+  tlsdx_ctx dx;
+} dx_grctx;
+
+static void dx_grdestroy(grand *r)
+{
+  dx_grctx *g = (dx_grctx *)r;
+  xfree((char *)g->ops.name);
+  xfree((octet *)g->dx.sd);
+  g->dx.k->ops->destroy(g->dx.k);
+  tlsdx_free(&g->dx);
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static void dx_seed(dx_grctx *g, const void *p, size_t sz)
+{
+  octet *q;
+  xfree((octet *)g->dx.sd);
+  g->dx.sd = q = xmalloc(sz);
+  memcpy(q, p, sz);
+  g->dx.sdsz = sz;
+}
+
+static int dx_grmisc(grand *r, unsigned op, ...)
+{
+  dx_grctx *g = (dx_grctx *)r;
+  va_list ap;
+  int rc = 0;
+  uint32 i;
+  octet buf[4];
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDBLOCK:
+       case GRAND_SEEDRAND:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT:
+      i = va_arg(ap, unsigned);
+      STORE32(buf, i);
+      dx_seed(g, buf, sizeof(buf));
+      break;
+    case GRAND_SEEDUINT32:
+      i = va_arg(ap, uint32);
+      STORE32(buf, i);
+      dx_seed(g, buf, sizeof(buf));
+      break;
+    case GRAND_SEEDBLOCK: {
+      const void *p = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      dx_seed(g, p, sz);
+    } break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      octet buf[16];
+      rr->ops->fill(rr, buf, sizeof(buf));
+      dx_seed(g, buf, sizeof(buf));
+    } break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static octet dx_grbyte(grand *r)
+{
+  dx_grctx *g = (dx_grctx *)r;
+  octet o;
+  tlsdx_encrypt(&g->dx, 0, &o, 1);
+  return (o);
+}
+
+static uint32 dx_grword(grand *r)
+{
+  dx_grctx *g = (dx_grctx *)r;
+  octet b[4];
+  tlsdx_encrypt(&g->dx, 0, &b, sizeof(b));
+  return (LOAD32(b));
+}
+
+static void dx_grfill(grand *r, void *p, size_t sz)
+{
+  dx_grctx *g = (dx_grctx *)r;
+  tlsdx_encrypt(&g->dx, 0, p, sz);
+}
+
+static const grand_ops dx_grops = {
+  "<tlsdx-dummy>",
+  GRAND_CRYPTO, 0,
+  dx_grmisc, dx_grdestroy,
+  dx_grword, dx_grbyte, dx_grword, grand_range, dx_grfill
+};
+
+/* ---@tlsdx_rand@ --- *
+ *
+ * Arguments:  @const gcmac *mc@ = MAC function to use
+ *             @const void *k@ = pointer to the key material
+ *             @size_t ksz@ = size of the key material
+ *             @const void *sd@ = pointer to the seed material
+ *             @size_t sdsz@ = size of the seed material
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a generic generator which does TLS data expansion.
+ */
+
+grand *tlsdx_rand(const gcmac *mc, const void *k, size_t ksz,
+                 const void *sd, size_t sdsz)
+{
+  dx_grctx *g = S_CREATE(dx_grctx);
+  dstr d = DSTR_INIT;
+  gmac *m = GM_KEY(mc, k, ksz);
+  octet *q = xmalloc(sdsz);
+  memcpy(q, sd, sdsz);
+  dstr_putf(&d, "tlsdx(%s)", mc->name);
+  g->ops = dx_grops;
+  g->ops.name = xstrdup(d.buf);
+  g->r.ops = &g->ops;
+  dstr_destroy(&d);
+  tlsdx_init(&g->dx, m, q, sdsz);
+  return (&g->r);
+}
+
+/* --- The actual very paranoid PRF ---------------------------------------*/
+
+/* --- @tlsprf_init@ --- *
+ *
+ * Arguments:  @tlsprf_ctx *c@ = pointer to context block
+ *             @const gcmac *mcx, *mcy@ = left and right MAC functions
+ *             @const void *k@ = pointer to the key material
+ *             @size_t ksz@ = size of the key material
+ *             @const void *sd@ = pointer to the seed material
+ *             @size_t sdsz@ = size of the seed material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a TLS PRF context.
+ */
+
+void tlsprf_init(tlsprf_ctx *c, const gcmac *mcx, const gcmac *mcy,
+                const void *k, size_t ksz, const void *sd, size_t sdsz)
+{
+  size_t n = (ksz + 1)/2;
+  const octet *kk = k;
+  tlsdx_init(&c->px, mcx->key(kk, n), sd, sdsz);
+  tlsdx_init(&c->py, mcy->key(kk + ksz - n, n), sd, sdsz);
+}
+
+/* --- @tlsprf_encrypt@ --- *
+ *
+ * Arguments:  @tlsprf_ctx *c@ = pointer to a context
+ *             @const void *src@ = pointer to source data
+ *             @void *dest@ = pointer to destination buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts data using the TLS pseudo-random function.  If the
+ *             destination pointer is null, the generator is spun and no
+ *             output is produced; if the source pointer is null, raw output
+ *             from the generator is written; otherwise, the source data is
+ *             XORed with the generator output.
+ */
+
+void tlsprf_encrypt(tlsprf_ctx *c, const void *src, void *dest, size_t sz)
+{
+  tlsdx_encrypt(&c->px, src, dest, sz);
+  tlsdx_encrypt(&c->py, dest, dest, sz);
+}
+
+/* --- @tlsprf_free@ --- *
+ *
+ * Arguments:  @tlsprf_ctx *c@ = pointer to a context
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a TLS PRF context.
+ */
+
+void tlsprf_free(tlsprf_ctx *c)
+{
+  c->px.k->ops->destroy(c->px.k);
+  c->py.k->ops->destroy(c->py.k);
+  tlsdx_free(&c->px);
+  tlsdx_free(&c->py);
+}
+
+/* --- Generic random number generator --- */
+
+typedef struct prf_grctx {
+  grand r;
+  grand_ops ops;
+  tlsprf_ctx prf;
+} prf_grctx;
+
+static void prf_grdestroy(grand *r)
+{
+  prf_grctx *g = (prf_grctx *)r;
+  xfree((char *)g->ops.name);
+  xfree((octet *)g->prf.px.sd);
+  tlsprf_free(&g->prf);
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static void prf_seed(prf_grctx *g, const void *p, size_t sz)
+{
+  octet *q;
+
+  xfree((octet *)g->prf.px.sz);
+  g->prf.px.sd = g->prf.py.sd = q = xmalloc(sz);
+  memcpy(q, p, sz);
+  g->prf.px.sdsz = g->prf.py.sdsz = sz;
+}
+
+static int prf_grmisc(grand *r, unsigned op, ...)
+{
+  prf_grctx *g = (prf_grctx *)r;
+  va_list ap;
+  int rc = 0;
+  uint32 i;
+  octet buf[4];
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDBLOCK:
+       case GRAND_SEEDRAND:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT:
+      i = va_arg(ap, unsigned);
+      STORE32(buf, i);
+      prf_seed(g, buf, sizeof(buf));
+      break;
+    case GRAND_SEEDUINT32:
+      i = va_arg(ap, uint32);
+      STORE32(buf, i);
+      prf_seed(g, buf, sizeof(buf));
+      break;
+    case GRAND_SEEDBLOCK: {
+      const void *p = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      prf_seed(g, p, sz);
+    } break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      octet buf[16];
+      rr->ops->fill(rr, buf, sizeof(buf));
+      prf_seed(g, buf, sizeof(buf));
+    } break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static octet prf_grbyte(grand *r)
+{
+  prf_grctx *g = (prf_grctx *)r;
+  octet o;
+  tlsprf_encrypt(&g->prf, 0, &o, 1);
+  return (o);
+}
+
+static uint32 prf_grword(grand *r)
+{
+  prf_grctx *g = (prf_grctx *)r;
+  octet b[4];
+  tlsprf_encrypt(&g->prf, 0, &b, sizeof(b));
+  return (LOAD32(b));
+}
+
+static void prf_grfill(grand *r, void *p, size_t sz)
+{
+  prf_grctx *g = (prf_grctx *)r;
+  tlsprf_encrypt(&g->prf, 0, p, sz);
+}
+
+static const grand_ops prf_grops = {
+  "<tlsprf-dummy>",
+  GRAND_CRYPTO, 0,
+  prf_grmisc, prf_grdestroy,
+  prf_grword, prf_grbyte, prf_grword, grand_range, prf_grfill
+};
+
+/* ---@tlsprf_rand@ --- *
+ *
+ * Arguments:  @const gcmac *mcx, *mcy@ = MAC function to use
+ *             @const void *k@ = pointer to the key material
+ *             @size_t ksz@ = size of the key material
+ *             @const void *sd@ = pointer to the seed material
+ *             @size_t sdsz@ = size of the seed material
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a generic generator which does TLS data expansion.
+ */
+
+grand *tlsprf_rand(const gcmac *mcx, const gcmac *mcy,
+                  const void *k, size_t ksz, const void *sd, size_t sdsz)
+{
+  prf_grctx *g = S_CREATE(prf_grctx);
+  dstr d = DSTR_INIT;
+  octet *q = xmalloc(sdsz);
+  memcpy(q, sd, sdsz);
+  dstr_putf(&d, "tlsprf(%s,%s)", mcx->name, mcy->name);
+  g->ops = prf_grops;
+  g->ops.name = xstrdup(d.buf);
+  g->r.ops = &g->ops;
+  dstr_destroy(&d);
+  tlsprf_init(&g->prf, mcx, mcy, k, ksz, q, sdsz);
+  return (&g->r);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+#include <string.h>
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#include "sha-hmac.h"
+#include "md5-hmac.h"
+
+static int v_generate(dstr *v)
+{
+  grand *g;
+  dstr d = DSTR_INIT;
+  int ok = 1;
+
+  g = tlsprf_rand(&md5_hmac, &sha_hmac,
+                 v[0].buf, v[0].len, v[1].buf, v[1].len);
+  dstr_ensure(&d, v[2].len);
+  d.len = v[2].len;
+  g->ops->fill(g, d.buf, d.len);
+  g->ops->destroy(g);
+  if (memcmp(v[2].buf, d.buf, d.len) != 0) {
+    ok = 0;
+    printf("\nfail tlsprf:"
+          "\n\tkey        = ");
+    type_hex.dump(&v[0], stdout);
+    printf("\n\tseed      = "); type_hex.dump(&v[1], stdout);
+    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
+    printf("\n\tcalculated = "); type_hex.dump(&d, stdout);
+    putchar('\n');
+  }
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "tlsprf", v_generate, { &type_hex, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/tlsprf");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/rand/tlsprf.h b/rand/tlsprf.h
new file mode 100644 (file)
index 0000000..f655e71
--- /dev/null
@@ -0,0 +1,203 @@
+/* -*-c-*-
+ *
+ * The TLS pseudo-random function
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_TLSPRF_H
+#define CATACOMB_TLSPRF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GMAC_H
+#  include "gmac.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct tlsdx_ctx {
+  gmac *k;                             /* The MAC key to use */
+  size_t hashsz;                       /* Size of hash outputs */
+  ghash *i, *o;                                /* Inner and outer hash contexts */
+  const octet *sd;                     /* Pointer to seed buffer */
+  size_t sdsz;                         /* Size of the seed buffer */
+  octet *p;                            /* Pointer to buffered output */
+  size_t sz;                           /* Bytes remaining in buffer */
+  octet *ai;                           /* Pointer to inner result */
+} tlsdx_ctx;
+
+typedef struct tlsprf_ctx {
+  tlsdx_ctx px, py;
+} tlsprf_ctx;
+
+/*----- The data expansion function ---------------------------------------*/
+
+/* --- @tlsdx_init@ --- *
+ *
+ * Arguments:  @tlsdx_ctx *c@ = pointer to a context
+ *             @gmac *m@ = pointer to a generic MAC instance
+ *             @const void *sd@ = pointer to the seed block
+ *             @size_t sdsz@ = size of the seed block
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context for the TLS data expansion function.
+ *             This doesn't take ownership of the MAC instance or the seed
+ *             memory, nor does it allocate copies.
+ */
+
+extern void tlsdx_init(tlsdx_ctx */*c*/, gmac */*m*/,
+                      const void */*sd*/, size_t /*sdsz*/);
+
+/* --- @tlsdx_encrypt@ --- *
+ *
+ * Arguments:  @tlsdx_ctx *c@ = pointer to a context
+ *             @const void *src@ = pointer to source data
+ *             @void *dest@ = pointer to destination buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts data using the TLS data expansion function.  If the
+ *             destination pointer is null, the generator is spun and no
+ *             output is produced; if the source pointer is null, raw output
+ *             from the generator is written; otherwise, the source data is
+ *             XORed with the generator output.
+ */
+
+extern void tlsdx_encrypt(tlsdx_ctx */*c*/, const void */*src*/,
+                         void */*dest*/, size_t /*sz*/);
+
+/* --- @tlsdx_free@ --- *
+ *
+ * Arguments:  @tlsdx_ctx *c@ = pointer to the context block
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a context for the TLS data expansion function
+ */
+
+extern void tlsdx_free(tlsdx_ctx */*c*/);
+
+/* ---@tlsdx_rand@ --- *
+ *
+ * Arguments:  @const gcmac *mc@ = MAC function to use
+ *             @const void *k@ = pointer to the key material
+ *             @size_t ksz@ = size of the key material
+ *             @const void *sd@ = pointer to the seed material
+ *             @size_t sdsz@ = size of the seed material
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a generic generator which does TLS data expansion.
+ */
+
+extern grand *tlsdx_rand(const gcmac */*mc*/,
+                        const void */*k*/, size_t /*ksz*/,
+                        const void */*sd*/, size_t /*sdsz*/);
+
+/* --- The actual very paranoid PRF ---------------------------------------*/
+
+/* --- @tlsprf_init@ --- *
+ *
+ * Arguments:  @tlsprf_ctx *c@ = pointer to context block
+ *             @const gcmac *mcx, *mcy@ = left and right MAC functions
+ *             @const void *k@ = pointer to the key material
+ *             @size_t ksz@ = size of the key material
+ *             @const void *sd@ = pointer to the seed material
+ *             @size_t sdsz@ = size of the seed material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a TLS PRF context.
+ */
+
+extern void tlsprf_init(tlsprf_ctx */*c*/,
+                       const gcmac */*mcx*/, const gcmac */*mcy*/,
+                       const void */*k*/, size_t /*ksz*/,
+                       const void */*sd*/, size_t /*sdsz*/);
+
+/* --- @tlsprf_encrypt@ --- *
+ *
+ * Arguments:  @tlsprf_ctx *c@ = pointer to a context
+ *             @const void *src@ = pointer to source data
+ *             @void *dest@ = pointer to destination buffer
+ *             @size_t sz@ = size of buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts data using the TLS pseudo-random function.  If the
+ *             destination pointer is null, the generator is spun and no
+ *             output is produced; if the source pointer is null, raw output
+ *             from the generator is written; otherwise, the source data is
+ *             XORed with the generator output.
+ */
+
+extern void tlsprf_encrypt(tlsprf_ctx */*c*/,
+                          const void */*src*/, void */*dest*/,
+                          size_t /*sz*/);
+
+/* --- @tlsprf_free@ --- *
+ *
+ * Arguments:  @tlsprf_ctx *c@ = pointer to a context
+ *
+ * Returns:    ---
+ *
+ * Use:                Frees a TLS PRF context.
+ */
+
+extern void tlsprf_free(tlsprf_ctx */*c*/);
+
+/* ---@tlsprf_rand@ --- *
+ *
+ * Arguments:  @const gcmac *mcx, *mcy@ = MAC function to use
+ *             @const void *k@ = pointer to the key material
+ *             @size_t ksz@ = size of the key material
+ *             @const void *sd@ = pointer to the seed material
+ *             @size_t sdsz@ = size of the seed material
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a generic generator which does TLS data expansion.
+ */
+
+extern grand *tlsprf_rand(const gcmac */*mcx*/, const gcmac */*mcy*/,
+                         const void */*k*/, size_t /*ksz*/,
+                         const void */*sd*/, size_t /*sdsz*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/rc2-tab.h b/rc2-tab.h
deleted file mode 100644 (file)
index 4a0a29a..0000000
--- a/rc2-tab.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rc2-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Substitution table for RC2
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_RC2_TAB_H
-#define CATACOMB_RC2_TAB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- S-box table -------------------------------------------------------*/
-
-#define RC2_PI {                                                       \
-  0xd9,        0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,                       \
-  0x28,        0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,                       \
-  0xc6,        0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,                       \
-  0x62,        0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,                       \
-  0x17,        0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,                       \
-  0x61,        0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,                       \
-  0xbd,        0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,                       \
-  0xf0,        0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,                       \
-  0x54,        0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,                       \
-  0x73,        0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,                       \
-  0x12,        0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,                       \
-  0x42,        0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,                       \
-  0x6f,        0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,                       \
-  0x27,        0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,                       \
-  0xf8,        0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,                       \
-  0x06,        0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,                       \
-  0x08,        0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,                       \
-  0x84,        0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,                       \
-  0x96,        0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,                       \
-  0x4b,        0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,                       \
-  0xc2,        0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,                       \
-  0x24,        0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,                       \
-  0x99,        0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,                       \
-  0xfc,        0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,                       \
-  0x2d,        0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,                       \
-  0x05,        0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,                       \
-  0xd3,        0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,                       \
-  0x63,        0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,                       \
-  0x0d,        0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,                       \
-  0xbb,        0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,                       \
-  0xc5,        0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,                       \
-  0x0a,        0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad                        \
-}
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rc2.c b/rc2.c
deleted file mode 100644 (file)
index 8241c06..0000000
--- a/rc2.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rc2.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The RC2 block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "paranoia.h"
-#include "rc2.h"
-#include "rc2-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet rc2_keysz[] = { KSZ_RANGE, RC2_KEYSZ, 1, 128, 1 };
-
-/*----- Important tables --------------------------------------------------*/
-
-static const octet pi[256] = RC2_PI;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rc2_braindamage@ --- *
- *
- * Arguments:  @rc2_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of key material in bytes
- *             @unsigned eb@ = desired effective key size, in bits
- *
- * Returns:    ---
- *
- * Use:                Initializes an RC2 expanded key, and braindamages it to the
- *             requested effective key size.  This is here for compatibility
- *             reasons.  You should be using @rc2_init@ in normal code,
- *             which doesn't actually apply braindamage.
- */
-
-void rc2_braindamage(rc2_ctx *k, const void *buf, size_t sz, unsigned eb)
-{
-  unsigned t8;
-  uint16 tm;
-  unsigned i;
-  uint16 *kk;
-  octet l[128];
-
-  KSZ_ASSERT(rc2, sz);
-
-  /* --- Compute the braindamage parameters --- */
-
-  t8 = (eb + 7) / 8;
-  tm = 0xff & ((1 << (8 + eb - 8 * t8)) - 1);
-
-  /* --- Copy and expand the initial key --- */
-
-  if (sz > sizeof(l))
-    sz = sizeof(l);
-  memcpy(l, buf, sz);
-
-  for (i = sz; i < sizeof(l); i++)
-    l[i] = pi[U8(l[i - 1] + l[i - sz])];
-
-  /* --- Braindamage the key --- */
-
-  i = sizeof(l) - t8;
-  l[i] = pi[l[i] & tm];
-  while (i) {
-    i--;
-    l[i] = pi[U8(l[i + 1] ^ l[i + t8])];
-  }
-
-  /* --- Write it to the key block --- */
-
-  kk = k->k;
-  for (i = 0; i < sizeof(l); i += 2)
-    *kk++ = LOAD16_L(l + i);
-  BURN(l);
-}
-
-/* --- @rc2_init@ --- *
- *
- * Arguments:  @rc2_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of key material in bytes
- *
- * Returns:    ---
- *
- * Use:                Initializes an RC2 expanded key.  The effective key size is
- *             set to be equal to the real key size, in bits.
- */
-
-void rc2_init(rc2_ctx *k, const void *buf, size_t sz)
-{
-  rc2_braindamage(k, buf, sz, sz * 8);
-}
-
-/*----- Encryption and decryption -----------------------------------------*/
-
-#define MIX(a, b, c, d, r, kk) do {                                    \
-  a += *kk++ + (d & c) + (~d & b);                                     \
-  a = ROL16(a, r);                                                     \
-} while (0)
-
-#define MASH(a, d, k) do {                                             \
-  a += k[d & 63];                                                      \
-} while (0)
-
-#define UNMIX(a, b, c, d, r, kk) do {                                  \
-  a = ROR16(a, r);                                                     \
-  a -= *--kk + (d & c) + (~d & b);                                     \
-} while (0)
-
-#define UNMASH(a, d, k) do {                                           \
-  a -= k[d & 63];                                                      \
-} while (0)
-
-/* --- @rc2_eblk@, @rc2_dblk@ --- *
- *
- * Arguments:  @const rc2_ctx *k@ = pointer to RC2 context
- *             @const uint32 s[2]@ = pointer to source block
- *             @const uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-void rc2_eblk(const rc2_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint16 a = U16(s[0] >>  0), b = U16(s[0] >> 16);
-  uint16 c = U16(s[1] >>  0), d = U16(s[1] >> 16);
-  const uint16 *kk = k->k;
-
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MASH(a, d, k->k); MASH(b, a, k->k);
-  MASH(c, b, k->k); MASH(d, c, k->k);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MASH(a, d, k->k); MASH(b, a, k->k);
-  MASH(c, b, k->k); MASH(d, c, k->k);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
-  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
-
-  dst[0] = a | (b << 16); dst[1] = c | (d << 16);
-}
-
-void rc2_dblk(const rc2_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint16 a = U16(s[0] >>  0), b = U16(s[0] >> 16);
-  uint16 c = U16(s[1] >>  0), d = U16(s[1] >> 16);
-  const uint16 *kk = k->k + 64;
-
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMASH(d, c, k->k); UNMASH(c, b, k->k);
-  UNMASH(b, a, k->k); UNMASH(a, d, k->k);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMASH(d, c, k->k); UNMASH(c, b, k->k);
-  UNMASH(b, a, k->k); UNMASH(a, d, k->k);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
-  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
-
-  dst[0] = a | (b << 16); dst[1] = c | (d << 16);
-}
-
-/*----- Custom test rig ---------------------------------------------------*
- *
- * I need to test the braindamage feature.
- */
-
-#ifdef TEST_RIG
-
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-static int verify(dstr *v)
-{
-  rc2_ctx k;
-  uint32 p[RC2_BLKSZ / 4];
-  uint32 c[RC2_BLKSZ / 4];
-  uint32 d[RC2_BLKSZ / 4];
-  dstr b = DSTR_INIT;
-  unsigned bd = *(unsigned *)v[1].buf;
-  int ok = 1;
-
-  /* --- Initialize the key buffer --- */
-
-  dstr_ensure(&b, RC2_BLKSZ);
-  b.len = RC2_BLKSZ;
-  rc2_braindamage(&k, v[0].buf, v[0].len, bd);
-  BLKC_LOAD(RC2, p, v[2].buf);
-  BLKC_LOAD(RC2, c, v[3].buf);
-
-  /* --- Test encryption --- */
-
-  BLKC_MOVE(RC2, d, p);
-  rc2_eblk(&k, d, d);
-  BLKC_STORE(RC2, b.buf, d);
-  if (memcmp(b.buf, v[3].buf, RC2_BLKSZ)) {
-    ok = 0;
-    printf("\nfail encryption:"
-          "\n\tkey        = ");
-    type_hex.dump(&v[0], stdout);
-    printf("\n\tbraindamage= %u", bd);
-    printf("\n\tplaintext  = "); type_hex.dump(&v[2], stdout);
-    printf("\n\texpected   = "); type_hex.dump(&v[3], stdout);
-    printf("\n\tcalculated = "); type_hex.dump(&b, stdout);
-    putchar('\n');
-  }
-
-  /* --- Test decryption --- */
-
-  BLKC_MOVE(RC2, d, c);
-  rc2_dblk(&k, d, d);
-  BLKC_STORE(RC2, b.buf, d);
-  if (memcmp(b.buf, v[2].buf, RC2_BLKSZ)) {
-    ok = 0;
-    printf("\nfail decryption:"
-          "\n\tkey        = ");
-    type_hex.dump(&v[0], stdout);
-    printf("\n\tbraindamage= %u", bd);
-    printf("\n\tciphertext = "); type_hex.dump(&v[3], stdout);
-    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
-    printf("\n\tcalculated = "); type_hex.dump(&b, stdout);
-    putchar('\n');
-  }
-
-  /* --- Return --- */
-
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "rc2", verify, { &type_hex, &type_int, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/rc2");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rc2.h b/rc2.h
deleted file mode 100644 (file)
index 5d35b14..0000000
--- a/rc2.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rc2.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The RC2 block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the RC2 block cipher -------------------------------------*
- *
- * RC2 was designed by Ron Rivest, and for a long time was a trade secret of
- * RSA Data Security Inc.  Like RC4, it leaked out, and has now been
- * described in RFC2268.  The RC2 key schedule is known to have some
- * weaknesses, although I'm not aware of any major results against the cipher
- * itself.  I'm also not aware of any legal problems with using the RC2
- * cipher.
- *
- * The oddest feature in the cipher is the key schedule.  It expands the
- * initial key material to 128 bytes, and then `brain-damages' it, according
- * to a supplied `effective key-bits' parameter, before expanding the
- * remaining key material back into the buffer.
- *
- * The key schedule allows second preimages to be computed trivially.
- */
-
-#ifndef CATACOMB_RC2_H
-#define CATACOMB_RC2_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define RC2_BLKSZ 8
-#define RC2_KEYSZ 16
-#define RC2_CLASS (N, L, 64)
-
-extern const octet rc2_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rc2_ctx {
-  uint16 k[64];
-} rc2_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rc2_braindamage@ --- *
- *
- * Arguments:  @rc2_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of key material in bytes
- *             @unsigned eb@ = desired effective key size, in bits
- *
- * Returns:    ---
- *
- * Use:                Initializes an RC2 expanded key, and braindamages it to the
- *             requested effective key size.  This is here for compatibility
- *             reasons.  You should be using @rc2_init@ in normal code,
- *             which doesn't actually apply braindamage.
- */
-
-extern void rc2_braindamage(rc2_ctx */*k*/, const void */*buf*/,
-                           size_t /*sz*/, unsigned /*eb*/);
-
-/* --- @rc2_init@ --- *
- *
- * Arguments:  @rc2_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of key material in bytes
- *
- * Returns:    ---
- *
- * Use:                Initializes an RC2 expanded key.  The effective key size is
- *             set to be equal to the real key size, in bits.
- */
-
-extern void rc2_init(rc2_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @rc2_eblk@, @rc2_dblk@ --- *
- *
- * Arguments:  @const rc2_ctx *k@ = pointer to RC2 context
- *             @const uint32 s[2]@ = pointer to source block
- *             @const uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void rc2_eblk(const rc2_ctx */*k*/,
-                    const uint32 */*s*/, uint32 */*dst*/);
-extern void rc2_dblk(const rc2_ctx */*k*/,
-                    const uint32 */*s*/, uint32 */*dst*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rc4.c b/rc4.c
deleted file mode 100644 (file)
index 83b5104..0000000
--- a/rc4.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rc4.c,v 1.6 2004/04/08 01:36:15 mdw Exp $
- *
- * The alleged RC4 stream cipher
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-#include <mLib/sub.h>
-
-#include "arena.h"
-#include "gcipher.h"
-#include "grand.h"
-#include "paranoia.h"
-#include "rc4.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet rc4_keysz[] = { KSZ_RANGE, RC4_KEYSZ, 1, 255, 1 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rc4_addkey@ --- *
- *
- * Arguments:  @rc4_ctx *ctx@ = pointer to context to key
- *             @const void *k@ = pointer to key data to use
- *             @size_t sz@ = size of the key data
- *
- * Returns:    ---
- *
- * Use:                Mixes key data with an RC4 context.  The RC4 context is not
- *             reset before mixing.  This may be used to mix new key
- *             material with an existing RC4 context.
- */
-
-void rc4_addkey(rc4_ctx *ctx, const void *k, size_t sz)
-{
-  unsigned i, j;
-  const octet *p = k, *q = p + sz;
-
-  KSZ_ASSERT(rc4, sz);
-
-  for (i = j = 0; i < 256; i++) {
-    unsigned si = ctx->s[i];
-    j = (j + si + *p++) & 0xff;
-    ctx->s[i] = ctx->s[j];
-    ctx->s[j] = si;
-    if (p == q)
-      p = k;
-  }
-
-  ctx->i = ctx->j = 0;
-}
-
-/* --- @rc4_init@ --- *
- *
- * Arguments:  @rc4_ctx *ctx@ = pointer to context to initialize
- *             @const void *k@ = pointer to key data to use
- *             @size_t sz@ = size of the key data
- *
- * Returns:    ---
- *
- * Use:                Initializes an RC4 context ready for use.
- */
-
-void rc4_init(rc4_ctx *ctx, const void *k, size_t sz)
-{
-  unsigned i;
-
-  for (i = 0; i < 256; i++)
-    ctx->s[i] = i;
-  ctx->f = 0;
-  rc4_addkey(ctx, k, sz);
-}
-
-/* --- @rc4_encrypt@ --- *
- *
- * Arguments:  @rc4_ctx *ctx@ = pointer to context to use
- *             @const void *src@ = pointer to the source block
- *             @void *dest@ = pointer to the destination block
- *             @size_t sz@ = size of the block
- *
- * Returns:    ---
- *
- * Use:                Encrypts or decrypts a block of data.  The destination may
- *             be null to just grind the generator around for a while.  It's
- *             recommended that you say `@rc4_encrypt(&ctx, 0, 0, 1024)@'
- *             after initializing a new context, to prevent keystream
- *             guessing attacks.  The source may be null to just extract a
- *             big lump of data from the generator.
- */
-
-void rc4_encrypt(rc4_ctx *ctx, const void *src, void *dest, size_t sz)
-{
-  const octet *s = src;
-  octet *d = dest;
-
-  if (!d)
-    RC4_OPEN(ctx, while (sz) { unsigned x; RC4_BYTE(x); sz--; });
-  else if (!s)
-    RC4_OPEN(ctx, while (sz) { RC4_BYTE(*d++); sz--; });
-  else
-    RC4_OPEN(ctx,
-            while (sz) { unsigned x; RC4_BYTE(x); *d++ = *s++ ^ x; sz--; });
-}
-
-/*----- Generic cipher interface ------------------------------------------*/
-
-typedef struct gctx {
-  gcipher c;
-  rc4_ctx rc4;
-} gctx;
-
-static const gcipher_ops gops;
-
-static gcipher *ginit(const void *k, size_t sz)
-{
-  gctx *g = S_CREATE(gctx);
-  g->c.ops = &gops;
-  rc4_init(&g->rc4, k, sz);
-  return (&g->c);
-}
-
-static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
-{
-  gctx *g = (gctx *)c;
-  rc4_encrypt(&g->rc4, s, t, sz);
-}
-
-static void gdestroy(gcipher *c)
-{
-  gctx *g = (gctx *)c;
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static const gcipher_ops gops = {
-  &rc4,
-  gencrypt, gencrypt, gdestroy, 0, 0
-};
-
-const gccipher rc4 = {
-  "rc4", rc4_keysz, 0,
-  ginit
-};
-
-/*----- Generic random number generator interface -------------------------*/
-
-typedef struct grctx {
-  grand r;
-  rc4_ctx rc4;
-} grctx;
-
-static void grdestroy(grand *r)
-{
-  grctx *g = (grctx *)r;
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static int grmisc(grand *r, unsigned op, ...)
-{
-  grctx *g = (grctx *)r;
-  va_list ap;
-  int rc = 0;
-  uint32 i;
-  octet buf[4];
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDBLOCK:
-       case GRAND_SEEDRAND:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT:
-      i = va_arg(ap, unsigned);
-      STORE32(buf, i);
-      rc4_addkey(&g->rc4, buf, sizeof(buf));
-      break;
-    case GRAND_SEEDUINT32:
-      i = va_arg(ap, uint32);
-      STORE32(buf, i);
-      rc4_addkey(&g->rc4, buf, sizeof(buf));
-      break;
-    case GRAND_SEEDBLOCK: {
-      const void *p = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      rc4_addkey(&g->rc4, p, sz);
-    } break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      octet buf[16];
-      rr->ops->fill(rr, buf, sizeof(buf));
-      rc4_addkey(&g->rc4, buf, sizeof(buf));
-    } break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static octet grbyte(grand *r)
-{
-  grctx *g = (grctx *)r;
-  octet o;
-  RC4_OPEN(&g->rc4, RC4_BYTE(o););
-  return (o);
-}
-
-static uint32 grword(grand *r)
-{
-  grctx *g = (grctx *)r;
-  octet b[4];
-  int i;
-  RC4_OPEN(&g->rc4,
-          for (i = 0; i < sizeof(b); i++)
-            RC4_BYTE(b[i]););
-  return (LOAD32(b));
-}
-
-static void grfill(grand *r, void *p, size_t sz)
-{
-  grctx *g = (grctx *)r;
-  rc4_encrypt(&g->rc4, 0, p, sz);
-}
-
-static const grand_ops grops = {
-  "rc4",
-  GRAND_CRYPTO, 0,
-  grmisc, grdestroy,
-  grword, grbyte, grword, grand_range, grfill
-};
-
-/* --- @rc4_rand@ --- *
- *
- * Arguments:  @const void *k@ = pointer to key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a random number interface wrapper around an
- *             OFB-mode block cipher.
- */
-
-grand *rc4_rand(const void *k, size_t sz)
-{
-  grctx *g = S_CREATE(grctx);
-  g->r.ops = &grops;
-  rc4_init(&g->rc4, k, sz);
-  return (&g->r);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-#include <string.h>
-
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-static int v_encrypt(dstr *v)
-{
-  rc4_ctx ctx;
-  dstr d = DSTR_INIT;
-  int ok = 1;
-
-  rc4_init(&ctx, v[0].buf, v[0].len);
-  dstr_ensure(&d, v[1].len);
-  d.len = v[1].len;
-  rc4_encrypt(&ctx, v[1].buf, d.buf, d.len);
-
-  if (memcmp(v[2].buf, d.buf, d.len) != 0) {
-    ok = 0;
-    printf("\nfail encryption:"
-          "\n\tkey        = ");
-    type_hex.dump(&v[0], stdout);
-    printf("\n\tplaintext  = "); type_hex.dump(&v[1], stdout);
-    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
-    printf("\n\tcalculated = "); type_hex.dump(&d, stdout);
-    putchar('\n');
-  }
-
-  return (ok);
-}
-
-static int v_generate(dstr *v)
-{
-  rc4_ctx ctx;
-  dstr d = DSTR_INIT;
-  int ok = 1;
-
-  rc4_init(&ctx, v[0].buf, v[0].len);
-  rc4_encrypt(&ctx, 0, 0, *(int *)v[1].buf);
-  dstr_ensure(&d, v[2].len);
-  d.len = v[2].len;
-  rc4_encrypt(&ctx, 0, d.buf, d.len);
-
-  if (memcmp(v[2].buf, d.buf, d.len) != 0) {
-    ok = 0;
-    printf("\nfail generation:"
-          "\n\tkey        = ");
-    type_hex.dump(&v[0], stdout);
-    printf("\n\tskip len   = %i", *(int *)v[1].buf);
-    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
-    printf("\n\tcalculated = "); type_hex.dump(&d, stdout);
-    putchar('\n');
-  }
-
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "rc4-encrypt", v_encrypt, { &type_hex, &type_hex, &type_hex, 0 } },
-  { "rc4-generate", v_generate, { &type_hex, &type_int, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/rc4");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rc4.h b/rc4.h
deleted file mode 100644 (file)
index 7df1348..0000000
--- a/rc4.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rc4.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The alleged RC4 stream cipher
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on RC4 ------------------------------------------------------*
- *
- * RC4 is a stream cipher desgigned by Ron Rivest.  For a while RC4 was a
- * trade secret of RSA Data Security, Inc., but somehow source code for a
- * cipher which interworks with RC4 was posted to the Cypherpunks mailing
- * list.
- */
-
-#ifndef CATACOMB_RC4_H
-#define CATACOMB_RC4_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rc4_ctx {
-  unsigned i, j;                       /* Indices into the @S@ table */
-  unsigned f;                          /* Flags word */
-  octet s[256];                                /* The ever-changing @S@ table */
-} rc4_ctx;
-
-#define RC4F_OPEN 1u
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- @RC4_OPEN@ --- *
- *
- * Arguments:  @ctx@ = pointer to an RC4 context
- *             @guts@ = code to perform within the RC4 context
- *
- * Use:                Performs some code within an RC4 context.  Some of the
- *             parameters are extracted from the context and held in local
- *             variables for speed.  Multiple calls to @RC4_BYTE@ may be
- *             made within the open context.  A context must only be
- *             opened once at a time.
- */
-
-#define RC4_OPEN(ctx, guts) do {                                       \
-  unsigned _rc4_i = (ctx)->i;                                          \
-  unsigned _rc4_j = (ctx)->j;                                          \
-  octet *_rc4_s = (ctx)->s;                                            \
-                                                                       \
-  assert(((void)"RC4 context may only be opened once at a time",       \
-         ((ctx)->f & RC4F_OPEN) == 0));                                \
-  (ctx)->f |= RC4F_OPEN;                                               \
-                                                                       \
-  guts                                                                 \
-                                                                       \
-  (ctx)->f &= ~RC4F_OPEN;                                              \
-  (ctx)->i = _rc4_i;                                                   \
-  (ctx)->j = _rc4_j;                                                   \
-} while (0)
-
-/* --- @RC4_BYTE@ --- *
- *
- * Arguments:  @x@ = output variable to set
- *
- * Use:                Extracts an octet from the lexically innermost open RC4
- *             context and places it in the variable @x@.
- */
-
-#define RC4_BYTE(x) do {                                               \
-  unsigned _si, _sj;                                                   \
-  _rc4_i = (_rc4_i + 1) & 0xff;                                                \
-  _si = _rc4_s[_rc4_i];                                                        \
-  _rc4_j = (_rc4_j + _si) & 0xff;                                      \
-  _sj = _rc4_s[_rc4_j];                                                        \
-  _rc4_s[_rc4_i] = _sj;                                                        \
-  _rc4_s[_rc4_j] = _si;                                                        \
-  (x) = _rc4_s[(_si + _sj) & 0xff];                                    \
-} while (0)
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rc4_addkey@ --- *
- *
- * Arguments:  @rc4_ctx *ctx@ = pointer to context to key
- *             @const void *k@ = pointer to key data to use
- *             @size_t sz@ = size of the key data
- *
- * Returns:    ---
- *
- * Use:                Mixes key data with an RC4 context.  The RC4 context is not
- *             reset before mixing.  This may be used to mix new key
- *             material with an existing RC4 context.
- */
-
-extern void rc4_addkey(rc4_ctx */*ctx*/, const void */*k*/, size_t /*sz*/);
-
-/* --- @rc4_init@ --- *
- *
- * Arguments:  @rc4_ctx *ctx@ = pointer to context to initialize
- *             @const void *k@ = pointer to key data to use
- *             @size_t sz@ = size of the key data
- *
- * Returns:    ---
- *
- * Use:                Initializes an RC4 context ready for use.
- */
-
-extern void rc4_init(rc4_ctx */*ctx*/, const void */*k*/, size_t /*sz*/);
-
-/* --- @rc4_encrypt@ --- *
- *
- * Arguments:  @rc4_ctx *ctx@ = pointer to context to use
- *             @const void *src@ = pointer to the source block
- *             @void *dest@ = pointer to the destination block
- *             @size_t sz@ = size of the block
- *
- * Returns:    ---
- *
- * Use:                Encrypts or decrypts a block of data.  The destination may
- *             be null to just grind the generator around for a while.  It's
- *             recommended that you say `@rc4_encrypt(&ctx, 0, 0, 1024)@'
- *             after initializing a new context, to prevent keystream
- *             guessing attacks.  The source may be null to just extract a
- *             big lump of data from the generator.
- */
-
-extern void rc4_encrypt(rc4_ctx */*ctx*/,
-                       const void */*src*/, void */*dest*/,
-                       size_t /*sz*/);
-
-/*----- Generic cipher interface ------------------------------------------*/
-
-#define RC4_KEYSZ 16
-extern const octet rc4_keysz[];
-
-extern const gccipher rc4;
-
-/*----- Generic random number generator interface -------------------------*/
-
-/* --- @rc4_rand@ --- *
- *
- * Arguments:  @const void *k@ = pointer to key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a random number interface wrapper around an
- *             OFB-mode block cipher.
- */
-
-extern grand *rc4_rand(const void */*k*/, size_t /*sz*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rc5.c b/rc5.c
deleted file mode 100644 (file)
index 306b5ec..0000000
--- a/rc5.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rc5.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The RC5-32/12 block cipher
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-
-#include "arena.h"
-#include "blkc.h"
-#include "gcipher.h"
-#include "rc5.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet rc5_keysz[] = { KSZ_RANGE, RC5_KEYSZ, 1, 255, 1 };
-
-/*----- Internal magical constants ----------------------------------------*/
-
-#define T ((RC5_ROUNDS + 1) * 2)
-#define P 0xb7e15163
-#define Q 0x9e3779b9
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rc5_init@ --- *
- *
- * Arguments:  @rc5_ctx *k@ = pointer to a key block
- *             @const void *sbuf@ = pointer to key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes an RC5 key block.
- */
-
-void rc5_init(rc5_ctx *k, const void *sbuf, size_t sz)
-{
-  uint32 *l;
-  size_t w;
-
-  /* --- Set up the @L@ table --- *
-   *
-   * This is slightly unfortunately defined.
-   */
-
-  KSZ_ASSERT(rc5, sz);
-
-  {
-    int i;
-    const octet *p = sbuf;
-
-    /* --- Create the buffer --- */
-
-    w = (sz + 3) / 4;
-    l = XS_ALLOC(w * sizeof(uint32));
-
-    /* --- Extract the key material --- */
-
-    for (i = 0; sz > 3; i++) {
-      l[i] = LOAD32_L(p);
-      p += 4;
-      sz -= 4;
-    }
-
-    /* --- Fix up the tail end --- */
-
-    if (sz) {
-      uint32 x = U8(*p++);
-      if (sz > 1) x |= (U8(*p++) <<  8);
-      if (sz > 2) x |= (U8(*p++) << 16);
-      l[i] = x;
-    }
-  }
-
-  /* --- Initialize the @S@ table --- */
-
-  {
-    int i;
-
-    k->s[0] = P;
-    for (i = 1; i < T; i++)
-      k->s[i] = k->s[i - 1] + Q;
-  }
-
-  /* --- Mix in the key --- */
-
-  {
-    int m = 3 * (w > T ? w : T);
-    int i, j, c;
-    uint32 a, b;
-
-    for (c = i = j = a = b = 0; c < m; c++) {
-      uint32 x;
-
-      x = k->s[i] + a + b;
-      k->s[i] = a = ROL32(x, 3);
-      i++; if (i >= T) i = 0;
-
-      x = l[j] + a + b;
-      l[j] = b = ROL32(x, a + b);
-      j++; if (j >= w) j = 0;
-    }
-  }
-
-  memset(l, 0, w * sizeof(uint32));
-  XS_FREE(l);
-}
-
-/* --- @EROUND@, @DROUND@ --- */
-
-#define EROUND(x, y, k) do {                                           \
-  uint32 _x;                                                           \
-  _x = x ^ y; x = ROL32(_x, y) + k[0];                                 \
-  _x = y ^ x; y = ROL32(_x, x) + k[1];                                 \
-  k += 2;                                                              \
-} while (0)
-
-#define DROUND(x, y, k) do {                                           \
-  uint32 _x;                                                           \
-  k -= 2;                                                              \
-  _x = y - k[1]; y = ROR32(_x, x) ^ x;                                 \
-  _x = x - k[0]; x = ROR32(_x, y) ^ y;                                 \
-} while (0)
-
-/* --- @EBLK@, @DBLK@ --- */
-
-#define EBLK(a, b, c, d, k) do {                                       \
-  uint32 _l, _r;                                                       \
-  const uint32 *_k = (k)->s;                                           \
-                                                                       \
-  _l = (a) + _k[0];                                                    \
-  _r = (b) + _k[1];                                                    \
-  _k += 2;                                                             \
-                                                                       \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  EROUND(_l, _r, _k);                                                  \
-  (c) = _l;                                                            \
-  (d) = _r;                                                            \
-} while (0)
-
-#define DBLK(a, b, c, d, k) do {                                       \
-  uint32 _l, _r;                                                       \
-  const uint32 *_k = (k)->s + T;                                       \
-                                                                       \
-  _l = (a);                                                            \
-  _r = (b);                                                            \
-                                                                       \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-  DROUND(_l, _r, _k);                                                  \
-                                                                       \
-  _k -= 2;                                                             \
-  (d) = _r - _k[1];                                                    \
-  (c) = _l - _k[0];                                                    \
-} while (0)
-
-/* --- @rc5_eblk@, @rc5_dblk@ --- *
- *
- * Arguments:  @const rc5_ctx *k@ = pointer to RC5 context block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 *d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low level block encryption and decryption.
- */
-
-void rc5_eblk(const rc5_ctx *k, const uint32 *s, uint32 *d)
-{
-  EBLK(s[0], s[1], d[0], d[1], k);
-}
-
-void rc5_dblk(const rc5_ctx *k, const uint32 *s, uint32 *d)
-{
-  DBLK(s[0], s[1], d[0], d[1], k);
-}
-
-/* --- Test rig --- */
-
-BLKC_TEST(RC5, rc5)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rc5.h b/rc5.h
deleted file mode 100644 (file)
index c029832..0000000
--- a/rc5.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rc5.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The RC5-32/12 block cipher
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on the RC5 block cipher -------------------------------------*
- *
- * RC5 was designed by Ron Rivest as a test vehicle for the use of data-
- * dependent rotations in cryptographic transformations.  The algorithm is
- * covered by a patent held by RSA Security Inc. (US Patent# 5,724,428).
- * It's vulnerable to some clever differential attacks, which can break it in
- * about %$2^{44}$% chosen plaintexts.  I don't recommend the use of this
- * cipher.
- */
-
-#ifndef CATACOMB_RC5_H
-#define CATACOMB_RC5_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define RC5_ROUNDS 12
-#define RC5_KEYSZ 10
-#define RC5_BLKSZ 8
-#define RC5_CLASS (N, L, 64)
-
-extern const octet rc5_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rc5_ctx {
-  uint32 s[2 * (RC5_ROUNDS + 1)];
-} rc5_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rc5_init@ --- *
- *
- * Arguments:  @rc5_ctx *k@ = pointer to a key block
- *             @const void *sbuf@ = pointer to key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes an RC5 key block.
- */
-
-extern void rc5_init(rc5_ctx */*k*/, const void */*sbuf*/, size_t /*sz*/);
-
-/* --- @rc5_eblk@, @rc5_dblk@ --- *
- *
- * Arguments:  @const rc5_ctx *k@ = pointer to RC5 context block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 *d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low level block encryption and decryption.
- */
-
-extern void rc5_eblk(const rc5_ctx */*k*/,
-                    const uint32 */*s*/, uint32 */*d*/);
-extern void rc5_dblk(const rc5_ctx */*k*/,
-                    const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rho.c b/rho.c
deleted file mode 100644 (file)
index a02eeba..0000000
--- a/rho.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rho.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Pollard's rho algorithm for discrete logs
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "fibrand.h"
-#include "mp.h"
-#include "mpmont.h"
-#include "mprand.h"
-#include "rho.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rho@ --- *
- *
- * Arguments:  @rho_ctx *cc@ = pointer to the context structure
- *             @void *x, *y@ = two (equal) base values (try 1)
- *             @mp *a, *b@ = logs of %$x$% (see below)
- *
- * Returns:    The discrete logarithm %$\log_g a$%, or null if the algorithm
- *             failed.  (This is unlikely, though possible.)
- *
- * Use:                Uses Pollard's rho algorithm to compute discrete logs in the
- *             group %$G$% generated by %$g$%.
- *
- *             The algorithm works by finding a cycle in a pseudo-random
- *             walk.  The function @ops->split@ should return an element
- *             from %$\{\,0, 1, 2\,\}$% according to its argument, in order
- *             to determine the walk.  At each step in the walk, we know a
- *             group element %$x \in G$% together with its representation as
- *             a product of powers of %$g$% and $%a$% (i.e., we know that
- *             %$x = g^\alpha a^\beta$% for some %$\alpha$%, %$\beta$%).
- *
- *             Locating a cycle gives us a collision
- *
- *               %$g^{\alpha} a^{\beta} = g^{\alpha'} a^{\beta'}$%
- *
- *             Taking logs of both sides (to base %$g$%) gives us that
- *
- *               %$\log a\equiv\frac{\alpha-\alpha'}{\beta'-\beta}\bmod{n}$%
- *
- *             Good initial values are %$x = y = 1$% (the multiplicative
- *             identity of %$G$%) and %$\alpha\equiv\beta\equiv0\bmod{n}$%.
- *             If that doesn't work then start choosing more `interesting'
- *             values.
- *
- *             Note that the algorithm requires minimal space but
- *             %$O(\sqrt{n})$% time.  Don't do this on large groups,
- *             particularly if you can find a decent factor base.
- *
- *             Finally, note that this function will free the input values
- *             when it's finished with them.  This probably isn't a great
- *             problem.
- */
-
-static void step(rho_ctx *cc, void *x, mp **a, mp **b)
-{
-  switch (cc->ops->split(x)) {
-    case 0:
-      cc->ops->mul(x, cc->g, cc->c);
-      *a = mp_add(*a, *a, MP_ONE);
-      if (MP_CMP(*a, >=, cc->n))
-       *a = mp_sub(*a, *a, cc->n);
-      break;
-    case 1:
-      cc->ops->sqr(x, cc->c);
-      *a = mp_lsl(*a, *a, 1);
-      if (MP_CMP(*a, >=, cc->n))
-       *a = mp_sub(*a, *a, cc->n);
-      *b = mp_lsl(*b, *b, 1);
-      if (MP_CMP(*b, >=, cc->n))
-       *b = mp_sub(*b, *b, cc->n);
-      break;
-    case 2:
-      cc->ops->mul(x, cc->a, cc->c);
-      *b = mp_add(*b, *b, MP_ONE);
-      if (MP_CMP(*b, >=, cc->n))
-       *b = mp_sub(*b, *b, cc->n);
-      break;
-  }
-}
-
-mp *rho(rho_ctx *cc, void *x, void *y, mp *a, mp *b)
-{
-  mp *aa = MP_COPY(a), *bb = MP_COPY(b);
-  mp *g;
-
-  /* --- Grind through the random walk until we find a collision --- */
-
-  do {
-    step(cc, x, &a, &b);
-    step(cc, y, &aa, &bb);
-    step(cc, y, &aa, &bb);
-  } while (!cc->ops->eq(x, y));
-  cc->ops->drop(x);
-  cc->ops->drop(y);
-
-  /* --- Now sort out the mess --- */
-
-  aa = mp_sub(aa, a, aa);
-  bb = mp_sub(bb, bb, b);
-  g = MP_NEW;
-  mp_gcd(&g, &bb, 0, bb, cc->n);
-  if (!MP_EQ(g, MP_ONE)) {
-    mp_drop(aa);
-    aa = 0;
-  } else {
-    aa = mp_mul(aa, aa, bb);
-    mp_div(0, &aa, aa, cc->n);
-  }
-
-  /* --- Done --- */
-
-  mp_drop(bb);
-  mp_drop(g);
-  mp_drop(a);
-  mp_drop(b);
-  return (aa);
-}
-
-/* --- @rho_prime@ --- *
- *
- * Arguments:  @mp *g@ = generator for the group
- *             @mp *a@ = value to find the logarithm of
- *             @mp *n@ = order of the group
- *             @mp *p@ = prime size of the underlying prime field
- *
- * Returns:    The discrete logarithm %$\log_g a$%.
- *
- * Use:                Computes discrete logarithms in a subgroup of a prime field.
- */
-
-static void prime_sqr(void *x, void *c)
-{
-  mp **p = x;
-  mp *a = *p;
-  a = mp_sqr(a, a);
-  a = mpmont_reduce(c, a, a);
-  *p = a;
-}
-
-static void prime_mul(void *x, void *y, void *c)
-{
-  mp **p = x;
-  mp *a = *p;
-  a = mpmont_mul(c, a, a, y);
-  *p = a;
-}
-
-static int prime_eq(void *x, void *y)
-{
-  return (MP_EQ(*(mp **)x, *(mp **)y));
-}
-
-static int prime_split(void *x)
-{
-  /* --- Notes on the splitting function --- *
-   *
-   * The objective is to produce a simple pseudorandom mapping from the
-   * underlying field \gf{p} to \{\,0, 1, 2\,\}$%.  This is further
-   * constrained by the fact that we must not have %$1 \mapsto 1$% (since
-   * otherwise the stepping function above will loop).
-   *
-   * The function we choose is very simple: we take the least significant
-   * word from the integer, add one (to prevent the %$1 \mapsto 1$% property
-   * described above) and reduce modulo 3.  This is slightly biased against
-   * the result 2, but this doesn't appear to be relevant.
-   */
-
-  return (((*(mp **)x)->v[0] + 1) % 3);
-}
-
-static void prime_drop(void *x)
-{
-  MP_DROP(*(mp **)x);
-}
-
-static const rho_ops prime_ops = {
-  prime_sqr, prime_mul, prime_eq, prime_split, prime_drop
-};
-
-mp *rho_prime(mp *g, mp *a, mp *n, mp *p)
-{
-  rho_ctx cc;
-  grand *r = 0;
-  mpmont mm;
-  mp *x, *y;
-  mp *aa, *bb;
-  mp *l;
-
-  /* --- Initialization --- */
-
-  mpmont_create(&mm, p);
-  cc.ops = &prime_ops;
-  cc.c = &mm;
-  cc.n = n;
-  cc.g = mpmont_mul(&mm, MP_NEW, g, mm.r2);
-  cc.a = mpmont_mul(&mm, MP_NEW, a, mm.r2);
-  x = MP_COPY(mm.r);
-  y = MP_COPY(x);
-  aa = bb = MP_ZERO;
-
-  /* --- The main loop --- */
-
-  while ((l = rho(&cc, &x, &y, aa, bb)) == 0) {
-    mp_expfactor f[2];
-
-    if (!r)
-      r = fibrand_create(0);
-    aa = mprand_range(MP_NEW, n, r, 0);
-    bb = mprand_range(MP_NEW, n, r, 0);
-    f[0].base = cc.g; f[0].exp = aa;
-    f[1].base = cc.a; f[1].exp = bb;
-    x = mpmont_mexpr(&mm, MP_NEW, f, 2);
-    y = MP_COPY(x);
-  }
-
-  /* --- Throw everything away now --- */
-
-  if (r)
-    r->ops->destroy(r);
-  mp_drop(cc.g);
-  mp_drop(cc.a);
-  mpmont_destroy(&mm);
-  return (l);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "dh.h"
-
-int main(void)
-{
-  dh_param dp;
-  mp *x, *y;
-  grand *r = fibrand_create(0);
-  mpmont mm;
-  mp *l;
-  int ok;
-
-  fputs("rho: ", stdout);
-  fflush(stdout);
-
-  dh_gen(&dp, 32, 256, 0, r, pgen_evspin, 0);
-  x = mprand_range(MP_NEW, dp.q, r, 0);
-  mpmont_create(&mm, dp.p);
-  y = mpmont_exp(&mm, MP_NEW, dp.g, x);
-  mpmont_destroy(&mm);
-  l = rho_prime(dp.g, y, dp.q, dp.p);
-  if (MP_EQ(x, l)) {
-    fputs(". ok\n", stdout);
-    ok = 1;
-  } else {
-    fputs("\n*** rho (discrete logs) failed\n", stdout);
-    ok = 0;
-  }
-
-  mp_drop(l);
-  mp_drop(x);
-  mp_drop(y);
-  r->ops->destroy(r);
-  dh_paramfree(&dp);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-
-  return (ok ? 0 : EXIT_FAILURE);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rho.h b/rho.h
deleted file mode 100644 (file)
index 75bf7fa..0000000
--- a/rho.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rho.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Pollard's rho algorithm for discrete logs
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_RHO_H
-#define CATACOMB_RHO_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- The group operations table --- */
-
-typedef struct rho_ops {
-  void (*sqr)(void *x, void *c);
-  void (*mul)(void *x, void *y, void *c);
-  int (*eq)(void *x, void *y);
-  int (*split)(void *x);
-  void (*drop)(void *x);
-} rho_ops;
-
-/* --- The Pollard's rho context structure --- */
-
-typedef struct rho_ctx {
-  const rho_ops *ops;                  /* Group operations table */
-  void *c;                             /* Context for group operations */
-  void *g, *a;                         /* Generator and argument for log */
-  mp *n;                               /* Cyclic group order */
-} rho_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rho@ --- *
- *
- * Arguments:  @rho_ctx *cc@ = pointer to the context structure
- *             @void *x, *y@ = two (equal) base values (try 1)
- *             @mp *a, *b@ = logs of %$x$% (see below)
- *
- * Returns:    The discrete logarithm %$\log_g a$%, or null if the algorithm
- *             failed.  (This is unlikely, though possible.)
- *
- * Use:                Uses Pollard's rho algorithm to compute discrete logs in the
- *             group %$G$% generated by %$g$%.
- *
- *             The algorithm works by finding a cycle in a pseudo-random
- *             walk.  The function @ops->split@ should return an element
- *             from %$\{\,0, 1, 2\,\}$% according to its argument, in order
- *             to determine the walk.  At each step in the walk, we know a
- *             group element %$x \in G$% together with its representation as
- *             a product of powers of %$g$% and $%a$% (i.e., we know that
- *             %$x = g^\alpha a^\beta$% for some %$\alpha$%, %$\beta$%).
- *
- *             Locating a cycle gives us a collision
- *
- *               %$g^{\alpha} a^{\beta} = g^{\alpha'} a^{\beta'}$%
- *
- *             Taking logs of both sides (to base %$g$%) gives us that
- *
- *               %$\log a\equiv\frac{\alpha-\alpha'}{\beta'-\beta}\bmod{n}$%
- *
- *             Good initial values are %$x = y = 1$% (the multiplicative
- *             identity of %$G$%) and %$\alpha\equiv\beta\equiv0\bmod{n}$%.
- *             If that doesn't work then start choosing more `interesting'
- *             values.
- *
- *             Note that the algorithm requires minimal space but
- *             %$O(\sqrt{n})$% time.  Don't do this on large groups,
- *             particularly if you can find a decent factor base.
- *
- *             Finally, note that this function will free the input values
- *             when it's finished with them.  This probably isn't a great
- *             problem.
- */
-
-extern mp *rho(rho_ctx */*cc*/, void */*x*/, void */*y*/,
-              mp */*a*/, mp */*b*/);
-
-/* --- @rho_prime@ --- *
- *
- * Arguments:  @mp *g@ = generator for the group
- *             @mp *a@ = value to find the logarithm of
- *             @mp *n@ = order of the group
- *             @mp *p@ = prime size of the underlying prime field
- *
- * Returns:    The discrete logarithm %$\log_g a$%.
- *
- * Use:                Computes discrete logarithms in a subgroup of a prime field.
- */
-
-extern mp *rho_prime(mp */*g*/, mp */*a*/, mp */*n*/, mp */*p*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rijndael-base.c b/rijndael-base.c
deleted file mode 100644 (file)
index 5230cbc..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael-base.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Low-level stuff for all Rijndael block sizes
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "rijndael.h"
-#include "rijndael-base.h"
-#include "rijndael-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet rijndael_keysz[] = { KSZ_RANGE, RIJNDAEL_KEYSZ, 4, 32, 4 };
-
-/*----- Constant tables ---------------------------------------------------*/
-
-const octet rijndael_s[256] = RIJNDAEL_S;
-const octet rijndael_si[256] = RIJNDAEL_SI;
-const uint32 rijndael_t[4][256] = RIJNDAEL_T;
-const uint32 rijndael_ti[4][256] = RIJNDAEL_TI;
-const uint32 rijndael_u[4][256] = RIJNDAEL_U;
-const octet rijndael_rcon[] = RIJNDAEL_RCON;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rijndael_setup@ --- *
- *
- * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
- *             @unsigned nb@ = number of words in the block
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Low-level key-scheduling.
- */
-
-void rijndael_setup(rijndael_ctx *k, unsigned nb, const void *buf, size_t sz)
-{
-  unsigned nk, nr, nw;
-  unsigned i, j, jj;
-  const octet *p;
-  uint32 ww;
-
-  /* --- Sort out the key size --- */
-
-  KSZ_ASSERT(rijndael, sz);
-  nk = sz / 4;
-
-  /* --- Select the number of rounds --- */
-
-  nr = (nk > nb ? nk : nb) + 6;
-  if (nr < 10)
-    nr = 10;
-  k->nr = nr;
-
-  /* --- Fetch the first key words out --- */
-
-  p = buf;
-  for (i = 0; i < nk; i++) {
-    k->w[i] = LOAD32_B(p);
-    p += 4;
-  }
-
-  /* --- Expand this material to fill the rest of the table --- */
-
-  nw = (nr + 1) * nb;
-  ww = k->w[i - 1];
-  p = RCON;
-  for (; i < nw; i++) {
-    uint32 w = k->w[i - nk];
-    if (i % nk == 0) {
-      ww = ROL32(ww, 8);
-      w ^= SUB(S, ww, ww, ww, ww) ^ (*p++ << 24);
-    } else if (nk > 6 && i % nk == 4)
-      w ^= SUB(S, ww, ww, ww, ww);
-    else
-      w ^= ww;
-    k->w[i] = ww = w;
-  }
-
-  /* --- Make the decryption keys --- */
-
-  j = nw; i = 0;
-
-  j -= nb; jj = 0;
-  for (; i < nb; i++)
-    k->wi[i] = k->w[j + jj++];
-
-  for (; i < nw - nb; i += nb) {
-    j -= nb;
-    for (jj = 0; jj < nb; jj++) {
-      uint32 w = k->w[j + jj];
-      k->wi[i + jj] = MIX(U, w, w, w, w);
-    }
-  }
-
-  j -= nb; jj = 0;
-  for (; i < nw; i++)
-    k->wi[i] = k->w[j + jj++];
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rijndael-base.h b/rijndael-base.h
deleted file mode 100644 (file)
index e3f168d..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael-base.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Internal header for Rijndael implementation
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_RIJNDAEL_BASE_H
-#define CATACOMB_RIJNDAEL_BASE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Constant tables ---------------------------------------------------*/
-
-extern const octet rijndael_s[256];
-extern const octet rijndael_si[256];
-extern const uint32 rijndael_t[4][256];
-extern const uint32 rijndael_ti[4][256];
-extern const uint32 rijndael_u[4][256];
-extern const octet rijndael_rcon[];
-
-#define S rijndael_s
-#define SI rijndael_si
-#define T rijndael_t
-#define TI rijndael_ti
-#define U rijndael_u
-#define RCON rijndael_rcon
-
-/*----- Handy macros ------------------------------------------------------*/
-
-#define SUB(s, a, b, c, d)                                             \
-  (s[U8((a) >> 24)] << 24 | s[U8((b) >> 16)] << 16 |                   \
-   s[U8((c) >> 8)] <<  8 | s[U8((d) >>  0)] <<  0)
-
-#define MIX(t, a, b, c, d)                                             \
-   (t[0][U8((a) >> 24)] ^ t[1][U8((b) >> 16)] ^                                \
-    t[2][U8((c) >>  8)] ^ t[3][U8((d) >>  0)])
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rijndael-mktab.c b/rijndael-mktab.c
deleted file mode 100644 (file)
index 0ecdfcd..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael-mktab.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Build precomputed tables for the Rijndael block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/bits.h>
-
-/*----- Magic variables ---------------------------------------------------*/
-
-static octet s[256], si[256];
-static uint32 t[4][256], ti[4][256];
-static uint32 u[4][256];
-static octet rc[32];
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mul@ --- *
- *
- * Arguments:  @unsigned x, y@ = polynomials over %$\gf{2^8}$%
- *             @unsigned m@ = modulus
- *
- * Returns:    The product of two polynomials.
- *
- * Use:                Computes a product of polynomials, quite slowly.
- */
-
-static unsigned mul(unsigned x, unsigned y, unsigned m)
-{
-  unsigned a = 0;
-  unsigned i;
-
-  for (i = 0; i < 8; i++) {
-    if (y & 1)
-      a ^= x;
-    y >>= 1;
-    x <<= 1;
-    if (x & 0x100)
-      x ^= m;
-  }
-
-  return (a);
-}
-
-/* --- @sbox@ --- *
- *
- * Build the S-box.
- *
- * This is built from inversion in the multiplicative group of
- * %$\gf{2^8}[x]/(p(x))$%, where %$p(x) = x^8 + x^4 + x^3 + x + 1$%, followed
- * by an affine transformation treating inputs as vectors over %$\gf{2}$%.
- * The result is a horrible function.
- *
- * The inversion is done slightly sneakily, by building log and antilog
- * tables.  Let %$a$% be an element of the finite field.  If the inverse of
- * %$a$% is %$a^{-1}$%, then %$\log a a^{-1} = 0$%.  Hence
- * %$\log a = -\log a^{-1}$%.  This saves fiddling about with Euclidean
- * algorithm.
- */
-
-#define S_MOD 0x11b
-
-static void sbox(void)
-{
-  octet log[256], alog[256];
-  unsigned x;
-  unsigned i;
-  unsigned g;
-
-  /* --- Find a suitable generator, and build log tables --- */
-
-  log[0] = 0;
-  for (g = 2; g < 256; g++) {
-    x = 1;
-    for (i = 0; i < 256; i++) {
-      log[x] = i;
-      alog[i] = x;
-      x = mul(x, g, S_MOD);
-      if (x == 1 && i != 254)
-       goto again;
-    }
-    goto done;
-  again:;
-  }
-  fprintf(stderr, "couldn't find generator\n");
-  exit(EXIT_FAILURE);
-done:;
-
-  /* --- Now grind through and do the affine transform --- *
-   *
-   * The matrix multiply is an AND and a parity op.  The add is an XOR.
-   */
-
-  for (i = 0; i < 256; i++) {
-    unsigned j;
-    unsigned m = 0xf8;
-    unsigned v = i ? alog[255 - log[i]] : 0;
-
-    assert(i == 0 || mul(i, v, S_MOD) == 1);
-
-    x = 0;
-    for (j = 0; j < 8; j++) {
-      unsigned r;
-      r = v & m;
-      r = (r >> 4) ^ r;
-      r = (r >> 2) ^ r;
-      r = (r >> 1) ^ r;
-      x = (x << 1) | (r & 1);
-      m = ROR8(m, 1);
-    }
-    x ^= 0x63;
-    s[i] = x;
-    si[x] = i;
-  }
-}
-
-/* --- @tbox@ --- *
- *
- * Construct the t tables for doing the round function efficiently.
- */
-
-static void tbox(void)
-{
-  unsigned i;
-
-  for (i = 0; i < 256; i++) {
-    uint32 a, b, c, d;
-    uint32 w;
-
-    /* --- Build a forwards t-box entry --- */
-
-    a = s[i];
-    b = a << 1; if (b & 0x100) b ^= S_MOD;
-    c = a ^ b;
-    w = (c << 0) | (a << 8) | (a << 16) | (b << 24);
-    t[0][i] = w;
-    t[1][i] = ROR32(w, 8);
-    t[2][i] = ROR32(w, 16);
-    t[3][i] = ROR32(w, 24);
-
-    /* --- Build a backwards t-box entry --- */
-
-    a = mul(si[i], 0x0e, S_MOD);
-    b = mul(si[i], 0x09, S_MOD);
-    c = mul(si[i], 0x0d, S_MOD);
-    d = mul(si[i], 0x0b, S_MOD);
-    w = (d << 0) | (c << 8) | (b << 16) | (a << 24);
-    ti[0][i] = w;
-    ti[1][i] = ROR32(w, 8);
-    ti[2][i] = ROR32(w, 16);
-    ti[3][i] = ROR32(w, 24);
-  }
-}
-
-/* --- @ubox@ --- *
- *
- * Construct the tables for performing the decryption key schedule.
- */
-
-static void ubox(void)
-{
-  unsigned i;
-
-  for (i = 0; i < 256; i++) {
-    uint32 a, b, c, d;
-    uint32 w;
-    a = mul(i, 0x0e, S_MOD);
-    b = mul(i, 0x09, S_MOD);
-    c = mul(i, 0x0d, S_MOD);
-    d = mul(i, 0x0b, S_MOD);
-    w = (d << 0) | (c << 8) | (b << 16) | (a << 24);
-    u[0][i] = w;
-    u[1][i] = ROR32(w, 8);
-    u[2][i] = ROR32(w, 16);
-    u[3][i] = ROR32(w, 24);
-  }
-}
-
-/* --- Round constants --- */
-
-static void rcon(void)
-{
-  unsigned r = 1;
-  int i;
-
-  for (i = 0; i < sizeof(rc); i++) {
-    rc[i] = r;
-    r <<= 1;
-    if (r & 0x100)
-      r ^= S_MOD;
-  }
-}
-
-/* --- @main@ --- */
-
-int main(void)
-{
-  int i, j;
-
-  puts("\
-/* -*-c-*-\n\
- *\n\
- * Rijndael tables [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_RIJNDAEL_TAB_H\n\
-#define CATACOMB_RIJNDAEL_TAB_H\n\
-");
-
-  /* --- Write out the S-box --- */
-
-  sbox();
-  fputs("\
-/* --- The byte substitution and its inverse --- */\n\
-\n\
-#define RIJNDAEL_S {                                                   \\\n\
-  ", stdout);
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", s[i]);
-    if (i == 255)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  fputs("\
-#define RIJNDAEL_SI {                                                  \\\n\
-  ", stdout);
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", si[i]);
-    if (i == 255)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  /* --- Write out the big t tables --- */
-
-  tbox();
-  fputs("\
-/* --- The big round tables --- */\n\
-\n\
-#define RIJNDAEL_T {                                                   \\\n\
-  { ", stdout);
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("0x%08lx", (unsigned long)t[j][i]);
-      if (i == 255) {
-       if (j == 3)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  fputs("\
-#define RIJNDAEL_TI {                                                  \\\n\
-  { ", stdout);
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("0x%08lx", (unsigned long)ti[j][i]);
-      if (i == 255) {
-       if (j == 3)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  /* --- Write out the big u tables --- */
-
-  ubox();
-  fputs("\
-/* --- The decryption key schedule tables --- */\n\
-\n\
-#define RIJNDAEL_U {                                                   \\\n\
-  { ", stdout);
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("0x%08lx", (unsigned long)u[j][i]);
-      if (i == 255) {
-       if (j == 3)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  /* --- Round constants --- */
-
-  rcon();
-  fputs("\
-/* --- The round constants --- */\n\
-\n\
-#define RIJNDAEL_RCON {                                                        \\\n\
-  ", stdout);
-  for (i = 0; i < sizeof(rc); i++) {
-    printf("0x%02x", rc[i]);
-    if (i == sizeof(rc) - 1)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  /* --- Done --- */
-
-  puts("#endif");
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rijndael.c b/rijndael.c
deleted file mode 100644 (file)
index 9eb5f21..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * The Rijndael block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "rijndael.h"
-#include "rijndael-base.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rijndael_init@ --- *
- *
- * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Rijndael context with a particular key.  This
- *             implementation of Rijndael doesn't impose any particular
- *             limits on the key size except that it must be multiple of 4
- *             bytes long.  256 bits seems sensible, though.
- */
-
-void rijndael_init(rijndael_ctx *k, const void *buf, size_t sz)
-{
-  rijndael_setup(k, RIJNDAEL_BLKSZ / 4, buf, sz);
-}
-
-/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
- *
- * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do {                        \
-  aa = what(t, a, b, c, d) ^ *w++;                                     \
-  bb = what(t, b, c, d, a) ^ *w++;                                     \
-  cc = what(t, c, d, a, b) ^ *w++;                                     \
-  dd = what(t, d, a, b, c) ^ *w++;                                     \
-} while (0)
-
-#define UNDO(what, t, aa, bb, cc, dd, a, b, c, d, w) do {              \
-  aa = what(t, a, d, c, b) ^ *w++;                                     \
-  bb = what(t, b, a, d, c) ^ *w++;                                     \
-  cc = what(t, c, b, a, d) ^ *w++;                                     \
-  dd = what(t, d, c, b, a) ^ *w++;                                     \
-} while (0)
-
-void rijndael_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
-  uint32 aa, bb, cc, dd;
-  const uint32 *w = k->w;
-
-  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
-  aa = a; bb = b; cc = c; dd = d;
-
-  switch (k->nr) {
-    case 14:
-      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-    case 13:
-      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-    case 12:
-      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-    case 11:
-      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-    case 10:
-    default:
-      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-  }
-  DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-}
-
-void rijndael_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
-  uint32 aa, bb, cc, dd;
-  const uint32 *w = k->wi;
-
-  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
-  aa = a; bb = b; cc = c; dd = d;
-
-  switch (k->nr) {
-    case 14:
-      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-    case 13:
-      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-    case 12:
-      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-    case 11:
-      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-    case 10:
-    default:
-      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-  }
-  UNDO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-}
-
-BLKC_TEST(RIJNDAEL, rijndael)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rijndael.h b/rijndael.h
deleted file mode 100644 (file)
index b1ba75f..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The Rijndael block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Rijndael block cipher --------------------------------*
- *
- * Invented by Joan Daemen and Vincent Rijmen, Rijndael is a fast, elegant
- * and relatively simple 128-bit block cipher.  It was chosen by NIST to be
- * the new Advanced Encryption Standard (AES) algorithm.
- *
- * Rijnadel appears to have a low security margin.  I recommend waiting
- * before using Rijndael for any sensitive applications.
- */
-
-#ifndef CATACOMB_RIJNDAEL_H
-#define CATACOMB_RIJNDAEL_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define RIJNDAEL_BLKSZ 16
-#define RIJNDAEL_KEYSZ 32
-#define RIJNDAEL_CLASS (N, B, 128)
-
-extern const octet rijndael_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-#define RIJNDAEL_MAXROUNDS 16
-#define RIJNDAEL_KWORDS ((RIJNDAEL_MAXROUNDS + 1) * 8)
-
-typedef struct rijndael_ctx {
-  unsigned nr;
-  uint32 w[RIJNDAEL_KWORDS];
-  uint32 wi[RIJNDAEL_KWORDS];
-} rijndael_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rijndael_setup@ --- *
- *
- * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
- *             @unsigned nb@ = number of words in the block
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Low-level key-scheduling.  Don't call this directly.
- */
-
-extern void rijndael_setup(rijndael_ctx */*k*/, unsigned /*nb*/,
-                          const void */*buf*/, size_t /*sz*/);
-
-/* --- @rijndael_init@ --- *
- *
- * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Rijndael context with a particular key.  This
- *             implementation of Rijndael doesn't impose any particular
- *             limits on the key size except that it must be multiple of 4
- *             bytes long.  256 bits seems sensible, though.
- */
-
-extern void rijndael_init(rijndael_ctx */*k*/,
-                         const void */*buf*/, size_t /*sz*/);
-
-/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
- *
- * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void rijndael_eblk(const rijndael_ctx */*k*/,
-                         const uint32 */*s*/, uint32 */*dst*/);
-extern void rijndael_dblk(const rijndael_ctx */*k*/,
-                         const uint32 */*s*/, uint32 */*dst*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rijndael192.c b/rijndael192.c
deleted file mode 100644 (file)
index aef5955..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael192.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Rijndael block cipher, 192-bit version
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "rijndael.h"
-#include "rijndael192.h"
-#include "rijndael-base.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rijndael192_init@ --- *
- *
- * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Rijndael context with a particular key.  This
- *             implementation of Rijndael doesn't impose any particular
- *             limits on the key size except that it must be multiple of 4
- *             bytes long.  256 bits seems sensible, though.
- */
-
-void rijndael192_init(rijndael_ctx *k, const void *buf, size_t sz)
-{
-  rijndael_setup(k, RIJNDAEL192_BLKSZ / 4, buf, sz);
-}
-
-/* --- @rijndael192_eblk@, @rijndael192_dblk@ --- *
- *
- * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define DO(what, t, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w) do {  \
-  aa = what(t, a, b, c, d) ^ *w++;                                     \
-  bb = what(t, b, c, d, e) ^ *w++;                                     \
-  cc = what(t, c, d, e, f) ^ *w++;                                     \
-  dd = what(t, d, e, f, a) ^ *w++;                                     \
-  ee = what(t, e, f, a, b) ^ *w++;                                     \
-  ff = what(t, f, a, b, c) ^ *w++;                                     \
-} while (0)
-
-#define UNDO(what, t, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w) do {        \
-  aa = what(t, a, f, e, d) ^ *w++;                                     \
-  bb = what(t, b, a, f, e) ^ *w++;                                     \
-  cc = what(t, c, b, a, f) ^ *w++;                                     \
-  dd = what(t, d, c, b, a) ^ *w++;                                     \
-  ee = what(t, e, d, c, b) ^ *w++;                                     \
-  ff = what(t, f, e, d, c) ^ *w++;                                     \
-} while (0)
-
-void rijndael192_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5];
-  uint32 aa, bb, cc, dd, ee, ff;
-  const uint32 *w = k->w;
-
-  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; e ^= *w++; f ^= *w++;
-  aa = a; bb = b; cc = c; dd = d; ee = e; ff = f;
-
-  switch (k->nr) {
-    case 14:
-      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-    case 13:
-      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-    case 12:
-    default:
-      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-  }
-  DO(SUB, S, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; dst[4] = e; dst[5] = f;
-}
-
-void rijndael192_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5];
-  uint32 aa, bb, cc, dd, ee, ff;
-  const uint32 *w = k->wi;
-
-  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; e ^= *w++; f ^= *w++;
-  aa = a; bb = b; cc = c; dd = d; ee = e; ff = f;
-
-  switch (k->nr) {
-    case 14:
-      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-    case 13:
-      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-    case 12:
-    default:
-      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
-  }
-  UNDO(SUB, SI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; dst[4] = e; dst[5] = f;
-}
-
-BLKC_TEST(RIJNDAEL192, rijndael192)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rijndael192.h b/rijndael192.h
deleted file mode 100644 (file)
index fb3d013..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael192.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Rijndael block cipher, 192-bit version
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_RIJNDAEL192_H
-#define CATACOMB_RIJNDAEL192_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_RIJNDAEL_H
-#  include "rijndael.h"
-#endif
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define RIJNDAEL192_BLKSZ 24
-#define RIJNDAEL192_KEYSZ 32
-#define RIJNDAEL192_CLASS (N, B, 192)
-
-#define rijndael192_keysz rijndael_keysz
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rijndael_ctx rijndael192_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rijndael192_init@ --- *
- *
- * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Rijndael context with a particular key.  This
- *             implementation of Rijndael doesn't impose any particular
- *             limits on the key size except that it must be multiple of 4
- *             bytes long.  256 bits seems sensible, though.
- */
-
-extern void rijndael192_init(rijndael_ctx */*k*/,
-                         const void */*buf*/, size_t /*sz*/);
-
-/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
- *
- * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void rijndael192_eblk(const rijndael_ctx */*k*/,
-                            const uint32 */*s*/, uint32 */*dst*/);
-extern void rijndael192_dblk(const rijndael_ctx */*k*/,
-                            const uint32 */*s*/, uint32 */*dst*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rijndael256.c b/rijndael256.c
deleted file mode 100644 (file)
index 27f06d7..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael256.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Rijndael block cipher, 256-bit version
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "rijndael.h"
-#include "rijndael256.h"
-#include "rijndael-base.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rijndael256_init@ --- *
- *
- * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Rijndael context with a particular key.  This
- *             implementation of Rijndael doesn't impose any particular
- *             limits on the key size except that it must be multiple of 4
- *             bytes long.  256 bits seems sensible, though.
- */
-
-void rijndael256_init(rijndael_ctx *k, const void *buf, size_t sz)
-{
-  rijndael_setup(k, RIJNDAEL256_BLKSZ / 4, buf, sz);
-}
-
-/* --- @rijndael256_eblk@, @rijndael256_dblk@ --- *
- *
- * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define DO(what, t,                                                    \
-          aa, bb, cc, dd, ee, ff, gg, hh,                              \
-          a, b, c, d, e, f, g, h, w) do {                              \
-  aa = what(t, a, b, d, e) ^ *w++;                                     \
-  bb = what(t, b, c, e, f) ^ *w++;                                     \
-  cc = what(t, c, d, f, g) ^ *w++;                                     \
-  dd = what(t, d, e, g, h) ^ *w++;                                     \
-  ee = what(t, e, f, h, a) ^ *w++;                                     \
-  ff = what(t, f, g, a, b) ^ *w++;                                     \
-  gg = what(t, g, h, b, c) ^ *w++;                                     \
-  hh = what(t, h, a, c, d) ^ *w++;                                     \
-} while (0)
-
-#define UNDO(what, t,                                                  \
-            aa, bb, cc, dd, ee, ff, gg, hh,                            \
-            a, b, c, d, e, f, g, h, w) do {                            \
-  aa = what(t, a, h, f, e) ^ *w++;                                     \
-  bb = what(t, b, a, g, f) ^ *w++;                                     \
-  cc = what(t, c, b, h, g) ^ *w++;                                     \
-  dd = what(t, d, c, a, h) ^ *w++;                                     \
-  ee = what(t, e, d, b, a) ^ *w++;                                     \
-  ff = what(t, f, e, c, b) ^ *w++;                                     \
-  gg = what(t, g, f, d, c) ^ *w++;                                     \
-  hh = what(t, h, g, e, d) ^ *w++;                                     \
-} while (0)
-
-void rijndael256_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
-  uint32 e = s[4], f = s[5], g = s[6], h = s[7];
-  uint32 aa, bb, cc, dd, ee, ff, gg, hh;
-  const uint32 *w = k->w;
-
-  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
-  e ^= *w++; f ^= *w++; g ^= *w++; h ^= *w++;
-
-  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  DO(SUB, S, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-  dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h;
-}
-
-void rijndael256_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
-  uint32 e = s[4], f = s[5], g = s[6], h = s[7];
-  uint32 aa, bb, cc, dd, ee, ff, gg, hh;
-  const uint32 *w = k->wi;
-
-  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
-  e ^= *w++; f ^= *w++; g ^= *w++; h ^= *w++;
-
-  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
-  UNDO(SUB, SI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-  dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h;
-}
-
-BLKC_TEST(RIJNDAEL256, rijndael256)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rijndael256.h b/rijndael256.h
deleted file mode 100644 (file)
index 79ab09e..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rijndael256.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Rijndael block cipher, 256-bit version
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_RIJNDAEL256_H
-#define CATACOMB_RIJNDAEL256_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_RIJNDAEL_H
-#  include "rijndael.h"
-#endif
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define RIJNDAEL256_BLKSZ 32
-#define RIJNDAEL256_KEYSZ 32
-#define RIJNDAEL256_CLASS (N, B, 256)
-
-#define rijndael256_keysz rijndael_keysz
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rijndael_ctx rijndael256_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rijndael256_init@ --- *
- *
- * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Rijndael context with a particular key.  This
- *             implementation of Rijndael doesn't impose any particular
- *             limits on the key size except that it must be multiple of 4
- *             bytes long.  256 bits seems sensible, though.
- */
-
-extern void rijndael256_init(rijndael_ctx */*k*/,
-                         const void */*buf*/, size_t /*sz*/);
-
-/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
- *
- * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void rijndael256_eblk(const rijndael_ctx */*k*/,
-                            const uint32 */*s*/, uint32 */*dst*/);
-extern void rijndael256_dblk(const rijndael_ctx */*k*/,
-                            const uint32 */*s*/, uint32 */*dst*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rmd128.c b/rmd128.c
deleted file mode 100644 (file)
index 10f56c4..0000000
--- a/rmd128.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rmd128.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The RIPEMD-128 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "rmd128.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rmd128_compress@ --- *
- *
- * Arguments:  @rmd128_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-128 compression function.
- */
-
-void rmd128_compress(rmd128_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d;
-  uint32 A, B, C, D;
-  uint32 buf[16];
-
-  /* --- Fetch the chaining variables --- */
-
-  a = A = ctx->a;
-  b = B = ctx->b;
-  c = C = ctx->c;
-  d = D = ctx->d;
-
-  /* --- 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) ^ (z))
-#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define H(x, y, z) (((x) | ~(y)) ^ (z))
-#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-
-#define T(w, x, y, z, i, r, f, k) do {                                 \
-  uint32 _t = w + f(x, y, z) + buf[i] + k;                             \
-  w = ROL32(_t, r);                                                    \
-} while (0)
-
-#define F1(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000)
-#define G1(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x5a827999)
-#define H1(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x6ed9eba1)
-#define I1(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x8f1bbcdc)
-
-#define F2(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x50a28be6)
-#define G2(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x5c4dd124)
-#define H2(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x6d703ef3)
-#define I2(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000)
-
-  /* --- First the left hand side --- */
-
-  F1(a, b, c, d,  0, 11);
-  F1(d, a, b, c,  1, 14);
-  F1(c, d, a, b,  2, 15);
-  F1(b, c, d, a,  3, 12);
-  F1(a, b, c, d,  4,  5);
-  F1(d, a, b, c,  5,  8);
-  F1(c, d, a, b,  6,  7);
-  F1(b, c, d, a,  7,  9);
-  F1(a, b, c, d,  8, 11);
-  F1(d, a, b, c,  9, 13);
-  F1(c, d, a, b, 10, 14);
-  F1(b, c, d, a, 11, 15);
-  F1(a, b, c, d, 12,  6);
-  F1(d, a, b, c, 13,  7);
-  F1(c, d, a, b, 14,  9);
-  F1(b, c, d, a, 15,  8);
-
-  G1(a, b, c, d,  7,  7);
-  G1(d, a, b, c,  4,  6);
-  G1(c, d, a, b, 13,  8);
-  G1(b, c, d, a,  1, 13);
-  G1(a, b, c, d, 10, 11);
-  G1(d, a, b, c,  6,  9);
-  G1(c, d, a, b, 15,  7);
-  G1(b, c, d, a,  3, 15);
-  G1(a, b, c, d, 12,  7);
-  G1(d, a, b, c,  0, 12);
-  G1(c, d, a, b,  9, 15);
-  G1(b, c, d, a,  5,  9);
-  G1(a, b, c, d,  2, 11);
-  G1(d, a, b, c, 14,  7);
-  G1(c, d, a, b, 11, 13);
-  G1(b, c, d, a,  8, 12);
-
-  H1(a, b, c, d,  3, 11);
-  H1(d, a, b, c, 10, 13);
-  H1(c, d, a, b, 14,  6);
-  H1(b, c, d, a,  4,  7);
-  H1(a, b, c, d,  9, 14);
-  H1(d, a, b, c, 15,  9);
-  H1(c, d, a, b,  8, 13);
-  H1(b, c, d, a,  1, 15);
-  H1(a, b, c, d,  2, 14);
-  H1(d, a, b, c,  7,  8);
-  H1(c, d, a, b,  0, 13);
-  H1(b, c, d, a,  6,  6);
-  H1(a, b, c, d, 13,  5);
-  H1(d, a, b, c, 11, 12);
-  H1(c, d, a, b,  5,  7);
-  H1(b, c, d, a, 12,  5);
-
-  I1(a, b, c, d,  1, 11);
-  I1(d, a, b, c,  9, 12);
-  I1(c, d, a, b, 11, 14);
-  I1(b, c, d, a, 10, 15);
-  I1(a, b, c, d,  0, 14);
-  I1(d, a, b, c,  8, 15);
-  I1(c, d, a, b, 12,  9);
-  I1(b, c, d, a,  4,  8);
-  I1(a, b, c, d, 13,  9);
-  I1(d, a, b, c,  3, 14);
-  I1(c, d, a, b,  7,  5);
-  I1(b, c, d, a, 15,  6);
-  I1(a, b, c, d, 14,  8);
-  I1(d, a, b, c,  5,  6);
-  I1(c, d, a, b,  6,  5);
-  I1(b, c, d, a,  2, 12);
-
-  /* --- And then the right hand side --- */
-
-  F2(A, B, C, D,  5,  8);
-  F2(D, A, B, C, 14,  9);
-  F2(C, D, A, B,  7,  9);
-  F2(B, C, D, A,  0, 11);
-  F2(A, B, C, D,  9, 13);
-  F2(D, A, B, C,  2, 15);
-  F2(C, D, A, B, 11, 15);
-  F2(B, C, D, A,  4,  5);
-  F2(A, B, C, D, 13,  7);
-  F2(D, A, B, C,  6,  7);
-  F2(C, D, A, B, 15,  8);
-  F2(B, C, D, A,  8, 11);
-  F2(A, B, C, D,  1, 14);
-  F2(D, A, B, C, 10, 14);
-  F2(C, D, A, B,  3, 12);
-  F2(B, C, D, A, 12,  6);
-
-  G2(A, B, C, D,  6,  9);
-  G2(D, A, B, C, 11, 13);
-  G2(C, D, A, B,  3, 15);
-  G2(B, C, D, A,  7,  7);
-  G2(A, B, C, D,  0, 12);
-  G2(D, A, B, C, 13,  8);
-  G2(C, D, A, B,  5,  9);
-  G2(B, C, D, A, 10, 11);
-  G2(A, B, C, D, 14,  7);
-  G2(D, A, B, C, 15,  7);
-  G2(C, D, A, B,  8, 12);
-  G2(B, C, D, A, 12,  7);
-  G2(A, B, C, D,  4,  6);
-  G2(D, A, B, C,  9, 15);
-  G2(C, D, A, B,  1, 13);
-  G2(B, C, D, A,  2, 11);
-
-  H2(A, B, C, D, 15,  9);
-  H2(D, A, B, C,  5,  7);
-  H2(C, D, A, B,  1, 15);
-  H2(B, C, D, A,  3, 11);
-  H2(A, B, C, D,  7,  8);
-  H2(D, A, B, C, 14,  6);
-  H2(C, D, A, B,  6,  6);
-  H2(B, C, D, A,  9, 14);
-  H2(A, B, C, D, 11, 12);
-  H2(D, A, B, C,  8, 13);
-  H2(C, D, A, B, 12,  5);
-  H2(B, C, D, A,  2, 14);
-  H2(A, B, C, D, 10, 13);
-  H2(D, A, B, C,  0, 13);
-  H2(C, D, A, B,  4,  7);
-  H2(B, C, D, A, 13,  5);
-
-  I2(A, B, C, D,  8, 15);
-  I2(D, A, B, C,  6,  5);
-  I2(C, D, A, B,  4,  8);
-  I2(B, C, D, A,  1, 11);
-  I2(A, B, C, D,  3, 14);
-  I2(D, A, B, C, 11, 14);
-  I2(C, D, A, B, 15,  6);
-  I2(B, C, D, A,  0, 14);
-  I2(A, B, C, D,  5,  6);
-  I2(D, A, B, C, 12,  9);
-  I2(C, D, A, B,  2, 12);
-  I2(B, C, D, A, 13,  9);
-  I2(A, B, C, D,  9, 12);
-  I2(D, A, B, C,  7,  5);
-  I2(C, D, A, B, 10, 15);
-  I2(B, C, D, A, 14,  8);
-
-  /* --- Recombine the two halves --- */
-
-  {
-    uint32
-       tmp = ctx->b + c + D;
-    ctx->b = ctx->c + d + A;
-    ctx->c = ctx->d + a + B;
-    ctx->d = ctx->a + b + C;
-    ctx->a = tmp;
-  }
-}
-
-/* --- @rmd128_init@ --- *
- *
- * Arguments:  @rmd128_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void rmd128_init(rmd128_ctx *ctx)
-{
-  ctx->a = 0x67452301;
-  ctx->b = 0xefcdab89;
-  ctx->c = 0x98badcfe;
-  ctx->d = 0x10325476;
-  ctx->off = 0;
-  ctx->nl = ctx->nh = 0;
-}
-
-/* --- @rmd128_set@ --- *
- *
- * Arguments:  @rmd128_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 rmd128_set(rmd128_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->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @rmd128_hash@ --- *
- *
- * Arguments:  @rmd128_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 rmd128_hash(rmd128_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(RMD128, rmd128, ctx, buf, sz);
-}
-
-/* --- @rmd128_done@ --- *
- *
- * Arguments:  @rmd128_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void rmd128_done(rmd128_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  HASH_MD5STRENGTH(RMD128, rmd128, 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);
-}
-
-/* --- @rmd128_state@ --- *
- *
- * Arguments:  @rmd128_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 @rmd128_set@.
- */
-
-unsigned long rmd128_state(rmd128_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);
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(RMD128, rmd128)
-
-/* --- Test code --- */
-
-HASH_TEST(RMD128, rmd128)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rmd128.h b/rmd128.h
deleted file mode 100644 (file)
index b121e3c..0000000
--- a/rmd128.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rmd128.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The RIPEMD-128 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Notes on the RIPEMD-128 hash function -----------------------------*
- *
- * RIPEMD-128 was invented by Hans Dobbertin, Antoon Bosselaers and Bart
- * Preneel, as a drop-in replacement for MD5 (with the same sized output).
- * It's a cut-down version of RIPEMD-160, which should be used in preference.
- */
-
-#ifndef CATACOMB_RMD128_H
-#define CATACOMB_RMD128_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define RMD128_BUFSZ 64
-#define RMD128_HASHSZ 16
-#define RMD128_STATESZ 16
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rmd128_ctx {
-  uint32 a, b, c, d;                   /* Chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[RMD128_BUFSZ];             /* Accumulation buffer */
-} rmd128_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rmd128_compress@ --- *
- *
- * Arguments:  @rmd128_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-128 compression function.
- */
-
-extern void rmd128_compress(rmd128_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @rmd128_init@ --- *
- *
- * Arguments:  @rmd128_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void rmd128_init(rmd128_ctx */*ctx*/);
-
-/* --- @rmd128_set@ --- *
- *
- * Arguments:  @rmd128_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 rmd128_set(rmd128_ctx */*ctx*/,
-                      const void */*buf*/, unsigned long /*count*/);
-
-/* --- @rmd128_hash@ --- *
- *
- * Arguments:  @rmd128_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 rmd128_hash(rmd128_ctx */*ctx*/,
-                       const void */*buf*/, size_t /*sz*/);
-
-/* --- @rmd128_done@ --- *
- *
- * Arguments:  @rmd128_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 rmd128_done(rmd128_ctx */*ctx*/, void */*hash*/);
-
-/* --- @rmd128_state@ --- *
- *
- * Arguments:  @rmd128_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 @rmd128_set@.
- */
-
-extern unsigned long rmd128_state(rmd128_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash rmd128;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rmd160.c b/rmd160.c
deleted file mode 100644 (file)
index f481209..0000000
--- a/rmd160.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rmd160.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The RIPEMD-160 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "rmd160.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rmd160_compress@ --- *
- *
- * Arguments:  @rmd160_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-160 compression function.
- */
-
-void rmd160_compress(rmd160_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d, e;
-  uint32 A, B, C, D, E;
-  uint32 buf[16];
-
-  /* --- Fetch the chaining variables --- */
-
-  a = A = ctx->a;
-  b = B = ctx->b;
-  c = C = ctx->c;
-  d = D = ctx->d;
-  e = 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) ^ (z))
-#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define H(x, y, z) (((x) | ~(y)) ^ (z))
-#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define J(x, y, z) ((x) ^ ((y) | ~(z)))
-
-#define T(v, w, x, y, z, i, r, f, k) do {                              \
-  uint32 _t = v + f(w, x, y) + buf[i] + k;                             \
-  v = ROL32(_t, r) + z; x = ROL32(x, 10);                              \
-} while (0)
-
-#define F1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000)
-#define G1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x5a827999)
-#define H1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6ed9eba1)
-#define I1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x8f1bbcdc)
-#define J1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0xa953fd4e)
-
-#define F2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0x50a28be6)
-#define G2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x5c4dd124)
-#define H2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6d703ef3)
-#define I2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x7a6d76e9)
-#define J2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000)
-
-  /* --- First the left hand side --- */
-
-  F1(a, b, c, d, e,  0, 11);
-  F1(e, a, b, c, d,  1, 14);
-  F1(d, e, a, b, c,  2, 15);
-  F1(c, d, e, a, b,  3, 12);
-  F1(b, c, d, e, a,  4,         5);
-  F1(a, b, c, d, e,  5,         8);
-  F1(e, a, b, c, d,  6,         7);
-  F1(d, e, a, b, c,  7,         9);
-  F1(c, d, e, a, b,  8, 11);
-  F1(b, c, d, e, a,  9, 13);
-  F1(a, b, c, d, e, 10, 14);
-  F1(e, a, b, c, d, 11, 15);
-  F1(d, e, a, b, c, 12,         6);
-  F1(c, d, e, a, b, 13,         7);
-  F1(b, c, d, e, a, 14,         9);
-  F1(a, b, c, d, e, 15,         8);
-
-  G1(e, a, b, c, d,  7,         7);
-  G1(d, e, a, b, c,  4,         6);
-  G1(c, d, e, a, b, 13,         8);
-  G1(b, c, d, e, a,  1,        13);
-  G1(a, b, c, d, e, 10,        11);
-  G1(e, a, b, c, d,  6,         9);
-  G1(d, e, a, b, c, 15,         7);
-  G1(c, d, e, a, b,  3,        15);
-  G1(b, c, d, e, a, 12,         7);
-  G1(a, b, c, d, e,  0,        12);
-  G1(e, a, b, c, d,  9,        15);
-  G1(d, e, a, b, c,  5,         9);
-  G1(c, d, e, a, b,  2,        11);
-  G1(b, c, d, e, a, 14,         7);
-  G1(a, b, c, d, e, 11,        13);
-  G1(e, a, b, c, d,  8,        12);
-
-  H1(d, e, a, b, c,  3,        11);
-  H1(c, d, e, a, b, 10,        13);
-  H1(b, c, d, e, a, 14,         6);
-  H1(a, b, c, d, e,  4,         7);
-  H1(e, a, b, c, d,  9,        14);
-  H1(d, e, a, b, c, 15,         9);
-  H1(c, d, e, a, b,  8,        13);
-  H1(b, c, d, e, a,  1,        15);
-  H1(a, b, c, d, e,  2,        14);
-  H1(e, a, b, c, d,  7,         8);
-  H1(d, e, a, b, c,  0,        13);
-  H1(c, d, e, a, b,  6,         6);
-  H1(b, c, d, e, a, 13,         5);
-  H1(a, b, c, d, e, 11,        12);
-  H1(e, a, b, c, d,  5,         7);
-  H1(d, e, a, b, c, 12,         5);
-
-  I1(c, d, e, a, b,  1,        11);
-  I1(b, c, d, e, a,  9,        12);
-  I1(a, b, c, d, e, 11,        14);
-  I1(e, a, b, c, d, 10,        15);
-  I1(d, e, a, b, c,  0,        14);
-  I1(c, d, e, a, b,  8,        15);
-  I1(b, c, d, e, a, 12,         9);
-  I1(a, b, c, d, e,  4,         8);
-  I1(e, a, b, c, d, 13,         9);
-  I1(d, e, a, b, c,  3,        14);
-  I1(c, d, e, a, b,  7,         5);
-  I1(b, c, d, e, a, 15,         6);
-  I1(a, b, c, d, e, 14,         8);
-  I1(e, a, b, c, d,  5,         6);
-  I1(d, e, a, b, c,  6,         5);
-  I1(c, d, e, a, b,  2,        12);
-
-  J1(b, c, d, e, a,  4,         9);
-  J1(a, b, c, d, e,  0,        15);
-  J1(e, a, b, c, d,  5,         5);
-  J1(d, e, a, b, c,  9,        11);
-  J1(c, d, e, a, b,  7,         6);
-  J1(b, c, d, e, a, 12,         8);
-  J1(a, b, c, d, e,  2,        13);
-  J1(e, a, b, c, d, 10,        12);
-  J1(d, e, a, b, c, 14,         5);
-  J1(c, d, e, a, b,  1,        12);
-  J1(b, c, d, e, a,  3,        13);
-  J1(a, b, c, d, e,  8,        14);
-  J1(e, a, b, c, d, 11,        11);
-  J1(d, e, a, b, c,  6,         8);
-  J1(c, d, e, a, b, 15,         5);
-  J1(b, c, d, e, a, 13,         6);
-
-  /* --- And then the right hand side --- */
-
-  F2(A, B, C, D, E,  5,         8);
-  F2(E, A, B, C, D, 14,         9);
-  F2(D, E, A, B, C,  7,         9);
-  F2(C, D, E, A, B,  0,        11);
-  F2(B, C, D, E, A,  9,        13);
-  F2(A, B, C, D, E,  2,        15);
-  F2(E, A, B, C, D, 11,        15);
-  F2(D, E, A, B, C,  4,         5);
-  F2(C, D, E, A, B, 13,         7);
-  F2(B, C, D, E, A,  6,         7);
-  F2(A, B, C, D, E, 15,         8);
-  F2(E, A, B, C, D,  8,        11);
-  F2(D, E, A, B, C,  1,        14);
-  F2(C, D, E, A, B, 10,        14);
-  F2(B, C, D, E, A,  3,        12);
-  F2(A, B, C, D, E, 12,         6);
-
-  G2(E, A, B, C, D,  6,         9);
-  G2(D, E, A, B, C, 11,        13);
-  G2(C, D, E, A, B,  3,        15);
-  G2(B, C, D, E, A,  7,         7);
-  G2(A, B, C, D, E,  0,        12);
-  G2(E, A, B, C, D, 13,         8);
-  G2(D, E, A, B, C,  5,         9);
-  G2(C, D, E, A, B, 10,        11);
-  G2(B, C, D, E, A, 14,         7);
-  G2(A, B, C, D, E, 15,         7);
-  G2(E, A, B, C, D,  8,        12);
-  G2(D, E, A, B, C, 12,         7);
-  G2(C, D, E, A, B,  4,         6);
-  G2(B, C, D, E, A,  9,        15);
-  G2(A, B, C, D, E,  1,        13);
-  G2(E, A, B, C, D,  2,        11);
-
-  H2(D, E, A, B, C, 15,         9);
-  H2(C, D, E, A, B,  5,         7);
-  H2(B, C, D, E, A,  1,        15);
-  H2(A, B, C, D, E,  3,        11);
-  H2(E, A, B, C, D,  7,         8);
-  H2(D, E, A, B, C, 14,         6);
-  H2(C, D, E, A, B,  6,         6);
-  H2(B, C, D, E, A,  9,        14);
-  H2(A, B, C, D, E, 11,        12);
-  H2(E, A, B, C, D,  8,        13);
-  H2(D, E, A, B, C, 12,         5);
-  H2(C, D, E, A, B,  2,        14);
-  H2(B, C, D, E, A, 10,        13);
-  H2(A, B, C, D, E,  0,        13);
-  H2(E, A, B, C, D,  4,         7);
-  H2(D, E, A, B, C, 13,         5);
-
-  I2(C, D, E, A, B,  8,        15);
-  I2(B, C, D, E, A,  6,         5);
-  I2(A, B, C, D, E,  4,         8);
-  I2(E, A, B, C, D,  1,        11);
-  I2(D, E, A, B, C,  3,        14);
-  I2(C, D, E, A, B, 11,        14);
-  I2(B, C, D, E, A, 15,         6);
-  I2(A, B, C, D, E,  0,        14);
-  I2(E, A, B, C, D,  5,         6);
-  I2(D, E, A, B, C, 12,         9);
-  I2(C, D, E, A, B,  2,        12);
-  I2(B, C, D, E, A, 13,         9);
-  I2(A, B, C, D, E,  9,        12);
-  I2(E, A, B, C, D,  7,         5);
-  I2(D, E, A, B, C, 10,        15);
-  I2(C, D, E, A, B, 14,         8);
-
-  J2(B, C, D, E, A, 12,         8);
-  J2(A, B, C, D, E, 15,         5);
-  J2(E, A, B, C, D, 10,        12);
-  J2(D, E, A, B, C,  4,         9);
-  J2(C, D, E, A, B,  1,        12);
-  J2(B, C, D, E, A,  5,         5);
-  J2(A, B, C, D, E,  8,        14);
-  J2(E, A, B, C, D,  7,         6);
-  J2(D, E, A, B, C,  6,         8);
-  J2(C, D, E, A, B,  2,        13);
-  J2(B, C, D, E, A, 13,         6);
-  J2(A, B, C, D, E, 14,         5);
-  J2(E, A, B, C, D,  0,        15);
-  J2(D, E, A, B, C,  3,        13);
-  J2(C, D, E, A, B,  9,        11);
-  J2(B, C, D, E, A, 11,        11);
-
-  /* --- Recombine the two halves --- */
-
-  {
-    uint32
-       tmp = ctx->b + c + D;
-    ctx->b = ctx->c + d + E;
-    ctx->c = ctx->d + e + A;
-    ctx->d = ctx->e + a + B;
-    ctx->e = ctx->a + b + C;
-    ctx->a = tmp;
-  }
-}
-
-/* --- @rmd160_init@ --- *
- *
- * Arguments:  @rmd160_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void rmd160_init(rmd160_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;
-}
-
-/* --- @rmd160_set@ --- *
- *
- * Arguments:  @rmd160_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 rmd160_set(rmd160_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);
-}
-
-/* --- @rmd160_hash@ --- *
- *
- * Arguments:  @rmd160_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 rmd160_hash(rmd160_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(RMD160, rmd160, ctx, buf, sz);
-}
-
-/* --- @rmd160_done@ --- *
- *
- * Arguments:  @rmd160_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void rmd160_done(rmd160_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  HASH_MD5STRENGTH(RMD160, rmd160, 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);
-}
-
-/* --- @rmd160_state@ --- *
- *
- * Arguments:  @rmd160_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 @rmd160_set@.
- */
-
-unsigned long rmd160_state(rmd160_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(RMD160, rmd160)
-
-/* --- Test code --- */
-
-HASH_TEST(RMD160, rmd160)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rmd160.h b/rmd160.h
deleted file mode 100644 (file)
index f97a462..0000000
--- a/rmd160.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rmd160.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * The RIPEMD-160 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Notes on the RIPEMD-160 hash function -----------------------------*
- *
- * RIPEMD-160 was invented by Hans Dobbertin, Antoon Bosselaers and Bart
- * Preneel.  It's a strengthened version of the original RIPEMD hash
- * function, fixing a vulnerability discovered by Hans Dobbertin.  The
- * RIPEMD-160 design team appears well respected in the cryptographic
- * community.  The author finds them more plausible than SHA-1, which is the
- * best alternative hash function.
- */
-
-#ifndef CATACOMB_RMD160_H
-#define CATACOMB_RMD160_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define RMD160_BUFSZ 64
-#define RMD160_HASHSZ 20
-#define RMD160_STATESZ 20
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rmd160_ctx {
-  uint32 a, b, c, d, e;                        /* Chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[RMD160_BUFSZ];             /* Accumulation buffer */
-} rmd160_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rmd160_compress@ --- *
- *
- * Arguments:  @rmd160_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-160 compression function.
- */
-
-extern void rmd160_compress(rmd160_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @rmd160_init@ --- *
- *
- * Arguments:  @rmd160_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void rmd160_init(rmd160_ctx */*ctx*/);
-
-/* --- @rmd160_set@ --- *
- *
- * Arguments:  @rmd160_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 rmd160_set(rmd160_ctx */*ctx*/,
-                      const void */*buf*/, unsigned long /*count*/);
-
-/* --- @rmd160_hash@ --- *
- *
- * Arguments:  @rmd160_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 rmd160_hash(rmd160_ctx */*ctx*/,
-                       const void */*buf*/, size_t /*sz*/);
-
-/* --- @rmd160_done@ --- *
- *
- * Arguments:  @rmd160_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 rmd160_done(rmd160_ctx */*ctx*/, void */*hash*/);
-
-/* --- @rmd160_state@ --- *
- *
- * Arguments:  @rmd160_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 @rmd160_set@.
- */
-
-extern unsigned long rmd160_state(rmd160_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash rmd160;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rmd256.c b/rmd256.c
deleted file mode 100644 (file)
index e2fc70a..0000000
--- a/rmd256.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rmd256.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The RIPEMD-256 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "rmd256.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rmd256_compress@ --- *
- *
- * Arguments:  @rmd256_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-256 compression function.
- */
-
-void rmd256_compress(rmd256_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d;
-  uint32 A, B, C, D;
-  uint32 buf[16];
-
-  /* --- Fetch the chaining variables --- */
-
-  a = ctx->a;
-  b = ctx->b;
-  c = ctx->c;
-  d = ctx->d;
-  A = ctx->A;
-  B = ctx->B;
-  C = ctx->C;
-  D = ctx->D;
-
-  /* --- 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) ^ (z))
-#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define H(x, y, z) (((x) | ~(y)) ^ (z))
-#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-
-#define T(w, x, y, z, i, r, f, k) do {                                 \
-  uint32 _t = w + f(x, y, z) + buf[i] + k;                             \
-  w = ROL32(_t, r);                                                    \
-} while (0)
-
-#define F1(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000)
-#define G1(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x5a827999)
-#define H1(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x6ed9eba1)
-#define I1(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x8f1bbcdc)
-
-#define F2(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x50a28be6)
-#define G2(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x5c4dd124)
-#define H2(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x6d703ef3)
-#define I2(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000)
-
-  /* --- We must do both sides together --- */
-
-  F1(a, b, c, d,  0, 11);
-  F1(d, a, b, c,  1, 14);
-  F1(c, d, a, b,  2, 15);
-  F1(b, c, d, a,  3, 12);
-  F1(a, b, c, d,  4,  5);
-  F1(d, a, b, c,  5,  8);
-  F1(c, d, a, b,  6,  7);
-  F1(b, c, d, a,  7,  9);
-  F1(a, b, c, d,  8, 11);
-  F1(d, a, b, c,  9, 13);
-  F1(c, d, a, b, 10, 14);
-  F1(b, c, d, a, 11, 15);
-  F1(a, b, c, d, 12,  6);
-  F1(d, a, b, c, 13,  7);
-  F1(c, d, a, b, 14,  9);
-  F1(b, c, d, a, 15,  8);
-
-  F2(A, B, C, D,  5,  8);
-  F2(D, A, B, C, 14,  9);
-  F2(C, D, A, B,  7,  9);
-  F2(B, C, D, A,  0, 11);
-  F2(A, B, C, D,  9, 13);
-  F2(D, A, B, C,  2, 15);
-  F2(C, D, A, B, 11, 15);
-  F2(B, C, D, A,  4,  5);
-  F2(A, B, C, D, 13,  7);
-  F2(D, A, B, C,  6,  7);
-  F2(C, D, A, B, 15,  8);
-  F2(B, C, D, A,  8, 11);
-  F2(A, B, C, D,  1, 14);
-  F2(D, A, B, C, 10, 14);
-  F2(C, D, A, B,  3, 12);
-  F2(B, C, D, A, 12,  6);
-
-  G1(A, b, c, d,  7,  7);
-  G1(d, A, b, c,  4,  6);
-  G1(c, d, A, b, 13,  8);
-  G1(b, c, d, A,  1, 13);
-  G1(A, b, c, d, 10, 11);
-  G1(d, A, b, c,  6,  9);
-  G1(c, d, A, b, 15,  7);
-  G1(b, c, d, A,  3, 15);
-  G1(A, b, c, d, 12,  7);
-  G1(d, A, b, c,  0, 12);
-  G1(c, d, A, b,  9, 15);
-  G1(b, c, d, A,  5,  9);
-  G1(A, b, c, d,  2, 11);
-  G1(d, A, b, c, 14,  7);
-  G1(c, d, A, b, 11, 13);
-  G1(b, c, d, A,  8, 12);
-
-  G2(a, B, C, D,  6,  9);
-  G2(D, a, B, C, 11, 13);
-  G2(C, D, a, B,  3, 15);
-  G2(B, C, D, a,  7,  7);
-  G2(a, B, C, D,  0, 12);
-  G2(D, a, B, C, 13,  8);
-  G2(C, D, a, B,  5,  9);
-  G2(B, C, D, a, 10, 11);
-  G2(a, B, C, D, 14,  7);
-  G2(D, a, B, C, 15,  7);
-  G2(C, D, a, B,  8, 12);
-  G2(B, C, D, a, 12,  7);
-  G2(a, B, C, D,  4,  6);
-  G2(D, a, B, C,  9, 15);
-  G2(C, D, a, B,  1, 13);
-  G2(B, C, D, a,  2, 11);
-
-  H1(A, B, c, d,  3, 11);
-  H1(d, A, B, c, 10, 13);
-  H1(c, d, A, B, 14,  6);
-  H1(B, c, d, A,  4,  7);
-  H1(A, B, c, d,  9, 14);
-  H1(d, A, B, c, 15,  9);
-  H1(c, d, A, B,  8, 13);
-  H1(B, c, d, A,  1, 15);
-  H1(A, B, c, d,  2, 14);
-  H1(d, A, B, c,  7,  8);
-  H1(c, d, A, B,  0, 13);
-  H1(B, c, d, A,  6,  6);
-  H1(A, B, c, d, 13,  5);
-  H1(d, A, B, c, 11, 12);
-  H1(c, d, A, B,  5,  7);
-  H1(B, c, d, A, 12,  5);
-
-  H2(a, b, C, D, 15,  9);
-  H2(D, a, b, C,  5,  7);
-  H2(C, D, a, b,  1, 15);
-  H2(b, C, D, a,  3, 11);
-  H2(a, b, C, D,  7,  8);
-  H2(D, a, b, C, 14,  6);
-  H2(C, D, a, b,  6,  6);
-  H2(b, C, D, a,  9, 14);
-  H2(a, b, C, D, 11, 12);
-  H2(D, a, b, C,  8, 13);
-  H2(C, D, a, b, 12,  5);
-  H2(b, C, D, a,  2, 14);
-  H2(a, b, C, D, 10, 13);
-  H2(D, a, b, C,  0, 13);
-  H2(C, D, a, b,  4,  7);
-  H2(b, C, D, a, 13,  5);
-
-  I1(A, B, C, d,  1, 11);
-  I1(d, A, B, C,  9, 12);
-  I1(C, d, A, B, 11, 14);
-  I1(B, C, d, A, 10, 15);
-  I1(A, B, C, d,  0, 14);
-  I1(d, A, B, C,  8, 15);
-  I1(C, d, A, B, 12,  9);
-  I1(B, C, d, A,  4,  8);
-  I1(A, B, C, d, 13,  9);
-  I1(d, A, B, C,  3, 14);
-  I1(C, d, A, B,  7,  5);
-  I1(B, C, d, A, 15,  6);
-  I1(A, B, C, d, 14,  8);
-  I1(d, A, B, C,  5,  6);
-  I1(C, d, A, B,  6,  5);
-  I1(B, C, d, A,  2, 12);
-
-  I2(a, b, c, D,  8, 15);
-  I2(D, a, b, c,  6,  5);
-  I2(c, D, a, b,  4,  8);
-  I2(b, c, D, a,  1, 11);
-  I2(a, b, c, D,  3, 14);
-  I2(D, a, b, c, 11, 14);
-  I2(c, D, a, b, 15,  6);
-  I2(b, c, D, a,  0, 14);
-  I2(a, b, c, D,  5,  6);
-  I2(D, a, b, c, 12,  9);
-  I2(c, D, a, b,  2, 12);
-  I2(b, c, D, a, 13,  9);
-  I2(a, b, c, D,  9, 12);
-  I2(D, a, b, c,  7,  5);
-  I2(c, D, a, b, 10, 15);
-  I2(b, c, D, a, 14,  8);
-
-  /* --- Recombine the two halves --- */
-
-  ctx->a += A;
-  ctx->b += B;
-  ctx->c += C;
-  ctx->d += D;
-  ctx->A += a;
-  ctx->B += b;
-  ctx->C += c;
-  ctx->D += d;
-}
-
-/* --- @rmd256_init@ --- *
- *
- * Arguments:  @rmd256_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void rmd256_init(rmd256_ctx *ctx)
-{
-  ctx->a = 0x67452301;
-  ctx->b = 0xefcdab89;
-  ctx->c = 0x98badcfe;
-  ctx->d = 0x10325476;
-  ctx->A = 0x76543210;
-  ctx->B = 0xfedcba98;
-  ctx->C = 0x89abcdef;
-  ctx->D = 0x01234567;
-  ctx->off = 0;
-  ctx->nl = ctx->nh = 0;
-}
-
-/* --- @rmd256_set@ --- *
- *
- * Arguments:  @rmd256_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 rmd256_set(rmd256_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->A = LOAD32_L(p + 16);
-  ctx->B = LOAD32_L(p + 20);
-  ctx->C = LOAD32_L(p + 24);
-  ctx->D = LOAD32_L(p + 28);
-  ctx->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @rmd256_hash@ --- *
- *
- * Arguments:  @rmd256_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 rmd256_hash(rmd256_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(RMD256, rmd256, ctx, buf, sz);
-}
-
-/* --- @rmd256_done@ --- *
- *
- * Arguments:  @rmd256_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void rmd256_done(rmd256_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  HASH_MD5STRENGTH(RMD256, rmd256, 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->A);
-  STORE32_L(p + 20, ctx->B);
-  STORE32_L(p + 24, ctx->C);
-  STORE32_L(p + 28, ctx->D);
-}
-
-/* --- @rmd256_state@ --- *
- *
- * Arguments:  @rmd256_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 @rmd256_set@.
- */
-
-unsigned long rmd256_state(rmd256_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->A);
-  STORE32_L(p + 20, ctx->B);
-  STORE32_L(p + 24, ctx->C);
-  STORE32_L(p + 28, ctx->D);
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(RMD256, rmd256)
-
-/* --- Test code --- */
-
-HASH_TEST(RMD256, rmd256)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rmd256.h b/rmd256.h
deleted file mode 100644 (file)
index aa1e883..0000000
--- a/rmd256.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rmd256.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The RIPEMD-256 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Notes on the RIPEMD-256 hash function -----------------------------*
- *
- * RIPEMD-256 was invented by Hans Dobbertin, Antoon Bosselaers and Bart
- * Preneel.  It's a double-width version of RIPEMD-128, constructed simply by
- * not gluing together the two parallel computations which RIPEMD-128 usually
- * does in its compression function.  The authors warn that, while its output
- * is twice as wide as that of RIPEMD-128, they don't expect it to offer any
- * more security.
- */
-
-#ifndef CATACOMB_RMD256_H
-#define CATACOMB_RMD256_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define RMD256_BUFSZ 64
-#define RMD256_HASHSZ 32
-#define RMD256_STATESZ 32
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rmd256_ctx {
-  uint32 a, b, c, d;                   /* Chaining variables */
-  uint32 A, B, C, D;                   /* More chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[RMD256_BUFSZ];             /* Accumulation buffer */
-} rmd256_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rmd256_compress@ --- *
- *
- * Arguments:  @rmd256_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-256 compression function.
- */
-
-extern void rmd256_compress(rmd256_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @rmd256_init@ --- *
- *
- * Arguments:  @rmd256_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void rmd256_init(rmd256_ctx */*ctx*/);
-
-/* --- @rmd256_set@ --- *
- *
- * Arguments:  @rmd256_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 rmd256_set(rmd256_ctx */*ctx*/,
-                      const void */*buf*/, unsigned long /*count*/);
-
-/* --- @rmd256_hash@ --- *
- *
- * Arguments:  @rmd256_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 rmd256_hash(rmd256_ctx */*ctx*/,
-                       const void */*buf*/, size_t /*sz*/);
-
-/* --- @rmd256_done@ --- *
- *
- * Arguments:  @rmd256_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 rmd256_done(rmd256_ctx */*ctx*/, void */*hash*/);
-
-/* --- @rmd256_state@ --- *
- *
- * Arguments:  @rmd256_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 @rmd256_set@.
- */
-
-extern unsigned long rmd256_state(rmd256_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash rmd256;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rmd320.c b/rmd320.c
deleted file mode 100644 (file)
index a91f874..0000000
--- a/rmd320.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rmd320.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The RIPEMD-320 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "rmd320.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rmd320_compress@ --- *
- *
- * Arguments:  @rmd320_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-320 compression function.
- */
-
-void rmd320_compress(rmd320_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d, e;
-  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;
-
-  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) ^ (z))
-#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define H(x, y, z) (((x) | ~(y)) ^ (z))
-#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define J(x, y, z) ((x) ^ ((y) | ~(z)))
-
-#define T(v, w, x, y, z, i, r, f, k) do {                              \
-  uint32 _t = v + f(w, x, y) + buf[i] + k;                             \
-  v = ROL32(_t, r) + z; x = ROL32(x, 10);                              \
-} while (0)
-
-#define F1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000)
-#define G1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x5a827999)
-#define H1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6ed9eba1)
-#define I1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x8f1bbcdc)
-#define J1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0xa953fd4e)
-
-#define F2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0x50a28be6)
-#define G2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x5c4dd124)
-#define H2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6d703ef3)
-#define I2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x7a6d76e9)
-#define J2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000)
-
-  /* --- We must do both lines together --- */
-
-  F1(a, b, c, d, e,  0, 11);
-  F1(e, a, b, c, d,  1, 14);
-  F1(d, e, a, b, c,  2, 15);
-  F1(c, d, e, a, b,  3, 12);
-  F1(b, c, d, e, a,  4,         5);
-  F1(a, b, c, d, e,  5,         8);
-  F1(e, a, b, c, d,  6,         7);
-  F1(d, e, a, b, c,  7,         9);
-  F1(c, d, e, a, b,  8, 11);
-  F1(b, c, d, e, a,  9, 13);
-  F1(a, b, c, d, e, 10, 14);
-  F1(e, a, b, c, d, 11, 15);
-  F1(d, e, a, b, c, 12,         6);
-  F1(c, d, e, a, b, 13,         7);
-  F1(b, c, d, e, a, 14,         9);
-  F1(a, b, c, d, e, 15,         8);
-
-  F2(A, B, C, D, E,  5,         8);
-  F2(E, A, B, C, D, 14,         9);
-  F2(D, E, A, B, C,  7,         9);
-  F2(C, D, E, A, B,  0,        11);
-  F2(B, C, D, E, A,  9,        13);
-  F2(A, B, C, D, E,  2,        15);
-  F2(E, A, B, C, D, 11,        15);
-  F2(D, E, A, B, C,  4,         5);
-  F2(C, D, E, A, B, 13,         7);
-  F2(B, C, D, E, A,  6,         7);
-  F2(A, B, C, D, E, 15,         8);
-  F2(E, A, B, C, D,  8,        11);
-  F2(D, E, A, B, C,  1,        14);
-  F2(C, D, E, A, B, 10,        14);
-  F2(B, C, D, E, A,  3,        12);
-  F2(A, B, C, D, E, 12,         6);
-
-  G1(e, A, b, c, d,  7,         7);
-  G1(d, e, A, b, c,  4,         6);
-  G1(c, d, e, A, b, 13,         8);
-  G1(b, c, d, e, A,  1,        13);
-  G1(A, b, c, d, e, 10,        11);
-  G1(e, A, b, c, d,  6,         9);
-  G1(d, e, A, b, c, 15,         7);
-  G1(c, d, e, A, b,  3,        15);
-  G1(b, c, d, e, A, 12,         7);
-  G1(A, b, c, d, e,  0,        12);
-  G1(e, A, b, c, d,  9,        15);
-  G1(d, e, A, b, c,  5,         9);
-  G1(c, d, e, A, b,  2,        11);
-  G1(b, c, d, e, A, 14,         7);
-  G1(A, b, c, d, e, 11,        13);
-  G1(e, A, b, c, d,  8,        12);
-
-  G2(E, a, B, C, D,  6,         9);
-  G2(D, E, a, B, C, 11,        13);
-  G2(C, D, E, a, B,  3,        15);
-  G2(B, C, D, E, a,  7,         7);
-  G2(a, B, C, D, E,  0,        12);
-  G2(E, a, B, C, D, 13,         8);
-  G2(D, E, a, B, C,  5,         9);
-  G2(C, D, E, a, B, 10,        11);
-  G2(B, C, D, E, a, 14,         7);
-  G2(a, B, C, D, E, 15,         7);
-  G2(E, a, B, C, D,  8,        12);
-  G2(D, E, a, B, C, 12,         7);
-  G2(C, D, E, a, B,  4,         6);
-  G2(B, C, D, E, a,  9,        15);
-  G2(a, B, C, D, E,  1,        13);
-  G2(E, a, B, C, D,  2,        11);
-
-  H1(d, e, A, B, c,  3,        11);
-  H1(c, d, e, A, B, 10,        13);
-  H1(B, c, d, e, A, 14,         6);
-  H1(A, B, c, d, e,  4,         7);
-  H1(e, A, B, c, d,  9,        14);
-  H1(d, e, A, B, c, 15,         9);
-  H1(c, d, e, A, B,  8,        13);
-  H1(B, c, d, e, A,  1,        15);
-  H1(A, B, c, d, e,  2,        14);
-  H1(e, A, B, c, d,  7,         8);
-  H1(d, e, A, B, c,  0,        13);
-  H1(c, d, e, A, B,  6,         6);
-  H1(B, c, d, e, A, 13,         5);
-  H1(A, B, c, d, e, 11,        12);
-  H1(e, A, B, c, d,  5,         7);
-  H1(d, e, A, B, c, 12,         5);
-
-  H2(D, E, a, b, C, 15,         9);
-  H2(C, D, E, a, b,  5,         7);
-  H2(b, C, D, E, a,  1,        15);
-  H2(a, b, C, D, E,  3,        11);
-  H2(E, a, b, C, D,  7,         8);
-  H2(D, E, a, b, C, 14,         6);
-  H2(C, D, E, a, b,  6,         6);
-  H2(b, C, D, E, a,  9,        14);
-  H2(a, b, C, D, E, 11,        12);
-  H2(E, a, b, C, D,  8,        13);
-  H2(D, E, a, b, C, 12,         5);
-  H2(C, D, E, a, b,  2,        14);
-  H2(b, C, D, E, a, 10,        13);
-  H2(a, b, C, D, E,  0,        13);
-  H2(E, a, b, C, D,  4,         7);
-  H2(D, E, a, b, C, 13,         5);
-
-  I1(C, d, e, A, B,  1,        11);
-  I1(B, C, d, e, A,  9,        12);
-  I1(A, B, C, d, e, 11,        14);
-  I1(e, A, B, C, d, 10,        15);
-  I1(d, e, A, B, C,  0,        14);
-  I1(C, d, e, A, B,  8,        15);
-  I1(B, C, d, e, A, 12,         9);
-  I1(A, B, C, d, e,  4,         8);
-  I1(e, A, B, C, d, 13,         9);
-  I1(d, e, A, B, C,  3,        14);
-  I1(C, d, e, A, B,  7,         5);
-  I1(B, C, d, e, A, 15,         6);
-  I1(A, B, C, d, e, 14,         8);
-  I1(e, A, B, C, d,  5,         6);
-  I1(d, e, A, B, C,  6,         5);
-  I1(C, d, e, A, B,  2,        12);
-
-  I2(c, D, E, a, b,  8,        15);
-  I2(b, c, D, E, a,  6,         5);
-  I2(a, b, c, D, E,  4,         8);
-  I2(E, a, b, c, D,  1,        11);
-  I2(D, E, a, b, c,  3,        14);
-  I2(c, D, E, a, b, 11,        14);
-  I2(b, c, D, E, a, 15,         6);
-  I2(a, b, c, D, E,  0,        14);
-  I2(E, a, b, c, D,  5,         6);
-  I2(D, E, a, b, c, 12,         9);
-  I2(c, D, E, a, b,  2,        12);
-  I2(b, c, D, E, a, 13,         9);
-  I2(a, b, c, D, E,  9,        12);
-  I2(E, a, b, c, D,  7,         5);
-  I2(D, E, a, b, c, 10,        15);
-  I2(c, D, E, a, b, 14,         8);
-
-  J1(B, C, D, e, A,  4,         9);
-  J1(A, B, C, D, e,  0,        15);
-  J1(e, A, B, C, D,  5,         5);
-  J1(D, e, A, B, C,  9,        11);
-  J1(C, D, e, A, B,  7,         6);
-  J1(B, C, D, e, A, 12,         8);
-  J1(A, B, C, D, e,  2,        13);
-  J1(e, A, B, C, D, 10,        12);
-  J1(D, e, A, B, C, 14,         5);
-  J1(C, D, e, A, B,  1,        12);
-  J1(B, C, D, e, A,  3,        13);
-  J1(A, B, C, D, e,  8,        14);
-  J1(e, A, B, C, D, 11,        11);
-  J1(D, e, A, B, C,  6,         8);
-  J1(C, D, e, A, B, 15,         5);
-  J1(B, C, D, e, A, 13,         6);
-
-  J2(b, c, d, E, a, 12,         8);
-  J2(a, b, c, d, E, 15,         5);
-  J2(E, a, b, c, d, 10,        12);
-  J2(d, E, a, b, c,  4,         9);
-  J2(c, d, E, a, b,  1,        12);
-  J2(b, c, d, E, a,  5,         5);
-  J2(a, b, c, d, E,  8,        14);
-  J2(E, a, b, c, d,  7,         6);
-  J2(d, E, a, b, c,  6,         8);
-  J2(c, d, E, a, b,  2,        13);
-  J2(b, c, d, E, a, 13,         6);
-  J2(a, b, c, d, E, 14,         5);
-  J2(E, a, b, c, d,  0,        15);
-  J2(d, E, a, b, c,  3,        13);
-  J2(c, d, E, a, b,  9,        11);
-  J2(b, c, d, E, a, 11,        11);
-
-  /* --- Write out the result --- */
-
-  ctx->a += A;
-  ctx->b += B;
-  ctx->c += C;
-  ctx->d += D;
-  ctx->e += E;
-  ctx->A += a;
-  ctx->B += b;
-  ctx->C += c;
-  ctx->D += d;
-  ctx->E += e;
-}
-
-/* --- @rmd320_init@ --- *
- *
- * Arguments:  @rmd320_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void rmd320_init(rmd320_ctx *ctx)
-{
-  ctx->a = 0x67452301;
-  ctx->b = 0xefcdab89;
-  ctx->c = 0x98badcfe;
-  ctx->d = 0x10325476;
-  ctx->e = 0xc3d2e1f0;
-  ctx->A = 0x76543210;
-  ctx->B = 0xfedcba98;
-  ctx->C = 0x89abcdef;
-  ctx->D = 0x01234567;
-  ctx->E = 0x3c2d1e0f;
-  ctx->off = 0;
-  ctx->nl = ctx->nh = 0;
-}
-
-/* --- @rmd320_set@ --- *
- *
- * Arguments:  @rmd320_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 rmd320_set(rmd320_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->A = LOAD32_L(p + 20);
-  ctx->B = LOAD32_L(p + 24);
-  ctx->C = LOAD32_L(p + 28);
-  ctx->D = LOAD32_L(p + 32);
-  ctx->E = LOAD32_L(p + 36);
-  ctx->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @rmd320_hash@ --- *
- *
- * Arguments:  @rmd320_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 rmd320_hash(rmd320_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(RMD320, rmd320, ctx, buf, sz);
-}
-
-/* --- @rmd320_done@ --- *
- *
- * Arguments:  @rmd320_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void rmd320_done(rmd320_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  HASH_MD5STRENGTH(RMD320, rmd320, 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);
-  STORE32_L(p + 20, ctx->A);
-  STORE32_L(p + 24, ctx->B);
-  STORE32_L(p + 28, ctx->C);
-  STORE32_L(p + 32, ctx->D);
-  STORE32_L(p + 36, ctx->E);
-}
-
-/* --- @rmd320_state@ --- *
- *
- * Arguments:  @rmd320_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 @rmd320_set@.
- */
-
-unsigned long rmd320_state(rmd320_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);
-  STORE32_L(p + 20, ctx->A);
-  STORE32_L(p + 24, ctx->B);
-  STORE32_L(p + 28, ctx->C);
-  STORE32_L(p + 32, ctx->D);
-  STORE32_L(p + 36, ctx->E);
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(RMD320, rmd320)
-
-/* --- Test code --- */
-
-HASH_TEST(RMD320, rmd320)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rmd320.h b/rmd320.h
deleted file mode 100644 (file)
index 592e96f..0000000
--- a/rmd320.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rmd320.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The RIPEMD-320 message digest function
- *
- * (c) 1998 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.
- */
-
-/*----- Notes on the RIPEMD-320 hash function -----------------------------*
- *
- * RIPEMD-320 was invented by Hans Dobbertin, Antoon Bosselaers and Bart
- * Preneel.  It's a double-width version of RIPEMD-160, constructed simply by
- * not gluing together the two parallel computations which RIPEMD-160 usually
- * does in its compression function.  The authors warn that, while its output
- * is twice as wide as that of RIPEMD-160, they don't expect it to offer any
- * more security.
- */
-
-#ifndef CATACOMB_RMD320_H
-#define CATACOMB_RMD320_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define RMD320_BUFSZ 64
-#define RMD320_HASHSZ 40
-#define RMD320_STATESZ 40
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct rmd320_ctx {
-  uint32 a, b, c, d, e;                        /* Chaining variables */
-  uint32 A, B, C, D, E;                        /* More chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[RMD320_BUFSZ];             /* Accumulation buffer */
-} rmd320_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @rmd320_compress@ --- *
- *
- * Arguments:  @rmd320_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                RIPEMD-320 compression function.
- */
-
-extern void rmd320_compress(rmd320_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @rmd320_init@ --- *
- *
- * Arguments:  @rmd320_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void rmd320_init(rmd320_ctx */*ctx*/);
-
-/* --- @rmd320_set@ --- *
- *
- * Arguments:  @rmd320_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 rmd320_set(rmd320_ctx */*ctx*/,
-                      const void */*buf*/, unsigned long /*count*/);
-
-/* --- @rmd320_hash@ --- *
- *
- * Arguments:  @rmd320_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 rmd320_hash(rmd320_ctx */*ctx*/,
-                       const void */*buf*/, size_t /*sz*/);
-
-/* --- @rmd320_done@ --- *
- *
- * Arguments:  @rmd320_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 rmd320_done(rmd320_ctx */*ctx*/, void */*hash*/);
-
-/* --- @rmd320_state@ --- *
- *
- * Arguments:  @rmd320_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 @rmd320_set@.
- */
-
-extern unsigned long rmd320_state(rmd320_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash rmd320;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rsa-fetch.c b/rsa-fetch.c
deleted file mode 100644 (file)
index 0236b67..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rsa-fetch.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Key fetching for RSA public and private keys
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "key.h"
-#include "rsa.h"
-
-/*----- Key fetching ------------------------------------------------------*/
-
-const key_fetchdef rsa_pubfetch[] = {
-  { "n",       offsetof(rsa_pub, n),           KENC_MP,        0 },
-  { "e",       offsetof(rsa_pub, e),           KENC_MP,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-static const key_fetchdef priv[] = {
-  { "p",       offsetof(rsa_priv, p),          KENC_MP,        0 },
-  { "q",       offsetof(rsa_priv, q),          KENC_MP,        0 },
-  { "q-inv",   offsetof(rsa_priv, q_inv),      KENC_MP,        0 },
-  { "d",       offsetof(rsa_priv, d),          KENC_MP,        0 },
-  { "d-mod-p", offsetof(rsa_priv, dp),         KENC_MP,        0 },
-  { "d-mod-q", offsetof(rsa_priv, dq),         KENC_MP,        0 },
-  { 0,         0,                              0,              0 }
-};
-
-const key_fetchdef rsa_privfetch[] = {
-  { "n",       offsetof(rsa_priv, n),          KENC_MP,        0 },
-  { "e",       offsetof(rsa_priv, e),          KENC_MP,        0 },
-  { "private", 0,                              KENC_STRUCT,    priv },
-  { 0,         0,                              0,              0 }
-};
-
-/* --- @rsa_pubfree@, @rsa_privfree@ --- *
- *
- * Arguments:  @rsa_pub *rp@, @rsa_priv *rp@ = pointer to key block
- *
- * Returns:    ---
- *
- * Use:                Frees an RSA key block.
- */
-
-void rsa_pubfree(rsa_pub *rp)
-{
-  mp_drop(rp->n);
-  mp_drop(rp->e);
-}
-
-void rsa_privfree(rsa_priv *rp)
-{
-  mp_drop(rp->n);
-  mp_drop(rp->e);
-  mp_drop(rp->p);
-  mp_drop(rp->q);
-  mp_drop(rp->q_inv);
-  mp_drop(rp->d);
-  mp_drop(rp->dp);
-  mp_drop(rp->dq);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rsa-gen.c b/rsa-gen.c
deleted file mode 100644 (file)
index 6005f61..0000000
--- a/rsa-gen.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * RSA parameter generation
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#include "grand.h"
-#include "mp.h"
-#include "mpint.h"
-#include "pgen.h"
-#include "rsa.h"
-#include "strongprime.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rsa_gen@ --- *
- *
- * Arguments:  @rsa_priv *rp@ = pointer to block to be filled in
- *             @unsigned nbits@ = required modulus size in bits
- *             @grand *r@ = random number source
- *             @unsigned n@ = number of attempts to make
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for the event handler
- *
- * Returns:    Zero if all went well, nonzero otherwise.
- *
- * Use:                Constructs a pair of strong RSA primes and other useful RSA
- *             parameters.  A small encryption exponent is chosen if
- *             possible.
- */
-
-int rsa_gen(rsa_priv *rp, unsigned nbits, grand *r, unsigned n,
-           pgen_proc *event, void *ectx)
-{
-  pgen_gcdstepctx g;
-  mp *phi = MP_NEW;
-
-  /* --- Bits of initialization --- */
-
-  rp->e = mp_fromulong(MP_NEW, 0x10001);
-  rp->d = MP_NEW;
-
-  /* --- Generate strong primes %$p$% and %$q$% --- *
-   *
-   * Constrain the GCD of @q@ to ensure that overly small private exponents
-   * are impossible.  Current results suggest that if %$d < n^{0.29}$% then
-   * it can be guessed fairly easily.  This implementation is rather more
-   * conservative about that sort of thing.
-   */
-
-again:
-  if ((rp->p = strongprime("p", MP_NEWSEC, nbits/2, r, n, event, ectx)) == 0)
-    goto fail_p;
-
-  /* --- Do painful fiddling with GCD steppers --- */
-
-  {
-    mp *q;
-    rabin rb;
-
-    if ((q = strongprime_setup("q", MP_NEWSEC, &g.jp, nbits / 2,
-                              r, n, event, ectx)) == 0)
-      goto fail_q;
-    g.r = mp_lsr(MP_NEW, rp->p, 1);
-    g.g = MP_NEW;
-    g.max = MP_256;
-    q = pgen("q", q, q, event, ectx, n, pgen_gcdstep, &g,
-                rabin_iters(nbits/2), pgen_test, &rb);
-    pfilt_destroy(&g.jp);
-    mp_drop(g.r);
-    if (!q) {
-      mp_drop(g.g);
-      if (n)
-       goto fail_q;
-      mp_drop(rp->p);
-      goto again;
-    }
-    rp->q = q;
-  }
-
-  /* --- Ensure that %$p > q$% --- *
-   *
-   * Also ensure that %$p$% and %$q$% are sufficiently different to deter
-   * square-root-based factoring methods.
-   */
-
-  phi = mp_sub(phi, rp->p, rp->q);
-  if (MP_LEN(phi) * 4 < MP_LEN(rp->p) * 3 ||
-      MP_LEN(phi) * 4 < MP_LEN(rp->q) * 3) {
-    mp_drop(rp->p);
-    mp_drop(g.g);
-    if (n)
-      goto fail_q;
-    mp_drop(rp->q);
-    goto again;
-  }
-
-  if (MP_NEGP(phi)) {
-    mp *z = rp->p;
-    rp->p = rp->q;
-    rp->q = z;
-  }
-
-  /* --- Work out the modulus and the CRT coefficient --- */
-
-  rp->n = mp_mul(MP_NEW, rp->p, rp->q);
-  rp->q_inv = mp_modinv(MP_NEW, rp->q, rp->p);
-
-  /* --- Work out %$\varphi(n) = (p - 1)(q - 1)$% --- *
-   *
-   * Save on further multiplications by noting that %$n = pq$% is known and
-   * that %$(p - 1)(q - 1) = pq - p - q + 1$%.  To minimize the size of @d@
-   * (useful for performance reasons, although not very because an overly
-   * small @d@ will be rejected for security reasons) this is then divided by
-   * %$\gcd(p - 1, q - 1)$%.
-   */
-
-  phi = mp_sub(phi, rp->n, rp->p);
-  phi = mp_sub(phi, phi, rp->q);
-  phi = mp_add(phi, phi, MP_ONE);
-  phi = mp_lsr(phi, phi, 1);
-  mp_div(&phi, 0, phi, g.g);
-
-  /* --- Decide on a public exponent --- *
-   *
-   * Simultaneously compute the private exponent.
-   */
-
-  mp_gcd(&g.g, 0, &rp->d, phi, rp->e);
-  if (!MP_EQ(g.g, MP_ONE) && MP_LEN(rp->d) * 4 > MP_LEN(rp->n) * 3)
-    goto fail_e;
-
-  /* --- Work out exponent residues --- */
-
-  rp->dp = MP_NEW; phi = mp_sub(phi, rp->p, MP_ONE);
-  mp_div(0, &rp->dp, rp->d, phi);
-
-  rp->dq = MP_NEW; phi = mp_sub(phi, rp->q, MP_ONE);
-  mp_div(0, &rp->dq, rp->d, phi);
-
-  /* --- Done --- */
-
-  mp_drop(phi);
-  mp_drop(g.g);
-  return (0);
-
-  /* --- Tidy up when something goes wrong --- */
-
-fail_e:
-  mp_drop(g.g);
-  mp_drop(phi);
-  mp_drop(rp->n);
-  mp_drop(rp->q_inv);
-  mp_drop(rp->q);
-fail_q:
-  mp_drop(rp->p);
-fail_p:
-  mp_drop(rp->e);
-  if (rp->d)
-    mp_drop(rp->d);
-  return (-1);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rsa-priv.c b/rsa-priv.c
deleted file mode 100644 (file)
index fe427bb..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rsa-priv.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * RSA private-key operations
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-
-#include "mp.h"
-#include "mpmont.h"
-#include "mprand.h"
-#include "rsa.h"
-
-/*----- Public key operations ---------------------------------------------*/
-
-/* --- @rsa_privcreate@ --- *
- *
- * Arguments:  @rsa_privctx *rd@ = pointer to an RSA private key context
- *             @rsa_priv *rp@ = pointer to RSA private key
- *             @grand *r@ = pointer to random number source for blinding
- *
- * Returns:    ---
- *
- * Use:                Initializes an RSA private-key context.  Keeping a context
- *             for several decryption or signing operations provides a minor
- *             performance benefit.
- *
- *             The random number source may be null if blinding is not
- *             desired.  This improves decryption speed, at the risk of
- *             permitting timing attacks.
- */
-
-void rsa_privcreate(rsa_privctx *rd, rsa_priv *rp, grand *r)
-{
-  rd->rp = rp;
-  rd->r = r;
-  if (r)
-    mpmont_create(&rd->nm, rp->n);
-  mpmont_create(&rd->pm, rp->p);
-  mpmont_create(&rd->qm, rp->q);
-}
-
-/* --- @rsa_privdestroy@ --- *
- *
- * Arguments:  @rsa_privctx *rd@ = pointer to an RSA decryption context
- *
- * Returns:    ---
- *
- * Use:                Destroys an RSA decryption context.
- */
-
-void rsa_privdestroy(rsa_privctx *rd)
-{
-  if (rd->r)
-    mpmont_destroy(&rd->nm);
-  mpmont_destroy(&rd->pm);
-  mpmont_destroy(&rd->qm);
-}
-
-/* --- @rsa_privop@ --- *
- *
- * Arguments:  @rsa_privctx *rd@ = pointer to RSA private key context
- *             @mp *d@ = destination
- *             @mp *c@ = input message
- *
- * Returns:    The transformed output message.
- *
- * Use:                Performs an RSA private key operation.  This function takes
- *             advantage of knowledge of the key factors in order to speed
- *             up decryption.  It also blinds the ciphertext prior to
- *             decryption and unblinds it afterwards to thwart timing
- *             attacks.
- */
-
-mp *rsa_privop(rsa_privctx *rd, mp *d, mp *c)
-{
-  mp *ki = MP_NEW;
-  rsa_priv *rp = rd->rp;
-
-  /* --- If so desired, set up a blinding constant --- *
-   *
-   * Choose a constant %$k$% relatively prime to the modulus %$m$%.  Compute
-   * %$c' = c k^e \bmod n$%, and %$k^{-1} \bmod n$%.  Don't bother with the
-   * CRT stuff here because %$e$% is chosen to be small.
-   */
-
-  c = MP_COPY(c);
-  if (rd->r) {
-    mp *k = MP_NEWSEC, *g = MP_NEW;
-
-    do {
-      k = mprand_range(k, rp->n, rd->r, 0);
-      mp_gcd(&g, 0, &ki, rp->n, k);
-    } while (!MP_EQ(g, MP_ONE));
-    k = mpmont_mul(&rd->nm, k, k, rd->nm.r2);
-    k = mpmont_expr(&rd->nm, k, k, rp->e);
-    c = mpmont_mul(&rd->nm, c, c, k);
-    mp_drop(k);
-    mp_drop(g);
-  }
-
-  /* --- Do the actual modular exponentiation --- *
-   *
-   * Use a slightly hacked version of the Chinese Remainder Theorem stuff.
-   *
-   * Let %$q' = q^{-1} \bmod p$%.  Then note that
-   * %$c^d \equiv q (q'(c_p^{d_p} - c_q^{d_q}) \bmod p) + c_q^{d_q} \pmod n$%
-   */
-
-  {
-    mp *cp = MP_NEW, *cq = MP_NEW;
-
-    /* --- Work out the two halves of the result --- */
-
-    mp_div(0, &cp, c, rp->p);
-    cp = mpmont_exp(&rd->pm, cp, cp, rp->dp);
-
-    mp_div(0, &cq, c, rp->q);
-    cq = mpmont_exp(&rd->qm, cq, cq, rp->dq);
-
-    /* --- Combine the halves using the result above --- */
-
-    d = mp_sub(d, cp, cq);
-    mp_div(0, &d, d, rp->p);
-    d = mpmont_mul(&rd->pm, d, d, rp->q_inv);
-    d = mpmont_mul(&rd->pm, d, d, rd->pm.r2);
-
-    d = mp_mul(d, d, rp->q);
-    d = mp_add(d, d, cq);
-    if (MP_CMP(d, >=, rp->n))
-      d = mp_sub(d, d, rp->n);
-
-    /* --- Tidy away temporary variables --- */
-
-    mp_drop(cp);
-    mp_drop(cq);
-  }
-
-  /* --- Finally, possibly remove the blinding factor --- */
-
-  if (ki) {
-    d = mpmont_mul(&rd->nm, d, d, ki);
-    d = mpmont_mul(&rd->nm, d, d, rd->nm.r2);
-    mp_drop(ki);
-  }
-
-  /* --- Done --- */
-
-  mp_drop(c);
-  return (d);
-}
-
-/* --- @rsa_qprivop@ --- *
- *
- * Arguments:  @rsa_priv *rp@ = pointer to RSA parameters
- *             @mp *d@ = destination
- *             @mp *c@ = input message
- *             @grand *r@ = pointer to random number source for blinding
- *
- * Returns:    Correctly transformed output message
- *
- * Use:                Performs an RSA private key operation, very carefully.
- */
-
-mp *rsa_qprivop(rsa_priv *rp, mp *d, mp *c, grand *r)
-{
-  rsa_privctx rd;
-  rsa_privcreate(&rd, rp, r);
-  d = rsa_privop(&rd, d, c);
-  rsa_privdestroy(&rd);
-  return (d);
-}
-
-/*----- Operations with padding -------------------------------------------*/
-
-/* --- @rsa_sign@ --- *
- *
- * Arguments:  @rsa_privctx *rp@ = pointer to an RSA private key context
- *             @mp *d@ = where to put the result
- *             @const void *m@ = pointer to input message
- *             @size_t msz@ = size of input message
- *             @rsa_pad *e@ = encoding procedure
- *             @void *earg@ = argument pointer for encoding procedure
- *
- * Returns:    The signature, as a multiprecision integer, or null on
- *             failure.
- *
- * Use:                Computes an RSA digital signature.
- */
-
-mp *rsa_sign(rsa_privctx *rp, mp *d, const void *m, size_t msz,
-            rsa_pad *e, void *earg)
-{
-  octet *p;
-  unsigned long nb = mp_bits(rp->rp->n);
-  size_t n = (nb + 7)/8;
-  arena *a = d && d->a ? d->a->a : arena_global;
-
-  p = x_alloc(a, n);
-  d = e(d, m, msz, p, n, nb, earg);
-  x_free(a, p);
-  return (d ? rsa_privop(rp, d, d) : 0);
-}
-
-/* --- @rsa_decrypt@ --- *
- *
- * Arguments:  @rsa_privctx *rp@ = pointer to an RSA private key context
- *             @mp *m@ = encrypted message, as a multiprecision integer
- *             @dstr *d@ = pointer to output string
- *             @rsa_decunpad *e@ = decoding procedure
- *             @void *earg@ = argument pointer for decoding procedure
- *
- * Returns:    The length of the output string if successful, negative on
- *             failure.
- *
- * Use:                Does RSA decryption.
- */
-
-int rsa_decrypt(rsa_privctx *rp, mp *m, dstr *d,
-               rsa_decunpad *e, void *earg)
-{
-  mp *p = rsa_privop(rp, MP_NEW, m);
-  unsigned long nb = mp_bits(rp->rp->n);
-  size_t n = (nb + 7)/8;
-  int rc;
-
-  dstr_ensure(d, n);
-  rc = e(p, (octet *)d->buf + d->len, n, nb, earg);
-  if (rc >= 0)
-    d->len += rc;
-  mp_drop(p);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rsa-pub.c b/rsa-pub.c
deleted file mode 100644 (file)
index e89d6ff..0000000
--- a/rsa-pub.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rsa-pub.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * [RSA encryption with padding *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/alloc.h>
-#include <mLib/bits.h>
-#include <mLib/dstr.h>
-
-#include "mp.h"
-#include "mpmont.h"
-#include "rsa.h"
-
-/*----- Public key operations ---------------------------------------------*/
-
-/* --- @rsa_pubcreate@ --- *
- *
- * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
- *             @rsa_pub *rp@ = pointer to RSA public key
- *
- * Returns:    ---
- *
- * Use:                Initializes an RSA public-key context.
- */
-
-void rsa_pubcreate(rsa_pubctx *rd, rsa_pub *rp)
-{
-  rd->rp = rp;
-  mpmont_create(&rd->mm, rp->n);
-}
-
-/* --- @rsa_pubdestroy@ --- *
- *
- * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
- *
- * Returns:    ---
- *
- * Use:                Destroys an RSA public-key context.
- */
-
-void rsa_pubdestroy(rsa_pubctx *rd)
-{
-  mpmont_destroy(&rd->mm);
-}
-
-/* --- @rsa_pubop@ --- *
- *
- * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
- *             @mp *d@ = destination
- *             @mp *p@ = input message
- *
- * Returns:    The transformed output message.
- *
- * Use:                Performs an RSA public key operation.
- */
-
-mp *rsa_pubop(rsa_pubctx *rd, mp *d, mp *p)
-{
-  return (mpmont_exp(&rd->mm, d, p, rd->rp->e));
-}
-
-/* --- @rsa_qpubop@ --- *
- *
- * Arguments:  @rsa_pub *rp@ = pointer to RSA parameters
- *             @mp *d@ = destination
- *             @mp *p@ = input message
- *
- * Returns:    Correctly transformed output message.
- *
- * Use:                Performs an RSA public key operation.
- */
-
-mp *rsa_qpubop(rsa_pub *rp, mp *d, mp *c)
-{
-  rsa_pubctx rd;
-  rsa_pubcreate(&rd, rp);
-  d = rsa_pubop(&rd, d, c);
-  rsa_pubdestroy(&rd);
-  return (d);
-}
-
-/*----- Operations with padding -------------------------------------------*/
-
-/* --- @rsa_encrypt@ --- *
- *
- * Arguments:  @rsa_pubctx *rp@ = pointer to an RSA public key context
- *             @mp *d@ = proposed destination integer
- *             @const void *m@ = pointer to input message
- *             @size_t msz@ = size of input message
- *             @rsa_pad *e@ = encoding procedure
- *             @void *earg@ = argument pointer for encoding procedure
- *
- * Returns:    The encrypted message, as a multiprecision integer, or null
- *             on failure.
- *
- * Use:                Does RSA encryption.
- */
-
-mp *rsa_encrypt(rsa_pubctx *rp, mp *d, const void *m, size_t msz,
-               rsa_pad *e, void *earg)
-{
-  octet *p;
-  unsigned long nb = mp_bits(rp->rp->n);
-  size_t n = (nb + 7)/8;
-  arena *a = d && d->a ? d->a->a : arena_global;
-
-  p = x_alloc(a, n);
-  d = e(d, m, msz, p, n, nb, earg);
-  x_free(a, p);
-  return (d ? rsa_pubop(rp, d, d) : 0);
-}
-
-/* --- @rsa_verify@ --- *
- *
- * Arguments:  @rsa_pubctx *rp@ = pointer to an RSA public key contxt
- *             @mp *s@ = the signature, as a multiprecision integer
- *             @const void *m@ = pointer to message to verify, or null
- *             @size_t msz@ = size of input message
- *             @dstr *d@ = pointer to output string, or null
- *             @rsa_vfrunpad *e@ = decoding procedure
- *             @void *earg@ = argument pointer for decoding procedure
- *
- * Returns:    The length of the output string if successful (0 if no output
- *             was wanted); negative on failure.
- *
- * Use:                Does RSA signature verification.  To use a signature scheme
- *             with recovery, pass in @m == 0@ and @d != 0@: the recovered
- *             message should appear in @d@.  To use a signature scheme with
- *             appendix, provide @m != 0@ and @d == 0@; the result should be
- *             zero for success.
- */
-
-int rsa_verify(rsa_pubctx *rp, mp *s, const void *m, size_t msz,
-              dstr *d, rsa_vrfunpad *e, void *earg)
-{
-  mp *p = rsa_pubop(rp, MP_NEW, s);
-  unsigned long nb = mp_bits(rp->rp->n);
-  size_t n = (nb + 7)/8;
-  dstr dd = DSTR_INIT;
-  int rc;
-
-  /* --- Decoder protocol --- *
-   *
-   * We deal with two kinds of decoders: ones with message recovery and ones
-   * with appendix.  A decoder with recovery will leave a message in the
-   * buffer and exit nonzero: we'll check that against @m@ if provided and
-   * just leave it otherwise.  A decoder with appendix will inspect @m@ and
-   * return zero or @-1@ itself.
-   */
-
-  if (!d) d = &dd;
-  dstr_ensure(d, n);
-  rc = e(p, m, msz, (octet *)d->buf + d->len, n, nb, earg);
-  if (rc > 0 && m) {
-    if (rc != msz || memcmp(d->buf + d->len, m, msz) != 0)
-      rc = -1;
-    else
-      rc = 0;
-  }
-  if (rc > 0)
-    d->len += rc;
-  mp_drop(p);
-  dstr_destroy(&dd);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rsa-recover.c b/rsa-recover.c
deleted file mode 100644 (file)
index 4546cc3..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rsa-recover.c,v 1.7 2004/04/08 01:36:15 mdw Exp $
- *
- * Recover RSA parameters
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "mp.h"
-#include "mpmont.h"
-#include "rsa.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @rsa_recover@ --- *
- *
- * Arguments:  @rsa_priv *rp@ = pointer to parameter block
- *
- * Returns:    Zero if all went well, nonzero if the parameters make no
- *             sense.
- *
- * Use:                Derives the full set of RSA parameters given a minimal set.
- */
-
-int rsa_recover(rsa_priv *rp)
-{
-  /* --- If there is no modulus, calculate it --- */
-
-  if (!rp->n) {
-    if (!rp->p || !rp->q)
-      return (-1);
-    rp->n = mp_mul(MP_NEW, rp->p, rp->q);
-  }
-
-  /* --- If there are no factors, compute them --- */
-
-  else if (!rp->p || !rp->q) {
-
-    /* --- If one is missing, use simple division to recover the other --- */
-
-    if (rp->p || rp->q) {
-      mp *r = MP_NEW;
-      if (rp->p)
-       mp_div(&rp->q, &r, rp->n, rp->p);
-      else
-       mp_div(&rp->p, &r, rp->n, rp->q);
-      if (!MP_EQ(r, MP_ZERO)) {
-       mp_drop(r);
-       return (-1);
-      }
-      mp_drop(r);
-    }
-
-    /* --- Otherwise use the public and private moduli --- */
-
-    else if (!rp->e || !rp->d)
-      return (-1);
-    else {
-      mp *t;
-      size_t s;
-      mp a; mpw aw;
-      mp *m1;
-      mpmont mm;
-      int i;
-      mp *z = MP_NEW;
-
-      /* --- Work out the appropriate exponent --- *
-       *
-       * I need to compute %$s$% and %$t$% such that %$2^s t = e d - 1$%, and
-       * %$t$% is odd.
-       */
-
-      t = mp_mul(MP_NEW, rp->e, rp->d);
-      t = mp_sub(t, t, MP_ONE);
-      t = mp_odd(t, t, &s);
-
-      /* --- Set up for the exponentiation --- */
-
-      mpmont_create(&mm, rp->n);
-      m1 = mp_sub(MP_NEW, rp->n, mm.r);
-
-      /* --- Now for the main loop --- *
-       *
-       * Choose candidate integers and attempt to factor the modulus.
-       */
-
-      mp_build(&a, &aw, &aw + 1);
-      i = 0;
-      for (;;) {
-      again:
-
-       /* --- Choose a random %$a$% and calculate %$z = a^t \bmod n$% --- *
-        *
-        * If %$z \equiv 1$% or %$z \equiv -1 \pmod n$% then this iteration
-        * is a failure.
-        */
-
-       aw = primetab[i++];
-       z = mpmont_mul(&mm, z, &a, mm.r2);
-       z = mpmont_expr(&mm, z, z, t);
-       if (MP_EQ(z, mm.r) || MP_EQ(z, m1))
-         continue;
-
-       /* --- Now square until something interesting happens --- *
-        *
-        * Compute %$z^{2i} \bmod n$%.  Eventually, I'll either get %$-1$% or
-        * %$1$%.  If the former, the number is uninteresting, and I need to
-        * restart.  If the latter, the previous number minus 1 has a common
-        * factor with %$n$%.
-        */
-
-       for (;;) {
-         mp *zz = mp_sqr(MP_NEW, z);
-         zz = mpmont_reduce(&mm, zz, zz);
-         if (MP_EQ(zz, mm.r)) {
-           mp_drop(zz);
-           goto done;
-         } else if (MP_EQ(zz, m1)) {
-           mp_drop(zz);
-           goto again;
-         }
-         mp_drop(z);
-         z = zz;
-       }
-      }
-
-      /* --- Do the factoring --- *
-       *
-       * Here's how it actually works.  I've found an interesting square
-       * root of %$1 \pmod n$%.  Any square root of 1 must be congruent to
-       * %$\pm 1$% modulo both %$p$% and %$q$%.  Both congruent to %$1$% is
-       * boring, as is both congruent to %$-1$%.  Subtracting one from the
-       * result makes it congruent to %$0$% modulo %$p$% or %$q$% (and
-       * nobody cares which), and hence can be extracted by a GCD
-       * operation.
-       */
-
-    done:
-      z = mpmont_reduce(&mm, z, z);
-      z = mp_sub(z, z, MP_ONE);
-      rp->p = MP_NEW;
-      mp_gcd(&rp->p, 0, 0, rp->n, z);
-      rp->q = MP_NEW;
-      mp_div(&rp->q, 0, rp->n, rp->p);
-      mp_drop(z);
-      mp_drop(t);
-      mp_drop(m1);
-      if (MP_CMP(rp->p, <, rp->q)) {
-       z = rp->p;
-       rp->p = rp->q;
-       rp->q = z;
-      }
-      mpmont_destroy(&mm);
-    }
-  }
-
-  /* --- If %$e$% or %$d$% is missing, recalculate it --- */
-
-  if (!rp->e || !rp->d) {
-    mp *phi;
-    mp *g = MP_NEW;
-    mp *p1, *q1;
-
-    /* --- Compute %$\varphi(n)$% --- */
-
-    phi = mp_sub(MP_NEW, rp->n, rp->p);
-    phi = mp_sub(phi, phi, rp->q);
-    phi = mp_add(phi, phi, MP_ONE);
-    p1 = mp_sub(MP_NEW, rp->p, MP_ONE);
-    q1 = mp_sub(MP_NEW, rp->q, MP_ONE);
-    mp_gcd(&g, 0, 0, p1, q1);
-    mp_div(&phi, 0, phi, g);
-    mp_drop(p1);
-    mp_drop(q1);
-
-    /* --- Recover the other exponent --- */
-
-    if (rp->e)
-      mp_gcd(&g, 0, &rp->d, phi, rp->e);
-    else if (rp->d)
-      mp_gcd(&g, 0, &rp->e, phi, rp->d);
-    else {
-      mp_drop(phi);
-      mp_drop(g);
-      return (-1);
-    }
-
-    mp_drop(phi);
-    if (!MP_EQ(g, MP_ONE)) {
-      mp_drop(g);
-      return (-1);
-    }
-    mp_drop(g);
-  }
-
-  /* --- Compute %$q^{-1} \bmod p$% --- */
-
-  if (!rp->q_inv)
-    mp_gcd(0, 0, &rp->q_inv, rp->p, rp->q);
-
-  /* --- Compute %$d \bmod (p - 1)$% and %$d \bmod (q - 1)$% --- */
-
-  if (!rp->dp) {
-    mp *p1 = mp_sub(MP_NEW, rp->p, MP_ONE);
-    mp_div(0, &rp->dp, rp->d, p1);
-    mp_drop(p1);
-  }
-  if (!rp->dq) {
-    mp *q1 = mp_sub(MP_NEW, rp->q, MP_ONE);
-    mp_div(0, &rp->dq, rp->d, q1);
-    mp_drop(q1);
-  }
-
-  /* --- Done --- */
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rsa-test.c b/rsa-test.c
deleted file mode 100644 (file)
index e4c330f..0000000
+++ /dev/null
@@ -1,514 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Testing RSA padding operations
- *
- * (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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "fibrand.h"
-#include "rsa.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-static int tencpad(int nbits,
-                  dstr *p, int rc, mp *c,
-                  const char *ename, dstr *eparam, rsa_pad *e, void *earg)
-{
-  size_t n = (nbits + 7)/8;
-  void *q = xmalloc(n);
-  mp *d;
-  int ok = 1;
-
-  d = e(MP_NEW, p->buf, p->len, q, n, nbits, earg);
-  if (!d == !rc || (!rc && !MP_EQ(d, c))) {
-    ok = 0;
-    fprintf(stderr, "*** %s padding failed!\n", ename);
-    fprintf(stderr, "*** padding bits = %d\n", nbits);
-    if (eparam) {
-      fprintf(stderr, "*** encoding parameters = ");
-      type_hex.dump(eparam, stderr);
-      fputc('\n', stderr);
-    }
-    fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr);
-    if (rc)
-      fprintf(stderr, "\n*** expected failure\n");
-    else {
-      MP_EPRINTX("\n*** expected", c);
-      MP_EPRINTX("*** computed", d);
-    }
-  }
-  mp_drop(d);
-  mp_drop(c);
-  xfree(q);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-#define tsigpad tencpad
-
-#define DSTR_EQ(x, y)                                                  \
-  ((x)->len == (y)->len && !memcmp((x)->buf, (y)->buf, (x)->len))
-
-static int tdecpad(int nbits,
-                  mp *c, int rc, dstr *p,
-                  const char *ename, dstr *eparam,
-                  rsa_decunpad *e, void *earg)
-{
-  dstr d = DSTR_INIT;
-  int n = (nbits + 7)/8;
-  int ok = 1;
-
-  dstr_ensure(&d, n);
-  n = e(c, (octet *)d.buf, n, nbits, earg);
-  if (n >= 0)
-    d.len += n;
-  if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) {
-    ok = 0;
-    fprintf(stderr, "*** %s encryption unpadding failed!\n", ename);
-    fprintf(stderr, "*** padding bits = %d\n", nbits);
-    if (eparam) {
-      fprintf(stderr, "*** encoding parameters = ");
-      type_hex.dump(eparam, stderr);
-      fputc('\n', stderr);
-    }
-    MP_EPRINTX("*** input", c);
-    if (rc < 0)
-      fprintf(stderr, "*** expected failure\n");
-    else {
-      fprintf(stderr, "*** expected: %d = ", rc); type_hex.dump(p, stderr);
-      fprintf(stderr, "\n*** computed: %d = ", n); type_hex.dump(&d, stderr);
-      fprintf(stderr, "\n");
-    }
-  }
-  mp_drop(c);
-  dstr_destroy(&d);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tvrfpad(int nbits,
-                  mp *c, dstr *m, int rc, dstr *p,
-                  const char *ename, dstr *eparam,
-                  rsa_vrfunpad *e, void *earg)
-{
-  dstr d = DSTR_INIT;
-  int n = (nbits + 7)/8;
-  int ok = 1;
-
-  dstr_ensure(&d, n);
-  n = e(c, m->len ? (octet *)m->buf : 0, m->len,
-       (octet *)d.buf, n, nbits, earg);
-  if (n >= 0)
-    d.len += n;
-  if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) {
-    ok = 0;
-    fprintf(stderr, "*** %s signature unpadding failed!\n", ename);
-    fprintf(stderr, "*** padding bits = %d\n", nbits);
-    MP_EPRINTX("*** input", c);
-    if (eparam) {
-      fprintf(stderr, "*** encoding parameters = ");
-      type_hex.dump(eparam, stderr);
-      fputc('\n', stderr);
-    }
-    fprintf(stderr, "*** message = "); type_hex.dump(m, stderr);
-    if (rc < 0)
-      fprintf(stderr, "\n*** expected failure\n");
-    else {
-      fprintf(stderr, "\n*** expected = %d: ", rc); type_hex.dump(p, stderr);
-      fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr);
-      fprintf(stderr, "\n");
-    }
-  }
-  mp_drop(c);
-  dstr_destroy(&d);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tencpub(rsa_pub *rp,
-                  dstr *p, int rc, mp *c,
-                  const char *ename, dstr *eparam, rsa_pad *e, void *earg)
-{
-  mp *d;
-  rsa_pubctx rpc;
-  int ok = 1;
-
-  rsa_pubcreate(&rpc, rp);
-  d = rsa_encrypt(&rpc, MP_NEW, p->buf, p->len, e, earg);
-  if (!d == !rc || (!rc && !MP_EQ(d, c))) {
-    ok = 0;
-    fprintf(stderr, "*** encrypt with %s padding failed!\n", ename);
-    MP_EPRINTX("*** key.n", rp->n);
-    MP_EPRINTX("*** key.e", rp->e);
-    if (eparam) {
-      fprintf(stderr, "*** encoding parameters = ");
-      type_hex.dump(eparam, stderr);
-      fputc('\n', stderr);
-    }
-    fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr);
-    if (rc)
-      fprintf(stderr, "\n*** expected failure\n");
-    else {
-      MP_EPRINTX("\n*** expected", c);
-      MP_EPRINTX("*** computed", d);
-    }
-  }
-  rsa_pubdestroy(&rpc);
-  rsa_pubfree(rp);
-  mp_drop(d);
-  mp_drop(c);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tsigpriv(rsa_priv *rp,
-                   dstr *p, int rc, mp *c,
-                   const char *ename, dstr *eparam, rsa_pad *e, void *earg)
-{
-  mp *d;
-  grand *r = fibrand_create(0);
-  rsa_privctx rpc;
-  int ok = 1;
-
-  rsa_privcreate(&rpc, rp, r);
-  d = rsa_sign(&rpc, MP_NEW, p->buf, p->len, e, earg);
-  if (!d == !rc || (!rc && !MP_EQ(d, c))) {
-    ok = 0;
-    fprintf(stderr, "*** sign with %s padding failed!\n", ename);
-    MP_EPRINTX("*** key.n", rp->n);
-    MP_EPRINTX("*** key.d", rp->d);
-    MP_EPRINTX("*** key.e", rp->e);
-    if (eparam) {
-      fprintf(stderr, "*** encoding parameters = ");
-      type_hex.dump(eparam, stderr);
-      fputc('\n', stderr);
-    }
-    fprintf(stderr, "*** input message = "); type_hex.dump(p, stderr);
-    if (rc)
-      fprintf(stderr, "\n*** expected failure\n");
-    else {
-      MP_EPRINTX("\n*** expected", c);
-      MP_EPRINTX("\n*** computed", d);
-    }
-  }
-  rsa_privdestroy(&rpc);
-  rsa_privfree(rp);
-  mp_drop(d);
-  mp_drop(c);
-  GR_DESTROY(r);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tdecpriv(rsa_priv *rp,
-                   mp *c, int rc, dstr *p,
-                   const char *ename, dstr *eparam,
-                   rsa_decunpad *e, void *earg)
-{
-  rsa_privctx rpc;
-  dstr d = DSTR_INIT;
-  grand *r = fibrand_create(0);
-  int n;
-  int ok = 1;
-
-  rsa_privcreate(&rpc, rp, r);
-  n = rsa_decrypt(&rpc, c, &d, e, earg);
-  if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) {
-    ok = 0;
-    fprintf(stderr, "*** decryption with %s padding failed!\n", ename);
-    MP_EPRINTX("*** key.n", rp->n);
-    MP_EPRINTX("*** key.d", rp->d);
-    MP_EPRINTX("*** key.e", rp->e);
-    if (eparam) {
-      fprintf(stderr, "*** encoding parameters = ");
-      type_hex.dump(eparam, stderr);
-      fputc('\n', stderr);
-    }
-    MP_EPRINTX("*** input", c);
-    if (rc < 0)
-      fprintf(stderr, "*** expected failure\n");
-    else {
-      fprintf(stderr, "*** expected = %d: ", rc); type_hex.dump(p, stderr);
-      fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr);
-      fprintf(stderr, "\n");
-    }
-  }
-  rsa_privdestroy(&rpc);
-  rsa_privfree(rp);
-  mp_drop(c);
-  dstr_destroy(&d);
-  GR_DESTROY(r);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-static int tvrfpub(rsa_pub *rp,
-                  mp *c, dstr *m, int rc, dstr *p,
-                  const char *ename, dstr *eparam,
-                  rsa_vrfunpad *e, void *earg)
-{
-  rsa_pubctx rpc;
-  dstr d = DSTR_INIT;
-  int n;
-  int ok = 1;
-
-  rsa_pubcreate(&rpc, rp);
-  n = rsa_verify(&rpc, c, m->len ? m->buf : 0, m->len, &d, e, earg);
-  if (n != rc || (rc >= 0 && !DSTR_EQ(&d, p))) {
-    ok = 0;
-    fprintf(stderr, "*** verification with %s padding failed!\n", ename);
-    MP_EPRINTX("*** key.n", rp->n);
-    MP_EPRINTX("*** key.e", rp->e);
-    if (eparam) {
-      fprintf(stderr, "*** encoding parameters = ");
-      type_hex.dump(eparam, stderr);
-      fputc('\n', stderr);
-    }
-    MP_EPRINTX("*** input", c);
-    fprintf(stderr, "*** message = "); type_hex.dump(m, stderr);
-    if (rc < 0)
-      fprintf(stderr, "\n*** expected failure\n");
-    else {
-      fprintf(stderr, "\n*** expected = %d: ", rc); type_hex.dump(p, stderr);
-      fprintf(stderr, "\n*** computed = %d: ", n); type_hex.dump(&d, stderr);
-      fprintf(stderr, "\n");
-    }
-  }
-  rsa_pubdestroy(&rpc);
-  rsa_pubfree(rp);
-  mp_drop(c);
-  dstr_destroy(&d);
-  assert(mparena_count(MPARENA_GLOBAL) == 0);
-  return (ok);
-}
-
-/*----- Deep magic --------------------------------------------------------*
- *
- * Wahey!  Whacko macro programming on curry and lager.  There's nothing like
- * it.
- */
-
-#define DECL_priv                                                      \
-  rsa_priv rp = { 0 };
-#define FUNC_priv                                                      \
-  rp.n = *(mp **)v++->buf;                                             \
-  rp.e = *(mp **)v++->buf;                                             \
-  rp.d = *(mp **)v++->buf;                                             \
-  rsa_recover(&rp);
-#define ARG_priv                                                       \
-  &rp,
-#define TAB_priv                                                       \
-  &type_mp, &type_mp, &type_mp,
-
-#define DECL_pub                                                       \
-  rsa_pub rp;
-#define FUNC_pub                                                       \
-  rp.n = *(mp **)v++->buf;                                             \
-  rp.e = *(mp **)v++->buf;
-#define ARG_pub                                                                \
-  &rp,
-#define TAB_pub                                                                \
-  &type_mp, &type_mp,
-
-#define DECL_pad                                                       \
-  int nbits;
-#define FUNC_pad                                                       \
-  nbits = *(int *)v++->buf;
-#define ARG_pad                                                                \
-  nbits,
-#define TAB_pad                                                                \
-  &type_int,
-
-#define DECL_enc                                                       \
-  dstr *p;                                                             \
-  int rc;                                                              \
-  mp *c;
-#define FUNC_enc                                                       \
-  p = v++;                                                             \
-  rc = *(int *)v++->buf;                                               \
-  c = *(mp **)v++->buf;
-#define ARG_enc                                                                \
-  p, rc, c,
-#define TAB_enc                                                                \
-  &type_hex, &type_int, &type_mp,
-
-#define DECL_sig DECL_enc
-#define FUNC_sig FUNC_enc
-#define ARG_sig ARG_enc
-#define TAB_sig TAB_enc
-
-#define DECL_dec                                                       \
-  mp *c;                                                               \
-  int rc;                                                              \
-  dstr *p;
-#define FUNC_dec                                                       \
-  c = *(mp **)v++->buf;                                                        \
-  rc = *(int *)v++->buf;                                               \
-  p = v++;
-#define ARG_dec                                                                \
-  c, rc, p,
-#define TAB_dec                                                                \
-  &type_mp, &type_int, &type_hex,
-
-#define DECL_vrf                                                       \
-  mp *c;                                                               \
-  dstr *m;                                                             \
-  int rc;                                                              \
-  dstr *p;
-#define FUNC_vrf                                                       \
-  c = *(mp **)v++->buf;                                                        \
-  m = v++;                                                             \
-  rc = *(int *)v++->buf;                                               \
-  p = v++;
-#define ARG_vrf                                                                \
-  c, m, rc, p,
-#define TAB_vrf                                                                \
-  &type_mp, &type_hex, &type_int, &type_hex,
-
-#define DECL_p1enc                                                     \
-  pkcs1 p1;                                                            \
-  dstr *ep;
-#define FUNC_p1enc                                                     \
-  p1.r = fib;                                                          \
-  ep = v++;                                                            \
-  p1.ep = ep->buf;                                                     \
-  p1.epsz = ep->len;
-#define ARG_p1enc                                                      \
-  "pkcs1", ep, pkcs1_cryptencode, &p1
-#define TAB_p1enc                                                      \
-  &type_hex
-
-#define DECL_p1sig DECL_p1enc
-#define FUNC_p1sig FUNC_p1enc
-#define ARG_p1sig                                                      \
-  "pkcs1", ep, pkcs1_sigencode, &p1
-#define TAB_p1sig TAB_p1enc
-
-#define DECL_p1dec DECL_p1enc
-#define FUNC_p1dec FUNC_p1enc
-#define ARG_p1dec                                                      \
-  "pkcs1", ep, pkcs1_cryptdecode, &p1
-#define TAB_p1dec TAB_p1enc
-
-#define DECL_p1vrf DECL_p1enc
-#define FUNC_p1vrf FUNC_p1enc
-#define ARG_p1vrf                                                      \
-  "pkcs1", ep, pkcs1_sigdecode, &p1
-#define TAB_p1vrf TAB_p1enc
-
-#define DECL_oaepenc                                                   \
-  oaep o;                                                              \
-  dstr *ep;
-#define FUNC_oaepenc                                                   \
-  o.r = fib;                                                           \
-  o.cc = gcipher_byname(v++->buf);                                     \
-  o.ch = ghash_byname(v++->buf);                                       \
-  ep = v++;                                                            \
-  o.ep = ep->buf;                                                      \
-  o.epsz = ep->len;
-#define ARG_oaepenc                                                    \
-  "oaep", ep, oaep_encode, &o
-#define TAB_oaepenc                                                    \
-  &type_string, &type_string, &type_hex
-
-#define DECL_oaepdec DECL_oaepenc
-#define FUNC_oaepdec FUNC_oaepenc
-#define ARG_oaepdec                                                    \
-  "oaep", ep, oaep_decode, &o
-#define TAB_oaepdec TAB_oaepenc
-
-#define DECL_psssig                                                    \
-  pss pp;
-#define FUNC_psssig                                                    \
-  pp.r = fib;                                                          \
-  pp.cc = gcipher_byname(v++->buf);                                    \
-  pp.ch = ghash_byname(v++->buf);                                      \
-  pp.ssz = *(int *)v++->buf;
-#define ARG_psssig                                                     \
-  "pss", 0, pss_encode, &pp
-#define TAB_psssig                                                     \
-  &type_string, &type_string, &type_int
-
-#define DECL_pssvrf DECL_psssig
-#define FUNC_pssvrf FUNC_psssig
-#define ARG_pssvrf                                                     \
-  "pss", 0, pss_decode, &pp
-#define TAB_pssvrf TAB_psssig
-
-#define TESTS(DO)                                                      \
-  DO(pad, enc, p1enc)                                                  \
-  DO(pad, dec, p1dec)                                                  \
-  DO(pad, sig, p1sig)                                                  \
-  DO(pad, vrf, p1vrf)                                                  \
-  DO(pub, enc, p1enc)                                                  \
-  DO(priv, dec, p1dec)                                                 \
-  DO(priv, sig, p1sig)                                                 \
-  DO(pub, vrf, p1vrf)                                                  \
-  DO(pad, enc, oaepenc)                                                        \
-  DO(pad, dec, oaepdec)                                                        \
-  DO(pub, enc, oaepenc)                                                        \
-  DO(priv, dec, oaepdec)                                               \
-  DO(pad, sig, psssig)                                                 \
-  DO(pad, vrf, pssvrf)                                                 \
-  DO(priv, sig, psssig)                                                        \
-  DO(pub, vrf, pssvrf)
-
-#define FUNCS(key, op, enc)                                            \
-  int t_##key##_##enc(dstr *v)                                         \
-  {                                                                    \
-    DECL_##key                                                         \
-    DECL_##op                                                          \
-    DECL_##enc                                                         \
-    fib->ops->misc(fib, GRAND_SEEDINT, 14);                            \
-    FUNC_##key                                                         \
-    FUNC_##op                                                          \
-    FUNC_##enc                                                         \
-    return (t##op##key(ARG_##key ARG_##op ARG_##enc));                 \
-  }
-
-#define TAB(key, op, enc)                                              \
-  { #enc "-" #key, t_##key##_##enc, { TAB_##key TAB_##op TAB_##enc } },
-
-static grand *fib;
-
-TESTS(FUNCS)
-
-static const test_chunk tests[] = {
-  TESTS(TAB)
-  { 0 }
-};
-
-int main(int argc, char *argv[])
-{
-  sub_init();
-  fib = fibrand_create(0);
-  test_run(argc, argv, tests, SRCDIR "/tests/rsa");
-  GR_DESTROY(fib);
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/rsa.h b/rsa.h
deleted file mode 100644 (file)
index f4b1c14..0000000
--- a/rsa.h
+++ /dev/null
@@ -1,404 +0,0 @@
-/* -*-c-*-
- *
- * $Id: rsa.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The RSA public-key cryptosystem
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_RSA_H
-#define CATACOMB_RSA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-#ifndef CATACOMB_KEY_H
-#  include "key.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-#ifndef CATACOMB_PGEN_H
-#  include "pgen.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- RSA private and public keys --- */
-
-typedef struct rsa_pub {
-  mp *n;
-  mp *e;
-} rsa_pub;
-
-typedef struct rsa_priv {
-  mp *n, *p, *q, *q_inv;
-  mp *e, *d, *dp, *dq;
-} rsa_priv;
-
-/* --- RSA private and public key contexts --- *
- *
- * These are used to store information about `active' keys which will speed
- * up the various operations.
- */
-
-typedef struct rsa_privctx {
-  rsa_priv *rp;
-  grand *r;
-  mpmont nm, pm, qm;
-} rsa_privctx;
-
-typedef struct rsa_pubctx {
-  mpmont mm;
-  rsa_pub *rp;
-} rsa_pubctx;
-
-/* --- Encoding and decoding function schemas --- *
- *
- * See `oaep.h' and `pkcs1.h' for appropriate encoding functions.
- */
-
-typedef mp *rsa_pad(mp */*d*/, const void */*m*/, size_t /*msz*/,
-                   octet */*b*/, size_t /*sz*/,
-                   unsigned long /*nbits*/, void */*p*/);
-
-typedef int rsa_decunpad(mp */*m*/, octet */*b*/, size_t /*sz*/,
-                        unsigned long /*nbits*/, void */*p*/);
-
-typedef int rsa_vrfunpad(mp */*s*/, const void */*m*/, size_t /*msz*/,
-                        octet */*b*/, size_t /*sz*/,
-                        unsigned long /*nbits*/, void */*p*/);
-
-/*----- Key fetching ------------------------------------------------------*/
-
-extern const key_fetchdef rsa_pubfetch[];
-#define RSA_PUBFETCHSZ 4
-
-extern const key_fetchdef rsa_privfetch[];
-#define RSA_PRIVFETCHSZ 12
-
-/* --- @rsa_pubfree@, @rsa_privfree@ --- *
- *
- * Arguments:  @rsa_pub *rp@, @rsa_priv *rp@ = pointer to key block
- *
- * Returns:    ---
- *
- * Use:                Frees an RSA key block.
- */
-
-extern void rsa_pubfree(rsa_pub */*rp*/);
-extern void rsa_privfree(rsa_priv */*rp*/);
-
-/*----- RSA private key operations ----------------------------------------*/
-
-/* --- @rsa_privcreate@ --- *
- *
- * Arguments:  @rsa_privctx *rd@ = pointer to an RSA private key context
- *             @rsa_priv *rp@ = pointer to RSA private key
- *             @grand *r@ = pointer to random number source for blinding
- *
- * Returns:    ---
- *
- * Use:                Initializes an RSA private-key context.  Keeping a context
- *             for several decryption or signing operations provides a minor
- *             performance benefit.
- *
- *             The random number source may be null if blinding is not
- *             desired.  This improves decryption speed, at the risk of
- *             permitting timing attacks.
- */
-
-extern void rsa_privcreate(rsa_privctx */*rd*/, rsa_priv */*rp*/,
-                          grand */*r*/);
-
-/* --- @rsa_privdestroy@ --- *
- *
- * Arguments:  @rsa_privctx *rd@ = pointer to an RSA decryption context
- *
- * Returns:    ---
- *
- * Use:                Destroys an RSA decryption context.
- */
-
-extern void rsa_privdestroy(rsa_privctx */*rd*/);
-
-/* --- @rsa_privop@ --- *
- *
- * Arguments:  @rsa_privctx *rd@ = pointer to RSA private key context
- *             @mp *d@ = destination
- *             @mp *c@ = input message
- *
- * Returns:    The transformed output message.
- *
- * Use:                Performs an RSA private key operation.  This function takes
- *             advantage of knowledge of the key factors in order to speed
- *             up decryption.  It also blinds the ciphertext prior to
- *             decryption and unblinds it afterwards to thwart timing
- *             attacks.
- */
-
-extern mp *rsa_privop(rsa_privctx */*rd*/, mp */*d*/, mp */*c*/);
-
-/* --- @rsa_qprivop@ --- *
- *
- * Arguments:  @rsa_priv *rp@ = pointer to RSA parameters
- *             @mp *d@ = destination
- *             @mp *c@ = input message
- *             @grand *r@ = pointer to random number source for blinding
- *
- * Returns:    Correctly transformed output message
- *
- * Use:                Performs an RSA private key operation, very carefully.
- */
-
-extern mp *rsa_qprivop(rsa_priv */*rp*/, mp */*d*/, mp */*c*/, grand */*r*/);
-
-/* --- @rsa_sign@ --- *
- *
- * Arguments:  @rsa_privctx *rp@ = pointer to an RSA private key context
- *             @mp *d@ = where to put the result
- *             @const void *m@ = pointer to input message
- *             @size_t msz@ = size of input message
- *             @rsa_pad *e@ = encoding procedure
- *             @void *earg@ = argument pointer for encoding procedure
- *
- * Returns:    The signature, as a multiprecision integer, or null on
- *             failure.
- *
- * Use:                Computes an RSA digital signature.
- */
-
-extern mp *rsa_sign(rsa_privctx */*rp*/, mp */*d*/,
-                   const void */*m*/, size_t /*msz*/,
-                   rsa_pad */*e*/, void */*earg*/);
-
-/* --- @rsa_decrypt@ --- *
- *
- * Arguments:  @rsa_privctx *rp@ = pointer to an RSA private key context
- *             @mp *m@ = encrypted message, as a multiprecision integer
- *             @dstr *d@ = pointer to output string
- *             @rsa_decunpad *e@ = decoding procedure
- *             @void *earg@ = argument pointer for decoding procedure
- *
- * Returns:    The length of the output string if successful, negative on
- *             failure.
- *
- * Use:                Does RSA decryption.
- */
-
-extern int rsa_decrypt(rsa_privctx */*rp*/, mp */*m*/,
-                      dstr */*d*/, rsa_decunpad */*e*/, void */*earg*/);
-
-/*----- RSA public key operations -----------------------------------------*/
-
-/* --- @rsa_pubcreate@ --- *
- *
- * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
- *             @rsa_pub *rp@ = pointer to RSA public key
- *
- * Returns:    ---
- *
- * Use:                Initializes an RSA public-key context.
- */
-
-extern void rsa_pubcreate(rsa_pubctx */*rd*/, rsa_pub */*rp*/);
-
-/* --- @rsa_pubdestroy@ --- *
- *
- * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
- *
- * Returns:    ---
- *
- * Use:                Destroys an RSA public-key context.
- */
-
-extern void rsa_pubdestroy(rsa_pubctx */*rd*/);
-
-/* --- @rsa_pubop@ --- *
- *
- * Arguments:  @rsa_pubctx *rd@ = pointer to an RSA public key context
- *             @mp *d@ = destination
- *             @mp *p@ = input message
- *
- * Returns:    The transformed output message.
- *
- * Use:                Performs an RSA public key operation.
- */
-
-extern mp *rsa_pubop(rsa_pubctx */*rd*/, mp */*d*/, mp */*p*/);
-
-/* --- @rsa_qpubop@ --- *
- *
- * Arguments:  @rsa_pub *rp@ = pointer to RSA parameters
- *             @mp *d@ = destination
- *             @mp *p@ = input message
- *
- * Returns:    Correctly transformed output message.
- *
- * Use:                Performs an RSA public key operation.
- */
-
-extern mp *rsa_qpubop(rsa_pub */*rp*/, mp */*d*/, mp */*c*/);
-
-/* --- @rsa_encrypt@ --- *
- *
- * Arguments:  @rsa_pubctx *rp@ = pointer to an RSA public key context
- *             @mp *d@ = proposed destination integer
- *             @const void *m@ = pointer to input message
- *             @size_t msz@ = size of input message
- *             @rsa_pad *e@ = encoding procedure
- *             @void *earg@ = argument pointer for encoding procedure
- *
- * Returns:    The encrypted message, as a multiprecision integer, or null
- *             on failure.
- *
- * Use:                Does RSA encryption.
- */
-
-extern mp *rsa_encrypt(rsa_pubctx */*rp*/, mp */*d*/,
-                      const void */*m*/, size_t /*msz*/,
-                      rsa_pad */*e*/, void */*earg*/);
-
-/* --- @rsa_verify@ --- *
- *
- * Arguments:  @rsa_pubctx *rp@ = pointer to an RSA public key contxt
- *             @mp *s@ = the signature, as a multiprecision integer
- *             @const void *m@ = pointer to message to verify, or null
- *             @size_t sz@ = size of input message
- *             @dstr *d@ = pointer to output string, or null
- *             @rsa_vfrunpad *e@ = decoding procedure
- *             @void *earg@ = argument pointer for decoding procedure
- *
- * Returns:    The length of the output string if successful (0 if no output
- *             was wanted); negative on failure.
- *
- * Use:                Does RSA signature verification.  To use a signature scheme
- *             with recovery, pass in @m == 0@ and @d != 0@: the recovered
- *             message should appear in @d@.  To use a signature scheme with
- *             appendix, provide @m != 0@ and @d == 0@; the result should be
- *             zero for success.
- */
-
-extern int rsa_verify(rsa_pubctx */*rp*/, mp */*s*/,
-                     const void */*m*/, size_t /*sz*/, dstr */*d*/,
-                     rsa_vrfunpad */*e*/, void */*earg*/);
-
-/*----- Miscellaneous operations ------------------------------------------*/
-
-/* --- @rsa_gen@ --- *
- *
- * Arguments:  @rsa_priv *rp@ = pointer to block to be filled in
- *             @unsigned nbits@ = required modulus size in bits
- *             @grand *r@ = random number source
- *             @unsigned n@ = number of attempts to make
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for the event handler
- *
- * Returns:    Zero if all went well, nonzero otherwise.
- *
- * Use:                Constructs a pair of strong RSA primes and other useful RSA
- *             parameters.  A small encryption exponent is chosen if
- *             possible.
- */
-
-extern int rsa_gen(rsa_priv */*rp*/, unsigned /*nbits*/,
-                  grand */*r*/, unsigned /*n*/,
-                  pgen_proc */*event*/, void */*ectx*/);
-
-/* --- @rsa_recover@ --- *
- *
- * Arguments:  @rsa_priv *rp@ = pointer to parameter block
- *
- * Returns:    Zero if all went well, nonzero if the parameters make no
- *             sense.
- *
- * Use:                Derives the full set of RSA parameters given a minimal set.
- */
-
-extern int rsa_recover(rsa_priv */*rp*/);
-
-/*----- Padding schemes ---------------------------------------------------*/
-
-/* --- PKCS1 padding --- */
-
-typedef struct pkcs1 {
-  grand *r;                            /* Random number source */
-  const void *ep;                      /* Encoding parameters block */
-  size_t epsz;                         /* Size of the parameter block */
-} pkcs1;
-
-extern rsa_pad pkcs1_cryptencode;
-extern rsa_decunpad pkcs1_cryptdecode;
-extern rsa_pad pkcs1_sigencode;
-extern rsa_vrfunpad pkcs1_sigdecode;
-
-/* --- OAEP --- */
-
-typedef struct oaep {
-  const gccipher *cc;                  /* Cipher class for masking */
-  const gchash *ch;                    /* Hash class for parameter block */
-  grand *r;                            /* Random number source */
-  const void *ep;                      /* Encoding parameters block */
-  size_t epsz;                         /* Size of the parameter block */
-} oaep;
-
-extern rsa_pad oaep_encode;
-extern rsa_decunpad oaep_decode;
-
-/* --- PSS --- */
-
-typedef struct pss {
-  const gccipher *cc;                  /* Cipher class for masking */
-  const gchash *ch;                    /* Hash class for choosing a seed */
-  grand *r;                            /* Random number source */
-  size_t ssz;                          /* Requested salt size */
-} pss;
-
-extern rsa_pad pss_encode;
-extern rsa_vrfunpad pss_decode;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/rspit.c b/rspit.c
deleted file mode 100644 (file)
index e471508..0000000
--- a/rspit.c
+++ /dev/null
@@ -1,1402 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Spit out random numbers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <math.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef PORTABLE
-#  include <unistd.h>
-#endif
-
-#include <mLib/darray.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sub.h>
-
-#include "fipstest.h"
-#include "grand.h"
-#include "maurer.h"
-#include "key.h"
-
-#include "lcrand.h"
-#include "fibrand.h"
-#include "rand.h"
-#include "noise.h"
-
-#include "bbs.h"
-#include "mprand.h"
-
-#include "rc4.h"
-#include "seal.h"
-
-#include "des-ofb.h"
-#include "des3-ofb.h"
-#include "rc2-ofb.h"
-#include "rc5-ofb.h"
-#include "mars-ofb.h"
-#include "skipjack-ofb.h"
-#include "tea-ofb.h"
-#include "xtea-ofb.h"
-#include "blowfish-ofb.h"
-#include "twofish-ofb.h"
-#include "idea-ofb.h"
-#include "cast128-ofb.h"
-#include "cast256-ofb.h"
-#include "noekeon-ofb.h"
-#include "rijndael-ofb.h"
-#include "rijndael192-ofb.h"
-#include "rijndael256-ofb.h"
-#include "safer-ofb.h"
-#include "safersk-ofb.h"
-#include "square-ofb.h"
-#include "serpent-ofb.h"
-
-#include "des-counter.h"
-#include "des3-counter.h"
-#include "rc2-counter.h"
-#include "rc5-counter.h"
-#include "mars-counter.h"
-#include "skipjack-counter.h"
-#include "tea-counter.h"
-#include "xtea-counter.h"
-#include "blowfish-counter.h"
-#include "twofish-counter.h"
-#include "idea-counter.h"
-#include "cast128-counter.h"
-#include "cast256-counter.h"
-#include "noekeon-counter.h"
-#include "rijndael-counter.h"
-#include "rijndael192-counter.h"
-#include "rijndael256-counter.h"
-#include "safer-counter.h"
-#include "safersk-counter.h"
-#include "square-counter.h"
-#include "serpent-counter.h"
-
-#include "md2-mgf.h"
-#include "md4-mgf.h"
-#include "md5-mgf.h"
-#include "sha-mgf.h"
-#include "tiger-mgf.h"
-#include "rmd128-mgf.h"
-#include "rmd160-mgf.h"
-#include "rmd256-mgf.h"
-#include "rmd320-mgf.h"
-
-#include "rmd160.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct gen {
-  const char *name;
-  grand *(*seed)(unsigned /*i*/);
-  unsigned i;
-  const char *help;
-} gen;
-
-extern gen generators[];
-
-#define CIPHERS                                                                \
-  E(DES, des)                                                          \
-  E(DES3, des3)                                                                \
-  E(RC2, rc2)                                                          \
-  E(RC5, rc5)                                                          \
-  E(MARS, mars)                                                                \
-  E(SKIPJACK, skipjack)                                                        \
-  E(TEA, tea)                                                          \
-  E(XTEA, xtea)                                                                \
-  E(BLOWFISH, blowfish)                                                        \
-  E(TWOFISH, twofish)                                                  \
-  E(IDEA, idea)                                                                \
-  E(CAST128, cast128)                                                  \
-  E(CAST256, cast256)                                                  \
-  E(SQUARE, square)                                                    \
-  E(SAFER, safer)                                                      \
-  E(SAFERSK, safersk)                                                  \
-  E(NOEKEON, noekeon)                                                  \
-  E(RIJNDAEL, rijndael)                                                        \
-  E(RIJNDAEL192, rijndael192)                                          \
-  E(RIJNDAEL256, rijndael256)                                          \
-  E(SERPENT, serpent)
-
-#define HASHES                                                         \
-  E(MD2, md2)                                                          \
-  E(MD4, md4)                                                          \
-  E(MD5, md5)                                                          \
-  E(SHA, sha)                                                          \
-  E(TIGER, tiger)                                                      \
-  E(RMD128, rmd128)                                                    \
-  E(RMD160, rmd160)                                                    \
-  E(RMD256, rmd256)                                                    \
-  E(RMD320, rmd320)
-
-#define E(PRE, pre) CIPHER_##PRE,
-enum { CIPHERS CIPHER__bogus };
-#undef E
-
-#define E(PRE, pre) HASH_##PRE,
-enum { HASHES HASH__bogus };
-#undef E
-
-static struct {
-  const octet *keysz;
-  size_t blksz;
-  grand *(*ofb)(const void */*k*/, size_t /*sz*/);
-  grand *(*counter)(const void */*k*/, size_t /*sz*/);
-} ciphertab[] = {
-#define E(PRE, pre)                                                    \
-  { pre##_keysz, PRE##_BLKSZ, pre##_ofbrand, pre##_counterrand },
-  CIPHERS
-#undef E
-};
-
-static struct {
-  const gchash *h;
-  const octet *keysz;
-  grand *(*mgf)(const void */*k*/, size_t /*sz*/);
-} hashtab[] = {
-#define E(PRE, pre)                                                    \
-  { &pre, pre##_mgfkeysz, pre##_mgfrand },
-  HASHES
-#undef E
-};
-
-/*----- Miscellaneous static data -----------------------------------------*/
-
-static FILE *outfp;
-static size_t outsz = 0;
-static unsigned maurer_lo = 5, maurer_hi = 8;
-
-static int argc;
-static char **argv;
-
-static unsigned flags = 0;
-
-#define f_progress 1u
-#define f_file 2u
-#define f_fips 4u
-#define f_maurer 8u
-#define f_timer 16u
-#define f_discard 32u
-
-/*----- Help options ------------------------------------------------------*/
-
-static void usage(FILE *fp)
-{
-  pquis(fp, "Usage: $ generator [options]\n");
-}
-
-static void version(FILE *fp)
-{
-  pquis(fp, "$, Catacomb version " VERSION "\n");
-}
-
-static void help(FILE *fp)
-{
-  version(fp);
-  fputc('\n', fp);
-  usage(fp);
-  pquis(fp, "\n\
-Emits a stream of random bytes suitable for, well, all sorts of things.\n\
-The primary objective is to be able to generate streams of input for\n\
-statistical tests, such as Diehard.\n\
-\n\
-Options are specific to the particular generator, although there's a\n\
-common core set:\n\
-\n\
--h, --help             Display this help message.\n\
--v, --version          Display the program's version number.\n\
--u, --usage            Display a useless usage message.\n\
-\n\
--l, --list             Show a list of the supported generators, with\n\
-                       their options.\n\
--f, --fipstest         Run the FIPS 140-1 randomness test.\n\
--m, --maurer[=LO-HI]   Run Maurer's universal statistical test.\n\
--o, --output FILE      Write output to FILE, not stdout.\n\
--z, --size SIZE                Emit SIZE bytes, not an unlimited number.\n\
--p, --progress         Show a little progress meter (on stderr).\n\
--T, --timer            Keep track of the CPU time used by the generator.\n\
--d, --discard          Discard the generated output.\n\
-\n\
-(A SIZE may be followed by `g' for gigabytes, `m' for megabytes, or\n\
-`k' for kilobytes.  If unqualified, an amount in bytes is assumed.)\n\
-");
-}
-
-/*----- Main options parser -----------------------------------------------*/
-
-static struct option opts[] = {
-
-  /* --- Standard GNU help options --- */
-
-  { "help",    0,              0,      'h' },
-  { "version", 0,              0,      'v' },
-  { "usage",   0,              0,      'u' },
-
-  /* --- Other useful things --- */
-
-  { "list",    0,              0,      'l' },
-  { "fipstest",        0,              0,      'f' },
-  { "maurer",  OPTF_ARGOPT,    0,      'm' },
-  { "output",  OPTF_ARGREQ,    0,      'o' },
-  { "size",    OPTF_ARGREQ,    0,      'z' },
-  { "progress",        0,              0,      'p' },
-  { "timer",   0,              0,      'T' },
-  { "discard", 0,              0,      'd' },
-
-  /* --- End of main table --- */
-
-  { 0,         0,              0,      0 }
-};
-
-static const char *sopts = "hvu lfm::o:z:pTd";
-
-#ifndef OPTION_V
-   DA_DECL(option_v, struct option);
-#  define OPTION_V
-#endif
-
-static option_v optv = DA_INIT;
-static dstr optd = DSTR_INIT;
-
-/* --- @addopts@ --- *
- *
- * Arguments:  @const char *s@ = pointer to short options
- *             @struct option *l@ = pointer to long options
- *
- * Returns:    ---
- *
- * Use:                Adds a collection of options to the table.
- */
-
-static void addopts(const char *s, struct option *l)
-{
-  dstr_puts(&optd, s);
-  if (DA_LEN(&optv))
-    DA_SHRINK(&optv, 1);
-  while (l->name)
-    DA_PUSH(&optv, *l++);
-  DA_PUSH(&optv, *l);
-}
-
-/* --- @opt@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    Next option from argument array.
- *
- * Use:                Fetches options, handling the standard ones.
- */
-
-static int opt(void)
-{
-  for (;;) {
-    int i = mdwopt(argc, argv, optd.buf, DA(&optv), 0, 0, 0);
-    switch (i) {
-      case 'h':
-       help(stdout);
-       exit(0);
-      case 'v':
-       version(stdout);
-       exit(0);
-      case 'u':
-       usage(stdout);
-       exit(0);
-      case 'l': {
-       gen *g;
-       puts("Generators supported:");
-       for (g = generators; g->name; g++)
-         printf("  %s %s\n", g->name, g->help);
-       exit(0);
-      } break;
-      case 'f':
-       flags |= f_fips;
-       break;
-      case 'm':
-       flags |= f_maurer;
-       if (optarg) {
-         char *p;
-         unsigned long lo, hi;
-         lo = strtoul(optarg, &p, 0);
-         if (*p == '-' || *p == ',')
-           hi = strtoul(p + 1, &p, 0);
-         else
-           hi = lo;
-         if (*p != 0 || hi < lo || lo == 0)
-           die(EXIT_FAILURE, "bad bit range `%s'", optarg);
-         maurer_lo = lo;
-         maurer_hi = hi;
-       }
-       break;
-      case 'o':
-       if (flags & f_file)
-         die(EXIT_FAILURE, "already set an output file");
-       if (strcmp(optarg, "-") == 0)
-         outfp = stdout;
-       else {
-         outfp = fopen(optarg, "w");
-         if (!outfp) {
-           die(EXIT_FAILURE, "couldn't open output file `%s': %s",
-               optarg, strerror(errno));
-         }
-       }
-       flags |= f_file;
-       break;
-      case 'z': {
-       char *p;
-       outsz = strtoul(optarg, &p, 0);
-       if (!outsz)
-         die(EXIT_FAILURE, "bad number `%s'", optarg);
-       switch (*p) {
-         case 'G': case 'g': outsz *= 1024;
-         case 'M': case 'm': outsz *= 1024;
-         case 'K': case 'k': outsz *= 1024;
-         case 0:
-           break;
-         default:
-           die(EXIT_FAILURE, "bad suffix `%s'", p);
-           break;
-       }
-       if (*p && p[1] != 0)
-         die(EXIT_FAILURE, "bad suffix `%s'", p);
-      } break;
-      case 'p':
-       flags |= f_progress;
-       break;
-      case 'T':
-       flags |= f_timer;
-       break;
-      case 'd':
-       flags |= f_discard;
-       break;
-      default:
-       return (i);
-    }
-  }
-}
-
-/*----- Manglers for seed strings -----------------------------------------*/
-
-/* --- @unhex@ --- *
- *
- * Arguments:  @const char *p@ = pointer to input string
- *             @char **end@ = where the end goes
- *             @dstr *d@ = output buffer
- *
- * Returns:    ---
- *
- * Use:                Transforms a hex string into a chunk of binary data.
- */
-
-static void unhex(const char *p, char **end, dstr *d)
-{
-  while (p[0] && p[1]) {
-    int x = p[0], y = p[1];
-    if ('0' <= x && x <= '9') x -= '0';
-    else if ('A' <= x && x <= 'F') x -= 'A' - 10;
-    else if ('a' <= x && x <= 'f') x -= 'a' - 10;
-    else x = 0;
-    if ('0' <= y && y <= '9') y -= '0';
-    else if ('A' <= y && y <= 'F') y -= 'A' - 10;
-    else if ('a' <= y && y <= 'f') y -= 'a' - 10;
-    else y = 0;
-    DPUTC(d, (x << 4) + y);
-    p += 2;
-  }
-  *end = (char *)p;
-}
-
-/* --- Generate a key --- */
-
-static void textkey(dstr *d, const char *p, const octet *ksz)
-{
-  size_t sz = strlen(p);
-
-  if (!sz)
-    die(EXIT_FAILURE, "zero-length key string");
-  if (keysz(sz, ksz) != sz)
-    DPUTM(d, p, sz);
-  else {
-    rmd160_mgfctx g;
-    rmd160_mgfinit(&g, p, sz);
-    sz = keysz(0, ksz);
-    dstr_ensure(d, sz);
-    rmd160_mgfencrypt(&g, 0, d->buf, sz);
-    d->len += sz;
-  }
-  assert(((void)"I can't seem to choose a good key size",
-         keysz(d->len, ksz) == d->len));
-}
-
-static void hexkey(dstr *d, const char *p, const octet *ksz)
-{
-  char *q;
-  unhex(optarg, &q, d);
-  if (*q)
-    die(EXIT_FAILURE, "bad hex key `%s'", p);
-  if (keysz(d->len, ksz) != d->len)
-    die(EXIT_FAILURE, "bad key length");
-}
-
-static void randkey(dstr *d, const octet *ksz)
-{
-  size_t sz = keysz(0, ksz);
-  dstr_ensure(d, sz);
-  rand_get(RAND_GLOBAL, d->buf, sz);
-  d->len += sz;
-}
-
-/*----- Generators --------------------------------------------------------*/
-
-/* --- Blum-Blum-Shub strong generator --- */
-
-static grand *gen_bbs(unsigned i)
-{
-  /* --- Default modulus --- *
-   *
-   * The factors of this number are
-   *
-   *  @p = 1229936431484295969649886203367009966370895964206162032259292413@
-   *     @7754313537966036459299022912838407755462506416274551744201653277@
-   *     @313130311731673973886822067@
-   *
-   *  @q = 9798171783943489959487301695884963889684294764514008432498259742@
-   *     @5374320073594018817245784145742769603334292182227671519041431067@
-   *     @61344781426317516045890159@
-   *
-   * Both %$p$% and %$q$% are prime; %$(p - 1)/2$% and %$(q - 1)/2$% have no
-   * common factors.  They were found using this program, with random
-   * starting points.
-   *
-   * I hope that, by publishing these factors, I'll dissuade people from
-   * actually using this modulus in an attempt to attain real security.  The
-   * program is quite quick at finding Blum numbers, so there's no excuse for
-   * not generating your own.
-   */
-
-  const char *mt =
-    "12051128439013574251357214209433471144307319411973256935382082"
-    "84356405274180923922403660880355098909699130818163691602989614"
-    "90135716255689660470370755013177656905237112577648090277537209"
-    "93607817155427455344810369808478266925293635284364998010510985"
-    "0503830397166360721262431179505917248447259735253684659338653";
-
-  /* --- Other things --- */
-
-  grand *r;
-  const char *xt = 0;
-  unsigned bits = 1024;
-  mp *m, *x;
-  unsigned show = 0;
-  const char *kfile = 0, *id = 0, *ktype = 0;
-
-  /* --- Parse options --- */
-
-  static struct option opts[] = {
-    { "modulus",       OPTF_ARGREQ,    0,      'M' },
-    { "generate",      0,              0,      'g' },
-    { "seed",          OPTF_ARGREQ,    0,      's' },
-    { "bits",          OPTF_ARGREQ,    0,      'b' },
-    { "show",          0,              0,      'S' },
-    { "keyring",       OPTF_ARGREQ,    0,      'k' },
-    { "id",            OPTF_ARGREQ,    0,      'i' },
-    { "type",          OPTF_ARGREQ,    0,      't' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("M:gs:b:Sk:i:t:", opts);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 'M':
-       mt = optarg;
-       break;
-      case 'g':
-       mt = 0;
-       break;
-      case 's':
-       xt = optarg;
-       break;
-      case 'b':
-       bits = strtoul(optarg, 0, 0);
-       if (bits == 0)
-         die(EXIT_FAILURE, "bad number of bits `%s'", optarg);
-       break;
-      case 'S':
-       show = 1;
-       break;
-      case 'k':
-       kfile = optarg;
-       mt = 0;
-       break;
-      case 'i':
-       id = optarg;
-       mt = 0;
-       break;
-      case 't':
-       ktype = optarg;
-       mt = 0;
-       break;
-      default:
-       return (0);
-    }
-  }
-
-  /* --- Generate a modulus if one is requested --- */
-
-  if (mt) {
-    char *p;
-    m = mp_readstring(MP_NEW, mt, &p, 0);
-    if (!m || *p || (m->v[0] & 3) != 1)
-      die(EXIT_FAILURE, "bad modulus `%s'", mt);
-    /* Unfortunately I don't know how to test for a Blum integer */
-  } else if (kfile || id || ktype) {
-    key_file kf;
-    key *kk;
-    key_data *kd;
-
-    /* --- Open the key file --- */
-
-    if (!kfile)
-      kfile = "keyring";
-    if (key_open(&kf, kfile, KOPEN_READ, key_moan, 0)) {
-      die(EXIT_FAILURE, "error opening key file `%s': %s",
-         kfile, strerror(errno));
-    }
-
-    /* --- Find the key --- */
-
-    if (id) {
-      if ((kk = key_bytag(&kf, id)) == 0)
-       die(EXIT_FAILURE, "key `%s' not found", id);
-    } else {
-      if (!ktype)
-       ktype = "bbs";
-      if ((kk = key_bytype(&kf, ktype)) == 0)
-       die(EXIT_FAILURE, "no suitable key with type `%s' found", ktype);
-    }
-
-    /* --- Read the key data --- */
-
-    if ((kk->k->e & KF_ENCMASK) != KENC_STRUCT)
-      die(EXIT_FAILURE, "key is not structured");
-    if ((kd = key_structfind(kk->k, "n")) == 0)
-      die(EXIT_FAILURE, "key has no subkey `n'");
-    if ((kd->e & KF_ENCMASK) != KENC_MP)
-      die(EXIT_FAILURE, "incompatible subkey encoding");
-    m = MP_COPY(kd->u.m);
-    key_close(&kf);
-  } else {
-    bbs_priv bp;
-
-    if (bbs_gen(&bp, bits, &rand_global, 0,
-               (flags & f_progress) ? pgen_ev : 0, 0))
-      die(EXIT_FAILURE, "modulus generation failed");
-    m = bp.n;
-
-    if (show) {
-      fputs("p = ", stderr);
-      mp_writefile(bp.p, stderr, 10);
-      fputs("\nq = ", stderr);
-      mp_writefile(bp.q, stderr, 10);
-      fputs("\nn = ", stderr);
-      mp_writefile(bp.n, stderr, 10);
-      fputc('\n', stderr);
-    }
-
-    mp_drop(bp.p);
-    mp_drop(bp.q);
-  }
-
-  /* --- Set up a seed --- */
-
-  if (!xt)
-    x = mprand(MP_NEW, mp_bits(m) - 1, &rand_global, 1);
-  else {
-    char *p;
-    x = mp_readstring(MP_NEW, xt, &p, 0);
-    if (*p)
-      die(EXIT_FAILURE, "bad modulus `%s'", xt);
-  }
-
-  /* --- Right --- */
-
-  r = bbs_rand(m, x);
-
-  mp_drop(m);
-  mp_drop(x);
-  return (r);
-}
-
-/* --- Catacomb's random number generator --- */
-
-static grand *gen_rand(unsigned i)
-{
-  grand *r = rand_create();
-  dstr d = DSTR_INIT;
-
-  static struct option opts[] = {
-    { "key",           OPTF_ARGREQ,    0,      'k' },
-    { "text",          OPTF_ARGREQ,    0,      't' },
-    { "hex",           OPTF_ARGREQ,    0,      'H' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("k:t:H:n", opts);
-
-  r->ops->misc(r, RAND_NOISESRC, &noise_source);
-  r->ops->misc(r, RAND_SEED, 160);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 'k':
-       DRESET(&d);
-       textkey(&d, optarg, rmd160_hmackeysz);
-       r->ops->misc(r, RAND_KEY, d.buf, d.len);
-       break;
-      case 't':
-       r->ops->misc(r, GRAND_SEEDBLOCK, optarg, strlen(optarg));
-       break;
-      case 'H':
-       DRESET(&d);
-       hexkey(&d, optarg, rmd160_hmackeysz);
-       r->ops->misc(r, GRAND_SEEDBLOCK, d.buf, d.len);
-       break;
-    }
-  }
-
-  dstr_destroy(&d);
-  return (r);
-}
-
-/* --- RC4 output --- */
-
-static grand *gen_rc4(unsigned i)
-{
-  grand *r;
-  dstr d = DSTR_INIT;
-
-  static struct option opts[] = {
-    { "key",           OPTF_ARGREQ,    0,      'k' },
-    { "hex",           OPTF_ARGREQ,    0,      'H' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("k:H:", opts);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 'k':
-       DRESET(&d);
-       textkey(&d, optarg, rc4_keysz);
-       break;
-      case 'H':
-       DRESET(&d);
-       hexkey(&d, optarg, rc4_keysz);
-       break;
-      default:
-       return (0);
-    }
-  }
-
-  if (!d.len)
-    randkey(&d, rc4_keysz);
-  r = rc4_rand(d.buf, d.len);
-  dstr_destroy(&d);
-  return (r);
-}
-
-/* --- SEAL output --- */
-
-static grand *gen_seal(unsigned i)
-{
-  grand *r;
-  dstr d = DSTR_INIT;
-  uint32 n = 0;
-
-  static struct option opts[] = {
-    { "key",           OPTF_ARGREQ,    0,      'k' },
-    { "hex",           OPTF_ARGREQ,    0,      'H' },
-    { "sequence",      OPTF_ARGREQ,    0,      'n' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("k:H:n:", opts);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 'k':
-       DRESET(&d);
-       textkey(&d, optarg, seal_keysz);
-       break;
-      case 'H':
-       DRESET(&d);
-       hexkey(&d, optarg, seal_keysz);
-       break;
-      case 'n': {
-       char *p;
-       n = strtoul(optarg, &p, 0);
-       if (*p)
-         die(EXIT_FAILURE, "bad number `%s'", optarg);
-      } break;
-      default:
-       return (0);
-    }
-  }
-
-  if (!d.len)
-    randkey(&d, seal_keysz);
-  r = seal_rand(d.buf, d.len, n);
-  dstr_destroy(&d);
-  return (r);
-}
-
-/* --- Output feedback generators --- */
-
-static grand *gen_ofb(unsigned i)
-{
-  grand *r;
-  dstr d = DSTR_INIT;
-  dstr iv = DSTR_INIT;
-
-  static struct option opts[] = {
-    { "key",           OPTF_ARGREQ,    0,      'k' },
-    { "hex",           OPTF_ARGREQ,    0,      'H' },
-    { "iv",            OPTF_ARGREQ,    0,      'i' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("k:H:i:", opts);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 'k':
-       DRESET(&d);
-       textkey(&d, optarg, ciphertab[i].keysz);
-       break;
-      case 'H':
-       DRESET(&d);
-       hexkey(&d, optarg, ciphertab[i].keysz);
-       break;
-      case 'i': {
-       char *p;
-       unhex(optarg, &p, &iv);
-       if (*p)
-         die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
-      } break;
-      default:
-       return (0);
-    }
-  }
-
-  if (!d.len)
-    randkey(&d, ciphertab[i].keysz);
-  r = ciphertab[i].ofb(d.buf, d.len);
-  if (iv.len) {
-    if (iv.len != ciphertab[i].blksz) {
-      die(EXIT_FAILURE, "bad IV length %lu (must be %lu)",
-         (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz);
-    }
-    r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf);
-  }
-
-  dstr_destroy(&d);
-  dstr_destroy(&iv);
-  return (r);
-}
-
-/* --- Counter generators --- */
-
-static grand *gen_counter(unsigned i)
-{
-  grand *r;
-  dstr d = DSTR_INIT;
-  dstr iv = DSTR_INIT;
-
-  static struct option opts[] = {
-    { "key",           OPTF_ARGREQ,    0,      'k' },
-    { "hex",           OPTF_ARGREQ,    0,      'H' },
-    { "iv",            OPTF_ARGREQ,    0,      'i' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("k:H:i:", opts);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 'k':
-       DRESET(&d);
-       textkey(&d, optarg, ciphertab[i].keysz);
-       break;
-      case 'H':
-       DRESET(&d);
-       hexkey(&d, optarg, ciphertab[i].keysz);
-       break;
-      case 'i': {
-       char *p;
-       unhex(optarg, &p, &iv);
-       if (*p)
-         die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
-      } break;
-      default:
-       return (0);
-    }
-  }
-
-  if (!d.len)
-    randkey(&d, ciphertab[i].keysz);
-  r = ciphertab[i].counter(d.buf, d.len);
-  if (iv.len) {
-    if (iv.len != ciphertab[i].blksz) {
-      die(EXIT_FAILURE, "bad IV length %lu (must be %lu)",
-         (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz);
-    }
-    r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf);
-  }
-
-  dstr_destroy(&d);
-  dstr_destroy(&iv);
-  return (r);
-}
-
-/* --- Mask generators --- */
-
-static grand *gen_mgf(unsigned i)
-{
-  grand *r;
-  dstr d = DSTR_INIT;
-  uint32 c = 0;
-
-  static struct option opts[] = {
-    { "key",           OPTF_ARGREQ,    0,      'k' },
-    { "hex",           OPTF_ARGREQ,    0,      'H' },
-    { "index",         OPTF_ARGREQ,    0,      'i' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("k:H:i:", opts);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 'k':
-       DRESET(&d);
-       textkey(&d, optarg, hashtab[i].keysz);
-       break;
-      case 'H':
-       DRESET(&d);
-       hexkey(&d, optarg, hashtab[i].keysz);
-       break;
-      case 'i': {
-       char *p;
-       c = strtoul(optarg, &p, 0);
-       if (*p)
-         die(EXIT_FAILURE, "bad index `%s'", optarg);
-      } break;
-      default:
-       return (0);
-    }
-  }
-
-  if (!d.len)
-    randkey(&d, hashtab[i].keysz);
-
-  r = hashtab[i].mgf(d.buf, d.len);
-  if (c)
-    r->ops->misc(r, GRAND_SEEDUINT32, c);
-
-  dstr_destroy(&d);
-  return (r);
-}
-
-/* --- Fibonacci generator --- */
-
-static grand *gen_fib(unsigned i)
-{
-  grand *r;
-  uint32 s = 0;
-  char *p;
-  unsigned set = 0;
-
-  static struct option opts[] = {
-    { "seed",          OPTF_ARGREQ,    0,      's' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("s:", opts);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 's':
-       s = strtoul(optarg, &p, 0);
-       if (*p)
-         die(EXIT_FAILURE, "bad integer `%s'", optarg);
-       set = 1;
-       break;
-      default:
-       return (0);
-    }
-  }
-  r = fibrand_create(s);
-  if (!set)
-    r->ops->misc(r, GRAND_SEEDRAND, &rand_global);
-  return (r);
-}
-
-/* --- LC generator --- */
-
-static grand *gen_lc(unsigned i)
-{
-  uint32 s = 0;
-  char *p;
-  unsigned set = 0;
-
-  static struct option opts[] = {
-    { "seed",          OPTF_ARGREQ,    0,      's' },
-    { 0,               0,              0,      0 }
-  };
-
-  addopts("s:", opts);
-
-  for (;;) {
-    int o = opt();
-    if (o < 0)
-      break;
-    switch (o) {
-      case 's':
-       s = strtoul(optarg, &p, 0);
-       if (*p)
-         die(EXIT_FAILURE, "bad integer `%s'", optarg);
-       set = 1;
-       break;
-      default:
-       return (0);
-    }
-  }
-  if (!set) {
-    do
-      s = rand_global.ops->range(&rand_global, LCRAND_P);
-    while (s == LCRAND_FIXEDPT);
-  }
-  return (lcrand_create(s));
-}
-
-/* --- Basic options parser -- can't generate output --- */
-
-static grand *gen_opts(unsigned i)
-{
-  while (opt() >= 0)
-    ;
-  return (0);
-}
-
-/*----- Generators table --------------------------------------------------*/
-
-gen generators[] = {
-  { "fibonacci",       gen_fib,        0,
-    "[-s SEED]" },
-  { "lc",              gen_lc,         0,
-    "[-s SEED]" },
-#define E(PRE, pre)                                                    \
-  { #pre "-ofb",       gen_ofb,        CIPHER_##PRE,                   \
-    "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
-  CIPHERS
-#undef E
-#define E(PRE, pre)                                                    \
-  { #pre "-counter",   gen_counter,    CIPHER_##PRE,                   \
-    "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
-  CIPHERS
-#undef E
-#define E(PRE, pre)                                                    \
-  { #pre "-mgf",       gen_mgf,        HASH_##PRE,                     \
-    "[-k KEY-PHRASE] [-H HEX-KEY] [-i INDEX]" },
-  HASHES
-#undef E
-  { "rc4",             gen_rc4,        0,
-    "[-k KEY-PHRASE] [-H HEX-KEY]" },
-  { "seal",            gen_seal,       0,
-    "[-k KEY-PHRASE] [-H HEX-KEY] [-n SEQ]" },
-  { "rand",            gen_rand,       0,
-    "[-n] [-k KEY-PHRASE] [-t TEXT-BLOCK] [-H HEX-BLOCK]" },
-  { "bbs",             gen_bbs,        0,
-    "[-gS] [-s SEED] [-M MODULUS] [-b BITS] [-k KEYRING] [-i TAG] [-t TYPE]"
-  },
-  { 0,                 0,              0, 0 },
-};
-
-static gen optsg = { "options", gen_opts, 0,
-                    "This message shouldn't be printed." };
-
-/*----- Random number generation ------------------------------------------*/
-
-static int genfile(const void *buf, size_t sz, void *p)
-{
-  FILE *fp = p;
-  if (fwrite(buf, 1, sz, fp) != sz)
-    die(EXIT_FAILURE, "error writing to file: %s", strerror(errno));
-  return (0);
-}
-
-static int genbuf(const void *buf, size_t sz, void *p)
-{
-  octet **pp = p;
-  memcpy(*pp, buf, sz);
-  *pp += sz;
-  return (0);
-}
-
-typedef struct genmaurer_ctx {
-  size_t n;
-  maurer_ctx *m;
-} genmaurer_ctx;
-
-static int genmaurer(const void *buf, size_t sz, void *p)
-{
-  genmaurer_ctx *g = p;
-  size_t i;
-
-  for (i = 0; i < g->n; i++)
-    maurer_test(&g->m[i], buf, sz);
-  return (0);
-}
-
-static int generate(grand *r, size_t outsz,
-                   int (*func)(const void *buf, size_t sz, void *p),
-                   void *p)
-{
-  static char kmg[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 };
-
-  unsigned percent = 0;
-  size_t kb = 0;
-  time_t last;
-  static char baton[] = "-\\|/";
-  char *bp;
-  int rc;
-  clock_t clk = 0;
-
-  /* --- Spit out random data --- */
-
-  last = time(0);
-  bp = baton;
-  if (flags & f_progress) {
-    char *errbuf = xmalloc(BUFSIZ);
-    setvbuf(stderr, errbuf, _IOLBF, BUFSIZ);
-    if (outsz)
-      fprintf(stderr, "[%*s]   0%%    0\r[/\b", 50, "");
-    else
-      fputs("[ ]    0\r[/\b", stderr);
-    fflush(stderr);
-  }
-
-#ifdef SIGPIPE
-  signal(SIGPIPE, SIG_IGN);
-#endif
-
-  do {
-    octet buf[BUFSIZ];
-    size_t sz = sizeof(buf);
-    clock_t c_start, c_stop;
-
-    /* --- Emit a bufferful (or less) of data --- */
-
-    if (outsz) {
-      if (sz > outsz - kb)
-       sz = outsz - kb;
-    }
-    c_start = clock();
-    r->ops->fill(r, buf, sz);
-    c_stop = clock();
-    clk += c_stop - c_start;
-    if (func && (rc = func(buf, sz, p)) != 0)
-      return (rc);
-    kb += sz;
-
-    /* --- Update the display --- */
-
-    if (flags & f_progress) {
-      time_t t = time(0);
-      unsigned up = 0;
-
-      if (percent > 100)
-       up = 1;
-
-      if (!outsz) {
-       if (difftime(t, last) > 1.0) {
-         up = 1;
-       }
-       if (up)
-         fputs(" ] ", stderr);
-      } else {
-       unsigned pc = kb * 100.0 / outsz;
-       if (pc > percent || percent > 100 || difftime(t, last) > 1.0) {
-         if (percent > 100)
-           percent = 0;
-         percent &= ~1;
-         for (; percent < (pc & ~1); percent += 2)
-           putc('.', stderr);
-         percent = pc;
-         for (; pc < 100; pc += 2)
-           putc(' ', stderr);
-         fprintf(stderr, "] %3i%% ", percent);
-         up = 1;
-       }
-      }
-
-      if (up) {
-       size_t q = kb;
-       char *kk = kmg;
-       while (q > 8192 && kk[1]) {
-         q >>= 10;
-         kk++;
-       }
-       fprintf(stderr, "%4i%c\r[", q, *kk);
-       if (outsz) {
-         unsigned pc;
-         for (pc = 0; pc < (percent & ~1); pc += 2)
-           putc('.', stderr);
-       }
-       last = t;
-      }
-
-      if (percent > 100)
-       percent = 0;
-
-      if (percent < 100) {
-       putc(*bp++, stderr);
-       putc('\b', stderr);
-       if (!*bp)
-         bp = baton;
-      }
-      fflush(stderr);
-    }
-
-    /* --- Terminate the loop --- */
-
-  } while (!outsz || kb < outsz);
-
-  if (flags & f_progress)
-    fputc('\n', stderr);
-  if (flags & f_timer) {
-    fprintf(stderr, "generated %lu bytes ", (unsigned long)outsz);
-    if (!clk)
-      fputs("too quickly to measure\n", stderr);
-    else {
-      char *kk;
-      double sec = (double)clk/CLOCKS_PER_SEC;
-      double bps = (outsz << 3)/sec;
-      for (kk = kmg; bps > 1024 && kk[1]; kk++, bps /= 1024)
-       ;
-      fprintf(stderr, "in %g secs (%g %cb/s)\n", sec, bps, *kk);
-    }
-  }
-  return (0);
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-int main(int ac, char *av[])
-{
-  gen *g = &optsg;
-  grand *r;
-
-  /* --- Initialize mLib --- */
-
-  ego(av[0]);
-  sub_init();
-
-  /* --- Set up the main Catacomb generator --- */
-
-  rand_noisesrc(RAND_GLOBAL, &noise_source);
-  rand_seed(RAND_GLOBAL, 160);
-
-  /* --- Initialize the options table --- */
-
-  addopts(sopts, opts);
-  argc = ac;
-  argv = av;
-  outfp = stdout;
-
-  /* --- Read the generator out of the first argument --- */
-
-  if (argc > 1 && *argv[1] != '-') {
-    const char *arg = av[1];
-    size_t sz = strlen(arg);
-    gen *gg;
-
-    g = 0;
-    for (gg = generators; gg->name; gg++) {
-      if (strncmp(arg, gg->name, sz) == 0) {
-       if (gg->name[sz] == 0) {
-         g = gg;
-         break;
-       } else if (g)
-         die(EXIT_FAILURE, "ambiguous generator name `%s'", arg);
-       else
-         g = gg;
-      }
-    }
-    if (!g)
-      die(EXIT_FAILURE, "unknown generator name `%s'", arg);
-    argc--;
-    argv++;
-  }
-
-  /* --- Get a generic random number generator --- */
-
-  r = g->seed(g->i);
-  if (!r || optind != ac - 1) {
-    usage(stderr);
-    exit(EXIT_FAILURE);
-  }
-
-  /* --- Do the FIPS test --- */
-
-  if (flags & f_fips) {
-    octet buf[FIPSTEST_BUFSZ];
-    unsigned rc;
-    octet *p = buf;
-
-    generate(r, sizeof(buf), genbuf, &p);
-    rc = fipstest(buf);
-    if (rc & FIPSTEST_MONOBIT)
-      moan("failed monobit test");
-    if (rc & FIPSTEST_POKER)
-      moan("failed poker test");
-    if (rc & FIPSTEST_RUNS)
-      moan("failed runs test");
-    if (rc & FIPSTEST_LONGRUNS)
-      moan("failed long runs test");
-    if (!rc && (flags & f_progress))
-      fputs("test passed\n", stderr);
-    return (rc ? EXIT_FAILURE : 0);
-  }
-
-  /* --- Do Maurer's test --- */
-
-  if (flags & f_maurer) {
-    size_t bufsz;
-    unsigned i;
-    unsigned rc = 0;
-    genmaurer_ctx g;
-
-    static struct { double x; const char *sig; } sigtab[] = {
-      { 3.2905, "1e-3" },
-      { 3.0902, "2e-3" },
-      { 2.8070, "5e-3" },
-      { 2.5758, "1e-2" },
-      { 0     , 0      }
-    };
-
-    g.n = maurer_hi - maurer_lo + 1;
-    g.m = xmalloc(g.n * sizeof(maurer_ctx));
-    for (i = 0; i < g.n; i++)
-      maurer_init(&g.m[i], i + maurer_lo);
-    bufsz = (100 * maurer_hi) << maurer_hi;
-
-    generate(r, bufsz, genmaurer, &g);
-
-    for (i = maurer_lo; i <= maurer_hi; i++) {
-      double z = maurer_done(&g.m[i - maurer_lo]);
-      double zz = fabs(z);
-      unsigned j;
-
-      for (j = 0; sigtab[j].sig; j++) {
-       if (zz > sigtab[j].x) {
-         rc = EXIT_FAILURE;
-         moan("failed, bits = %u, sig = %s, Z_u = %g",
-              i, sigtab[j].sig, z);
-         break;
-       }
-      }
-      if (flags & f_progress)
-       fprintf(stderr, "bits = %u, Z_u = %g\n", i, z);
-    }
-
-    xfree(g.m);
-    return (rc);
-  }
-
-  /* --- Discard --- */
-
-  if (flags & f_discard) {
-    generate(r, outsz, 0, 0);
-    return (0);
-  }
-
-  /* --- Write to a file --- */
-
-#ifndef PORTABLE
-  if (!(flags & f_file) && isatty(STDOUT_FILENO))
-    die(EXIT_FAILURE, "writing output to a terminal is a bad idea");
-#endif
-
-  generate(r, outsz, genfile, outfp);
-
-  /* --- Done --- */
-
-  r->ops->destroy(r);
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/safer-mktab.c b/safer-mktab.c
deleted file mode 100644 (file)
index 869d66f..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/* -*-c-*-
- *
- * $Id: safer-mktab.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate tables for SAFER
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/bits.h>
-
-/*----- Main code ---------------------------------------------------------*/
-
-int main(void)
-{
-  octet s[256], si[256];
-  unsigned x, i;
-
-  x = 1;
-  for (i = 0; i < 256; i++) {
-    if (x < 256) {
-      s[i] = x;
-      si[x] = i;
-    }
-    x = (x * 45)%257;
-  }
-  s[128] = 0;
-  si[0] = 128;
-
-  fputs("\
-/* -*-c-*-\n\
- *\n\
- * SAFER tables [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_SAFER_TAB_H\n\
-#define CATACOMB_SAFER_TAB_H\n\
-\n\
-", stdout);
-
-  fputs("\
-/* --- S-boxes --- */\n\
-\n\
-#define SAFER_S {                                                      \\\n\
-  ", stdout);
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", s[i]);
-    if (i == 255)
-      fputs("                  \\\n}\n\n", stdout);
-    else if ((i + 1)%8 == 0)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  fputs("\
-#define SAFER_SI {                                                     \\\n\
-  ", stdout);
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", si[i]);
-    if (i == 255)
-      fputs("                  \\\n}\n\n", stdout);
-    else if ((i + 1)%8 == 0)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  puts("#endif");
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/safer.c b/safer.c
deleted file mode 100644 (file)
index 6a63565..0000000
--- a/safer.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/* -*-c-*-
- *
- * $Id: safer.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The SAFER block cipher
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "paranoia.h"
-#include "safer.h"
-#include "safer-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet safer_keysz[] = { KSZ_SET, 8, 16, 0 };
-
-/*----- Important tables --------------------------------------------------*/
-
-static const octet s[265] = SAFER_S, si[256] = SAFER_SI;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @safer_setup@ --- *
- *
- * Arguments:  @safer_ctx *k@ = pointer to context to initialize
- *             @unsigned r@ = number of rounds wanted
- *             @unsigned f@ = various other flags
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of key material in bytes
- *
- * Returns:    ---
- *
- * Use:                Initializes an SAFER expanded key.  A default number of
- *             rounds is chosen, based on the key length.
- */
-
-struct ksched {
-  unsigned i;
-  octet x[9];
-};
-
-static void init(struct ksched *t, const octet *k)
-{
-  memcpy(t->x, k, 8);
-  t->i = 1;
-}
-
-static void init_sk(struct ksched *t, const octet *k)
-{
-  unsigned i;
-  octet x;
-  memcpy(t->x, k, 8);
-  for (x = 0, i = 0; i < 8; x ^= k[i++])
-    ;
-  t->x[8] = x;
-  t->i = 1;
-}
-
-static void next(struct ksched *t, octet *k)
-{
-  unsigned i;
-  if (k) {
-    memcpy(k, t->x, 8);
-    if (t->i > 1) {
-      for (i = 0; i < 8; i++)
-       k[i] += s[s[U8(9*t->i + i + 1)]];
-    }
-  }
-  for (i = 0; i < 8; i++)
-    t->x[i] = ROL8(t->x[i], 3);
-  t->i++;
-}
-
-static void next_sk(struct ksched *t, octet *k)
-{
-  unsigned i;
-  i = (t->i - 1)%9;
-  if (k) {
-    if (i < 2)
-      memcpy(k, t->x + i, 8);
-    else {
-      memcpy(k, t->x + i, 9 - i);
-      memcpy(k + 9 - i, t->x, i - 1);
-    }
-    if (t->i > 1) {
-      for (i = 0; i < 8; i++)
-       k[i] += s[s[U8(9*t->i + i + 1)]];
-    }
-  }
-  for (i = 0; i < 9; i++)
-    t->x[i] = ROL8(t->x[i], 3);
-  t->i++;
-}
-
-void safer_setup(safer_ctx *k, unsigned r, unsigned f,
-                const void *buf, size_t sz)
-{
-  struct ksched ka, kb;
-  void (*in)(struct ksched *, const octet *);
-  void (*nx)(struct ksched *, octet *);
-  octet *kk;
-
-  assert(r <= SAFER_MAXROUNDS);
-  KSZ_ASSERT(safer, sz);
-
-  if (f & SAFER_SK) {
-    in = init_sk;
-    nx = next_sk;
-  } else {
-    in = init;
-    nx = next;
-  }
-
-  in(&kb, buf);
-  in(&ka, sz == 8 ? buf : (const octet *)buf + 8);
-
-  k->r = r;
-  kk = k->k;
-  while (r) {
-    nx(&ka, kk); nx(&kb, 0); kk += 8;
-    nx(&kb, kk); nx(&ka, 0); kk += 8;
-    r--;
-  }
-  nx(&ka, kk); kk += 8;
-}
-
-/* --- @safer_init@, @safersk_init@ --- *
- *
- * Arguments:  @safer_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of key material in bytes
- *
- * Returns:    ---
- *
- * Use:                Initializes an SAFER expanded key.  A default number of
- *             rounds is chosen, based on the key length.
- */
-
-void safer_init(safer_ctx *k, const void *buf, size_t sz)
-{
-  safer_setup(k, sz == 8 ? 6 : 10, 0, buf, sz);
-}
-
-void safersk_init(safer_ctx *k, const void *buf, size_t sz)
-{
-  safer_setup(k, sz == 8 ? 8 : 10, SAFER_SK, buf, sz);
-}
-
-/* --- @safer_eblk@, @safer_dblk@ --- *
- *
- * Arguments:  @const safer_ctx *k@ = pointer to SAFER context
- *             @const uint32 s[2]@ = pointer to source block
- *             @const uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define UNPACK(src, a, b, c, d, e, f, g, h) do {                       \
-  a = U8(src[0] >> 24); b = U8(src[0] >> 16);                          \
-  c = U8(src[0] >>  8); d = U8(src[0] >>  0);                          \
-  e = U8(src[1] >> 24); f = U8(src[1] >> 16);                          \
-  g = U8(src[1] >>  8); h = U8(src[1] >>  0);                          \
-} while (0)
-
-#define PACK(dst, a, b, c, d, e, f, g, h) do {                         \
-  dst[0] = (U8(a) << 24) | (U8(b) << 16) | (U8(c) << 8) | U8(d);       \
-  dst[1] = (U8(e) << 24) | (U8(f) << 16) | (U8(g) << 8) | U8(h);       \
-} while (0)
-
-#define F(x, y) y += x, x += y
-#define G(x, y) x -= y, y -= x
-
-#define PHT(a, b, c, d, e, f, g, h) do {                               \
-  F(a, b); F(c, d); F(e, f); F(g, h);                                  \
-  F(a, c); F(e, g); F(b, d); F(f, h);                                  \
-  F(a, e); F(b, f); F(c, g); F(d, h);                                  \
-} while (0)
- #define IPHT(a, b, c, d, e, f, g, h) do {                             \
-  G(a, e); G(b, f); G(c, g); G(d, h);                                  \
-  G(a, c); G(e, g); G(b, d); G(f, h);                                  \
-  G(a, b); G(c, d); G(e, f); G(g, h);                                  \
-} while (0)
-
-#define KXA(k, a, b, c, d, e, f, g, h) do {                            \
-  a ^= *k++; b += *k++; c += *k++; d ^= *k++;                          \
-  e ^= *k++; f += *k++; g += *k++; h ^= *k++;                          \
-} while (0)
-#define SUB(a, b, c, d, e, f, g, h) do {                               \
-  a = s[U8(a)]; b = si[U8(b)]; c = si[U8(c)]; d = s[U8(d)];            \
-  e = s[U8(e)]; f = si[U8(f)]; g = si[U8(g)]; h = s[U8(h)];            \
-} while (0)
-#define KAX(k, a, b, c, d, e, f, g, h) do {                            \
-  a += *k++; b ^= *k++; c ^= *k++; d += *k++;                          \
-  e += *k++; f ^= *k++; g ^= *k++; h += *k++;                          \
-} while (0)
-
-#define KXS(k, a, b, c, d, e, f, g, h) do {                            \
-  h ^= *--k; g -= *--k; f -= *--k; e ^= *--k;                          \
-  d ^= *--k; c -= *--k; b -= *--k; a ^= *--k;                          \
-} while (0)
-#define ISUB(a, b, c, d, e, f, g, h) do {                              \
-  a = si[U8(a)]; b = s[U8(b)]; c = s[U8(c)]; d = si[U8(d)];            \
-  e = si[U8(e)]; f = s[U8(f)]; g = s[U8(g)]; h = si[U8(h)];            \
-} while (0)
-#define KSX(k, a, b, c, d, e, f, g, h) do {                            \
-  h -= *--k; g ^= *--k; f ^= *--k; e -= *--k;                          \
-  d -= *--k; c ^= *--k; b ^= *--k; a -= *--k;                          \
-} while (0)
-
-#define EROUND(k, a, b, c, d, e, f, g, h) do {                         \
-  KXA(k, a, b, c, d, e, f, g, h);                                      \
-  SUB(a, b, c, d, e, f, g, h);                                         \
-  KAX(k, a, b, c, d, e, f, g, h);                                      \
-  PHT(a, b, c, d, e, f, g, h);                                         \
-} while (0)
-
-#define DROUND(k, a, b, c, d, e, f, g, h) do {                         \
-  IPHT(a, b, c, d, e, f, g, h);                                                \
-  KSX(k, a, b, c, d, e, f, g, h);                                      \
-  ISUB(a, b, c, d, e, f, g, h);                                                \
-  KXS(k, a, b, c, d, e, f, g, h);                                      \
-} while (0)
-
-
-void safer_eblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
-{
-  octet a, b, c, d, e, f, g, h;
-  unsigned r = k->r;
-  const octet *kk = k->k;
-
-  UNPACK(src, a, b, c, d, e, f, g, h);
-  while (r >= 3) {
-    EROUND(kk, a, b, c, d, e, f, g, h);
-    EROUND(kk, a, e, b, f, c, g, d, h);
-    EROUND(kk, a, c, e, g, b, d, f, h);
-    r -= 3;
-  }
-  switch (r) {
-    case 0:
-      KXA(kk, a, b, c, d, e, f, g, h);
-      PACK(dst, a, b, c, d, e, f, g ,h);
-      break;
-    case 1:
-      EROUND(kk, a, b, c, d, e, f, g, h);
-      KXA(kk, a, e, b, f, c, g, d, h);
-      PACK(dst, a, e, b, f, c, g, d, h);
-      break;
-    case 2:
-      EROUND(kk, a, b, c, d, e, f, g, h);
-      EROUND(kk, a, e, b, f, c, g, d, h);
-      KXA(kk, a, c, e, g, b, d, f, h);
-      PACK(dst, a, c, e, g, b, d, f, h);
-      break;
-  }
-}
-
-void safer_dblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
-{
-  octet a, b, c, d, e, f, g, h;
-  unsigned r = k->r;
-  const octet *kk = k->k + 16 * r + 8;
-  switch (r%3) {
-    default:
-    case 0:
-      UNPACK(src, a, b, c, d, e, f, g, h);
-      KXS(kk, a, b, c, d, e, f, g, h);
-      break;
-    case 1:
-      UNPACK(src, a, e, b, f, c, g, d, h);
-      KXS(kk, a, e, b, f, c, g, d, h);
-      r--;
-      goto one_round;
-    case 2:
-      UNPACK(src, a, c, e, g, b, d, f, h);
-      KXS(kk, a, c, e, g, b, d, f, h);
-      r -= 2;
-      DROUND(kk, a, e, b, f, c, g, d, h);
-    one_round:
-      DROUND(kk, a, b, c, d, e, f, g, h);
-      break;
-  }
-  while (r) {
-    DROUND(kk, a, c, e, g, b, d, f, h);
-    DROUND(kk, a, e, b, f, c, g, d, h);
-    DROUND(kk, a, b, c, d, e, f, g, h);
-    r -= 3;
-  }
-  PACK(dst, a, b, c, d, e, f, g, h);
-}
-
-BLKC_TEST(SAFER, safer)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/safer.h b/safer.h
deleted file mode 100644 (file)
index 198bc8e..0000000
--- a/safer.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* -*-c-*-
- *
- * $Id: safer.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The SAFER block cipher
- *
- * (c) 2001 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.
- */
-
-/*----- Notes on the SAFER block cipher -----------------------------------*
- *
- * SAFER was designed by James Massey (who also worked on IDEA) for Cylink.
- * It's free -- patents or other silliness.  The original key schedule had
- * some weaknesses, and a new one (the SK version) was added.  SAFER has a
- * variable number of rounds.  The standard interface uses the recommended
- * number for the given key schedule algorithm and key size.
- *
- * SAFER got a bad press in Schneier's book `Applied Cryptography'.  I think
- * this is undeserved.  SAFER is a well-designed cipher which mostly looks
- * pretty solid.
- */
-
-#ifndef CATACOMB_SAFER_H
-#define CATACOMB_SAFER_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define SAFER_BLKSZ 8
-#define SAFER_KEYSZ 8
-#define SAFER_CLASS (N, B, 64)
-
-#define SAFERSK_BLKSZ SAFER_BLKSZ
-#define SAFERSK_KEYSZ 16
-#define SAFERSK_CLASS SAFER_CLASS
-
-#define SAFER_MAXROUNDS 12
-
-extern const octet safer_keysz[];
-#define safersk_keysz safer_keysz
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct safer_ctx {
-  octet k[8 * (2 * SAFER_MAXROUNDS + 1)];
-  unsigned r;
-} safer_ctx, safersk_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @safer_setup@ --- *
- *
- * Arguments:  @safer_ctx *k@ = pointer to context to initialize
- *             @unsigned r@ = number of rounds wanted
- *             @unsigned f@ = various other flags
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of key material in bytes
- *
- * Returns:    ---
- *
- * Use:                Initializes an SAFER expanded key.  A default number of
- *             rounds is chosen, based on the key length.
- */
-
-#define SAFER_SK 1u
-
-extern void safer_setup(safer_ctx */*k*/, unsigned /*r*/, unsigned /*f*/,
-                       const void */*buf*/, size_t /*sz*/);
-
-/* --- @safer_init@, @safersk_init@ --- *
- *
- * Arguments:  @safer_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of key material in bytes
- *
- * Returns:    ---
- *
- * Use:                Initializes an SAFER expanded key.  A default number of
- *             rounds is chosen, based on the key length.
- */
-
-extern void safer_init(safer_ctx */*k*/,
-                      const void */*buf*/, size_t /*sz*/);
-extern void safersk_init(safer_ctx */*k*/,
-                        const void */*buf*/, size_t /*sz*/);
-
-/* --- @safer_eblk@, @safer_dblk@ --- *
- *
- * Arguments:  @const safer_ctx *k@ = pointer to SAFER context
- *             @const uint32 s[2]@ = pointer to source block
- *             @const uint32 d[2]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void safer_eblk(const safer_ctx */*k*/,
-                      const uint32 */*s*/, uint32 */*dst*/);
-extern void safer_dblk(const safer_ctx */*k*/,
-                      const uint32 */*s*/, uint32 */*dst*/);
-
-#define safersk_eblk safer_eblk
-#define safersk_dblk safer_dblk
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/safersk.c b/safersk.c
deleted file mode 100644 (file)
index 6ea27c9..0000000
--- a/safersk.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/* -*-c-*-
- *
- * $Id: safersk.c,v 1.1 2001/04/29 17:37:35 mdw Exp $
- *
- * Stub source for SAFER SK
- *
- * (c) 2001 Straylight/Edgeware
- */
-
-#include "blkc.h"
-#include "safersk.h"
-
-const char *safersk_magic = "Compile this useless file";
-
-BLKC_TEST(SAFERSK, safersk)
-
diff --git a/safersk.h b/safersk.h
deleted file mode 100644 (file)
index 7403de7..0000000
--- a/safersk.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -*-c-*-
- *
- * $Id: safersk.h,v 1.1 2001/04/29 17:37:35 mdw Exp $
- *
- * Stub header for SAFER SK
- *
- * (c) 2001 Straylight/Edgeware
- */
-
-#ifndef CATACOMB_SAFERSK_H
-#define CATACOMB_SAFERSK_H
-
-#include "safer.h"
-
-extern const char *safersk_magic;
-
-#endif
diff --git a/seal.c b/seal.c
deleted file mode 100644 (file)
index 444a11c..0000000
--- a/seal.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/* -*-c-*-
- *
- * $Id: seal.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The SEAL pseudo-random function family
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "arena.h"
-#include "gcipher.h"
-#include "grand.h"
-#include "paranoia.h"
-#include "seal.h"
-#include "sha.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet seal_keysz[] = { KSZ_ANY, SHA_HASHSZ };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @gamma@ --- *
- *
- * Arguments:  @uint32 *p@ = output table
- *             @size_t sz@ = size of the output table
- *             @const void *k@ = pointer to key material
- *             @unsigned i@ = integer offset
- *
- * Returns:    ---
- *
- * Use:                Initializes a SEAL key table.
- */
-
-static void gamma(uint32 *p, size_t sz, const void *k, unsigned i)
-{
-  uint32 buf[80] = { 0 };
-  const octet *kk = k;
-  uint32 aa = LOAD32(kk);
-  uint32 bb = LOAD32(kk + 4);
-  uint32 cc = LOAD32(kk + 8);
-  uint32 dd = LOAD32(kk + 12);
-  uint32 ee = LOAD32(kk + 16);
-
-  unsigned skip = i % 5;
-  i /= 5;
-
-  /* --- While there's hashing to do, do hashing --- */
-
-  while (sz) {
-    uint32 a = aa, b = bb, c = cc, d = dd, e = ee;
-    int j;
-
-    /* --- Initialize and expand the buffer --- */
-
-    buf[0] = i++;
-
-    for (j = 16; j < 80; j++) {
-      uint32 x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16];
-      buf[j] = ROL32(x, 1);
-    }
-
-    /* --- 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) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-
-#define T(v, w, x, y, z, i, f, k) do {                                 \
-  uint32 _x;                                                           \
-  z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k;                       \
-  w = ROR32(w, 2);                                                     \
-  _x = v; v = z; z = y; y = x; x = w; w = _x;                          \
-} while (0)
-
-#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999)
-#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1)
-#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc)
-#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6)
-
-    /* --- The main compression function --- *
-     *
-     * Since this isn't doing bulk hashing, do it the easy way.
-     */
-
-    for (j = 0; j < 20; j++)
-      FF(a, b, c, d, e, j);
-    for (j = 20; j < 40; j++)
-      GG(a, b, c, d, e, j);
-    for (j = 40; j < 60; j++)
-      HH(a, b, c, d, e, j);
-    for (j = 60; j < 80; j++)
-      II(a, b, c, d, e, j);
-
-    /* --- Do the chaining at the end --- */
-
-    a += aa; b += bb; c += cc; d += dd; e += ee;
-
-    /* --- Write to the output buffer --- */
-
-    switch (skip) {
-      case 0:
-       if (sz) { *p++ = a; sz--; }
-      case 1:
-       if (sz) { *p++ = b; sz--; }
-      case 2:
-       if (sz) { *p++ = c; sz--; }
-      case 3:
-       if (sz) { *p++ = d; sz--; }
-      case 4:
-       if (sz) { *p++ = e; sz--; }
-       skip = 0;
-    }
-  }
-}
-
-/* --- @seal_initkey@ --- *
- *
- * Arguments:  @seal_key *k@ = pointer to key block
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a SEAL key block.  The key material may be any
- *             size, but if it's not 20 bytes long it's passed to SHA for
- *             hashing first.
- */
-
-void seal_initkey(seal_key *k, const void *buf, size_t sz)
-{
-  /* --- Hash the key if it's the wrong size --- */
-
-  if (sz == SHA_HASHSZ)
-    memcpy(k->k, buf, sizeof(k->k));
-  else {
-    sha_ctx c;
-    sha_init(&c);
-    sha_hash(&c, buf, sz);
-    sha_done(&c, k->k);
-  }
-
-  /* --- Expand the key to fit the various tables --- */
-
-  gamma(k->t, 512, k->k, 0);
-  gamma(k->s, 256, k->k, 0x1000);
-  gamma(k->r, SEAL_R, k->k, 0x2000);
-}
-
-/* --- @seal_reset@ --- *
- *
- * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
- *
- * Returns:    ---
- *
- * Use:                Resets the context so that more data can be extracted from
- *             it.
- */
-
-static void seal_reset(seal_ctx *c)
-{
-  seal_key *k = c->k;
-  uint32 n = c->n;
-  uint32 A, B, C, D;
-  unsigned p;
-
-  /* --- Initialize the new chaining variables --- */
-
-  if (c->l >= SEAL_R) {
-    gamma(c->rbuf, SEAL_R, k->k, c->ri);
-    c->ri += SEAL_R;
-    c->l = 0;
-    c->r = c->rbuf;
-  }
-
-  A = n ^ c->r[0];
-  B = ROR32(n, 8) ^ c->r[1];
-  C = ROR32(n, 16) ^ c->r[2];
-  D = ROR32(n, 24) ^ c->r[3];
-  c->l += 4;
-  c->r += 4;
-
-  /* --- Ensure that everything is sufficiently diffused --- */
-
-  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
-  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
-  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
-  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
-  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
-  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
-  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
-  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
-
-  /* --- Write out some context --- */
-
-  c->n1 = D; c->n2 = B; c->n3 = A; c->n4 = C;
-
-  /* --- Diffuse some more --- */
-
-  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
-  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
-  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
-  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
-
-  /* --- Write out the magic numbers --- */
-
-  c->a = A; c->b = B; c->c = C; c->d = D;
-  c->i = 0;
-}
-
-/* --- @seal_initctx@ --- *
- *
- * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
- *             @seal_key *k@ = pointer to a SEAL key
- *             @uint32 n@ = integer sequence number
- *
- * Returns:    ---
- *
- * Use:                Initializes a SEAL context which can be used for random
- *             number generation or whatever.
- */
-
-void seal_initctx(seal_ctx *c, seal_key *k, uint32 n)
-{
-  c->k = k;
-  c->n = n;
-  c->l = 0;
-  c->r = k->r;
-  c->ri = 0x2000 + SEAL_R;
-  c->qsz = 0;
-  seal_reset(c);
-}
-
-/* --- @seal_encrypt@ --- *
- *
- * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
- *             @const void *src@ = pointer to source data
- *             @void *dest@ = pointer to destination data
- *             @size_t sz@ = size of the data
- *
- * Returns:    ---
- *
- * Use:                Encrypts a block of data using SEAL.  If @src@ is zero,
- *             @dest@ is filled with SEAL output.  If @dest@ is zero, the
- *             SEAL generator is just spun around for a bit.  This shouldn't
- *             be necessary, because SEAL isn't RC4.
- */
-
-void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz)
-{
-  const octet *s = src;
-  octet *d = dest;
-
-  /* --- Expect a big dollop of bytes --- */
-
-  if (sz > c->qsz) {
-    seal_key *k = c->k;
-    uint32 A = c->a, B = c->b, C = c->c, D = c->d;
-    uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
-    uint32 aa, bb, cc, dd;
-    unsigned j = c->i;
-
-    /* --- Empty the queue first --- */
-
-    if (c->qsz) {
-      if (d) {
-       unsigned i;
-       octet *p = c->q + sizeof(c->q) - c->qsz;
-       for (i = 0; i < c->qsz; i++)
-         *d++ = (s ? *s++ ^ *p++ : *p++);
-      }
-      sz -= c->qsz;
-    }
-
-    /* --- Main sequence --- */
-
-    for (;;) {
-      unsigned P, Q;
-
-      /* --- Reset if we've run out of steam on this iteration --- */
-
-      if (j == 256) {
-       seal_reset(c);
-       A = c->a, B = c->b, C = c->c, D = c->d;
-       n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
-       j = 0;
-      }
-
-      /* --- Make some new numbers --- */
-
-      P = A & 0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A;
-      Q = B & 0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B;
-      P = (P + C) & 0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C;
-      Q = (Q + D) & 0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D;
-      P = (P + A) & 0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9);
-      Q = (Q + B) & 0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9);
-      P = (P + C) & 0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9);
-      Q = (Q + D) & 0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9);
-
-      /* --- Remember the output and set up the next round --- */
-
-      aa = B + k->s[j + 0];
-      bb = C ^ k->s[j + 1];
-      cc = D + k->s[j + 2];
-      dd = A ^ k->s[j + 3];
-      j += 4;
-
-      if (j & 4)
-       A += n1, B += n2, C ^= n1, D ^= n2;
-      else
-       A += n3, B += n4, C ^= n3, D ^= n4;
-
-      /* --- Bail out here if we need to do buffering --- */
-
-      if (sz < 16)
-       break;
-
-      /* --- Write the next 16 bytes --- */
-
-      if (d) {
-       if (s) {
-         aa ^= LOAD32_L(s + 0);
-         bb ^= LOAD32_L(s + 4);
-         cc ^= LOAD32_L(s + 8);
-         dd ^= LOAD32_L(s + 12);
-         s += 16;
-       }
-       STORE32_L(d + 0, aa);
-       STORE32_L(d + 4, bb);
-       STORE32_L(d + 8, cc);
-       STORE32_L(d + 12, dd);
-       d += 16;
-      }
-      sz -= 16;
-    }
-
-    /* --- Write the new queue --- */
-
-    STORE32_L(c->q + 0, aa);
-    STORE32_L(c->q + 4, bb);
-    STORE32_L(c->q + 8, cc);
-    STORE32_L(c->q + 12, dd);
-    c->qsz = 16;
-
-    c->a = A; c->b = B; c->c = C; c->d = D;
-    c->i = j;
-  }
-
-  /* --- Deal with the rest from the queue --- */
-
-  if (sz) {
-    unsigned i;
-    octet *p = c->q + sizeof(c->q) - c->qsz;
-    if (d) {
-      for (i = 0; i < sz; i++)
-       *d++ = (s ? *s++ ^ *p++ : *p++);
-    }
-    c->qsz -= sz;
-  }
-}
-
-/*----- Generic cipher interface ------------------------------------------*/
-
-typedef struct gctx {
-  gcipher c;
-  seal_key k;
-  seal_ctx cc;
-} gctx;
-
-static const gcipher_ops gops;
-
-static gcipher *ginit(const void *k, size_t sz)
-{
-  gctx *g = S_CREATE(gctx);
-  g->c.ops = &gops;
-  seal_initkey(&g->k, k, sz);
-  seal_initctx(&g->cc, &g->k, 0);
-  return (&g->c);
-}
-
-static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
-{
-  gctx *g = (gctx *)c;
-  seal_encrypt(&g->cc, s, t, sz);
-}
-
-static void gsetiv(gcipher *c, const void *iv)
-{
-  gctx *g = (gctx *)c;
-  uint32 n = *(const uint32 *)iv;
-  seal_initctx(&g->cc, &g->k, n);
-}
-
-static void gdestroy(gcipher *c)
-{
-  gctx *g = (gctx *)c;
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static const gcipher_ops gops = {
-  &seal,
-  gencrypt, gencrypt, gdestroy, gsetiv, 0
-};
-
-const gccipher seal = {
-  "seal", seal_keysz, 0,
-  ginit
-};
-
-/*----- Generic random number generator interface -------------------------*/
-
-typedef struct grctx {
-  grand r;
-  seal_key k;
-  seal_ctx cc;
-} grctx;
-
-static void grdestroy(grand *r)
-{
-  grctx *g = (grctx *)r;
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static int grmisc(grand *r, unsigned op, ...)
-{
-  grctx *g = (grctx *)r;
-  va_list ap;
-  int rc = 0;
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDBLOCK:
-       case GRAND_SEEDRAND:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT:
-      seal_initctx(&g->cc, &g->k, va_arg(ap, int));
-      break;
-    case GRAND_SEEDUINT32:
-      seal_initctx(&g->cc, &g->k, va_arg(ap, uint32));
-      break;
-    case GRAND_SEEDBLOCK: {
-      const void *p = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      uint32 n;
-      if (sz >= 4)
-       n = LOAD32_L(p);
-      else {
-       octet buf[4] = { 0 };
-       memcpy(buf, p, sz);
-       n = LOAD32_L(p);
-      }
-      seal_initctx(&g->cc, &g->k, n);
-    } break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      seal_initctx(&g->cc, &g->k, rr->ops->word(rr));
-    } break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static octet grbyte(grand *r)
-{
-  grctx *g = (grctx *)r;
-  octet o;
-  seal_encrypt(&g->cc, 0, &o, 1);
-  return (o);
-}
-
-static uint32 grword(grand *r)
-{
-  grctx *g = (grctx *)r;
-  octet b[4];
-  seal_encrypt(&g->cc, 0, b, 4);
-  return (LOAD32(b));
-}
-
-static void grfill(grand *r, void *p, size_t sz)
-{
-  grctx *g = (grctx *)r;
-  seal_encrypt(&g->cc, 0, p, sz);
-}
-
-static const grand_ops grops = {
-  "seal",
-  GRAND_CRYPTO, 0,
-  grmisc, grdestroy,
-  grword, grbyte, grword, grand_range, grfill
-};
-
-/* --- @seal_rand@ --- *
- *
- * Arguments:  @const void *k@ = pointer to key material
- *             @size_t sz@ = size of key material
- *             @uint32 n@ = sequence number
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a random number interface wrapper around a SEAL
- *             pseudorandom function.
- */
-
-grand *seal_rand(const void *k, size_t sz, uint32 n)
-{
-  grctx *g = S_CREATE(grctx);
-  g->r.ops = &grops;
-  seal_initkey(&g->k, k, sz);
-  seal_initctx(&g->cc, &g->k, n);
-  return (&g->r);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <string.h>
-
-#include <mLib/testrig.h>
-
-static int verify(dstr *v)
-{
-  seal_key k;
-  seal_ctx c;
-  uint32 n = *(uint32 *)v[1].buf;
-  dstr d = DSTR_INIT;
-  dstr z = DSTR_INIT;
-  int i;
-  int ok = 1;
-
-  DENSURE(&d, v[2].len);
-  DENSURE(&z, v[2].len);
-  memset(z.buf, 0, v[2].len);
-  z.len = d.len = v[2].len;
-  seal_initkey(&k, v[0].buf, v[0].len);
-
-  for (i = 0; i < v[2].len; i++) {
-    seal_initctx(&c, &k, n);
-    seal_encrypt(&c, 0, d.buf, i);
-    seal_encrypt(&c, z.buf, d.buf + i, d.len - i);
-    if (memcmp(d.buf, v[2].buf, d.len) != 0) {
-      ok = 0;
-      printf("*** seal failure\n");
-      printf("*** k = "); type_hex.dump(&v[0], stdout); putchar('\n');
-      printf("*** n = %08lx\n", (unsigned long)n);
-      printf("*** i = %i\n", i);
-      printf("*** expected = "); type_hex.dump(&v[2], stdout); putchar('\n');
-      printf("*** computed = "); type_hex.dump(&d, stdout); putchar('\n');
-    }
-  }
-
-  dstr_destroy(&d);
-  dstr_destroy(&z);
-
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "seal", verify, { &type_hex, &type_uint32, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/seal");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/seal.h b/seal.h
deleted file mode 100644 (file)
index bee3b30..0000000
--- a/seal.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/* -*-c-*-
- *
- * $Id: seal.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The SEAL pseudo-random function family
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the SEAL pseudo-random function family -------------------*
- *
- * SEAL is a slightly odd cryptographic primitive.  It was designed by Phil
- * Rogaway and Don Coppersmith at IBM, basically as an exercise in producing
- * a really fast symmetric cipher of some kind.  They succeeded: SEAL is
- * faster than the much simpler RC4.
- *
- * For each key, it gives you %$2^{32}$% different output streams.  This
- * implementation imposes no length limits on the size of output streams and
- * performs careful buffer handling to allow arbitrary amounts of data to be
- * extracted.  In practice, extracting more than about 64K is possibly dodgy
- * from a security point of view.
- *
- * SEAL is patented.
- */
-
-#ifndef CATACOMB_SEAL_H
-#define CATACOMB_SEAL_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GCIPHER_H
-#  include "gcipher.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-#define SEAL_R 256
-
-typedef struct seal_key {
-  octet k[20];                         /* Copy of the 160-bit key */
-  uint32 t[512];                       /* Substitution table */
-  uint32 s[256];                       /* Magic for each iteration */
-  uint32 r[SEAL_R];                    /* Magic for the first 64K */
-} seal_key;
-
-typedef struct seal_ctx {
-  seal_key *k;                         /* Pointer to the key block */
-  uint32 *r, ri;                       /* Pointer to current magic */
-  uint32 n, l;                         /* Various indices into things */
-  uint32 a, b, c, d;                   /* Current chaining variables */
-  uint32 n1, n2, n3, n4;               /* Increments for the variables */
-  unsigned i;                          /* Index into current iteration */
-  octet q[16];                         /* Output buffer */
-  unsigned qsz;                                /* Number of bytes in the buffer */
-  uint32 rbuf[SEAL_R];                 /* Buffer for later magic */
-} seal_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @seal_initkey@ --- *
- *
- * Arguments:  @seal_key *k@ = pointer to key block
- *             @const void *buf@ = pointer to key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a SEAL key block.  The key material may be any
- *             size, but if it's not 20 bytes long it's passed to SHA for
- *             hashing first.
- */
-
-extern void seal_initkey(seal_key */*k*/,
-                        const void */*buf*/, size_t /*sz*/);
-
-/* --- @seal_initctx@ --- *
- *
- * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
- *             @seal_key *k@ = pointer to a SEAL key
- *             @uint32 n@ = integer sequence number
- *
- * Returns:    ---
- *
- * Use:                Initializes a SEAL context which can be used for random
- *             number generation or whatever.
- */
-
-extern void seal_initctx(seal_ctx */*c*/, seal_key */*k*/, uint32 /*n*/);
-
-/* --- @seal_encrypt@ --- *
- *
- * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
- *             @const void *src@ = pointer to source data
- *             @void *dest@ = pointer to destination data
- *             @size_t sz@ = size of the data
- *
- * Returns:    ---
- *
- * Use:                Encrypts a block of data using SEAL.  If @src@ is zero,
- *             @dest@ is filled with SEAL output.  If @dest@ is zero, the
- *             SEAL generator is just spun around for a bit.  This shouldn't
- *             be necessary, because SEAL isn't RC4.
- */
-
-extern void seal_encrypt(seal_ctx */*c*/, const void */*src*/,
-                        void */*dest*/, size_t /*sz*/);
-
-/*----- Generic cipher interface ------------------------------------------*/
-
-#define SEAL_KEYSZ 20
-extern const octet seal_keysz[];
-
-extern const gccipher seal;
-
-/*----- Generic random number generator interface -------------------------*/
-
-/* --- @seal_rand@ --- *
- *
- * Arguments:  @const void *k@ = pointer to key material
- *             @size_t sz@ = size of key material
- *             @uint32 n@ = sequence number
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a random number interface wrapper around a SEAL
- *             pseudorandom function.
- */
-
-extern grand *seal_rand(const void */*k*/, size_t /*sz*/, uint32 /*n*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/serpent-check.c b/serpent-check.c
deleted file mode 100644 (file)
index 340af4f..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*-c-*-
- *
- * $Id: serpent-check.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Check the Serpent S-boxes
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/bits.h>
-
-#include "serpent-sbox.h"
-
-/*----- S-box tables ------------------------------------------------------*/
-
-static const octet s[8][16] = {
-  {  3,         8, 15,  1, 10,  6,  5, 11, 14, 13,  4,  2,  7,  0,  9, 12 },
-  { 15, 12,  2,         7,  9,  0,  5, 10,  1, 11, 14,  8,  6, 13,  3,  4 },
-  {  8,         6,  7,  9,  3, 12, 10, 15, 13,  1, 14,  4,  0, 11,  5,  2 },
-  {  0, 15, 11,         8, 12,  9,  6,  3, 13,  1,  2,  4, 10,  7,  5, 14 },
-  {  1, 15,  8,         3, 12,  0, 11,  6,  2,  5,  4, 10,  9, 14,  7, 13 },
-  { 15,         5,  2, 11,  4, 10,  9, 12,  0,  3, 14,  8, 13,  6,  7,  1 },
-  {  7,         2, 12,  5,  8,  4,  6, 11, 14,  9,  1, 15, 13,  3, 10,  0 },
-  {  1, 13, 15,         0, 14,  8,  2, 11,  7,  4, 12, 10,  9,  3,  5,  6 }
-};
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @check@ --- *
- *
- * Arguments:  @unsigned a, b, c, d@ = four bitslice output registers
- *             @const octet *p@ = pointer to S-box
- *
- * Returns:    Zero if OK, nonzero on failure.
- *
- * Use:                Checks that an S-box output is correct.
- */
-
-static int check(unsigned a, unsigned b, unsigned c, unsigned d,
-                const octet *p)
-{
-  octet buf[16];
-  octet *q = buf;
-  unsigned i;
-
-  for (i = 0; i < 16; i++) {
-    *q++ = (a & 1) | ((b & 1) << 1) | ((c & 1) << 2) | ((d & 1) << 3);
-    a >>= 1; b >>= 1; c >>= 1; d >>= 1;
-  }
-  return (memcmp(buf, p, sizeof(buf)));
-}
-
-#define CHECK(i) do {                                                  \
-  unsigned a = 0xaaaa, b = 0xcccc, c = 0xf0f0, d = 0xff00;             \
-  S##i(a, b, c, d);                                                    \
-  if (check(a, b, c, d, s[i])) {                                       \
-    fprintf(stderr, "failure in S%i\n", i);                            \
-    rc = EXIT_FAILURE;                                                 \
-  }                                                                    \
-  IS##i(a, b, c, d);                                                   \
-  if (a != 0xaaaa || b != 0xcccc || c != 0xf0f0 || d != 0xff00) {      \
-    fprintf(stderr, "failure in IS%i\n", i);                           \
-    rc = EXIT_FAILURE;                                                 \
-  }                                                                    \
-} while (0)
-
-int main(void)
-{
-  int rc = 0;
-  CHECK(0); CHECK(1); CHECK(2); CHECK(3);
-  CHECK(4); CHECK(5); CHECK(6); CHECK(7);
-  return (rc);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/serpent-sbox.h b/serpent-sbox.h
deleted file mode 100644 (file)
index 1612330..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/* -*-c-*-
- *
- * $Id: serpent-sbox.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Bitslice S-box implementations
- *
- * (c) 2000 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.
- */
-
-/*----- Credit where it's due ---------------------------------------------*
- *
- * These S-box expressions are taken from the paper `Speeding up Serpent', by
- * Dag Arne Osvik, submitted to AES3.
- */
-
-#ifndef CATACOMB_SERPENT_SBOX_H
-#define CATACOMB_SERPENT_SBOX_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Macros provided ---------------------------------------------------*/
-
-/* --- @S0@ --- */
-
-#define S0(r0, r1, r2, r3) do {                                                \
-  uint32 r4;                                                           \
-  r3 ^= r0; r4 = r1; r1 &= r3; r4 ^= r2;                               \
-  r1 ^= r0; r0 |= r3; r0 ^= r4; r4 ^= r3;                              \
-  r3 ^= r2; r2 |= r1; r2 ^= r4; r4 = ~r4;                              \
-  r4 |= r1; r1 ^= r3; r1 ^= r4; r3 |= r0;                              \
-  r1 ^= r3; r4 ^= r3;                                                  \
-  r3 = r0; r0 = r1; r1 = r4;                                           \
-} while (0)
-
-#define IS0(r0, r1, r2, r3) do {                                       \
-  uint32 r4;                                                           \
-  r2 = ~r2; r4 = r1; r1 |= r0; r4 = ~r4;                               \
-  r1 ^= r2; r2 |= r4; r1 ^= r3; r0 ^= r4;                              \
-  r2 ^= r0; r0 &= r3; r4 ^= r0; r0 |= r1;                              \
-  r0 ^= r2; r3 ^= r4; r2 ^= r1; r3 ^= r0;                              \
-  r3 ^= r1; r2 &= r3; r4 ^= r2;                                                \
-  r2 = r1; r1 = r4;                                                    \
-} while (0)
-
-/* --- @S1@ --- */
-
-#define S1(r0, r1, r2, r3) do {                                                \
-  uint32 r4;                                                           \
-  r0 = ~r0; r2 = ~r2; r4  = r0; r0 &= r1;                              \
-  r2 ^= r0; r0 |= r3; r3 ^= r2; r1 ^= r0;                              \
-  r0 ^= r4; r4 |= r1; r1 ^= r3; r2 |= r0;                              \
-  r2 &= r4; r0 ^= r1; r1 &= r2; r1 ^= r0;                              \
-  r0 &= r2; r0 ^= r4;                                                  \
-  r4 = r0; r0 = r2; r2 = r3; r3 = r1; r1 = r4;                         \
-} while (0)
-
-#define IS1(r0, r1, r2, r3) do {                                       \
-  uint32 r4;                                                           \
-  r4  = r1; r1 ^= r3; r3 &= r1; r4 ^= r2;                              \
-  r3 ^= r0; r0 |= r1; r2 ^= r3; r0 ^= r4;                              \
-  r0 |= r2; r1 ^= r3; r0 ^= r1; r1 |= r3;                              \
-  r1 ^= r0; r4 = ~r4; r4 ^= r1; r1 |= r0;                              \
-  r1 ^= r0; r1 |= r4; r3 ^= r1;                                                \
-  r1 = r0; r0 = r4; r4 = r2; r2 = r3; r3 = r4;                         \
-} while (0)
-
-/* --- @S2@ --- */
-
-#define S2(r0, r1, r2, r3) do {                                                \
-  uint32 r4;                                                           \
-  r4  = r0; r0 &= r2; r0 ^= r3; r2 ^= r1;                              \
-  r2 ^= r0; r3 |= r4; r3 ^= r1; r4 ^= r2;                              \
-  r1  = r3; r3 |= r4; r3 ^= r0; r0 &= r1;                              \
-  r4 ^= r0; r1 ^= r3; r1 ^= r4; r4 = ~r4;                              \
-  r0 = r2; r2 = r1; r1 = r3; r3 = r4;                                  \
-} while (0)
-
-#define IS2(r0, r1, r2, r3) do {                                       \
-  uint32 r4;                                                           \
-  r2 ^= r3; r3 ^= r0; r4  = r3; r3 &= r2;                              \
-  r3 ^= r1; r1 |= r2; r1 ^= r4; r4 &= r3;                              \
-  r2 ^= r3; r4 &= r0; r4 ^= r2; r2 &= r1;                              \
-  r2 |= r0; r3 = ~r3; r2 ^= r3; r0 ^= r3;                              \
-  r0 &= r1; r3 ^= r4; r3 ^= r0;                                                \
-  r0 = r1; r1 = r4;                                                    \
-} while (0)
-
-/* --- @S3@ --- */
-
-#define S3(r0, r1, r2, r3) do {                                                \
-  uint32 r4;                                                           \
-  r4  = r0; r0 |= r3; r3 ^= r1; r1 &= r4;                              \
-  r4 ^= r2; r2 ^= r3; r3 &= r0; r4 |= r1;                              \
-  r3 ^= r4; r0 ^= r1; r4 &= r0; r1 ^= r3;                              \
-  r4 ^= r2; r1 |= r0; r1 ^= r2; r0 ^= r3;                              \
-  r2  = r1; r1 |= r3; r1 ^= r0;                                                \
-  r0 = r1; r1 = r2; r2 = r3; r3 = r4;                                  \
-} while (0)
-
-#define IS3(r0, r1, r2, r3) do {                                       \
-  uint32 r4;                                                           \
-  r4  = r2; r2 ^= r1; r0 ^= r2; r4 &= r2;                              \
-  r4 ^= r0; r0 &= r1; r1 ^= r3; r3 |= r4;                              \
-  r2 ^= r3; r0 ^= r3; r1 ^= r4; r3 &= r2;                              \
-  r3 ^= r1; r1 ^= r0; r1 |= r2; r0 ^= r3;                              \
-  r1 ^= r4; r0 ^= r1;                                                  \
-  r4 = r0; r0 = r2; r2 = r3; r3 = r4;                                  \
-} while (0)
-
-/* --- @S4@ --- */
-
-#define S4(r0, r1, r2, r3) do {                                                \
-  uint32 r4;                                                           \
-  r1 ^= r3; r3 = ~r3; r2 ^= r3; r3 ^= r0;                              \
-  r4  = r1; r1 &= r3; r1 ^= r2; r4 ^= r3;                              \
-  r0 ^= r4; r2 &= r4; r2 ^= r0; r0 &= r1;                              \
-  r3 ^= r0; r4 |= r1; r4 ^= r0; r0 |= r3;                              \
-  r0 ^= r2; r2 &= r3; r0 = ~r0; r4 ^= r2;                              \
-  r2 = r0; r0 = r1; r1 = r4;                                           \
-} while (0)
-
-#define IS4(r0, r1, r2, r3) do {                                       \
-  uint32 r4;                                                           \
-  r4  = r2; r2 &= r3; r2 ^= r1; r1 |= r3;                              \
-  r1 &= r0; r4 ^= r2; r4 ^= r1; r1 &= r2;                              \
-  r0 = ~r0; r3 ^= r4; r1 ^= r3; r3 &= r0;                              \
-  r3 ^= r2; r0 ^= r1; r2 &= r0; r3 ^= r0;                              \
-  r2 ^= r4, r2 |= r3; r3 ^= r0; r2 ^= r1;                              \
-  r1 = r3; r3 = r4;                                                    \
-} while (0)
-
-/* --- @S5@ --- */
-
-#define S5(r0, r1, r2, r3) do {                                                \
-  uint32 r4;                                                           \
-  r0 ^= r1; r1 ^= r3; r3 = ~r3; r4  = r1;                              \
-  r1 &= r0; r2 ^= r3; r1 ^= r2; r2 |= r4;                              \
-  r4 ^= r3; r3 &= r1; r3 ^= r0; r4 ^= r1;                              \
-  r4 ^= r2; r2 ^= r0; r0 &= r3; r2 = ~r2;                              \
-  r0 ^= r4; r4 |= r3; r2 ^= r4;                                                \
-  r4 = r3; r3 = r2; r2 = r0; r0 = r1; r1 = r4;                         \
-} while (0)
-
-#define IS5(r0, r1, r2, r3) do {                                       \
-  uint32 r4;                                                           \
-  r1 = ~r1; r4 = r3; r2 ^= r1; r3 |= r0;                               \
-  r3 ^= r2; r2 |= r1; r2 &= r0; r4 ^= r3;                              \
-  r2 ^= r4; r4 |= r0; r4 ^= r1; r1 &= r2;                              \
-  r1 ^= r3; r4 ^= r2; r3 &= r4; r4 ^= r1;                              \
-  r3 ^= r4; r4 = ~r4; r3 ^= r0;                                                \
-  r0 = r1; r1 = r4; r4 = r3; r3 = r2; r2 = r4;                         \
-} while (0)
-
-/* --- @S6@ --- */
-
-#define S6(r0, r1, r2, r3) do {                                                \
-  uint32 r4;                                                           \
-  r2 = ~r2; r4 = r3; r3 &= r0; r0 ^= r4;                               \
-  r3 ^= r2; r2 |= r4; r1 ^= r3; r2 ^= r0;                              \
-  r0 |= r1; r2 ^= r1; r4 ^= r0; r0 |= r3;                              \
-  r0 ^= r2; r4 ^= r3; r4 ^= r0; r3 = ~r3;                              \
-  r2 &= r4; r2 ^= r3;                                                  \
-  r3 = r2; r2 = r4;                                                    \
-} while (0)
-
-#define IS6(r0, r1, r2, r3) do {                                       \
-  uint32 r4;                                                           \
-  r0 ^= r2; r4 = r2; r2 &= r0; r4 ^= r3;                               \
-  r2 = ~r2; r3 ^= r1; r2 ^= r3; r4 |= r0;                              \
-  r0 ^= r2; r3 ^= r4; r4 ^= r1; r1 &= r3;                              \
-  r1 ^= r0; r0 ^= r3; r0 |= r2; r3 ^= r1;                              \
-  r4 ^= r0;                                                            \
-  r0 = r1; r1 = r2; r2 = r4;                                           \
-} while (0)
-
-/* --- @S7@ --- */
-
-#define S7(r0, r1, r2, r3) do {                                                \
-  uint32 r4;                                                           \
-  r4  = r1; r1 |= r2; r1 ^= r3; r4 ^= r2;                              \
-  r2 ^= r1; r3 |= r4; r3 &= r0; r4 ^= r2;                              \
-  r3 ^= r1; r1 |= r4; r1 ^= r0; r0 |= r4;                              \
-  r0 ^= r2; r1 ^= r4; r2 ^= r1; r1 &= r0;                              \
-  r1 ^= r4; r2 = ~r2; r2 |= r0; r4 ^= r2;                              \
-  r2 = r1; r1 = r3; r3 = r0; r0 = r4;                                  \
-} while (0)
-
-#define IS7(r0, r1, r2, r3) do {                                       \
-  uint32 r4;                                                           \
-  r4  = r2; r2 ^= r0; r0 &= r3; r4 |= r3;                              \
-  r2 = ~r2; r3 ^= r1; r1 |= r0; r0 ^= r2;                              \
-  r2 &= r4; r3 &= r4; r1 ^= r2; r2 ^= r0;                              \
-  r0 |= r2; r4 ^= r1; r0 ^= r3; r3 ^= r4;                              \
-  r4 |= r0; r3 ^= r2; r4 ^= r2;                                                \
-  r2 = r1; r1 = r0; r0 = r3; r3 = r4;                                  \
-} while (0)
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/serpent.c b/serpent.c
deleted file mode 100644 (file)
index 9c03764..0000000
--- a/serpent.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* -*-c-*-
- *
- * $Id: serpent.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Serpent block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "serpent.h"
-#include "serpent-sbox.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet serpent_keysz[] = { KSZ_RANGE, SERPENT_KEYSZ, 0, 32, 1 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @serpent_init@ --- *
- *
- * Arguments:  @serpent_ctx *k@ = pointer to context block to initialize
- *             @const void *buf@ = pointer to input buffer
- *             @size_t sz@ = size of input buffer
- *
- * Returns:    ---
- *
- * Use:                Initializes a Serpent context.  The key may be any length of
- *             up to 32 bytes (256 bits).
- */
-
-void serpent_init(serpent_ctx *k, const void *buf, size_t sz)
-{
-  uint32 a;
-  unsigned b;
-  const octet *p, *q;
-  size_t i;
-  uint32 pk[8 + 132];
-
-  KSZ_ASSERT(serpent, sz);
-
-  /* --- Read the key into the buffer --- */
-
-  if (sz > 32)
-    sz = 32;
-  i = 0; p = buf; q = p + sz;
-  a = 0; b = 0;
-  while (p < q) {
-    a |= (uint32)*p++ << b;
-    b += 8;
-    if (b == 32) {
-      pk[i++] = a;
-      a = 0; b = 0;
-    }
-  }
-
-  /* --- Pad short keys --- */
-
-  if (i < 8) {
-    a |= 0x01 << b;
-    b += 8;
-    pk[i++] = a;
-    for (; i < 8; i++)
-      pk[i] = 0;
-  }
-
-  /* --- Expand the prekeys to fill the buffer --- */
-
-  for (i = 8; i < 8 + 132; i++) {
-    uint32 x = (pk[i - 8] ^ pk[i - 5] ^ pk[i - 3] ^ pk[i - 1] ^
-               (i - 8) ^ 0x9e3779b9);
-    k->k[i - 8] = pk[i] = ROL32(x, 11);
-  }
-
-  /* --- Now substitute everything --- */
-
-  i = 0;
-  goto midway;
-  while (i < 132) {
-#define KSUB(r) do {                                                   \
-    uint32 a, b, c, d;                                                 \
-    a = k->k[i]; b = k->k[i + 1]; c = k->k[i + 2]; d = k->k[i + 3];    \
-    S##r(a, b, c, d);                                                  \
-    k->k[i] = a; k->k[i + 1] = b; k->k[i + 2] = c; k->k[i + 3] = d;    \
-    i += 4;                                                            \
-} while (0)
-    KSUB(2); KSUB(1); KSUB(0); KSUB(7);
-    KSUB(6); KSUB(5); KSUB(4);
-  midway:
-    KSUB(3);
-#undef KSUB
-  }
-}
-
-/* --- @serpent_eblk@, @serpent_dblk@ --- *
- *
- * Arguments:  @const serpent_ctx *k@ = pointer to key context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption.
- */
-
-#define EROUND(a, b, c, d, r, k) do {                                  \
-  a ^= *k++; b ^= *k++; c ^= *k++; d ^= *k++;                          \
-  S##r(a, b, c, d);                                                    \
-  a = ROL32(a, 13); c = ROL32(c,  3); b ^= a ^ c; d ^= c ^ (a << 3);   \
-  b = ROL32(b, 1); d = ROL32(d,  7); a ^= b ^ d; c ^= d ^ (b << 7);    \
-  a = ROL32(a, 5); c = ROL32(c, 22);                                   \
-} while (0)
-
-#define DROUND(a, b, c, d, r, k) do {                                  \
-  IS##r(a, b, c, d);                                                   \
-  d ^= *--k; c ^= *--k; b ^= *--k; a ^= *--k;                          \
-  a = ROR32(a, 5); c = ROR32(c, 22); a ^= b ^ d; c ^= d ^ (b << 7);    \
-  b = ROR32(b, 1); d = ROR32(d,  7); b ^= a ^ c; d ^= c ^ (a << 3);    \
-  a = ROR32(a, 13); c = ROR32(c,  3);                                  \
-} while (0)
-
-void serpent_eblk(const serpent_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
-  const uint32 *kk = k->k;
-
-  EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
-  EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
-  EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
-  EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
-
-  EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
-  EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
-  EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
-  EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
-
-  EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
-  EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
-  EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
-  EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
-
-  EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
-  EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
-  EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
-  EROUND(aa, bb, cc, dd, 6, kk);
-
-  aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++;
-  S7(aa, bb, cc, dd);
-  aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++;
-  d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
-}
-
-void serpent_dblk(const serpent_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
-  const uint32 *kk = k->k + 132;
-
-  dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk;
-
-  DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
-  DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
-  DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
-  DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
-
-  DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
-  DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
-  DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
-  DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
-
-  DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
-  DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
-  DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
-  DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
-
-  DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
-  DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
-  DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
-  DROUND(aa, bb, cc, dd, 1, kk);
-
-  IS0(aa, bb, cc, dd);
-  dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk;
-  d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
-}
-
-BLKC_TEST(SERPENT, serpent)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/serpent.h b/serpent.h
deleted file mode 100644 (file)
index bbab712..0000000
--- a/serpent.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*-c-*-
- *
- * $Id: serpent.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The Serpent block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Serpent block cipher ---------------------------------*
- *
- * Serpent was designed and proposed for the AES contest by Ross Anderson,
- * Eli Biham and Lars Knudsen.  It's not particularly quick, but is
- * stunningly secure.  The best differential and linear attacks are
- * speculated to require %$2^{256}$% texts (it's a 128-bit block cipher).
- * The designers originally intended to file a patent, but failed to persue
- * it.  Use of the algorithm is completely unencumbered.
- */
-
-#ifndef CATACOMB_SERPENT_H
-#define CATACOMB_SERPENT_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define SERPENT_BLKSZ 16
-#define SERPENT_KEYSZ 32
-#define SERPENT_CLASS (N, L, 128)
-
-extern const octet serpent_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct serpent_ctx {
-  uint32 k[4 * 33];
-} serpent_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @serpent_init@ --- *
- *
- * Arguments:  @serpent_ctx *k@ = pointer to context block to initialize
- *             @const void *buf@ = pointer to input buffer
- *             @size_t sz@ = size of input buffer
- *
- * Returns:    ---
- *
- * Use:                Initializes a Serpent context.  The key may be any length of
- *             up to 32 bytes (256 bits).
- */
-
-extern void serpent_init(serpent_ctx */*k*/,
-                        const void */*buf*/, size_t /*sz*/);
-
-/* --- @serpent_eblk@, @serpent_dblk@ --- *
- *
- * Arguments:  @const serpent_ctx *k@ = pointer to key context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption.
- */
-
-extern void serpent_eblk(const serpent_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*d*/);
-extern void serpent_dblk(const serpent_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/sha.c b/sha.c
deleted file mode 100644 (file)
index 157b81b..0000000
--- a/sha.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sha.c,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of the SHA-1 hash function
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "sha.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @sha_compress@ --- *
- *
- * Arguments:  @sha_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                SHA-1 compression function.
- */
-
-void sha_compress(sha_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d, e;
-  uint32 buf[80];
-
-  /* --- Fetch the chaining variables --- */
-
-  a = ctx->a;
-  b = ctx->b;
-  c = ctx->c;
-  d = ctx->d;
-  e = ctx->e;
-
-  /* --- Fetch and expand the buffer contents --- */
-
-  {
-    int i;
-    const octet *p;
-
-    for (i = 0, p = sbuf; i < 16; i++, p += 4)
-      buf[i] = LOAD32(p);
-    for (i = 16; i < 80; i++) {
-      uint32 x = buf[i - 3] ^ buf[i - 8] ^ buf[i - 14] ^ buf[i - 16];
-      buf[i] = ROL32(x, 1);
-    }
-  }
-
-  /* --- 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) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-
-#define T(v, w, x, y, z, i, f, k) do {                                 \
-  z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k;                       \
-  w = ROR32(w, 2);                                                     \
-} while (0)
-
-#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999)
-#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1)
-#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc)
-#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6)
-
-  /* --- The main compression function --- */
-
-  FF(a, b, c, d, e,  0);
-  FF(e, a, b, c, d,  1);
-  FF(d, e, a, b, c,  2);
-  FF(c, d, e, a, b,  3);
-  FF(b, c, d, e, a,  4);
-  FF(a, b, c, d, e,  5);
-  FF(e, a, b, c, d,  6);
-  FF(d, e, a, b, c,  7);
-  FF(c, d, e, a, b,  8);
-  FF(b, c, d, e, a,  9);
-  FF(a, b, c, d, e, 10);
-  FF(e, a, b, c, d, 11);
-  FF(d, e, a, b, c, 12);
-  FF(c, d, e, a, b, 13);
-  FF(b, c, d, e, a, 14);
-  FF(a, b, c, d, e, 15);
-  FF(e, a, b, c, d, 16);
-  FF(d, e, a, b, c, 17);
-  FF(c, d, e, a, b, 18);
-  FF(b, c, d, e, a, 19);
-
-  GG(a, b, c, d, e, 20);
-  GG(e, a, b, c, d, 21);
-  GG(d, e, a, b, c, 22);
-  GG(c, d, e, a, b, 23);
-  GG(b, c, d, e, a, 24);
-  GG(a, b, c, d, e, 25);
-  GG(e, a, b, c, d, 26);
-  GG(d, e, a, b, c, 27);
-  GG(c, d, e, a, b, 28);
-  GG(b, c, d, e, a, 29);
-  GG(a, b, c, d, e, 30);
-  GG(e, a, b, c, d, 31);
-  GG(d, e, a, b, c, 32);
-  GG(c, d, e, a, b, 33);
-  GG(b, c, d, e, a, 34);
-  GG(a, b, c, d, e, 35);
-  GG(e, a, b, c, d, 36);
-  GG(d, e, a, b, c, 37);
-  GG(c, d, e, a, b, 38);
-  GG(b, c, d, e, a, 39);
-
-  HH(a, b, c, d, e, 40);
-  HH(e, a, b, c, d, 41);
-  HH(d, e, a, b, c, 42);
-  HH(c, d, e, a, b, 43);
-  HH(b, c, d, e, a, 44);
-  HH(a, b, c, d, e, 45);
-  HH(e, a, b, c, d, 46);
-  HH(d, e, a, b, c, 47);
-  HH(c, d, e, a, b, 48);
-  HH(b, c, d, e, a, 49);
-  HH(a, b, c, d, e, 50);
-  HH(e, a, b, c, d, 51);
-  HH(d, e, a, b, c, 52);
-  HH(c, d, e, a, b, 53);
-  HH(b, c, d, e, a, 54);
-  HH(a, b, c, d, e, 55);
-  HH(e, a, b, c, d, 56);
-  HH(d, e, a, b, c, 57);
-  HH(c, d, e, a, b, 58);
-  HH(b, c, d, e, a, 59);
-
-  II(a, b, c, d, e, 60);
-  II(e, a, b, c, d, 61);
-  II(d, e, a, b, c, 62);
-  II(c, d, e, a, b, 63);
-  II(b, c, d, e, a, 64);
-  II(a, b, c, d, e, 65);
-  II(e, a, b, c, d, 66);
-  II(d, e, a, b, c, 67);
-  II(c, d, e, a, b, 68);
-  II(b, c, d, e, a, 69);
-  II(a, b, c, d, e, 70);
-  II(e, a, b, c, d, 71);
-  II(d, e, a, b, c, 72);
-  II(c, d, e, a, b, 73);
-  II(b, c, d, e, a, 74);
-  II(a, b, c, d, e, 75);
-  II(e, a, b, c, d, 76);
-  II(d, e, a, b, c, 77);
-  II(c, d, e, a, b, 78);
-  II(b, c, d, e, a, 79);
-
-  /* --- Update the chaining variables --- */
-
-  ctx->a += a;
-  ctx->b += b;
-  ctx->c += c;
-  ctx->d += d;
-  ctx->e += e;
-}
-
-/* --- @sha_init@ --- *
- *
- * Arguments:  @sha_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void sha_init(sha_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;
-}
-
-/* --- @sha_set@ --- *
- *
- * Arguments:  @sha_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 sha_set(sha_ctx *ctx, const void *buf, unsigned long count)
-{
-  const octet *p = buf;
-  ctx->a = LOAD32(p +  0);
-  ctx->b = LOAD32(p +  4);
-  ctx->c = LOAD32(p +  8);
-  ctx->d = LOAD32(p + 12);
-  ctx->e = LOAD32(p + 16);
-  ctx->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @sha_hash@ --- *
- *
- * Arguments:  @sha_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 sha_hash(sha_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(SHA, sha, ctx, buf, sz);
-}
-
-/* --- @sha_done@ --- *
- *
- * Arguments:  @sha_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void sha_done(sha_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  HASH_PAD(SHA, sha, ctx, 0x80, 0, 8);
-  STORE32(ctx->buf + SHA_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3));
-  STORE32(ctx->buf + SHA_BUFSZ - 4, ctx->nl << 3);
-  sha_compress(ctx, ctx->buf);
-  STORE32(p +  0, ctx->a);
-  STORE32(p +  4, ctx->b);
-  STORE32(p +  8, ctx->c);
-  STORE32(p + 12, ctx->d);
-  STORE32(p + 16, ctx->e);
-}
-
-/* --- @sha_state@ --- *
- *
- * Arguments:  @sha_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 @sha_set@.
- */
-
-unsigned long sha_state(sha_ctx *ctx, void *state)
-{
-  octet *p = state;
-  STORE32(p +  0, ctx->a);
-  STORE32(p +  4, ctx->b);
-  STORE32(p +  8, ctx->c);
-  STORE32(p + 12, ctx->d);
-  STORE32(p + 16, ctx->e);
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(SHA, sha)
-
-/* --- Test code --- */
-
-HASH_TEST(SHA, sha)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/sha.h b/sha.h
deleted file mode 100644 (file)
index 0ce367a..0000000
--- a/sha.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sha.h,v 1.6 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of the SHA-1 hash function
- *
- * (c) 1999 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.
- */
-
-/*----- Notes on the SHA-1 hash function ----------------------------------*
- *
- * SHA (Secure Hash Algorithm) was designed by the NSA, for use with the
- * Digital Signature Algorithm.  It is defined by FIPS 180-1.  It has gained
- * wide acceptance since its initial publication, and is probably now most
- * people's collision-resistant function of choice.  The author prefers
- * RIPEMD-160, for no particularly good reasons.
- */
-
-#ifndef CATACOMB_SHA_H
-#define CATACOMB_SHA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define SHA_BUFSZ 64
-#define SHA_HASHSZ 20
-#define SHA_STATESZ 20
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct sha_ctx {
-  uint32 a, b, c, d, e;                        /* Chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[SHA_BUFSZ];                        /* Accumulation buffer */
-} sha_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @sha_compress@ --- *
- *
- * Arguments:  @sha_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                SHA compression function.
- */
-
-extern void sha_compress(sha_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @sha_init@ --- *
- *
- * Arguments:  @sha_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void sha_init(sha_ctx */*ctx*/);
-
-/* --- @sha_set@ --- *
- *
- * Arguments:  @sha_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 sha_set(sha_ctx */*ctx*/, const void */*buf*/,
-                   unsigned long /*count*/);
-
-/* --- @sha_hash@ --- *
- *
- * Arguments:  @sha_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 sha_hash(sha_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @sha_done@ --- *
- *
- * Arguments:  @sha_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 sha_done(sha_ctx */*ctx*/, void */*hash*/);
-
-/* --- @sha_state@ --- *
- *
- * Arguments:  @sha_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 @sha_set@.
- */
-
-extern unsigned long sha_state(sha_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash sha;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/sha224.c b/sha224.c
deleted file mode 100644 (file)
index 2eceba0..0000000
--- a/sha224.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sha224.c,v 1.1 2004/03/21 22:43:34 mdw Exp $
- *
- * Stub code for SHA-224
- */
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "sha224.h"
-
-GHASH_DEF(SHA224, sha224)
-HASH_TEST(SHA224, sha224)
diff --git a/sha224.h b/sha224.h
deleted file mode 100644 (file)
index 23684b7..0000000
--- a/sha224.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sha224.h,v 1.1 2004/03/21 22:43:34 mdw Exp $
- *
- * Stub header for SHA-224
- */
-
-#ifndef CATACOMB_SHA224_H
-#define CATACOMB_SHA224_H
-
-#include "sha256.h"
-
-#endif
diff --git a/sha256.c b/sha256.c
deleted file mode 100644 (file)
index 683ba13..0000000
--- a/sha256.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sha256.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of the SHA-256 hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "sha256.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @sha256_compress@, @sha224_compress@ --- *
- *
- * Arguments:  @sha256_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                SHA-256 compression function.
- */
-
-void sha256_compress(sha256_ctx *ctx, const void *sbuf)
-{
-  uint32 a, b, c, d, e, f, g, h;
-  uint32 buf[64];
-
-  /* --- Fetch the chaining variables --- */
-
-  a = ctx->a;
-  b = ctx->b;
-  c = ctx->c;
-  d = ctx->d;
-  e = ctx->e;
-  f = ctx->f;
-  g = ctx->g;
-  h = ctx->h;
-
-  /* --- Definitions for round functions --- */
-
-#define CH(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-
-#define S0(x) (ROR32((x),  2) ^ ROR32((x), 13) ^ ROR32((x), 22))
-#define S1(x) (ROR32((x),  6) ^ ROR32((x), 11) ^ ROR32((x), 25))
-#define s0(x) (ROR32((x),  7) ^ ROR32((x), 18) ^ LSR32((x),  3))
-#define s1(x) (ROR32((x), 17) ^ ROR32((x), 19) ^ LSR32((x), 10))
-
-#define T(a, b, c, d, e, f, g, h, i, k) do {                           \
-  uint32 t1 = h + S1(e) + CH(e, f, g) + k + buf[i];                    \
-  uint32 t2 = S0(a) + MAJ(a, b, c);                                    \
-  d += t1; h = t1 + t2;                                                        \
-} while (0)
-
-  /* --- Fetch and expand the buffer contents --- */
-
-  {
-    int i;
-    const octet *p;
-
-    for (i = 0, p = sbuf; i < 16; i++, p += 4)
-      buf[i] = LOAD32(p);
-    for (i = 16; i < 64; i++)
-      buf[i] = s1(buf[i - 2]) + buf[i - 7] + s0(buf[i - 15]) + buf[i - 16];
-  }
-
-  /* --- The main compression function --- */
-
-  T(a, b, c, d, e, f, g, h,  0, 0x428a2f98);
-  T(h, a, b, c, d, e, f, g,  1, 0x71374491);
-  T(g, h, a, b, c, d, e, f,  2, 0xb5c0fbcf);
-  T(f, g, h, a, b, c, d, e,  3, 0xe9b5dba5);
-  T(e, f, g, h, a, b, c, d,  4, 0x3956c25b);
-  T(d, e, f, g, h, a, b, c,  5, 0x59f111f1);
-  T(c, d, e, f, g, h, a, b,  6, 0x923f82a4);
-  T(b, c, d, e, f, g, h, a,  7, 0xab1c5ed5);
-  T(a, b, c, d, e, f, g, h,  8, 0xd807aa98);
-  T(h, a, b, c, d, e, f, g,  9, 0x12835b01);
-  T(g, h, a, b, c, d, e, f, 10, 0x243185be);
-  T(f, g, h, a, b, c, d, e, 11, 0x550c7dc3);
-  T(e, f, g, h, a, b, c, d, 12, 0x72be5d74);
-  T(d, e, f, g, h, a, b, c, 13, 0x80deb1fe);
-  T(c, d, e, f, g, h, a, b, 14, 0x9bdc06a7);
-  T(b, c, d, e, f, g, h, a, 15, 0xc19bf174);
-  T(a, b, c, d, e, f, g, h, 16, 0xe49b69c1);
-  T(h, a, b, c, d, e, f, g, 17, 0xefbe4786);
-  T(g, h, a, b, c, d, e, f, 18, 0x0fc19dc6);
-  T(f, g, h, a, b, c, d, e, 19, 0x240ca1cc);
-  T(e, f, g, h, a, b, c, d, 20, 0x2de92c6f);
-  T(d, e, f, g, h, a, b, c, 21, 0x4a7484aa);
-  T(c, d, e, f, g, h, a, b, 22, 0x5cb0a9dc);
-  T(b, c, d, e, f, g, h, a, 23, 0x76f988da);
-  T(a, b, c, d, e, f, g, h, 24, 0x983e5152);
-  T(h, a, b, c, d, e, f, g, 25, 0xa831c66d);
-  T(g, h, a, b, c, d, e, f, 26, 0xb00327c8);
-  T(f, g, h, a, b, c, d, e, 27, 0xbf597fc7);
-  T(e, f, g, h, a, b, c, d, 28, 0xc6e00bf3);
-  T(d, e, f, g, h, a, b, c, 29, 0xd5a79147);
-  T(c, d, e, f, g, h, a, b, 30, 0x06ca6351);
-  T(b, c, d, e, f, g, h, a, 31, 0x14292967);
-  T(a, b, c, d, e, f, g, h, 32, 0x27b70a85);
-  T(h, a, b, c, d, e, f, g, 33, 0x2e1b2138);
-  T(g, h, a, b, c, d, e, f, 34, 0x4d2c6dfc);
-  T(f, g, h, a, b, c, d, e, 35, 0x53380d13);
-  T(e, f, g, h, a, b, c, d, 36, 0x650a7354);
-  T(d, e, f, g, h, a, b, c, 37, 0x766a0abb);
-  T(c, d, e, f, g, h, a, b, 38, 0x81c2c92e);
-  T(b, c, d, e, f, g, h, a, 39, 0x92722c85);
-  T(a, b, c, d, e, f, g, h, 40, 0xa2bfe8a1);
-  T(h, a, b, c, d, e, f, g, 41, 0xa81a664b);
-  T(g, h, a, b, c, d, e, f, 42, 0xc24b8b70);
-  T(f, g, h, a, b, c, d, e, 43, 0xc76c51a3);
-  T(e, f, g, h, a, b, c, d, 44, 0xd192e819);
-  T(d, e, f, g, h, a, b, c, 45, 0xd6990624);
-  T(c, d, e, f, g, h, a, b, 46, 0xf40e3585);
-  T(b, c, d, e, f, g, h, a, 47, 0x106aa070);
-  T(a, b, c, d, e, f, g, h, 48, 0x19a4c116);
-  T(h, a, b, c, d, e, f, g, 49, 0x1e376c08);
-  T(g, h, a, b, c, d, e, f, 50, 0x2748774c);
-  T(f, g, h, a, b, c, d, e, 51, 0x34b0bcb5);
-  T(e, f, g, h, a, b, c, d, 52, 0x391c0cb3);
-  T(d, e, f, g, h, a, b, c, 53, 0x4ed8aa4a);
-  T(c, d, e, f, g, h, a, b, 54, 0x5b9cca4f);
-  T(b, c, d, e, f, g, h, a, 55, 0x682e6ff3);
-  T(a, b, c, d, e, f, g, h, 56, 0x748f82ee);
-  T(h, a, b, c, d, e, f, g, 57, 0x78a5636f);
-  T(g, h, a, b, c, d, e, f, 58, 0x84c87814);
-  T(f, g, h, a, b, c, d, e, 59, 0x8cc70208);
-  T(e, f, g, h, a, b, c, d, 60, 0x90befffa);
-  T(d, e, f, g, h, a, b, c, 61, 0xa4506ceb);
-  T(c, d, e, f, g, h, a, b, 62, 0xbef9a3f7);
-  T(b, c, d, e, f, g, h, a, 63, 0xc67178f2);
-
-  /* --- Update the chaining variables --- */
-
-  ctx->a += a;
-  ctx->b += b;
-  ctx->c += c;
-  ctx->d += d;
-  ctx->e += e;
-  ctx->f += f;
-  ctx->g += g;
-  ctx->h += h;
-}
-
-/* --- @sha256_init@, @sha224_init@ --- *
- *
- * Arguments:  @sha256_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void sha256_init(sha256_ctx *ctx)
-{
-  ctx->a = 0x6a09e667;
-  ctx->b = 0xbb67ae85;
-  ctx->c = 0x3c6ef372;
-  ctx->d = 0xa54ff53a;
-  ctx->e = 0x510e527f;
-  ctx->f = 0x9b05688c;
-  ctx->g = 0x1f83d9ab;
-  ctx->h = 0x5be0cd19;
-  ctx->off = 0;
-  ctx->nl = ctx->nh = 0;
-}
-
-void sha224_init(sha256_ctx *ctx)
-{
-  ctx->a = 0xc1059ed8;
-  ctx->b = 0x367cd507;
-  ctx->c = 0x3070dd17;
-  ctx->d = 0xf70e5939;
-  ctx->e = 0xffc00b31;
-  ctx->f = 0x68581511;
-  ctx->g = 0x64f98fa7;
-  ctx->h = 0xbefa4fa4;
-  ctx->off = 0;
-  ctx->nl = ctx->nh = 0;
-}
-
-/* --- @sha256_set@, @sha224_set@ --- *
- *
- * Arguments:  @sha256_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 sha256_set(sha256_ctx *ctx, const void *buf, unsigned long count)
-{
-  const octet *p = buf;
-  ctx->a = LOAD32(p +  0);
-  ctx->b = LOAD32(p +  4);
-  ctx->c = LOAD32(p +  8);
-  ctx->d = LOAD32(p + 12);
-  ctx->e = LOAD32(p + 16);
-  ctx->f = LOAD32(p + 20);
-  ctx->g = LOAD32(p + 24);
-  ctx->h = LOAD32(p + 28);
-  ctx->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @sha256_hash@, @sha224_hash@ --- *
- *
- * Arguments:  @sha256_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 sha256_hash(sha256_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(SHA256, sha256, ctx, buf, sz);
-}
-
-/* --- @sha256_done, @sha224_done@ --- *
- *
- * Arguments:  @sha256_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-static void final(sha256_ctx *ctx)
-{
-  HASH_PAD(SHA256, sha256, ctx, 0x80, 0, 8);
-  STORE32(ctx->buf + SHA256_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3));
-  STORE32(ctx->buf + SHA256_BUFSZ - 4, ctx->nl << 3);
-  sha256_compress(ctx, ctx->buf);
-}
-
-void sha256_done(sha256_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  final(ctx);
-  STORE32(p +  0, ctx->a);
-  STORE32(p +  4, ctx->b);
-  STORE32(p +  8, ctx->c);
-  STORE32(p + 12, ctx->d);
-  STORE32(p + 16, ctx->e);
-  STORE32(p + 20, ctx->f);
-  STORE32(p + 24, ctx->g);
-  STORE32(p + 28, ctx->h);
-}
-
-void sha224_done(sha224_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  final(ctx);
-  STORE32(p +  0, ctx->a);
-  STORE32(p +  4, ctx->b);
-  STORE32(p +  8, ctx->c);
-  STORE32(p + 12, ctx->d);
-  STORE32(p + 16, ctx->e);
-  STORE32(p + 20, ctx->f);
-  STORE32(p + 24, ctx->g);
-}
-
-/* --- @sha256_state@, @sha224_state@ --- *
- *
- * Arguments:  @sha256_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 @sha256_set@.
- */
-
-unsigned long sha256_state(sha256_ctx *ctx, void *state)
-{
-  octet *p = state;
-  STORE32(p +  0, ctx->a);
-  STORE32(p +  4, ctx->b);
-  STORE32(p +  8, ctx->c);
-  STORE32(p + 12, ctx->d);
-  STORE32(p + 16, ctx->e);
-  STORE32(p + 20, ctx->f);
-  STORE32(p + 24, ctx->g);
-  STORE32(p + 28, ctx->h);
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(SHA256, sha256)
-
-/* --- Test code --- */
-
-HASH_TEST(SHA256, sha256)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/sha256.h b/sha256.h
deleted file mode 100644 (file)
index 7b21dd2..0000000
--- a/sha256.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Implementation of the SHA-256 hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the SHA-256 hash function --------------------------------*
- *
- * SHA-1 (Secure Hash Algorithm) was designed by the NSA, for use with the
- * Digital Signature Algorithm.  This is an evolution with a larger output
- * size, intended to provide security commensurate with 128-bit AES.  At the
- * time of writing, SHA-256 is very new, and can't be trusted too far.
- */
-
-#ifndef CATACOMB_SHA256_H
-#define CATACOMB_SHA256_H
-#define CATACOMB_SHA224_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define SHA256_BUFSZ 64
-#define SHA256_HASHSZ 32
-#define SHA256_STATESZ 32
-
-#define SHA224_BUFSZ 64
-#define SHA224_HASHSZ 28
-#define SHA224_STATESZ 32
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct sha256_ctx {
-  uint32 a, b, c, d, e, f, g, h;       /* Chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[SHA256_BUFSZ];             /* Accumulation buffer */
-} sha256_ctx, sha224_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @sha256_compress@, @sha224_compress@ --- *
- *
- * Arguments:  @sha256_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                SHA-256 compression function.
- */
-
-extern void sha256_compress(sha256_ctx */*ctx*/, const void */*sbuf*/);
-#define sha224_compress sha256_compress
-
-/* --- @sha256_init@, @sha224_init@ --- *
- *
- * Arguments:  @sha256_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void sha256_init(sha256_ctx */*ctx*/);
-extern void sha224_init(sha256_ctx */*ctx*/);
-
-/* --- @sha256_set@, @sha224_set@ --- *
- *
- * Arguments:  @sha256_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 sha256_set(sha256_ctx */*ctx*/, const void */*buf*/,
-                      unsigned long /*count*/);
-#define sha224_set sha256_set
-
-/* --- @sha256_hash@, @sha224_hash@ --- *
- *
- * Arguments:  @sha256_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 sha256_hash(sha256_ctx */*ctx*/,
-                       const void */*buf*/, size_t /*sz*/);
-#define sha224_hash sha256_hash
-
-/* --- @sha256_done@, @sha224_done@ --- *
- *
- * Arguments:  @sha256_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 sha256_done(sha256_ctx */*ctx*/, void */*hash*/);
-extern void sha224_done(sha256_ctx */*ctx*/, void */*hash*/);
-
-/* --- @sha256_state@, @sha224_state@ --- *
- *
- * Arguments:  @sha256_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 @sha256_set@.
- */
-
-extern unsigned long sha256_state(sha256_ctx */*ctx*/, void */*state*/);
-#define sha224_state sha256_state
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash sha256;
-extern const gchash sha224;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/sha384.c b/sha384.c
deleted file mode 100644 (file)
index a634ef7..0000000
--- a/sha384.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sha384.c,v 1.1 2000/10/15 17:48:15 mdw Exp $
- *
- * Stub code for SHA-384
- */
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "sha384.h"
-
-GHASH_DEF(SHA384, sha384)
-HASH_TEST(SHA384, sha384)
diff --git a/sha384.h b/sha384.h
deleted file mode 100644 (file)
index 661ca60..0000000
--- a/sha384.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sha384.h,v 1.1 2000/10/15 17:48:15 mdw Exp $
- *
- * Stub header for SHA-384
- */
-
-#ifndef CATACOMB_SHA384_H
-#define CATACOMB_SHA384_H
-
-#include "sha512.h"
-
-#endif
diff --git a/sha512.c b/sha512.c
deleted file mode 100644 (file)
index 2f39472..0000000
--- a/sha512.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sha512.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of the SHA-512 hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "sha512.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @sha512_compress@, @sha384_compress@ --- *
- *
- * Arguments:  @sha512_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                SHA-512 compression function.
- */
-
-void sha512_compress(sha512_ctx *ctx, const void *sbuf)
-{
-  kludge64 a, b, c, d, e, f, g, h;
-  kludge64 buf[80];
-  int i;
-
-  static const kludge64 K[80] = {
-    X64(428a2f98, d728ae22), X64(71374491, 23ef65cd),
-    X64(b5c0fbcf, ec4d3b2f), X64(e9b5dba5, 8189dbbc),
-    X64(3956c25b, f348b538), X64(59f111f1, b605d019),
-    X64(923f82a4, af194f9b), X64(ab1c5ed5, da6d8118),
-    X64(d807aa98, a3030242), X64(12835b01, 45706fbe),
-    X64(243185be, 4ee4b28c), X64(550c7dc3, d5ffb4e2),
-    X64(72be5d74, f27b896f), X64(80deb1fe, 3b1696b1),
-    X64(9bdc06a7, 25c71235), X64(c19bf174, cf692694),
-    X64(e49b69c1, 9ef14ad2), X64(efbe4786, 384f25e3),
-    X64(0fc19dc6, 8b8cd5b5), X64(240ca1cc, 77ac9c65),
-    X64(2de92c6f, 592b0275), X64(4a7484aa, 6ea6e483),
-    X64(5cb0a9dc, bd41fbd4), X64(76f988da, 831153b5),
-    X64(983e5152, ee66dfab), X64(a831c66d, 2db43210),
-    X64(b00327c8, 98fb213f), X64(bf597fc7, beef0ee4),
-    X64(c6e00bf3, 3da88fc2), X64(d5a79147, 930aa725),
-    X64(06ca6351, e003826f), X64(14292967, 0a0e6e70),
-    X64(27b70a85, 46d22ffc), X64(2e1b2138, 5c26c926),
-    X64(4d2c6dfc, 5ac42aed), X64(53380d13, 9d95b3df),
-    X64(650a7354, 8baf63de), X64(766a0abb, 3c77b2a8),
-    X64(81c2c92e, 47edaee6), X64(92722c85, 1482353b),
-    X64(a2bfe8a1, 4cf10364), X64(a81a664b, bc423001),
-    X64(c24b8b70, d0f89791), X64(c76c51a3, 0654be30),
-    X64(d192e819, d6ef5218), X64(d6990624, 5565a910),
-    X64(f40e3585, 5771202a), X64(106aa070, 32bbd1b8),
-    X64(19a4c116, b8d2d0c8), X64(1e376c08, 5141ab53),
-    X64(2748774c, df8eeb99), X64(34b0bcb5, e19b48a8),
-    X64(391c0cb3, c5c95a63), X64(4ed8aa4a, e3418acb),
-    X64(5b9cca4f, 7763e373), X64(682e6ff3, d6b2b8a3),
-    X64(748f82ee, 5defb2fc), X64(78a5636f, 43172f60),
-    X64(84c87814, a1f0ab72), X64(8cc70208, 1a6439ec),
-    X64(90befffa, 23631e28), X64(a4506ceb, de82bde9),
-    X64(bef9a3f7, b2c67915), X64(c67178f2, e372532b),
-    X64(ca273ece, ea26619c), X64(d186b8c7, 21c0c207),
-    X64(eada7dd6, cde0eb1e), X64(f57d4f7f, ee6ed178),
-    X64(06f067aa, 72176fba), X64(0a637dc5, a2c898a6),
-    X64(113f9804, bef90dae), X64(1b710b35, 131c471b),
-    X64(28db77f5, 23047d84), X64(32caab7b, 40c72493),
-    X64(3c9ebe0a, 15c9bebc), X64(431d67c4, 9c100d4c),
-    X64(4cc5d4be, cb3e42b6), X64(597f299c, fc657e2a),
-    X64(5fcb6fab, 3ad6faec), X64(6c44198c, 4a475817)
-  };
-
-  /* --- Fetch the chaining variables --- */
-
-  a = ctx->a;
-  b = ctx->b;
-  c = ctx->c;
-  d = ctx->d;
-  e = ctx->e;
-  f = ctx->f;
-  g = ctx->g;
-  h = ctx->h;
-
-  /* --- Definitions for round functions --- */
-
-#define CH(d, x, y, z) do {                                            \
-  kludge64 _x; AND64((d), (x), (y)); CPL64(_x, (x));                   \
-  AND64(_x, _x, (z)); OR64((d), (d), _x);                              \
-} while (0)
-
-#define MAJ(d, x, y, z) do {                                           \
-  kludge64 _x; AND64((d), (x), (y)); AND64(_x, (x), (z));              \
-  OR64((d), (d), _x); AND64(_x, (y), (z)); OR64((d), (d), _x);         \
-} while (0)
-
-#define SIGMA(d, x, i, j, k, last, what) do {                          \
-  kludge64 _x; ROR64_((d), (x), (i)); ROR64_(_x, (x), (j));            \
-  XOR64((d), (d), _x); last##64_(_x, (x), (k)); XOR64((d), (d), _x);   \
-} while (0)
-
-#define S0(d, x) SIGMA(d, x, 28, 34, 39, ROR, S0);
-#define S1(d, x) SIGMA(d, x, 14, 18, 41, ROR, S1);
-#define s0(d, x) SIGMA(d, x,  1,  8,  7, LSR, s0);
-#define s1(d, x) SIGMA(d, x, 19, 61,  6, LSR, s1);
-
-#define T(a, b, c, d, e, f, g, h, i) do {                              \
-  kludge64 t1, t2, x;                                                  \
-  ADD64(t1, buf[i], K[i]); ADD64(t1, t1, h);                           \
-  S1(x, e); ADD64(t1, t1, x); CH(x, e, f, g); ADD64(t1, t1, x);                \
-  S0(t2, a); MAJ(x, a, b, c); ADD64(t2, t2, x);                                \
-  ADD64(d, d, t1); ADD64(h, t1, t2);                                   \
-} while (0)
-
-  /* --- Fetch and expand the buffer contents --- */
-
-  {
-    const octet *p;
-
-    for (i = 0, p = sbuf; i < 16; i++, p += 8)
-      LOAD64_(buf[i], p);
-    for (i = 16; i < 80; i++) {
-      kludge64 x;
-      buf[i] = buf[i - 7]; s1(x, buf[i - 2]); ADD64(buf[i], buf[i], x);
-      s0(x, buf[i - 15]); ADD64(buf[i], buf[i], x);
-      ADD64(buf[i], buf[i], buf[i - 16]);
-    }
-  }
-
-  /* --- The main compression function --- */
-
-  for (i = 0; i < 80; i += 8) {
-    T(a, b, c, d, e, f, g, h, i + 0);
-    T(h, a, b, c, d, e, f, g, i + 1);
-    T(g, h, a, b, c, d, e, f, i + 2);
-    T(f, g, h, a, b, c, d, e, i + 3);
-    T(e, f, g, h, a, b, c, d, i + 4);
-    T(d, e, f, g, h, a, b, c, i + 5);
-    T(c, d, e, f, g, h, a, b, i + 6);
-    T(b, c, d, e, f, g, h, a, i + 7);
-  }
-
-  /* --- Update the chaining variables --- */
-
-  ADD64(ctx->a, ctx->a, a);
-  ADD64(ctx->b, ctx->b, b);
-  ADD64(ctx->c, ctx->c, c);
-  ADD64(ctx->d, ctx->d, d);
-  ADD64(ctx->e, ctx->e, e);
-  ADD64(ctx->f, ctx->f, f);
-  ADD64(ctx->g, ctx->g, g);
-  ADD64(ctx->h, ctx->h, h);
-}
-
-/* --- @sha512_init@, @sha384_init@ --- *
- *
- * Arguments:  @sha512_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void sha512_init(sha512_ctx *ctx)
-{
-  SET64(ctx->a,        0x6a09e667, 0xf3bcc908);
-  SET64(ctx->b,        0xbb67ae85, 0x84caa73b);
-  SET64(ctx->c,        0x3c6ef372, 0xfe94f82b);
-  SET64(ctx->d,        0xa54ff53a, 0x5f1d36f1);
-  SET64(ctx->e,        0x510e527f, 0xade682d1);
-  SET64(ctx->f,        0x9b05688c, 0x2b3e6c1f);
-  SET64(ctx->g,        0x1f83d9ab, 0xfb41bd6b);
-  SET64(ctx->h,        0x5be0cd19, 0x137e2179);
-  ctx->off = 0;
-  ctx->nh = ctx->nl = 0;
-}
-
-void sha384_init(sha512_ctx *ctx)
-{
-  SET64(ctx->a,        0xcbbb9d5d, 0xc1059ed8);
-  SET64(ctx->b,        0x629a292a, 0x367cd507);
-  SET64(ctx->c,        0x9159015a, 0x3070dd17);
-  SET64(ctx->d,        0x152fecd8, 0xf70e5939);
-  SET64(ctx->e,        0x67332667, 0xffc00b31);
-  SET64(ctx->f,        0x8eb44a87, 0x68581511);
-  SET64(ctx->g,        0xdb0c2e0d, 0x64f98fa7);
-  SET64(ctx->h,        0x47b5481d, 0xbefa4fa4);
-  ctx->off = 0;
-  ctx->nh = ctx->nl = 0;
-}
-
-/* --- @sha512_set@, @sha384_set@ --- *
- *
- * Arguments:  @sha512_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 sha512_set(sha512_ctx *ctx, const void *buf, unsigned long count)
-{
-  const octet *p = buf;
-  LOAD64_(ctx->a, p +  0);
-  LOAD64_(ctx->b, p +  8);
-  LOAD64_(ctx->c, p + 16);
-  LOAD64_(ctx->d, p + 24);
-  LOAD64_(ctx->e, p + 32);
-  LOAD64_(ctx->f, p + 40);
-  LOAD64_(ctx->g, p + 48);
-  LOAD64_(ctx->h, p + 56);
-  ctx->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @sha512_hash@, @sha384_hash@ --- *
- *
- * Arguments:  @sha512_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 sha512_hash(sha512_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(SHA512, sha512, ctx, buf, sz);
-}
-
-/* --- @sha512_done@, @sha384_done@ --- *
- *
- * Arguments:  @sha512_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-static void final(sha512_ctx *ctx)
-{
-  HASH_PAD(SHA512, sha512, ctx, 0x80, 0, 16);
-  memset(ctx->buf + SHA512_BUFSZ - 16, 0, 8);
-  STORE32(ctx->buf + SHA512_BUFSZ -  8, (ctx->nl >> 29) | (ctx->nh << 3));
-  STORE32(ctx->buf + SHA512_BUFSZ -  4, ctx->nl << 3);
-  sha512_compress(ctx, ctx->buf);
-}
-
-void sha512_done(sha512_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  final(ctx);
-  STORE64_(p + 0, ctx->a);
-  STORE64_(p + 8, ctx->b);
-  STORE64_(p + 16, ctx->c);
-  STORE64_(p + 24, ctx->d);
-  STORE64_(p + 32, ctx->e);
-  STORE64_(p + 40, ctx->f);
-  STORE64_(p + 48, ctx->g);
-  STORE64_(p + 56, ctx->h);
-}
-
-void sha384_done(sha384_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  final(ctx);
-  STORE64_(p + 0, ctx->a);
-  STORE64_(p + 8, ctx->b);
-  STORE64_(p + 16, ctx->c);
-  STORE64_(p + 24, ctx->d);
-  STORE64_(p + 32, ctx->e);
-  STORE64_(p + 40, ctx->f);
-}
-
-/* --- @sha512_state@, @sha384_state@ --- *
- *
- * Arguments:  @sha512_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 @sha512_set@.
- */
-
-unsigned long sha512_state(sha512_ctx *ctx, void *state)
-{
-  octet *p = state;
-  STORE64_(p + 0, ctx->a);
-  STORE64_(p + 8, ctx->b);
-  STORE64_(p + 16, ctx->c);
-  STORE64_(p + 24, ctx->d);
-  STORE64_(p + 32, ctx->e);
-  STORE64_(p + 40, ctx->f);
-  STORE64_(p + 48, ctx->g);
-  STORE64_(p + 56, ctx->h);
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(SHA512, sha512)
-
-/* --- Test code --- */
-
-HASH_TEST(SHA512, sha512)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/sha512.h b/sha512.h
deleted file mode 100644 (file)
index f727e82..0000000
--- a/sha512.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Implementation of the SHA-512 hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the SHA-512 hash function --------------------------------*
- *
- * SHA-1 (Secure Hash Algorithm) was designed by the NSA, for use with the
- * Digital Signature Algorithm.  This is an evolution with a larger output
- * size, intended to provide security commensurate with 256-bit AES.  At the
- * time of writing, SHA-512 is very new, and can't be trusted too far.  There
- * is also a truncated version, SHA-384, which provides security commensurate
- * with 192-bit AES.
- */
-
-#ifndef CATACOMB_SHA512_H
-#define CATACOMB_SHA512_H
-#define CATACOMB_SHA384_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define SHA512_BUFSZ 128
-#define SHA512_HASHSZ 64
-#define SHA512_STATESZ 64
-
-#define SHA384_BUFSZ 128
-#define SHA384_HASHSZ 48
-#define SHA384_STATESZ 64
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct sha512_ctx {
-  kludge64 a, b, c, d, e, f, g, h;     /* Chaining variables */
-  uint32 nh, nl;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[SHA512_BUFSZ];             /* Accumulation buffer */
-} sha512_ctx, sha384_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @sha512_compress@, @sha384_compress@ --- *
- *
- * Arguments:  @sha512_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                SHA-512 compression function.
- */
-
-extern void sha512_compress(sha512_ctx */*ctx*/, const void */*sbuf*/);
-#define sha384_compress sha512_compress
-
-/* --- @sha512_init@, @sha384_init@ --- *
- *
- * Arguments:  @sha512_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void sha512_init(sha512_ctx */*ctx*/);
-extern void sha384_init(sha512_ctx */*ctx*/);
-
-/* --- @sha512_set@, @sha384_set@ --- *
- *
- * Arguments:  @sha512_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 sha512_set(sha512_ctx */*ctx*/, const void */*buf*/,
-                      unsigned long /*count*/);
-#define sha384_set sha512_set
-
-/* --- @sha512_hash@, @sha384_hash@ --- *
- *
- * Arguments:  @sha512_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 sha512_hash(sha512_ctx */*ctx*/,
-                       const void */*buf*/, size_t /*sz*/);
-#define sha384_hash sha512_hash
-
-/* --- @sha512_done@, @sha384_done@ --- *
- *
- * Arguments:  @sha512_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 sha512_done(sha512_ctx */*ctx*/, void */*hash*/);
-extern void sha384_done(sha512_ctx */*ctx*/, void */*hash*/);
-
-/* --- @sha512_state@, @sha384_state@ --- *
- *
- * Arguments:  @sha512_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 @sha512_set@.
- */
-
-extern unsigned long sha512_state(sha512_ctx */*ctx*/, void */*state*/);
-#define sha384_state sha512_state
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash sha512;
-extern const gchash sha384;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/share.c b/share.c
deleted file mode 100644 (file)
index 1afa189..0000000
--- a/share.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Shamir's secret sharing
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "grand.h"
-#include "mp.h"
-#include "mpint.h"
-#include "mpbarrett.h"
-#include "mprand.h"
-#include "pgen.h"
-#include "rabin.h"
-#include "share.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @share_create@ --- *
- *
- * Arguments:  @share *s@ = pointer to share context to initialize
- *             @unsigned t@ = threshold for the system
- *
- * Returns:    ---
- *
- * Use:                Initializes a sharing context.
- */
-
-void share_create(share *s, unsigned t)
-{
-  s->t = t;
-  s->i = 0;
-  s->p = 0;
-  s->v = 0;
-}
-
-/* --- @share_destroy@ --- *
- *
- * Arguments:  @share *s@ = pointer to share context to destroy
- *
- * Returns:    ---
- *
- * Use:                Disposes of a sharing context.  All memory is freed, all
- *             integers are dropped.
- */
-
-void share_destroy(share *s)
-{
-  unsigned i;
-
-  /* --- Dispose of the share vector --- */
-
-  if (s->v) {
-    for (i = 0; i < s->t; i++)
-      mp_drop(s->v[i].y);
-    xfree(s->v);
-  }
-
-  /* --- Other stuff --- */
-
-  mp_drop(s->p);
-}
-
-/* --- @share_mkshares@ --- *
- *
- * Arguments:  @share *s@ = pointer to share context to fill in
- *             @grand *r@ = pointer to random number source
- *             @mp *n@ = the secret to share
- *
- * Returns:    ---
- *
- * Use:                Initializes a sharing context to be able to create shares.
- *             The context structure is expected to be mostly filled in.  In
- *             particular, @t@ must be initialized.  If @p@ is zero, a prime
- *             number of appropriate size is generated automatically.  If
- *             @v@ is zero, a vector of appropriate size is allocated.  You
- *             should use the macro @SHARE_INIT@ or @share_create@ to
- *             construct sharing contexts.
- */
-
-void share_mkshares(share *s, grand *r, mp *n)
-{
-  unsigned i;
-
-  /* --- If there's no prime, construct one --- */
-
-  if (!s->p) {
-    pgen_filterctx pf;
-    rabin pr;
-    mp *p;
-    unsigned bits = (mp_octets(n) + 1) * 8;
-
-    pf.step = 2;
-    p = mprand(MP_NEW, bits, r, 1);
-    s->p = pgen("p", p, p, 0, 0, 0, pgen_filter, &pf,
-               rabin_iters(bits), pgen_test, &pr);
-  }
-
-  /* --- Construct the polynomial --- */
-
-  if (!s->v)
-    s->v = xmalloc(s->t * sizeof(share_pt));
-  for (i = 0; i < s->t - 1; i++)
-    s->v[i].y = mprand_range(MP_NEWSEC, s->p, r, 0);
-  s->v[s->t - 1].y = mp_copy(n);
-}
-
-/* --- @share_get@ --- *
- *
- * Arguments:  @share *s@ = pointer to share conext
- *             @mp *d@ = destination for the share
- *             @unsigned x@ = share index to fetch
- *
- * Returns:    The share, as requested.
- *
- * Use:                Extracts a share from the system.  You may extract @MPW_MAX@
- *             shares, or @s->p@ shares from the system, whichever is
- *             smaller.  Shares are indexed from 0.
- */
-
-mp *share_get(share *s, mp *d, unsigned x)
-{
-  mpbarrett mb;
-  mpw uw = x + 1;
-  mp u;
-  unsigned i;
-
-  /* --- Various bits of initialization --- */
-
-  mp_build(&u, &uw, &uw + 1);
-  mp_drop(d);
-
-  /* --- Evaluate the polynomial at %$x = i + 1$% --- */
-
-  d = MP_ZERO;
-  mpbarrett_create(&mb, s->p);
-  for (i = 0; i < s->t; i++) {
-    d = mp_mul(d, d, &u);
-    d = mp_add(d, d, s->v[i].y);
-    d = mpbarrett_reduce(&mb, d, d);
-  }
-  mpbarrett_destroy(&mb);
-
-  return (d);
-}
-
-/* --- @share_addedp@ --- *
- *
- * Arguments:  @share *s@ = pointer to sharing context
- *             @unsigned x@ = which share number to check
- *
- * Returns:    Nonzero if share @x@ has been added already, zero if it
- *             hasn't.
- */
-
-int share_addedp(share *s, unsigned x)
-{
-  unsigned i;
-
-  for (i = 0; i < s->i; i++) {
-    if (s->v[i].x == x + 1)
-      return (1);
-  }
-  return (0);
-}
-
-/* --- @share_add@ --- *
- *
- * Arguments:  @share *s@ = pointer to sharing context
- *             @unsigned x@ = which share number this is
- *             @mp *y@ = the share value
- *
- * Returns:    Number of shares required before recovery may be performed.
- *
- * Use:                Adds a share to the context.  The context must have been
- *             initialized with the correct prime @p@ and threshold @t@.
- */
-
-unsigned share_add(share *s, unsigned x, mp *y)
-{
-  assert(((void)"Share context is full", s->i < s->t));
-  assert(((void)"Share already present", !share_addedp(s, x)));
-
-  /* --- If no vector has been allocated, create one --- */
-
-  if (!s->v) {
-    unsigned i;
-    s->v = xmalloc(s->t * sizeof(share_pt));
-    s->i = 0;
-    for (i = 0; i < s->t; i++)
-      s->v[i].y = 0;
-  }
-
-  /* --- Store the share in the vector --- */
-
-  s->v[s->i].x = x + 1;
-  s->v[s->i].y = mp_copy(y);
-  s->i++;
-
-  /* --- Done --- */
-
-  return (s->t - s->i);
-}
-
-/* --- @share_combine@ --- *
- *
- * Arguments:  @share *s@ = pointer to share context
- *
- * Returns:    The secret, as a multiprecision integer.
- *
- * Use:                Reconstructs a secret, given enough shares.
- */
-
-mp *share_combine(share *s)
-{
-  mp *a = MP_ZERO;
-  mpbarrett mb;
-  unsigned i, j;
-  mp ii, jj;
-  mpw iiw, jjw;
-  mp *m = MP_NEW;
-
-  /* --- Sanity checking --- */
-
-  assert(((void)"Not enough shares yet", s->i == s->t));
-
-  /* --- Initialization --- */
-
-  mpbarrett_create(&mb, s->p);
-  mp_build(&ii, &iiw, &iiw + 1);
-  mp_build(&jj, &jjw, &jjw + 1);
-
-  /* --- Grind through the shares --- */
-
-  for (i = 0; i < s->t; i++) {
-    mp *c = MP_ONE;
-
-    iiw = s->v[i].x;
-    for (j = 0; j < s->t; j++) {
-      if (i == j)
-       continue;
-      jjw = s->v[j].x;
-      if (s->v[j].x >= s->v[i].x)
-       m = mp_sub(m, &jj, &ii);
-      else {
-       m = mp_sub(m, &ii, &jj);
-       m = mp_sub(m, s->p, m);
-      }
-      m = mp_modinv(m, m, s->p);
-      c = mp_mul(c, c, &jj);
-      c = mpbarrett_reduce(&mb, c, c);
-      c = mp_mul(c, c, m);
-      c = mpbarrett_reduce(&mb, c, c);
-    }
-    c = mp_mul(c, c, s->v[i].y);
-    c = mpbarrett_reduce(&mb, c, c);
-    a = mp_add(a, a, c);
-    mp_drop(c);
-  }
-
-  a = mpbarrett_reduce(&mb, a, a);
-  mp_drop(m);
-  mpbarrett_destroy(&mb);
-  return (a);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include "fibrand.h"
-
-static int verify(grand *r)
-{
-  unsigned n = r->ops->range(r, 16) + 8;
-  unsigned t = r->ops->range(r, n - 1) + 1;
-  unsigned len = r->ops->range(r, 160);
-
-  mp **v = xmalloc(t * sizeof(mp *));
-  unsigned *p = xmalloc(n * sizeof(unsigned));
-  mp *sec = mprand(MP_NEW, len, r, 0);
-  share s;
-  mp *pp;
-  mp *ss;
-  unsigned i;
-
-  int ok = 1;
-
-  for (i = 0; i < n; i++)
-    p[i] = i;
-  for (i = 0; i < t; i++) {
-    unsigned long j = r->ops->range(r, n - i);
-    unsigned x = p[i];
-    p[i] = p[i + j];
-    p[i + j] = x;
-  }
-
-  share_create(&s, t);
-  share_mkshares(&s, r, sec);
-  for (i = 0; i < t; i++)
-    v[i] = share_get(&s, MP_NEW, p[i]);
-  pp = mp_copy(s.p);
-  share_destroy(&s);
-  assert(mparena_count(MPARENA_GLOBAL) + mparena_count(MPARENA_SECURE) == t + 2);
-
-  share_create(&s, t);
-  s.p = pp;
-  for (i = 0; i < t; i++)
-    share_add(&s, p[i], v[i]);
-  ss = share_combine(&s);
-  share_destroy(&s);
-
-  if (!MP_EQ(sec, ss)) {
-    ok = 0;
-    fprintf(stderr, "\nbad recombination of shares\n");
-  };
-
-  mp_drop(sec);
-  mp_drop(ss);
-
-  for (i = 0; i < t; i++)
-    mp_drop(v[i]);
-
-  xfree(v);
-  xfree(p);
-
-  assert(mparena_count(MPARENA_GLOBAL) + mparena_count(MPARENA_SECURE) == 0);
-  return (ok);
-}
-
-int main(void)
-{
-  grand *r = fibrand_create(0);
-  unsigned i;
-  int ok = 1;
-
-  fputs("share: ", stdout);
-  for (i = 0; i < 40; i++) {
-    if (!verify(r))
-      ok = 0;
-    fputc('.', stdout);
-    fflush(stdout);
-  }
-
-  if (ok)
-    fputs(" ok\n", stdout);
-  else
-    fputs(" failed\n", stdout);
-  return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/share.h b/share.h
deleted file mode 100644 (file)
index 5500a4c..0000000
--- a/share.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Shamir's secret sharing
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the sharing system ---------------------------------------*
- *
- * Shamir's secret-sharing system is based on polynomial interpolation modulo
- * a prime number.  It is `perfect' in that fewer participants than the
- * threshold can derive no information about the secret by pooling their
- * shares, and `ideal' in that the shares are the same size as the secret.
- *
- * This implementation stays close to the definition, in order to support
- * other schemes for (e.g.) threshold cryptography.  It is, however, rather
- * slow.
- */
-
-#ifndef CATACOMB_SHARE_H
-#define CATACOMB_SHARE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_MP_H
-#  include "mp.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-/* --- A secret sharing context --- */
-
-typedef struct share_pt {
-  unsigned x;                          /* Index of this share */
-  mp *y;                               /* Payload of this share */
-} share_pt;
-
-typedef struct share {
-  unsigned t;                          /* Threshold */
-  unsigned i;                          /* Next free slot in the vector */
-  mp *p;                               /* Modulus for arithmetic */
-  share_pt *v;                         /* Vector of share information */
-} share;
-
-#define SHARE_INIT(t) { t, 0, 0, 0 }
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @share_create@ --- *
- *
- * Arguments:  @share *s@ = pointer to share context to initialize
- *             @unsigned t@ = threshold for the system
- *
- * Returns:    ---
- *
- * Use:                Initializes a sharing context.
- */
-
-extern void share_create(share */*s*/, unsigned /*t*/);
-
-/* --- @share_destroy@ --- *
- *
- * Arguments:  @share *s@ = pointer to share context to destroy
- *
- * Returns:    ---
- *
- * Use:                Disposes of a sharing context.  All memory is freed, all
- *             integers are dropped.
- */
-
-extern void share_destroy(share */*s*/);
-
-/* --- @share_mkshares@ --- *
- *
- * Arguments:  @share *s@ = pointer to share context to fill in
- *             @grand *r@ = pointer to random number source
- *             @mp *n@ = the secret to share
- *
- * Returns:    ---
- *
- * Use:                Initializes a sharing context to be able to create shares.
- *             The context structure is expected to be mostly filled in.  In
- *             particular, @t@ must be initialized.  If @p@ is zero, a prime
- *             number of appropriate size is generated automatically.  If
- *             @v@ is zero, a vector of appropriate size is allocated.  You
- *             should use the macro @SHARE_INIT@ or @share_create@ to
- *             construct sharing contexts.
- */
-
-extern void share_mkshares(share */*s*/, grand */*r*/, mp */*n*/);
-
-/* --- @share_get@ --- *
- *
- * Arguments:  @share *s@ = pointer to share conext
- *             @mp *d@ = destination for the share
- *             @unsigned x@ = share index to fetch
- *
- * Returns:    The share, as requested.
- *
- * Use:                Extracts a share from the system.  You may extract @MPW_MAX@
- *             shares, or @s->p@ shares from the system, whichever is
- *             smaller.  Shares are indexed from 0.
- */
-
-extern mp *share_get(share */*s*/, mp */*d*/, unsigned /*x*/);
-
-/* --- @share_addedp@ --- *
- *
- * Arguments:  @share *s@ = pointer to sharing context
- *             @unsigned x@ = which share number to check
- *
- * Returns:    Nonzero if share @x@ has been added already, zero if it
- *             hasn't.
- */
-
-extern int share_addedp(share */*s*/, unsigned /*x*/);
-
-/* --- @share_add@ --- *
- *
- * Arguments:  @share *s@ = pointer to sharing context
- *             @unsigned x@ = which share number this is
- *             @mp *y@ = the share value
- *
- * Returns:    Number of shares required before recovery may be performed.
- *
- * Use:                Adds a share to the context.  The context must have been
- *             initialized with the correct prime @p@ and threshold @t@.
- */
-
-extern unsigned share_add(share */*s*/, unsigned /*x*/, mp */*y*/);
-
-/* --- @share_combine@ --- *
- *
- * Arguments:  @share *s@ = pointer to share context
- *
- * Returns:    The secret, as a multiprecision integer.
- *
- * Use:                Reconstructs a secret, given enough shares.
- */
-
-extern mp *share_combine(share */*s*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/skipjack-tab.h b/skipjack-tab.h
deleted file mode 100644 (file)
index cee075e..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*-c-*-
- *
- * $Id: skipjack-tab.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Skipjack S-box
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_SKIPJACK_TAB_H
-#define CATACOMB_SKIPJACK_TAB_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- The S-box ---------------------------------------------------------*/
-
-#define SKIPJACK_S {                                                   \
-  0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4,                      \
-  0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,                      \
-  0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e,                      \
-  0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,                      \
-  0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68,                      \
-  0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,                      \
-  0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19,                      \
-  0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,                      \
-  0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b,                      \
-  0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,                      \
-  0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0,                      \
-  0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,                      \
-  0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69,                      \
-  0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,                      \
-  0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20,                      \
-  0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,                      \
-  0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43,                      \
-  0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,                      \
-  0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa,                      \
-  0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,                      \
-  0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87,                      \
-  0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,                      \
-  0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b,                      \
-  0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,                      \
-  0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0,                      \
-  0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,                      \
-  0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1,                      \
-  0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,                      \
-  0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5,                      \
-  0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,                      \
-  0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3,                      \
-  0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46                       \
-}
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/skipjack.c b/skipjack.c
deleted file mode 100644 (file)
index d87f22c..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/* -*-c-*-
- *
- * $Id: skipjack.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * The Skipjack block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "skipjack.h"
-#include "skipjack-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet skipjack_keysz[] = { KSZ_SET, 10, 0 };
-
-/*----- The Skipjack S-box ------------------------------------------------*/
-
-static const octet f[256] = SKIPJACK_S;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @skipjack_init@ --- *
- *
- * Arguments:  @skipjack_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Skipjack key buffer.  The key buffer must be
- *             exactly 10 bytes long.
- */
-
-void skipjack_init(skipjack_ctx *k, const void *buf, size_t sz)
-{
-  const octet *b = buf;
-  uint32 crud;
-  KSZ_ASSERT(skipjack, sz);
-  k->ka = LOAD32(b);
-  k->kb = LOAD32(b + 4);
-  crud = LOAD16(b + 8);
-  k->kc = U32((crud << 16) | (k->ka >> 16));
-  k->kd = U32((k->ka << 16) | (k->kb >> 16));
-  k->ke = U32((k->kb << 16) | crud);
-  crud = 0;
-}
-
-/* --- @skipjack_eblk@, @skipjack_dblk@ --- *
- *
- * Arguments:  @const skipjack_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to skipjacktination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define G(x, k) do {                                                   \
-  octet _x = U8(x >> 8), _y = U8(x);                                   \
-  _x ^= f[_y ^ U8(k >> 24)];                                           \
-  _y ^= f[_x ^ U8(k >> 16)];                                           \
-  _x ^= f[_y ^ U8(k >> 8)];                                            \
-  _y ^= f[_x ^ U8(k >> 0)];                                            \
-  x = (_x << 8) | _y;                                                  \
-} while (0)
-
-#define RULE_A(w, x, y, z, n, k) do {                                  \
-  G(w, k); z ^= w ^ n++;                                               \
-} while (0)
-
-#define RULE_B(w, x, y, z, n, k) do {                                  \
-  x ^= w ^ n++; G(w, k);                                               \
-} while (0)
-
-void skipjack_eblk(const skipjack_ctx *k, const uint32 *s, uint32 *d)
-{
-  unsigned n = 1;
-  uint16 w = U16(s[0] >> 16), x = U16(s[0]);
-  uint16 y = U16(s[1] >> 16), z = U16(s[1]);
-  uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke;
-
-  RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb);
-  RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd);
-  RULE_A(w, x, y, z, n, ke); RULE_A(z, w, x, y, n, ka);
-  RULE_A(y, z, w, x, n, kb); RULE_A(x, y, z, w, n, kc);
-  RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke);
-  RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb);
-  RULE_B(w, x, y, z, n, kc); RULE_B(z, w, x, y, n, kd);
-  RULE_B(y, z, w, x, n, ke); RULE_B(x, y, z, w, n, ka);
-  RULE_A(w, x, y, z, n, kb); RULE_A(z, w, x, y, n, kc);
-  RULE_A(y, z, w, x, n, kd); RULE_A(x, y, z, w, n, ke);
-  RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb);
-  RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd);
-  RULE_B(w, x, y, z, n, ke); RULE_B(z, w, x, y, n, ka);
-  RULE_B(y, z, w, x, n, kb); RULE_B(x, y, z, w, n, kc);
-  RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke);
-  RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb);
-
-  d[0] = ((uint32)w << 16) | (uint32)x;
-  d[1] = ((uint32)y << 16) | (uint32)z;
-}
-
-#define G_INV(x, k) do {                                               \
-  octet _x = U8(x >> 8), _y = U8(x);                                   \
-  _y ^= f[_x ^ U8(k >> 0)];                                            \
-  _x ^= f[_y ^ U8(k >> 8)];                                            \
-  _y ^= f[_x ^ U8(k >> 16)];                                           \
-  _x ^= f[_y ^ U8(k >> 24)];                                           \
-  x = (_x << 8) | _y;                                                  \
-} while (0)
-
-#define RULE_A_INV(w, x, y, z, n, i) do {                              \
-  w ^= x ^ --n; G_INV(x, i);                                           \
-} while (0)
-
-#define RULE_B_INV(w, x, y, z, n, i) do {                              \
-  G_INV(x, i); y ^= x ^ --n;                                           \
-} while (0)
-
-void skipjack_dblk(const skipjack_ctx *k, const uint32 *s, uint32 *d)
-{
-  unsigned n = 33;
-  uint16 w = U16(s[0] >> 16), x = U16(s[0]);
-  uint16 y = U16(s[1] >> 16), z = U16(s[1]);
-  uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke;
-
-  RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka);
-  RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd);
-  RULE_B_INV(w, x, y, z, n, kc); RULE_B_INV(x, y, z, w, n, kb);
-  RULE_B_INV(y, z, w, x, n, ka); RULE_B_INV(z, w, x, y, n, ke);
-  RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc);
-  RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka);
-  RULE_A_INV(w, x, y, z, n, ke); RULE_A_INV(x, y, z, w, n, kd);
-  RULE_A_INV(y, z, w, x, n, kc); RULE_A_INV(z, w, x, y, n, kb);
-  RULE_B_INV(w, x, y, z, n, ka); RULE_B_INV(x, y, z, w, n, ke);
-  RULE_B_INV(y, z, w, x, n, kd); RULE_B_INV(z, w, x, y, n, kc);
-  RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka);
-  RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd);
-  RULE_A_INV(w, x, y, z, n, kc); RULE_A_INV(x, y, z, w, n, kb);
-  RULE_A_INV(y, z, w, x, n, ka); RULE_A_INV(z, w, x, y, n, ke);
-  RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc);
-  RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka);
-
-  d[0] = ((uint32)w << 16) | (uint32)x;
-  d[1] = ((uint32)y << 16) | (uint32)z;
-}
-
-BLKC_TEST(SKIPJACK, skipjack)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/skipjack.h b/skipjack.h
deleted file mode 100644 (file)
index 0afff1f..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*-c-*-
- *
- * $Id: skipjack.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The Skipjack block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Skipjack block cipher --------------------------------*
- *
- * Skipjack was designed by the NSA, as a type II algorithm to be used in the
- * Clipper system.  It was initially classified, so that it couldn't be used
- * without the key escrow feature, though a team of `respectable'
- * cryptographers, including Dorothy Denning, had a quick look at it and
- * pronounced it `good', as if this was meant to be convincing.  It is
- * apparently a particular parameterization of a family which includes type I
- * algorithms.  Since declassification, Biham has discovered a miss-in-the-
- * middle attack which breaks Skipjack with 31 rounds faster than brute
- * force.
- *
- * This implementation is provided for interest's sake, and possibly for
- * interoperability, rather than as a good cipher to use.
- */
-
-#ifndef CATACOMB_SKIPJACK_H
-#define CATACOMB_SKIPJACK_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define SKIPJACK_BLKSZ 8
-#define SKIPJACK_KEYSZ 10
-#define SKIPJACK_CLASS (N, B, 64)
-
-extern const octet skipjack_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct skipjack_ctx {
-  uint32 ka, kb, kc, kd, ke;
-} skipjack_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @skipjack_init@ --- *
- *
- * Arguments:  @skipjack_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Skipjack key buffer.  The key buffer must be
- *             exactly 10 bytes long.
- */
-
-extern void skipjack_init(skipjack_ctx */*k*/,
-                         const void */*buf*/, size_t /*sz*/);
-
-/* --- @skipjack_eblk@, @skipjack_dblk@ --- *
- *
- * Arguments:  @const skipjack_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to skipjacktination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void skipjack_eblk(const skipjack_ctx */*k*/,
-                         const uint32 */*s*/, uint32 */*d*/);
-extern void skipjack_dblk(const skipjack_ctx */*k*/,
-                         const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/square-mktab.c b/square-mktab.c
deleted file mode 100644 (file)
index f1c7f02..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/* -*-c-*-
- *
- * $Id: square-mktab.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Build precomputed tables for the Square block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/bits.h>
-
-/*----- Magic variables ---------------------------------------------------*/
-
-static octet s[256], si[256];
-static uint32 t[4][256], ti[4][256];
-static uint32 u[4][256];
-static octet rc[32];
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @mul@ --- *
- *
- * Arguments:  @unsigned x, y@ = polynomials over %$\gf{2^8}$%
- *             @unsigned m@ = modulus
- *
- * Returns:    The product of two polynomials.
- *
- * Use:                Computes a product of polynomials, quite slowly.
- */
-
-static unsigned mul(unsigned x, unsigned y, unsigned m)
-{
-  unsigned a = 0;
-  unsigned i;
-
-  for (i = 0; i < 8; i++) {
-    if (y & 1)
-      a ^= x;
-    y >>= 1;
-    x <<= 1;
-    if (x & 0x100)
-      x ^= m;
-  }
-
-  return (a);
-}
-
-/* --- @sbox@ --- *
- *
- * Build the S-box.
- *
- * This is built from inversion in the multiplicative group of
- * %$\gf{2^8}[x]/(p(x))$%, where %$p(x) = x^8+x^7+x^6+x^5+x^4+x^2+1$%,
- * followed by an affine transformation treating inputs as vectors over
- * %$\gf{2}$%.  The result is a horrible function.
- *
- * The inversion is done slightly sneakily, by building log and antilog
- * tables.  Let %$a$% be an element of the finite field.  If the inverse of
- * %$a$% is %$a^{-1}$%, then %$\log a a^{-1} = 0$%.  Hence
- * %$\log a = -\log a^{-1}$%.  This saves fiddling about with Euclidean
- * algorithm.
- */
-
-#define S_MOD 0x1f5
-
-static void sbox(void)
-{
-  octet log[256], alog[256];
-  unsigned x;
-  unsigned i;
-  unsigned g;
-
-  /* --- Find a suitable generator, and build log tables --- */
-
-  log[0] = 0;
-  for (g = 2; g < 256; g++) {
-    x = 1;
-    for (i = 0; i < 256; i++) {
-      log[x] = i;
-      alog[i] = x;
-      x = mul(x, g, S_MOD);
-      if (x == 1 && i != 254)
-       goto again;
-    }
-    goto done;
-  again:;
-  }
-  fprintf(stderr, "couldn't find generator\n");
-  exit(EXIT_FAILURE);
-done:;
-
-  /* --- Now grind through and do the affine transform --- *
-   *
-   * The matrix multiply is an AND and a parity op.  The add is an XOR.
-   */
-
-  for (i = 0; i < 256; i++) {
-    unsigned j;
-    octet m[] = { 0xd6, 0x7b, 0x3d, 0x1f, 0x0f, 0x05, 0x03, 0x01 };
-    unsigned v = i ? alog[255 - log[i]] : 0;
-
-    assert(i == 0 || mul(i, v, S_MOD) == 1);
-
-    x = 0;
-    for (j = 0; j < 8; j++) {
-      unsigned r;
-      r = v & m[j];
-      r = (r >> 4) ^ r;
-      r = (r >> 2) ^ r;
-      r = (r >> 1) ^ r;
-      x = (x << 1) | (r & 1);
-    }
-    x ^= 0xb1;
-    s[i] = x;
-    si[x] = i;
-  }
-}
-
-/* --- @tbox@ --- *
- *
- * Construct the t tables for doing the round function efficiently.
- */
-
-static void tbox(void)
-{
-  unsigned i;
-
-  for (i = 0; i < 256; i++) {
-    uint32 a, b, c, d;
-    uint32 w;
-
-    /* --- Build a forwards t-box entry --- */
-
-    a = s[i];
-    b = a << 1; if (b & 0x100) b ^= S_MOD;
-    c = a ^ b;
-    w = (b << 0) | (a << 8) | (a << 16) | (c << 24);
-    t[0][i] = w;
-    t[1][i] = ROL32(w, 8);
-    t[2][i] = ROL32(w, 16);
-    t[3][i] = ROL32(w, 24);
-
-    /* --- Build a backwards t-box entry --- */
-
-    a = mul(si[i], 0x0e, S_MOD);
-    b = mul(si[i], 0x09, S_MOD);
-    c = mul(si[i], 0x0d, S_MOD);
-    d = mul(si[i], 0x0b, S_MOD);
-    w = (a << 0) | (b << 8) | (c << 16) | (d << 24);
-    ti[0][i] = w;
-    ti[1][i] = ROL32(w, 8);
-    ti[2][i] = ROL32(w, 16);
-    ti[3][i] = ROL32(w, 24);
-  }
-}
-
-/* --- @ubox@ --- *
- *
- * Construct the tables for performing the key schedule.
- */
-
-static void ubox(void)
-{
-  unsigned i;
-
-  for (i = 0; i < 256; i++) {
-    uint32 a, b, c;
-    uint32 w;
-    a = i;
-    b = a << 1; if (b & 0x100) b ^= S_MOD;
-    c = a ^ b;
-    w = (b << 0) | (a << 8) | (a << 16) | (c << 24);
-    u[0][i] = w;
-    u[1][i] = ROL32(w, 8);
-    u[2][i] = ROL32(w, 16);
-    u[3][i] = ROL32(w, 24);
-  }
-}
-
-/* --- Round constants --- */
-
-void rcon(void)
-{
-  unsigned r = 1;
-  int i;
-
-  for (i = 0; i < sizeof(rc); i++) {
-    rc[i] = r;
-    r <<= 1;
-    if (r & 0x100)
-      r ^= S_MOD;
-  }
-}
-
-/* --- @main@ --- */
-
-int main(void)
-{
-  int i, j;
-
-  puts("\
-/* -*-c-*-\n\
- *\n\
- * Square tables [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_SQUARE_TAB_H\n\
-#define CATACOMB_SQUARE_TAB_H\n\
-");
-
-  /* --- Write out the S-box --- */
-
-  sbox();
-  fputs("\
-/* --- The byte substitution and its inverse --- */\n\
-\n\
-#define SQUARE_S {                                                     \\\n\
-  ", stdout);
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", s[i]);
-    if (i == 255)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  fputs("\
-#define SQUARE_SI {                                                    \\\n\
-  ", stdout);
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", si[i]);
-    if (i == 255)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  /* --- Write out the big t tables --- */
-
-  tbox();
-  fputs("\
-/* --- The big round tables --- */\n\
-\n\
-#define SQUARE_T {                                                     \\\n\
-  { ", stdout);
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("0x%08x", t[j][i]);
-      if (i == 255) {
-       if (j == 3)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  fputs("\
-#define SQUARE_TI {                                                    \\\n\
-  { ", stdout);
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("0x%08x", ti[j][i]);
-      if (i == 255) {
-       if (j == 3)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  /* --- Write out the big u tables --- */
-
-  ubox();
-  fputs("\
-/* --- The key schedule tables --- */\n\
-\n\
-#define SQUARE_U {                                                     \\\n\
-  { ", stdout);
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("0x%08x", u[j][i]);
-      if (i == 255) {
-       if (j == 3)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  /* --- Round constants --- */
-
-  rcon();
-  fputs("\
-/* --- The round constants --- */\n\
-\n\
-#define SQUARE_RCON {                                                  \\\n\
-  ", stdout);
-  for (i = 0; i < sizeof(rc); i++) {
-    printf("0x%02x", rc[i]);
-    if (i == sizeof(rc) - 1)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  /* --- Done --- */
-
-  puts("#endif");
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/square.c b/square.c
deleted file mode 100644 (file)
index 6ed8d86..0000000
--- a/square.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* -*-c-*-
- *
- * $Id: square.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The Square block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "paranoia.h"
-#include "square.h"
-#include "square-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet square_keysz[] = { KSZ_RANGE, SQUARE_KEYSZ, 4, 16, 4 };
-
-/*----- Constant tables ---------------------------------------------------*/
-
-static const octet S[256] = SQUARE_S, SI[256] = SQUARE_SI;
-static const uint32 T[4][256] = SQUARE_T, TI[4][256] = SQUARE_TI;
-static const uint32 U[4][256] = SQUARE_U;
-static const octet rcon[] = SQUARE_RCON;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @square_init@ --- *
- *
- * Arguments:  @square_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Square context with a particular key.  Square
- *             keys must be a multiple of 32 bits long, and may be at most
- *             128 bits.
- */
-
-void square_init(square_ctx *k, const void *buf, size_t sz)
-{
-  unsigned nk, nr, nw;
-  unsigned i, j, jj;
-  const octet *p;
-  uint32 ww;
-  uint32 kk[SQUARE_KWORDS];
-
-  /* --- Sort out the key size --- */
-
-  KSZ_ASSERT(square, sz);
-  nk = sz / 4;
-
-  /* --- Fetch the first key words out --- */
-
-  p = buf;
-  for (i = 0; i < nk; i++) {
-    kk[i] = LOAD32_L(p);
-    p += 4;
-  }
-  nr = 8;
-
-  /* --- Expand this material to fill the rest of the table --- */
-
-  nw = (nr + 1) * 4;
-  ww = kk[i - 1];
-  p = rcon;
-  for (; i < nw; i++) {
-    uint32 w = kk[i - nk];
-    if (i % nk == 0) {
-      ww = ROR32(ww, 8);
-      w ^= ww ^ *p++;
-    } else
-      w ^= ww;
-    kk[i] = ww = w;
-  }
-
-  /* --- Make the encryption and decryption keys --- */
-
-  for (i = 0; i < nr * 4; i++) {
-    uint32 w = kk[i];
-    k->w[i] = (U[0][U8(w >>  0)] ^ U[1][U8(w >>         8)] ^
-              U[2][U8(w >> 16)] ^ U[3][U8(w >> 24)]);
-  }
-  for (; i < nw; i++)
-    k->w[i] = kk[i];
-
-  jj = nw;
-  for (i = 0; i < nr * 4; i += 4) {
-    jj -= 4;
-    for (j = 0; j < 4; j++)
-      k->wi[i + j] = kk[jj + j];
-  }
-  for (j = 0; j < 4; j++)
-    k->wi[i + j] = k->w[j];
-
-  BURN(kk);
-}
-
-/* --- @square_eblk@, @square_dblk@ --- *
- *
- * Arguments:  @const square_ctx *k@ = pointer to Square context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define SUB(s, sh, a, b, c, d)                                         \
-  (s[U8((a) >> sh)] << 0 | s[U8((b) >> sh)] <<  8 |                    \
-   s[U8((c) >> sh)] << 16 | s[U8((d) >> sh)] << 24)
-
-#define MIX(t, sh, a, b, c, d)                                         \
-  (t[0][U8((a) >> sh)] ^ t[1][U8((b) >> sh)] ^                         \
-   t[2][U8((c) >> sh)] ^ t[3][U8((d) >> sh)])
-
-#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do {                        \
-  aa = what(t, 0, a, b, c, d) ^ *w++;                                  \
-  bb = what(t, 8, a, b, c, d) ^ *w++;                                  \
-  cc = what(t, 16, a, b, c, d) ^ *w++;                                 \
-  dd = what(t, 24, a, b, c, d) ^ *w++;                                 \
-} while (0)
-
-void square_eblk(const square_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
-  uint32 aa, bb, cc, dd;
-  const uint32 *w = k->w;
-
-  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
-
-  DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-  DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-  DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-  DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-  DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-  DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
-  DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
-  DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-}
-
-void square_dblk(const square_ctx *k, const uint32 *s, uint32 *dst)
-{
-  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
-  uint32 aa, bb, cc, dd;
-  const uint32 *w = k->wi;
-
-  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
-
-  DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-  DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-  DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-  DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-  DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-  DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
-  DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
-  DO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w);
-
-  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
-}
-
-BLKC_TEST(SQUARE, square)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/square.h b/square.h
deleted file mode 100644 (file)
index 60a0876..0000000
--- a/square.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* -*-c-*-
- *
- * $Id: square.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Square block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Square block cipher ----------------------------------*
- *
- * Invented by Joan Daemen and Vincent Rijmen, Square is a fast and
- * relatively simple 128-bit block cipher.  It is the predecessor to
- * Rijndael.  I have grave doubts about the security of Square, though: a
- * dedicated attack against Square's structure by Knudsen has been extended
- * by the Twofish team against Rijndael, and I believe that this extended
- * attack is also effective against Square.  This is a shame: the structure
- * of Square (and Rijndael) is extremely elegant, and has some extremely nice
- * properties.
- */
-
-#ifndef CATACOMB_SQUARE_H
-#define CATACOMB_SQUARE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define SQUARE_BLKSZ 16
-#define SQUARE_KEYSZ 16
-#define SQUARE_CLASS (N, L, 128)
-
-extern const octet square_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-#define SQUARE_MAXROUNDS 8
-#define SQUARE_KWORDS ((SQUARE_MAXROUNDS + 1) * (SQUARE_BLKSZ / 4))
-
-typedef struct square_ctx {
-  uint32 w[SQUARE_KWORDS];
-  uint32 wi[SQUARE_KWORDS];
-} square_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @square_init@ --- *
- *
- * Arguments:  @square_ctx *k@ = pointer to context to initialize
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of the key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Square context with a particular key.  This
- *             implementation of Square doesn't impose any particular
- *             limits on the key size except that it must be multiple of 4
- *             bytes long.  256 bits seems sensible, though.
- */
-
-extern void square_init(square_ctx */*k*/,
-                         const void */*buf*/, size_t /*sz*/);
-
-/* --- @square_eblk@, @square_dblk@ --- *
- *
- * Arguments:  @const square_ctx *k@ = pointer to Square context
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void square_eblk(const square_ctx */*k*/,
-                         const uint32 */*s*/, uint32 */*dst*/);
-extern void square_dblk(const square_ctx */*k*/,
-                         const uint32 */*s*/, uint32 */*dst*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/sslprf.c b/sslprf.c
deleted file mode 100644 (file)
index 866ef89..0000000
--- a/sslprf.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sslprf.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The SSL pseudo-random function
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/sub.h>
-
-#include "arena.h"
-#include "ghash.h"
-#include "grand.h"
-#include "paranoia.h"
-#include "sslprf.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @step@ --- *
- *
- * Arguments:  @sslprf_ctx *c@ = pointer to context structure
- *
- * Returns:    ---
- *
- * Use:                Steps the generator.
- */
-
-static void step(sslprf_ctx *c)
-{
-  octet buf[64];
-  size_t n, sz;
-  octet x;
-  ghash *h, *hh;
-  octet *p;
-
-  h = GH_INIT(c->ci);
-  x = 'A' + c->i - 1;
-  for (sz = c->i++; sz > 0; sz -= n) {
-    n = sz;
-    if (n > sizeof(buf))
-      n = sizeof(buf);
-    memset(buf, x, n);
-    GH_HASH(h, buf, n);
-  }
-  GH_HASH(h, c->k, c->ksz);
-  GH_HASH(h, c->sd, c->sdsz);
-  p = GH_DONE(h, 0);
-
-  hh = GH_INIT(c->co);
-  GH_HASH(hh, c->k, c->ksz);
-  GH_HASH(hh, p, c->ihashsz);
-  c->p = GH_DONE(hh, 0);
-  GH_DESTROY(h);
-
-  c->h = hh;
-  c->sz = c->ohashsz;
-}
-
-/* --- @sslprf_init@ --- *
- *
- * Arguments:  @sslprf_ctx *c@ = pointer to a context structure
- *             @const gchash *hco, *hci@ = outer and inner hash functions
- *             @const void *k@ = pointer to secret buffer
- *             @size_t ksz@ = size of the secret
- *             @const void *sd@ = pointer to seed buffer
- *             @size_t sdsz@ = size of the seed
- *
- * Returns:    ---
- *
- * Use:                Initializes an SSL generator context.
- */
-
-void sslprf_init(sslprf_ctx *c, const gchash *hco, const gchash *hci,
-                const void *k, size_t ksz,
-                const void *sd, size_t sdsz)
-{
-  c->co = hco; c->ci = hci;
-  c->ohashsz = hco->hashsz; c->ihashsz = hci->hashsz;
-  c->k = k; c->ksz = ksz; c->sd = sd; c->sdsz = sdsz;
-  c->i = 1;
-  step(c);
-}
-
-/* --- @sslprf_encrypt@ --- *
- *
- * Arguments:  @sslprf_ctx *c@ = pointer to a context structure
- *             @const void *src@ = pointer to source buffer
- *             @void *dest@ = pointer to destination buffer
- *             @size_t sz@ = size of the buffers
- *
- * Returns:    ---
- *
- * Use:                Encrypts data using the SSL pseudo-random function.  If the
- *             destination pointer is null, the generator is spun and no
- *             output is produced; if the source pointer is null, raw output
- *             from the generator is written; otherwise, the source data is
- *             XORed with the generator output.
- */
-
-void sslprf_encrypt(sslprf_ctx *c, const void *src, void *dest, size_t sz)
-{
-  const octet *s = src;
-  octet *d = dest;
-  size_t i, n;
-
-  while (sz) {
-    if (!c->sz) {
-      GH_DESTROY(c->h);
-      step(c);
-    }
-    n = c->sz;
-    if (n > sz)
-      n = sz;
-    if (d) {
-      if (!s)
-       memcpy(d, c->p, n);
-      else {
-       for (i = 0; i < n; i++) d[i] = s[i] ^ c->p[i];
-       s += n;
-      }
-      d += n;
-    }
-    c->p += n;
-    c->sz -= n;
-    sz -= n;
-  }
-}
-
-/* --- @sslprf_free@ --- *
- *
- * Arguments:  @sslprf_ctx@ = pointer to a context
- *
- * Returns:    ---
- *
- * Use:                Frees resources held in an SSL generator context.
- */
-
-void sslprf_free(sslprf_ctx *c)
-{
-  GH_DESTROY(c->h);
-}
-
-/* --- Generic random number generator --- */
-
-typedef struct grctx {
-  grand r;
-  grand_ops ops;
-  sslprf_ctx prf;
-} grctx;
-
-static void grdestroy(grand *r)
-{
-  grctx *g = (grctx *)r;
-  xfree((char *)g->ops.name);
-  xfree((octet *)g->prf.sd);
-  sslprf_free(&g->prf);
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static void seed(grctx *g, const void *p, size_t sz)
-{
-  octet *q;
-  xfree((octet *)g->prf.sd);
-  g->prf.sd = q = xmalloc(sz);
-  memcpy(q, p, sz);
-  g->prf.sdsz = sz;
-}
-
-static int grmisc(grand *r, unsigned op, ...)
-{
-  grctx *g = (grctx *)r;
-  va_list ap;
-  int rc = 0;
-  uint32 i;
-  octet buf[4];
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDBLOCK:
-       case GRAND_SEEDRAND:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT:
-      i = va_arg(ap, unsigned);
-      STORE32(buf, i);
-      seed(g, buf, sizeof(buf));
-      break;
-    case GRAND_SEEDUINT32:
-      i = va_arg(ap, uint32);
-      STORE32(buf, i);
-      seed(g, buf, sizeof(buf));
-      break;
-    case GRAND_SEEDBLOCK: {
-      const void *p = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      seed(g, p, sz);
-    } break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      octet buf[16];
-      rr->ops->fill(rr, buf, sizeof(buf));
-      seed(g, buf, sizeof(buf));
-    } break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static octet grbyte(grand *r)
-{
-  grctx *g = (grctx *)r;
-  octet o;
-  sslprf_encrypt(&g->prf, 0, &o, 1);
-  return (o);
-}
-
-static uint32 grword(grand *r)
-{
-  grctx *g = (grctx *)r;
-  octet b[4];
-  sslprf_encrypt(&g->prf, 0, &b, sizeof(b));
-  return (LOAD32(b));
-}
-
-static void grfill(grand *r, void *p, size_t sz)
-{
-  grctx *g = (grctx *)r;
-  sslprf_encrypt(&g->prf, 0, p, sz);
-}
-
-static const grand_ops grops = {
-  "<sslprf-dummy>",
-  GRAND_CRYPTO, 0,
-  grmisc, grdestroy,
-  grword, grbyte, grword, grand_range, grfill
-};
-
-/* ---@sslprf_rand@ --- *
- *
- * Arguments:  @const gchash *hco, const gchash *hci@ = hash functions
- *             @const void *k@ = pointer to the key material
- *             @size_t ksz@ = size of the key material
- *             @const void *sd@ = pointer to the seed material
- *             @size_t sdsz@ = size of the seed material
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a generic generator which does TLS data expansion.
- */
-
-grand *sslprf_rand(const gchash *hco, const gchash *hci,
-                  const void *k, size_t ksz,
-                  const void *sd, size_t sdsz)
-{
-  grctx *g = S_CREATE(grctx);
-  dstr d = DSTR_INIT;
-  octet *q = xmalloc(sdsz);
-  memcpy(q, sd, sdsz);
-  dstr_putf(&d, "sslprf(%s,%s)", hco->name, hci->name);
-  g->ops = grops;
-  g->ops.name = xstrdup(d.buf);
-  g->r.ops = &g->ops;
-  dstr_destroy(&d);
-  sslprf_init(&g->prf, hco, hci, k, ksz, q, sdsz);
-  return (&g->r);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-#include <string.h>
-
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#include "sha.h"
-#include "md5.h"
-
-static int v_generate(dstr *v)
-{
-  grand *g;
-  dstr d = DSTR_INIT;
-  int ok = 1;
-
-  g = sslprf_rand(&md5, &sha, v[0].buf, v[0].len, v[1].buf, v[1].len);
-  dstr_ensure(&d, v[2].len);
-  d.len = v[2].len;
-  g->ops->fill(g, d.buf, d.len);
-  g->ops->destroy(g);
-  if (memcmp(v[2].buf, d.buf, d.len) != 0) {
-    ok = 0;
-    printf("\nfail sslprf:"
-          "\n\tkey        = ");
-    type_hex.dump(&v[0], stdout);
-    printf("\n\tseed      = "); type_hex.dump(&v[1], stdout);
-    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
-    printf("\n\tcalculated = "); type_hex.dump(&d, stdout);
-    putchar('\n');
-  }
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "sslprf", v_generate, { &type_hex, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/sslprf");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/sslprf.h b/sslprf.h
deleted file mode 100644 (file)
index 136ee07..0000000
--- a/sslprf.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* -*-c-*-
- *
- * $Id: sslprf.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The SSL pseudo-random function
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_SSLPRF_H
-#define CATACOMB_SSLPRF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GMAC_H
-#  include "gmac.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct sslprf_ctx {
-  const gchash *co, *ci;               /* Outer and inner hash functions */
-  size_t ohashsz, ihashsz;             /* Size of the hash outputs */
-  ghash *h;                            /* Hash context from last time */
-  const octet *k;                      /* Pointer to the secret */
-  size_t ksz;                          /* Size of the secret buffer */
-  const octet *sd;                     /* Pointer to the seed */
-  size_t sdsz;                         /* Size of the seed buffer */
-  unsigned i;                          /* Which iteration this is */
-  octet *p;                            /* Pointer to output buffer */
-  size_t sz;                           /* How many bytes are left */
-} sslprf_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @sslprf_init@ --- *
- *
- * Arguments:  @sslprf_ctx *c@ = pointer to a context structure
- *             @const gchash *hco, *hci@ = outer and inner hash functions
- *             @const void *k@ = pointer to secret buffer
- *             @size_t ksz@ = size of the secret
- *             @const void *sd@ = pointer to seed buffer
- *             @size_t sdsz@ = size of the seed
- *
- * Returns:    ---
- *
- * Use:                Initializes an SSL generator context.
- */
-
-extern void sslprf_init(sslprf_ctx */*c*/,
-                       const gchash */*hco*/, const gchash */*hci*/,
-                       const void */*k*/, size_t /*ksz*/,
-                       const void */*sd*/, size_t /*sdsz*/);
-
-/* --- @sslprf_encrypt@ --- *
- *
- * Arguments:  @sslprf_ctx *c@ = pointer to a context structure
- *             @const void *src@ = pointer to source buffer
- *             @void *dest@ = pointer to destination buffer
- *             @size_t sz@ = size of the buffers
- *
- * Returns:    ---
- *
- * Use:                Encrypts data using the SSL pseudo-random function.  If the
- *             destination pointer is null, the generator is spun and no
- *             output is produced; if the source pointer is null, raw output
- *             from the generator is written; otherwise, the source data is
- *             XORed with the generator output.
- */
-
-extern void sslprf_encrypt(sslprf_ctx */*c*/,
-                          const void */*src*/, void */*dest*/,
-                          size_t /*sz*/);
-
-/* --- @sslprf_free@ --- *
- *
- * Arguments:  @sslprf_ctx@ = pointer to a context
- *
- * Returns:    ---
- *
- * Use:                Frees resources held in an SSL generator context.
- */
-
-extern void sslprf_free(sslprf_ctx */*c*/);
-
-/* ---@sslprf_rand@ --- *
- *
- * Arguments:  @const gchash *hco, const gchash *hci@ = hash functions
- *             @const void *k@ = pointer to the key material
- *             @size_t ksz@ = size of the key material
- *             @const void *sd@ = pointer to the seed material
- *             @size_t sdsz@ = size of the seed material
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a generic generator which does TLS data expansion.
- */
-
-extern grand *sslprf_rand(const gchash */*hco*/, const gchash */*hci*/,
-                         const void */*k*/, size_t /*ksz*/,
-                         const void */*sd*/, size_t /*sdsz*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/strongprime.c b/strongprime.c
deleted file mode 100644 (file)
index 866533d..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/* -*-c-*-
- *
- * $Id: strongprime.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate `strong' prime numbers
- *
- * (c) 1999 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#include "grand.h"
-#include "rand.h"
-#include "mp.h"
-#include "mpmont.h"
-#include "mprand.h"
-#include "pgen.h"
-#include "pfilt.h"
-#include "rabin.h"
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @strongprime_setup@ --- *
- *
- * Arguments:  @const char *name@ = pointer to name root
- *             @mp *d@ = destination for search start point
- *             @pfilt *f@ = where to store filter jump context
- *             @unsigned nbits@ = number of bits wanted
- *             @grand *r@ = random number source
- *             @unsigned n@ = number of attempts to make
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for the event handler
- *
- * Returns:    A starting point for a `strong' prime search, or zero.
- *
- * Use:                Sets up for a strong prime search, so that primes with
- *             particular properties can be found.  It's probably important
- *             to note that the number left in the filter context @f@ is
- *             congruent to 2 (mod 4).
- */
-
-mp *strongprime_setup(const char *name, mp *d, pfilt *f, unsigned nbits,
-                     grand *r, unsigned n, pgen_proc *event, void *ectx)
-{
-  mp *s, *t, *q;
-  dstr dn = DSTR_INIT;
-
-  mp *rr = d;
-  pgen_filterctx c;
-  pgen_jumpctx j;
-  rabin rb;
-
-  /* --- The bitslop parameter --- *
-   *
-   * There's quite a lot of prime searching to be done.  The constant
-   * @BITSLOP@ is a (low) approximation to the base-2 log of the expected
-   * number of steps to find a prime number.  Experimentation shows that
-   * numbers around 10 seem to be good.
-   */
-
-#define BITSLOP 12
-
-  /* --- Choose two primes %$s$% and %$t$% of half the required size --- */
-
-  assert(((void)"nbits too small in strongprime_setup", nbits/2 > BITSLOP));
-  nbits = nbits/2 - BITSLOP;
-  c.step = 1;
-
-  rr = mprand(rr, nbits, r, 1);
-  DRESET(&dn); dstr_putf(&dn, "%s [s]", name);
-  if ((s = pgen(dn.buf, MP_NEWSEC, rr, event, ectx, n, pgen_filter, &c,
-          rabin_iters(nbits), pgen_test, &rb)) == 0)
-    goto fail_s;
-
-  rr = mprand(rr, nbits, r, 1);
-  DRESET(&dn); dstr_putf(&dn, "%s [t]", name);
-  if ((t = pgen(dn.buf, MP_NEWSEC, rr, event, ectx, n, pgen_filter, &c,
-               rabin_iters(nbits), pgen_test, &rb)) == 0)
-    goto fail_t;
-
-  /* --- Choose a suitable value for %$r = 2it + 1$% for some %$i$% --- */
-
-  rr = mp_lsl(rr, t, 1);
-  pfilt_create(&c.f, rr);
-  rr = mp_lsl(rr, rr, BITSLOP - 1);
-  rr = mp_add(rr, rr, MP_ONE);
-  DRESET(&dn); dstr_putf(&dn, "%s [r]", name);
-  j.j = &c.f;
-  nbits += BITSLOP;
-  q = pgen(dn.buf, MP_NEW, rr, event, ectx, n, pgen_jump, &j,
-          rabin_iters(nbits), pgen_test, &rb);
-  pfilt_destroy(&c.f);
-  if (!q)
-    goto fail_r;
-
-  /* --- Select a suitable starting-point for finding %$p$% --- *
-   *
-   * This computes %$p_0 = 2(s^{r - 2} \bmod r)s - 1$%.
-   */
-
-  {
-    mpmont mm;
-
-    mpmont_create(&mm, q);
-    rr = mp_sub(rr, q, MP_TWO);
-    rr = mpmont_exp(&mm, rr, s, rr);
-    mpmont_destroy(&mm);
-    rr = mp_mul(rr, rr, s);
-    rr = mp_lsl(rr, rr, 1);
-    rr = mp_sub(rr, rr, MP_ONE);
-  }
-
-  /* --- Now find %$p = p_0 + 2jrs$% for some %$j$% --- */
-
-  {
-    mp *x;
-    x = mp_mul(MP_NEW, q, s);
-    x = mp_lsl(x, x, 1);
-    pfilt_create(f, x);
-    x = mp_lsl(x, x, BITSLOP - 1);
-    rr = mp_add(rr, rr, x);
-    mp_drop(x);
-  }
-
-  /* --- Return the result --- */
-
-  mp_drop(q);
-  mp_drop(t);
-  mp_drop(s);
-  dstr_destroy(&dn);
-  return (rr);
-
-  /* --- Tidy up if something failed --- */
-
-fail_r:
-  mp_drop(t);
-fail_t:
-  mp_drop(s);
-fail_s:
-  mp_drop(rr);
-  dstr_destroy(&dn);
-  return (0);
-
-#undef BITSLOP
-}
-
-/* --- @strongprime@ --- *
- *
- * Arguments:  @const char *name@ = pointer to name root
- *             @mp *d@ = destination integer
- *             @unsigned nbits@ = number of bits wanted
- *             @grand *r@ = random number source
- *             @unsigned n@ = number of attempts to make
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for the event handler
- *
- * Returns:    A `strong' prime, or zero.
- *
- * Use:                Finds `strong' primes.  A strong prime %$p$% is such that
- *
- *               * %$p - 1$% has a large prime factor %$r$%,
- *               * %$p + 1$% has a large prime factor %$s$%, and
- *               * %$r - 1$% has a large prime factor %$t$%.
- *
- *             The numbers produced may be slightly larger than requested,
- *             by a few bits.
- */
-
-mp *strongprime(const char *name, mp *d, unsigned nbits, grand *r,
-               unsigned n, pgen_proc *event, void *ectx)
-{
-  pfilt f;
-  pgen_jumpctx j;
-  rabin rb;
-
-  d = strongprime_setup(name, d, &f, nbits, r, n, event, ectx);
-  j.j = &f;
-  d = pgen(name, d, d, event, ectx, n, pgen_jump, &j,
-          rabin_iters(nbits), pgen_test, &rb);
-  pfilt_destroy(&f);
-  return (d);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/strongprime.h b/strongprime.h
deleted file mode 100644 (file)
index 1986d80..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*-c-*-
- *
- * $Id: strongprime.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate `strong' prime numbers
- *
- * (c) 1999 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.
- */
-
-#ifndef CATACOMB_STRONGPRIME_H
-#define CATACOMB_STRONGPRIME_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-#ifndef CATACOMB_PGEN_H
-#  include "pgen.h"
-#endif
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @strongprime_setup@ --- *
- *
- * Arguments:  @const char *name@ = pointer to name root
- *             @mp *d@ = destination for search start point
- *             @pfilt *f@ = where to store filter jump context
- *             @unsigned nbits@ = number of bits wanted
- *             @grand *r@ = random number source
- *             @unsigned n@ = number of attempts to make
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for the event handler
- *
- * Returns:    A starting point for a `strong' prime search, or zero.
- *
- * Use:                Sets up for a strong prime search, so that primes with
- *             particular properties can be found.  It's probably important
- *             to note that the number left in the filter context @f@ is
- *             congruent to 2 (mod 4).
- */
-
-extern mp *strongprime_setup(const char */*name*/, mp */*d*/, pfilt */*f*/,
-                            unsigned /*nbits*/, grand */*r*/,
-                            unsigned /*n*/, pgen_proc */*event*/,
-                            void */*ectx*/);
-
-/* --- @strongprime@ --- *
- *
- * Arguments:  @const char *name@ = pointer to name root
- *             @mp *d@ = destination integer
- *             @unsigned nbits@ = number of bits wanted
- *             @grand *r@ = random number source
- *             @unsigned n@ = number of attempts to make
- *             @pgen_proc *event@ = event handler function
- *             @void *ectx@ = argument for the event handler
- *
- * Returns:    A `strong' prime, or zero.
- *
- * Use:                Finds `strong' primes.  A strong prime %$p$% is such that
- *
- *               * %$p - 1$% has a large prime factor %$r$%,
- *               * %$p + 1$% has a large prime factor %$s$%, and
- *               * %$r - 1$% has a large prime factor %$t$%.
- *
- *             The numbers produced may be slightly larger than requested,
- *             by a few bits.
- */
-
-extern mp *strongprime(const char */*name*/, mp */*d*/, unsigned /*nbits*/,
-                      grand */*r*/, unsigned /*n*/,
-                      pgen_proc */*event*/, void */*ectx*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/symm/Makefile.am b/symm/Makefile.am
new file mode 100644 (file)
index 0000000..9c2895b
--- /dev/null
@@ -0,0 +1,401 @@
+### -*-makefile-*-
+###
+### Build script for symmetric cryptography
+###
+### (c) 2013 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.
+
+include $(top_srcdir)/vars.am
+
+noinst_LTLIBRARIES      = libsymm.la
+libsymm_la_SOURCES      =
+nodist_libsymm_la_SOURCES =
+
+TEST_LIBS               = libsymm.la
+
+VPATH                  += modes
+
+###--------------------------------------------------------------------------
+### Autogenerated lists.
+
+## Fancy template substitutions.
+multigen                = $(PYTHON) $(srcdir)/multigen
+EXTRA_DIST             += multigen
+
+## The heart of this is an enormous cross-product of crypto primitives and
+## the corresponding modes of operation.  Rather than write it out longhand,
+## we generate it using `multigen'.  Unfortunately, this needs to be done
+## at the Automake level, which causes some interesting bootstrapping
+## problems.
+include modes.am
+
+EXTRA_DIST             += modes.am.in modes.am
+MAINTAINERCLEANFILES   += $(srcdir)/modes.am
+
+## Generate the lists.
+$(srcdir)/modes.am: modes.am.in
+       $(AM_V_GEN)$(multigen) -g $(srcdir)/modes.am.in $(srcdir)/modes.am \
+               blkc="$(BLKCS)" \
+                       blkcmode="$(BLKCMODES)" \
+                       blkcciphermode="$(BLKCCIPHERMODES)" \
+               hash="$(HASHES)" \
+                       hashmode="$(HASHMODES)" \
+                       hashciphermode="$(HASHCIPHERMODES)" \
+                       hashmacmode="$(HASHMACMODES)"
+
+## Initialize lists of known classes.
+ALL_CIPHERS             = $(CIPHER_MODES)
+ALL_HASHES              = $(HASHES)
+ALL_MACS                = $(MAC_MODES)
+
+###--------------------------------------------------------------------------
+### Block ciphers.
+
+BLKCS                   =
+BLKCMODES               =
+
+BLKCCIPHERMODES                 =
+BLKCMODES              += $(BLKCCIPHERMODES)
+
+## A tool for translating the AES-contest test vectors into a form our test
+## rigs understand.
+EXTRA_DIST             += aes-trans
+
+## Block cipher utility macros, mainly used in mode implementations.
+pkginclude_HEADERS     += blkc.h
+
+## Source code and headers for the block ciphers.
+libsymm_la_SOURCES     += $(BLKC_C)
+pkginclude_HEADERS     += $(BLKC_H)
+
+## Schneier's `Blowfish' block cipher.
+BLKCS                  += blowfish
+blowfish.lo: blowfish-tab.h
+CLEANFILES             += blowfish-tab.h
+noinst_PROGRAMS                += blowfish-mktab
+blowfish_mktab_CPPFLAGS         = $(AM_CPPFLAGS) -DQUIET
+blowfish-tab.h: blowfish-mktab$e
+       $(AM_V_GEN)./blowfish-mktab >blowfish-tab.h.new && \
+               mv blowfish-tab.h.new blowfish-tab.h
+
+## Adams and Tavares' `CAST' block ciphers.
+BLKCS                  += cast128 cast256
+libsymm_la_SOURCES     += cast-s.c cast-sk.c cast-base.h cast-tab.h
+cast256.$t: t/cast256
+EXTRA_DIST             += t/cast256.aes
+MAINTAINERCLEANFILES   += $(srcdir)/t/cast256
+t/cast256: t/cast256.aes
+       $(AM_V_GEN)$(srcdir)/aes-trans CAST256 \
+               <$(srcdir)/t/cast256.aes \
+               >$(srcdir)/t/cast256.new && \
+       mv $(srcdir)/t/cast256.new $(srcdir)/t/cast256
+
+## IBM's `DES' block cipher, by Feistel, Coppersmith, and others.
+BLKCS                  += des des3
+libsymm_la_SOURCES     += des-base.h des-base.c desx-tab.h
+des-base.lo: des-tab.h
+CLEANFILES             += des-tab.h
+noinst_PROGRAMS                += des-mktab
+des-tab.h: des-mktab$e
+       $(AM_V_GEN)./des-mktab >des-tab.h.new && \
+               mv des-tab.h.new des-tab.h
+
+## Rivest's `DESX' variant, with pre- and post-whitening.
+BLKCS                  += desx
+libsymm_la_SOURCES     += desx-tab.h
+
+## Lai and Massey's IDEA.
+BLKCS                  += idea
+
+## IBM's `MARS' block cipher.
+BLKCS                  += mars
+mars.lo: mars-tab.h
+CLEANFILES             += mars-tab.h
+noinst_PROGRAMS                += mars-mktab
+mars-tab.h: mars-mktab$e
+       $(AM_V_GEN)./mars-mktab >mars-tab.h.new && \
+               mv mars-tab.h.new mars-tab.h
+mars.$t: t/mars
+EXTRA_DIST             += t/mars.aes
+MAINTAINERCLEANFILES   += $(srcdir)/t/mars
+t/mars: t/mars.aes
+       $(AM_V_GEN)$(srcdir)/aes-trans Mars \
+               <$(srcdir)/t/mars.aes \
+               >$(srcdir)/t/mars.new && \
+       mv $(srcdir)/t/mars.new $(srcdir)/t/mars
+
+## Daemen, Peeters, Van Assche and Rijmen's `Noekeon'.
+BLKCS                  += noekeon
+
+## Rivest's `RC2' block cipher.
+BLKCS                  += rc2
+libsymm_la_SOURCES     += rc2-tab.h
+
+## Rivest's `RC5'.
+BLKCS                  += rc5
+
+## Daemen and Rijmen's `Rijndael' block cipher, selected as AES.
+BLKCS                  += rijndael rijndael192 rijndael256
+libsymm_la_SOURCES     += rijndael-base.h rijndael-base.c
+rijndael-base.lo: rijndael-tab.h
+CLEANFILES             += rijndael-tab.h
+noinst_PROGRAMS                += rijndael-mktab
+rijndael-tab.h: rijndael-mktab$e
+       $(AM_V_GEN)./rijndael-mktab >rijndael-tab.h.new && \
+               mv rijndael-tab.h.new rijndael-tab.h
+rijndael.$t: t/rijndael
+EXTRA_DIST             += t/rijndael.aes
+MAINTAINERCLEANFILES   += $(srcdir)/t/rijndael
+t/rijndael: t/rijndael.aes
+       $(AM_V_GEN)$(srcdir)/aes-trans Rijndael \
+               <$(srcdir)/t/rijndael.aes \
+               >$(srcdir)/t/rijndael.new && \
+       mv $(srcdir)/t/rijndael.new $(srcdir)/t/rijndael
+
+## Massey's `SAFER' block ciphers.
+BLKCS                  += safer safersk
+safer.lo: safer-tab.h
+CLEANFILES             += safer-tab.h
+noinst_PROGRAMS                += safer-mktab
+safer-tab.h: safer-mktab$e
+       $(AM_V_GEN)./safer-mktab >safer-tab.h.new && \
+               mv safer-tab.h.new safer-tab.h
+
+## Anderson, Biham and Knudsen's `Serpent' block cipher.
+BLKCS                  += serpent
+libsymm_la_SOURCES     += serpent-sbox.h
+noinst_PROGRAMS                += serpent-check
+TESTS                  += serpent-check
+serpent.$t: t/serpent
+EXTRA_DIST             += t/serpent.aes
+MAINTAINERCLEANFILES   += $(srcdir)/t/serpent
+t/serpent: t/serpent.aes
+       $(AM_V_GEN)$(srcdir)/aes-trans Serpent -v rev=1 \
+               <$(srcdir)/t/serpent.aes \
+               >$(srcdir)/t/serpent.new && \
+       mv $(srcdir)/t/serpent.new $(srcdir)/t/serpent
+
+## The National Security Agency's `Skipjack' block cipher.  You don't want to
+## use this.
+BLKCS                  += skipjack
+libsymm_la_SOURCES     += skipjack-tab.h
+
+## Daemen and Rijmen's `Square' block cipher.
+BLKCS                  += square
+square.lo: square-tab.h
+CLEANFILES             += square-tab.h
+noinst_PROGRAMS                += square-mktab
+square-tab.h: square-mktab$e
+       $(AM_V_GEN)./square-mktab >square-tab.h.new && \
+               mv square-tab.h.new square-tab.h
+
+## Wheeler and Needham's `TEA' and `XTEA' block ciphers.
+BLKCS                  += tea xtea
+
+## Schneier, Kelsey, Whiting, Wagner, Hall and Ferguson's `Twofish' block
+## cipher.
+BLKCS                  += twofish
+twofish.lo: twofish-tab.h
+CLEANFILES             += twofish-tab.h
+noinst_PROGRAMS                += twofish-mktab
+twofish-tab.h: twofish-mktab$e
+       $(AM_V_GEN)./twofish-mktab >twofish-tab.h.new && \
+               mv twofish-tab.h.new twofish-tab.h
+twofish.$t: t/twofish
+EXTRA_DIST             += t/twofish.aes
+MAINTAINERCLEANFILES   += $(srcdir)/t/twofish
+t/twofish: t/twofish.aes
+       $(AM_V_GEN)$(srcdir)/aes-trans Twofish \
+               <$(srcdir)/t/twofish.aes \
+               >$(srcdir)/t/twofish.new && \
+       mv $(srcdir)/t/twofish.new $(srcdir)/t/twofish
+
+## The old NIST modes for DES.
+BLKCCIPHERMODES                += cbc cfb ecb ofb
+
+## Counter mode.
+BLKCCIPHERMODES                += counter
+
+###--------------------------------------------------------------------------
+### Hash functions.
+
+HASHES                  =
+HASHMODES               =
+
+HASHCIPHERMODES                 =
+HASHMODES              += $(HASHCIPHERMODES)
+
+HASHMACMODES            =
+HASHMODES              += $(HASHMACMODES)
+
+## Common definitions for hash functions.
+pkginclude_HEADERS     += hash.h
+
+## Source code and headers for the hash functions.
+libsymm_la_SOURCES     += $(HASH_C)
+pkginclude_HEADERS     += $(HASH_H)
+
+## Lim and KISA's `HAS-160', recommended for use with KCDSA.
+HASHES                 += has160
+
+## Rivest's `MD' series of hash functions
+HASHES                 += md2 md4 md5
+libsymm_la_SOURCES     += md2-tab.h
+
+## Dobbertin, Bosselaers and Preneel's `RIPEMD' suite.
+HASHES                 += rmd128 rmd160 rmd256 rmd320
+
+## The National Security Agency's `SHA-1' hash function.
+HASHES                 += sha
+
+## The National Security Agency's `SHA-2' suite.
+HASHES                 += sha224 sha256
+HASHES                 += sha384 sha512
+
+## Anderson and Biham's `Tiger' hash function.
+HASHES                 += tiger
+libsymm_la_SOURCES     += tiger-base.h
+tiger.lo: tiger-tab.h
+CLEANFILES             += tiger-tab.h
+noinst_PROGRAMS                += tiger-mktab
+tiger-tab.h: tiger-mktab$e
+       $(AM_V_GEN)./tiger-mktab >tiger-tab.h.new && \
+               mv tiger-tab.h.new tiger-tab.h
+
+## Barreto and Rijmen's `Whirlpool' hash function.
+HASHES                 += whirlpool whirlpool256
+whirlpool.lo: whirlpool-tab.h
+CLEANFILES             += whirlpool-tab.h
+noinst_PROGRAMS                += whirlpool-mktab
+whirlpool-tab.h: whirlpool-mktab$e
+       $(AM_V_GEN)./whirlpool-mktab >whirlpool-tab.h.new && \
+               mv whirlpool-tab.h.new whirlpool-tab.h
+
+## Bellare, Canetti and Krawczyk's `HMAC' mode for message authentication.
+HASHMACMODES           += hmac
+
+## MGF1, used in OAEP and PSS.
+HASHCIPHERMODES                += mgf
+
+###--------------------------------------------------------------------------
+### Other symmetric primitives.
+
+## The CRC32 algorithm, which is useful, but has no worthwhile security.
+pkginclude_HEADERS     += crc32.h
+libsymm_la_SOURCES     += crc32.c
+ALL_HASHES             += crc32=gcrc32
+
+## Rivest's `RC4' stream cipher.
+pkginclude_HEADERS     += rc4.h
+libsymm_la_SOURCES     += rc4.c
+TESTS                  += rc4.$t
+EXTRA_DIST             += t/rc4
+ALL_CIPHERS            += rc4
+
+## Coppersmith and Rogaway's `SEAL' pseudorandom function.
+pkginclude_HEADERS     += seal.h
+libsymm_la_SOURCES     += seal.c
+TESTS                  += seal.$t
+EXTRA_DIST             += t/seal
+ALL_CIPHERS            += seal
+
+###--------------------------------------------------------------------------
+### Autogenerated mode implementations.
+
+## The master stamp file, indicating that we generated all of the sources.
+CLEANFILES             += modes/gen-stamp
+EXTRA_DIST             += mode.h.in mode.c.in
+modes/gen-stamp:
+       $(AM_V_at)$(MKDIR_P) modes
+       $(AM_V_GEN)$(multigen) -g $(srcdir)/mode.c.in \
+               modes/@base-@mode.c \
+               base="$(BLKCS)" mode="$(BLKCMODES)"
+       $(AM_V_at)$(multigen) -g $(srcdir)/mode.h.in \
+               modes/@base-@mode.h \
+               base="$(BLKCS)" mode="$(BLKCMODES)"
+       $(AM_V_at)$(multigen) -g $(srcdir)/mode.c.in \
+               modes/@base-@mode.c \
+               base="$(HASHES)" mode="$(HASHMODES)"
+       $(AM_V_at)$(multigen) -g $(srcdir)/mode.h.in \
+               modes/@base-@mode.h \
+               base="$(HASHES)" mode="$(HASHMODES)"
+       $(AM_V_at)touch modes/gen-stamp
+
+## The individual mode interfaces and implementations.
+pkginclude_HEADERS     += $(MODE_H)
+
+## Generated implementations.
+BUILT_SOURCES          += $(GENMODES_C)
+CLEANFILES             += $(GENMODES_C)
+nodist_libsymm_la_SOURCES += $(GENMODES_C)
+$(GENMODES_C): modes/gen-stamp
+
+## Generated interfaces.
+BUILT_SOURCES          += $(GENMODES_H)
+CLEANFILES             += $(GENMODES_H)
+nodist_pkginclude_HEADERS += $(GENMODES_H)
+$(GENMODES_H): modes/gen-stamp
+
+###--------------------------------------------------------------------------
+### Tables of classes for encryption, hashing, and message authentication.
+
+## The skeleton for the class tables.
+EXTRA_DIST             += gthingtab.c.in
+
+## Table of cipher classes.
+pkginclude_HEADERS     += gcipher.h
+CLEANFILES             += gciphertab.c
+nodist_libsymm_la_SOURCES += gciphertab.c
+gciphertab.c: gthingtab.c.in
+       $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gciphertab.c \
+               what=gcipher cls=gccipher thing="$(ALL_CIPHERS)"
+
+## Table of hash classes.
+pkginclude_HEADERS     += ghash.h ghash-def.h
+CLEANFILES             += ghashtab.c
+nodist_libsymm_la_SOURCES += ghashtab.c
+ghashtab.c: gthingtab.c.in
+       $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in ghashtab.c \
+               what=ghash cls=gchash thing="$(ALL_HASHES)"
+
+## Table of MAC classes.
+pkginclude_HEADERS     += gmac.h
+CLEANFILES             += gmactab.c
+nodist_libsymm_la_SOURCES += gmactab.c
+gmactab.c: gthingtab.c.in
+       $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gmactab.c \
+               what=gmac cls=gcmac thing="$(ALL_MACS)"
+
+###--------------------------------------------------------------------------
+### Testing.
+
+## Run the test programs.
+TESTS                  += $(SYMM_TESTS)
+EXTRA_DIST             += $(SYMM_TEST_FILES)
+
+## A piece of sample text for round-trip testing encryption modes.
+EXTRA_DIST             += daftstory.h
+
+## Clean the debris from the `modes' subdirectory.
+CLEANFILES             += modes/*.to modes/*.$t
+
+###----- That's all, folks --------------------------------------------------
similarity index 100%
rename from tests/aes-trans
rename to symm/aes-trans
diff --git a/symm/blkc.h b/symm/blkc.h
new file mode 100644 (file)
index 0000000..d6e3da0
--- /dev/null
@@ -0,0 +1,345 @@
+/* -*-c-*-
+ *
+ * Common definitions for block ciphers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_BLKC_H
+#define CATACOMB_BLKC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+
+#include <mLib/bits.h>
+
+/*----- Theory of operation -----------------------------------------------*
+ *
+ * A block cipher has associated with it a triple, called PRE_CLASS, of the
+ * form `(TYPE, ENDIAN, BITS)', where TYPE is either `N' (representing an
+ * implemented bit size) or `X' (representing an unimplemented bit size,
+ * causing loops to be compiled rather than unrolled code), ENDIAN is `B'
+ * (big) or `L' (little), and BITS is the block size of the cipher in bits.
+ */
+
+/*----- Data movement macros ----------------------------------------------*/
+
+/*
+ * `The C preprocessor.  You will never find a more wretched hive of bogus
+ * hackery.  We must be cautious.'
+ */
+
+/* --- General dispatch macros --- */
+
+#define BLKC_DOGLUE(x, y) x ## y
+#define BLKC_GLUE(x, y) BLKC_DOGLUE(x, y)
+#define BLKC_APPLY(f, x) f x
+#define BLKC_FIRST(x, y, z) x
+#define BLKC_SECOND(x, y, z) y
+#define BLKC_THIRD(x, y, z) z
+#define BLKC_TYPE(PRE) BLKC_APPLY(BLKC_FIRST, PRE##_CLASS)
+#define BLKC_ENDIAN(PRE) BLKC_APPLY(BLKC_SECOND, PRE##_CLASS)
+#define BLKC_BITS(PRE) BLKC_APPLY(BLKC_THIRD, PRE##_CLASS)
+
+#define BLKC_STORE_E(PRE) BLKC_GLUE(STORE32_, BLKC_ENDIAN(PRE))
+#define BLKC_LOAD_E(PRE) BLKC_GLUE(LOAD32_, BLKC_ENDIAN(PRE))
+
+/* --- Interface macros --- */
+
+#define BLKC_STORE(PRE, b, w)                                          \
+  BLKC_GLUE(BLKC_STORE_, BLKC_TYPE(PRE))                               \
+    (PRE, b, w, BLKC_STORE_E(PRE), BLKC_BITS(PRE))
+
+#define BLKC_XSTORE(PRE, b, w, wx)                                     \
+  BLKC_GLUE(BLKC_XSTORE_, BLKC_TYPE(PRE))                              \
+    (PRE, b, w, wx, BLKC_STORE_E(PRE), BLKC_BITS(PRE))
+
+#define BLKC_LOAD(PRE, w, b)                                           \
+  BLKC_GLUE(BLKC_LOAD_, BLKC_TYPE(PRE))                                        \
+    (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE))
+
+#define BLKC_XLOAD(PRE, w, b)                                          \
+  BLKC_GLUE(BLKC_XLOAD_, BLKC_TYPE(PRE))                               \
+    (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE))
+
+#define BLKC_MOVE(PRE, w, wx)                                          \
+  BLKC_GLUE(BLKC_MOVE_, BLKC_TYPE(PRE))                                        \
+    (PRE, w, wx, BLKC_BITS(PRE))
+
+#define BLKC_XMOVE(PRE, w, wx)                                         \
+  BLKC_GLUE(BLKC_XMOVE_, BLKC_TYPE(PRE))                               \
+    (PRE, w, wx, BLKC_BITS(PRE))
+
+#define BLKC_STEP(PRE, w)                                              \
+  BLKC_GLUE(BLKC_STEP_X_, BLKC_ENDIAN(PRE))                            \
+    (PRE, w)
+
+#define BLKC_ZERO(PRE, w)                                              \
+  BLKC_GLUE(BLKC_ZERO_, BLKC_TYPE(PRE))                                        \
+    (PRE, w, BLKC_BITS(PRE))
+
+#define BLKC_SET(PRE, w, x)                                            \
+  BLKC_GLUE(BLKC_SET_X_, BLKC_ENDIAN(PRE))                             \
+    (PRE, w, x)
+
+#define BLKC_SHOW(PRE, tag, w) do {                                    \
+  fputs(tag ": ", stdout);                                             \
+  BLKC_SKEL_X(PRE, BLKC_W(w);, printf("%08x ", *_w++););               \
+  fputc('\n', stdout);                                                 \
+} while (0)
+
+/* --- General implementation skeleton --- */
+
+#define BLKC_SKEL(PRE, decl, guts) do {                                        \
+  decl                                                                 \
+  guts                                                                 \
+} while (0)
+
+#define BLKC_P(p) register octet *_p = (octet *)(p)
+#define BLKC_W(w) register uint32 *_w = (w)
+#define BLKC_WX(wx) register uint32 *_wx = (wx)
+
+/* --- Implementation for unusual block sizes --- */
+
+#define BLKC_SKEL_X(PRE, decl, guts)                                   \
+  BLKC_SKEL(PRE, unsigned _i; decl,                                    \
+           for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) {                  \
+             guts                                                      \
+           })
+
+#define BLKC_STORE_X(PRE, b, w, op, n)                                 \
+  BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w);,                                \
+             op(_p, *_w); _p += 4; _w++; )
+
+#define BLKC_XSTORE_X(PRE, b, w, wx, op, n)                            \
+  BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);,     \
+             op(_p, *_w ^ *_wx); _p += 4; _w++; _wx++; )
+
+#define BLKC_LOAD_X(PRE, w, b, op, n)                                  \
+  BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);,                                \
+             *_w = op(_p); _p += 4; _w++; )
+
+#define BLKC_XLOAD_X(PRE, w, b, op, n)                                 \
+  BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);,                                \
+             *_w ^= op(_p); _p += 4; _w++; )
+
+#define BLKC_MOVE_X(PRE, w, wx, n)                                     \
+  BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);,                      \
+             *_w = *_wx; _w++; _wx++; )                                \
+
+#define BLKC_XMOVE_X(PRE, w, wx, n)                                    \
+  BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);,                      \
+             *_w ^= *_wx; _w++; _wx++; )                               \
+
+#define BLKC_ZERO_X(PRE, w, n)                                         \
+  BLKC_SKEL_X(PRE, BLKC_W(w);, *_w++ = 0;)
+
+#define BLKC_STEP_X_B(PRE, w) do {                                     \
+  unsigned _i = PRE##_BLKSZ / 4; BLKC_W(w); uint32 _x = 0;             \
+  while (_i && !_x) { _i--; _w[_i] = _x = U32(_w[_i] + 1); }           \
+} while (0)
+
+#define BLKC_STEP_X_L(PRE, w) do {                                     \
+  unsigned _i = 0; BLKC_W(w); uint32 _x = 0;                           \
+  while (_i < PRE##_BLKSZ / 4 && !_x)                                  \
+    { _w[_i] = _x = U32(_w[_i] + 1); _i++; }                           \
+} while (0)
+
+#define BLKC_SET_X_B(PRE, w, x) do {                                   \
+  unsigned _i; BLKC_W(w); unsigned long _x = x;                                \
+  for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) {                           \
+    *_w++ = U32(_x);                                                   \
+    _x = ((_x & ~MASK32) >> 16) >> 16;                                 \
+  }                                                                    \
+} while (0)
+
+#define BLKC_SET_X_L(PRE, w, x) do {                                   \
+  unsigned _i; BLKC_W(w); unsigned long _x = x;        _w += PRE##_BLKSZ / 4;  \
+  for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) {                           \
+    *--_w = U32(_x);                                                   \
+    _x = ((_x & ~MASK32) >> 16) >> 16;                                 \
+  }                                                                    \
+} while (0)
+
+/* --- Implementation for known block sizes --- */
+
+#define BLKC_SKEL_64(PRE, decl, op, guts)                              \
+  BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1);)
+
+#define BLKC_SKEL_96(PRE, decl, op, guts)                              \
+  BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2);)
+
+#define BLKC_SKEL_128(PRE, decl, op, guts)                             \
+  BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);)
+
+#define BLKC_SKEL_192(PRE, decl, op, guts)                             \
+  BLKC_SKEL(PRE, decl,                                                 \
+           guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);         \
+           guts(op, 4); guts(op, 5);)
+
+#define BLKC_SKEL_256(PRE, decl, op, guts)                             \
+  BLKC_SKEL(PRE, decl,                                                 \
+           guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);         \
+           guts(op, 4); guts(op, 5); guts(op, 6); guts(op, 7);)
+
+#define BLKC_STORE_GUTS(op, i) op(_p + 4 * i, _w[i])
+#define BLKC_XSTORE_GUTS(op, i) op(_p + 4 * i, _w[i] ^ _wx[i])
+#define BLKC_LOAD_GUTS(op, i) _w[i] = op(_p + 4 * i)
+#define BLKC_XLOAD_GUTS(op, i) _w[i] ^= op(_p + 4 * i)
+#define BLKC_MOVE_GUTS(op, i) _w[i] = _wx[i]
+#define BLKC_XMOVE_GUTS(op, i) _w[i] ^= _wx[i]
+#define BLKC_ZERO_GUTS(op, i) _w[i] = 0
+
+#define BLKC_STORE_N(PRE, b, w, op, n)                                 \
+  BLKC_GLUE(BLKC_SKEL_, n)                                             \
+    (PRE, BLKC_P(b); const BLKC_W(w);, op, BLKC_STORE_GUTS)
+
+#define BLKC_XSTORE_N(PRE, b, w, wx, op, n)                            \
+  BLKC_GLUE(BLKC_SKEL_, n)                                             \
+    (PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);,              \
+     op, BLKC_XSTORE_GUTS)
+
+#define BLKC_LOAD_N(PRE, w, b, op, n)                                  \
+  BLKC_GLUE(BLKC_SKEL_, n)                                             \
+    (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_LOAD_GUTS)
+
+#define BLKC_XLOAD_N(PRE, w, b, op, n)                                 \
+  BLKC_GLUE(BLKC_SKEL_, n)                                             \
+    (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_XLOAD_GUTS)
+
+#define BLKC_MOVE_N(PRE, w, wx, n)                                     \
+  BLKC_GLUE(BLKC_SKEL_, n)                                             \
+    (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_MOVE_GUTS)
+
+#define BLKC_ZERO_N(PRE, w, n)                                         \
+  BLKC_GLUE(BLKC_SKEL_, n)                                             \
+    (PRE, BLKC_W(w); , op, BLKC_ZERO_GUTS)
+
+#define BLKC_XMOVE_N(PRE, w, wx, n)                                    \
+  BLKC_GLUE(BLKC_SKEL_, n)                                             \
+    (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_XMOVE_GUTS)
+
+/*----- Test rig for block ciphers ----------------------------------------*/
+
+/* --- @BLKC_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for cipher-specific definitions
+ *
+ * Use:                Standard test rig for block ciphers.
+ */
+
+#ifdef TEST_RIG
+
+#include <string.h>
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define BLKC_VERIFY(PRE, pre)                                          \
+                                                                       \
+static int pre##_verify(dstr *v)                                       \
+{                                                                      \
+  pre##_ctx k;                                                         \
+  uint32 p[PRE##_BLKSZ / 4];                                           \
+  uint32 c[PRE##_BLKSZ / 4];                                           \
+  uint32 d[PRE##_BLKSZ / 4];                                           \
+  dstr b = DSTR_INIT;                                                  \
+  int ok = 1;                                                          \
+                                                                       \
+  /* --- Initialize the key buffer --- */                              \
+                                                                       \
+  dstr_ensure(&b, PRE##_BLKSZ);                                                \
+  b.len = PRE##_BLKSZ;                                                 \
+  pre##_init(&k, v[0].buf, v[0].len);                                  \
+  BLKC_LOAD(PRE, p, v[1].buf);                                         \
+  BLKC_LOAD(PRE, c, v[2].buf);                                         \
+                                                                       \
+  /* --- Test encryption --- */                                                \
+                                                                       \
+  BLKC_MOVE(PRE, d, p);                                                        \
+  pre##_eblk(&k, d, d);                                                        \
+  BLKC_STORE(PRE, b.buf, d);                                           \
+  if (memcmp(b.buf, v[2].buf, PRE##_BLKSZ)) {                          \
+    ok = 0;                                                            \
+    printf("\nfail encryption:"                                                \
+          "\n\tkey        = ");                                        \
+    type_hex.dump(&v[0], stdout);                                      \
+    printf("\n\tplaintext  = "); type_hex.dump(&v[1], stdout);         \
+    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);         \
+    printf("\n\tcalculated = "); type_hex.dump(&b, stdout);            \
+    putchar('\n');                                                     \
+  }                                                                    \
+                                                                       \
+  /* --- Test decryption --- */                                                \
+                                                                       \
+  BLKC_MOVE(PRE, d, c);                                                        \
+  pre##_dblk(&k, d, d);                                                        \
+  BLKC_STORE(PRE, b.buf, d);                                           \
+  if (memcmp(b.buf, v[1].buf, PRE##_BLKSZ)) {                          \
+    ok = 0;                                                            \
+    printf("\nfail decryption:"                                                \
+          "\n\tkey        = ");                                        \
+    type_hex.dump(&v[0], stdout);                                      \
+    printf("\n\tciphertext = "); type_hex.dump(&v[2], stdout);         \
+    printf("\n\texpected   = "); type_hex.dump(&v[1], stdout);         \
+    printf("\n\tcalculated = "); type_hex.dump(&b, stdout);            \
+    putchar('\n');                                                     \
+  }                                                                    \
+                                                                       \
+  /* --- Return --- */                                                 \
+                                                                       \
+  return (ok);                                                         \
+}
+
+#define BLKC_TEST(PRE, pre)                                            \
+                                                                       \
+BLKC_VERIFY(PRE, pre)                                                  \
+                                                                       \
+static const test_chunk defs[] = {                                     \
+  { #pre, pre##_verify, { &type_hex, &type_hex, &type_hex, 0 } },      \
+  { 0, 0, { 0 } }                                                      \
+};                                                                     \
+                                                                       \
+int main(int argc, char *argv[])                                       \
+{                                                                      \
+  test_run(argc, argv, defs, SRCDIR"/t/" #pre);                                \
+  return (0);                                                          \
+}
+
+#else
+#  define BLKC_VERIFY(PRE, pre)
+#  define BLKC_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/blowfish-mktab.c b/symm/blowfish-mktab.c
new file mode 100644 (file)
index 0000000..752fb32
--- /dev/null
@@ -0,0 +1,190 @@
+/* -*-c-*-
+ *
+ * Build Blowfish key table
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @spigot@ --- *
+ *
+ * Arguments:  @uint32 *buf@ = pointer to the output buffer
+ *             @size_t n@ = number of output digits wanted
+ *
+ * Returns:    ---
+ *
+ * Use:                Writes digits of %$\pi$% to the given array.  The algorithm
+ *             is based on the Spigot algorithm by Stanley Rabinowitz and
+ *             Stan Wagon, published in Amer.Math.Monthly, March 1995, with
+ *             bug fixes by C. Haenel.  I then bodged it to output hex
+ *             digits rather than decimal ones, and to leave off the initial
+ *             `3'.
+ *
+ *             I've not analysed the algorithm very much.
+ */
+
+#define SPIGOT_WORDS (18 + 4 * 256ul)
+#define SPIGOT_BITS 8
+#define SPIGOT_RADIX (1ul << SPIGOT_BITS)
+#define SPIGOT_BUFLEN (SPIGOT_WORDS * 32)
+
+#ifdef QUIET
+#  define Q(x)
+#else
+#  define Q(x) x
+#endif
+
+static void spigot(uint32 *buf, size_t n)
+{
+  uint32 acc = 0;
+  int b = -1;
+  unsigned a[SPIGOT_BUFLEN] = { 0 };
+  uint32 p = 0;
+  unsigned f = 0;
+  unsigned max = 32 * n;
+  Q( size_t step = n / 60; )
+
+  Q( fputs("[                                                         ]\r[",
+          stderr); )
+
+#define EMIT(z) do {                                                   \
+  if (b == -1)                                                         \
+    b = 0;                                                             \
+  else {                                                               \
+    acc = (acc << SPIGOT_BITS) | (z);                                  \
+    b += SPIGOT_BITS;                                                  \
+    if (b == 32) {                                                     \
+      *buf++ = acc;                                                    \
+      acc = 0;                                                         \
+      b = 0;                                                           \
+      n--;                                                             \
+      if (!n)                                                          \
+       goto done;                                                      \
+      Q( if (n % step == 0)                                            \
+          fputc('.', stderr); )                                        \
+    }                                                                  \
+  }                                                                    \
+} while (0)
+
+  while (n) {
+    uint32 q = 0;
+    uint32 i;
+    uint32 x = 0;
+    uint32 k = max * 2 - 1;
+
+    for (i = max; i; i--) {
+      x = (b == -1 ? SPIGOT_RADIX * 2 : a[i - 1] << SPIGOT_BITS) + q * i;
+      q = x / k;
+      a[i - 1] = x - q * k;
+      k -= 2;
+    }
+
+    k = x & (SPIGOT_RADIX - 1);
+    if (k == SPIGOT_RADIX - 1)
+      f++;
+    else {
+      EMIT(p + (x >> SPIGOT_BITS));
+      if (f) {
+       unsigned d = (x >= SPIGOT_RADIX ? 0 : SPIGOT_RADIX - 1);
+       while (f) {
+         EMIT(d);
+         f--;
+       }
+      }
+      p = k;
+    }
+  }
+
+done:;
+  Q( fputc('\n', stderr); )
+
+#undef EMIT
+}
+
+/* --- @main@ --- */
+
+int main(void)
+{
+  uint32 dbuf[SPIGOT_WORDS];
+  int i, j;
+  uint32 *d = dbuf;
+
+  spigot(d, SPIGOT_WORDS);
+
+  fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * Blowfish initial key table [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_BLOWFISH_TAB_H\n\
+#define CATACOMB_BLOWFISH_TAB_H\n\
+\n\
+#define BLOWFISH_IKEY {                                                        \\\n\
+  { ", stdout);
+
+  for (i = 0; i < 18; i++) {
+    printf("0x%08x", *d++);
+    if (i == 17)
+      fputs(" },                                               \\\n\
+                                                                       \\\n\
+  { ", stdout);
+    else if (i % 4 == 3)
+      fputs(",                 \\\n    ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+    printf("0x%08x", *d++);
+    if (i == 255) {
+      if (j == 3)
+       fputs(" }                       \\\n}\n\n#endif\n", stdout);
+      else
+       fputs(" },                      \\\n\
+                                                                       \\\n\
+  { ", stdout);
+    } else if (i % 4 == 3)
+      fputs(",                 \\\n    ", stdout);
+    else
+      fputs(", ", stdout);
+    }
+  }
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/blowfish.c b/symm/blowfish.c
new file mode 100644 (file)
index 0000000..4bfb84d
--- /dev/null
@@ -0,0 +1,206 @@
+/* -*-c-*-
+ *
+ * The Blowfish block cipher
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "blowfish.h"
+#include "blowfish-tab.h"
+#include "blkc.h"
+#include "gcipher.h"
+#include "paranoia.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+static const blowfish_ctx ikey = BLOWFISH_IKEY;
+
+const octet blowfish_keysz[] = { KSZ_RANGE, BLOWFISH_KEYSZ, 1, 56, 1 };
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define ROUND(k, x, y, r) do {                                         \
+  x ^= *r;                                                             \
+  y ^= ((k->s0[U8(x >> 24)] +                                          \
+        k->s1[U8(x >> 16)]) ^                                          \
+        k->s2[U8(x >>  8)]) +                                          \
+        k->s3[U8(x >>  0)];                                            \
+} while (0)
+
+#define EBLK(k, a, b, c, d) do {                                       \
+  const uint32 *_r = k->p;                                             \
+  uint32 _x = a;                                                       \
+  uint32 _y = b;                                                       \
+  ROUND(k, _x, _y, _r++);                                              \
+  ROUND(k, _y, _x, _r++);                                              \
+  ROUND(k, _x, _y, _r++);                                              \
+  ROUND(k, _y, _x, _r++);                                              \
+  ROUND(k, _x, _y, _r++);                                              \
+  ROUND(k, _y, _x, _r++);                                              \
+  ROUND(k, _x, _y, _r++);                                              \
+  ROUND(k, _y, _x, _r++);                                              \
+  ROUND(k, _x, _y, _r++);                                              \
+  ROUND(k, _y, _x, _r++);                                              \
+  ROUND(k, _x, _y, _r++);                                              \
+  ROUND(k, _y, _x, _r++);                                              \
+  ROUND(k, _x, _y, _r++);                                              \
+  ROUND(k, _y, _x, _r++);                                              \
+  ROUND(k, _x, _y, _r++);                                              \
+  ROUND(k, _y, _x, _r++);                                              \
+  c = _y ^ k->p[17];                                                   \
+  d = _x ^ k->p[16];                                                   \
+} while (0)
+
+#define DBLK(k, a, b, c, d) do {                                       \
+  const uint32 *_r = k->p + 18;                                                \
+  uint32 _x = a;                                                       \
+  uint32 _y = b;                                                       \
+  ROUND(k, _x, _y, --_r);                                              \
+  ROUND(k, _y, _x, --_r);                                              \
+  ROUND(k, _x, _y, --_r);                                              \
+  ROUND(k, _y, _x, --_r);                                              \
+  ROUND(k, _x, _y, --_r);                                              \
+  ROUND(k, _y, _x, --_r);                                              \
+  ROUND(k, _x, _y, --_r);                                              \
+  ROUND(k, _y, _x, --_r);                                              \
+  ROUND(k, _x, _y, --_r);                                              \
+  ROUND(k, _y, _x, --_r);                                              \
+  ROUND(k, _x, _y, --_r);                                              \
+  ROUND(k, _y, _x, --_r);                                              \
+  ROUND(k, _x, _y, --_r);                                              \
+  ROUND(k, _y, _x, --_r);                                              \
+  ROUND(k, _x, _y, --_r);                                              \
+  ROUND(k, _y, _x, --_r);                                              \
+  c = _y ^ k->p[0];                                                    \
+  d = _x ^ k->p[1];                                                    \
+} while (0)
+
+/*----- Low-level encryption interface ------------------------------------*/
+
+/* --- @blowfish_init@ --- *
+ *
+ * Arguments:  @blowfish_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Blowfish key buffer.  Blowfish accepts
+ *             a more-or-less arbitrary size key.
+ */
+
+void blowfish_init(blowfish_ctx *k, const void *buf, size_t sz)
+{
+  KSZ_ASSERT(blowfish, sz);
+
+  /* --- Copy the initial value over --- */
+
+  memcpy(k, &ikey, sizeof(ikey));
+
+  /* --- Initialize the %$P$% array --- */
+
+  {
+    const octet *p = buf;
+    const octet *q = p + sz;
+    int i = 0, j = 0;
+    uint32 x = 0;
+
+    while (i < 18) {
+      x = (x << 8) | U8(*p++);
+      if (p >= q)
+       p = buf;
+      if (++j >= 4) {
+       k->p[i++] ^= x;
+       x = 0;
+       j = 0;
+      }
+    }
+
+    x = 0;
+  }
+
+  /* --- Now mangle the complete array of keys --- */
+
+  {
+    uint32 b[2];
+    int i;
+
+    b[0] = b[1] = 0;
+
+    for (i = 0; i < 18; i += 2) {
+      blowfish_eblk(k, b, b);
+      k->p[i] = b[0]; k->p[i + 1] = b[1];
+    }
+
+    for (i = 0; i < 256; i += 2) {
+      blowfish_eblk(k, b, b);
+      k->s0[i] = b[0]; k->s0[i + 1] = b[1];
+    }
+
+    for (i = 0; i < 256; i += 2) {
+      blowfish_eblk(k, b, b);
+      k->s1[i] = b[0]; k->s1[i + 1] = b[1];
+    }
+
+    for (i = 0; i < 256; i += 2) {
+      blowfish_eblk(k, b, b);
+      k->s2[i] = b[0]; k->s2[i + 1] = b[1];
+    }
+
+    for (i = 0; i < 256; i += 2) {
+      blowfish_eblk(k, b, b);
+      k->s3[i] = b[0]; k->s3[i + 1] = b[1];
+    }
+
+    BURN(b);
+  }
+}
+
+/* --- @blowfish_eblk@, @blowfish_dblk@ --- *
+ *
+ * Arguments:  @const blowfish_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+void blowfish_eblk(const blowfish_ctx *k, const uint32 *s, uint32 *d)
+{
+  EBLK(k, s[0], s[1], d[0], d[1]);
+}
+
+void blowfish_dblk(const blowfish_ctx *k, const uint32 *s, uint32 *d)
+{
+  DBLK(k, s[0], s[1], d[0], d[1]);
+}
+
+BLKC_TEST(BLOWFISH, blowfish)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/blowfish.h b/symm/blowfish.h
new file mode 100644 (file)
index 0000000..eedf820
--- /dev/null
@@ -0,0 +1,105 @@
+/* -*-c-*-
+ *
+ * The Blowfish block cipher
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Notes on the Blowfish block cipher --------------------------------*
+ *
+ * Blowfish was invented by Bruce Schneier.  The algorithm is unpatented and
+ * free for anyone to use.  It's fast, simple, offers a big key, and is
+ * looking relatively bulletproof.  It's also this author's block cipher of
+ * choice, for what little that's worth.  The disadvantage is that Blowfish
+ * has a particularly heavyweight key schedule.
+ */
+
+#ifndef CATACOMB_BLOWFISH_H
+#define CATACOMB_BLOWFISH_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define BLOWFISH_BLKSZ 8
+#define BLOWFISH_KEYSZ 32
+#define BLOWFISH_CLASS (N, B, 64)
+
+extern const octet blowfish_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct blowfish_ctx {
+  uint32 p[18];
+  uint32 s0[256], s1[256], s2[256], s3[256];
+} blowfish_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @blowfish_init@ --- *
+ *
+ * Arguments:  @blowfish_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Blowfish key buffer.  Blowfish accepts
+ *             a more-or-less arbitrary size key.
+ */
+
+extern void blowfish_init(blowfish_ctx */*k*/,
+                         const void */*buf*/, size_t /*sz*/);
+
+/* --- @blowfish_eblk@, @blowfish_dblk@ --- *
+ *
+ * Arguments:  @const blowfish_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void blowfish_eblk(const blowfish_ctx */*k*/,
+                         const uint32 */*s*/, uint32 */*d*/);
+
+extern void blowfish_dblk(const blowfish_ctx */*k*/,
+                         const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/cast-base.h b/symm/cast-base.h
new file mode 100644 (file)
index 0000000..8a8dcc6
--- /dev/null
@@ -0,0 +1,65 @@
+/* -*-c-*-
+ *
+ * Basic macros and definitions for CAST-128 and CAST-256
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_CAST_BASE_H
+#define CATACOMB_CAST_BASE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Round functions ---------------------------------------------------*/
+
+#define CAST_R_guts(km, kr, xx, yy, aop, bop, cop) do {                        \
+  uint32 i = km aop yy;                                                        \
+  unsigned _r = kr;                                                    \
+  i = ROL32(i, _r);                                                    \
+  xx ^= ((cast_s[0][U8(i >> 24)] bop                                   \
+         cast_s[1][U8(i >> 16)]) cop                                   \
+         cast_s[2][U8(i >>  8)]) aop                                   \
+         cast_s[3][U8(i >>  0)];                                       \
+} while (0)
+
+#define CAST_R1(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, +, ^, -)
+#define CAST_R2(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, ^, -, +)
+#define CAST_R3(km, kr, xx, yy) CAST_R_guts(km, kr, xx, yy, -, +, ^)
+
+/*----- Global variables --------------------------------------------------*/
+
+extern const uint32 cast_s[4][256], cast_sk[4][256];
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/cast-s.c b/symm/cast-s.c
new file mode 100644 (file)
index 0000000..968d888
--- /dev/null
@@ -0,0 +1,39 @@
+/* -*-c-*-
+ *
+ * Basic S-boxes for CAST-128 and CAST-256
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "cast-base.h"
+#include "cast-tab.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const uint32 cast_s[4][256] = CAST_S;
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/cast-sk.c b/symm/cast-sk.c
new file mode 100644 (file)
index 0000000..d1620ee
--- /dev/null
@@ -0,0 +1,39 @@
+/* -*-c-*-
+ *
+ * Key-schedule S-boxes for CAST-128
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "cast-base.h"
+#include "cast-tab.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const uint32 cast_sk[4][256] = CAST_SK;
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/cast-tab.h b/symm/cast-tab.h
new file mode 100644 (file)
index 0000000..b6e2f9f
--- /dev/null
@@ -0,0 +1,567 @@
+/* -*-c-*-
+ *
+ * S-boxes for CAST-128 and CAST-256
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_CAST_TAB_H
+#define CATACOMB_CAST_TAB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- S-box tables ------------------------------------------------------*/
+
+#define CAST_S {                                                       \
+  { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a,                    \
+    0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,                    \
+    0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675,                    \
+    0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,                    \
+    0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2,                    \
+    0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,                    \
+    0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f,                    \
+    0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,                    \
+    0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de,                    \
+    0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,                    \
+    0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f,                    \
+    0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,                    \
+    0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d,                    \
+    0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,                    \
+    0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165,                    \
+    0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,                    \
+    0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272,                    \
+    0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,                    \
+    0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d,                    \
+    0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,                    \
+    0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a,                    \
+    0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,                    \
+    0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f,                    \
+    0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,                    \
+    0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9,                    \
+    0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,                    \
+    0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6,                    \
+    0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,                    \
+    0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9,                    \
+    0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,                    \
+    0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e,                    \
+    0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,                    \
+    0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e,                    \
+    0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,                    \
+    0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82,                    \
+    0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,                    \
+    0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac,                    \
+    0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,                    \
+    0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f,                    \
+    0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,                    \
+    0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491,                    \
+    0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,                    \
+    0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de,                    \
+    0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,                    \
+    0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a,                    \
+    0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,                    \
+    0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79,                    \
+    0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,                    \
+    0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779,                    \
+    0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,                    \
+    0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755,                    \
+    0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,                    \
+    0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb,                    \
+    0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,                    \
+    0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0,                    \
+    0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,                    \
+    0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79,                    \
+    0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,                    \
+    0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298,                    \
+    0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,                    \
+    0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571,                    \
+    0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,                    \
+    0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d,                    \
+    0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf },                  \
+                                                                       \
+  { 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380,                    \
+    0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,                    \
+    0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba,                    \
+    0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,                    \
+    0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909,                    \
+    0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,                    \
+    0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b,                    \
+    0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,                    \
+    0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4,                    \
+    0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,                    \
+    0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f,                    \
+    0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,                    \
+    0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21,                    \
+    0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,                    \
+    0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d,                    \
+    0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,                    \
+    0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f,                    \
+    0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,                    \
+    0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d,                    \
+    0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,                    \
+    0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4,                    \
+    0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,                    \
+    0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801,                    \
+    0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,                    \
+    0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755,                    \
+    0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,                    \
+    0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709,                    \
+    0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,                    \
+    0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b,                    \
+    0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,                    \
+    0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c,                    \
+    0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,                    \
+    0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9,                    \
+    0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,                    \
+    0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3,                    \
+    0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,                    \
+    0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9,                    \
+    0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,                    \
+    0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab,                    \
+    0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,                    \
+    0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4,                    \
+    0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,                    \
+    0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43,                    \
+    0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,                    \
+    0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8,                    \
+    0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,                    \
+    0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171,                    \
+    0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,                    \
+    0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89,                    \
+    0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,                    \
+    0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b,                    \
+    0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,                    \
+    0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb,                    \
+    0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,                    \
+    0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e,                    \
+    0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,                    \
+    0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea,                    \
+    0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,                    \
+    0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea,                    \
+    0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,                    \
+    0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd,                    \
+    0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,                    \
+    0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef,                    \
+    0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 },                  \
+                                                                       \
+  { 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907,                    \
+    0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,                    \
+    0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae,                    \
+    0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,                    \
+    0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e,                    \
+    0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,                    \
+    0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc,                    \
+    0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,                    \
+    0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e,                    \
+    0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,                    \
+    0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f,                    \
+    0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,                    \
+    0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99,                    \
+    0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,                    \
+    0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f,                    \
+    0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,                    \
+    0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380,                    \
+    0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,                    \
+    0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8,                    \
+    0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,                    \
+    0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504,                    \
+    0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,                    \
+    0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6,                    \
+    0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,                    \
+    0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e,                    \
+    0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,                    \
+    0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d,                    \
+    0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,                    \
+    0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1,                    \
+    0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,                    \
+    0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c,                    \
+    0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,                    \
+    0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15,                    \
+    0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,                    \
+    0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4,                    \
+    0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,                    \
+    0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b,                    \
+    0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,                    \
+    0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392,                    \
+    0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,                    \
+    0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231,                    \
+    0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,                    \
+    0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889,                    \
+    0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,                    \
+    0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67,                    \
+    0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,                    \
+    0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49,                    \
+    0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,                    \
+    0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d,                    \
+    0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,                    \
+    0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d,                    \
+    0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,                    \
+    0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e,                    \
+    0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,                    \
+    0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767,                    \
+    0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,                    \
+    0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce,                    \
+    0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,                    \
+    0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24,                    \
+    0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,                    \
+    0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0,                    \
+    0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,                    \
+    0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5,                    \
+    0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 },                  \
+                                                                       \
+  { 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298,                    \
+    0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,                    \
+    0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120,                    \
+    0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,                    \
+    0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220,                    \
+    0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,                    \
+    0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe,                    \
+    0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,                    \
+    0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701,                    \
+    0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,                    \
+    0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b,                    \
+    0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,                    \
+    0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93,                    \
+    0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,                    \
+    0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746,                    \
+    0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,                    \
+    0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9,                    \
+    0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,                    \
+    0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb,                    \
+    0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,                    \
+    0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c,                    \
+    0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,                    \
+    0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7,                    \
+    0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,                    \
+    0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340,                    \
+    0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,                    \
+    0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327,                    \
+    0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,                    \
+    0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec,                    \
+    0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,                    \
+    0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205,                    \
+    0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,                    \
+    0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031,                    \
+    0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,                    \
+    0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5,                    \
+    0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,                    \
+    0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c,                    \
+    0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,                    \
+    0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69,                    \
+    0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,                    \
+    0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9,                    \
+    0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,                    \
+    0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff,                    \
+    0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,                    \
+    0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3,                    \
+    0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,                    \
+    0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2,                    \
+    0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,                    \
+    0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff,                    \
+    0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,                    \
+    0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091,                    \
+    0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,                    \
+    0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df,                    \
+    0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,                    \
+    0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf,                    \
+    0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,                    \
+    0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367,                    \
+    0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,                    \
+    0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c,                    \
+    0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,                    \
+    0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43,                    \
+    0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,                    \
+    0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e,                    \
+    0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 }                   \
+}
+
+#define CAST_SK {                                                      \
+  { 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911,                    \
+    0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,                    \
+    0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00,                    \
+    0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,                    \
+    0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180,                    \
+    0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,                    \
+    0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2,                    \
+    0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,                    \
+    0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725,                    \
+    0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,                    \
+    0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b,                    \
+    0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,                    \
+    0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571,                    \
+    0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,                    \
+    0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec,                    \
+    0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,                    \
+    0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea,                    \
+    0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,                    \
+    0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263,                    \
+    0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,                    \
+    0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468,                    \
+    0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,                    \
+    0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b,                    \
+    0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,                    \
+    0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284,                    \
+    0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,                    \
+    0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4,                    \
+    0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,                    \
+    0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7,                    \
+    0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,                    \
+    0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce,                    \
+    0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,                    \
+    0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6,                    \
+    0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,                    \
+    0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4,                    \
+    0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,                    \
+    0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561,                    \
+    0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,                    \
+    0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6,                    \
+    0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,                    \
+    0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406,                    \
+    0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,                    \
+    0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472,                    \
+    0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,                    \
+    0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487,                    \
+    0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,                    \
+    0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288,                    \
+    0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,                    \
+    0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2,                    \
+    0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,                    \
+    0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78,                    \
+    0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,                    \
+    0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76,                    \
+    0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,                    \
+    0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0,                    \
+    0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,                    \
+    0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58,                    \
+    0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,                    \
+    0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2,                    \
+    0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,                    \
+    0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be,                    \
+    0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,                    \
+    0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55,                    \
+    0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 },                  \
+                                                                       \
+  { 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c,                    \
+    0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,                    \
+    0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9,                    \
+    0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,                    \
+    0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e,                    \
+    0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,                    \
+    0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866,                    \
+    0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,                    \
+    0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c,                    \
+    0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,                    \
+    0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd,                    \
+    0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,                    \
+    0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53,                    \
+    0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,                    \
+    0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d,                    \
+    0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,                    \
+    0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf,                    \
+    0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,                    \
+    0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807,                    \
+    0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,                    \
+    0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a,                    \
+    0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,                    \
+    0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563,                    \
+    0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,                    \
+    0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0,                    \
+    0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,                    \
+    0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be,                    \
+    0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,                    \
+    0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0,                    \
+    0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,                    \
+    0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2,                    \
+    0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,                    \
+    0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853,                    \
+    0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,                    \
+    0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa,                    \
+    0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,                    \
+    0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9,                    \
+    0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,                    \
+    0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751,                    \
+    0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,                    \
+    0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358,                    \
+    0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,                    \
+    0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397,                    \
+    0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,                    \
+    0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459,                    \
+    0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,                    \
+    0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4,                    \
+    0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,                    \
+    0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f,                    \
+    0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,                    \
+    0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb,                    \
+    0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,                    \
+    0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2,                    \
+    0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,                    \
+    0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab,                    \
+    0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,                    \
+    0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b,                    \
+    0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,                    \
+    0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b,                    \
+    0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,                    \
+    0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855,                    \
+    0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,                    \
+    0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454,                    \
+    0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f },                  \
+                                                                       \
+  { 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693,                    \
+    0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,                    \
+    0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82,                    \
+    0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,                    \
+    0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd,                    \
+    0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,                    \
+    0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f,                    \
+    0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,                    \
+    0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9,                    \
+    0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,                    \
+    0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e,                    \
+    0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,                    \
+    0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83,                    \
+    0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,                    \
+    0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e,                    \
+    0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,                    \
+    0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a,                    \
+    0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,                    \
+    0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f,                    \
+    0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,                    \
+    0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b,                    \
+    0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,                    \
+    0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78,                    \
+    0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,                    \
+    0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d,                    \
+    0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,                    \
+    0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802,                    \
+    0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,                    \
+    0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9,                    \
+    0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,                    \
+    0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302,                    \
+    0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,                    \
+    0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858,                    \
+    0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,                    \
+    0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a,                    \
+    0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,                    \
+    0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4,                    \
+    0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,                    \
+    0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df,                    \
+    0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,                    \
+    0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9,                    \
+    0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,                    \
+    0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c,                    \
+    0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,                    \
+    0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07,                    \
+    0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,                    \
+    0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939,                    \
+    0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,                    \
+    0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e,                    \
+    0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,                    \
+    0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378,                    \
+    0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,                    \
+    0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd,                    \
+    0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,                    \
+    0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567,                    \
+    0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,                    \
+    0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2,                    \
+    0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,                    \
+    0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf,                    \
+    0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,                    \
+    0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2,                    \
+    0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,                    \
+    0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada,                    \
+    0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 },                  \
+                                                                       \
+  { 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095,                    \
+    0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,                    \
+    0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174,                    \
+    0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,                    \
+    0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940,                    \
+    0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,                    \
+    0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42,                    \
+    0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,                    \
+    0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164,                    \
+    0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,                    \
+    0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4,                    \
+    0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,                    \
+    0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0,                    \
+    0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,                    \
+    0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6,                    \
+    0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,                    \
+    0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491,                    \
+    0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,                    \
+    0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b,                    \
+    0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,                    \
+    0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8,                    \
+    0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,                    \
+    0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006,                    \
+    0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,                    \
+    0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564,                    \
+    0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,                    \
+    0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab,                    \
+    0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,                    \
+    0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc,                    \
+    0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,                    \
+    0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8,                    \
+    0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,                    \
+    0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441,                    \
+    0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,                    \
+    0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f,                    \
+    0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,                    \
+    0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504,                    \
+    0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,                    \
+    0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c,                    \
+    0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,                    \
+    0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6,                    \
+    0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,                    \
+    0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd,                    \
+    0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,                    \
+    0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4,                    \
+    0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,                    \
+    0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc,                    \
+    0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,                    \
+    0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba,                    \
+    0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,                    \
+    0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf,                    \
+    0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,                    \
+    0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603,                    \
+    0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,                    \
+    0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37,                    \
+    0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,                    \
+    0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819,                    \
+    0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,                    \
+    0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d,                    \
+    0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,                    \
+    0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347,                    \
+    0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,                    \
+    0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d,                    \
+    0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e }                   \
+}
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/cast128.c b/symm/cast128.c
new file mode 100644 (file)
index 0000000..cbff8d1
--- /dev/null
@@ -0,0 +1,300 @@
+/* -*-c-*-
+ *
+ * The CAST-128 block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "cast-base.h"
+#include "cast128.h"
+#include "gcipher.h"
+#include "paranoia.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet cast128_keysz[] = { KSZ_RANGE, CAST128_KEYSZ, 0, 16, 1 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @cast128_init@ --- *
+ *
+ * Arguments:  @cast128_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a CAST-128 key buffer.  CAST-128 accepts
+ *             128-bit keys or shorter.
+ */
+
+void cast128_init(cast128_ctx *k, const void *buf, size_t sz)
+{
+  const octet *p = buf;
+  uint32 kk[4];
+  unsigned i;
+  uint32 a, b, c, d,  aa, bb, cc, dd;
+
+  /* --- Fiddle with the key size a bit --- */
+
+  KSZ_ASSERT(cast128, sz);
+
+  if (sz > 10)
+    k->r = 16;
+  else
+    k->r = 12;
+
+  /* --- Read the key into the array --- */
+
+  i = 0;
+  b = 32; aa = 0;
+  for (;;) {
+    if (!sz)
+      break;
+    b -= 8;
+    aa |= ((uint32)*p++ << b);
+    sz--;
+    if (b == 0) {
+      kk[i++] = aa;
+      if (i == 4)
+       break;
+      aa = 0;
+      b = 32;
+    }
+  }
+
+  for (; i < 4; i++) {
+    kk[i] = aa;
+    aa = 0;
+  }
+
+  /* --- Read the key words out --- */
+
+  a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3];
+
+#define X_0123 a
+#define X_4567 b
+#define X_89ab c
+#define X_cdef d
+
+#define X_0 U8(X_0123 >> 24)
+#define X_1 U8(X_0123 >> 16)
+#define X_2 U8(X_0123 >>  8)
+#define X_3 U8(X_0123 >>  0)
+#define X_4 U8(X_4567 >> 24)
+#define X_5 U8(X_4567 >> 16)
+#define X_6 U8(X_4567 >>  8)
+#define X_7 U8(X_4567 >>  0)
+#define X_8 U8(X_89ab >> 24)
+#define X_9 U8(X_89ab >> 16)
+#define X_a U8(X_89ab >>  8)
+#define X_b U8(X_89ab >>  0)
+#define X_c U8(X_cdef >> 24)
+#define X_d U8(X_cdef >> 16)
+#define X_e U8(X_cdef >>  8)
+#define X_f U8(X_cdef >>  0)
+
+#define Z_0123 aa
+#define Z_4567 bb
+#define Z_89ab cc
+#define Z_cdef dd
+
+#define Z_0 U8(Z_0123 >> 24)
+#define Z_1 U8(Z_0123 >> 16)
+#define Z_2 U8(Z_0123 >>  8)
+#define Z_3 U8(Z_0123 >>  0)
+#define Z_4 U8(Z_4567 >> 24)
+#define Z_5 U8(Z_4567 >> 16)
+#define Z_6 U8(Z_4567 >>  8)
+#define Z_7 U8(Z_4567 >>  0)
+#define Z_8 U8(Z_89ab >> 24)
+#define Z_9 U8(Z_89ab >> 16)
+#define Z_a U8(Z_89ab >>  8)
+#define Z_b U8(Z_89ab >>  0)
+#define Z_c U8(Z_cdef >> 24)
+#define Z_d U8(Z_cdef >> 16)
+#define Z_e U8(Z_cdef >>  8)
+#define Z_f U8(Z_cdef >>  0)
+
+#define SK(w, x, y, z)                                                 \
+  cast_sk[0][w] ^ cast_sk[1][x] ^ cast_sk[2][y] ^ cast_sk[3][z]
+
+  i = 0;
+  Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8];
+  Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a];
+  Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9];
+  Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b];
+  k->km[i++] = SK(Z_8, Z_9, Z_7, Z_6) ^ cast_sk[0][Z_2];
+  k->km[i++] = SK(Z_a, Z_b, Z_5, Z_4) ^ cast_sk[1][Z_6];
+  k->km[i++] = SK(Z_c, Z_d, Z_3, Z_2) ^ cast_sk[2][Z_9];
+  k->km[i++] = SK(Z_e, Z_f, Z_1, Z_0) ^ cast_sk[3][Z_c];
+  X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0];
+  X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2];
+  X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1];
+  X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3];
+  k->km[i++] = SK(X_3, X_2, X_c, X_d) ^ cast_sk[0][X_8];
+  k->km[i++] = SK(X_1, X_0, X_e, X_f) ^ cast_sk[1][X_d];
+  k->km[i++] = SK(X_7, X_6, X_8, X_9) ^ cast_sk[2][X_3];
+  k->km[i++] = SK(X_5, X_4, X_a, X_b) ^ cast_sk[3][X_7];
+  Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8];
+  Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a];
+  Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9];
+  Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b];
+  k->km[i++] = SK(Z_3, Z_2, Z_c, Z_d) ^ cast_sk[0][Z_9];
+  k->km[i++] = SK(Z_1, Z_0, Z_e, Z_f) ^ cast_sk[1][Z_c];
+  k->km[i++] = SK(Z_7, Z_6, Z_8, Z_9) ^ cast_sk[2][Z_2];
+  k->km[i++] = SK(Z_5, Z_4, Z_a, Z_b) ^ cast_sk[3][Z_6];
+  X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0];
+  X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2];
+  X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1];
+  X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3];
+  k->km[i++] = SK(X_8, X_9, X_7, X_6) ^ cast_sk[0][X_3];
+  k->km[i++] = SK(X_a, X_b, X_5, X_4) ^ cast_sk[1][X_7];
+  k->km[i++] = SK(X_c, X_d, X_3, X_2) ^ cast_sk[2][X_8];
+  k->km[i++] = SK(X_e, X_f, X_1, X_0) ^ cast_sk[3][X_d];
+
+  i = 0;
+  Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8];
+  Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a];
+  Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9];
+  Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b];
+  k->kr[i++] = (SK(Z_8, Z_9, Z_7, Z_6) ^ cast_sk[0][Z_2]) & 0x1f;
+  k->kr[i++] = (SK(Z_a, Z_b, Z_5, Z_4) ^ cast_sk[1][Z_6]) & 0x1f;
+  k->kr[i++] = (SK(Z_c, Z_d, Z_3, Z_2) ^ cast_sk[2][Z_9]) & 0x1f;
+  k->kr[i++] = (SK(Z_e, Z_f, Z_1, Z_0) ^ cast_sk[3][Z_c]) & 0x1f;
+  X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0];
+  X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2];
+  X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1];
+  X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3];
+  k->kr[i++] = (SK(X_3, X_2, X_c, X_d) ^ cast_sk[0][X_8]) & 0x1f;
+  k->kr[i++] = (SK(X_1, X_0, X_e, X_f) ^ cast_sk[1][X_d]) & 0x1f;
+  k->kr[i++] = (SK(X_7, X_6, X_8, X_9) ^ cast_sk[2][X_3]) & 0x1f;
+  k->kr[i++] = (SK(X_5, X_4, X_a, X_b) ^ cast_sk[3][X_7]) & 0x1f;
+  Z_0123 = X_0123 ^ SK(X_d, X_f, X_c, X_e) ^ cast_sk[2][X_8];
+  Z_4567 = X_89ab ^ SK(Z_0, Z_2, Z_1, Z_3) ^ cast_sk[3][X_a];
+  Z_89ab = X_cdef ^ SK(Z_7, Z_6, Z_5, Z_4) ^ cast_sk[0][X_9];
+  Z_cdef = X_4567 ^ SK(Z_a, Z_9, Z_b, Z_8) ^ cast_sk[1][X_b];
+  k->kr[i++] = (SK(Z_3, Z_2, Z_c, Z_d) ^ cast_sk[0][Z_9]) & 0x1f;
+  k->kr[i++] = (SK(Z_1, Z_0, Z_e, Z_f) ^ cast_sk[1][Z_c]) & 0x1f;
+  k->kr[i++] = (SK(Z_7, Z_6, Z_8, Z_9) ^ cast_sk[2][Z_2]) & 0x1f;
+  k->kr[i++] = (SK(Z_5, Z_4, Z_a, Z_b) ^ cast_sk[3][Z_6]) & 0x1f;
+  X_0123 = Z_89ab ^ SK(Z_5, Z_7, Z_4, Z_6) ^ cast_sk[2][Z_0];
+  X_4567 = Z_0123 ^ SK(X_0, X_2, X_1, X_3) ^ cast_sk[3][Z_2];
+  X_89ab = Z_4567 ^ SK(X_7, X_6, X_5, X_4) ^ cast_sk[0][Z_1];
+  X_cdef = Z_cdef ^ SK(X_a, X_9, X_b, X_8) ^ cast_sk[1][Z_3];
+  k->kr[i++] = (SK(X_8, X_9, X_7, X_6) ^ cast_sk[0][X_3]) & 0x1f;
+  k->kr[i++] = (SK(X_a, X_b, X_5, X_4) ^ cast_sk[1][X_7]) & 0x1f;
+  k->kr[i++] = (SK(X_c, X_d, X_3, X_2) ^ cast_sk[2][X_8]) & 0x1f;
+  k->kr[i++] = (SK(X_e, X_f, X_1, X_0) ^ cast_sk[3][X_d]) & 0x1f;
+
+  BURN(kk);
+}
+
+/* --- @cast128_eblk@, @cast128_dblk@ --- *
+ *
+ * Arguments:  @const cast128_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+void cast128_eblk(const cast128_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 a = s[0], b = s[1];
+  const uint32 *km = k->km;
+  const octet *kr = k->kr;
+
+  switch (k->r) {
+    default:
+      CAST_R1(*km++, *kr++, a, b);
+      CAST_R2(*km++, *kr++, b, a);
+      CAST_R3(*km++, *kr++, a, b);
+      CAST_R1(*km++, *kr++, b, a);
+      CAST_R2(*km++, *kr++, a, b);
+      CAST_R3(*km++, *kr++, b, a);
+      CAST_R1(*km++, *kr++, a, b);
+      CAST_R2(*km++, *kr++, b, a);
+      CAST_R3(*km++, *kr++, a, b);
+      CAST_R1(*km++, *kr++, b, a);
+      CAST_R2(*km++, *kr++, a, b);
+      CAST_R3(*km++, *kr++, b, a);
+      if (k->r == 12)
+       break;
+      CAST_R1(*km++, *kr++, a, b);
+      CAST_R2(*km++, *kr++, b, a);
+      CAST_R3(*km++, *kr++, a, b);
+      CAST_R1(*km++, *kr++, b, a);
+      break;
+  }
+
+  d[0] = b; d[1] = a;
+}
+
+void cast128_dblk(const cast128_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 a = s[0], b = s[1];
+  const uint32 *km = k->km + k->r;
+  const octet *kr = k->kr + k->r;
+
+  switch (k->r) {
+    case 16:
+    default:
+      CAST_R1(*--km, *--kr, a, b);
+      CAST_R3(*--km, *--kr, b, a);
+      CAST_R2(*--km, *--kr, a, b);
+      CAST_R1(*--km, *--kr, b, a);
+    case 12:
+      CAST_R3(*--km, *--kr, a, b);
+      CAST_R2(*--km, *--kr, b, a);
+      CAST_R1(*--km, *--kr, a, b);
+      CAST_R3(*--km, *--kr, b, a);
+      CAST_R2(*--km, *--kr, a, b);
+      CAST_R1(*--km, *--kr, b, a);
+      CAST_R3(*--km, *--kr, a, b);
+      CAST_R2(*--km, *--kr, b, a);
+      CAST_R1(*--km, *--kr, a, b);
+      CAST_R3(*--km, *--kr, b, a);
+      CAST_R2(*--km, *--kr, a, b);
+      CAST_R1(*--km, *--kr, b, a);
+      break;
+  }
+
+  d[0] = b; d[1] = a;
+}
+
+BLKC_TEST(CAST128, cast128)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/cast128.h b/symm/cast128.h
new file mode 100644 (file)
index 0000000..01ba6c6
--- /dev/null
@@ -0,0 +1,114 @@
+/* -*-c-*-
+ *
+ * The CAST-128 block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the CAST-128 block cipher --------------------------------*
+ *
+ * CAST, designed by Carlisle Adams and Stafford Tavares, is a method for
+ * designing block ciphers, based around the concept of `bent functions'.  It
+ * is described in the paper `Constructing Symmetric Ciphers using the CAST
+ * Design Procedure' by Carlisle Adams.
+ *
+ * CAST-128, defined in RFC2144, is a particular instance of the CAST design
+ * procedure, The cipher seems strong and fairly quick.  The design procedure
+ * itself is patented, although the cipher CAST-128 is free to use.
+ *
+ * Although CAST ciphers are resistant to differential and linear
+ * cryptanalysis, some instances have been broken by more advanced techniques
+ * -- the CAST procedure does not guarantee a strong cipher.  However,
+ * CAST-128 has so far resisted all attacks against it, and has now been
+ * accepted by the Canadian government for protection of all `Designated'
+ * material.
+ */
+
+#ifndef CATACOMB_CAST128_H
+#define CATACOMB_CAST128_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define CAST128_BLKSZ 8
+#define CAST128_KEYSZ 16
+#define CAST128_CLASS (N, B, 64)
+
+extern const octet cast128_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct cast128_ctx {
+  unsigned r;
+  uint32 km[16];
+  octet kr[16];
+} cast128_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @cast128_init@ --- *
+ *
+ * Arguments:  @cast128_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a CAST-128 key buffer.  CAST-128 accepts
+ *             128-bit keys or shorter.
+ */
+
+extern void cast128_init(cast128_ctx */*k*/,
+                        const void */*buf*/, size_t /*sz*/);
+
+/* --- @cast128_eblk@, @cast128_dblk@ --- *
+ *
+ * Arguments:  @const cast128_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void cast128_eblk(const cast128_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*d*/);
+
+extern void cast128_dblk(const cast128_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/cast256.c b/symm/cast256.c
new file mode 100644 (file)
index 0000000..38aec60
--- /dev/null
@@ -0,0 +1,203 @@
+/* -*-c-*-
+ *
+ * The CAST-256 block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "cast-base.h"
+#include "cast256.h"
+#include "gcipher.h"
+#include "paranoia.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet cast256_keysz[] = { KSZ_RANGE, CAST256_KEYSZ, 0, 32, 1 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @cast256_init@ --- *
+ *
+ * Arguments:  @cast128_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a CAST-256 key buffer.  CAST-256 accepts
+ *             256-bit keys or shorter.
+ */
+
+void cast256_init(cast256_ctx *k, const void *buf, size_t sz)
+{
+  const octet *p = buf;
+  uint32 kk[8];
+  uint32 *km;
+  octet *kr;
+  unsigned i, j;
+  uint32 a, b, c, d, e, f, g, h;
+  uint32 m;
+  unsigned r;
+
+  /* --- Fiddle with the key size --- */
+
+  KSZ_ASSERT(cast256, sz);
+
+  /* --- Read the key into the array --- */
+
+  i = 0;
+  b = 32; a = 0;
+  for (;;) {
+    if (!sz)
+      break;
+    b -= 8;
+    a |= ((uint32)*p++ << b);
+    sz--;
+    if (b == 0) {
+      kk[i++] = a;
+      if (i == 8)
+       break;
+      a = 0;
+      b = 32;
+    }
+  }
+
+  for (; i < 8; i++) {
+    kk[i] = a;
+    a = 0;
+  }
+
+  /* --- Read the key words out --- */
+
+  a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3];
+  e = kk[4]; f = kk[5]; g = kk[6]; h = kk[7];
+
+#define ROOT2 0x5a827999
+#define ROOT3 0x6ed9eba1
+
+  m = ROOT2;
+  r = 19;
+
+  km = k->km;
+  kr = k->kr;
+  for (i = 0; i < 12; i++) {
+    for (j = 0; j < 2; j++) {
+      CAST_R1(m, r, g, h); m += ROOT3; r = (r + 17) & 0x1f;
+      CAST_R2(m, r, f, g); m += ROOT3; r = (r + 17) & 0x1f;
+      CAST_R3(m, r, e, f); m += ROOT3; r = (r + 17) & 0x1f;
+      CAST_R1(m, r, d, e); m += ROOT3; r = (r + 17) & 0x1f;
+      CAST_R2(m, r, c, d); m += ROOT3; r = (r + 17) & 0x1f;
+      CAST_R3(m, r, b, c); m += ROOT3; r = (r + 17) & 0x1f;
+      CAST_R1(m, r, a, b); m += ROOT3; r = (r + 17) & 0x1f;
+      CAST_R2(m, r, h, a); m += ROOT3; r = (r + 17) & 0x1f;
+    }
+    km[0] = h; km[1] = f; km[2] = d; km[3] = b;
+    kr[0] = a & 0x1f; kr[1] = c & 0x1f; kr[2] = e & 0x1f; kr[3] = g & 0x1f;
+    km += 4; kr += 4;
+  }
+}
+
+/* --- @cast256_eblk@, @cast256_dblk@ --- *
+ *
+ * Arguments:  @const cast256_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define Q0(k, r, a, b, c, d) do {                                      \
+  CAST_R1(k[0], r[0], c, d);                                           \
+  CAST_R2(k[1], r[1], b, c);                                           \
+  CAST_R3(k[2], r[2], a, b);                                           \
+  CAST_R1(k[3], r[3], d, a);                                           \
+} while (0)
+
+#define Q1(k, r, a, b, c, d) do {                                      \
+  CAST_R1(k[3], r[3], d, a);                                           \
+  CAST_R3(k[2], r[2], a, b);                                           \
+  CAST_R2(k[1], r[1], b, c);                                           \
+  CAST_R1(k[0], r[0], c, d);                                           \
+} while (0)
+
+void cast256_eblk(const cast256_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
+  const uint32 *km = k->km;
+  const octet *kr = k->kr;
+
+  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+
+  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+  Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+
+  d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
+}
+
+void cast256_dblk(const cast256_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
+  const uint32 *km = k->km + 48;
+  const octet *kr = k->kr + 48;
+
+  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+
+  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+  km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+
+  d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
+}
+
+BLKC_TEST(CAST256, cast256)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/cast256.h b/symm/cast256.h
new file mode 100644 (file)
index 0000000..dd96460
--- /dev/null
@@ -0,0 +1,109 @@
+/* -*-c-*-
+ *
+ * The CAST-128 block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the CAST-256 block cipher --------------------------------*
+ *
+ * CAST, designed by Carlisle Adams and Stafford Tavares, is a method for
+ * designing block ciphers, based around the concept of `bent functions'.  It
+ * is described in the paper `Constructing Symmetric Ciphers using the CAST
+ * Design Procedure' by Carlisle Adams.
+ *
+ * CAST-256, defined in RFC2612, is a particular instance of the CAST design
+ * procedure.  It is an `incomplete' Feistel network.  It uses the same
+ * S-boxes and round functions as CAST-128.
+ *
+ * CAST-256 was submitted to the AES contest, but was not selected as one of
+ * the five `finalist' algorithms.
+ */
+
+#ifndef CATACOMB_CAST256_H
+#define CATACOMB_CAST256_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define CAST256_BLKSZ 16
+#define CAST256_KEYSZ 32
+#define CAST256_CLASS (N, B, 128)
+
+extern const octet cast256_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct cast256_ctx {
+  uint32 km[48];
+  octet kr[48];
+} cast256_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @cast256_init@ --- *
+ *
+ * Arguments:  @cast256_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a CAST-256 key buffer.  CAST-256 accepts
+ *             256-bit keys or shorter.
+ */
+
+extern void cast256_init(cast256_ctx */*k*/,
+                        const void */*buf*/, size_t /*sz*/);
+
+/* --- @cast256_eblk@, @cast256_dblk@ --- *
+ *
+ * Arguments:  @const cast256_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void cast256_eblk(const cast256_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*d*/);
+
+extern void cast256_dblk(const cast256_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/cbc-def.h b/symm/cbc-def.h
new file mode 100644 (file)
index 0000000..f48ee46
--- /dev/null
@@ -0,0 +1,547 @@
+/* -*-c-*-
+ *
+ * Definitions for cipher block chaining mode
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_CBC_DEF_H
+#define CATACOMB_CBC_DEF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+#  include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @CBC_DEF@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates an implementation for CBC stealing mode.
+ */
+
+#define CBC_DEF(PRE, pre)                                              \
+                                                                       \
+/* --- @pre_cbcgetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @const pre_cbcctx *ctx@ = pointer to CBC context block  \
+ *             @void *iv@ = pointer to output data block               \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reads the currently set IV.  Reading and setting an IV  \
+ *             is transparent to the CBC encryption or decryption      \
+ *             process.                                                \
+ */                                                                    \
+                                                                       \
+void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv)                 \
+{                                                                      \
+  BLKC_STORE(PRE, iv, ctx->iv);                                                \
+}                                                                      \
+                                                                       \
+/* --- @pre_cbcsetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
+ *             @cnost void *iv@ = pointer to IV to set                 \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the IV to use for subsequent encryption.           \
+ */                                                                    \
+                                                                       \
+void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv)                 \
+{                                                                      \
+  BLKC_LOAD(PRE, ctx->iv, iv);                                         \
+}                                                                      \
+                                                                       \
+/* --- @pre_cbcsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the CBC context to use a different cipher key.     \
+ */                                                                    \
+                                                                       \
+void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k)            \
+{                                                                      \
+  ctx->ctx = *k;                                                       \
+}                                                                      \
+                                                                       \
+/* --- @pre_cbcinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to cipher context           \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a CBC context ready for use.  The @iv@      \
+ *             argument may be passed as a null pointer to set a zero  \
+ *             IV.  Apart from that, this call is equivalent to calls  \
+ *             to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@.      \
+ */                                                                    \
+                                                                       \
+void pre##_cbcinit(pre##_cbcctx *ctx,                                  \
+                    const void *key, size_t sz,                        \
+                    const void *iv)                                    \
+{                                                                      \
+  static const octet zero[PRE##_BLKSZ] = { 0 };                                \
+  pre##_init(&ctx->ctx, key, sz);                                      \
+  BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero);                             \
+}                                                                      \
+                                                                       \
+/* --- @pre_cbcencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts a block with a block cipher in CBC mode, with  \
+ *             ciphertext stealing and other clever tricks.            \
+ *             Essentially, data can be encrypted in arbitrary sized   \
+ *             chunks, although decryption must use the same chunks.   \
+ */                                                                    \
+                                                                       \
+void pre##_cbcencrypt(pre##_cbcctx *ctx,                               \
+                       const void *src, void *dest,                    \
+                       size_t sz)                                      \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+                                                                       \
+  /* --- Empty blocks are trivial --- */                               \
+                                                                       \
+  if (!sz)                                                             \
+    return;                                                            \
+                                                                       \
+  /* --- Extra magical case for a short block --- *                    \
+   *                                                                   \
+   * Encrypt the IV, then exclusive-or the plaintext with the octets   \
+   * of the encrypted IV, shifting ciphertext octets in instead.  This \
+   * basically switches over to CFB.                                   \
+   */                                                                  \
+                                                                       \
+  if (sz < PRE##_BLKSZ) {                                              \
+    octet b[PRE##_BLKSZ];                                              \
+    unsigned i;                                                                \
+                                                                       \
+    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
+    BLKC_STORE(PRE, b, ctx->iv);                                       \
+    if (d) {                                                           \
+      for (i = 0; i < sz; i++)                                         \
+       d[i] = b[i] ^ (s ? s[i] : 0);                                   \
+    }                                                                  \
+    memmove(b, b + sz, PRE##_BLKSZ - sz);                              \
+    memcpy(b + PRE##_BLKSZ - sz, d, sz);                               \
+    BLKC_LOAD(PRE, ctx->iv, b);                                                \
+    return;                                                            \
+  }                                                                    \
+                                                                       \
+  /* --- Do the main chunk of encryption --- *                         \
+   *                                                                   \
+   * This will do the whole lot if it's a whole number of blocks.  For \
+   * each block, XOR it with the previous ciphertext in @iv@, encrypt, \
+   * and keep a copy of the ciphertext for the next block.             \
+   */                                                                  \
+                                                                       \
+  while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                 \
+    if (s) {                                                           \
+      BLKC_XLOAD(PRE, ctx->iv, s);                                     \
+      s += PRE##_BLKSZ;                                                        \
+    }                                                                  \
+    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
+    if (d) {                                                           \
+      BLKC_STORE(PRE, d, ctx->iv);                                     \
+      d += PRE##_BLKSZ;                                                        \
+    }                                                                  \
+    sz -= PRE##_BLKSZ;                                                 \
+  }                                                                    \
+                                                                       \
+  /* --- Do the tail-end block and bit-left-over --- *                 \
+   *                                                                   \
+   * This isn't very efficient.  That shouldn't matter much.           \
+   */                                                                  \
+                                                                       \
+  if (sz) {                                                            \
+    octet b[PRE##_BLKSZ];                                              \
+    unsigned i;                                                                \
+                                                                       \
+    /* --- Let @sz@ be the size of the partial block --- */            \
+                                                                       \
+    sz -= PRE##_BLKSZ;                                                 \
+                                                                       \
+    /* --- First stage --- *                                           \
+     *                                                                 \
+     * XOR the complete block with the current IV, and encrypt it.  The        \
+     * first part of the result is the partial ciphertext block.  Don't        \
+     * write that out yet, because I've not read the partial plaintext \
+     * block.                                                          \
+     */                                                                        \
+                                                                       \
+    if (s) BLKC_XLOAD(PRE, ctx->iv, s);                                        \
+    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
+    BLKC_STORE(PRE, b, ctx->iv);                                       \
+                                                                       \
+    /* --- Second stage --- *                                          \
+     *                                                                 \
+     * Now XOR in the partial plaintext block, writing out the         \
+     * ciphertext as I go.  Then encrypt, and write the complete       \
+     * ciphertext block.                                               \
+     */                                                                        \
+                                                                       \
+    if (s) s += PRE##_BLKSZ;                                           \
+    if (d) d += PRE##_BLKSZ;                                           \
+    for (i = 0; i < sz; i++) {                                         \
+      register octet x = b[i];                                         \
+      if (s) b[i] ^= s[i];                                             \
+      if (d) d[i] = x;                                                 \
+    }                                                                  \
+    BLKC_LOAD(PRE, ctx->iv, b);                                                \
+    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
+    if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv);                  \
+  }                                                                    \
+                                                                       \
+  /* --- Done --- */                                                   \
+                                                                       \
+  return;                                                              \
+}                                                                      \
+                                                                       \
+/* --- @pre_cbcdecrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Decrypts a block with a block cipher in CBC mode, with  \
+ *             ciphertext stealing and other clever tricks.            \
+ *             Essentially, data can be encrypted in arbitrary sized   \
+ *             chunks, although decryption must use the same chunks.   \
+ */                                                                    \
+                                                                       \
+void pre##_cbcdecrypt(pre##_cbcctx *ctx,                               \
+                       const void *src, void *dest,                    \
+                       size_t sz)                                      \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+                                                                       \
+  /* --- Empty blocks are trivial --- */                               \
+                                                                       \
+  if (!sz)                                                             \
+    return;                                                            \
+                                                                       \
+  /* --- Extra magical case for a short block --- *                    \
+   *                                                                   \
+   * Encrypt the IV, then exclusive-or the ciphertext with the octets  \
+   * of the encrypted IV, shifting ciphertext octets in instead.  This \
+   * basically switches over to CFB.                                   \
+   */                                                                  \
+                                                                       \
+  if (sz < PRE##_BLKSZ) {                                              \
+    octet b[PRE##_BLKSZ], c[PRE##_BLKSZ];                              \
+    unsigned i;                                                                \
+                                                                       \
+    pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                           \
+    BLKC_STORE(PRE, b, ctx->iv);                                       \
+    for (i = 0; i < sz; i++) {                                         \
+      register octet x = s[i];                                         \
+      d[i] = b[i] ^ x;                                                 \
+      c[i] = x;                                                                \
+    }                                                                  \
+    memmove(b, b + sz, PRE##_BLKSZ - sz);                              \
+    memcpy(b + PRE##_BLKSZ - sz, c, sz);                               \
+    BLKC_LOAD(PRE, ctx->iv, b);                                                \
+    return;                                                            \
+  }                                                                    \
+                                                                       \
+  /* --- Do the main chunk of decryption --- *                         \
+   *                                                                   \
+   * This will do the whole lot if it's a whole number of blocks.  For \
+   * each block, decrypt, XOR it with the previous ciphertext in @iv@, \
+   * and keep a copy of the ciphertext for the next block.             \
+   */                                                                  \
+                                                                       \
+  while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                 \
+    uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4];                   \
+    BLKC_LOAD(PRE, niv, s);                                            \
+    pre##_dblk(&ctx->ctx, niv, b);                                     \
+    BLKC_XSTORE(PRE, d, b, ctx->iv);                                   \
+    BLKC_MOVE(PRE, ctx->iv, niv);                                      \
+    s += PRE##_BLKSZ;                                                  \
+    d += PRE##_BLKSZ;                                                  \
+    sz -= PRE##_BLKSZ;                                                 \
+  }                                                                    \
+                                                                       \
+  /* --- Do the tail-end block and bit-left-over --- *                 \
+   *                                                                   \
+   * This isn't very efficient.  That shouldn't matter much.           \
+   */                                                                  \
+                                                                       \
+  if (sz) {                                                            \
+    octet b[PRE##_BLKSZ];                                              \
+    uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4];                  \
+    unsigned i;                                                                \
+                                                                       \
+    /* --- Let @sz@ be the size of the partial block --- */            \
+                                                                       \
+    sz -= PRE##_BLKSZ;                                                 \
+                                                                       \
+    /* --- First stage --- *                                           \
+     *                                                                 \
+     * Take the complete ciphertext block, and decrypt it.  This block \
+     * is carried over for the next encryption operation.              \
+     */                                                                        \
+                                                                       \
+    BLKC_LOAD(PRE, niv, s);                                            \
+    pre##_dblk(&ctx->ctx, niv, bk);                                    \
+                                                                       \
+    /* --- Second stage --- *                                          \
+     *                                                                 \
+     * XORing the first few bytes of this with the partial ciphertext  \
+     * block recovers the partial plaintext block.  At the same time,  \
+     * write the partial ciphertext block's contents in ready for stage        \
+     * three.                                                          \
+     */                                                                        \
+                                                                       \
+    BLKC_STORE(PRE, b, bk);                                            \
+    s += PRE##_BLKSZ;                                                  \
+    d += PRE##_BLKSZ;                                                  \
+    for (i = 0; i < sz; i++) {                                         \
+      register octet x = s[i];                                         \
+      d[i] = b[i] ^ x;                                                 \
+      b[i] = x;                                                                \
+    }                                                                  \
+                                                                       \
+    /* --- Third stage --- *                                           \
+     *                                                                 \
+     * Decrypt the block we've got left, and XOR with the initial IV to        \
+     * recover the complete plaintext block.                           \
+     */                                                                        \
+                                                                       \
+    BLKC_LOAD(PRE, bk, b);                                             \
+    pre##_dblk(&ctx->ctx, bk, bk);                                     \
+    BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv);                    \
+    BLKC_MOVE(PRE, ctx->iv, niv);                                      \
+  }                                                                    \
+                                                                       \
+  /* --- Done --- */                                                   \
+                                                                       \
+  return;                                                              \
+}                                                                      \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+static const gcipher_ops gops;                                         \
+                                                                       \
+typedef struct gctx {                                                  \
+  gcipher c;                                                           \
+  pre##_cbcctx k;                                                      \
+} gctx;                                                                        \
+                                                                       \
+static gcipher *ginit(const void *k, size_t sz)                                \
+{                                                                      \
+  gctx *g = S_CREATE(gctx);                                            \
+  g->c.ops = &gops;                                                    \
+  pre##_cbcinit(&g->k, k, sz, 0);                                      \
+  return (&g->c);                                                      \
+}                                                                      \
+                                                                       \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_cbcencrypt(&g->k, s, t, sz);                                   \
+}                                                                      \
+                                                                       \
+static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_cbcdecrypt(&g->k, s, t, sz);                                   \
+}                                                                      \
+                                                                       \
+static void gdestroy(gcipher *c)                                       \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static void gsetiv(gcipher *c, const void *iv)                         \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_cbcsetiv(&g->k, iv);                                           \
+}                                                                      \
+                                                                       \
+static const gcipher_ops gops = {                                      \
+  &pre##_cbc,                                                          \
+  gencrypt, gdecrypt, gdestroy, gsetiv, 0                              \
+};                                                                     \
+                                                                       \
+const gccipher pre##_cbc = {                                           \
+  #pre "-cbc", pre##_keysz, PRE##_BLKSZ,                               \
+  ginit                                                                        \
+};                                                                     \
+                                                                       \
+CBC_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @CBC_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use:                Standard test rig for CBC functions.
+ */
+
+#define CBC_TEST(PRE, pre)                                             \
+                                                                       \
+/* --- Initial plaintext for the test --- */                           \
+                                                                       \
+static const octet text[] = TEXT;                                      \
+                                                                       \
+/* --- Key and IV to use --- */                                                \
+                                                                       \
+static const octet key[] = KEY;                                                \
+static const octet iv[] = IV;                                          \
+                                                                       \
+/* --- Buffers for encryption and decryption output --- */             \
+                                                                       \
+static octet ct[sizeof(text)];                                         \
+static octet pt[sizeof(text)];                                         \
+                                                                       \
+static void hexdump(const octet *p, size_t sz)                         \
+{                                                                      \
+  const octet *q = p + sz;                                             \
+  for (sz = 0; p < q; p++, sz++) {                                     \
+    printf("%02x", *p);                                                        \
+    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
+      putchar(':');                                                    \
+  }                                                                    \
+}                                                                      \
+                                                                       \
+int main(void)                                                         \
+{                                                                      \
+  size_t sz = 0, rest;                                                 \
+  pre##_cbcctx ctx;                                                    \
+  pre##_ctx k;                                                         \
+  int status = 0;                                                      \
+  int done = 0;                                                                \
+                                                                       \
+  size_t keysz = PRE##_KEYSZ ?                                         \
+    PRE##_KEYSZ : strlen((const char *)key);                           \
+                                                                       \
+  fputs(#pre "-cbc: ", stdout);                                                \
+                                                                       \
+  pre##_init(&k, key, keysz);                                          \
+  pre##_cbcsetkey(&ctx, &k);                                           \
+                                                                       \
+  while (sz <= sizeof(text)) {                                         \
+    rest = sizeof(text) - sz;                                          \
+    memcpy(ct, text, sizeof(text));                                    \
+    pre##_cbcsetiv(&ctx, iv);                                          \
+    pre##_cbcencrypt(&ctx, ct, ct, sz);                                        \
+    pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest);                    \
+    memcpy(pt, ct, sizeof(text));                                      \
+    pre##_cbcsetiv(&ctx, iv);                                          \
+    pre##_cbcdecrypt(&ctx, pt, pt, sz);                                        \
+    pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest);                    \
+    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
+      done++;                                                          \
+      if (sizeof(text) < 40 || done % 8 == 0)                          \
+       fputc('.', stdout);                                             \
+      if (done % 480 == 0)                                             \
+       fputs("\n\t", stdout);                                          \
+      fflush(stdout);                                                  \
+    } else {                                                           \
+      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
+      status = 1;                                                      \
+      printf("\tplaintext      = "); hexdump(text, sz);                        \
+       printf(", "); hexdump(text + sz, rest);                         \
+       fputc('\n', stdout);                                            \
+      printf("\tciphertext     = "); hexdump(ct, sz);                  \
+       printf(", "); hexdump(ct + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      printf("\trecovered text = "); hexdump(pt, sz);                  \
+       printf(", "); hexdump(pt + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      fputc('\n', stdout);                                             \
+    }                                                                  \
+    if (sz < 63)                                                       \
+      sz++;                                                            \
+    else                                                               \
+      sz += 9;                                                         \
+  }                                                                    \
+                                                                       \
+  fputs(status ? " failed\n" : " ok\n", stdout);                       \
+  return (status);                                                     \
+}
+
+#else
+#  define CBC_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/cbc.h b/symm/cbc.h
new file mode 100644 (file)
index 0000000..5f1f22a
--- /dev/null
@@ -0,0 +1,171 @@
+/* -*-c-*-
+ *
+ * Ciphertext block chaining for block ciphers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_CBC_H
+#define CATACOMB_CBC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @CBC_DECL@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates declarations for CBC stealing mode.
+ */
+
+#define CBC_DECL(PRE, pre)                                             \
+                                                                       \
+/* --- Cipher block chaining context --- */                            \
+                                                                       \
+typedef struct pre##_cbcctx {                                          \
+  pre##_ctx ctx;                       /* Underlying cipher context */ \
+  uint32 iv[PRE##_BLKSZ / 4];          /* Previous ciphertext or IV */ \
+} pre##_cbcctx;                                                                \
+                                                                       \
+/* --- @pre_cbcgetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @const pre_cbcctx *ctx@ = pointer to CBC context block  \
+ *             @void *iv@ = pointer to output data block               \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reads the currently set IV.  Reading and setting an IV  \
+ *             is transparent to the CBC encryption or decryption      \
+ *             process.                                                \
+ */                                                                    \
+                                                                       \
+extern void pre##_cbcgetiv(const pre##_cbcctx */*ctx*/,                        \
+                          void */*iv*/);                               \
+                                                                       \
+/* --- @pre_cbcsetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
+ *             @cnost void *iv@ = pointer to IV to set                 \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the IV to use for subsequent encryption.           \
+ */                                                                    \
+                                                                       \
+extern void pre##_cbcsetiv(pre##_cbcctx */*ctx*/,                      \
+                          const void */*iv*/);                         \
+                                                                       \
+/* --- @pre_cbcsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the CBC context to use a different cipher key.     \
+ */                                                                    \
+                                                                       \
+extern void pre##_cbcsetkey(pre##_cbcctx */*ctx*/,                     \
+                           const pre##_ctx */*k*/);                    \
+                                                                       \
+/* --- @pre_cbcinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to cipher context           \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a CBC context ready for use.  The @iv@      \
+ *             argument may be passed as a null pointer to set a zero  \
+ *             IV.  Apart from that, this call is equivalent to calls  \
+ *             to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@.      \
+ */                                                                    \
+                                                                       \
+extern void pre##_cbcinit(pre##_cbcctx */*ctx*/,                       \
+                         const void */*key*/, size_t /*sz*/,           \
+                         const void */*iv*/);                          \
+                                                                       \
+/* --- @pre_cbcencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts a block with a block cipher in CBC mode, with  \
+ *             ciphertext stealing and other clever tricks.            \
+ *             Essentially, data can be encrypted in arbitrary sized   \
+ *             chunks, although decryption must use the same chunks.   \
+ */                                                                    \
+                                                                       \
+extern void pre##_cbcencrypt(pre##_cbcctx */*ctx*/,                    \
+                            const void */*src*/, void */*dest*/,       \
+                            size_t /*sz*/);                            \
+                                                                       \
+/* --- @pre_cbcdecrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_cbcctx *ctx@ = pointer to CBC context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Decrypts a block with a block cipher in CBC mode, with  \
+ *             ciphertext stealing and other clever tricks.            \
+ *             Essentially, data can be encrypted in arbitrary sized   \
+ *             chunks, although decryption must use the same chunks.   \
+ */                                                                    \
+                                                                       \
+extern void pre##_cbcdecrypt(pre##_cbcctx */*ctx*/,                    \
+                            const void */*src*/, void */*dest*/,       \
+                            size_t /*sz*/);                            \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+extern const gccipher pre##_cbc;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/cfb-def.h b/symm/cfb-def.h
new file mode 100644 (file)
index 0000000..767f4c4
--- /dev/null
@@ -0,0 +1,506 @@
+/* -*-c-*-
+ *
+ * Definitions for ciphertext feedback mode
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_CFB_DEF_H
+#define CATACOMB_CFB_DEF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+#  include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @CFB_DEF@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates an implementation for CFB mode.
+ */
+
+#define CFB_DEF(PRE, pre)                                              \
+                                                                       \
+/* --- @pre_cfbgetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @const pre_cfbctx *ctx@ = pointer to CFB context block  \
+ *             @void *iv@ = pointer to output data block               \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reads the currently set IV.  Reading and setting an IV  \
+ *             is not transparent to the cipher.  It will add a `step' \
+ *             which must be matched by a similar operation during     \
+ *             decryption.                                             \
+ */                                                                    \
+                                                                       \
+void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv)                 \
+{                                                                      \
+  octet *p = iv;                                                       \
+  unsigned off = ctx->off;                                             \
+  unsigned rest = PRE##_BLKSZ - off;                                   \
+  memcpy(p, ctx->iv + off, rest);                                      \
+  memcpy(p + rest, ctx->iv, off);                                      \
+}                                                                      \
+                                                                       \
+/* --- @pre_cfbsetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *             @cnost void *iv@ = pointer to IV to set                 \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the IV to use for subsequent encryption.           \
+ */                                                                    \
+                                                                       \
+void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv)                 \
+{                                                                      \
+  memcpy(ctx->iv, iv, PRE##_BLKSZ);                                    \
+  ctx->off = PRE##_BLKSZ;                                              \
+}                                                                      \
+                                                                       \
+/* --- @pre_cfbbdry@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Inserts a boundary during encryption.  Successful       \
+ *             decryption must place a similar boundary.               \
+ */                                                                    \
+                                                                       \
+void pre##_cfbbdry(pre##_cfbctx *ctx)                                  \
+{                                                                      \
+  uint32 niv[PRE##_BLKSZ / 4];                                         \
+  BLKC_LOAD(PRE, niv, ctx->iv);                                                \
+  pre##_eblk(&ctx->ctx, niv, niv);                                     \
+  BLKC_STORE(PRE, ctx->iv, niv);                                       \
+  ctx->off = PRE##_BLKSZ;                                              \
+  BURN(niv);                                                           \
+}                                                                      \
+                                                                       \
+/* --- @pre_cfbsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the CFB context to use a different cipher key.     \
+ */                                                                    \
+                                                                       \
+void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k)            \
+{                                                                      \
+  ctx->ctx = *k;                                                       \
+  ctx->off = PRE##_BLKSZ;                                              \
+}                                                                      \
+                                                                       \
+/* --- @pre_cfbinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to cipher context           \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a CFB context ready for use.  You should    \
+ *             ensure that the IV chosen is unique: reusing an IV will \
+ *             compromise the security of at least the first block     \
+ *             encrypted.  This is equivalent to calls to @pre_init@,  \
+ *             @pre_cfbsetkey@ and @pre_cfbsetiv@.                     \
+ */                                                                    \
+                                                                       \
+void pre##_cfbinit(pre##_cfbctx *ctx,                                  \
+                    const void *key, size_t sz,                        \
+                    const void *iv)                                    \
+{                                                                      \
+  static const octet zero[PRE##_BLKSZ] = { 0 };                                \
+  pre##_init(&ctx->ctx, key, sz);                                      \
+  pre##_cfbsetiv(ctx, iv ? iv : zero);                                 \
+}                                                                      \
+                                                                       \
+/* --- @pre_cfbencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts a block with a block cipher in CFB mode.  The  \
+ *             input block may be arbitrary in size.  CFB mode is not  \
+ *             sensitive to block boundaries.                          \
+ */                                                                    \
+                                                                       \
+void pre##_cfbencrypt(pre##_cfbctx *ctx,                               \
+                       const void *src, void *dest,                    \
+                       size_t sz)                                      \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+  unsigned off = ctx->off;                                             \
+                                                                       \
+  /* --- Empty blocks are trivial --- */                               \
+                                                                       \
+  if (!sz)                                                             \
+    return;                                                            \
+                                                                       \
+  /* --- If I can deal with the block from my buffer, do that --- */   \
+                                                                       \
+  if (sz < PRE##_BLKSZ - off)                                          \
+    goto small;                                                                \
+                                                                       \
+  /* --- Finish off what's left in my buffer --- */                    \
+                                                                       \
+  while (off < PRE##_BLKSZ) {                                          \
+    register octet x = *s++;                                           \
+    ctx->iv[off] ^= x;                                                 \
+    if (d) *d++ = ctx->iv[off];                                                \
+    off++;                                                             \
+    sz--;                                                              \
+  }                                                                    \
+                                                                       \
+  /* --- Main encryption loop --- */                                   \
+                                                                       \
+  {                                                                    \
+    uint32 iv[PRE##_BLKSZ / 4];                                                \
+    BLKC_LOAD(PRE, iv, ctx->iv);                                       \
+                                                                       \
+    for (;;) {                                                         \
+      pre##_eblk(&ctx->ctx, iv, iv);                                   \
+      if (sz < PRE##_BLKSZ)                                            \
+       break;                                                          \
+      if (s) {                                                         \
+       BLKC_XLOAD(PRE, iv, s);                                         \
+       s += PRE##_BLKSZ;                                               \
+      }                                                                        \
+      if (d) {                                                         \
+       BLKC_STORE(PRE, d, iv);                                         \
+       d += PRE##_BLKSZ;                                               \
+      }                                                                        \
+      sz -= PRE##_BLKSZ;                                               \
+    }                                                                  \
+    off = 0;                                                           \
+    BLKC_STORE(PRE, ctx->iv, iv);                                      \
+  }                                                                    \
+                                                                       \
+  /* --- Tidying up the tail end --- */                                        \
+                                                                       \
+  if (sz) {                                                            \
+  small:                                                               \
+    do {                                                               \
+      register octet x = *s++;                                         \
+      ctx->iv[off] ^= x;                                               \
+      if (d) *d++ = ctx->iv[off];                                      \
+      off++;                                                           \
+      sz--;                                                            \
+    } while (sz);                                                      \
+  }                                                                    \
+                                                                       \
+  /* --- Done --- */                                                   \
+                                                                       \
+  ctx->off = off;                                                      \
+  return;                                                              \
+}                                                                      \
+                                                                       \
+/* --- @pre_cfbdecrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Decrypts a block with a block cipher in CFB mode.  The  \
+ *             input block may be arbitrary in size.  CFB mode is not  \
+ *             sensitive to block boundaries.                          \
+ */                                                                    \
+                                                                       \
+void pre##_cfbdecrypt(pre##_cfbctx *ctx,                               \
+                       const void *src, void *dest,                    \
+                       size_t sz)                                      \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+  unsigned off = ctx->off;                                             \
+                                                                       \
+  /* --- Empty blocks are trivial --- */                               \
+                                                                       \
+  if (!sz)                                                             \
+    return;                                                            \
+                                                                       \
+  /* --- If I can deal with the block from my buffer, do that --- */   \
+                                                                       \
+  if (sz < PRE##_BLKSZ - off)                                          \
+    goto small;                                                                \
+                                                                       \
+  /* --- Finish off what's left in my buffer --- */                    \
+                                                                       \
+  while (off < PRE##_BLKSZ) {                                          \
+    register octet x = *s++;                                           \
+    *d++ = ctx->iv[off] ^ x;                                           \
+    ctx->iv[off++] = x;                                                        \
+    sz--;                                                              \
+  }                                                                    \
+                                                                       \
+  /* --- Main encryption loop --- */                                   \
+                                                                       \
+  {                                                                    \
+    uint32 iv[PRE##_BLKSZ / 4];                                                \
+    BLKC_LOAD(PRE, iv, ctx->iv);                                       \
+                                                                       \
+    for (;;) {                                                         \
+      uint32 x[PRE##_BLKSZ / 4];                                       \
+      pre##_eblk(&ctx->ctx, iv, iv);                                   \
+      if (sz < PRE##_BLKSZ)                                            \
+       break;                                                          \
+      BLKC_LOAD(PRE, x, s);                                            \
+      BLKC_XSTORE(PRE, d, iv, x);                                      \
+      BLKC_MOVE(PRE, iv, x);                                           \
+      s += PRE##_BLKSZ;                                                        \
+      d += PRE##_BLKSZ;                                                        \
+      sz -= PRE##_BLKSZ;                                               \
+    }                                                                  \
+    off = 0;                                                           \
+    BLKC_STORE(PRE, ctx->iv, iv);                                      \
+  }                                                                    \
+                                                                       \
+  /* --- Tidying up the tail end --- */                                        \
+                                                                       \
+  if (sz) {                                                            \
+  small:                                                               \
+    do {                                                               \
+      register octet x = *s++;                                         \
+      *d++ = ctx->iv[off] ^ x;                                         \
+      ctx->iv[off++] = x;                                              \
+      sz--;                                                            \
+    } while (sz);                                                      \
+  }                                                                    \
+                                                                       \
+  /* --- Done --- */                                                   \
+                                                                       \
+  ctx->off = off;                                                      \
+  return;                                                              \
+}                                                                      \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+static const gcipher_ops gops;                                         \
+                                                                       \
+typedef struct gctx {                                                  \
+  gcipher c;                                                           \
+  pre##_cfbctx k;                                                      \
+} gctx;                                                                        \
+                                                                       \
+static gcipher *ginit(const void *k, size_t sz)                                \
+{                                                                      \
+  gctx *g = S_CREATE(gctx);                                            \
+  g->c.ops = &gops;                                                    \
+  pre##_cfbinit(&g->k, k, sz, 0);                                      \
+  return (&g->c);                                                      \
+}                                                                      \
+                                                                       \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_cfbencrypt(&g->k, s, t, sz);                                   \
+}                                                                      \
+                                                                       \
+static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_cfbdecrypt(&g->k, s, t, sz);                                   \
+}                                                                      \
+                                                                       \
+static void gdestroy(gcipher *c)                                       \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static void gsetiv(gcipher *c, const void *iv)                         \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_cfbsetiv(&g->k, iv);                                           \
+}                                                                      \
+                                                                       \
+static void gbdry(gcipher *c)                                          \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_cfbbdry(&g->k);                                                        \
+}                                                                      \
+                                                                       \
+static const gcipher_ops gops = {                                      \
+  &pre##_cfb,                                                          \
+  gencrypt, gdecrypt, gdestroy, gsetiv, gbdry                          \
+};                                                                     \
+                                                                       \
+const gccipher pre##_cfb = {                                           \
+  #pre "-cfb", pre##_keysz, PRE##_BLKSZ,                               \
+  ginit                                                                        \
+};                                                                     \
+                                                                       \
+CFB_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @CFB_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use:                Standard test rig for CFB functions.
+ */
+
+#define CFB_TEST(PRE, pre)                                             \
+                                                                       \
+/* --- Initial plaintext for the test --- */                           \
+                                                                       \
+static const octet text[] = TEXT;                                      \
+                                                                       \
+/* --- Key and IV to use --- */                                                \
+                                                                       \
+static const octet key[] = KEY;                                                \
+static const octet iv[] = IV;                                          \
+                                                                       \
+/* --- Buffers for encryption and decryption output --- */             \
+                                                                       \
+static octet ct[sizeof(text)];                                         \
+static octet pt[sizeof(text)];                                         \
+                                                                       \
+static void hexdump(const octet *p, size_t sz)                         \
+{                                                                      \
+  const octet *q = p + sz;                                             \
+  for (sz = 0; p < q; p++, sz++) {                                     \
+    printf("%02x", *p);                                                        \
+    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
+      putchar(':');                                                    \
+  }                                                                    \
+}                                                                      \
+                                                                       \
+int main(void)                                                         \
+{                                                                      \
+  size_t sz = 0, rest;                                                 \
+  pre##_cfbctx ctx;                                                    \
+  int status = 0;                                                      \
+  int done = 0;                                                                \
+  pre##_ctx k;                                                         \
+                                                                       \
+  size_t keysz = PRE##_KEYSZ ?                                         \
+    PRE##_KEYSZ : strlen((const char *)key);                           \
+                                                                       \
+  fputs(#pre "-cfb: ", stdout);                                                \
+                                                                       \
+  pre##_init(&k, key, keysz);                                          \
+  pre##_cfbsetkey(&ctx, &k);                                           \
+                                                                       \
+  while (sz <= sizeof(text)) {                                         \
+    rest = sizeof(text) - sz;                                          \
+    memcpy(ct, text, sizeof(text));                                    \
+    pre##_cfbsetiv(&ctx, iv);                                          \
+    pre##_cfbencrypt(&ctx, ct, ct, sz);                                        \
+    pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest);                    \
+    memcpy(pt, ct, sizeof(text));                                      \
+    pre##_cfbsetiv(&ctx, iv);                                          \
+    pre##_cfbdecrypt(&ctx, pt, pt, rest);                              \
+    pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz);                  \
+    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
+      done++;                                                          \
+      if (sizeof(text) < 40 || done % 8 == 0)                          \
+       fputc('.', stdout);                                             \
+      if (done % 480 == 0)                                             \
+       fputs("\n\t", stdout);                                          \
+      fflush(stdout);                                                  \
+    } else {                                                           \
+      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
+      status = 1;                                                      \
+      printf("\tplaintext      = "); hexdump(text, sz);                        \
+       printf(", "); hexdump(text + sz, rest);                         \
+       fputc('\n', stdout);                                            \
+      printf("\tciphertext     = "); hexdump(ct, sz);                  \
+       printf(", "); hexdump(ct + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      printf("\trecovered text = "); hexdump(pt, sz);                  \
+       printf(", "); hexdump(pt + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      fputc('\n', stdout);                                             \
+    }                                                                  \
+    if (sz < 63)                                                       \
+      sz++;                                                            \
+    else                                                               \
+      sz += 9;                                                         \
+  }                                                                    \
+                                                                       \
+  fputs(status ? " failed\n" : " ok\n", stdout);                       \
+  return (status);                                                     \
+}
+
+#else
+#  define CFB_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/cfb.h b/symm/cfb.h
new file mode 100644 (file)
index 0000000..c357115
--- /dev/null
@@ -0,0 +1,184 @@
+/* -*-c-*-
+ *
+ * Ciphertext feedback for block ciphers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_CFB_H
+#define CATACOMB_CFB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- @CFB_DECL@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates declarations for CFB mode.
+ */
+
+#define CFB_DECL(PRE, pre)                                             \
+                                                                       \
+/* --- Ciphertext feedback context --- */                              \
+                                                                       \
+typedef struct pre##_cfbctx {                                          \
+  pre##_ctx ctx;                       /* Underlying cipher context */ \
+  unsigned off;                                /* Offset into @iv@ buffer */   \
+  octet iv[PRE##_BLKSZ];               /* Previous ciphertext or IV */ \
+} pre##_cfbctx;                                                                \
+                                                                       \
+/* --- @pre_cfbgetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @const pre_cfbctx *ctx@ = pointer to CFB context block  \
+ *             @void *iv@ = pointer to output data block               \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reads the currently set IV.  Reading and setting an IV  \
+ *             is not transparent to the cipher.  It will add a `step' \
+ *             which must be matched by a similar operation during     \
+ *             decryption.                                             \
+ */                                                                    \
+                                                                       \
+extern void pre##_cfbgetiv(const pre##_cfbctx */*ctx*/,                        \
+                          void */*iv*/);                               \
+                                                                       \
+/* --- @pre_cfbsetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *             @cnost void *iv@ = pointer to IV to set                 \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the IV to use for subsequent encryption.           \
+ */                                                                    \
+                                                                       \
+extern void pre##_cfbsetiv(pre##_cfbctx */*ctx*/,                      \
+                          const void */*iv*/);                         \
+                                                                       \
+/* --- @pre_cfbbdry@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Inserts a boundary during encryption.  Successful       \
+ *             decryption must place a similar boundary.               \
+ */                                                                    \
+                                                                       \
+extern void pre##_cfbbdry(pre##_cfbctx */*ctx*/);                      \
+                                                                       \
+/* --- @pre_cfbsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the CFB context to use a different cipher key.     \
+ */                                                                    \
+                                                                       \
+extern void pre##_cfbsetkey(pre##_cfbctx */*ctx*/,                     \
+                           const pre##_ctx */*k*/);                    \
+                                                                       \
+/* --- @pre_cfbinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to cipher context           \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a CFB context ready for use.  You should    \
+ *             ensure that the IV chosen is unique: reusing an IV will \
+ *             compromise the security of at least the first block     \
+ *             encrypted.  This is equivalent to calls to @pre_init@,  \
+ *             @pre_cfbsetkey@ and @pre_cfbsetiv@.                     \
+ */                                                                    \
+                                                                       \
+extern void pre##_cfbinit(pre##_cfbctx */*ctx*/,                       \
+                         const void */*key*/, size_t /*sz*/,           \
+                         const void */*iv*/);                          \
+                                                                       \
+/* --- @pre_cfbencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts a block with a block cipher in CFB mode.  The  \
+ *             input block may be arbitrary in size.  CFB mode is not  \
+ *             sensitive to block boundaries.                          \
+ */                                                                    \
+                                                                       \
+extern void pre##_cfbencrypt(pre##_cfbctx */*ctx*/,                    \
+                            const void */*src*/, void */*dest*/,       \
+                            size_t /*sz*/);                            \
+                                                                       \
+/* --- @pre_cfbencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_cfbctx *ctx@ = pointer to CFB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Decrypts a block with a block cipher in CFB mode.  The  \
+ *             input block may be arbitrary in size.  CFB mode is not  \
+ *             sensitive to block boundaries.                          \
+ */                                                                    \
+                                                                       \
+extern void pre##_cfbdecrypt(pre##_cfbctx */*ctx*/,                    \
+                            const void */*src*/, void */*dest*/,       \
+                            size_t /*sz*/);                            \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+extern const gccipher pre##_cfb;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/counter-def.h b/symm/counter-def.h
new file mode 100644 (file)
index 0000000..2f35323
--- /dev/null
@@ -0,0 +1,533 @@
+/* -*-c-*-
+ *
+ * Block cipher counter mode (or long cycle mode)
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_COUNTER_DEF_H
+#define CATACOMB_COUNTER_DEF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+#  include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @COUNTER_DEF@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates definitions for counter mode.
+ */
+
+#define COUNTER_DEF(PRE, pre)                                          \
+                                                                       \
+/* --- @pre_countergetiv@ --- *                                                \
+ *                                                                     \
+ * Arguments:  @const pre_counterctx *ctx@ = pointer to counter        \
+ *                     context                                         \
+ *             @void *iv@ = pointer to output data block               \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reads the currently set IV.  Reading and setting an IV  \
+ *             is not transparent to the cipher.  It will add a `step' \
+ *             which must be matched by a similar operation during     \
+ *             decryption.                                             \
+ */                                                                    \
+                                                                       \
+void pre##_countergetiv(const pre##_counterctx *ctx, void *iv)         \
+{                                                                      \
+  BLKC_STORE(PRE, iv, ctx->n);                                         \
+}                                                                      \
+                                                                       \
+/* --- @pre_countersetiv@ --- *                                                \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
+ *             @cnost void *iv@ = pointer to IV to set                 \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the IV to use for subsequent encryption.           \
+ */                                                                    \
+                                                                       \
+void pre##_countersetiv(pre##_counterctx *ctx, const void *iv)         \
+{                                                                      \
+  BLKC_LOAD(PRE, ctx->n, iv);                                          \
+  ctx->off = PRE##_BLKSZ;                                              \
+}                                                                      \
+                                                                       \
+/* --- @pre_counterbdry@ --- *                                         \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Inserts a boundary during encryption.  Successful       \
+ *             decryption must place a similar boundary.               \
+ */                                                                    \
+                                                                       \
+void pre##_counterbdry(pre##_counterctx *ctx)                          \
+{                                                                      \
+  BLKC_STEP(PRE, ctx->n);                                              \
+  ctx->off = PRE##_BLKSZ;                                              \
+}                                                                      \
+                                                                       \
+/* --- @pre_countersetkey@ --- *                                       \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the counter context to use a different cipher key. \
+ */                                                                    \
+                                                                       \
+void pre##_countersetkey(pre##_counterctx *ctx, const pre##_ctx *k)    \
+{                                                                      \
+  ctx->ctx = *k;                                                       \
+}                                                                      \
+                                                                       \
+/* --- @pre_counterinit@ --- *                                         \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to cipher context       \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a counter context ready for use.  You       \
+ *             should ensure that the IV chosen is unique: reusing an  \
+ *             IV will compromise the security of the entire           \
+ *             plaintext.  This is equivalent to calls to @pre_init@,  \
+ *             @pre_countersetkey@ and @pre_countersetiv@.             \
+ */                                                                    \
+                                                                       \
+void pre##_counterinit(pre##_counterctx *ctx,                          \
+                      const void *key, size_t sz,                      \
+                      const void *iv)                                  \
+{                                                                      \
+  static const octet zero[PRE##_BLKSZ] = { 0 };                                \
+  pre##_init(&ctx->ctx, key, sz);                                      \
+  pre##_countersetiv(ctx, iv ? iv : zero);                             \
+}                                                                      \
+                                                                       \
+/* --- @pre_counterencrypt@ --- *                                      \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts or decrypts a block with a block cipher in     \
+ *             counter mode: encryption and decryption are the same in \
+ *             counter.  The destination may be null to just churn the \
+ *             feedback round for a bit.  The source may be null to    \
+ *             use the cipher as a random data generator.              \
+ */                                                                    \
+                                                                       \
+void pre##_counterencrypt(pre##_counterctx *ctx,                       \
+                         const void *src, void *dest,                  \
+                         size_t sz)                                    \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+  unsigned off = ctx->off;                                             \
+                                                                       \
+  /* --- Empty blocks are trivial --- */                               \
+                                                                       \
+  if (!sz)                                                             \
+    return;                                                            \
+                                                                       \
+  /* --- If I can deal with the block from my buffer, do that --- */   \
+                                                                       \
+  if (sz < PRE##_BLKSZ - off)                                          \
+    goto small;                                                                \
+                                                                       \
+  /* --- Finish off what's left in my buffer --- */                    \
+                                                                       \
+  if (!d)                                                              \
+    sz -= PRE##_BLKSZ - off;                                           \
+  else {                                                               \
+    while (off < PRE##_BLKSZ) {                                                \
+      register octet x = s ? *s++ : 0;                                 \
+      *d++ = ctx->buf[off++] ^ x;                                      \
+      sz--;                                                            \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  /* --- Main encryption loop --- */                                   \
+                                                                       \
+  {                                                                    \
+    uint32 n[PRE##_BLKSZ / 4];                                         \
+                                                                       \
+    for (;;) {                                                         \
+      pre##_eblk(&ctx->ctx, ctx->n, n);                                        \
+      BLKC_STEP(PRE, ctx->n);                                          \
+      if (sz < PRE##_BLKSZ)                                            \
+       break;                                                          \
+      if (d) {                                                         \
+       if (!s)                                                         \
+         BLKC_STORE(PRE, d, n);                                        \
+       else {                                                          \
+         uint32 x[PRE##_BLKSZ / 4];                                    \
+         BLKC_LOAD(PRE, x, s);                                         \
+         BLKC_XSTORE(PRE, d, n, x);                                    \
+         s += PRE##_BLKSZ;                                             \
+       }                                                               \
+       d += PRE##_BLKSZ;                                               \
+      }                                                                        \
+      sz -= PRE##_BLKSZ;                                               \
+    }                                                                  \
+                                                                       \
+    BLKC_STORE(PRE, ctx->buf, n);                                      \
+    off = 0;                                                           \
+  }                                                                    \
+                                                                       \
+  /* --- Tidying up the tail end --- */                                        \
+                                                                       \
+  if (sz) {                                                            \
+  small:                                                               \
+    if (!d)                                                            \
+      off += sz;                                                       \
+    else do {                                                          \
+      register octet x = s ? *s++ : 0;                                 \
+      *d++ = ctx->buf[off++] ^ x;                                      \
+      sz--;                                                            \
+    } while (sz);                                                      \
+  }                                                                    \
+                                                                       \
+  /* --- Done --- */                                                   \
+                                                                       \
+  ctx->off = off;                                                      \
+  return;                                                              \
+}                                                                      \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+static const gcipher_ops gops;                                         \
+                                                                       \
+typedef struct gctx {                                                  \
+  gcipher c;                                                           \
+  pre##_counterctx k;                                                  \
+} gctx;                                                                        \
+                                                                       \
+static gcipher *ginit(const void *k, size_t sz)                                \
+{                                                                      \
+  gctx *g = S_CREATE(gctx);                                            \
+  g->c.ops = &gops;                                                    \
+  pre##_counterinit(&g->k, k, sz, 0);                                  \
+  return (&g->c);                                                      \
+}                                                                      \
+                                                                       \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_counterencrypt(&g->k, s, t, sz);                               \
+}                                                                      \
+                                                                       \
+static void gdestroy(gcipher *c)                                       \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static void gsetiv(gcipher *c, const void *iv)                         \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_countersetiv(&g->k, iv);                                       \
+}                                                                      \
+                                                                       \
+static void gbdry(gcipher *c)                                          \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_counterbdry(&g->k);                                            \
+}                                                                      \
+                                                                       \
+static const gcipher_ops gops = {                                      \
+  &pre##_counter,                                                      \
+  gencrypt, gencrypt, gdestroy, gsetiv, gbdry                          \
+};                                                                     \
+                                                                       \
+const gccipher pre##_counter = {                                       \
+  #pre "-counter", pre##_keysz, PRE##_BLKSZ,                           \
+  ginit                                                                        \
+};                                                                     \
+                                                                       \
+/* --- Generic random number generator interface --- */                        \
+                                                                       \
+typedef struct grctx {                                                 \
+  grand r;                                                             \
+  pre##_counterctx k;                                                  \
+} grctx;                                                               \
+                                                                       \
+static void grdestroy(grand *r)                                                \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static int grmisc(grand *r, unsigned op, ...)                          \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  va_list ap;                                                          \
+  int rc = 0;                                                          \
+  octet buf[PRE##_BLKSZ];                                              \
+  va_start(ap, op);                                                    \
+                                                                       \
+  switch (op) {                                                                \
+    case GRAND_CHECK:                                                  \
+      switch (va_arg(ap, unsigned)) {                                  \
+       case GRAND_CHECK:                                               \
+       case GRAND_SEEDINT:                                             \
+       case GRAND_SEEDUINT32:                                          \
+       case GRAND_SEEDBLOCK:                                           \
+       case GRAND_SEEDRAND:                                            \
+         rc = 1;                                                       \
+         break;                                                        \
+       default:                                                        \
+         rc = 0;                                                       \
+         break;                                                        \
+      }                                                                        \
+      break;                                                           \
+    case GRAND_SEEDINT:                                                        \
+      BLKC_SET(PRE, g->k.n, va_arg(ap, unsigned));                     \
+      g->k.off = PRE##_BLKSZ;                                          \
+      break;                                                           \
+    case GRAND_SEEDUINT32:                                             \
+      BLKC_SET(PRE, g->k.n, va_arg(ap, uint32));                       \
+      g->k.off = PRE##_BLKSZ;                                          \
+      break;                                                           \
+    case GRAND_SEEDBLOCK: {                                            \
+      const void *p = va_arg(ap, const void *);                                \
+      size_t sz = va_arg(ap, size_t);                                  \
+      if (sz < sizeof(buf)) {                                          \
+       memset(buf, 0, sizeof(buf));                                    \
+       memcpy(buf, p, sz);                                             \
+       p = buf;                                                        \
+      }                                                                        \
+      pre##_countersetiv(&g->k, p);                                    \
+    } break;                                                           \
+    case GRAND_SEEDRAND: {                                             \
+      grand *rr = va_arg(ap, grand *);                                 \
+      rr->ops->fill(rr, buf, sizeof(buf));                             \
+      pre##_countersetiv(&g->k, buf);                                  \
+    } break;                                                           \
+    default:                                                           \
+      GRAND_BADOP;                                                     \
+      break;                                                           \
+  }                                                                    \
+                                                                       \
+  va_end(ap);                                                          \
+  return (rc);                                                         \
+}                                                                      \
+                                                                       \
+static octet grbyte(grand *r)                                          \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  octet o;                                                             \
+  pre##_counterencrypt(&g->k, 0, &o, 1);                               \
+  return (o);                                                          \
+}                                                                      \
+                                                                       \
+static uint32 grword(grand *r)                                         \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  octet b[4];                                                          \
+  pre##_counterencrypt(&g->k, 0, b, sizeof(b));                                \
+  return (LOAD32(b));                                                  \
+}                                                                      \
+                                                                       \
+static void grfill(grand *r, void *p, size_t sz)                       \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  pre##_counterencrypt(&g->k, 0, p, sz);                               \
+}                                                                      \
+                                                                       \
+static const grand_ops grops = {                                       \
+  #pre "-counter",                                                     \
+  GRAND_CRYPTO, 0,                                                     \
+  grmisc, grdestroy,                                                   \
+  grword, grbyte, grword, grand_range, grfill                          \
+};                                                                     \
+                                                                       \
+/* --- @pre_counterrand@ --- *                                         \
+ *                                                                     \
+ * Arguments:  @const void *k@ = pointer to key material               \
+ *             @size_t sz@ = size of key material                      \
+ *                                                                     \
+ * Returns:    Pointer to generic random number generator interface.   \
+ *                                                                     \
+ * Use:                Creates a random number interface wrapper around an     \
+ *             counter-mode block cipher.                              \
+ */                                                                    \
+                                                                       \
+grand *pre##_counterrand(const void *k, size_t sz)                     \
+{                                                                      \
+  grctx *g = S_CREATE(grctx);                                          \
+  g->r.ops = &grops;                                                   \
+  pre##_counterinit(&g->k, k, sz, 0);                                  \
+  return (&g->r);                                                      \
+}                                                                      \
+                                                                       \
+COUNTER_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @COUNTER_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use:                Standard test rig for counter functions.
+ */
+
+#define COUNTER_TEST(PRE, pre)                                         \
+                                                                       \
+/* --- Initial plaintext for the test --- */                           \
+                                                                       \
+static const octet text[] = TEXT;                                      \
+                                                                       \
+/* --- Key and IV to use --- */                                                \
+                                                                       \
+static const octet key[] = KEY;                                                \
+static const octet iv[] = IV;                                          \
+                                                                       \
+/* --- Buffers for encryption and decryption output --- */             \
+                                                                       \
+static octet ct[sizeof(text)];                                         \
+static octet pt[sizeof(text)];                                         \
+                                                                       \
+static void hexdump(const octet *p, size_t sz)                         \
+{                                                                      \
+  const octet *q = p + sz;                                             \
+  for (sz = 0; p < q; p++, sz++) {                                     \
+    printf("%02x", *p);                                                        \
+    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
+      putchar(':');                                                    \
+  }                                                                    \
+}                                                                      \
+                                                                       \
+int main(void)                                                         \
+{                                                                      \
+  size_t sz = 0, rest;                                                 \
+  pre##_counterctx ctx;                                                        \
+  int status = 0;                                                      \
+  int done = 0;                                                                \
+  pre##_ctx k;                                                         \
+                                                                       \
+  size_t keysz = PRE##_KEYSZ ?                                         \
+    PRE##_KEYSZ : strlen((const char *)key);                           \
+                                                                       \
+  fputs(#pre "-counter: ", stdout);                                    \
+                                                                       \
+  pre##_init(&k, key, keysz);                                          \
+  pre##_countersetkey(&ctx, &k);                                       \
+                                                                       \
+  while (sz <= sizeof(text)) {                                         \
+    rest = sizeof(text) - sz;                                          \
+    memcpy(ct, text, sizeof(text));                                    \
+    pre##_countersetiv(&ctx, iv);                                      \
+    pre##_counterencrypt(&ctx, ct, ct, sz);                            \
+    pre##_counterencrypt(&ctx, ct + sz, ct + sz, rest);                        \
+    memcpy(pt, ct, sizeof(text));                                      \
+    pre##_countersetiv(&ctx, iv);                                      \
+    pre##_counterencrypt(&ctx, pt, pt, rest);                          \
+    pre##_counterencrypt(&ctx, pt + rest, pt + rest, sz);              \
+    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
+      done++;                                                          \
+      if (sizeof(text) < 40 || done % 8 == 0)                          \
+       fputc('.', stdout);                                             \
+      if (done % 480 == 0)                                             \
+       fputs("\n\t", stdout);                                          \
+      fflush(stdout);                                                  \
+    } else {                                                           \
+      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
+      status = 1;                                                      \
+      printf("\tplaintext      = "); hexdump(text, sz);                        \
+       printf(", "); hexdump(text + sz, rest);                         \
+       fputc('\n', stdout);                                            \
+      printf("\tciphertext     = "); hexdump(ct, sz);                  \
+       printf(", "); hexdump(ct + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      printf("\trecovered text = "); hexdump(pt, sz);                  \
+       printf(", "); hexdump(pt + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      fputc('\n', stdout);                                             \
+    }                                                                  \
+    if (sz < 63)                                                       \
+      sz++;                                                            \
+    else                                                               \
+      sz += 9;                                                         \
+  }                                                                    \
+                                                                       \
+  fputs(status ? " failed\n" : " ok\n", stdout);                       \
+  return (status);                                                     \
+}
+
+#else
+#  define COUNTER_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/counter.h b/symm/counter.h
new file mode 100644 (file)
index 0000000..7e07b3c
--- /dev/null
@@ -0,0 +1,187 @@
+/* -*-c-*-
+ *
+ * Block cipher counter mode (or long cycle mode)
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_COUNTER_H
+#define CATACOMB_COUNTER_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @COUNTER_DECL@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use:                Makes declarations for counter mode.
+ */
+
+#define COUNTER_DECL(PRE, pre)                                         \
+                                                                       \
+/* --- Counter mode context --- */                                     \
+                                                                       \
+typedef struct pre##_counterctx {                                      \
+  pre##_ctx ctx;                       /* Underlying cipher context */ \
+  unsigned off;                                /* Current offset in buffer */  \
+  octet buf[PRE##_BLKSZ];              /* Output buffer */             \
+  uint32 n[PRE##_BLKSZ / 4];           /* Counter */                   \
+} pre##_counterctx;                                                    \
+                                                                       \
+/* --- @pre_countergetiv@ --- *                                                \
+ *                                                                     \
+ * Arguments:  @const pre_counterctx *ctx@ = pointer to counter        \
+ *                     context                                         \
+ *             @void *iv@ = pointer to output data block               \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reads the currently set IV.  Reading and setting an IV  \
+ *             is not transparent to the cipher.  It will add a `step' \
+ *             which must be matched by a similar operation during     \
+ *             decryption.                                             \
+ */                                                                    \
+                                                                       \
+extern void pre##_countergetiv(const pre##_counterctx */*ctx*/,                \
+                              void */*iv*/);                           \
+                                                                       \
+/* --- @pre_countersetiv@ --- *                                                \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
+ *             @cnost void *iv@ = pointer to IV to set                 \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the IV to use for subsequent encryption.           \
+ */                                                                    \
+                                                                       \
+extern void pre##_countersetiv(pre##_counterctx */*ctx*/,              \
+                              const void */*iv*/);                     \
+                                                                       \
+/* --- @pre_counterbdry@ --- *                                         \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Inserts a boundary during encryption.  Successful       \
+ *             decryption must place a similar boundary.               \
+ */                                                                    \
+                                                                       \
+extern void pre##_counterbdry(pre##_counterctx */*ctx*/);              \
+                                                                       \
+/* --- @pre_countersetkey@ --- *                                       \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the counter context to use a different cipher key. \
+ */                                                                    \
+                                                                       \
+extern void pre##_countersetkey(pre##_counterctx */*ctx*/,             \
+                               const pre##_ctx */*k*/);                \
+                                                                       \
+/* --- @pre_counterinit@ --- *                                         \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to cipher context       \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a counter context ready for use.  You       \
+ *             should ensure that the IV chosen is unique: reusing an  \
+ *             IV will compromise the security of the entire           \
+ *             plaintext.  This is equivalent to calls to @pre_init@,  \
+ *             @pre_countersetkey@ and @pre_countersetiv@.             \
+ */                                                                    \
+                                                                       \
+extern void pre##_counterinit(pre##_counterctx */*ctx*/,               \
+                             const void */*key*/, size_t /*sz*/,       \
+                             const void */*iv*/);                      \
+                                                                       \
+/* --- @pre_counterencrypt@ --- *                                      \
+ *                                                                     \
+ * Arguments:  @pre_counterctx *ctx@ = pointer to counter context      \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts or decrypts a block with a block cipher in     \
+ *             counter mode: encryption and decryption are the same in \
+ *             counter.  The destination may be null to just churn the \
+ *             feedback round for a bit.  The source may be null to    \
+ *             use the cipher as a random data generator.              \
+ */                                                                    \
+                                                                       \
+extern void pre##_counterencrypt(pre##_counterctx */*ctx*/,            \
+                                const void */*src*/, void */*dest*/,   \
+                                size_t /*sz*/);                        \
+                                                                       \
+/* --- @pre_counterrand@ --- *                                         \
+ *                                                                     \
+ * Arguments:  @const void *k@ = pointer to key material               \
+ *             @size_t sz@ = size of key material                      \
+ *                                                                     \
+ * Returns:    Pointer to generic random number generator interface.   \
+ *                                                                     \
+ * Use:                Creates a random number interface wrapper around an     \
+ *             counter-mode block cipher.                              \
+ */                                                                    \
+                                                                       \
+extern grand *pre##_counterrand(const void */*k*/, size_t /*sz*/);     \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+extern const gccipher pre##_counter;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/crc32.c b/symm/crc32.c
new file mode 100644 (file)
index 0000000..4b6f27b
--- /dev/null
@@ -0,0 +1,89 @@
+/* -*-c-*-
+ *
+ * Generic hash wrapper for CRC32
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/crc32.h>
+#include <mLib/sub.h>
+
+#include "arena.h"
+#include "crc32.h"
+#include "ghash.h"
+#include "paranoia.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+typedef struct gctx {
+  ghash h;
+  uint32 c;
+  octet buf[4];
+} gctx;
+
+static const ghash_ops gops;
+
+static ghash *ghinit(void)
+{
+  gctx *g = S_CREATE(gctx);
+  g->h.ops = &gops;
+  g->c = 0;
+  return (&g->h);
+}
+
+static void ghhash(ghash *h, const void *p, size_t sz)
+{
+  gctx *g = (gctx *)h;
+  CRC32(g->c, g->c, p, sz);
+}
+
+static octet *ghdone(ghash *h, void *buf)
+{
+  gctx *g = (gctx *)h;
+  if (!buf)
+    buf = g->buf;
+  STORE32(buf, g->c);
+  return (buf);
+}
+
+static void ghdestroy(ghash *h)
+{
+  gctx *g = (gctx *)h;
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static ghash *ghcopy(ghash *h)
+{
+  gctx *g = (gctx *)h;
+  gctx *gg = S_CREATE(gctx);
+  memcpy(gg, g, sizeof(gctx));
+  return (&gg->h);
+}
+
+static const ghash_ops gops = { &gcrc32, ghhash, ghdone, ghdestroy, ghcopy };
+const gchash gcrc32 = { "crc32", 4, ghinit };
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/crc32.h b/symm/crc32.h
new file mode 100644 (file)
index 0000000..a242273
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*-c-*-
+ *
+ * Generic hash wrapper for CRC32
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_CRC32_H
+#define CATACOMB_CRC32_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/crc32.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Generic interface -------------------------------------------------*/
+
+extern const gchash gcrc32;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/daftstory.h b/symm/daftstory.h
new file mode 100644 (file)
index 0000000..b4d6b58
--- /dev/null
@@ -0,0 +1,76 @@
+/* -*-c-*-
+ *
+ * Daft story for use in test encryptions
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_DAFTSTORY_H
+#define CATACOMB_DAFTSTORY_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- Don't ask --- */
+
+#ifdef SMALL_TEST
+#  define TEXT "A small piece of text for testing encryption."
+#else
+#  define STORY "\
+Once upon a time there were a beautiful princess, a slightly nutty wizard,\n\
+and a watermelon.  Now, the watermelon had decided that it probably wasn't\n\
+going to get very far with the princess unless it did something pretty\n\
+drastic.  So it asked the wizard to turn it into a handsome prince.\n\
+\n\
+At least, this is the way that the wizard viewed the situation.  He might\n\
+have just hallucinated it all; those mushrooms had looked ever so nice.\n\
+\n\
+Back to the point.  The watermelon had expressed its desire not to be a\n\
+watermelon any more.  And the wizard was probably tripping something quite\n\
+powerful.  He hunted around a bit for his staff, and mumbled something\n\
+that film directors would think of as sounding appropriately arcane and\n\
+mystical (but was, in fact, just the ingredients list for an ancient\n\
+remedy for athlete's foot) and *pop*.  Cooked watermelon.  Yuk.\n\
+\n\
+Later in the year, the princess tripped over the hem of her dress, fell\n\
+down a spiral staircase, and died.  The king ordered dressmakers to attach\n\
+safety warnings to long dresses.\n\
+\n\
+And the wizard?         Who cares?\n\
+"
+#  define TEXT STORY STORY
+#endif
+
+#define KEY "Penguins rule OK, rhubarb cauliflower"
+#define IV "EdgewareCatacomb, parsley, sage, rosemary and thyme"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/des-base.c b/symm/des-base.c
new file mode 100644 (file)
index 0000000..4d55881
--- /dev/null
@@ -0,0 +1,39 @@
+/* -*-c-*-
+ *
+ * Common features for DES implementation
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "des-base.h"
+#include "des-tab.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const uint32 des_sp[8][64] = DES_SP;
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/des-base.h b/symm/des-base.h
new file mode 100644 (file)
index 0000000..49bbed7
--- /dev/null
@@ -0,0 +1,156 @@
+/* -*-c-*-
+ *
+ * Common features for DES implementation
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_DES_BASE_H
+#define CATACOMB_DES_BASE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- External data -----------------------------------------------------*/
+
+extern const uint32 des_sp[8][64];
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @DES_ROUND@ --- *
+ *
+ * This is the basic DES round function.  The inputs are the two subkey
+ * halves, and the left and right block halves.  Note that the block halves
+ * are rotated left one place at this point.  This wraps what's meant to be
+ * the top bit around to the bottom, so I get a clear run at the S-boxes.
+ */
+
+#define DES_ROUND(ka, kb, x, y) do {                                   \
+  uint32 _t = (y) ^ (ka);                                              \
+  (x) ^= des_sp[7][(_t >>  0) & 0x3f] ^                                        \
+        des_sp[5][(_t >>  8) & 0x3f] ^                                 \
+        des_sp[3][(_t >> 16) & 0x3f] ^                                 \
+        des_sp[1][(_t >> 24) & 0x3f];                                  \
+  _t = ROR32((y), 4) ^ (kb);                                           \
+  (x) ^= des_sp[6][(_t >>  0) & 0x3f] ^                                        \
+        des_sp[4][(_t >>  8) & 0x3f] ^                                 \
+        des_sp[2][(_t >> 16) & 0x3f] ^                                 \
+        des_sp[0][(_t >> 24) & 0x3f];                                  \
+} while (0)
+
+/* --- @DES_IP@, @DES_IPINV@ --- *
+ *
+ * The cryptographically useless initial and final permutations.  The initial
+ * permutation also rotates the two block halves left by one place.  This is
+ * undone by the inverse permutation at the end.
+ */
+
+#define DES_IP(x, y) do {                                              \
+  uint32 _t;                                                           \
+  _t = (y ^ (x >> 4)) & 0x0f0f0f0f; y ^= _t; x ^= _t << 4;             \
+  _t = (x ^ (x >> 18)) & 0x00003333; x ^= _t; x ^= _t << 18;           \
+  _t = (y ^ (y >> 18)) & 0x00003333; y ^= _t; y ^= _t << 18;           \
+  _t = (x ^ (x >> 9)) & 0x00550055; x ^= _t; x ^= _t << 9;             \
+  _t = (y ^ (y >> 9)) & 0x00550055; y ^= _t; y ^= _t << 9;             \
+  _t = (x ^ (x >> 24)) & 0x000000ff; x ^= _t; x ^= _t << 24;           \
+  _t = (y ^ (y >> 24)) & 0x000000ff; y ^= _t; y ^= _t << 24;           \
+  _t = (y ^ (x >> 16)) & 0x0000ffff; y ^= _t; x ^= _t << 16;           \
+  x = ROL32(x, 1); y = ROL32(y, 1);                                    \
+} while (0)
+
+#define DES_IPINV(x, y) do {                                           \
+  uint32 _t;                                                           \
+  x = ROR32(x, 1); y = ROR32(y, 1);                                    \
+  _t = (y ^ (x >> 16)) & 0x0000ffff; y ^= _t; x ^= _t << 16;           \
+  _t = (x ^ (x >> 24)) & 0x000000ff; x ^= _t; x ^= _t << 24;           \
+  _t = (y ^ (y >> 24)) & 0x000000ff; y ^= _t; y ^= _t << 24;           \
+  _t = (y ^ (x >> 4)) & 0x0f0f0f0f; y ^= _t; x ^= _t << 4;             \
+  _t = (x ^ (x >> 18)) & 0x00003333; x ^= _t; x ^= _t << 18;           \
+  _t = (y ^ (y >> 18)) & 0x00003333; y ^= _t; y ^= _t << 18;           \
+  _t = (x ^ (x >> 9)) & 0x00550055; x ^= _t; x ^= _t << 9;             \
+  _t = (y ^ (y >> 9)) & 0x00550055; y ^= _t; y ^= _t << 9;             \
+} while (0)
+
+/* --- @DES_EBLK@, @DES_DBLK@ --- *
+ *
+ * Whole block encryption and decryption.
+ */
+
+#define DES_EBLK(k, a, b, c, d) do {                                   \
+  const uint32 *_k = (k);                                              \
+  uint32 _x = (a), _y = (b);                                           \
+  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _x, _y); _k += 2;                            \
+  DES_ROUND(_k[0], _k[1], _y, _x); _k += 2;                            \
+  (c) = _y;                                                            \
+  (d) = _x;                                                            \
+} while (0)
+
+#define DES_DBLK(k, a, b, c, d) do {                                   \
+  const uint32 *_k = (k) + 32;                                         \
+  uint32 _x = (a), _y = (b);                                           \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _x, _y);                            \
+  _k -= 2; DES_ROUND(_k[0], _k[1], _y, _x);                            \
+  (c) = _y;                                                            \
+  (d) = _x;                                                            \
+} while (0)
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/des-mktab.c b/symm/des-mktab.c
new file mode 100644 (file)
index 0000000..5dc8c4a
--- /dev/null
@@ -0,0 +1,285 @@
+/* -*-c-*-
+ *
+ * Build combined S-P tables for DES
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+/*----- Static variables --------------------------------------------------*/
+
+/* --- S boxes --- */
+
+static const char s[8][4][16] = {
+
+  /* --- S1 --- */
+
+  { { 14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7 },
+    {  0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8 },
+    {  4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0 },
+    { 15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13 } },
+
+  /* --- S2 --- */
+
+  { { 15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10 },
+    {  3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5 },
+    {  0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15 },
+    { 13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9 } },
+
+  /* --- S3 --- */
+
+  { { 10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8 },
+    { 13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1 },
+    { 13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7 },
+    {  1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12 } },
+
+  /* --- S4 --- */
+
+  { {  7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15 },
+    { 13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9 },
+    { 10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4 },
+    {  3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14 } },
+
+  /* --- S5 --- */
+
+  { {  2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9 },
+    { 14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6 },
+    {  4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14 },
+    { 11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3 } },
+
+  /* --- S6 --- */
+
+  { { 12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11 },
+    { 10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8 },
+    {  9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6 },
+    {  4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13 } },
+
+  /* --- S7 --- */
+
+  { {  4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1 },
+    { 13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6 },
+    {  1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2 },
+    {  6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12 } },
+
+  /* --- S8 --- */
+
+  { { 13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7 },
+    {  1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2 },
+    {  7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8 },
+    {  2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11 } }
+};
+
+/* --- P table --- */
+
+static char p[32] = {
+  16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
+   2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
+};
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @unique@ --- *
+ *
+ * Arguments:  @const char *t@ = pointer to table
+ *             @int base@ = base of the data
+ *             @int sz@ = number of elements
+ *             @const char *name@ = name of this table
+ *             @...@ = things to fill in
+ *
+ * Returns:    Zero if it failed, nonzero if it didn't.
+ *
+ * Use:                Validates a table.  All the elements must be in range and
+ *             unique.
+ */
+
+static int unique(const char *t, int base, int sz, const char *name, ...)
+{
+  char u[32];
+  char nbuf[128];
+  int i;
+  int ok = 1;
+
+  {
+    va_list ap;
+    va_start(ap, name);
+    vsprintf(nbuf, name, ap);
+    va_end(ap);
+  }
+
+  if (sz > sizeof(u)) {
+    fprintf(stderr, "internal error: table `%s' too large\n", nbuf);
+    exit(EXIT_FAILURE);
+  }
+  memset(u, 0, sizeof(u));
+  for (i = 0; i < sz; i++) {
+    int x = t[i] - base;
+    if (x >= sz) {
+      fprintf(stderr, "validation error: %i too big (index %i) in %s\n",
+             x + base, i, nbuf);
+      ok = 0;
+    } else if (u[x]) {
+      fprintf(stderr, "validation error: duplicate %i (index %i) in %s\n",
+             x + base, i, nbuf);
+      ok = 0;
+    }
+    u[x] = 1;
+  }
+  for (i = 0; i < sz; i++) {
+    if (!u[i]) {
+      fprintf(stderr, "validation error: missing %i in %s\n",
+             i + base, nbuf);
+      ok = 0;
+    }
+  }
+
+  return (ok);
+}
+
+/* --- @validate@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    Only if everything's OK.
+ *
+ * Use:                Validates the tables.  A bit.  Not much at all...
+ */
+
+static void validate(void)
+{
+  int i, j;
+  int ok = 1;
+
+  for (i = 0; i < 8; i++) for (j = 0; j < 4; j++)
+    if (!unique(s[i][j], 0, 16, "sbox %i, row %i", i, j)) ok = 0;
+  if (!unique(p, 1, 32, "p")) ok = 0;
+  if (!ok)
+    exit(EXIT_FAILURE);
+}
+
+/* --- @permute@ --- *
+ *
+ * Arguments:  @unsigned long x@ = value to permute
+ *
+ * Returns:    Permuted version of @x@.
+ *
+ * Use:                Permutes a number.  The result is the input value after
+ *             having been spewed through the @P@ permutation, and then
+ *             (and this is important) rotated left one place.
+ */
+
+static unsigned long permute(unsigned long x)
+{
+  unsigned long y = 0;
+  unsigned i;
+
+  for (i = 0; i < 32; i++) {
+    if (x & (1 << (32 - p[i])))
+      y |= (1 << (31 - i));
+  }
+  return (ROL32(y, 1));
+}
+
+/* --- @mangle@ --- *
+ *
+ * Arguments:  @const char s[4][16]@ = an s-box
+ *             @unsigned long ss[64]@ = output buffer
+ *             @int bitoff@ = bit offset to use
+ *
+ * Returns:    ---
+ *
+ * Use:                Mangles the s-box.  Specifically, the bizarre indexing is
+ *             transformed into something sensible, and the result is
+ *             permuted according to the @p@ table.
+ */
+
+static void mangle(const char s[4][16], unsigned long *ss, int bitoff)
+{
+  unsigned i;
+  for (i = 0; i < 64; i++) {
+    unsigned row = ((i & 0x20) >> 4) | (i & 0x01);
+    unsigned col = (i & 0x1e) >> 1;
+    ss[i] = permute(s[row][col] << bitoff);
+  }
+}
+
+/* --- @main@ --- */
+
+int main(void)
+{
+  int i, j;
+  unsigned long ss[64];
+  const char *sep;
+
+  validate();
+
+  fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * DES tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_DES_TAB_H\n\
+#define CATACOMB_DES_TAB_H\n\
+\n\
+#define DES_SP {                                                       \\\n\
+", stdout);
+  for (i = 0; i < 8; i++) {
+    mangle(s[i], ss, 28 - 4 * i);
+    printf("\
+                                                                       \\\n\
+  /* --- SP[%i] --- */                                                 \\\n\
+                                                                       \\\n\
+", i);
+    sep = "  { ";
+    for (j = 0; j < 64; j++) {
+      printf("%s0x%08lx", sep, ss[j]);
+      if (j % 4 == 3)
+       sep = ",                        \\\n    ";
+      else
+       sep = ", ";
+    }
+    printf(" }%s                       \\\n", i == 7 ? "" : ",");
+  }
+  fputs("\
+}\n\
+\n\
+#endif\n\
+", stdout);
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/des.c b/symm/des.c
new file mode 100644 (file)
index 0000000..06400a1
--- /dev/null
@@ -0,0 +1,279 @@
+/* -*-c-*-
+ *
+ * The Data Encryption Standard
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "des-base.h"
+#include "des.h"
+#include "gcipher.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet des_keysz[] = { KSZ_SET, 7, 8, 0 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @permute@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to permutation table
+ *             @uint32 a, b@ = source value to permute
+ *             @uint32 *d@ = destination for value
+ *
+ * Returns:    ---
+ *
+ * Use:                Performs a 64-bit permutation.  The table is given in the
+ *             normal (but bizarre) DES bit numbering system.  That's not to
+ *             say that the tables in this source file are like the normal
+ *             DES tables, because they're not.
+ */
+
+static void permute(const char *p, uint32 a, uint32 b, uint32 *d)
+{
+  uint32 x = 0, y = 0;
+  int i;
+
+  for (i = 0; i < 32; i++) {
+    int q = p[i];
+    uint32 t;
+    if (!q)
+      continue;
+    else if (q <= 32)
+      t = a;
+    else {
+      t = b;
+      q -= 32;
+    }
+    if (t & (1 << (32 - q)))
+      x |= (1 << (31 - i));
+  }
+
+  p += 32;
+
+  for (i = 0; i < 32; i++) {
+    int q = p[i];
+    uint32 t;
+    if (!q)
+      continue;
+    else if (q <= 32)
+      t = a;
+    else {
+      t = b;
+      q -= 32;
+    }
+    if (t & (1 << (32 - q)))
+      y |= (1 << (31 - i));
+  }
+
+  d[0] = x;
+  d[1] = y;
+}
+
+/* --- @des_expand@ --- *
+ *
+ * Arguments:  @const octet *k@ = pointer to key material
+ *             @size_t n@ = number of octets of key material (7 or 8)
+ *             @uint32 *xx, *yy@ = where to put the results
+ *
+ * Returns:    ---
+ *
+ * Use:                Extracts 64 bits of key material from the given buffer,
+ *             possibly expanding it from 56 to 64 bits on the way.
+ *             Parity is set correctly if the key is expanded.
+ */
+
+void des_expand(const octet *k, size_t n, uint32 *xx, uint32 *yy)
+{
+  uint32 x, y, z;
+
+  if (n == 8) {
+    x = LOAD32(k + 0);
+    y = LOAD32(k + 4);
+  } else {
+    x = LOAD32(k + 0);
+    x = (x & 0xfe000000) | ((x & 0x01fffff0) >> 1);
+    x = (x & 0xfffe0000) | ((x & 0x0001fff8) >> 1);
+    x = (x & 0xfffffe00) | ((x & 0x000001fc) >> 1);
+    z = x; z ^= z >> 4; z ^= z >> 2; z ^= z >> 1;
+    x |= (z & 0x01010101) ^ 0x01010101;
+    y = LOAD32(k + 3) << 1; /* Note: misaligned */
+    y = (y & 0x000000fe) | ((y & 0x1fffff00) << 1);
+    y = (y & 0x0000fefe) | ((y & 0x3fff0000) << 1);
+    y = (y & 0x00fefefe) | ((y & 0x7f000000) << 1);
+    z = y; z ^= z >> 4; z ^= z >> 2; z ^= z >> 1;
+    y |= (z & 0x01010101) ^ 0x01010101;
+  }
+  *xx = x; *yy = y;
+}
+
+/* --- @des_init@ --- *
+ *
+ * Arguments:  @des_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DES key buffer.  The key buffer may be either 7
+ *             or 8 bytes long.  If it's 8 bytes, the key is assumed to be
+ *             padded with parity bits in the low order bit of each octet.
+ *             These are stripped out without checking prior to the actual
+ *             key scheduling.
+ */
+
+void des_init(des_ctx *k, const void *buf, size_t sz)
+{
+  uint32 x, y;
+  uint32 *kp = k->k;
+  uint32 ka[2];
+  int i;
+
+  /* --- @pc1@ --- *
+   *
+   * This cryptographically useless permutation is used to mangle the key
+   * before it's subjected to the key schedule proper.  I've not actually
+   * messed it about much except for inserting padding at the beginning of
+   * the two halves of the key.
+   */
+
+  static const char pc1[] = {
+     0,         0,  0,  0,
+    57, 49, 41, 33, 25, 17,  9,
+     1, 58, 50, 42, 34, 26, 18,
+    10,         2, 59, 51, 43, 35, 27,
+    19, 11,  3, 60, 52, 44, 36,
+     0,         0,  0,  0,
+    63, 55, 47, 39, 31, 23, 15,
+     7, 62, 54, 46, 38, 30, 22,
+    14,         6, 61, 53, 45, 37, 29,
+    21, 13,  5, 28, 20, 12,  4
+  };
+
+  /* --- @pc2@ --- *
+   *
+   * This irritating but necessary permutation mangles the key between the
+   * simple rotation-based schedule and the actual XOR with which it modifies
+   * the behaviour of the cipher.
+   *
+   * This version of the table doesn't look much like the original.  This is
+   * because some parts of the world have been permuted in order to make
+   * things simpler for the round function.  In particular, everything is
+   * rotated left one place to avoid problems with the wraparound of the
+   * expansion permutation, and the key is split between odd and even S-boxes
+   * rather than high and low ones.  That's without the complication of the
+   * padding bits in the representation of the 56-bit proto-key.
+   */
+
+  static const char pc2[] = {
+     0,         0,  3 + 4, 28 + 4, 15 + 4,  6 + 4, 21 + 4, 10 + 4, /* S-box 2 */
+     0,         0, 16 + 4,  7 + 4, 27 + 4, 20 + 4, 13 + 4,  2 + 4, /* S-box 4 */
+     0,         0, 30 + 8, 40 + 8, 51 + 8, 45 + 8, 33 + 8, 48 + 8, /* S-box 6 */
+     0,         0, 46 + 8, 42 + 8, 50 + 8, 36 + 8, 29 + 8, 32 + 8, /* S-box 8 */
+     0,         0, 14 + 4, 17 + 4, 11 + 4, 24 + 4,  1 + 4,  5 + 4, /* S-box 1 */
+     0,         0, 23 + 4, 19 + 4, 12 + 4,  4 + 4, 26 + 4,  8 + 4, /* S-box 3 */
+     0,         0, 41 + 8, 52 + 8, 31 + 8, 37 + 8, 47 + 8, 55 + 8, /* S-box 5 */
+     0,         0, 44 + 8, 49 + 8, 39 + 8, 56 + 8, 34 + 8, 53 + 8  /* S-box 7 */
+  };
+
+  /* --- @v@ --- *
+   *
+   * Contains the rotation amounts for the key halves.
+   */
+
+  static const char v[] = {
+    1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+  };
+
+  /* --- Extract the key into my registers --- *
+   *
+   * The 7 byte case is rather horrible.  It expands the key to the 8 byte
+   * case before going any further.  It could probably do with its own @pc1@
+   * table.
+   */
+
+  KSZ_ASSERT(des, sz);
+  des_expand(buf, sz, &x, &y);
+
+  /* --- Permute using the pointless PC1 --- */
+
+  permute(pc1, x, y, ka);
+  x = ka[0]; y = ka[1];
+
+  /* --- Now for the key schedule proper --- */
+
+  for (i = 0; i < 16; i++) {
+    if (v[i] == 1) {
+      x = ((x << 1) | (x >> 27)) & 0x0fffffff;
+      y = ((y << 1) | (y >> 27)) & 0x0fffffff;
+    } else {
+      x = ((x << 2) | (x >> 26)) & 0x0fffffff;
+      y = ((y << 2) | (y >> 26)) & 0x0fffffff;
+    }
+    permute(pc2, x, y, kp);
+    kp += 2;
+  }
+}
+
+/* --- @des_eblk@, @des_dblk@ --- *
+ *
+ * Arguments:  @const des_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+void des_eblk(const des_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 x = s[0], y = s[1];
+  DES_IP(x, y);
+  DES_EBLK(k->k, x, y, x, y);
+  DES_IPINV(x, y);
+  d[0] = x, d[1] = y;
+}
+
+void des_dblk(const des_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 x = s[0], y = s[1];
+  DES_IP(x, y);
+  DES_DBLK(k->k, x, y, x, y);
+  DES_IPINV(x, y);
+  d[0] = x, d[1] = y;
+}
+
+BLKC_TEST(DES, des)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/des.h b/symm/des.h
new file mode 100644 (file)
index 0000000..682be6b
--- /dev/null
@@ -0,0 +1,124 @@
+/* -*-c-*-
+ *
+ * The Data Encryption Standard
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on the Data Encryption Standard -----------------------------*
+ *
+ * Almost twenty years after it was first accepted, DES is still the standard
+ * block cipher.  It's showing its age in its small key size and poor
+ * optimiziation for software implementations, but it's not really been badly
+ * dented by the intensive analysis thrown at it.
+ *
+ * This interface is here for compatibility with existing protocols, and
+ * because it's a trivial veneer over the base DES code which is used by the
+ * @des3@ interface which implements proper strong triple-DES.
+ */
+
+#ifndef CATACOMB_DES_H
+#define CATACOMB_DES_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define DES_BLKSZ 8
+#define DES_KEYSZ 7
+#define DES_CLASS (N, B, 64)
+
+extern const octet des_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct des_ctx {
+  uint32 k[32];
+} des_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @des_expand@ --- *
+ *
+ * Arguments:  @const octet *k@ = pointer to key material
+ *             @size_t n@ = number of octets of key material (7 or 8)
+ *             @uint32 *xx, *yy@ = where to put the results
+ *
+ * Returns:    ---
+ *
+ * Use:                Extracts 64 bits of key material from the given buffer,
+ *             possibly expanding it from 56 to 64 bits on the way.
+ *             Parity is set correctly if the key is expanded.
+ */
+
+extern void des_expand(const octet */*k*/, size_t /*n*/,
+                      uint32 */*xx*/, uint32 */*yy*/);
+
+/* --- @des_init@ --- *
+ *
+ * Arguments:  @des_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DES key buffer.  The key buffer may be either 7
+ *             or 8 bytes long.  If it's 8 bytes, the key is assumed to be
+ *             padded with parity bits in the low order bit of each octet.
+ *             These are stripped out without checking prior to the actual
+ *             key scheduling.
+ */
+
+extern void des_init(des_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @des_eblk@, @des_dblk@ --- *
+ *
+ * Arguments:  @const des_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void des_eblk(const des_ctx */*k*/,
+                    const uint32 */*s*/, uint32 */*d*/);
+extern void des_dblk(const des_ctx */*k*/,
+                    const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/des3.c b/symm/des3.c
new file mode 100644 (file)
index 0000000..dedd9f2
--- /dev/null
@@ -0,0 +1,117 @@
+/* -*-c-*-
+ *
+ * Implementation of double- and triple-DES
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "des-base.h"
+#include "des.h"
+#include "des3.h"
+#include "gcipher.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet des3_keysz[] = { KSZ_SET, 21, 7, 8, 14, 16, 24, 0 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @des3_init@ --- *
+ *
+ * Arguments:  @des3_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DES key buffer.  The key buffer may have length
+ *             7, 8, 14, 16, 21, or 24.  These correspond to one, two or
+ *             three DES keys, either packed or unpacked (i.e., still
+ *             containing parity bits).
+ */
+
+void des3_init(des3_ctx *k, const void *buf, size_t sz)
+{
+  size_t step;
+  const octet *p = buf;
+
+  KSZ_ASSERT(des3, sz);
+
+  if (sz % 7 == 0)
+    step = 7;
+  else
+    step = 8;
+
+  des_init(&k->a, p, step);
+  if (sz > 8) p += step;
+  des_init(&k->b, p, step);
+  if (sz > 16) p += step; else p = buf;
+  des_init(&k->c, p, step);
+}
+
+/* --- @des3_eblk@, @des3_dblk@ --- *
+ *
+ * Arguments:  @const des3_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+void des3_eblk(const des3_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 x = s[0], y = s[1];
+  DES_IP(x, y);
+  DES_EBLK(k->a.k, x, y, x, y);
+  DES_DBLK(k->b.k, x, y, x, y);
+  DES_EBLK(k->c.k, x, y, x, y);
+  DES_IPINV(x, y);
+  d[0] = x, d[1] = y;
+}
+
+void des3_dblk(const des3_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 x = s[0], y = s[1];
+  DES_IP(x, y);
+  DES_DBLK(k->c.k, x, y, x, y);
+  DES_EBLK(k->b.k, x, y, x, y);
+  DES_DBLK(k->a.k, x, y, x, y);
+  DES_IPINV(x, y);
+  d[0] = x, d[1] = y;
+}
+
+BLKC_TEST(DES3, des3)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/des3.h b/symm/des3.h
new file mode 100644 (file)
index 0000000..881f558
--- /dev/null
@@ -0,0 +1,108 @@
+/* -*-c-*-
+ *
+ * Implementation of double- and triple-DES
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_DES3_H
+#define CATACOMB_DES3_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Notes on double- and triple-DES -----------------------------------*
+ *
+ * The normal recommendation for using DES now is `triple DES'.
+ * Conventionally, this involves an encrypt-decrypt-encrypt sequence,
+ * although whether the first and last operations use the same key is
+ * unfortunately not agreed upon.  This interface handles both cases (and the
+ * single-key one too, although the simple @des@ calls are quicker for that).
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_DES_H
+#  include "des.h"
+#endif
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define DES3_BLKSZ 8
+#define DES3_KEYSZ 21
+#define DES3_CLASS (N, B, 64)
+
+extern const octet des3_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct des3_ctx {
+  des_ctx a, b, c;
+} des3_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @des3_init@ --- *
+ *
+ * Arguments:  @des3_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DES key buffer.  The key buffer may have length
+ *             7, 8, 14, 16, 21, or 24.  These correspond to one, two or
+ *             three DES keys, either packed or unpacked (i.e., still
+ *             containing parity bits).
+ */
+
+extern void des3_init(des3_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @des3_eblk@, @des_dblk@ --- *
+ *
+ * Arguments:  @const des3_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void des3_eblk(const des3_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+extern void des3_dblk(const des3_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/desx-tab.h b/symm/desx-tab.h
new file mode 100644 (file)
index 0000000..f1b54d4
--- /dev/null
@@ -0,0 +1,78 @@
+/* -*-c-*-
+ *
+ * Tables for DESX
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_DESX_TAB_H
+#define CATACOMB_DESX_TAB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- S-box table -------------------------------------------------------*/
+
+#define DESX_S {                                                       \
+  0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a,                      \
+  0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0,                      \
+  0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b,                      \
+  0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a,                      \
+  0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda,                      \
+  0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36,                      \
+  0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8,                      \
+  0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c,                      \
+  0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17,                      \
+  0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60,                      \
+  0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72,                      \
+  0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa,                      \
+  0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd,                      \
+  0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e,                      \
+  0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b,                      \
+  0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf,                      \
+  0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77,                      \
+  0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6,                      \
+  0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3,                      \
+  0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3,                      \
+  0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e,                      \
+  0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c,                      \
+  0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d,                      \
+  0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2,                      \
+  0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46,                      \
+  0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5,                      \
+  0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97,                      \
+  0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5,                      \
+  0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef,                      \
+  0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,                      \
+  0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf,                      \
+  0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab,                      \
+}
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/desx.c b/symm/desx.c
new file mode 100644 (file)
index 0000000..d65ffa7
--- /dev/null
@@ -0,0 +1,149 @@
+/* -*-c-*-
+ *
+ * Implementation of DESX
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "des-base.h"
+#include "des.h"
+#include "desx.h"
+#include "desx-tab.h"
+#include "gcipher.h"
+
+/*----- Tables ------------------------------------------------------------*/
+
+static const octet s[256] = DESX_S;
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet desx_keysz[] = { KSZ_SET, 23, 7, 8, 15, 16, 24, 0 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @desx_init@ --- *
+ *
+ * Arguments:  @desx_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DESX key buffer.  The key buffer contains, in
+ *             order, a single-DES key (either 7 or 8 bytes), an optional
+ *             8-byte pre-whitening key, and an optional 8-byte
+ *             port-whitening key.  If no whitening keys are specified, the
+ *             algorithm becomes the same as single-DES.
+ */
+
+static void mangle(octet *b, const octet *p)
+{
+  unsigned i;
+
+  for (i = 0; i < 8; i++)
+    b[i] = *p++ ^ s[b[i] ^ b[(i + 1) & 7u]];
+}
+
+void desx_init(desx_ctx *k, const void *buf, size_t sz)
+{
+  const octet *p = buf, *kk = buf;
+  size_t n;
+
+  KSZ_ASSERT(desx, sz);
+
+  n = sz % 8 == 7 ? 7 : 8;
+  des_init(&k->k, p, n);
+  p += n;
+  sz -= n;
+  if (!sz)
+    k->prea = k->preb = k->posta = k->postb = 0;
+  else {
+    const octet *q = p;
+    k->prea = LOAD32(q + 0);
+    k->preb = LOAD32(q + 4);
+    p += 8;
+    sz -= 8;
+    if (sz) {
+      k->posta = LOAD32(p + 0);
+      k->postb = LOAD32(p + 4);
+    } else {
+      octet b[16];
+      uint32 x, y;
+
+      des_expand(kk, n, &x, &y);
+      STORE32(b + 8, x); STORE32(b + 12, y);
+      memset(b, 0, 8);
+      mangle(b, b + 8);
+      mangle(b, q);
+      k->posta = LOAD32(b + 0);
+      k->postb = LOAD32(b + 4);
+    }
+  }
+}
+
+/* --- @desx_eblk@, @desx_dblk@ --- *
+ *
+ * Arguments:  @const desx_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+void desx_eblk(const desx_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 x = s[0], y = s[1];
+  x ^= k->prea; y ^= k->preb;
+  DES_IP(x, y);
+  DES_EBLK(k->k.k, x, y, x, y);
+  DES_IPINV(x, y);
+  x ^= k->posta; y ^= k->postb;
+  d[0] = x, d[1] = y;
+}
+
+void desx_dblk(const desx_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 x = s[0], y = s[1];
+  x ^= k->posta; y ^= k->postb;
+  DES_IP(x, y);
+  DES_DBLK(k->k.k, x, y, x, y);
+  DES_IPINV(x, y);
+  x ^= k->prea; y ^= k->preb;
+  d[0] = x, d[1] = y;
+}
+
+BLKC_TEST(DESX, desx)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/desx.h b/symm/desx.h
new file mode 100644 (file)
index 0000000..62e8300
--- /dev/null
@@ -0,0 +1,109 @@
+/* -*-c-*-
+ *
+ * The DESX algorithm
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Notes on DESX -----------------------------------------------------*
+ *
+ * DESX was designed by Ron Rivest in 1986 as a simple and cheap way to
+ * strengthen DES against exhaustive search.  It also increases the
+ * difficulty of differential and linear attacks.
+ */
+
+#ifndef CATACOMB_DESX_H
+#define CATACOMB_DESX_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_DES_H
+#  include "des.h"
+#endif
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define DESX_BLKSZ 8
+#define DESX_KEYSZ 23
+#define DESX_CLASS (N, B, 64)
+
+extern const octet desx_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct desx_ctx {
+  des_ctx k;
+  uint32 prea, preb;
+  uint32 posta, postb;
+} desx_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @desx_init@ --- *
+ *
+ * Arguments:  @desx_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a DESX key buffer.  The key buffer contains, in
+ *             order, an optional 8-byte pre-whitening key, a single-DES key
+ *             (either 7 or 8 bytes), and an optional 8-byte port-whitening
+ *             key.  If no whitening keys are specified, the algorithm
+ *             becomes the same as single-DES.
+ */
+
+extern void desx_init(desx_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @desx_eblk@, @desx_dblk@ --- *
+ *
+ * Arguments:  @const desx_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void desx_eblk(const desx_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+extern void desx_dblk(const desx_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/ecb-def.h b/symm/ecb-def.h
new file mode 100644 (file)
index 0000000..ea153a2
--- /dev/null
@@ -0,0 +1,471 @@
+/* -*-c-*-
+ *
+ * Definitions electronic code book mode
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_ECB_DEF_H
+#define CATACOMB_ECB_DEF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+#  include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @ECB_DEF@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates an implementation for ECB stealing mode.
+ */
+
+#define ECB_DEF(PRE, pre)                                              \
+                                                                       \
+/* --- @pre_ecbsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the ECB context to use a different cipher key.     \
+ */                                                                    \
+                                                                       \
+void pre##_ecbsetkey(pre##_ecbctx *ctx, const pre##_ctx *k)            \
+{                                                                      \
+  ctx->ctx = *k;                                                       \
+}                                                                      \
+                                                                       \
+/* --- @pre_ecbinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_ecbctx *ctx@ = pointer to cipher context           \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes an ECB context ready for use.  This is      \
+ *             equivalent to calls to @pre_init@ and @pre_setkey@.     \
+ */                                                                    \
+                                                                       \
+void pre##_ecbinit(pre##_ecbctx *ctx,                                  \
+                    const void *key, size_t sz,                        \
+                    const void *iv)                                    \
+{                                                                      \
+  pre##_init(&ctx->ctx, key, sz);                                      \
+}                                                                      \
+                                                                       \
+/* --- @pre_ecbencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts a block with a block cipher in ECB mode, with  \
+ *             ciphertext stealing and other clever tricks.            \
+ *             Essentially, data can be encrypted in arbitrary sized   \
+ *             chunks, although decryption must use the same chunks.   \
+ */                                                                    \
+                                                                       \
+void pre##_ecbencrypt(pre##_ecbctx *ctx,                               \
+                       const void *src, void *dest,                    \
+                       size_t sz)                                      \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+                                                                       \
+  /* --- Empty blocks are trivial --- */                               \
+                                                                       \
+  if (!sz)                                                             \
+    return;                                                            \
+                                                                       \
+  /* --- Short blocks aren't allowed in ECB --- *                      \
+   *                                                                   \
+   * There's absolutely nothing secure I can do with them.             \
+   */                                                                  \
+                                                                       \
+  assert(((void)"ECB must have at least one whole block to work with", \
+         sz >= PRE##_BLKSZ));                                          \
+                                                                       \
+  /* --- Do the main chunk of encryption --- *                         \
+   *                                                                   \
+   * This will do the whole lot if it's a whole number of blocks.  Just        \
+   * give each block to the cipher in turn.  This is trivial.          \
+   * Hopefully...                                                      \
+   */                                                                  \
+                                                                       \
+  while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                 \
+    uint32 x[PRE##_BLKSZ / 4];                                         \
+    if (!s)                                                            \
+      BLKC_ZERO(PRE, x);                                               \
+    else {                                                             \
+      BLKC_LOAD(PRE, x, s);                                            \
+      s += PRE##_BLKSZ;                                                        \
+    }                                                                  \
+    pre##_eblk(&ctx->ctx, x, x);                                       \
+    if (d) {                                                           \
+      BLKC_STORE(PRE, d, x);                                           \
+      d += PRE##_BLKSZ;                                                        \
+    }                                                                  \
+    sz -= PRE##_BLKSZ;                                                 \
+  }                                                                    \
+                                                                       \
+  /* --- Do the tail-end block and bit-left-over --- *                 \
+   *                                                                   \
+   * This isn't very efficient.  That shouldn't matter much.           \
+   */                                                                  \
+                                                                       \
+  if (sz) {                                                            \
+    uint32 x[PRE##_BLKSZ / 4];                                         \
+    octet b[PRE##_BLKSZ];                                              \
+    unsigned i;                                                                \
+                                                                       \
+    /* --- Let @sz@ be the size of the partial block --- */            \
+                                                                       \
+    sz -= PRE##_BLKSZ;                                                 \
+                                                                       \
+    /* --- First stage --- *                                           \
+     *                                                                 \
+     * Read in the current block, and encrypt it.  The first part of   \
+     * the result is the partial ciphertext block.  Don't write that   \
+     * out yet, because I've not read the partial plaintext block.     \
+     */                                                                        \
+                                                                       \
+    if (!s)                                                            \
+      BLKC_ZERO(PRE, x);                                               \
+    else {                                                             \
+      BLKC_LOAD(PRE, x, s);                                            \
+      s += PRE##_BLKSZ;                                                        \
+    }                                                                  \
+    pre##_eblk(&ctx->ctx, x, x);                                       \
+    BLKC_STORE(PRE, b, x);                                             \
+                                                                       \
+    /* --- Second stage --- *                                          \
+     *                                                                 \
+     * Now move in the partial plaintext block, writing out the                \
+     * ciphertext as I go.  Then encrypt, and write the complete       \
+     * ciphertext block.                                               \
+     */                                                                        \
+                                                                       \
+    if (d) d += PRE##_BLKSZ;                                           \
+    for (i = 0; i < sz; i++) {                                         \
+      register octet y = b[i];                                         \
+      b[i] = s[i];                                                     \
+      if (d) d[i] = y;                                                 \
+    }                                                                  \
+    BLKC_LOAD(PRE, x, b);                                              \
+    pre##_eblk(&ctx->ctx, x, x);                                       \
+    if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, x);                                \
+  }                                                                    \
+                                                                       \
+  /* --- Done --- */                                                   \
+                                                                       \
+  return;                                                              \
+}                                                                      \
+                                                                       \
+/* --- @pre_ecbdecrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Decrypts a block with a block cipher in ECB mode, with  \
+ *             ciphertext stealing and other clever tricks.            \
+ *             Essentially, data can be encrypted in arbitrary sized   \
+ *             chunks, although decryption must use the same chunks.   \
+ */                                                                    \
+                                                                       \
+void pre##_ecbdecrypt(pre##_ecbctx *ctx,                               \
+                       const void *src, void *dest,                    \
+                       size_t sz)                                      \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+                                                                       \
+  /* --- Empty blocks are trivial --- */                               \
+                                                                       \
+  if (!sz)                                                             \
+    return;                                                            \
+                                                                       \
+  /* --- Short blocks aren't allowed in ECB --- *                      \
+   *                                                                   \
+   * There's absolutely nothing secure I can do with them.             \
+   */                                                                  \
+                                                                       \
+  assert(((void)"ECB must have at least one whole block to work with", \
+         sz >= PRE##_BLKSZ));                                          \
+                                                                       \
+  /* --- Do the main chunk of decryption --- *                         \
+   *                                                                   \
+   * This will do the whole lot if it's a whole number of blocks.      \
+   * Each block is just handed to the block cipher in turn.            \
+   */                                                                  \
+                                                                       \
+  while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                 \
+    uint32 x[PRE##_BLKSZ / 4];                                         \
+    BLKC_LOAD(PRE, x, s);                                              \
+    pre##_dblk(&ctx->ctx, x, x);                                       \
+    BLKC_STORE(PRE, d, x);                                             \
+    s += PRE##_BLKSZ;                                                  \
+    d += PRE##_BLKSZ;                                                  \
+    sz -= PRE##_BLKSZ;                                                 \
+  }                                                                    \
+                                                                       \
+  /* --- Do the tail-end block and bit-left-over --- *                 \
+   *                                                                   \
+   * This isn't very efficient.  That shouldn't matter much.           \
+   */                                                                  \
+                                                                       \
+  if (sz) {                                                            \
+    uint32 x[PRE##_BLKSZ / 4];                                         \
+    octet b[PRE##_BLKSZ];                                              \
+    unsigned i;                                                                \
+                                                                       \
+    /* --- Let @sz@ be the size of the partial block --- */            \
+                                                                       \
+    sz -= PRE##_BLKSZ;                                                 \
+                                                                       \
+    /* --- First stage --- *                                           \
+     *                                                                 \
+     * Take the complete ciphertext block, and decrypt it.  This block \
+     * is carried over for the next encryption operation.              \
+     */                                                                        \
+                                                                       \
+    BLKC_LOAD(PRE, x, s);                                              \
+    pre##_dblk(&ctx->ctx, x, x);                                       \
+    BLKC_STORE(PRE, b, x);                                             \
+                                                                       \
+    /* --- Second stage --- *                                          \
+     *                                                                 \
+     * The first few bytes are the partial plaintext block.  Write that        \
+     * and replace with the partial ciphertext block.  Then decrypt    \
+     * what's left as the complete plaintext.                          \
+     */                                                                        \
+                                                                       \
+    s += PRE##_BLKSZ;                                                  \
+    d += PRE##_BLKSZ;                                                  \
+    for (i = 0; i < sz; i++) {                                         \
+      register octet y = s[i];                                         \
+      d[i] = b[i];                                                     \
+      b[i] = y;                                                                \
+    }                                                                  \
+    BLKC_LOAD(PRE, x, b);                                              \
+    pre##_dblk(&ctx->ctx, x, x);                                       \
+    BLKC_STORE(PRE, d - PRE##_BLKSZ, x);                               \
+  }                                                                    \
+                                                                       \
+  /* --- Done --- */                                                   \
+                                                                       \
+  return;                                                              \
+}                                                                      \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+static const gcipher_ops gops;                                         \
+                                                                       \
+typedef struct gctx {                                                  \
+  gcipher c;                                                           \
+  pre##_ecbctx k;                                                      \
+} gctx;                                                                        \
+                                                                       \
+static gcipher *ginit(const void *k, size_t sz)                                \
+{                                                                      \
+  gctx *g = S_CREATE(gctx);                                            \
+  g->c.ops = &gops;                                                    \
+  pre##_ecbinit(&g->k, k, sz, 0);                                      \
+  return (&g->c);                                                      \
+}                                                                      \
+                                                                       \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_ecbencrypt(&g->k, s, t, sz);                                   \
+}                                                                      \
+                                                                       \
+static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_ecbdecrypt(&g->k, s, t, sz);                                   \
+}                                                                      \
+                                                                       \
+static void gdestroy(gcipher *c)                                       \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static const gcipher_ops gops = {                                      \
+  &pre##_ecb,                                                          \
+  gencrypt, gdecrypt, gdestroy, 0, 0                                   \
+};                                                                     \
+                                                                       \
+const gccipher pre##_ecb = {                                           \
+  #pre "-ecb", pre##_keysz, PRE##_BLKSZ,                               \
+  ginit                                                                        \
+};                                                                     \
+                                                                       \
+ECB_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @ECB_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use:                Standard test rig for ECB functions.
+ */
+
+#define ECB_TEST(PRE, pre)                                             \
+                                                                       \
+/* --- Initial plaintext for the test --- */                           \
+                                                                       \
+static const octet text[] = TEXT;                                      \
+                                                                       \
+/* --- Key and IV to use --- */                                                \
+                                                                       \
+static const octet key[] = KEY;                                                \
+static const octet iv[] = IV;                                          \
+                                                                       \
+/* --- Buffers for encryption and decryption output --- */             \
+                                                                       \
+static octet ct[sizeof(text)];                                         \
+static octet pt[sizeof(text)];                                         \
+                                                                       \
+static void hexdump(const octet *p, size_t sz)                         \
+{                                                                      \
+  const octet *q = p + sz;                                             \
+  for (sz = 0; p < q; p++, sz++) {                                     \
+    printf("%02x", *p);                                                        \
+    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
+      putchar(':');                                                    \
+  }                                                                    \
+}                                                                      \
+                                                                       \
+int main(void)                                                         \
+{                                                                      \
+  size_t sz = 0, rest;                                                 \
+  pre##_ecbctx ctx;                                                    \
+  int status = 0;                                                      \
+  int done = 0;                                                                \
+                                                                       \
+  size_t keysz = PRE##_KEYSZ ?                                         \
+    PRE##_KEYSZ : strlen((const char *)key);                           \
+                                                                       \
+  fputs(#pre "-ecb: ", stdout);                                                \
+                                                                       \
+  pre##_ecbinit(&ctx, key, keysz, iv);                                 \
+                                                                       \
+  while (sz <= sizeof(text)) {                                         \
+    rest = sizeof(text) - sz;                                          \
+    if ((sz != 0 && sz < PRE##_BLKSZ) ||                               \
+       (rest != 0 && rest < PRE##_BLKSZ))                              \
+      goto next;                                                       \
+    memcpy(ct, text, sizeof(text));                                    \
+    pre##_ecbencrypt(&ctx, ct, ct, sz);                                        \
+    pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest);                    \
+    memcpy(pt, ct, sizeof(text));                                      \
+    pre##_ecbdecrypt(&ctx, pt, pt, sz);                                        \
+    pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest);                    \
+    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
+      done++;                                                          \
+      if (sizeof(text) < 40 || done % 8 == 0)                          \
+       fputc('.', stdout);                                             \
+      if (done % 480 == 0)                                             \
+       fputs("\n\t", stdout);                                          \
+      fflush(stdout);                                                  \
+    } else {                                                           \
+      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
+      status = 1;                                                      \
+      printf("\tplaintext      = "); hexdump(text, sz);                        \
+       printf(", "); hexdump(text + sz, rest);                         \
+       fputc('\n', stdout);                                            \
+      printf("\tciphertext     = "); hexdump(ct, sz);                  \
+       printf(", "); hexdump(ct + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      printf("\trecovered text = "); hexdump(pt, sz);                  \
+       printf(", "); hexdump(pt + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      fputc('\n', stdout);                                             \
+    }                                                                  \
+  next:                                                                        \
+    if (sz < 63)                                                       \
+      sz++;                                                            \
+    else                                                               \
+      sz += 9;                                                         \
+  }                                                                    \
+                                                                       \
+  fputs(status ? " failed\n" : " ok\n", stdout);                       \
+  return (status);                                                     \
+}
+
+#else
+#  define ECB_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/ecb.h b/symm/ecb.h
new file mode 100644 (file)
index 0000000..4f5d525
--- /dev/null
@@ -0,0 +1,138 @@
+/* -*-c-*-
+ *
+ * Electronic code book for block ciphers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_ECB_H
+#define CATACOMB_ECB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @ECB_DECL@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates declarations for ECB stealing mode.
+ */
+
+#define ECB_DECL(PRE, pre)                                             \
+                                                                       \
+/* --- Electronic codebook context --- */                              \
+                                                                       \
+typedef struct pre##_ecbctx {                                          \
+  pre##_ctx ctx;                       /* Underlying cipher context */ \
+} pre##_ecbctx;                                                                \
+                                                                       \
+/* --- @pre_ecbsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the ECB context to use a different cipher key.     \
+ */                                                                    \
+                                                                       \
+extern void pre##_ecbsetkey(pre##_ecbctx */*ctx*/,                     \
+                           const pre##_ctx */*k*/);                    \
+                                                                       \
+/* --- @pre_ecbinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_ecbctx *ctx@ = pointer to cipher context           \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes an ECB context ready for use.  This is      \
+ *             equivalent to calls to @pre_init@ and @pre_setkey@.     \
+ */                                                                    \
+                                                                       \
+extern void pre##_ecbinit(pre##_ecbctx */*ctx*/,                       \
+                         const void */*key*/, size_t /*sz*/,           \
+                         const void */*iv*/);                          \
+                                                                       \
+/* --- @pre_ecbencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts a block with a block cipher in ECB mode, with  \
+ *             ciphertext stealing and other clever tricks.            \
+ *             Essentially, data can be encrypted in arbitrary sized   \
+ *             chunks, although decryption must use the same chunks.   \
+ */                                                                    \
+                                                                       \
+extern void pre##_ecbencrypt(pre##_ecbctx */*ctx*/,                    \
+                            const void */*src*/, void */*dest*/,       \
+                            size_t /*sz*/);                            \
+                                                                       \
+/* --- @pre_ecbdecrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_ecbctx *ctx@ = pointer to ECB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Decrypts a block with a block cipher in ECB mode, with  \
+ *             ciphertext stealing and other clever tricks.            \
+ *             Essentially, data can be encrypted in arbitrary sized   \
+ *             chunks, although decryption must use the same chunks.   \
+ */                                                                    \
+                                                                       \
+extern void pre##_ecbdecrypt(pre##_ecbctx */*ctx*/,                    \
+                            const void */*src*/, void */*dest*/,       \
+                            size_t /*sz*/);                            \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+extern const gccipher pre##_ecb;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/gcipher.h b/symm/gcipher.h
new file mode 100644 (file)
index 0000000..efe9f51
--- /dev/null
@@ -0,0 +1,96 @@
+/* -*-c-*-
+ *
+ * Generic symmetric cipher interface
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_GCIPHER_H
+#define CATACOMB_GCIPHER_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_KEYSZ_H
+#  include "keysz.h"
+#endif
+
+/*----- Generic symmetric cipher interface --------------------------------*/
+
+typedef struct gcipher {
+  const struct gcipher_ops *ops;       /* Pointer to cipher operations */
+} gcipher;
+
+typedef struct gcipher_ops {
+  const struct gccipher *c;            /* Pointer to cipher class */
+  void (*encrypt)(gcipher */*c*/, const void */*s*/,
+                 void */*t*/, size_t /*sz*/);
+  void (*decrypt)(gcipher */*c*/, const void */*s*/,
+                 void */*t*/, size_t /*sz*/);
+  void (*destroy)(gcipher */*c*/);
+  void (*setiv)(gcipher */*c*/, const void */*iv*/);
+  void (*bdry)(gcipher */*c*/);
+} gcipher_ops;
+
+typedef struct gccipher {
+  const char *name;                    /* Cipher name */
+  const octet *keysz;                  /* Preferred key size table */
+  size_t blksz;                                /* Block size or zero if none */
+  gcipher *(*init)(const void */*k*/, size_t /*sz*/);
+} gccipher;
+
+#define GC_INIT(cc, k, sz)     (cc)->init((k), (sz))
+#define GC_CLASS(cc)           (cc)->ops->c
+#define GC_ENCRYPT(c, s, t, sz)        (c)->ops->encrypt((c), (s), (t), (sz))
+#define GC_DECRYPT(c, s, t, sz)        (c)->ops->decrypt((c), (s), (t), (sz))
+#define GC_DESTROY(c)          (c)->ops->destroy((c))
+#define GC_SETIV(c, iv)                (c)->ops->setiv((c), (iv))
+#define GC_BDRY(c)             (c)->ops->bdry((c))
+
+/*----- Tables ------------------------------------------------------------*/
+
+extern const gccipher *const gciphertab[];
+
+/* --- @gcipher_byname@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to name string
+ *
+ * Returns:    The named cipher class, or null.
+ */
+
+extern const gccipher *gcipher_byname(const char */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/ghash-def.h b/symm/ghash-def.h
new file mode 100644 (file)
index 0000000..2ede96f
--- /dev/null
@@ -0,0 +1,119 @@
+/* -*-c-*-
+ *
+ * Definitions for generic hash interface
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_GHASH_DEF_H
+#define CATACOMB_GHASH_DEF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+/*----- Generic hash function interface -----------------------------------*/
+
+/* --- @GHASH_DEF@ --- *
+ *
+ * Arguments:  @PRE, pre@ = prefixes for hash function
+ *
+ * Use:                Defines the generic hash instance.
+ */
+
+#define GHASH_DEF(PRE, pre)                                            \
+                                                                       \
+static const ghash_ops gops;                                           \
+                                                                       \
+typedef struct gctx {                                                  \
+  ghash h;                                                             \
+  pre##_ctx c;                                                         \
+  octet buf[PRE##_HASHSZ];                                             \
+} gctx;                                                                        \
+                                                                       \
+static ghash *ghinit(void)                                             \
+{                                                                      \
+  gctx *g = S_CREATE(gctx);                                            \
+  g->h.ops = &gops;                                                    \
+  pre##_init(&g->c);                                                   \
+  return (&g->h);                                                      \
+}                                                                      \
+                                                                       \
+static void ghhash(ghash *h, const void *p, size_t sz)                 \
+{                                                                      \
+  gctx *g = (gctx *)h;                                                 \
+  pre##_hash(&g->c, p, sz);                                            \
+}                                                                      \
+                                                                       \
+static octet *ghdone(ghash *h, void *buf)                              \
+{                                                                      \
+  gctx *g = (gctx *)h;                                                 \
+  if (!buf)                                                            \
+    buf = g->buf;                                                      \
+  pre##_done(&g->c, buf);                                              \
+  return (buf);                                                                \
+}                                                                      \
+                                                                       \
+static void ghdestroy(ghash *h)                                                \
+{                                                                      \
+  gctx *g = (gctx *)h;                                                 \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static ghash *ghcopy(ghash *h)                                         \
+{                                                                      \
+  gctx *g = (gctx *)h;                                                 \
+  gctx *gg = S_CREATE(gctx);                                           \
+  memcpy(gg, g, sizeof(gctx));                                         \
+  return (&gg->h);                                                     \
+}                                                                      \
+                                                                       \
+static const ghash_ops gops =                                          \
+  { &pre, ghhash, ghdone, ghdestroy, ghcopy };                         \
+const gchash pre = { #pre, PRE##_HASHSZ, ghinit, PRE##_BUFSZ };
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/ghash.h b/symm/ghash.h
new file mode 100644 (file)
index 0000000..2f6a6cd
--- /dev/null
@@ -0,0 +1,154 @@
+/* -*-c-*-
+ *
+ * Generic hash function interface
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_GHASH_H
+#define CATACOMB_GHASH_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Generic hash function interface -----------------------------------*/
+
+typedef struct ghash {
+  const struct ghash_ops *ops;         /* Pointer to hash operations */
+} ghash;
+
+typedef struct ghash_ops {
+  const struct gchash *c;              /* Pointer to hash class */
+  void (*hash)(ghash */*h*/, const void */*p*/, size_t /*sz*/); /* Hash */
+  octet *(*done)(ghash */*h*/, void */*buf*/); /* Write result */
+  void (*destroy)(ghash */*h*/);       /* Destroy hash block */
+  ghash *(*copy)(ghash */*h*/);                /* Make a copy of the hash context */
+} ghash_ops;
+
+#define GH_INIT(ch)            (ch)->init()
+#define GH_CLASS(h)            (h)->ops->c
+#define GH_HASH(h, p, sz)      (h)->ops->hash((h), (p), (sz))
+#define GH_DONE(h, buf)                (h)->ops->done((h), (buf))
+#define GH_DESTROY(h)          (h)->ops->destroy((h))
+#define GH_COPY(h)             (h)->ops->copy((h))
+
+#define GH_HASHU_(h, n, W)  do {                                       \
+  TY_U##W n_ = (n); octet b_[SZ_##W];                                  \
+  STORE##W(b_, n_); GH_HASH((h), b_, SZ_##W);                          \
+} while (0)
+#define GH_HASHU8(h, n)         GH_HASHU_((h), (n), 8)
+#define GH_HASHU16(h, n) GH_HASHU_((h), (n), 16)
+#define GH_HASHU16_B(h, n) GH_HASHU_((h), (n), 16_B)
+#define GH_HASHU16_L(h, n) GH_HASHU_((h), (n), 16_L)
+#define GH_HASHU24(h, n) GH_HASHU_((h), (n), 24)
+#define GH_HASHU24_B(h, n) GH_HASHU_((h), (n), 24_B)
+#define GH_HASHU24_L(h, n) GH_HASHU_((h), (n), 24_L)
+#define GH_HASHU32(h, n) GH_HASHU_((h), (n), 32)
+#define GH_HASHU32_B(h, n) GH_HASHU_((h), (n), 32_B)
+#define GH_HASHU32_L(h, n) GH_HASHU_((h), (n), 32_L)
+#ifdef HAVE_UINT64
+#  define GH_HASHU64(h, n) GH_HASHU_((h), (n), 64)
+#  define GH_HASHU64_B(h, n) GH_HASHU_((h), (n), 64_B)
+#  define GH_HASHU64_L(h, n) GH_HASHU_((h), (n), 64_L)
+#endif
+
+#define GH_HASHBUF_(h, p, sz, W) do {                                  \
+  size_t sz_ = (sz); assert(sz_ <= MASK##W);                           \
+  GH_HASHU_(h, sz_, W); GH_HASH(h, (p), sz_);                          \
+} while (0)
+#define GH_HASHBUF8(h, p, sz) GH_HASHBUF_((h), (p), (sz), 8)
+#define GH_HASHBUF16(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16)
+#define GH_HASHBUF16_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16_L)
+#define GH_HASHBUF16_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 16_B)
+#define GH_HASHBUF24(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24)
+#define GH_HASHBUF24_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24_L)
+#define GH_HASHBUF24_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 24_B)
+#define GH_HASHBUF32(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32)
+#define GH_HASHBUF32_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32_L)
+#define GH_HASHBUF32_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 32_B)
+#ifdef HAVE_UINT64
+#  define GH_HASHBUF64(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64)
+#  define GH_HASHBUF64_L(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64_L)
+#  define GH_HASHBUF64_B(h, p, sz) GH_HASHBUF_((h), (p), (sz), 64_B)
+#endif
+
+#define GH_HASHSTR_(h, p, W) do {                                      \
+  const char *p_ = (p); GH_HASHBUF_((h), p_, strlen(p_), W);           \
+} while (0)
+#define GH_HASHSTR8(h, p) GH_HASHSTR_((h), (p), 8)
+#define GH_HASHSTR16(h, p) GH_HASHSTR_((h), (p), 16)
+#define GH_HASHSTR16_L(h, p) GH_HASHSTR_((h), (p), 16_L)
+#define GH_HASHSTR16_B(h, p) GH_HASHSTR_((h), (p), 16_B)
+#define GH_HASHSTR24(h, p) GH_HASHSTR_((h), (p), 24)
+#define GH_HASHSTR24_L(h, p) GH_HASHSTR_((h), (p), 24_L)
+#define GH_HASHSTR24_B(h, p) GH_HASHSTR_((h), (p), 24_B)
+#define GH_HASHSTR32(h, p) GH_HASHSTR_((h), (p), 32)
+#define GH_HASHSTR32_L(h, p) GH_HASHSTR_((h), (p), 32_L)
+#define GH_HASHSTR32_B(h, p) GH_HASHSTR_((h), (p), 32_B)
+#ifdef HAVE_UINT64
+#  define GH_HASHSTR64(h, p) GH_HASHSTR_((h), (p), 64)
+#  define GH_HASHSTR64_L(h, p) GH_HASHSTR_((h), (p), 64_L)
+#  define GH_HASHSTR64_B(h, p) GH_HASHSTR_((h), (p), 64_B)
+#endif
+
+#define GH_HASHSTRZ(h, p) do {                                         \
+  const char *p_ = (p); GH_HASH((h), p_, strlen(p_) + 1);              \
+} while (0)
+#define GH_HASHSTR(h, p) do {                                          \
+  const char *p_ = (p); GH_HASH((h), p_, strlen(p_));                  \
+} while (0)
+
+typedef struct gchash {
+  const char *name;                    /* Name of the hash function */
+  size_t hashsz;                       /* Size of output hash */
+  ghash *(*init)(void);                        /* Create a new hash instance */
+  size_t bufsz;                                /* Buffer size, or zero */
+} gchash;
+
+/*----- Tables ------------------------------------------------------------*/
+
+extern const gchash *const ghashtab[];
+
+/* --- @ghash_byname@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to name string
+ *
+ * Returns:    The named cipher class, or null.
+ */
+
+extern const gchash *ghash_byname(const char */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/gmac.h b/symm/gmac.h
new file mode 100644 (file)
index 0000000..efd4a02
--- /dev/null
@@ -0,0 +1,90 @@
+/* -*-c-*-
+ *
+ * Generic MAC function interface
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_GMAC_H
+#define CATACOMB_GMAC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Generic MAC function interface ------------------------------------*/
+
+typedef struct gmac {
+  const struct gmac_ops *ops;          /* Pointer to MAC operations */
+} gmac;
+
+typedef struct gmac_ops {
+  const struct gcmac *c;               /* Pointer to MAC class */
+  ghash *(*init)(gmac */*m*/);         /* Create keyed hash instance */
+  void (*destroy)(gmac */*m*/);                /* Destroy MAC key block */
+} gmac_ops;
+
+typedef struct gcmac {
+  const char *name;                    /* Name of the MAC function */
+  size_t hashsz;                       /* Size of output hash */
+  const octet *keysz;                  /* Key size options */
+  gmac *(*key)(const void */*k*/, size_t /*sz*/); /* Create key */
+} gcmac;
+
+#define GM_KEY(cm, k, ksz)     (cm)->key((k), (ksz))
+#define GM_CLASS(km)           (km)->ops->c
+#define GM_INIT(km)            (km)->ops->init((km))
+#define GM_DESTROY(km)         (km)->ops->destroy((km))
+
+/*----- Tables ------------------------------------------------------------*/
+
+extern const gcmac *const gmactab[];
+
+/* --- @gmac_byname@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to name string
+ *
+ * Returns:    The named cipher class, or null.
+ */
+
+extern const gcmac *gmac_byname(const char */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
similarity index 100%
rename from gthingtab.c.in
rename to symm/gthingtab.c.in
diff --git a/symm/has160.c b/symm/has160.c
new file mode 100644 (file)
index 0000000..483b9fe
--- /dev/null
@@ -0,0 +1,246 @@
+/* -*-c-*-
+ *
+ * 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.
+ */
+
+/*----- 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/symm/has160.h b/symm/has160.h
new file mode 100644 (file)
index 0000000..d3c17f1
--- /dev/null
@@ -0,0 +1,157 @@
+/* -*-c-*-
+ *
+ * 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.
+ */
+
+/*----- 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
diff --git a/symm/hash.h b/symm/hash.h
new file mode 100644 (file)
index 0000000..31cf4a8
--- /dev/null
@@ -0,0 +1,277 @@
+/* -*-c-*-
+ *
+ * Generic handling for message digest functions
+ *
+ * (c) 1998 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.
+ */
+
+#ifndef CATACOMB_HASH_H
+#define CATACOMB_HASH_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @HASH_BUFFER@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for hash-specific definitions
+ *             @ictx@ = pointer to context block for the hash
+ *             @ibuf@ = pointer to input data to hash
+ *             @isz@ = size of buffer
+ *
+ * Use:                Handles buffering of input data to a hash function.  The
+ *             hash's compression function is called when the buffer is
+ *             full.  Note that the compression function can be called on
+ *             data which is at odd alignments; it is expected to cope
+ *             gracefully with this (possibly by copying the data into its
+ *             internal buffer before starting).
+ */
+
+#define HASH_BUFFER(PRE, pre, ictx, ibuf, isz) do {                    \
+  pre##_ctx *_bctx = (ictx);                                           \
+  size_t _bsz = (isz);                                                 \
+  const octet *_bbuf = (octet *)(ibuf);                                        \
+                                                                       \
+  /* --- Add on the size done so far --- *                             \
+   *                                                                   \
+   * Messy, because trapping overflow is difficult when you don't know \
+   * how many bits you've actually got.                                        \
+   */                                                                  \
+                                                                       \
+  {                                                                    \
+    uint32 _l = U32(_bsz);                                             \
+    uint32 _h = ((_bsz & ~MASK32) >> 16) >> 16;                                \
+    _bctx->nh += _h;                                                   \
+    _bctx->nl += _l;                                                   \
+    if (_bctx->nl < _l || _bctx->nl & ~MASK32)                         \
+      _bctx->nh++;                                                     \
+  }                                                                    \
+                                                                       \
+  /* --- Handle very small contributions --- */                                \
+                                                                       \
+  if (_bctx->off + _bsz < PRE##_BUFSZ) {                               \
+    memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz);                      \
+    _bctx->off += _bsz;                                                        \
+  } else {                                                             \
+                                                                       \
+    /* --- Handle an initial partial buffer --- */                     \
+                                                                       \
+    if (_bctx->off) {                                                  \
+      size_t s = PRE##_BUFSZ - _bctx->off;                             \
+      memcpy(_bctx->buf + _bctx->off, _bbuf, s);                       \
+      pre##_compress(_bctx, _bctx->buf);                               \
+      _bsz -= s; _bbuf += s;                                           \
+    }                                                                  \
+                                                                       \
+    /* --- Do whole buffers while we can --- */                                \
+                                                                       \
+    while (_bsz >= PRE##_BUFSZ) {                                      \
+      pre##_compress(_bctx, _bbuf);                                    \
+      _bsz -= PRE##_BUFSZ; _bbuf += PRE##_BUFSZ;                       \
+    }                                                                  \
+                                                                       \
+    /* --- And wrap up at the end --- */                               \
+                                                                       \
+    if (_bsz)                                                          \
+      memcpy(_bctx->buf, _bbuf, _bsz);                                 \
+    _bctx->off = _bsz;                                                 \
+  }                                                                    \
+} while (0)
+
+/* --- @HASH_PAD@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for hash-specific definitions
+ *             @ictx@ = pointer to context block for the hash
+ *             @term@ = terminator character to write following the data
+ *             @pad@ = pad character to fill with
+ *             @diff@ = size of space to leave at the end of the last block
+ *
+ * Use:                Does padding for message digest functions.
+ */
+
+#define HASH_PAD(PRE, pre, ictx, term, pad, diff) do {                 \
+  pre##_ctx *_pctx = (ictx);                                           \
+                                                                       \
+  _pctx->buf[_pctx->off] = term;                                       \
+  _pctx->off++;                                                                \
+  if (_pctx->off > PRE##_BUFSZ - diff) {                               \
+    if (_pctx->off < PRE##_BUFSZ)                                      \
+      memset(_pctx->buf + _pctx->off, pad, PRE##_BUFSZ - _pctx->off);  \
+    pre##_compress(_pctx, _pctx->buf);                                 \
+    memset(_pctx->buf, pad, PRE##_BUFSZ - diff);                       \
+  } else                                                               \
+    memset(_pctx->buf + _pctx->off, pad,                               \
+          PRE##_BUFSZ - _pctx->off - diff);                            \
+} while (0)
+
+/* --- @HASH_MD5STRENGTH@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for hash-specific definitions
+ *             @ictx@ = pointer to context block for the hash
+ *
+ * Use:                Does MD5-style MD strengthening.  The data is terminated
+ *             by a single set bit, padded with zero bits, and then a 64-
+ *             bit length is written, little-end first.
+ */
+
+#define HASH_MD5STRENGTH(PRE, pre, ictx) do {                          \
+  pre##_ctx *_mctx = (ictx);                                           \
+  HASH_PAD(PRE, pre, _mctx, 0x80u, 0, 8);                              \
+  STORE32_L(_mctx->buf + PRE##_BUFSZ - 8, _mctx->nl << 3);             \
+  STORE32_L(_mctx->buf + PRE##_BUFSZ - 4,                              \
+           (_mctx->nl >> 29) | (_mctx->nh << 3));                      \
+  pre##_compress(_mctx, _mctx->buf);                                   \
+} while (0)
+
+/* --- @HASH_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for hash-specfic definitions
+ *
+ * Use:                Standard test rig for hash functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define HASH_BUFLEN 100000
+
+#define HASH_TEST(PRE, pre)                                            \
+                                                                       \
+static int verify(dstr *v)                                             \
+{                                                                      \
+  pre##_ctx ctx;                                                       \
+  int ok = 1;                                                          \
+  int i;                                                               \
+  octet *p;                                                            \
+  int szs[] = { 1, 7, 192, -1, 0 }, *ip;                               \
+  size_t sz;                                                           \
+  dstr d;                                                              \
+                                                                       \
+  dstr_create(&d);                                                     \
+  dstr_ensure(&d, PRE##_HASHSZ);                                       \
+  d.len = PRE##_HASHSZ;                                                        \
+                                                                       \
+  for (ip = szs; *ip; ip++) {                                          \
+    i = *ip;                                                           \
+    sz = v[0].len;                                                     \
+    if (i == -1)                                                       \
+      i = sz;                                                          \
+    if (i > sz)                                                                \
+      continue;                                                                \
+    p = (octet *)v[0].buf;                                             \
+    pre##_init(&ctx);                                                  \
+    while (sz) {                                                       \
+      if (i > sz)                                                      \
+       i = sz;                                                         \
+      pre##_hash(&ctx, p, i);                                          \
+      p += i;                                                          \
+      sz -= i;                                                         \
+    }                                                                  \
+    pre##_done(&ctx, d.buf);                                           \
+    if (memcmp(d.buf, v[1].buf, PRE##_HASHSZ) != 0) {                  \
+      printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\texpected = ",    \
+            *ip, v[0].buf);                                            \
+      type_hex.dump(&v[1], stdout);                                    \
+      fputs("\n\tcomputed = ", stdout);                                        \
+      type_hex.dump(&d, stdout);                                       \
+      putchar('\n');                                                   \
+      ok = 0;                                                          \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  dstr_destroy(&d);                                                    \
+  return (ok);                                                         \
+}                                                                      \
+                                                                       \
+static int verifyrep(dstr *v)                                          \
+{                                                                      \
+  pre##_ctx ctx;                                                       \
+  size_t len = v[0].len;                                               \
+  int n = *(int *)v[1].buf;                                            \
+  int nd = 0;                                                          \
+  int nn = len;                                                                \
+  int ok = 1;                                                          \
+  octet *p, *q;                                                                \
+  dstr d = DSTR_INIT;                                                  \
+                                                                       \
+  while (nn < HASH_BUFLEN && (n & 1) == 0) { nd++; nn <<= 1; n >>= 1; }        \
+  p = xmalloc(nn);                                                     \
+  memcpy(p, v[0].buf, len);                                            \
+  q = p + len;                                                         \
+  while (nd--) { memcpy(q, p, len); q += len; len <<= 1; }             \
+                                                                       \
+  dstr_ensure(&d, PRE##_HASHSZ);                                       \
+  d.len = PRE##_HASHSZ;                                                        \
+  pre##_init(&ctx);                                                    \
+  while (n--) pre##_hash(&ctx, p, len);                                        \
+  pre##_done(&ctx, d.buf);                                             \
+                                                                       \
+  if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) {                    \
+    printf("\nfail:\n\tinput = `%s'\n\treps = `%i'\n\texpected = ",    \
+            v[0].buf, *(int *)v[1].buf);                               \
+    type_hex.dump(&v[2], stdout);                                      \
+    fputs("\n\tcomputed = ", stdout);                                  \
+    type_hex.dump(&d, stdout);                                         \
+    putchar('\n');                                                     \
+    ok = 0;                                                            \
+  }                                                                    \
+  xfree(p);                                                            \
+  dstr_destroy(&d);                                                    \
+  return (ok);                                                         \
+}                                                                      \
+                                                                       \
+static test_chunk defs[] = {                                           \
+  { #pre, verify, { &type_string, &type_hex, 0 } },                    \
+  { #pre "-rep", verifyrep,                                            \
+    { &type_string, &type_int, &type_hex, 0 } },                       \
+  { 0, 0, { 0 } }                                                      \
+};                                                                     \
+                                                                       \
+int main(int argc, char *argv[])                                       \
+{                                                                      \
+  ego(argv[0]);                                                                \
+  test_run(argc, argv, defs, SRCDIR"/t/" #pre);                                \
+  return (0);                                                          \
+}
+
+#else
+#  define HASH_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/hmac-def.h b/symm/hmac-def.h
new file mode 100644 (file)
index 0000000..032c69f
--- /dev/null
@@ -0,0 +1,442 @@
+/* -*-c-*-
+ *
+ * Definitions for HMAC and NMAC
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_HMAC_DEF_H
+#define CATACOMB_HMAC_DEF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_GMAC_H
+#  include "gmac.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @HMAC_DEF@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying hash function
+ *
+ * Use:                Creates implementations for the HMAC and NMAC functions.
+ */
+
+#define HMAC_DEF(PRE, pre)                                             \
+                                                                       \
+/* --- Useful constants --- */                                         \
+                                                                       \
+const octet pre##_hmackeysz[] = { KSZ_ANY, PRE##_STATESZ };            \
+const octet pre##_sslmackeysz[] = { KSZ_ANY, PRE##_STATESZ };          \
+const octet pre##_nmackeysz[] = { KSZ_SET, 2 * PRE##_STATESZ, 0 };     \
+                                                                       \
+/* --- @pre_nmacinit@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_macctx *key@ = pointer to a MAC key object         \
+ *             @const void *ok@ = pointer to outer hash init vector    \
+ *             @const void *ik@ = pointer to inner hash init vector    \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a MAC key for doing NMAC hashing.           \
+ */                                                                    \
+                                                                       \
+void pre##_nmacinit(pre##_mackey *key, const void *ok, const void *ik) \
+{                                                                      \
+  memcpy(key->ochain, ok, PRE##_STATESZ);                              \
+  memcpy(key->ichain, ik, PRE##_STATESZ);                              \
+  key->ocount = key->icount = 0;                                       \
+}                                                                      \
+                                                                       \
+/* --- @pre_hmacinit@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_mackey *key@ = pointer to MAC key object           \
+ *             @const void *k@ = pointer to key to use                 \
+ *             @size_t sz@ = size of key data                          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a MAC key for doing HMAC hashing.  Keys     \
+ *             longer than the hash function's output size aren't very \
+ *             useful, but are accepted.  Keys longer than the hash's  \
+ *             block size are also accepted; they are hashed before    \
+ *             use, as specified in RFC2104.                           \
+ */                                                                    \
+                                                                       \
+void pre##_hmacinit(pre##_mackey *key, const void *k, size_t sz)       \
+{                                                                      \
+  int i;                                                               \
+  const octet *kbuf = k;                                               \
+  pre##_ctx ctx;                                                       \
+  octet buf[PRE##_HASHSZ];                                             \
+                                                                       \
+  if (sz > PRE##_BUFSZ)        {                                               \
+    pre##_init(&ctx);                                                  \
+    pre##_hash(&ctx, k, sz);                                           \
+    pre##_done(&ctx, buf);                                             \
+    kbuf = buf;                                                                \
+    sz = PRE##_HASHSZ;                                                 \
+  }                                                                    \
+                                                                       \
+  pre##_init(&ctx);                                                    \
+  memset(ctx.buf, 0x5c, PRE##_BUFSZ);                                  \
+  for (i = 0; i < sz; i++)                                             \
+    ctx.buf[i] ^= kbuf[i];                                             \
+  pre##_compress(&ctx, ctx.buf);                                       \
+  pre##_state(&ctx, key->ochain);                                      \
+                                                                       \
+  pre##_init(&ctx);                                                    \
+  memset(ctx.buf, 0x36, PRE##_BUFSZ);                                  \
+  for (i = 0; i < sz; i++)                                             \
+    ctx.buf[i] ^= kbuf[i];                                             \
+  pre##_compress(&ctx, ctx.buf);                                       \
+  pre##_state(&ctx, key->ichain);                                      \
+                                                                       \
+  key->ocount = key->icount = PRE##_BUFSZ;                             \
+  BURN(ctx);                                                           \
+}                                                                      \
+                                                                       \
+/* --- @pre_sslmacinit@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_mackey *key@ = pointer to MAC key object           \
+ *             @const void *k@ = pointer to key to use                 \
+ *             @size_t sz@ = size of key data                          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a MAC key for doing hasing using the SSL3   \
+ *             variant of HMAC.                                        \
+ */                                                                    \
+                                                                       \
+void pre##_sslmacinit(pre##_mackey *key, const void *k, size_t sz)     \
+{                                                                      \
+  const octet *kbuf = k;                                               \
+  pre##_ctx ctx;                                                       \
+  octet buf[PRE##_HASHSZ];                                             \
+                                                                       \
+  if (sz > PRE##_BUFSZ)        {                                               \
+    pre##_init(&ctx);                                                  \
+    pre##_hash(&ctx, k, sz);                                           \
+    pre##_done(&ctx, buf);                                             \
+    kbuf = buf;                                                                \
+    sz = PRE##_HASHSZ;                                                 \
+  }                                                                    \
+                                                                       \
+  pre##_init(&ctx);                                                    \
+  memcpy(ctx.buf, kbuf, sz);                                           \
+  memset(ctx.buf + sz, 0x5c, PRE##_BUFSZ - sz);                                \
+  pre##_compress(&ctx, ctx.buf);                                       \
+  pre##_state(&ctx, key->ochain);                                      \
+                                                                       \
+  pre##_init(&ctx);                                                    \
+  memcpy(ctx.buf, kbuf, sz);                                           \
+  memset(ctx.buf + sz, 0x36, PRE##_BUFSZ - sz);                                \
+  pre##_compress(&ctx, ctx.buf);                                       \
+  pre##_state(&ctx, key->ichain);                                      \
+                                                                       \
+  key->ocount = key->icount = PRE##_BUFSZ;                             \
+  BURN(ctx);                                                           \
+}                                                                      \
+                                                                       \
+/* --- @pre_macinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
+ *             @const pre_mackey *key@ = pointer to MAC key block      \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Instantiates a MAC context from a key block.            \
+ */                                                                    \
+                                                                       \
+void pre##_macinit(pre##_macctx *ctx, const pre##_mackey *key)         \
+{                                                                      \
+  memcpy(ctx->chain, key->ochain, PRE##_STATESZ);                      \
+  ctx->count = key->ocount;                                            \
+  pre##_set(&ctx->ctx, key->ichain, key->icount);                      \
+}                                                                      \
+                                                                       \
+/* --- @pre_machash@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
+ *             @const void *buf@ = pointer to buffer                   \
+ *             @size_t sz@ = size of the buffer                        \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Hashes a buffer.                                        \
+ */                                                                    \
+                                                                       \
+void pre##_machash(pre##_macctx *ctx, const void *buf, size_t sz)      \
+{                                                                      \
+  pre##_hash(&ctx->ctx, buf, sz);                                      \
+}                                                                      \
+                                                                       \
+/* --- @pre_macdone@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
+ *             @void *mac@ = pointer to buffer to receive MAC          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Returns the result of a MAC computation.                \
+ */                                                                    \
+                                                                       \
+void pre##_macdone(pre##_macctx *ctx, void *mac)                       \
+{                                                                      \
+  pre##_done(&ctx->ctx, mac);                                          \
+  pre##_set(&ctx->ctx, ctx->chain, ctx->count);                                \
+  pre##_hash(&ctx->ctx, mac, PRE##_HASHSZ);                            \
+  pre##_done(&ctx->ctx, mac);                                          \
+}                                                                      \
+                                                                       \
+/* --- Generic MAC interface --- */                                    \
+                                                                       \
+static const gmac_ops gkops;                                           \
+static const ghash_ops gops, gnops, gsslops;                           \
+                                                                       \
+typedef struct gkctx {                                                 \
+  gmac m;                                                              \
+  const ghash_ops *gops;                                               \
+  pre##_mackey k;                                                      \
+} gkctx;                                                               \
+                                                                       \
+typedef struct gctx {                                                  \
+  ghash h;                                                             \
+  pre##_macctx c;                                                      \
+  octet buf[PRE##_HASHSZ];                                             \
+} gctx;                                                                        \
+                                                                       \
+static ghash *gkinit(gmac *m)                                          \
+{                                                                      \
+  gkctx *gk = (gkctx *)m;                                              \
+  gctx *g = S_CREATE(gctx);                                            \
+  g->h.ops = gk->gops;                                                 \
+  pre##_macinit(&g->c, &gk->k);                                                \
+  return (&g->h);                                                      \
+}                                                                      \
+                                                                       \
+static gmac *gkey(const void *k, size_t sz)                            \
+{                                                                      \
+  gkctx *gk = S_CREATE(gkctx);                                         \
+  gk->m.ops = &gkops;                                                  \
+  gk->gops = &gops;                                                    \
+  pre##_hmacinit(&gk->k, k, sz);                                       \
+  return (&gk->m);                                                     \
+}                                                                      \
+                                                                       \
+static gmac *gnkey(const void *k, size_t sz)                           \
+{                                                                      \
+  gkctx *gk = S_CREATE(gkctx);                                         \
+  const octet *kk = k;                                                 \
+  assert(keysz(sz, pre##_nmackeysz) == sz);                            \
+  gk->m.ops = &gkops;                                                  \
+  gk->gops = &gnops;                                                   \
+  pre##_nmacinit(&gk->k, kk, kk + PRE##_STATESZ);                      \
+  return (&gk->m);                                                     \
+}                                                                      \
+                                                                       \
+static gmac *gsslkey(const void *k, size_t sz)                         \
+{                                                                      \
+  gkctx *gk = S_CREATE(gkctx);                                         \
+  gk->m.ops = &gkops;                                                  \
+  gk->gops = &gsslops;                                                 \
+  pre##_sslmacinit(&gk->k, k, sz);                                     \
+  return (&gk->m);                                                     \
+}                                                                      \
+                                                                       \
+static void ghhash(ghash *h, const void *p, size_t sz)                 \
+{                                                                      \
+  gctx *g = (gctx *)h;                                                 \
+  pre##_machash(&g->c, p, sz);                                         \
+}                                                                      \
+                                                                       \
+static octet *ghdone(ghash *h, void *buf)                              \
+{                                                                      \
+  gctx *g = (gctx *)h;                                                 \
+  if (!buf)                                                            \
+    buf = g->buf;                                                      \
+  pre##_macdone(&g->c, buf);                                           \
+  return (buf);                                                                \
+}                                                                      \
+                                                                       \
+static ghash *ghcopy(ghash *h)                                         \
+{                                                                      \
+  gctx *g = (gctx *)h;                                                 \
+  gctx *gg = S_CREATE(gctx);                                           \
+  memcpy(gg, g, sizeof(gctx));                                         \
+  return (&gg->h);                                                     \
+}                                                                      \
+                                                                       \
+static void ghdestroy(ghash *h)                                                \
+{                                                                      \
+  gctx *g = (gctx *)h;                                                 \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static void gkdestroy(gmac *m)                                         \
+{                                                                      \
+  gkctx *gk = (gkctx *)m;                                              \
+  BURN(*gk);                                                           \
+  S_DESTROY(gk);                                                       \
+}                                                                      \
+                                                                       \
+static ghash *ghinit(void)                                             \
+{                                                                      \
+  assert(((void)"Attempt to instantiate an unkeyed MAC", 0));          \
+  return (0);                                                          \
+}                                                                      \
+                                                                       \
+const gcmac pre##_nmac =                                               \
+  { #pre "-nmac", PRE##_HASHSZ, pre##_nmackeysz, gnkey };              \
+const gcmac pre##_hmac =                                               \
+  { #pre "-hmac", PRE##_HASHSZ, pre##_hmackeysz, gkey };               \
+const gcmac pre##_sslmac =                                             \
+  { #pre "-sslmac", PRE##_HASHSZ, pre##_sslmackeysz, gsslkey };                \
+static const gmac_ops gkops = { &pre##_hmac, gkinit, gkdestroy };      \
+static const gmac_ops gnkops = { &pre##_nmac, gkinit, gkdestroy };     \
+static const gmac_ops gsslkops = { &pre##_sslmac, gkinit, gkdestroy }; \
+static const gchash gch = { #pre "-hmac", PRE##_HASHSZ, ghinit };      \
+static const ghash_ops gops =                                          \
+  { &gch, ghhash, ghdone, ghdestroy, ghcopy };                         \
+static const gchash gnch = { #pre "-nmac", PRE##_HASHSZ, ghinit };     \
+static const ghash_ops gnops =                                         \
+  { &gch, ghhash, ghdone, ghdestroy, ghcopy };                         \
+static const gchash gsslch = { #pre "-sslmac", PRE##_HASHSZ, ghinit }; \
+static const ghash_ops gsslops =                                       \
+  { &gch, ghhash, ghdone, ghdestroy, ghcopy };                         \
+                                                                       \
+HMAC_TEST(PRE, pre)
+
+/* --- @HMAC_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for hash-specfic definitions
+ *
+ * Use:                Standard test rig for MAC functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define HMAC_TEST(PRE, pre)                                            \
+                                                                       \
+static int macverify(dstr *v)                                          \
+{                                                                      \
+  pre##_macctx cctx;                                                   \
+  pre##_mackey ckey;                                                   \
+  int ok = 1;                                                          \
+  int i;                                                               \
+  octet *p;                                                            \
+  int szs[] = { 1, 7, 192, -1, 0 }, *ip;                               \
+  size_t csz;                                                          \
+  dstr d;                                                              \
+                                                                       \
+  dstr_create(&d);                                                     \
+  dstr_ensure(&d, PRE##_HASHSZ);                                       \
+  d.len = PRE##_HASHSZ;                                                        \
+                                                                       \
+  pre##_hmacinit(&ckey, v[1].buf, v[1].len);                           \
+                                                                       \
+  for (ip = szs; *ip; ip++) {                                          \
+    i = *ip;                                                           \
+    csz = v[0].len;                                                    \
+    if (i == -1)                                                       \
+      i = csz;                                                         \
+    if (i > csz)                                                       \
+      continue;                                                                \
+    p = (octet *)v[0].buf;                                             \
+    pre##_macinit(&cctx, &ckey);                                       \
+    while (csz) {                                                      \
+      if (i > csz)                                                     \
+       i = csz;                                                        \
+      pre##_machash(&cctx, p, i);                                      \
+      p += i;                                                          \
+      csz -= i;                                                                \
+    }                                                                  \
+    pre##_macdone(&cctx, d.buf);                                       \
+    if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) {                  \
+      printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\tkey = ",         \
+            *ip, v[0].buf);                                            \
+      type_hex.dump(&v[1], stdout);                                    \
+      fputs("\n\texpected = ", stdout);                                        \
+      type_hex.dump(&v[2], stdout);                                    \
+      fputs("\n\tcomputed = ", stdout);                                        \
+      type_hex.dump(&d, stdout);                                       \
+      putchar('\n');                                                   \
+      ok = 0;                                                          \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  dstr_destroy(&d);                                                    \
+  return (ok);                                                         \
+}                                                                      \
+                                                                       \
+static test_chunk macdefs[] = {                                                \
+  { #pre "-hmac", macverify,                                           \
+    { &type_string, &type_hex, &type_hex, 0 } },                       \
+  { 0, 0, { 0 } }                                                      \
+};                                                                     \
+                                                                       \
+int main(int argc, char *argv[])                                       \
+{                                                                      \
+  ego(argv[0]);                                                                \
+  test_run(argc, argv, macdefs, SRCDIR"/t/" #pre);                     \
+  return (0);                                                          \
+}
+
+#else
+#  define HMAC_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/hmac.h b/symm/hmac.h
new file mode 100644 (file)
index 0000000..12da5fd
--- /dev/null
@@ -0,0 +1,189 @@
+/* -*-c-*-
+ *
+ * Generic code for HMAC and NMAC
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Notes on the HMAC and NMAC constructions --------------------------*
+ *
+ * Designed by Mihir Bellare, Ran Canetti and Hugo Krawczyk, NMAC is a method
+ * for constructing keyed message authentication algorithms from unkeyed hash
+ * functions.  It has been proven to provide useful security given reasonable
+ * assumptions about the underlying hash function.  HMAC is an alternative
+ * formulation which doesn't require low-level access to the hash function's
+ * implementation.  NMAC was designed to allow MD5 has a suitable underlying
+ * hash function, even though doubts were already being raised about its
+ * collision resistance.
+ */
+
+#ifndef CATACOMB_HMAC_H
+#define CATACOMB_HMAC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GMAC_H
+#  include "gmac.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @HMAC_DECL@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying hash function
+ *
+ * Use:                Creates declarations for the HMAC and NMAC functions.
+ */
+
+#define HMAC_DECL(PRE, pre)                                            \
+                                                                       \
+/* --- An HMAC or NMAC key --- */                                      \
+                                                                       \
+typedef struct pre##_mackey {                                          \
+  octet ochain[PRE##_STATESZ];         /* Chaining for outer hash */   \
+  unsigned ocount;                     /* Byte count for outer hash */ \
+  octet ichain[PRE##_STATESZ];         /* Chaining for inner hash */   \
+  unsigned icount;                     /* Byte count for inner hash */ \
+} pre##_mackey;                                                                \
+                                                                       \
+/* --- An HMAC or NMAC hashing context --- */                          \
+                                                                       \
+typedef struct pre##_macctx {                                          \
+  pre##_ctx ctx;                       /* Context for main hashing */  \
+  octet chain[PRE##_STATESZ];          /* Chaining for outer hash */   \
+  unsigned count;                      /* Byte count for outer hash */ \
+} pre##_macctx;                                                                \
+                                                                       \
+/* --- Other useful constants --- */                                   \
+                                                                       \
+extern const octet pre##_hmackeysz[];                                  \
+extern const octet pre##_nmackeysz[];                                  \
+extern const octet pre##_sslmackeysz[];                                        \
+                                                                       \
+/* --- @pre_nmacinit@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_macctx *key@ = pointer to a MAC key object         \
+ *             @const void *ok@ = pointer to outer hash init vector    \
+ *             @const void *ik@ = pointer to inner hash init vector    \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a MAC key for doing NMAC hashing.           \
+ */                                                                    \
+                                                                       \
+extern void pre##_nmacinit(pre##_mackey */*key*/,                      \
+                          const void */*ok*/, const void */*ik*/);     \
+                                                                       \
+/* --- @pre_hmacinit@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_mackey *key@ = pointer to MAC key object           \
+ *             @const void *k@ = pointer to key to use                 \
+ *             @size_t sz@ = size of key data                          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a MAC key for doing HMAC hashing.  Keys     \
+ *             longer than the hash function's output size aren't very \
+ *             useful, but are accepted.  Keys longer than the hash's  \
+ *             block size are also accepted; they are hashed before    \
+ *             use, as specified in RFC2104.                           \
+ */                                                                    \
+                                                                       \
+extern void pre##_hmacinit(pre##_mackey */*key*/,                      \
+                          const void */*k*/, size_t /*sz*/);           \
+                                                                       \
+/* --- @pre_sslmacinit@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_mackey *key@ = pointer to MAC key object           \
+ *             @const void *k@ = pointer to key to use                 \
+ *             @size_t sz@ = size of key data                          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a MAC key for doing hasing using the SSL3   \
+ *             variant of HMAC.                                        \
+ */                                                                    \
+                                                                       \
+extern void pre##_sslmacinit(pre##_mackey */*key*/,                    \
+                            const void */*k*/, size_t /*sz*/);         \
+                                                                       \
+/* --- @pre_macinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
+ *             @const pre_mackey *key@ = pointer to MAC key block      \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Instantiates a MAC context from a key block.            \
+ */                                                                    \
+                                                                       \
+extern void pre##_macinit(pre##_macctx */*ctx*/,                       \
+                         const pre##_mackey */*key*/);                 \
+                                                                       \
+/* --- @pre_machash@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
+ *             @const void *buf@ = pointer to buffer                   \
+ *             @size_t sz@ = size of the buffer                        \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Hashes a buffer.                                        \
+ */                                                                    \
+                                                                       \
+extern void pre##_machash(pre##_macctx */*ctx*/,                       \
+                         const void */*buf*/, size_t /*sz*/);          \
+                                                                       \
+/* --- @pre_macdone@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_macctx *ctx@ = pointer to MAC context block        \
+ *             @void *mac@ = pointer to buffer to receive MAC          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Returns the result of a MAC computation.                \
+ */                                                                    \
+                                                                       \
+extern void pre##_macdone(pre##_macctx */*ctx*/, void */*mac*/);       \
+                                                                       \
+/* --- Generic MAC interface --- */                                    \
+                                                                       \
+extern const gcmac pre##_hmac;                                         \
+extern const gcmac pre##_nmac;                                         \
+extern const gcmac pre##_sslmac;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/idea.c b/symm/idea.c
new file mode 100644 (file)
index 0000000..51edb2d
--- /dev/null
@@ -0,0 +1,273 @@
+/* -*-c-*-
+ *
+ * Implementation of the IDEA cipher
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "idea.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet idea_keysz[] = { KSZ_SET, IDEA_KEYSZ };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @inv@ --- *
+ *
+ * Arguments:  @uint16 n@ = number to invert
+ *
+ * Returns:    Multiplicative inverse of @n@ %$\pmod{2^{16} + 1}$%.
+ *
+ * Use:                Computes multiplicative inverses.  This is handy for the
+ *             decryption key scheduling.
+ */
+
+static uint16 inv(uint16 n)
+{
+  uint32 m = 0x10001;
+  uint32 a = 1, b = 0;
+  uint32 nn = n;
+
+  if (!nn)
+    nn = 0x10000;
+  for (;;) {
+    uint32 q, r, t;
+    if (!(r = m % nn))
+      break;
+    q = m / nn;
+    m = nn; nn = r;
+    t = a; a = b - q * a; b = t;
+  }
+  if (a > MASK16)
+    a += 1;
+  return (U16(a));
+}
+
+/* --- @MUL@ --- *
+ *
+ * Arguments @x@ and @y@ are two 32-bit values to multiply.  On exit, @x@ is
+ * the product of the two arguments.  The result is not normalized back to 16
+ * bits; the arguments are not expected to be normalized.
+ *
+ * This code is from `Side Channel Attack Hardening of the IDEA Cipher',
+ * published by Ascom Tech.
+ */
+
+#define MUL(x, y) do {                                                 \
+  unsigned _t;                                                         \
+  uint32 _tt;                                                          \
+                                                                       \
+  x = U16(x - 1);                                                      \
+  _t = U16(y - 1);                                                     \
+  _tt = (uint32)x * (uint32)_t + (uint32)x + (uint32)_t + 1;           \
+  x = U16(_tt);                                                                \
+  _t = U16(_tt >> 16);                                                 \
+  x = x - _t + (x <= _t);                                              \
+} while (0)
+
+/* --- @idea_init@ --- *
+ *
+ * Arguments:  @idea_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an IDEA key buffer.  The buffer must be exactly
+ *             16 bytes in size, because IDEA is only defined with a key
+ *             size of 128 bits.
+ */
+
+void idea_init(idea_ctx *k, const void *buf, size_t sz)
+{
+  KSZ_ASSERT(idea, sz);
+
+  /* --- Unpack the encryption key --- */
+
+  {
+    const octet *p = buf;
+    uint16 *q = k->e;
+    uint32 a = LOAD32(p +  0);
+    uint32 b = LOAD32(p +  4);
+    uint32 c = LOAD32(p +  8);
+    uint32 d = LOAD32(p + 12);
+    int i;
+
+    /* --- Main unpacking loop --- */
+
+    for (i = 0; i < 6; i++) {
+
+      /* --- Spit out the next 8 subkeys --- */
+
+      q[0] = U16(a >> 16);
+      q[1] = U16(a >>  0);
+      q[2] = U16(b >> 16);
+      q[3] = U16(b >>  0);
+      q[4] = U16(c >> 16);
+      q[5] = U16(c >>  0);
+      q[6] = U16(d >> 16);
+      q[7] = U16(d >>  0);
+      q += 8;
+
+      /* --- Rotate and permute the subkeys --- */
+
+      {
+       uint32 t = a;
+       a = U32((a << 25) | (b >> 7));
+       b = U32((b << 25) | (c >> 7));
+       c = U32((c << 25) | (d >> 7));
+       d = U32((d << 25) | (t >> 7));
+      }
+    }
+
+    /* --- Write out the tail-enders --- */
+
+    q[0] = U16(a >> 16);
+    q[1] = U16(a >>  0);
+    q[2] = U16(b >> 16);
+    q[3] = U16(b >>  0);
+  }
+
+  /* --- Convert this into the decryption key --- */
+
+  {
+    uint16 *p = k->e + 52;
+    uint16 *q = k->d;
+    int i;
+
+    /* --- Translate the main round keys --- */
+
+    for (i = 0; i < 8; i++) {
+      p -= 6;
+      q[4] = p[0];
+      q[5] = p[1];
+      q[0] = inv(p[2]);
+      q[3] = inv(p[5]);
+      if (i) {
+       q[1] = 0x10000 - p[4];
+       q[2] = 0x10000 - p[3];
+      } else {
+       q[1] = 0x10000 - p[3];
+       q[2] = 0x10000 - p[4];
+      }
+      q += 6;
+    }
+
+    /* --- Translate the tail-enders --- */
+
+    p -= 4;
+    q[0] = inv(p[0]);
+    q[1] = 0x10000 - p[1];
+    q[2] = 0x10000 - p[2];
+    q[3] = inv(p[3]);
+  }
+}
+
+/* --- @ROUND@ --- */
+
+#define MIX(k, a, b, c, d) do {                                                \
+  MUL(a, k[0]);                                                                \
+  b += k[1];                                                           \
+  c += k[2];                                                           \
+  MUL(d, k[3]);                                                                \
+} while (0)
+
+#define MA(k, a, b, c, d) do {                                         \
+  unsigned _u = a ^ c;                                                 \
+  unsigned _v = b ^ d;                                                 \
+  MUL(_u, k[4]);                                                       \
+  _v += _u;                                                            \
+  MUL(_v, k[5]);                                                       \
+  _u += _v;                                                            \
+  a ^= _v;                                                             \
+  b ^= _u;                                                             \
+  c ^= _v;                                                             \
+  d ^= _u;                                                             \
+} while (0);
+
+#define ROUND(k, a, b, c, d) do {                                      \
+  MIX(k, a, b, c, d);                                                  \
+  MA(k, a, b, c, d);                                                   \
+  (k) += 6;                                                            \
+} while (0)
+
+/* --- Encryption --- */
+
+#define EBLK(k, a, b, c, d) do {                                       \
+  unsigned _a = U16(a >> 16);                                          \
+  unsigned _b = U16(a >>  0);                                          \
+  unsigned _c = U16(b >> 16);                                          \
+  unsigned _d = U16(b >>  0);                                          \
+  const uint16 *_k = (k);                                              \
+                                                                       \
+  ROUND(_k, _a, _b, _c, _d);                                           \
+  ROUND(_k, _a, _c, _b, _d);                                           \
+  ROUND(_k, _a, _b, _c, _d);                                           \
+  ROUND(_k, _a, _c, _b, _d);                                           \
+  ROUND(_k, _a, _b, _c, _d);                                           \
+  ROUND(_k, _a, _c, _b, _d);                                           \
+  ROUND(_k, _a, _b, _c, _d);                                           \
+  ROUND(_k, _a, _c, _b, _d);                                           \
+  MIX  (_k, _a, _c, _b, _d);                                           \
+  c = ((uint32)U16(_a) << 16) | (uint32)U16(_c);                       \
+  d = ((uint32)U16(_b) << 16) | (uint32)U16(_d);                       \
+} while (0)
+
+#define DBLK(k, a, b) EBLK((k), (a), (b))
+
+/* --- @idea_eblk@, @idea_dblk@ --- *
+ *
+ * Arguments:  @const idea_ctx *k@ = pointer to a key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+void idea_eblk(const idea_ctx *k, const uint32 *s, uint32 *d)
+{
+  EBLK(k->e, s[0], s[1], d[0], d[1]);
+}
+
+void idea_dblk(const idea_ctx *k, const uint32 *s, uint32 *d)
+{
+  EBLK(k->d, s[0], s[1], d[0], d[1]);
+}
+
+BLKC_TEST(IDEA, idea)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/idea.h b/symm/idea.h
new file mode 100644 (file)
index 0000000..a25a82a
--- /dev/null
@@ -0,0 +1,111 @@
+/* -*-c-*-
+ *
+ * Implementation of the IDEA cipher
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on the IDEA block cipher ------------------------------------*
+ *
+ * IDEA was invented by James Massey and Xuejia Lai.  The fundamental idea
+ * underlying the cipher is combining incompatible group operations.  The
+ * algorithm's main claim to fame is that it is the symmetric cipher in PGP
+ * version 2.
+ *
+ * The IDEA algorithm is allegedly patented by Ascom Tech A.G., even in the
+ * UK and Europe.  Ascom are willing to grant licences for use in software
+ * which forbids commercial use, but this is not compatible with Free
+ * Software Foundation ideology.  The author recommends against the use of
+ * the IDEA cipher entirely.  Blowfish is conceptually simpler, appears more
+ * concervative, offers a larger keyspace, runs faster, and is in the public
+ * domain.
+ */
+
+#ifndef CATACOMB_IDEA_H
+#define CATACOMB_IDEA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define IDEA_BLKSZ 8
+#define IDEA_KEYSZ 16
+#define IDEA_CLASS (N, B, 64)
+
+extern const octet idea_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct idea_ctx {
+  uint16 e[52];
+  uint16 d[52];
+} idea_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @idea_init@ --- *
+ *
+ * Arguments:  @idea_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an IDEA key buffer.  The buffer must be exactly
+ *             16 bytes in size, because IDEA is only defined with a key
+ *             size of 128 bits.
+ */
+
+extern void idea_init(idea_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @idea_eblk@, @idea_dblk@ --- *
+ *
+ * Arguments:  @const idea_ctx *k@ = pointer to a key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void idea_eblk(const idea_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+extern void idea_dblk(const idea_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/mars-mktab.c b/symm/mars-mktab.c
new file mode 100644 (file)
index 0000000..750f727
--- /dev/null
@@ -0,0 +1,315 @@
+/* -*-c-*-
+ *
+ * Generate the MARS S-box table
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "sha.h"
+
+/*----- SHA-1 (quick version) ---------------------------------------------*/
+
+/* --- @sha_compress@ --- *
+ *
+ * Arguments:  @sha_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA-1 compression function.
+ */
+
+void sha_compress(sha_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d, e;
+  uint32 buf[80];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = ctx->a;
+  b = ctx->b;
+  c = ctx->c;
+  d = ctx->d;
+  e = ctx->e;
+
+  /* --- Fetch and expand the buffer contents --- */
+
+  {
+    int i;
+    const octet *p;
+
+    for (i = 0, p = sbuf; i < 16; i++, p += 4)
+      buf[i] = LOAD32(p);
+    for (i = 16; i < 80; i++) {
+      uint32 x = buf[i - 3] ^ buf[i - 8] ^ buf[i - 14] ^ buf[i - 16];
+      buf[i] = ROL32(x, 1);
+    }
+  }
+
+  /* --- 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) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+
+#define T(v, w, x, y, z, i, f, k) do {                                 \
+  uint32 _x;                                                           \
+  z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k;                       \
+  w = ROR32(w, 2);                                                     \
+  _x = v; v = z; z = y; y = x; x = w; w = _x;                          \
+} while (0)
+
+#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999)
+#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1)
+#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc)
+#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6)
+
+  /* --- The main compression function --- */
+
+  {
+    unsigned i;
+    for (i = 0; i < 20; i++)
+      FF(a, b, c, d, e, i);
+    for (i = 20; i < 40; i++)
+      GG(a, b, c, d, e, i);
+    for (i = 40; i < 60; i++)
+      HH(a, b, c, d, e, i);
+    for (i = 60; i < 80; i++)
+      II(a, b, c, d, e, i);
+  }
+
+  ctx->a += a;
+  ctx->b += b;
+  ctx->c += c;
+  ctx->d += d;
+  ctx->e += e;
+}
+
+/* --- @sha_init@ --- *
+ *
+ * Arguments:  @sha_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void sha_init(sha_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;
+}
+
+/* --- @sha_hash@ --- *
+ *
+ * Arguments:  @sha_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 sha_hash(sha_ctx *ctx, const void *buf, size_t sz)
+{
+  sha_ctx *_bctx = (ctx);
+  size_t _bsz = (sz);
+  const octet *_bbuf = (octet *) (buf);
+
+  {
+    uint32 _l = ((uint32) ((_bsz) & MASK32));
+    uint32 _h = ((_bsz & ~MASK32) >> 16) >> 16;
+    _bctx->nh += _h;
+    _bctx->nl += _l;
+    if (_bctx->nl < _l || _bctx->nl & ~MASK32)
+      _bctx->nh++;
+  }
+  if (_bctx->off + _bsz < SHA_BUFSZ) {
+    memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz);
+    _bctx->off += _bsz;
+  } else {
+    if (_bctx->off) {
+      size_t s = SHA_BUFSZ - _bctx->off;
+      memcpy(_bctx->buf + _bctx->off, _bbuf, s);
+      sha_compress(_bctx, _bctx->buf);
+      _bsz -= s;
+      _bbuf += s;
+    }
+    while (_bsz >= SHA_BUFSZ) {
+      sha_compress(_bctx, _bbuf);
+      _bsz -= SHA_BUFSZ;
+      _bbuf += SHA_BUFSZ;
+    }
+    if (_bsz)
+      memcpy(_bctx->buf, _bbuf, _bsz);
+    _bctx->off = _bsz;
+  }
+}
+
+/* --- @sha_done@ --- *
+ *
+ * Arguments:  @sha_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void sha_done(sha_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  {
+    sha_ctx *_pctx = (ctx);
+    _pctx->buf[_pctx->off] = 0x80;
+    _pctx->off++;
+    if (_pctx->off > SHA_BUFSZ - 8) {
+      if (_pctx->off < SHA_BUFSZ)
+       memset(_pctx->buf + _pctx->off, 0, SHA_BUFSZ - _pctx->off);
+      sha_compress(_pctx, _pctx->buf);
+      memset(_pctx->buf, 0, SHA_BUFSZ - 8);
+    } else
+      memset(_pctx->buf + _pctx->off, 0, SHA_BUFSZ - _pctx->off - 8);
+  }
+  STORE32(ctx->buf + SHA_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3));
+  STORE32(ctx->buf + SHA_BUFSZ - 4, ctx->nl << 3);
+  sha_compress(ctx, ctx->buf);
+  STORE32(p +  0, ctx->a);
+  STORE32(p +  4, ctx->b);
+  STORE32(p +  8, ctx->c);
+  STORE32(p + 12, ctx->d);
+  STORE32(p + 16, ctx->e);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+static void mks(uint32 c3, uint32 *s)
+{
+  octet ibuf[16], obuf[20];
+  sha_ctx h;
+  unsigned i, j;
+
+  STORE32_L(ibuf +  4, 0xb7e15162);
+  STORE32_L(ibuf +  8, 0x243f6a88);
+  STORE32_L(ibuf + 12, c3);
+
+  for (i = 0; i < 510; i += 5) {
+    STORE32_L(ibuf, i);
+    sha_init(&h);
+    sha_hash(&h, ibuf, sizeof(ibuf));
+    sha_done(&h, obuf);
+    for (j = 0; j < 5; j++)
+      *s++ = LOAD32_L(obuf + (4 * j));
+  }
+  STORE32_L(ibuf, i);
+  sha_init(&h);
+  sha_hash(&h, ibuf, sizeof(ibuf));
+  sha_done(&h, obuf);
+  for (j = 0; i < 512; j++, i++)
+    *s++ = LOAD32_L(obuf + (4 * j));
+}
+
+static void fix(uint32 *s)
+{
+  unsigned i, j, n;
+  uint32 d;
+
+  for (i = 0; i < 512; i++) {
+    for (j = i & ~255u; j < ((i + 255) & ~255u); j++) {
+      if (i == j)
+       continue;
+      d = s[i] ^ s[j];
+      n = 0;
+      if (!(d & 0xff000000)) n++;
+      if (!(d & 0x00ff0000)) n++;
+      if (!(d & 0x0000ff00)) n++;
+      if (!(d & 0x000000ff)) n++;
+      if (n >= 2) {
+       s[i] = U32(s[i] * 3);
+       goto fixed;
+      }
+    }
+  fixed:;
+  }
+}
+
+int main(void)
+{
+  uint32 s[512];
+  unsigned i;
+
+  mks(0x02917d59, s);
+  fix(s);
+
+  puts("\
+/* -*-c-*-\n\
+ *\n\
+ * MARS tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_MARS_TAB_H\n\
+#define CATACOMB_MARS_TAB_H\n\
+");
+
+  fputs("\
+/* --- The S-box --- */\n\
+\n\
+#define MARS_S {                                                       \\\n\
+  ", stdout);
+  for (i = 0; i < 512; i++) {
+    printf("0x%08lx", (unsigned long)s[i]);
+    if (i == 511)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 4 == 3)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  puts("#endif");
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/mars.c b/symm/mars.c
new file mode 100644 (file)
index 0000000..6f73b42
--- /dev/null
@@ -0,0 +1,264 @@
+/* -*-c-*-
+ *
+ * The MARS block cipher
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "mars.h"
+#include "mars-tab.h"
+#include "paranoia.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet mars_keysz[] = { KSZ_RANGE, MARS_KEYSZ, 0, 56, 4 };
+
+/*----- Useful tables -----------------------------------------------------*/
+
+static const uint32 s[512] = MARS_S;
+#define s0 (s +          0)
+#define s1 (s + 256)
+#define bb (s + 265)
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mars_init@ --- *
+ *
+ * Arguments:  @mars_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a MARS key buffer.  MARS accepts key sizes
+ *             between 128 and 448 bits which are a multiple of 32 bits.
+ */
+
+void mars_init(mars_ctx *k, const void *buf, size_t sz)
+{
+  uint32 t[15];
+  uint32 *kk = k->k;
+  const octet *p;
+  unsigned i, j, ii;
+
+  KSZ_ASSERT(mars, sz);
+
+  /* --- Copy the key into the temporary buffer --- */
+
+  p = buf;
+  for (i = 0; i < sz/4; i++) {
+    t[i] = LOAD32_L(p);
+    p += 4;
+  }
+  t[i++] = sz/4;
+  for (; i < 15; i++)
+    t[i] = 0;
+
+  /* --- Now spit out the actual key material --- */
+
+  for (j = 0; j < 4; j++) {
+    uint32 x;
+
+    /* --- Do the linear mixing stage --- */
+
+    for (i = 0; i < 15; i++) {
+      x = t[(i + 8)%15] ^ t[(i + 13)%15];
+      t[i] ^= ROL32(x, 3) ^ ((i << 2) | j);
+    }
+
+    /* --- Now do the Feistel stirring stage --- */
+
+    x = t[14];
+    for (ii = 0; ii < 4; ii++) {
+      for (i = 0; i < 15; i++) {
+       x = t[i] + s[x & 511u];
+       t[i] = x = ROL32(x, 9);
+      }
+    }
+
+    /* --- And spit out the key material --- */
+
+    for (i = 0; i < 10; i++)
+      *kk++ = t[(4 * i)%15];
+  }
+
+  /* --- Finally, fix up the multiplicative entries --- */
+
+  for (i = 5; i < 37; i += 2) {
+    uint32 w, m, x;
+    j = k->k[i] & 3u;
+    w = k->k[i] | 3u;
+
+    /* --- Compute the magic mask value --- */
+
+    m = 0;
+    for (ii = 0; ii <= 22; ii++) {
+      x = w >> ii;
+      if ((x & 0x3ff) == 0x3ff || (x & 0x3ff) == 0)
+       m |= 0x3ff << ii;
+    }
+    m &= ~(((w ^ (w << 1)) | (w ^ (w >> 1))) | 0x80000003);
+
+    /* --- Add in the bias entry to fix up the key --- */
+
+    x = ROL32(bb[j], k->k[i - 1]);
+    k->k[i] = w ^ (x & m);
+  }
+}
+
+/* --- @mars_eblk@, @mars_dblk@ --- *
+ *
+ * Arguments:  @const mars_ctx *k@ = pointer to key block
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define KADD(k, a, b, c, d)  a += *k++, b += *k++, c += *k++, d += *k++
+#define KSUB(k, a, b, c, d)  a -= *k++, b -= *k++, c -= *k++, d -= *k++
+#define IKADD(k, a, b, c, d) d += *--k, c += *--k, b += *--k, a += *--k
+#define IKSUB(k, a, b, c, d) d -= *--k, c -= *--k, b -= *--k, a -= *--k
+
+#define MIX(a, b, c, d) do {                                           \
+  b ^= s0[(a >>         0) & 0xff];                                            \
+  b += s1[(a >>         8) & 0xff];                                            \
+  c += s0[(a >> 16) & 0xff];                                           \
+  d ^= s1[(a >> 24) & 0xff];                                           \
+  a = ROL32(a, 8);                                                     \
+} while (0)
+
+#define IMIX(a, b, c, d) do {                                          \
+  a = ROR32(a, 8);                                                     \
+  d ^= s1[(a >> 24) & 0xff];                                           \
+  c -= s0[(a >> 16) & 0xff];                                           \
+  b -= s1[(a >>         8) & 0xff];                                            \
+  b ^= s0[(a >>         0) & 0xff];                                            \
+} while (0)
+
+#define E(x, y, z, k, a) do {                                          \
+  uint32 kx = *k++, ky = *k++;                                         \
+  y = a + kx;                                                          \
+  a = ROL32(a, 13); z = a * ky; z = ROL32(z, 5);                       \
+  x = s[y & 511u] ^ z; y = ROL32(y, z);                                        \
+  z = ROL32(z, 5); x ^= z; x = ROL32(x, z);                            \
+} while (0)
+
+#define IE(x, y, z, k, a) do {                                         \
+  uint32 ky = *--k, kx = *--k;                                         \
+  z = a * ky;                                                          \
+  a = ROR32(a, 13); y = a + kx; z = ROL32(z, 5);                       \
+  x = s[y & 511u] ^ z; y = ROL32(y, z);                                        \
+  z = ROL32(z, 5); x ^= z; x = ROL32(x, z);                            \
+} while (0)
+
+#define ROUND(k, a, b, c, d) do {                                      \
+  uint32 x, y, z;                                                      \
+  E(x, y, z, k, a);                                                    \
+  b += x; c += y; d ^= z;                                              \
+} while (0)
+
+#define IROUND(k, a, b, c, d) do {                                     \
+  uint32 x, y, z;                                                      \
+  IE(x, y, z, k, a);                                                   \
+  b -= x; c -= y; d ^= z;                                              \
+} while (0)
+
+void mars_eblk(const mars_ctx *k, const uint32 *src, uint32 *dst)
+{
+  uint32 a, b, c, d;
+  const uint32 *kk = k->k;
+
+  a = src[0], b = src[1], c = src[2], d = src[3];
+  KADD(kk, a, b, c, d);
+
+  MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c;
+  MIX(c, d, a, b); MIX(d, a, b, c);
+  MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c;
+  MIX(c, d, a, b); MIX(d, a, b, c);
+
+  ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a);
+  ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c);
+  ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a);
+  ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c);
+
+  ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c);
+  ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a);
+  ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c);
+  ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a);
+
+  IMIX(a, d, c, b); IMIX(b, a, d, c);
+  c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a);
+  IMIX(a, d, c, b); IMIX(b, a, d, c);
+  c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a);
+
+  KSUB(kk, a, b, c, d);
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+}
+
+void mars_dblk(const mars_ctx *k, const uint32 *src, uint32 *dst)
+{
+  uint32 a, b, c, d;
+  const uint32 *kk = k->k + 40;
+
+  a = src[0], b = src[1], c = src[2], d = src[3];
+  IKADD(kk, a, b, c, d);
+
+  MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b;
+  MIX(b, a, d, c); MIX(a, d, c, b);
+  MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b;
+  MIX(b, a, d, c); MIX(a, d, c, b);
+
+  IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d);
+  IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b);
+  IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d);
+  IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b);
+
+  IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b);
+  IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d);
+  IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b);
+  IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d);
+
+  IMIX(d, a, b, c); IMIX(c, d, a, b);
+  b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d);
+  IMIX(d, a, b, c); IMIX(c, d, a, b);
+  b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d);
+
+  IKSUB(kk, a, b, c, d);
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+}
+
+BLKC_TEST(MARS, mars)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/mars.h b/symm/mars.h
new file mode 100644 (file)
index 0000000..f13f8a8
--- /dev/null
@@ -0,0 +1,104 @@
+/* -*-c-*-
+ *
+ * The MARS block cipher
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Notes on the MARS block cipher ------------------------------------*
+ *
+ * MARS was IBM's submission to the AES contest.  It was designed by a number
+ * of clever people at the T. J. Watson labs, and made it to the second round
+ * of the contest.  Unfortunately, MARS is rather messy.  There are some
+ * awkward corner cases in the key schedule algorithm, for example, that show
+ * up very rarely.
+ */
+
+#ifndef CATACOMB_MARS_H
+#define CATACOMB_MARS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define MARS_BLKSZ 16
+#define MARS_KEYSZ 32
+#define MARS_CLASS (N, L, 128)
+
+extern const octet mars_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct mars_ctx {
+  uint32 k[40];
+} mars_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @mars_init@ --- *
+ *
+ * Arguments:  @mars_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a MARS key buffer.  MARS accepts key sizes
+ *             between 128 and 448 bits which are a multiple of 32 bits.
+ */
+
+extern void mars_init(mars_ctx */*k*/,
+                     const void */*buf*/, size_t /*sz*/);
+
+/* --- @mars_eblk@, @mars_dblk@ --- *
+ *
+ * Arguments:  @const mars_ctx *k@ = pointer to key block
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void mars_eblk(const mars_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+
+extern void mars_dblk(const mars_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/md2-tab.h b/symm/md2-tab.h
new file mode 100644 (file)
index 0000000..3e1b2e9
--- /dev/null
@@ -0,0 +1,78 @@
+/* -*-c-*-
+ *
+ * Tables for MD2
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_MD2_TAB_H
+#define CATACOMB_MD2_TAB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- S-box table -------------------------------------------------------*/
+
+#define MD2_S {                                                                \
+  0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01,                      \
+  0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13,                      \
+  0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c,                      \
+  0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca,                      \
+  0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16,                      \
+  0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,                      \
+  0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49,                      \
+  0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a,                      \
+  0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f,                      \
+  0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21,                      \
+  0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27,                      \
+  0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,                      \
+  0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1,                      \
+  0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6,                      \
+  0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6,                      \
+  0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1,                      \
+  0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,                      \
+  0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,                      \
+  0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6,                      \
+  0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f,                      \
+  0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a,                      \
+  0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26,                      \
+  0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09,                      \
+  0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,                      \
+  0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa,                      \
+  0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a,                      \
+  0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d,                      \
+  0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39,                      \
+  0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4,                      \
+  0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,                      \
+  0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a,                      \
+  0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14                       \
+}
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/md2.c b/symm/md2.c
new file mode 100644 (file)
index 0000000..180bc65
--- /dev/null
@@ -0,0 +1,221 @@
+/* -*-c-*-
+ *
+ * The MD2 message digest function
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "md2.h"
+#include "md2-tab.h"
+
+/*----- Tables ------------------------------------------------------------*/
+
+static const octet s[256] = MD2_S;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @md2_compress@ --- *
+ *
+ * Arguments:  @md2_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                MD2 compression and checksum function.
+ */
+
+void md2_compress(md2_ctx *ctx, const void *sbuf)
+{
+  unsigned i;
+  unsigned t;
+  octet x[MD2_BUFSZ];
+  octet y[MD2_BUFSZ];
+
+  /* --- Handy macro for doing something lots of times --- */
+
+#define DO(what, where) do {                                           \
+  what(where,  0); what(where, 1); what(where,  2); what(where,  3);   \
+  what(where,  4); what(where, 5); what(where,  6); what(where,  7);   \
+  what(where,  8); what(where, 9); what(where, 10); what(where, 11);   \
+  what(where, 12); what(where, 13); what(where, 14); what(where, 15);  \
+} while (0)
+
+  /* --- Do the hashing first to avoid corrupting the checksum --- */
+
+  memcpy(x, sbuf, sizeof(x));
+#define X(z, i) y[i] = z[i] ^ ctx->h[i]
+  DO(X, x);
+#undef X
+
+  t = 0;
+  for (i = 0; i < 18; i++) {
+#define X(z, i) t = z[i] ^= s[t];
+    DO(X, ctx->h);
+    DO(X, x);
+    DO(X, y);
+#undef X
+    t = U8(t + i);
+  }
+
+  /* --- Now compute the checksum --- */
+
+  t = ctx->c[MD2_BUFSZ - 1];
+#define X(z, i) t = ctx->c[i] ^= s[z[i] ^ t]
+  DO(X, ((const octet *)sbuf));
+#undef X
+
+#undef DO
+}
+
+/* --- @md2_init@ --- *
+ *
+ * Arguments:  @md2_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void md2_init(md2_ctx *ctx)
+{
+  memset(ctx->c, 0, sizeof(ctx->c));
+  memset(ctx->h, 0, sizeof(ctx->h));
+  ctx->off = 0;
+}
+
+/* --- @md2_set@ --- *
+ *
+ * Arguments:  @md2_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 md2_set(md2_ctx *ctx, const void *buf, unsigned long count)
+{
+  const octet *p = buf;
+  memcpy(ctx->h, p, MD2_BUFSZ);
+  memcpy(ctx->c, p + MD2_BUFSZ, MD2_BUFSZ);
+  ctx->off = 0;
+}
+
+/* --- @md2_hash@ --- *
+ *
+ * Arguments:  @md2_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 md2_hash(md2_ctx *ctx, const void *buf, size_t sz)
+{
+  const octet *bbuf = (octet *)buf;
+
+  /* --- Code automatically expanded from @HASH_BUFFER@ and tidied --- */
+
+  if (ctx->off + sz < MD2_BUFSZ) {
+    memcpy(ctx->buf + ctx->off, bbuf, sz);
+    ctx->off += sz;
+  } else {
+    if (ctx->off) {
+      size_t s = MD2_BUFSZ - ctx->off;
+      memcpy(ctx->buf + ctx->off, bbuf, s);
+      md2_compress(ctx, ctx->buf);
+      sz -= s;
+      bbuf += s;
+    }
+    while (sz >= MD2_BUFSZ) {
+      md2_compress(ctx, bbuf);
+      sz -= MD2_BUFSZ; bbuf += MD2_BUFSZ;
+    }
+    if (sz)
+      memcpy(ctx->buf, bbuf, sz);
+    ctx->off = sz;
+  }
+}
+
+/* --- @md2_done@ --- *
+ *
+ * Arguments:  @md2_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void md2_done(md2_ctx *ctx, void *hash)
+{
+  unsigned pad = MD2_BUFSZ - ctx->off;
+  unsigned i;
+  for (i = ctx->off; i < MD2_BUFSZ; i++)
+    ctx->buf[i] = pad;
+  md2_compress(ctx, ctx->buf);
+  md2_compress(ctx, ctx->c);
+  memcpy(hash, ctx->h, MD2_BUFSZ);
+}
+
+/* --- @md2_state@ --- *
+ *
+ * Arguments:  @md2_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 @md2_set@.
+ */
+
+unsigned long md2_state(md2_ctx *ctx, void *state)
+{
+  octet *p = state;
+  memcpy(p, ctx->h, MD2_BUFSZ);
+  memcpy(p + MD2_BUFSZ, ctx->c, MD2_BUFSZ);
+  return (0);
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(MD2, md2)
+
+/* --- Test code --- */
+
+HASH_TEST(MD2, md2)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/md2.h b/symm/md2.h
new file mode 100644 (file)
index 0000000..26a1f2a
--- /dev/null
@@ -0,0 +1,156 @@
+/* -*-c-*-
+ *
+ * The MD2 message digest function
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Notes on the MD2 hash function ------------------------------------*
+ *
+ * MD2 was designed by Ron Rivest.  It's not recommended for new applications
+ * because only the `checksum' part of the function resists collision-finding
+ * attacks.  It's not very fast either.  However, it's still used in
+ * standards, and having it available can be useful.
+ */
+
+#ifndef CATACOMB_MD2_H
+#define CATACOMB_MD2_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define MD2_BUFSZ 16
+#define MD2_HASHSZ 16
+#define MD2_STATESZ 32
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct md2_ctx {
+  octet c[MD2_BUFSZ];                  /* Checksum buffer */
+  octet h[MD2_BUFSZ];                  /* Hash result buffer */
+  octet buf[MD2_BUFSZ];                        /* Input buffer */
+  unsigned off;                                /* Offset into buffer */
+} md2_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @md2_compress@ --- *
+ *
+ * Arguments:  @md2_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                MD2 compression function.
+ */
+
+extern void md2_compress(md2_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @md2_init@ --- *
+ *
+ * Arguments:  @md2_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void md2_init(md2_ctx */*ctx*/);
+
+/* --- @md2_set@ --- *
+ *
+ * Arguments:  @md2_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 md2_set(md2_ctx */*ctx*/, const void */*buf*/,
+                   unsigned long /*count*/);
+
+/* --- @md2_hash@ --- *
+ *
+ * Arguments:  @md2_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 md2_hash(md2_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @md2_done@ --- *
+ *
+ * Arguments:  @md2_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 md2_done(md2_ctx */*ctx*/, void */*hash*/);
+
+/* --- @md2_state@ --- *
+ *
+ * Arguments:  @md2_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 @md2_set@.
+ */
+
+extern unsigned long md2_state(md2_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash md2;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/md4.c b/symm/md4.c
new file mode 100644 (file)
index 0000000..eee5d6b
--- /dev/null
@@ -0,0 +1,257 @@
+/* -*-c-*-
+ *
+ * The MD4 message digest function
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "md4.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @md4_compress@ --- *
+ *
+ * Arguments:  @md4_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-160 compression function.
+ */
+
+void md4_compress(md4_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d;
+  uint32 buf[16];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = ctx->a;
+  b = ctx->b;
+  c = ctx->c;
+  d = ctx->d;
+
+  /* --- 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)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+#define T(w, x, y, z, i, r, k, f) do {                                 \
+  uint32 _t = w + f(x, y, z) + buf[i] + k;                             \
+  w = ROL32(_t, r);                                                    \
+} while (0)
+
+#define FF(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x00000000, F)
+#define GG(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x5a827999, G)
+#define HH(w, x, y, z, i, r) T(w, x, y, z, i, r, 0x6ed9eba1, H)
+
+  /* --- The main compression function --- */
+
+  FF(a, b, c, d,  0,  3);
+  FF(d, a, b, c,  1,  7);
+  FF(c, d, a, b,  2, 11);
+  FF(b, c, d, a,  3, 19);
+  FF(a, b, c, d,  4,  3);
+  FF(d, a, b, c,  5,  7);
+  FF(c, d, a, b,  6, 11);
+  FF(b, c, d, a,  7, 19);
+  FF(a, b, c, d,  8,  3);
+  FF(d, a, b, c,  9,  7);
+  FF(c, d, a, b, 10, 11);
+  FF(b, c, d, a, 11, 19);
+  FF(a, b, c, d, 12,  3);
+  FF(d, a, b, c, 13,  7);
+  FF(c, d, a, b, 14, 11);
+  FF(b, c, d, a, 15, 19);
+
+  GG(a, b, c, d,  0,  3);
+  GG(d, a, b, c,  4,  5);
+  GG(c, d, a, b,  8,  9);
+  GG(b, c, d, a, 12, 13);
+  GG(a, b, c, d,  1,  3);
+  GG(d, a, b, c,  5,  5);
+  GG(c, d, a, b,  9,  9);
+  GG(b, c, d, a, 13, 13);
+  GG(a, b, c, d,  2,  3);
+  GG(d, a, b, c,  6,  5);
+  GG(c, d, a, b, 10,  9);
+  GG(b, c, d, a, 14, 13);
+  GG(a, b, c, d,  3,  3);
+  GG(d, a, b, c,  7,  5);
+  GG(c, d, a, b, 11,  9);
+  GG(b, c, d, a, 15, 13);
+
+  HH(a, b, c, d,  0,  3);
+  HH(d, a, b, c,  8,  9);
+  HH(c, d, a, b,  4, 11);
+  HH(b, c, d, a, 12, 15);
+  HH(a, b, c, d,  2,  3);
+  HH(d, a, b, c, 10,  9);
+  HH(c, d, a, b,  6, 11);
+  HH(b, c, d, a, 14, 15);
+  HH(a, b, c, d,  1,  3);
+  HH(d, a, b, c,  9,  9);
+  HH(c, d, a, b,  5, 11);
+  HH(b, c, d, a, 13, 15);
+  HH(a, b, c, d,  3,  3);
+  HH(d, a, b, c, 11,  9);
+  HH(c, d, a, b,  7, 11);
+  HH(b, c, d, a, 15, 15);
+
+  /* --- Update the chaining variables --- */
+
+  ctx->a += a;
+  ctx->b += b;
+  ctx->c += c;
+  ctx->d += d;
+}
+
+/* --- @md4_init@ --- *
+ *
+ * Arguments:  @md4_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void md4_init(md4_ctx *ctx)
+{
+  ctx->a = 0x67452301;
+  ctx->b = 0xefcdab89;
+  ctx->c = 0x98badcfe;
+  ctx->d = 0x10325476;
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+/* --- @md4_set@ --- *
+ *
+ * Arguments:  @md4_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 md4_set(md4_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->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @md4_hash@ --- *
+ *
+ * Arguments:  @md4_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 md4_hash(md4_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(MD4, md4, ctx, buf, sz);
+}
+
+/* --- @md4_done@ --- *
+ *
+ * Arguments:  @md4_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void md4_done(md4_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_MD5STRENGTH(MD4, md4, 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);
+}
+
+/* --- @md4_state@ --- *
+ *
+ * Arguments:  @md4_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 @md4_set@.
+ */
+
+unsigned long md4_state(md4_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);
+  return (ctx->nl | ((ctx->nh >> 16) >> 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(MD4, md4)
+
+/* --- Test rig --- */
+
+HASH_TEST(MD4, md4)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/md4.h b/symm/md4.h
new file mode 100644 (file)
index 0000000..29ca730
--- /dev/null
@@ -0,0 +1,157 @@
+/* -*-c-*-
+ *
+ * The MD4 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Notes on the MD4 hash function ------------------------------------*
+ *
+ * MD4 was designed by Ron Rivest.  It's now well and truly broken: not only
+ * have collisions been discovered, a slightly cut-down version has been
+ * shown to be non-preimage-resistant.  On the other hand, MD4 is fast and
+ * makes a good heavy-duty checksum.  Just don't rely on it being
+ * cryptographically strong, 'cos it ain't.
+ */
+
+#ifndef CATACOMB_MD4_H
+#define CATACOMB_MD4_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define MD4_BUFSZ 64
+#define MD4_HASHSZ 16
+#define MD4_STATESZ 16
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct md4_ctx {
+  uint32 a, b, c, d;                   /* Chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[MD4_BUFSZ];                        /* Accumulation buffer */
+} md4_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @md4_compress@ --- *
+ *
+ * Arguments:  @md4_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                MD4 compression function.
+ */
+
+extern void md4_compress(md4_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @md4_init@ --- *
+ *
+ * Arguments:  @md4_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void md4_init(md4_ctx */*ctx*/);
+
+/* --- @md4_set@ --- *
+ *
+ * Arguments:  @md4_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 md4_set(md4_ctx */*ctx*/, const void */*buf*/,
+                   unsigned long /*count*/);
+
+/* --- @md4_hash@ --- *
+ *
+ * Arguments:  @md4_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 md4_hash(md4_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @md4_done@ --- *
+ *
+ * Arguments:  @md4_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 md4_done(md4_ctx */*ctx*/, void */*hash*/);
+
+/* --- @md4_state@ --- *
+ *
+ * Arguments:  @md4_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 @md4_set@.
+ */
+
+extern unsigned long md4_state(md4_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash md4;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/md5.c b/symm/md5.c
new file mode 100644 (file)
index 0000000..f3b37e1
--- /dev/null
@@ -0,0 +1,276 @@
+/* -*-c-*-
+ *
+ * The MD5 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "md5.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @md5_compress@ --- *
+ *
+ * Arguments:  @md5_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                MD5 compression function.
+ */
+
+void md5_compress(md5_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d;
+  uint32 buf[16];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = ctx->a;
+  b = ctx->b;
+  c = ctx->c;
+  d = ctx->d;
+
+  /* --- 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) & (z)) | ((y) & ~(z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+#define T(w, x, y, z, i, r, k, f) do {                                 \
+  uint32 _t = w + f(x, y, z) + buf[i] + k;                             \
+  w = ROL32(_t, r) + x;                                                        \
+} while (0)
+
+#define FF(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, F)
+#define GG(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, G)
+#define HH(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, H)
+#define II(w, x, y, z, i, r, k) T(w, x, y, z, i, r, k, I)
+
+  /* --- The main compression function --- */
+
+  FF(a, b, c, d,  0,  7, 0xd76aa478);
+  FF(d, a, b, c,  1, 12, 0xe8c7b756);
+  FF(c, d, a, b,  2, 17, 0x242070db);
+  FF(b, c, d, a,  3, 22, 0xc1bdceee);
+  FF(a, b, c, d,  4,  7, 0xf57c0faf);
+  FF(d, a, b, c,  5, 12, 0x4787c62a);
+  FF(c, d, a, b,  6, 17, 0xa8304613);
+  FF(b, c, d, a,  7, 22, 0xfd469501);
+  FF(a, b, c, d,  8,  7, 0x698098d8);
+  FF(d, a, b, c,  9, 12, 0x8b44f7af);
+  FF(c, d, a, b, 10, 17, 0xffff5bb1);
+  FF(b, c, d, a, 11, 22, 0x895cd7be);
+  FF(a, b, c, d, 12,  7, 0x6b901122);
+  FF(d, a, b, c, 13, 12, 0xfd987193);
+  FF(c, d, a, b, 14, 17, 0xa679438e);
+  FF(b, c, d, a, 15, 22, 0x49b40821);
+
+  GG(a, b, c, d,  1,  5, 0xf61e2562);
+  GG(d, a, b, c,  6,  9, 0xc040b340);
+  GG(c, d, a, b, 11, 14, 0x265e5a51);
+  GG(b, c, d, a,  0, 20, 0xe9b6c7aa);
+  GG(a, b, c, d,  5,  5, 0xd62f105d);
+  GG(d, a, b, c, 10,  9, 0x02441453);
+  GG(c, d, a, b, 15, 14, 0xd8a1e681);
+  GG(b, c, d, a,  4, 20, 0xe7d3fbc8);
+  GG(a, b, c, d,  9,  5, 0x21e1cde6);
+  GG(d, a, b, c, 14,  9, 0xc33707d6);
+  GG(c, d, a, b,  3, 14, 0xf4d50d87);
+  GG(b, c, d, a,  8, 20, 0x455a14ed);
+  GG(a, b, c, d, 13,  5, 0xa9e3e905);
+  GG(d, a, b, c,  2,  9, 0xfcefa3f8);
+  GG(c, d, a, b,  7, 14, 0x676f02d9);
+  GG(b, c, d, a, 12, 20, 0x8d2a4c8a);
+
+  HH(a, b, c, d,  5,  4, 0xfffa3942);
+  HH(d, a, b, c,  8, 11, 0x8771f681);
+  HH(c, d, a, b, 11, 16, 0x6d9d6122);
+  HH(b, c, d, a, 14, 23, 0xfde5380c);
+  HH(a, b, c, d,  1,  4, 0xa4beea44);
+  HH(d, a, b, c,  4, 11, 0x4bdecfa9);
+  HH(c, d, a, b,  7, 16, 0xf6bb4b60);
+  HH(b, c, d, a, 10, 23, 0xbebfbc70);
+  HH(a, b, c, d, 13,  4, 0x289b7ec6);
+  HH(d, a, b, c,  0, 11, 0xeaa127fa);
+  HH(c, d, a, b,  3, 16, 0xd4ef3085);
+  HH(b, c, d, a,  6, 23, 0x04881d05);
+  HH(a, b, c, d,  9,  4, 0xd9d4d039);
+  HH(d, a, b, c, 12, 11, 0xe6db99e5);
+  HH(c, d, a, b, 15, 16, 0x1fa27cf8);
+  HH(b, c, d, a,  2, 23, 0xc4ac5665);
+
+  II(a, b, c, d,  0,  6, 0xf4292244);
+  II(d, a, b, c,  7, 10, 0x432aff97);
+  II(c, d, a, b, 14, 15, 0xab9423a7);
+  II(b, c, d, a,  5, 21, 0xfc93a039);
+  II(a, b, c, d, 12,  6, 0x655b59c3);
+  II(d, a, b, c,  3, 10, 0x8f0ccc92);
+  II(c, d, a, b, 10, 15, 0xffeff47d);
+  II(b, c, d, a,  1, 21, 0x85845dd1);
+  II(a, b, c, d,  8,  6, 0x6fa87e4f);
+  II(d, a, b, c, 15, 10, 0xfe2ce6e0);
+  II(c, d, a, b,  6, 15, 0xa3014314);
+  II(b, c, d, a, 13, 21, 0x4e0811a1);
+  II(a, b, c, d,  4,  6, 0xf7537e82);
+  II(d, a, b, c, 11, 10, 0xbd3af235);
+  II(c, d, a, b,  2, 15, 0x2ad7d2bb);
+  II(b, c, d, a,  9, 21, 0xeb86d391);
+
+  /* --- Update the chaining variables --- */
+
+  ctx->a += a;
+  ctx->b += b;
+  ctx->c += c;
+  ctx->d += d;
+}
+
+/* --- @md5_init@ --- *
+ *
+ * Arguments:  @md5_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void md5_init(md5_ctx *ctx)
+{
+  ctx->a = 0x67452301;
+  ctx->b = 0xefcdab89;
+  ctx->c = 0x98badcfe;
+  ctx->d = 0x10325476;
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+/* --- @md5_set@ --- *
+ *
+ * Arguments:  @md5_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 md5_set(md5_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->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @md5_hash@ --- *
+ *
+ * Arguments:  @md5_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 md5_hash(md5_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(MD5, md5, ctx, buf, sz);
+}
+
+/* --- @md5_done@ --- *
+ *
+ * Arguments:  @md5_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void md5_done(md5_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_MD5STRENGTH(MD5, md5, 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);
+}
+
+/* --- @md5_state@ --- *
+ *
+ * Arguments:  @md5_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 @md5_set@.
+ */
+
+unsigned long md5_state(md5_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);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(MD5, md5)
+
+/* --- Test code --- */
+
+HASH_TEST(MD5, md5)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/md5.h b/symm/md5.h
new file mode 100644 (file)
index 0000000..4248db2
--- /dev/null
@@ -0,0 +1,158 @@
+/* -*-c-*-
+ *
+ * The MD5 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Notes on the MD5 hash function ------------------------------------*
+ *
+ * MD5 was designed by Ron Rivest.  It was intended to be a more conservative
+ * design than the slightly earlier MD4, and indeed while MD4 has been pretty
+ * much demolished by subsequent cryptanalysis, MD5 is still standing
+ * shakily.  It's provided here not because the author recommends its use but
+ * because it's a common standard, and is often handy in non-cryptographic
+ * applications.  It's also still useful in constructions such as HMAC.
+ */
+
+#ifndef CATACOMB_MD5_H
+#define CATACOMB_MD5_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define MD5_BUFSZ 64
+#define MD5_HASHSZ 16
+#define MD5_STATESZ 16
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct md5_ctx {
+  uint32 a, b, c, d;                   /* Chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[MD5_BUFSZ];                        /* Accumulation buffer */
+} md5_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @md5_compress@ --- *
+ *
+ * Arguments:  @md5_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                MD5 compression function.
+ */
+
+extern void md5_compress(md5_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @md5_init@ --- *
+ *
+ * Arguments:  @md5_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void md5_init(md5_ctx */*ctx*/);
+
+/* --- @md5_set@ --- *
+ *
+ * Arguments:  @md5_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 md5_set(md5_ctx */*ctx*/, const void */*buf*/,
+                   unsigned long /*count*/);
+
+/* --- @md5_hash@ --- *
+ *
+ * Arguments:  @md5_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 md5_hash(md5_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @md5_done@ --- *
+ *
+ * Arguments:  @md5_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 md5_done(md5_ctx */*ctx*/, void */*hash*/);
+
+/* --- @md5_state@ --- *
+ *
+ * Arguments:  @md5_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 @md5_set@.
+ */
+
+extern unsigned long md5_state(md5_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash md5;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/mgf-def.h b/symm/mgf-def.h
new file mode 100644 (file)
index 0000000..b5105ed
--- /dev/null
@@ -0,0 +1,458 @@
+/* -*-c-*-
+ *
+ * Definitions for the MGF-1 mask generator
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_MGF_DEF_H
+#define CATACOMB_MGF_DEF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define MGF_DEF(PRE, pre)                                              \
+                                                                       \
+/* --- Useful constants --- */                                         \
+                                                                       \
+const octet pre##_mgfkeysz[] = { KSZ_ANY, PRE##_HASHSZ };              \
+                                                                       \
+/* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- *                                \
+ *                                                                     \
+ * Arguments:  @pre_mgfctx *k@ = pointer to context to initialize      \
+ *             @const void *p@ = pointer to data to contribute         \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                A multi-step keying procedure for initializing an MGF   \
+ *             context.  The data is contributed to a hashing context  \
+ *             which is then used for mask generation.  If you only    \
+ *             have a fixed buffer, you can save a lot of effort by    \
+ *             simply calling @pre_mgfinit@.                           \
+ */                                                                    \
+                                                                       \
+void pre##_mgfkeybegin(pre##_mgfctx *k)                                        \
+{                                                                      \
+  k->c = 0;                                                            \
+  k->bsz = 0;                                                          \
+  pre##_init(&k->k);                                                   \
+}                                                                      \
+                                                                       \
+void pre##_mgfkeyadd(pre##_mgfctx *k, const void *p, size_t sz)                \
+{                                                                      \
+  pre##_hash(&k->k, p, sz);                                            \
+}                                                                      \
+                                                                       \
+/* ---- @pre_mgfinit@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_mgfctx *k@ = pointer to context to initialize      \
+ *             @const void *p@ = pointer to data to contribute         \
+ *             @size_t sz@ = size of data to contribute                \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                A simpler interface to initialization if all of your    \
+ *             keying material is in one place.                        \
+ */                                                                    \
+                                                                       \
+void pre##_mgfinit(pre##_mgfctx *k, const void *p, size_t sz)          \
+{                                                                      \
+  k->c = 0;                                                            \
+  k->bsz = 0;                                                          \
+  pre##_init(&k->k);                                                   \
+  pre##_hash(&k->k, p, sz);                                            \
+}                                                                      \
+                                                                       \
+/* --- @pre_mgfencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_mgfctx *k@ = pointer to masking context            \
+ *             @const void *s@ = pointer to source buffer              \
+ *             @void *d@ = pointer to destination buffer               \
+ *             @size_t sz@ = size of buffers                           \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Outputs pseudorandom data, or masks an input buffer.    \
+ *                                                                     \
+ *             If @s@ is nonzero, the source material is exclusive-    \
+ *             orred with the generated mask.  If @d@ is zero, the     \
+ *             generator is simply spun around for a while, which      \
+ *             isn't very useful.                                      \
+ */                                                                    \
+                                                                       \
+void pre##_mgfencrypt(pre##_mgfctx *k, const void *s,                  \
+                     void *d, size_t sz)                               \
+{                                                                      \
+  const octet *ss = s;                                                 \
+  octet *dd = d;                                                       \
+                                                                       \
+  /* --- Empty the buffer if there's anything there --- */             \
+                                                                       \
+  if (k->bsz) {                                                                \
+    const octet *p = k->buf + PRE##_HASHSZ - k->bsz;                   \
+    size_t n = sz > k->bsz ? k->bsz : sz;                              \
+    sz -= n;                                                           \
+    k->bsz -= n;                                                       \
+    if (dd) {                                                          \
+      if (!ss) {                                                       \
+       memcpy(dd, p, n);                                               \
+       dd += n;                                                        \
+      } else {                                                         \
+       while (n) {                                                     \
+         *dd++ = *ss++ ^ *p++;                                         \
+         n--;                                                          \
+       }                                                               \
+      }                                                                        \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  /* --- While necessary, generate some more mask --- */               \
+                                                                       \
+  while (sz) {                                                         \
+    pre##_ctx c = k->k;                /* Not quick! */                        \
+    size_t n;                                                          \
+                                                                       \
+    STORE32(k->buf, k->c);                                             \
+    k->c++;                                                            \
+    pre##_hash(&c, k->buf, 4);                                         \
+    pre##_done(&c, k->buf);                                            \
+    n = sz > PRE##_HASHSZ ? PRE##_HASHSZ : sz;                         \
+    k->bsz = PRE##_HASHSZ - n;                                         \
+    sz -= n;                                                           \
+    if (dd) {                                                          \
+      const octet *p = k->buf;                                         \
+      if (!ss) {                                                       \
+       memcpy(dd, p, n);                                               \
+       dd += n;                                                        \
+      } else {                                                         \
+       while (n) {                                                     \
+         *dd++ = *ss++ ^ *p++;                                         \
+         n--;                                                          \
+       }                                                               \
+      }                                                                        \
+    }                                                                  \
+  }                                                                    \
+}                                                                      \
+                                                                       \
+/* --- @pre_mgfsetindex@ --- *                                         \
+ *                                                                     \
+ * Arguments:  @pre_mgfctx *k@ = pointer to masking context            \
+ *             @uint32 *c@ = new index to set                          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets a new index.  This may be used to step around the  \
+ *             output stream in a rather crude way.                    \
+ */                                                                    \
+                                                                       \
+void pre##_mgfsetindex(pre##_mgfctx *k, uint32 c)                      \
+{                                                                      \
+  k->c = c;                                                            \
+  k->bsz = 0;                                                          \
+}                                                                      \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+static const gcipher_ops gops;                                         \
+                                                                       \
+typedef struct gctx {                                                  \
+  gcipher c;                                                           \
+  pre##_mgfctx k;                                                      \
+} gctx;                                                                        \
+                                                                       \
+static gcipher *ginit(const void *k, size_t sz)                                \
+{                                                                      \
+  gctx *g = S_CREATE(gctx);                                            \
+  g->c.ops = &gops;                                                    \
+  pre##_mgfinit(&g->k, k, sz);                                         \
+  return (&g->c);                                                      \
+}                                                                      \
+                                                                       \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_mgfencrypt(&g->k, s, t, sz);                                   \
+}                                                                      \
+                                                                       \
+static void gdestroy(gcipher *c)                                       \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static const gcipher_ops gops = {                                      \
+  &pre##_mgf,                                                          \
+  gencrypt, gencrypt, gdestroy, 0, 0                                   \
+};                                                                     \
+                                                                       \
+const gccipher pre##_mgf = {                                           \
+  #pre "-mgf", pre##_mgfkeysz, 0,                                      \
+  ginit                                                                        \
+};                                                                     \
+                                                                       \
+/* --- Generic random number generator interface --- */                        \
+                                                                       \
+typedef struct grctx {                                                 \
+  grand r;                                                             \
+  pre##_mgfctx k;                                                      \
+} grctx;                                                               \
+                                                                       \
+static void grdestroy(grand *r)                                                \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static int grmisc(grand *r, unsigned op, ...)                          \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  va_list ap;                                                          \
+  int rc = 0;                                                          \
+  va_start(ap, op);                                                    \
+                                                                       \
+  switch (op) {                                                                \
+    case GRAND_CHECK:                                                  \
+      switch (va_arg(ap, unsigned)) {                                  \
+       case GRAND_CHECK:                                               \
+       case GRAND_SEEDINT:                                             \
+       case GRAND_SEEDUINT32:                                          \
+       case GRAND_SEEDBLOCK:                                           \
+       case GRAND_SEEDRAND:                                            \
+         rc = 1;                                                       \
+         break;                                                        \
+       default:                                                        \
+         rc = 0;                                                       \
+         break;                                                        \
+      }                                                                        \
+      break;                                                           \
+    case GRAND_SEEDINT:                                                        \
+      pre##_mgfsetindex(&g->k, va_arg(ap, unsigned));                  \
+      break;                                                           \
+    case GRAND_SEEDUINT32:                                             \
+      pre##_mgfsetindex(&g->k, va_arg(ap, uint32));                    \
+      break;                                                           \
+    case GRAND_SEEDBLOCK: {                                            \
+      const void *p = va_arg(ap, const void *);                                \
+      size_t sz = va_arg(ap, size_t);                                  \
+      pre##_hash(&g->k.k, p, sz);                                      \
+    } break;                                                           \
+    case GRAND_SEEDRAND: {                                             \
+      octet buf[PRE##_BUFSZ];                                          \
+      grand *rr = va_arg(ap, grand *);                                 \
+      rr->ops->fill(rr, buf, sizeof(buf));                             \
+      pre##_hash(&g->k.k, buf, sizeof(buf));                           \
+    } break;                                                           \
+    default:                                                           \
+      GRAND_BADOP;                                                     \
+      break;                                                           \
+  }                                                                    \
+                                                                       \
+  va_end(ap);                                                          \
+  return (rc);                                                         \
+}                                                                      \
+                                                                       \
+static octet grbyte(grand *r)                                          \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  octet o;                                                             \
+  pre##_mgfencrypt(&g->k, 0, &o, 1);                                   \
+  return (o);                                                          \
+}                                                                      \
+                                                                       \
+static uint32 grword(grand *r)                                         \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  octet b[4];                                                          \
+  pre##_mgfencrypt(&g->k, 0, b, sizeof(b));                            \
+  return (LOAD32(b));                                                  \
+}                                                                      \
+                                                                       \
+static void grfill(grand *r, void *p, size_t sz)                       \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  pre##_mgfencrypt(&g->k, 0, p, sz);                                   \
+}                                                                      \
+                                                                       \
+static const grand_ops grops = {                                       \
+  #pre "-mgf",                                                         \
+  GRAND_CRYPTO, 0,                                                     \
+  grmisc, grdestroy,                                                   \
+  grword, grbyte, grword, grand_range, grfill                          \
+};                                                                     \
+                                                                       \
+/* --- @pre_mgfrand@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @const void *k@ = pointer to key material               \
+ *             @size_t sz@ = size of key material                      \
+ *                                                                     \
+ * Returns:    Pointer to a generic random number generator instance.  \
+ *                                                                     \
+ * Use:                Creates a random number interface wrapper around an     \
+ *             MGF-1-mode hash function.                               \
+ */                                                                    \
+                                                                       \
+extern grand *pre##_mgfrand(const void *k, size_t sz)                  \
+{                                                                      \
+  grctx *g = S_CREATE(grctx);                                          \
+  g->r.ops = &grops;                                                   \
+  pre##_mgfinit(&g->k, k, sz);                                         \
+  return (&g->r);                                                      \
+}                                                                      \
+                                                                       \
+MGF_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @MGF_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use:                Standard test rig for MGF functions.
+ */
+
+#define MGF_TEST(PRE, pre)                                             \
+                                                                       \
+/* --- Initial plaintext for the test --- */                           \
+                                                                       \
+static const octet text[] = TEXT;                                      \
+                                                                       \
+/* --- Key and IV to use --- */                                                \
+                                                                       \
+static const octet key[] = KEY;                                                \
+                                                                       \
+/* --- Buffers for encryption and decryption output --- */             \
+                                                                       \
+static octet ct[sizeof(text)];                                         \
+static octet pt[sizeof(text)];                                         \
+                                                                       \
+static void hexdump(const octet *p, size_t sz)                         \
+{                                                                      \
+  const octet *q = p + sz;                                             \
+  for (sz = 0; p < q; p++, sz++) {                                     \
+    printf("%02x", *p);                                                        \
+    if ((sz + 1) % PRE##_HASHSZ == 0)                                  \
+      putchar(':');                                                    \
+  }                                                                    \
+}                                                                      \
+                                                                       \
+int main(void)                                                         \
+{                                                                      \
+  size_t sz = 0, rest;                                                 \
+  pre##_mgfctx ctx;                                                    \
+  int status = 0;                                                      \
+  int done = 0;                                                                \
+                                                                       \
+  size_t keysz = strlen((const char *)key);                            \
+                                                                       \
+  fputs(#pre "-mgf: ", stdout);                                                \
+                                                                       \
+  pre##_mgfinit(&ctx, key, keysz);                                     \
+                                                                       \
+  while (sz <= sizeof(text)) {                                         \
+    rest = sizeof(text) - sz;                                          \
+    memcpy(ct, text, sizeof(text));                                    \
+    pre##_mgfsetindex(&ctx, 0);                                                \
+    pre##_mgfencrypt(&ctx, ct, ct, sz);                                        \
+    pre##_mgfencrypt(&ctx, ct + sz, ct + sz, rest);                    \
+    memcpy(pt, ct, sizeof(text));                                      \
+    pre##_mgfsetindex(&ctx, 0);                                                \
+    pre##_mgfencrypt(&ctx, pt, pt, rest);                              \
+    pre##_mgfencrypt(&ctx, pt + rest, pt + rest, sz);                  \
+    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
+      done++;                                                          \
+      if (sizeof(text) < 40 || done % 8 == 0)                          \
+       fputc('.', stdout);                                             \
+      if (done % 480 == 0)                                             \
+       fputs("\n\t", stdout);                                          \
+      fflush(stdout);                                                  \
+    } else {                                                           \
+      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
+      status = 1;                                                      \
+      printf("\tplaintext      = "); hexdump(text, sz);                        \
+       printf(", "); hexdump(text + sz, rest);                         \
+       fputc('\n', stdout);                                            \
+      printf("\tciphertext     = "); hexdump(ct, sz);                  \
+       printf(", "); hexdump(ct + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      printf("\trecovered text = "); hexdump(pt, sz);                  \
+       printf(", "); hexdump(pt + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      fputc('\n', stdout);                                             \
+    }                                                                  \
+    if (sz < 63)                                                       \
+      sz++;                                                            \
+    else                                                               \
+      sz += 9;                                                         \
+  }                                                                    \
+                                                                       \
+  fputs(status ? " failed\n" : " ok\n", stdout);                       \
+  return (status);                                                     \
+}
+
+#else
+#  define MGF_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/mgf.h b/symm/mgf.h
new file mode 100644 (file)
index 0000000..d5b0fd1
--- /dev/null
@@ -0,0 +1,162 @@
+/* -*-c-*-
+ *
+ * The MGF mask generation function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the MGF-1 mask generating function -----------------------*
+ *
+ * The idea of a mask-generating function is that given an input of arbitrary
+ * size, it can emit a pseudorandom output `mask' of arbitrary size.  This is
+ * used in PKCS#1 OAEP (RFC2437).  My recommendation would be to use a decent
+ * stream cipher instead, like RC4 or SEAL.  MGF-1 isn't very fast.
+ */
+
+#ifndef CATACOMB_MGF_H
+#define CATACOMB_MGF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define MGF_DECL(PRE, pre)                                             \
+                                                                       \
+/* --- An MGF generation context --- */                                        \
+                                                                       \
+typedef struct pre##_mgfctx {                                          \
+  pre##_ctx k;                         /* Underlying key context */    \
+  uint32 c;                            /* Counter */                   \
+  octet buf[PRE##_HASHSZ];             /* Output buffer */             \
+  size_t bsz;                          /* Size of buffered data */     \
+} pre##_mgfctx;                                                                \
+                                                                       \
+/* --- Other useful constants --- */                                   \
+                                                                       \
+extern const octet pre##_mgfkeysz[];                                   \
+                                                                       \
+/* --- @pre_mgfkeybegin@, @pre_mgfkeyadd@ --- *                                \
+ *                                                                     \
+ * Arguments:  @pre_mgfctx *k@ = pointer to context to initialize      \
+ *             @const void *p@ = pointer to data to contribute         \
+ *             @size_t sz@ = size of data to contribute                \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                A multi-step keying procedure for initializing an MGF   \
+ *             context.  The data is contributed to a hashing context  \
+ *             which is then used for mask generation.  If you only    \
+ *             have a fixed buffer, you can save a lot of effort by    \
+ *             simply calling @pre_mgfinit@.                           \
+ */                                                                    \
+                                                                       \
+extern void pre##_mgfkeybegin(pre##_mgfctx */*k*/);                    \
+extern void pre##_mgfkeyadd(pre##_mgfctx */*k*/,                       \
+                           const void */*p*/, size_t /*sz*/);          \
+                                                                       \
+/* ---- @pre_mgfinit@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_mgfctx *k@ = pointer to context to initialize      \
+ *             @const void *p@ = pointer to data to contribute         \
+ *             @size_t sz@ = size of data to contribute                \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                A simpler interface to initialization if all of your    \
+ *             keying material is in one place.                        \
+ */                                                                    \
+                                                                       \
+extern void pre##_mgfinit(pre##_mgfctx */*k*/,                         \
+                         const void */*p*/, size_t /*sz*/);            \
+                                                                       \
+/* --- @pre_mgfencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_mgfctx *k@ = pointer to masking context            \
+ *             @const void *s@ = pointer to source buffer              \
+ *             @void *d@ = pointer to destination buffer               \
+ *             @size_t sz@ = size of buffers                           \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Outputs pseudorandom data, or masks an input buffer.    \
+ *                                                                     \
+ *             If @s@ is nonzero, the source material is exclusive-    \
+ *             orred with the generated mask.  If @d@ is zero, the     \
+ *             generator is simply spun around for a while, which      \
+ *             isn't very useful.                                      \
+ */                                                                    \
+                                                                       \
+extern void pre##_mgfencrypt(pre##_mgfctx */*k*/, const void */*s*/,   \
+                            void */*d*/, size_t /*sz*/);               \
+                                                                       \
+/* --- @pre_mgfsetindex@ --- *                                         \
+ *                                                                     \
+ * Arguments:  @pre_mgfctx *k@ = pointer to masking context            \
+ *             @uint32 *c@ = new index to set                          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets a new index.  This may be used to step around the  \
+ *             output stream in a rather crude way.                    \
+ */                                                                    \
+                                                                       \
+extern void pre##_mgfsetindex(pre##_mgfctx */*k*/, uint32 /*c*/);      \
+                                                                       \
+/* --- @pre_mgfrand@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @const void *k@ = pointer to key material               \
+ *             @size_t sz@ = size of key material                      \
+ *                                                                     \
+ * Returns:    Pointer to a generic random number generator instance.  \
+ *                                                                     \
+ * Use:                Creates a random number interface wrapper around an     \
+ *             MGF-1-mode hash function.                               \
+ */                                                                    \
+                                                                       \
+extern grand *pre##_mgfrand(const void */*k*/, size_t /*sz*/);         \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+extern const gccipher pre##_mgf;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
similarity index 100%
rename from mode.c.in
rename to symm/mode.c.in
similarity index 100%
rename from mode.h.in
rename to symm/mode.h.in
diff --git a/symm/modes.am.in b/symm/modes.am.in
new file mode 100644 (file)
index 0000000..4cbc88f
--- /dev/null
@@ -0,0 +1,77 @@
+%## -*-makefile-*-
+%#
+### -*-makefile-*- GENERATED from modes.make.in
+###
+### Lots of lists of crypto primitives in various modes of operation.
+
+## Test programs for symmetric primitives.
+SYMM_TESTS =
+
+## Source and header files for primitives under modes of operation.
+GENMODES_C =
+GENMODES_H =
+
+## Block cipher modes.
+%repeat
+GENMODES_C += modes/@blkc-@blkcmode.c
+GENMODES_H += modes/@blkc-@blkcmode.h
+SYMM_TESTS += @blkc-@blkcmode.$t
+%end
+
+## Hash function modes.
+%repeat
+GENMODES_C += modes/@hash-@hashmode.c
+GENMODES_H += modes/@hash-@hashmode.h
+SYMM_TESTS += @hash-@hashmode.$t
+%end
+
+## Interface and implementation headers for the various modes.
+MODE_H =
+%repeat
+MODE_H += @blkcmode.h @blkcmode-def.h
+%end
+%repeat
+MODE_H += @hashmode.h @hashmode-def.h
+%end
+
+## Block cipher interfaces and implementations.
+BLKC_C =
+BLKC_H =
+%repeat
+BLKC_C += @blkc.c
+BLKC_H += @blkc.h
+SYMM_TESTS += @blkc.$t
+%end
+
+## Hash function interfaces and implementations.
+HASH_C =
+HASH_H =
+%repeat
+HASH_C += @hash.c
+HASH_H += @hash.h
+SYMM_TESTS += @hash.$t
+%end
+
+## Modes for symmetric encryption.
+CIPHER_MODES =
+%repeat
+CIPHER_MODES += @blkc-@blkcciphermode
+%end
+%repeat
+CIPHER_MODES += @hash-@hashciphermode
+%end
+
+## Modes for message authentication.
+MAC_MODES =
+%repeat
+MAC_MODES += @hash-@hashmacmode
+%end
+
+## Test input files.
+SYMM_TEST_FILES =
+%repeat
+SYMM_TEST_FILES += t/@blkc
+%end
+%repeat
+SYMM_TEST_FILES += t/@hash
+%end
similarity index 100%
rename from multigen
rename to symm/multigen
diff --git a/symm/noekeon.c b/symm/noekeon.c
new file mode 100644 (file)
index 0000000..6452091
--- /dev/null
@@ -0,0 +1,193 @@
+/* -*-c-*-
+ *
+ * The Noekeon block cipher
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "noekeon.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet noekeon_keysz[] = { KSZ_SET, NOEKEON_KEYSZ, 0 };
+
+/*----- Magic constants ---------------------------------------------------*/
+
+/* --- To generate the magic --- *
+ *
+ * perl -e'@@r=();$x=0x80;for(0..16){push(@@r,$x);$x<<=1;$x^=0x11b
+ * if$x&0x100;};print join(", ",map{sprintf"0x%02x",$_}@@r),"\n";'
+ */
+
+static const octet rcon[17] = {
+  0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+  0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
+  0xd4
+};
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @noekeon_init@--- *
+ *
+ * Arguments:  @noekeon_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Noekeon key buffer.  Noekeon accepts a 128-bit
+ *             key.
+ */
+
+void noekeon_init(noekeon_ctx *k, const void *buf, size_t sz)
+{
+  const octet *p = buf;
+  static const noekeon_ctx nullkey = { { 0, 0, 0, 0 } };
+
+  KSZ_ASSERT(noekeon, sz);
+  k->k[0] = LOAD32(p + 0);
+  k->k[1] = LOAD32(p + 4);
+  k->k[2] = LOAD32(p + 8);
+  k->k[3] = LOAD32(p + 12);
+  noekeon_eblk(&nullkey, k->k, k->k);
+}
+
+/* --- @noekeon_eblk@, @noekeon_dblk@ --- *
+ *
+ * Arguments:  @const noekeon_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define GAMMA(a, b, c, d) do {                                         \
+  uint32 _x;                                                           \
+  b ^= ~(c | d); a ^= b & c;                                           \
+  _x = d; d = a; a = _x;                                               \
+  c ^= a ^ b ^ d;                                                      \
+  b ^= ~(c | d); a ^= b & c;                                           \
+} while (0)
+
+#define THETA(ka, kb, kc, kd, a, b, c, d) do {                         \
+  uint32 _x;                                                           \
+  _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x;     \
+  a ^= ka; b ^= kb; c ^= kc; d ^= kd;                                  \
+  _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x;     \
+} while (0)
+
+#define ITHETA(ka, kb, kc, kd, a, b, c, d) do {                                \
+  uint32 _x;                                                           \
+  _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x;     \
+  a ^= ka; b ^= kb; c ^= kc; d ^= kd;                                  \
+  _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x;     \
+} while (0)
+
+#define PI1(a, b, c, d) do {                                           \
+  b = ROL32(b, 1); c = ROL32(c, 5); d = ROL32(d, 2);                   \
+} while (0)
+
+#define PI2(a, b, c, d) do {                                           \
+  b = ROR32(b, 1); c = ROR32(c, 5); d = ROR32(d, 2);                   \
+} while (0)
+
+#define ROUND(r, ka, kb, kc, kd, a, b, c, d) do {                      \
+  a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d);                                \
+  PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d);                 \
+} while (0)
+
+#define IROUND(r, ka, kb, kc, kd, a, b, c, d) do {                     \
+  ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r;                       \
+  PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d);                 \
+} while (0)
+
+void noekeon_eblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst)
+{
+  uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3];
+  uint32 a = src[0], b = src[1], c = src[2], d = src[3];
+  const octet *r = rcon;
+
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+  ROUND(r, ka, kb, kc, kd, a, b, c, d);
+
+  a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+}
+
+void noekeon_dblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst)
+{
+  uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3];
+  uint32 a = src[0], b = src[1], c = src[2], d = src[3];
+  const octet *r = rcon + sizeof(rcon);
+
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+  IROUND(r, ka, kb, kc, kd, a, b, c, d);
+
+  ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r;
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+}
+
+BLKC_TEST(NOEKEON, noekeon)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/noekeon.h b/symm/noekeon.h
new file mode 100644 (file)
index 0000000..744db96
--- /dev/null
@@ -0,0 +1,103 @@
+/* -*-c-*-
+ *
+ * The Noekeon block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Noekeon block cipher --------------------------------*
+ *
+ * A Nessie entry, by Joan Daemen, Michael Peeters, Gilles Van Assche and
+ * Vincent Rijmen, two of whom were the designers of the AES winner
+ * Rijndael.  It's a simple cipher, based on Serpent-style bit-slicing.
+ * Speed is about middle-of-the-road -- about as fast as SAFER, faster than
+ * MARS.
+ */
+
+#ifndef CATACOMB_NOEKEON_H
+#define CATACOMB_NOEKEON_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define NOEKEON_BLKSZ 16
+#define NOEKEON_KEYSZ 16
+#define NOEKEON_CLASS (N, B, 128)
+
+extern const octet noekeon_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct noekeon_ctx {
+  uint32 k[4];
+} noekeon_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @noekeon_init@ --- *
+ *
+ * Arguments:  @noekeon_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Noekeon context with a particular key.  This
+ *             uses indirect keying.  The key must be 128 bits long.
+ */
+
+extern void noekeon_init(noekeon_ctx */*k*/,
+                        const void */*buf*/, size_t /*sz*/);
+
+/* --- @noekeon_eblk@, @noekeon_dblk@ --- *
+ *
+ * Arguments:  @const noekeon_ctx *k@ = pointer to Noekeon context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void noekeon_eblk(const noekeon_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*dst*/);
+extern void noekeon_dblk(const noekeon_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*dst*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/ofb-def.h b/symm/ofb-def.h
new file mode 100644 (file)
index 0000000..6b1357d
--- /dev/null
@@ -0,0 +1,545 @@
+/* -*-c-*-
+ *
+ * Definitions for output feedback mode
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_OFB_DEF_H
+#define CATACOMB_OFB_DEF_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+#  include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+#  include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @OFB_DEF@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates definitions for output feedback mode.
+ */
+
+#define OFB_DEF(PRE, pre)                                              \
+                                                                       \
+/* --- @pre_ofbgetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @const pre_ofbctx *ctx@ = pointer to OFB context block  \
+ *             @void *iv@ = pointer to output data block               \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reads the currently set IV.  Reading and setting an IV  \
+ *             is not transparent to the cipher.  It will add a `step' \
+ *             which must be matched by a similar operation during     \
+ *             decryption.                                             \
+ */                                                                    \
+                                                                       \
+void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv)                 \
+{                                                                      \
+  octet *p = iv;                                                       \
+  unsigned off = ctx->off;                                             \
+  unsigned rest = PRE##_BLKSZ - off;                                   \
+  memcpy(p, ctx->iv + off, rest);                                      \
+  memcpy(p + rest, ctx->iv, off);                                      \
+}                                                                      \
+                                                                       \
+/* --- @pre_ofbsetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
+ *             @cnost void *iv@ = pointer to IV to set                 \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the IV to use for subsequent encryption.           \
+ */                                                                    \
+                                                                       \
+void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv)                 \
+{                                                                      \
+  memcpy(ctx->iv, iv, PRE##_BLKSZ);                                    \
+  ctx->off = PRE##_BLKSZ;                                              \
+}                                                                      \
+                                                                       \
+/* --- @pre_ofbbdry@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Inserts a boundary during encryption.  Successful       \
+ *             decryption must place a similar boundary.               \
+ */                                                                    \
+                                                                       \
+void pre##_ofbbdry(pre##_ofbctx *ctx)                                  \
+{                                                                      \
+  uint32 niv[PRE##_BLKSZ / 4];                                         \
+  BLKC_LOAD(PRE, niv, ctx->iv);                                                \
+  pre##_eblk(&ctx->ctx, niv, niv);                                     \
+  BLKC_STORE(PRE, ctx->iv, niv);                                       \
+  ctx->off = PRE##_BLKSZ;                                              \
+  BURN(niv);                                                           \
+}                                                                      \
+                                                                       \
+/* --- @pre_ofbsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the OFB context to use a different cipher key.     \
+ */                                                                    \
+                                                                       \
+void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k)            \
+{                                                                      \
+  ctx->ctx = *k;                                                       \
+}                                                                      \
+                                                                       \
+/* --- @pre_ofbinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to cipher context           \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a OFB context ready for use.  You should    \
+ *             ensure that the IV chosen is unique: reusing an IV will \
+ *             compromise the security of the entire plaintext.  This  \
+ *             is equivalent to calls to @pre_init@, @pre_ofbsetkey@   \
+ *             and @pre_ofbsetiv@.                                     \
+ */                                                                    \
+                                                                       \
+void pre##_ofbinit(pre##_ofbctx *ctx,                                  \
+                    const void *key, size_t sz,                        \
+                    const void *iv)                                    \
+{                                                                      \
+  static const octet zero[PRE##_BLKSZ] = { 0 };                                \
+  pre##_init(&ctx->ctx, key, sz);                                      \
+  pre##_ofbsetiv(ctx, iv ? iv : zero);                                 \
+}                                                                      \
+                                                                       \
+/* --- @pre_ofbencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts or decrypts a block with a block cipher in OFB \
+ *             mode: encryption and decryption are the same in OFB.    \
+ *             The destination may be null to just churn the feedback  \
+ *             round for a bit.  The source may be null to use the     \
+ *             cipher as a random data generator.                      \
+ */                                                                    \
+                                                                       \
+void pre##_ofbencrypt(pre##_ofbctx *ctx,                               \
+                       const void *src, void *dest,                    \
+                       size_t sz)                                      \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+  unsigned off = ctx->off;                                             \
+                                                                       \
+  /* --- Empty blocks are trivial --- */                               \
+                                                                       \
+  if (!sz)                                                             \
+    return;                                                            \
+                                                                       \
+  /* --- If I can deal with the block from my buffer, do that --- */   \
+                                                                       \
+  if (sz < PRE##_BLKSZ - off)                                          \
+    goto small;                                                                \
+                                                                       \
+  /* --- Finish off what's left in my buffer --- */                    \
+                                                                       \
+  if (!d)                                                              \
+    sz -= PRE##_BLKSZ - off;                                           \
+  else {                                                               \
+    while (off < PRE##_BLKSZ) {                                                \
+      register octet x = s ? *s++ : 0;                                 \
+      *d++ = ctx->iv[off++] ^ x;                                       \
+      sz--;                                                            \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  /* --- Main encryption loop --- */                                   \
+                                                                       \
+  {                                                                    \
+    uint32 iv[PRE##_BLKSZ / 4];                                                \
+    BLKC_LOAD(PRE, iv, ctx->iv);                                       \
+                                                                       \
+    for (;;) {                                                         \
+      pre##_eblk(&ctx->ctx, iv, iv);                                   \
+      if (sz < PRE##_BLKSZ)                                            \
+       break;                                                          \
+      if (d) {                                                         \
+       if (!s)                                                         \
+         BLKC_STORE(PRE, d, iv);                                       \
+       else {                                                          \
+         uint32 x[PRE##_BLKSZ / 4];                                    \
+         BLKC_LOAD(PRE, x, s);                                         \
+         BLKC_XSTORE(PRE, d, iv, x);                                   \
+         s += PRE##_BLKSZ;                                             \
+       }                                                               \
+       d += PRE##_BLKSZ;                                               \
+      }                                                                        \
+      sz -= PRE##_BLKSZ;                                               \
+    }                                                                  \
+                                                                       \
+    BLKC_STORE(PRE, ctx->iv, iv);                                      \
+    off = 0;                                                           \
+  }                                                                    \
+                                                                       \
+  /* --- Tidying up the tail end --- */                                        \
+                                                                       \
+  if (sz) {                                                            \
+  small:                                                               \
+    if (!d)                                                            \
+      off += sz;                                                       \
+    else do {                                                          \
+      register octet x = s ? *s++ : 0;                                 \
+      *d++ = ctx->iv[off++] ^ x;                                       \
+      sz--;                                                            \
+    } while (sz);                                                      \
+  }                                                                    \
+                                                                       \
+  /* --- Done --- */                                                   \
+                                                                       \
+  ctx->off = off;                                                      \
+  return;                                                              \
+}                                                                      \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+static const gcipher_ops gops;                                         \
+                                                                       \
+typedef struct gctx {                                                  \
+  gcipher c;                                                           \
+  pre##_ofbctx k;                                                      \
+} gctx;                                                                        \
+                                                                       \
+static gcipher *ginit(const void *k, size_t sz)                                \
+{                                                                      \
+  gctx *g = S_CREATE(gctx);                                            \
+  g->c.ops = &gops;                                                    \
+  pre##_ofbinit(&g->k, k, sz, 0);                                      \
+  return (&g->c);                                                      \
+}                                                                      \
+                                                                       \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)    \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_ofbencrypt(&g->k, s, t, sz);                                   \
+}                                                                      \
+                                                                       \
+static void gdestroy(gcipher *c)                                       \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static void gsetiv(gcipher *c, const void *iv)                         \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_ofbsetiv(&g->k, iv);                                           \
+}                                                                      \
+                                                                       \
+static void gbdry(gcipher *c)                                          \
+{                                                                      \
+  gctx *g = (gctx *)c;                                                 \
+  pre##_ofbbdry(&g->k);                                                        \
+}                                                                      \
+                                                                       \
+static const gcipher_ops gops = {                                      \
+  &pre##_ofb,                                                          \
+  gencrypt, gencrypt, gdestroy, gsetiv, gbdry                          \
+};                                                                     \
+                                                                       \
+const gccipher pre##_ofb = {                                           \
+  #pre "-ofb", pre##_keysz, PRE##_BLKSZ,                               \
+  ginit                                                                        \
+};                                                                     \
+                                                                       \
+/* --- Generic random number generator interface --- */                        \
+                                                                       \
+typedef struct grctx {                                                 \
+  grand r;                                                             \
+  pre##_ofbctx k;                                                      \
+} grctx;                                                               \
+                                                                       \
+static void grdestroy(grand *r)                                                \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  BURN(*g);                                                            \
+  S_DESTROY(g);                                                                \
+}                                                                      \
+                                                                       \
+static int grmisc(grand *r, unsigned op, ...)                          \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  va_list ap;                                                          \
+  int rc = 0;                                                          \
+  uint32 i;                                                            \
+  octet buf[PRE##_BLKSZ];                                              \
+  va_start(ap, op);                                                    \
+                                                                       \
+  switch (op) {                                                                \
+    case GRAND_CHECK:                                                  \
+      switch (va_arg(ap, unsigned)) {                                  \
+       case GRAND_CHECK:                                               \
+       case GRAND_SEEDINT:                                             \
+       case GRAND_SEEDUINT32:                                          \
+       case GRAND_SEEDBLOCK:                                           \
+       case GRAND_SEEDRAND:                                            \
+         rc = 1;                                                       \
+         break;                                                        \
+       default:                                                        \
+         rc = 0;                                                       \
+         break;                                                        \
+      }                                                                        \
+      break;                                                           \
+    case GRAND_SEEDINT:                                                        \
+      memset(buf, 0, sizeof(buf));                                     \
+      i = va_arg(ap, unsigned);                                                \
+      STORE32(buf, i);                                                 \
+      pre##_ofbsetiv(&g->k, buf);                                      \
+      break;                                                           \
+    case GRAND_SEEDUINT32:                                             \
+      memset(buf, 0, sizeof(buf));                                     \
+      i = va_arg(ap, uint32);                                          \
+      STORE32(buf, i);                                                 \
+      pre##_ofbsetiv(&g->k, buf);                                      \
+      break;                                                           \
+    case GRAND_SEEDBLOCK: {                                            \
+      const void *p = va_arg(ap, const void *);                                \
+      size_t sz = va_arg(ap, size_t);                                  \
+      if (sz < sizeof(buf)) {                                          \
+       memset(buf, 0, sizeof(buf));                                    \
+       memcpy(buf, p, sz);                                             \
+       p = buf;                                                        \
+      }                                                                        \
+      pre##_ofbsetiv(&g->k, p);                                                \
+    } break;                                                           \
+    case GRAND_SEEDRAND: {                                             \
+      grand *rr = va_arg(ap, grand *);                                 \
+      rr->ops->fill(rr, buf, sizeof(buf));                             \
+      pre##_ofbsetiv(&g->k, buf);                                      \
+    } break;                                                           \
+    default:                                                           \
+      GRAND_BADOP;                                                     \
+      break;                                                           \
+  }                                                                    \
+                                                                       \
+  va_end(ap);                                                          \
+  return (rc);                                                         \
+}                                                                      \
+                                                                       \
+static octet grbyte(grand *r)                                          \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  octet o;                                                             \
+  pre##_ofbencrypt(&g->k, 0, &o, 1);                                   \
+  return (o);                                                          \
+}                                                                      \
+                                                                       \
+static uint32 grword(grand *r)                                         \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  octet b[4];                                                          \
+  pre##_ofbencrypt(&g->k, 0, b, sizeof(b));                            \
+  return (LOAD32(b));                                                  \
+}                                                                      \
+                                                                       \
+static void grfill(grand *r, void *p, size_t sz)                       \
+{                                                                      \
+  grctx *g = (grctx *)r;                                               \
+  pre##_ofbencrypt(&g->k, 0, p, sz);                                   \
+}                                                                      \
+                                                                       \
+static const grand_ops grops = {                                       \
+  #pre "-ofb",                                                         \
+  GRAND_CRYPTO, 0,                                                     \
+  grmisc, grdestroy,                                                   \
+  grword, grbyte, grword, grand_range, grfill                          \
+};                                                                     \
+                                                                       \
+/* --- @pre_ofbrand@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @const void *k@ = pointer to key material               \
+ *             @size_t sz@ = size of key material                      \
+ *                                                                     \
+ * Returns:    Pointer to generic random number generator interface.   \
+ *                                                                     \
+ * Use:                Creates a random number interface wrapper around an     \
+ *             OFB-mode block cipher.                                  \
+ */                                                                    \
+                                                                       \
+grand *pre##_ofbrand(const void *k, size_t sz)                         \
+{                                                                      \
+  grctx *g = S_CREATE(grctx);                                          \
+  g->r.ops = &grops;                                                   \
+  pre##_ofbinit(&g->k, k, sz, 0);                                      \
+  return (&g->r);                                                      \
+}                                                                      \
+                                                                       \
+OFB_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @OFB_TEST@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use:                Standard test rig for OFB functions.
+ */
+
+#define OFB_TEST(PRE, pre)                                             \
+                                                                       \
+/* --- Initial plaintext for the test --- */                           \
+                                                                       \
+static const octet text[] = TEXT;                                      \
+                                                                       \
+/* --- Key and IV to use --- */                                                \
+                                                                       \
+static const octet key[] = KEY;                                                \
+static const octet iv[] = IV;                                          \
+                                                                       \
+/* --- Buffers for encryption and decryption output --- */             \
+                                                                       \
+static octet ct[sizeof(text)];                                         \
+static octet pt[sizeof(text)];                                         \
+                                                                       \
+static void hexdump(const octet *p, size_t sz)                         \
+{                                                                      \
+  const octet *q = p + sz;                                             \
+  for (sz = 0; p < q; p++, sz++) {                                     \
+    printf("%02x", *p);                                                        \
+    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
+      putchar(':');                                                    \
+  }                                                                    \
+}                                                                      \
+                                                                       \
+int main(void)                                                         \
+{                                                                      \
+  size_t sz = 0, rest;                                                 \
+  pre##_ofbctx ctx;                                                    \
+  int status = 0;                                                      \
+  int done = 0;                                                                \
+  pre##_ctx k;                                                         \
+                                                                       \
+  size_t keysz = PRE##_KEYSZ ?                                         \
+    PRE##_KEYSZ : strlen((const char *)key);                           \
+                                                                       \
+  fputs(#pre "-ofb: ", stdout);                                                \
+                                                                       \
+  pre##_init(&k, key, keysz);                                          \
+  pre##_ofbsetkey(&ctx, &k);                                           \
+                                                                       \
+  while (sz <= sizeof(text)) {                                         \
+    rest = sizeof(text) - sz;                                          \
+    memcpy(ct, text, sizeof(text));                                    \
+    pre##_ofbsetiv(&ctx, iv);                                          \
+    pre##_ofbencrypt(&ctx, ct, ct, sz);                                        \
+    pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest);                    \
+    memcpy(pt, ct, sizeof(text));                                      \
+    pre##_ofbsetiv(&ctx, iv);                                          \
+    pre##_ofbencrypt(&ctx, pt, pt, rest);                              \
+    pre##_ofbencrypt(&ctx, pt + rest, pt + rest, sz);                  \
+    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
+      done++;                                                          \
+      if (sizeof(text) < 40 || done % 8 == 0)                          \
+       fputc('.', stdout);                                             \
+      if (done % 480 == 0)                                             \
+       fputs("\n\t", stdout);                                          \
+      fflush(stdout);                                                  \
+    } else {                                                           \
+      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
+      status = 1;                                                      \
+      printf("\tplaintext      = "); hexdump(text, sz);                        \
+       printf(", "); hexdump(text + sz, rest);                         \
+       fputc('\n', stdout);                                            \
+      printf("\tciphertext     = "); hexdump(ct, sz);                  \
+       printf(", "); hexdump(ct + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      printf("\trecovered text = "); hexdump(pt, sz);                  \
+       printf(", "); hexdump(pt + sz, rest);                           \
+       fputc('\n', stdout);                                            \
+      fputc('\n', stdout);                                             \
+    }                                                                  \
+    if (sz < 63)                                                       \
+      sz++;                                                            \
+    else                                                               \
+      sz += 9;                                                         \
+  }                                                                    \
+                                                                       \
+  fputs(status ? " failed\n" : " ok\n", stdout);                       \
+  return (status);                                                     \
+}
+
+#else
+#  define OFB_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/ofb.h b/symm/ofb.h
new file mode 100644 (file)
index 0000000..5eec2ff
--- /dev/null
@@ -0,0 +1,185 @@
+/* -*-c-*-
+ *
+ * Output feedback for block ciphers
+ *
+ * (c) 1999 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.
+ */
+
+#ifndef CATACOMB_OFB_H
+#define CATACOMB_OFB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @OFB_DECL@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use:                Makes declarations for output feedback mode.
+ */
+
+#define OFB_DECL(PRE, pre)                                             \
+                                                                       \
+/* --- Output feedback context --- */                                  \
+                                                                       \
+typedef struct pre##_ofbctx {                                          \
+  pre##_ctx ctx;                       /* Underlying cipher context */ \
+  unsigned off;                                /* Current offset in buffer */  \
+  octet iv[PRE##_BLKSZ];               /* Output buffer and IV */      \
+} pre##_ofbctx;                                                                \
+                                                                       \
+/* --- @pre_ofbgetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @const pre_ofbctx *ctx@ = pointer to OFB context block  \
+ *             @void *iv@ = pointer to output data block               \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reads the currently set IV.  Reading and setting an IV  \
+ *             is not transparent to the cipher.  It will add a `step' \
+ *             which must be matched by a similar operation during     \
+ *             decryption.                                             \
+ */                                                                    \
+                                                                       \
+extern void pre##_ofbgetiv(const pre##_ofbctx */*ctx*/,                        \
+                          void */*iv*/);                               \
+                                                                       \
+/* --- @pre_ofbsetiv@ --- *                                            \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
+ *             @cnost void *iv@ = pointer to IV to set                 \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the IV to use for subsequent encryption.           \
+ */                                                                    \
+                                                                       \
+extern void pre##_ofbsetiv(pre##_ofbctx */*ctx*/,                      \
+                          const void */*iv*/);                         \
+                                                                       \
+/* --- @pre_ofbbdry@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Inserts a boundary during encryption.  Successful       \
+ *             decryption must place a similar boundary.               \
+ */                                                                    \
+                                                                       \
+extern void pre##_ofbbdry(pre##_ofbctx */*ctx*/);                      \
+                                                                       \
+/* --- @pre_ofbsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
+ *             @const pre_ctx *k@ = pointer to cipher context          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Sets the OFB context to use a different cipher key.     \
+ */                                                                    \
+                                                                       \
+extern void pre##_ofbsetkey(pre##_ofbctx */*ctx*/,                     \
+                           const pre##_ctx */*k*/);                    \
+                                                                       \
+/* --- @pre_ofbinit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to cipher context           \
+ *             @const void *key@ = pointer to the key buffer           \
+ *             @size_t sz@ = size of the key                           \
+ *             @const void *iv@ = pointer to initialization vector     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes a OFB context ready for use.  You should    \
+ *             ensure that the IV chosen is unique: reusing an IV will \
+ *             compromise the security of the entire plaintext.  This  \
+ *             is equivalent to calls to @pre_init@, @pre_ofbsetkey@   \
+ *             and @pre_ofbsetiv@.                                     \
+ */                                                                    \
+                                                                       \
+extern void pre##_ofbinit(pre##_ofbctx */*ctx*/,                       \
+                         const void */*key*/, size_t /*sz*/,           \
+                         const void */*iv*/);                          \
+                                                                       \
+/* --- @pre_ofbencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_ofbctx *ctx@ = pointer to OFB context block        \
+ *             @const void *src@ = pointer to source data              \
+ *             @void *dest@ = pointer to destination data              \
+ *             @size_t sz@ = size of block to be encrypted             \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Encrypts or decrypts a block with a block cipher in OFB \
+ *             mode: encryption and decryption are the same in OFB.    \
+ *             The destination may be null to just churn the feedback  \
+ *             round for a bit.  The source may be null to use the     \
+ *             cipher as a random data generator.                      \
+ */                                                                    \
+                                                                       \
+extern void pre##_ofbencrypt(pre##_ofbctx */*ctx*/,                    \
+                            const void */*src*/, void */*dest*/,       \
+                            size_t /*sz*/);                            \
+                                                                       \
+/* --- @pre_ofbrand@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @const void *k@ = pointer to key material               \
+ *             @size_t sz@ = size of key material                      \
+ *                                                                     \
+ * Returns:    Pointer to generic random number generator interface.   \
+ *                                                                     \
+ * Use:                Creates a random number interface wrapper around an     \
+ *             OFB-mode block cipher.                                  \
+ */                                                                    \
+                                                                       \
+extern grand *pre##_ofbrand(const void */*k*/, size_t /*sz*/);         \
+                                                                       \
+/* --- Generic cipher interface --- */                                 \
+                                                                       \
+extern const gccipher pre##_ofb;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rc2-tab.h b/symm/rc2-tab.h
new file mode 100644 (file)
index 0000000..48b46e0
--- /dev/null
@@ -0,0 +1,78 @@
+/* -*-c-*-
+ *
+ * Substitution table for RC2
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_RC2_TAB_H
+#define CATACOMB_RC2_TAB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- S-box table -------------------------------------------------------*/
+
+#define RC2_PI {                                                       \
+  0xd9,        0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,                       \
+  0x28,        0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,                       \
+  0xc6,        0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,                       \
+  0x62,        0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,                       \
+  0x17,        0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,                       \
+  0x61,        0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,                       \
+  0xbd,        0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,                       \
+  0xf0,        0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,                       \
+  0x54,        0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,                       \
+  0x73,        0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,                       \
+  0x12,        0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,                       \
+  0x42,        0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,                       \
+  0x6f,        0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,                       \
+  0x27,        0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,                       \
+  0xf8,        0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,                       \
+  0x06,        0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,                       \
+  0x08,        0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,                       \
+  0x84,        0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,                       \
+  0x96,        0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,                       \
+  0x4b,        0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,                       \
+  0xc2,        0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,                       \
+  0x24,        0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,                       \
+  0x99,        0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,                       \
+  0xfc,        0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,                       \
+  0x2d,        0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,                       \
+  0x05,        0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,                       \
+  0xd3,        0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,                       \
+  0x63,        0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,                       \
+  0x0d,        0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,                       \
+  0xbb,        0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,                       \
+  0xc5,        0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,                       \
+  0x0a,        0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad                        \
+}
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rc2.c b/symm/rc2.c
new file mode 100644 (file)
index 0000000..4ea85b6
--- /dev/null
@@ -0,0 +1,327 @@
+/* -*-c-*-
+ *
+ * The RC2 block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "paranoia.h"
+#include "rc2.h"
+#include "rc2-tab.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet rc2_keysz[] = { KSZ_RANGE, RC2_KEYSZ, 1, 128, 1 };
+
+/*----- Important tables --------------------------------------------------*/
+
+static const octet pi[256] = RC2_PI;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rc2_braindamage@ --- *
+ *
+ * Arguments:  @rc2_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of key material in bytes
+ *             @unsigned eb@ = desired effective key size, in bits
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RC2 expanded key, and braindamages it to the
+ *             requested effective key size.  This is here for compatibility
+ *             reasons.  You should be using @rc2_init@ in normal code,
+ *             which doesn't actually apply braindamage.
+ */
+
+void rc2_braindamage(rc2_ctx *k, const void *buf, size_t sz, unsigned eb)
+{
+  unsigned t8;
+  uint16 tm;
+  unsigned i;
+  uint16 *kk;
+  octet l[128];
+
+  KSZ_ASSERT(rc2, sz);
+
+  /* --- Compute the braindamage parameters --- */
+
+  t8 = (eb + 7) / 8;
+  tm = 0xff & ((1 << (8 + eb - 8 * t8)) - 1);
+
+  /* --- Copy and expand the initial key --- */
+
+  if (sz > sizeof(l))
+    sz = sizeof(l);
+  memcpy(l, buf, sz);
+
+  for (i = sz; i < sizeof(l); i++)
+    l[i] = pi[U8(l[i - 1] + l[i - sz])];
+
+  /* --- Braindamage the key --- */
+
+  i = sizeof(l) - t8;
+  l[i] = pi[l[i] & tm];
+  while (i) {
+    i--;
+    l[i] = pi[U8(l[i + 1] ^ l[i + t8])];
+  }
+
+  /* --- Write it to the key block --- */
+
+  kk = k->k;
+  for (i = 0; i < sizeof(l); i += 2)
+    *kk++ = LOAD16_L(l + i);
+  BURN(l);
+}
+
+/* --- @rc2_init@ --- *
+ *
+ * Arguments:  @rc2_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of key material in bytes
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RC2 expanded key.  The effective key size is
+ *             set to be equal to the real key size, in bits.
+ */
+
+void rc2_init(rc2_ctx *k, const void *buf, size_t sz)
+{
+  rc2_braindamage(k, buf, sz, sz * 8);
+}
+
+/*----- Encryption and decryption -----------------------------------------*/
+
+#define MIX(a, b, c, d, r, kk) do {                                    \
+  a += *kk++ + (d & c) + (~d & b);                                     \
+  a = ROL16(a, r);                                                     \
+} while (0)
+
+#define MASH(a, d, k) do {                                             \
+  a += k[d & 63];                                                      \
+} while (0)
+
+#define UNMIX(a, b, c, d, r, kk) do {                                  \
+  a = ROR16(a, r);                                                     \
+  a -= *--kk + (d & c) + (~d & b);                                     \
+} while (0)
+
+#define UNMASH(a, d, k) do {                                           \
+  a -= k[d & 63];                                                      \
+} while (0)
+
+/* --- @rc2_eblk@, @rc2_dblk@ --- *
+ *
+ * Arguments:  @const rc2_ctx *k@ = pointer to RC2 context
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @const uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+void rc2_eblk(const rc2_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint16 a = U16(s[0] >>  0), b = U16(s[0] >> 16);
+  uint16 c = U16(s[1] >>  0), d = U16(s[1] >> 16);
+  const uint16 *kk = k->k;
+
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MASH(a, d, k->k); MASH(b, a, k->k);
+  MASH(c, b, k->k); MASH(d, c, k->k);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MASH(a, d, k->k); MASH(b, a, k->k);
+  MASH(c, b, k->k); MASH(d, c, k->k);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+  MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
+  MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
+
+  dst[0] = a | (b << 16); dst[1] = c | (d << 16);
+}
+
+void rc2_dblk(const rc2_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint16 a = U16(s[0] >>  0), b = U16(s[0] >> 16);
+  uint16 c = U16(s[1] >>  0), d = U16(s[1] >> 16);
+  const uint16 *kk = k->k + 64;
+
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMASH(d, c, k->k); UNMASH(c, b, k->k);
+  UNMASH(b, a, k->k); UNMASH(a, d, k->k);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMASH(d, c, k->k); UNMASH(c, b, k->k);
+  UNMASH(b, a, k->k); UNMASH(a, d, k->k);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+  UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
+  UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
+
+  dst[0] = a | (b << 16); dst[1] = c | (d << 16);
+}
+
+/*----- Custom test rig ---------------------------------------------------*
+ *
+ * I need to test the braindamage feature.
+ */
+
+#ifdef TEST_RIG
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+static int verify(dstr *v)
+{
+  rc2_ctx k;
+  uint32 p[RC2_BLKSZ / 4];
+  uint32 c[RC2_BLKSZ / 4];
+  uint32 d[RC2_BLKSZ / 4];
+  dstr b = DSTR_INIT;
+  unsigned bd = *(unsigned *)v[1].buf;
+  int ok = 1;
+
+  /* --- Initialize the key buffer --- */
+
+  dstr_ensure(&b, RC2_BLKSZ);
+  b.len = RC2_BLKSZ;
+  rc2_braindamage(&k, v[0].buf, v[0].len, bd);
+  BLKC_LOAD(RC2, p, v[2].buf);
+  BLKC_LOAD(RC2, c, v[3].buf);
+
+  /* --- Test encryption --- */
+
+  BLKC_MOVE(RC2, d, p);
+  rc2_eblk(&k, d, d);
+  BLKC_STORE(RC2, b.buf, d);
+  if (memcmp(b.buf, v[3].buf, RC2_BLKSZ)) {
+    ok = 0;
+    printf("\nfail encryption:"
+          "\n\tkey        = ");
+    type_hex.dump(&v[0], stdout);
+    printf("\n\tbraindamage= %u", bd);
+    printf("\n\tplaintext  = "); type_hex.dump(&v[2], stdout);
+    printf("\n\texpected   = "); type_hex.dump(&v[3], stdout);
+    printf("\n\tcalculated = "); type_hex.dump(&b, stdout);
+    putchar('\n');
+  }
+
+  /* --- Test decryption --- */
+
+  BLKC_MOVE(RC2, d, c);
+  rc2_dblk(&k, d, d);
+  BLKC_STORE(RC2, b.buf, d);
+  if (memcmp(b.buf, v[2].buf, RC2_BLKSZ)) {
+    ok = 0;
+    printf("\nfail decryption:"
+          "\n\tkey        = ");
+    type_hex.dump(&v[0], stdout);
+    printf("\n\tbraindamage= %u", bd);
+    printf("\n\tciphertext = "); type_hex.dump(&v[3], stdout);
+    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
+    printf("\n\tcalculated = "); type_hex.dump(&b, stdout);
+    putchar('\n');
+  }
+
+  /* --- Return --- */
+
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "rc2", verify, { &type_hex, &type_int, &type_hex, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/rc2");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rc2.h b/symm/rc2.h
new file mode 100644 (file)
index 0000000..8b72a8b
--- /dev/null
@@ -0,0 +1,128 @@
+/* -*-c-*-
+ *
+ * The RC2 block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the RC2 block cipher -------------------------------------*
+ *
+ * RC2 was designed by Ron Rivest, and for a long time was a trade secret of
+ * RSA Data Security Inc.  Like RC4, it leaked out, and has now been
+ * described in RFC2268.  The RC2 key schedule is known to have some
+ * weaknesses, although I'm not aware of any major results against the cipher
+ * itself.  I'm also not aware of any legal problems with using the RC2
+ * cipher.
+ *
+ * The oddest feature in the cipher is the key schedule.  It expands the
+ * initial key material to 128 bytes, and then `brain-damages' it, according
+ * to a supplied `effective key-bits' parameter, before expanding the
+ * remaining key material back into the buffer.
+ *
+ * The key schedule allows second preimages to be computed trivially.
+ */
+
+#ifndef CATACOMB_RC2_H
+#define CATACOMB_RC2_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define RC2_BLKSZ 8
+#define RC2_KEYSZ 16
+#define RC2_CLASS (N, L, 64)
+
+extern const octet rc2_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rc2_ctx {
+  uint16 k[64];
+} rc2_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rc2_braindamage@ --- *
+ *
+ * Arguments:  @rc2_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of key material in bytes
+ *             @unsigned eb@ = desired effective key size, in bits
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RC2 expanded key, and braindamages it to the
+ *             requested effective key size.  This is here for compatibility
+ *             reasons.  You should be using @rc2_init@ in normal code,
+ *             which doesn't actually apply braindamage.
+ */
+
+extern void rc2_braindamage(rc2_ctx */*k*/, const void */*buf*/,
+                           size_t /*sz*/, unsigned /*eb*/);
+
+/* --- @rc2_init@ --- *
+ *
+ * Arguments:  @rc2_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of key material in bytes
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RC2 expanded key.  The effective key size is
+ *             set to be equal to the real key size, in bits.
+ */
+
+extern void rc2_init(rc2_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @rc2_eblk@, @rc2_dblk@ --- *
+ *
+ * Arguments:  @const rc2_ctx *k@ = pointer to RC2 context
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @const uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void rc2_eblk(const rc2_ctx */*k*/,
+                    const uint32 */*s*/, uint32 */*dst*/);
+extern void rc2_dblk(const rc2_ctx */*k*/,
+                    const uint32 */*s*/, uint32 */*dst*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rc4.c b/symm/rc4.c
new file mode 100644 (file)
index 0000000..0d02062
--- /dev/null
@@ -0,0 +1,367 @@
+/* -*-c-*-
+ *
+ * The alleged RC4 stream cipher
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#include "arena.h"
+#include "gcipher.h"
+#include "grand.h"
+#include "paranoia.h"
+#include "rc4.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet rc4_keysz[] = { KSZ_RANGE, RC4_KEYSZ, 1, 255, 1 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rc4_addkey@ --- *
+ *
+ * Arguments:  @rc4_ctx *ctx@ = pointer to context to key
+ *             @const void *k@ = pointer to key data to use
+ *             @size_t sz@ = size of the key data
+ *
+ * Returns:    ---
+ *
+ * Use:                Mixes key data with an RC4 context.  The RC4 context is not
+ *             reset before mixing.  This may be used to mix new key
+ *             material with an existing RC4 context.
+ */
+
+void rc4_addkey(rc4_ctx *ctx, const void *k, size_t sz)
+{
+  unsigned i, j;
+  const octet *p = k, *q = p + sz;
+
+  KSZ_ASSERT(rc4, sz);
+
+  for (i = j = 0; i < 256; i++) {
+    unsigned si = ctx->s[i];
+    j = (j + si + *p++) & 0xff;
+    ctx->s[i] = ctx->s[j];
+    ctx->s[j] = si;
+    if (p == q)
+      p = k;
+  }
+
+  ctx->i = ctx->j = 0;
+}
+
+/* --- @rc4_init@ --- *
+ *
+ * Arguments:  @rc4_ctx *ctx@ = pointer to context to initialize
+ *             @const void *k@ = pointer to key data to use
+ *             @size_t sz@ = size of the key data
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RC4 context ready for use.
+ */
+
+void rc4_init(rc4_ctx *ctx, const void *k, size_t sz)
+{
+  unsigned i;
+
+  for (i = 0; i < 256; i++)
+    ctx->s[i] = i;
+  ctx->f = 0;
+  rc4_addkey(ctx, k, sz);
+}
+
+/* --- @rc4_encrypt@ --- *
+ *
+ * Arguments:  @rc4_ctx *ctx@ = pointer to context to use
+ *             @const void *src@ = pointer to the source block
+ *             @void *dest@ = pointer to the destination block
+ *             @size_t sz@ = size of the block
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts or decrypts a block of data.  The destination may
+ *             be null to just grind the generator around for a while.  It's
+ *             recommended that you say `@rc4_encrypt(&ctx, 0, 0, 1024)@'
+ *             after initializing a new context, to prevent keystream
+ *             guessing attacks.  The source may be null to just extract a
+ *             big lump of data from the generator.
+ */
+
+void rc4_encrypt(rc4_ctx *ctx, const void *src, void *dest, size_t sz)
+{
+  const octet *s = src;
+  octet *d = dest;
+
+  if (!d)
+    RC4_OPEN(ctx, while (sz) { unsigned x; RC4_BYTE(x); sz--; });
+  else if (!s)
+    RC4_OPEN(ctx, while (sz) { RC4_BYTE(*d++); sz--; });
+  else
+    RC4_OPEN(ctx,
+            while (sz) { unsigned x; RC4_BYTE(x); *d++ = *s++ ^ x; sz--; });
+}
+
+/*----- Generic cipher interface ------------------------------------------*/
+
+typedef struct gctx {
+  gcipher c;
+  rc4_ctx rc4;
+} gctx;
+
+static const gcipher_ops gops;
+
+static gcipher *ginit(const void *k, size_t sz)
+{
+  gctx *g = S_CREATE(gctx);
+  g->c.ops = &gops;
+  rc4_init(&g->rc4, k, sz);
+  return (&g->c);
+}
+
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
+{
+  gctx *g = (gctx *)c;
+  rc4_encrypt(&g->rc4, s, t, sz);
+}
+
+static void gdestroy(gcipher *c)
+{
+  gctx *g = (gctx *)c;
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static const gcipher_ops gops = {
+  &rc4,
+  gencrypt, gencrypt, gdestroy, 0, 0
+};
+
+const gccipher rc4 = {
+  "rc4", rc4_keysz, 0,
+  ginit
+};
+
+/*----- Generic random number generator interface -------------------------*/
+
+typedef struct grctx {
+  grand r;
+  rc4_ctx rc4;
+} grctx;
+
+static void grdestroy(grand *r)
+{
+  grctx *g = (grctx *)r;
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static int grmisc(grand *r, unsigned op, ...)
+{
+  grctx *g = (grctx *)r;
+  va_list ap;
+  int rc = 0;
+  uint32 i;
+  octet buf[4];
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDBLOCK:
+       case GRAND_SEEDRAND:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT:
+      i = va_arg(ap, unsigned);
+      STORE32(buf, i);
+      rc4_addkey(&g->rc4, buf, sizeof(buf));
+      break;
+    case GRAND_SEEDUINT32:
+      i = va_arg(ap, uint32);
+      STORE32(buf, i);
+      rc4_addkey(&g->rc4, buf, sizeof(buf));
+      break;
+    case GRAND_SEEDBLOCK: {
+      const void *p = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      rc4_addkey(&g->rc4, p, sz);
+    } break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      octet buf[16];
+      rr->ops->fill(rr, buf, sizeof(buf));
+      rc4_addkey(&g->rc4, buf, sizeof(buf));
+    } break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static octet grbyte(grand *r)
+{
+  grctx *g = (grctx *)r;
+  octet o;
+  RC4_OPEN(&g->rc4, RC4_BYTE(o););
+  return (o);
+}
+
+static uint32 grword(grand *r)
+{
+  grctx *g = (grctx *)r;
+  octet b[4];
+  int i;
+  RC4_OPEN(&g->rc4,
+          for (i = 0; i < sizeof(b); i++)
+            RC4_BYTE(b[i]););
+  return (LOAD32(b));
+}
+
+static void grfill(grand *r, void *p, size_t sz)
+{
+  grctx *g = (grctx *)r;
+  rc4_encrypt(&g->rc4, 0, p, sz);
+}
+
+static const grand_ops grops = {
+  "rc4",
+  GRAND_CRYPTO, 0,
+  grmisc, grdestroy,
+  grword, grbyte, grword, grand_range, grfill
+};
+
+/* --- @rc4_rand@ --- *
+ *
+ * Arguments:  @const void *k@ = pointer to key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a random number interface wrapper around an
+ *             OFB-mode block cipher.
+ */
+
+grand *rc4_rand(const void *k, size_t sz)
+{
+  grctx *g = S_CREATE(grctx);
+  g->r.ops = &grops;
+  rc4_init(&g->rc4, k, sz);
+  return (&g->r);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+#include <string.h>
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+static int v_encrypt(dstr *v)
+{
+  rc4_ctx ctx;
+  dstr d = DSTR_INIT;
+  int ok = 1;
+
+  rc4_init(&ctx, v[0].buf, v[0].len);
+  dstr_ensure(&d, v[1].len);
+  d.len = v[1].len;
+  rc4_encrypt(&ctx, v[1].buf, d.buf, d.len);
+
+  if (memcmp(v[2].buf, d.buf, d.len) != 0) {
+    ok = 0;
+    printf("\nfail encryption:"
+          "\n\tkey        = ");
+    type_hex.dump(&v[0], stdout);
+    printf("\n\tplaintext  = "); type_hex.dump(&v[1], stdout);
+    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
+    printf("\n\tcalculated = "); type_hex.dump(&d, stdout);
+    putchar('\n');
+  }
+
+  return (ok);
+}
+
+static int v_generate(dstr *v)
+{
+  rc4_ctx ctx;
+  dstr d = DSTR_INIT;
+  int ok = 1;
+
+  rc4_init(&ctx, v[0].buf, v[0].len);
+  rc4_encrypt(&ctx, 0, 0, *(int *)v[1].buf);
+  dstr_ensure(&d, v[2].len);
+  d.len = v[2].len;
+  rc4_encrypt(&ctx, 0, d.buf, d.len);
+
+  if (memcmp(v[2].buf, d.buf, d.len) != 0) {
+    ok = 0;
+    printf("\nfail generation:"
+          "\n\tkey        = ");
+    type_hex.dump(&v[0], stdout);
+    printf("\n\tskip len   = %i", *(int *)v[1].buf);
+    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
+    printf("\n\tcalculated = "); type_hex.dump(&d, stdout);
+    putchar('\n');
+  }
+
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "rc4-encrypt", v_encrypt, { &type_hex, &type_hex, &type_hex, 0 } },
+  { "rc4-generate", v_generate, { &type_hex, &type_int, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/rc4");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rc4.h b/symm/rc4.h
new file mode 100644 (file)
index 0000000..caeeadb
--- /dev/null
@@ -0,0 +1,195 @@
+/* -*-c-*-
+ *
+ * The alleged RC4 stream cipher
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on RC4 ------------------------------------------------------*
+ *
+ * RC4 is a stream cipher desgigned by Ron Rivest.  For a while RC4 was a
+ * trade secret of RSA Data Security, Inc., but somehow source code for a
+ * cipher which interworks with RC4 was posted to the Cypherpunks mailing
+ * list.
+ */
+
+#ifndef CATACOMB_RC4_H
+#define CATACOMB_RC4_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rc4_ctx {
+  unsigned i, j;                       /* Indices into the @S@ table */
+  unsigned f;                          /* Flags word */
+  octet s[256];                                /* The ever-changing @S@ table */
+} rc4_ctx;
+
+#define RC4F_OPEN 1u
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @RC4_OPEN@ --- *
+ *
+ * Arguments:  @ctx@ = pointer to an RC4 context
+ *             @guts@ = code to perform within the RC4 context
+ *
+ * Use:                Performs some code within an RC4 context.  Some of the
+ *             parameters are extracted from the context and held in local
+ *             variables for speed.  Multiple calls to @RC4_BYTE@ may be
+ *             made within the open context.  A context must only be
+ *             opened once at a time.
+ */
+
+#define RC4_OPEN(ctx, guts) do {                                       \
+  unsigned _rc4_i = (ctx)->i;                                          \
+  unsigned _rc4_j = (ctx)->j;                                          \
+  octet *_rc4_s = (ctx)->s;                                            \
+                                                                       \
+  assert(((void)"RC4 context may only be opened once at a time",       \
+         ((ctx)->f & RC4F_OPEN) == 0));                                \
+  (ctx)->f |= RC4F_OPEN;                                               \
+                                                                       \
+  guts                                                                 \
+                                                                       \
+  (ctx)->f &= ~RC4F_OPEN;                                              \
+  (ctx)->i = _rc4_i;                                                   \
+  (ctx)->j = _rc4_j;                                                   \
+} while (0)
+
+/* --- @RC4_BYTE@ --- *
+ *
+ * Arguments:  @x@ = output variable to set
+ *
+ * Use:                Extracts an octet from the lexically innermost open RC4
+ *             context and places it in the variable @x@.
+ */
+
+#define RC4_BYTE(x) do {                                               \
+  unsigned _si, _sj;                                                   \
+  _rc4_i = (_rc4_i + 1) & 0xff;                                                \
+  _si = _rc4_s[_rc4_i];                                                        \
+  _rc4_j = (_rc4_j + _si) & 0xff;                                      \
+  _sj = _rc4_s[_rc4_j];                                                        \
+  _rc4_s[_rc4_i] = _sj;                                                        \
+  _rc4_s[_rc4_j] = _si;                                                        \
+  (x) = _rc4_s[(_si + _sj) & 0xff];                                    \
+} while (0)
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rc4_addkey@ --- *
+ *
+ * Arguments:  @rc4_ctx *ctx@ = pointer to context to key
+ *             @const void *k@ = pointer to key data to use
+ *             @size_t sz@ = size of the key data
+ *
+ * Returns:    ---
+ *
+ * Use:                Mixes key data with an RC4 context.  The RC4 context is not
+ *             reset before mixing.  This may be used to mix new key
+ *             material with an existing RC4 context.
+ */
+
+extern void rc4_addkey(rc4_ctx */*ctx*/, const void */*k*/, size_t /*sz*/);
+
+/* --- @rc4_init@ --- *
+ *
+ * Arguments:  @rc4_ctx *ctx@ = pointer to context to initialize
+ *             @const void *k@ = pointer to key data to use
+ *             @size_t sz@ = size of the key data
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RC4 context ready for use.
+ */
+
+extern void rc4_init(rc4_ctx */*ctx*/, const void */*k*/, size_t /*sz*/);
+
+/* --- @rc4_encrypt@ --- *
+ *
+ * Arguments:  @rc4_ctx *ctx@ = pointer to context to use
+ *             @const void *src@ = pointer to the source block
+ *             @void *dest@ = pointer to the destination block
+ *             @size_t sz@ = size of the block
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts or decrypts a block of data.  The destination may
+ *             be null to just grind the generator around for a while.  It's
+ *             recommended that you say `@rc4_encrypt(&ctx, 0, 0, 1024)@'
+ *             after initializing a new context, to prevent keystream
+ *             guessing attacks.  The source may be null to just extract a
+ *             big lump of data from the generator.
+ */
+
+extern void rc4_encrypt(rc4_ctx */*ctx*/,
+                       const void */*src*/, void */*dest*/,
+                       size_t /*sz*/);
+
+/*----- Generic cipher interface ------------------------------------------*/
+
+#define RC4_KEYSZ 16
+extern const octet rc4_keysz[];
+
+extern const gccipher rc4;
+
+/*----- Generic random number generator interface -------------------------*/
+
+/* --- @rc4_rand@ --- *
+ *
+ * Arguments:  @const void *k@ = pointer to key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a random number interface wrapper around an
+ *             OFB-mode block cipher.
+ */
+
+extern grand *rc4_rand(const void */*k*/, size_t /*sz*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rc5.c b/symm/rc5.c
new file mode 100644 (file)
index 0000000..634f0b7
--- /dev/null
@@ -0,0 +1,230 @@
+/* -*-c-*-
+ *
+ * The RC5-32/12 block cipher
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+
+#include "arena.h"
+#include "blkc.h"
+#include "gcipher.h"
+#include "rc5.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet rc5_keysz[] = { KSZ_RANGE, RC5_KEYSZ, 1, 255, 1 };
+
+/*----- Internal magical constants ----------------------------------------*/
+
+#define T ((RC5_ROUNDS + 1) * 2)
+#define P 0xb7e15163
+#define Q 0x9e3779b9
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rc5_init@ --- *
+ *
+ * Arguments:  @rc5_ctx *k@ = pointer to a key block
+ *             @const void *sbuf@ = pointer to key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RC5 key block.
+ */
+
+void rc5_init(rc5_ctx *k, const void *sbuf, size_t sz)
+{
+  uint32 *l;
+  size_t w;
+
+  /* --- Set up the @L@ table --- *
+   *
+   * This is slightly unfortunately defined.
+   */
+
+  KSZ_ASSERT(rc5, sz);
+
+  {
+    int i;
+    const octet *p = sbuf;
+
+    /* --- Create the buffer --- */
+
+    w = (sz + 3) / 4;
+    l = XS_ALLOC(w * sizeof(uint32));
+
+    /* --- Extract the key material --- */
+
+    for (i = 0; sz > 3; i++) {
+      l[i] = LOAD32_L(p);
+      p += 4;
+      sz -= 4;
+    }
+
+    /* --- Fix up the tail end --- */
+
+    if (sz) {
+      uint32 x = U8(*p++);
+      if (sz > 1) x |= (U8(*p++) <<  8);
+      if (sz > 2) x |= (U8(*p++) << 16);
+      l[i] = x;
+    }
+  }
+
+  /* --- Initialize the @S@ table --- */
+
+  {
+    int i;
+
+    k->s[0] = P;
+    for (i = 1; i < T; i++)
+      k->s[i] = k->s[i - 1] + Q;
+  }
+
+  /* --- Mix in the key --- */
+
+  {
+    int m = 3 * (w > T ? w : T);
+    int i, j, c;
+    uint32 a, b;
+
+    for (c = i = j = a = b = 0; c < m; c++) {
+      uint32 x;
+
+      x = k->s[i] + a + b;
+      k->s[i] = a = ROL32(x, 3);
+      i++; if (i >= T) i = 0;
+
+      x = l[j] + a + b;
+      l[j] = b = ROL32(x, a + b);
+      j++; if (j >= w) j = 0;
+    }
+  }
+
+  memset(l, 0, w * sizeof(uint32));
+  XS_FREE(l);
+}
+
+/* --- @EROUND@, @DROUND@ --- */
+
+#define EROUND(x, y, k) do {                                           \
+  uint32 _x;                                                           \
+  _x = x ^ y; x = ROL32(_x, y) + k[0];                                 \
+  _x = y ^ x; y = ROL32(_x, x) + k[1];                                 \
+  k += 2;                                                              \
+} while (0)
+
+#define DROUND(x, y, k) do {                                           \
+  uint32 _x;                                                           \
+  k -= 2;                                                              \
+  _x = y - k[1]; y = ROR32(_x, x) ^ x;                                 \
+  _x = x - k[0]; x = ROR32(_x, y) ^ y;                                 \
+} while (0)
+
+/* --- @EBLK@, @DBLK@ --- */
+
+#define EBLK(a, b, c, d, k) do {                                       \
+  uint32 _l, _r;                                                       \
+  const uint32 *_k = (k)->s;                                           \
+                                                                       \
+  _l = (a) + _k[0];                                                    \
+  _r = (b) + _k[1];                                                    \
+  _k += 2;                                                             \
+                                                                       \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  EROUND(_l, _r, _k);                                                  \
+  (c) = _l;                                                            \
+  (d) = _r;                                                            \
+} while (0)
+
+#define DBLK(a, b, c, d, k) do {                                       \
+  uint32 _l, _r;                                                       \
+  const uint32 *_k = (k)->s + T;                                       \
+                                                                       \
+  _l = (a);                                                            \
+  _r = (b);                                                            \
+                                                                       \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+  DROUND(_l, _r, _k);                                                  \
+                                                                       \
+  _k -= 2;                                                             \
+  (d) = _r - _k[1];                                                    \
+  (c) = _l - _k[0];                                                    \
+} while (0)
+
+/* --- @rc5_eblk@, @rc5_dblk@ --- *
+ *
+ * Arguments:  @const rc5_ctx *k@ = pointer to RC5 context block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 *d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low level block encryption and decryption.
+ */
+
+void rc5_eblk(const rc5_ctx *k, const uint32 *s, uint32 *d)
+{
+  EBLK(s[0], s[1], d[0], d[1], k);
+}
+
+void rc5_dblk(const rc5_ctx *k, const uint32 *s, uint32 *d)
+{
+  DBLK(s[0], s[1], d[0], d[1], k);
+}
+
+/* --- Test rig --- */
+
+BLKC_TEST(RC5, rc5)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rc5.h b/symm/rc5.h
new file mode 100644 (file)
index 0000000..c21b56d
--- /dev/null
@@ -0,0 +1,101 @@
+/* -*-c-*-
+ *
+ * The RC5-32/12 block cipher
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on the RC5 block cipher -------------------------------------*
+ *
+ * RC5 was designed by Ron Rivest as a test vehicle for the use of data-
+ * dependent rotations in cryptographic transformations.  The algorithm is
+ * covered by a patent held by RSA Security Inc. (US Patent# 5,724,428).
+ * It's vulnerable to some clever differential attacks, which can break it in
+ * about %$2^{44}$% chosen plaintexts.  I don't recommend the use of this
+ * cipher.
+ */
+
+#ifndef CATACOMB_RC5_H
+#define CATACOMB_RC5_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define RC5_ROUNDS 12
+#define RC5_KEYSZ 10
+#define RC5_BLKSZ 8
+#define RC5_CLASS (N, L, 64)
+
+extern const octet rc5_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rc5_ctx {
+  uint32 s[2 * (RC5_ROUNDS + 1)];
+} rc5_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rc5_init@ --- *
+ *
+ * Arguments:  @rc5_ctx *k@ = pointer to a key block
+ *             @const void *sbuf@ = pointer to key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an RC5 key block.
+ */
+
+extern void rc5_init(rc5_ctx */*k*/, const void */*sbuf*/, size_t /*sz*/);
+
+/* --- @rc5_eblk@, @rc5_dblk@ --- *
+ *
+ * Arguments:  @const rc5_ctx *k@ = pointer to RC5 context block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 *d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low level block encryption and decryption.
+ */
+
+extern void rc5_eblk(const rc5_ctx */*k*/,
+                    const uint32 */*s*/, uint32 */*d*/);
+extern void rc5_dblk(const rc5_ctx */*k*/,
+                    const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rijndael-base.c b/symm/rijndael-base.c
new file mode 100644 (file)
index 0000000..d3ec0d6
--- /dev/null
@@ -0,0 +1,133 @@
+/* -*-c-*-
+ *
+ * Low-level stuff for all Rijndael block sizes
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "rijndael.h"
+#include "rijndael-base.h"
+#include "rijndael-tab.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet rijndael_keysz[] = { KSZ_RANGE, RIJNDAEL_KEYSZ, 4, 32, 4 };
+
+/*----- Constant tables ---------------------------------------------------*/
+
+const octet rijndael_s[256] = RIJNDAEL_S;
+const octet rijndael_si[256] = RIJNDAEL_SI;
+const uint32 rijndael_t[4][256] = RIJNDAEL_T;
+const uint32 rijndael_ti[4][256] = RIJNDAEL_TI;
+const uint32 rijndael_u[4][256] = RIJNDAEL_U;
+const octet rijndael_rcon[] = RIJNDAEL_RCON;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rijndael_setup@ --- *
+ *
+ * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
+ *             @unsigned nb@ = number of words in the block
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level key-scheduling.
+ */
+
+void rijndael_setup(rijndael_ctx *k, unsigned nb, const void *buf, size_t sz)
+{
+  unsigned nk, nr, nw;
+  unsigned i, j, jj;
+  const octet *p;
+  uint32 ww;
+
+  /* --- Sort out the key size --- */
+
+  KSZ_ASSERT(rijndael, sz);
+  nk = sz / 4;
+
+  /* --- Select the number of rounds --- */
+
+  nr = (nk > nb ? nk : nb) + 6;
+  if (nr < 10)
+    nr = 10;
+  k->nr = nr;
+
+  /* --- Fetch the first key words out --- */
+
+  p = buf;
+  for (i = 0; i < nk; i++) {
+    k->w[i] = LOAD32_B(p);
+    p += 4;
+  }
+
+  /* --- Expand this material to fill the rest of the table --- */
+
+  nw = (nr + 1) * nb;
+  ww = k->w[i - 1];
+  p = RCON;
+  for (; i < nw; i++) {
+    uint32 w = k->w[i - nk];
+    if (i % nk == 0) {
+      ww = ROL32(ww, 8);
+      w ^= SUB(S, ww, ww, ww, ww) ^ (*p++ << 24);
+    } else if (nk > 6 && i % nk == 4)
+      w ^= SUB(S, ww, ww, ww, ww);
+    else
+      w ^= ww;
+    k->w[i] = ww = w;
+  }
+
+  /* --- Make the decryption keys --- */
+
+  j = nw; i = 0;
+
+  j -= nb; jj = 0;
+  for (; i < nb; i++)
+    k->wi[i] = k->w[j + jj++];
+
+  for (; i < nw - nb; i += nb) {
+    j -= nb;
+    for (jj = 0; jj < nb; jj++) {
+      uint32 w = k->w[j + jj];
+      k->wi[i + jj] = MIX(U, w, w, w, w);
+    }
+  }
+
+  j -= nb; jj = 0;
+  for (; i < nw; i++)
+    k->wi[i] = k->w[j + jj++];
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rijndael-base.h b/symm/rijndael-base.h
new file mode 100644 (file)
index 0000000..b213b13
--- /dev/null
@@ -0,0 +1,71 @@
+/* -*-c-*-
+ *
+ * Internal header for Rijndael implementation
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_RIJNDAEL_BASE_H
+#define CATACOMB_RIJNDAEL_BASE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Constant tables ---------------------------------------------------*/
+
+extern const octet rijndael_s[256];
+extern const octet rijndael_si[256];
+extern const uint32 rijndael_t[4][256];
+extern const uint32 rijndael_ti[4][256];
+extern const uint32 rijndael_u[4][256];
+extern const octet rijndael_rcon[];
+
+#define S rijndael_s
+#define SI rijndael_si
+#define T rijndael_t
+#define TI rijndael_ti
+#define U rijndael_u
+#define RCON rijndael_rcon
+
+/*----- Handy macros ------------------------------------------------------*/
+
+#define SUB(s, a, b, c, d)                                             \
+  (s[U8((a) >> 24)] << 24 | s[U8((b) >> 16)] << 16 |                   \
+   s[U8((c) >> 8)] <<  8 | s[U8((d) >>  0)] <<  0)
+
+#define MIX(t, a, b, c, d)                                             \
+   (t[0][U8((a) >> 24)] ^ t[1][U8((b) >> 16)] ^                                \
+    t[2][U8((c) >>  8)] ^ t[3][U8((d) >>  0)])
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rijndael-mktab.c b/symm/rijndael-mktab.c
new file mode 100644 (file)
index 0000000..4260de6
--- /dev/null
@@ -0,0 +1,368 @@
+/* -*-c-*-
+ *
+ * Build precomputed tables for the Rijndael block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Magic variables ---------------------------------------------------*/
+
+static octet s[256], si[256];
+static uint32 t[4][256], ti[4][256];
+static uint32 u[4][256];
+static octet rc[32];
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mul@ --- *
+ *
+ * Arguments:  @unsigned x, y@ = polynomials over %$\gf{2^8}$%
+ *             @unsigned m@ = modulus
+ *
+ * Returns:    The product of two polynomials.
+ *
+ * Use:                Computes a product of polynomials, quite slowly.
+ */
+
+static unsigned mul(unsigned x, unsigned y, unsigned m)
+{
+  unsigned a = 0;
+  unsigned i;
+
+  for (i = 0; i < 8; i++) {
+    if (y & 1)
+      a ^= x;
+    y >>= 1;
+    x <<= 1;
+    if (x & 0x100)
+      x ^= m;
+  }
+
+  return (a);
+}
+
+/* --- @sbox@ --- *
+ *
+ * Build the S-box.
+ *
+ * This is built from inversion in the multiplicative group of
+ * %$\gf{2^8}[x]/(p(x))$%, where %$p(x) = x^8 + x^4 + x^3 + x + 1$%, followed
+ * by an affine transformation treating inputs as vectors over %$\gf{2}$%.
+ * The result is a horrible function.
+ *
+ * The inversion is done slightly sneakily, by building log and antilog
+ * tables.  Let %$a$% be an element of the finite field.  If the inverse of
+ * %$a$% is %$a^{-1}$%, then %$\log a a^{-1} = 0$%.  Hence
+ * %$\log a = -\log a^{-1}$%.  This saves fiddling about with Euclidean
+ * algorithm.
+ */
+
+#define S_MOD 0x11b
+
+static void sbox(void)
+{
+  octet log[256], alog[256];
+  unsigned x;
+  unsigned i;
+  unsigned g;
+
+  /* --- Find a suitable generator, and build log tables --- */
+
+  log[0] = 0;
+  for (g = 2; g < 256; g++) {
+    x = 1;
+    for (i = 0; i < 256; i++) {
+      log[x] = i;
+      alog[i] = x;
+      x = mul(x, g, S_MOD);
+      if (x == 1 && i != 254)
+       goto again;
+    }
+    goto done;
+  again:;
+  }
+  fprintf(stderr, "couldn't find generator\n");
+  exit(EXIT_FAILURE);
+done:;
+
+  /* --- Now grind through and do the affine transform --- *
+   *
+   * The matrix multiply is an AND and a parity op.  The add is an XOR.
+   */
+
+  for (i = 0; i < 256; i++) {
+    unsigned j;
+    unsigned m = 0xf8;
+    unsigned v = i ? alog[255 - log[i]] : 0;
+
+    assert(i == 0 || mul(i, v, S_MOD) == 1);
+
+    x = 0;
+    for (j = 0; j < 8; j++) {
+      unsigned r;
+      r = v & m;
+      r = (r >> 4) ^ r;
+      r = (r >> 2) ^ r;
+      r = (r >> 1) ^ r;
+      x = (x << 1) | (r & 1);
+      m = ROR8(m, 1);
+    }
+    x ^= 0x63;
+    s[i] = x;
+    si[x] = i;
+  }
+}
+
+/* --- @tbox@ --- *
+ *
+ * Construct the t tables for doing the round function efficiently.
+ */
+
+static void tbox(void)
+{
+  unsigned i;
+
+  for (i = 0; i < 256; i++) {
+    uint32 a, b, c, d;
+    uint32 w;
+
+    /* --- Build a forwards t-box entry --- */
+
+    a = s[i];
+    b = a << 1; if (b & 0x100) b ^= S_MOD;
+    c = a ^ b;
+    w = (c << 0) | (a << 8) | (a << 16) | (b << 24);
+    t[0][i] = w;
+    t[1][i] = ROR32(w, 8);
+    t[2][i] = ROR32(w, 16);
+    t[3][i] = ROR32(w, 24);
+
+    /* --- Build a backwards t-box entry --- */
+
+    a = mul(si[i], 0x0e, S_MOD);
+    b = mul(si[i], 0x09, S_MOD);
+    c = mul(si[i], 0x0d, S_MOD);
+    d = mul(si[i], 0x0b, S_MOD);
+    w = (d << 0) | (c << 8) | (b << 16) | (a << 24);
+    ti[0][i] = w;
+    ti[1][i] = ROR32(w, 8);
+    ti[2][i] = ROR32(w, 16);
+    ti[3][i] = ROR32(w, 24);
+  }
+}
+
+/* --- @ubox@ --- *
+ *
+ * Construct the tables for performing the decryption key schedule.
+ */
+
+static void ubox(void)
+{
+  unsigned i;
+
+  for (i = 0; i < 256; i++) {
+    uint32 a, b, c, d;
+    uint32 w;
+    a = mul(i, 0x0e, S_MOD);
+    b = mul(i, 0x09, S_MOD);
+    c = mul(i, 0x0d, S_MOD);
+    d = mul(i, 0x0b, S_MOD);
+    w = (d << 0) | (c << 8) | (b << 16) | (a << 24);
+    u[0][i] = w;
+    u[1][i] = ROR32(w, 8);
+    u[2][i] = ROR32(w, 16);
+    u[3][i] = ROR32(w, 24);
+  }
+}
+
+/* --- Round constants --- */
+
+static void rcon(void)
+{
+  unsigned r = 1;
+  int i;
+
+  for (i = 0; i < sizeof(rc); i++) {
+    rc[i] = r;
+    r <<= 1;
+    if (r & 0x100)
+      r ^= S_MOD;
+  }
+}
+
+/* --- @main@ --- */
+
+int main(void)
+{
+  int i, j;
+
+  puts("\
+/* -*-c-*-\n\
+ *\n\
+ * Rijndael tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_RIJNDAEL_TAB_H\n\
+#define CATACOMB_RIJNDAEL_TAB_H\n\
+");
+
+  /* --- Write out the S-box --- */
+
+  sbox();
+  fputs("\
+/* --- The byte substitution and its inverse --- */\n\
+\n\
+#define RIJNDAEL_S {                                                   \\\n\
+  ", stdout);
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", s[i]);
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  fputs("\
+#define RIJNDAEL_SI {                                                  \\\n\
+  ", stdout);
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", si[i]);
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Write out the big t tables --- */
+
+  tbox();
+  fputs("\
+/* --- The big round tables --- */\n\
+\n\
+#define RIJNDAEL_T {                                                   \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08lx", (unsigned long)t[j][i]);
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  fputs("\
+#define RIJNDAEL_TI {                                                  \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08lx", (unsigned long)ti[j][i]);
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  /* --- Write out the big u tables --- */
+
+  ubox();
+  fputs("\
+/* --- The decryption key schedule tables --- */\n\
+\n\
+#define RIJNDAEL_U {                                                   \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08lx", (unsigned long)u[j][i]);
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  /* --- Round constants --- */
+
+  rcon();
+  fputs("\
+/* --- The round constants --- */\n\
+\n\
+#define RIJNDAEL_RCON {                                                        \\\n\
+  ", stdout);
+  for (i = 0; i < sizeof(rc); i++) {
+    printf("0x%02x", rc[i]);
+    if (i == sizeof(rc) - 1)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Done --- */
+
+  puts("#endif");
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rijndael.c b/symm/rijndael.c
new file mode 100644 (file)
index 0000000..9d8e739
--- /dev/null
@@ -0,0 +1,158 @@
+/* -*-c-*-
+ *
+ * The Rijndael block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "rijndael.h"
+#include "rijndael-base.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rijndael_init@ --- *
+ *
+ * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Rijndael context with a particular key.  This
+ *             implementation of Rijndael doesn't impose any particular
+ *             limits on the key size except that it must be multiple of 4
+ *             bytes long.  256 bits seems sensible, though.
+ */
+
+void rijndael_init(rijndael_ctx *k, const void *buf, size_t sz)
+{
+  rijndael_setup(k, RIJNDAEL_BLKSZ / 4, buf, sz);
+}
+
+/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
+ *
+ * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do {                        \
+  aa = what(t, a, b, c, d) ^ *w++;                                     \
+  bb = what(t, b, c, d, a) ^ *w++;                                     \
+  cc = what(t, c, d, a, b) ^ *w++;                                     \
+  dd = what(t, d, a, b, c) ^ *w++;                                     \
+} while (0)
+
+#define UNDO(what, t, aa, bb, cc, dd, a, b, c, d, w) do {              \
+  aa = what(t, a, d, c, b) ^ *w++;                                     \
+  bb = what(t, b, a, d, c) ^ *w++;                                     \
+  cc = what(t, c, b, a, d) ^ *w++;                                     \
+  dd = what(t, d, c, b, a) ^ *w++;                                     \
+} while (0)
+
+void rijndael_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
+  uint32 aa, bb, cc, dd;
+  const uint32 *w = k->w;
+
+  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
+  aa = a; bb = b; cc = c; dd = d;
+
+  switch (k->nr) {
+    case 14:
+      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+    case 13:
+      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+    case 12:
+      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+    case 11:
+      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+    case 10:
+    default:
+      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+      DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+      DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+  }
+  DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+}
+
+void rijndael_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
+  uint32 aa, bb, cc, dd;
+  const uint32 *w = k->wi;
+
+  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
+  aa = a; bb = b; cc = c; dd = d;
+
+  switch (k->nr) {
+    case 14:
+      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+    case 13:
+      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+    case 12:
+      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+    case 11:
+      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+    case 10:
+    default:
+      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+      UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+  }
+  UNDO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+}
+
+BLKC_TEST(RIJNDAEL, rijndael)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rijndael.h b/symm/rijndael.h
new file mode 100644 (file)
index 0000000..7b93440
--- /dev/null
@@ -0,0 +1,126 @@
+/* -*-c-*-
+ *
+ * The Rijndael block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Rijndael block cipher --------------------------------*
+ *
+ * Invented by Joan Daemen and Vincent Rijmen, Rijndael is a fast, elegant
+ * and relatively simple 128-bit block cipher.  It was chosen by NIST to be
+ * the new Advanced Encryption Standard (AES) algorithm.
+ *
+ * Rijnadel appears to have a low security margin.  I recommend waiting
+ * before using Rijndael for any sensitive applications.
+ */
+
+#ifndef CATACOMB_RIJNDAEL_H
+#define CATACOMB_RIJNDAEL_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define RIJNDAEL_BLKSZ 16
+#define RIJNDAEL_KEYSZ 32
+#define RIJNDAEL_CLASS (N, B, 128)
+
+extern const octet rijndael_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+#define RIJNDAEL_MAXROUNDS 16
+#define RIJNDAEL_KWORDS ((RIJNDAEL_MAXROUNDS + 1) * 8)
+
+typedef struct rijndael_ctx {
+  unsigned nr;
+  uint32 w[RIJNDAEL_KWORDS];
+  uint32 wi[RIJNDAEL_KWORDS];
+} rijndael_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rijndael_setup@ --- *
+ *
+ * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
+ *             @unsigned nb@ = number of words in the block
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level key-scheduling.  Don't call this directly.
+ */
+
+extern void rijndael_setup(rijndael_ctx */*k*/, unsigned /*nb*/,
+                          const void */*buf*/, size_t /*sz*/);
+
+/* --- @rijndael_init@ --- *
+ *
+ * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Rijndael context with a particular key.  This
+ *             implementation of Rijndael doesn't impose any particular
+ *             limits on the key size except that it must be multiple of 4
+ *             bytes long.  256 bits seems sensible, though.
+ */
+
+extern void rijndael_init(rijndael_ctx */*k*/,
+                         const void */*buf*/, size_t /*sz*/);
+
+/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
+ *
+ * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void rijndael_eblk(const rijndael_ctx */*k*/,
+                         const uint32 */*s*/, uint32 */*dst*/);
+extern void rijndael_dblk(const rijndael_ctx */*k*/,
+                         const uint32 */*s*/, uint32 */*dst*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rijndael192.c b/symm/rijndael192.c
new file mode 100644 (file)
index 0000000..424f8f9
--- /dev/null
@@ -0,0 +1,159 @@
+/* -*-c-*-
+ *
+ * The Rijndael block cipher, 192-bit version
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "rijndael.h"
+#include "rijndael192.h"
+#include "rijndael-base.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rijndael192_init@ --- *
+ *
+ * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Rijndael context with a particular key.  This
+ *             implementation of Rijndael doesn't impose any particular
+ *             limits on the key size except that it must be multiple of 4
+ *             bytes long.  256 bits seems sensible, though.
+ */
+
+void rijndael192_init(rijndael_ctx *k, const void *buf, size_t sz)
+{
+  rijndael_setup(k, RIJNDAEL192_BLKSZ / 4, buf, sz);
+}
+
+/* --- @rijndael192_eblk@, @rijndael192_dblk@ --- *
+ *
+ * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define DO(what, t, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w) do {  \
+  aa = what(t, a, b, c, d) ^ *w++;                                     \
+  bb = what(t, b, c, d, e) ^ *w++;                                     \
+  cc = what(t, c, d, e, f) ^ *w++;                                     \
+  dd = what(t, d, e, f, a) ^ *w++;                                     \
+  ee = what(t, e, f, a, b) ^ *w++;                                     \
+  ff = what(t, f, a, b, c) ^ *w++;                                     \
+} while (0)
+
+#define UNDO(what, t, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w) do {        \
+  aa = what(t, a, f, e, d) ^ *w++;                                     \
+  bb = what(t, b, a, f, e) ^ *w++;                                     \
+  cc = what(t, c, b, a, f) ^ *w++;                                     \
+  dd = what(t, d, c, b, a) ^ *w++;                                     \
+  ee = what(t, e, d, c, b) ^ *w++;                                     \
+  ff = what(t, f, e, d, c) ^ *w++;                                     \
+} while (0)
+
+void rijndael192_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5];
+  uint32 aa, bb, cc, dd, ee, ff;
+  const uint32 *w = k->w;
+
+  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; e ^= *w++; f ^= *w++;
+  aa = a; bb = b; cc = c; dd = d; ee = e; ff = f;
+
+  switch (k->nr) {
+    case 14:
+      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+    case 13:
+      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+    case 12:
+    default:
+      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      DO(MIX, T, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      DO(MIX, T, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+  }
+  DO(SUB, S, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; dst[4] = e; dst[5] = f;
+}
+
+void rijndael192_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5];
+  uint32 aa, bb, cc, dd, ee, ff;
+  const uint32 *w = k->wi;
+
+  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++; e ^= *w++; f ^= *w++;
+  aa = a; bb = b; cc = c; dd = d; ee = e; ff = f;
+
+  switch (k->nr) {
+    case 14:
+      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+    case 13:
+      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+    case 12:
+    default:
+      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+      UNDO(MIX, TI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+      UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, a, b, c, d, e, f, w);
+  }
+  UNDO(SUB, SI, a, b, c, d, e, f, aa, bb, cc, dd, ee, ff, w);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; dst[4] = e; dst[5] = f;
+}
+
+BLKC_TEST(RIJNDAEL192, rijndael192)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rijndael192.h b/symm/rijndael192.h
new file mode 100644 (file)
index 0000000..b9357cd
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*-c-*-
+ *
+ * The Rijndael block cipher, 192-bit version
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_RIJNDAEL192_H
+#define CATACOMB_RIJNDAEL192_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_RIJNDAEL_H
+#  include "rijndael.h"
+#endif
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define RIJNDAEL192_BLKSZ 24
+#define RIJNDAEL192_KEYSZ 32
+#define RIJNDAEL192_CLASS (N, B, 192)
+
+#define rijndael192_keysz rijndael_keysz
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rijndael_ctx rijndael192_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rijndael192_init@ --- *
+ *
+ * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Rijndael context with a particular key.  This
+ *             implementation of Rijndael doesn't impose any particular
+ *             limits on the key size except that it must be multiple of 4
+ *             bytes long.  256 bits seems sensible, though.
+ */
+
+extern void rijndael192_init(rijndael_ctx */*k*/,
+                         const void */*buf*/, size_t /*sz*/);
+
+/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
+ *
+ * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void rijndael192_eblk(const rijndael_ctx */*k*/,
+                            const uint32 */*s*/, uint32 */*dst*/);
+extern void rijndael192_dblk(const rijndael_ctx */*k*/,
+                            const uint32 */*s*/, uint32 */*dst*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rijndael256.c b/symm/rijndael256.c
new file mode 100644 (file)
index 0000000..9fb7298
--- /dev/null
@@ -0,0 +1,159 @@
+/* -*-c-*-
+ *
+ * The Rijndael block cipher, 256-bit version
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "rijndael.h"
+#include "rijndael256.h"
+#include "rijndael-base.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rijndael256_init@ --- *
+ *
+ * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Rijndael context with a particular key.  This
+ *             implementation of Rijndael doesn't impose any particular
+ *             limits on the key size except that it must be multiple of 4
+ *             bytes long.  256 bits seems sensible, though.
+ */
+
+void rijndael256_init(rijndael_ctx *k, const void *buf, size_t sz)
+{
+  rijndael_setup(k, RIJNDAEL256_BLKSZ / 4, buf, sz);
+}
+
+/* --- @rijndael256_eblk@, @rijndael256_dblk@ --- *
+ *
+ * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define DO(what, t,                                                    \
+          aa, bb, cc, dd, ee, ff, gg, hh,                              \
+          a, b, c, d, e, f, g, h, w) do {                              \
+  aa = what(t, a, b, d, e) ^ *w++;                                     \
+  bb = what(t, b, c, e, f) ^ *w++;                                     \
+  cc = what(t, c, d, f, g) ^ *w++;                                     \
+  dd = what(t, d, e, g, h) ^ *w++;                                     \
+  ee = what(t, e, f, h, a) ^ *w++;                                     \
+  ff = what(t, f, g, a, b) ^ *w++;                                     \
+  gg = what(t, g, h, b, c) ^ *w++;                                     \
+  hh = what(t, h, a, c, d) ^ *w++;                                     \
+} while (0)
+
+#define UNDO(what, t,                                                  \
+            aa, bb, cc, dd, ee, ff, gg, hh,                            \
+            a, b, c, d, e, f, g, h, w) do {                            \
+  aa = what(t, a, h, f, e) ^ *w++;                                     \
+  bb = what(t, b, a, g, f) ^ *w++;                                     \
+  cc = what(t, c, b, h, g) ^ *w++;                                     \
+  dd = what(t, d, c, a, h) ^ *w++;                                     \
+  ee = what(t, e, d, b, a) ^ *w++;                                     \
+  ff = what(t, f, e, c, b) ^ *w++;                                     \
+  gg = what(t, g, f, d, c) ^ *w++;                                     \
+  hh = what(t, h, g, e, d) ^ *w++;                                     \
+} while (0)
+
+void rijndael256_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
+  uint32 e = s[4], f = s[5], g = s[6], h = s[7];
+  uint32 aa, bb, cc, dd, ee, ff, gg, hh;
+  const uint32 *w = k->w;
+
+  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
+  e ^= *w++; f ^= *w++; g ^= *w++; h ^= *w++;
+
+  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  DO(MIX, T, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  DO(MIX, T, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  DO(SUB, S, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+  dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h;
+}
+
+void rijndael256_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
+  uint32 e = s[4], f = s[5], g = s[6], h = s[7];
+  uint32 aa, bb, cc, dd, ee, ff, gg, hh;
+  const uint32 *w = k->wi;
+
+  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
+  e ^= *w++; f ^= *w++; g ^= *w++; h ^= *w++;
+
+  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  UNDO(MIX, TI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+  UNDO(MIX, TI, aa, bb, cc, dd, ee, ff, gg, hh, a, b, c, d, e, f, g, h, w);
+  UNDO(SUB, SI, a, b, c, d, e, f, g, h, aa, bb, cc, dd, ee, ff, gg, hh, w);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+  dst[4] = e; dst[5] = f; dst[6] = g; dst[7] = h;
+}
+
+BLKC_TEST(RIJNDAEL256, rijndael256)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rijndael256.h b/symm/rijndael256.h
new file mode 100644 (file)
index 0000000..fce2d0e
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*-c-*-
+ *
+ * The Rijndael block cipher, 256-bit version
+ *
+ * (c) 2001 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.
+ */
+
+#ifndef CATACOMB_RIJNDAEL256_H
+#define CATACOMB_RIJNDAEL256_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_RIJNDAEL_H
+#  include "rijndael.h"
+#endif
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define RIJNDAEL256_BLKSZ 32
+#define RIJNDAEL256_KEYSZ 32
+#define RIJNDAEL256_CLASS (N, B, 256)
+
+#define rijndael256_keysz rijndael_keysz
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rijndael_ctx rijndael256_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rijndael256_init@ --- *
+ *
+ * Arguments:  @rijndael_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Rijndael context with a particular key.  This
+ *             implementation of Rijndael doesn't impose any particular
+ *             limits on the key size except that it must be multiple of 4
+ *             bytes long.  256 bits seems sensible, though.
+ */
+
+extern void rijndael256_init(rijndael_ctx */*k*/,
+                         const void */*buf*/, size_t /*sz*/);
+
+/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
+ *
+ * Arguments:  @const rijndael_ctx *k@ = pointer to Rijndael context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void rijndael256_eblk(const rijndael_ctx */*k*/,
+                            const uint32 */*s*/, uint32 */*dst*/);
+extern void rijndael256_dblk(const rijndael_ctx */*k*/,
+                            const uint32 */*s*/, uint32 */*dst*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rmd128.c b/symm/rmd128.c
new file mode 100644 (file)
index 0000000..85b6c33
--- /dev/null
@@ -0,0 +1,356 @@
+/* -*-c-*-
+ *
+ * The RIPEMD-128 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "rmd128.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rmd128_compress@ --- *
+ *
+ * Arguments:  @rmd128_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-128 compression function.
+ */
+
+void rmd128_compress(rmd128_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d;
+  uint32 A, B, C, D;
+  uint32 buf[16];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = A = ctx->a;
+  b = B = ctx->b;
+  c = C = ctx->c;
+  d = D = ctx->d;
+
+  /* --- 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) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+
+#define T(w, x, y, z, i, r, f, k) do {                                 \
+  uint32 _t = w + f(x, y, z) + buf[i] + k;                             \
+  w = ROL32(_t, r);                                                    \
+} while (0)
+
+#define F1(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000)
+#define G1(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x5a827999)
+#define H1(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x6ed9eba1)
+#define I1(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x8f1bbcdc)
+
+#define F2(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x50a28be6)
+#define G2(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x5c4dd124)
+#define H2(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x6d703ef3)
+#define I2(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000)
+
+  /* --- First the left hand side --- */
+
+  F1(a, b, c, d,  0, 11);
+  F1(d, a, b, c,  1, 14);
+  F1(c, d, a, b,  2, 15);
+  F1(b, c, d, a,  3, 12);
+  F1(a, b, c, d,  4,  5);
+  F1(d, a, b, c,  5,  8);
+  F1(c, d, a, b,  6,  7);
+  F1(b, c, d, a,  7,  9);
+  F1(a, b, c, d,  8, 11);
+  F1(d, a, b, c,  9, 13);
+  F1(c, d, a, b, 10, 14);
+  F1(b, c, d, a, 11, 15);
+  F1(a, b, c, d, 12,  6);
+  F1(d, a, b, c, 13,  7);
+  F1(c, d, a, b, 14,  9);
+  F1(b, c, d, a, 15,  8);
+
+  G1(a, b, c, d,  7,  7);
+  G1(d, a, b, c,  4,  6);
+  G1(c, d, a, b, 13,  8);
+  G1(b, c, d, a,  1, 13);
+  G1(a, b, c, d, 10, 11);
+  G1(d, a, b, c,  6,  9);
+  G1(c, d, a, b, 15,  7);
+  G1(b, c, d, a,  3, 15);
+  G1(a, b, c, d, 12,  7);
+  G1(d, a, b, c,  0, 12);
+  G1(c, d, a, b,  9, 15);
+  G1(b, c, d, a,  5,  9);
+  G1(a, b, c, d,  2, 11);
+  G1(d, a, b, c, 14,  7);
+  G1(c, d, a, b, 11, 13);
+  G1(b, c, d, a,  8, 12);
+
+  H1(a, b, c, d,  3, 11);
+  H1(d, a, b, c, 10, 13);
+  H1(c, d, a, b, 14,  6);
+  H1(b, c, d, a,  4,  7);
+  H1(a, b, c, d,  9, 14);
+  H1(d, a, b, c, 15,  9);
+  H1(c, d, a, b,  8, 13);
+  H1(b, c, d, a,  1, 15);
+  H1(a, b, c, d,  2, 14);
+  H1(d, a, b, c,  7,  8);
+  H1(c, d, a, b,  0, 13);
+  H1(b, c, d, a,  6,  6);
+  H1(a, b, c, d, 13,  5);
+  H1(d, a, b, c, 11, 12);
+  H1(c, d, a, b,  5,  7);
+  H1(b, c, d, a, 12,  5);
+
+  I1(a, b, c, d,  1, 11);
+  I1(d, a, b, c,  9, 12);
+  I1(c, d, a, b, 11, 14);
+  I1(b, c, d, a, 10, 15);
+  I1(a, b, c, d,  0, 14);
+  I1(d, a, b, c,  8, 15);
+  I1(c, d, a, b, 12,  9);
+  I1(b, c, d, a,  4,  8);
+  I1(a, b, c, d, 13,  9);
+  I1(d, a, b, c,  3, 14);
+  I1(c, d, a, b,  7,  5);
+  I1(b, c, d, a, 15,  6);
+  I1(a, b, c, d, 14,  8);
+  I1(d, a, b, c,  5,  6);
+  I1(c, d, a, b,  6,  5);
+  I1(b, c, d, a,  2, 12);
+
+  /* --- And then the right hand side --- */
+
+  F2(A, B, C, D,  5,  8);
+  F2(D, A, B, C, 14,  9);
+  F2(C, D, A, B,  7,  9);
+  F2(B, C, D, A,  0, 11);
+  F2(A, B, C, D,  9, 13);
+  F2(D, A, B, C,  2, 15);
+  F2(C, D, A, B, 11, 15);
+  F2(B, C, D, A,  4,  5);
+  F2(A, B, C, D, 13,  7);
+  F2(D, A, B, C,  6,  7);
+  F2(C, D, A, B, 15,  8);
+  F2(B, C, D, A,  8, 11);
+  F2(A, B, C, D,  1, 14);
+  F2(D, A, B, C, 10, 14);
+  F2(C, D, A, B,  3, 12);
+  F2(B, C, D, A, 12,  6);
+
+  G2(A, B, C, D,  6,  9);
+  G2(D, A, B, C, 11, 13);
+  G2(C, D, A, B,  3, 15);
+  G2(B, C, D, A,  7,  7);
+  G2(A, B, C, D,  0, 12);
+  G2(D, A, B, C, 13,  8);
+  G2(C, D, A, B,  5,  9);
+  G2(B, C, D, A, 10, 11);
+  G2(A, B, C, D, 14,  7);
+  G2(D, A, B, C, 15,  7);
+  G2(C, D, A, B,  8, 12);
+  G2(B, C, D, A, 12,  7);
+  G2(A, B, C, D,  4,  6);
+  G2(D, A, B, C,  9, 15);
+  G2(C, D, A, B,  1, 13);
+  G2(B, C, D, A,  2, 11);
+
+  H2(A, B, C, D, 15,  9);
+  H2(D, A, B, C,  5,  7);
+  H2(C, D, A, B,  1, 15);
+  H2(B, C, D, A,  3, 11);
+  H2(A, B, C, D,  7,  8);
+  H2(D, A, B, C, 14,  6);
+  H2(C, D, A, B,  6,  6);
+  H2(B, C, D, A,  9, 14);
+  H2(A, B, C, D, 11, 12);
+  H2(D, A, B, C,  8, 13);
+  H2(C, D, A, B, 12,  5);
+  H2(B, C, D, A,  2, 14);
+  H2(A, B, C, D, 10, 13);
+  H2(D, A, B, C,  0, 13);
+  H2(C, D, A, B,  4,  7);
+  H2(B, C, D, A, 13,  5);
+
+  I2(A, B, C, D,  8, 15);
+  I2(D, A, B, C,  6,  5);
+  I2(C, D, A, B,  4,  8);
+  I2(B, C, D, A,  1, 11);
+  I2(A, B, C, D,  3, 14);
+  I2(D, A, B, C, 11, 14);
+  I2(C, D, A, B, 15,  6);
+  I2(B, C, D, A,  0, 14);
+  I2(A, B, C, D,  5,  6);
+  I2(D, A, B, C, 12,  9);
+  I2(C, D, A, B,  2, 12);
+  I2(B, C, D, A, 13,  9);
+  I2(A, B, C, D,  9, 12);
+  I2(D, A, B, C,  7,  5);
+  I2(C, D, A, B, 10, 15);
+  I2(B, C, D, A, 14,  8);
+
+  /* --- Recombine the two halves --- */
+
+  {
+    uint32
+       tmp = ctx->b + c + D;
+    ctx->b = ctx->c + d + A;
+    ctx->c = ctx->d + a + B;
+    ctx->d = ctx->a + b + C;
+    ctx->a = tmp;
+  }
+}
+
+/* --- @rmd128_init@ --- *
+ *
+ * Arguments:  @rmd128_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void rmd128_init(rmd128_ctx *ctx)
+{
+  ctx->a = 0x67452301;
+  ctx->b = 0xefcdab89;
+  ctx->c = 0x98badcfe;
+  ctx->d = 0x10325476;
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+/* --- @rmd128_set@ --- *
+ *
+ * Arguments:  @rmd128_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 rmd128_set(rmd128_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->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @rmd128_hash@ --- *
+ *
+ * Arguments:  @rmd128_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 rmd128_hash(rmd128_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(RMD128, rmd128, ctx, buf, sz);
+}
+
+/* --- @rmd128_done@ --- *
+ *
+ * Arguments:  @rmd128_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void rmd128_done(rmd128_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_MD5STRENGTH(RMD128, rmd128, 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);
+}
+
+/* --- @rmd128_state@ --- *
+ *
+ * Arguments:  @rmd128_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 @rmd128_set@.
+ */
+
+unsigned long rmd128_state(rmd128_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);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(RMD128, rmd128)
+
+/* --- Test code --- */
+
+HASH_TEST(RMD128, rmd128)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rmd128.h b/symm/rmd128.h
new file mode 100644 (file)
index 0000000..c139561
--- /dev/null
@@ -0,0 +1,156 @@
+/* -*-c-*-
+ *
+ * The RIPEMD-128 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Notes on the RIPEMD-128 hash function -----------------------------*
+ *
+ * RIPEMD-128 was invented by Hans Dobbertin, Antoon Bosselaers and Bart
+ * Preneel, as a drop-in replacement for MD5 (with the same sized output).
+ * It's a cut-down version of RIPEMD-160, which should be used in preference.
+ */
+
+#ifndef CATACOMB_RMD128_H
+#define CATACOMB_RMD128_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define RMD128_BUFSZ 64
+#define RMD128_HASHSZ 16
+#define RMD128_STATESZ 16
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rmd128_ctx {
+  uint32 a, b, c, d;                   /* Chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[RMD128_BUFSZ];             /* Accumulation buffer */
+} rmd128_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rmd128_compress@ --- *
+ *
+ * Arguments:  @rmd128_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-128 compression function.
+ */
+
+extern void rmd128_compress(rmd128_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @rmd128_init@ --- *
+ *
+ * Arguments:  @rmd128_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void rmd128_init(rmd128_ctx */*ctx*/);
+
+/* --- @rmd128_set@ --- *
+ *
+ * Arguments:  @rmd128_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 rmd128_set(rmd128_ctx */*ctx*/,
+                      const void */*buf*/, unsigned long /*count*/);
+
+/* --- @rmd128_hash@ --- *
+ *
+ * Arguments:  @rmd128_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 rmd128_hash(rmd128_ctx */*ctx*/,
+                       const void */*buf*/, size_t /*sz*/);
+
+/* --- @rmd128_done@ --- *
+ *
+ * Arguments:  @rmd128_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 rmd128_done(rmd128_ctx */*ctx*/, void */*hash*/);
+
+/* --- @rmd128_state@ --- *
+ *
+ * Arguments:  @rmd128_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 @rmd128_set@.
+ */
+
+extern unsigned long rmd128_state(rmd128_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash rmd128;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rmd160.c b/symm/rmd160.c
new file mode 100644 (file)
index 0000000..bc7e867
--- /dev/null
@@ -0,0 +1,399 @@
+/* -*-c-*-
+ *
+ * The RIPEMD-160 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "rmd160.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rmd160_compress@ --- *
+ *
+ * Arguments:  @rmd160_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-160 compression function.
+ */
+
+void rmd160_compress(rmd160_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d, e;
+  uint32 A, B, C, D, E;
+  uint32 buf[16];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = A = ctx->a;
+  b = B = ctx->b;
+  c = C = ctx->c;
+  d = D = ctx->d;
+  e = 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) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define J(x, y, z) ((x) ^ ((y) | ~(z)))
+
+#define T(v, w, x, y, z, i, r, f, k) do {                              \
+  uint32 _t = v + f(w, x, y) + buf[i] + k;                             \
+  v = ROL32(_t, r) + z; x = ROL32(x, 10);                              \
+} while (0)
+
+#define F1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000)
+#define G1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x5a827999)
+#define H1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6ed9eba1)
+#define I1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x8f1bbcdc)
+#define J1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0xa953fd4e)
+
+#define F2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0x50a28be6)
+#define G2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x5c4dd124)
+#define H2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6d703ef3)
+#define I2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x7a6d76e9)
+#define J2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000)
+
+  /* --- First the left hand side --- */
+
+  F1(a, b, c, d, e,  0, 11);
+  F1(e, a, b, c, d,  1, 14);
+  F1(d, e, a, b, c,  2, 15);
+  F1(c, d, e, a, b,  3, 12);
+  F1(b, c, d, e, a,  4,         5);
+  F1(a, b, c, d, e,  5,         8);
+  F1(e, a, b, c, d,  6,         7);
+  F1(d, e, a, b, c,  7,         9);
+  F1(c, d, e, a, b,  8, 11);
+  F1(b, c, d, e, a,  9, 13);
+  F1(a, b, c, d, e, 10, 14);
+  F1(e, a, b, c, d, 11, 15);
+  F1(d, e, a, b, c, 12,         6);
+  F1(c, d, e, a, b, 13,         7);
+  F1(b, c, d, e, a, 14,         9);
+  F1(a, b, c, d, e, 15,         8);
+
+  G1(e, a, b, c, d,  7,         7);
+  G1(d, e, a, b, c,  4,         6);
+  G1(c, d, e, a, b, 13,         8);
+  G1(b, c, d, e, a,  1,        13);
+  G1(a, b, c, d, e, 10,        11);
+  G1(e, a, b, c, d,  6,         9);
+  G1(d, e, a, b, c, 15,         7);
+  G1(c, d, e, a, b,  3,        15);
+  G1(b, c, d, e, a, 12,         7);
+  G1(a, b, c, d, e,  0,        12);
+  G1(e, a, b, c, d,  9,        15);
+  G1(d, e, a, b, c,  5,         9);
+  G1(c, d, e, a, b,  2,        11);
+  G1(b, c, d, e, a, 14,         7);
+  G1(a, b, c, d, e, 11,        13);
+  G1(e, a, b, c, d,  8,        12);
+
+  H1(d, e, a, b, c,  3,        11);
+  H1(c, d, e, a, b, 10,        13);
+  H1(b, c, d, e, a, 14,         6);
+  H1(a, b, c, d, e,  4,         7);
+  H1(e, a, b, c, d,  9,        14);
+  H1(d, e, a, b, c, 15,         9);
+  H1(c, d, e, a, b,  8,        13);
+  H1(b, c, d, e, a,  1,        15);
+  H1(a, b, c, d, e,  2,        14);
+  H1(e, a, b, c, d,  7,         8);
+  H1(d, e, a, b, c,  0,        13);
+  H1(c, d, e, a, b,  6,         6);
+  H1(b, c, d, e, a, 13,         5);
+  H1(a, b, c, d, e, 11,        12);
+  H1(e, a, b, c, d,  5,         7);
+  H1(d, e, a, b, c, 12,         5);
+
+  I1(c, d, e, a, b,  1,        11);
+  I1(b, c, d, e, a,  9,        12);
+  I1(a, b, c, d, e, 11,        14);
+  I1(e, a, b, c, d, 10,        15);
+  I1(d, e, a, b, c,  0,        14);
+  I1(c, d, e, a, b,  8,        15);
+  I1(b, c, d, e, a, 12,         9);
+  I1(a, b, c, d, e,  4,         8);
+  I1(e, a, b, c, d, 13,         9);
+  I1(d, e, a, b, c,  3,        14);
+  I1(c, d, e, a, b,  7,         5);
+  I1(b, c, d, e, a, 15,         6);
+  I1(a, b, c, d, e, 14,         8);
+  I1(e, a, b, c, d,  5,         6);
+  I1(d, e, a, b, c,  6,         5);
+  I1(c, d, e, a, b,  2,        12);
+
+  J1(b, c, d, e, a,  4,         9);
+  J1(a, b, c, d, e,  0,        15);
+  J1(e, a, b, c, d,  5,         5);
+  J1(d, e, a, b, c,  9,        11);
+  J1(c, d, e, a, b,  7,         6);
+  J1(b, c, d, e, a, 12,         8);
+  J1(a, b, c, d, e,  2,        13);
+  J1(e, a, b, c, d, 10,        12);
+  J1(d, e, a, b, c, 14,         5);
+  J1(c, d, e, a, b,  1,        12);
+  J1(b, c, d, e, a,  3,        13);
+  J1(a, b, c, d, e,  8,        14);
+  J1(e, a, b, c, d, 11,        11);
+  J1(d, e, a, b, c,  6,         8);
+  J1(c, d, e, a, b, 15,         5);
+  J1(b, c, d, e, a, 13,         6);
+
+  /* --- And then the right hand side --- */
+
+  F2(A, B, C, D, E,  5,         8);
+  F2(E, A, B, C, D, 14,         9);
+  F2(D, E, A, B, C,  7,         9);
+  F2(C, D, E, A, B,  0,        11);
+  F2(B, C, D, E, A,  9,        13);
+  F2(A, B, C, D, E,  2,        15);
+  F2(E, A, B, C, D, 11,        15);
+  F2(D, E, A, B, C,  4,         5);
+  F2(C, D, E, A, B, 13,         7);
+  F2(B, C, D, E, A,  6,         7);
+  F2(A, B, C, D, E, 15,         8);
+  F2(E, A, B, C, D,  8,        11);
+  F2(D, E, A, B, C,  1,        14);
+  F2(C, D, E, A, B, 10,        14);
+  F2(B, C, D, E, A,  3,        12);
+  F2(A, B, C, D, E, 12,         6);
+
+  G2(E, A, B, C, D,  6,         9);
+  G2(D, E, A, B, C, 11,        13);
+  G2(C, D, E, A, B,  3,        15);
+  G2(B, C, D, E, A,  7,         7);
+  G2(A, B, C, D, E,  0,        12);
+  G2(E, A, B, C, D, 13,         8);
+  G2(D, E, A, B, C,  5,         9);
+  G2(C, D, E, A, B, 10,        11);
+  G2(B, C, D, E, A, 14,         7);
+  G2(A, B, C, D, E, 15,         7);
+  G2(E, A, B, C, D,  8,        12);
+  G2(D, E, A, B, C, 12,         7);
+  G2(C, D, E, A, B,  4,         6);
+  G2(B, C, D, E, A,  9,        15);
+  G2(A, B, C, D, E,  1,        13);
+  G2(E, A, B, C, D,  2,        11);
+
+  H2(D, E, A, B, C, 15,         9);
+  H2(C, D, E, A, B,  5,         7);
+  H2(B, C, D, E, A,  1,        15);
+  H2(A, B, C, D, E,  3,        11);
+  H2(E, A, B, C, D,  7,         8);
+  H2(D, E, A, B, C, 14,         6);
+  H2(C, D, E, A, B,  6,         6);
+  H2(B, C, D, E, A,  9,        14);
+  H2(A, B, C, D, E, 11,        12);
+  H2(E, A, B, C, D,  8,        13);
+  H2(D, E, A, B, C, 12,         5);
+  H2(C, D, E, A, B,  2,        14);
+  H2(B, C, D, E, A, 10,        13);
+  H2(A, B, C, D, E,  0,        13);
+  H2(E, A, B, C, D,  4,         7);
+  H2(D, E, A, B, C, 13,         5);
+
+  I2(C, D, E, A, B,  8,        15);
+  I2(B, C, D, E, A,  6,         5);
+  I2(A, B, C, D, E,  4,         8);
+  I2(E, A, B, C, D,  1,        11);
+  I2(D, E, A, B, C,  3,        14);
+  I2(C, D, E, A, B, 11,        14);
+  I2(B, C, D, E, A, 15,         6);
+  I2(A, B, C, D, E,  0,        14);
+  I2(E, A, B, C, D,  5,         6);
+  I2(D, E, A, B, C, 12,         9);
+  I2(C, D, E, A, B,  2,        12);
+  I2(B, C, D, E, A, 13,         9);
+  I2(A, B, C, D, E,  9,        12);
+  I2(E, A, B, C, D,  7,         5);
+  I2(D, E, A, B, C, 10,        15);
+  I2(C, D, E, A, B, 14,         8);
+
+  J2(B, C, D, E, A, 12,         8);
+  J2(A, B, C, D, E, 15,         5);
+  J2(E, A, B, C, D, 10,        12);
+  J2(D, E, A, B, C,  4,         9);
+  J2(C, D, E, A, B,  1,        12);
+  J2(B, C, D, E, A,  5,         5);
+  J2(A, B, C, D, E,  8,        14);
+  J2(E, A, B, C, D,  7,         6);
+  J2(D, E, A, B, C,  6,         8);
+  J2(C, D, E, A, B,  2,        13);
+  J2(B, C, D, E, A, 13,         6);
+  J2(A, B, C, D, E, 14,         5);
+  J2(E, A, B, C, D,  0,        15);
+  J2(D, E, A, B, C,  3,        13);
+  J2(C, D, E, A, B,  9,        11);
+  J2(B, C, D, E, A, 11,        11);
+
+  /* --- Recombine the two halves --- */
+
+  {
+    uint32
+       tmp = ctx->b + c + D;
+    ctx->b = ctx->c + d + E;
+    ctx->c = ctx->d + e + A;
+    ctx->d = ctx->e + a + B;
+    ctx->e = ctx->a + b + C;
+    ctx->a = tmp;
+  }
+}
+
+/* --- @rmd160_init@ --- *
+ *
+ * Arguments:  @rmd160_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void rmd160_init(rmd160_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;
+}
+
+/* --- @rmd160_set@ --- *
+ *
+ * Arguments:  @rmd160_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 rmd160_set(rmd160_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);
+}
+
+/* --- @rmd160_hash@ --- *
+ *
+ * Arguments:  @rmd160_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 rmd160_hash(rmd160_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(RMD160, rmd160, ctx, buf, sz);
+}
+
+/* --- @rmd160_done@ --- *
+ *
+ * Arguments:  @rmd160_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void rmd160_done(rmd160_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_MD5STRENGTH(RMD160, rmd160, 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);
+}
+
+/* --- @rmd160_state@ --- *
+ *
+ * Arguments:  @rmd160_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 @rmd160_set@.
+ */
+
+unsigned long rmd160_state(rmd160_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(RMD160, rmd160)
+
+/* --- Test code --- */
+
+HASH_TEST(RMD160, rmd160)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rmd160.h b/symm/rmd160.h
new file mode 100644 (file)
index 0000000..fef7112
--- /dev/null
@@ -0,0 +1,159 @@
+/* -*-c-*-
+ *
+ * The RIPEMD-160 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Notes on the RIPEMD-160 hash function -----------------------------*
+ *
+ * RIPEMD-160 was invented by Hans Dobbertin, Antoon Bosselaers and Bart
+ * Preneel.  It's a strengthened version of the original RIPEMD hash
+ * function, fixing a vulnerability discovered by Hans Dobbertin.  The
+ * RIPEMD-160 design team appears well respected in the cryptographic
+ * community.  The author finds them more plausible than SHA-1, which is the
+ * best alternative hash function.
+ */
+
+#ifndef CATACOMB_RMD160_H
+#define CATACOMB_RMD160_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define RMD160_BUFSZ 64
+#define RMD160_HASHSZ 20
+#define RMD160_STATESZ 20
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rmd160_ctx {
+  uint32 a, b, c, d, e;                        /* Chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[RMD160_BUFSZ];             /* Accumulation buffer */
+} rmd160_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rmd160_compress@ --- *
+ *
+ * Arguments:  @rmd160_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-160 compression function.
+ */
+
+extern void rmd160_compress(rmd160_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @rmd160_init@ --- *
+ *
+ * Arguments:  @rmd160_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void rmd160_init(rmd160_ctx */*ctx*/);
+
+/* --- @rmd160_set@ --- *
+ *
+ * Arguments:  @rmd160_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 rmd160_set(rmd160_ctx */*ctx*/,
+                      const void */*buf*/, unsigned long /*count*/);
+
+/* --- @rmd160_hash@ --- *
+ *
+ * Arguments:  @rmd160_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 rmd160_hash(rmd160_ctx */*ctx*/,
+                       const void */*buf*/, size_t /*sz*/);
+
+/* --- @rmd160_done@ --- *
+ *
+ * Arguments:  @rmd160_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 rmd160_done(rmd160_ctx */*ctx*/, void */*hash*/);
+
+/* --- @rmd160_state@ --- *
+ *
+ * Arguments:  @rmd160_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 @rmd160_set@.
+ */
+
+extern unsigned long rmd160_state(rmd160_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash rmd160;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rmd256.c b/symm/rmd256.c
new file mode 100644 (file)
index 0000000..99648f5
--- /dev/null
@@ -0,0 +1,374 @@
+/* -*-c-*-
+ *
+ * The RIPEMD-256 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "rmd256.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rmd256_compress@ --- *
+ *
+ * Arguments:  @rmd256_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-256 compression function.
+ */
+
+void rmd256_compress(rmd256_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d;
+  uint32 A, B, C, D;
+  uint32 buf[16];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = ctx->a;
+  b = ctx->b;
+  c = ctx->c;
+  d = ctx->d;
+  A = ctx->A;
+  B = ctx->B;
+  C = ctx->C;
+  D = ctx->D;
+
+  /* --- 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) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+
+#define T(w, x, y, z, i, r, f, k) do {                                 \
+  uint32 _t = w + f(x, y, z) + buf[i] + k;                             \
+  w = ROL32(_t, r);                                                    \
+} while (0)
+
+#define F1(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000)
+#define G1(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x5a827999)
+#define H1(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x6ed9eba1)
+#define I1(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x8f1bbcdc)
+
+#define F2(w, x, y, z, i, r) T(w, x, y, z, i, r, I, 0x50a28be6)
+#define G2(w, x, y, z, i, r) T(w, x, y, z, i, r, H, 0x5c4dd124)
+#define H2(w, x, y, z, i, r) T(w, x, y, z, i, r, G, 0x6d703ef3)
+#define I2(w, x, y, z, i, r) T(w, x, y, z, i, r, F, 0x00000000)
+
+  /* --- We must do both sides together --- */
+
+  F1(a, b, c, d,  0, 11);
+  F1(d, a, b, c,  1, 14);
+  F1(c, d, a, b,  2, 15);
+  F1(b, c, d, a,  3, 12);
+  F1(a, b, c, d,  4,  5);
+  F1(d, a, b, c,  5,  8);
+  F1(c, d, a, b,  6,  7);
+  F1(b, c, d, a,  7,  9);
+  F1(a, b, c, d,  8, 11);
+  F1(d, a, b, c,  9, 13);
+  F1(c, d, a, b, 10, 14);
+  F1(b, c, d, a, 11, 15);
+  F1(a, b, c, d, 12,  6);
+  F1(d, a, b, c, 13,  7);
+  F1(c, d, a, b, 14,  9);
+  F1(b, c, d, a, 15,  8);
+
+  F2(A, B, C, D,  5,  8);
+  F2(D, A, B, C, 14,  9);
+  F2(C, D, A, B,  7,  9);
+  F2(B, C, D, A,  0, 11);
+  F2(A, B, C, D,  9, 13);
+  F2(D, A, B, C,  2, 15);
+  F2(C, D, A, B, 11, 15);
+  F2(B, C, D, A,  4,  5);
+  F2(A, B, C, D, 13,  7);
+  F2(D, A, B, C,  6,  7);
+  F2(C, D, A, B, 15,  8);
+  F2(B, C, D, A,  8, 11);
+  F2(A, B, C, D,  1, 14);
+  F2(D, A, B, C, 10, 14);
+  F2(C, D, A, B,  3, 12);
+  F2(B, C, D, A, 12,  6);
+
+  G1(A, b, c, d,  7,  7);
+  G1(d, A, b, c,  4,  6);
+  G1(c, d, A, b, 13,  8);
+  G1(b, c, d, A,  1, 13);
+  G1(A, b, c, d, 10, 11);
+  G1(d, A, b, c,  6,  9);
+  G1(c, d, A, b, 15,  7);
+  G1(b, c, d, A,  3, 15);
+  G1(A, b, c, d, 12,  7);
+  G1(d, A, b, c,  0, 12);
+  G1(c, d, A, b,  9, 15);
+  G1(b, c, d, A,  5,  9);
+  G1(A, b, c, d,  2, 11);
+  G1(d, A, b, c, 14,  7);
+  G1(c, d, A, b, 11, 13);
+  G1(b, c, d, A,  8, 12);
+
+  G2(a, B, C, D,  6,  9);
+  G2(D, a, B, C, 11, 13);
+  G2(C, D, a, B,  3, 15);
+  G2(B, C, D, a,  7,  7);
+  G2(a, B, C, D,  0, 12);
+  G2(D, a, B, C, 13,  8);
+  G2(C, D, a, B,  5,  9);
+  G2(B, C, D, a, 10, 11);
+  G2(a, B, C, D, 14,  7);
+  G2(D, a, B, C, 15,  7);
+  G2(C, D, a, B,  8, 12);
+  G2(B, C, D, a, 12,  7);
+  G2(a, B, C, D,  4,  6);
+  G2(D, a, B, C,  9, 15);
+  G2(C, D, a, B,  1, 13);
+  G2(B, C, D, a,  2, 11);
+
+  H1(A, B, c, d,  3, 11);
+  H1(d, A, B, c, 10, 13);
+  H1(c, d, A, B, 14,  6);
+  H1(B, c, d, A,  4,  7);
+  H1(A, B, c, d,  9, 14);
+  H1(d, A, B, c, 15,  9);
+  H1(c, d, A, B,  8, 13);
+  H1(B, c, d, A,  1, 15);
+  H1(A, B, c, d,  2, 14);
+  H1(d, A, B, c,  7,  8);
+  H1(c, d, A, B,  0, 13);
+  H1(B, c, d, A,  6,  6);
+  H1(A, B, c, d, 13,  5);
+  H1(d, A, B, c, 11, 12);
+  H1(c, d, A, B,  5,  7);
+  H1(B, c, d, A, 12,  5);
+
+  H2(a, b, C, D, 15,  9);
+  H2(D, a, b, C,  5,  7);
+  H2(C, D, a, b,  1, 15);
+  H2(b, C, D, a,  3, 11);
+  H2(a, b, C, D,  7,  8);
+  H2(D, a, b, C, 14,  6);
+  H2(C, D, a, b,  6,  6);
+  H2(b, C, D, a,  9, 14);
+  H2(a, b, C, D, 11, 12);
+  H2(D, a, b, C,  8, 13);
+  H2(C, D, a, b, 12,  5);
+  H2(b, C, D, a,  2, 14);
+  H2(a, b, C, D, 10, 13);
+  H2(D, a, b, C,  0, 13);
+  H2(C, D, a, b,  4,  7);
+  H2(b, C, D, a, 13,  5);
+
+  I1(A, B, C, d,  1, 11);
+  I1(d, A, B, C,  9, 12);
+  I1(C, d, A, B, 11, 14);
+  I1(B, C, d, A, 10, 15);
+  I1(A, B, C, d,  0, 14);
+  I1(d, A, B, C,  8, 15);
+  I1(C, d, A, B, 12,  9);
+  I1(B, C, d, A,  4,  8);
+  I1(A, B, C, d, 13,  9);
+  I1(d, A, B, C,  3, 14);
+  I1(C, d, A, B,  7,  5);
+  I1(B, C, d, A, 15,  6);
+  I1(A, B, C, d, 14,  8);
+  I1(d, A, B, C,  5,  6);
+  I1(C, d, A, B,  6,  5);
+  I1(B, C, d, A,  2, 12);
+
+  I2(a, b, c, D,  8, 15);
+  I2(D, a, b, c,  6,  5);
+  I2(c, D, a, b,  4,  8);
+  I2(b, c, D, a,  1, 11);
+  I2(a, b, c, D,  3, 14);
+  I2(D, a, b, c, 11, 14);
+  I2(c, D, a, b, 15,  6);
+  I2(b, c, D, a,  0, 14);
+  I2(a, b, c, D,  5,  6);
+  I2(D, a, b, c, 12,  9);
+  I2(c, D, a, b,  2, 12);
+  I2(b, c, D, a, 13,  9);
+  I2(a, b, c, D,  9, 12);
+  I2(D, a, b, c,  7,  5);
+  I2(c, D, a, b, 10, 15);
+  I2(b, c, D, a, 14,  8);
+
+  /* --- Recombine the two halves --- */
+
+  ctx->a += A;
+  ctx->b += B;
+  ctx->c += C;
+  ctx->d += D;
+  ctx->A += a;
+  ctx->B += b;
+  ctx->C += c;
+  ctx->D += d;
+}
+
+/* --- @rmd256_init@ --- *
+ *
+ * Arguments:  @rmd256_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void rmd256_init(rmd256_ctx *ctx)
+{
+  ctx->a = 0x67452301;
+  ctx->b = 0xefcdab89;
+  ctx->c = 0x98badcfe;
+  ctx->d = 0x10325476;
+  ctx->A = 0x76543210;
+  ctx->B = 0xfedcba98;
+  ctx->C = 0x89abcdef;
+  ctx->D = 0x01234567;
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+/* --- @rmd256_set@ --- *
+ *
+ * Arguments:  @rmd256_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 rmd256_set(rmd256_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->A = LOAD32_L(p + 16);
+  ctx->B = LOAD32_L(p + 20);
+  ctx->C = LOAD32_L(p + 24);
+  ctx->D = LOAD32_L(p + 28);
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @rmd256_hash@ --- *
+ *
+ * Arguments:  @rmd256_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 rmd256_hash(rmd256_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(RMD256, rmd256, ctx, buf, sz);
+}
+
+/* --- @rmd256_done@ --- *
+ *
+ * Arguments:  @rmd256_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void rmd256_done(rmd256_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_MD5STRENGTH(RMD256, rmd256, 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->A);
+  STORE32_L(p + 20, ctx->B);
+  STORE32_L(p + 24, ctx->C);
+  STORE32_L(p + 28, ctx->D);
+}
+
+/* --- @rmd256_state@ --- *
+ *
+ * Arguments:  @rmd256_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 @rmd256_set@.
+ */
+
+unsigned long rmd256_state(rmd256_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->A);
+  STORE32_L(p + 20, ctx->B);
+  STORE32_L(p + 24, ctx->C);
+  STORE32_L(p + 28, ctx->D);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(RMD256, rmd256)
+
+/* --- Test code --- */
+
+HASH_TEST(RMD256, rmd256)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rmd256.h b/symm/rmd256.h
new file mode 100644 (file)
index 0000000..9d4d206
--- /dev/null
@@ -0,0 +1,160 @@
+/* -*-c-*-
+ *
+ * The RIPEMD-256 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Notes on the RIPEMD-256 hash function -----------------------------*
+ *
+ * RIPEMD-256 was invented by Hans Dobbertin, Antoon Bosselaers and Bart
+ * Preneel.  It's a double-width version of RIPEMD-128, constructed simply by
+ * not gluing together the two parallel computations which RIPEMD-128 usually
+ * does in its compression function.  The authors warn that, while its output
+ * is twice as wide as that of RIPEMD-128, they don't expect it to offer any
+ * more security.
+ */
+
+#ifndef CATACOMB_RMD256_H
+#define CATACOMB_RMD256_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define RMD256_BUFSZ 64
+#define RMD256_HASHSZ 32
+#define RMD256_STATESZ 32
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rmd256_ctx {
+  uint32 a, b, c, d;                   /* Chaining variables */
+  uint32 A, B, C, D;                   /* More chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[RMD256_BUFSZ];             /* Accumulation buffer */
+} rmd256_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rmd256_compress@ --- *
+ *
+ * Arguments:  @rmd256_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-256 compression function.
+ */
+
+extern void rmd256_compress(rmd256_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @rmd256_init@ --- *
+ *
+ * Arguments:  @rmd256_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void rmd256_init(rmd256_ctx */*ctx*/);
+
+/* --- @rmd256_set@ --- *
+ *
+ * Arguments:  @rmd256_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 rmd256_set(rmd256_ctx */*ctx*/,
+                      const void */*buf*/, unsigned long /*count*/);
+
+/* --- @rmd256_hash@ --- *
+ *
+ * Arguments:  @rmd256_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 rmd256_hash(rmd256_ctx */*ctx*/,
+                       const void */*buf*/, size_t /*sz*/);
+
+/* --- @rmd256_done@ --- *
+ *
+ * Arguments:  @rmd256_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 rmd256_done(rmd256_ctx */*ctx*/, void */*hash*/);
+
+/* --- @rmd256_state@ --- *
+ *
+ * Arguments:  @rmd256_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 @rmd256_set@.
+ */
+
+extern unsigned long rmd256_state(rmd256_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash rmd256;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/rmd320.c b/symm/rmd320.c
new file mode 100644 (file)
index 0000000..022903e
--- /dev/null
@@ -0,0 +1,424 @@
+/* -*-c-*-
+ *
+ * The RIPEMD-320 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "rmd320.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rmd320_compress@ --- *
+ *
+ * Arguments:  @rmd320_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-320 compression function.
+ */
+
+void rmd320_compress(rmd320_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d, e;
+  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;
+
+  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) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define J(x, y, z) ((x) ^ ((y) | ~(z)))
+
+#define T(v, w, x, y, z, i, r, f, k) do {                              \
+  uint32 _t = v + f(w, x, y) + buf[i] + k;                             \
+  v = ROL32(_t, r) + z; x = ROL32(x, 10);                              \
+} while (0)
+
+#define F1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000)
+#define G1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x5a827999)
+#define H1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6ed9eba1)
+#define I1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x8f1bbcdc)
+#define J1(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0xa953fd4e)
+
+#define F2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, J, 0x50a28be6)
+#define G2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, I, 0x5c4dd124)
+#define H2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, H, 0x6d703ef3)
+#define I2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, G, 0x7a6d76e9)
+#define J2(v, w, x, y, z, i, r) T(v, w, x, y, z, i, r, F, 0x00000000)
+
+  /* --- We must do both lines together --- */
+
+  F1(a, b, c, d, e,  0, 11);
+  F1(e, a, b, c, d,  1, 14);
+  F1(d, e, a, b, c,  2, 15);
+  F1(c, d, e, a, b,  3, 12);
+  F1(b, c, d, e, a,  4,         5);
+  F1(a, b, c, d, e,  5,         8);
+  F1(e, a, b, c, d,  6,         7);
+  F1(d, e, a, b, c,  7,         9);
+  F1(c, d, e, a, b,  8, 11);
+  F1(b, c, d, e, a,  9, 13);
+  F1(a, b, c, d, e, 10, 14);
+  F1(e, a, b, c, d, 11, 15);
+  F1(d, e, a, b, c, 12,         6);
+  F1(c, d, e, a, b, 13,         7);
+  F1(b, c, d, e, a, 14,         9);
+  F1(a, b, c, d, e, 15,         8);
+
+  F2(A, B, C, D, E,  5,         8);
+  F2(E, A, B, C, D, 14,         9);
+  F2(D, E, A, B, C,  7,         9);
+  F2(C, D, E, A, B,  0,        11);
+  F2(B, C, D, E, A,  9,        13);
+  F2(A, B, C, D, E,  2,        15);
+  F2(E, A, B, C, D, 11,        15);
+  F2(D, E, A, B, C,  4,         5);
+  F2(C, D, E, A, B, 13,         7);
+  F2(B, C, D, E, A,  6,         7);
+  F2(A, B, C, D, E, 15,         8);
+  F2(E, A, B, C, D,  8,        11);
+  F2(D, E, A, B, C,  1,        14);
+  F2(C, D, E, A, B, 10,        14);
+  F2(B, C, D, E, A,  3,        12);
+  F2(A, B, C, D, E, 12,         6);
+
+  G1(e, A, b, c, d,  7,         7);
+  G1(d, e, A, b, c,  4,         6);
+  G1(c, d, e, A, b, 13,         8);
+  G1(b, c, d, e, A,  1,        13);
+  G1(A, b, c, d, e, 10,        11);
+  G1(e, A, b, c, d,  6,         9);
+  G1(d, e, A, b, c, 15,         7);
+  G1(c, d, e, A, b,  3,        15);
+  G1(b, c, d, e, A, 12,         7);
+  G1(A, b, c, d, e,  0,        12);
+  G1(e, A, b, c, d,  9,        15);
+  G1(d, e, A, b, c,  5,         9);
+  G1(c, d, e, A, b,  2,        11);
+  G1(b, c, d, e, A, 14,         7);
+  G1(A, b, c, d, e, 11,        13);
+  G1(e, A, b, c, d,  8,        12);
+
+  G2(E, a, B, C, D,  6,         9);
+  G2(D, E, a, B, C, 11,        13);
+  G2(C, D, E, a, B,  3,        15);
+  G2(B, C, D, E, a,  7,         7);
+  G2(a, B, C, D, E,  0,        12);
+  G2(E, a, B, C, D, 13,         8);
+  G2(D, E, a, B, C,  5,         9);
+  G2(C, D, E, a, B, 10,        11);
+  G2(B, C, D, E, a, 14,         7);
+  G2(a, B, C, D, E, 15,         7);
+  G2(E, a, B, C, D,  8,        12);
+  G2(D, E, a, B, C, 12,         7);
+  G2(C, D, E, a, B,  4,         6);
+  G2(B, C, D, E, a,  9,        15);
+  G2(a, B, C, D, E,  1,        13);
+  G2(E, a, B, C, D,  2,        11);
+
+  H1(d, e, A, B, c,  3,        11);
+  H1(c, d, e, A, B, 10,        13);
+  H1(B, c, d, e, A, 14,         6);
+  H1(A, B, c, d, e,  4,         7);
+  H1(e, A, B, c, d,  9,        14);
+  H1(d, e, A, B, c, 15,         9);
+  H1(c, d, e, A, B,  8,        13);
+  H1(B, c, d, e, A,  1,        15);
+  H1(A, B, c, d, e,  2,        14);
+  H1(e, A, B, c, d,  7,         8);
+  H1(d, e, A, B, c,  0,        13);
+  H1(c, d, e, A, B,  6,         6);
+  H1(B, c, d, e, A, 13,         5);
+  H1(A, B, c, d, e, 11,        12);
+  H1(e, A, B, c, d,  5,         7);
+  H1(d, e, A, B, c, 12,         5);
+
+  H2(D, E, a, b, C, 15,         9);
+  H2(C, D, E, a, b,  5,         7);
+  H2(b, C, D, E, a,  1,        15);
+  H2(a, b, C, D, E,  3,        11);
+  H2(E, a, b, C, D,  7,         8);
+  H2(D, E, a, b, C, 14,         6);
+  H2(C, D, E, a, b,  6,         6);
+  H2(b, C, D, E, a,  9,        14);
+  H2(a, b, C, D, E, 11,        12);
+  H2(E, a, b, C, D,  8,        13);
+  H2(D, E, a, b, C, 12,         5);
+  H2(C, D, E, a, b,  2,        14);
+  H2(b, C, D, E, a, 10,        13);
+  H2(a, b, C, D, E,  0,        13);
+  H2(E, a, b, C, D,  4,         7);
+  H2(D, E, a, b, C, 13,         5);
+
+  I1(C, d, e, A, B,  1,        11);
+  I1(B, C, d, e, A,  9,        12);
+  I1(A, B, C, d, e, 11,        14);
+  I1(e, A, B, C, d, 10,        15);
+  I1(d, e, A, B, C,  0,        14);
+  I1(C, d, e, A, B,  8,        15);
+  I1(B, C, d, e, A, 12,         9);
+  I1(A, B, C, d, e,  4,         8);
+  I1(e, A, B, C, d, 13,         9);
+  I1(d, e, A, B, C,  3,        14);
+  I1(C, d, e, A, B,  7,         5);
+  I1(B, C, d, e, A, 15,         6);
+  I1(A, B, C, d, e, 14,         8);
+  I1(e, A, B, C, d,  5,         6);
+  I1(d, e, A, B, C,  6,         5);
+  I1(C, d, e, A, B,  2,        12);
+
+  I2(c, D, E, a, b,  8,        15);
+  I2(b, c, D, E, a,  6,         5);
+  I2(a, b, c, D, E,  4,         8);
+  I2(E, a, b, c, D,  1,        11);
+  I2(D, E, a, b, c,  3,        14);
+  I2(c, D, E, a, b, 11,        14);
+  I2(b, c, D, E, a, 15,         6);
+  I2(a, b, c, D, E,  0,        14);
+  I2(E, a, b, c, D,  5,         6);
+  I2(D, E, a, b, c, 12,         9);
+  I2(c, D, E, a, b,  2,        12);
+  I2(b, c, D, E, a, 13,         9);
+  I2(a, b, c, D, E,  9,        12);
+  I2(E, a, b, c, D,  7,         5);
+  I2(D, E, a, b, c, 10,        15);
+  I2(c, D, E, a, b, 14,         8);
+
+  J1(B, C, D, e, A,  4,         9);
+  J1(A, B, C, D, e,  0,        15);
+  J1(e, A, B, C, D,  5,         5);
+  J1(D, e, A, B, C,  9,        11);
+  J1(C, D, e, A, B,  7,         6);
+  J1(B, C, D, e, A, 12,         8);
+  J1(A, B, C, D, e,  2,        13);
+  J1(e, A, B, C, D, 10,        12);
+  J1(D, e, A, B, C, 14,         5);
+  J1(C, D, e, A, B,  1,        12);
+  J1(B, C, D, e, A,  3,        13);
+  J1(A, B, C, D, e,  8,        14);
+  J1(e, A, B, C, D, 11,        11);
+  J1(D, e, A, B, C,  6,         8);
+  J1(C, D, e, A, B, 15,         5);
+  J1(B, C, D, e, A, 13,         6);
+
+  J2(b, c, d, E, a, 12,         8);
+  J2(a, b, c, d, E, 15,         5);
+  J2(E, a, b, c, d, 10,        12);
+  J2(d, E, a, b, c,  4,         9);
+  J2(c, d, E, a, b,  1,        12);
+  J2(b, c, d, E, a,  5,         5);
+  J2(a, b, c, d, E,  8,        14);
+  J2(E, a, b, c, d,  7,         6);
+  J2(d, E, a, b, c,  6,         8);
+  J2(c, d, E, a, b,  2,        13);
+  J2(b, c, d, E, a, 13,         6);
+  J2(a, b, c, d, E, 14,         5);
+  J2(E, a, b, c, d,  0,        15);
+  J2(d, E, a, b, c,  3,        13);
+  J2(c, d, E, a, b,  9,        11);
+  J2(b, c, d, E, a, 11,        11);
+
+  /* --- Write out the result --- */
+
+  ctx->a += A;
+  ctx->b += B;
+  ctx->c += C;
+  ctx->d += D;
+  ctx->e += E;
+  ctx->A += a;
+  ctx->B += b;
+  ctx->C += c;
+  ctx->D += d;
+  ctx->E += e;
+}
+
+/* --- @rmd320_init@ --- *
+ *
+ * Arguments:  @rmd320_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void rmd320_init(rmd320_ctx *ctx)
+{
+  ctx->a = 0x67452301;
+  ctx->b = 0xefcdab89;
+  ctx->c = 0x98badcfe;
+  ctx->d = 0x10325476;
+  ctx->e = 0xc3d2e1f0;
+  ctx->A = 0x76543210;
+  ctx->B = 0xfedcba98;
+  ctx->C = 0x89abcdef;
+  ctx->D = 0x01234567;
+  ctx->E = 0x3c2d1e0f;
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+/* --- @rmd320_set@ --- *
+ *
+ * Arguments:  @rmd320_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 rmd320_set(rmd320_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->A = LOAD32_L(p + 20);
+  ctx->B = LOAD32_L(p + 24);
+  ctx->C = LOAD32_L(p + 28);
+  ctx->D = LOAD32_L(p + 32);
+  ctx->E = LOAD32_L(p + 36);
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @rmd320_hash@ --- *
+ *
+ * Arguments:  @rmd320_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 rmd320_hash(rmd320_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(RMD320, rmd320, ctx, buf, sz);
+}
+
+/* --- @rmd320_done@ --- *
+ *
+ * Arguments:  @rmd320_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void rmd320_done(rmd320_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_MD5STRENGTH(RMD320, rmd320, 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);
+  STORE32_L(p + 20, ctx->A);
+  STORE32_L(p + 24, ctx->B);
+  STORE32_L(p + 28, ctx->C);
+  STORE32_L(p + 32, ctx->D);
+  STORE32_L(p + 36, ctx->E);
+}
+
+/* --- @rmd320_state@ --- *
+ *
+ * Arguments:  @rmd320_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 @rmd320_set@.
+ */
+
+unsigned long rmd320_state(rmd320_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);
+  STORE32_L(p + 20, ctx->A);
+  STORE32_L(p + 24, ctx->B);
+  STORE32_L(p + 28, ctx->C);
+  STORE32_L(p + 32, ctx->D);
+  STORE32_L(p + 36, ctx->E);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(RMD320, rmd320)
+
+/* --- Test code --- */
+
+HASH_TEST(RMD320, rmd320)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/rmd320.h b/symm/rmd320.h
new file mode 100644 (file)
index 0000000..7fdf388
--- /dev/null
@@ -0,0 +1,160 @@
+/* -*-c-*-
+ *
+ * The RIPEMD-320 message digest function
+ *
+ * (c) 1998 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.
+ */
+
+/*----- Notes on the RIPEMD-320 hash function -----------------------------*
+ *
+ * RIPEMD-320 was invented by Hans Dobbertin, Antoon Bosselaers and Bart
+ * Preneel.  It's a double-width version of RIPEMD-160, constructed simply by
+ * not gluing together the two parallel computations which RIPEMD-160 usually
+ * does in its compression function.  The authors warn that, while its output
+ * is twice as wide as that of RIPEMD-160, they don't expect it to offer any
+ * more security.
+ */
+
+#ifndef CATACOMB_RMD320_H
+#define CATACOMB_RMD320_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define RMD320_BUFSZ 64
+#define RMD320_HASHSZ 40
+#define RMD320_STATESZ 40
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rmd320_ctx {
+  uint32 a, b, c, d, e;                        /* Chaining variables */
+  uint32 A, B, C, D, E;                        /* More chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[RMD320_BUFSZ];             /* Accumulation buffer */
+} rmd320_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rmd320_compress@ --- *
+ *
+ * Arguments:  @rmd320_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                RIPEMD-320 compression function.
+ */
+
+extern void rmd320_compress(rmd320_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @rmd320_init@ --- *
+ *
+ * Arguments:  @rmd320_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void rmd320_init(rmd320_ctx */*ctx*/);
+
+/* --- @rmd320_set@ --- *
+ *
+ * Arguments:  @rmd320_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 rmd320_set(rmd320_ctx */*ctx*/,
+                      const void */*buf*/, unsigned long /*count*/);
+
+/* --- @rmd320_hash@ --- *
+ *
+ * Arguments:  @rmd320_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 rmd320_hash(rmd320_ctx */*ctx*/,
+                       const void */*buf*/, size_t /*sz*/);
+
+/* --- @rmd320_done@ --- *
+ *
+ * Arguments:  @rmd320_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 rmd320_done(rmd320_ctx */*ctx*/, void */*hash*/);
+
+/* --- @rmd320_state@ --- *
+ *
+ * Arguments:  @rmd320_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 @rmd320_set@.
+ */
+
+extern unsigned long rmd320_state(rmd320_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash rmd320;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/safer-mktab.c b/symm/safer-mktab.c
new file mode 100644 (file)
index 0000000..d9ae784
--- /dev/null
@@ -0,0 +1,102 @@
+/* -*-c-*-
+ *
+ * Generate tables for SAFER
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(void)
+{
+  octet s[256], si[256];
+  unsigned x, i;
+
+  x = 1;
+  for (i = 0; i < 256; i++) {
+    if (x < 256) {
+      s[i] = x;
+      si[x] = i;
+    }
+    x = (x * 45)%257;
+  }
+  s[128] = 0;
+  si[0] = 128;
+
+  fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * SAFER tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_SAFER_TAB_H\n\
+#define CATACOMB_SAFER_TAB_H\n\
+\n\
+", stdout);
+
+  fputs("\
+/* --- S-boxes --- */\n\
+\n\
+#define SAFER_S {                                                      \\\n\
+  ", stdout);
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", s[i]);
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if ((i + 1)%8 == 0)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  fputs("\
+#define SAFER_SI {                                                     \\\n\
+  ", stdout);
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", si[i]);
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if ((i + 1)%8 == 0)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  puts("#endif");
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/safer.c b/symm/safer.c
new file mode 100644 (file)
index 0000000..055a5f6
--- /dev/null
@@ -0,0 +1,323 @@
+/* -*-c-*-
+ *
+ * The SAFER block cipher
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "paranoia.h"
+#include "safer.h"
+#include "safer-tab.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet safer_keysz[] = { KSZ_SET, 8, 16, 0 };
+
+/*----- Important tables --------------------------------------------------*/
+
+static const octet s[265] = SAFER_S, si[256] = SAFER_SI;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @safer_setup@ --- *
+ *
+ * Arguments:  @safer_ctx *k@ = pointer to context to initialize
+ *             @unsigned r@ = number of rounds wanted
+ *             @unsigned f@ = various other flags
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of key material in bytes
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an SAFER expanded key.  A default number of
+ *             rounds is chosen, based on the key length.
+ */
+
+struct ksched {
+  unsigned i;
+  octet x[9];
+};
+
+static void init(struct ksched *t, const octet *k)
+{
+  memcpy(t->x, k, 8);
+  t->i = 1;
+}
+
+static void init_sk(struct ksched *t, const octet *k)
+{
+  unsigned i;
+  octet x;
+  memcpy(t->x, k, 8);
+  for (x = 0, i = 0; i < 8; x ^= k[i++])
+    ;
+  t->x[8] = x;
+  t->i = 1;
+}
+
+static void next(struct ksched *t, octet *k)
+{
+  unsigned i;
+  if (k) {
+    memcpy(k, t->x, 8);
+    if (t->i > 1) {
+      for (i = 0; i < 8; i++)
+       k[i] += s[s[U8(9*t->i + i + 1)]];
+    }
+  }
+  for (i = 0; i < 8; i++)
+    t->x[i] = ROL8(t->x[i], 3);
+  t->i++;
+}
+
+static void next_sk(struct ksched *t, octet *k)
+{
+  unsigned i;
+  i = (t->i - 1)%9;
+  if (k) {
+    if (i < 2)
+      memcpy(k, t->x + i, 8);
+    else {
+      memcpy(k, t->x + i, 9 - i);
+      memcpy(k + 9 - i, t->x, i - 1);
+    }
+    if (t->i > 1) {
+      for (i = 0; i < 8; i++)
+       k[i] += s[s[U8(9*t->i + i + 1)]];
+    }
+  }
+  for (i = 0; i < 9; i++)
+    t->x[i] = ROL8(t->x[i], 3);
+  t->i++;
+}
+
+void safer_setup(safer_ctx *k, unsigned r, unsigned f,
+                const void *buf, size_t sz)
+{
+  struct ksched ka, kb;
+  void (*in)(struct ksched *, const octet *);
+  void (*nx)(struct ksched *, octet *);
+  octet *kk;
+
+  assert(r <= SAFER_MAXROUNDS);
+  KSZ_ASSERT(safer, sz);
+
+  if (f & SAFER_SK) {
+    in = init_sk;
+    nx = next_sk;
+  } else {
+    in = init;
+    nx = next;
+  }
+
+  in(&kb, buf);
+  in(&ka, sz == 8 ? buf : (const octet *)buf + 8);
+
+  k->r = r;
+  kk = k->k;
+  while (r) {
+    nx(&ka, kk); nx(&kb, 0); kk += 8;
+    nx(&kb, kk); nx(&ka, 0); kk += 8;
+    r--;
+  }
+  nx(&ka, kk); kk += 8;
+}
+
+/* --- @safer_init@, @safersk_init@ --- *
+ *
+ * Arguments:  @safer_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of key material in bytes
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an SAFER expanded key.  A default number of
+ *             rounds is chosen, based on the key length.
+ */
+
+void safer_init(safer_ctx *k, const void *buf, size_t sz)
+{
+  safer_setup(k, sz == 8 ? 6 : 10, 0, buf, sz);
+}
+
+void safersk_init(safer_ctx *k, const void *buf, size_t sz)
+{
+  safer_setup(k, sz == 8 ? 8 : 10, SAFER_SK, buf, sz);
+}
+
+/* --- @safer_eblk@, @safer_dblk@ --- *
+ *
+ * Arguments:  @const safer_ctx *k@ = pointer to SAFER context
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @const uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define UNPACK(src, a, b, c, d, e, f, g, h) do {                       \
+  a = U8(src[0] >> 24); b = U8(src[0] >> 16);                          \
+  c = U8(src[0] >>  8); d = U8(src[0] >>  0);                          \
+  e = U8(src[1] >> 24); f = U8(src[1] >> 16);                          \
+  g = U8(src[1] >>  8); h = U8(src[1] >>  0);                          \
+} while (0)
+
+#define PACK(dst, a, b, c, d, e, f, g, h) do {                         \
+  dst[0] = (U8(a) << 24) | (U8(b) << 16) | (U8(c) << 8) | U8(d);       \
+  dst[1] = (U8(e) << 24) | (U8(f) << 16) | (U8(g) << 8) | U8(h);       \
+} while (0)
+
+#define F(x, y) y += x, x += y
+#define G(x, y) x -= y, y -= x
+
+#define PHT(a, b, c, d, e, f, g, h) do {                               \
+  F(a, b); F(c, d); F(e, f); F(g, h);                                  \
+  F(a, c); F(e, g); F(b, d); F(f, h);                                  \
+  F(a, e); F(b, f); F(c, g); F(d, h);                                  \
+} while (0)
+ #define IPHT(a, b, c, d, e, f, g, h) do {                             \
+  G(a, e); G(b, f); G(c, g); G(d, h);                                  \
+  G(a, c); G(e, g); G(b, d); G(f, h);                                  \
+  G(a, b); G(c, d); G(e, f); G(g, h);                                  \
+} while (0)
+
+#define KXA(k, a, b, c, d, e, f, g, h) do {                            \
+  a ^= *k++; b += *k++; c += *k++; d ^= *k++;                          \
+  e ^= *k++; f += *k++; g += *k++; h ^= *k++;                          \
+} while (0)
+#define SUB(a, b, c, d, e, f, g, h) do {                               \
+  a = s[U8(a)]; b = si[U8(b)]; c = si[U8(c)]; d = s[U8(d)];            \
+  e = s[U8(e)]; f = si[U8(f)]; g = si[U8(g)]; h = s[U8(h)];            \
+} while (0)
+#define KAX(k, a, b, c, d, e, f, g, h) do {                            \
+  a += *k++; b ^= *k++; c ^= *k++; d += *k++;                          \
+  e += *k++; f ^= *k++; g ^= *k++; h += *k++;                          \
+} while (0)
+
+#define KXS(k, a, b, c, d, e, f, g, h) do {                            \
+  h ^= *--k; g -= *--k; f -= *--k; e ^= *--k;                          \
+  d ^= *--k; c -= *--k; b -= *--k; a ^= *--k;                          \
+} while (0)
+#define ISUB(a, b, c, d, e, f, g, h) do {                              \
+  a = si[U8(a)]; b = s[U8(b)]; c = s[U8(c)]; d = si[U8(d)];            \
+  e = si[U8(e)]; f = s[U8(f)]; g = s[U8(g)]; h = si[U8(h)];            \
+} while (0)
+#define KSX(k, a, b, c, d, e, f, g, h) do {                            \
+  h -= *--k; g ^= *--k; f ^= *--k; e -= *--k;                          \
+  d -= *--k; c ^= *--k; b ^= *--k; a -= *--k;                          \
+} while (0)
+
+#define EROUND(k, a, b, c, d, e, f, g, h) do {                         \
+  KXA(k, a, b, c, d, e, f, g, h);                                      \
+  SUB(a, b, c, d, e, f, g, h);                                         \
+  KAX(k, a, b, c, d, e, f, g, h);                                      \
+  PHT(a, b, c, d, e, f, g, h);                                         \
+} while (0)
+
+#define DROUND(k, a, b, c, d, e, f, g, h) do {                         \
+  IPHT(a, b, c, d, e, f, g, h);                                                \
+  KSX(k, a, b, c, d, e, f, g, h);                                      \
+  ISUB(a, b, c, d, e, f, g, h);                                                \
+  KXS(k, a, b, c, d, e, f, g, h);                                      \
+} while (0)
+
+
+void safer_eblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
+{
+  octet a, b, c, d, e, f, g, h;
+  unsigned r = k->r;
+  const octet *kk = k->k;
+
+  UNPACK(src, a, b, c, d, e, f, g, h);
+  while (r >= 3) {
+    EROUND(kk, a, b, c, d, e, f, g, h);
+    EROUND(kk, a, e, b, f, c, g, d, h);
+    EROUND(kk, a, c, e, g, b, d, f, h);
+    r -= 3;
+  }
+  switch (r) {
+    case 0:
+      KXA(kk, a, b, c, d, e, f, g, h);
+      PACK(dst, a, b, c, d, e, f, g ,h);
+      break;
+    case 1:
+      EROUND(kk, a, b, c, d, e, f, g, h);
+      KXA(kk, a, e, b, f, c, g, d, h);
+      PACK(dst, a, e, b, f, c, g, d, h);
+      break;
+    case 2:
+      EROUND(kk, a, b, c, d, e, f, g, h);
+      EROUND(kk, a, e, b, f, c, g, d, h);
+      KXA(kk, a, c, e, g, b, d, f, h);
+      PACK(dst, a, c, e, g, b, d, f, h);
+      break;
+  }
+}
+
+void safer_dblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
+{
+  octet a, b, c, d, e, f, g, h;
+  unsigned r = k->r;
+  const octet *kk = k->k + 16 * r + 8;
+  switch (r%3) {
+    default:
+    case 0:
+      UNPACK(src, a, b, c, d, e, f, g, h);
+      KXS(kk, a, b, c, d, e, f, g, h);
+      break;
+    case 1:
+      UNPACK(src, a, e, b, f, c, g, d, h);
+      KXS(kk, a, e, b, f, c, g, d, h);
+      r--;
+      goto one_round;
+    case 2:
+      UNPACK(src, a, c, e, g, b, d, f, h);
+      KXS(kk, a, c, e, g, b, d, f, h);
+      r -= 2;
+      DROUND(kk, a, e, b, f, c, g, d, h);
+    one_round:
+      DROUND(kk, a, b, c, d, e, f, g, h);
+      break;
+  }
+  while (r) {
+    DROUND(kk, a, c, e, g, b, d, f, h);
+    DROUND(kk, a, e, b, f, c, g, d, h);
+    DROUND(kk, a, b, c, d, e, f, g, h);
+    r -= 3;
+  }
+  PACK(dst, a, b, c, d, e, f, g, h);
+}
+
+BLKC_TEST(SAFER, safer)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/safer.h b/symm/safer.h
new file mode 100644 (file)
index 0000000..6186d96
--- /dev/null
@@ -0,0 +1,139 @@
+/* -*-c-*-
+ *
+ * The SAFER block cipher
+ *
+ * (c) 2001 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.
+ */
+
+/*----- Notes on the SAFER block cipher -----------------------------------*
+ *
+ * SAFER was designed by James Massey (who also worked on IDEA) for Cylink.
+ * It's free -- patents or other silliness.  The original key schedule had
+ * some weaknesses, and a new one (the SK version) was added.  SAFER has a
+ * variable number of rounds.  The standard interface uses the recommended
+ * number for the given key schedule algorithm and key size.
+ *
+ * SAFER got a bad press in Schneier's book `Applied Cryptography'.  I think
+ * this is undeserved.  SAFER is a well-designed cipher which mostly looks
+ * pretty solid.
+ */
+
+#ifndef CATACOMB_SAFER_H
+#define CATACOMB_SAFER_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define SAFER_BLKSZ 8
+#define SAFER_KEYSZ 8
+#define SAFER_CLASS (N, B, 64)
+
+#define SAFERSK_BLKSZ SAFER_BLKSZ
+#define SAFERSK_KEYSZ 16
+#define SAFERSK_CLASS SAFER_CLASS
+
+#define SAFER_MAXROUNDS 12
+
+extern const octet safer_keysz[];
+#define safersk_keysz safer_keysz
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct safer_ctx {
+  octet k[8 * (2 * SAFER_MAXROUNDS + 1)];
+  unsigned r;
+} safer_ctx, safersk_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @safer_setup@ --- *
+ *
+ * Arguments:  @safer_ctx *k@ = pointer to context to initialize
+ *             @unsigned r@ = number of rounds wanted
+ *             @unsigned f@ = various other flags
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of key material in bytes
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an SAFER expanded key.  A default number of
+ *             rounds is chosen, based on the key length.
+ */
+
+#define SAFER_SK 1u
+
+extern void safer_setup(safer_ctx */*k*/, unsigned /*r*/, unsigned /*f*/,
+                       const void */*buf*/, size_t /*sz*/);
+
+/* --- @safer_init@, @safersk_init@ --- *
+ *
+ * Arguments:  @safer_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of key material in bytes
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an SAFER expanded key.  A default number of
+ *             rounds is chosen, based on the key length.
+ */
+
+extern void safer_init(safer_ctx */*k*/,
+                      const void */*buf*/, size_t /*sz*/);
+extern void safersk_init(safer_ctx */*k*/,
+                        const void */*buf*/, size_t /*sz*/);
+
+/* --- @safer_eblk@, @safer_dblk@ --- *
+ *
+ * Arguments:  @const safer_ctx *k@ = pointer to SAFER context
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @const uint32 d[2]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void safer_eblk(const safer_ctx */*k*/,
+                      const uint32 */*s*/, uint32 */*dst*/);
+extern void safer_dblk(const safer_ctx */*k*/,
+                      const uint32 */*s*/, uint32 */*dst*/);
+
+#define safersk_eblk safer_eblk
+#define safersk_dblk safer_dblk
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/safersk.c b/symm/safersk.c
new file mode 100644 (file)
index 0000000..e665410
--- /dev/null
@@ -0,0 +1,14 @@
+/* -*-c-*-
+ *
+ * Stub source for SAFER SK
+ *
+ * (c) 2001 Straylight/Edgeware
+ */
+
+#include "blkc.h"
+#include "safersk.h"
+
+const char *safersk_magic = "Compile this useless file";
+
+BLKC_TEST(SAFERSK, safersk)
+
diff --git a/symm/safersk.h b/symm/safersk.h
new file mode 100644 (file)
index 0000000..7087432
--- /dev/null
@@ -0,0 +1,15 @@
+/* -*-c-*-
+ *
+ * Stub header for SAFER SK
+ *
+ * (c) 2001 Straylight/Edgeware
+ */
+
+#ifndef CATACOMB_SAFERSK_H
+#define CATACOMB_SAFERSK_H
+
+#include "safer.h"
+
+extern const char *safersk_magic;
+
+#endif
diff --git a/symm/seal.c b/symm/seal.c
new file mode 100644 (file)
index 0000000..df7cd1b
--- /dev/null
@@ -0,0 +1,614 @@
+/* -*-c-*-
+ *
+ * The SEAL pseudo-random function family
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "arena.h"
+#include "gcipher.h"
+#include "grand.h"
+#include "paranoia.h"
+#include "seal.h"
+#include "sha.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet seal_keysz[] = { KSZ_ANY, SHA_HASHSZ };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gamma@ --- *
+ *
+ * Arguments:  @uint32 *p@ = output table
+ *             @size_t sz@ = size of the output table
+ *             @const void *k@ = pointer to key material
+ *             @unsigned i@ = integer offset
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a SEAL key table.
+ */
+
+static void gamma(uint32 *p, size_t sz, const void *k, unsigned i)
+{
+  uint32 buf[80] = { 0 };
+  const octet *kk = k;
+  uint32 aa = LOAD32(kk);
+  uint32 bb = LOAD32(kk + 4);
+  uint32 cc = LOAD32(kk + 8);
+  uint32 dd = LOAD32(kk + 12);
+  uint32 ee = LOAD32(kk + 16);
+
+  unsigned skip = i % 5;
+  i /= 5;
+
+  /* --- While there's hashing to do, do hashing --- */
+
+  while (sz) {
+    uint32 a = aa, b = bb, c = cc, d = dd, e = ee;
+    int j;
+
+    /* --- Initialize and expand the buffer --- */
+
+    buf[0] = i++;
+
+    for (j = 16; j < 80; j++) {
+      uint32 x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16];
+      buf[j] = ROL32(x, 1);
+    }
+
+    /* --- 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) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+
+#define T(v, w, x, y, z, i, f, k) do {                                 \
+  uint32 _x;                                                           \
+  z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k;                       \
+  w = ROR32(w, 2);                                                     \
+  _x = v; v = z; z = y; y = x; x = w; w = _x;                          \
+} while (0)
+
+#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999)
+#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1)
+#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc)
+#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6)
+
+    /* --- The main compression function --- *
+     *
+     * Since this isn't doing bulk hashing, do it the easy way.
+     */
+
+    for (j = 0; j < 20; j++)
+      FF(a, b, c, d, e, j);
+    for (j = 20; j < 40; j++)
+      GG(a, b, c, d, e, j);
+    for (j = 40; j < 60; j++)
+      HH(a, b, c, d, e, j);
+    for (j = 60; j < 80; j++)
+      II(a, b, c, d, e, j);
+
+    /* --- Do the chaining at the end --- */
+
+    a += aa; b += bb; c += cc; d += dd; e += ee;
+
+    /* --- Write to the output buffer --- */
+
+    switch (skip) {
+      case 0:
+       if (sz) { *p++ = a; sz--; }
+      case 1:
+       if (sz) { *p++ = b; sz--; }
+      case 2:
+       if (sz) { *p++ = c; sz--; }
+      case 3:
+       if (sz) { *p++ = d; sz--; }
+      case 4:
+       if (sz) { *p++ = e; sz--; }
+       skip = 0;
+    }
+  }
+}
+
+/* --- @seal_initkey@ --- *
+ *
+ * Arguments:  @seal_key *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a SEAL key block.  The key material may be any
+ *             size, but if it's not 20 bytes long it's passed to SHA for
+ *             hashing first.
+ */
+
+void seal_initkey(seal_key *k, const void *buf, size_t sz)
+{
+  /* --- Hash the key if it's the wrong size --- */
+
+  if (sz == SHA_HASHSZ)
+    memcpy(k->k, buf, sizeof(k->k));
+  else {
+    sha_ctx c;
+    sha_init(&c);
+    sha_hash(&c, buf, sz);
+    sha_done(&c, k->k);
+  }
+
+  /* --- Expand the key to fit the various tables --- */
+
+  gamma(k->t, 512, k->k, 0);
+  gamma(k->s, 256, k->k, 0x1000);
+  gamma(k->r, SEAL_R, k->k, 0x2000);
+}
+
+/* --- @seal_reset@ --- *
+ *
+ * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
+ *
+ * Returns:    ---
+ *
+ * Use:                Resets the context so that more data can be extracted from
+ *             it.
+ */
+
+static void seal_reset(seal_ctx *c)
+{
+  seal_key *k = c->k;
+  uint32 n = c->n;
+  uint32 A, B, C, D;
+  unsigned p;
+
+  /* --- Initialize the new chaining variables --- */
+
+  if (c->l >= SEAL_R) {
+    gamma(c->rbuf, SEAL_R, k->k, c->ri);
+    c->ri += SEAL_R;
+    c->l = 0;
+    c->r = c->rbuf;
+  }
+
+  A = n ^ c->r[0];
+  B = ROR32(n, 8) ^ c->r[1];
+  C = ROR32(n, 16) ^ c->r[2];
+  D = ROR32(n, 24) ^ c->r[3];
+  c->l += 4;
+  c->r += 4;
+
+  /* --- Ensure that everything is sufficiently diffused --- */
+
+  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+
+  /* --- Write out some context --- */
+
+  c->n1 = D; c->n2 = B; c->n3 = A; c->n4 = C;
+
+  /* --- Diffuse some more --- */
+
+  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+
+  /* --- Write out the magic numbers --- */
+
+  c->a = A; c->b = B; c->c = C; c->d = D;
+  c->i = 0;
+}
+
+/* --- @seal_initctx@ --- *
+ *
+ * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
+ *             @seal_key *k@ = pointer to a SEAL key
+ *             @uint32 n@ = integer sequence number
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a SEAL context which can be used for random
+ *             number generation or whatever.
+ */
+
+void seal_initctx(seal_ctx *c, seal_key *k, uint32 n)
+{
+  c->k = k;
+  c->n = n;
+  c->l = 0;
+  c->r = k->r;
+  c->ri = 0x2000 + SEAL_R;
+  c->qsz = 0;
+  seal_reset(c);
+}
+
+/* --- @seal_encrypt@ --- *
+ *
+ * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
+ *             @const void *src@ = pointer to source data
+ *             @void *dest@ = pointer to destination data
+ *             @size_t sz@ = size of the data
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts a block of data using SEAL.  If @src@ is zero,
+ *             @dest@ is filled with SEAL output.  If @dest@ is zero, the
+ *             SEAL generator is just spun around for a bit.  This shouldn't
+ *             be necessary, because SEAL isn't RC4.
+ */
+
+void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz)
+{
+  const octet *s = src;
+  octet *d = dest;
+
+  /* --- Expect a big dollop of bytes --- */
+
+  if (sz > c->qsz) {
+    seal_key *k = c->k;
+    uint32 A = c->a, B = c->b, C = c->c, D = c->d;
+    uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
+    uint32 aa, bb, cc, dd;
+    unsigned j = c->i;
+
+    /* --- Empty the queue first --- */
+
+    if (c->qsz) {
+      if (d) {
+       unsigned i;
+       octet *p = c->q + sizeof(c->q) - c->qsz;
+       for (i = 0; i < c->qsz; i++)
+         *d++ = (s ? *s++ ^ *p++ : *p++);
+      }
+      sz -= c->qsz;
+    }
+
+    /* --- Main sequence --- */
+
+    for (;;) {
+      unsigned P, Q;
+
+      /* --- Reset if we've run out of steam on this iteration --- */
+
+      if (j == 256) {
+       seal_reset(c);
+       A = c->a, B = c->b, C = c->c, D = c->d;
+       n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
+       j = 0;
+      }
+
+      /* --- Make some new numbers --- */
+
+      P = A & 0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A;
+      Q = B & 0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B;
+      P = (P + C) & 0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C;
+      Q = (Q + D) & 0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D;
+      P = (P + A) & 0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9);
+      Q = (Q + B) & 0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9);
+      P = (P + C) & 0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9);
+      Q = (Q + D) & 0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9);
+
+      /* --- Remember the output and set up the next round --- */
+
+      aa = B + k->s[j + 0];
+      bb = C ^ k->s[j + 1];
+      cc = D + k->s[j + 2];
+      dd = A ^ k->s[j + 3];
+      j += 4;
+
+      if (j & 4)
+       A += n1, B += n2, C ^= n1, D ^= n2;
+      else
+       A += n3, B += n4, C ^= n3, D ^= n4;
+
+      /* --- Bail out here if we need to do buffering --- */
+
+      if (sz < 16)
+       break;
+
+      /* --- Write the next 16 bytes --- */
+
+      if (d) {
+       if (s) {
+         aa ^= LOAD32_L(s + 0);
+         bb ^= LOAD32_L(s + 4);
+         cc ^= LOAD32_L(s + 8);
+         dd ^= LOAD32_L(s + 12);
+         s += 16;
+       }
+       STORE32_L(d + 0, aa);
+       STORE32_L(d + 4, bb);
+       STORE32_L(d + 8, cc);
+       STORE32_L(d + 12, dd);
+       d += 16;
+      }
+      sz -= 16;
+    }
+
+    /* --- Write the new queue --- */
+
+    STORE32_L(c->q + 0, aa);
+    STORE32_L(c->q + 4, bb);
+    STORE32_L(c->q + 8, cc);
+    STORE32_L(c->q + 12, dd);
+    c->qsz = 16;
+
+    c->a = A; c->b = B; c->c = C; c->d = D;
+    c->i = j;
+  }
+
+  /* --- Deal with the rest from the queue --- */
+
+  if (sz) {
+    unsigned i;
+    octet *p = c->q + sizeof(c->q) - c->qsz;
+    if (d) {
+      for (i = 0; i < sz; i++)
+       *d++ = (s ? *s++ ^ *p++ : *p++);
+    }
+    c->qsz -= sz;
+  }
+}
+
+/*----- Generic cipher interface ------------------------------------------*/
+
+typedef struct gctx {
+  gcipher c;
+  seal_key k;
+  seal_ctx cc;
+} gctx;
+
+static const gcipher_ops gops;
+
+static gcipher *ginit(const void *k, size_t sz)
+{
+  gctx *g = S_CREATE(gctx);
+  g->c.ops = &gops;
+  seal_initkey(&g->k, k, sz);
+  seal_initctx(&g->cc, &g->k, 0);
+  return (&g->c);
+}
+
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
+{
+  gctx *g = (gctx *)c;
+  seal_encrypt(&g->cc, s, t, sz);
+}
+
+static void gsetiv(gcipher *c, const void *iv)
+{
+  gctx *g = (gctx *)c;
+  uint32 n = *(const uint32 *)iv;
+  seal_initctx(&g->cc, &g->k, n);
+}
+
+static void gdestroy(gcipher *c)
+{
+  gctx *g = (gctx *)c;
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static const gcipher_ops gops = {
+  &seal,
+  gencrypt, gencrypt, gdestroy, gsetiv, 0
+};
+
+const gccipher seal = {
+  "seal", seal_keysz, 0,
+  ginit
+};
+
+/*----- Generic random number generator interface -------------------------*/
+
+typedef struct grctx {
+  grand r;
+  seal_key k;
+  seal_ctx cc;
+} grctx;
+
+static void grdestroy(grand *r)
+{
+  grctx *g = (grctx *)r;
+  BURN(*g);
+  S_DESTROY(g);
+}
+
+static int grmisc(grand *r, unsigned op, ...)
+{
+  grctx *g = (grctx *)r;
+  va_list ap;
+  int rc = 0;
+  va_start(ap, op);
+
+  switch (op) {
+    case GRAND_CHECK:
+      switch (va_arg(ap, unsigned)) {
+       case GRAND_CHECK:
+       case GRAND_SEEDINT:
+       case GRAND_SEEDUINT32:
+       case GRAND_SEEDBLOCK:
+       case GRAND_SEEDRAND:
+         rc = 1;
+         break;
+       default:
+         rc = 0;
+         break;
+      }
+      break;
+    case GRAND_SEEDINT:
+      seal_initctx(&g->cc, &g->k, va_arg(ap, int));
+      break;
+    case GRAND_SEEDUINT32:
+      seal_initctx(&g->cc, &g->k, va_arg(ap, uint32));
+      break;
+    case GRAND_SEEDBLOCK: {
+      const void *p = va_arg(ap, const void *);
+      size_t sz = va_arg(ap, size_t);
+      uint32 n;
+      if (sz >= 4)
+       n = LOAD32_L(p);
+      else {
+       octet buf[4] = { 0 };
+       memcpy(buf, p, sz);
+       n = LOAD32_L(p);
+      }
+      seal_initctx(&g->cc, &g->k, n);
+    } break;
+    case GRAND_SEEDRAND: {
+      grand *rr = va_arg(ap, grand *);
+      seal_initctx(&g->cc, &g->k, rr->ops->word(rr));
+    } break;
+    default:
+      GRAND_BADOP;
+      break;
+  }
+
+  va_end(ap);
+  return (rc);
+}
+
+static octet grbyte(grand *r)
+{
+  grctx *g = (grctx *)r;
+  octet o;
+  seal_encrypt(&g->cc, 0, &o, 1);
+  return (o);
+}
+
+static uint32 grword(grand *r)
+{
+  grctx *g = (grctx *)r;
+  octet b[4];
+  seal_encrypt(&g->cc, 0, b, 4);
+  return (LOAD32(b));
+}
+
+static void grfill(grand *r, void *p, size_t sz)
+{
+  grctx *g = (grctx *)r;
+  seal_encrypt(&g->cc, 0, p, sz);
+}
+
+static const grand_ops grops = {
+  "seal",
+  GRAND_CRYPTO, 0,
+  grmisc, grdestroy,
+  grword, grbyte, grword, grand_range, grfill
+};
+
+/* --- @seal_rand@ --- *
+ *
+ * Arguments:  @const void *k@ = pointer to key material
+ *             @size_t sz@ = size of key material
+ *             @uint32 n@ = sequence number
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a random number interface wrapper around a SEAL
+ *             pseudorandom function.
+ */
+
+grand *seal_rand(const void *k, size_t sz, uint32 n)
+{
+  grctx *g = S_CREATE(grctx);
+  g->r.ops = &grops;
+  seal_initkey(&g->k, k, sz);
+  seal_initctx(&g->cc, &g->k, n);
+  return (&g->r);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <string.h>
+
+#include <mLib/testrig.h>
+
+static int verify(dstr *v)
+{
+  seal_key k;
+  seal_ctx c;
+  uint32 n = *(uint32 *)v[1].buf;
+  dstr d = DSTR_INIT;
+  dstr z = DSTR_INIT;
+  int i;
+  int ok = 1;
+
+  DENSURE(&d, v[2].len);
+  DENSURE(&z, v[2].len);
+  memset(z.buf, 0, v[2].len);
+  z.len = d.len = v[2].len;
+  seal_initkey(&k, v[0].buf, v[0].len);
+
+  for (i = 0; i < v[2].len; i++) {
+    seal_initctx(&c, &k, n);
+    seal_encrypt(&c, 0, d.buf, i);
+    seal_encrypt(&c, z.buf, d.buf + i, d.len - i);
+    if (memcmp(d.buf, v[2].buf, d.len) != 0) {
+      ok = 0;
+      printf("*** seal failure\n");
+      printf("*** k = "); type_hex.dump(&v[0], stdout); putchar('\n');
+      printf("*** n = %08lx\n", (unsigned long)n);
+      printf("*** i = %i\n", i);
+      printf("*** expected = "); type_hex.dump(&v[2], stdout); putchar('\n');
+      printf("*** computed = "); type_hex.dump(&d, stdout); putchar('\n');
+    }
+  }
+
+  dstr_destroy(&d);
+  dstr_destroy(&z);
+
+  return (ok);
+}
+
+static test_chunk defs[] = {
+  { "seal", verify, { &type_hex, &type_uint32, &type_hex, 0 } },
+  { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+  test_run(argc, argv, defs, SRCDIR"/t/seal");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/seal.h b/symm/seal.h
new file mode 100644 (file)
index 0000000..875994e
--- /dev/null
@@ -0,0 +1,163 @@
+/* -*-c-*-
+ *
+ * The SEAL pseudo-random function family
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the SEAL pseudo-random function family -------------------*
+ *
+ * SEAL is a slightly odd cryptographic primitive.  It was designed by Phil
+ * Rogaway and Don Coppersmith at IBM, basically as an exercise in producing
+ * a really fast symmetric cipher of some kind.  They succeeded: SEAL is
+ * faster than the much simpler RC4.
+ *
+ * For each key, it gives you %$2^{32}$% different output streams.  This
+ * implementation imposes no length limits on the size of output streams and
+ * performs careful buffer handling to allow arbitrary amounts of data to be
+ * extracted.  In practice, extracting more than about 64K is possibly dodgy
+ * from a security point of view.
+ *
+ * SEAL is patented.
+ */
+
+#ifndef CATACOMB_SEAL_H
+#define CATACOMB_SEAL_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+#define SEAL_R 256
+
+typedef struct seal_key {
+  octet k[20];                         /* Copy of the 160-bit key */
+  uint32 t[512];                       /* Substitution table */
+  uint32 s[256];                       /* Magic for each iteration */
+  uint32 r[SEAL_R];                    /* Magic for the first 64K */
+} seal_key;
+
+typedef struct seal_ctx {
+  seal_key *k;                         /* Pointer to the key block */
+  uint32 *r, ri;                       /* Pointer to current magic */
+  uint32 n, l;                         /* Various indices into things */
+  uint32 a, b, c, d;                   /* Current chaining variables */
+  uint32 n1, n2, n3, n4;               /* Increments for the variables */
+  unsigned i;                          /* Index into current iteration */
+  octet q[16];                         /* Output buffer */
+  unsigned qsz;                                /* Number of bytes in the buffer */
+  uint32 rbuf[SEAL_R];                 /* Buffer for later magic */
+} seal_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @seal_initkey@ --- *
+ *
+ * Arguments:  @seal_key *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a SEAL key block.  The key material may be any
+ *             size, but if it's not 20 bytes long it's passed to SHA for
+ *             hashing first.
+ */
+
+extern void seal_initkey(seal_key */*k*/,
+                        const void */*buf*/, size_t /*sz*/);
+
+/* --- @seal_initctx@ --- *
+ *
+ * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
+ *             @seal_key *k@ = pointer to a SEAL key
+ *             @uint32 n@ = integer sequence number
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a SEAL context which can be used for random
+ *             number generation or whatever.
+ */
+
+extern void seal_initctx(seal_ctx */*c*/, seal_key */*k*/, uint32 /*n*/);
+
+/* --- @seal_encrypt@ --- *
+ *
+ * Arguments:  @seal_ctx *c@ = pointer to a SEAL context
+ *             @const void *src@ = pointer to source data
+ *             @void *dest@ = pointer to destination data
+ *             @size_t sz@ = size of the data
+ *
+ * Returns:    ---
+ *
+ * Use:                Encrypts a block of data using SEAL.  If @src@ is zero,
+ *             @dest@ is filled with SEAL output.  If @dest@ is zero, the
+ *             SEAL generator is just spun around for a bit.  This shouldn't
+ *             be necessary, because SEAL isn't RC4.
+ */
+
+extern void seal_encrypt(seal_ctx */*c*/, const void */*src*/,
+                        void */*dest*/, size_t /*sz*/);
+
+/*----- Generic cipher interface ------------------------------------------*/
+
+#define SEAL_KEYSZ 20
+extern const octet seal_keysz[];
+
+extern const gccipher seal;
+
+/*----- Generic random number generator interface -------------------------*/
+
+/* --- @seal_rand@ --- *
+ *
+ * Arguments:  @const void *k@ = pointer to key material
+ *             @size_t sz@ = size of key material
+ *             @uint32 n@ = sequence number
+ *
+ * Returns:    Pointer to generic random number generator interface.
+ *
+ * Use:                Creates a random number interface wrapper around a SEAL
+ *             pseudorandom function.
+ */
+
+extern grand *seal_rand(const void */*k*/, size_t /*sz*/, uint32 /*n*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/serpent-check.c b/symm/serpent-check.c
new file mode 100644 (file)
index 0000000..7f95ffc
--- /dev/null
@@ -0,0 +1,99 @@
+/* -*-c-*-
+ *
+ * Check the Serpent S-boxes
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "serpent-sbox.h"
+
+/*----- S-box tables ------------------------------------------------------*/
+
+static const octet s[8][16] = {
+  {  3,         8, 15,  1, 10,  6,  5, 11, 14, 13,  4,  2,  7,  0,  9, 12 },
+  { 15, 12,  2,         7,  9,  0,  5, 10,  1, 11, 14,  8,  6, 13,  3,  4 },
+  {  8,         6,  7,  9,  3, 12, 10, 15, 13,  1, 14,  4,  0, 11,  5,  2 },
+  {  0, 15, 11,         8, 12,  9,  6,  3, 13,  1,  2,  4, 10,  7,  5, 14 },
+  {  1, 15,  8,         3, 12,  0, 11,  6,  2,  5,  4, 10,  9, 14,  7, 13 },
+  { 15,         5,  2, 11,  4, 10,  9, 12,  0,  3, 14,  8, 13,  6,  7,  1 },
+  {  7,         2, 12,  5,  8,  4,  6, 11, 14,  9,  1, 15, 13,  3, 10,  0 },
+  {  1, 13, 15,         0, 14,  8,  2, 11,  7,  4, 12, 10,  9,  3,  5,  6 }
+};
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @check@ --- *
+ *
+ * Arguments:  @unsigned a, b, c, d@ = four bitslice output registers
+ *             @const octet *p@ = pointer to S-box
+ *
+ * Returns:    Zero if OK, nonzero on failure.
+ *
+ * Use:                Checks that an S-box output is correct.
+ */
+
+static int check(unsigned a, unsigned b, unsigned c, unsigned d,
+                const octet *p)
+{
+  octet buf[16];
+  octet *q = buf;
+  unsigned i;
+
+  for (i = 0; i < 16; i++) {
+    *q++ = (a & 1) | ((b & 1) << 1) | ((c & 1) << 2) | ((d & 1) << 3);
+    a >>= 1; b >>= 1; c >>= 1; d >>= 1;
+  }
+  return (memcmp(buf, p, sizeof(buf)));
+}
+
+#define CHECK(i) do {                                                  \
+  unsigned a = 0xaaaa, b = 0xcccc, c = 0xf0f0, d = 0xff00;             \
+  S##i(a, b, c, d);                                                    \
+  if (check(a, b, c, d, s[i])) {                                       \
+    fprintf(stderr, "failure in S%i\n", i);                            \
+    rc = EXIT_FAILURE;                                                 \
+  }                                                                    \
+  IS##i(a, b, c, d);                                                   \
+  if (a != 0xaaaa || b != 0xcccc || c != 0xf0f0 || d != 0xff00) {      \
+    fprintf(stderr, "failure in IS%i\n", i);                           \
+    rc = EXIT_FAILURE;                                                 \
+  }                                                                    \
+} while (0)
+
+int main(void)
+{
+  int rc = 0;
+  CHECK(0); CHECK(1); CHECK(2); CHECK(3);
+  CHECK(4); CHECK(5); CHECK(6); CHECK(7);
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/serpent-sbox.h b/symm/serpent-sbox.h
new file mode 100644 (file)
index 0000000..f59155c
--- /dev/null
@@ -0,0 +1,228 @@
+/* -*-c-*-
+ *
+ * Bitslice S-box implementations
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Credit where it's due ---------------------------------------------*
+ *
+ * These S-box expressions are taken from the paper `Speeding up Serpent', by
+ * Dag Arne Osvik, submitted to AES3.
+ */
+
+#ifndef CATACOMB_SERPENT_SBOX_H
+#define CATACOMB_SERPENT_SBOX_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Macros provided ---------------------------------------------------*/
+
+/* --- @S0@ --- */
+
+#define S0(r0, r1, r2, r3) do {                                                \
+  uint32 r4;                                                           \
+  r3 ^= r0; r4 = r1; r1 &= r3; r4 ^= r2;                               \
+  r1 ^= r0; r0 |= r3; r0 ^= r4; r4 ^= r3;                              \
+  r3 ^= r2; r2 |= r1; r2 ^= r4; r4 = ~r4;                              \
+  r4 |= r1; r1 ^= r3; r1 ^= r4; r3 |= r0;                              \
+  r1 ^= r3; r4 ^= r3;                                                  \
+  r3 = r0; r0 = r1; r1 = r4;                                           \
+} while (0)
+
+#define IS0(r0, r1, r2, r3) do {                                       \
+  uint32 r4;                                                           \
+  r2 = ~r2; r4 = r1; r1 |= r0; r4 = ~r4;                               \
+  r1 ^= r2; r2 |= r4; r1 ^= r3; r0 ^= r4;                              \
+  r2 ^= r0; r0 &= r3; r4 ^= r0; r0 |= r1;                              \
+  r0 ^= r2; r3 ^= r4; r2 ^= r1; r3 ^= r0;                              \
+  r3 ^= r1; r2 &= r3; r4 ^= r2;                                                \
+  r2 = r1; r1 = r4;                                                    \
+} while (0)
+
+/* --- @S1@ --- */
+
+#define S1(r0, r1, r2, r3) do {                                                \
+  uint32 r4;                                                           \
+  r0 = ~r0; r2 = ~r2; r4  = r0; r0 &= r1;                              \
+  r2 ^= r0; r0 |= r3; r3 ^= r2; r1 ^= r0;                              \
+  r0 ^= r4; r4 |= r1; r1 ^= r3; r2 |= r0;                              \
+  r2 &= r4; r0 ^= r1; r1 &= r2; r1 ^= r0;                              \
+  r0 &= r2; r0 ^= r4;                                                  \
+  r4 = r0; r0 = r2; r2 = r3; r3 = r1; r1 = r4;                         \
+} while (0)
+
+#define IS1(r0, r1, r2, r3) do {                                       \
+  uint32 r4;                                                           \
+  r4  = r1; r1 ^= r3; r3 &= r1; r4 ^= r2;                              \
+  r3 ^= r0; r0 |= r1; r2 ^= r3; r0 ^= r4;                              \
+  r0 |= r2; r1 ^= r3; r0 ^= r1; r1 |= r3;                              \
+  r1 ^= r0; r4 = ~r4; r4 ^= r1; r1 |= r0;                              \
+  r1 ^= r0; r1 |= r4; r3 ^= r1;                                                \
+  r1 = r0; r0 = r4; r4 = r2; r2 = r3; r3 = r4;                         \
+} while (0)
+
+/* --- @S2@ --- */
+
+#define S2(r0, r1, r2, r3) do {                                                \
+  uint32 r4;                                                           \
+  r4  = r0; r0 &= r2; r0 ^= r3; r2 ^= r1;                              \
+  r2 ^= r0; r3 |= r4; r3 ^= r1; r4 ^= r2;                              \
+  r1  = r3; r3 |= r4; r3 ^= r0; r0 &= r1;                              \
+  r4 ^= r0; r1 ^= r3; r1 ^= r4; r4 = ~r4;                              \
+  r0 = r2; r2 = r1; r1 = r3; r3 = r4;                                  \
+} while (0)
+
+#define IS2(r0, r1, r2, r3) do {                                       \
+  uint32 r4;                                                           \
+  r2 ^= r3; r3 ^= r0; r4  = r3; r3 &= r2;                              \
+  r3 ^= r1; r1 |= r2; r1 ^= r4; r4 &= r3;                              \
+  r2 ^= r3; r4 &= r0; r4 ^= r2; r2 &= r1;                              \
+  r2 |= r0; r3 = ~r3; r2 ^= r3; r0 ^= r3;                              \
+  r0 &= r1; r3 ^= r4; r3 ^= r0;                                                \
+  r0 = r1; r1 = r4;                                                    \
+} while (0)
+
+/* --- @S3@ --- */
+
+#define S3(r0, r1, r2, r3) do {                                                \
+  uint32 r4;                                                           \
+  r4  = r0; r0 |= r3; r3 ^= r1; r1 &= r4;                              \
+  r4 ^= r2; r2 ^= r3; r3 &= r0; r4 |= r1;                              \
+  r3 ^= r4; r0 ^= r1; r4 &= r0; r1 ^= r3;                              \
+  r4 ^= r2; r1 |= r0; r1 ^= r2; r0 ^= r3;                              \
+  r2  = r1; r1 |= r3; r1 ^= r0;                                                \
+  r0 = r1; r1 = r2; r2 = r3; r3 = r4;                                  \
+} while (0)
+
+#define IS3(r0, r1, r2, r3) do {                                       \
+  uint32 r4;                                                           \
+  r4  = r2; r2 ^= r1; r0 ^= r2; r4 &= r2;                              \
+  r4 ^= r0; r0 &= r1; r1 ^= r3; r3 |= r4;                              \
+  r2 ^= r3; r0 ^= r3; r1 ^= r4; r3 &= r2;                              \
+  r3 ^= r1; r1 ^= r0; r1 |= r2; r0 ^= r3;                              \
+  r1 ^= r4; r0 ^= r1;                                                  \
+  r4 = r0; r0 = r2; r2 = r3; r3 = r4;                                  \
+} while (0)
+
+/* --- @S4@ --- */
+
+#define S4(r0, r1, r2, r3) do {                                                \
+  uint32 r4;                                                           \
+  r1 ^= r3; r3 = ~r3; r2 ^= r3; r3 ^= r0;                              \
+  r4  = r1; r1 &= r3; r1 ^= r2; r4 ^= r3;                              \
+  r0 ^= r4; r2 &= r4; r2 ^= r0; r0 &= r1;                              \
+  r3 ^= r0; r4 |= r1; r4 ^= r0; r0 |= r3;                              \
+  r0 ^= r2; r2 &= r3; r0 = ~r0; r4 ^= r2;                              \
+  r2 = r0; r0 = r1; r1 = r4;                                           \
+} while (0)
+
+#define IS4(r0, r1, r2, r3) do {                                       \
+  uint32 r4;                                                           \
+  r4  = r2; r2 &= r3; r2 ^= r1; r1 |= r3;                              \
+  r1 &= r0; r4 ^= r2; r4 ^= r1; r1 &= r2;                              \
+  r0 = ~r0; r3 ^= r4; r1 ^= r3; r3 &= r0;                              \
+  r3 ^= r2; r0 ^= r1; r2 &= r0; r3 ^= r0;                              \
+  r2 ^= r4, r2 |= r3; r3 ^= r0; r2 ^= r1;                              \
+  r1 = r3; r3 = r4;                                                    \
+} while (0)
+
+/* --- @S5@ --- */
+
+#define S5(r0, r1, r2, r3) do {                                                \
+  uint32 r4;                                                           \
+  r0 ^= r1; r1 ^= r3; r3 = ~r3; r4  = r1;                              \
+  r1 &= r0; r2 ^= r3; r1 ^= r2; r2 |= r4;                              \
+  r4 ^= r3; r3 &= r1; r3 ^= r0; r4 ^= r1;                              \
+  r4 ^= r2; r2 ^= r0; r0 &= r3; r2 = ~r2;                              \
+  r0 ^= r4; r4 |= r3; r2 ^= r4;                                                \
+  r4 = r3; r3 = r2; r2 = r0; r0 = r1; r1 = r4;                         \
+} while (0)
+
+#define IS5(r0, r1, r2, r3) do {                                       \
+  uint32 r4;                                                           \
+  r1 = ~r1; r4 = r3; r2 ^= r1; r3 |= r0;                               \
+  r3 ^= r2; r2 |= r1; r2 &= r0; r4 ^= r3;                              \
+  r2 ^= r4; r4 |= r0; r4 ^= r1; r1 &= r2;                              \
+  r1 ^= r3; r4 ^= r2; r3 &= r4; r4 ^= r1;                              \
+  r3 ^= r4; r4 = ~r4; r3 ^= r0;                                                \
+  r0 = r1; r1 = r4; r4 = r3; r3 = r2; r2 = r4;                         \
+} while (0)
+
+/* --- @S6@ --- */
+
+#define S6(r0, r1, r2, r3) do {                                                \
+  uint32 r4;                                                           \
+  r2 = ~r2; r4 = r3; r3 &= r0; r0 ^= r4;                               \
+  r3 ^= r2; r2 |= r4; r1 ^= r3; r2 ^= r0;                              \
+  r0 |= r1; r2 ^= r1; r4 ^= r0; r0 |= r3;                              \
+  r0 ^= r2; r4 ^= r3; r4 ^= r0; r3 = ~r3;                              \
+  r2 &= r4; r2 ^= r3;                                                  \
+  r3 = r2; r2 = r4;                                                    \
+} while (0)
+
+#define IS6(r0, r1, r2, r3) do {                                       \
+  uint32 r4;                                                           \
+  r0 ^= r2; r4 = r2; r2 &= r0; r4 ^= r3;                               \
+  r2 = ~r2; r3 ^= r1; r2 ^= r3; r4 |= r0;                              \
+  r0 ^= r2; r3 ^= r4; r4 ^= r1; r1 &= r3;                              \
+  r1 ^= r0; r0 ^= r3; r0 |= r2; r3 ^= r1;                              \
+  r4 ^= r0;                                                            \
+  r0 = r1; r1 = r2; r2 = r4;                                           \
+} while (0)
+
+/* --- @S7@ --- */
+
+#define S7(r0, r1, r2, r3) do {                                                \
+  uint32 r4;                                                           \
+  r4  = r1; r1 |= r2; r1 ^= r3; r4 ^= r2;                              \
+  r2 ^= r1; r3 |= r4; r3 &= r0; r4 ^= r2;                              \
+  r3 ^= r1; r1 |= r4; r1 ^= r0; r0 |= r4;                              \
+  r0 ^= r2; r1 ^= r4; r2 ^= r1; r1 &= r0;                              \
+  r1 ^= r4; r2 = ~r2; r2 |= r0; r4 ^= r2;                              \
+  r2 = r1; r1 = r3; r3 = r0; r0 = r4;                                  \
+} while (0)
+
+#define IS7(r0, r1, r2, r3) do {                                       \
+  uint32 r4;                                                           \
+  r4  = r2; r2 ^= r0; r0 &= r3; r4 |= r3;                              \
+  r2 = ~r2; r3 ^= r1; r1 |= r0; r0 ^= r2;                              \
+  r2 &= r4; r3 &= r4; r1 ^= r2; r2 ^= r0;                              \
+  r0 |= r2; r4 ^= r1; r0 ^= r3; r3 ^= r4;                              \
+  r4 |= r0; r3 ^= r2; r4 ^= r2;                                                \
+  r2 = r1; r1 = r0; r0 = r3; r3 = r4;                                  \
+} while (0)
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/serpent.c b/symm/serpent.c
new file mode 100644 (file)
index 0000000..5ad0fc9
--- /dev/null
@@ -0,0 +1,213 @@
+/* -*-c-*-
+ *
+ * The Serpent block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "serpent.h"
+#include "serpent-sbox.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet serpent_keysz[] = { KSZ_RANGE, SERPENT_KEYSZ, 0, 32, 1 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @serpent_init@ --- *
+ *
+ * Arguments:  @serpent_ctx *k@ = pointer to context block to initialize
+ *             @const void *buf@ = pointer to input buffer
+ *             @size_t sz@ = size of input buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Serpent context.  The key may be any length of
+ *             up to 32 bytes (256 bits).
+ */
+
+void serpent_init(serpent_ctx *k, const void *buf, size_t sz)
+{
+  uint32 a;
+  unsigned b;
+  const octet *p, *q;
+  size_t i;
+  uint32 pk[8 + 132];
+
+  KSZ_ASSERT(serpent, sz);
+
+  /* --- Read the key into the buffer --- */
+
+  if (sz > 32)
+    sz = 32;
+  i = 0; p = buf; q = p + sz;
+  a = 0; b = 0;
+  while (p < q) {
+    a |= (uint32)*p++ << b;
+    b += 8;
+    if (b == 32) {
+      pk[i++] = a;
+      a = 0; b = 0;
+    }
+  }
+
+  /* --- Pad short keys --- */
+
+  if (i < 8) {
+    a |= 0x01 << b;
+    b += 8;
+    pk[i++] = a;
+    for (; i < 8; i++)
+      pk[i] = 0;
+  }
+
+  /* --- Expand the prekeys to fill the buffer --- */
+
+  for (i = 8; i < 8 + 132; i++) {
+    uint32 x = (pk[i - 8] ^ pk[i - 5] ^ pk[i - 3] ^ pk[i - 1] ^
+               (i - 8) ^ 0x9e3779b9);
+    k->k[i - 8] = pk[i] = ROL32(x, 11);
+  }
+
+  /* --- Now substitute everything --- */
+
+  i = 0;
+  goto midway;
+  while (i < 132) {
+#define KSUB(r) do {                                                   \
+    uint32 a, b, c, d;                                                 \
+    a = k->k[i]; b = k->k[i + 1]; c = k->k[i + 2]; d = k->k[i + 3];    \
+    S##r(a, b, c, d);                                                  \
+    k->k[i] = a; k->k[i + 1] = b; k->k[i + 2] = c; k->k[i + 3] = d;    \
+    i += 4;                                                            \
+} while (0)
+    KSUB(2); KSUB(1); KSUB(0); KSUB(7);
+    KSUB(6); KSUB(5); KSUB(4);
+  midway:
+    KSUB(3);
+#undef KSUB
+  }
+}
+
+/* --- @serpent_eblk@, @serpent_dblk@ --- *
+ *
+ * Arguments:  @const serpent_ctx *k@ = pointer to key context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption.
+ */
+
+#define EROUND(a, b, c, d, r, k) do {                                  \
+  a ^= *k++; b ^= *k++; c ^= *k++; d ^= *k++;                          \
+  S##r(a, b, c, d);                                                    \
+  a = ROL32(a, 13); c = ROL32(c,  3); b ^= a ^ c; d ^= c ^ (a << 3);   \
+  b = ROL32(b, 1); d = ROL32(d,  7); a ^= b ^ d; c ^= d ^ (b << 7);    \
+  a = ROL32(a, 5); c = ROL32(c, 22);                                   \
+} while (0)
+
+#define DROUND(a, b, c, d, r, k) do {                                  \
+  IS##r(a, b, c, d);                                                   \
+  d ^= *--k; c ^= *--k; b ^= *--k; a ^= *--k;                          \
+  a = ROR32(a, 5); c = ROR32(c, 22); a ^= b ^ d; c ^= d ^ (b << 7);    \
+  b = ROR32(b, 1); d = ROR32(d,  7); b ^= a ^ c; d ^= c ^ (a << 3);    \
+  a = ROR32(a, 13); c = ROR32(c,  3);                                  \
+} while (0)
+
+void serpent_eblk(const serpent_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
+  const uint32 *kk = k->k;
+
+  EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
+  EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
+  EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
+  EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
+
+  EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
+  EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
+  EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
+  EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
+
+  EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
+  EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
+  EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
+  EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
+
+  EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
+  EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
+  EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
+  EROUND(aa, bb, cc, dd, 6, kk);
+
+  aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++;
+  S7(aa, bb, cc, dd);
+  aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++;
+  d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
+}
+
+void serpent_dblk(const serpent_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
+  const uint32 *kk = k->k + 132;
+
+  dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk;
+
+  DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
+  DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
+  DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
+  DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
+
+  DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
+  DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
+  DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
+  DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
+
+  DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
+  DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
+  DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
+  DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
+
+  DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
+  DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
+  DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
+  DROUND(aa, bb, cc, dd, 1, kk);
+
+  IS0(aa, bb, cc, dd);
+  dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk;
+  d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
+}
+
+BLKC_TEST(SERPENT, serpent)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/serpent.h b/symm/serpent.h
new file mode 100644 (file)
index 0000000..05cc31c
--- /dev/null
@@ -0,0 +1,104 @@
+/* -*-c-*-
+ *
+ * The Serpent block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Serpent block cipher ---------------------------------*
+ *
+ * Serpent was designed and proposed for the AES contest by Ross Anderson,
+ * Eli Biham and Lars Knudsen.  It's not particularly quick, but is
+ * stunningly secure.  The best differential and linear attacks are
+ * speculated to require %$2^{256}$% texts (it's a 128-bit block cipher).
+ * The designers originally intended to file a patent, but failed to persue
+ * it.  Use of the algorithm is completely unencumbered.
+ */
+
+#ifndef CATACOMB_SERPENT_H
+#define CATACOMB_SERPENT_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define SERPENT_BLKSZ 16
+#define SERPENT_KEYSZ 32
+#define SERPENT_CLASS (N, L, 128)
+
+extern const octet serpent_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct serpent_ctx {
+  uint32 k[4 * 33];
+} serpent_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @serpent_init@ --- *
+ *
+ * Arguments:  @serpent_ctx *k@ = pointer to context block to initialize
+ *             @const void *buf@ = pointer to input buffer
+ *             @size_t sz@ = size of input buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Serpent context.  The key may be any length of
+ *             up to 32 bytes (256 bits).
+ */
+
+extern void serpent_init(serpent_ctx */*k*/,
+                        const void */*buf*/, size_t /*sz*/);
+
+/* --- @serpent_eblk@, @serpent_dblk@ --- *
+ *
+ * Arguments:  @const serpent_ctx *k@ = pointer to key context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption.
+ */
+
+extern void serpent_eblk(const serpent_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*d*/);
+extern void serpent_dblk(const serpent_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/sha.c b/symm/sha.c
new file mode 100644 (file)
index 0000000..e4b5023
--- /dev/null
@@ -0,0 +1,304 @@
+/* -*-c-*-
+ *
+ * Implementation of the SHA-1 hash function
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "sha.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @sha_compress@ --- *
+ *
+ * Arguments:  @sha_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA-1 compression function.
+ */
+
+void sha_compress(sha_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d, e;
+  uint32 buf[80];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = ctx->a;
+  b = ctx->b;
+  c = ctx->c;
+  d = ctx->d;
+  e = ctx->e;
+
+  /* --- Fetch and expand the buffer contents --- */
+
+  {
+    int i;
+    const octet *p;
+
+    for (i = 0, p = sbuf; i < 16; i++, p += 4)
+      buf[i] = LOAD32(p);
+    for (i = 16; i < 80; i++) {
+      uint32 x = buf[i - 3] ^ buf[i - 8] ^ buf[i - 14] ^ buf[i - 16];
+      buf[i] = ROL32(x, 1);
+    }
+  }
+
+  /* --- 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) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+
+#define T(v, w, x, y, z, i, f, k) do {                                 \
+  z = ROL32(v, 5) + f(w, x, y) + z + buf[i] + k;                       \
+  w = ROR32(w, 2);                                                     \
+} while (0)
+
+#define FF(v, w, x, y, z, i) T(v, w, x, y, z, i, F, 0x5a827999)
+#define GG(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0x6ed9eba1)
+#define HH(v, w, x, y, z, i) T(v, w, x, y, z, i, H, 0x8f1bbcdc)
+#define II(v, w, x, y, z, i) T(v, w, x, y, z, i, G, 0xca62c1d6)
+
+  /* --- The main compression function --- */
+
+  FF(a, b, c, d, e,  0);
+  FF(e, a, b, c, d,  1);
+  FF(d, e, a, b, c,  2);
+  FF(c, d, e, a, b,  3);
+  FF(b, c, d, e, a,  4);
+  FF(a, b, c, d, e,  5);
+  FF(e, a, b, c, d,  6);
+  FF(d, e, a, b, c,  7);
+  FF(c, d, e, a, b,  8);
+  FF(b, c, d, e, a,  9);
+  FF(a, b, c, d, e, 10);
+  FF(e, a, b, c, d, 11);
+  FF(d, e, a, b, c, 12);
+  FF(c, d, e, a, b, 13);
+  FF(b, c, d, e, a, 14);
+  FF(a, b, c, d, e, 15);
+  FF(e, a, b, c, d, 16);
+  FF(d, e, a, b, c, 17);
+  FF(c, d, e, a, b, 18);
+  FF(b, c, d, e, a, 19);
+
+  GG(a, b, c, d, e, 20);
+  GG(e, a, b, c, d, 21);
+  GG(d, e, a, b, c, 22);
+  GG(c, d, e, a, b, 23);
+  GG(b, c, d, e, a, 24);
+  GG(a, b, c, d, e, 25);
+  GG(e, a, b, c, d, 26);
+  GG(d, e, a, b, c, 27);
+  GG(c, d, e, a, b, 28);
+  GG(b, c, d, e, a, 29);
+  GG(a, b, c, d, e, 30);
+  GG(e, a, b, c, d, 31);
+  GG(d, e, a, b, c, 32);
+  GG(c, d, e, a, b, 33);
+  GG(b, c, d, e, a, 34);
+  GG(a, b, c, d, e, 35);
+  GG(e, a, b, c, d, 36);
+  GG(d, e, a, b, c, 37);
+  GG(c, d, e, a, b, 38);
+  GG(b, c, d, e, a, 39);
+
+  HH(a, b, c, d, e, 40);
+  HH(e, a, b, c, d, 41);
+  HH(d, e, a, b, c, 42);
+  HH(c, d, e, a, b, 43);
+  HH(b, c, d, e, a, 44);
+  HH(a, b, c, d, e, 45);
+  HH(e, a, b, c, d, 46);
+  HH(d, e, a, b, c, 47);
+  HH(c, d, e, a, b, 48);
+  HH(b, c, d, e, a, 49);
+  HH(a, b, c, d, e, 50);
+  HH(e, a, b, c, d, 51);
+  HH(d, e, a, b, c, 52);
+  HH(c, d, e, a, b, 53);
+  HH(b, c, d, e, a, 54);
+  HH(a, b, c, d, e, 55);
+  HH(e, a, b, c, d, 56);
+  HH(d, e, a, b, c, 57);
+  HH(c, d, e, a, b, 58);
+  HH(b, c, d, e, a, 59);
+
+  II(a, b, c, d, e, 60);
+  II(e, a, b, c, d, 61);
+  II(d, e, a, b, c, 62);
+  II(c, d, e, a, b, 63);
+  II(b, c, d, e, a, 64);
+  II(a, b, c, d, e, 65);
+  II(e, a, b, c, d, 66);
+  II(d, e, a, b, c, 67);
+  II(c, d, e, a, b, 68);
+  II(b, c, d, e, a, 69);
+  II(a, b, c, d, e, 70);
+  II(e, a, b, c, d, 71);
+  II(d, e, a, b, c, 72);
+  II(c, d, e, a, b, 73);
+  II(b, c, d, e, a, 74);
+  II(a, b, c, d, e, 75);
+  II(e, a, b, c, d, 76);
+  II(d, e, a, b, c, 77);
+  II(c, d, e, a, b, 78);
+  II(b, c, d, e, a, 79);
+
+  /* --- Update the chaining variables --- */
+
+  ctx->a += a;
+  ctx->b += b;
+  ctx->c += c;
+  ctx->d += d;
+  ctx->e += e;
+}
+
+/* --- @sha_init@ --- *
+ *
+ * Arguments:  @sha_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void sha_init(sha_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;
+}
+
+/* --- @sha_set@ --- *
+ *
+ * Arguments:  @sha_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 sha_set(sha_ctx *ctx, const void *buf, unsigned long count)
+{
+  const octet *p = buf;
+  ctx->a = LOAD32(p +  0);
+  ctx->b = LOAD32(p +  4);
+  ctx->c = LOAD32(p +  8);
+  ctx->d = LOAD32(p + 12);
+  ctx->e = LOAD32(p + 16);
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @sha_hash@ --- *
+ *
+ * Arguments:  @sha_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 sha_hash(sha_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(SHA, sha, ctx, buf, sz);
+}
+
+/* --- @sha_done@ --- *
+ *
+ * Arguments:  @sha_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void sha_done(sha_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_PAD(SHA, sha, ctx, 0x80, 0, 8);
+  STORE32(ctx->buf + SHA_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3));
+  STORE32(ctx->buf + SHA_BUFSZ - 4, ctx->nl << 3);
+  sha_compress(ctx, ctx->buf);
+  STORE32(p +  0, ctx->a);
+  STORE32(p +  4, ctx->b);
+  STORE32(p +  8, ctx->c);
+  STORE32(p + 12, ctx->d);
+  STORE32(p + 16, ctx->e);
+}
+
+/* --- @sha_state@ --- *
+ *
+ * Arguments:  @sha_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 @sha_set@.
+ */
+
+unsigned long sha_state(sha_ctx *ctx, void *state)
+{
+  octet *p = state;
+  STORE32(p +  0, ctx->a);
+  STORE32(p +  4, ctx->b);
+  STORE32(p +  8, ctx->c);
+  STORE32(p + 12, ctx->d);
+  STORE32(p + 16, ctx->e);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(SHA, sha)
+
+/* --- Test code --- */
+
+HASH_TEST(SHA, sha)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/sha.h b/symm/sha.h
new file mode 100644 (file)
index 0000000..77f8feb
--- /dev/null
@@ -0,0 +1,157 @@
+/* -*-c-*-
+ *
+ * Implementation of the SHA-1 hash function
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Notes on the SHA-1 hash function ----------------------------------*
+ *
+ * SHA (Secure Hash Algorithm) was designed by the NSA, for use with the
+ * Digital Signature Algorithm.  It is defined by FIPS 180-1.  It has gained
+ * wide acceptance since its initial publication, and is probably now most
+ * people's collision-resistant function of choice.  The author prefers
+ * RIPEMD-160, for no particularly good reasons.
+ */
+
+#ifndef CATACOMB_SHA_H
+#define CATACOMB_SHA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define SHA_BUFSZ 64
+#define SHA_HASHSZ 20
+#define SHA_STATESZ 20
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct sha_ctx {
+  uint32 a, b, c, d, e;                        /* Chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[SHA_BUFSZ];                        /* Accumulation buffer */
+} sha_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @sha_compress@ --- *
+ *
+ * Arguments:  @sha_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA compression function.
+ */
+
+extern void sha_compress(sha_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @sha_init@ --- *
+ *
+ * Arguments:  @sha_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void sha_init(sha_ctx */*ctx*/);
+
+/* --- @sha_set@ --- *
+ *
+ * Arguments:  @sha_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 sha_set(sha_ctx */*ctx*/, const void */*buf*/,
+                   unsigned long /*count*/);
+
+/* --- @sha_hash@ --- *
+ *
+ * Arguments:  @sha_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 sha_hash(sha_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @sha_done@ --- *
+ *
+ * Arguments:  @sha_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 sha_done(sha_ctx */*ctx*/, void */*hash*/);
+
+/* --- @sha_state@ --- *
+ *
+ * Arguments:  @sha_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 @sha_set@.
+ */
+
+extern unsigned long sha_state(sha_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash sha;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/sha224.c b/symm/sha224.c
new file mode 100644 (file)
index 0000000..997c51a
--- /dev/null
@@ -0,0 +1,12 @@
+/* -*-c-*-
+ *
+ * Stub code for SHA-224
+ */
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "sha224.h"
+
+GHASH_DEF(SHA224, sha224)
+HASH_TEST(SHA224, sha224)
diff --git a/symm/sha224.h b/symm/sha224.h
new file mode 100644 (file)
index 0000000..3a49569
--- /dev/null
@@ -0,0 +1,11 @@
+/* -*-c-*-
+ *
+ * Stub header for SHA-224
+ */
+
+#ifndef CATACOMB_SHA224_H
+#define CATACOMB_SHA224_H
+
+#include "sha256.h"
+
+#endif
diff --git a/symm/sha256.c b/symm/sha256.c
new file mode 100644 (file)
index 0000000..a8796d3
--- /dev/null
@@ -0,0 +1,333 @@
+/* -*-c-*-
+ *
+ * Implementation of the SHA-256 hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "sha256.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @sha256_compress@, @sha224_compress@ --- *
+ *
+ * Arguments:  @sha256_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA-256 compression function.
+ */
+
+void sha256_compress(sha256_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d, e, f, g, h;
+  uint32 buf[64];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = ctx->a;
+  b = ctx->b;
+  c = ctx->c;
+  d = ctx->d;
+  e = ctx->e;
+  f = ctx->f;
+  g = ctx->g;
+  h = ctx->h;
+
+  /* --- Definitions for round functions --- */
+
+#define CH(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+
+#define S0(x) (ROR32((x),  2) ^ ROR32((x), 13) ^ ROR32((x), 22))
+#define S1(x) (ROR32((x),  6) ^ ROR32((x), 11) ^ ROR32((x), 25))
+#define s0(x) (ROR32((x),  7) ^ ROR32((x), 18) ^ LSR32((x),  3))
+#define s1(x) (ROR32((x), 17) ^ ROR32((x), 19) ^ LSR32((x), 10))
+
+#define T(a, b, c, d, e, f, g, h, i, k) do {                           \
+  uint32 t1 = h + S1(e) + CH(e, f, g) + k + buf[i];                    \
+  uint32 t2 = S0(a) + MAJ(a, b, c);                                    \
+  d += t1; h = t1 + t2;                                                        \
+} while (0)
+
+  /* --- Fetch and expand the buffer contents --- */
+
+  {
+    int i;
+    const octet *p;
+
+    for (i = 0, p = sbuf; i < 16; i++, p += 4)
+      buf[i] = LOAD32(p);
+    for (i = 16; i < 64; i++)
+      buf[i] = s1(buf[i - 2]) + buf[i - 7] + s0(buf[i - 15]) + buf[i - 16];
+  }
+
+  /* --- The main compression function --- */
+
+  T(a, b, c, d, e, f, g, h,  0, 0x428a2f98);
+  T(h, a, b, c, d, e, f, g,  1, 0x71374491);
+  T(g, h, a, b, c, d, e, f,  2, 0xb5c0fbcf);
+  T(f, g, h, a, b, c, d, e,  3, 0xe9b5dba5);
+  T(e, f, g, h, a, b, c, d,  4, 0x3956c25b);
+  T(d, e, f, g, h, a, b, c,  5, 0x59f111f1);
+  T(c, d, e, f, g, h, a, b,  6, 0x923f82a4);
+  T(b, c, d, e, f, g, h, a,  7, 0xab1c5ed5);
+  T(a, b, c, d, e, f, g, h,  8, 0xd807aa98);
+  T(h, a, b, c, d, e, f, g,  9, 0x12835b01);
+  T(g, h, a, b, c, d, e, f, 10, 0x243185be);
+  T(f, g, h, a, b, c, d, e, 11, 0x550c7dc3);
+  T(e, f, g, h, a, b, c, d, 12, 0x72be5d74);
+  T(d, e, f, g, h, a, b, c, 13, 0x80deb1fe);
+  T(c, d, e, f, g, h, a, b, 14, 0x9bdc06a7);
+  T(b, c, d, e, f, g, h, a, 15, 0xc19bf174);
+  T(a, b, c, d, e, f, g, h, 16, 0xe49b69c1);
+  T(h, a, b, c, d, e, f, g, 17, 0xefbe4786);
+  T(g, h, a, b, c, d, e, f, 18, 0x0fc19dc6);
+  T(f, g, h, a, b, c, d, e, 19, 0x240ca1cc);
+  T(e, f, g, h, a, b, c, d, 20, 0x2de92c6f);
+  T(d, e, f, g, h, a, b, c, 21, 0x4a7484aa);
+  T(c, d, e, f, g, h, a, b, 22, 0x5cb0a9dc);
+  T(b, c, d, e, f, g, h, a, 23, 0x76f988da);
+  T(a, b, c, d, e, f, g, h, 24, 0x983e5152);
+  T(h, a, b, c, d, e, f, g, 25, 0xa831c66d);
+  T(g, h, a, b, c, d, e, f, 26, 0xb00327c8);
+  T(f, g, h, a, b, c, d, e, 27, 0xbf597fc7);
+  T(e, f, g, h, a, b, c, d, 28, 0xc6e00bf3);
+  T(d, e, f, g, h, a, b, c, 29, 0xd5a79147);
+  T(c, d, e, f, g, h, a, b, 30, 0x06ca6351);
+  T(b, c, d, e, f, g, h, a, 31, 0x14292967);
+  T(a, b, c, d, e, f, g, h, 32, 0x27b70a85);
+  T(h, a, b, c, d, e, f, g, 33, 0x2e1b2138);
+  T(g, h, a, b, c, d, e, f, 34, 0x4d2c6dfc);
+  T(f, g, h, a, b, c, d, e, 35, 0x53380d13);
+  T(e, f, g, h, a, b, c, d, 36, 0x650a7354);
+  T(d, e, f, g, h, a, b, c, 37, 0x766a0abb);
+  T(c, d, e, f, g, h, a, b, 38, 0x81c2c92e);
+  T(b, c, d, e, f, g, h, a, 39, 0x92722c85);
+  T(a, b, c, d, e, f, g, h, 40, 0xa2bfe8a1);
+  T(h, a, b, c, d, e, f, g, 41, 0xa81a664b);
+  T(g, h, a, b, c, d, e, f, 42, 0xc24b8b70);
+  T(f, g, h, a, b, c, d, e, 43, 0xc76c51a3);
+  T(e, f, g, h, a, b, c, d, 44, 0xd192e819);
+  T(d, e, f, g, h, a, b, c, 45, 0xd6990624);
+  T(c, d, e, f, g, h, a, b, 46, 0xf40e3585);
+  T(b, c, d, e, f, g, h, a, 47, 0x106aa070);
+  T(a, b, c, d, e, f, g, h, 48, 0x19a4c116);
+  T(h, a, b, c, d, e, f, g, 49, 0x1e376c08);
+  T(g, h, a, b, c, d, e, f, 50, 0x2748774c);
+  T(f, g, h, a, b, c, d, e, 51, 0x34b0bcb5);
+  T(e, f, g, h, a, b, c, d, 52, 0x391c0cb3);
+  T(d, e, f, g, h, a, b, c, 53, 0x4ed8aa4a);
+  T(c, d, e, f, g, h, a, b, 54, 0x5b9cca4f);
+  T(b, c, d, e, f, g, h, a, 55, 0x682e6ff3);
+  T(a, b, c, d, e, f, g, h, 56, 0x748f82ee);
+  T(h, a, b, c, d, e, f, g, 57, 0x78a5636f);
+  T(g, h, a, b, c, d, e, f, 58, 0x84c87814);
+  T(f, g, h, a, b, c, d, e, 59, 0x8cc70208);
+  T(e, f, g, h, a, b, c, d, 60, 0x90befffa);
+  T(d, e, f, g, h, a, b, c, 61, 0xa4506ceb);
+  T(c, d, e, f, g, h, a, b, 62, 0xbef9a3f7);
+  T(b, c, d, e, f, g, h, a, 63, 0xc67178f2);
+
+  /* --- Update the chaining variables --- */
+
+  ctx->a += a;
+  ctx->b += b;
+  ctx->c += c;
+  ctx->d += d;
+  ctx->e += e;
+  ctx->f += f;
+  ctx->g += g;
+  ctx->h += h;
+}
+
+/* --- @sha256_init@, @sha224_init@ --- *
+ *
+ * Arguments:  @sha256_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void sha256_init(sha256_ctx *ctx)
+{
+  ctx->a = 0x6a09e667;
+  ctx->b = 0xbb67ae85;
+  ctx->c = 0x3c6ef372;
+  ctx->d = 0xa54ff53a;
+  ctx->e = 0x510e527f;
+  ctx->f = 0x9b05688c;
+  ctx->g = 0x1f83d9ab;
+  ctx->h = 0x5be0cd19;
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+void sha224_init(sha256_ctx *ctx)
+{
+  ctx->a = 0xc1059ed8;
+  ctx->b = 0x367cd507;
+  ctx->c = 0x3070dd17;
+  ctx->d = 0xf70e5939;
+  ctx->e = 0xffc00b31;
+  ctx->f = 0x68581511;
+  ctx->g = 0x64f98fa7;
+  ctx->h = 0xbefa4fa4;
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+/* --- @sha256_set@, @sha224_set@ --- *
+ *
+ * Arguments:  @sha256_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 sha256_set(sha256_ctx *ctx, const void *buf, unsigned long count)
+{
+  const octet *p = buf;
+  ctx->a = LOAD32(p +  0);
+  ctx->b = LOAD32(p +  4);
+  ctx->c = LOAD32(p +  8);
+  ctx->d = LOAD32(p + 12);
+  ctx->e = LOAD32(p + 16);
+  ctx->f = LOAD32(p + 20);
+  ctx->g = LOAD32(p + 24);
+  ctx->h = LOAD32(p + 28);
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @sha256_hash@, @sha224_hash@ --- *
+ *
+ * Arguments:  @sha256_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 sha256_hash(sha256_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(SHA256, sha256, ctx, buf, sz);
+}
+
+/* --- @sha256_done, @sha224_done@ --- *
+ *
+ * Arguments:  @sha256_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+static void final(sha256_ctx *ctx)
+{
+  HASH_PAD(SHA256, sha256, ctx, 0x80, 0, 8);
+  STORE32(ctx->buf + SHA256_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3));
+  STORE32(ctx->buf + SHA256_BUFSZ - 4, ctx->nl << 3);
+  sha256_compress(ctx, ctx->buf);
+}
+
+void sha256_done(sha256_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  final(ctx);
+  STORE32(p +  0, ctx->a);
+  STORE32(p +  4, ctx->b);
+  STORE32(p +  8, ctx->c);
+  STORE32(p + 12, ctx->d);
+  STORE32(p + 16, ctx->e);
+  STORE32(p + 20, ctx->f);
+  STORE32(p + 24, ctx->g);
+  STORE32(p + 28, ctx->h);
+}
+
+void sha224_done(sha224_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  final(ctx);
+  STORE32(p +  0, ctx->a);
+  STORE32(p +  4, ctx->b);
+  STORE32(p +  8, ctx->c);
+  STORE32(p + 12, ctx->d);
+  STORE32(p + 16, ctx->e);
+  STORE32(p + 20, ctx->f);
+  STORE32(p + 24, ctx->g);
+}
+
+/* --- @sha256_state@, @sha224_state@ --- *
+ *
+ * Arguments:  @sha256_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 @sha256_set@.
+ */
+
+unsigned long sha256_state(sha256_ctx *ctx, void *state)
+{
+  octet *p = state;
+  STORE32(p +  0, ctx->a);
+  STORE32(p +  4, ctx->b);
+  STORE32(p +  8, ctx->c);
+  STORE32(p + 12, ctx->d);
+  STORE32(p + 16, ctx->e);
+  STORE32(p + 20, ctx->f);
+  STORE32(p + 24, ctx->g);
+  STORE32(p + 28, ctx->h);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(SHA256, sha256)
+
+/* --- Test code --- */
+
+HASH_TEST(SHA256, sha256)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/sha256.h b/symm/sha256.h
new file mode 100644 (file)
index 0000000..aab843d
--- /dev/null
@@ -0,0 +1,169 @@
+/* -*-c-*-
+ *
+ * Implementation of the SHA-256 hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the SHA-256 hash function --------------------------------*
+ *
+ * SHA-1 (Secure Hash Algorithm) was designed by the NSA, for use with the
+ * Digital Signature Algorithm.  This is an evolution with a larger output
+ * size, intended to provide security commensurate with 128-bit AES.  At the
+ * time of writing, SHA-256 is very new, and can't be trusted too far.
+ */
+
+#ifndef CATACOMB_SHA256_H
+#define CATACOMB_SHA256_H
+#define CATACOMB_SHA224_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define SHA256_BUFSZ 64
+#define SHA256_HASHSZ 32
+#define SHA256_STATESZ 32
+
+#define SHA224_BUFSZ 64
+#define SHA224_HASHSZ 28
+#define SHA224_STATESZ 32
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct sha256_ctx {
+  uint32 a, b, c, d, e, f, g, h;       /* Chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[SHA256_BUFSZ];             /* Accumulation buffer */
+} sha256_ctx, sha224_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @sha256_compress@, @sha224_compress@ --- *
+ *
+ * Arguments:  @sha256_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA-256 compression function.
+ */
+
+extern void sha256_compress(sha256_ctx */*ctx*/, const void */*sbuf*/);
+#define sha224_compress sha256_compress
+
+/* --- @sha256_init@, @sha224_init@ --- *
+ *
+ * Arguments:  @sha256_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void sha256_init(sha256_ctx */*ctx*/);
+extern void sha224_init(sha256_ctx */*ctx*/);
+
+/* --- @sha256_set@, @sha224_set@ --- *
+ *
+ * Arguments:  @sha256_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 sha256_set(sha256_ctx */*ctx*/, const void */*buf*/,
+                      unsigned long /*count*/);
+#define sha224_set sha256_set
+
+/* --- @sha256_hash@, @sha224_hash@ --- *
+ *
+ * Arguments:  @sha256_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 sha256_hash(sha256_ctx */*ctx*/,
+                       const void */*buf*/, size_t /*sz*/);
+#define sha224_hash sha256_hash
+
+/* --- @sha256_done@, @sha224_done@ --- *
+ *
+ * Arguments:  @sha256_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 sha256_done(sha256_ctx */*ctx*/, void */*hash*/);
+extern void sha224_done(sha256_ctx */*ctx*/, void */*hash*/);
+
+/* --- @sha256_state@, @sha224_state@ --- *
+ *
+ * Arguments:  @sha256_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 @sha256_set@.
+ */
+
+extern unsigned long sha256_state(sha256_ctx */*ctx*/, void */*state*/);
+#define sha224_state sha256_state
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash sha256;
+extern const gchash sha224;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/sha384.c b/symm/sha384.c
new file mode 100644 (file)
index 0000000..e7de7ad
--- /dev/null
@@ -0,0 +1,12 @@
+/* -*-c-*-
+ *
+ * Stub code for SHA-384
+ */
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "sha384.h"
+
+GHASH_DEF(SHA384, sha384)
+HASH_TEST(SHA384, sha384)
diff --git a/symm/sha384.h b/symm/sha384.h
new file mode 100644 (file)
index 0000000..ed7731f
--- /dev/null
@@ -0,0 +1,11 @@
+/* -*-c-*-
+ *
+ * Stub header for SHA-384
+ */
+
+#ifndef CATACOMB_SHA384_H
+#define CATACOMB_SHA384_H
+
+#include "sha512.h"
+
+#endif
diff --git a/symm/sha512.c b/symm/sha512.c
new file mode 100644 (file)
index 0000000..d4df182
--- /dev/null
@@ -0,0 +1,340 @@
+/* -*-c-*-
+ *
+ * Implementation of the SHA-512 hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "sha512.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @sha512_compress@, @sha384_compress@ --- *
+ *
+ * Arguments:  @sha512_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA-512 compression function.
+ */
+
+void sha512_compress(sha512_ctx *ctx, const void *sbuf)
+{
+  kludge64 a, b, c, d, e, f, g, h;
+  kludge64 buf[80];
+  int i;
+
+  static const kludge64 K[80] = {
+    X64(428a2f98, d728ae22), X64(71374491, 23ef65cd),
+    X64(b5c0fbcf, ec4d3b2f), X64(e9b5dba5, 8189dbbc),
+    X64(3956c25b, f348b538), X64(59f111f1, b605d019),
+    X64(923f82a4, af194f9b), X64(ab1c5ed5, da6d8118),
+    X64(d807aa98, a3030242), X64(12835b01, 45706fbe),
+    X64(243185be, 4ee4b28c), X64(550c7dc3, d5ffb4e2),
+    X64(72be5d74, f27b896f), X64(80deb1fe, 3b1696b1),
+    X64(9bdc06a7, 25c71235), X64(c19bf174, cf692694),
+    X64(e49b69c1, 9ef14ad2), X64(efbe4786, 384f25e3),
+    X64(0fc19dc6, 8b8cd5b5), X64(240ca1cc, 77ac9c65),
+    X64(2de92c6f, 592b0275), X64(4a7484aa, 6ea6e483),
+    X64(5cb0a9dc, bd41fbd4), X64(76f988da, 831153b5),
+    X64(983e5152, ee66dfab), X64(a831c66d, 2db43210),
+    X64(b00327c8, 98fb213f), X64(bf597fc7, beef0ee4),
+    X64(c6e00bf3, 3da88fc2), X64(d5a79147, 930aa725),
+    X64(06ca6351, e003826f), X64(14292967, 0a0e6e70),
+    X64(27b70a85, 46d22ffc), X64(2e1b2138, 5c26c926),
+    X64(4d2c6dfc, 5ac42aed), X64(53380d13, 9d95b3df),
+    X64(650a7354, 8baf63de), X64(766a0abb, 3c77b2a8),
+    X64(81c2c92e, 47edaee6), X64(92722c85, 1482353b),
+    X64(a2bfe8a1, 4cf10364), X64(a81a664b, bc423001),
+    X64(c24b8b70, d0f89791), X64(c76c51a3, 0654be30),
+    X64(d192e819, d6ef5218), X64(d6990624, 5565a910),
+    X64(f40e3585, 5771202a), X64(106aa070, 32bbd1b8),
+    X64(19a4c116, b8d2d0c8), X64(1e376c08, 5141ab53),
+    X64(2748774c, df8eeb99), X64(34b0bcb5, e19b48a8),
+    X64(391c0cb3, c5c95a63), X64(4ed8aa4a, e3418acb),
+    X64(5b9cca4f, 7763e373), X64(682e6ff3, d6b2b8a3),
+    X64(748f82ee, 5defb2fc), X64(78a5636f, 43172f60),
+    X64(84c87814, a1f0ab72), X64(8cc70208, 1a6439ec),
+    X64(90befffa, 23631e28), X64(a4506ceb, de82bde9),
+    X64(bef9a3f7, b2c67915), X64(c67178f2, e372532b),
+    X64(ca273ece, ea26619c), X64(d186b8c7, 21c0c207),
+    X64(eada7dd6, cde0eb1e), X64(f57d4f7f, ee6ed178),
+    X64(06f067aa, 72176fba), X64(0a637dc5, a2c898a6),
+    X64(113f9804, bef90dae), X64(1b710b35, 131c471b),
+    X64(28db77f5, 23047d84), X64(32caab7b, 40c72493),
+    X64(3c9ebe0a, 15c9bebc), X64(431d67c4, 9c100d4c),
+    X64(4cc5d4be, cb3e42b6), X64(597f299c, fc657e2a),
+    X64(5fcb6fab, 3ad6faec), X64(6c44198c, 4a475817)
+  };
+
+  /* --- Fetch the chaining variables --- */
+
+  a = ctx->a;
+  b = ctx->b;
+  c = ctx->c;
+  d = ctx->d;
+  e = ctx->e;
+  f = ctx->f;
+  g = ctx->g;
+  h = ctx->h;
+
+  /* --- Definitions for round functions --- */
+
+#define CH(d, x, y, z) do {                                            \
+  kludge64 _x; AND64((d), (x), (y)); CPL64(_x, (x));                   \
+  AND64(_x, _x, (z)); OR64((d), (d), _x);                              \
+} while (0)
+
+#define MAJ(d, x, y, z) do {                                           \
+  kludge64 _x; AND64((d), (x), (y)); AND64(_x, (x), (z));              \
+  OR64((d), (d), _x); AND64(_x, (y), (z)); OR64((d), (d), _x);         \
+} while (0)
+
+#define SIGMA(d, x, i, j, k, last, what) do {                          \
+  kludge64 _x; ROR64_((d), (x), (i)); ROR64_(_x, (x), (j));            \
+  XOR64((d), (d), _x); last##64_(_x, (x), (k)); XOR64((d), (d), _x);   \
+} while (0)
+
+#define S0(d, x) SIGMA(d, x, 28, 34, 39, ROR, S0);
+#define S1(d, x) SIGMA(d, x, 14, 18, 41, ROR, S1);
+#define s0(d, x) SIGMA(d, x,  1,  8,  7, LSR, s0);
+#define s1(d, x) SIGMA(d, x, 19, 61,  6, LSR, s1);
+
+#define T(a, b, c, d, e, f, g, h, i) do {                              \
+  kludge64 t1, t2, x;                                                  \
+  ADD64(t1, buf[i], K[i]); ADD64(t1, t1, h);                           \
+  S1(x, e); ADD64(t1, t1, x); CH(x, e, f, g); ADD64(t1, t1, x);                \
+  S0(t2, a); MAJ(x, a, b, c); ADD64(t2, t2, x);                                \
+  ADD64(d, d, t1); ADD64(h, t1, t2);                                   \
+} while (0)
+
+  /* --- Fetch and expand the buffer contents --- */
+
+  {
+    const octet *p;
+
+    for (i = 0, p = sbuf; i < 16; i++, p += 8)
+      LOAD64_(buf[i], p);
+    for (i = 16; i < 80; i++) {
+      kludge64 x;
+      buf[i] = buf[i - 7]; s1(x, buf[i - 2]); ADD64(buf[i], buf[i], x);
+      s0(x, buf[i - 15]); ADD64(buf[i], buf[i], x);
+      ADD64(buf[i], buf[i], buf[i - 16]);
+    }
+  }
+
+  /* --- The main compression function --- */
+
+  for (i = 0; i < 80; i += 8) {
+    T(a, b, c, d, e, f, g, h, i + 0);
+    T(h, a, b, c, d, e, f, g, i + 1);
+    T(g, h, a, b, c, d, e, f, i + 2);
+    T(f, g, h, a, b, c, d, e, i + 3);
+    T(e, f, g, h, a, b, c, d, i + 4);
+    T(d, e, f, g, h, a, b, c, i + 5);
+    T(c, d, e, f, g, h, a, b, i + 6);
+    T(b, c, d, e, f, g, h, a, i + 7);
+  }
+
+  /* --- Update the chaining variables --- */
+
+  ADD64(ctx->a, ctx->a, a);
+  ADD64(ctx->b, ctx->b, b);
+  ADD64(ctx->c, ctx->c, c);
+  ADD64(ctx->d, ctx->d, d);
+  ADD64(ctx->e, ctx->e, e);
+  ADD64(ctx->f, ctx->f, f);
+  ADD64(ctx->g, ctx->g, g);
+  ADD64(ctx->h, ctx->h, h);
+}
+
+/* --- @sha512_init@, @sha384_init@ --- *
+ *
+ * Arguments:  @sha512_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void sha512_init(sha512_ctx *ctx)
+{
+  SET64(ctx->a,        0x6a09e667, 0xf3bcc908);
+  SET64(ctx->b,        0xbb67ae85, 0x84caa73b);
+  SET64(ctx->c,        0x3c6ef372, 0xfe94f82b);
+  SET64(ctx->d,        0xa54ff53a, 0x5f1d36f1);
+  SET64(ctx->e,        0x510e527f, 0xade682d1);
+  SET64(ctx->f,        0x9b05688c, 0x2b3e6c1f);
+  SET64(ctx->g,        0x1f83d9ab, 0xfb41bd6b);
+  SET64(ctx->h,        0x5be0cd19, 0x137e2179);
+  ctx->off = 0;
+  ctx->nh = ctx->nl = 0;
+}
+
+void sha384_init(sha512_ctx *ctx)
+{
+  SET64(ctx->a,        0xcbbb9d5d, 0xc1059ed8);
+  SET64(ctx->b,        0x629a292a, 0x367cd507);
+  SET64(ctx->c,        0x9159015a, 0x3070dd17);
+  SET64(ctx->d,        0x152fecd8, 0xf70e5939);
+  SET64(ctx->e,        0x67332667, 0xffc00b31);
+  SET64(ctx->f,        0x8eb44a87, 0x68581511);
+  SET64(ctx->g,        0xdb0c2e0d, 0x64f98fa7);
+  SET64(ctx->h,        0x47b5481d, 0xbefa4fa4);
+  ctx->off = 0;
+  ctx->nh = ctx->nl = 0;
+}
+
+/* --- @sha512_set@, @sha384_set@ --- *
+ *
+ * Arguments:  @sha512_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 sha512_set(sha512_ctx *ctx, const void *buf, unsigned long count)
+{
+  const octet *p = buf;
+  LOAD64_(ctx->a, p +  0);
+  LOAD64_(ctx->b, p +  8);
+  LOAD64_(ctx->c, p + 16);
+  LOAD64_(ctx->d, p + 24);
+  LOAD64_(ctx->e, p + 32);
+  LOAD64_(ctx->f, p + 40);
+  LOAD64_(ctx->g, p + 48);
+  LOAD64_(ctx->h, p + 56);
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @sha512_hash@, @sha384_hash@ --- *
+ *
+ * Arguments:  @sha512_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 sha512_hash(sha512_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(SHA512, sha512, ctx, buf, sz);
+}
+
+/* --- @sha512_done@, @sha384_done@ --- *
+ *
+ * Arguments:  @sha512_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+static void final(sha512_ctx *ctx)
+{
+  HASH_PAD(SHA512, sha512, ctx, 0x80, 0, 16);
+  memset(ctx->buf + SHA512_BUFSZ - 16, 0, 8);
+  STORE32(ctx->buf + SHA512_BUFSZ -  8, (ctx->nl >> 29) | (ctx->nh << 3));
+  STORE32(ctx->buf + SHA512_BUFSZ -  4, ctx->nl << 3);
+  sha512_compress(ctx, ctx->buf);
+}
+
+void sha512_done(sha512_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  final(ctx);
+  STORE64_(p + 0, ctx->a);
+  STORE64_(p + 8, ctx->b);
+  STORE64_(p + 16, ctx->c);
+  STORE64_(p + 24, ctx->d);
+  STORE64_(p + 32, ctx->e);
+  STORE64_(p + 40, ctx->f);
+  STORE64_(p + 48, ctx->g);
+  STORE64_(p + 56, ctx->h);
+}
+
+void sha384_done(sha384_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  final(ctx);
+  STORE64_(p + 0, ctx->a);
+  STORE64_(p + 8, ctx->b);
+  STORE64_(p + 16, ctx->c);
+  STORE64_(p + 24, ctx->d);
+  STORE64_(p + 32, ctx->e);
+  STORE64_(p + 40, ctx->f);
+}
+
+/* --- @sha512_state@, @sha384_state@ --- *
+ *
+ * Arguments:  @sha512_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 @sha512_set@.
+ */
+
+unsigned long sha512_state(sha512_ctx *ctx, void *state)
+{
+  octet *p = state;
+  STORE64_(p + 0, ctx->a);
+  STORE64_(p + 8, ctx->b);
+  STORE64_(p + 16, ctx->c);
+  STORE64_(p + 24, ctx->d);
+  STORE64_(p + 32, ctx->e);
+  STORE64_(p + 40, ctx->f);
+  STORE64_(p + 48, ctx->g);
+  STORE64_(p + 56, ctx->h);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(SHA512, sha512)
+
+/* --- Test code --- */
+
+HASH_TEST(SHA512, sha512)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/sha512.h b/symm/sha512.h
new file mode 100644 (file)
index 0000000..2f3edc2
--- /dev/null
@@ -0,0 +1,171 @@
+/* -*-c-*-
+ *
+ * Implementation of the SHA-512 hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the SHA-512 hash function --------------------------------*
+ *
+ * SHA-1 (Secure Hash Algorithm) was designed by the NSA, for use with the
+ * Digital Signature Algorithm.  This is an evolution with a larger output
+ * size, intended to provide security commensurate with 256-bit AES.  At the
+ * time of writing, SHA-512 is very new, and can't be trusted too far.  There
+ * is also a truncated version, SHA-384, which provides security commensurate
+ * with 192-bit AES.
+ */
+
+#ifndef CATACOMB_SHA512_H
+#define CATACOMB_SHA512_H
+#define CATACOMB_SHA384_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define SHA512_BUFSZ 128
+#define SHA512_HASHSZ 64
+#define SHA512_STATESZ 64
+
+#define SHA384_BUFSZ 128
+#define SHA384_HASHSZ 48
+#define SHA384_STATESZ 64
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct sha512_ctx {
+  kludge64 a, b, c, d, e, f, g, h;     /* Chaining variables */
+  uint32 nh, nl;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[SHA512_BUFSZ];             /* Accumulation buffer */
+} sha512_ctx, sha384_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @sha512_compress@, @sha384_compress@ --- *
+ *
+ * Arguments:  @sha512_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA-512 compression function.
+ */
+
+extern void sha512_compress(sha512_ctx */*ctx*/, const void */*sbuf*/);
+#define sha384_compress sha512_compress
+
+/* --- @sha512_init@, @sha384_init@ --- *
+ *
+ * Arguments:  @sha512_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void sha512_init(sha512_ctx */*ctx*/);
+extern void sha384_init(sha512_ctx */*ctx*/);
+
+/* --- @sha512_set@, @sha384_set@ --- *
+ *
+ * Arguments:  @sha512_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 sha512_set(sha512_ctx */*ctx*/, const void */*buf*/,
+                      unsigned long /*count*/);
+#define sha384_set sha512_set
+
+/* --- @sha512_hash@, @sha384_hash@ --- *
+ *
+ * Arguments:  @sha512_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 sha512_hash(sha512_ctx */*ctx*/,
+                       const void */*buf*/, size_t /*sz*/);
+#define sha384_hash sha512_hash
+
+/* --- @sha512_done@, @sha384_done@ --- *
+ *
+ * Arguments:  @sha512_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 sha512_done(sha512_ctx */*ctx*/, void */*hash*/);
+extern void sha384_done(sha512_ctx */*ctx*/, void */*hash*/);
+
+/* --- @sha512_state@, @sha384_state@ --- *
+ *
+ * Arguments:  @sha512_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 @sha512_set@.
+ */
+
+extern unsigned long sha512_state(sha512_ctx */*ctx*/, void */*state*/);
+#define sha384_state sha512_state
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash sha512;
+extern const gchash sha384;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/skipjack-tab.h b/symm/skipjack-tab.h
new file mode 100644 (file)
index 0000000..8994bbb
--- /dev/null
@@ -0,0 +1,78 @@
+/* -*-c-*-
+ *
+ * The Skipjack S-box
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_SKIPJACK_TAB_H
+#define CATACOMB_SKIPJACK_TAB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- The S-box ---------------------------------------------------------*/
+
+#define SKIPJACK_S {                                                   \
+  0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4,                      \
+  0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,                      \
+  0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e,                      \
+  0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,                      \
+  0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68,                      \
+  0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,                      \
+  0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19,                      \
+  0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,                      \
+  0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b,                      \
+  0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,                      \
+  0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0,                      \
+  0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,                      \
+  0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69,                      \
+  0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,                      \
+  0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20,                      \
+  0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,                      \
+  0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43,                      \
+  0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,                      \
+  0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa,                      \
+  0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,                      \
+  0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87,                      \
+  0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,                      \
+  0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b,                      \
+  0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,                      \
+  0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0,                      \
+  0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,                      \
+  0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1,                      \
+  0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,                      \
+  0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5,                      \
+  0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,                      \
+  0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3,                      \
+  0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46                       \
+}
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/skipjack.c b/symm/skipjack.c
new file mode 100644 (file)
index 0000000..bd58ede
--- /dev/null
@@ -0,0 +1,176 @@
+/* -*-c-*-
+ *
+ * The Skipjack block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "skipjack.h"
+#include "skipjack-tab.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet skipjack_keysz[] = { KSZ_SET, 10, 0 };
+
+/*----- The Skipjack S-box ------------------------------------------------*/
+
+static const octet f[256] = SKIPJACK_S;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @skipjack_init@ --- *
+ *
+ * Arguments:  @skipjack_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Skipjack key buffer.  The key buffer must be
+ *             exactly 10 bytes long.
+ */
+
+void skipjack_init(skipjack_ctx *k, const void *buf, size_t sz)
+{
+  const octet *b = buf;
+  uint32 crud;
+  KSZ_ASSERT(skipjack, sz);
+  k->ka = LOAD32(b);
+  k->kb = LOAD32(b + 4);
+  crud = LOAD16(b + 8);
+  k->kc = U32((crud << 16) | (k->ka >> 16));
+  k->kd = U32((k->ka << 16) | (k->kb >> 16));
+  k->ke = U32((k->kb << 16) | crud);
+  crud = 0;
+}
+
+/* --- @skipjack_eblk@, @skipjack_dblk@ --- *
+ *
+ * Arguments:  @const skipjack_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to skipjacktination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define G(x, k) do {                                                   \
+  octet _x = U8(x >> 8), _y = U8(x);                                   \
+  _x ^= f[_y ^ U8(k >> 24)];                                           \
+  _y ^= f[_x ^ U8(k >> 16)];                                           \
+  _x ^= f[_y ^ U8(k >> 8)];                                            \
+  _y ^= f[_x ^ U8(k >> 0)];                                            \
+  x = (_x << 8) | _y;                                                  \
+} while (0)
+
+#define RULE_A(w, x, y, z, n, k) do {                                  \
+  G(w, k); z ^= w ^ n++;                                               \
+} while (0)
+
+#define RULE_B(w, x, y, z, n, k) do {                                  \
+  x ^= w ^ n++; G(w, k);                                               \
+} while (0)
+
+void skipjack_eblk(const skipjack_ctx *k, const uint32 *s, uint32 *d)
+{
+  unsigned n = 1;
+  uint16 w = U16(s[0] >> 16), x = U16(s[0]);
+  uint16 y = U16(s[1] >> 16), z = U16(s[1]);
+  uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke;
+
+  RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb);
+  RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd);
+  RULE_A(w, x, y, z, n, ke); RULE_A(z, w, x, y, n, ka);
+  RULE_A(y, z, w, x, n, kb); RULE_A(x, y, z, w, n, kc);
+  RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke);
+  RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb);
+  RULE_B(w, x, y, z, n, kc); RULE_B(z, w, x, y, n, kd);
+  RULE_B(y, z, w, x, n, ke); RULE_B(x, y, z, w, n, ka);
+  RULE_A(w, x, y, z, n, kb); RULE_A(z, w, x, y, n, kc);
+  RULE_A(y, z, w, x, n, kd); RULE_A(x, y, z, w, n, ke);
+  RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb);
+  RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd);
+  RULE_B(w, x, y, z, n, ke); RULE_B(z, w, x, y, n, ka);
+  RULE_B(y, z, w, x, n, kb); RULE_B(x, y, z, w, n, kc);
+  RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke);
+  RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb);
+
+  d[0] = ((uint32)w << 16) | (uint32)x;
+  d[1] = ((uint32)y << 16) | (uint32)z;
+}
+
+#define G_INV(x, k) do {                                               \
+  octet _x = U8(x >> 8), _y = U8(x);                                   \
+  _y ^= f[_x ^ U8(k >> 0)];                                            \
+  _x ^= f[_y ^ U8(k >> 8)];                                            \
+  _y ^= f[_x ^ U8(k >> 16)];                                           \
+  _x ^= f[_y ^ U8(k >> 24)];                                           \
+  x = (_x << 8) | _y;                                                  \
+} while (0)
+
+#define RULE_A_INV(w, x, y, z, n, i) do {                              \
+  w ^= x ^ --n; G_INV(x, i);                                           \
+} while (0)
+
+#define RULE_B_INV(w, x, y, z, n, i) do {                              \
+  G_INV(x, i); y ^= x ^ --n;                                           \
+} while (0)
+
+void skipjack_dblk(const skipjack_ctx *k, const uint32 *s, uint32 *d)
+{
+  unsigned n = 33;
+  uint16 w = U16(s[0] >> 16), x = U16(s[0]);
+  uint16 y = U16(s[1] >> 16), z = U16(s[1]);
+  uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke;
+
+  RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka);
+  RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd);
+  RULE_B_INV(w, x, y, z, n, kc); RULE_B_INV(x, y, z, w, n, kb);
+  RULE_B_INV(y, z, w, x, n, ka); RULE_B_INV(z, w, x, y, n, ke);
+  RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc);
+  RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka);
+  RULE_A_INV(w, x, y, z, n, ke); RULE_A_INV(x, y, z, w, n, kd);
+  RULE_A_INV(y, z, w, x, n, kc); RULE_A_INV(z, w, x, y, n, kb);
+  RULE_B_INV(w, x, y, z, n, ka); RULE_B_INV(x, y, z, w, n, ke);
+  RULE_B_INV(y, z, w, x, n, kd); RULE_B_INV(z, w, x, y, n, kc);
+  RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka);
+  RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd);
+  RULE_A_INV(w, x, y, z, n, kc); RULE_A_INV(x, y, z, w, n, kb);
+  RULE_A_INV(y, z, w, x, n, ka); RULE_A_INV(z, w, x, y, n, ke);
+  RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc);
+  RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka);
+
+  d[0] = ((uint32)w << 16) | (uint32)x;
+  d[1] = ((uint32)y << 16) | (uint32)z;
+}
+
+BLKC_TEST(SKIPJACK, skipjack)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/skipjack.h b/symm/skipjack.h
new file mode 100644 (file)
index 0000000..ab43709
--- /dev/null
@@ -0,0 +1,110 @@
+/* -*-c-*-
+ *
+ * The Skipjack block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Skipjack block cipher --------------------------------*
+ *
+ * Skipjack was designed by the NSA, as a type II algorithm to be used in the
+ * Clipper system.  It was initially classified, so that it couldn't be used
+ * without the key escrow feature, though a team of `respectable'
+ * cryptographers, including Dorothy Denning, had a quick look at it and
+ * pronounced it `good', as if this was meant to be convincing.  It is
+ * apparently a particular parameterization of a family which includes type I
+ * algorithms.  Since declassification, Biham has discovered a miss-in-the-
+ * middle attack which breaks Skipjack with 31 rounds faster than brute
+ * force.
+ *
+ * This implementation is provided for interest's sake, and possibly for
+ * interoperability, rather than as a good cipher to use.
+ */
+
+#ifndef CATACOMB_SKIPJACK_H
+#define CATACOMB_SKIPJACK_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define SKIPJACK_BLKSZ 8
+#define SKIPJACK_KEYSZ 10
+#define SKIPJACK_CLASS (N, B, 64)
+
+extern const octet skipjack_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct skipjack_ctx {
+  uint32 ka, kb, kc, kd, ke;
+} skipjack_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @skipjack_init@ --- *
+ *
+ * Arguments:  @skipjack_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Skipjack key buffer.  The key buffer must be
+ *             exactly 10 bytes long.
+ */
+
+extern void skipjack_init(skipjack_ctx */*k*/,
+                         const void */*buf*/, size_t /*sz*/);
+
+/* --- @skipjack_eblk@, @skipjack_dblk@ --- *
+ *
+ * Arguments:  @const skipjack_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to skipjacktination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void skipjack_eblk(const skipjack_ctx */*k*/,
+                         const uint32 */*s*/, uint32 */*d*/);
+extern void skipjack_dblk(const skipjack_ctx */*k*/,
+                         const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/square-mktab.c b/symm/square-mktab.c
new file mode 100644 (file)
index 0000000..a2e90e3
--- /dev/null
@@ -0,0 +1,366 @@
+/* -*-c-*-
+ *
+ * Build precomputed tables for the Square block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Magic variables ---------------------------------------------------*/
+
+static octet s[256], si[256];
+static uint32 t[4][256], ti[4][256];
+static uint32 u[4][256];
+static octet rc[32];
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @mul@ --- *
+ *
+ * Arguments:  @unsigned x, y@ = polynomials over %$\gf{2^8}$%
+ *             @unsigned m@ = modulus
+ *
+ * Returns:    The product of two polynomials.
+ *
+ * Use:                Computes a product of polynomials, quite slowly.
+ */
+
+static unsigned mul(unsigned x, unsigned y, unsigned m)
+{
+  unsigned a = 0;
+  unsigned i;
+
+  for (i = 0; i < 8; i++) {
+    if (y & 1)
+      a ^= x;
+    y >>= 1;
+    x <<= 1;
+    if (x & 0x100)
+      x ^= m;
+  }
+
+  return (a);
+}
+
+/* --- @sbox@ --- *
+ *
+ * Build the S-box.
+ *
+ * This is built from inversion in the multiplicative group of
+ * %$\gf{2^8}[x]/(p(x))$%, where %$p(x) = x^8+x^7+x^6+x^5+x^4+x^2+1$%,
+ * followed by an affine transformation treating inputs as vectors over
+ * %$\gf{2}$%.  The result is a horrible function.
+ *
+ * The inversion is done slightly sneakily, by building log and antilog
+ * tables.  Let %$a$% be an element of the finite field.  If the inverse of
+ * %$a$% is %$a^{-1}$%, then %$\log a a^{-1} = 0$%.  Hence
+ * %$\log a = -\log a^{-1}$%.  This saves fiddling about with Euclidean
+ * algorithm.
+ */
+
+#define S_MOD 0x1f5
+
+static void sbox(void)
+{
+  octet log[256], alog[256];
+  unsigned x;
+  unsigned i;
+  unsigned g;
+
+  /* --- Find a suitable generator, and build log tables --- */
+
+  log[0] = 0;
+  for (g = 2; g < 256; g++) {
+    x = 1;
+    for (i = 0; i < 256; i++) {
+      log[x] = i;
+      alog[i] = x;
+      x = mul(x, g, S_MOD);
+      if (x == 1 && i != 254)
+       goto again;
+    }
+    goto done;
+  again:;
+  }
+  fprintf(stderr, "couldn't find generator\n");
+  exit(EXIT_FAILURE);
+done:;
+
+  /* --- Now grind through and do the affine transform --- *
+   *
+   * The matrix multiply is an AND and a parity op.  The add is an XOR.
+   */
+
+  for (i = 0; i < 256; i++) {
+    unsigned j;
+    octet m[] = { 0xd6, 0x7b, 0x3d, 0x1f, 0x0f, 0x05, 0x03, 0x01 };
+    unsigned v = i ? alog[255 - log[i]] : 0;
+
+    assert(i == 0 || mul(i, v, S_MOD) == 1);
+
+    x = 0;
+    for (j = 0; j < 8; j++) {
+      unsigned r;
+      r = v & m[j];
+      r = (r >> 4) ^ r;
+      r = (r >> 2) ^ r;
+      r = (r >> 1) ^ r;
+      x = (x << 1) | (r & 1);
+    }
+    x ^= 0xb1;
+    s[i] = x;
+    si[x] = i;
+  }
+}
+
+/* --- @tbox@ --- *
+ *
+ * Construct the t tables for doing the round function efficiently.
+ */
+
+static void tbox(void)
+{
+  unsigned i;
+
+  for (i = 0; i < 256; i++) {
+    uint32 a, b, c, d;
+    uint32 w;
+
+    /* --- Build a forwards t-box entry --- */
+
+    a = s[i];
+    b = a << 1; if (b & 0x100) b ^= S_MOD;
+    c = a ^ b;
+    w = (b << 0) | (a << 8) | (a << 16) | (c << 24);
+    t[0][i] = w;
+    t[1][i] = ROL32(w, 8);
+    t[2][i] = ROL32(w, 16);
+    t[3][i] = ROL32(w, 24);
+
+    /* --- Build a backwards t-box entry --- */
+
+    a = mul(si[i], 0x0e, S_MOD);
+    b = mul(si[i], 0x09, S_MOD);
+    c = mul(si[i], 0x0d, S_MOD);
+    d = mul(si[i], 0x0b, S_MOD);
+    w = (a << 0) | (b << 8) | (c << 16) | (d << 24);
+    ti[0][i] = w;
+    ti[1][i] = ROL32(w, 8);
+    ti[2][i] = ROL32(w, 16);
+    ti[3][i] = ROL32(w, 24);
+  }
+}
+
+/* --- @ubox@ --- *
+ *
+ * Construct the tables for performing the key schedule.
+ */
+
+static void ubox(void)
+{
+  unsigned i;
+
+  for (i = 0; i < 256; i++) {
+    uint32 a, b, c;
+    uint32 w;
+    a = i;
+    b = a << 1; if (b & 0x100) b ^= S_MOD;
+    c = a ^ b;
+    w = (b << 0) | (a << 8) | (a << 16) | (c << 24);
+    u[0][i] = w;
+    u[1][i] = ROL32(w, 8);
+    u[2][i] = ROL32(w, 16);
+    u[3][i] = ROL32(w, 24);
+  }
+}
+
+/* --- Round constants --- */
+
+void rcon(void)
+{
+  unsigned r = 1;
+  int i;
+
+  for (i = 0; i < sizeof(rc); i++) {
+    rc[i] = r;
+    r <<= 1;
+    if (r & 0x100)
+      r ^= S_MOD;
+  }
+}
+
+/* --- @main@ --- */
+
+int main(void)
+{
+  int i, j;
+
+  puts("\
+/* -*-c-*-\n\
+ *\n\
+ * Square tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_SQUARE_TAB_H\n\
+#define CATACOMB_SQUARE_TAB_H\n\
+");
+
+  /* --- Write out the S-box --- */
+
+  sbox();
+  fputs("\
+/* --- The byte substitution and its inverse --- */\n\
+\n\
+#define SQUARE_S {                                                     \\\n\
+  ", stdout);
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", s[i]);
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  fputs("\
+#define SQUARE_SI {                                                    \\\n\
+  ", stdout);
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", si[i]);
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Write out the big t tables --- */
+
+  tbox();
+  fputs("\
+/* --- The big round tables --- */\n\
+\n\
+#define SQUARE_T {                                                     \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08x", t[j][i]);
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  fputs("\
+#define SQUARE_TI {                                                    \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08x", ti[j][i]);
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  /* --- Write out the big u tables --- */
+
+  ubox();
+  fputs("\
+/* --- The key schedule tables --- */\n\
+\n\
+#define SQUARE_U {                                                     \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08x", u[j][i]);
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  /* --- Round constants --- */
+
+  rcon();
+  fputs("\
+/* --- The round constants --- */\n\
+\n\
+#define SQUARE_RCON {                                                  \\\n\
+  ", stdout);
+  for (i = 0; i < sizeof(rc); i++) {
+    printf("0x%02x", rc[i]);
+    if (i == sizeof(rc) - 1)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Done --- */
+
+  puts("#endif");
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/square.c b/symm/square.c
new file mode 100644 (file)
index 0000000..490b917
--- /dev/null
@@ -0,0 +1,194 @@
+/* -*-c-*-
+ *
+ * The Square block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "paranoia.h"
+#include "square.h"
+#include "square-tab.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet square_keysz[] = { KSZ_RANGE, SQUARE_KEYSZ, 4, 16, 4 };
+
+/*----- Constant tables ---------------------------------------------------*/
+
+static const octet S[256] = SQUARE_S, SI[256] = SQUARE_SI;
+static const uint32 T[4][256] = SQUARE_T, TI[4][256] = SQUARE_TI;
+static const uint32 U[4][256] = SQUARE_U;
+static const octet rcon[] = SQUARE_RCON;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @square_init@ --- *
+ *
+ * Arguments:  @square_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Square context with a particular key.  Square
+ *             keys must be a multiple of 32 bits long, and may be at most
+ *             128 bits.
+ */
+
+void square_init(square_ctx *k, const void *buf, size_t sz)
+{
+  unsigned nk, nr, nw;
+  unsigned i, j, jj;
+  const octet *p;
+  uint32 ww;
+  uint32 kk[SQUARE_KWORDS];
+
+  /* --- Sort out the key size --- */
+
+  KSZ_ASSERT(square, sz);
+  nk = sz / 4;
+
+  /* --- Fetch the first key words out --- */
+
+  p = buf;
+  for (i = 0; i < nk; i++) {
+    kk[i] = LOAD32_L(p);
+    p += 4;
+  }
+  nr = 8;
+
+  /* --- Expand this material to fill the rest of the table --- */
+
+  nw = (nr + 1) * 4;
+  ww = kk[i - 1];
+  p = rcon;
+  for (; i < nw; i++) {
+    uint32 w = kk[i - nk];
+    if (i % nk == 0) {
+      ww = ROR32(ww, 8);
+      w ^= ww ^ *p++;
+    } else
+      w ^= ww;
+    kk[i] = ww = w;
+  }
+
+  /* --- Make the encryption and decryption keys --- */
+
+  for (i = 0; i < nr * 4; i++) {
+    uint32 w = kk[i];
+    k->w[i] = (U[0][U8(w >>  0)] ^ U[1][U8(w >>         8)] ^
+              U[2][U8(w >> 16)] ^ U[3][U8(w >> 24)]);
+  }
+  for (; i < nw; i++)
+    k->w[i] = kk[i];
+
+  jj = nw;
+  for (i = 0; i < nr * 4; i += 4) {
+    jj -= 4;
+    for (j = 0; j < 4; j++)
+      k->wi[i + j] = kk[jj + j];
+  }
+  for (j = 0; j < 4; j++)
+    k->wi[i + j] = k->w[j];
+
+  BURN(kk);
+}
+
+/* --- @square_eblk@, @square_dblk@ --- *
+ *
+ * Arguments:  @const square_ctx *k@ = pointer to Square context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define SUB(s, sh, a, b, c, d)                                         \
+  (s[U8((a) >> sh)] << 0 | s[U8((b) >> sh)] <<  8 |                    \
+   s[U8((c) >> sh)] << 16 | s[U8((d) >> sh)] << 24)
+
+#define MIX(t, sh, a, b, c, d)                                         \
+  (t[0][U8((a) >> sh)] ^ t[1][U8((b) >> sh)] ^                         \
+   t[2][U8((c) >> sh)] ^ t[3][U8((d) >> sh)])
+
+#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do {                        \
+  aa = what(t, 0, a, b, c, d) ^ *w++;                                  \
+  bb = what(t, 8, a, b, c, d) ^ *w++;                                  \
+  cc = what(t, 16, a, b, c, d) ^ *w++;                                 \
+  dd = what(t, 24, a, b, c, d) ^ *w++;                                 \
+} while (0)
+
+void square_eblk(const square_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
+  uint32 aa, bb, cc, dd;
+  const uint32 *w = k->w;
+
+  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
+
+  DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+  DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+  DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+  DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+  DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+  DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
+  DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
+  DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+}
+
+void square_dblk(const square_ctx *k, const uint32 *s, uint32 *dst)
+{
+  uint32 a = s[0], b = s[1], c = s[2], d = s[3];
+  uint32 aa, bb, cc, dd;
+  const uint32 *w = k->wi;
+
+  a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
+
+  DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+  DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+  DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+  DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+  DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+  DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
+  DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
+  DO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w);
+
+  dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
+}
+
+BLKC_TEST(SQUARE, square)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/square.h b/symm/square.h
new file mode 100644 (file)
index 0000000..25671d8
--- /dev/null
@@ -0,0 +1,112 @@
+/* -*-c-*-
+ *
+ * The Square block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Square block cipher ----------------------------------*
+ *
+ * Invented by Joan Daemen and Vincent Rijmen, Square is a fast and
+ * relatively simple 128-bit block cipher.  It is the predecessor to
+ * Rijndael.  I have grave doubts about the security of Square, though: a
+ * dedicated attack against Square's structure by Knudsen has been extended
+ * by the Twofish team against Rijndael, and I believe that this extended
+ * attack is also effective against Square.  This is a shame: the structure
+ * of Square (and Rijndael) is extremely elegant, and has some extremely nice
+ * properties.
+ */
+
+#ifndef CATACOMB_SQUARE_H
+#define CATACOMB_SQUARE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define SQUARE_BLKSZ 16
+#define SQUARE_KEYSZ 16
+#define SQUARE_CLASS (N, L, 128)
+
+extern const octet square_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+#define SQUARE_MAXROUNDS 8
+#define SQUARE_KWORDS ((SQUARE_MAXROUNDS + 1) * (SQUARE_BLKSZ / 4))
+
+typedef struct square_ctx {
+  uint32 w[SQUARE_KWORDS];
+  uint32 wi[SQUARE_KWORDS];
+} square_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @square_init@ --- *
+ *
+ * Arguments:  @square_ctx *k@ = pointer to context to initialize
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of the key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Square context with a particular key.  This
+ *             implementation of Square doesn't impose any particular
+ *             limits on the key size except that it must be multiple of 4
+ *             bytes long.  256 bits seems sensible, though.
+ */
+
+extern void square_init(square_ctx */*k*/,
+                         const void */*buf*/, size_t /*sz*/);
+
+/* --- @square_eblk@, @square_dblk@ --- *
+ *
+ * Arguments:  @const square_ctx *k@ = pointer to Square context
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void square_eblk(const square_ctx */*k*/,
+                         const uint32 */*s*/, uint32 */*dst*/);
+extern void square_dblk(const square_ctx */*k*/,
+                         const uint32 */*s*/, uint32 */*dst*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/t/.gitignore b/symm/t/.gitignore
new file mode 100644 (file)
index 0000000..88cf471
--- /dev/null
@@ -0,0 +1,5 @@
+cast256
+mars
+rijndael
+serpent
+twofish
diff --git a/symm/t/blowfish b/symm/t/blowfish
new file mode 100644 (file)
index 0000000..449f967
--- /dev/null
@@ -0,0 +1,119 @@
+# Test vectors for Blowfish
+
+blowfish {
+
+  # --- Main block cipher ---
+  #
+  # Taken from Bruce Schneier's web pages, I think...
+
+  0000000000000000 0000000000000000 4ef997456198dd78;
+  ffffffffffffffff ffffffffffffffff 51866fd5b85ecb8a;
+  3000000000000000 1000000000000001 7d856f9a613063f2;
+  1111111111111111 1111111111111111 2466dd878b963c9d;
+  0123456789abcdef 1111111111111111 61f9c3802281b096;
+  1111111111111111 0123456789abcdef 7d0cc630afda1ec7;
+  0000000000000000 0000000000000000 4ef997456198dd78;
+  fedcba9876543210 0123456789abcdef 0aceab0fc6a0a28d;
+  7ca110454a1a6e57 01a1d6d039776742 59c68245eb05282b;
+  0131d9619dc1376e 5cd54ca83def57da b1b8cc0b250f09a0;
+  07a1133e4a0b2686 0248d43806f67172 1730e5778bea1da4;
+  3849674c2602319e 51454b582ddf440a a25e7856cf2651eb;
+  04b915ba43feb5b6 42fd443059577fa2 353882b109ce8f1a;
+  0113b970fd34f2ce 059b5e0851cf143a 48f4d0884c379918;
+  0170f175468fb5e6 0756d8e0774761d2 432193b78951fc98;
+  43297fad38e373fe 762514b829bf486a 13f04154d69d1ae5;
+  07a7137045da2a16 3bdd119049372802 2eedda93ffd39c79;
+  04689104c2fd3b2f 26955f6835af609a d887e0393c2da6e3;
+  37d06bb516cb7546 164d5e404f275232 5f99d04f5b163969;
+  1f08260d1ac2465e 6b056e18759f5cca 4a057a3b24d3977b;
+  584023641aba6176 004bd6ef09176062 452031c1e4fada8e;
+  025816164629b007 480d39006ee762f2 7555ae39f59b87bd;
+  49793ebc79b3258f 437540c8698f3cfa 53c55f9cb49fc019;
+  4fb05e1515ab73a7 072d43a077075292 7a8e7bfa937e89a3;
+  49e95d6d4ca229bf 02fe55778117f12a cf9c5d7a4986adb5;
+  018310dc409b26d6 1d9d5c5018f728c2 d1abb290658bc778;
+  1c587f1c13924fef 305532286d6f295a 55cb3774d13ef201;
+  0101010101010101 0123456789abcdef fa34ec4847b268b2;
+  1f1f1f1f0e0e0e0e 0123456789abcdef a790795108ea3cae;
+  e0fee0fef1fef1fe 0123456789abcdef c39e072d9fac631d;
+  0000000000000000 ffffffffffffffff 014933e0cdaff6e4;
+  ffffffffffffffff 0000000000000000 f21e9a77b71c49bc;
+  0123456789abcdef 0000000000000000 245946885754369a;
+  fedcba9876543210 ffffffffffffffff 6b5c5a9c5d9e0a5a;
+
+  # --- Key schedule test ---
+  #
+  # From wherever the previous tests came from.
+
+  f0
+       fedcba9876543210        f9ad597c49db005e;
+
+  f0e1
+       fedcba9876543210        e91d21c1d961a6d6;
+
+  f0e1d2
+       fedcba9876543210        e9c2b70a1bc65cf3;
+
+  f0e1d2c3
+       fedcba9876543210        be1e639408640f05;
+
+  f0e1d2c3b4
+       fedcba9876543210        b39e44481bdb1e6e;
+
+  f0e1d2c3b4a5
+       fedcba9876543210        9457aa83b1928c0d;
+
+  f0e1d2c3b4a596
+       fedcba9876543210        8bb77032f960629d;
+
+  f0e1d2c3b4a59687
+       fedcba9876543210        e87a244e2cc85e82;
+
+  f0e1d2c3b4a5968778
+       fedcba9876543210        15750e7a4f4ec577;
+
+  f0e1d2c3b4a596877869
+       fedcba9876543210        122ba70b3ab64ae0;
+
+  f0e1d2c3b4a5968778695a
+       fedcba9876543210        3a833c9affc537f6;
+
+  f0e1d2c3b4a5968778695a4b
+       fedcba9876543210        9409da87a90f6bf2;
+
+  f0e1d2c3b4a5968778695a4b3c
+       fedcba9876543210        884f80625060b8b4;
+
+  f0e1d2c3b4a5968778695a4b3c2d
+       fedcba9876543210        1f85031c19e11968;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e
+       fedcba9876543210        79d9373a714ca34f;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f
+       fedcba9876543210        93142887ee3be15c;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f00
+       fedcba9876543210        03429e838ce2d14b;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f0011
+       fedcba9876543210        a4299e27469ff67b;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f001122
+       fedcba9876543210        afd5aed1c1bc96a8;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f00112233
+       fedcba9876543210        10851c0e3858da9f;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344
+       fedcba9876543210        e6f51ed79b9db21f;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455
+       fedcba9876543210        64a6e14afd36b46f;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566
+       fedcba9876543210        80c7d7d45a5479ad;
+
+  f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677
+       fedcba9876543210        05044b62fa52d080;
+}
diff --git a/symm/t/cast128 b/symm/t/cast128
new file mode 100644 (file)
index 0000000..a456ea0
--- /dev/null
@@ -0,0 +1,15 @@
+# Test vectors for CAST128
+
+cast128 {
+  0123456712345678234567893456789a
+  0123456789abcdef
+  238b4fe5847e44b2;
+
+  01234567123456782345
+  0123456789abcdef
+  eb6a711a2c02271b;
+
+  0123456712
+  0123456789abcdef
+  7ac816d16e9b302e;
+}
similarity index 100%
rename from tests/cast256.aes
rename to symm/t/cast256.aes
diff --git a/symm/t/des b/symm/t/des
new file mode 100644 (file)
index 0000000..7b75304
--- /dev/null
@@ -0,0 +1,62 @@
+# Test vectors for DES
+
+des {
+  # --- 7-byte keys ---
+
+  00451338957377 4e6f772069732074 3fa40e8a984d4815;
+  b6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1;
+
+  # --- 8-byte keys ---
+
+  0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
+  0022446688aaccee 4e6f772069732074 3fa40e8a984d4815;
+  0123456789abcdef 68652074696d6520 6a271787ab8883f9;
+  0123456789abcdef 666f7220616c6c20 893d51ec4b563b53;
+  0123456789abcdef 0123456789abcde7 c95744256a5ed31d;
+  b763d297f70606fb 328da675ff5abd2c cd3e9f9b670671d1;
+
+  # --- Tests for all DES S-boxes ---
+
+  7ca110454a1a6e57 01a1d6d039776742 690f5b0d9a26939b;
+  0131d9619dc1376e 5cd54ca83def57da 7a389d10354bd271;
+  07a1133e4a0b2686 0248d43806f67172 868ebb51cab4599a;
+  3849674c2602319e 51454b582ddf440a 7178876e01f19b2a;
+  04b915ba43feb5b6 42fd443059577fa2 af37fb421f8c4095;
+  0113b970fd34f2ce 059b5e0851cf143a 86a560f10ec6d85b;
+  0170f175468fb5e6 0756d8e0774761d2 0cd3da020021dc09;
+  43297fad38e373fe 762514b829bf486a ea676b2cb7db2b7a;
+  07a7137045da2a16 3bdd119049372802 dfd64a815caf1a0f;
+  04689104c2fd3b2f 26955f6835af609a 5c513c9c4886c088;
+  37d06bb516cb7546 164d5e404f275232 0a2aeeae3ff4ab77;
+  1f08260d1ac2465e 6b056e18759f5cca ef1bf03e5dfa575a;
+  584023641aba6176 004bd6ef09176062 88bf0db6d70dee56;
+  025816164629b007 480d39006ee762f2 a1f9915541020b56;
+  49793ebc79b3258f 437540c8698f3cfa 6fbf1cafcffd0556;
+  4fb05e1515ab73a7 072d43a077075292 2f22e49bab7ca1ac;
+  49e95d6d4ca229bf 02fe55778117f12a 5a6b612cc26cce4a;
+  018310dc409b26d6 1d9d5c5018f728c2 5f4c038ed12b2e41;
+  1c587f1c13924fef 305532286d6f295a 63fac0d034d9f793;
+
+  # --- Rivest's test vector set ---
+
+  9474b8e8c73bca7d 9474b8e8c73bca7d 8da744e0c94e5e17;
+  8da744e0c94e5e17 0cdb25e3ba3c6d79 8da744e0c94e5e17;
+  0cdb25e3ba3c6d79 0cdb25e3ba3c6d79 4784c4ba5006081f;
+  4784c4ba5006081f 1cf1fc126f2ef842 4784c4ba5006081f;
+  1cf1fc126f2ef842 1cf1fc126f2ef842 e4be250042098d13;
+  e4be250042098d13 7bfc5dc6adb5797c e4be250042098d13;
+  7bfc5dc6adb5797c 7bfc5dc6adb5797c 1ab3b4d82082fb28;
+  1ab3b4d82082fb28 c1576a14de707097 1ab3b4d82082fb28;
+  c1576a14de707097 c1576a14de707097 739b68cd2e26782a;
+  739b68cd2e26782a 2a59f0c464506edb 739b68cd2e26782a;
+  2a59f0c464506edb 2a59f0c464506edb a5c39d4251f0a81e;
+  a5c39d4251f0a81e 7239ac9a6107ddb1 a5c39d4251f0a81e;
+  7239ac9a6107ddb1 7239ac9a6107ddb1 070cac8590241233;
+  070cac8590241233 78f87b6e3dfecf61 070cac8590241233;
+  78f87b6e3dfecf61 78f87b6e3dfecf61 95ec2578c2c433f0;
+  95ec2578c2c433f0 1b1a2ddb4c642438 95ec2578c2c433f0;
+
+  # --- The EFF answer to Matt Blaze's challenge ---
+
+  0e329232ea6d0d73 8787878787878787 0000000000000000;
+}
diff --git a/symm/t/des3 b/symm/t/des3
new file mode 100644 (file)
index 0000000..f1adb1a
--- /dev/null
@@ -0,0 +1,41 @@
+# Test vectors for double and triple DES
+
+des3 {
+  # --- Some simple single-DES things ---
+
+  00451338957377 4e6f772069732074 3fa40e8a984d4815;
+  b6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1;
+
+  0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
+  0123456789abcdef 68652074696d6520 6a271787ab8883f9;
+  0123456789abcdef 666f7220616c6c20 893d51ec4b563b53;
+  0123456789abcdef 0123456789abcde7 c95744256a5ed31d;
+
+  0045133895737700451338957377 4e6f772069732074 3fa40e8a984d4815;
+  b6c74cbf60c1fdb6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1;
+
+  0123456789abcdef0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
+  0123456789abcdef0123456789abcdef 68652074696d6520 6a271787ab8883f9;
+  0123456789abcdef0123456789abcdef 666f7220616c6c20 893d51ec4b563b53;
+  0123456789abcdef0123456789abcdef 0123456789abcde7 c95744256a5ed31d;
+
+  004513389573770045133895737700451338957377
+       4e6f772069732074 3fa40e8a984d4815;
+  b6c74cbf60c1fdb6c74cbf60c1fdb6c74cbf60c1fd
+       328da675ff5abd2c cd3e9f9b670671d1;
+
+  0123456789abcdef0123456789abcdef0123456789abcdef
+       4e6f772069732074 3fa40e8a984d4815;
+  0123456789abcdef0123456789abcdef0123456789abcdef
+       68652074696d6520 6a271787ab8883f9;
+  0123456789abcdef0123456789abcdef0123456789abcdef
+       666f7220616c6c20 893d51ec4b563b53;
+  0123456789abcdef0123456789abcdef0123456789abcdef
+       0123456789abcde7 c95744256a5ed31d;
+
+  # --- Genuine longer keys ---
+
+  0123456789abcdeffedcba9876543210 0123456789abcde7 7f1d0a77826b8aff;
+  0123456789abcdeffedcba987654321089abcdef01234567
+       0123456789abcde7 de0b7c06ae5e0ed5;
+}
diff --git a/symm/t/desx b/symm/t/desx
new file mode 100644 (file)
index 0000000..0f64086
--- /dev/null
@@ -0,0 +1,22 @@
+# Test vectors for DES
+
+desx {
+  # --- From SCAN ---
+
+  0123456789abcdef1011121314151617
+    4445535864657378 d8fa5084fad4b35c;
+  01010101010101010123456789abcdef1011121314151617
+    94dbe082549a14ef 9011121314151617;
+
+  # --- 7-bit key tests ---
+
+  004513389573771011121314151617
+    4445535864657378 d8fa5084fad4b35c;
+  000000000000000123456789abcdef1011121314151617
+    94dbe082549a14ef 9011121314151617;
+
+  # --- Equivalence tests ---
+
+  00451338957377 4e6f772069732074 3fa40e8a984d4815;
+  0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
+}
diff --git a/symm/t/has160 b/symm/t/has160
new file mode 100644 (file)
index 0000000..e1a3086
--- /dev/null
@@ -0,0 +1,51 @@
+# Test vectors for HAS160 hash function
+
+# --- 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;
+}
diff --git a/symm/t/idea b/symm/t/idea
new file mode 100644 (file)
index 0000000..c0b928d
--- /dev/null
@@ -0,0 +1,26 @@
+# Test vectors for IDEA
+
+# --- Thin on the ground, these are ---
+
+idea {
+  00010002000300040005000600070008 0000000100020003 11fbed2b01986de5;
+  00000000000000000000000000000000 0000000000000000 0001000100000000;
+  000027ed8f5c3e8baf16560d14c90b43 0000abbf94ff8b5f cbbb2e6c05ee8c89;
+  000027ed8f5c3e8baf16560d14c90b43 6889f5647ab23d59 61d5397046f99637;
+  000027ed8f5c3e8baf16560d14c90b43 6c2e3617da2bac35 b2229067630f7045;
+  000027ed8f5c3e8baf16560d14c90b43 819440ca2065d112 c88600093b348575;
+  000027ed8f5c3e8baf16560d14c90b43 848f836780938169 4821b99f61acebb7;
+  000027ed8f5c3e8baf16560d14c90b43 ac4856242b121589 85c6b232294c2f27;
+  000027ed8f5c3e8baf16560d14c90b43 cbe465f232f9d85c b67ac767c0c06a55;
+  000027ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1320f99bfe052804;
+  000027ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 ef4899b48de5907c;
+  729a27ed8f5c3e8baf16560d14c90b43 0000abbf94ff8b5f 65861be574e1eab6;
+  729a27ed8f5c3e8baf16560d14c90b43 6889f5647ab23d59 f963468b52f45d4d;
+  729a27ed8f5c3e8baf16560d14c90b43 6c2e3617da2bac35 1569e0627007b12e;
+  729a27ed8f5c3e8baf16560d14c90b43 819440ca2065d112 264a8bba66959075;
+  729a27ed8f5c3e8baf16560d14c90b43 848f836780938169 d7e0468226d0fc56;
+  729a27ed8f5c3e8baf16560d14c90b43 ac4856242b121589 95cd92f44bacb72d;
+  729a27ed8f5c3e8baf16560d14c90b43 cbe465f232f9d85c bce24dc8d0961c44;
+  729a27ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1d0cb2af1654820a;
+  729a27ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 29358cc6c83828ae;
+}
similarity index 100%
rename from tests/mars.aes
rename to symm/t/mars.aes
diff --git a/symm/t/md2 b/symm/t/md2
new file mode 100644 (file)
index 0000000..e478ae8
--- /dev/null
@@ -0,0 +1,77 @@
+# Test vectors for MD2 hash function
+
+# --- Basic hash function ---
+#
+# Test vectors from RFC1319.  The last was generated using OpenSSL.
+
+md2 {
+  ""                   8350e5a3e24c153df2275c9f80692773;
+  "a"                  32ec01ec4a6dac72c0ab96fb34c0b5d1;
+  "abc"                        da853b0d3f88d99b30283a69e6ded6bb;
+  "message digest"     ab4f496bfb2a530b219ff33031fe06b0;
+  "abcdefghijklmnopqrstuvwxyz"
+                       4e8ddff3650292ab5a4108c3aa47940b;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+                       da33def2a42df13975352846c30338cd;
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+                       d5976f79d83d3a0dc9806c3c66f3efd8;
+
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+"                      9bc05c2f44930f59882bb885a75b4c95;
+}
+
+# --- HMAC mode ---
+#
+# These are just regression tests, generated internally.
+
+md2-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       b524be0196e491ed44823746cd8923af;
+
+  "what do ya want for nothing?"
+       4a656665
+       292f9d34f9e311846de86c495d7adfa2;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       ff09238e4bded84b5490bc42cfd5c265;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       ea3181bf1cc387f12ed0637105fb219d;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       7177f2b3e5583078ee122f94fe3c784a;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       615b1c392f5aaeeeab7e82572e6395d5;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       df0b12810892f0c7559802d5c0ce1157;
+}
diff --git a/symm/t/md4 b/symm/t/md4
new file mode 100644 (file)
index 0000000..0b78cc4
--- /dev/null
@@ -0,0 +1,57 @@
+# Test vectors for MD4 hash function
+
+# --- Basic hash function ---
+#
+# Test vectors from RFC1186 and some others I generated using the reference
+# implementation.
+
+md4 {
+  ""                   31d6cfe0d16ae931b73c59d7e0c089c0;
+  "a"                  bde52cb31de33e46245e05fbdbd6fb24;
+  "abc"                        a448017aaf21d8525fc10ae87aa6729d;
+  "message digest"     d9130a8164549fe818874806e1c7014b;
+  "abcdefghijklmnopqrstuvwxyz"
+                       d79e1c308aa5bbcdeea8ed63df412da9;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+                       043f8582f241db351ce627e153e7f0e4;
+}
+
+# --- HMAC mode ---
+#
+# No test vectors available.  The HMAC implementation has not been tested
+# against an external reference.  However, MD4 isn't strong enough to make
+# a realistic MAC anyway, and use of md4-mac is thoroughly deprecated.  The
+# HMAC code is autogenerated anyway, and ought to be reliable and correct.
+#
+# These test vectors are here to spot changes in behaviour rather than ensure
+# interoperability.
+
+md4-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       90a79458f58f437e21f169cdba283da6;
+
+  "what do ya want for nothing?"
+       4a656665
+       be192c588a8e914d8a59b474a828128f;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       75e5fb6e71ca6dcdd9fca269a9a3cd9c;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       fb14cddf9efe11ad24033fc70f37bb9e;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       6306262f9ba0e83f9ce3f15aafc23be8;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       545b8f2577657042df628fbb98430d5f;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       0192f3442ad5d1ea5268306ab0d4962e;
+}
diff --git a/symm/t/md5 b/symm/t/md5
new file mode 100644 (file)
index 0000000..533c562
--- /dev/null
@@ -0,0 +1,78 @@
+# Test vectors for MD5 hash function
+
+# --- Basic hash function ---
+#
+# Test vectors from RFC1321 and some others I generated using the reference
+# implementation.
+
+md5 {
+  ""                   d41d8cd98f00b204e9800998ecf8427e;
+  "a"                  0cc175b9c0f1b6a831c399e269772661;
+  "abc"                        900150983cd24fb0d6963f7d28e17f72;
+  "message digest"     f96b697d7cb7938d525a2f31aaf161d0;
+  "abcdefghijklmnopqrstuvwxyz"
+                       c3fcd3d76192e4007dfb496cca67e13b;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+                       d174ab98d277d9f5a5611c2c9f419d9f;
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+                       57edf4a22be3c955ac49da2e2107b67a;
+
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+"                      2b65a7ba4acd105ef2cb9adebd9f0bfa;
+}
+
+# --- HMAC mode ---
+#
+# Test vectors from RFC2104 and RFC2202.
+
+md5-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       9294727a3638bb1c13f48ef8158bfc9d;
+
+  "what do ya want for nothing?"
+       4a656665
+       750c783e6ab0b503eaa86e310a5db738;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       56be34521d144c88dbb8c733f0e8b3f6;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       697eaf0aca3a3aea3a75164746ffaa79;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       56461ef2342edc00f9bab995690efd4c;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       6f630fad67cda0ee1fb1f562db3aa53e;
+}
diff --git a/symm/t/noekeon b/symm/t/noekeon
new file mode 100644 (file)
index 0000000..0764732
--- /dev/null
@@ -0,0 +1,10 @@
+# Test vectors for Noekeon
+
+noekeon {
+  00000000000000000000000000000000
+    00000000000000000000000000000000 ba6933819299c71699a99f08f678178b;
+  ffffffffffffffffffffffffffffffff
+    ffffffffffffffffffffffffffffffff 52f88a7b283c1f7bdf7b6faa5011c7d8;
+  ba6933819299c71699a99f08f678178b
+    52f88a7b283c1f7bdf7b6faa5011c7d8 5096f2bfc82ae6e2d9495515c277fa70;
+}
diff --git a/symm/t/rc2 b/symm/t/rc2
new file mode 100644 (file)
index 0000000..ed90d3f
--- /dev/null
@@ -0,0 +1,13 @@
+# Test vectors for RC2
+
+rc2 {
+   0000000000000000 63 0000000000000000 ebb773f993278eff;
+   ffffffffffffffff 64 ffffffffffffffff 278b27e42e2f0d49;
+   3000000000000000 64 1000000000000001 30649edf9be7d2c2;
+   88 64 0000000000000000 61a8a244adacccf0;
+   88bca90e90875a 64 0000000000000000 6ccf4308974c267f;
+   88bca90e90875a7f0f79c384627bafb2 64 0000000000000000 1a807d272bbe5db1;
+   88bca90e90875a7f0f79c384627bafb2 128 0000000000000000 2269552ab0f85ca6;
+   88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e 129
+   0000000000000000 5b78d3a43dfff1f1;
+}
diff --git a/symm/t/rc4 b/symm/t/rc4
new file mode 100644 (file)
index 0000000..4e55ba5
--- /dev/null
@@ -0,0 +1,25 @@
+# Test vectors for RC4
+#
+#
+# These test vectors come from two places: the Usenet article confirming that
+# the alleged RC4 source is interoperable with the BSAFE version, and some
+# tests I performed with the RC4-in-a-signature Perl version.  Some testing
+# with the SSLeay version shows that for an all-zero key I'm compatible, but
+# with any other I'm not.  Since I pass the Usenet test vectors (which I
+# found in the SSLeay sources!), and I'm compatible with at least one other
+# implementation, I'm happy that I'm in the right here.
+
+rc4-encrypt {
+  0123456789abcdef     0123456789abcdef        75b7878099e0c596;
+  0123456789abcdef
+       010101010101010101010101010101010101010101
+       7595c3e6114a09780c4ad452338e1ffd9a1be9498f;
+}
+
+rc4-generate {
+  00                   0       de188941a3375d3a8a061e67576e926d;
+  01fe23dc45ba6798     0       643ded26ae29c15cda4f2b96d66baf2c;
+  08192a3b4c5d6e7f     1024    abb3a32a2ba4d409752923aa4032be16;
+  0123456789abcdef     0       7494c2e7104b0879;
+  ef012345             0       d6a141a7ec3c38dfbd61;
+}
diff --git a/symm/t/rc5 b/symm/t/rc5
new file mode 100644 (file)
index 0000000..e7a02c9
--- /dev/null
@@ -0,0 +1,15 @@
+# Test vectors for RC5-32/12
+
+# --- Main cipher test vectors ---
+#
+# Taken from `The RC5 Encryption Algorithm' by Rivest.  Important: the
+# test vectors given in the paper are given as 32-bit words, not bytes, so
+# since RC5 is little-endian they need to be swapped here.
+
+rc5 {
+  00000000000000000000000000000000 0000000000000000 21a5dbee154b8f6d;
+  915f4619be41b2516355a50110a9ce91 21a5dbee154b8f6d f7c013ac5b2b8952;
+  783348e75aeb0f2fd7b169bb8dc16787 f7c013ac5b2b8952 2f42b3b70369fc92;
+  dc49db1375a5584f6485b413b5f12baf 2f42b3b70369fc92 65c178b284d197cc;
+  5269f149d41ba0152497574d7f153125 65c178b284d197cc eb44e415da319824;
+}
similarity index 100%
rename from tests/rijndael.aes
rename to symm/t/rijndael.aes
diff --git a/symm/t/rijndael192 b/symm/t/rijndael192
new file mode 100644 (file)
index 0000000..d7732ff
--- /dev/null
@@ -0,0 +1,2884 @@
+# Test vectors for Rijndael
+
+rijndael192 {
+  01000000000000000000000000000000
+       023a67f4591abd1dc00c5abebebe0397a3b347451ad3112d
+       7ff75c2eeefa7f368c8a8b4520696533bff5aba750f61004;
+  02000000000000000000000000000000
+       506a186359362e62a58444f018f882194d728766ca6ff976
+       6288af2dd607059b760ec2ae99287ff4f5f135350c6533b3;
+  04000000000000000000000000000000
+       ca5c42150025d70706f9df66c6a149878f99b02d80d24af6
+       2740c22885fa7f6979eed72c31254719f75097913d55d089;
+  08000000000000000000000000000000
+       03ebd2ad4e4c4b8767eef082e0671b8a40aa83205dd2cd7d
+       50d067dfe60008dcff6c8f6011a56b04297a0886b818fdb3;
+  10000000000000000000000000000000
+       c8b526b380f2b8ddf60ad4527b585b36bc886f915906f34a
+       ee2550dd5a911da2bb85424687b6d06e18607d9800822a8b;
+  20000000000000000000000000000000
+       b5fe0634f8cc42cad26dd7448ed44288ff054435747606ac
+       fabc0ae4d9eb26ed89375f1e24215540b37d106c3f4429b3;
+  40000000000000000000000000000000
+       2a8b55370b58585cd5c545065c1236876c25f7227043f697
+       9a2efe9a23f99898519dfc86bd82ac51311356e96a744e4c;
+  80000000000000000000000000000000
+       225d2952c570bd85c57b60bdf0d7813cee77f88eb94b9fe0
+       66391730c52594f80fdf06e5da751aad9613767c8a7dbc12;
+  00010000000000000000000000000000
+       4ebb41c4aeee673f8a24dca03806b456d7f0371f59ad215d
+       e20e4d661c9411afca8208e71c2245954316b17d355cc87f;
+  00020000000000000000000000000000
+       1ece0d84de9d85f599c043e81ed0d0788b0300dc720806f1
+       8b58730dc35a5b8b679a38662163bbf61f4bcb963d67c0c9;
+  00040000000000000000000000000000
+       0acbe6c5eb0b944562a37976acdeaaa343d28c1023805af2
+       77ab5a554203d92b600fe57510c081be22d9a0474158fa0c;
+  00080000000000000000000000000000
+       41be3904653a1575e5b06c44aea5d2136df8f9ccd7f42897
+       84ddaa529a9e0c24bb4437fd7c59d126e9f3a2fd144747a8;
+  00100000000000000000000000000000
+       1f64e3968eecb4f75248981ee4afe469df2506d85373244e
+       c0e3387b78dc708656ce32cb56ba8f3a7481db57b2e2f31c;
+  00200000000000000000000000000000
+       4aa4faa759d8ae50e22eb0c8d9a35a5ac45d8c321e7945a8
+       f912da323759360ab2a17b8903a3995ba1fd286b4f5c0428;
+  00400000000000000000000000000000
+       ef444349c97db6ced680f42fb6c5be12b6093315d9735c99
+       a8e88259daf069ab83caf0827dd8a70aec60763343f1d5e8;
+  00800000000000000000000000000000
+       52d311d50f4b8dadb35e14061d24b77128f5fd8f1a4408cc
+       830b1649d46496e4e3379c6af09ef3a2db387234e20e0f8a;
+  00000100000000000000000000000000
+       e7bcd07378c8fa7412cdca4747b825586c1d1db42cb9e3f5
+       f646e68c39285ce45d564195ab947cef8f842e83a0039311;
+  00000200000000000000000000000000
+       2d6f4c9d74fa658286d89ac21a293b0dbfa23a8b5509d22f
+       ecab2eb6d811c3c5cbb7ca9697039c0183deba100bd857ef;
+  00000400000000000000000000000000
+       553847fabc37d17234bd17f7d9306530bf778143642aaf86
+       6b4c872d23f5e2055dd7b7dfb5e4b7e9e2ca030a4248d033;
+  00000800000000000000000000000000
+       940ab6a034bee50736899c4d635156aca5417be2643202a6
+       7518c4af96fa52e3c0b00b874d394c4aa633d0cba04ef54c;
+  00001000000000000000000000000000
+       fac2d9c5408abd20b4cb620b4e9ae56f94d5c4a1d5875dd1
+       cb766e2a037a343083229141d004ba100c4f33de8e064961;
+  00002000000000000000000000000000
+       b4e037145cfe062329702825eef3c0187602e7c81b196d01
+       f307dab2d4b0c4e95024e95bf869da3759038799142e7a4e;
+  00004000000000000000000000000000
+       faf4093cecf9b49b79ac867cb8eb254f4e6b1cdc0fa8d2e1
+       c5a7383e7e51e02872407a34099bffbd43e2369e5b3c4bfb;
+  00008000000000000000000000000000
+       13226b07eb7e44d65c4eac727e788fc246c71b7877150716
+       74cd36201eb1e07da6d7f7a922fb4cc9bb76e13b1f770fbe;
+  00000001000000000000000000000000
+       a4d115e01be2e296dc61104749f5cf13e1b0660b619901da
+       6cd992b789f2e6bcae1fc4c54e31983a91cfe80221065d45;
+  00000002000000000000000000000000
+       c177c0361498f3b8162b8a1e4791d393c90f9be62af73a0d
+       8fea60d9cc0b31580e42a55bf633d926458eab2269e284c3;
+  00000004000000000000000000000000
+       b3fa237d5af3b8b030559f59b22394b94d8b71fe7c499896
+       090181d182605dc6d04734312631193af9ba97a41e36cd6d;
+  00000008000000000000000000000000
+       d43a7d6e1c6e6bd70ddf057df51171968f135cc628c87aee
+       a83d729f48beaad53c4703edf669cc3b8172b1f3815826ea;
+  00000010000000000000000000000000
+       d4a801587858558d74174ec9bf5af46357cb6b509c1cd3c6
+       3c8d553aad2e9e9b57012b8b624864282605a202e770988b;
+  00000020000000000000000000000000
+       a244142ed94451165b1b284659dd09bf19522d8ede74fa50
+       56a4918a03a03e7522287f2697058a5a4568ee1044abb7a5;
+  00000040000000000000000000000000
+       256c7215a7a1f6277efd963ac44f273a67331722a35733a6
+       772bad0f5ba9b17a70db868fa6c94e894332da2be4188990;
+  00000080000000000000000000000000
+       0180a9b501ffa92c8d82f9a6841762c0a999f075374ba5ed
+       b2866da4615cd4dc433537c2946f8892b44f3bd0b2c4dd72;
+  00000000010000000000000000000000
+       74094fb2efc7ad295a4e59e6f3cc4bca98f9ca9426f1dc7d
+       66e1d8c5b64590a10887d4f30d593e21a988ccc2cb0c56f3;
+  00000000020000000000000000000000
+       e0f2350c0bc86af716d0e3a4a43f7226642e41247cc365a8
+       47a078702ce531d10d0ee151761fbba5e8b62354fa78b6f2;
+  00000000040000000000000000000000
+       422af1fef9c1b8c8a0ef3b62abb1318556ed6fc1f66a9d87
+       b334db883014ca79f7822e91203840185153bb845171cf62;
+  00000000080000000000000000000000
+       94112b3e064fbe4658252cd678a689e30989d9801f8026bc
+       9960c684f52a14396a807b1457b55a6e8805adbd2cad3ea7;
+  00000000100000000000000000000000
+       9cdaf684882ddd6dc44fa74b080f6a3b63fa4ddf2a8708f2
+       9640e06263fcdc7f42e8364b6832202026b715b1d604802b;
+  00000000200000000000000000000000
+       c138345c90c2823c192bb0a347baa310068951f512554d95
+       f0b31139a5e0d808349a5897341ceab6d1c92ad0db7efa56;
+  00000000400000000000000000000000
+       8ea80f74f49292759317b0b4a1bd488edc883616c04c8920
+       3e2a07a682bf608ec4f94faaac7049323435e17bdf8ce8bf;
+  00000000800000000000000000000000
+       d170aa41a6e50b8b2738de41f189cf9991eaade3dbd5dec5
+       4b0901022f4449e5fca714fb4a08524c0b33632a704ed726;
+  00000000000100000000000000000000
+       9a308261c52d829caacc1b70eb47049a598a4702e22aad0a
+       0bcd79778982f5797fb92d16d7e772e624a65e15dde0dcee;
+  00000000000200000000000000000000
+       40cff4c8c86429193aa94de96b2719a99f60cbca577980f5
+       47ed4c47df14c5a14290faf23855088bb0fd75d8f209f276;
+  00000000000400000000000000000000
+       ba4d0f077f721f3939f1389d44a86fcd7f2591b94c9e9080
+       adf066342c154cf5c2fb2609be3126b1bfa8098d8be8f1c4;
+  00000000000800000000000000000000
+       4c635236910df9d5d1a6ed65c7252a72fb20a716bb64d9b8
+       ee98a1c2c6a9c9590f626f4b7f685c8575da477a356d557b;
+  00000000001000000000000000000000
+       fd3fb55926f16ac3c458669f23a4647fb771ccaa49cafb4b
+       c3757d955b8944c8dfb62e77cf643f6d8b58261916aec7b6;
+  00000000002000000000000000000000
+       ab5289cafd68c2bd7facced12251962f7be2b30a99945c9f
+       92f2d77a9f0dd409bf737cda459d7d3dce6e407dba592858;
+  00000000004000000000000000000000
+       050c239f2157e5355525ffe4557e54b2c8838a68899707cf
+       c3317fdb7edf02d7b43ff293346977da2a22108748574302;
+  00000000008000000000000000000000
+       287c55a9636fd7123dd9851cf5c27c73f3f3a165a4b5ab31
+       ef8d185840b9f6f057792cecc2880366dbee7e5b56a38fd5;
+  00000000000001000000000000000000
+       cc76fb5b7e8316d4c74e1df3f913139e739d9f30e0e320b9
+       9dd58b054a33098f0228bc6b05712e9c7a50add7868a2f96;
+  00000000000002000000000000000000
+       aa21dae2afdb95ad368f9c1babf2769407cb6d7975d41257
+       3591625006cb3c2bda175be3f715a6ed63d59261a3182f5d;
+  00000000000004000000000000000000
+       8cc0d35698def74ded8c1d8222b67e543af62f9627978c80
+       4829e5802b83b5614b58d68305aa94f06aaf37a0c0c4ed5e;
+  00000000000008000000000000000000
+       da702b5e9b3c7ce13681b3e1a38ae1babd06a0ba46612f63
+       9d162f4850b8b4e4b1a01213138c1f22c863e32c12539a87;
+  00000000000010000000000000000000
+       486599f86813923735d14c4308f142eb8a57086a8507255b
+       40b857e962dfe1f9d1dd46b69ab4f5ff7faf34b407623c3c;
+  00000000000020000000000000000000
+       82f7da5f0379e2cb4e3b58a03ca3de256b282dce73285090
+       1bf3d369ccd413ad0f95a1928715fb8ed55aeb2e9d93f2cc;
+  00000000000040000000000000000000
+       3a2ccdf7ca733ef507a485ab20c62cf6fb13cd1281008b49
+       335d30e28232b4bc1dff9de3a4a9faebd4b5accc3cd2eac6;
+  00000000000080000000000000000000
+       5129bfb136556242d24c0a69d1b471e39bef4502dcc6ab63
+       0e7f709d8e65ecdeccf0f8f51e1eadd4deb33218ca96133d;
+  00000000000000010000000000000000
+       bb55b9b172f5102a71d27564fb441ad75ef525e3c7b95569
+       2fe4ac5360626eff86d72d472cff3428f0891f2e708c1fc0;
+  00000000000000020000000000000000
+       29e121d9d060b4cb1a8b985514642d2ae657d1bee74622af
+       330a0002c3bb7bdd1141085283a2390d50b992667e9c7a2e;
+  00000000000000040000000000000000
+       1eab5cf16eaed7787fdca7a4a13f02e89e838e28fee07574
+       f351daecc945e7f4fb609f83b30f4a5f96d8d453770235a1;
+  00000000000000080000000000000000
+       1d1c207423b291e4faa33ba5511d99fa0a1d6217dfb01503
+       f8d4232565a6ec23973b2814fe0d4b0d795df4afb24646bc;
+  00000000000000100000000000000000
+       428cd893c5c48447e67a5a78ced4e75b9424d26162396397
+       df261879c0edbb80b244a8f95c319bd2f09db2fd24e46664;
+  00000000000000200000000000000000
+       d559589331a70000a25b0bdcc69edfadacca1a42e26858c8
+       408b5610b79984e6b95c48b6b370c670b054a7f4218bf388;
+  00000000000000400000000000000000
+       4b3ae76b7fd6acc18a44eb946daa6bb70d58086904f61243
+       926965c763cbb68699d3e77aa76acebff7be816b27cdae87;
+  00000000000000800000000000000000
+       c5fb0e875cc5f0d3b8e3056be3c1fef7cb653c2d357de33f
+       acad4ba4b859549071b491f07e7f90d50ff1e9aaf9d4c566;
+  00000000000000000100000000000000
+       50f32b167426251526e8f63bab0d615e016e03058902fe4f
+       e899b8984e8f6e7203c364181d89439c3bac8e60914d5644;
+  00000000000000000200000000000000
+       54418fd49d84a2e725f99459c10454af6e408b945e108275
+       cbda143f3ee4dab705f1a91bc941054ffd0ad144d50368b7;
+  00000000000000000400000000000000
+       6117166e773302a1b3d21e869407c18a13655033d5ca007b
+       bbb97e4178dbe65c25ec8002b53ef7932c4ae1cfb947918c;
+  00000000000000000800000000000000
+       f89ddf74283be908896c62bc18feaa8d305e9ae4278233ce
+       2089a78434cf69651c06cf00dbe89bb6b446e4f3db6ce8e5;
+  00000000000000001000000000000000
+       03af049da485a4b4ddb468bf3261c38aad2a71c96f990a22
+       46146187446746bbf8dcc71cb5c583506244c1468a015144;
+  00000000000000002000000000000000
+       aa70df415bd87335969b4fb3c363529061a3da319ef2d890
+       a63e67308c4b7f2b33f279bee222a9869446c8c0c250cf06;
+  00000000000000004000000000000000
+       dad7d93b5a7bff63476de8b3d20190a29f28eecc88495d3d
+       9839a4942c8f69283e91eca22ffd198a4a79e68ec07e578f;
+  00000000000000008000000000000000
+       59d603166b649e9be642bd3ccbc03f7d9abb3e89aaf0f1c6
+       8686e6909dcd9f787f9fa180a46d1d433bf2721a238faab1;
+  00000000000000000001000000000000
+       7bb6311899138ae33f095f79487a8c1ff8efc0a1ba1c0844
+       69e02af433d3d1234a315658f80f6dbad8339e77b894a3bf;
+  00000000000000000002000000000000
+       27112725333fed86f93b09ac882e54cc2c625de0970a56c0
+       d840315b675f117468782d16dd143961e972a62733ab5b12;
+  00000000000000000004000000000000
+       798b2230146a75a46854e26ed0cb07419e79ac176059f223
+       f543a2dffe039126eacbb3c5253d3e0656df5886aa7dc934;
+  00000000000000000008000000000000
+       fdf295ab966e035dc8d9c6a7d378aa1fed50f85e09afc9fd
+       1e353b843bfdfb8e04196ebc2a2fba0e6ac7651aec3034a8;
+  00000000000000000010000000000000
+       4b9bb076f6e3b227ff27210398252df65e9e2fe255b13992
+       e42c1d4b04422a38c1dc7a4bc241ee1f4b9aa5a2aa42047e;
+  00000000000000000020000000000000
+       f45fa1b841562f0d20769390f1dafd13324bf86216565f5e
+       7e96c285bffe97be47ea277140b179e92daa6a13647905b4;
+  00000000000000000040000000000000
+       de745e5baa6ac8a095898d562c187de0064d23c9b748a115
+       10cf435b1841a119ef753a471f57261af2d137b2eef59c81;
+  00000000000000000080000000000000
+       ca3c51b2670418b4ec09ffce8f626bbe891b266446f89853
+       fb5c6a49a40e79c468ae275331230e37f5e47c3a10159d58;
+  00000000000000000000010000000000
+       0a9529d7ca30fca5081c364376c766fa5cb0a488bff9f638
+       149db4dddd0c11aef1e7ffe76286351b2212a17771bb3bba;
+  00000000000000000000020000000000
+       ac80ed034867425e0482cd34ee6666ff8ed09cad5901c0c9
+       3a4cc4d2888134ad2d77ef262a222c79b66d93226209e6ec;
+  00000000000000000000040000000000
+       c01846df500d6d9da7755fee30847e2b6e5ef2af29fb768d
+       234eee5672c9964bfaeff3d7612ad7796d52630dc86bca96;
+  00000000000000000000080000000000
+       c15f53accfc0d88ab029139dd65019fa6003b7afe2bd4e54
+       a0d7bfcdeb22254d8ea42219368656569742324922a9ee6d;
+  00000000000000000000100000000000
+       ff213f49aee42eac2aa72d7a29e7ab41aa7f586012e9f97f
+       f17c2e5990d08495dc94764f8e85c51851a4f413b581584c;
+  00000000000000000000200000000000
+       25cae6c9325a23f04d3f14e8c2c2d2e7cf47f4245a813568
+       e2f0783438ad7bd9a4f84b1b3a895c05714c514dac819bb1;
+  00000000000000000000400000000000
+       22870931c60c3752f5eb3408f4f4f311ecc94d45746334b3
+       6b62d15ad6d4d9a0bcf4f718fa02fcd154922ae0eabb53ba;
+  00000000000000000000800000000000
+       c08edd588aefb0162ed5a83866b4125c4763187fa2c3a0ec
+       06c5641d79eb161bac7db67e4563298fb255ba9d19795081;
+  00000000000000000000000100000000
+       a27d1bf8dd539451b9c1be660a658551358e0d5e24afc3b9
+       7676d1200c042937af0775b682b8a079e537e09ed0aa4683;
+  00000000000000000000000200000000
+       985703a552bf2ef0f0b13cdfdcea1b5f0e8aa26dd0a2df73
+       7c2f3cd5a37195e38378625ba3dcc0331b5f541a8ab99782;
+  00000000000000000000000400000000
+       6ec0cf3e2eebe473928c8816aacafa30697d2f1886216355
+       74cd8be145dae8057f60216a73c5facedb9f4e82e0bd65cb;
+  00000000000000000000000800000000
+       616f098bebcbf2ed4b706c97bf2515c3b0816deb15de4059
+       d15e35c97769885b1a3d35e8e1fe85b693ec2c8744417bfa;
+  00000000000000000000001000000000
+       e8dd7dbcf07d102c7eaaade8d9024829251e934d0da9d7aa
+       e3999556264744496ad4d86d445457888419bbe8871d7b4d;
+  00000000000000000000002000000000
+       1fa50547af8d9f2d55028008536f066753c17fc8e2d44057
+       4acb79c912d344fae3419ef5700aa6a3d883184f34e5d59e;
+  00000000000000000000004000000000
+       92eeebbe20902b4c0a5f890399c32c243e89d8ed91332e3e
+       e46625fbad57eb9c626e2125cf248e269332527015dcd3e3;
+  00000000000000000000008000000000
+       cdbf15c739d3fc86f9420eedf6a0956502a4a733217102f4
+       81c056e8176355317af92ba38e40fd5c26f907b285f840ea;
+  00000000000000000000000001000000
+       2d349f3bd80ff88f4eee644682b62fd1eb719b9c81b816f6
+       9d44dd091630b3772cb94b8c652a15df0474881371f0b04e;
+  00000000000000000000000002000000
+       6c53dac01503d4ea8e2da6e54403fd20c1f5a1f967732cde
+       4c17e967bb54e474f3e323d4f0e18ce40e44ea61c2338cd4;
+  00000000000000000000000004000000
+       1991e580e4801fc43a1aaef646626306f5b86f93bc114393
+       7237846ab5e292d29a7f115d0b10530720a1d5ea7c5aedf2;
+  00000000000000000000000008000000
+       89c2a0916aaf1f36b54c0ac5f74a2cf7ae2d151e9ba39b22
+       fdb640c3275ac44815c50f2d872e28060501598e7e9947ea;
+  00000000000000000000000010000000
+       5c052c84dea984ffd5703103883523da2208e3bfa1e06649
+       5e97c772783c94a50d288284afa25295f877e5c29d174529;
+  00000000000000000000000020000000
+       89dd0a9f15abb0e943d4bd0eb37e9280cb046c88999a5f14
+       b8979c6cd28d05d20e4b3ea5ef472ae7d62a2470014f6e7c;
+  00000000000000000000000040000000
+       fe7ded8a12dcd5bae797cc30cd0596052ef5a56c0924f199
+       30272a00835e69223739d31e66a87ee9810c3181cafa4c5a;
+  00000000000000000000000080000000
+       5a856f3220f42525eb711f1895eb09403fddbebfff60851a
+       ac07c9e6190701a516d89034e9af0229a2ea8bd42ec699aa;
+  00000000000000000000000000010000
+       ae67448d9fc57e487a4bab448208035dc06ffae8b5e9e8f4
+       693ce9e015e6f445bab0613cf858e152baf438c76bea9239;
+  00000000000000000000000000020000
+       349b4b3daff60002fead10f7f11f1ba69a7142c2256214a3
+       b24cef9c0a98b607339f148be6af519555fdb8d59237e06f;
+  00000000000000000000000000040000
+       0d3724d48fbd0b053b9594042107bd4b91bdcd98a6fa14f9
+       ac041956dca2caab9d5e40d344a5ff2e02e48cc638be7058;
+  00000000000000000000000000080000
+       29bb7572498bf205d1939c754ba87e3a4f1a2c866bff4377
+       c2b627375f0020f1e01df599ccd0c9afef8f72f2fc8c432c;
+  00000000000000000000000000100000
+       79898e51f8e2ff9303d2eaf1c113d4be2d7fd73c4f29c1d4
+       02ff562fdf5ba2e325a7daa8e77485d261bf798a70562492;
+  00000000000000000000000000200000
+       91ab2704db9e0cb20236885aa1812677767f29887a3825f9
+       945703d5a2ed4c7fbc46641a86b1c4ae52e2b6ae86370b7e;
+  00000000000000000000000000400000
+       d15999107c2747d3df7e21240b729cafaf32e45ff2e2eb94
+       0621fbacd6f9e17748a251d9ce0f6279c0b4f76de76ca07a;
+  00000000000000000000000000800000
+       3022e256e1700e1b38860e08860de7ee7011a471744c4a28
+       5d0cea63850c605346b1bbde1277bd04e9a7ea67dcb95a0c;
+  00000000000000000000000000000100
+       c41bad6d44d9b3ddb77289d0bc75728ea32d21174989429d
+       daf7d221677be4c01c524941b43a6583b736f59485c37f9e;
+  00000000000000000000000000000200
+       c244e345c8771efc91cf85737fbbe0e7f9fe1ad53727bda8
+       0e45be68828f5dbe2cec1eb6631dd455f9f742ec1c6d5734;
+  00000000000000000000000000000400
+       ea91f3b274796e1a463d3263acf96d8192c927d1fa66b022
+       53a6eb98500423e77e4a17fe1e936500a3411d9d194ee941;
+  00000000000000000000000000000800
+       b955548cb651e31e94102068eccd141d55333cbb3e34946d
+       07af2dbc8c097871dd3ceabb8645a164f445226eac474927;
+  00000000000000000000000000001000
+       7f7864177e868e5e4a07a99252eadd43b0529bf5b9b05013
+       2746566baca5f019ff0eea70d3eb82278398c9e9926c3883;
+  00000000000000000000000000002000
+       55cafc87e6ce1e903805d23153711dc8c7e8d269e19be3eb
+       7946dffc2d8ab6a40a397f81eedb2568c6df9f0b06391d82;
+  00000000000000000000000000004000
+       95bd56e986ab583193786c37328d4dde20e62b0d39c19b9c
+       1f261cbca6aa0875c3b610990236178251d2865b5033ea5f;
+  00000000000000000000000000008000
+       21b185e2c61a750a4dbc47d1af6cf3b47f56ceb362d785b5
+       ce8b0dd60ba2d9b6e2582aa6b262cdc674d96848a67641fe;
+  00000000000000000000000000000001
+       e7d5e316da3127f89538a3b2d24e5f7e8006557dcb03b5e5
+       d41ee11b4115c2e2155c0bc35b31d8c38e2282d17ef5ab4b;
+  00000000000000000000000000000002
+       dc4a61888202b8e52a97af475726e545372aa67912ca8cb1
+       c4c595fbf14bd2e4f55acff059c17c243ebbb6e979713bd0;
+  00000000000000000000000000000004
+       c4306af68bbe3af8b223151aa99c94488c8107fbfdd3b680
+       d15a72460ab5a62385c5db730fce1ddd02ca531d250b114d;
+  00000000000000000000000000000008
+       5c33a8ad6ca05fc247427b898126e4ab9fd05ed334e14c68
+       8f887594d5f3a14aba879167d605d2ca84abd2aa60ca85dc;
+  00000000000000000000000000000010
+       d8abe4455e58859d84b0594f2804f77f15ad38887e29d705
+       407f2f3751880efd85de8ba315f222712df2674f20c9baa4;
+  00000000000000000000000000000020
+       20b5cc79b89b41aaef175caf0975d6d8f2be320075b8cfbc
+       6b366acae30d75bf715a67703cf61e349229015e3587ec05;
+  00000000000000000000000000000040
+       3cb706cb93bc33a1fe6b1a68c9c902d187b6c57abee350dc
+       a1d213280eb276238acf137f2ef7b15216b571f42c9dce58;
+  00000000000000000000000000000080
+       7654351a040718ddd3d7fb2cd9af802c17e7db0e7a6cfaf5
+       ee3058937fc02624cc4ec6d19a7c8d3a655c6e8fc8c12622;
+  0100000000000000000000000000000000000000
+       d0b1960db19a85a7a77e46229b9f985139829c3aa120c3ae
+       c642be9d84e9f449586f6329a6d0783aafc5b9a71d5fdfcf;
+  0200000000000000000000000000000000000000
+       fbed0648eebac5ad6af9c89f04c759f5b3caaaf2fc77b33a
+       e2f666ffea4b816c59587f2cc5c4007a6e797c66c20d454d;
+  0400000000000000000000000000000000000000
+       c5310bb95af7c9a72af7fe845bcfc5944f98606f21d7d414
+       91ddc7e0d5626d0929262a339e488e7b80b59c748b99d96d;
+  0800000000000000000000000000000000000000
+       2c22bb4931178c38b575e8a697e774f4b6cc49163b4fc863
+       a29c3dfc98b1061718a8b858b582badd3565354c7dfa11e4;
+  1000000000000000000000000000000000000000
+       004b667ecd93b6cf8120b4d13f63cc8676f25669cfd54198
+       e61ac997edc61a530e21d3fa92597765bf8088eeb044378b;
+  2000000000000000000000000000000000000000
+       cac87cd9c6a8336a855d7fa479a41348615befe661bccd5f
+       3c4de80c174170a85b453b0245b40090c62d7c733e691cd3;
+  4000000000000000000000000000000000000000
+       271170c80822719aa7abc308af71bff47220c9c0e1d0af10
+       6adc1a35f39600a3ded1dfa8db6f54d06975f3df17410963;
+  8000000000000000000000000000000000000000
+       c799a3e1f803ebf7674e82af4e130a1edb80fff06b36913e
+       5255a39bc0b3903213e8af99c129481a1a91546435a0b9f4;
+  0001000000000000000000000000000000000000
+       7f5dd7178fc11e33e75039cd3b31c3ba715669a2d97fd67d
+       ea9f8cfdfbf79ffc004244db67a186188761b94dcb680ede;
+  0002000000000000000000000000000000000000
+       890342e3bab9d5c12af0eb1147adf72ced3c858a36666765
+       fb317078fc5a6f72cd05ed99754244c1d832bce05b495ce9;
+  0004000000000000000000000000000000000000
+       4dc89624333568e75ad013d4777641293110c8293a4564eb
+       5c215202bce7ac289462ee973b208517a100effc3f045037;
+  0008000000000000000000000000000000000000
+       eb39a4f0a41388595563ca25220d2ba33e8827e6886dee50
+       6c3cbd45e11b03f217232c6e8f412b2d45626fcbecbbd046;
+  0010000000000000000000000000000000000000
+       c3768a3a08cde5986f31f19adeb5637c2517e4b793e75c8e
+       e16c0fd6a2460933f758b736979efb34a9c35df0b58c290c;
+  0020000000000000000000000000000000000000
+       c4ad863e851697c80ed0607192c54debcf7c66fa38c4a4af
+       7907d69fb955ab18bf7c198454c6d8d15e4226b08e322ad6;
+  0040000000000000000000000000000000000000
+       d2090fd250ba63f3a708140e11ef64f8afcff45dc70cef3f
+       dd4c891a83c86dd31eb4973dd3948a94d1fbbe6f03fc26c6;
+  0080000000000000000000000000000000000000
+       110a9f65db98d165f6d71f8350ab602f4b2039e162744741
+       54d10329bfcb29cd51fbcabda51e28a5d2009694353a43f6;
+  0000010000000000000000000000000000000000
+       a8c1ba8a548e6f3ed996445f62845dcc078495a6cf9739cc
+       6a2fe74b53328830ba707a56c80935b74dec32a312c5f6f2;
+  0000020000000000000000000000000000000000
+       94c0028f97319ac431e83414b6c660939b11047f310854b7
+       46a1a901558c6bbb0f8be8662095454d9decbcfa416557da;
+  0000040000000000000000000000000000000000
+       cb4c1feaab04ab5a6bd70259afafd3bee103ec9f90a5150a
+       270e073e9de7d0f5c887b62093e705b6457d0eb070b3c68b;
+  0000080000000000000000000000000000000000
+       b9d1993a3ea9b0f635d37edcb4c5ce7bdaccf5be5cb7bf02
+       8400b07b3cb30c941e468274b10c77ba3d853c418c2efa15;
+  0000100000000000000000000000000000000000
+       b4ab6fb85ee6b43cf76adc45644eecee472abcdad771604d
+       97133160d397d761ded692085318c15285392e4887563703;
+  0000200000000000000000000000000000000000
+       7367a4de601e0bf5244fb989a03fc80ed93d3141424b9477
+       c3085f4757b45152825ea9197538a5797bb15b374231992b;
+  0000400000000000000000000000000000000000
+       8e97f0e67b27ace30dc30a4ae45670c1378dc2b5bbe12400
+       c9a494ceb0d7e51eefc737a9ca0e8af490be4e6a5ed1ce6b;
+  0000800000000000000000000000000000000000
+       2713deee079aabbabc432a62e260b8d9291e98595dc86623
+       e6ef22a2af39e8cc4415dcf216b7a998b98a7d240e2c3e07;
+  0000000100000000000000000000000000000000
+       3dfd7ba2b48e4ffd7c0885552dbab3133c2757683fd817a9
+       7e98b7592893cf2253c1b393e5dacbb233dc803589421eaf;
+  0000000200000000000000000000000000000000
+       2ea177197993e7c293ce7a59bd3deef17485c206dd19195d
+       f1758101cddd487e37c8e5b179cc2d90f15adaa047c61a90;
+  0000000400000000000000000000000000000000
+       8fb6036b6580c04c433fb07d0760fef91bba85272739c0c0
+       11c2bc53cfc7fde6fdccefe4f20dba513c465b092194a3a4;
+  0000000800000000000000000000000000000000
+       703784863ff9e7e3c09fa9bf128ea31dbd2b8b4f5cb99e36
+       936d221d1f0c14b6f01cb3028873895e5b24d16f0031ab8f;
+  0000001000000000000000000000000000000000
+       5a69ea7cc7fa7302fcbd1ac2d07dc7c6621ee0aff1d018a4
+       41c2343b468dcccc3ccfda966cc9ba78d8d57083ae27f29a;
+  0000002000000000000000000000000000000000
+       c89944b86c5edf216c8a8f8e58eb307bd311e11e66ee4ebe
+       b38dc49125243cc11781df4559f9d84640a7338403236c85;
+  0000004000000000000000000000000000000000
+       3c669450967f16dda82835eaa8cd3877fa8de68ddd5c59b1
+       278e188e35f3c26eb8bff5c03a5b266f0f51aaa4a603081d;
+  0000008000000000000000000000000000000000
+       9823a5e5bdb3ca2edc47618be7ba9ca742d5f0d2198047d3
+       21a333410512108c86dc7950ab1abe701a9e3d856e6d9269;
+  0000000001000000000000000000000000000000
+       981fa376decb5e95a92b842e2dee03c562d8ebde0c8d6cc6
+       370eb81d50ef15a799ca481521a24966d033da29486007cd;
+  0000000002000000000000000000000000000000
+       44b698fa4f4f6bf89fc66a23abb6145d9713908bb03705d5
+       fe70a9986d13fbf73500352f742708a29eba0f80d324843d;
+  0000000004000000000000000000000000000000
+       fee1b9fad13700816390e29880a83233e7b90cf183cd3527
+       0c8ab7fceeeb439397c095de04ae56eb867499360c6033ab;
+  0000000008000000000000000000000000000000
+       31defe3570475738ce89f436ab737800c6a59fce561372b7
+       d78ea1624b5ed5cce49a46ead9237bbb48b90327db11c74f;
+  0000000010000000000000000000000000000000
+       652a17e6b330a95d8237cfa2356e47c295585ba7666fd7f4
+       f85f595cc857f48461b889a0ca7f6245866e45946f5c8522;
+  0000000020000000000000000000000000000000
+       a658d408b3856df66df0e5026173ae70627a649b836c5011
+       38ccb2e915fdfa02fdc9b19a8fa446b538559c6d74af7f97;
+  0000000040000000000000000000000000000000
+       84ce7b3fab5d81b85e00681ed7b2ea130c53e405233408f6
+       92d8342bebfc338cec2bb424174d7951ce2ad5407211a53a;
+  0000000080000000000000000000000000000000
+       17a24739d92ed5f4f09f886a435af20a3f786bceeb86293c
+       f51ef9e9d4841d25699f1199bf1b66d3f54e1e1b91e91482;
+  0000000000010000000000000000000000000000
+       eaa616b384519b85852137c3f4ee61b6b48a2eba21d566d9
+       9e58a0b7cb6d0872f9882cb52abf91ccd7978367ff6228e9;
+  0000000000020000000000000000000000000000
+       ebd576de80da794a234a8be925c69e88bede65f64d7225bb
+       aede5cc115eff89d20b3ecde8d4e03a7935d368c20c837c4;
+  0000000000040000000000000000000000000000
+       4090b3588edef6e689399495eea36b33fb23104527e353ed
+       5295d7a3f7ec90d084282a1a0eb82d6cff90ac2a25f6d3db;
+  0000000000080000000000000000000000000000
+       947b834b466d2f3d92ef9512c3e450f0b578e9ac3be212e7
+       eff671d27f5e2af474962fa0f66b63276b24e484c66be17b;
+  0000000000100000000000000000000000000000
+       e611b6a6801fdb802ba7499c39a966bbd8b8410f79ddfada
+       357c82dda476be8ad41b40e2269ad52baa9d806c2143f84c;
+  0000000000200000000000000000000000000000
+       86e67d84b15f9f40a0fff739679044f91b0ed0376a1095ad
+       d72da9a06dc17ce4fcb24d51b804262513573c799a57b130;
+  0000000000400000000000000000000000000000
+       c19000056d359565e51b7a3de313c57ff2bb35d76393acc4
+       e5bd4cbffd461144135051d8555128786a9e106d063a6993;
+  0000000000800000000000000000000000000000
+       2570f1f193ad3a0d2314158dd137347dd99690a6b886bc5c
+       0146f5cc2c6b14652e8aa52d1c4733ba5e367a57109c5bf4;
+  0000000000000100000000000000000000000000
+       7526b9f746fbf4396e5663ba52f5bfa682b0501fbd36b5bc
+       107ae0fa5444fec8cc7d0f01eafa3eb0fffd7c34ac6869bd;
+  0000000000000200000000000000000000000000
+       abbd3dbd4a1864fc20f7226f563a7f5098ff273cc8bf6576
+       fd12b3b1749e8469a8ec879560b583e2dd88784db4c25879;
+  0000000000000400000000000000000000000000
+       e281a5fd1b6a7aaeef32e40482d6291aa697cffa21dc27a9
+       0cef0579d12fdce29f96f135be671012502db1f95a55f8f0;
+  0000000000000800000000000000000000000000
+       abff457652774b07fdc99738bac8ec162a01b73f8a71b126
+       970ff7ab84f483c9f1e73567d7f38163363b14850fad8834;
+  0000000000001000000000000000000000000000
+       1d75fbd8451f22a0b0a4a9c62ac6a5716511600bc76e8378
+       6be81dfd6a58e989c4a7d5f1f8fa22f36b079894564434e8;
+  0000000000002000000000000000000000000000
+       362b88b73e2cd980d5d78d3b7c591fa0b1e70a9ed5eba7a5
+       7f3c71fecac4105cee4c489c01f975a232402c4635b515fa;
+  0000000000004000000000000000000000000000
+       a76d84d4eeb86444c3a948c0a798b9dd2778a96e30e61aba
+       992557baa0a7dd9a06007681153f98f02c19d6de76d898fd;
+  0000000000008000000000000000000000000000
+       667c962b1ba89807b086fa168e80aeee355e825176e212eb
+       785d4ed06bcdb3f0fd2cb716ee9a1a3c462fc9b51e305082;
+  0000000000000001000000000000000000000000
+       c0ce233a95f06506ecc20c9d94ec5c6c757b4c5b0727d492
+       157a5a7d1e8e91495bba18085d26338a3b1463d4e9db858e;
+  0000000000000002000000000000000000000000
+       85b69eb5d5b732a8bb0b1a9b3693116f983675785aedff22
+       c6fea81b9347c9e7567fbad82d5b8912bbb76dba8f4a29d8;
+  0000000000000004000000000000000000000000
+       2795aa156ddfa00c39642ab05e286c964ed00633bd60c5f6
+       b7aedfef19724e4782a10536428547040ff7f59c8767f2d3;
+  0000000000000008000000000000000000000000
+       86a2b6fb19ca72c2958a6569aaabc0d7d1f2d7dcd2b5b61e
+       39130045632a3ee79eca91f2f29056c887192ce4436614ad;
+  0000000000000010000000000000000000000000
+       38a0281fc43a1c8719f255c575a9b1dea32a4c81e2d4a934
+       24a434c2d65df7b788bf3bf0664a22928ce07df667017502;
+  0000000000000020000000000000000000000000
+       8c8bd4434261667e10c6e5527640e4be2fd50112c27604a4
+       95c7dc7d90348e480db9cef4b640dbc62f4bd76714cbdca5;
+  0000000000000040000000000000000000000000
+       7a20a0e0bdc0ce07559e7e247fe27b2e57a3a2bfd1ac0964
+       ce680c2c69f4951a45434e164644c36dec6abb246bd4f1b9;
+  0000000000000080000000000000000000000000
+       cbf7402991a61ead1dfa657b8688ec6b1d3755f1c12d975c
+       5bc02ef2adf14ec62187882da764fb4bcd8837eaa3f8014c;
+  0000000000000000010000000000000000000000
+       e4218125dc4a288d9bcb43710ec3029f0a5d631dfe401b47
+       ae21a4b216e530a6ab6c14c8d1c728db79109ec58cf93a0f;
+  0000000000000000020000000000000000000000
+       1c7038534568125aac9c0b8f3cf3df6b5c409f47d6cf7a36
+       5b87e5ab0f97669d705271c435c4e070712bd16f2c5d2e68;
+  0000000000000000040000000000000000000000
+       10d92270537442d4b847b42107047bc05239ef1ca981e89a
+       931bc9341a445caea1a5088b2b4121e8f8ef085a86075715;
+  0000000000000000080000000000000000000000
+       cb5438433b829ea6a99da8216785cf60b99ceb0923b9571f
+       f239aad41f8d994e8019211e64520780dea454282a625568;
+  0000000000000000100000000000000000000000
+       720dd5511ad848d9c25861488223d168fe72bcb22918fda2
+       c39891cba3b1e61e71101f3dfb2e72b1bed9866050dcc11a;
+  0000000000000000200000000000000000000000
+       f0b450e144ae3ca96a39f8ec440bd9cd20bb77deda9307e6
+       0da749458faef5ceb6192c90857a7aa5bd010fdc57799dfb;
+  0000000000000000400000000000000000000000
+       01e54bdceb03d02c43f7a24495c462287bdc2bd34ea16e0c
+       89cba811c829d32dc1bd8e3302c13415dc9676975cb8ea60;
+  0000000000000000800000000000000000000000
+       47207ea139f08fc11911585ac7b449116552db41f111c437
+       798c17318213280bdc778c2e761913983673079ef8d74230;
+  0000000000000000000100000000000000000000
+       bddc51901a7f6556334147d54051bb50ddfc42b4ea97d1d0
+       07c366e28a2cca1cf218b56e12277e18c7ddc698f2ac48ec;
+  0000000000000000000200000000000000000000
+       c2e65edfbb87317b24d411449ed48f323b12ccc1d5a5b7ff
+       fd99a7ce5d3e82b466e1b5396a0fac675678d17237b6d52b;
+  0000000000000000000400000000000000000000
+       30a8d0ef4c28908b2f18b2bb9848eae86269ac525798ae76
+       c36b40691fb3860ed243d7c4ca22dbe6300b84dfc91f541a;
+  0000000000000000000800000000000000000000
+       d2bfc99db253d16a9b3da4c77b4d8ae6ce5a82388ad113c2
+       5a005838a2a9713b8384cbb052ff742664f69a24260a03d4;
+  0000000000000000001000000000000000000000
+       2a916a4edd73e4dca0a529a08b8f9d29e437edaa9ea50bb0
+       bc202d61c79a55eed0cc2489c4ba4c7b5bdaccf3e6404dba;
+  0000000000000000002000000000000000000000
+       bf7879a48b750f7b9392746617c768581f3b21b231ce81e3
+       67560a5ac0f6d75e0b9e0c81e006d685923d80bdfc75c064;
+  0000000000000000004000000000000000000000
+       fd436ed32f95d1682008a0faff041f4793f67fadbef3645d
+       ad24e531f725780b4e2a33c01e1cab0c278bcb6f40edc186;
+  0000000000000000008000000000000000000000
+       524a9d2ffc5a0261bb2db2158632b886966ac2935c05c0d8
+       e9615c9cede6feaf6877611d633c2454d3acdde2ae2ceb4c;
+  0000000000000000000001000000000000000000
+       a6a9f7b07ba8db6b135bddcebf9f137b46c21366c742b3c8
+       2f54bbdf8a289de06c20837df3752765970d582f7cfbb5ed;
+  0000000000000000000002000000000000000000
+       af9c61ac592907f8526a96bb7b6fb146c5a069aee0775b07
+       c79a6ccbc8d009fc3358646fee5236fe6b739f02f2bb5a86;
+  0000000000000000000004000000000000000000
+       0ac8672af776f5e1ca0fe859501d3676b5358f9b22f856e8
+       f113bbcafb23ccc325b906522b4058e6cb26fcf24abf6658;
+  0000000000000000000008000000000000000000
+       498b0116b3767b651da3b7d4ec2d513305d1260826d3c166
+       862fd18cd2fa16ae249b66066db3cb871fb1571678bfc82b;
+  0000000000000000000010000000000000000000
+       bdc25d6e937f2e889fd774cab71fc86b2898652c44406193
+       e48d25b9e80fe5bee1fa7e6480c9f4502fd0d5e1534f7748;
+  0000000000000000000020000000000000000000
+       978a52ba33b411f1dd33ccb5f9fa7978014ff0877a8ae115
+       9710fffcc51af2e428f5a4da72ab1fd721be7ad3aaeef40a;
+  0000000000000000000040000000000000000000
+       a79c6dc139e5d91b27102f5fa0f1b8e6482fa96fecb021dd
+       15605d2943c8c9d182208e4db05075e132e451086a9b609a;
+  0000000000000000000080000000000000000000
+       321eac9f621e2ac12cbe8b5d5d1a75fc03f6c16371374934
+       548803f109cf611d2e7ec0e87098e27b2c149194ed832352;
+  0000000000000000000000010000000000000000
+       50117692ce6e19e23d553a4266cc3458f8b05e02c7dec8c9
+       6c83e70eebb0018f4d6e229404e39688bd07666f6733b560;
+  0000000000000000000000020000000000000000
+       ff480a631e43dfdab88f31f20699a113d7a6ff04d8f33bab
+       a1485a58f6d8c01604dadfda7d03d7717a8dd2c2d20a074e;
+  0000000000000000000000040000000000000000
+       23e5ca641b9b76fee53eb3f8783a24030dccfdacefc8ef29
+       d4a1f481e845a6025b3bc9901a003e2a3b4a6ea49e8ebdbf;
+  0000000000000000000000080000000000000000
+       e06841bfb58278e02eef5c29cf5d05c00274e18bb34d967b
+       70097b468635250585a96b9d81f1d54cab338095c33b954a;
+  0000000000000000000000100000000000000000
+       853d124cdc7b138c9b17798a4f1aaa343bc179c7aebfbaa9
+       59b5ca04ffb3d7277c0e0505e8be581641f233e7824d5e11;
+  0000000000000000000000200000000000000000
+       5998176bd90c122ed78911aa5948a5ad2a07df42cc41e967
+       bf577dc495b1f12096a3c1503d1c3a1263895dfc9669a2dd;
+  0000000000000000000000400000000000000000
+       d11f16da1b85b6b7f91fd0c4e24122c9169b45fcc0f630f2
+       03d6401fd083a0700a06a243c8cee99c0966e61230c70901;
+  0000000000000000000000800000000000000000
+       24d65de955a156e8253055f73589da884636a0c5058bf6b4
+       e89aa9e074432b437f15b56f6d38a7fcb24cbb208337dd01;
+  0000000000000000000000000100000000000000
+       4b93290373c2747ab475d7f4992477727b21391f0cb42739
+       959d181d009c0d0898a694b8d850647d76961f611682ea7c;
+  0000000000000000000000000200000000000000
+       93fff47d6977a99536ab313546ba940048841fba7a5fd9eb
+       f8769c05212e6d6d4093fbd80ea4559513b3d18f62ed698c;
+  0000000000000000000000000400000000000000
+       c8070ba52cb08c0f814b025d10071efaa91babd0a3a8a1bd
+       fa1c2ca6ecc071ecb923ccadc0f69acb701daef5f56f1936;
+  0000000000000000000000000800000000000000
+       0a3ce83ede05ef4dc7095fa9234e419fc31acf8696e9cb1a
+       b6fdefc344f34cfff5b2e2e4afa00f426607f4ec1f727eff;
+  0000000000000000000000001000000000000000
+       4dc5c361823d632dcc5813096d9e0ec1e0f797d303d75e7a
+       f156ae67015b18cb6ecda9e03c6558a67b89834a175e5e77;
+  0000000000000000000000002000000000000000
+       ab85aa11008c58f59b58019794a2b480cf51aade35a2d269
+       9c2821ffb2e3dc84b9608d607133e4b34e35643de130442e;
+  0000000000000000000000004000000000000000
+       87dc8d3de6852d06a9712bd570873c1620800ffd01e35b17
+       0fbe6f80f9306e00330a42a9d7e57cc68c0d992b70d9e982;
+  0000000000000000000000008000000000000000
+       606855c5e2af7d73a759c740552e82ccb6cebe5509d6b8e7
+       78e8ab0a55e16027dacacf1de95a31f9cfe73bbb17aeacd9;
+  0000000000000000000000000001000000000000
+       a739b8e8bd92be110edb4378a58e0ccd15d564093f303750
+       124ef1013fa8a440375625eb3d056d78bbeab4f5e808783a;
+  0000000000000000000000000002000000000000
+       58ec509a6c549d855602a8ebe8cd3e81be9125f7df70a84c
+       fd3f5db70bb2eba772ec550e30b2b3e5d51aea15ec0f2e3d;
+  0000000000000000000000000004000000000000
+       447c79e0983fb296711c2fff964122ed7ed11292c018d2e2
+       83e12d4da49d463333fe370cd180c683ba65f9145a76aa18;
+  0000000000000000000000000008000000000000
+       be55d4ffe6d7cca90032c0808f58bb3b1713e19b1151ac0b
+       9514f1e6c4e615dc11d0e4f9a25646f2d3361fd038bd8cad;
+  0000000000000000000000000010000000000000
+       b2288fec987471fff2d3625f55630630c6344b720e2f9d17
+       f7eb7d549d9279701f73b30ac5747fb2caadf10af6967bc2;
+  0000000000000000000000000020000000000000
+       f4092ee2b5f070731b2d68a0acf2dfd5caff8b7302f00eea
+       181be1b17f1bb5df53c76582bc5f460fd90eca3f273f004f;
+  0000000000000000000000000040000000000000
+       7421b7fae0482f6cf39682fcf32a7c23377f46d15e5d2fab
+       bebc8fdcaae6d0891571abba31fd6b5525e3825689951ff4;
+  0000000000000000000000000080000000000000
+       6a0271edebc4ee46a837798b8a11e11fc9dd37f5eac9cea5
+       f88c774103bfd9656cad11ad4b2ff3246a79271f9bd319e3;
+  0000000000000000000000000000010000000000
+       7e7790676f13b58bff48031105e4b0e0ddea47e227cab1b6
+       95e30e5b38892f17c26315287bb12011906932ef6888c307;
+  0000000000000000000000000000020000000000
+       e1f369e67be60abe334c75c254bd5f819d15397e52ce1991
+       5e08e9923dcac610c4f228b1feac23bc6e0ee8f2880625d3;
+  0000000000000000000000000000040000000000
+       5da337bd8a553d4a311d9cd0d00cd8c1292a248704f08e67
+       be4b68b824170d0a635b10c1dadb2a69146f5a9ff9c45d7a;
+  0000000000000000000000000000080000000000
+       f36268dc83dad1fb42ac11a70d2b04c3074caf05f0d28e4b
+       93e3bdb8ae0c1283991383131f42785aa6c13efac96a4ac2;
+  0000000000000000000000000000100000000000
+       f509a4aaa4dd6d33c58f09517fd61b0a3e173981cee23328
+       0d3acc8d01a95faa7bae199eadb1b7f0a6799cc193a36b87;
+  0000000000000000000000000000200000000000
+       f06206eb3ca9d5b3a97ce33c86ab3ec88e025396414965f4
+       06c48b3173b95040a1b30b80892f28205bc3073c06af9690;
+  0000000000000000000000000000400000000000
+       d94cd93f0aa42e7aadc3fe5134a75e22901a277a9a8b8914
+       d040857811c9e9ba2b1d13842e74a2aa3242e8b92106d648;
+  0000000000000000000000000000800000000000
+       de0fcacadfd215ef8ad575bdaa2fc3530d913a03801a7e93
+       142c97486e896f09f6694b3fb82fc7e6da00fe9882351ad4;
+  0000000000000000000000000000000100000000
+       416e67c9024af80ce9084c854109b4d78fca84cffd481f3c
+       b9a534a054aa28ae408d293652388f7dc8782441dae29783;
+  0000000000000000000000000000000200000000
+       1967362294f80c18835408ec52e69b4863a0e463f759a6f0
+       95e7f20d718ffc48412abc598fad1826697b7545c8e3e0af;
+  0000000000000000000000000000000400000000
+       1ce4ad11f24cf2785769f676ecfd2cd5479766bb09236f8c
+       ae02eac15efa0b102722ec4b393323c3f9b4299ec8d62ed6;
+  0000000000000000000000000000000800000000
+       e3c9df7ae6d132da795747f26daf2a538776ed4694636419
+       9c6012e67ff701322397ad7a374116289b3b1e35277812ac;
+  0000000000000000000000000000001000000000
+       f4faf834e3aa92af4178e31d770e7ebf70bebcab1752c561
+       f6fe6c69c4227663ce35b7abb77b78df395f2ebf8523cf28;
+  0000000000000000000000000000002000000000
+       d667bdd9f5967cc525310fefc616998b4705ed09714a55df
+       efb98baf6fe8946fe39778606ae2fa874502918c0885ff8e;
+  0000000000000000000000000000004000000000
+       830e96038280527632cbc228474953ec407956662ecd1e7f
+       bc1b15c2f9951c77111f6aca5fc75222615e4a12287edc86;
+  0000000000000000000000000000008000000000
+       6afe6de17fbd8260c7dce898f26d002a6359800bb5789c23
+       f3c39e7caa6be7d346d62eccf9e1d20a4df2f2c52f0c4c2e;
+  0000000000000000000000000000000001000000
+       6eb5d0fab61828d24ae3323d3018f65400c8c3c0ded66ded
+       5a585a0bf790d36ca04f6e3db2a8240bde8674bf26d0bcc5;
+  0000000000000000000000000000000002000000
+       279323d7c326dfe129bab246202e23158e24abf280e04a5e
+       721cf1d8e73cad3c3ab65d34cd83fc131acb73161d33ee18;
+  0000000000000000000000000000000004000000
+       6e74528189d18b5d8de86975b2272b708dc62f912bb1f90e
+       8e2431350408e2394201afeed37957886df2ec97eb5a872e;
+  0000000000000000000000000000000008000000
+       0e4780dbee0c09822f67da8b98aced5440e3641fc8c80d4b
+       5049f512c2cb135fb8842351a8cb5502bfb9895914494497;
+  0000000000000000000000000000000010000000
+       b40751d42e542a27240b1c25d17d088fdf35357a8e606b65
+       0e9feaceb106eafffd46da59acfd588c91510fdb60f6c101;
+  0000000000000000000000000000000020000000
+       ccdf33f8a14357509960e96ffd707d34d6e125593c470b22
+       da36d09446c89b49417909efc8ab9b8884a82676d0083b27;
+  0000000000000000000000000000000040000000
+       7b51094cfa2d2972b921feb7bc4910af27329e6417eab51e
+       4af16a9cd82694f045f72a419bac4b36c8f4d1ba7b6d7853;
+  0000000000000000000000000000000080000000
+       8912b55eabcae2fd33cc24d48c77e9ea91ad17637fcc4e9a
+       ecdedb7cb770eb34f181e7f4e168d3cb97a62eda8a93a71d;
+  0000000000000000000000000000000000010000
+       4da00b91551750c9e42920ca30cb60c6800614cdd94478f8
+       a1fb6aac2ba91f1db16292fba881ec25ec5139a05bef8360;
+  0000000000000000000000000000000000020000
+       1ac4f21d876b643c6a4e7dbde96f5b46871988c089075722
+       957f88bb33b20c12a264f47f483a7319275351c5beae257c;
+  0000000000000000000000000000000000040000
+       cf0e9847cf96d79d483634b86b9d946163fc7f75ad200380
+       090dcf1b1e3d1614b9a81368ae7494eaebafa78f7c8ee545;
+  0000000000000000000000000000000000080000
+       8776c8edab400e4e107458c529119fb645ed0232c13ef316
+       c190562aa4f0e4a8a0b142d3842e16a1e4145a865533f820;
+  0000000000000000000000000000000000100000
+       5364915ad601a7b24e7fa93224e0f890c1b19976ef727604
+       8fb3df4ab244c50af5acdd8273bbdd5ee22433978a1eb577;
+  0000000000000000000000000000000000200000
+       ac3f6c09935979c1c7ed97fb57b6b4effc7ae93007905959
+       65d4b7f38a928a43be02d8c01e6de2709e2eafe4cbdf00d3;
+  0000000000000000000000000000000000400000
+       6531fb35b522582fd8e344b4967d4fd96f3f028df9b8a0f0
+       433d474f5759f5a6268d21ff330185eefd7581fb417824ad;
+  0000000000000000000000000000000000800000
+       cddb346f0a62dab089d9d08e5728c390528341a65207762a
+       15a50b1d5b86af3bbc2d769639d1863187e6abf155550d85;
+  0000000000000000000000000000000000000100
+       76a743ed49c15a6ae22baed339d3b3de0538d9dd9a5fad03
+       2f81d127787c8b56417ec1b0eeed0bedf24dfaaa5fc101a9;
+  0000000000000000000000000000000000000200
+       959c1be8dc4a8d23c065d0af24ac881204f64c6ac6f39649
+       e5535e583d915bcc451d04d40f88d00d531eab1e74a85936;
+  0000000000000000000000000000000000000400
+       60f09275f915ecd4753a88c14f310627a68c85b0059cc7cd
+       f2eb6f33261a6f1521acf10950689cf8300ea1f7dd02c455;
+  0000000000000000000000000000000000000800
+       a582a3a84d722b1888eef5459d744f4c9bf0f254393eade3
+       5171c29052d8aa3d3bed54ed6013e5bf27f0ca0c256e5df0;
+  0000000000000000000000000000000000001000
+       5075b276fc0c1b44b34c2d7103a321119dfd5ca9858f5ebd
+       c3e543ed7b34b725a060380f5f351859b5cd34c3655c1bb8;
+  0000000000000000000000000000000000002000
+       76ecbfce581f71b255f56aa7118900ca55482a1402d508ac
+       16f238cab43a3e15aa8bdb6546bf4907171d6062faf6d51e;
+  0000000000000000000000000000000000004000
+       48c37ef151bd87c3c8af4b33d2cce7007aeb511e4c9eea95
+       b78ed418a8749a58fd1fa8eccd28ed1ce220682caae446b4;
+  0000000000000000000000000000000000008000
+       efbc6f0100835c8051fa95f338915f80004763efd684f982
+       e88cad94409c47ee2fb48fea7996afd75780fdc66f55e145;
+  0000000000000000000000000000000000000001
+       8f537350f5a94603ac84b105dad1ce2b27e775b251ffcaf1
+       ccf28017b1b6d8e853094535b78c0c533ca88d3119f88130;
+  0000000000000000000000000000000000000002
+       73bf403e90243af00ae3573bf26cbbfaf22bfc64c25042ba
+       842c8b6edfd5470e1261b53cf3f495c03e7ffbf747917b03;
+  0000000000000000000000000000000000000004
+       b2e7d8fb0bb71f3543285e36b768726cdbad667cd415fedc
+       cae46b71316c769290340cdfc99c9751fcdf53a911e75700;
+  0000000000000000000000000000000000000008
+       391c06d7329a903e22f310c602d86877dd921f82e15173be
+       e2b1e5114f1648ba3449d564fb1ee26d7c325630777a6ae5;
+  0000000000000000000000000000000000000010
+       b54aa87e67f0e182a88660fe8df6a34dc2fb021fc80e372a
+       30d3fcde749a306eb9d5aad0527c7e187449beb5a0b4e2a1;
+  0000000000000000000000000000000000000020
+       003bc47785839c9c0d915eddb61b2eefb3e474c86cccd321
+       388746b96cc6ccadf4f86e0a98baa5dcf6d2c777195a8b07;
+  0000000000000000000000000000000000000040
+       c737e23e4813ee5321ac10198e108ad3cb59dc35a46aa4e2
+       987655569a6d6c797b7c432b8711c1c4a29c95c8849fbb6f;
+  0000000000000000000000000000000000000080
+       2ea5c63608597b7da53a2ceed973943951552fffd89c0101
+       1d6673cdb23e07fd73fb0f325b98a9d7640a118e170b20ae;
+  010000000000000000000000000000000000000000000000
+       950227a0e0af4be87ad9923642ae064a989f7bd41783a808
+       9d1b35004e09dc8a26c67a60c358a299cfd493a5825d2bfc;
+  020000000000000000000000000000000000000000000000
+       e06478bdbb64dfc81293d20b3babe451119c00a57abc32d5
+       5cba681dc30a6350b640f6ff5d82b9a59ef4724cceacd6a8;
+  040000000000000000000000000000000000000000000000
+       9e2a31deb5c28e271d69790d7dde1fc96b5e2f727ba863d7
+       383972aa8b8a05beacfd3cca26b84ea7e658f0a161c44307;
+  080000000000000000000000000000000000000000000000
+       e7248873cbe00a5eb07d18a36dd1551e1de656f175795b68
+       72c76c4142011ef65b3ee4d1d92845dec5d24c09b8e15ea6;
+  100000000000000000000000000000000000000000000000
+       bc6a56d706b865d0d0bb17f6f56a946b19b6463823b50705
+       5856456857fe3829df5ae6ce9c1559e2ec272e2023bed389;
+  200000000000000000000000000000000000000000000000
+       fc9f70464be8294b04c3092a09815ca7cbd9e4007e35a6e7
+       1873b51c4e65ef63ea2ad3ab7bbe2933c53607c2f4f822ad;
+  400000000000000000000000000000000000000000000000
+       9252b21b6ee8ad2618bbbb0624fc077c593422d73c205172
+       3fa2ea516e55274a6eeffc125729b4f323395a9375fabe20;
+  800000000000000000000000000000000000000000000000
+       23ff2420dc5bfa41b4c1e02c9724c8356973ee4c29900941
+       eb5c441b2c65f801f3781c59bcfba202ccca06a5a0daace2;
+  000100000000000000000000000000000000000000000000
+       21bb39d0e07a104683fcabcbf086ae38505f21119eb69eb5
+       317efbc320dc245436f65995b9555a70567061f15b882765;
+  000200000000000000000000000000000000000000000000
+       5faa02f914a0d07a3ef66ad9b85dd7292cfca0e96b41b18f
+       ac6668e2d5bc13abf89ab4ef5ba02e4893c63453fe6cdfd1;
+  000400000000000000000000000000000000000000000000
+       fd2edab89c53584e62d29154ae3eb025eda061a2094d1c55
+       074cae6a1865c11c8a740c06500f972946ef3f7cfca6c784;
+  000800000000000000000000000000000000000000000000
+       1200e02bfb0d2994eee80495fe6f8db63f480f23b06943ae
+       665960dec953660aa472689e099663ea2e9281bc0ec42b70;
+  001000000000000000000000000000000000000000000000
+       d7680b371b3db05b0fd319e98c4fb48faa5147c24fb8dc98
+       f0faf1fe00730c1795fbc5865cf67def50d494e9b0e40085;
+  002000000000000000000000000000000000000000000000
+       0ba73097866cf7add6a87d76db9512a2965f43a59842dc9c
+       867abf83d19cda8d1c980c008be09eb6d3fd4c2a3aefe157;
+  004000000000000000000000000000000000000000000000
+       0efdd7ae03dd5d0586093ce70bb56933d277cf262a708e53
+       15828719856c5b9f77c12dace0afd8bf79de06c99b18ca32;
+  008000000000000000000000000000000000000000000000
+       f8aa22bf8e9b805311ea0cfeb6633a4d333c25df26a44086
+       d24bebb6a79cf48786be0aa33e3f0d904f4c1c256ce5284e;
+  000001000000000000000000000000000000000000000000
+       bd4971c056be4d3e3a7a7f727700ab237838abe0cb8006c7
+       ab9a06b02608dc9824147e4fae22347564145cc72acf6d63;
+  000002000000000000000000000000000000000000000000
+       47dd63c99f11d04f002c78b4a9f7e87e6a95103f6b952088
+       ad3844299f2996c7124618b420a5d20476f8724a1a2a554f;
+  000004000000000000000000000000000000000000000000
+       c23a8c3c1c99c1094e0e33ea48a795e457124f219a7ca076
+       1756e14debebb81278d38a6e1e030c41ab3ad10db3723956;
+  000008000000000000000000000000000000000000000000
+       4e51df50080c1c5ead84794c7f8c0b6af24eb44940230a54
+       6ffad11649a0460c565e360be1d922b3882760bf6f6cdb0a;
+  000010000000000000000000000000000000000000000000
+       94544aa77e6f2e88130f6d882ce6d41b92805e8a33bbf758
+       afbfa3504fa60b0c174dc726c32e36cf044730b03de81da9;
+  000020000000000000000000000000000000000000000000
+       4fcde9e30ebe03a1f724f6b00d806273582e1cdfc15ff147
+       80558bc2b6f44c7ba7d6640d99278f274b2290e3d574e93f;
+  000040000000000000000000000000000000000000000000
+       2fc3569fa2e00eef7c411f2b469869e37982de1d4a6e6a6d
+       6adb474171dac11f836848dc4753239335b91b1f5e1392fc;
+  000080000000000000000000000000000000000000000000
+       fc5b0abf6a26469cbc8b64bd73322994717393eef4fcfb9d
+       3c2acabbf67983924899ccfc1d003cd931f4808fd2aba192;
+  000000010000000000000000000000000000000000000000
+       4c72a0fc014cb5ca4e85b0871f3fce111bfeb1ee212bc3f3
+       ef0ba0a4ccfef260c42884b03ca09c7bbd022b3c69d2efaf;
+  000000020000000000000000000000000000000000000000
+       723a6062b95c8e17cd63441dc3542103ef5b62b2ee67f696
+       0a0c19d7009f4984767aac9284ee75784b632ff2b8b0165e;
+  000000040000000000000000000000000000000000000000
+       00f433db06d51a81037b312e1687b90668b14b5c87019e79
+       2769bcb9e372babe64498035c9ca6d385e713f2c62da9830;
+  000000080000000000000000000000000000000000000000
+       c00a26a106c43e944d8012181e873d57658bd3efbef46926
+       beb3b2eeb0e4cf7af92ab9eedab0afaceda36a4d158fc060;
+  000000100000000000000000000000000000000000000000
+       2b6af19499046a72002bb08321899ea1196e43a3445dc66a
+       53355ad208629b72a6b63955ea29d96f8625ef065d7bfbfb;
+  000000200000000000000000000000000000000000000000
+       b8bd2b3ca21a4e9c46f3a6ee8283c629e51ad868be5da5eb
+       099fb4ee85dd16e2adb3a8392721eddef3284ebe72a629fc;
+  000000400000000000000000000000000000000000000000
+       e7a823381ecefd169648af7cdebe27bdd33575997b16c9ea
+       2087cb8faf6e0f87bfd483bef04ae0aa84b7faf1d66c3067;
+  000000800000000000000000000000000000000000000000
+       10bf2538f02d13d5d6df68708a1a875152c8253a189c44a6
+       d7c45cd1b7df5ee240c9e19d9a875c99d06bffd5b58249e0;
+  000000000100000000000000000000000000000000000000
+       d60033a9a4020d3be5214edc136c993f05a04a3e8ea5c8a4
+       25b00716396a5cc3c54215e42da5c2642073d967fc26dbee;
+  000000000200000000000000000000000000000000000000
+       c69e4ed75ca48419d526e5997f9634d1cc230c49158907d5
+       b8eedcc2227f3593df72a78ed1100394eb65f9098b5eb4f1;
+  000000000400000000000000000000000000000000000000
+       9dd47ff28851b4da258c41aedadb4d407e39dcf8421fe2fe
+       913ceb307bd491e5a5e7c6945c7b3ccf2b30571beeab889e;
+  000000000800000000000000000000000000000000000000
+       245dadd57e5ea520d0319892ecb964fc7d7d75ac259196e5
+       06ed9325638f5f233cc3c6687e966d18d13a2376a7d0d2e3;
+  000000001000000000000000000000000000000000000000
+       4b88b385ae2ce90610c3de9942359182b23cf96617b01a50
+       1789bd30c366f57f606c139d7dc7c00bd6999994bc225eba;
+  000000002000000000000000000000000000000000000000
+       ced8575125b759ba6fb81c4cf51b309f1199038471b1034f
+       4d3bb5964432e95176d2438ae186c9ecd0aba9b71899b85b;
+  000000004000000000000000000000000000000000000000
+       2d74c25a841900a8b9a663b0ef0dbb1e24a4950eb06445e3
+       e766ee906e42ad9fbde3aeb74fdc464fc3eb72c87bef45cb;
+  000000008000000000000000000000000000000000000000
+       20f7f88a12d40f3cb6b592008dec36ee508387a7870e8ba0
+       68f515a58c25941d27fc209666df7caac05c6ac143a883dd;
+  000000000001000000000000000000000000000000000000
+       9c95399291b0d3202663fd9f6ee972975c862cedbf2461e3
+       cd0987b7da9744e475b9a457e34330216858240559c3758c;
+  000000000002000000000000000000000000000000000000
+       877cf0278449adf691b20d5b453d891951a1d1e8eb03c47c
+       5b16a43b032ca092aaa101ce8d0daf61894d53075fe02768;
+  000000000004000000000000000000000000000000000000
+       bae2c00d2a033ad2acd8719acfb01332aaf91987a84b046d
+       b9f4306305a262b7a8341f8bd9a30722b18479e8a722c030;
+  000000000008000000000000000000000000000000000000
+       3a8b7c986f313adf30c17005fc8f4e4783cc7efbabb45b0e
+       80c005616ccd2e26d65e3b9d6b3284218a90448b59d6a4c1;
+  000000000010000000000000000000000000000000000000
+       fd95f34a972382c5c78e702b777c873040970ec04477a9b7
+       0f8ef6fab119411fcac25d7794514f6879ccadfbbdcf1737;
+  000000000020000000000000000000000000000000000000
+       0e76cd58cca1993794ee6fd9537271c337844d69317a3064
+       0187210213980e21d629cf30ce5702e6c3a78fbec1847c30;
+  000000000040000000000000000000000000000000000000
+       7cc71eda22e83901a5e7d5d0fc5a2dd1a9a74c25146406ed
+       040739cf452779ac78d307c96dc0298e34f9ed95b4bddce2;
+  000000000080000000000000000000000000000000000000
+       34a0f031a22247f0583237ab3084581ea0cd8df336723285
+       3a9ec82043173a791c04b9b8be7ffb35118bf09e3d2ee0ff;
+  000000000000010000000000000000000000000000000000
+       0b6cf14a5abe2dd979c268d5145083b48889d69df0d37708
+       991b6be8eee496149a181200b1fd081e437a9b5fc0cac4e0;
+  000000000000020000000000000000000000000000000000
+       08cc9b13e27d4cd3e3d7563eef1dbba235abec2a418f1852
+       ae9edb5746fdacfa76de58675cbbd24a4a7e77d96fbe7b6c;
+  000000000000040000000000000000000000000000000000
+       824c0dec5d6a4df429da24bb8e2fc8a4372bb92074a2727a
+       8f0715b035222ee533b0981f01550e8e5a9e24412d9ddfb4;
+  000000000000080000000000000000000000000000000000
+       68c15e06234437eeb45d5108e8259a70e13258dbab25b697
+       8d177379a2039c1a7843ad87fc6ee1393a4cee80a2751141;
+  000000000000100000000000000000000000000000000000
+       1001198aada4c22c4dc1d84fa1e010cd54835e132f22dfeb
+       b8cd530fe6ca419cfd7bb8081845fcde53b2adedbd801018;
+  000000000000200000000000000000000000000000000000
+       9ee54d6bc7e24d0c738ddfb263e5b63fa26811b76b578409
+       7f7446709375b8e32d8f0fc000eac04f0b1b82a3125cdf96;
+  000000000000400000000000000000000000000000000000
+       85c19ef941156968fe05f7fb61bbec5122012fa0fd4bc828
+       7168634d5b191ffacd2f8e4928119d68627bd4b027db18c5;
+  000000000000800000000000000000000000000000000000
+       2e644758b3e889cdaf5c845e4ed308be6a3eea514f893e6f
+       d077d2ee5cc8d36b632d4e983578d6bc894ed2006b57b466;
+  000000000000000100000000000000000000000000000000
+       d86c637f816b37de534d296fe76092971f47418fe1250959
+       b15790c9ab783aac93d8944f77eb9d0d3ef9fecac04a2918;
+  000000000000000200000000000000000000000000000000
+       864954a4c173fcf64b26cd5f046a1c7a05d1c947e054f155
+       4fb4609c1b2739d513358c7bcf38385f1d90431c60437b6f;
+  000000000000000400000000000000000000000000000000
+       7429d917ca0f35eedf754a3dfc87fa86efb1c7d67297343b
+       7c66f4fc42a427a5175cbb09feac1aea770471a8566ea04f;
+  000000000000000800000000000000000000000000000000
+       3782aa7d7eb154ed5d96a1cba095ddab7d2446cfc02928bc
+       1e6d44ca07547ad0916761154378d997b27c06f4162dcf9a;
+  000000000000001000000000000000000000000000000000
+       a668c27906252b42c57223bf1041b4474a265e456e2b2ecd
+       3560a2b61ac784e7a96ef52262e6dc91e50518c9fac3b4b0;
+  000000000000002000000000000000000000000000000000
+       c84f1667f91ee7bdfc4354dc978f0d7cb7bdbf8851a26120
+       c7e80fbe3e6f54d7b6e5d8b678c95da1836ee1f51d9433ae;
+  000000000000004000000000000000000000000000000000
+       29292efb39b4bcf42c932f53d49b14c97594be6e0b3433f1
+       37073c3c11ddb32e01fdfd49f6eb19b2b651fa9243a77376;
+  000000000000008000000000000000000000000000000000
+       55fada32dbb1f89e56aa524e1fd89d54b43c4df2bc223e4b
+       d6d58bfc7a97a059494c17ef3affdf7d3e1702e78ca36062;
+  000000000000000001000000000000000000000000000000
+       ccd662881392daf3ff1ed0021b38e19d8ab8d01a2bf58700
+       336934b6f95645d246b72d600bd366a77d312065ff9ecfe8;
+  000000000000000002000000000000000000000000000000
+       922bf0e21bef2411ae54cd3cc6d5eb7a9ecfadb1db60fc5e
+       88d77b89f6936f6249cd1128bbd9ca6625fcb1fc3a08a251;
+  000000000000000004000000000000000000000000000000
+       f687602ca24ca63d2a29a2767278dc6548520317451902e5
+       55d57692a413659d964e04914e6256bf92155c60c99bb55e;
+  000000000000000008000000000000000000000000000000
+       b5f8969d59419a804c80468b2a9de9c79516a0799abac18c
+       c1057e3f43e1ebaf15d380a7e0e6de243f7f2fa3950e4c99;
+  000000000000000010000000000000000000000000000000
+       e04bc9f8b61a4f9de92ae6244c7b2a4e08f6c3e3f1448f33
+       0f8fde70f9e667cf2e9ceaffbac28d2e209ea2abcbbb8a77;
+  000000000000000020000000000000000000000000000000
+       e971da1f557584cf07135aca681908701acdaf839e3712d4
+       09acbfeb972d8a06fbf34de6c82365c23d999cd74647abff;
+  000000000000000040000000000000000000000000000000
+       bda162e322c262b9d35b36e0e46a23676014fe48429f5cdc
+       aa5b0598386fb110a46a87c8fbcaeb516de28ea2ed7f8d20;
+  000000000000000080000000000000000000000000000000
+       fd9ed1383cec0c64be074a4d57ddf0afe49e5ad2c009fe66
+       fa16f08eef73e9de97deb09eb19f332ea42193d110bd8404;
+  000000000000000000010000000000000000000000000000
+       27f427404340f50680538b37b52c848743366495fc402563
+       abaa5141060bf1bf3134136e0b0b141ab248d2ddb9ff063d;
+  000000000000000000020000000000000000000000000000
+       ae41da022c6449e1e8a428ec9b889ffdb8a437d6480a0c81
+       15abc9a52c7469e98ce02e534753cc84f76cae07acddc082;
+  000000000000000000040000000000000000000000000000
+       f0b9b3502228b1f620038dad3f8851b141a294c1248d68ab
+       b76b98012d904ebba304ae707227df9950522a6d5d4461a8;
+  000000000000000000080000000000000000000000000000
+       60ffd6930e94706f169e7067ae595c5e8e0ddf0b77db2829
+       3e8e2ac1f42519bdf5bec90400c716fae98a1be517fd4792;
+  000000000000000000100000000000000000000000000000
+       de5aea72327f9a7b74a5f80fda52e2157b22ea92e14adca2
+       55d09602919f23cdab77f5c03bc381a6bb318b8468f21c8d;
+  000000000000000000200000000000000000000000000000
+       0b5ab5730b4974b1eb97cf228b330248a095259668378c80
+       268cf5bc198bc91b6644663d29ba29f90916737b513b54a2;
+  000000000000000000400000000000000000000000000000
+       c7fda4b796b2152eee8141d57bad874253c307c6458ba9bd
+       0211fccf6da981c4e1de0f8b8fe3e1dc12e57d0ba2c4bd45;
+  000000000000000000800000000000000000000000000000
+       0ccf6e36230d2a3fcf1c3166362811bcebbf84ab4c6266dd
+       d185d6a587f704393c58c0808b9054aba16b27c46129afdd;
+  000000000000000000000100000000000000000000000000
+       d0eb3bac789ca548310b28febf4ebe3a8730edc80788e322
+       72d5147984e036a42b7b803b1ab7e8de83a5bfaaed63eb93;
+  000000000000000000000200000000000000000000000000
+       f1f9a72096a0d35a3bde4203b234d6fd8fe7cee52c73d3b2
+       45b9e1ac776727e325b3d07cdcb8c7950586be2ba64a7e20;
+  000000000000000000000400000000000000000000000000
+       a0f475abb02d86fca05f4ee38a4b96f1671edc37e4921789
+       92e568e95bb7da1bd9c413d3c506edd480ca5a2022145e18;
+  000000000000000000000800000000000000000000000000
+       c2cb82eb6202462faffbe17860caf958127837bb56679d26
+       84a77a9c5053d7b382937ae4058a0c2c8e0cae806750047b;
+  000000000000000000001000000000000000000000000000
+       f69a70aaa3145b6648b244b0cfe95e258de12960733fef39
+       8e1d6e60c18153a420586a9525a8a35a0e01c33d445d394c;
+  000000000000000000002000000000000000000000000000
+       ce821767e1c5200f6e949eac5d032365a021002376f286ba
+       66c57c2559bff8bb523acf8308a6e87d48507287f78d5fb2;
+  000000000000000000004000000000000000000000000000
+       25a78a2f37beea632aba391e99c8ee0cbd895861704b0508
+       7837958ca54303afcf6497fbfc3feab75fa8dacbb2da0271;
+  000000000000000000008000000000000000000000000000
+       424443625ccf703366b5006c2a06a5844107afeaca134291
+       67d5149bf0ef07975a81fbb90367b0c388c71706a71b57de;
+  000000000000000000000001000000000000000000000000
+       0c4b5edc7c9af09602270ecfcb227a08c3eb41e8e743c46f
+       38451d3e127ced080e76deac3a2608e4ba9c6f64858986f9;
+  000000000000000000000002000000000000000000000000
+       3806f72a054c5cae45b69837bf2ed1cf3d95f548ceb6ab8c
+       bf3a0b3586be379283cc846f0e2f7a726667f22b4bd8073d;
+  000000000000000000000004000000000000000000000000
+       53acb46560bcc190fae42c7a64bf9dc3523d6e039a6a2362
+       1662cc1720996bb8a3af6255e767b3197904d036ffc66bf6;
+  000000000000000000000008000000000000000000000000
+       02f3e87b459d0f8b9efc00443a035552f21f114b7b85f451
+       a9b157c5bfa6119d89b2c205b7a1f9742865b4c1e7f64501;
+  000000000000000000000010000000000000000000000000
+       8c5505d686afcdecb2260e057ac8f325657df05bf9b05966
+       5ec81b79d35ba3280ea12e5b043b3e31e268829e3d563eff;
+  000000000000000000000020000000000000000000000000
+       55cb50e1caf5c71429c98f03714b692ea31b1c43cae13b34
+       c889fdec89a6a1495614efaf5af9ba6defb5a56452ddf97a;
+  000000000000000000000040000000000000000000000000
+       a738befdbe5ca885c080949c0c6d20ae12673cc7d20f8f83
+       b6a93ddc7d3c794fc40483401e90d67841b9f5354e14c5ee;
+  000000000000000000000080000000000000000000000000
+       ad437b56deab48e58dbac0415241c21f1e58f9697810c86e
+       5f39077bf328fac90226b173cd437ef53ecb7a98e0cd4439;
+  000000000000000000000000010000000000000000000000
+       bea057a143e4fca512bc0a7905a92efde0403dfc766633d0
+       e22ff885888f579985075b711375ab522d0f44def0571561;
+  000000000000000000000000020000000000000000000000
+       52ae9040cda27f5ee7fe1414b48401560faa8141518dc3d8
+       ca197b53ddce530fdd18c70d16cfb3ebcfabaf86f28a3593;
+  000000000000000000000000040000000000000000000000
+       6bb619e1ad95c1cae465758158d3eb2f49eeb6fdf72f46b6
+       87c5624f8f1cd1ebef2de00f71c5747bd1b62abdba15326d;
+  000000000000000000000000080000000000000000000000
+       6420252af652e672b66ba8b28241d159e9ba6359c5c9b917
+       090a8bc5603faff86b116c11c4934bf8f5c1aaa119fd4b04;
+  000000000000000000000000100000000000000000000000
+       1761ffce62135461d02a5426b1c31ba1e693ab9a12aa68e6
+       82d92d00ab3f980a7b07e7fa4edd44dcda5b0f57cf6911ad;
+  000000000000000000000000200000000000000000000000
+       8f05ebc8491092d047674a6c6b984e95076dbcbc476ee825
+       66a587a3f6a816a6fc8c5ae7945b26f5386a156fd886e8a3;
+  000000000000000000000000400000000000000000000000
+       b5b04bb84c64d7d82a9a6627b45e2d730e619261ccaf8612
+       0b258b61b0732a06f0b3b1e6128461525f14b93edcf6e65b;
+  000000000000000000000000800000000000000000000000
+       94efc3bae8b030363dc12b9d98f462a53e669bab96a04bd6
+       d19b3eee10c9305677102f713cc0e44dd94b38b586e66c85;
+  000000000000000000000000000100000000000000000000
+       44f615f33c33876b0a7f5eaf4e5194228138486b7bb661d8
+       324dd74ce8e0b2353f6b0956d90db45d0ba174348fbe8009;
+  000000000000000000000000000200000000000000000000
+       ab1ee468f066b46ee35ff4cf3b061e0b032c11316e829294
+       0b9fe8ce0e6ec4775aba86a76e6f15b01139c55952356e45;
+  000000000000000000000000000400000000000000000000
+       ff5f9a1310f1972c3e2ff648f5c7a3c253910b6f4c9cec98
+       ce4364ba24319ee0e1d7b47207ed8fd704d41284f857aafd;
+  000000000000000000000000000800000000000000000000
+       67547ca22ec3022cd81a011d8a36f081e6e6665d53d59615
+       3eab5b8d3cb573b7cd71dfd69f8865da04e88bed2c22fcc4;
+  000000000000000000000000001000000000000000000000
+       43a0b4632e7b5746206f24fcc0cc5c02abedccf93209a90c
+       86f8af1e716badbcc467b179e06f84c4a0b7050b3d381646;
+  000000000000000000000000002000000000000000000000
+       84e3a90828dc4d3a965e6a2ab5d0aa532aab68bd6dc61171
+       780e5dae9e9d1f276da173517a11d0b70daafbafef4ec191;
+  000000000000000000000000004000000000000000000000
+       a59916e1e69488af5c2315227ae07a1fd29c7e88316de33d
+       dd0a3a126707ea8a9b19b2bca7d6c6f91e4288707da624b3;
+  000000000000000000000000008000000000000000000000
+       5bb210f3f571f79c7b6020cd4076feecebce67313fd4e92c
+       5dd34c33bd75b5cc2712c284f06ebd0771f03bbe6a0933ef;
+  000000000000000000000000000001000000000000000000
+       16377666962332f0d015c24a8a64c8fba0a6b0026448df2d
+       4dc232f7602f414acd74682fc955cd7a39e965277ab13f73;
+  000000000000000000000000000002000000000000000000
+       88a0800a751e61a4cf3556fc09a5e2267f012c48125f9b6f
+       0fae8ad675be20c5cf2811f31e013754e20600d789d0d366;
+  000000000000000000000000000004000000000000000000
+       536255493cd9b75e93b7b3d8a22b9a5250f5715da602c2a8
+       eb03a459e1ecfcf80d8c869a0800d10d9bf0eb16deb0feb0;
+  000000000000000000000000000008000000000000000000
+       d23dab5d3651b9b3d90315939175223e6e3dd8f06c87b2f4
+       bc59d143168febd05f77d5edc352db18040573e5e90c1b97;
+  000000000000000000000000000010000000000000000000
+       a991cf922b451c1eeb6052888c28b5c51371101c15ac05e6
+       10467d595653eca2298f0fb16b0260e79c2f6bfc1fe0b9bd;
+  000000000000000000000000000020000000000000000000
+       a54de96886108612191972a6c17cc10f2fe3b218433cb6e9
+       19ade54eb641c24ef2cf34831b80002993d1f584f5126112;
+  000000000000000000000000000040000000000000000000
+       4df1ea44dc58b80b0d4ffb6440a023175f0de0ca13e5b20f
+       3b73e209e5db273ea076697eb09a23d75a06763c95ddfa52;
+  000000000000000000000000000080000000000000000000
+       f8266b0377535bdeb855801f5815c1c51e6de75d9372c249
+       8f3b81b9b8daa6b9134c358fd69df65d682a2bb1e3897653;
+  000000000000000000000000000000010000000000000000
+       96712bf387a2bd8915be3400cfe50c9edba2a03e24e9da7e
+       bdcee44e3c128f80ab846ceebd787775d7d12a8c0c4b1b7f;
+  000000000000000000000000000000020000000000000000
+       86e7bd89620da09a32041eed8dc60f4df1708c674baf7d9f
+       7ac5acbe1e3549204cd4940e4189424dc800a37e3bf49645;
+  000000000000000000000000000000040000000000000000
+       cb943d6a0c33f4d6fc0856026a2e0f8b8b15572789cc156b
+       3e16f341f83c585e427dee9184d650a00206454148fe2c47;
+  000000000000000000000000000000080000000000000000
+       15abf241bbb3e72ffc263366ccfe5c42b8afa0e615246fa2
+       1bbc37453d729fa3f560cdcefafa5bec04097b34f04e69e0;
+  000000000000000000000000000000100000000000000000
+       e3a2fbaf70c336c960076e25901b08ea70f00cfbdb678c99
+       6199c398d7970a32a506c58e7deaef154b08bd660cda65dd;
+  000000000000000000000000000000200000000000000000
+       4ba54ce0040ef1780a0286d10ac5cf13f563d688c214080a
+       e2d23bc27ecd4508c2b934c201410ec11ccf581738f9deb6;
+  000000000000000000000000000000400000000000000000
+       81953955d6a216c4be8a3dc461783a0af5edc5f4291f4edf
+       858b1e9cd5c1b34c7df03a68aa618a046e9870f3edd2be08;
+  000000000000000000000000000000800000000000000000
+       46be627870c3f043209d65725bf2a546aee9d2dc6d355f03
+       6d35d794d51108c1828114d73df644f5e537523567ba3866;
+  000000000000000000000000000000000100000000000000
+       6081001224d8a1b4062908a261bab7dc4dcbadefb31c47fb
+       e62bd23c4597a7fa473c3fae0d3b499cdfbb81a3cf2ff46e;
+  000000000000000000000000000000000200000000000000
+       9cd0184802fb4297083c8fe4289a50b0b54daf57ce7d3c7f
+       f08cf7cef963531dd323b2d85ee2e57956eefb463813e810;
+  000000000000000000000000000000000400000000000000
+       cd2a4132daaadd45eef34602ab287ab35da3216d7e0c2201
+       18bd53d544503fbbfe63fc730f9ea3f83a92a075b9c731b1;
+  000000000000000000000000000000000800000000000000
+       7dd4dab1cceab233b8f440e7c798d926d6672fae111b97a6
+       0155e424ee93cbeb18f5de8353fac06917061248e64a1db0;
+  000000000000000000000000000000001000000000000000
+       2bebc540b952ee15d29456eeb9754bbfd6d14dd4df9ee357
+       4a6e99f2277d6436c5f76ed6143a0a5e0871842134a67f9b;
+  000000000000000000000000000000002000000000000000
+       c599a8f74e66cc416087a2c232debb1b9ca96ef0eecf7692
+       deb16181993fbe042307dea974ae92137f39a6107a6cd52c;
+  000000000000000000000000000000004000000000000000
+       1ed3a61376f1e6730127787de72c37ba58d748acdad988b5
+       4b4d63ad13b6e936379710f9f1c9d5c01a3884713e2323c4;
+  000000000000000000000000000000008000000000000000
+       e976691853eee2c466e8d9ecac6f2be9dd4d119250e9687b
+       a9d8242d5171109459a60bf382bf5542278a0fafd6a31c33;
+  000000000000000000000000000000000001000000000000
+       817d9313109eac3b60bc647e881f9fd77296b7fd5521a4fa
+       083fe0e8e375636af03941ea797f9a5a7798cfab8b260e19;
+  000000000000000000000000000000000002000000000000
+       3609713a1383562d139c62be8b46b22814c52d0498bd0743
+       31cac650c1affaeac478b5cc8145e5afff54f9c486803fb6;
+  000000000000000000000000000000000004000000000000
+       b6da3ad2f7b51786fb5a1e52cdeaccfbeddc948211e1fd6c
+       afb15f06a78e82084de6200f85b0f7ba6c9f80ee34fbff8b;
+  000000000000000000000000000000000008000000000000
+       30e517ce758f7bfd6d50c44802880144b2f0b37052cc5efb
+       3183baf097aa12da6830fb3781b803f32e8f89f01cd9d25e;
+  000000000000000000000000000000000010000000000000
+       c561eb0df785893728c7ab68541ee65b5de5f0def12f1570
+       92f0838b81ecc63bd92162455803a4865f3771af19d0cfd0;
+  000000000000000000000000000000000020000000000000
+       d5fd1003a7018381ade31fe9ce9a64126ee798d2a2ec8733
+       7336952580c0fd50af4df8939122ccb98963c88631f4e74e;
+  000000000000000000000000000000000040000000000000
+       99d96e0cdccd1a71a29a6e15441a2d3a25a0718ea84c2726
+       04c80e68b0f9daeddbf4a243332a2a9c03684811420318dd;
+  000000000000000000000000000000000080000000000000
+       5c123dbda2b026c444fc873e2884e7c733642451b8c58bea
+       e4a1520b9dbb0580eadd7e983e5f7ffca560a2aa69cb4acd;
+  000000000000000000000000000000000000010000000000
+       aa82a0f119dd67acec85d42d52866a18fc250f5b063bbc67
+       e01b60199b085ecb412d68b2b4fc65b5ea827a6f5e2a7b85;
+  000000000000000000000000000000000000020000000000
+       e3d91efce207edf5a3f0c5412c517ca2caf860fb80c75a23
+       5b79bb6bd28b687eb07afe51566ea4b1a791aa9620734a22;
+  000000000000000000000000000000000000040000000000
+       120d205dc675f1585fa3b9cf92627e7644be58785b0ab209
+       98f71325ccdd857d0eac2bcd8e6201ea042569d2b06dc82f;
+  000000000000000000000000000000000000080000000000
+       ecc047da556e6c5ea7c195ed3c5386f60dd3b95537e41aed
+       b21cb8440842e4bde27ee84bfcbf0ee0bc8b8b3ad88455e2;
+  000000000000000000000000000000000000100000000000
+       9c595d82e523573893ef08454be25082e3e2dfdbe71f6634
+       e040f8c529241507b3f450b48f1f05605c1566443dfae0e3;
+  000000000000000000000000000000000000200000000000
+       35f4e989da7d064611287588d3566eb092c87405cbdc6873
+       913e8b1818b9f317ac16b02ff0226c0d7749d40612eb5a6b;
+  000000000000000000000000000000000000400000000000
+       8efaff57d270546c21d4728e904409ebf9d19d86ba797a1b
+       4423538d5d87cfb5c636b71801ed86751b722779545a73e0;
+  000000000000000000000000000000000000800000000000
+       38f285b482c3d66af4e661a07a3e6069143cad4dc1e3e804
+       6f1184beb0f6f27e0e2389d84bc6df3d54a51bd1c6336b8b;
+  000000000000000000000000000000000000000100000000
+       9ab7f76f277e7c5e9e437d44506feac61c20c40c50d4f4a6
+       f5c357f4d66b8e96f8245c41324e8645cfa9953dcb2f4b70;
+  000000000000000000000000000000000000000200000000
+       6077ee198eee87d2ab2bc968f4f594b7db9070b367409f9d
+       8e3e4e0f06c954bf256d3ff91852e1b2b392665c4385d9e2;
+  000000000000000000000000000000000000000400000000
+       dd9d75908bbdc05e2cfb8df5d1db68ccce7bbe7f121eacc2
+       78082c854cd92adbc3c37daee124d4d9a7d97b9c6c7ff4d9;
+  000000000000000000000000000000000000000800000000
+       41e7465edc8a9d8bc8f4eded1405c82d2fe9dd6232807b95
+       3a4701a2768128fdd2dbf43278039f36226d0f32401c2f46;
+  000000000000000000000000000000000000001000000000
+       c08c6119ee2a2197f963a599bd65b0590ef5a519e33c636e
+       977467c483d31158e24a00e7057e9122d84b8c29df6a40bc;
+  000000000000000000000000000000000000002000000000
+       af0bc2d846a385793ff0719690346f88e8906d59d731b053
+       5961660b15037b718ca51d2162edbc423c42ff094c3a74c2;
+  000000000000000000000000000000000000004000000000
+       00fb58016823ff21666d4834be7777977c39dc524831f78d
+       16f43859a26050bab89f24747aa2f159f7f952a4f7d0b423;
+  000000000000000000000000000000000000008000000000
+       8888994bacf06498d6c65514458e0dcd5c47a89096431c97
+       84d3b8542bce25195af4c2c2db5278afb5c090980e978d84;
+  000000000000000000000000000000000000000001000000
+       5c09111b5f1d7071f9ff25551b298c3ce446aa3413097e62
+       583739a94482dd2d485b26f9eb11466298b1ad5c1acb1204;
+  000000000000000000000000000000000000000002000000
+       04aec49c4fb80d6561c745f51784f4f3d31547bd4de5a94c
+       e7f83b28e61a9eb7929382f435c7113a3110a08c7cb69634;
+  000000000000000000000000000000000000000004000000
+       8391493f0cff3eedcb9fe1bdd422793ee5e124d343b375f0
+       2d9e4938f6c4c337b943809490c1b6ff3c843bb0bff1dded;
+  000000000000000000000000000000000000000008000000
+       6d1246c48d1683a7fd7329c85ba193d285192c8831176913
+       32f271fc06af76ab98807731b3a47eeac2a107c02cf30196;
+  000000000000000000000000000000000000000010000000
+       3cd9d97a17d77d3f3e9edb8d72032b5f655f948b32f59e00
+       5d7c293fa62a9a1f91b0baef7efd96f8e35188f75cd8a331;
+  000000000000000000000000000000000000000020000000
+       cfcc2990da7be7df288d8be5f9be1deff14637612107ab29
+       e381e161b0b8bf30d3b28575c72f5605a83d5ea4d23a34b5;
+  000000000000000000000000000000000000000040000000
+       ac740d1ff0eacc8d57f042f7835ad95a80edcd3fdf28371b
+       7ccb5ead7d391d393d19ce552040dd00ee411901f82f53ed;
+  000000000000000000000000000000000000000080000000
+       177a0fcbbe76481f473a27bf63aaf2ab9d127e399a3c73c2
+       e21338988039b5aebe5cb3d5b632250b9801271a117440cc;
+  000000000000000000000000000000000000000000010000
+       96ca2977c2f58083155573e55b681ac307b40e601652836b
+       678a557c88b2e1df13ac012a7104d40d33349b981db71476;
+  000000000000000000000000000000000000000000020000
+       0e7ba2f3476c82f01ab7fdc7203ad2cfca591ecc829d8409
+       daab2f21fd15fdc90a7cb7a6a56a0d0c6942ae2b86113373;
+  000000000000000000000000000000000000000000040000
+       b309f8daf59f74bac80f710fe07350f899bb1492f24e1425
+       aadd706e551425657e4e8d5138a8d13337d53346885b2ecc;
+  000000000000000000000000000000000000000000080000
+       2d392f58a4b220211b884f4287ad76c9f9515ec47c284290
+       9aa9a624109b06d5722df543b3b0e105052ad578b54e47d1;
+  000000000000000000000000000000000000000000100000
+       cccb9eb8fc84365765163c40bd24b6bb51a45e7345bd7a14
+       6d9e8097f75b13cb808d2c44efaa556a56aa7c9ab8106563;
+  000000000000000000000000000000000000000000200000
+       78a5d8d79b63dc0324761e93b76a7c79d6455539ffa6f088
+       8b6df918ec48a084ee472612bf14b3611a9a9c10660f31a7;
+  000000000000000000000000000000000000000000400000
+       c8240b82b4e438074aac4a34be3d0b01b3b7a5c1746f5dd0
+       5c4650702bfc551e85a269d7f97fd98d49db0f45f40ea608;
+  000000000000000000000000000000000000000000800000
+       e6880f3681fdc188ceab24c0c1cb3f90357fd05130687b07
+       f53ef53b6216d61118877eee6f9406f076a9b8bf4b31ad9b;
+  000000000000000000000000000000000000000000000100
+       c734620cda2c3f3b71d8195949898c8740acb8444fa9e1e3
+       2083e8448b090301f991ac6687179d6773c128dee6aff608;
+  000000000000000000000000000000000000000000000200
+       2f67eb665331c85869ce51b067c6e6e94cc8ab45fc71407c
+       b61d957135c33783e803e9e535702f2818c21ff62be94c51;
+  000000000000000000000000000000000000000000000400
+       d590b7a848006f402461a88874eb9b5d9add7ec80c81b154
+       febf425ef71bc535730788b70bcc2833e08accaeae7e9ee6;
+  000000000000000000000000000000000000000000000800
+       b02090c689481635b33f992e13b59eea15aaf9f25b778979
+       417ed646b20cbab90952020eee8069dbe00f18d2572f8d72;
+  000000000000000000000000000000000000000000001000
+       ff1e358c8bd643176d87f75c2175c4b66ab1ffaf0079c012
+       b06d3d892f6d85bf268276d7102d7471eaca99b16260a39c;
+  000000000000000000000000000000000000000000002000
+       57d86ced26040b7dc14c2f47cbce1f5c70398ec902d6d484
+       d8ea3cdcc2566d14f6d996971796161e493677cbad536027;
+  000000000000000000000000000000000000000000004000
+       1cbd6500cb1061ae856e10557c84f085d340b5ac6394de48
+       0fdb3c9f37cd7b03b4ad10a5a090afaabc9eb6e623721af1;
+  000000000000000000000000000000000000000000008000
+       18975b942cfdbe8391c4e2a96e03df6cc3d44d1be1fdb697
+       86f3a467cd9b71208dd75efb91fc77a1dcc25dd45a6002f6;
+  000000000000000000000000000000000000000000000001
+       806011240d6c13fab000555504cc68fa756d5c0cd85d2933
+       7793edb94f67a425483b90cc7b869880143272ee85ca2ad3;
+  000000000000000000000000000000000000000000000002
+       3d04d556fbf1d4dd76fa97215fe58c170d0198c19d5a0b8e
+       850321dd6927deef53ce43fcdd07df6a3aa1fbe0d26026d6;
+  000000000000000000000000000000000000000000000004
+       b1a243ffdbccf642800db3cd11beb064a2674f49ae9c6550
+       850c7c28e1d1dd64373ddb8388755325671fd7cdf34fdd2d;
+  000000000000000000000000000000000000000000000008
+       3705ff7df146cebda207c1fc2348252f28156b752e9cd167
+       418592dcaf9178228f66511810bfed87e7ac9d2a138d741e;
+  000000000000000000000000000000000000000000000010
+       a4597f7b0bc5b5cd53bbc04d644901b385d2c5d03aa0e363
+       f1f007c32f306ef45e0f78c24bbdf7507a62e44861c1d579;
+  000000000000000000000000000000000000000000000020
+       3f2e6b8d77db0bb0f4dc09f8b3f5ef841b65f389194865ae
+       d50dcc3d890fac6c458ffe6334a2ecfe329f9ccac8bcd609;
+  000000000000000000000000000000000000000000000040
+       db05a0aed5d55023dee7dd6671cbcf71cfbb29c10c4babd2
+       8925fce6cf19f3b2f34d61b894b213a8c59e69a3993cfdb4;
+  000000000000000000000000000000000000000000000080
+       4c73cdb5851ef5a107ae0acc485cfe49f23051ada2cfba2b
+       dc81803c4aba313b5bf42236e208b8bf66d62810ec0a8fc8;
+  01000000000000000000000000000000000000000000000000000000
+       e466a171f30130c5886045ab035a744b80a63cf10ad50670
+       7d0a3d9a3ad5af4590a18eab995623914ab2377cfe35d3be;
+  02000000000000000000000000000000000000000000000000000000
+       3979486436134c0b0d1cbf612b6745e7a43038c176e50759
+       dc0c555a7b1425e8d83ae80934676ece2a2f8a654196dbe7;
+  04000000000000000000000000000000000000000000000000000000
+       517b1b4b00e143a73e315298830e0fd8f0692549b4efa53f
+       b47ae72ce84e68257377022abb9cbb566e58c501e1ae8956;
+  08000000000000000000000000000000000000000000000000000000
+       197c1cc090ee4f199c5573cfa65f6bc84ab8957fc8c2be23
+       a56f67e2313fcd2fdf621da945eef4e31a8fd9d0445b1b66;
+  10000000000000000000000000000000000000000000000000000000
+       d59e9e6be1cefd6881df7772eeb46295e7c6ef787264ea73
+       9c9bbcab22f66a437538d795d041399093f694c669b2f559;
+  20000000000000000000000000000000000000000000000000000000
+       de47466a965a4d5d92eed3b856591fbb787ce6863da4d8f6
+       94a4c31a6e8418b46529e547d7a9aa0e1d2962a63eee5654;
+  40000000000000000000000000000000000000000000000000000000
+       36dbd72833a532f365e6be111aafe17c2fd49f21f4eaad76
+       6327e174d21ea698cf34bffe36672e7ffa931abb615148aa;
+  80000000000000000000000000000000000000000000000000000000
+       c10d857d362ebe177aa6b240bb27340b0ad2b283cbaaa84f
+       184d05e1651645e67d0d42eea84f4a8c56972014aeab4602;
+  00010000000000000000000000000000000000000000000000000000
+       b23943ae799651f7219dad8ead93d03c4eed373f6389b117
+       ff33f2564db3a027b45f2652ac244eff9d5641212fe33a33;
+  00020000000000000000000000000000000000000000000000000000
+       9126da9f43bbdbd9216f40c2414236438b5520304f21b2fd
+       f7c8bc04d48f4b18f44044f6a5175b67e5a0369475e38840;
+  00040000000000000000000000000000000000000000000000000000
+       d73e01f210826c0205aaad28db4cb341804a696f1b683a14
+       47632f2712f7d9a63c7fb8c1462279e3c5d824ecfe35d3d3;
+  00080000000000000000000000000000000000000000000000000000
+       3a8a518775a687bcd6245cd6e8504765275b7c9df76817b7
+       884f7908451106aa852323dee7b353a4b1686cc7f74b738f;
+  00100000000000000000000000000000000000000000000000000000
+       c054a470e6d41003d3b20ba165d391cdc934138b55ad957d
+       2ff8dd62427119acf5427b73db572167f953f778b5536a3b;
+  00200000000000000000000000000000000000000000000000000000
+       ac86f7a300e3f4b248c17113ab2a5ff0ec5aa11c26f7e9cf
+       f391deaba561f263728c3810c4246bb850a38c22c3d0ff22;
+  00400000000000000000000000000000000000000000000000000000
+       ed1cc342bb9b9f0463f8254343f79ef3ff75359bf78c6a06
+       e657015d282084ec74214fb5926eacebe91b2b0818cd96c2;
+  00800000000000000000000000000000000000000000000000000000
+       275083f0158e81bbdb5bddd8471d4346d2dc2dfdeda59d17
+       85405f2ff391329b38a6bcbaec9890fd5f6c27c43c4d42ae;
+  00000100000000000000000000000000000000000000000000000000
+       5d875aebf5496ef91d1fb5fd6b7c10ca3472ac04190fb5a5
+       30f8d4f4e34ded31074ab7bdd98cdee6995f363361dfb67a;
+  00000200000000000000000000000000000000000000000000000000
+       ea05609c5f54d16590cbf9bee2fa008f60aac96ed40148ae
+       0356240ac83e1f2874e37d5577009d79cea8ab677d05d35e;
+  00000400000000000000000000000000000000000000000000000000
+       241a143eb59063bcf573483f0453cd3b7c20613e976e1677
+       584f0cef868af6aae2474278099ecf8d9af01d1b540c1853;
+  00000800000000000000000000000000000000000000000000000000
+       8d642d6c2ddeb938e63fe0da1f84700ae21c35317652dcf8
+       e692d249d7c24d32555f7a69d88980e56b33e95659ea5182;
+  00001000000000000000000000000000000000000000000000000000
+       abe335a44913c306c289a66bdc6551dfaf69febea41c73f1
+       669f21ff2d1979cf255d0f357d477f62a2c376e2f7e49ee4;
+  00002000000000000000000000000000000000000000000000000000
+       88ace268351b45c9ad63579ad01f5631fc6ac91d5de6ef19
+       065b1d6414049be6fd09ae8f4cf9101e625ac3781f146a3e;
+  00004000000000000000000000000000000000000000000000000000
+       a6d8ec0b3de91563f75df992e97a5f8565333056dbeb5495
+       c56801660652b4d8973edeec960f6c606f553af746e7fb36;
+  00008000000000000000000000000000000000000000000000000000
+       a159457dde64aa20ffb81591e52a684c4f01f224d77de994
+       2ce28f10c61918f29a4ced6d5969aad3e26397d68b273e3a;
+  00000001000000000000000000000000000000000000000000000000
+       0658da014d05ae4231fb93096483492482ee0ce8495a482d
+       945a27517e687cd2fd0d03c57dbdea162b4fe10d05081869;
+  00000002000000000000000000000000000000000000000000000000
+       85ca27e90b91de2e400a59c00ed82116302cd2a1367c3411
+       fb1858e39f2cf75d36fc308270510d9710fc6bab72fb3162;
+  00000004000000000000000000000000000000000000000000000000
+       fc60f7ea828f3813eba9d5136a34ce868510a6f5c9d61124
+       74fa96b782f8e68a9b93c82ff428feaaa66a75331df5e98d;
+  00000008000000000000000000000000000000000000000000000000
+       49a4c0b759451a9047440e8ba0670a750a69f92aab520c26
+       4e1631c860ed0a4a9917983f15f889383860921298bf76f6;
+  00000010000000000000000000000000000000000000000000000000
+       090c2326593b51e1dc6d59542c8ec15d2f60302371489e36
+       8f961912ca14f7208c5608eea98208eea9d45255e5f4c900;
+  00000020000000000000000000000000000000000000000000000000
+       04f1eb6340739f6c37e3b0571b1d41553adfb376053ce64d
+       242c48e139838ae26843e54dc149b154bf3e8c490fe0f1e8;
+  00000040000000000000000000000000000000000000000000000000
+       ad61378d9b886d236a585a35749caf40552a018246cd8203
+       ea01b68642d2988df8d124f74dafa6abf853b017d4cb5496;
+  00000080000000000000000000000000000000000000000000000000
+       5291f7145b376f42de91b492a803c3da552d1bf3cae38f74
+       1bbcbcd28382cb960e12663fa17ce99d8fd996480afdacc8;
+  00000000010000000000000000000000000000000000000000000000
+       3283a8ad59723b954c26d32641e1aca7ecc37cad79757fb1
+       331cd49fd0def48a4c449efbcb35b3ee20552fc441300884;
+  00000000020000000000000000000000000000000000000000000000
+       1e9b00edfb67ee5e7e72d5bde45c69dda0f0b9f145ba376a
+       b11264164e9e70271ea379123bba996844d8224b2c4a5792;
+  00000000040000000000000000000000000000000000000000000000
+       891d65411edc72bfad04c2b32dc4f3daa46fdbcdf2295b7e
+       7019b3daf1d8d054ced0c9b41903c328cef85eb8b30490ed;
+  00000000080000000000000000000000000000000000000000000000
+       a692a308739c497d2fbc905d2c1212d9ba02b5c896330480
+       87747a33be359d180b13c7c2da559adae20d7e3fa677d80a;
+  00000000100000000000000000000000000000000000000000000000
+       a646d48b3a7570c884b7d20b3ec1910062742ea29f9b87db
+       6dba393a5c0c22f991052587f2d03cbd6fa1b97032ce8d70;
+  00000000200000000000000000000000000000000000000000000000
+       b9980daa0335682e0d5f943db1d63f76a5afba294b00c894
+       6dcff8118dbd4938d98327457b611b78bc6fc3858308d44e;
+  00000000400000000000000000000000000000000000000000000000
+       5a6d143a6bbe108a8e865d262700c5e3d681a864c9bf2889
+       bb00e78a312810a37d218fe1e898e34ba684df92d5df8a80;
+  00000000800000000000000000000000000000000000000000000000
+       27b44c0f87ac23ff95a31e1b328d928a1c08104a3d67a9a2
+       2d2fc5dacb8cc5cb49812ff3fb4c4dc710b27126aca8af6d;
+  00000000000100000000000000000000000000000000000000000000
+       52a8962f43e282225863b45fcbdca1c7970d05cdee3661ae
+       0138f4025e6f693f784e26c368f3e99bfc912da83619df70;
+  00000000000200000000000000000000000000000000000000000000
+       9d778e66c779bab53e8bd4cba07121af23a00a64f2d69033
+       74818f00faeb596041c9f60ecf7fd36ce6ca568bea39cc20;
+  00000000000400000000000000000000000000000000000000000000
+       541065c87d92ba58c18ae8220da27a8d54ad7741989ad6c8
+       4c5ed522130b99c5d54d6c9d500e04646deafd63003904ef;
+  00000000000800000000000000000000000000000000000000000000
+       2f20f79d4c2b14d94977d1079c3c94c781df42adf3d6901f
+       ff0efe5eeb85df42c23a1c7cb86b3ef67a423f7dfe4a8ebd;
+  00000000001000000000000000000000000000000000000000000000
+       2e5c45b439d98cde7dd553cc7f6d55867792f2b97d4096fa
+       432b23888d0e8efa3ca6e7770a9b70add2d31113d187cd15;
+  00000000002000000000000000000000000000000000000000000000
+       dc84f5bf78bed0ec4011a808b3ccba862ffe18c6bd0af093
+       8a7df628ccdb8d0d9527d0ac6a2a37cc3496ce920a6549af;
+  00000000004000000000000000000000000000000000000000000000
+       a8950cd163f3bcef61d2fd66c2c84a7069498f1a4480fa9b
+       a52e41655dcb9f4419b3aafdeb1b388fdea9ede2eb71d55e;
+  00000000008000000000000000000000000000000000000000000000
+       48ec823bb0601d23644fecaf15522422ebfc773c6741921d
+       a9f9ecb94e7a4a0f6196d9f585f981529aadf5b1ee13c5aa;
+  00000000000001000000000000000000000000000000000000000000
+       4a360f8b6fb99125be62dda9f47fc5568119ab2e76dcb2da
+       a2bb0963d479e76d1f32a7e724ca64982093d519649a2676;
+  00000000000002000000000000000000000000000000000000000000
+       5628f1141e35d240bcf5ec4bfadb44376b82edc1c1821181
+       00fe7d461f3b521fe1d76fdfcfaee8b2f95be74121660550;
+  00000000000004000000000000000000000000000000000000000000
+       6b7e5c402de45b783cbf0bc2a922f034d93d41dd69a02d98
+       4e64fb1db55e3b0c622002306567bd38068dff297b8caddf;
+  00000000000008000000000000000000000000000000000000000000
+       2a0a0ac9f03ce1be0f6a913cca6f12dafb4ee79af1173aea
+       da2b5561384eedd083365dbfdbac266556f306779654a946;
+  00000000000010000000000000000000000000000000000000000000
+       1c1b4df7b4f126620df92c52fbcc07d7b8a5aa44f3e5f1ab
+       46626e5971070b4cd57d5b49f3b3e228e2dbd1b9798e79ed;
+  00000000000020000000000000000000000000000000000000000000
+       5682d5056b30cd7b84911adaf1af2af99fb16fe82beed222
+       a62abeb1341cb2cc15a3947ce8b571d2b48ebc7365072e2b;
+  00000000000040000000000000000000000000000000000000000000
+       f20e8c97b521ed21e72686e503b30412060626094e2569ae
+       caa011296fd4dc935074560a2608c9e1db2848ae25f4395d;
+  00000000000080000000000000000000000000000000000000000000
+       461dcc25da2c567f2c330d1ba39172451f8b0c1e4575623b
+       e4a8929a202cd9cf07a3a914d900eda1a1aa79dfe332fef6;
+  00000000000000010000000000000000000000000000000000000000
+       179913568dd00f3c3e6638fff80b19078f605d2989b40f4e
+       98901d6c7f82903c81fb45e93a8d70b2126a40465cc82536;
+  00000000000000020000000000000000000000000000000000000000
+       01d0dd28e61252d14ec58b782dc7c777f3e88a652014bb84
+       71802a1c775ec9574b443f5ff43868d8df47620e291aa4be;
+  00000000000000040000000000000000000000000000000000000000
+       0f6ebfa8809b841679990649948d76b1d79ec12ece1f4751
+       69f01483dd242bf68434e66b66fb25ee6115664ce75850ba;
+  00000000000000080000000000000000000000000000000000000000
+       089df5d6f5a4f9967693d8872da3808eccabe037cae99337
+       95ce5e283ee609b6d62bbeb996d3c99bc11e66250f2884d0;
+  00000000000000100000000000000000000000000000000000000000
+       da907941cc5d4349988756b71b3d625ffa68f36ddb5b76d1
+       ab0b6cfc89a17453f0a7e76216d4c134d8385732e8b7ea9a;
+  00000000000000200000000000000000000000000000000000000000
+       61ff06d4942fd9296587bdfba1e8e27d42d7701ac7efb31c
+       69f0acaa8622c8d71497ed99f646d033d81b943cf2da78f4;
+  00000000000000400000000000000000000000000000000000000000
+       6bd9b77d87473a6501421f565884cc9bca0ff6cdbd8608cf
+       c25e725bddaead2ac2c854d645565cff9d13a49325318470;
+  00000000000000800000000000000000000000000000000000000000
+       779ee5f0fe88dc65da96ffda43e5bbd77fc34efa0eea92d3
+       1d32b8d6e4ca8735ff8489f3316e5dde7eae25346199436d;
+  00000000000000000100000000000000000000000000000000000000
+       dfe0750917dfced0bfdce54668950a91b3697636a7f622da
+       785410a4bd7246c3f351ec3c17dd4fbea179d282bd3edd35;
+  00000000000000000200000000000000000000000000000000000000
+       d88b50720ac2b514d8e32766e4c10f52099b7c9dbdfa4639
+       ee78f304793920cd1996322df67166ccce319c7b79aedbca;
+  00000000000000000400000000000000000000000000000000000000
+       40297cfb793bc7411ac6a38c2f5e35f13e076c96e3ba8cd7
+       8b19a2d7268324413e76dbef51d544522afcfdb234a80b79;
+  00000000000000000800000000000000000000000000000000000000
+       bf474a47de1427ffc76f22f85fdcb322eceb654b82ae1476
+       c1107b5c9aea17142905e7423c03ada55b4de08d68551412;
+  00000000000000001000000000000000000000000000000000000000
+       5430fc20a9a834d033b1931d41c692682a389b6bd68abfb2
+       d5007648b6b5c9b3ce44fe8c8261af3509f2854bf12bca03;
+  00000000000000002000000000000000000000000000000000000000
+       dc814d7cafd842955d624394a5885e9900fb48302c02079d
+       a8507e6a2969200463221a3d8baa430a65dff06e495d54f7;
+  00000000000000004000000000000000000000000000000000000000
+       eec73ecf6bda3f4dda70ddac567649e3acae53c79973d91a
+       43eb2159dde1ef21d0fdfe7d0313f5d608b12ae157c0175c;
+  00000000000000008000000000000000000000000000000000000000
+       b31185b8c7a09b6c8431604c9d73a92cb0e368af1e109593
+       1621f258ac6562bf15900e46ee38ce54d17fa998a6718126;
+  00000000000000000001000000000000000000000000000000000000
+       861599547a7005f367bcf4bb2d7e77d23ae864dc0a97f3a4
+       e81d4a8675c7805ae2ddfc663db35f050decd5bfd14f89dd;
+  00000000000000000002000000000000000000000000000000000000
+       4fa5147d9ec4057b649f7cff1202fc99cae58e1aefccdab9
+       064b3918cd10ce4f246d3f79ff52e3fb20f770f07e942b01;
+  00000000000000000004000000000000000000000000000000000000
+       35eaeba3a19c8fcbe86181577734db4cc2ae23a0035fe2be
+       6338c7f38226401f0a4c72c5c4a43a14ffcf0724f7cc579e;
+  00000000000000000008000000000000000000000000000000000000
+       843eb5da5349484b83b951550554fbcffca7c80861860b84
+       1d127da43d43487a2221c36ee63ba71f75e6e7254307037d;
+  00000000000000000010000000000000000000000000000000000000
+       39864279e3c8580727d48936a1620cf01667f76e3c300498
+       137a5254e5815de51641a5d15b2691b31e08512537427e3d;
+  00000000000000000020000000000000000000000000000000000000
+       c6d896c129ea56b02c159cade2a6cbbc974ec04ffb4f538b
+       e546edaf391396e7c5cfacf94cf37ff79ca56a0418872860;
+  00000000000000000040000000000000000000000000000000000000
+       f35dfbaa8f13910ba7f3a9de5a9fd6f36d8dd8a444fd3144
+       b3882f070df1375e3e84e933de4e4372ccd8dd84923d228f;
+  00000000000000000080000000000000000000000000000000000000
+       ea26fbac4c2c5e46100785a99008d4ae890ad258918aa18b
+       768ec538c5f61bad6e7b49ae664ccd4ad481c8c37f317b31;
+  00000000000000000000010000000000000000000000000000000000
+       477c6bc073748fc4c0511b0d1e180315530037ef71cb4026
+       7d8bdebdcf35e2c38c6d9d19bf97f6fa76e75a3f9ae22e9a;
+  00000000000000000000020000000000000000000000000000000000
+       655699d22c61a253572cd6d4df64d4fab06874c340e95783
+       7cd5f30366d96ce31338f5438263c887d4698a2d1f826509;
+  00000000000000000000040000000000000000000000000000000000
+       accdb0fada298f97c199b0b75ebec0f8eda6c819a322cc84
+       839916db991581426da7dad428a2ce1f1fdfe0e94551e45c;
+  00000000000000000000080000000000000000000000000000000000
+       710b2db656a99904896580bc97453f7af6d40326f8ccfa0f
+       a02c312babab962db4503415f05d52b2f30bfcc35869f08b;
+  00000000000000000000100000000000000000000000000000000000
+       b09a7b21b66ea4e6409b36515c849ab0c89cd4793b86aad7
+       25d64c7e387e9f7fb9bcae80fcb95e60ee764b4b91f5a623;
+  00000000000000000000200000000000000000000000000000000000
+       961df75dd24a7f370750a17c2025867442411790e604c7d5
+       762b027acee1b991b90b83f9d918f2f74e84383f425c64a9;
+  00000000000000000000400000000000000000000000000000000000
+       d9a3a55ac9d2517b149b2a6981a1123c0d9b4abe03982e03
+       cd43bb557f2674593b8692472f225fb4c7f5f207ea1ebcf6;
+  00000000000000000000800000000000000000000000000000000000
+       3d42aaf1230930786e7febf219ff6c90759295547a2c0e9f
+       3a00b929fe7dd2f848d9078fe862bdc1abfb0b242f2709a7;
+  00000000000000000000000100000000000000000000000000000000
+       4dc0cb0a3d1ab6fffab767a4ef3d47f029d9f035192d7dc8
+       a10e7b96eda011b4b927bce0d98b6822540b9b7521a22b57;
+  00000000000000000000000200000000000000000000000000000000
+       5b23eaf61681e3574a8a097d763a3cd828626b749851ce7c
+       fb624ad9a049613c27011972f01dc669560322040aa7c4af;
+  00000000000000000000000400000000000000000000000000000000
+       f6db6f3ddbab5d3228812a70fba910ed17ef493b8cec3ca9
+       dc3c24735d9fa10c848f9b09a9fd8514ea4c1a576f8ef4d8;
+  00000000000000000000000800000000000000000000000000000000
+       07f9b15343927460366de4a9ac3f819566e670f4b58a00d3
+       bb6bfb31664ac99f9af977589ada9831b121ad90466375dc;
+  00000000000000000000001000000000000000000000000000000000
+       a305415baba5afdae40a6f9a1b6e8e3232e143a7f1138c6e
+       5d4109fa28245a22bd6c812016617e1aaa21c9e5b5cdf87e;
+  00000000000000000000002000000000000000000000000000000000
+       74cd6460d4ac168edb0e544890907cd954c24c468ed87848
+       0ce59ed2694fe93103eafe67f702b32dd5545e5fa53b261c;
+  00000000000000000000004000000000000000000000000000000000
+       4cf6e84f95eda559ec34c93a2e4ad35325e0885642d4dab5
+       6e8d542ff0d468d44331de0482b9f483ef1e81afce8556c9;
+  00000000000000000000008000000000000000000000000000000000
+       223fbd1515d17968e6365920d08afefc8dcc1b7aa1a48a94
+       846cd8e79252fddc2bd9dc79047d55c96158dd9834e79e43;
+  00000000000000000000000001000000000000000000000000000000
+       3d42cf134f2ce3f69168b13b9104bf20e720aa1ca5db3abb
+       076f0dc3b495de14b6626ef3986cf70fcc62c73101b3c00b;
+  00000000000000000000000002000000000000000000000000000000
+       62964b3de5a5f29fb46af05e22e604adc0ddd469023572a3
+       b53b2d9fddfd2e9ea18258fcc56afdefacb68000766cb625;
+  00000000000000000000000004000000000000000000000000000000
+       ce9999154c2cb7cac5bff38080d9cb5bf7e25e48469907a7
+       126fb43d45542ca289681f8a96f1eca1f78065dc3d563476;
+  00000000000000000000000008000000000000000000000000000000
+       c316c04b5351c4a9ab217b997403bdcd4b6b0cdbeeb61020
+       8359e9725a86108c9e9df165c8db8dfd97ef0c0d5ecf8700;
+  00000000000000000000000010000000000000000000000000000000
+       037524620d481439f805bd9b97f564fc54fad6d68ebf6d37
+       1a3ce3addd3aa06fe3c0851bb36d6484d00b71e2f7f24f93;
+  00000000000000000000000020000000000000000000000000000000
+       678374857cc068a2a29348279f2a9ec8edfecc0cd658defc
+       b22c3aaefa728e55ac29d4b624eae74248f3f983029b4b30;
+  00000000000000000000000040000000000000000000000000000000
+       dc8f9708feef6e43a07c93abff90668180ab88838767164f
+       d3afd33038af52da8546589a263cc81dad1d99d156b321a5;
+  00000000000000000000000080000000000000000000000000000000
+       6eac02f84c3e0ac288f692dcbef8ae12cab31fbd53d97397
+       2ad2aaafe7a7ac392fad7a0287fa2f2d2681dab726bf44a6;
+  00000000000000000000000000010000000000000000000000000000
+       efe7d7c2bf9e3822761cdac372165820b9ab2ec899424e8a
+       cb3757944a16a71ec99813133ed5745459defd3bbce8bc73;
+  00000000000000000000000000020000000000000000000000000000
+       48b83fc1b61f1f635033c366f9ada4d79966f82a68764c7b
+       0844cda500c0ddeaeed7b63f2223877838f379aa7504661f;
+  00000000000000000000000000040000000000000000000000000000
+       842e81ad0e1d515d7cab6f58288c30357dbc621387091fae
+       9afa55ddff3b59ff3a6d3b52d011ea090cbd32b56f25ecd8;
+  00000000000000000000000000080000000000000000000000000000
+       de27653b243a814cfeeb90eef9d612ab98224704e328923f
+       093aab7b15166c45d7381decbdb00d3fcc62e59d6d3fbc59;
+  00000000000000000000000000100000000000000000000000000000
+       80199c47a849f02460357ba7c920b4f91007ccc3572f8a95
+       975554126ac6b55767e57be44de8141f83d2c6e88371c207;
+  00000000000000000000000000200000000000000000000000000000
+       18214d1c20eb598db7ef9e19f66b41be9a3c6a28a2a06c09
+       36d76057e43f8033756217742d563bd811e1130b9273a3ab;
+  00000000000000000000000000400000000000000000000000000000
+       b02556b90f7846ed7ef080a17b6131cc6e34de764fedf66f
+       c5a1433480f37105516a2903fbf4a2cadf94061dad71dc47;
+  00000000000000000000000000800000000000000000000000000000
+       67f22905a1db5aa9dbc49b92986a0e6a76f555b26fa844cb
+       9197f321a515351baf650e1375ccf1d0964653e35e4f2f3c;
+  00000000000000000000000000000100000000000000000000000000
+       e684a0b52b370cb0d1a56313d388a136108c642d3b39bc9d
+       62943cc6636002312b13fa373109f4291ccfaa872da2ee77;
+  00000000000000000000000000000200000000000000000000000000
+       5a4dda4fc12d0c760398b47169e470f74446acb791559bc6
+       0bcd3206810ee183fee9b0bb838efa857d695ca3e7ed1253;
+  00000000000000000000000000000400000000000000000000000000
+       9fc13edf3cd388716e9f4e1494d8a0a96281dc961d4548a3
+       a26ac7726848e147e7ced7cca7e4503ee20f42705fcfc755;
+  00000000000000000000000000000800000000000000000000000000
+       86f93d79f1f26b011541ae929aa31b9a4c84e8c4d880d5f9
+       c967183176facd949e28f687f2086f29a6b6c955d64b6178;
+  00000000000000000000000000001000000000000000000000000000
+       2dda65d35ba60b691738ab14de4aa36c4ab68618547f1b4f
+       0db07d9558e660576689ff6572d2af9edd01452072c50fb6;
+  00000000000000000000000000002000000000000000000000000000
+       90a296d7040d9ee0fd061caddf8e617c536560e397e9725c
+       69a73a1e466811b91368ca4791ac75045174f24c389aca14;
+  00000000000000000000000000004000000000000000000000000000
+       466cf4d9755f99cfe79a8d73f0e9274e266e6acae13155f7
+       83b4f7458050bfe285c60e56424314fd6b01a6194fba4960;
+  00000000000000000000000000008000000000000000000000000000
+       93d678400420bd1d482812485d96fdb170b4f055e1bf98a4
+       400aefb2a3dcdda2e48195eca5b600eed2a4c6c70db3a20f;
+  00000000000000000000000000000001000000000000000000000000
+       61a2973e5424ba1c6d3e276569114d4ebdfadf198bdeb004
+       12957492fc5e51fb9f87b5f263486bd6e9030ca493e40b1a;
+  00000000000000000000000000000002000000000000000000000000
+       38e6ce3158f5b500a01c1920345e2680695993ac084b84a9
+       1e11bdc8bc76b33ce64300760fc35e8bca2b8f7f8f708287;
+  00000000000000000000000000000004000000000000000000000000
+       b8d2cf2220f5ab4797feab4ac9bd35cbd2564dcfb099b5e6
+       3f66306393714717cc65e6a61242cc809c1a7c56f03ca87b;
+  00000000000000000000000000000008000000000000000000000000
+       2b402e5af6ef5af420416bf1f5a2ac86576443db7e33974d
+       61313e285d7928b69426ac7310ee16c80138c71adb9acf2e;
+  00000000000000000000000000000010000000000000000000000000
+       002baae76bcd86eda5bc78d008ba23b0d2e772ff31004297
+       ac9e2599d3b76610df2a492191e54ae52f2d1fd0583eb4b5;
+  00000000000000000000000000000020000000000000000000000000
+       bc03714729c9d4d276860ca7654dc3ff0956f84e1bbb9efe
+       90ea6fccf1b49e1dcde379e04fdc02ffe00e30e07d5fed1b;
+  00000000000000000000000000000040000000000000000000000000
+       aa901e454ded6dd58dfeb8204b59bad80b570ccf24cbb23d
+       22b08dc3430cb5ceca63a8a9b39ae41d6fd3dfcf95a1c88c;
+  00000000000000000000000000000080000000000000000000000000
+       b5e0906965a567b3784924265066b5a1756bf0cebd39518c
+       bb18608dc7c7fe6f59d011573234a4208a227f341bdd786f;
+  00000000000000000000000000000000010000000000000000000000
+       ae8b977065e3abf413f592cdefa3d2da660649f0e2f5a94c
+       82899bc15e3efebe9338ac27ee29ea69dccfecd7e649af51;
+  00000000000000000000000000000000020000000000000000000000
+       a0b0a11f8461d83fa6fa785cba312b64367555de2759d4e5
+       0daffded48564ebbe98f69964b4959ea0aebe5a28a3d5a58;
+  00000000000000000000000000000000040000000000000000000000
+       fa55efcb4c907fcef36a43f6c2608639b56ce2effad4f6d2
+       fb02f2826bf087101311832eb00d57a1d771d705ef70e337;
+  00000000000000000000000000000000080000000000000000000000
+       1cc3544ae7b7c2737b6bd7e2ac832d681434326a556df8fc
+       083d876d584412e85543eeee4512f059636c21f7bde4d3f9;
+  00000000000000000000000000000000100000000000000000000000
+       1d4fa6dc25e6fd24a5ff13a30f63e783860c6c671ef428c4
+       90863553710ecfbec99e8b2b415b4e4f71dd88f6ebce7e38;
+  00000000000000000000000000000000200000000000000000000000
+       45beef6f77bfaa83e25df7fd33806a7dc63175fc25c8a29e
+       39fe2f8bfcc92b89431b08d5d9e3788f92fd10b9d5e18e70;
+  00000000000000000000000000000000400000000000000000000000
+       28043c18a7e18389d6d73860977e2cb0c9cd282a267c5b72
+       17cb6c2df1e9b9fa149d0f0785f8f2f263da16ecf1935d89;
+  00000000000000000000000000000000800000000000000000000000
+       4765dfba04c731becb1085f02d4f5eda72689f4bae916ea3
+       5d3068aebac8cb3cf5516b77384dc3416e2b5e8c982bbdd6;
+  00000000000000000000000000000000000100000000000000000000
+       46f68d6acada331052225f714a5729c8116d19076f00ce44
+       e7d20a3ca6208e5f407aa0f94f79bdcf82ad79592a079ff6;
+  00000000000000000000000000000000000200000000000000000000
+       82b3c9ade76a91b3672754877beb7f1a2c87daec16b8667b
+       13edc9289453530b65339df5c6c82c0a31d9e0b90e3ac873;
+  00000000000000000000000000000000000400000000000000000000
+       f36b6f67f121d8bb7f5de602902a9110abc7ff403913f3e6
+       4407a45e633e76537036fece0a3c71c0f15b88027b3303e1;
+  00000000000000000000000000000000000800000000000000000000
+       03deea8338479826f1687012b30423234a36163e4aad49e6
+       9f7f6b5f8dd376aa0716651283ae9f0908f0cb4b34b771bb;
+  00000000000000000000000000000000001000000000000000000000
+       e853a06b951d48565445889b4e320bfe1c6b9084720cd142
+       aae2e8c15f771e0ed58f8a92ef4da29759c38de9565ea06e;
+  00000000000000000000000000000000002000000000000000000000
+       9d1546729f32d2188be60529b218bd703736f74e9f432d35
+       201f67b0162aced8172d99e73ab0a182154f3615f2e28f4f;
+  00000000000000000000000000000000004000000000000000000000
+       07e669da1d9c8e593fda3ced0eb617708f2ac422d43c45ac
+       1cd97e6d08da27f0daa041282df010e0f43908d8dd36b9c0;
+  00000000000000000000000000000000008000000000000000000000
+       6bf530e97b29ece372e7ba9a7831dfbf56d66936e773ff19
+       fa8388bd4a8c495383efebcc1416fd38a139db06a1729f4b;
+  00000000000000000000000000000000000001000000000000000000
+       5d83bb98570d03ed7b6e5288911100680abe75d88c9ec453
+       51b426c7cfa0c0b178ed9def654b7e777164c7c1d945d394;
+  00000000000000000000000000000000000002000000000000000000
+       4747797b044c2fc06cc39bdc2ed894585aad485e039b4988
+       79a1b62a586d5a72bbb16ed12d7b6692fd5526872388ce8e;
+  00000000000000000000000000000000000004000000000000000000
+       9f79507a0960c45fa87e8f83cc6699a4932ba4c15791bcdb
+       4a055efe90785b26b43cba08efbffd9de944028147f471f9;
+  00000000000000000000000000000000000008000000000000000000
+       cb56d08085757939b6542b8a6b80caac7508683cae4752e4
+       73a4795fa9184b465d6a6c3fbb3afee1d77daf4a9b4617af;
+  00000000000000000000000000000000000010000000000000000000
+       765cbda6115109ee35dd5132d1467963c8d01c98c45c3453
+       02c719a0f74edba7975927b1854d3508b8f3ac1208c197ba;
+  00000000000000000000000000000000000020000000000000000000
+       0209e8466c40204db5fdd3359b27e40920c79c1c63c6f030
+       9ffb260428629704470a539de1daa6f7afd55bd0aa2ba9ed;
+  00000000000000000000000000000000000040000000000000000000
+       5738c3f833379616dc030b4000f32d672d30fe2246aac454
+       5b92b0ac5fd6fc2fa16f09c3b561300423f6d85e30e3cb26;
+  00000000000000000000000000000000000080000000000000000000
+       f7675f3bba2be50634a853bba205f33616eba5716513e28c
+       5da69b1cb28398302f5896aefe2013ca82d0435550770288;
+  00000000000000000000000000000000000000010000000000000000
+       d3589f775c28ad54dbc5b3f5fac58c7f714b02a76c724212
+       570c32b8036aea0148294b6e3a7f7645716f4a34a7d391b9;
+  00000000000000000000000000000000000000020000000000000000
+       b3cbc1dcf7bafd4831b3008d60d90bb94ce50ad0cd633bf4
+       d12cfaf58ebb31eb52c15279b6dc2288d403c5095801bf96;
+  00000000000000000000000000000000000000040000000000000000
+       a4fbc80a9d9e447197727034ebe3b15160cbc7cd9f269fc2
+       199b46bf2f636e5cf1ec0f1941a82d8b6d64e1b663894942;
+  00000000000000000000000000000000000000080000000000000000
+       0c6ebfc561c10d994fd1475a2a3675341f7593f9f66cad31
+       6a8e9c8aa02e39174dbbde841585d9e874730a52d61649ba;
+  00000000000000000000000000000000000000100000000000000000
+       25bdd9705ce78a156f3776455ddc4581aa1aec50684936c9
+       ccbe10b3b46d201f199b58c3d19d1f9638d2886e7ce0478c;
+  00000000000000000000000000000000000000200000000000000000
+       613f897e927225132429762e4dda85c607abba9a858c8996
+       f76e01e51cea715d0dff5d54736c93bdfbf019c78a0bdd1b;
+  00000000000000000000000000000000000000400000000000000000
+       65e343dc8bb79912567a55f71e99b3feaf3ee50c427c6143
+       f0d0a8cb38b9d35d3b6aa98d14c323458dcd13e1ce4a7772;
+  00000000000000000000000000000000000000800000000000000000
+       be901e27296d7b03a1a7b96f1cd04fe3082ceae9efc53a5e
+       359b7c239f049c9643aae5cf2d928dbcd5b05a4cee9ac27c;
+  00000000000000000000000000000000000000000100000000000000
+       c4707ac4f4b93bcf32243d79dd30ec29ab7f36fabc2febce
+       c70cff93a2465945e80ff266fa22d2680caa09f4d3679f65;
+  00000000000000000000000000000000000000000200000000000000
+       d30d652d01d6935233b1c345293f0936146cfd487a2601a6
+       0b752affdb6fb51a9e4811e71bcd057d0c586feb5f992e9d;
+  00000000000000000000000000000000000000000400000000000000
+       c5ecb03f48abf44cfa91c989948e4a211a0a8843a74154f5
+       3fc154fc54f79ecdbdfeea0e394341f4f0b9947eacf35ef1;
+  00000000000000000000000000000000000000000800000000000000
+       eac3e4e82fd8888c86cd00b70624420bc40a329308291941
+       643b0abd39245647ecd9b49028267e84a3fa5f4c1528e9a0;
+  00000000000000000000000000000000000000001000000000000000
+       ba153e4e10b7e393efcac79f73f7a6a78717e866110a6c18
+       98e9a632cb6e6ce3b28f461d51d2f95fcb476f25259338a7;
+  00000000000000000000000000000000000000002000000000000000
+       2f5e5111f2c6689c1b7922f13b77bc21d1dcfa0548a365e3
+       7381da06831dad907c647f476b6b7acaa1c4f8bf39f906b2;
+  00000000000000000000000000000000000000004000000000000000
+       29289bc290af03cb098c53e68749b16d5622d3db2f3011eb
+       8844a8e6f3c043c0a6e1ad0c7f2aeea959e314cc794d7481;
+  00000000000000000000000000000000000000008000000000000000
+       2a2993ed185b84670e2bb7aba5ccb4144bff86ca3c3e37ef
+       76d2ab7bf99472ca115b666c932e90d21df5cb555e2d7985;
+  00000000000000000000000000000000000000000001000000000000
+       44a7149685be83061a8141f9f86fb598a2d2489af958237c
+       12d9cd9df6be396ecf0dcb2eea70261db337379379a56b41;
+  00000000000000000000000000000000000000000002000000000000
+       2a54c1eb6658e329179fa565fe8e70dcd325148c764f3278
+       6da20c81af891dc85b8b42aaa370c490e2342d401ed8b36b;
+  00000000000000000000000000000000000000000004000000000000
+       d002d417bb650e197d87823051824f0060127a5d9a80cde2
+       b6858026aee1cefb44780100c66666a157ef41771be03d5f;
+  00000000000000000000000000000000000000000008000000000000
+       c87daae7c988751a47c8b2defef5662711bffcda2b04c68d
+       b9f0df2039ed2a5645162dda2143829d5c4d6e6a3ce2bd66;
+  00000000000000000000000000000000000000000010000000000000
+       82c21873ca16ff6e831d9a630dc8edeef5c0e45233d9e653
+       10115819eb20be42ca003cf7b313446ffb522e1fd1e3878c;
+  00000000000000000000000000000000000000000020000000000000
+       d9209dc4bc41a359f42281e85ae7a815a372ee810992f297
+       38a198719939dd10ff3f978a6ccd182f8a2a7ce6c79f6d45;
+  00000000000000000000000000000000000000000040000000000000
+       7772821616ba97f2cd390075d0d207742eed03e4ef9ae8fa
+       4ba5d91e1ce3f521d1365157de2adc666222c222ec2d3227;
+  00000000000000000000000000000000000000000080000000000000
+       4c49fbe58fa73f8f6984924ee2feb30c11af06b6127c23e8
+       4a5c4b2cf401cdc8a8d42fa2c04065aa52f351b20b60df20;
+  00000000000000000000000000000000000000000000010000000000
+       af551b0b91cc045e718974bdb030e0f2c70c512aa2ea1032
+       a1649d4e580003a845693e8b25388a7b9789126e672548c8;
+  00000000000000000000000000000000000000000000020000000000
+       877e0d6ba70f8642e068805a01abc9f66f6ca53371ee07e0
+       9bad4b2043b8ca9d9045dcad8d3b85c1e7c312f54c93d465;
+  00000000000000000000000000000000000000000000040000000000
+       737a994ba01e24ff5a87cfc942c7e398b9fe8f5c36480f7f
+       206781c03a35312079afa8630dfef2597c886e9a8d6668d7;
+  00000000000000000000000000000000000000000000080000000000
+       f3699997c4c0df71ca34541d9326d4439ea2b6dd194ede4a
+       c9b558da91f88f4fb0f1ae1c462102cef0a0f03b5e001cfc;
+  00000000000000000000000000000000000000000000100000000000
+       258e1e16d13ce49d113eed5aa036400fa1967e8f9e3f2a52
+       8b3e40554cc38790919fbac7dc1ad86334e4df9c2a50078a;
+  00000000000000000000000000000000000000000000200000000000
+       edec557cf03cf9bfa8694c02a366ec44d552bd9034eba4fa
+       905b8240be31313ead25d8380c55f6d1a0df89179884b494;
+  00000000000000000000000000000000000000000000400000000000
+       a655d39d3d8b773c9fdde7c9ad2fe5f8967800a621b91aa7
+       23f9a1388e522b6b7eec35c9f1c027385f2f74aa8d9feaf1;
+  00000000000000000000000000000000000000000000800000000000
+       11ba6f9a3cdb2a23aa1b923c797b5ec61b8f67aecc8218bd
+       f2994709f5fdf5edca503eb14a1b237c272cd7a16c4bb072;
+  00000000000000000000000000000000000000000000000100000000
+       9f6c02ee484726800d87ee458e3c69fd4b44f3a93714a791
+       e489a54780e1d8facf73b69d02dbe550ba970997f292993f;
+  00000000000000000000000000000000000000000000000200000000
+       d11f7985dc2c25d01e3a830c612875b27459321fee2de1e2
+       cb5311c276aa3b8092c9a63b569d6b2c6f5738ed264029fa;
+  00000000000000000000000000000000000000000000000400000000
+       f3fa791265d231b06bf42f5d120edc44c080ae541f58043e
+       0dd8b041c1a3dcd2e9f79fa6b027ebf3aedfed442c4139e4;
+  00000000000000000000000000000000000000000000000800000000
+       21ac1c566d8473defc012313319fc2d8da50af71121186be
+       b39f67818cf2269e439ccf386aa13dd404ff5233b9345e61;
+  00000000000000000000000000000000000000000000001000000000
+       316273fc4a0b6ddd90574335fb8a0a20ed0a0104e70e9a1f
+       832163f88a2b62a4aaf619fea36cfa56d8979011bbb8fda6;
+  00000000000000000000000000000000000000000000002000000000
+       00b5c352659ab100326d110075c041f8217976ed3821547f
+       fb48516c09d9593945e71a141fccaa663e8df96a44eb9327;
+  00000000000000000000000000000000000000000000004000000000
+       6bc65cafae23e4394e970f4679861a2aafeaefe19633bb51
+       875173998a5e5ea76517c0b0a229219e0a5f3700d1fb75ac;
+  00000000000000000000000000000000000000000000008000000000
+       71d385beb370fc18c1d7173cb75b3b1f15d30d8e3ccc7cbf
+       1902091418ff8923ae4d4ea42fe9ce406a2cc5a394def524;
+  00000000000000000000000000000000000000000000000001000000
+       960d8a3ececaae6e42d47d39fea65aa3ecf2d5ab7140944a
+       a981274234e998b241ef58d3424055faa7f701c312b7f958;
+  00000000000000000000000000000000000000000000000002000000
+       5cefd34143969f72981162d8d10bf719973e9fbe7e9492f2
+       0ddeebd6797292c2f539f8f0a82dc646f42cedbe163f89e9;
+  00000000000000000000000000000000000000000000000004000000
+       f70b2d5be4989f4e7711d02c0bc03a7e1a8f8cc605e3a853
+       f7778358e0e77f7f7ef7ed5c41005f49ec91e4d45c3d8495;
+  00000000000000000000000000000000000000000000000008000000
+       89957ec9016662bfedfcb4872c182e648edf00dc59012050
+       b425631c3d6d683c8183590c99058c18c9c3d4cf56d10500;
+  00000000000000000000000000000000000000000000000010000000
+       01edcc0af8796870f0cbc9ca12d1beeae0a693fcec632a3c
+       f848bbcb8b7710c805d884ce13c231f7d83ff63444065406;
+  00000000000000000000000000000000000000000000000020000000
+       960fe2a9d448e5b2ab8dd99ec58a6c07c40b5af464631c34
+       55ae3aa987bdd74c63fd3b0cb5818557dc4f2b886a73d880;
+  00000000000000000000000000000000000000000000000040000000
+       ab20af3c5b1df2a2d9eea9a2c524bbc83fd1195103f76856
+       1826890675b9f2cd2b2af4b1fa67fea727f2b036bbd82d66;
+  00000000000000000000000000000000000000000000000080000000
+       c2261c4fa3ab84dd38c7ec512ac972a05e29b6ed65852e29
+       f941c28063eba8408762134ca5c6132a2854c545d7a64377;
+  00000000000000000000000000000000000000000000000000010000
+       3d9da2d2eaeb97d162cd86f1bb343deda244a304ed9232c0
+       77aaa14ed3e383a2e6c4455797ce6d683a20e280d5ec9ab8;
+  00000000000000000000000000000000000000000000000000020000
+       9a121137759cfcfe9167b57727df46bf5b8d35e54e813ab7
+       2536cd77c22795c50384c0ffb3c667b13ec99de25b8cc659;
+  00000000000000000000000000000000000000000000000000040000
+       8c308d1e799e8e4e483c0ed00a4468d06932c66c7fa66b4e
+       db1b00bb64b9011494de6a0605dd496d5ff97a89f7928490;
+  00000000000000000000000000000000000000000000000000080000
+       ef3da9e874c3c3abe1b6ce46bc78107e5bd6e5d4223c07d8
+       6c942783ad9307f21b698970e99be812ce10bec7282a809f;
+  00000000000000000000000000000000000000000000000000100000
+       e3465e5da4ac75dd663bbe7f59cea84db1d4cd987b659a1d
+       ebd3d5e7fd0495a999cce1d056b0e694cfd1167d277e41f3;
+  00000000000000000000000000000000000000000000000000200000
+       9e115d1a939d05b6a970dcbb27a1d29182117ae6f90a6b8f
+       7a0a4b5b59c7594fac6801ddc6b20ff56e6842ca0ff395d0;
+  00000000000000000000000000000000000000000000000000400000
+       eae903ee25f7c95a7384f4516e88d89ec8423789b8abeffd
+       1442520d0cd4a9342da833f247446e08e200369637db11fc;
+  00000000000000000000000000000000000000000000000000800000
+       134cb0fcb97808665bb77439cc40fcc189067eb89f8965dd
+       b101aa60872909d82906bc746f64d174b8eb2ad70ecf1abc;
+  00000000000000000000000000000000000000000000000000000100
+       2fdf734b5a69c30be8214ad46a0327487d97fa2f694b6f6b
+       87340c26b15fecebe01b98b3b86d3b0d434855c0d747c85a;
+  00000000000000000000000000000000000000000000000000000200
+       17c9d9be32dfb06cfbd47e8467d7464d85366a42fa7b1121
+       71065364320dc8ebf10abc71915b9a37fe13fbe8012be9cf;
+  00000000000000000000000000000000000000000000000000000400
+       b242f3fc2bbfbe89a3f0ca2605244b692ee7d96fca5ec3e5
+       ba5c15f7e1dea1c4c02d81b446b6b97e91d3f27acc3ece9c;
+  00000000000000000000000000000000000000000000000000000800
+       1389f6dbb847264179557e2a635c3f0cd843f5b82a457cf6
+       064d9fb5d2409e24bbeba7e45c4c57156c4fb11f373e76ca;
+  00000000000000000000000000000000000000000000000000001000
+       42f828955b36c547dfbad0c56d6b4d2f623ef52ef7fa2738
+       3e80ab94606fef79fec3d3bfcb8707d9726cbe27233cb419;
+  00000000000000000000000000000000000000000000000000002000
+       e23e23434169161071da977b4620dbe5beb6fa04b47b432d
+       9c1963564bf7a6473027442cb42cef4ef2e248090be98c2b;
+  00000000000000000000000000000000000000000000000000004000
+       e30e30336add2c54af49b3f2d172c5c151eb7dccd049f423
+       b8d3c3935a0470147bff00344d0a9ca5ebd06ea22bfd2d6c;
+  00000000000000000000000000000000000000000000000000008000
+       299e23a4828145c8c2bb7db4819b175ffd57ed50af2db5ae
+       791ff2f9a6f0dc8bee326d9eadd920da1edc5d2a17d327d8;
+  00000000000000000000000000000000000000000000000000000001
+       37de5c10c2e92a137264787163cb8ae954d81933dcf9cecc
+       29ecfaa7a976d0b3dc7edd2066cefe484ad12f9aead252f7;
+  00000000000000000000000000000000000000000000000000000002
+       0442bd68ddf0523120c45e5b858520cc025719fd408d757c
+       373a1aa3eac3bb1b5a96a20e8e65bc41c5894deb725e27c5;
+  00000000000000000000000000000000000000000000000000000004
+       4a6cd629968c0b125350dc0ff1ab3a603c0b93e9a3e56c1d
+       03779efb521048c170b78c8502b166d9fa5813527e504e13;
+  00000000000000000000000000000000000000000000000000000008
+       f4d8d2f1b211988847b5313b5fefb87ad44d824767c22cad
+       647f58392ce955573d3f741ffb51ec3cffb6fdb662996ab6;
+  00000000000000000000000000000000000000000000000000000010
+       980a235b4a173431de984f8210de069493a85242bf14f269
+       1b4e10e4fbba7103e91b9977a6e4f492f04318e3aaba2419;
+  00000000000000000000000000000000000000000000000000000020
+       647f56d74ca28c355462bedce39dc1dd85dad8aa5b1307a1
+       534a6e7b84c5303539ad359bf6c0603f29106f6333df6bf7;
+  00000000000000000000000000000000000000000000000000000040
+       da74d3bc915e164c185021b9085367232a1e10b8d063186b
+       86caf736c5ddc7b3e4c15644a19334fb805ac1d869a88866;
+  00000000000000000000000000000000000000000000000000000080
+       7343f4e043fd65520bd2d84e8c3edb26e617a654f05bf05c
+       e31bf2ac0a70d475260de31778ed39005cec782018514932;
+  0100000000000000000000000000000000000000000000000000000000000000
+       9f5070b134d17734e035f8382ad4c1f61f83a6a9a0667e1e
+       6c64f62e4376d0e962ece7e1aae286ddb0deca287e90b156;
+  0200000000000000000000000000000000000000000000000000000000000000
+       3749a578adb8406d74022aa37e419f6a1fc561da5d11f163
+       c59fb6c711df8e2ab61e9acaf513da8f1c76b91c272a6726;
+  0400000000000000000000000000000000000000000000000000000000000000
+       c8c990a321ea2a6a87066981b4982e89accabb0cbae03efb
+       b7502857ce96c6e469bfedcd3dc8eeb3f0326358bc076618;
+  0800000000000000000000000000000000000000000000000000000000000000
+       73e3d8ac9ed3560c15322b54e30ab8d2c2162f029663c79f
+       260b56cace6aef56377acf544c6899c81eff1a27c5d36f82;
+  1000000000000000000000000000000000000000000000000000000000000000
+       738f42325ef664ec8928bc526abec512b8ea953e33ed0006
+       2090089fd9fcc5aed2612744712dae81c09ff05e5e4d615e;
+  2000000000000000000000000000000000000000000000000000000000000000
+       e8f4aac282194e7e31743aa524f7d9b004d2e63e0a30511b
+       3b6c4ff45cf657d73bfe0ff0725b594a97d75a4cd02eebc9;
+  4000000000000000000000000000000000000000000000000000000000000000
+       6ca217b943cef2c7e222e163bfec73c9f2a5b5674a39955c
+       359b596401604ba4f686b1f81dfbc33e6333a6ab054d9b5d;
+  8000000000000000000000000000000000000000000000000000000000000000
+       ac011f99d6766074346e8155ac4a132558775649391ef793
+       21a191c34b73b95fdec1b26477ba3711c668e7e03b9e72fd;
+  0001000000000000000000000000000000000000000000000000000000000000
+       1bf0e285f67aff5b9e50c33f72819e4954345c81d4bf4d70
+       82e9cf04f361e790544077fded5dc925866c0f6598016e62;
+  0002000000000000000000000000000000000000000000000000000000000000
+       7af6bdf52d8cb70ad56ba7ca466315e9431c9be251059915
+       ab68dab956704aa49dc6938771e720d53afb6c001a9c45dc;
+  0004000000000000000000000000000000000000000000000000000000000000
+       6b64c2b68c3a70c98a3a27d73fde094efc351355708bb8e5
+       b3e7e648edbdce4024fe88afd65bcf79756146f37ba2b523;
+  0008000000000000000000000000000000000000000000000000000000000000
+       bafc3238aebf8a428a560cf351d235dbde917cc1743c94c4
+       2bd0b7ab6759ca6461974b402f77287d4047b6c580ed057e;
+  0010000000000000000000000000000000000000000000000000000000000000
+       e3c12e9c2d584133495b3ad8a93a18303809cae7ac8a5c35
+       01f1f0781ab946f016082703b7a5f0a8e2538e6399fb2a27;
+  0020000000000000000000000000000000000000000000000000000000000000
+       15b55c96181a311f3f7f74f1eb85acd21405e577c99ce7e6
+       7be214ae039f75aff28c25e1693d9509b95e7702100136bd;
+  0040000000000000000000000000000000000000000000000000000000000000
+       ef286b5b57c90b082099f1ba63d66b831c2636dbf89284de
+       405ff3ab609cad17a727f3a32a728176f60738ee93ea4ce3;
+  0080000000000000000000000000000000000000000000000000000000000000
+       6a9f9a517d801e276faed59b37815a0543470f62ddcb36d0
+       6cfd80ee554662542fa45f8619fa8596a5b0fa90207c6e3a;
+  0000010000000000000000000000000000000000000000000000000000000000
+       2c65e60021dce4ab35356c77e3a8d9d489b229961214d45c
+       84fb478f9555f964aa1c963c796afc08249dfa483cea11a5;
+  0000020000000000000000000000000000000000000000000000000000000000
+       6290778c236da149367eff1a881fb693e5fc1577b911bd50
+       fed8ace2fa769e2e59191c11af5981610c7f1d1cd16a63c0;
+  0000040000000000000000000000000000000000000000000000000000000000
+       f3a53dab4a1b2ee51c925c64b80509168fe2c4a39f89eb9b
+       fb14272d3dd9a4a43c3c77edcb2ee13d1c0cf5736c100e3f;
+  0000080000000000000000000000000000000000000000000000000000000000
+       37853db27afa67b912d92274f952fe6cffcea6749c9cf346
+       5c3738ff494ec6280aa714196e4285d78ad3efe97dcbd993;
+  0000100000000000000000000000000000000000000000000000000000000000
+       de4ee75f7a008440578d541a9e9beae7ae6f2ce540682a51
+       aa01dc968b1c9c699098297c7a6230ed03e9d1f8930fba2e;
+  0000200000000000000000000000000000000000000000000000000000000000
+       ec682371507c5eacf5b1c6510338f9979c93480dfeb327a4
+       00a05844fa3d11d1ecfab19b2fed0d6eaebe4265a89c2214;
+  0000400000000000000000000000000000000000000000000000000000000000
+       e1e5590bbbd38ba2e79d7f674c1446517c0fb92ea29d4b08
+       d3e5d1af3b1798d750976f6744baa274a9ecf75c44efe46e;
+  0000800000000000000000000000000000000000000000000000000000000000
+       121dadba2540831650bab205a38ede0f515ffaee7788932b
+       2ae7182cd02fda62b2fca3aa1459f88ba131f5037734d486;
+  0000000100000000000000000000000000000000000000000000000000000000
+       bfcf69c073a8f4110b4f2506e422d57ac27336ca35fc55b7
+       9b92c327f8d3a10f0294570ce6dbad15e63828cce97ff2e2;
+  0000000200000000000000000000000000000000000000000000000000000000
+       f9e64438a44d994229bfc83934b5900cd3742508d8c1e3f4
+       a91cde6622ae50df47b3efb44188211a9cb855dd13f196e0;
+  0000000400000000000000000000000000000000000000000000000000000000
+       02bc24f93a54d95614eb323e668dbb078db65376f8222669
+       12e0a8abaf64c61b674b1e7e80245c8486d0b8b958d23d63;
+  0000000800000000000000000000000000000000000000000000000000000000
+       38fd0dd2508ccaaf72e404c3aa6197ecdebc6bccc2906e35
+       e7178e54aba498545f12beab6f4566d0af8ddd737e1094f9;
+  0000001000000000000000000000000000000000000000000000000000000000
+       6c2bdfe67c48ab3cb5e107ef3bad9aaaf4b7815775e31441
+       51dfedda78ac4f3bd74de1129075f40b6489e7dcef913c8f;
+  0000002000000000000000000000000000000000000000000000000000000000
+       9996e38570d89d1e4c716d17d2d18cace32196b32b13dd4f
+       4d69155a61196d98ba7d4c3760cb5b42ca7826433f767477;
+  0000004000000000000000000000000000000000000000000000000000000000
+       2e5f7b788f621e6e00e568a5d6f6366a204be180a4150c1c
+       ef2f1ced4c859dc6abe9a7797f94474a8c5cc738524cb51c;
+  0000008000000000000000000000000000000000000000000000000000000000
+       225d5651c62b76b58162ee3565c87920e73f8b26874b5834
+       51d5591d45055db3213c2037ea19d19e3f30c57930cb408c;
+  0000000001000000000000000000000000000000000000000000000000000000
+       778f01b3f568dc1cc0190d8a9d45f046ad0d7bd0a2e83bd5
+       a659640486d774d149cfa752fe07f16839ad0a4e0965023e;
+  0000000002000000000000000000000000000000000000000000000000000000
+       07469341cf3d3fa4f1e4503d51b2147eecece66e55a4aacf
+       0f4db2767bcdce2479987e1dee35bce57d3f0c1f064e8388;
+  0000000004000000000000000000000000000000000000000000000000000000
+       fbb5a12272515cb6cef56c3394497f17c295a8168ab7cf52
+       79e3d684921c85b2aee19fd542fd0e326d06db185ed4b2eb;
+  0000000008000000000000000000000000000000000000000000000000000000
+       23b46f278eab2f8cdad836b7a0805cdb5705959dfad8a8f6
+       47e50febaeb4948f0f08b02d8f00ff84b1a4e28741b84be1;
+  0000000010000000000000000000000000000000000000000000000000000000
+       755fc8fb5a4247070161365d075fdca9c315f7ecb9638c5b
+       c0a7a431c614f79e0efa949a89b0a1d3a44b726f75cca6df;
+  0000000020000000000000000000000000000000000000000000000000000000
+       d1777c337f61776201449d5dda39dd3acf48b521ea993028
+       10e87a928e0ef507398afe7f1d3de0cfe3be585831d6b8fa;
+  0000000040000000000000000000000000000000000000000000000000000000
+       ed33aa1685adb27dbc81bff9211d9199feb400b8084362b2
+       c75e37d353c1cf37451eeb3739c92d3111e5e6a95c3f6a1f;
+  0000000080000000000000000000000000000000000000000000000000000000
+       bc37576aeb1bf24f50806c7b96cc3ebedf64f5d444238cfe
+       ee28dd6263ba7f0cdc8588aeb27563e83dd26a66c519a3ff;
+  0000000000010000000000000000000000000000000000000000000000000000
+       18a038c2820a8f3e7df91219c8937a403fc5b04476b5b00d
+       9e3908a1ed2c0d5b7d8ca231a0e9d965c5bedd70c2e91782;
+  0000000000020000000000000000000000000000000000000000000000000000
+       266d38db2332f7b5aac71f5e9c4f201abb66e07d3e0f33c6
+       aa256588a4aa4bee6595a18b9083ebd7b4e33adb2f7f3112;
+  0000000000040000000000000000000000000000000000000000000000000000
+       4e456d28fdb91a55600a0f0a940ff6a23e99a7ace2302257
+       7faaa8ceac5fdb90aa67d0cbfc3ba885c19236ccede0267c;
+  0000000000080000000000000000000000000000000000000000000000000000
+       b7e154b0cef10b51c0c37d92d1ee18f87e9c034bef605109
+       b953b77fc877b9877c566c04077eba7de5ce3712302f5bec;
+  0000000000100000000000000000000000000000000000000000000000000000
+       23076ca9ba4b66fd5dad468e32b6aabd89157dd9484de084
+       afe987cc7c00e457432b4343130c0efab5ab5bde088a8b09;
+  0000000000200000000000000000000000000000000000000000000000000000
+       ba9528c919d59237d542419e822ea53d44d7709ed8831393
+       a46e0010238e90da8a824c99e48ddd516b53d1b58babfb67;
+  0000000000400000000000000000000000000000000000000000000000000000
+       a45c47b8b5d93ac468ce2698c4bb818d18cddd27d3c90ef1
+       05d4636e0dc06295cf47fbe08564a1a890d42be50da9a712;
+  0000000000800000000000000000000000000000000000000000000000000000
+       009e53d4f953ad0a4e3a6f424958319f9b0ebcd4eb32e6b7
+       b26f95360e1f006e78c56c7bdb60aa517c08b6b353ef3954;
+  0000000000000100000000000000000000000000000000000000000000000000
+       60beab9429813d3bbc70a65f440af15b1bcec02ab53e3b17
+       25eb48a26dc3ec9d67440f4adfaeebf3c851cfb774f5d9fd;
+  0000000000000200000000000000000000000000000000000000000000000000
+       8446b9d837207ac194d094bfa5768dad1bc7ac62b507d6f6
+       b93872a3955bfcb3a085def48e48ad7468172a3ef1381296;
+  0000000000000400000000000000000000000000000000000000000000000000
+       b18d63b9b8f957da2cb1d8315958058f607ee9aa10803040
+       f8fa5297afba5460f910507495a4aa3c03c08ccbe658173a;
+  0000000000000800000000000000000000000000000000000000000000000000
+       8569811b5e86046299507b8f1ca054bbd291997c92120b1e
+       56b1179f4e1abf339b12b0c9a05b428171dd207e2f90e9ee;
+  0000000000001000000000000000000000000000000000000000000000000000
+       b2641a18af6dd774a608b6b7a498b5962ea67f5b52807803
+       7a7e0f1cf78a9fa1421196d03455525341514b24dcbbccb8;
+  0000000000002000000000000000000000000000000000000000000000000000
+       5ee40a1926ada020139789a195f1d7fcfd8339a5905d8c91
+       bcf4d04a361be5738498700a057b6a767af995b1ae9cc990;
+  0000000000004000000000000000000000000000000000000000000000000000
+       97fc38aa8fb864828a1f8ae469219da97ecc1d352fd8478b
+       fbb3e38a2e3ae33ce7cbd0d9ef4278ecbbca11e5571a21b3;
+  0000000000008000000000000000000000000000000000000000000000000000
+       ba1314e36083bcbb1f01a1b0dcee1c5167d95058d03cb298
+       9c1f480bafe7df16d6ee5d5e44296998acbed57fa981cc8d;
+  0000000000000001000000000000000000000000000000000000000000000000
+       d1c445fbbb6c11b248816ee124502e8d9a44750df0288c84
+       bde77bc4f65398b2e4385be1e459925ab0b29fad2e2ec1c0;
+  0000000000000002000000000000000000000000000000000000000000000000
+       91e1b29bac8b3004b7e0a3c4df1f49131b73cf7ee9daf237
+       e6838a7e1686dedfb4f590be43684645a9b1b4d41178368c;
+  0000000000000004000000000000000000000000000000000000000000000000
+       a618c81acb2f8ffa633fae6f430d849213633f506ecfb4a9
+       4fb027cf52b913a04d493a225be16d06e8bdd2e335a59f11;
+  0000000000000008000000000000000000000000000000000000000000000000
+       425ac642bdb172b0d8af9b5e8733b4138f9a8b73c53e78df
+       fafc2c7ef14412e28b3091420e524b7a617fcb79fd7a2333;
+  0000000000000010000000000000000000000000000000000000000000000000
+       bb83697c816b291cbeacef56116984f1bcac5d1185a96046
+       94ef1fed71ae8838ea5dcd1fd87df10aa5dfdaf7247b20f5;
+  0000000000000020000000000000000000000000000000000000000000000000
+       b9a35b83d2fc63f3a59889ed2464ad35fe2304bc8b243620
+       c072779c8f7c58b5e54f87de26ff3e8c9bcbddcd843d0ec3;
+  0000000000000040000000000000000000000000000000000000000000000000
+       d5ea0b3466ac121ad1117536c22443eb6206c8f0cb129db8
+       2d3e46147b3d926b59e2d3d848a519ae9d0dab3002c7a447;
+  0000000000000080000000000000000000000000000000000000000000000000
+       efa22fd1dbb1fd3fe8b4713b358382a3ebfb7971d71c619b
+       db33941cff2f3ba57574a6babe30d3a2482fa5fabe541248;
+  0000000000000000010000000000000000000000000000000000000000000000
+       ec54918b940cca8540c84dfb4951115e41eea879f69226e7
+       c3f4bbd94a5f8ab825e14d399d1d63b419b920a985eb537c;
+  0000000000000000020000000000000000000000000000000000000000000000
+       882f20f80febf9a64f8513d9da4a84ed12230066759e0baf
+       171124ee711829702478c993e0a69614a5fa6abe5693c757;
+  0000000000000000040000000000000000000000000000000000000000000000
+       999b241ea0f1f9d8291458bc1706019f2a62597d2e08e808
+       afaa8b4bed7aec429f62ef6bd157ea1b0cca67b539d35f8c;
+  0000000000000000080000000000000000000000000000000000000000000000
+       9d1c95595d1c8b43b32dcbd7d157ed0cc500beceb9ad7dfb
+       cfbc5738f8c2d1fe1489aeb853e7afe75d3228e820e5d1f8;
+  0000000000000000100000000000000000000000000000000000000000000000
+       939c98efb6a332bd0d106b0ad73c7bea3b27509089a9b3ed
+       f8ddedef92e523ba101a8cbc3f5910457b4c10f632ea8c1b;
+  0000000000000000200000000000000000000000000000000000000000000000
+       62260cb25a9c5f13da85ba16c781315e00fcf91a14ecfe7d
+       4a81f4764d73cff0c6c598bb14d03dbe7456d84480b3d97b;
+  0000000000000000400000000000000000000000000000000000000000000000
+       d13026196c4648cf6eb48ab504801dceb09c184da5d02206
+       ffdd66bf5a8ef884b365ff79cb468a07483ce1af9c781ad6;
+  0000000000000000800000000000000000000000000000000000000000000000
+       1950354058a14fa13adea19ad18be46eaeae9d314400ecc7
+       3911826bb13fb45bcee0680c2e2988d22c404120b67174a4;
+  0000000000000000000100000000000000000000000000000000000000000000
+       cab6747886cacbd533a4a28581622772ca4026b7735cfd62
+       1e03b32dbe480ae229b614d23e1d0ca3b4089d622b525960;
+  0000000000000000000200000000000000000000000000000000000000000000
+       c258d3ab881322905a693d6eb560b14c93c6e1f1ace6cba3
+       ca58904c0affa64dc2fc1fd744de880eb86876a93c30c04e;
+  0000000000000000000400000000000000000000000000000000000000000000
+       d059b736116667cfd8f94e294252ccc57adfb59c7f2a5f39
+       2f3e359bb0ae9d420049351b1b256049f61ba52996f08036;
+  0000000000000000000800000000000000000000000000000000000000000000
+       8b8c9610ae81e48055eec551f0d52cc552b12753c6bb7924
+       fc2c7edfce13b888076c6b8932a76c00aed86dc34bcb04a9;
+  0000000000000000001000000000000000000000000000000000000000000000
+       95f736d9848960fe82200410199208bc50bff3776e7d800a
+       01da25ce699dad03299a6b2f02422deb0296463df7976a1a;
+  0000000000000000002000000000000000000000000000000000000000000000
+       348e25a9a47f7371785c033e858054e8b84b4aca450330bf
+       46e40e1b342b0197a6c9823810b563ab162a4afff3ef8d3c;
+  0000000000000000004000000000000000000000000000000000000000000000
+       398d57d71fbbc564ba40316a04a78661be30188d8a00a9c2
+       1dc6b4d53c6cb47c518a07e6caf6aebb60879202c2902404;
+  0000000000000000008000000000000000000000000000000000000000000000
+       8c2ce222b3845769ac1b5c6087a4a78767bb7b5b6db0b844
+       386089aa0f982dab5aec5ce3c0d6c22e57850ef5dad854d5;
+  0000000000000000000001000000000000000000000000000000000000000000
+       367067c67a278f8da0b6d95e01e1300c4ce4dc4564643a1a
+       d9f7b526134055e0863b763367ef09c4999b3d3f7478f2fc;
+  0000000000000000000002000000000000000000000000000000000000000000
+       c4531ccef569e7ac3fe27aee4f9413a5ea932d077eafe749
+       f8617cd036e260fcf3cfcfd7227ae8ec3823dc1806a5186c;
+  0000000000000000000004000000000000000000000000000000000000000000
+       b23ab66b0a48a91976906f145c49acf72cfa24a718e29d43
+       db0602809ba65f935b2b761ac68698f44ab52e3073318480;
+  0000000000000000000008000000000000000000000000000000000000000000
+       84e2f169348f9c12292bae0e4a411c04bbae0dae1010c6fe
+       abb60974909b46172f0ff9f8d3e0c1ac90e354ef5d8d4b96;
+  0000000000000000000010000000000000000000000000000000000000000000
+       178f1df13876d9aabf1d7567a9ac8548033ab879cea6c62d
+       e8275ded5d48c972e53d5542d039c3c0643bc221ec7ba6af;
+  0000000000000000000020000000000000000000000000000000000000000000
+       df2371204f0d5fb0d345feacc299424b1f09c4fdfe740b29
+       1d7867481c4958a1e96b74d7564fab9081826baaef1c0bc1;
+  0000000000000000000040000000000000000000000000000000000000000000
+       85f193b35e480c86febd733e3d73c5e533f5af5fa670464c
+       aa297d5e92606023fcd76ff39b447bd6f8b528d2eb8aa389;
+  0000000000000000000080000000000000000000000000000000000000000000
+       3c7e3ef5b75bdd8c4ebf0ab567fa9dfab7b14f65465d5202
+       2d1d772ca4e8c4627d10252c17f8de9fe4eb5f2410036f8f;
+  0000000000000000000000010000000000000000000000000000000000000000
+       7946c21f3ec9019663b088701ec2fe303a91473d66166c07
+       e0781ca73a7ba4da909faabd4ac41a9d2a04aee40741a362;
+  0000000000000000000000020000000000000000000000000000000000000000
+       bdc80943ef24005d2b2b9cf4a622cdeee6052c94028be903
+       c1a5cf266e621e1dc67f7d95e8d4a0352abbe6906e2509a3;
+  0000000000000000000000040000000000000000000000000000000000000000
+       a363dfe9c29405923502bb20f0ca9433d2bd2e935bd158c6
+       73ecbaa847e33990a348518355d24250d78ba4bfe0cc6ec5;
+  0000000000000000000000080000000000000000000000000000000000000000
+       91a79788d280aa0f726e81b5e120fd0d175e9f835196013f
+       417a49bc83ff1cae0de19f5469644fdcff16a19b0c48e2ca;
+  0000000000000000000000100000000000000000000000000000000000000000
+       4899462607deead1c0bd532d7aca9b707ab2e7fe0e29b590
+       a81d309f9faf421664ba046616b4dc07c918d857d3d84905;
+  0000000000000000000000200000000000000000000000000000000000000000
+       0aaae126611efd36cfaabc703328ce88567f1e1ae8d98ab9
+       642e95674700002ad5aa27d465b538e764fe7bd9c14c73aa;
+  0000000000000000000000400000000000000000000000000000000000000000
+       89518487c389f394664d1db1e9110d4f31ee5a30ab504538
+       9096525261c9c51132a575c2fa95ec45b126d1978b3c8f0f;
+  0000000000000000000000800000000000000000000000000000000000000000
+       48a115999ac4106147c25c8af6490e3f864fe07a4aa0814b
+       6034cf7c5049884a7251bfe1e908db7ae5a242bd7528cb80;
+  0000000000000000000000000100000000000000000000000000000000000000
+       f4a37d22f6ccc6807c77a2b00892c34f751e6af9d507b7f2
+       f05a07fe2964989df5de5c5568f0cc2a4cc385a0046653a8;
+  0000000000000000000000000200000000000000000000000000000000000000
+       504eb8d6d794ad17fb17701daa68a27909c10b07db35d59c
+       04d1a5d0a25f37c358ad1544a61c35e3b27bb8e872a66657;
+  0000000000000000000000000400000000000000000000000000000000000000
+       df0ad9ae9ea8203f839254c51201e4badf59280ec5791f21
+       60d514f1dc0ae5f0041b7dc951c2b7878620178f6cdf40b5;
+  0000000000000000000000000800000000000000000000000000000000000000
+       f134b86ddc24cedefa5919802e2ee4a1b8b3dfdbd6d4707f
+       a2a6684093c8fc7fda6d78137007ed72ae90c2bdd5457351;
+  0000000000000000000000001000000000000000000000000000000000000000
+       c1227e56f680ff943c4a6eae53aa8c47603dc225a0770151
+       20a18398e209070d630fd66253f8198d838c133fb8b2877d;
+  0000000000000000000000002000000000000000000000000000000000000000
+       618aed56a6e67024f44a5182f8b3a0429f1f816e40d36940
+       f4a5ef442826ecf4f7b51af42c67ca6efa9eeb05c950d0e1;
+  0000000000000000000000004000000000000000000000000000000000000000
+       993f917a093d0593ffef2ee61717769d0310a338971ad5c3
+       633c510c65b17337fa6600f7b8c587f06cdbce7eed021dcf;
+  0000000000000000000000008000000000000000000000000000000000000000
+       d08c7506bc96104784ffd62989f3e7f14b7941408aff19a9
+       4ef7c78afbe041881669a436f0b3a2c175bd1872d417f427;
+  0000000000000000000000000001000000000000000000000000000000000000
+       e4c926c1c6af627ff4aea8915cbddf2d51fea4f8efbc84f7
+       297dc1f8f2f34488496c0a7315c434545c2c356da2f2b8a8;
+  0000000000000000000000000002000000000000000000000000000000000000
+       a1d9f20b38fc8ff10284673b5401b340d3606374c0705387
+       538fac79ea64656d7b752ea715238b7168b7fc3e3c307e79;
+  0000000000000000000000000004000000000000000000000000000000000000
+       48a83c0d5aaa75c08186e0c3b43c12359d64ef6c5b51178f
+       ae4c16dbfd40480fec24032f13ce1ce1ee236785754befa4;
+  0000000000000000000000000008000000000000000000000000000000000000
+       98c9f42280dbba13cc6058bcb1fc101f535c17ceadb39384
+       97c2fcd700e5ba4010191d1a2bf39b94ef26c1f10eb5dea4;
+  0000000000000000000000000010000000000000000000000000000000000000
+       6e5185272ea765f9c63e084aceb39635fc7064c5500933a4
+       789c9eef18191c6eb37ff8bc61737be04cdb38074cf16342;
+  0000000000000000000000000020000000000000000000000000000000000000
+       f1a2076d13ea103ec3bc2a7981628b6c46b7e05ea2b8cff0
+       1c960f47235aa3c2f7db928c79eef79c1abb58df32be0519;
+  0000000000000000000000000040000000000000000000000000000000000000
+       2a25e1c3d40e114369c652f39101b149ad121e1e297568f0
+       39a862fc9c7501571eebb68fda325a20bfbc18b8d1dc06a2;
+  0000000000000000000000000080000000000000000000000000000000000000
+       4c368f98b55ba57c8a9f50143c85ba209f46b19a287fe96d
+       805862de2dbfb0b5fc8522fe1775db56cae5d782c5ed78fb;
+  0000000000000000000000000000010000000000000000000000000000000000
+       a0c97c9e66701e6478fb012dc563dcbb1f5c6da5ab22e1c7
+       7deb07741bae22c3a4e245df6f6f0ea157e8c2fe11277248;
+  0000000000000000000000000000020000000000000000000000000000000000
+       c1aff5f111b93662f2101a991dc73b3c6ae24a7305ffe5dc
+       0c4cda55e6b291dff5fd90fa1b5fec0d74e2658a9fb8be12;
+  0000000000000000000000000000040000000000000000000000000000000000
+       2f7e8a0ccc58df1c6241c31911d531e9990eb7849c9dd986
+       57a80345e95f8e8f0c235e56e34b0b92bb6c3f7d1da32f1d;
+  0000000000000000000000000000080000000000000000000000000000000000
+       22bea653be4b485e68b8579537213762f44e42f6d810a498
+       7c4fb10db02107f924884cc1813fafc08800fd616c7463f3;
+  0000000000000000000000000000100000000000000000000000000000000000
+       d7542072c23ba5a53a81ef80fd2e18a4fa4e797ff6600040
+       2a7bf2b00a0e7248f754fa91239b22954286887269c33386;
+  0000000000000000000000000000200000000000000000000000000000000000
+       67cdb364f19b764b08f2fbe24e0d8f5045cd24643068dbb5
+       bdcb57ef947437c8607c456b12a0e35dee06a72ddc6b39bc;
+  0000000000000000000000000000400000000000000000000000000000000000
+       4b69f9d96da82a8e111ba914616b8181351b6c7378c398ab
+       c3c93b51b1523b3d5cff783005bc32aebb490df5dffbf54e;
+  0000000000000000000000000000800000000000000000000000000000000000
+       9cd63826b5c968a2b91637f08960fff1db80be3e5f4e1b10
+       37e40726553084bf60ccfa589cd5a7ad328a9d2731b07c22;
+  0000000000000000000000000000000100000000000000000000000000000000
+       9e35e64ebdb49e1eee17085264da59b066e3bbe33369e668
+       e700e349d9ba81dc389c9ea47ae3397d2021cbb0a1dc3f50;
+  0000000000000000000000000000000200000000000000000000000000000000
+       d01966c6c3c1743b53cd852ed40141a122f10191b1c31a86
+       cbb249292e1f8720ed8bd068e08d00e58b5b6ded6db35967;
+  0000000000000000000000000000000400000000000000000000000000000000
+       5d22197b1f31e555244767a519cf1612dcb1e0c389dc5e85
+       6c356e034f76f45d77eac2372b1b8d13fe37a9793267579f;
+  0000000000000000000000000000000800000000000000000000000000000000
+       7a6346dd4b48c8e2578dc9e44cef59b355e745603ad70e56
+       e0ad6bfb7dd04c50408813e9ffc253a786a79f322270e3c7;
+  0000000000000000000000000000001000000000000000000000000000000000
+       cd6744a38f58ff1565c63b618f6d4602f48424ef96cba9fe
+       223ebbfcee0d2261dcac64d4457563e8662cead4f842f885;
+  0000000000000000000000000000002000000000000000000000000000000000
+       e7181dde8f2bb5257724386d775d816db6ba1788840b2ef3
+       ce12f93c38f34c761b6290ab661bea7a94d7bedcce619c42;
+  0000000000000000000000000000004000000000000000000000000000000000
+       35144d4cd483e6ff784cdaba5d8fe43457400002e50652b5
+       c9d58b472c45d4a0bc60c5f068babd4761119b8411392863;
+  0000000000000000000000000000008000000000000000000000000000000000
+       49e3852d9ebf4a20761f9e3cc5af7079f92434f3cc0498bc
+       b5111d55ae21a4dd1d94208eb1e2bddc2121792c0865ea1c;
+  0000000000000000000000000000000001000000000000000000000000000000
+       b5be1b964131cf4bcc472ff83c7175747c0a8142a1b592cf
+       82bd1f73170e94ea2dd2533fcb2e10b86d223ab573b7acb5;
+  0000000000000000000000000000000002000000000000000000000000000000
+       436643b8310b2f8012fff1718d811445febcb62174eeaf89
+       4d73981253903319bbf05beaf81b161b5eda9da17a6c465f;
+  0000000000000000000000000000000004000000000000000000000000000000
+       26fe5bba90ad70222b6e0dfb3f910225dfd1d94e8a6eeeb1
+       e50c6fed998ff52d18c1cfaef6486c7dda0353d609893ed2;
+  0000000000000000000000000000000008000000000000000000000000000000
+       167ca811688841bbc017aef57f046c72c89cfb105675abd6
+       474b913d96b3065573859d90259e7170ed086c7e85e6f833;
+  0000000000000000000000000000000010000000000000000000000000000000
+       2241fe3b5601c4f8691132f7fef47b2a705ee925419fb2b8
+       e4f6a1a195420d5be230460d72cb10e0d5fa98e3473dcddb;
+  0000000000000000000000000000000020000000000000000000000000000000
+       f73edb64726d1038febe1182d24c9df9ac4c2e44d27350a1
+       d023f50e6c5815af9f68c18fa011c72a0ac1de37ba50052d;
+  0000000000000000000000000000000040000000000000000000000000000000
+       414f12c0bd23b6541fe25e485c99ce83c5d29d5284c6d635
+       b9be932cebc3b0451aca78b190970be486bff89022dbdef8;
+  0000000000000000000000000000000080000000000000000000000000000000
+       9cb48ce5c9bbf7cdf172e72b8ef47ee0b9954d4d83f64e85
+       ddbad8bb1b68dbe0d1c2377a9f851cdd40941f1e8b17a72e;
+  0000000000000000000000000000000000010000000000000000000000000000
+       9ad04eb679eb45041adb6e18229ab8ef134f96b9ec4efa8e
+       af91847fd9a9b0853b5adc3952ec93b729931bafac0960c5;
+  0000000000000000000000000000000000020000000000000000000000000000
+       7fdf8d84ca1f1ef75921d13340a8613a4abce59f8e6719a0
+       048a8092055d9bc71038c2adc3fc74a9941b1bad6bb0d748;
+  0000000000000000000000000000000000040000000000000000000000000000
+       3bb8a2eede247347d3293a7827b935696db66633154f6eb8
+       6da269df5b0af347a91ef471261dc6aae07939d7562dd17e;
+  0000000000000000000000000000000000080000000000000000000000000000
+       76cdee34adbfe476b19f218ad192ff91cc764594ea84e9e9
+       b89d091dbfdd454d3de741971939aa47c84b65e5601ed69e;
+  0000000000000000000000000000000000100000000000000000000000000000
+       a5be84ab2131cc15fe88214e692c2a1c93649c302935f68e
+       74a065159a3a25b7beab96afda6cb4a15f0f0974650825d2;
+  0000000000000000000000000000000000200000000000000000000000000000
+       a1c10a2b8f9117b9c7d2bb4a4b8fb19ad5862a070afb8f34
+       11b10a5b03c2e735c20aa91c796a30e1e5012eea5d17a2fb;
+  0000000000000000000000000000000000400000000000000000000000000000
+       f30f479b09b7078984a91a14766ca5331ca54f237e832e00
+       2754d3cdeb587cacac85e5b9bc2a8df745b72ae84c83e30b;
+  0000000000000000000000000000000000800000000000000000000000000000
+       f15256ae559de534a46259c458ed699763917bb67c42caa5
+       998dda9353cad5811b4d26b418d2c36ac8241cf9162afcb2;
+  0000000000000000000000000000000000000100000000000000000000000000
+       e9dd34edf9072580a9e6bf92f517160410c41b28056a8acd
+       0dbf466153aff0de4e09a06fac89bde833afca483a514c02;
+  0000000000000000000000000000000000000200000000000000000000000000
+       a3af6ddf33c781ddce6b0033eb3afe64149b1e22c3298b6d
+       8d18a7ab3755354db7ce3336d2ad1870d83f84efbabf3f1e;
+  0000000000000000000000000000000000000400000000000000000000000000
+       943acab0e9cf4ec9267798ec18e96ea9c4953d194d06572e
+       2ce3b4bf975ef64655d8bf4e56016cb2889016c1884d649d;
+  0000000000000000000000000000000000000800000000000000000000000000
+       b150a772fa4e01a865d822ad9f08e192a2f09e10ba815686
+       d4e5f4ca1ab70dd9ba5b5af2efaa89b3a273cc13dd63bc5b;
+  0000000000000000000000000000000000001000000000000000000000000000
+       685d0a283480caadd55b2866fb4a0a41b6c7cd10a178c267
+       4e8943a076e33ac2517b897f25f5e1b946a421676d59866f;
+  0000000000000000000000000000000000002000000000000000000000000000
+       6adb8fb9971688de77028f21a600d2ec2e7ea7469aa68f49
+       d25f5e79e204a87897d24530d30e7fd55f852298fe41b993;
+  0000000000000000000000000000000000004000000000000000000000000000
+       34e213c058fa256f43ce41f0a636f04d6de70d66fe58fd7b
+       b5a6056e1a9fe00af39fc4f6dcc737bfaaf953b94c3d7d62;
+  0000000000000000000000000000000000008000000000000000000000000000
+       acfa06bba285a64d49b3e40fa21a87807bab2e1b8be93dc5
+       9c607c350a79fcb9c3c08482a9899662911dd9d78241e5af;
+  0000000000000000000000000000000000000001000000000000000000000000
+       af8fe6e769d9a9de9103857c73cfc48caf07a0a162a9c84e
+       badb8bf3e3901514c364d5ab4fd71dbb4adafc33a57e0dbb;
+  0000000000000000000000000000000000000002000000000000000000000000
+       03e0acc3efbcef91c181e6b725efe6d5988aa3fcf2d97918
+       3562afdb394cb6c829361868d3fe9e2a795dc73d6650c385;
+  0000000000000000000000000000000000000004000000000000000000000000
+       deefc043580767155330551bbb6aefbfeb83f2a53645534a
+       c8162770dbda0fc2e009cbc088d52b75e0c5b3d8c3aa935d;
+  0000000000000000000000000000000000000008000000000000000000000000
+       ee46ee36468537d3eb9a8712e6ac1658c502a2ee5f3b9dab
+       9f7aa36fec8e73e4e31f29bae48a0484eae73f9b1afa9eb1;
+  0000000000000000000000000000000000000010000000000000000000000000
+       f724e6422f7b27fcb8f589d2c1303a57c1a029486a5049a9
+       04ba1444c6b13adef4ca56bfd9723f32813dd2e96f7fd03f;
+  0000000000000000000000000000000000000020000000000000000000000000
+       3fa0e90f02790b3a69e7c89a13d6237f2673e06ee8350c6c
+       68709de5c53ea86e2ddf950a5f9accf42013439e1528ffc2;
+  0000000000000000000000000000000000000040000000000000000000000000
+       dd0a534025a9e27706db2a670c60f0b02dfc511b1b96bfd3
+       195469451086eeeec709c9906f70dbb4b1f69bafbf3764b0;
+  0000000000000000000000000000000000000080000000000000000000000000
+       a4da0b9a38fef97bc79f467b2f3377e146dc3b15803892d8
+       1a60ea09b20c6f489204d8118b122c5867833c7ef3bfae13;
+  0000000000000000000000000000000000000000010000000000000000000000
+       4ce7a4c772c8f9ef1e4fd4702305e22a16658796d594c785
+       2bc89b262839d2e7c5a4d6c6d54d2c12c3b6f393f74911c5;
+  0000000000000000000000000000000000000000020000000000000000000000
+       f8bbca32a6f4757c7f11f4135ab07d44abcf888c01104279
+       92f67af3b9e25a74c087616ff87b74940ef2e13bdee48a8f;
+  0000000000000000000000000000000000000000040000000000000000000000
+       d7a63b5010a345f136e5410666d62c0d0db6c72a14cb0e40
+       480a96adbe7e4e18fb726976e153421b959e118d53db9782;
+  0000000000000000000000000000000000000000080000000000000000000000
+       1e73ce2be743ce28821a6f9fa91746ec106e6027ee10813d
+       4c295b3a21cc9e8fcc591dde212cfd4813bc12add97b6c5d;
+  0000000000000000000000000000000000000000100000000000000000000000
+       3eaf2b1202ae5b92708c0ebac3f190c3716ef8c42f7e3eb1
+       5cd7adf3e81c0d0362b0b2d6ff1ba5a8c2bd1adae8e3750d;
+  0000000000000000000000000000000000000000200000000000000000000000
+       5fe4c2d04550aed6b268726c60e2a3bdaee377ce8dded8f0
+       3c1c3483e260bec348c8e0efde742b41d16f75054171b1ca;
+  0000000000000000000000000000000000000000400000000000000000000000
+       4571854265e30e3b8f55932f432def3e8c817608c600871f
+       290bbe7940b15a6f592caf95508152e4016adb9a5ad04a90;
+  0000000000000000000000000000000000000000800000000000000000000000
+       a1955f1a9e1c293f46422688b749ddaedac0de5392039212
+       2eadf68986a238b85ab9576d1fe2fb8dc0c166f574ba2019;
+  0000000000000000000000000000000000000000000100000000000000000000
+       c0382ec488cb6cd0ab2ed8079e57229ca27219138da9ca68
+       ed3ebf43bc1b7b5f4ee91e71d07b2cb4eb3f661cfc31b8ab;
+  0000000000000000000000000000000000000000000200000000000000000000
+       22eeabdba671f4cfe635b615c4cb4f759263bd01ee087152
+       8d38f4ef0fd7b17469f70779e40c45a58b862d81bcfbe619;
+  0000000000000000000000000000000000000000000400000000000000000000
+       10da653a6533ea959ac42304fee9983a673ff5fa6e5fe9c3
+       9f253744a1337662c662f359128b5446ea5d9f24c0bd9ec1;
+  0000000000000000000000000000000000000000000800000000000000000000
+       ab7f47fcb791cfe0d6fe82904f63653e747b8930bed679d4
+       862e7a3bd1cad80aeeec6510428e173529e4fd5b1385b8f7;
+  0000000000000000000000000000000000000000001000000000000000000000
+       2fcd824a19c499683a7c43edd5f5e930d5ada53282ab92b5
+       ba1f9df708477b5e0ffafa8e17af2c78b45ea8dc9f960ce0;
+  0000000000000000000000000000000000000000002000000000000000000000
+       8ac9cec56baa8ac099a09910199e1bd22b8a12b35b9825ad
+       1ab5db73d52b33050688969f6048d74c1f39e1a019481850;
+  0000000000000000000000000000000000000000004000000000000000000000
+       a2970217cd733f9e3a2fba569b5c69549b1d85fa0762065e
+       ae252ce23450578857e504ec52b91a452a44ee6e284e2fd2;
+  0000000000000000000000000000000000000000008000000000000000000000
+       f13b417168c5175dc741d3abff665b90323806d25a7ffd1c
+       c95a2a90eec8869f2d9c3274fc5c23ada2d19576ff61ee70;
+  0000000000000000000000000000000000000000000001000000000000000000
+       5fe138aee8e0a7ae229395928700fa9a37f51ae1ce8a7d9e
+       16bc8db3599524e304c3b1315c953e244bf106019952f465;
+  0000000000000000000000000000000000000000000002000000000000000000
+       072a6b141853fcd7c03087fb051ca86c2999e287a19acc06
+       6e39c731cafc7ab8cc4302937a6eb2f48d5b69f59a8ab6c9;
+  0000000000000000000000000000000000000000000004000000000000000000
+       6e61abf961c86ab5d8ff5fdc86fd254077c50b20831af694
+       db7d8555b0499464c07e8046d2424702977304ea2ed3dfdf;
+  0000000000000000000000000000000000000000000008000000000000000000
+       c554b1f1bb02a20c71ccc3a5844cbdaab6ac6065f1981773
+       3ab9f2337b4b69e8cc3074bed8ec371642f191e4a504238e;
+  0000000000000000000000000000000000000000000010000000000000000000
+       51b3412d7e6cdfa87026451d611b398963ed0f7914be657e
+       8b4c78acb1464f76d7217ec4420c84ed8914426b96e995f5;
+  0000000000000000000000000000000000000000000020000000000000000000
+       4e2b6793fbcb06050191865e6cd61abdd7f3cb3cfa0a198a
+       40587eccc2c8c15bd735fc22c776f16c18c019fb7b4b04d9;
+  0000000000000000000000000000000000000000000040000000000000000000
+       9e32130b3039abe1c5e5b26c41e633218e7e17be20463769
+       52e3af3dd33eb613e5022c26a0e97b3a43d983db2dd3d8ed;
+  0000000000000000000000000000000000000000000080000000000000000000
+       c18d4991afb0f844fe4430eb4ceef9600f0707f526d50cb1
+       60f22bca3934262d0d4d8f8118df4325b2440a2cefec2c8a;
+  0000000000000000000000000000000000000000000000010000000000000000
+       ba1c2f2d4855d9bffc68849e061cb23af605aad9e1ca459d
+       3f9c6666ca2497aba5f22dc6d49efdb97e63b7e05de5f3e6;
+  0000000000000000000000000000000000000000000000020000000000000000
+       a58dadf4b734ba815d34bb5fc543b46db3b427f2f4d89c3b
+       b0c10ef8e3a3ff48c57b8f1b60d0b10b5b4f2121167e8d1e;
+  0000000000000000000000000000000000000000000000040000000000000000
+       34b7ba1db271bde528765d75773f5956464b714d9c994878
+       a0e25defbe4b845460e20fdb066c63a1e4593c63e88b6b8c;
+  0000000000000000000000000000000000000000000000080000000000000000
+       cf5cc81f0e5924e5c7503f919f137c50a7f59c664a36f278
+       0e3b9fcea7afbbb9c756a53d04c8dc3930bdbbc219b92e0b;
+  0000000000000000000000000000000000000000000000100000000000000000
+       809712627c15317a1ff6a5a53a9af3726209d3dc74f281af
+       9e4ede48a23fa258a1c7550087bcbf7cbc1a0239b35900cf;
+  0000000000000000000000000000000000000000000000200000000000000000
+       6dda715bb1227452f50923799bf245029bee7eb6a6203b41
+       4987a0919df53153f00e23d8eb5cc95b873c0ad9b40f3c46;
+  0000000000000000000000000000000000000000000000400000000000000000
+       baa6dffbedd6c9bd75b929d444800382a3fd330d43eefb50
+       06f07bfa7811fed5de8eb93a5c2b28ca90558c62e4821ebb;
+  0000000000000000000000000000000000000000000000800000000000000000
+       9327fe772c60b53dfc5e11c56bad70b6321acdcd88beec99
+       86f5bbbd94e1ceb8cf9b07fecd13bcba73ae64951c37e637;
+  0000000000000000000000000000000000000000000000000100000000000000
+       3395521584ec93e8579797d3a966bd1c2380a66f95982be7
+       4383715ed3d034f970662395f3d1f0c5d14a9cc926c5cd02;
+  0000000000000000000000000000000000000000000000000200000000000000
+       f9d37ca7294d832210c1e653e441007b56381b1af68ab0fa
+       e1cd78182664abe5ad64c6188a901ac00e8006ac7176d0fb;
+  0000000000000000000000000000000000000000000000000400000000000000
+       25adde24141811ca576c77e10c61b07e9ba9fb023cd8bd9c
+       e04f17ea502b9ab5b0f1c7ac16affb150df42cccd56152e5;
+  0000000000000000000000000000000000000000000000000800000000000000
+       8903e96a3fcb869b6ed8ebd05b41d15eeea0b1b8c175fd1a
+       aa89b098ff1dad397e3ac31c21cfdcaf1889a704e9ea946a;
+  0000000000000000000000000000000000000000000000001000000000000000
+       fcbd400b1a05a47c9ea7f1c4e52403a6bdaeae6c2a6048cc
+       761b1b18c0637dfd6d55d87a4f113b68af688f81f8d4f5fe;
+  0000000000000000000000000000000000000000000000002000000000000000
+       88c39912dd77f2510290e9b32fdff085e167a338862d6766
+       7bcd793c08afc09b27b95aceb0d9616d7fd66335020e55ef;
+  0000000000000000000000000000000000000000000000004000000000000000
+       51208b60bc0f91bfe1054342a73ade654872554eed23c450
+       426a4e6f17ae2f29a35133cc6300736b32b5679c8780165e;
+  0000000000000000000000000000000000000000000000008000000000000000
+       003625a0bb5f162b18bab7b498553bd1ee67b969a504f533
+       ff852ceabb97d9928cbc671b3987a21d0622bf480f9857c9;
+  0000000000000000000000000000000000000000000000000001000000000000
+       9a776d5d249c627fd74d868ca2e5f30f9578e7dc3c1b4e49
+       713cf88deca40e521d15324aca994976f1d970ed4f118906;
+  0000000000000000000000000000000000000000000000000002000000000000
+       47b7a8e4643e9ba7917144b787496f6e08a7c03e17ae9c6b
+       17f02b23ced0669a67d6fd22870f8f60937c956c7aed718b;
+  0000000000000000000000000000000000000000000000000004000000000000
+       09702bdb907f135f8ac4564319bb91e0272c5f49f63d6c2c
+       04cedb6f979d648ec677348f46b3b6d2e491b3c735791ec2;
+  0000000000000000000000000000000000000000000000000008000000000000
+       859421e35f2789869f2bc401e802a7a2e5a3dd671d0dd761
+       d4430b200d778d764b57e4abbd9b6f2a0bebd6d4ca76dfcc;
+  0000000000000000000000000000000000000000000000000010000000000000
+       ce6f45b33b4517f6de34eec218103ab52e2f7c9ee5c3d5a7
+       5aa67eb1b6382cc16467d12322af504d4a7c5c6883fe7551;
+  0000000000000000000000000000000000000000000000000020000000000000
+       55e3dca7d6904f0bd898779f77eb57cb670777f8e5840821
+       dc0b2bd616b31cc061911a30121130880221b4c3b49942dc;
+  0000000000000000000000000000000000000000000000000040000000000000
+       29bcce433a0f89958c85cfe3d4acfcf9d2392c25c75e638d
+       5cd8ef967295257dc0fc379f496f484961ee297633e64cec;
+  0000000000000000000000000000000000000000000000000080000000000000
+       735d4826ff04c760e49504fae1a49ff1070648d3c7d0170c
+       28961576dbd22448001631547726e7cb517df4fa6d9e486d;
+  0000000000000000000000000000000000000000000000000000010000000000
+       a4522ada107ea62be6bf5b5bf160b4c75e15f6ef0d16595e
+       b45177640fd710089c014d55a72101fc7f973bf462f6e0e2;
+  0000000000000000000000000000000000000000000000000000020000000000
+       42298f9e5660dde82a88fd096bfadb44aa0ce8615f5e2ea1
+       c24ccf0957f55d4b9390672e525622b9453092176e5feb6a;
+  0000000000000000000000000000000000000000000000000000040000000000
+       371b0a87d047cad422619a1ab8bbf8d2421625c36eb54734
+       154be268071b1b7d6548bf3933ce23e892dd4ef599e3cd7c;
+  0000000000000000000000000000000000000000000000000000080000000000
+       1b3a0995a3ea458e99eca6ce81d8d2943d3ce4036f280185
+       5e1eaae31384cca72fe15cb928e7247a289569759c92f347;
+  0000000000000000000000000000000000000000000000000000100000000000
+       75bf29ac66c69352ae6cc00493f8e448e3d568327b9cf474
+       543795ab540b32b3248a0d6518e6c3b865eeaebb36e5802b;
+  0000000000000000000000000000000000000000000000000000200000000000
+       5a0399a8cb30b225742bc5cdb7b19c2e090bb1e195a66791
+       c76ef9568728d4ddd5520ee9876a73ca72123eaf9ed79751;
+  0000000000000000000000000000000000000000000000000000400000000000
+       d18c12e6527e6e0f607a6babc9848f54082c3bc3bae5828a
+       dc5d12790a1da64c1976d0b8d6d66d9874f0b887444ec537;
+  0000000000000000000000000000000000000000000000000000800000000000
+       870a20d71492d99531323a86994e43af13c7519bd2527e6c
+       02d19d7b5cc70a320bdcfdd41f9921ffe0d6742644399c52;
+  0000000000000000000000000000000000000000000000000000000100000000
+       54b0a108605642493ce135710d562de7c32889b831abf8f2
+       654df69490c47dd5fff15effb5cb315585ae64cf6d8a69d2;
+  0000000000000000000000000000000000000000000000000000000200000000
+       a59695a3fa53bc16c5ca7fa67f939076ae5c60fe454556ec
+       528c3c4bd121d39056898a0034b596a433c8e70a509274f8;
+  0000000000000000000000000000000000000000000000000000000400000000
+       b2035a4f13eed6a75ff080223dc8e342de3d213c294c9b2b
+       823cf02821214fd46d9a8a8def8920b8fd02043a90915754;
+  0000000000000000000000000000000000000000000000000000000800000000
+       7e6009fc5a9a4bcb932fba990f5b27279ddf357a71f4f8fb
+       a18b1ee4c68c9b9db4b9351c147bdbc901af12d956eef5c5;
+  0000000000000000000000000000000000000000000000000000001000000000
+       2ea14149be04b3f717bd70eecd2c263da8bb87513c7a3a35
+       65f1bef465ed26b40bf1ffb916cbf111ce5d5549eb19a401;
+  0000000000000000000000000000000000000000000000000000002000000000
+       82560beaf44f02d49699d4288779c46b26e1449b3d347e1f
+       ad005df53b419cd35042f844834157cad6ff20b9820c58ec;
+  0000000000000000000000000000000000000000000000000000004000000000
+       4f16682c365b3b245e2ac0851460e935d293ee25ed63b926
+       f155888b05d06adb3b212c988978b509c819ccffce05a3cb;
+  0000000000000000000000000000000000000000000000000000008000000000
+       65130d454a144c68a45274fb5a34000e47bda215d7ef794e
+       7dc0c4ad2951417bceb94b84224e2392ea24e878db411d70;
+  0000000000000000000000000000000000000000000000000000000001000000
+       b229d4e287009b3bfaadc07ef82c7dcb23aa3efd3ccad210
+       0d391fe98acba6abb8fed9caadddc59cc933b07eecf98879;
+  0000000000000000000000000000000000000000000000000000000002000000
+       e997bd8285b6ac3f3f14fbc98e8a6f2d7f310eb250a1d3ea
+       374efdbadf8a357324705281c621abd460fa3bd5818898a7;
+  0000000000000000000000000000000000000000000000000000000004000000
+       e88323084406260258f70be1a98be9f175bd33dba86dc309
+       f689401325a73fe8d162b13d808a4027360d85594700776e;
+  0000000000000000000000000000000000000000000000000000000008000000
+       5c877129c311d257a8b929cdce288c8c41d29f48c7f09645
+       766bc49677fa50b1a9089308c82f973b16250d8ce85fb972;
+  0000000000000000000000000000000000000000000000000000000010000000
+       3847656ab3097dbdb9f850b3eaede060015145dfebe081b0
+       c824634dbe6bcc4e3c0e4814267577d0a8e88e6484956e47;
+  0000000000000000000000000000000000000000000000000000000020000000
+       d6722ced938f45256e6bfac3209d8afc3332bfc4b9728f6e
+       510d68ab75eb49f7aa970e4c8d4458f26c76da52b97d9c2f;
+  0000000000000000000000000000000000000000000000000000000040000000
+       e46d2ddbc9e9cd7668f0345ecb38f4b9d033e6277c770339
+       754eaf9252e18b20b04528133b5513d0b45eb610332bbbee;
+  0000000000000000000000000000000000000000000000000000000080000000
+       6b179b4be801c3c22c67820b4a0602da09b36a0b4003e19b
+       594fbe016179a0c60e814192aa5acf26b8c7263288e5e6ef;
+  0000000000000000000000000000000000000000000000000000000000010000
+       d3b5ae53b5bbed9e11806475fb8e892abad4d0df57d37432
+       925c57438355e2ed191f44a62ef5d233e736d533c384b23b;
+  0000000000000000000000000000000000000000000000000000000000020000
+       3c69bd1198742f571ba466d75f33e2f8875bca181e7c5060
+       2cbce555cb50bfbc7f03b5cae522dcc9e3a6f652d7f95ee7;
+  0000000000000000000000000000000000000000000000000000000000040000
+       faf5577aa967ce1b528cb3183d311a4a01fe0bcb8eff52eb
+       359c1f635ba4aeea1496961d0acea82f8b287e6c333c631f;
+  0000000000000000000000000000000000000000000000000000000000080000
+       17a59ff4260e682c5fd265c4c8cbb1f2394df520878d54e7
+       bd62dc2010bb988cd034dc3471b8771c1e83cada3160a162;
+  0000000000000000000000000000000000000000000000000000000000100000
+       cb77f4cacf18f51a20b2b2a9424df516ca09da86df7e060c
+       8f21087d1f761b40dc9fdc48591725f6c3ab8c996da2e69f;
+  0000000000000000000000000000000000000000000000000000000000200000
+       efbb6a40a6bb6a73f2b00fe2672d9d9c418be6077d05d6d0
+       11556df337561494f1a88048287e274b091fdc8c3248fdaf;
+  0000000000000000000000000000000000000000000000000000000000400000
+       482e51026536799a4adde4ed551b5b37bd946806f72a1e84
+       5c83416d574c4d4fa9f844a8bbf2502a2e423e9333ba5c09;
+  0000000000000000000000000000000000000000000000000000000000800000
+       3f2aba49c1d122f4fcb3fcaca344b48526426a3a11792420
+       bc2446d092a3cb6c47d34d6b8dc6504e71faf9cab27d5af5;
+  0000000000000000000000000000000000000000000000000000000000000100
+       d64b82bf6776e07d16dad6b610bc5ccd1566a340d5439920
+       9f0ec7057d88a8b9a1d7f37e8ae54ddc286143aded0b727d;
+  0000000000000000000000000000000000000000000000000000000000000200
+       10ac120667f6cc8fb3eb5e4fca09393e4d752378c1ff3aff
+       84fffb34309cd0f900753a880af05503913925a676ccf8bb;
+  0000000000000000000000000000000000000000000000000000000000000400
+       913aba9a2ee4d9cdbfd723b02acd5fdbcecdba6e5ee9fba5
+       a6935a6a0f5be5e36a5ddd2489a849723bbf32193b352276;
+  0000000000000000000000000000000000000000000000000000000000000800
+       2096ad29e264550d7f50f5225b174de08c4e33407e229ef8
+       322b672ed96a11c24452ab02e5bbfcbd8d2c055dd4ff1502;
+  0000000000000000000000000000000000000000000000000000000000001000
+       e2fa3c20c1c3697f0fbef257014f4a0851c7a424287f58b6
+       3dcf94cfeeec73127384a8dc89d1de1791c2bffa516848e3;
+  0000000000000000000000000000000000000000000000000000000000002000
+       25d94a019001c3a4fd30bd51206497e094942ae9691215ec
+       c52be65c97df81a1cdf06760d79bdfa04a8a11024535c51a;
+  0000000000000000000000000000000000000000000000000000000000004000
+       20acbb4cb8509b255bf293e116b32d01a284c10402387352
+       f98ab11ac1e9fd49d644292f7e70d78bc8528c5c85afb7a9;
+  0000000000000000000000000000000000000000000000000000000000008000
+       b61f153afbed502f9e64d13a25107529e614e39b992d3d22
+       f720e227475a727d1e3f9ee9bc7d3ba079ce32d076a2cbd9;
+  0000000000000000000000000000000000000000000000000000000000000001
+       1621dca63b7555e070a05b5a265a0ab530a79e71542ed333
+       220384f259384d523e7b0328739f608d976b2498cf77c7cf;
+  0000000000000000000000000000000000000000000000000000000000000002
+       35ed02357b26181864f5de07718913a33ed9fab93d845302
+       c7f8b065f6bd6d800c8881040c68828189979be2c86abe64;
+  0000000000000000000000000000000000000000000000000000000000000004
+       e0cbbdcc0724419ab098dc25606c6277160215eb3a166b5b
+       106d2fc9c5e5d2f8a7e6ba7db2a4e1927adc2ab6a26d20aa;
+  0000000000000000000000000000000000000000000000000000000000000008
+       2879e25e570e536c936c8bcd66bd780047b73d53922933ea
+       c3cf14d55169ad5281175057db3a614351dd78ca57c9ada1;
+  0000000000000000000000000000000000000000000000000000000000000010
+       45ed18e18449285fdf874b675784b18d412e504075c61fcd
+       bfb1f7d80745dd69a5fd479fe14c449ebd1ff19501c42ccf;
+  0000000000000000000000000000000000000000000000000000000000000020
+       3ccc94e3f12a3e2e4321e397300aa6444ec21526098b0eaa
+       0ac9c1ae854812f92615b3fc45e65c945f3e1ceb8efd4a9a;
+  0000000000000000000000000000000000000000000000000000000000000040
+       f300d3a47eb7d9bf3215140c894b4e8888040541424e4c11
+       74587eb6e7f9b2ecf7bcd8f63948ad0417f439f8596ad52e;
+  0000000000000000000000000000000000000000000000000000000000000080
+       df6e46c2dbf69f357bbe22bf604efca58a7352a18f41a7ad
+       1d5fa8d85dc2428dabb69eb4c9cea7180f2fa554eadb9dc4;
+}
diff --git a/symm/t/rijndael256 b/symm/t/rijndael256
new file mode 100644 (file)
index 0000000..9a4b866
--- /dev/null
@@ -0,0 +1,2884 @@
+# Test vectors for Rijndael
+
+rijndael256 {
+  01000000000000000000000000000000
+       0d166d15e764fb6bc005df25b169d93f1cc03580e9dd4a19c4bd7cd32e6ca03b
+       a8dcbf6ab9a5d693428c82d2de78a4fecd75573d00d25a1cd7723a3897521c4c;
+  02000000000000000000000000000000
+       ba36af55f2b81650aabe5f1496e0675bf42979ccbe66ce7e9dc42269c8a40378
+       710168005b92abf4e5fc36d9ae0aab11a872720aef853e37d7a929bf4ae023e1;
+  04000000000000000000000000000000
+       79c77f01ae4a137b07fcc8be95693b7157b55aa02bfab77bc0ebbf7b383dfd9f
+       1b82ae9934d5fd2ee151529c7cf17ee653ad859b80d1ab1a02b31f23e17c1526;
+  08000000000000000000000000000000
+       ce6c53e5ceb51d313d95c7831966807d25eac9fbadd3802f7bfbff4f9cf2dd51
+       1263853b8b7f61e02cc9568c6e925b79375a1d7212277bbb44e15aa5874842f3;
+  10000000000000000000000000000000
+       be529de8125596ed7ef7621e6fa1ea17343eb9b3c34181484e09af18dcc8343b
+       f91c5fd5f8fe1692a9cd403531ee7643ffd91de0a8238e3263f361c22b31bac2;
+  20000000000000000000000000000000
+       62bcd58193cc12ed08ce4a5b51d3a679678a1561be6a805e69e1f1b2da45e7c8
+       9d1ee83ac951bece4f9535b1f4d461b99960b0021be3b8d4c8d20521ed3978c6;
+  40000000000000000000000000000000
+       ababd0ea311aea38cb364d367c27462d7c7c874cd8138dab3d8331d90c483e2a
+       e360e0bfc704c664550069c9c675304dd24121be987dd76b7e718f8a1aa2277b;
+  80000000000000000000000000000000
+       93b811f0e3bf6c0b00d4f8002783ce01c24ac3671dc198805aba8846dfebb288
+       1726d2a0c6d4d7078322b48824071fc4c6226b8a10bdd8d09bd6b90d5cff9812;
+  00010000000000000000000000000000
+       8b9328500908af71236b5ed841a9e177fac26c81034dffb99e89753de0aeb4d0
+       1ae78759e134dbeebbea45fe9a0a66174264a1efe55a87569fe1a1568a28544d;
+  00020000000000000000000000000000
+       c5c7c19175d9ab800bf358d066f0da2e86fd20ee6ba4e5cfec1e8b1932b42466
+       7b0069d82b61439e71a7cc911d3253f71efc8da14244dddaf323283c9c99c123;
+  00040000000000000000000000000000
+       a5a088b14f876b6291f5a92993540f972012b6e8a0eaf2ab0adaca3b3410c888
+       ca33da2e73e8a8f62fb2b6c23f59a54363fff8bb3c806c6c71e1c22b6f90c81e;
+  00080000000000000000000000000000
+       9c482dd8e9e514270d153a310d4179166391ccc10ff594133d2b023c307fc951
+       3e0d22a6e0dc4c5952b417ca6edcab1edf6438fece9e4d05a409d0adde7331b3;
+  00100000000000000000000000000000
+       cbb011e00200dc67a685963f6dd64373b87eee0e1db3c2c3b9f31a290682c7e4
+       4a71ca431d8e66467b67a5dda1c759f4e5a70eb6fa990d8621fc8c107ecc31ed;
+  00200000000000000000000000000000
+       c134cbc298d7fc2a3df295534c5b51a810999bc66c64ce5810086ac896af12aa
+       e21d816bd83eb2ccee4c12c0060a07b5a9b1f52639e957db1ba3c94b0d1ef5d9;
+  00400000000000000000000000000000
+       00d96bf86467d8eecc800930d9ab0511252f62ddf77a2c6fcf560ec64a99992e
+       8f8cb84f6ec8a751a2c52140d1aaccffd75be6f0750c0f4300d8a95be1497d13;
+  00800000000000000000000000000000
+       dfbc41532baf8d1ee9c00f40cb9dd9c9970949d182a651af9809ef097d9f95b5
+       adeaba98648d76d63be914a169821e4b6b816965082a56c64a2600cd0b0ab1b3;
+  00000100000000000000000000000000
+       3ec45f406e61c9c862add48b59e2193a9e044d8450dcf06ec9781ea54b25770d
+       0cb3cb766c1b3af62594b5beb5f794c537fca3ef3a7aa34c19965d194d616590;
+  00000200000000000000000000000000
+       5f63e9e91b5cf923dffa47b0430c9c5741e36bbbf2f7561e5e4522a9dd086f59
+       c8d48dfaddd6db42fb88d5e5a774d796ca0ccbd2aea63ed8af958be542577c60;
+  00000400000000000000000000000000
+       aaa49691c18a878cae6d8ef28cea273d39a85d65ac6656efadba875d4de8dd7e
+       ab5274393cec473dda0b9b0d150c3119a6c7c7c5f546bbfd48be3fec8e0b5ceb;
+  00000800000000000000000000000000
+       a7a1884e2e0ff36211f92ececf5d10a026f0d7fca3ec36bb4fdb3dc39c8b0286
+       ffdddaf16fce3a8ee9ffaefec4f86d0a12b153b1642147201fa93f0165d95786;
+  00001000000000000000000000000000
+       ca7d8e1fbc8de0b208ef96a731cde9e71447c7976a7b4b70f6c6670c3683825d
+       373578f19f83d5af1ba61e156754fe0b8210d75b3b94e4ea7c94d51f2c6db580;
+  00002000000000000000000000000000
+       82e91aea18e826867c8df83eb68d783f70792019c350859c4c6eddc40017aeb9
+       01ebc069581ee246b6f49707ea3d5e0f7b22665c40f111963d2e42f45c937f95;
+  00004000000000000000000000000000
+       46acbcffb692d63566c52fd7f0ec13199b07b747c75d5edbf1a3f684b51f634c
+       3c1563b0cc61be41ff454b2b1b4f7dd9b102efd860a6e60a245391629963440e;
+  00008000000000000000000000000000
+       0ed05e750de5f56965775ce44dec375ab74d16c9537df755ec21402b3a10d0ce
+       662e2d66cbc1a9018e142430e5fa0093dc5aa33d99e225944fc651d0234424de;
+  00000001000000000000000000000000
+       bba5a7e1d984cb9c1c37f664632649363524e1e2206ece1d998fcc2706545d7b
+       889def781d00c866e878bec6965ff82def729be52611d0b805ebdc97541a63a9;
+  00000002000000000000000000000000
+       99da531198516629a6c5625c483bd08ad864b54914efd29982737f6572076b55
+       40ea49fa08ecaf017df5e73f9ecca8c24bfddd40327add7407badeb51d551f21;
+  00000004000000000000000000000000
+       9c7e2c74e8a14ef12e6a8106608bc3e70206ebd402457cca671e6804ad55648f
+       5eef85026cd49329caa947624c88c91e27f817f8d01768b98d121a69d9cade76;
+  00000008000000000000000000000000
+       53e1750bc3bf2cfd3ee05caff29cd98c56cb32ffb75548c8b3482a266b4a1067
+       6236cf6d9974e50472854642a529c86ef62599e4172e3bf5d12909721a6e606d;
+  00000010000000000000000000000000
+       2cf3f5109eab2d3c501f70b3ae1fd8c744f1c1dfa41f34921f55a3547c76110f
+       6b9f52bd5d1ab2d483a614f590f571b1f086aa63bfd0c197c02d514d03a7f695;
+  00000020000000000000000000000000
+       81e041228896707809dec23dc43f023ad3a8b741fb097158de5abdd9e8e63e2a
+       bd80f493cba17cbfd79870c1fd0f7052ebcb07d19f3b7101e6ee9a64691b0e33;
+  00000040000000000000000000000000
+       df020d98627cda7f93bdda5f2544b46530b645ab1c619583a8d34ece8f0402e2
+       d56f8c7d45ced4bd015c413b5076cd494ebf0ee3c6564b1c8980b6db9f8ef18d;
+  00000080000000000000000000000000
+       3f2a2e2d05337597567e45ffff3644d1b78d446e54113961a282c63693137ddf
+       ed749629bc2a4d3a97a678bc810913458dc7f06d181e6c2ce232b01da705cc59;
+  00000000010000000000000000000000
+       7276b5b02da780407cbe4a9feb17230e308d01d37c2d50b2f357d2c25342736e
+       da1d5b5238aa6516f1bc3982e6a22d18a404645edd961251d8242fbc639ef442;
+  00000000020000000000000000000000
+       94df6723a4b7e8a3c548a794ae9dd2d44c2596e6a2b313f4caee48b2dab60d0c
+       9b760a577ba48b855d2787253507b5405745ada1060c99ce476c3cd5863015b6;
+  00000000040000000000000000000000
+       b0942965db151da90df6354e57d78c3b0e6c31e624c610dc018d3e1411c13239
+       5c37701aa5d1d0b1681ec86eafbb59f8acca725816ec73edc7ff34a68b1414a1;
+  00000000080000000000000000000000
+       4193eb057627735cfa1e3a6b1ff107898c1df42499bdbdb50999808a4443c616
+       2048e754d9481745d95a3e6b4d54cd7b3ca5c09fcc27f22a6bb3b411e4213ac9;
+  00000000100000000000000000000000
+       6496cb3d2a6d1927a86aeb9a81838b7782554d67dd17da1eb55d86e680f18a67
+       bf66014d7eb0b274ca931b913b1a792f9b303b6cb1581914f7d12ad92cfdfdb9;
+  00000000200000000000000000000000
+       5f2e0aad9d2b66428bd14e92e04ba45c1b2c4d8a3626af7e14ba88ed30a939b0
+       53359f5e143fc6c5ed119106f09ed6020c07a840f37c881a19fbb664a2932912;
+  00000000400000000000000000000000
+       b7ac23c7ea16038b23ff99fd8471a66173c72992009d67c136ce635b6c9d9a0f
+       9c1a45cf93c6c3eaa67f56c6fb0004ff9182d4c76cebb113a297a6786bc3a7e8;
+  00000000800000000000000000000000
+       6af8fbcd1498dbaf169b3c6cbf99c0d954f0a6074a391b50ceb179a25b76a4d8
+       4f6042a77083581ff33c731111d3040fb551a9139bedf5266b83e0bdf5f4e9f8;
+  00000000000100000000000000000000
+       66af8d706d38d51808409619ee4672ad39c45025094bff004dcab2d29057ae9f
+       5866f66669833af9565097ab80f6b7ab00acc862e71767cf94e7c59dc0645ec4;
+  00000000000200000000000000000000
+       6839cd0cbbd72732d67074d3573594cc7db1285aff8e8c2fbb8eac3d0e22b3f7
+       d5df2fc8ccd2699e5af63b16538339487a94145dc1ed775fbb852b368106dc15;
+  00000000000400000000000000000000
+       4a2afabea926caf55464e6508976960589b0681c0f0c42f6dabde37b3f2c2d7b
+       8b17b2bdb951c39d359b5ffbfe5fd62fc5cf948652429c43b3a580a044fc2202;
+  00000000000800000000000000000000
+       75ae68f8e02256da8395c00d1a79a398914aab74c1aeb6a1fd49ffa1e25115b5
+       182317ac645d381058cfb6582eed55afd1c41a01c1ae6984f475c1c9829b51fc;
+  00000000001000000000000000000000
+       371cda9a5c73b8faf952ce65d226947fb69d22412669709a3759279e3b652b30
+       3d4b5768c554b31a48a8f2493aba5267e7ae2825a224e7fe296dfb2cd18826f4;
+  00000000002000000000000000000000
+       ee23c425adef80ebdde63fe7a6191d8065d719c3d24fc8939956225a3e4d9e57
+       67aa7cca219754c484451c80e76329984eacb8a664bd122ee7c81133f0448bb5;
+  00000000004000000000000000000000
+       781a2bfdcf0f59ff6feb06131eaadec6b3f86febd94e875be5b88262d9a61e61
+       90e87594d441c52f3b940079b3144b16efbb7da652f85ded012e72df45c5f947;
+  00000000008000000000000000000000
+       619835ea64b097c90af092514b6fdd58a5773f4492148463c98a2422e6d29ed8
+       94cff55bfec62839a98e2099bf70024bfa3f36ee382d79273da4cffd2af262c3;
+  00000000000001000000000000000000
+       089af763aad8339e9a9019899dac708f9edd78d984d42105b218191e4547ef1b
+       8f5400c80a1a6944e1494e72823013571bc53a7a0da4ca876a34aa3fc923e431;
+  00000000000002000000000000000000
+       e8da39299778df8feabfc548421775fc8ec1d473bc24397281c1b494fe35bd97
+       ba3a2f4ad75c1a36d8ce2488d80d9a7c37886f0f25cefa6f906c1d3c97028c9c;
+  00000000000004000000000000000000
+       1b6dea579c09a10ff8296c9d2fb29ffaef89169a901f48a1de8d1867e71bed1d
+       306fc026f4f82433051bc469f6b4dbab3840332f6069a91df2cd5f8fa71779d5;
+  00000000000008000000000000000000
+       84ccdeb939ed5ac41671c7c60404991c4411b5ece49d01401a10a3b906381777
+       5ac3702f5a3b7d54d5cd6f60fb5ba7f4eef23aac98c068f706042c91f7b9c8dc;
+  00000000000010000000000000000000
+       f05402b141f7578d2e7190d607ed24c60d169c798c36dbf510f57c106b4796a3
+       d7853ee992f541e06ec1bfae4e0ce59cd02ec65130dd2c5b25164325ff72a89f;
+  00000000000020000000000000000000
+       c225cd7a41b66da52a753fd620c04655e1f5028857f5004617228d0a79677ccc
+       44534e3a429b02d1280c784bc3d43d3f3f7d68a5c1e4bec773bba7fede5b539e;
+  00000000000040000000000000000000
+       5b02c15dfeacdac4a847dbde35f251aaffc17704bf8727a5ad53f84d0315a405
+       b9520766f0f67abb9e3a879239650cc41d90716560d83f6c2115e62c67ff9bd4;
+  00000000000080000000000000000000
+       397b5b0ad0d8540d90b96a293e9e3ebffbb2ab2272c93f5c854a1316cc45fa00
+       effc84efef486e591669f535d5cef87b0cbb224b7e33e0068b4d058a8a81b4d0;
+  00000000000000010000000000000000
+       1e8942d564866774f20a8abe42694994b281278037f373b5c867115bfc8500ad
+       052566319e8cfe1627f10d5ec55ec4eb50cd1b8e82c7bc9859f7b1ede1d2822f;
+  00000000000000020000000000000000
+       b71ca147cb496c3c65099a87e63026aa51d044ce55145adb861f1d473c1d856b
+       d08a2b0bc7ad08d1ff0a4b7f5c285ea9df8b7583536dd58f8d184f9c7a657909;
+  00000000000000040000000000000000
+       c048a83a291148835727a9792e7864550e71812eed389d97c8bace4246ea75dd
+       0af26c6f1f02650ab2532756ae34d59d8580310cc4c3c26f147ff1197a6e09eb;
+  00000000000000080000000000000000
+       4d425145fd1166ade64ccfd5e52734ebbdc31ad4512f74e4a7e5e3e0d24dc18d
+       35855dfc6ae18052f682b171895f775aa94c293dee1512635f1ed5216fb96558;
+  00000000000000100000000000000000
+       9ea4fddb10565fbcd92c352fc81fea49a755a3b64e98ace666f81f42678c33ee
+       e8e17030571a18fb74a91d93c8d2907a5befb7f0695770d203965b25984c9238;
+  00000000000000200000000000000000
+       48059d5828c995e546f8bc6579a167c9ce53d6fde10cf3b7d923be137093aba3
+       4bb16948d4126f77882f10aa89876c55b80b390fd516eef2fb1db6c1527b28c8;
+  00000000000000400000000000000000
+       d3a5ff5dc944cd7944103104173b40aab097ffd6973f7cde14a001c522818872
+       247d0b74d7149225a6c05f832fd51e221730ee857b34671a4b9509cb2e2bd4da;
+  00000000000000800000000000000000
+       2883cdec39ade0aefa06f3d046ceefb87df0dbaa79e978af5828c429d4fcdcfe
+       7ad775fd0742338854dd747b5381637ca5260c90e3954774cb4a2ae8c5a0b92d;
+  00000000000000000100000000000000
+       8d09a89b9bd6428d8461d17682b84cec190cd76a230fbaad63179ae678106aa1
+       11762fa2295143bccbb767f201dc866258bc600c7ba012fbe8caa8fcbf493790;
+  00000000000000000200000000000000
+       e57182f9cfe9d9d189e3d679c02e5102fbc6b7fa449357739bc7ad2c7b479214
+       2203765631ddd429485e18f78dfde1b869195f81d8366f352faf8d48dac3a7ad;
+  00000000000000000400000000000000
+       29e7e527c65204a7a21ca5db7b9a4d9e3341a1af894ec0773de2f3dae3d3143e
+       b87c10b138e84a56de01841ed2f73b15d192500e89337e964025ebf6f6387297;
+  00000000000000000800000000000000
+       b6a6752bc5bee6d41ccc022092cc46b27145fe2902091c054363cfb472d48b81
+       43352f812f48951dc628216466304c09d1f03b19d807eef29a3f720378777241;
+  00000000000000001000000000000000
+       278b6c69b23d755bda9eb003a50fe7a928a38d7c9b85eb71692c79d7e0f0800b
+       dcf964dfdd2ced07b2aa36622f1fd8b7d222d02f9acdf1c1acfbdff9a0199b59;
+  00000000000000002000000000000000
+       cc50d65a6a9184a5f14102010cb4600393da166d264a605150b1c0718f1e04a8
+       c22ee130cb19ece6ba705757d6a416abb709c691898293d31eb66a72ebf81549;
+  00000000000000004000000000000000
+       c0ce6ea99eeb4674828fcd37fb65e7c2af9ea924a19d121a7f940a026fd2dc40
+       315be95dd9b189d192c5c9333a145d8897af5ad256ff8026fdde53f841b99756;
+  00000000000000008000000000000000
+       f5fc52f270dc27f07ad2780891d9995c914f8931dc45f6a1fe423fa5fcfd4a1a
+       f3d2d39afaae2eb6bb9cfc255ca09ed8c46152e75d13f6e2e9f818a94b9a729d;
+  00000000000000000001000000000000
+       c5e467ab0c5dadbacba076637d3ef4a54d1f086612b970b78f562980324e2d31
+       9f1e48b2dbd80ab69f76fc5e827653dbaef521afb5d6949351ebbc31f82c0a65;
+  00000000000000000002000000000000
+       34abac049584a4d1e29bdb7c08ff7ca43dea973e6bbf196ff470d43712610a9d
+       676e22e0c042aab946ee5d009cac02b91c104bf324526c39e6b3a8ce57734ff6;
+  00000000000000000004000000000000
+       701c6d175096e7e8ad4187c1b592cf81db897a54fddbb542152c7d50b3f1b81a
+       77119d05608366998aa3b08e473f4bfaf9e694bc15c15f73e8f33b3fadffbea9;
+  00000000000000000008000000000000
+       4e98b3ace7c111c1e81f6f2b407a934877a1c08fd0dfa9eb80698d985d68fe23
+       83c58c3066f0c4feff1d4d5a098afd3521e30fd8a0ee221a80671ab1c17f40b5;
+  00000000000000000010000000000000
+       e1b4125ee35b0e69f1aac9556596147bc526647375781e1926732976a77f7550
+       a341567706ab2a2cb79adcbccd39c81eea1e36e1e0eb8f118a9fbc502eeaf105;
+  00000000000000000020000000000000
+       e479c9546ebfad858cb2353808aaf1a51b1473f229f81e13e1b5dc7cc7fef349
+       572915a2eeb3dba77a3596075313d43709e01baff1e591bcbaa209703d3a0bff;
+  00000000000000000040000000000000
+       6ca46d724403120fa8517f40a36eaa1759653b2d91cc9107c2328602d04ace40
+       4785180fd5f43b9941ba27ef0ef72eefddc77c9dd6ad7ea0f11211b8b55e3025;
+  00000000000000000080000000000000
+       32b9348cbb3eebcafdb4716b69b73b0677e1e5e3e6e68758615809fd06a15368
+       22d90cef816242b9dcc7fb7fa644eaf9643da10bb1136cf6788178aac1e532a9;
+  00000000000000000000010000000000
+       c3ed54670a25cba194830476ffb2f5d765d5dcf476235a0e7df9f405a8679771
+       caaf44da13d9a6a68c162810196a8de1facb747efee5d73d0916da3c4828382e;
+  00000000000000000000020000000000
+       7e20b32d7ff48cd1be4108dcee7c9e61c99d3d23a79c770a3aa10853e04b0dd2
+       75779c17a8ef0d15cb1eb48decdf3d8c3823eea7c8e75b8b2393b898c4c0ca6e;
+  00000000000000000000040000000000
+       43adf9131d705d4a66e300af90ce15d82574e71ca62988ccf4cd03a460518889
+       fdbc8f6097b19e5ce90411f88acd3002d27270de234d79d8808b950f65e3921c;
+  00000000000000000000080000000000
+       93f2c1b9a55a325d39e769b23da246865f66e15f25dd6f84f44e58ecdadd2091
+       06db50bf315c02892d1bbb304b63ad876b8123cb87a9d1c4b1681abac4a6230d;
+  00000000000000000000100000000000
+       39bcb5eb623be3e37858c37e7ee77a56f7983b4ae246658264b760e77242437e
+       ce60286ff551c33f6a96510bbd33632721db632291c54543b641b0de5d0045a6;
+  00000000000000000000200000000000
+       b1e70576e01c1f029dd9b309670bc41161bb13888b1c93c6f8a0fd2f5a6e7fc3
+       45e345d2b2610909dc837aaaf07d58117189369c8e3bfc5b718457083a61346a;
+  00000000000000000000400000000000
+       dc8af5dde236c0d2a18ad310a21abab9549a54c4b3f16d6e3433578f35f04322
+       94580e73b2ecb615c73fced8aa1b14180068b8a1aebd3b677e1d37c21df4abc0;
+  00000000000000000000800000000000
+       53823c917b2dade044551689d7f703fa83f31237af4f4687016c4ec13f435993
+       1bef0d32e4ee66c805f793553852ec7b803b300c5434215cceabd276fedea323;
+  00000000000000000000000100000000
+       2c5d0e5a610cc3dafc0ea2340d8340667a7870ffeaa2b88056ce23c93131f9cc
+       5e73c45a4318ac800e3459af74eb3fa7a2010b3bbd53c9bcd51613fc63cc79b2;
+  00000000000000000000000200000000
+       118d26d3c0856588f39d2f654eff64ded5e93fd1900e85abbec0a2c25cfce7d0
+       20d1d578de49459eb928acf39f46dc28089dd3972e57818e0a49f46c6d0576d2;
+  00000000000000000000000400000000
+       c1253993f9b3f51578f16f5766161b3ff425cf569432121dad3eb9623b9ebcf7
+       9acbaa6aa62d50751f95583545dc3b83c235e18a2b868f4d866e86417c75a22a;
+  00000000000000000000000800000000
+       538012f59baf81597c561b999827d7e177542fda70c9b8a20180042cf49f0511
+       088a9449af39cc0b2a88863fa939f31c8730e696ae260a286e8e5f725167e725;
+  00000000000000000000001000000000
+       8e058aa747ad629433aef87fa710053792c9ecfd6f04f749aaf97bfe280707ae
+       70add57b59bd76f07688c0d9753dc6576301471052885ca8bfce36a8ae17a7dc;
+  00000000000000000000002000000000
+       54eea8fd10d61d8b8edd62f26c4bfc47a1b444210c1550c7860cf558de3f3e02
+       d22c759d1cf0da43c9ad0cc3ab34fd4c0d24dd4f0a12050af976705422abae39;
+  00000000000000000000004000000000
+       b117f239922fa9d89f9a0d77d212f54a82c20b14d2031892a1215ab70dac40b6
+       e9f9ec1886337f55d43ed990227687c796aaf978af708ca6ed2308e4b706a2a5;
+  00000000000000000000008000000000
+       bd17e0f86d1043e1f48b5e3bd2267bb9d1834d4c710207deb618b9786610c0e2
+       e251c120f7141aa0942b275c26e487212849330a798f392229a2b4909b97e9de;
+  00000000000000000000000001000000
+       62a328c617554b9382aac406ecaa84370fc28c0b600711ea2ec5d132231913d6
+       568c846b732c9ec98cf437fe67a223a7e7b63d42b20e57fe95572a2fc6cbda10;
+  00000000000000000000000002000000
+       41242d5ab9cdf29b78ad952fe5a967918df393d64613df7145adc5f540ac163c
+       87b5af373d78b9edc963cfa1f2b88a55143fe2996403cf6b12ba4d2a4de0dd95;
+  00000000000000000000000004000000
+       8d075e35e0cb14e23310bb213e59c416d35bcdfa548b7e4a45ef159c10635532
+       57392072b104f59f65043656c14ddaf32ac366f0cdbedffa7c5482be297da5b3;
+  00000000000000000000000008000000
+       01a45d81b5100e5d8971525bf21993c8d18d637b17d91b5d704c54cf081ddc60
+       73790c7237a1eecf35349452f60d4c934dec2a3f42f4bcc4939e63245bb97882;
+  00000000000000000000000010000000
+       09843cdeef62a0420a74674575790d67934f88dcb8492a6f15aff243c8e15e4f
+       dc36416b1f0a13a0270816309d20507c6479f735acb3b35c0e5700c5349d07f0;
+  00000000000000000000000020000000
+       31612d05a352c54e516e379767c096a79a1c4234bd17d4f46c73205980561b8f
+       9370ac5d3c467aa1f55b94fdf7b396c2f2c425d65e49a225d4a12354d586e2d9;
+  00000000000000000000000040000000
+       ca61064d6edd95e3aebb9ad2ebf54d515272ecf033e146c7501a240aefb1f026
+       68c498a69f4546f60242658595a81dbb0eff031e29bffb9263411f8d346e6836;
+  00000000000000000000000080000000
+       f126d3c9eadd62db15cd371ba858acad93d9c0905c3e956566dbd1e5fbe4e43b
+       0dc0eb6ca4d30b01f19db8d9484cbc92af194cb9cc5e698af8f9bee1a08a2f19;
+  00000000000000000000000000010000
+       1f4b3e99d260d36d735f79f453108bd7ebf8746af1f39348adc65d59af6a29a1
+       8a50046878a62f10557d8e94bfeeb1a26ba39a9a5a76881ca056deb54082db16;
+  00000000000000000000000000020000
+       b4f573c9327db5e44aa95583f188849edd8454c6f31eb18765de7142ff91420a
+       74890b23d53da33244da9f908d4812d27677a294c61e3d29d7dd495f394201a4;
+  00000000000000000000000000040000
+       e52d19603539f17a03ea93ca700b9eeb5a9d23de423d4631787c1572dec40780
+       b97b5d286cdefb8d83cf18e6c1912adc34522bb6488e7abce2cbf743851743de;
+  00000000000000000000000000080000
+       3abdcaa1600a946271ca2ba7fe9c7290b5f90adc1978e0cd5348747b118cbecb
+       f740e693758e1e5626bbd773a0a42a967a540498f250312d862579f7da3b534c;
+  00000000000000000000000000100000
+       77411d75f740551a003ecd086d4563c881714a79d053f1d99120dd742d002fe3
+       8cb92110e3a28d7c42852b6e1e16f31c08693879ee68c8eee020ed9466904b82;
+  00000000000000000000000000200000
+       09338341baf259f56644c919461974c3b7c81e3347d983545a993239bf051f62
+       1697fb4786570b99034fa0bbec3111b1d2765ad4f21492721b797ac485844630;
+  00000000000000000000000000400000
+       728b0b2d9086928d19bbd761bbd18ce018114f9a357fc719416629be99d569ee
+       bfb243eb7dba6ceb8fcbfa948b91d438a9ac80c960adaea75af7de45fc3cd519;
+  00000000000000000000000000800000
+       213be2a825b5694f131d20465a490f8805cce1b471ade0fef8ae05d473d888c3
+       fe381bc82b11191ae1ba5e0e526bc64eef8a69052805c532ddfdf7a68f26c6cc;
+  00000000000000000000000000000100
+       0918a9151b01813bbb43772707ed48e88464966f41581a23d1422e936b6e5dae
+       65b87265aeefe0e04cdf2917a51f7c46b96b95645d4b4f8ddc40fe9de229e1e0;
+  00000000000000000000000000000200
+       d684c064f8ff906797e3c1046bd1dd19f1defa5a33292947081c35cb8c2dc0fe
+       0e4fc41d8e7761c4e75c62da50b762820e396c794ec02386f96ab6ae4f1bdee5;
+  00000000000000000000000000000400
+       568310b144f484cb6468d0140ed4d3ad6da518960f79660c7ac827f065f8f9bc
+       ac82171949984f7dd3d23417b98cee5ba45cf9e67bc2682c134ed58828f29ef3;
+  00000000000000000000000000000800
+       3478b762b87196cf1f12e19dbbfa8b9f7ae89c5ba32ade4b9e292f40bed5daac
+       f455d1be4bd6c9d8f2ba12ee2506ec58774f51c61c434fd29bd307703909f9fc;
+  00000000000000000000000000001000
+       61b4393bc414920b4cd28f1b62bd7d14ce09750ad2d5fa055d7264808bb49021
+       3c6b3f7410e47215bcf5649ec69aa2aea42593d18ef388f60ad8c1a74a159aae;
+  00000000000000000000000000002000
+       76ce612f9d8530ea654509986ba4a0645df0d0b80e10e2b12e6a4cb702f95c2a
+       c0d96527fe806580b6be5d69156b82dc48bbd4b12d4990993d40cafac328f24f;
+  00000000000000000000000000004000
+       72d9661f54335be3bf33f58b0691ec93c9a609c17f0fa2dfbec2447eb34e767b
+       e93447fc36f2f9d37e2cb768c89db3516d2101efe05d0c3b22223a1ccda827e3;
+  00000000000000000000000000008000
+       8e021165e98627b217339085ae839f83eac9175aff22755ad7f74ebaa20fc5b6
+       5d2972b74ff22287c8d6e4e970bba73ef9fee1e4fef6ab2b99d89266369d5069;
+  00000000000000000000000000000001
+       dc73ffab02254f4b2284ffd856e2919e87fc0b9527d57b9e3bf61a31d03b81dd
+       635008b2f0fa61c84f18d7a35a7a7348a962f913d1c9b2b4a5254d571da005a7;
+  00000000000000000000000000000002
+       4afecb963e1c36d3136cc4f4daf50e6bff15f54267917b3351678e4600523aa6
+       7fa9d1013537692d705c5182b9091c05966dca86d0028e14189116c19f000260;
+  00000000000000000000000000000004
+       9f4b44c46e94743c924e4d8cc858d6283e60143cc0874a1937306a75052fe73b
+       b6024707af59bbbb0615bac2ca2a33da7b06f1073959f2c40c3959bfe97393b5;
+  00000000000000000000000000000008
+       63876e05b127c60c29841b6ca86ebd18fef4dda37a6a3406e043b26bef1c3e22
+       a14ec552b38c9dc86fcd937f6e9693728fb6a2fb7d3d58171cc0ea566917ff0a;
+  00000000000000000000000000000010
+       9edb39dd3c860b44b0b9c8c3ad0409c4d5d46ab9da835790caa0dee5fc52f638
+       500c304547307d1fe152c11064fec74c57ce41f6aab2b169c2f16f6d08fe64c7;
+  00000000000000000000000000000020
+       d8a17909a21e577f2e328d71016f71de512b713fea91321410a115be5acdf642
+       41f6f55e0f5f58366cf9545cd5468e2d4959ea3e68dfe86ab05bffff37e9b7c5;
+  00000000000000000000000000000040
+       e6b771c2479f884e6b02273538b9c801699b85cf9becab29c5fd6a0cadabe4cd
+       73ab7c6f4490bdc9db345fd394569b6ecb8a645e0d3d96f6b04ed878f24c399e;
+  00000000000000000000000000000080
+       0f2643a424943fb1911fd77fbda4bddec8e2c7e0fef23aeed6229717f6fe08cb
+       cc23471cfdb0baa7a388ad9117c1f18762ef40c169b31ea08d045cb79499f78c;
+  0100000000000000000000000000000000000000
+       8070a4f0b3cb8b5c98a481a434bcd1f9fbe57a6bd2234f65d3b13837669d0123
+       ff5afd2824da440e1db01ece9ffffdf0f385dde8d53e1d2bcc105cc6ef9da6e7;
+  0200000000000000000000000000000000000000
+       d6eb96497103e048ac9c11cb94a715d02eeadf278cbeab8fad0cb6a0ec5b0cbc
+       bbe61f08d13b874806e69dd218276e5063e7f1f751f5925db4589e4c3da1e297;
+  0400000000000000000000000000000000000000
+       59d339d55b08d800ac4ca97c8d86a5e7c1aaee0c7e65ffa266927b3405d60e98
+       96f4751d5ef02128272f745f849b156b1ae4e9b0644a5067fce133d27c60d732;
+  0800000000000000000000000000000000000000
+       de5325a11316c25fe1b91e65f79d3c6a22b828c4964f23fc45e633f15a87d595
+       079c540a230618dfe713e1829b8c7e93b0e158daecbc960bebadb82320efa77b;
+  1000000000000000000000000000000000000000
+       596f017382966b3627b1f25542af544e84ba96d8fd3a8aeb70144ebf31542388
+       59c9bcd67749151c8298766fb67942b6f7eae3cf18a4360fdb712cd5e75bdd7e;
+  2000000000000000000000000000000000000000
+       b7949a04ac3f445ce916cb9e09a05f9806ca7f0566c08f8f0dcceb97c46d1b95
+       f7f160bb58a6190f3c070f2cac35b8ee30849382870b34b705e4f7dd308fa403;
+  4000000000000000000000000000000000000000
+       3c881dd73e0144100351026376ce0a6a1941f10c03fa89ff2428d8826cbf1903
+       7aefa4b489a42ac86c105d410f5979fcae26792159419768cfd6aa1fc80a6f34;
+  8000000000000000000000000000000000000000
+       b32024da4d4bf274e91d9bc3fe46dc22e69c8b4a63d64c7b25e670f7c03c8bfa
+       8e14c8584620b3d9782e828cacf93af391de629ef9c5befe7da320ad6f9f8b36;
+  0001000000000000000000000000000000000000
+       0f4214c4d1bee959bc8c28d62cce6dad19939f6f860d23c635bbe5f384f12cff
+       6008e0537b75cd2014da4133cd7712759fa1643be44533e1b2a03dc54e2290b2;
+  0002000000000000000000000000000000000000
+       3ec7603e6690a95b44d45c6fde7fc3a78aa7b6eed2bfb895edb615a46867a7d1
+       f8fa68c2908dd06a866a2c4fa3badee7c599a096346716ab31a7561db7788e25;
+  0004000000000000000000000000000000000000
+       52dfd065752448ecb5ec6b0d6cf8fb9f8e8a49e2102e8ff7c37d5b3dde9c0a28
+       b1f3f4bf235dff66f32faa679ebfd5b325611ba7d3f8fc51d9913e12f14de3f5;
+  0008000000000000000000000000000000000000
+       3687e56d4ddb4747cc5bd9d87d788741762c70d9788726b5cf55212994138b9c
+       81515cb2c8263971f764fb31fea9bf985b8407f30fe10c58ba520806832e6e73;
+  0010000000000000000000000000000000000000
+       d3b22949ce07d1f3d987af325246b02d4ee0e7a25ac7ba10d9fc3b92733fb076
+       448dccbba85ba4427e57bf048c2edccb826188767fa6223cce97709c3f3bf0bd;
+  0020000000000000000000000000000000000000
+       d6d1af9d789c6e91d1843d9ca3a45a0b7acbe96a94653bed6745d3c664d372ac
+       c32c33ab9df34036b5d18dff8fe15e57b3b290b0b734417035e68bb6661f2d17;
+  0040000000000000000000000000000000000000
+       bd8dc5a89393dfe78f81b85ba045b2d7a2035e38bb21f44b3ce1b15c617da6f2
+       d0a5f64dfa590de17e3fd7b9fde24de1418221879c0465ff2e9b8528d3cd4c1c;
+  0080000000000000000000000000000000000000
+       6e53761d95b891678bfa2f193b92d41b83e8c20532f35558be5038e0e85a0e8b
+       ca8bf1a499c9993cd56e17e5db838f99ee6e29d0f4ba6b0d684f543b71d7a489;
+  0000010000000000000000000000000000000000
+       43ed0aca7101f8fb1495a03ced519942c69f4504f2be3509ab35c0be0de4cc2f
+       b4536eea97929db21b08fe4ea78d3069f286234e2e287a3097480538bac74b62;
+  0000020000000000000000000000000000000000
+       da9389cf54ee87ca918aa30b99a37f50f67e2ee8d27f15cacb4f74fbb1455844
+       28dca73c0a5b6500370aa766fd03b596ef1ad7cc27843ea83c846a258c595024;
+  0000040000000000000000000000000000000000
+       61a6288bad6f3a91a68752814a0c8acefc56b94b4c45b282d3ae3ef6029e0490
+       8b8433d94c9e6b4df405d6d3214889231efb191e1d3aec05081f982f32054841;
+  0000080000000000000000000000000000000000
+       d7141bfb37d834afa650bb1d7839b34d1ae0ddd517864ca48b310b53dba1a47c
+       f68a00c3126b04a87d6a9ff061fc5c8a2d0e66ac263094fd3f081c14412c4a73;
+  0000100000000000000000000000000000000000
+       8ed10898964b362405b3996a4a6ba087330190e6bca03990e3218a33411783f5
+       baab2232f4ca0ed0f54fdb2b0f73f8433c9af741034117f9f5d2cd10615941c4;
+  0000200000000000000000000000000000000000
+       89d7ef42eab86d3209b67353e76da8d8063c91447f916f91378a627a49a0e459
+       2a517f1fdd3019a3d026d9f3a47545ee96634ac8e13b1064a57f82218628039d;
+  0000400000000000000000000000000000000000
+       009ac31bd1a5117e0368fdc254230a92cfbadd5984fedfe684b3ad18d0489f41
+       a5d26e2813bc41a4e9c40af519b72ac6b2a2188c8b89c77a410b6fc732c41581;
+  0000800000000000000000000000000000000000
+       1270970a59191c419b2de4003db3467cf453ad79ee93ccd5ec06da794a0174a3
+       99e4e43c3199b6f493fa633303ec08942b6991188b987900ff3b39699f7b6485;
+  0000000100000000000000000000000000000000
+       ef02c43eac97a89b7f0ffd491a031dead11231530abaf2ac6b2ade53e2f742be
+       8a74dc87527389474c1399ac4b7f4c47522d8b93df856c96c129456e5bcfa0d8;
+  0000000200000000000000000000000000000000
+       66efd72c1ad170588847c1ac5f1e957e38e4e40eb891bb75093ee03d19339141
+       8a822f512118c172bf832680ccb9e0e867e04ee2022db6a27d98ed56ea9069a0;
+  0000000400000000000000000000000000000000
+       cdd36ee6c5cf010b1b093b8f5e0d91d742af7a32b6e98f9ba412c1d523687e5b
+       92f8d1fa8d6eda70f7c404088b519cbcd3f31a755b74a7c4474ae4eca952c7ce;
+  0000000800000000000000000000000000000000
+       99576731bb509c8f2789eca8269cb7d200e7e7c487a59586e7ca065c6947c844
+       c4041960f5ffca9c75a7d27f5865fab9f2c8c536ad6408d191470f2e0d6ce33d;
+  0000001000000000000000000000000000000000
+       a49eced3ac57b8733ac330b477469b8d0d127edbb76c8b928ef8f3f6e7a844ad
+       c048e5899e9eaac8ef454098a4bb1a48e0cf58a06d4f1f19f490452e43c23888;
+  0000002000000000000000000000000000000000
+       6372e04bdbf3f8d4998cf16dcb310a17d4257042c2ab5f31ce7d75a7c4477ce5
+       e6eb8f3eb48465f368a434ea0e66a5d1bd4a8bcb3cc665a48f9e20d6c15e2d8d;
+  0000004000000000000000000000000000000000
+       aa3bf81795afc567b3860441ba542fadbe778b837d89972e419d9dea5f886cbf
+       2fe69f415c844ef3ead9e86620844dfdc9af44c0133e5655130fd53e59b9052a;
+  0000008000000000000000000000000000000000
+       8a5c212066e91da99ccd0a8ae0fa1c7f232ff503fdf33d84a6311d421c8a6e32
+       a2d43b8ed9c582f1ec1b7867b74c81c17450698fb8c2e2333e4a7fb9986180aa;
+  0000000001000000000000000000000000000000
+       e65a5b5f8bf7395960e4150e682c586156617280b5dfa259310491ebbe5bffa5
+       473a1e953ea38940e3d84df3ba7b6fefbb7bdf7302a9a9d959d088aa56fc439f;
+  0000000002000000000000000000000000000000
+       215237bc89cf72610eb50cc2f788fb66f5dcf5a36b11148d25f87d3fda60432e
+       e1e465d5d23f00aac475c9021a5dabd753c292e6e0670d8db8e5e2519476c3df;
+  0000000004000000000000000000000000000000
+       521741c91ad5fde0abe8ddca960ca3535041fdb1e6446194e63d1930e7c96be3
+       32611c8c38cc3a0df330bdfc4ad7366287ab2c22dedd6a852e63eea38e84192f;
+  0000000008000000000000000000000000000000
+       dd7eb22684ae6346df02da61fabe51ff32fe48e5c2f276976054c7fb400ca640
+       8702b65a7d1b61b5843dfe394cead041a481f9ddb368187b60291730d7132b7f;
+  0000000010000000000000000000000000000000
+       5fd0b1e839354deea2b44c7811c94c81a8153e6bbfed98d4e744b02fc965bb5f
+       3c6bec05f5cdb092483cecb0f7996d3aecbdb8f7d738bbfcae9d25a210d3b94e;
+  0000000020000000000000000000000000000000
+       39c6626868026b6a15c5ccfa2f83dda7018b6f2f576de8cdf009d84008fc726e
+       b7e8ff789bee4bdab1fc6c75c73d83dc3cbc1d60c232f54c4dd946470b7f0b8b;
+  0000000040000000000000000000000000000000
+       c945f53f19eed324dd2035a90014bfeee3c46216f26e7b74978dbeca03765dc7
+       38b825729109c791dc588f392f448085ae8da62feae27adb5d667b7006fb1edd;
+  0000000080000000000000000000000000000000
+       ce0d4ce7c9a8c7ccd6ea6e5d433c4d7db4663542a7d1c90dd431e552045f5155
+       c50ca8e102497116dbb78c0bfeb0e39939b5aa59bb7cac8f127ff9f693f7b124;
+  0000000000010000000000000000000000000000
+       dd675ec3415137b62955dc917d348109c45c85de9c60095f94539dc9cbfde9e6
+       f26014ef5bebf40dab8052592070a3a2f0eb6fac1b0627a8cad7c8fd19511e41;
+  0000000000020000000000000000000000000000
+       cc5398fb1486ee124e32221736c765e88006f8e0f31f65e337f0703241497896
+       e8527d10755dc5ed2512898102fa37a952e12d5a9cf99ca663c4f8aa556107ae;
+  0000000000040000000000000000000000000000
+       ba7a51cbdfcb2b3b9bf200cd0a5c7998c5753f861ca0d2591c7df18319b0780a
+       6a5aa39bd5e4856eff8ce57422623aeb5c5fc7099c6d59e0b8d1f47040f833bc;
+  0000000000080000000000000000000000000000
+       f8b7f1b3006cfe461b183397ff4ca13eaaf8c34528f48eac5514614eef979d2b
+       c276a602c32cb0a9f15d45a70f606272179ff0b13e804fc3290d14cea182d555;
+  0000000000100000000000000000000000000000
+       8ba47e063938c6cadd65fc3db823e83edde887175d6103417f2648a86ecfa38f
+       f2b45766823ad20d89b12b1eb65ea10ac1f4ca042408f775e82c3a86c7d870ca;
+  0000000000200000000000000000000000000000
+       82f0a8825caedbaef6991dd7cc33d8a22757b4b65186bbb70dd274486bfdc6e9
+       e98621489d27a3f8ffafa5f60c454f5b43073fa13b7b1e44cf5b42c1f410b757;
+  0000000000400000000000000000000000000000
+       c748b58d58bd39b77224713354f8abe888a55813cedbd581c811edb61f6ea33e
+       0341ef9ecee1633e77d1d8152dbc4b536cf1d5106e279f99bdefc7f65b002dd1;
+  0000000000800000000000000000000000000000
+       cb1703a29bfa0d5f8e074f8c8efad1c3f99c3c9d56270a3b0b223d792414a6a5
+       153618a5aa9ce0a5640c395dbd5c65fc78ec091d9268083bf1a8ea6309572237;
+  0000000000000100000000000000000000000000
+       da0eb94b57b73ce632f0e096e8b9657a8df2a7602ff80f33bd23621b3a9011bc
+       84946c36ac9e6ee65c9f39aeada388f91304420de373b45eb9899941e2059bd9;
+  0000000000000200000000000000000000000000
+       28593a296d86d90b64ccf70ad60d0806c194a49477369151d8d1b1f534a73ccc
+       f4a5b4c8f1d7a01e23b7695421e91f864044ca51b3d6e946eda4dccc66bbde88;
+  0000000000000400000000000000000000000000
+       5432743ae99f48de5c2c943b81b4c994e7af4a9df102302bce61e51da7b7b1f0
+       cabeb087d68155a0ebfd81f81ea7a0451347e8bf2b409e4d3db752de191edaa6;
+  0000000000000800000000000000000000000000
+       c68b1f8b2e568b015ae4684c81d28e1dc4f2bf15ea8637043589555e59fea56c
+       3c7c59a6b7446857459e8c2812f318c99d6f2eb8afdc8f7cf3fe79b9e43ebe6f;
+  0000000000001000000000000000000000000000
+       1e2ce4d6fd55f7b624b05e5ceea3915ec6f061229fc5897fb5ccbd2041477968
+       eb6ff717f26c66672b5c99bb95c0604d812a70360e361cfc1ed6f67226f2f738;
+  0000000000002000000000000000000000000000
+       882b04a32f0ae1ee1c03856d4997bf168482eb9e3c66db15caa3a5ff61f92663
+       a28f92837893ca7cdaeb5afb82ec7808d6c0aa734a81c4f9e8c207211fc00dd3;
+  0000000000004000000000000000000000000000
+       0e6d2c813dbcf23cd711ecda6066bb9d03a9babe2f6471d683494b58c0788d44
+       4c601b1e752c45492e42f54e5eb528bd884a242a96bb8a638d9b92201ebb3707;
+  0000000000008000000000000000000000000000
+       6e697fe8636b48bea38357c377f999c717fa7ab055a124b20868098aec8def00
+       cabcf9f62a30e5a27df4064af20a3d6f0db35f915f556fc9c349f41575f97247;
+  0000000000000001000000000000000000000000
+       9bb65307fb501877e3ada81442cde498d1e05d7cb5deaf88ff1f0b6db92da4a1
+       c7972bfb8c66bee89a3cae24999a2671a661bb5e3591f811749725c31e95daeb;
+  0000000000000002000000000000000000000000
+       4b1c3460a94891e4f8708feda342f8c13de4f500ecf890c23b54614f759c351f
+       3dccf6aafd9acc0a52003729bc92cf541c72f1175408aef6754c07308f3186f9;
+  0000000000000004000000000000000000000000
+       237f3b1b70bebf261fadf4fbc61f4aed6b2f7d41fd0bc3b8701ec87f0ace3b73
+       9b575ace6a7d3614985498611990b61cc6fede975d36c08b48f083a2eda498b2;
+  0000000000000008000000000000000000000000
+       55819dc855dc272f8e813f473d0be9f7b0ee777581c68236fd55ba7cfd7fad54
+       01e96efb1cf82aef7bb041c59e16696a196fd263376d478d12d5c21f8b76bf38;
+  0000000000000010000000000000000000000000
+       46a9e2ece5c6a61677e9fa44e91c15ce095e6c2af0e66e3daaca8be8f55bc072
+       9d1d1717693d05487a24e6c0824c07ad87c0490e6a29de6332e5aa0130311fa8;
+  0000000000000020000000000000000000000000
+       9163353b13ab53a5f0cb758072b96891fb46d429da59ef58cda3ba1a9a2162e0
+       2a939e32e660b6cbd4ec22903b3eb454acabe834e59ce753bbb566bda8e5745d;
+  0000000000000040000000000000000000000000
+       53653c0563d023d51c758273c7ffff07897ed19015f2b352543711805f25d2a2
+       638a9f6d0768463b2716ca71fa1c3ef0a758cc2f47e0d3c3afcb50202f251ee3;
+  0000000000000080000000000000000000000000
+       7b1d6650b48a58d529d174d40c34ece0c4725893508723c9e110306f12d2769a
+       09a5fc3739cd6e79e94e250eceef8a31bdb30ecb4f4f47e18f9a3645e82e2642;
+  0000000000000000010000000000000000000000
+       92fcbceb6fba200a50f039637b8afda2c5d4a06efdc98e6094a986d0eeee92ef
+       08250f4cc12c732a3b1a82411ec4a8604bf119f69b07072961758780c7db87e4;
+  0000000000000000020000000000000000000000
+       82af5330a7aa9696a6be8129342b9b1bbace0b879ca107b5184c0902793efa49
+       c286bf6ab754af7f16244b9de2566e9442e13919b2d699d62f52d384362f6331;
+  0000000000000000040000000000000000000000
+       93e0bf62136720977660e0eabd4694514371b3b54a27027dccdfbff5aac51f34
+       29955264c6c52f5fc3c5475f4f6d478f1b17618585097b9fdeae091bdb9e8446;
+  0000000000000000080000000000000000000000
+       69563766cc3b858a015e0655cc056ac5356ac37f3561495fab6a012ea62276b1
+       41bda0a8164a083e3caac42fb15d94247181034d2ade38a1b4399eaaac07cbd5;
+  0000000000000000100000000000000000000000
+       ef0523a9b2ca36ad2b3b9bd9c2209a1ab8c8dd205e48140d577de7ac0fae02f6
+       5f3f8b6b15d822ff9d852c701294d5c1bc2e5e20c4da9e56dc2ae6f1ab33c084;
+  0000000000000000200000000000000000000000
+       0df666c1b2d781312887e6d30f21f12e6e2d4dfc2bdc0b5484f85d35c091a453
+       87a7fe3652e203d98ec75f3c61afbd47f8fe2f50505860a093a7aee292366d10;
+  0000000000000000400000000000000000000000
+       99d1b163bd4fdd4bed820ddd6f4b5b8fa0f1590a97117956570a1a0fa075c473
+       24e6a698f9880e19447971c1de0d598472d66df54ccb88624369af5339e4627d;
+  0000000000000000800000000000000000000000
+       8a76142c207334f1482a7b748f48fd583e34ecc52c33ca6938a10afe9fdabc43
+       8311c7ba99465892df7554b6c06740333d4f4e79496b6bff747d87bb3f88f780;
+  0000000000000000000100000000000000000000
+       1db97ea24610af47d6b4a43c2ef0b031a81547d98723e46aaec6d8b4e29c2d8e
+       ead758aa4b4ce689d61f7705ebdaff4334bb882e8286fd6655398a8f5013449f;
+  0000000000000000000200000000000000000000
+       38f0302fc696e3e644a4c58400b050275c75dd77880b7c81b48bc49f5eec4566
+       fbf97ae99430d0582c8818945aafaa9d08516a56150d96842c67a69aeb6f79db;
+  0000000000000000000400000000000000000000
+       e10afdea821dcc504167b562bb1abacebf03a183a29a85593f51aa83463ccf42
+       1a60ae0e1289cb5477717f4bc7fb936b91d2018a7121f29db751b5ab9c739657;
+  0000000000000000000800000000000000000000
+       f8178e6e47dd9e38fa46d139e9da92320ccc56580ca6790e6739d98a16cbff2b
+       4d5274c530a947a0475c0581f946897e2b4f9e01cfd5e9edd5f00109724d63ef;
+  0000000000000000001000000000000000000000
+       057dad112fab7e5e2f13bfe3692d29cf7231169ba5456837384e1d3178d44399
+       493491ac15958b53294afddbcbdeeacb34f1862c38f0f8514b3190d494611dea;
+  0000000000000000002000000000000000000000
+       32783556b2a205849744b683e3c1cb67a4546671d51adb868f2abc741d277ddf
+       8b7ed6253816d59663a99df68a9c4437ac9ad45c2d400097e69c1492f5a26ef1;
+  0000000000000000004000000000000000000000
+       192b1eceb03afbee8bce727185baf599c1e281b6819b219f7c604646362ef507
+       21c826646e076e934f521cdb6933b547e1f58a1005eb492d768a8abf545f99eb;
+  0000000000000000008000000000000000000000
+       151ac1d0c9497bf7905ac32c3bee78042c1cf57d144b33563c0d524197e1684f
+       532ae17f1858e56b4fc1c3442a3eb5aceb9c38dbf6c8373740d2c70ace135610;
+  0000000000000000000001000000000000000000
+       43d263d71480616fc8d3ee5f26a7b4322f64c52e2eb08bf45da98a501379d42f
+       10915428d4d72172524b0af0a985b857b11fb208305fc96bcb0bc5da329e5a4e;
+  0000000000000000000002000000000000000000
+       b93915219589225d93000fcb969ae487a545f909fc74b6eefae8ead8697f4a94
+       2071b90c399dacf0251cd331d008b40d75c5fef91e76c2319ab297226cfbb751;
+  0000000000000000000004000000000000000000
+       63304c37894c70bb5d871c7cebd6a03e5e63f4e1d0ce0149c287f148d2b43bce
+       5d7fcfed1eb5cc9052d66c073e9817db944323b90f2e60871781078aeb23cc33;
+  0000000000000000000008000000000000000000
+       56f9602f84bb4c0c7d7cbcf427a401fa8c063edead092d93a27ecedbbc080238
+       683821a05f317992c6ed3dcc523d147872ee872552fd4d9935e72cb6880c8ffd;
+  0000000000000000000010000000000000000000
+       a36adff7f8c3aafad248f0c875e959212b533e09747a95c89b6443487b426be8
+       2028682f6b9482f668e55b06144ce444d4bfffdbdb119b2552bb2ceccfdbad5c;
+  0000000000000000000020000000000000000000
+       76131f29b957f35e6b776ea6a737199b00f945ecfd146443de23d1c68434209d
+       1f40950024d089bc682ee4b0fb5fbe079f988058993f3d3ff928cf087cb99dbc;
+  0000000000000000000040000000000000000000
+       6589aac4967d58ae26372b64a7fe4741ed93ad4bf7fbe61f147c0bb21056d95b
+       5bcc6be06b77e64e4f04ab552a0035c664be7c6ebb2a781e7156cce573e2856e;
+  0000000000000000000080000000000000000000
+       c6ad32c723a34b02cfab4f5f9d5b6f14d2a27655620fff9650c5f496271594e2
+       64dcacef6699660227dad31c50c1752711dfd4df95efd2918391371cbdb19f6b;
+  0000000000000000000000010000000000000000
+       637460f7bd663081a501baf9fbd8f910d32b74f95532c73d2931cc1c70b6f61c
+       6611acee8bd7dc914cb5b2310aa37c44041d2d16d2c6f66493d7d0364ea0d137;
+  0000000000000000000000020000000000000000
+       2498e35499439986614f26286ced257b12145afa582093f2df311a6eb768a3ad
+       552f96f75bc0d3c7995970c9785cec08d1e6a848906604d7ca1410caa09110b8;
+  0000000000000000000000040000000000000000
+       08d3d5cfaacdfd78f5890e84ebffa55f6a30b332d09aa99f9a39c57b1a6e64c5
+       bdb53e5e22c6dfa1a7ee078c6dde02f999d36a8d2bbb4bd6d8d63344b50d7f19;
+  0000000000000000000000080000000000000000
+       6cfe9b516cf7e08a58d825e13c4602c1c878297b993fcfe48398e8d6db759940
+       38f793f71c6896b2ae6bd730a548210cbd9345ba211180de67385a6be2aad623;
+  0000000000000000000000100000000000000000
+       eeb6ee8db37ba7df8caa911e25dc2fa0077b3931780d2ce06d4a15e89a2c859c
+       f4755374b79e4a32021ef5a228d8eda5e7aafebd43f4c6bad599e957e3b1adf2;
+  0000000000000000000000200000000000000000
+       6ba41750ef7da69feb66952b1ed18b75e20086c0bab3481d8211a686f317166d
+       278cdb6ba1b4a9b624564a5a76a713887abdeca0ece63a6f0aeca268d8ada97c;
+  0000000000000000000000400000000000000000
+       872c1762ef5842c8c9f7117ead43024f8ad0734be8d1dfb48b2be8fae98cd374
+       7cf31344e19d4886a0b36cc6b4777658216be3a32048e89dda78470379c0c653;
+  0000000000000000000000800000000000000000
+       5263be92980bc943839a9024fb1140864999ff02fe7ddaaa35d3d89f9f345c13
+       9a9012f7b455a4b8c50d5917fb5969723b70ab3e0cf18cfd5a1b841aa6c0e1ff;
+  0000000000000000000000000100000000000000
+       451146802e160f788555b58164ff946820a782bce9ae691a2969fcb250b66773
+       1f85560430ebcb39c18ad9bb8dc49c0b1e1d730bf8cb43121a8c94a62daf56a4;
+  0000000000000000000000000200000000000000
+       83a737dc4f27d59528e688c55a52e4c44d518dbbccbf81bde212b87e9c63bd53
+       9fb8cee4a538fe0add8823986f50ee648c36504c1ef9054b748cc437ff31d25e;
+  0000000000000000000000000400000000000000
+       83154c350ea26c88f23c2585c4c1ce85f7febba6ccec68b960f2bd2ae6284c15
+       9243e796bbe38ca38d0d517116510236b81b5e84d662a059c9834cd57eb2408a;
+  0000000000000000000000000800000000000000
+       78f73dc4ddcd6357d1cb4fd1e61d2456cc37d84babbf5a6e70f9609ff9527602
+       e0f9f54c77861caefe4ba8ea6a870a5831cdb61ff0658ae74177562676c049b4;
+  0000000000000000000000001000000000000000
+       24203a6fcd8ea87e057f38fa775d88c1caaafcd57982d97ed5fa6b99a2814e10
+       7d327425d003904c745509c265bd70ace892a7ad23496f335386af2b3fd8a2c8;
+  0000000000000000000000002000000000000000
+       832c6e20ac336d8d215c1b618870c33857ff4e616df40dba963cc422f9cbd3b4
+       ad1f44b624941028a116896f053305978f382b85ae3b24330fbbb328fc835cd7;
+  0000000000000000000000004000000000000000
+       b68daadcf692eb67c1a69e854424f45a3cc07fb7c042563ce5db29811909fa5d
+       4e62699870105da1c27da11a482a5c79f174881179d3448d9518547b12341eb7;
+  0000000000000000000000008000000000000000
+       af03141ab732bbae48789b2efd96995ef50977d07a7d9ee741cdc1440904c599
+       8b295745e425a4b798d230f62adf6cf8ed49183098666157987fccddec8f0113;
+  0000000000000000000000000001000000000000
+       b69d0bbfed16b59a8772777e09c866fb51391d77552a32d8a971678776e97a08
+       1cb999bb1e7e9dd64a64302e09447755ee9c1744139de4cdbd61088bc17fc24c;
+  0000000000000000000000000002000000000000
+       5c982237e3d812369a5084f68792b88f33fdb8278bab9c069572c4d2d4e8b1fe
+       7a4c0dbbeaae1b31858f8a8e4628b56ef552d738301b4462ffd682af0d26e871;
+  0000000000000000000000000004000000000000
+       b502c31e76e20b5cced9f96fcf49e786b477dae329aa612edc58c8c4b310c881
+       3dc3b0f31b61c28bf208b35ad68715ae247a8bd3ece8c6d38f4d03281e0eaae2;
+  0000000000000000000000000008000000000000
+       1cf7cb0fe06fb987e82a7097abebff97b074e00d32ca59e259bb64baf610b932
+       a8f685fdb0fd2a5090ccc7d7635431954e6eb4b58ca2110fe691562800725f89;
+  0000000000000000000000000010000000000000
+       0fec5eeeffe04cab0fff3d6cae817db15a4151fe22a6e3ccccdb2e56b36c3ad9
+       7df075f7326a189ce1f5ed3b8428731f67d743e2bbb3037043aefc55a401b534;
+  0000000000000000000000000020000000000000
+       3ea8f911b282f21db8709031e607c193b4604a8b44ec36be34cf0eac039346ae
+       1ea420045663890821dd21eff43b2fbb86568519bdef2a13dc2d141c05e36830;
+  0000000000000000000000000040000000000000
+       8a84fd4bc516cb8fc163352c8fd600c8f1a07861f052964727d61a91d155e7a6
+       3b8683901243ba7aa8705259365f64ff8daa64604c34bedbf4d655c20ec28b99;
+  0000000000000000000000000080000000000000
+       de1e1860d637140cbc270026885c391982d0855c7177106b1a38103d3cb5d956
+       21c1f9266ef014b9bb8f9b9fbb884679d1e411f96e1173ece0609fa01cb0b16a;
+  0000000000000000000000000000010000000000
+       4e62340d4fe3b25f02522336c45b8f18b5944d41a72e0af43e2c1dbf4c32a504
+       185c48576c96afd58a5209a255a7324f850fc9a3be04080f9a744a5da8ab71c9;
+  0000000000000000000000000000020000000000
+       9c44e17c60b2e4a25454659dc72aa415c4701d1c31170d9d403a2f16adc6521a
+       092e70d956ecd2c938d1ab9b95588dcbb1fed47a6cbef019cb538c1bce1b20fb;
+  0000000000000000000000000000040000000000
+       c60d7ec161b0ae0e347bcba7755c40cdf150d67901070ac4698f1d7c593e6d33
+       1892f5f715f53024bf4b04aed4605e34539b21260ead7e00c4fede1b58f3f3f5;
+  0000000000000000000000000000080000000000
+       7b4709c2543c6c98e858392f44244e3a4606e5459910badafbca6422762af235
+       fa8b0b95b7d3897667c8798b5288bea05b8585264f1067592e70584d45e54468;
+  0000000000000000000000000000100000000000
+       f6a82f150ce106cd0b67c6251144cd0934623f64a7c0c02cf20f88c5b81b8f9f
+       d08611f1a55c0fa0022732787866879f6057bcb0d3bd8be4950de988f2703b5b;
+  0000000000000000000000000000200000000000
+       036d8796288546f6c8faa0137f542b79232b1f710f00d993bdd209d608b2a983
+       0e4ee8dbde805bd218495fb6e0c012da36af3118fe3abcead1cb9b1d0d9ad7e8;
+  0000000000000000000000000000400000000000
+       93bf0d046d56227e10a60b6724d8195732ac7497dafbc5f0415aec8f721feab3
+       508975892533164bd482c18d17b1190de8ac5c603e22dc78dc033dd56d70e498;
+  0000000000000000000000000000800000000000
+       92242df9e82635f00fd079b03fb3e4ed2e479076a756daf823ef97e067bc0a9d
+       e52168fc1c39bcdaecc13f07ad602234f0d6fec3ab60edcc2703b2ebd9a428a8;
+  0000000000000000000000000000000100000000
+       f20f59b1d2d69ab79957d62fa9a683180b95d772f33205637f3bd211a570c182
+       ba077c245b7cb7030d882130b15298bcbf15f4dcdf2df67865687956f2d68f8f;
+  0000000000000000000000000000000200000000
+       0c5eb80aa685a53d856cadb59327c84b33379abcc06329cc10af1096ab8e9454
+       8d8ef3a1486b1ba3e3423ee8e188036bd06a73abc506cfdde791de57f35818e0;
+  0000000000000000000000000000000400000000
+       c1b93bce555e86197fbe389b926c37d918d88bbf3d704496986c0cf3bd959840
+       3a7a664d89b1acdb853c6bba7c7de3322545bf58971c93f2b8c9085d3734e31a;
+  0000000000000000000000000000000800000000
+       b9ad33f00c7029630ff7db4528327cdccc612b607e63faf35978fd27810f345b
+       291fda0e13c6a6aa8354acd6be229759e97a52cfffb3956dc6a1dae438e26565;
+  0000000000000000000000000000001000000000
+       3f7e83921a8fda45c6681ceea340a1bed22ef6ed784fa8ec0301cff998bef05a
+       bba9ed3d86edc3e850c58372960a340aa75046aeb845b53ac521b8b05800ae48;
+  0000000000000000000000000000002000000000
+       d504cbfa2d69cbf0108df37bd476fc93db12df17eac4a10f52c5d9e8560b7a93
+       81b71096f284866b1423cd41da22f003afacab0911f08c98a23bc508866a2d82;
+  0000000000000000000000000000004000000000
+       ca5c7b0f2e05939fb7b30358930f2db8461c4a8735971b7d0ecb429ad519e9ab
+       a7b781dd1aaa84c9ea0fc8977f9ebab91af4910197205e5fdf90568e51106c2c;
+  0000000000000000000000000000008000000000
+       96e9e78698c3eb928ac8bf2a6572d1c153f6311d3d250115e502ded03dfc2e74
+       e20aabbb2137804b4493fe7b17e3b9331592f8f44ed1903d1d1209b26fbe9a5d;
+  0000000000000000000000000000000001000000
+       07334423e99b879202679cc4e3f674a82a731d02ceb5e74cab08c90b6228f0ae
+       74458c222e857b9033a9f0453f366f4ad8b4cdae922b8a80e46aacbdd6f647bb;
+  0000000000000000000000000000000002000000
+       68c3f9679c7a21ca77da909fe45578928bea63c882d577d08049a05103efcd56
+       3d0ef4fd9b8359f4aeb1031c31508876e8f0ef38f8613bf027823e9aeb005445;
+  0000000000000000000000000000000004000000
+       be2bf2722cd6eab12cf20d28cbed792662bc26f0b92295e53411267d4c72cebf
+       2187e559b2130dae8142fb0757341c0a1e6df31508e6a19aba5ab2cbb0a9c872;
+  0000000000000000000000000000000008000000
+       cc30e166ad1cf014644af5c3b6c65b45fa594e5e371e404388e8c051e7dfa4a2
+       fbd37c904a34800318acec016ed34c12de8d8d1241256d4a96a1ef02d707d53a;
+  0000000000000000000000000000000010000000
+       c3b8c49a86a432001397415ccc1eea4d77c5e7b1e6b8dc208d69f2865a6b8678
+       de5469250f0cc42d2e202f29af0e13b31ae5acc68fd5107819880d3db6e0b8ce;
+  0000000000000000000000000000000020000000
+       c169eabc1437d7301865ffe544bffe0767cc733500d6a67cef204f6078d58328
+       4c09cd0d212dd836a6e4af52c5fb1ee851f5cb07465e5f592fb8024d1b0c1dc6;
+  0000000000000000000000000000000040000000
+       758c11f8fe1f10f109d8df4790de952c900afc7a985c6844195a86c66bb0780c
+       6985483375dab29f2c9ddf2e4acfaf9ec9ec0b90d0ff59a51f76901449125973;
+  0000000000000000000000000000000080000000
+       c818f59d0447e726d2839c82a4c12360f7ff8012d84bbc1a367cdb2299457199
+       d1e7b740f3c2549929ba0d3210f259df6ef2322e9ee4d6f317ea4fc8ec4d2998;
+  0000000000000000000000000000000000010000
+       3aec597f7d31483f810f14fcddf9be067f56080a048a9e3b4098e6e28918a800
+       7e85288628803f83717499b69f17adcd5a66ad8dac68d0851db8eafcdab3cb08;
+  0000000000000000000000000000000000020000
+       0b6e2edb89d22c535a5a68e75ebcb0087ef1f236d2a2266a9d543d6adf24f479
+       ac7fee6480f401eb8902005f7b8d512094017f3caacb8249082606c36d98d51e;
+  0000000000000000000000000000000000040000
+       da610e5a8a7a85ea2b84bbcf3b40098290a15d4ab3bdf91d7e21fa524937c783
+       477e7784dedbaab64f19ea69b8761c66d5da3c5cb51551dff47e3fa0c68fefdb;
+  0000000000000000000000000000000000080000
+       0e8f5819b7a66f25281862c132d5f339cfd0fd4ac4f91c14f226ac0033dd1117
+       42352ac10368ccd3b833fec7b048741501711ab1036dc7d159e150055a11586b;
+  0000000000000000000000000000000000100000
+       f546da839861af04600c9417e0fe884b8c1b6f4a9a9d36c4da7b6ee24ff3c4f3
+       c543450e77a3e87a7be1d6233b79b3e42597228f0e08c4f833622194f64afa71;
+  0000000000000000000000000000000000200000
+       f4dd95284ab89c6c53d7ae177d25aa3739dc721ac0870c2793f3723b6e093363
+       48118b3d2203906c7b319273f372bddae10266d0d8065e636cf0bfd747c7c984;
+  0000000000000000000000000000000000400000
+       14094297b5bed9c5d7651a2787c232c9c9089f542b76f39b264c1b591c4f2e18
+       09a61a1aef6ad53d3e2b6e93389a279752f78c62bcf530b7cf0c1f3bd3e3b529;
+  0000000000000000000000000000000000800000
+       212101a1952ec6158effde6a7d48a4929304fdeab258257266530262a8ad48f3
+       f991e1ad77a2e13b92906767da523e4d057eeaa263794a087a02bb0339972b9a;
+  0000000000000000000000000000000000000100
+       ec652827a0f5cbec1068ec4193a152e4a80d797867646412d18367645db6df2d
+       033741b62e08f79b8d6192c93775508f23100fc3a4f35c3073cb7130a5211abe;
+  0000000000000000000000000000000000000200
+       646046dc56a8b7a4186e481ebf943949eccbe7147e0220de8dd05fa656e92dbc
+       cb5e4fef77193f8256bfc49a91e001a036582e2e3eff8173b27af708b7e8480d;
+  0000000000000000000000000000000000000400
+       bae05fa0ca832ff9875fb1c886d8ec8eac6b730bd2427b9cfa8696d3ab3cf5b2
+       aa4ea07107c3b1cc519fbecddf7c966aab50188cdd0d46bc866b19e882deab36;
+  0000000000000000000000000000000000000800
+       1f8b6b9b95efdc182d35f1ec5104489893c70bf1fe7ccaa67ae55ceca5152981
+       100e51e4e6d5a44653b9c51ba6c9f070bea9d470bf1ee0faeee1d05122cdde50;
+  0000000000000000000000000000000000001000
+       c1703da3b5c222872d09d493d03d07e36e6d04e8901a248ce5fc620c5dafc381
+       f282d2b589be28bf64c3f8a454be2101322666b3c7b71369496d630cb5c5fdb3;
+  0000000000000000000000000000000000002000
+       e76669b223af08035c5deb05e10666ad09a99af191a3ff30bbb7202b65a25033
+       15240875b0e1b9427a28e2123f85f74a1b5924e3600453ee45556bb328e8e941;
+  0000000000000000000000000000000000004000
+       511c0362a229d88ba90a523f862d35c0305b08dcf4b9e37bbe2efcb0dea8e6fb
+       e8eb57458b73a15d4eea4dbfc95dfe99ea52b7f07cb3964d1c0caa83de2fefde;
+  0000000000000000000000000000000000008000
+       45d00f70b107ec873736a23b9ec02b78e68c6ffbbda1778e4a96d01d42b20eae
+       f5d0539741362a0c93861d3c167aebc148a5b34fb3299e600abce538bef5fc5e;
+  0000000000000000000000000000000000000001
+       41ef971618e7923106427505bc765943909724f81c8bc9b0de756867d40b444b
+       8bb9e4dcab530ed4e491e020b59ceaefdac18d23ed01acde992f20f44dc74004;
+  0000000000000000000000000000000000000002
+       2536ff6dd06c356f864fd003738e87a81c5bfb44bb7714838c5d068300abea93
+       291f63a30d86a1aa7347a9483d8cba05eb27375c43adc7fddb0ea9bc50e5a794;
+  0000000000000000000000000000000000000004
+       55dbca7e091006fe395367c4250fec2d1b994aacdf8026072d1f3d92fc7475f6
+       da7cf09785d9b6792e20dea6dce0fd4e65bf87cf47ac674a83588f3642d6d50a;
+  0000000000000000000000000000000000000008
+       f662573e1d83a2b58697b4f1923396b7d89c56fbcb21a5a3834232c8c0451f57
+       b6f749429a2d9ba1b479cfc96886c679c7431b93a95b87f9187680c1a7b7c792;
+  0000000000000000000000000000000000000010
+       a398f5779517a7db0f56007407f9cff857fd68803441d31bb6a4752a77dd3495
+       89ccf7cfec665a5dccbdef72ebb60388a3e2a892d6030574bfa92f4e61efe6ba;
+  0000000000000000000000000000000000000020
+       58a9c4323b56584a8d5378d2004c1d6f491752ab9f1b750b9745f6b5f4c21cca
+       acd8d6b0c04002442e0c3c983fe656d5cc54c2782c60d867cf7445cb57feef1d;
+  0000000000000000000000000000000000000040
+       98303a1f445013eb3be40cff0d6f4395501b83b825d4897520aacd6a36703962
+       1d92ad624dd448b62117c533e70c0d13ea5b3a66310a979edff479a50b99ea17;
+  0000000000000000000000000000000000000080
+       11c40125db6ef51d57e603b8beec27babde3fe9ab63fc52a0cf7f76854c936b3
+       b9dc8672196f58cbcc5708f68f510d6f908b8a7cc0df0ff83d3a7c8303e78777;
+  010000000000000000000000000000000000000000000000
+       f9e96db294715055a91833db0fb33e9c91b54bede26f9a06abdab80a60311e1a
+       90b679951b11be0bea2a87a3eb8c22f42bfd07e51f33362a1ac0d7bd959b5191;
+  020000000000000000000000000000000000000000000000
+       0c38a41f055332c76457a13f95ba264155c979c9124b5dde77318c49d1f4c01b
+       405919405dc48814b279e93f34899237ad9ff2f2aaab9a4d7b04d5572a34c541;
+  040000000000000000000000000000000000000000000000
+       1dae71958a2d1f4c332bd9f343abb658590e874b4bb4ab807773e95bb42cf82b
+       a87bef2e0ce41b11221e01b86192f0eca8c89fe36b119933e832d9b317abe3e4;
+  080000000000000000000000000000000000000000000000
+       a77d1b5d96eef9626430b7e785c2be959a590145b9a61bcb9fb5044f3b923908
+       c9cb7b952ad619267f7a7ba9420f6e3933d66c3a3bd4c4ae3229bc2b462db40a;
+  100000000000000000000000000000000000000000000000
+       c1eada4d6ace84fc75d62263d98c696e2df8207bd62981d48abd2523dde36862
+       db58cc33ea77f996d3d7688c7b6072a5e7d17ab605ecc15437b5bbd4dcdc5b99;
+  200000000000000000000000000000000000000000000000
+       8b76cf095a4d226114ce825b21d0548fe181ac262ce014fea4d3a4245abeacb4
+       17584d0428af390a9d0f8c51a493870f7feafea51c183ffd9594fc1e7f41d8a0;
+  400000000000000000000000000000000000000000000000
+       386b7fb85d0c186aed83e7c88ace5d6246ec46fcc3ba61b5e92da090a0754071
+       17d13a676e2a474b6ebfb05c4011cdbaeab55275c5f702b2c40c772a76b08339;
+  800000000000000000000000000000000000000000000000
+       874247921bb170b486c9e211aaf4f27133550367d8d759894b9e429ebe34908e
+       ff52d5217ebff26f8f5be14884fc05a9771997a062892f75700ec9d0f4d1173f;
+  000100000000000000000000000000000000000000000000
+       399895248799ad09b0e0a870717c7093e959e07b7ebe416cabdcfb57286a4f34
+       e3702614230bc36ef9b87cb99d79aa4cdd9e9d18d18ba4ca94f250ebdf04d890;
+  000200000000000000000000000000000000000000000000
+       392524e09fc57d2bfa227523fef0bad4155ea55f8a848464b7b7c005f6130579
+       9d595d7b010214a82e295f3440a682601764080288a2bef2fc208f9ed728110d;
+  000400000000000000000000000000000000000000000000
+       f49c44ceca01eb2d6ca71ae5b9363445261b39be75c75f0c054c1de37d95ed5a
+       b1de2734994d1d0d8b0ec0057ba4fbfcc1fb6ac30620c327c9161c18ea91e942;
+  000800000000000000000000000000000000000000000000
+       ff5b158392cdff642112789624b80d177aff782cc1a0ded6ef5a6da5230abbf2
+       a844ebaf2b4f0c005d5e0345f7b3268a401181cfca767970bbec2c65e739ee1d;
+  001000000000000000000000000000000000000000000000
+       eee541e6da8eb4d6ea2d0bfe3eaf5c29df99da4b258190ba5da5da8e8ca97819
+       04e41aaeaa28c8e1c7e113e3cc1734121fc73804d9aa9ca4ffe8ddc896eb723f;
+  002000000000000000000000000000000000000000000000
+       89f6a98d1287e78538d98345aeef5ea194a30bdd61d708010f3a3e8abe347774
+       1ccae829fff9e409ddac526fa4b4393fb9b91783d8ec6ff842321b830979e4ef;
+  004000000000000000000000000000000000000000000000
+       ceeebaa4ef1833984f356d6cbac91c98b032f8179a2f0ebb078b45d361059b6d
+       57c5a1d7c45a9cb0cb1ca9832f23d598cb253512372406d791539b5ba788936f;
+  008000000000000000000000000000000000000000000000
+       12455456daf8787770ef743ccda298d054122db7520cd1bcfb87d81da2b94aad
+       4a849587efe4291325f12ab50cefdf56cfea5e2137851021cabcd8e93230b3c1;
+  000001000000000000000000000000000000000000000000
+       07ebcbd8034e24f2af24d3722dc24e897756aafe2f6c7b22174b319dda5753a4
+       85d342b06d631f4975fc5ce6b7c6839cfe3a5d3837a132aa977a631719233573;
+  000002000000000000000000000000000000000000000000
+       e5c7b3af8f548c6684e5026f317cb0e3a27fe8c0550a5527cc9dac57ce767143
+       f215844a8622bac9330dcaa70e0fd34bf732a9556a6f653d798b48f23659a643;
+  000004000000000000000000000000000000000000000000
+       348bdff0e8f4b4490b2ae937b1ea6ae55a05301efd0342787184e8b8fe98f561
+       1f71659657bc15ce1c9e3d2a6e7a78fc0c8d337899b9268eb3bfe0b6326c2bc7;
+  000008000000000000000000000000000000000000000000
+       f72265f6266e5e3d810f5a65540206134d7e6f0b61335b646a5cea952986e5f0
+       1afa3d7fd71b74805878066b66cdbbe1151d64324ab82ffa6541a5e43622bb2b;
+  000010000000000000000000000000000000000000000000
+       71fb92a42e7522fc907b549b8e21be2f5e20f926eb1db7e551196c4c6f9fd49a
+       ed2e6b920912cb498db549b149bd50d7dee9c2065643968fdcf6144e79e60ca5;
+  000020000000000000000000000000000000000000000000
+       31d89b14ae2f205e80b1ea8bb265781350078058040cfd6cfa007e590a0d2975
+       8b57df307a928b8f04640d5602a31077f62538d711dedb4b0684a1f20d65ac57;
+  000040000000000000000000000000000000000000000000
+       ac0fc0e2bfff393b95228ec598d065969643d940bce158b882c4214dea7afece
+       34eecde2a39bb9c4714f1f071f152c0058d1eecd56cdbdda05e747b0bc6b807f;
+  000080000000000000000000000000000000000000000000
+       b8379d824ecdc66d335d64670d4fd20d3d1a2f632c845d9630688ddd5c64a661
+       9332b14faf54b15574702406ec02a7500defaa0de2a53ec1ad906ad8e6158e63;
+  000000010000000000000000000000000000000000000000
+       55adce8670eb35789c2b4f3c3f2a3c461b1a88131cb4bde0a54d3f4c886216fe
+       de33b8f153920f6f4a3fcea1b31618990d933db5a20828b143e5349e85384f0f;
+  000000020000000000000000000000000000000000000000
+       0e72d86ce21c254b393a2078c148cc6158d33ebc471e74ea9e7edf7bf936218c
+       7d19909092cff079bfa3854e6753967012a66277cb65771cec208e379c671f9c;
+  000000040000000000000000000000000000000000000000
+       6c5d6c93ef13bde1eb5f205ab7379e9764aa5cb4bce63fd68bddebf71ac6d750
+       64bc9c9bb728abb28fd2da7f958c16d120269d103e406aa17107a4d7f8d1b4ba;
+  000000080000000000000000000000000000000000000000
+       290a101970cb6dacbd175f3ca67860e10cc5ffa6e7829a40df0cc04345744de7
+       f0d4fb87d679b178dd0fb39d754e35638266ddd66f61d616419c867c52398c38;
+  000000100000000000000000000000000000000000000000
+       2c9c6a93c3c41f66cae82a912625b939203193e4cd0bc67dcc1ab882af0fb2a8
+       00307a8c0c9904b84973bd324a8397c4aa159176f0ba3cf4771f40a652151342;
+  000000200000000000000000000000000000000000000000
+       061dd076bec69c3870f387a1d74a5a506e0ae64912b850829113b9db9988e869
+       029977f0d27d81a985781061a05477fb032c7a5b6bea7365510be2ce8e3611fc;
+  000000400000000000000000000000000000000000000000
+       99e9d96e330e25d7d4d74a82232a6012c7b0332ac209985fa99a3eb4cdae4285
+       045480ead04b22fd287620db1e4b333d7d191fddca5539cd9ddb1b5ac51ba37d;
+  000000800000000000000000000000000000000000000000
+       1b3b4e1eb2ceaded0eb41e2d4ae3169df36d87db3fc7c6c5df7e06c27e68c60a
+       4b7087216d8396b8274fddc2fa2c300eac624313e62eb924e09eb6f608895aa4;
+  000000000100000000000000000000000000000000000000
+       ddbc04456d25f8af3cbd2fdf819256750c07fede724710b370b767ab6f3e777b
+       80e07a753961ac4a46dbc1f3c2ac510ee59a4e6c06672e67acdb2f9d393947ea;
+  000000000200000000000000000000000000000000000000
+       355e89d48b6ad74e2c253432722b3896ae7296c9e83e76f14e78b0f7e5fc8580
+       5d0307032aa30386ebf5f07b4a05175b4d3f460c95599b9de4a5098d645754bf;
+  000000000400000000000000000000000000000000000000
+       a692bb60016d3849f8e31b5c1956f809264aa39ee0096120e3c04466b4b72e0c
+       0183ff6d49c4bf650117e1ed085ab2b3d2d4614209db86689c98d9b859b3a5a6;
+  000000000800000000000000000000000000000000000000
+       a1f561c977e24c5da0b75ea3706804b868223245259dcb6350eef44ceda2c248
+       2a4d332bd753a98daa3e3d4cc3fce08319b0aee1b6a710af18f6604e6cacce51;
+  000000001000000000000000000000000000000000000000
+       d60a120d9cd41286c8a39d0a177c75304383017cf1fcc07cdaaf8a69290e7ea1
+       b1c53a187c59bb9490c50a8f10cc3ca1c6a5a3970a059d461318ba7a32b1e8da;
+  000000002000000000000000000000000000000000000000
+       57bf964c24d87f4e1bc0c301d912b61ce9244022f0b566ffb0c0f2e6acde4ffa
+       bfc70c61151cf16bfc039483b8a00f3906a2d151c44b9e684d0195e0794c2862;
+  000000004000000000000000000000000000000000000000
+       08af63069dc10fbf50e649321cd8b1ee039b7691fd6399d81e3565edf94b8193
+       54de4c85b5666702354f8ec087cbc0640faaf8e8d6c304ffbc21aa439943cd18;
+  000000008000000000000000000000000000000000000000
+       a77e3c5155aae9fe9baa0fb81cf9b2b60a70d9adf420844e9f8b01883706550a
+       403b00473e00a57ef3822d0bb6d75a99963974ffddacb9d4e5baa9ba47deaf2f;
+  000000000001000000000000000000000000000000000000
+       a667891d3c97262683fa83a7b781d6f6b987888dcfe9f6b58b4ea8bbfc22eb26
+       fca3b57ec70df2d5093ca93b2235be57883e1dc46f11a9eae73e047f1d2c5cfc;
+  000000000002000000000000000000000000000000000000
+       1af42c0f7468eb361d4f56f3e5f45f5daeb1c2a25666804d685f1584d5ba30e9
+       decc0c6bf3e04078c839acd2a62a4184aa1a1097a630a4e40012e9beaaf26a0d;
+  000000000004000000000000000000000000000000000000
+       c15c4ae428c067595c5fbcc12bae69ad529b7b114d30274a70a0a51e4f87a7aa
+       f02e1d8e8fe536918a9e62bf48195e8e45f8daad77718d78f223acbb8b8390d6;
+  000000000008000000000000000000000000000000000000
+       fe4a31645836d26c668ae9348047765294d707d38587c30e31493e3b9efbd239
+       021cfc4d6d24bff9ed344a57a62b9e9adc0fe0fb8b0d2a4723ef756126fe28c7;
+  000000000010000000000000000000000000000000000000
+       2bb1292e04c105a871dcf6a366745441995c46e94ade34d4f7ef353e3732fb12
+       8edc70cc753d1a7499063ca76a49c49ecac4797045b9acef9bf93b363e1baef4;
+  000000000020000000000000000000000000000000000000
+       af7539c5952da58d8074de796697cbde1a991e0216edaf51ea363734035fc41a
+       f39beaecd22482bd6e1851c739a1a8de9d11c3d9c11a4cdb45f3bc0010cbe5b3;
+  000000000040000000000000000000000000000000000000
+       bfaa17172e854602a411f39bfe808176a30726ab4139799c2ae294bfac9066df
+       edaaf454146e8d399df89babdb13498cf57ec6419d6faa51a8493fe3f55e968a;
+  000000000080000000000000000000000000000000000000
+       52280d21e201c397e77d527e62c85c23cc479fc81dfa10e19fb9d1ae84fe582a
+       c906c9878e2e36ed742c8ad5e39357e0188c0e5a59fa9d6c0cdc5831457deca9;
+  000000000000010000000000000000000000000000000000
+       ea223c68adf66b076da0eec9f38467139bfc51a4056650c25b1604fc7009b983
+       7ea0c34ab6f734dd80f82709f23a7ea3b3a426b2d2561d839eea4b33114d8e11;
+  000000000000020000000000000000000000000000000000
+       9fa09dba1210f7cff3b54575cff0e91706f96ddee75d625dd98b55058c04641b
+       707785567fd0c4d6982267bbedee319bb65be7e40cebef299b051edc5ee19674;
+  000000000000040000000000000000000000000000000000
+       0462dc1e6dbac8d94b9b3f6f36909ee367cd21fe348a37f8eb149ecf77459c15
+       6f7287e3838fd23a5de96afa60eeb3e3eac80346645cb729849cf06e4574f93f;
+  000000000000080000000000000000000000000000000000
+       5bb868af6de2f9814b2d53de8c4eb53597ef6bd7ad1a130b0f006b1e71b6f344
+       3e882386e07775def74428bfbeb380ddde3526cffa40ed4fcc0e98642dc9d29f;
+  000000000000100000000000000000000000000000000000
+       2e5ad6aa5701ad5cfb42c92f6e1142cc2e0dd24d57a28430d3c4aba7818a11a0
+       bf294d4623f8e6c683b29cbf1ebcf82338210199efdce2485f0c096b40bd3535;
+  000000000000200000000000000000000000000000000000
+       6ddac861bd903abb303e8d7faa58939f6949bbcaa60341c2b9e2f32254154e61
+       ce0f3955956a0e9b92d0611bb7d400bc782a61d688790a7293821accd4dd3ab8;
+  000000000000400000000000000000000000000000000000
+       6c34fb5023d0cbed7e5fe09bca96c261a22706ad118e4f8e813fdf578f6a9222
+       4d53255e814b9e35f5fada8f444266a11450e21fc8cdc11841071cbaa7392b17;
+  000000000000800000000000000000000000000000000000
+       1d9e348d053585d72af0d606e2a9792646fb591ec72c39e73895100c538e929f
+       6cbdde875e20309dcd32d18fe4c31c98274f10cc88811a14db03b002d1651bad;
+  000000000000000100000000000000000000000000000000
+       624c21fc425a9fa178eb5d8346050301d655bdf9e948fa79dd2b659122ae5864
+       fd411dad007bc21eb90442ffa404e205a4c6037dfec390ca055c2d1ba0d835fa;
+  000000000000000200000000000000000000000000000000
+       05a695c429b54c6ac459fec77cdf33a0e44d5d1f4dc6679fb4d1f3d07b35c984
+       ec983376a5c111ea502fb4accc49d7d465f1645b747192969ffdb7ddda5769fe;
+  000000000000000400000000000000000000000000000000
+       eb0221e48c3562cacc4c31e2dd24cfc04aff04addc4751d747033be31d7ff0b9
+       6d7d733c19b709ff780ea3d71e47faa447fae866c5bf76089abf4c09bf6e7f15;
+  000000000000000800000000000000000000000000000000
+       852be3267c18c0a005af19266019311e17ae0a266688398def4fe1a6d0f5ff8e
+       6ad20d62c5ca5be801698d6f43654c4e8b895a5bdd7bc1d7d9ea04d876f8bf54;
+  000000000000001000000000000000000000000000000000
+       2ad2d89c102216f17a52aee77b8e812d1d0102ab13c65fba559cab28682300fa
+       9b95e0998f7112dab5de7f64457634205d654ea4ec4a32076ba30cafb218f801;
+  000000000000002000000000000000000000000000000000
+       f61d03a67d0209e4986cd503c3a0d6d5314563e11a473d7fbd5fe4d913eccd05
+       a3c39a8321366853d78f1ffef9e2df9b09abe5a0d67fa0b0c0b02a653c23a8e1;
+  000000000000004000000000000000000000000000000000
+       8053b9bb606dd5f3e6fb5ba949485fb0be1bf2f3be881ef57d8ff653a7a2ad97
+       29c8a343460b0eded72a0f80b0b266899424195a8b3f5662abae0d58286c2517;
+  000000000000008000000000000000000000000000000000
+       a52ab95b69c30484126546b9151f9fea89b6d479391b097c9f636abe89b123b8
+       1f76b1e1d8e7eb427115a8e7fb239e461f67bacece83e576979623f86badd31f;
+  000000000000000001000000000000000000000000000000
+       a7ce6c6eac537320138e72f4ed71b57497132c19f58a3a0e864ccfee8f13e243
+       f31e719aa7b0aed4e324c1406fb38c7b574706555561fb57ed4fd59565b285a5;
+  000000000000000002000000000000000000000000000000
+       db419afa205c8ec1b824f9ab843f1bc377062337149291e559600148604b93cf
+       b54b0859085a9a0581286feaa0d2375f0e73ee1d306803f405021050406f6760;
+  000000000000000004000000000000000000000000000000
+       c97eb377cd16f86cd7efde7438d678933d5a76cb0cbf4938b00756b42d3986fa
+       5535c0c0f43ef9b8b78b532ba60fcdc5dec4428ad62fd36af221378e13b59cd2;
+  000000000000000008000000000000000000000000000000
+       9c379451bacebe09fe466301cbd2f15be7637a6d992b7e67ad25efa503e19da2
+       e8ed8e2367fda7b029bdcc7fea10bfff2fb9ee44017f63794fa45464e60e906d;
+  000000000000000010000000000000000000000000000000
+       d806c06a1f28c1a7a03d11529e298069f38713d0113255cd7260fe11dccd2459
+       0a6d37fc381c2cfdea6d2dcd4ee9873da18c46d028fead0861e3c0ed6d4afae4;
+  000000000000000020000000000000000000000000000000
+       3e26ea35664eb065ea94e6c8536af313c938b01a4ddb2145c907321084d1effd
+       3d7efc858d2c97fc00f2f0edf39d38e5ec673c99de7238f704b809140e3698a9;
+  000000000000000040000000000000000000000000000000
+       c21ed702582aa1d8259b2c892c6b4a0c55aee1382fb64d4c9ef218a8bd8fc0f2
+       b71a4d0e405d55d5001e92bc2cbdb822b65cf12501b8186943fd471568d82b42;
+  000000000000000080000000000000000000000000000000
+       0595bf54addfb813ce8cf9a40a072e1eac4022f848bf4a9955617e1fa4a64f0d
+       a888376775afac427e11eaf788eee2854e2c3dbb03a2116e3f082a24459e79e3;
+  000000000000000000010000000000000000000000000000
+       f7c300b01efb460b636c7af17379662cd501c7e6a0c7b86315127ba7a20f238d
+       ad9876d442b0e84db1eb82d3c3f98f768cb4243107d05ce90952f4afb89e3206;
+  000000000000000000020000000000000000000000000000
+       7922dbdb167fb4c155e062c0d5aa8b2868b893ca2cae86df02c776871b48a8ac
+       ae3720bf2f5b7a2fc753e87251e810e3c5d3e0960a4cf6c1985a2a0e7838ce03;
+  000000000000000000040000000000000000000000000000
+       8c8a5188f9ea500e7ba44d0c5c5296292b602bea998940826972ac75a55d19fd
+       75bacb58ec93ed5ce9c57a4830e0385998c3c92b6284601461e7ccfa234673b5;
+  000000000000000000080000000000000000000000000000
+       855b265da2e77cec64a7c96360221ad7c08bc343ffc173ace59cf2c1f94d7248
+       6967ef1cfebbc0ad1f54833c93232d5623abe3f2a34e0a24b9688783c3a9e5a1;
+  000000000000000000100000000000000000000000000000
+       81db501d3f871e765776d8d7750860c36ca39a73baea80df76168436e1dc282c
+       b12600493e0d643ad4c5bce38f4ff6170d582228eb9f4fab66eef8b1e6e60399;
+  000000000000000000200000000000000000000000000000
+       69fa38fc792f646a679f2c69f886f1e46d0d98ae7648b7ad51bd3d92ef09e2ab
+       2ca758e5230bb97262bf6ca5c4ddd5d3fc8f566561b297bc139cea05cecd517c;
+  000000000000000000400000000000000000000000000000
+       07fa8e571b3b715b7adb4a0c1a42a0f5617db1ab04a3ad9d6e3f99dc392643ed
+       fadeeb6d2032e571c2461e588e7efea5e38b2214ec23fe7b4a7b60c512e8a66a;
+  000000000000000000800000000000000000000000000000
+       d86ba78cf143fc53aa651f018248c67331e69be66a33b44b3dac4f3f86b293bd
+       e91b1044bd8bed5ae2cfb269d6fdbd229cc6c5a0cc560acddaff1fcc7dcc939b;
+  000000000000000000000100000000000000000000000000
+       4474e5926f15e979554b25ee62ca5895d69ba5f7b7264d52e936a5d7e218b7d1
+       da76d56dd52888a891d31d09a2698d6605e279d90ae2f55bdc01775dd816e433;
+  000000000000000000000200000000000000000000000000
+       5cf87fb984e1765a31e392dad79752549f6f9537aa800671cdbb0d89cb9ee6f7
+       309de2c3260c2a08340ce164b7cd17ff93d1939f3949fd5dbf46f75c5f13861e;
+  000000000000000000000400000000000000000000000000
+       fdef588c63309dab2aa804e9d897034fc81b6f1d168cb3f9976eb5a6dfdc52b8
+       83564b42d78039e88afc04e3f34b8863e7f94b4dfcc8c8c22e22f7dd17a9650b;
+  000000000000000000000800000000000000000000000000
+       dc29b2dc786b940f80371a1b1994e59cc5ea72348f1415dc9b9cb13af8acc81b
+       0656387e108812013b668a343044ed99e7239bc1c4e8e2698e8cb7998993b1da;
+  000000000000000000001000000000000000000000000000
+       309bd7d5cc9be260f1b43a255989368fa3a0fe7451c982fc7393b6bc6c784f60
+       b1327d75358cefb96216f21b4432b1b603ef504186470991c12e21f4d42c609a;
+  000000000000000000002000000000000000000000000000
+       2a4899c9dc7dfdccc936fb1308b9b43c8df1eb6537fdd1b5084b44c71905d71a
+       50b7d28d9599ec0558f1cdb5bd28b223585b7d7f4e3a11c2f63941d99baf82a9;
+  000000000000000000004000000000000000000000000000
+       8413c2819f780bb3a7d51aa0144d74dcc8f66f2db12a5e2dd739df4002355aff
+       8a15145629c86c5c699ce2a012ee46dff8d81d86f08c5d9b7580d30558adb269;
+  000000000000000000008000000000000000000000000000
+       ab65bb89011ff73cd9aab4fc39f31853f3214768a6a0fec7454551dfc1c67648
+       c92067f0ed0db296e72556344a39ee1e85f3690e568a47ec635b6a38935699f2;
+  000000000000000000000001000000000000000000000000
+       6ef6fcb11ce017ae7067d34547b1e996d045b193281ea44245a348708d896bd7
+       5d85c3700c5cc45a069469a7039f84334f7f068de6b5bb9c76c2af5345eba955;
+  000000000000000000000002000000000000000000000000
+       a748292aa251b84a1a518074dc24d42c9a491752d2c2c12511b2e6bab39c7157
+       03bf62836deb2ebffe32fcafe5db76b8a6e1ce3f411dcaa429fd14d0c86df3a1;
+  000000000000000000000004000000000000000000000000
+       44a8fdd43b3829bfa1290f00d3f796d1a4340d81221c0b1e0428bdc16960558a
+       96f6822810f9d3851b97c08616ff80f5f6810486347890cc682d551e34cc6655;
+  000000000000000000000008000000000000000000000000
+       44fd0991d1c3e30e50af350e41c0676b016478fd9ec4c9c66b5fbb6fd0c9eab7
+       921055ef1b383f9de45cda31c5ca372ba5ac67918305cc1817dadf8346380644;
+  000000000000000000000010000000000000000000000000
+       6535a47b9ff05940f35e68f6830b1edd6c1a3cca3c69008d77cfbc90813f2c70
+       7b3b359c5ea3575d730a4d6c206ae731f59cc538d7e7ea7065c16adad980eae1;
+  000000000000000000000020000000000000000000000000
+       9bf44b4910301b9f2e6ef3841a6bee5733b34459acff031c39b9ebca609a9ab7
+       dc57249ff0a59f590d2d1ab020e3beba7e95598c75bd0567055285e44de4fc5c;
+  000000000000000000000040000000000000000000000000
+       dae9a5b164e39be36b1acbbb357d414486098d20de2634d16cb9d04d0b5c5b9e
+       0a0877b39f37f8a142fda7618e6c4a06fe02921461264fb7f0a68de184d2af64;
+  000000000000000000000080000000000000000000000000
+       5e90bed387aab9681116b7f1e2fdbb47fffffcd40c35856c25ea58b452339129
+       318899c5f84a5ea7de2b391b4cd069ac2f341a820a3ab3241058d21018d5de59;
+  000000000000000000000000010000000000000000000000
+       e89f195b0e9bb3d7487aa791f436e5757e22ad78a5c525c367476383b88923b7
+       751b55b6122f2ca9459abeb94d4a65188ecb7a02ff43cfe10ad4adf68a9ddac1;
+  000000000000000000000000020000000000000000000000
+       0906b6674e6538ea82a33a89a47ffce4fbb489e6c2efdb5d1b99031fd4c5f99a
+       a75f0ccb1495e7cf617a8aa9ea4ede5a2665ffbda0c4e7328a86395485f0d852;
+  000000000000000000000000040000000000000000000000
+       9f58ae0629353e100d7e769c61b53516bb2a0c6b843c3d54dcb8049cc98d1446
+       0298031326cbecc865a64b254af3c187f97c7fc1370c48a67fe137985eba00ad;
+  000000000000000000000000080000000000000000000000
+       6e65f3a436d028afa3cf36e14fbb09484c6d60c656d405530da442fc3a95827e
+       4d44aa7d331fddc2b173191d70836ac2062093823e88f42418b1b2b624be7d2f;
+  000000000000000000000000100000000000000000000000
+       0d84cffdcf30d929475439e5ac19e65414b1a987c17d39ac5fdcd1f88fdbea61
+       bb2c7066132af737383955b50aafc2629f62ae9a0906cf063af6950c7d93edb8;
+  000000000000000000000000200000000000000000000000
+       aa89078f9b49ba132929b8cdc17f0c72f03485a3f30145eae08a37b8077b1e7a
+       bf3d4ea78a22782aa1978b42b88fc58ab4594bce39dad5b564c9603d9f18bcc5;
+  000000000000000000000000400000000000000000000000
+       d54d3dfdffaeab5ece06009b61de0b631d2503251e08f5d946439dc3e23c93c5
+       eb4e97cd5fb0ade077a1e463b46642785d5df66693ca3cafe4073148d4ecd8d6;
+  000000000000000000000000800000000000000000000000
+       2546c7077b11fda1d13fc0a58757bf47408f4fa6801c6240a31b0821d7294bbd
+       7d6f42de54cd407eed7ffd603a9cf2e2e03d5bfa3f7a2a1adff261292f5e30a0;
+  000000000000000000000000000100000000000000000000
+       2f8eb8d9a3f973e0657700dd113b1fe4a124979e54206ee368c04b5507539ae2
+       65398aa3cc2250c82a47a3812637c270959613211682d1d14fe9f70524e72df1;
+  000000000000000000000000000200000000000000000000
+       cd7604e207e7e65de5458e56b470deb55562d2fd0f7de38468badb7d30c1107e
+       04e11299732ac33fbfafd8b73ea585ad11202a865c4d633c25e690580b527654;
+  000000000000000000000000000400000000000000000000
+       d0f99bf98c30dcfaac9a4f14693febd6e44eed176f86d7a9b7d0ff38f7ef9b10
+       eb250f8278f8602594b53456dab86a4714943910985144ad7e1044877949c9a1;
+  000000000000000000000000000800000000000000000000
+       20078dcf344356d93c8874fb3ba99fa55446d9082e96981d6e4b0bf25241dfcf
+       1ef8439de2abc9ee2a524e76eb98773c851de2272e9ff82872de69120dba2e3f;
+  000000000000000000000000001000000000000000000000
+       6ecbc7d196fd0ec594426f8ef67f04e3fb0b187616403c3d770f07ef83e839f6
+       74f801a04bdfc3aa70c62c8111989822e36dd3954a18c03817b4958900ea6fc8;
+  000000000000000000000000002000000000000000000000
+       bb295bdde6c445e83709b56a027ac1491e3da32d1e27a2d40d4c604e534cf5bb
+       091799a866abd7ebf18e6ac9421d394b1247deaf31e8a65ea3ea5156b78ffd67;
+  000000000000000000000000004000000000000000000000
+       34d2916c9570990e5a2ce1f8fd3f4d92fd55227835ae79729494c2a56f3181ad
+       bd9dc29b42443bdf687aad6aeb0de8dcac403e13f40dfab97d289f5d8905d68a;
+  000000000000000000000000008000000000000000000000
+       6e8e0e6a1bcab3b9c4914c1b7dbad41180fd39f4077920381e6e5d43ae29056b
+       d331837650a86a752e106d56056d34f6c60daee1f2ca2f5d32fa3d4c4b11f590;
+  000000000000000000000000000001000000000000000000
+       d15117718cda91b580c8ee37b7e92a92aafb1bacef081c8dc4efe8d9035cc3cc
+       dc40f2cba1490588030c77a2deba609aefda9dbb2de7caa20a27dc78b0d6a35d;
+  000000000000000000000000000002000000000000000000
+       85e78f287d6dc01f23c5a7e0f3a79f7cec29705c18210ae5da37a5e787c7b900
+       4b0f88ed23950fcd28af65ed71b102b108dddf354464430823ac654c89f8146e;
+  000000000000000000000000000004000000000000000000
+       674696bdfb8b749f045e4901d5327e907608abc8a441acc85298c4ec38207d7f
+       cc25d43dc704c71f4e18d3bc796c5d12db5771d929aac483f51b11923ad032bb;
+  000000000000000000000000000008000000000000000000
+       f59b32955794603eec1664d94b565126b08f689979381d4d7371a1f02d5939bc
+       f6a18c580d6b019f0ccf24d0585b612a9d0194292880c2bcd329b16d32d32eaf;
+  000000000000000000000000000010000000000000000000
+       8331de42dd7f34562c261a24c4206206fd2f7c82077daaf793a8c13cb7736658
+       64d0688016e1fbaa84efa02d12f38becf1cc3b49af8095c645e006245d04e7a3;
+  000000000000000000000000000020000000000000000000
+       33f329a6f1febd546b8dfe981052f456f1cf068257d61e4215d0270b731cf416
+       8a1bbc62bdff88601e65eacb63f3b81188df1715dc75e46e80e8d4bad7d080be;
+  000000000000000000000000000040000000000000000000
+       e13972f07f517f8e11951b51107feb546906c2c9c9fedded414c099e65ac612b
+       e0cd462d9c2676ccb8f3395ee3793469dbd0ee8bfe9b70ecc64c1a3a7cbc1afb;
+  000000000000000000000000000080000000000000000000
+       30dc82438a0c01fe8916bd3d50ba378ba74c7902fe123850134bd254de36010f
+       b49612b958bd2f20a3662304ca13b856c325fad90020638ed5824963a8e047fc;
+  000000000000000000000000000000010000000000000000
+       8bfc581db5e81ad346b934c1567c30409d0f7260895d7ff5900791730d3a780a
+       fe79bea87199dda2ed990add427118e574a293bcfb9a7cb74dac47ceeca73c19;
+  000000000000000000000000000000020000000000000000
+       074c4229882668f1d1b2fc749d8a839f23d247e01efd86bc569422904fe86499
+       420687e93a67c0b5c4e4c4f39f596f314ac56a18f1fdf78a671b50465d200f89;
+  000000000000000000000000000000040000000000000000
+       c60780f4ac3b1507ce3d9e899af33930a44aea6cfa09ea11df9894f06d54286b
+       9fda5c99d571f89a8b5a38f4fac48c5c21ddc91fedc481a951a8d1fa6956bdb8;
+  000000000000000000000000000000080000000000000000
+       fc3f7afe9eab56e59f7ac6aac5255e74dcac9a467887fb1e047531aa6b7c946d
+       200436b4ccbab5f0cf2d8f6987364e88c650e5c432372a30d9aa9bb6e1c2665d;
+  000000000000000000000000000000100000000000000000
+       bd0f3ea9e305732b6f99f6d27d4e29cfedf59b3e6b24052ce0fac6b055ec9eec
+       57ac440ffebd1a3babc1b39aa1c19bcc9086f3a841190949d3fd70387a69435d;
+  000000000000000000000000000000200000000000000000
+       b06265193cdafe2055c504f94068ba76858ce5e8c1723ce078821158c653051b
+       7457c97d616c01e642a7608045444fa985ce002df0a8b87033a31fa4110c742d;
+  000000000000000000000000000000400000000000000000
+       5478345da67f4dd32024104c5c0eb13cf4165f29ad5f0c946e35eb44a6a4e97e
+       0e56f1fb7c9245ac5fcd148ec00511ed693a82a2390deabfcf2f7525a4bcc0e4;
+  000000000000000000000000000000800000000000000000
+       9f583a1aaab317311422672cb6a29c036551d7653bc11274a53c50aa28958310
+       e381e3727134a1ab4dbb3944447d869cfcb9cd8baf5472f1ea55d0c3911b2aab;
+  000000000000000000000000000000000100000000000000
+       ef31cb4447629b94a8c2bf6c2479e8d0fca2a9c3bed40506bdd009b859c1a234
+       2be2a20df00a0b9473601282902595bd30960b6eebff3eccd2772047e91bbbfa;
+  000000000000000000000000000000000200000000000000
+       822f1e0b80d284ab77242e6ea6a31c7b9478fbeccd019640bd790721b94fc602
+       f81e837b98de88119be6906594a26b93342990a9e432808df9bc3ff8f794fbc7;
+  000000000000000000000000000000000400000000000000
+       1b048b3da8ac57c867d65c7054771b0e0f0160b7a389b9cd0c2a4c2230ecee02
+       14d4fe78bb906ab8a1174bcb83b11dc828e284f7799be720784d2c8c8c9b60e4;
+  000000000000000000000000000000000800000000000000
+       6d572bb0230a9c543f278d4e44d25f07a3e337fb6bfb62443cbf9f63d54d3d23
+       ec8fbf1c617dfce2e2888692f4233252500f6370f9ba9aba9976346f0b45db5d;
+  000000000000000000000000000000001000000000000000
+       8f0737b4a2c72a5401388a64943d931cca5100f896ffaacab6bc6857163cb364
+       4961e5c5d4983ffcefa36d2d31f013b55d339192be61f2d7d525c9514851b9a6;
+  000000000000000000000000000000002000000000000000
+       865fc49a982f200c0ce91ca8389997385cea07d2054e215624ba915da86ab56e
+       9f9f408687229eebcf6d6b11a2b0e0983f8166fa538fdabbf24b5faf7a5729f0;
+  000000000000000000000000000000004000000000000000
+       a265014d381bf64416498ec6cd0d8280fcccff8ad00a8af1b87ffb279a5f44db
+       0f96100cad1c7d79f2c7d266c2676a1aa04e507613cdfc88a9a5b032749a6849;
+  000000000000000000000000000000008000000000000000
+       69c3ce6588db62df37606f44388b5d743e9589338f479a42b1994a8649b35353
+       03e557b5d65d9ce0ed50e2e77365e6dac2c5534dd29ea0ff6d6f3191ecdf3ff3;
+  000000000000000000000000000000000001000000000000
+       3abdda974690d01044e1283d277823fa099234b137298cd9edf814c7df994f1d
+       0624991cab7a0f9eaf650bfe2329966038ccff5599c66af5fbf77ab2a7028ee9;
+  000000000000000000000000000000000002000000000000
+       ae97a705ea10bf85929124addd1d620aadd98c35157e1ec67827243a013a1a55
+       1f33262e18666311dc61128867b31a015996924ea43a468fac7f06421b117a79;
+  000000000000000000000000000000000004000000000000
+       1b11cc975752a04198e012614cc5a52c7570af58acd7a52cd479ff25f422a84d
+       036163f34610434f92b23d88b6b9abab66dbcdcb1b3681ab63f8126ff5f3ceca;
+  000000000000000000000000000000000008000000000000
+       726d34090d8de7bd8892b9e20cdd176e425b49147ff02714e13e3ba4c0176094
+       cd95775f2b5274867a6485b92d8fb68c43e5b18dae52cf2a9aecdf82fa2756e5;
+  000000000000000000000000000000000010000000000000
+       438b7eb9e29d625f827dbea30ee486dea4b8fba4432b35b3f1f598a49d1e3efb
+       f27446705c795d27c75f4e152c40979f838a577485e87154ad49e141f3906bad;
+  000000000000000000000000000000000020000000000000
+       b3e751e53ca877bb58140b3830ed6ca88828ee8eedc414e46f4530368559724e
+       1ef875af1f5a2bb7b3705060dca18a0bbd2944e9510d1cec7d5dca01fd030abc;
+  000000000000000000000000000000000040000000000000
+       0d85bc30d372bc51fec89036f8dc2a9a0c44dc732a35dc986c3308aa732dbfc6
+       41e311175cf4715f3a63de6e9d09a8f1e1ed35c7dff4ce55452dff184c67ccfb;
+  000000000000000000000000000000000080000000000000
+       2911634025868ff4d90af8f03797e04facdc14c995031b8c1d399a8fb54f7945
+       a23be5413808deebd664fb8bf8a44616086bd9fcd7012a6b019a288f179a61e0;
+  000000000000000000000000000000000000010000000000
+       dd1c1f9aa7639f84405b4ee50a0af7c1da71bc4ca4d7a84037390039073926c1
+       1cecf7f9da8b89b1793380b3ec02a069dbf91804af70248783c6eac500e72b54;
+  000000000000000000000000000000000000020000000000
+       357fb20348241fab58252324b651366750f5fa3cda129beb249fd55c520ee8fa
+       7943f92bda9aa429f4c67f6c60fb64f467eac75cf674f24c7e7d2b96afe230ae;
+  000000000000000000000000000000000000040000000000
+       08933e7505bc9dafaa5cd4742c4321dfeed5eab0db0e8a06922f66e9b2f1d449
+       80060d8f8c9c4e78eb37a9a0ab618a212a18b809b653ba6fba4f9223a895fd55;
+  000000000000000000000000000000000000080000000000
+       1a75b005be0c2e4d5ecfd57407a92c1261cb94edc3fdb86201e4122d10f178b4
+       68507c27736ef6d31e5c4abfad5e6494659724880f0e14f7cd92e4f81780216e;
+  000000000000000000000000000000000000100000000000
+       4168cb291d201eff8f05e4266aa8a1f458cb66e3b01ce233ffb41f8aa6e9a12b
+       db84289b819e513d5116ca4aeb480616a03d7804b41e4125b03de8cb3852d6d0;
+  000000000000000000000000000000000000200000000000
+       44a8f5928c2dc60ce18587c8f558258d0a5718773644b028fdc86d3aea135a4e
+       0fa47daf31ccc8ec352c84e860b704b52dea2f15969bd08ed94063edaa5eb891;
+  000000000000000000000000000000000000400000000000
+       be7aa43951c4bee8cb3d2fd3a4869f498bf59994128cc3fa0abe0c9a317ca562
+       8c8f3694ff0333cae80183e03542e563a3bc3c25dd36c016300987445b1c0385;
+  000000000000000000000000000000000000800000000000
+       279595b2e3d27000ad59360b237948d578dbfe442129ce09c963ea2467883447
+       5b0366c4833db132340334597fa4ae42c9591952639e86c7a5c5aaa67eeff61f;
+  000000000000000000000000000000000000000100000000
+       3d0e6083f6dd8af24aa64f4f95c02de180ff34db8a5967bf47a38f048ba1907f
+       e16eb2abd16c38a5a13461b1992bf3622545c338c06bddff3c31ff4f11bfd7f0;
+  000000000000000000000000000000000000000200000000
+       7184ce9462840f4f061fd8ab9053c7074a6a3fcaaf1bb7c660cf0237770f16cf
+       19919262f08dab0f920541fdeb8f12b7a01e2f4350c9e42bf08819fa3d7cdbed;
+  000000000000000000000000000000000000000400000000
+       7e6d7e42393e2e8cf0dd13f0f8c175796c07312be0d038162018f9f059192bb6
+       222f78b280402f19ad7ef8fff7bb9baa080925eac811f9d07a0e2625b8d0d3f9;
+  000000000000000000000000000000000000000800000000
+       ea6608f32a44501ad7d272ae5d4a02ba172c0da0d2ebbe99e6acc74d782b0a25
+       d9b0c977617742962071dd97d359a589f323442201ed8c049ddd19986d6a7e59;
+  000000000000000000000000000000000000001000000000
+       ac34522fa1a172f61671921a073eebcccffea629c88c3efb024def587e85815c
+       5cbaed86ba8d85fe7a1b7598344b467fc75c425bca2e057e4d29583c1339e2df;
+  000000000000000000000000000000000000002000000000
+       8ef6979bc1593327ddf83f3582ca3089bd28441d603a68438b6b8963d5d5be7a
+       2f35459f0fe78ed10cc345dbe5bda63ca032064173ea2222d8a44183efad70a1;
+  000000000000000000000000000000000000004000000000
+       e7137bbea6d5f12f35607bc208a48f9af232ba192552783ec1f1cb2ed9390abe
+       400a562793f9a5340981d297af0bf0cef8ddd966b4245192676aceb0b830cd29;
+  000000000000000000000000000000000000008000000000
+       0c10c073d596ebf8e92b9df89659d7e395c9755f0bde20386da97e61e28edcd4
+       1c16a91cabc951a2cad46336e8b8d63e442bde79569c953ca9040638fe7a6854;
+  000000000000000000000000000000000000000001000000
+       f2c778bed0cab8b49b63bbd4cd2e4b3839737629c76af97e41256fb5a51fb135
+       c459e872e3d85d83bd6c02678ce707d4b55cf8baaa990a1bce85297089777032;
+  000000000000000000000000000000000000000002000000
+       48ea086a4b426c28b7a789f863d6078fa557c8075f151bb376c19b0333c7617f
+       3619d9a633fd99cd676764ebf0bde6392726c71c09edf1cdf6a83082043c8837;
+  000000000000000000000000000000000000000004000000
+       88887c189b997032785c0211647d16f01dee57453dd8ae457904181346e3387c
+       a01ea4e80af98fd522c73f363fe1f67ca74b2f550cca01e1a831a371818f0a67;
+  000000000000000000000000000000000000000008000000
+       d1cc08438475d0a365e113a4f6cd2b3f8dd0fd16f11a7a91a24d7d57bc299a76
+       5211117b058e16a42041313422e59b867c25234913f19ce0d3e8ba2c83a1b604;
+  000000000000000000000000000000000000000010000000
+       a08d0c7258596d8ac11e99955d27dc5e58c1a94f3122821cb62bb7750f8c86a2
+       828f22a04c97d1608bff3c343450975b321b1f1078f4b8bb8e392bfc3d6ada6b;
+  000000000000000000000000000000000000000020000000
+       cfa3d2646ed862a2f5e1a0012446f25b320368f817a9f6aa34679e8256b31713
+       18ed4648e98ef43131ea244158d550f391d10aff20a786b49a7206e0cb810a17;
+  000000000000000000000000000000000000000040000000
+       9f3a7d42e935c1f2e486976714115dad69a44ab16a251d2ee8d59f09f752d43e
+       9d28bedbe24fdb9b7d428a5bf6f290a0d3fcd4c5d3083e8dad1deed29278352b;
+  000000000000000000000000000000000000000080000000
+       5c99b3f3fe50e3d2337417eda4801ebac775bb7505ca0dc7d42bae82ae9ab9af
+       8f3d15786baead2a7a7a821f651b2cdb354da45133f8f41886362285e8ae0303;
+  000000000000000000000000000000000000000000010000
+       465980c12032bfaff4119e7a258e0d9c9d10ebdd694c594eceb203e3b44ce3ae
+       9a2ba16d5bbaef21e0c7c28cfbab685e91840ed1c6c7e2d9afc52110f000543a;
+  000000000000000000000000000000000000000000020000
+       72a31c0f8e054b278ebd35af35661bb0bb23890d62bc4ff567883e8d6df3a64b
+       d5a094453f00fbd672acc45fc68ca31e00260b6fb0bad3e6c1adf2a6cb873a5a;
+  000000000000000000000000000000000000000000040000
+       51ee7d952e9d6ab691ae0af0cd24daa737043475b208ff66adb3fa5c09f3647f
+       36a7317d1f7e27f7cbe2745adfdc49ddbff3e6406da0f0bf79b5b64877ee94fa;
+  000000000000000000000000000000000000000000080000
+       03d5fefc307c92f49299cb1561e8925e4b333530d1d39e6576d999d6b18e9566
+       c80301e64d2a3c192dba0fa08c12a1ce1410185174b5e97f1b7e124418566dc4;
+  000000000000000000000000000000000000000000100000
+       02b1c0b7e3d4c64bedd8ca69dbca551dbb34c54007c70dfeecc64f40ec689040
+       7d9f113f627086a13dbae2a8d59a60f0d9c59693dc38db1262a6cf63ce1e161f;
+  000000000000000000000000000000000000000000200000
+       31aec9854efd20aa692d58e5f35f9715aa6744763e80a2b84c52e7746024e4f0
+       e298bc6d65a88ef0dda69e3cdf8f39ec836881da986c94aa8e55ebeee896f376;
+  000000000000000000000000000000000000000000400000
+       b6b7b784d08b13e5e9bc1de7c580a2a84bf0ce0863ace791eaaa5c448e419b12
+       a7f496e466a7d3a93f52a704b165bf1798f159d1fad3e3d33cda5551e6e81b33;
+  000000000000000000000000000000000000000000800000
+       7edbb0b8915926a8a2e8fee143b729415135b88414a2009f0d5d1c0683973534
+       21b1c8e53b342159b8bf091b43534ee08f4584ab504dbcdab6ef108edd7addf7;
+  000000000000000000000000000000000000000000000100
+       66b011b48e7c4d63065e119be7d76dc2fe5f4832892e521b3919a567f28d78cd
+       883378f113fb173d55e21afac17b6bcc13c5b825b7b39c4587e36a7bf56d33f5;
+  000000000000000000000000000000000000000000000200
+       36b722f7c39d54cb3b5fd4a891b3895d6da18a6206cd9228b5f890a04a732d2b
+       5ae23efac307c817a93408eaab3c71fb182b8c339c6ecd86a04dac2ea551974c;
+  000000000000000000000000000000000000000000000400
+       8c62713ee186f9c9b85d3b39433a8fc48005e4b772243e2c59a0b6c9c5f8d945
+       fd48ec5913d2c5a24898454ee7d127a2b3faafeaa51f1eb6bfddfdd89f29f55a;
+  000000000000000000000000000000000000000000000800
+       6cb6e49700ea40fc2250f75122c7658603d210b28fd5a7d330e7eb7270571b92
+       faa3c13c45e6a6058fc008d29710e17df435ca6fe03c802390e66a1f5d35f448;
+  000000000000000000000000000000000000000000001000
+       e209f79562f3acae829c8ac46326527581961f6a9c50efaacf05cfc299770d3d
+       47fa35bd28db056ad2c960ffbf195b6726b8ba70d0e1036deb00191e1007bc73;
+  000000000000000000000000000000000000000000002000
+       039ac5fc8be0833d2b344b501949b94965ee8ca968d41f799bdf4788c69dc9ff
+       ea9f5b28839e0ce7da245f22957bfaa6f23aa9e91797f94ba41c563ff207eb24;
+  000000000000000000000000000000000000000000004000
+       f8b3de78e36105f66bfb9030186225b551c54719d03a327e477a15cdae4c442a
+       558f352e51df92eaf816878a8117507571e77ed0af9196f621172ab63c57e96b;
+  000000000000000000000000000000000000000000008000
+       a95ec4094654e78134ebfcd6d99696b59ad8922953c88d4676e690235a07bec0
+       0904f4197e14bf542f25be01e01f2902e389f872389040754b4150ce17e8a8b3;
+  000000000000000000000000000000000000000000000001
+       e4e55a685ce73b8e8c38484cc3a095ec77d79d4213bd7e8509e634cd22794e76
+       e52aea0a67ffce6c423f49f19799b5cc144430a97a4a11cb81a15325ba58182b;
+  000000000000000000000000000000000000000000000002
+       e82db75f9ac6e522e32c0bb59d526efb83041531ca7f8c10b50206fa1f5c0f95
+       afff3847b075d3ba60d574c58dd38734e585c6835e7080ee22dd11fbaad76187;
+  000000000000000000000000000000000000000000000004
+       11c10caddec7e7df6e2b3cead72466db28943603073b181c54586cd97668913d
+       4892b31c3728824d569af42be89c87986ec1d7e3ba680d77269b6d66a8674a87;
+  000000000000000000000000000000000000000000000008
+       8b10fe1f2dd03e24b962a91d341424db2fb31a98e99cc36ece76fce644e7626f
+       42f3a523c2108ffcc693ac50991144dee446980819ca6748337b75212f426d7f;
+  000000000000000000000000000000000000000000000010
+       268ca8eee4d8bbecea331da0299a3c7722ecc81f6d9e0f360365ae115be736e4
+       b39d8ee9b20baf88f8073d5c50091a4ac02e050680ec0483f13896fbd08ee022;
+  000000000000000000000000000000000000000000000020
+       dcb7c3ee50078883fc516b99f8ddda0cacd6df989d7408b90ba4b79ca9aeee25
+       a306a8182bf7d39636b924b1398bfd4a3eb54ca10a2a92deb6394ae6ae5635d2;
+  000000000000000000000000000000000000000000000040
+       3e8bbb3bdd23331becabe027092f9600030a29cf101d49a0645fb19839aba819
+       3d0ef0e093c0df6b7a6efaa547dbf7f96c77a195e7f32791c02e8d6d84bbd999;
+  000000000000000000000000000000000000000000000080
+       3001310564521f5f6cc2ff5138270e2b01c98f1e0e0df104f218a7bbd4c528cb
+       ca56375249968d85431fda8a0f5a94a676f725730eb2387673e8e2196530d40a;
+  01000000000000000000000000000000000000000000000000000000
+       2464195fdfbc0fc81a28fb4f56453d5bcc3641a478bb8e217a12e81d209a0d69
+       764217beaa547cdc74d61dddb77759fa4a46818fd71b77ef19a66ec61bad44ec;
+  02000000000000000000000000000000000000000000000000000000
+       e093cbcd15d9d26d2299aa256ac0ffa9479e82a7e6921c22330459282c643640
+       2d6e17704b89f170344a816657e838141938dfcb7710fbd748230abd423a8327;
+  04000000000000000000000000000000000000000000000000000000
+       bfc89ff49188394972ac2fcc77e4275e8b7e190ad88ec18dd46cde1e8d08fb3a
+       240721b9d03626e7222eb91b29b1b56effaa86b815c8041ab46f92fd86ef6fa3;
+  08000000000000000000000000000000000000000000000000000000
+       4f8fae102a0f00b1ea06377d3d331df3b492d4038a01467998878f9ca6101860
+       2b928f67b786b6977666abcc44bec615d27ac4ee3f6e3e0620a32174b0428d08;
+  10000000000000000000000000000000000000000000000000000000
+       1580bccabd91d69db6608f185b39e46bb8c2822fdb63f55fcfbfda08897217d1
+       db3cffd2dd7293de5ac9b47dc91e8c8c12a4890e67a5ff9399821dc7282e3125;
+  20000000000000000000000000000000000000000000000000000000
+       6b99c58f03c9ade53b87383363db9b60a1cc3ef8b81b13c146b2f3356becde35
+       f77668010fc0f6ab4438ba294b19a62756316746da733e22eb9432e4b8d92665;
+  40000000000000000000000000000000000000000000000000000000
+       e711df4d46fa41caaaa9ef1db1abe8fa9d73fcfc2c8f7bc0bcaf238d88acf2f0
+       f923b9ffc408776d2e79903cf46bd57b4243142de89554a6c42c535469f4afb5;
+  80000000000000000000000000000000000000000000000000000000
+       6a3a9121b368c3513dd88522b3a9d1fecc6403f30eb1dfafabdb2467db85c4b0
+       ffc4cc0d9b92617db41d1d9e1f71ea3962f57624f85c06cc774e0789bad7d70e;
+  00010000000000000000000000000000000000000000000000000000
+       4cb64c389bcf6ff3c15f28ccf61486e2aace7c54492d2e52f91672fc1ef68c38
+       c12c3d78af5ed1c2a1b8f03127a2b183ad5876c181ddaf0b55b7d275b1270406;
+  00020000000000000000000000000000000000000000000000000000
+       39e2ac45e699af272119c0f264488b382a93468433ffb73066e1b052f0b95114
+       e4859a08895657b444b0a92cd027ad01b2045cafc91d5a58a70d4881df7f749d;
+  00040000000000000000000000000000000000000000000000000000
+       be12959b811b7990538165d11ad379332c729f72666c2d177bff7c6585c4fdcc
+       2da68a259c2a68a877d5387f01faa64ab6a537e11e2e4620b4edc957dadfc1c0;
+  00080000000000000000000000000000000000000000000000000000
+       bd27f6928a39f0404957f340701b23f529af3a4ddcaf3176f7e5b78f31027cef
+       9df676b4ad16eef5fc3d9074ef1fd0286dbb7714679449b8059a86187013cfd7;
+  00100000000000000000000000000000000000000000000000000000
+       0f6c337b825811e0f4afc216133a38726cfb6d6de0da7bb8f33961a2c21be234
+       14b48beec8faeccb9500285799ef73532853b8c7cf630d64ad934884eff923d5;
+  00200000000000000000000000000000000000000000000000000000
+       96b9131980599233f75d381de365ee5d71706e880840e6f97365628a1929fd32
+       651b53f4d5f76fc3eead20ef4f8bdfce994a9f4411d9ed9d9a82e2d39966295b;
+  00400000000000000000000000000000000000000000000000000000
+       90131368532a05827eaf2ae0c7f7486def928c0cc3c97364fb3a33ecdce76a41
+       1070e529c583863ea11745c08ad3511e25f00fb1f6566e9a65d15c4c5b9db9f0;
+  00800000000000000000000000000000000000000000000000000000
+       9e194d490e2e1a13f067736c1b4c02babbaff92656b39f2cbfbf79bcef509d32
+       d68bf125bc9d18f357263378f1418d0407554c006bea0d57fce3284ebb23e996;
+  00000100000000000000000000000000000000000000000000000000
+       9edaf8d2affd9975fc6edc4d7551d745f3ef5c1c2e9b6e866ecac4370718f00d
+       11538a9cfde310ee1af5b1bdb89fdf7235b65f06804c1717b50a3a7bada18be9;
+  00000200000000000000000000000000000000000000000000000000
+       699a6253b34d53c925a3ca885546ff6f075ec5f8f2512556f5c9939dbc66521d
+       94fae63abb388be332f694d27344004f9cff783d7e0efcaccf6869622f1a7a21;
+  00000400000000000000000000000000000000000000000000000000
+       c8fa8a591d52dfbdd4de31dc5e7e2e34c1116f9136872d482adacf6c4ae5ea4b
+       d5a6965f1bb3023d6fd54c871732bec898a322a815adc5ef4ee92fbba3292ca4;
+  00000800000000000000000000000000000000000000000000000000
+       755e57fa2b60ea3d49217a983e01ecd990b9f801b4bd418ed9218b0e0ab6aedc
+       4dd53d0bce528d27e721a7e57dc1cc996de9fe7a1a9b68bb166e4ca3883273d8;
+  00001000000000000000000000000000000000000000000000000000
+       d7fcd3441c6e19f5fe50a13e8df8efeb313ea4c3d5c98a4d0218a15d2fba0501
+       03b82200d043d05cd925deb405da6fe465da86a542a99138286dd3c15180b11e;
+  00002000000000000000000000000000000000000000000000000000
+       5c2aa4b1da995bdb48012fb3597f0c293ad32d35ef0b1d18818389bf293c06f4
+       5cb31ce813dabc594db8769257f0f8d6f56228968032ec3faa6089959fd312b9;
+  00004000000000000000000000000000000000000000000000000000
+       b492eb88b267d7e8d5b2c4f627e0134f0948dc958c3f9c3b9d53cef81d395fe9
+       c17fe250e789278e9f00eb8c4031415a534797685eb90b531e6034b72bf11a45;
+  00008000000000000000000000000000000000000000000000000000
+       b37285ea7dbf2e60444ff339c6675efcc427f8fa6d0dbd4ec23f0936b60a1f36
+       a18f8cec0b0886c08e43b9ebac17c592b95e87e8eda9dbedd9d05982f8769e0b;
+  00000001000000000000000000000000000000000000000000000000
+       5cc14e4f6ef530df34196f17746dd9b10e10890beac586e16603b0a28754538d
+       8397bdd286cc5961b1414830586eb2114cbbe9f626ac355da9596861320277c7;
+  00000002000000000000000000000000000000000000000000000000
+       18c5f953553658bfe311783c54e1d3b988b7e13e5b1a05ff7b725a1b3fb97815
+       14f9a5aa033cfc16b02ef4d7749e136521607a74e1d874d18b257ea98078376c;
+  00000004000000000000000000000000000000000000000000000000
+       986ed4e41b1925be50769c2b9f3bf9c42060e69f4825b0b27eab36628f43e727
+       0ba3f96bba6070ab9f18a6a8a3bd38db4174456c0eacc8c52ec067d8f0baf138;
+  00000008000000000000000000000000000000000000000000000000
+       29dc264f8b38836ca14e4635397a48a18a489adce20717d417c004cf39c9444f
+       971c02c844cc79d7464f0b7ae3ebeb6ba461d1c257ae052127d6c35dacc7931f;
+  00000010000000000000000000000000000000000000000000000000
+       23c02c0924ece0eca2b9a113953f86926c7db6973ef792b7ad30ac5146bc8c1e
+       d5b1e384a939c12b9eea540dd46dcadf861831a2eebce73b0ae8de42bd83504a;
+  00000020000000000000000000000000000000000000000000000000
+       a8001a31579cd64e94ebd9e4a18818749bb0f0fc01ebeb456b8c0e065142c220
+       f124e79fcf5f18fe452ee9e6593b1b2b3ecd0f68a8faecdc09c04ff179b9b01a;
+  00000040000000000000000000000000000000000000000000000000
+       1f01e394b147f07da857c34896d8dee3f7888042e609ab70df48268ca31dcc5a
+       04d77d393666c558f69724357158eb7bfbbb05a8a38c5f5b48e082d2ddf39ff6;
+  00000080000000000000000000000000000000000000000000000000
+       ba3d2f96d7bd899d2d6142369471c133bdf1ab5a9a584745538c78631b095aa4
+       1f008bc2a6ae865927fa85b29a2c45304f09b8275e5ecfb62eb44ca5244b0937;
+  00000000010000000000000000000000000000000000000000000000
+       8fe14f887a1b802593b62ee61d7bd8f2733db0babcd41652ac1185d2d18f578a
+       1103c814cf73455d6dd34ba8846b724fb00d6cbfeca562bc97d118f4cad784d4;
+  00000000020000000000000000000000000000000000000000000000
+       8f767cb1db48efa0a1c5d642152edd3a050a1114facc07cd41409bcac7147f58
+       c08e42a5019bbe1275375549b91dd15819b71b8a7592152cf8d94e964860535b;
+  00000000040000000000000000000000000000000000000000000000
+       82b7a2e84536cc2d2758df01658bae073b29b11339f212e320a3d7de2b14971e
+       20aec4d43c582e1cef05b6e268b61a2f9633221ca785943ea7885f690242cd00;
+  00000000080000000000000000000000000000000000000000000000
+       76ac83b90aea0742f8ade2be9b160a297d8fe8b98daa5c54b4be2e44fb88cc21
+       18d1c8486e2b6f25e3f0164c2c0417af50f2438431deb4d4965f0cdf8cbb39d8;
+  00000000100000000000000000000000000000000000000000000000
+       0c2e937c9717fdd4868c019ee1bdddcc7ff68d5df4bf8175a59c13fe9ffa9ec3
+       1c754234c085b09ee98fe2049b0722502e0edc5508cca7190eaafaf90df3d310;
+  00000000200000000000000000000000000000000000000000000000
+       acc18876ae7cc4f1a183357d04e461987b1208b2b99f8d77a5544a07bd8fe89e
+       9f73b6c96743fdf8e1dc88e0022a45e19349ca3ec2bd691f2e5d5b08114c99f1;
+  00000000400000000000000000000000000000000000000000000000
+       88ad33df55b990c06a2d16d9978913c23b287c7b1e220c42477c46104503a766
+       f0042fdfa21c7405dbb441051b9e0f9a31e6f007a0a8fa43f97c86eae96acd38;
+  00000000800000000000000000000000000000000000000000000000
+       a3579b6a7d1d0efb2ff2cdfcf23612c9b2650beda7a67cc46e1844ed0dd12e69
+       1ab34729d9777a4009e98a196bce38d4431729e5ea6901824c50bcfb49b657e6;
+  00000000000100000000000000000000000000000000000000000000
+       966dab579c1d3702ddbe8656f9240b4efc6704391715442a66bec541456b5710
+       06345acc4e0e9682b21f66a220fada9b4f6d82504d3b73c8f6c89311dfcb1352;
+  00000000000200000000000000000000000000000000000000000000
+       12e01acdffc14a9fa3bddfb492bc348bc0c95eebbaabd17948113e63ace4c51d
+       9d40be7abc07a4cdd77219952ec81d8e1ef8178df21a2cbc927587c116c5e08d;
+  00000000000400000000000000000000000000000000000000000000
+       1f9f2968843c0133d070e8f0617a545b55fbd9a659e1ba9be16313d7e24a33f5
+       1eb163f3918a775d7c2cf6bad06d42359d9e4d0f0596822bb90d0db104156652;
+  00000000000800000000000000000000000000000000000000000000
+       1f007682755a014c1b88d7b541b296c7cf6613e2d5644517a49e0caab2f84392
+       eaa620472fc4f60a17390cdabe5a9410646b2754f26d6490bd89d8bd14d63824;
+  00000000001000000000000000000000000000000000000000000000
+       8071f28971756eac7456c7e41a8157cad949b67902f67b0186cb5ff521814381
+       7b3b7fd81181c132321b9e97ccfbe4983aab6c72dcde30e9172271de5ffcde90;
+  00000000002000000000000000000000000000000000000000000000
+       b7c03ef5de01672dd35370e37f77309ca808868dff56bbb094f9b0ac7c37872e
+       653410001ff58bd0701ec54a5302c5dd95994b6fdcb271447477dc1d35f32b28;
+  00000000004000000000000000000000000000000000000000000000
+       5057644476a033599dfc0b2dfe388660dae6c40828a464c931623997a3b2b1de
+       dcc23d1e17bceedee546c8452cdcfc43dfe3a36f0623371066a857a592b44c87;
+  00000000008000000000000000000000000000000000000000000000
+       cc9d90401fa604d973e99f78ea9d9e0945344f4098d2307f7402956de7ca915c
+       d877bc8623e95266ed10ed810f144ea4f7889636f63b36b478819200b06b2dc0;
+  00000000000001000000000000000000000000000000000000000000
+       270edd6834636fc90df711b57e4ec2a70c66189d9f149b8c6691ee901dd76c97
+       776b8906523e21663f84527687791c7f625a3eb1d456d430711212bfa0b36ff0;
+  00000000000002000000000000000000000000000000000000000000
+       c8d389b72ccbf5df09926294aa3a548cc07fe5693ddb4a4e69f82f736399fbf7
+       5177a1928aa122ff0281da5954ec854b2fafc3065b9d636f08bf7c6892054894;
+  00000000000004000000000000000000000000000000000000000000
+       99cdf287f3a952867f4aca8fca230fdd2799829786a09a778df717200910f704
+       3369a095516c39906e537b571b36537076baf3e00e634ce403017204cdc8a2cb;
+  00000000000008000000000000000000000000000000000000000000
+       23613557e1e34d83b979d4740aacf64ff2e7c353418d351932af432b4c3feac0
+       84bb895e1e113c431bcdd2f3bb02259efdc882fdca482085f64bb3490217e143;
+  00000000000010000000000000000000000000000000000000000000
+       1fddf34a6c90b4d87235c5851c031e9c6c9608c22b6bcd1f1988211f8025d381
+       4687c0880f5e092eb50faef790418e0dd5ef304b7e52cd7733cbf60c29e336a1;
+  00000000000020000000000000000000000000000000000000000000
+       7a448bca6c19369a549a89ce4c077fac787ff47683238cbde1bf4109d66fe10d
+       f5814b2ecb0954cd18dd3e633bc67890f30350c7fa2a4e2ed7fda17c4c224572;
+  00000000000040000000000000000000000000000000000000000000
+       6fae8a02043b344c817ab30fdc3709eadfd9dc3e50a260ad4ceb503f0dda2ca7
+       3a167f36f5c524677eb0acb05c715e614573e2c0a685a7e30bb9b111df493c9c;
+  00000000000080000000000000000000000000000000000000000000
+       8dc4aedcc4b4e7b7f96ba908e1ddcf7f07d8d26db0f599c5228404fa2e5e7fce
+       244309f24c16fd9ac28cb4c01c7354833be4d339754b8439d61c88afb7082679;
+  00000000000000010000000000000000000000000000000000000000
+       dd772809159b566a07beb6411bfb77d8511601aa33886ff217f3d6bea6b0348a
+       512926d3ded3f02d9aff5795050f2d1b8c0a7be7f7ed31b3ba085acc7d54ed8c;
+  00000000000000020000000000000000000000000000000000000000
+       d74853e986ef4ed4fe6e23538677a9b1800fd309e46d7cadc0be6ebce447fa58
+       6fe50d1ee521a88ae60582ec2e89acf5bb55dc13db2c5f45b01f2e95b4c3469f;
+  00000000000000040000000000000000000000000000000000000000
+       3e4b0bcf8c7de8760cc7262618235b6c76807130470bd84928652849bf2c424a
+       88823ee8d85199139edd4f77810ba859047ceb0cc640d10a9eb418c08280bd8c;
+  00000000000000080000000000000000000000000000000000000000
+       f417f0dec902322fb3754d0b5f1e841837549ac42efaa46d2c31cbd5cdb7bbbb
+       4da04434a336e640bda841c17baab0c0e71f048c092782019016ca6fb89d8e72;
+  00000000000000100000000000000000000000000000000000000000
+       e6a2f06bbd9b5d79ea935d8d53cf2098a4a838229e4b257258d5978c850f7086
+       9087fb1b85be7c7cf4fc0c3b89da6e36c7256190477b7d6a74fd1833c19bbbad;
+  00000000000000200000000000000000000000000000000000000000
+       1ccda6c45abbc6010a3267ee4e43af80f52499a819fd9bbb4c3df8a063fe0881
+       fa616cfd0404f965e3fec16148c60189850611b2d28f87dd1fea7f53218a53b4;
+  00000000000000400000000000000000000000000000000000000000
+       4e98a243a3167f35843ce0ead838066ed5747725daa3298eb97fadfeb2a47b8b
+       13b78a61908c40108d7bdae03e85ddf8d164ad161a6de1ca1f0e51a9d04010a9;
+  00000000000000800000000000000000000000000000000000000000
+       1bf5711f13594876f995324a6f688ef78fae8ba70ea49c175a27ef75ec85493d
+       6e3cdb2bbcc44b41b6e307fa774296889b4b5e92ba079789f60e9006b04d13cf;
+  00000000000000000100000000000000000000000000000000000000
+       442d9ba00e7313b035ab128ba863df68c0a19f1a7e572198086d7f79744cd088
+       02bdecf5b7f72546612d60fa301e01abbfbbfe27b4710d26f0c5bd50ed50dbd3;
+  00000000000000000200000000000000000000000000000000000000
+       246185ae4fd65b354b04f4fa186d700c49d3d9f5018a917a31042af8e33be63d
+       a9264216ce3b8a5ed76ce229955191d9ff66391b9792979dfa5d7c1fbbaf9c22;
+  00000000000000000400000000000000000000000000000000000000
+       1515f8b044f42fcbc8f04ac3ee3b89ce56e87f98b72134225603777fd1d66c88
+       3cedbc3b1cf63d957f2366876810213b778aaefd83f5c889dfebea8c35d2d4b3;
+  00000000000000000800000000000000000000000000000000000000
+       037337c0a20e54350483349a393194c5ce8f0104f3bbf2e9cdbdb4f8c93b4eb4
+       a52ee568f98bcdc658f48700b7b6062d2951a110bf0f3e48548325ab9212be1d;
+  00000000000000001000000000000000000000000000000000000000
+       9afcb8f2fb0c8f7957bfe3972ab4831c47c35f1deb5f01674637bcf4d0626d6e
+       7239fe3b5aab7daeca3c9016771b1ef6e67b3e3eddda777e12e8657b3f84336a;
+  00000000000000002000000000000000000000000000000000000000
+       abf8f708cf84184fa21b16ce492317060ba039e0815f186b162efdb47be5ca34
+       03a023c9dd6ce45f68000261b0ee2f1a8fb549c8469bf539a785feca009d289c;
+  00000000000000004000000000000000000000000000000000000000
+       115090529147724bb2280029f146ca67d19feb98e1d68991e3557b7f31c65731
+       e4db5a302db7910a999a6b04d5302132b3f1a21d416f4d70d2ca6c9500b4658c;
+  00000000000000008000000000000000000000000000000000000000
+       f8c24f3510ab36e692191e520edd4b8f7ca62e4c38976ca74f5b45fe75f0336d
+       0a20e557bf3112da79d211fafce885b2d2857270912da2301466294ab9bb6bb8;
+  00000000000000000001000000000000000000000000000000000000
+       006d35fbc723cf42718e015af9aa85a58785fcf5139f031de5913f4a4c9cee1f
+       79d9972f8ef149e5bdb2aea1855694834e88bc28d97f7506fd016e63984a3b09;
+  00000000000000000002000000000000000000000000000000000000
+       b6a8633cfd175b9d20f60805043ae68cd2e4b19d7306af279a476a1467147162
+       ac59474a091105832d53ca2ad5e4ef74ba1c7e227bd484d582523c8e8814062f;
+  00000000000000000004000000000000000000000000000000000000
+       be3e898c1f7be5fea90ea6dba94fb56d73af2540130004c2beec5244d402f219
+       2e091331eacada55955eaa588b2d7a0b60cccb37bd8ac7c1c29d5567adb7d0c7;
+  00000000000000000008000000000000000000000000000000000000
+       3173147bf3d87cfdaca80b6eb38a83f935844f04cbadae7f1de427533de75e13
+       fd7dc829a4cdca020ef6529b6f556393640d97049ae1c0ad75bd202f09cd3557;
+  00000000000000000010000000000000000000000000000000000000
+       597eedc7cd929393f4c1293f2dc579fa4f2afe807d5a2fb5bd0a896439be3183
+       e8c9cfc002d3eb8da47c8528600f0947d6049d34f6e1b1fb0c2e1fcf2691c3c4;
+  00000000000000000020000000000000000000000000000000000000
+       d3e7c0f4191f1a9fc7f2aa84a60daf5162b8b591cb44e7af87738378f7804c23
+       2cf8bedf4b3a75974868365f6b5baaa8c4594812130330352f3edbc791a01892;
+  00000000000000000040000000000000000000000000000000000000
+       35e398c0d94aac9865c5c693f3763923f32555817648121efdc2ecfc35fc354a
+       395e5543d4a31c9539f5c0a62a407abccc8fa71f52c075d5ddd927ad17e56fa2;
+  00000000000000000080000000000000000000000000000000000000
+       50ddee1bdc4c0f8f0d0c3bdb456a6e0a30c71b1e08d247841eda50a85c761ebb
+       6926a97fe085da68d6527a538644790ca8f8a4c68f3ecf49c3cf876a53d97479;
+  00000000000000000000010000000000000000000000000000000000
+       cf136f837e9c0078534bb9fcfef063fbac5dd5b7eda010502e4aed7819745a28
+       9b1a9914ba2586855e1f108998000010796c128ec5e822c3c49f1483ea7da01c;
+  00000000000000000000020000000000000000000000000000000000
+       dafd823ea2231a3d6590214a7bc68b9ea6159daad95778f44f3c287476b24e36
+       47906dd563422e0aee32cfb8b7cccf6c27c33e07189ab94dbfdb3fb348076c13;
+  00000000000000000000040000000000000000000000000000000000
+       2ea591c02005a5a83c6a5fd17025aee427825c07ecda07b78bc540013256314b
+       79af8d2a7eb63c32ce27f241dac9162dde7cb6bf0430a1ac59689807c98c3b6b;
+  00000000000000000000080000000000000000000000000000000000
+       340b58195ae4140093e1224f811e8e01fefbb3a61f87aba168836442c42fa094
+       4cde591cfdc70d3c8ad8f7fa942a84f5416c3758aab6c685e1c4cb9389a9aab2;
+  00000000000000000000100000000000000000000000000000000000
+       2ab8b78dff91d272586a56a661ac935a75ca0ec6c2dc6bef69b2d27889499aa2
+       3da491825757927a27b452da2e8e72e5525264af26739977392968c0351a90f9;
+  00000000000000000000200000000000000000000000000000000000
+       a151a348620cfe87d074baa730916f8eb8373970261759c8079b0a88eeff2741
+       e7d0a61a9258933ce905ff235b0287f215cada2453030a5c5aacbfe8fd93a4cd;
+  00000000000000000000400000000000000000000000000000000000
+       68185b88fd6b8ebe0ec150d966f3d48e03c51e5fbbf61d272bddc84003951168
+       e74bada25673f8bb50492cbed8b197af930133b104da958ed64f47b5dd61e68b;
+  00000000000000000000800000000000000000000000000000000000
+       8ca43156c06749fcce60d345cea15ecdca2cdea81b1bdf82025900fc856dd365
+       fd4c9ddd669d86d2298f5ef817e4516f8848a541d0eb4375eb2ea06eb1c3d681;
+  00000000000000000000000100000000000000000000000000000000
+       722563e1f5a521e0084ae6699bdbcef49147bc2db9d08eca8a155a91eff9e707
+       2053cb249b323faae9778c1bff22eec9759a6d04f67487197004fc6cf790e1e1;
+  00000000000000000000000200000000000000000000000000000000
+       3abf333bef3ae7f4f7c92a57195f758f1d116ee9c40978c24f435152b511ad98
+       417aabbc6aff1f7dd197c89c16fbcb87ca9b121dd19d21501723feb8a339dfac;
+  00000000000000000000000400000000000000000000000000000000
+       2a1a82d29a6c710fb7d35b1b66aa836ae340d4a9cfcefc5045a954d5988fad3b
+       64d9d9567db3b4372cff3be7c789a8bc6451311fe0ad9e527edd2c6a3e97820d;
+  00000000000000000000000800000000000000000000000000000000
+       92748e1df36ce322398858729265955801e70528990c15e102e1bfc6949126ec
+       944ec92f07e11a517fdcff7a41c72c02a3be354a2e3fd92cc2b6c03ae35a5738;
+  00000000000000000000001000000000000000000000000000000000
+       93a79e8843e5e49a7c61b9adbf5869b70a24b1786f2a476dc9b2b4b7a6d6147c
+       b44c96b6fc150dea743d84a3406926377ed403eb619b870ce414ad0bed5c6149;
+  00000000000000000000002000000000000000000000000000000000
+       613f858f69b87d4f2ea1287d2817ff708af8ca2292388c60ff64bbf772ad0014
+       9e98afbf45a14662e33355be5aac0e67a93389037ef6e04d72cd53c9f2091b4a;
+  00000000000000000000004000000000000000000000000000000000
+       26a5c693be3a5082796dea97f05cc2da9a8e1d3ef60e810d104d2105ebf81b63
+       f8765cb141bb16f91a002fbf0996a7b0ff8889c4545e2625bb870103ed996f7d;
+  00000000000000000000008000000000000000000000000000000000
+       6d6ae36d361da7f12442c0c5a389f6aa4967d9e1b538512ccc4f86058270d714
+       4a5be549a0f0b646e97933d3b4d645a0552e3b1b9d5474950ba154b3fb243f6e;
+  00000000000000000000000001000000000000000000000000000000
+       cd97ad2ab79d5e6893bc8676fc1756902033f5e502f48723e0c8f1bd636fd5ed
+       702acc3d216d71a16db827a4e53b16629923fe73b2f5ad3b5147c9d40b043841;
+  00000000000000000000000002000000000000000000000000000000
+       69bfe6dbf88d693e34ba867a3faae2a545c630c033a168fbad9a000b0a3d63c9
+       8c11ba612c0113627f0703c930a595f03b132c77677385b2f55eb951295b50bd;
+  00000000000000000000000004000000000000000000000000000000
+       474504641ebd7e5e886cfac4e8ab717829d7afc4653051a7ec4cb6136c5725cf
+       2f671c3f45b8f697207dd3edfdcbd228fbace746bc9982b107eac863a755a645;
+  00000000000000000000000008000000000000000000000000000000
+       403c4c767ab1fed06a95d0a42e6fb058092996c1e7f9cd74023bd7f7f5e65cc9
+       c767847b6384b478668f053277ed1e655e0e0822d6504a73c2a97adb344c0c50;
+  00000000000000000000000010000000000000000000000000000000
+       be00a382ce11f4b574bfff2e48e622d25d709fa043d2fc7c8ecdce33a6ca7272
+       a8a42c740d6fce54fa53651fb2b0cb0d8888d8999bde23cf6f5b42c8e2d1297b;
+  00000000000000000000000020000000000000000000000000000000
+       823eba2a58a9c7a43b4781255bb178a00ec401692a9f3cb64eb6b86146a89c3b
+       27e4c00de764619ff0956cdc0599bb20e92d2e39e2f6a5461311b357ba5acdfc;
+  00000000000000000000000040000000000000000000000000000000
+       1b9c442bfd36d7b57e185468b3fceb4b928718b24e8fe9618648119df1d75345
+       7d89665bc3883b2d57e3eb097f3f66289e08c21ecc3d641dc2ee301be9a0b7a1;
+  00000000000000000000000080000000000000000000000000000000
+       e52301462399a0fc87356c8d3015aef445c71699a0016598756a1a89ba3f717b
+       884a598ffbbb2a2ffc52fdcc89b46ea399ac6f46e73bafc7a851a6fbab090165;
+  00000000000000000000000000010000000000000000000000000000
+       02429ab56ca22bccd71cc987d3d38b99bc6144e2c70e2bbd1158a9c8020c17da
+       9a2f84e0a9669cb81d36359adef338a98a82da479028e3dd8485adbd89d05bb0;
+  00000000000000000000000000020000000000000000000000000000
+       124eda8fdf5c7db30c8223cecc62cc5cd66c26cd29b4d0ea304f277c77fbb6ee
+       442969316b10b8bfb2a65611b09a098910deb26468ac2fa906087f4c85e634c7;
+  00000000000000000000000000040000000000000000000000000000
+       52d01eb026e4dcea52de1a1f1435fc008d246693f38ef05f1957dee04b1e7a8e
+       3153ae837aab345e33a38cb4d4e7277dbec1fc15fba9a5d9124dde3d4681ca8b;
+  00000000000000000000000000080000000000000000000000000000
+       5e15dfa8d87cde6e726bec2aab6d7c23d059af8ea25fbdfe349f9ee20d1fa3b6
+       ce57c0f4eda33d4a4f89336649d50334ee4cbba06c2e3e61ab7a9406507b5a74;
+  00000000000000000000000000100000000000000000000000000000
+       dc9fa20173488d514672039328f6d51b58f8e08468543cdc74840178ecfda865
+       7faa9670311e55c500d83c0dad131081666d5e3efae876d5d4aceebb108caea2;
+  00000000000000000000000000200000000000000000000000000000
+       18f4ceb5efe6105f7557cfad6a335da2a84939887aa9ea69bd72aefe2c2e5d94
+       782f9a52b35d7966ab285611567cc7ab48fea542533da985dbc14945c4fcdd72;
+  00000000000000000000000000400000000000000000000000000000
+       770c3b2300ffdfad2c87e1b06245d4dae9c0bf98c8a0ed071c94356e24b35cb4
+       cecf717190bdd7b0e9bded5bf59751254f10563f16e4d4e8439e69bc7a269aab;
+  00000000000000000000000000800000000000000000000000000000
+       54c6058fe589f2fdee3379bfba956f77f6d752501e76ebc124d65ef45bb407a1
+       e269e946d75ef8fcdd9ced031c21f7d14a4640b7fbf34d45236c2cef1e6e5df9;
+  00000000000000000000000000000100000000000000000000000000
+       22628fc8d9ccc487132ce5b75fc6e16d729412de93b644c9152d216587f57eff
+       1b4c46083ed8c87b31820641c90a5891f82397582d827dc7e53ed4690f12f8df;
+  00000000000000000000000000000200000000000000000000000000
+       4c4c2b14336eeffe279cbbf23bcdff9f77e73e7e2b01f27ecceca8adc189b3cf
+       9368b0e82b3bac88ae4d521a8a834f53ef6040f120c4e40513a5cf3f7f13b930;
+  00000000000000000000000000000400000000000000000000000000
+       30d18017f87290383852b0ecd0a8b284c85a590073c4aabceb860b6b59edfab1
+       fe477785fb346cc1f00550f7ae473f0d6c7406ecd2b85774ec9d70057bb30ada;
+  00000000000000000000000000000800000000000000000000000000
+       30897b2e3c37ad2ad3d990e71a5a5d87fb696e43430200b63840b6a90ff6f687
+       6564eadc218e0753d51b472c3b8a16f6ace1f08ca436fc43d4ab566423063056;
+  00000000000000000000000000001000000000000000000000000000
+       6b86652d2308db067793d8efbabc60c248487a662844d65731c9f352a0b11082
+       cbd3b17629ec688bf2404446edc156cf2dae31b7d9e251212fa6e720a16caf0d;
+  00000000000000000000000000002000000000000000000000000000
+       902742d8e4b5a14e5b2f6444cd5770169d82b4a084a754b334cd25cea9c4ed81
+       b80ad89010cc9ce05d6d7976205c975e1a6c5dc5134d2a67dd0c984591ad8615;
+  00000000000000000000000000004000000000000000000000000000
+       7c820a4af9bc911ba3f5848386da8219e0b46d39ce42dec61cde449f348159aa
+       dee9870c0c8fed693fa8354d3bac82102bbd56eab88b8127e4cd706be81c70b7;
+  00000000000000000000000000008000000000000000000000000000
+       6eae2da5a59fc6b3f482c8807fc30add517914fce8b45d346e19b03680f7a08c
+       3d8170b8496ae73d6be7e048e61c9a21072ef2023e2b76a744f2012c3a7cc3bd;
+  00000000000000000000000000000001000000000000000000000000
+       dc5e94f0a7bce3155d87e4e5a274a4bdd20b6268a78265ab00d8f0aba23b9a31
+       ba700f0a95807925d6e72db3eada829f80050470b8f13db0a7f9528eae284e06;
+  00000000000000000000000000000002000000000000000000000000
+       409bca4c7a1cc9d627010605c790802a9e91e08d6c7febaf6ff507c441b83c3f
+       df58babb7a632afc991ef13c3ff7f647ed1e073c027225ed5e713235328ad697;
+  00000000000000000000000000000004000000000000000000000000
+       7c0429fd417a0023263089551cc9a497c6aa70aaa7f7dd1f07d3b760524a41b7
+       dc5b1bf2dc4280dc044c094d4eeab87c9c54b8d1977fabfa3376c0f07ce2042c;
+  00000000000000000000000000000008000000000000000000000000
+       a287c270e99030621f52acf1588bb8e0aac7dc1859c49e331aad589ea94426c1
+       0d9779c3cb59c8589c6a336c9c459ce19d3db33697815b3a459996d24e950701;
+  00000000000000000000000000000010000000000000000000000000
+       06923622b8250acedbdff5cad2f88a8327d7e07ceff7a40520eef9ba4ca7c7a7
+       d4738c1a3aa671759b15fe887963eee5782fb1eda3421ee372a5217315e832e9;
+  00000000000000000000000000000020000000000000000000000000
+       52660b96d56a3032a48e3c1ccca1ce1fafffd43b05d96e8ecda1123898cca637
+       c5d66379ce7c299d4a1958bfde3b035d7e07af1bd640511fb12637ba7a28ed8c;
+  00000000000000000000000000000040000000000000000000000000
+       b7bc824845abe7aded1676ebeb1b5db28f7eda76830da2348c873d1d1bda24e8
+       a3c9daf34c78459933f3d113eca779b8f0e412a140c04430d8c0369697c4f762;
+  00000000000000000000000000000080000000000000000000000000
+       b9b434ddbd0d969547f4e575819e2012d3429bc172cccad53ffafe9fae9eff87
+       38ebcfba6197d3dabc8dcc1bc22ceefafcd9734f2b0c2f91728480e35bc43d92;
+  00000000000000000000000000000000010000000000000000000000
+       2058aadc3e731b05017d412a720696d297ce2975efc4bd202011d3aa43d12ed0
+       3ca5d92cca0b200af76f87b19ca01c328e44b4ce171d8444a42ea529c4586bfd;
+  00000000000000000000000000000000020000000000000000000000
+       d351e7ecdd3aa6c0826526115dee7a6064988947a22728073ad5d85c77bbc934
+       62fc94852584bee32bd1977fbf330e782385bad2fff9acfd2e62183a5b07d52c;
+  00000000000000000000000000000000040000000000000000000000
+       4af5b6af3be9dc3516f7d0785c3211b8c86486b6d171d8653a603903bd592cba
+       1815168c3e0c51a6c52848fa4c0c2459b1149854dfe234ea15e9c67be9fb9766;
+  00000000000000000000000000000000080000000000000000000000
+       d19f4e25914afa257fe634f5b88909444c4670540dd0775b67eba234441a78cf
+       ff79f959dd28be8a30311b64a9a47f9836966f0effcf80f003144a562ede9dc7;
+  00000000000000000000000000000000100000000000000000000000
+       4664cd40879d3e2cf76b67e617ad300b071758be8dcdf76b2d2c3ef3f4538c53
+       c4cb7520809efae915b15fdf7d45ff8df6c506e522d72dbaf576e6c724135df5;
+  00000000000000000000000000000000200000000000000000000000
+       69fc75db35df38c50e9400caa21e4255adefd3932f01830f79bbe438c5c341f3
+       4e67c1fcb607d92f3107b3f7a84e02c7c2424b59a7beed3e4ad07435fca755b1;
+  00000000000000000000000000000000400000000000000000000000
+       a6db7bc42c9a02150177bcdcbff996d4e63639367de8a3459d5a422c0a391a60
+       390e3998a3a6b2e5a99719ca25e065ed20162053efd9e64574a679b0b5d9d66a;
+  00000000000000000000000000000000800000000000000000000000
+       409ec85f059ce5969f275f36bcec4b7d623a4e2dd6ac4f68abd8d5d7a0a422e7
+       5ad305c93905815c67ed4c67208c50350e71c48ef9c4b4d2fe846dcac41a6cf7;
+  00000000000000000000000000000000000100000000000000000000
+       59a81ede728ccae99bedba5ee8d3ac4499579316ae5f7109e2656c558a7a0733
+       2307ba4eba7da1e4a566e99eeebdecff041fed0f1549c595b14230fca2a1164b;
+  00000000000000000000000000000000000200000000000000000000
+       0c6b0f0151ae8ee876698da2eac5eac9ba1227e13e98336a93fe3793274a43d4
+       f3baa2841495261d6b156a5886578662bcbcd13fd68ac542cd03f4331273f847;
+  00000000000000000000000000000000000400000000000000000000
+       f510f5e9b370b1b34a4cde599cef0b80c4f657688239f3de82a12376140fd934
+       7ee1e4a96f8b73817a2b57e3e4d0982cb92e05ebb06348681d097d7f55cf12cd;
+  00000000000000000000000000000000000800000000000000000000
+       d7b38ec40b465126d428dad054a190a25bde83fe1f2ae87db9dc3adcc0bb660f
+       04d42fb3907165cd7c1d75da7087da71ba524cbfee56fed771f16dc3e8e176b7;
+  00000000000000000000000000000000001000000000000000000000
+       414f693e93a088ab8bb5cf5049d6f3ac67e654e786fce08559dfcd96dc6a3b23
+       ccc0fdf2941815dd9c050fd1c9d1e9414492912cdee277465583384a15d761d9;
+  00000000000000000000000000000000002000000000000000000000
+       00a7a468282dd455b469ed76c0d67e0f507a53bbc7fd1941e8bd600bea43b982
+       4c8795a55684958d392aea1409dd01020912380b5c81bc868629ccf393594930;
+  00000000000000000000000000000000004000000000000000000000
+       d1bff2f245ce0690ba74588794d7306c934ec83dd8d7811493726c95822a899c
+       856c5179cdae63a65f1b107e0859a1ac790b014746a7bc7bb4385bfc9fff1630;
+  00000000000000000000000000000000008000000000000000000000
+       d873980acedd7383fdb371beabef1cd1fbb5dadd665f2f118262ad539a118153
+       59a325d64f1e454646459c72f81b797d534a6f8f0ccccc38a8ff47298f1dcb9e;
+  00000000000000000000000000000000000001000000000000000000
+       d8c4dd99bfdc3bc0d25516a7980651bb545077500e01e3b543cd72ca97844486
+       f0334ce2c74691e3aa5fbc12a25d5d6a14fef43bd4df05a2f3f2c9b34d4f2c44;
+  00000000000000000000000000000000000002000000000000000000
+       f6959bea04ef9ce9e73c363959e28ab6404e8dbca900dd2284f2b848a109f768
+       81f4bfd5b8b0df8b32299d101d339ef40f9655962916b5219145ae074338bf40;
+  00000000000000000000000000000000000004000000000000000000
+       411c1c715da711eaba6972e77e408d6f5a76371d10dc7a165f2150c89154db7a
+       3d1b85da27fd34e9ffacf8703b958073366ed819459b1a153db135e4a5835ed0;
+  00000000000000000000000000000000000008000000000000000000
+       c57d8cec898496dfa1331457c00b2d1962c1df9788d36f155ab8b94e985aff15
+       92e1ca0643703a1bfc56842a4d6f87d2acf0ae3dc58935fcba5d847aab6bf920;
+  00000000000000000000000000000000000010000000000000000000
+       c16ad6e1a87c475ddc84d7664f11932debeed6d987cd05e9c6fc493b0a68e261
+       3c984416b43aa267eb6e0c6a68f8a41ee2a34e14d93839ec47d2b256289b4827;
+  00000000000000000000000000000000000020000000000000000000
+       cc414cc5970efd4418917369edcffce4be969ef4fd721b376e85f9eb1ea7d483
+       fffe4d5022ba7bf9feb0d5e8c8a87df1a49dc2353edf5a2b9cb66863cfd64661;
+  00000000000000000000000000000000000040000000000000000000
+       b2c9d7c5d8ff0bb054ab8f440915839840e7c9489ac78045fd1b49e0581809cf
+       6b0de74a81dbc155fb23b033b45f6b3eb6256fca7fbffb4fcf0ddfadc177659d;
+  00000000000000000000000000000000000080000000000000000000
+       d68ceb6c0de43d2a62284fc86b872f6686ed0ee6710539cc295fa290d46f3d17
+       3f70e4f08444b9bb7d03552aa0272fcdf3f30803e2608cb299c2880e63f7e24a;
+  00000000000000000000000000000000000000010000000000000000
+       c6dfe5c3e64ec36a7c043ffe4b119f4cb7e40acf0d1b61fd12bde9f8253f6387
+       abd8bc56bc0d4c5d136fcb6af803493efc80f0f0d00fe47ec4dd70d455ab04bf;
+  00000000000000000000000000000000000000020000000000000000
+       c75facc882297be6c90d4d00bc8acc443c112d7f58a20f819a987fdb01ee14df
+       2aedc8d591536166b58e3bb5fca7e63b348357762912aa6a83458186ef315c34;
+  00000000000000000000000000000000000000040000000000000000
+       43113d85e6094d67cd03a9111397b014557a6850a8d796e16736cfc40fe0621e
+       89730f25612fa04d00a1cc4732efeebba1b80c993238786386cfce09bf10359d;
+  00000000000000000000000000000000000000080000000000000000
+       60794b89b36592975d54a0448e7708e6017d4027fa3891b0335cad062ffe8db4
+       0d3401a2c417efe1859b4b165e676a7a5ac031a89094a0173bf46529e0078adb;
+  00000000000000000000000000000000000000100000000000000000
+       6bdfe911c6703becfeb5c205f11d2aecc6a81dc22c365b48c1929a81dc67f32c
+       61c6c80e40ab88b27bfbbf703522570fd971e8af2b460ea72ec59a92b3701558;
+  00000000000000000000000000000000000000200000000000000000
+       24dbbd8de57a959b62a1668e29ebc7514c71ade4fd64c40b482bc98057d77b34
+       671e53090529d3258abd0349e9ec5ecbd0506d211d6228f4e2babcc68699e5ed;
+  00000000000000000000000000000000000000400000000000000000
+       cf4174ad172064185cb5c1774f08f4e47767579f5ccf71a87e622605041ee5e7
+       8617dee6d4146da406e826d90003fd4f3a77a566d21b8e45649aac687450da4e;
+  00000000000000000000000000000000000000800000000000000000
+       016f5989221bbcab0a3cc90a99f6e1f21c9cce56249855bea90eb6b0e3ff925b
+       cf450821f51f1c80221821fd04d9676d3a81f9c003b692a33d21f21d7054e6c0;
+  00000000000000000000000000000000000000000100000000000000
+       00d2fdd6d13ecbde57f8346b651c3d21fac7c08c0d5624d27b77f70583a58c21
+       89de016c263121254e78dbc2df605a71de36313d855994e9ebdc45556e721749;
+  00000000000000000000000000000000000000000200000000000000
+       c5d03f396dc1b171f23ed0a25571c3f3bd773bb887aac4ba4320afa817e9b460
+       c223bee85f757c23c67c009f1b0912d4370315f91cdcbde866c35ed0e205a848;
+  00000000000000000000000000000000000000000400000000000000
+       701df4f85e7de8ab8887806541c49911f6c0f3038751d9c109216059df06cacd
+       a5e35984cfce2a1000a593cfb80f79e6e8c38d5791bb7e96344bfd3dfbea88b9;
+  00000000000000000000000000000000000000000800000000000000
+       b58876deb62a3c880f51acb743ad9eaa2119321e096d591b06f3dbca6ef924d1
+       829c940bfc3409ec73391740d7652466113ba5a5b03118376c726351747b8b34;
+  00000000000000000000000000000000000000001000000000000000
+       b6bdcc6d4af946d02f2ce1f8c04df35f1c1790a663ca40bcb57697d780365439
+       99624b3c7338e8f23faf22b4a89deee5fa8bf7022903db3fa36c6f9957a819a1;
+  00000000000000000000000000000000000000002000000000000000
+       79d9fcfd5ddb19aa8a8eb84496eed8fc1d815f7fbfef3162273fb108bf230da5
+       9534a0ae4ba8babe4308789f732f6197c6867d222ccbc2eaa064d598a4c24ee8;
+  00000000000000000000000000000000000000004000000000000000
+       c6c6b524090066e3b3cf196fba642cb3f8c5aa63e734b47d45279e7debcbcb4c
+       ff20409e1bd929705cfc445c37924f4b2b9151b08839c53b464eb68a807f977b;
+  00000000000000000000000000000000000000008000000000000000
+       4c14e7b11e9c079bdaf893fc1e6dfbc38f205e04373760e06afb6c5fefcfdaf4
+       a01f116e3bef972205aabe1494f76b70f1c6372b74f79f4a23904c58b1b51fb3;
+  00000000000000000000000000000000000000000001000000000000
+       2ab3bb7f3211b75c80b01b15ded624e8046bfcac7c5f88ded7d5e5e030992b95
+       374d7ca16d59e8b6b128b7035caded032134dacc94c88b549e3891282e92cac3;
+  00000000000000000000000000000000000000000002000000000000
+       06bc1a54e4a68178acc810f2f9144d01fe6724ebf72225b67a0b138df10dc6fa
+       27f3b1d7e61cd1c3b73f72e367a9a4f6fa4010c94a2cfe173850d832e45e89d7;
+  00000000000000000000000000000000000000000004000000000000
+       f9c484b67e531856f5134b4ada1a231f6f66e6a1d383fbb1e7fe7a7399a39918
+       f4c1eaaed3e8c5e62c5573b0779afcbd197aefc1cf881392e00659e0749b2256;
+  00000000000000000000000000000000000000000008000000000000
+       8e00b017b4c601c6ab9e606f19e1210ca98b5cf020a2874fbed90f3e9ee0af9b
+       2998fbafa21326c14cc0eccf3db5bca7daa744a086e58adbd15537576a5129a5;
+  00000000000000000000000000000000000000000010000000000000
+       7fd2a56e82a8a82c0ab027ccfb68acf4b894bcaf0c03ceab68ad3f198d9336e1
+       0ea3d8f711178f80f559bc8f4402dfbe51c6dae84e3fba861050513c4b63f8d6;
+  00000000000000000000000000000000000000000020000000000000
+       12eb27967c9c4c286496836bff364450b767e969aa8b53f7dcc1101cdc535eb8
+       b30dc7c5d8e4bfb50f29b1be19fd953c6f6d6250ec2f1b9a1fb4b457d928e98d;
+  00000000000000000000000000000000000000000040000000000000
+       1630f9a365245fb0b5f8684e3b467ac06d34651076feff3f6718a9c37a1b58c6
+       3240790bc28be631963ea289f5a3266f65bbf0f86e169751cf7512e4c12419d1;
+  00000000000000000000000000000000000000000080000000000000
+       8cfd772627622c4ddd26eea011ed6160ede81e488b3c651d4526a34449921724
+       5081e4d0a86395debd81de249553a4936a510f15d07c031cad7caa563ebe0668;
+  00000000000000000000000000000000000000000000010000000000
+       2bb3f8ff8c4fe0f4e66073bb662cc09311adf20fb22d6464b4d778250b542537
+       69f83515e69eecadeec5eab86e2f0bbf11ba2bad521a6f21da06ac02331db838;
+  00000000000000000000000000000000000000000000020000000000
+       fc635cbb01ae965a24eb7e27c1f20b45fd2f2722918ecd8eb362bb52216ba279
+       0a97f58b8cecbb100f67b8d4d46ba01a8f68d6b4c7bd06e28ffdedd28e46f076;
+  00000000000000000000000000000000000000000000040000000000
+       b35aea1e5f09265b3b7b6748baaaa97ff46d7118491875464590bceec70b93cc
+       962374c521986b0cd478f4353c06a28a1203da79cb98a198f3523206b22606ed;
+  00000000000000000000000000000000000000000000080000000000
+       89e462fe5d5c5325c5ee9252c73530692c6c29a1a3c7f389f83d533ca1b1a83e
+       dfd663c857be90d098b8170eaeeb7ed8a6948c8a314a74599691335a8a18c2b8;
+  00000000000000000000000000000000000000000000100000000000
+       47d9c74cf8b7148a6427408e3aeb790b355bf02b447bc57c6f8c05b7c51ee8be
+       28e4223e24ad191369fffebf62c84059c519f49018427b41bb8b67ee9c820222;
+  00000000000000000000000000000000000000000000200000000000
+       ff3ce376a28ece62a73a9c00a6ffc69767e836a8a17b49b824a4ad20c0ff0a21
+       630c092e5521f6041ede8c61e73678198e19fb339a04daf94f9f923854f3d7ef;
+  00000000000000000000000000000000000000000000400000000000
+       fadd0fbf5f7d4eca5fc145d4aa79f7f529950335b9d45d592f3eab084c4e883d
+       0f9c8706d1385a2f0ad3a0407460f86def321d3ec5072694ee0272740a12427a;
+  00000000000000000000000000000000000000000000800000000000
+       cd6248d7199c68291a4d828f24d534f6fa28e4b8706974f439e28625cf8e2310
+       b9cde77e2e12ea77ef2ee43e153a26bf09071198249550603c63c7709ec6d090;
+  00000000000000000000000000000000000000000000000100000000
+       bdc4b06d8fc5e5d3b3285ab19e1210271170c1ca306b61c888230f1d1a6b4c11
+       2e393090c2212bc3e2ae80d367d4a0821dbc121a0b4b7efb989f980918fc3412;
+  00000000000000000000000000000000000000000000000200000000
+       2e0b37d02fafd0b335c0e3da36d1b67ad4ff988f2dccf9dfa5722247133f71f7
+       52e68f282e5c041eb7c8d8bef21ef3c7ac045101b3f32211507f781f0f347815;
+  00000000000000000000000000000000000000000000000400000000
+       327e75a7c2c7df51c76632e55ce0f3e54ca2cce1ca5bf9bc4dab9bb4c68713de
+       49bb9922ddff6cd9b917a2697b399c7f0cd803a0f9ef25bbd06cad0c8a97d2e4;
+  00000000000000000000000000000000000000000000000800000000
+       d95ad5b34ade4fd38e6c02bce505bef6454349dfe71aaaeeea53daf6944c76ef
+       5774340daa33bf6056a6f415c82df4e48da319997b38664fc2a9dc0acbe03212;
+  00000000000000000000000000000000000000000000001000000000
+       a52178fc875cd004eed999610933fe8db73387b935d06ea14abdaffd7d870452
+       a1a6144b8ab070d6a8cde942e6443e72bee40937eb89c3760c94f5fa74c1a6b4;
+  00000000000000000000000000000000000000000000002000000000
+       588d9c2260a9ecfa95da0f3ae80ed811fdadc55a6b19ca178d705ddb4f7827fd
+       e21dd6f24a2344b05df56af868b16c9566c3e93562894bcd82a945ba514c5a87;
+  00000000000000000000000000000000000000000000004000000000
+       d15499d0351be2608940d7460b38cefdf5ee7503fce68579fe3a186bae4e5998
+       95d149362856e80e436470d08205d79591520d67694178863d929c1283d5a541;
+  00000000000000000000000000000000000000000000008000000000
+       0bb9403874309bdac289a847e6be5642e67f71443097d7c1cc9e0787b6c4252e
+       600cacd782749f2f91a3a26a67ebe9d31593fd520a8046f5a60cface42853a89;
+  00000000000000000000000000000000000000000000000001000000
+       9b9613f244651fd3dbfebbb6dc96b52b1a771aae0b6f4bfb7d71342a0462b013
+       44d70fcdc3c9308e2e6229b2214bf6fa9ac83fa7d3dc0b7a29f2c5f3ec090b1f;
+  00000000000000000000000000000000000000000000000002000000
+       259d92266dc21f7d30e7070a48a58a0a739ef71aa4e0c1bf919df19bba0c6e35
+       aebd1c82b24831566492dd4b424b824fe95a52c44aa1cca0b5542e1090cc1fa9;
+  00000000000000000000000000000000000000000000000004000000
+       27be0b934efa113d8c8101dd8d56c4076398c8d6e7977f347e23749b5a73f313
+       ba77447b42e23157c2ee9b4c0037f4c9ea37a9a22e9abe2a23f94d3bddafba82;
+  00000000000000000000000000000000000000000000000008000000
+       f5430f15301470f840f91e7b75ea4cc7395b43f1edfe9bab362e8939969484a0
+       ba43279cb5c71882e6c3ea7a43e456e6e5c8fd15310e38f1a8537f52993e1b5b;
+  00000000000000000000000000000000000000000000000010000000
+       d3fe3b4294f674572da05aa1617fecde382a03e2a429a7f5257c8aa906057091
+       7a033fd229116872c2c1a18b74fc37213c903e59ccbf0d382a946fc4204967d9;
+  00000000000000000000000000000000000000000000000020000000
+       68645bb3921c1c55b0ee6e262e71b654cb8236f1844dc8b83eb012659a1db873
+       c8375d6b2755a13d69f6d2027211bc5a331d0bddf05ad8a79244eafd075e07a2;
+  00000000000000000000000000000000000000000000000040000000
+       ea6fa9dce63e87a3aec87ca45455b89ebd39631a914824edce01560edd20f6df
+       1b37c1283b94e96ce366845d3b9bdbb067a489c33c00345e310a2c9086c987c2;
+  00000000000000000000000000000000000000000000000080000000
+       b4398d7d35ac622252854e8e113cba5a8946ce716e3858105e4261cefdff24dd
+       2d6c9392643deb1174875897917c864d9e75e9eb22dc83f754cba0605f800265;
+  00000000000000000000000000000000000000000000000000010000
+       57ec1c68ee07d85bc8ed73c0ee1c0b3d7b17ee95094a1b027d00e3359bdc68cc
+       76693250618daf58a86d6b7dcea6f4cde1663615cc771996f2bab17cee73c4cd;
+  00000000000000000000000000000000000000000000000000020000
+       1939a6b965e7e13d46f888ceb7f41bff97a46a6ace11d3786097761e47c0d4ee
+       4783bd9c5b469d4a03fde86a90fab3dd73d009004d333771155889bc19fed805;
+  00000000000000000000000000000000000000000000000000040000
+       887c0455fa369ad1a63a89fe53f5c1f1f873e36673a554c19d3251ca1f401781
+       90697bd7073e82b723503b0fb86c3106d6d4d39036e9e8741b9d76f79dca96c9;
+  00000000000000000000000000000000000000000000000000080000
+       09ed519fdf745461e1fb8e10471c54d52f3455fb7aa6db264b2757b02829ed41
+       e36c4cfbbc607b301a28f6c0f96774722d7dfbfedde89e97674438ed31fc424c;
+  00000000000000000000000000000000000000000000000000100000
+       61b58f25174e379b185ce40c08717b11460e6839c1dc0d0a7430a9f367960376
+       eb6bcedc9b1a70fbb749f9535f59d60dde1a6a3de6cf21d083bb43b696d0d455;
+  00000000000000000000000000000000000000000000000000200000
+       98e164ed01ec6f3a53ec5eb1d7930aa8f7689ef6d3b3f5359618d53a6f291180
+       539a4febceefe3e49cc2dd3100b1873ec5a6b03c04544bd9930e213bcf79c5f4;
+  00000000000000000000000000000000000000000000000000400000
+       e9956f811053405dffb566909338e93bec1c4ba2a02cc5c6bba8def3570ddf29
+       8aea5d2e8e322dbc2454e236228a6661c2e49bec36749e784398b8afde823e69;
+  00000000000000000000000000000000000000000000000000800000
+       423e3d2da9cf293c881cbabc625ebc58eb58f68cbfdf74eca77d0c85def81286
+       138283360cc8db7f3cb1845cc2d7e3dd55698564c62ff10cefacbc7e754bda0d;
+  00000000000000000000000000000000000000000000000000000100
+       459fb60e8f40da7efdd66d01a15959a3ceecda42ae8bae622510e92bd4374c43
+       058ffc8eb9c8c74755f80ff096b1ddd1f9ec9746fdd63f81fe94f5aaff3a4455;
+  00000000000000000000000000000000000000000000000000000200
+       d56a4841787cdb240d452797278e2065d92d94284b60ac78bb0d90775dbc9172
+       6414921eac73dba768b88d3753b4b61bee16ea189676d58c85f758cd4a04891f;
+  00000000000000000000000000000000000000000000000000000400
+       ea53b043630e6f958784f0f7dc6354418901f654c4b06ff40ab6c4909f917ff3
+       50eba9af77a57a86c497ac90e535e47645a967e5a678735e9db13175da4eaddd;
+  00000000000000000000000000000000000000000000000000000800
+       d7f30fa8111469c48de76fe0d1148ff48675cdfddca0ac977330d094ff796b81
+       eaa3b53439f65b9d8b47a24ac6ff75a66e93aab097670ccf484197c868a0216f;
+  00000000000000000000000000000000000000000000000000001000
+       aef29399dee534bd8ff17b1b2057787a151255bd76bfce66f6344194009935fd
+       7489520edaff91fca342b7a90edfe649756e561662f41db5b12fbecf99219897;
+  00000000000000000000000000000000000000000000000000002000
+       ff1026c8390f4688f025b03a0758bf56c2ae84c580ade19c22332eb5dabb2d65
+       44c179aa7070f032236520142146813b55a0a9a58209d3e869b8969e66935073;
+  00000000000000000000000000000000000000000000000000004000
+       43a11b9a09783a0d7d079eecff5933c84b52f96efe0e38a21cb97b6410663128
+       2216c885bc941c655dd6d0ba0b32944c2e501823cf9b5322b51827445b74ff7d;
+  00000000000000000000000000000000000000000000000000008000
+       b8af4aa7c1fe35b031ee050dbd2d247091f173179686ef8d0659446d643f2e14
+       73044c40077491735fc44b1471a94c5585d0b267971270e18a54b67954e52a80;
+  00000000000000000000000000000000000000000000000000000001
+       896855032d11655c16bd94f994b8f47e2f82be1c0b3a296bfcb18e0a1e9b4edc
+       75ce1a2f4d77d032b86cd65dbfd97936e82d76f16f87247e1a9fd39b95307577;
+  00000000000000000000000000000000000000000000000000000002
+       0082359d931ab3fc8791ea89c01e74d7a6ad0e40c7a0fc369055c28f8714c679
+       648955a8ddf7ac11dff9967156faa35f1e5bb74eb92e395099575b87799ff709;
+  00000000000000000000000000000000000000000000000000000004
+       7bbd0fa76452768bdd69cd448b13b28f1ffd689df6e4f4c0c0201924078a702c
+       3e9efedff4cf93e8bd34c4a1a8f06916410fa99d326a4ba831aec1c1d9c7d60f;
+  00000000000000000000000000000000000000000000000000000008
+       5cf1e70d83b64b87b5b4533a0d0974a871fce3d68b085587e4434d1789c5a036
+       2cb01ab75e4ac0d2d248b1e2fe2c3a43cbb99a90ca7485357eff8f4bcf001ea6;
+  00000000000000000000000000000000000000000000000000000010
+       15ad3287e48777b536309c26f3d4cd928f9f11c2d88eed60e4ee42151a78ad6b
+       135d93ca9bd490f23afd619476cb934e42f7b383cde0c5db99503b3fe325b34b;
+  00000000000000000000000000000000000000000000000000000020
+       7206c6beb79aafd394150835d6f2bccf7d7454b6c5b80afe0c8afc311430226f
+       95373efb0b18c40fd7a2c98bf86805c0b8e6d964e12e025df90f1f63e631abb8;
+  00000000000000000000000000000000000000000000000000000040
+       34adfd7c6b2ba94580eea815dc441161d91e427412f54c42df398360f43074b7
+       635bd00a91fe3410088ee2dafce819f26a2f44e194fc39732cb56ac470536592;
+  00000000000000000000000000000000000000000000000000000080
+       bd56867e5c02612bd20abce0a51c8c0a9a5c3ebe27af33b743d22f1862bc9b40
+       393bc6a1c9cef4829b5586e99952006b7e4af3056df28511fee2902eb5d30940;
+  0100000000000000000000000000000000000000000000000000000000000000
+       e15988e471d6475f8094d5704775b2ea578ada4ccd7fb6bdda530b250688c0a7
+       9b4c62614948194ec5e0d4672100f4cf032166ee1bad7d12ac3c3c292992bb01;
+  0200000000000000000000000000000000000000000000000000000000000000
+       384fca7c5554145250796aba74422059a6152117b9bbf50b492d8dcc4fcd9fa9
+       dc2c3521c82fa8613489e815af3bf6bff23a61a31e136870e7b88df6d2c9ef50;
+  0400000000000000000000000000000000000000000000000000000000000000
+       12390d4e80fbb7ee99c80a68175dcc167177486d618d1baa5009587cd2543496
+       7ca3a28cffaf1d2d71aefcacb467f7176bf23325406236a468f9a2b75ca67eba;
+  0800000000000000000000000000000000000000000000000000000000000000
+       8c43057345f8ee64b5e04daff7d9758b663e27d9249c68401e17650d38418597
+       75c3b729c8e8da036b60b63af24fc564a3a4ac1eb2e92fd59158474f744c5a12;
+  1000000000000000000000000000000000000000000000000000000000000000
+       2b7e0219d0d2dfff42597690df40e53c8bae17d0d363eb001636f91658fd4d78
+       ed444d40e243dce63b77c45a4eb89fc5a0af2bab390e32903c7ed80ebe3fd989;
+  2000000000000000000000000000000000000000000000000000000000000000
+       c0af2ffcdb963b3f836f09d07dd7529ca029baf32d683a030d8b70f64115319e
+       81adeaea6574660ebf126d45700aa212d7df72cfb15ac7320544f901c87b364a;
+  4000000000000000000000000000000000000000000000000000000000000000
+       bdab381ffe13374b4c0fb2befb836b2a5676f551d9879230574063a7da33f55e
+       b73c6979db28f0090352ead9194481458c53a75716e82eec0d392f80cd7f414d;
+  8000000000000000000000000000000000000000000000000000000000000000
+       059590c11ad59af788160a3dd52ba242f35e9d7c9ac2716732d45892fb7e311e
+       1cf8b9d052386a37bad7006fcf1a5ed0b2ca509fa9b408d164928465b7df55ec;
+  0001000000000000000000000000000000000000000000000000000000000000
+       2f59734e38211765d309b8885c0d7f12802adcfd236259e710b60f215b17e91f
+       b7543107d7a8d59fc58ccb5bf9cc9cd3b0aab40b936519018321e67ee4212f3b;
+  0002000000000000000000000000000000000000000000000000000000000000
+       b459777f2e4be5802ec40b675b180cb7362d58849b5a1002e9006d684803d1a1
+       263e0b651894b849ebcdda7de136f12c2b417864d0bab6d752676645aa44663c;
+  0004000000000000000000000000000000000000000000000000000000000000
+       dded78e34b5117415696866ab8277777298ba600ef8ebb0a833ada9f0fb14abb
+       048cfb659677a1f6021da5cbbe7c045a6630d62c12354ba889f16dfae298f0cc;
+  0008000000000000000000000000000000000000000000000000000000000000
+       23f9f9b2c9a37dbb2c46156eb1e369247bc9e3ab18b392d900933fdb2319dcb4
+       b9116aea9a465f603f0d0b5f2b432bbe2eb8b5b7150cd41c88df744d1d157458;
+  0010000000000000000000000000000000000000000000000000000000000000
+       00d9408d7012e74b3587b5549ee41a45150149b07a71b11b5a6787d0180405c1
+       efb7ea812e9772898305defb02e62520cb5518f11bc7d1cb72aecb2a230786e8;
+  0020000000000000000000000000000000000000000000000000000000000000
+       0e1acef35626a60c99bb971a72fbdb80d40adb9e1566e522f03d0d9781abb92b
+       39e66a48d565bc75e2e307de3555f1bb2161fab013186e827ef720b5e67af7e6;
+  0040000000000000000000000000000000000000000000000000000000000000
+       147cade7c9326104bf45afe6b8c180cd7a8a45ed9e1798846af473f241424325
+       c8b47d8c7fc71f2650dc9fcd2e76656486f7f2cf79d4fc3e5b0397bf19a268f0;
+  0080000000000000000000000000000000000000000000000000000000000000
+       e435935752dcf49c03afe77b217af4fe8bfe3b83be1f237e80b1c5396aa60635
+       ad3294a5729d4b56f5cbe417867b2895150207493091ca5b2da71661a837ea45;
+  0000010000000000000000000000000000000000000000000000000000000000
+       2b0962a7233ae8f0f0c6f82d96f1fb6788b57cea3e20b18d21c01fb20c523e45
+       e282636fae01bffda7e59095c3b46c85ee2df7e2f3f4eb5e9c423459dd085ae4;
+  0000020000000000000000000000000000000000000000000000000000000000
+       150ec1d69180c1f65fd412fabc62eeb80146a46fd5fd7a7035c887da5d712812
+       95aefd097ac6ca69d1dc282ae7ccda8409ef4ec0a4e8d7e052a52313c3d5fea2;
+  0000040000000000000000000000000000000000000000000000000000000000
+       f21b883c84743f00ae25aa937c88eeff2820c8b7ec16f485d811fd58f5758710
+       5ceab4fbe84572e441c6d31bab9c213a29aeda39b5369cd5a036f0d5d3052ed4;
+  0000080000000000000000000000000000000000000000000000000000000000
+       e3790ad0decf178ff259a5c7340f944c253551a0e2a0efeacfafe6cb49774d8a
+       93ce491989013119060c84df54e1ccf3627ce8149ff44100c08b903ec868dc29;
+  0000100000000000000000000000000000000000000000000000000000000000
+       3eecc58989f78b6969f687ee0aa2c1230af4bb0efd5e26008e798b802996b458
+       55fb0121a5c2f72d1c830f431ae990c24071ddd60fe7ed997d92f433aa53e66c;
+  0000200000000000000000000000000000000000000000000000000000000000
+       ccef63e7caef39a6ade4da89f2fa47f4132fd354b4d594dffcd40db73171b787
+       baf36d6cd4920d94301b649592ba1e990742357ea55191c40538a761fde817a2;
+  0000400000000000000000000000000000000000000000000000000000000000
+       d39bc7cd53aeafe63933d8bb7130a1d2fc85bf58bf76cda3683349a5257e5feb
+       4e8a84d2bc89a1b2ffd5fe2e8ad3c5315bbaa5be3e9688291fdea97b19ec425d;
+  0000800000000000000000000000000000000000000000000000000000000000
+       a3d929cdd10fa4b13adc1df77dcaaf9348cd8993305d3ade70ccec50d2747d88
+       ae241bb3dad4d6400c3d3ecf5587ff814f71708d9d85003b461ed4f714bc2830;
+  0000000100000000000000000000000000000000000000000000000000000000
+       641578d6f15bb8f26e1a4e96b798f7f7e1dd592ffcd472f4af3bb90292835e38
+       8b66ed19f74864e216e4c1962326876c3d015c84f368992a51a3a7c66809c8d5;
+  0000000200000000000000000000000000000000000000000000000000000000
+       81f3b791c83a0dc0da90a8e5b1460033240aafc65663b5ef8ae4b0988acc3070
+       4ba6a9d06282dd9854b5e75e3989a550a37c1a00c12199ea5c859f47408186b6;
+  0000000400000000000000000000000000000000000000000000000000000000
+       59359a60897c5d84c7c3a2cfc44408a9a07f3020d2b7c5f1eaf41fd08aa482c1
+       836e0c9e8c3a7974cc99bd938a7c9c596d21d1fc7e8674321b1faebb9aafe0e6;
+  0000000800000000000000000000000000000000000000000000000000000000
+       fd2541c2421b5a58f8e9c89f9bd93a3f214690c86a30505050809f0e17965ec5
+       52b5f31bec989a9c167fb3bda2d145ed912e656435e4c2720b109c4161ea6499;
+  0000001000000000000000000000000000000000000000000000000000000000
+       a7870f4f9859f4c90747cd5a3175576969893f21f80644a85ca361c64c2760e5
+       c025483295777b1b75c3f4c1311c1621d40ef55a8a74dd0f85afc16c33141731;
+  0000002000000000000000000000000000000000000000000000000000000000
+       e7ae0b42a64b89f72741ff01fa56ed16cb405d7de6af172da31d28b6624394e1
+       a3bbf26da16b92b30f5be3f1b5a4b82ca60fa12330f546f6dbe21692397e6007;
+  0000004000000000000000000000000000000000000000000000000000000000
+       bea4feb7093ed08d59b1a9e367ccd59c81ac315e4fa6bff4dcda083a54ce7713
+       e17743b422ba9726647323c9d863b28f672f0635965bdc5e99fd713a890fa807;
+  0000008000000000000000000000000000000000000000000000000000000000
+       bd7d0e194ab34c866664434679054a512ff4520c382a2c16164e3b92579986ea
+       2b901d39fe9d3ad0f151be728cc8bf052a5cad3fd622da0bce99df60f5d0b900;
+  0000000001000000000000000000000000000000000000000000000000000000
+       26221c4832d8daaa40a4cdf52027ad389342882b578d50690bebc93df5bfae86
+       906cbda011d3f989b85301d147e5f89c16e0d5f5236ee549f463d8e7c1230ab9;
+  0000000002000000000000000000000000000000000000000000000000000000
+       aaf7fd79a7ee0cf2622f61a7dde9ddd110cf585989f9fbcaba4bf8c87f97a6ca
+       9221202cf78d38d22b97d3634615cdd7a1b327d0cf2edaf7ba665e2ddc98ffb9;
+  0000000004000000000000000000000000000000000000000000000000000000
+       ea7e4e250134fd0a6d57d45877fc13e83bd8eae4bd096371ac85d09b634888b3
+       3295b4d323d829813a3c0bc074075c3e133979d02137237ddf6abaa52c3d6633;
+  0000000008000000000000000000000000000000000000000000000000000000
+       3944e76bdaec5b16c8c76c7e06452163f22ce79092bd9e3a024aa5c208eaa795
+       6f8a8a7b2dddfc1018cb4e0b7757f3e1444514c3ea056ce0cae81b8701de92f9;
+  0000000010000000000000000000000000000000000000000000000000000000
+       3b4c4ac914d85958a0b5e7b8876575573681f0b313cfc0fb7f444c9e7e268615
+       312e801156e12476a12b20be7468806e9f28bd00e3c0647ba9220be6167045fa;
+  0000000020000000000000000000000000000000000000000000000000000000
+       91bef844e50dfbc56fd6e2f3b7bdaa1276c316876dc81e1d6403ca7d91dd0e3c
+       e9dc7208167be2abed48d00beb3b9859b9e4eea2b54ae8c8bf78d59f5fdf6bd6;
+  0000000040000000000000000000000000000000000000000000000000000000
+       9e024081abac727a02f619c51ce63bed18745597dce3b48ede6f61f808bf9dc4
+       2c6eebd23f08b4e8a9ba12c04ffe281c6fd241a1bfffd7850bca3e8e9b258c1c;
+  0000000080000000000000000000000000000000000000000000000000000000
+       1659ebf81126d5ab0ebda35420c9be79e92a439b50660ba62dbcaa62ebbb6bce
+       30972cf1c7ff5ca04ad0636279a0a6e4c9fe9a41af9d3d357f286fc68ebb0a6a;
+  0000000000010000000000000000000000000000000000000000000000000000
+       114312df5056368e8facf69d0dafd7f99954ba6188579e70eca4daaf63a4bf8d
+       6ed87684e24e9e8c80e7a974280a4a7210b2fb50578cff2e87f3c4f86eec23b6;
+  0000000000020000000000000000000000000000000000000000000000000000
+       bb6e664338c2483b6619919cff1cbd4a133e9bd461184b040fdbf08711a53c0c
+       5a6a0f2f51d127d55e7659c4cfb59a4e17d329bc299ab38e18e3140c562596dc;
+  0000000000040000000000000000000000000000000000000000000000000000
+       a467e32c18c448d11324ef06f11efe402e7b8a9411ca83e52ae20a82eb5df7a6
+       84c2e9f00dcc6856f70ccc51f498d85679c79240f371937fd4179c5c45b0cf25;
+  0000000000080000000000000000000000000000000000000000000000000000
+       0eac2d63862bf03c7d9acbb84b3ec60624a40941764d1fa716d6e08f5039f114
+       dc89b1858f887d16f98b1f068e27f7d46dbb8a0df469541423d0c811298f00ef;
+  0000000000100000000000000000000000000000000000000000000000000000
+       97537e552910025fade2073196f52788773bbae3ce6c7b1fcc72b55ff7ef3f0b
+       49d9bb818972c65f846c31dd70412de0a193fdeacaf609dd401e929b23914e9a;
+  0000000000200000000000000000000000000000000000000000000000000000
+       9408c086b3246cdd588066e449a9be69377a74c14b1f00994ff2094af3747861
+       74bc32c2914794908ac3ef670a00f9dd28e0037add9eaacfe07da756042b050c;
+  0000000000400000000000000000000000000000000000000000000000000000
+       7ad5a463142244224dd5abd8342df7126e0156d92af07aa012d63b5f1b44fb6e
+       d82d65ada9a01bd4e9b3e79fe2d15a2075c392865b647e357099b3f1d61c92f1;
+  0000000000800000000000000000000000000000000000000000000000000000
+       6d65afe3a94c84045bfe3b6aa7b159c68a64464a71f4b5a25de424d4b8cf7d3b
+       b80da8204dbe46d527b120b4b025c01541f6d51bf962303cc276f8610558aeed;
+  0000000000000100000000000000000000000000000000000000000000000000
+       afaedc6195d899fd7a085f180ffcaa940345956b194d340a2deee29c0dd2d971
+       7b88861666b09d3dd874eee025910267da0de663f3762fba0d5183ac81b59a24;
+  0000000000000200000000000000000000000000000000000000000000000000
+       6ca33fb495f9b49ab2434c86bd50f1c68bf627fb423d5785d9a94557bb789a32
+       dda8002e8a2c6ae938a347121e2e6a191b11a47fe0f2609d8df6504eabadcd4c;
+  0000000000000400000000000000000000000000000000000000000000000000
+       048745f71e427f377631cf8b93d762ed69b23d5ce92cf88bbbd1c39d83c50962
+       9b467d9f35a61cad87273246229d0a666e7d37b4a3c3ee48e89f7316b59f9258;
+  0000000000000800000000000000000000000000000000000000000000000000
+       199409ed0f69f84c55ff5816d48f78d7b9ba691a2f4c9d41f38f20e01cab00fc
+       8168a685bce08ec00ab7e7fbc20dad4cf1a9af5ca3cc7fe72ab7a770bdac10da;
+  0000000000001000000000000000000000000000000000000000000000000000
+       130e28c699dce84779ddfaea0a45be76cbbf3fd14a9c71b50c9ced5eb2cf6edf
+       9d17f71aca5b6175d82e6a7bad34a8d21a4bc1bc404462807035c0c855033865;
+  0000000000002000000000000000000000000000000000000000000000000000
+       4a376dc814c679fb3fae93836a06bad1cd77db067f76ccfe60987559ed4b7cbc
+       26932158e76eaf55cfba5398b06d11ce6c88b078aaead0ddedf5e5b2505d5ed6;
+  0000000000004000000000000000000000000000000000000000000000000000
+       5a04e963f90bbd5bdb3f616f3d52f23dccbc4652fa313de5d1fbf70c829f6261
+       0c65c4f4d6adbfbeb91488a00e16e978a75dcdaa4ed9302148aead46d3f8e8a0;
+  0000000000008000000000000000000000000000000000000000000000000000
+       f4efa7971e1b1cbd41d9ccc7c84b46ca24781c118409fdc8d86ff3825c033e85
+       0393c2f10ddc2c93911de8c22b192dc78be826d84405beb42e5cce91e0234620;
+  0000000000000001000000000000000000000000000000000000000000000000
+       aab379abcb48184edc2400e7942943710acaf92763cb82368779535b2fc1f3b3
+       b29bde1e9b5ec2d359a8be97db7bcaa7bde9f2c3e88c6536b3a58d62bd7c1501;
+  0000000000000002000000000000000000000000000000000000000000000000
+       308e739a98aef258e547d0bcd9e204da0f2c7d983383650506e66e9dbd9b0857
+       9089ef809029209d37c2895b5f098e38d68ecaaef8c2d6fcc04d72928b921c59;
+  0000000000000004000000000000000000000000000000000000000000000000
+       1f7a8bef337a14785dee818be84bc9350fe1951a9a6272f797ea1f5e71a1b022
+       39148fbdfc0e0acf1f30123f11b67d72651b0d87b0e8541c9c232f07e2f93549;
+  0000000000000008000000000000000000000000000000000000000000000000
+       4f0c06166efdb1bece929d31c2981e96b4a5935f1c314e4ec0b10c0c761c8f7f
+       68cf4918507324eecf2cf991b5731b368a1c6bef35fd1f1c940929b1e45b1332;
+  0000000000000010000000000000000000000000000000000000000000000000
+       7714ca9fa1ea7c235585ade167931ea4435a61d1d983aad7dd5452b0a291befb
+       32f56751d799fe84ce7075cfe927fdb57bbe7e06eb9c88dfe4b14497a3d8d6d9;
+  0000000000000020000000000000000000000000000000000000000000000000
+       cb00fdf9a48bb507803079638584ba025d303d2b0cd5b81de2b644a61ac5d891
+       fd821a3c9d6d04bd07a28669046eb4a7764de97e056f0aed9356d06046365ccd;
+  0000000000000040000000000000000000000000000000000000000000000000
+       7af41ede49449402d065d70e9617be50ea74283c639f75a4dcd794950a2ad075
+       a9126f01a04a287ba196d148de77256dd86b41a4937fea307e19c40dbdbb253b;
+  0000000000000080000000000000000000000000000000000000000000000000
+       b5736b632b346a2210ecdeb95a0337903449fe2154ba97da8ac5213a5cca2453
+       a4a924f69ed450c80e1c090b327b75ae8c900bc0530bc580ad9096545e60dc4b;
+  0000000000000000010000000000000000000000000000000000000000000000
+       305cce4b3deadb80ca17a1f06bf1a8dcce2d1d66f2c25e7b2703062460f0b7e2
+       9071f39206f73eb7e1af21cbfdcc006a017521078254de35af24593f093ebae5;
+  0000000000000000020000000000000000000000000000000000000000000000
+       17fb9295d4f1e2c6717227dc01503b953dd54b327029b8577480a4e87d7ca1c0
+       cae92b888cc88e686a780206dcbd4d301e03ed5258fe0d8df01c8d8b9d6c63b2;
+  0000000000000000040000000000000000000000000000000000000000000000
+       27cb60b2e45fe4d7580ecab6446613dd2e9c773ba905a724458c51a2dcc1425b
+       a57c7f3c84048bac329e1e463f0c7226c51c9e6549d3379b78c89176ec316d08;
+  0000000000000000080000000000000000000000000000000000000000000000
+       893d82ceaf9116fd2b78f36c570da29b84d7fea87ee8f0f6678652879b8d50c6
+       f3f98c24d5c885055d318006e2cdff776412208b714d286cade4d3541686e281;
+  0000000000000000100000000000000000000000000000000000000000000000
+       f8dce549ef52a9912c8aa83f82c818dad9252b7f9711c828179329141e3de5d0
+       819acfd983335211dc97948e599fa664319a9c589ee11c181c5c0780d379d77d;
+  0000000000000000200000000000000000000000000000000000000000000000
+       2915e806c01c17a353729c6c3f943b9c34e9cfaeef6becae2935d471a34f0940
+       548123fe86f653b4b0a10e361369be8f0863b4b5f15c34d7ca2e48e9e25d1b5e;
+  0000000000000000400000000000000000000000000000000000000000000000
+       d9a23e63ca5828b15fe38ad7e48d44659263d27f0390af84066154585087e771
+       b26569bb88ab49ee647671a9cfd14764d60efa99e7aed11ee373af93ed061f22;
+  0000000000000000800000000000000000000000000000000000000000000000
+       1d24835d30eb9201019d8444bb92f2598bcb1ed42346acf53810e4aa8788ff73
+       8e0c78cbee01d9ee871f2457743ef0362c15d9c93d23a12626c4e80623903181;
+  0000000000000000000100000000000000000000000000000000000000000000
+       a0cecac4bfd7aa747230a7c795997255068dbbba5997633ead02ffb3454619e6
+       018a38a0e5ca7db27847e3eb2854a4d6a64c0a41b3c59cc3d38ea58ec25dc93b;
+  0000000000000000000200000000000000000000000000000000000000000000
+       f9a9da5740a32c62bcda5efca357870d8725965abc40aaf260a18fd4ac42aa43
+       1eca828dee97965f8e8d7c1b0e87125f8f9ac3b6bee8b0b730bf3afc905cd19a;
+  0000000000000000000400000000000000000000000000000000000000000000
+       4d2aa6eae1040cd338063d6cb66911fc026027db5a53b91b3612d11b2be3f710
+       c749d747ca70eb7bbe5a160bf61c1e1f573366a473943ccb60129e46ff757792;
+  0000000000000000000800000000000000000000000000000000000000000000
+       21b0debd7ab6d7149c058c9d69f466f9480b9ad20a59e807c9186496023f7b79
+       eb1556e90beab9b3b1c5f9e520de345877a2ec446f0976f76bba0e11fe056186;
+  0000000000000000001000000000000000000000000000000000000000000000
+       612a8d66984e3e664af0daeae9bd903e04f63a761123d7536639d027ced1d682
+       1577663f2b58aed2fa1b2eb87d1e86d8af977ff7439c52d4947a29f7f3ea2605;
+  0000000000000000002000000000000000000000000000000000000000000000
+       b502222789a36d5a9a245c0fff70ea43c2e96e5fb57fb81510aab99f80c35a32
+       0303b621ed6b340068159fdb857eb2a5479dfa6183604730b72d01233fd71586;
+  0000000000000000004000000000000000000000000000000000000000000000
+       3df5c158a338ceaff80de71a2918dcf210ea5001716256b445c82ac4691f1fc0
+       af811728f6e887608a5b6795b8ac6b07ab68ef95394effbf6d46b50418a77a46;
+  0000000000000000008000000000000000000000000000000000000000000000
+       39b25d1e214df0a0283bce92879f056beac64269f127b0494c5e8fd4ac4b6ac4
+       5e3e7c6d0dc7ade448def91c280287733a78bba5fc3f636f9d8a6552b0142b7d;
+  0000000000000000000001000000000000000000000000000000000000000000
+       00fadb701238f00fbb1d1096d3e451bed024b66aa9274760dab49ddac5c3946d
+       020e78dc0f6e465fe54cc7257f547f1b48e908bf6052d7e3a5f55b58cdd507aa;
+  0000000000000000000002000000000000000000000000000000000000000000
+       d1c21ccbcddba34b3862b0d3c0e11e309458ad69d5ba1d42fbf33f8d8a592eb7
+       8427323b69e874b89fd3c981244e6c1a98e9baafc9cd7699028b54d5a80c4bf7;
+  0000000000000000000004000000000000000000000000000000000000000000
+       e783e2f80223d3bac0e249c4af0fdd6f765199defa2831e1285aa7969cd57c63
+       44935fe4ef59a0979502daba5dfc7c16ec69c1af8af85a3fd8bebd486929ea5e;
+  0000000000000000000008000000000000000000000000000000000000000000
+       27bcfbd734964e7fc8a634b2ce3fa63ee453235af33b689fdcb47d6aaca6a6df
+       df37ee8f5ca3e21e7948163c9a189852f7df18b117e4743dbba2c770f670b8eb;
+  0000000000000000000010000000000000000000000000000000000000000000
+       a66846baae257774b4cdbf9ed5257c9c18c070836e35d580b95e2a7b961ff402
+       d77a334ad77df938ce6042c2c06c868c507b298c59010a47eafee4203c9f47f0;
+  0000000000000000000020000000000000000000000000000000000000000000
+       0dbac39c772bbe1c52105d00fa32d51a03191ed6707e175680397623e793e9bd
+       0efe80fdaff4975cdcbaf28286917ad218a6bfe685fc5bdf616a40e2171297ff;
+  0000000000000000000040000000000000000000000000000000000000000000
+       8db6613e226d37bb68c89e455efc591f7e2b7b7da543c3be7d9058105ccc2388
+       0d74d3b700d64545bf4a06f0625edf7d7e3a8828de3b6c95ca42e1e5b19a06fb;
+  0000000000000000000080000000000000000000000000000000000000000000
+       abb71c9c7f39df0dc16a00939f50759ab116eaf2024b7e690c0469fd9c6477a4
+       b2432584bf1f12c9f50b9f51db6ec5082cbfbaa85202d903fd3c790a7e8c3008;
+  0000000000000000000000010000000000000000000000000000000000000000
+       f0a0ee6776fc98821b1695e6b253eb7eb3055f779fade81bae006e98f6dfe53a
+       4e38aa14fe50a3ede3998e72a989dc77300dd5e216b4b41fd23dae7d59cbad7f;
+  0000000000000000000000020000000000000000000000000000000000000000
+       c24fb46f0f7d123468c9e4ec68fccc7eb4986e44c8110733d1268c124f238711
+       d0aa9dc510363f80f3bd100f4fd816faf90e32b941b8e5501a171edd01ea91d3;
+  0000000000000000000000040000000000000000000000000000000000000000
+       cbaee780343e98edb69d95e50fe41cadf820f8e7959bb0f2580a14014df68335
+       0b13c8fd89a314d72478401f4e39d5817a9a98103ab45a458f8d23b2ebd4353d;
+  0000000000000000000000080000000000000000000000000000000000000000
+       06b5fd3436cb561d100e3d1034d4c790a35e3e634fe76ccb028112818c581ddd
+       2238d8f8aade266f01cd8f189bb04ce9fb8c2f30b5290a6011f2ea392cb5d716;
+  0000000000000000000000100000000000000000000000000000000000000000
+       b0d0316c92cf2844091b87d25ebefb5a0dfe2d60782962b7f65cf974ffc5394d
+       7e6a4fdae611b25c6d62fae841a2a8b0dd5ed0f56ee0b652b2233624e9e55717;
+  0000000000000000000000200000000000000000000000000000000000000000
+       a0687fcebbfc5d0ffc70dfd89701eae4dcc0e0897a61f7d02f3a200e1fbc0195
+       52991b10dda46ae9a31210dd90e997745dd7a45d6782f621baec5e1b09c652ac;
+  0000000000000000000000400000000000000000000000000000000000000000
+       7885103c2ddbdb34f21679c908148b48affd3030f33135ae6aeab813d76e4c7d
+       32662258f351ed45638fbd08f4a9ece8cbf4259973336276ef51883445b067f5;
+  0000000000000000000000800000000000000000000000000000000000000000
+       1d166eb905ee23d8608ba8df50d9ec70a29423bd25cc87cdacd5d8b3df321535
+       587b6f652ee658e4ffa3a16b95d717bf692eddb0f85fea3498ed89e2debbd053;
+  0000000000000000000000000100000000000000000000000000000000000000
+       8470559686b1ce1f8297a3a2b32087cdcad147773001dd844fb4fc61bc0fe45f
+       29ed1711366d01a87565165de5cdd0c817ab620aae1573be16d28cd51cd0e8cd;
+  0000000000000000000000000200000000000000000000000000000000000000
+       45c7e02ac7f22af7a8fa1b6dba56ecba6be159a7a4537cc34d5970a0aab038c7
+       477d6fa3adbad6057928cbcba71d116fbadc96bec9ebcf5f1bdedd39e32d1cb0;
+  0000000000000000000000000400000000000000000000000000000000000000
+       162c6b51feb10bf69bcc8fe12859b447b03af9c63d12239f1ad5ac948f3763d7
+       643e17074976de5a5ce66320e5ec38b631016e2d3caabe52f0ba8e56a9d0badf;
+  0000000000000000000000000800000000000000000000000000000000000000
+       f9299e0e09e8e4d408da8f4dc9e15c11b8d8e4708ca5c73bfc8714cbe42b9457
+       b64579adcf37e3bdb652e15fd7221d9bb23a149b9d0cd1bb621aa60fbbea3374;
+  0000000000000000000000001000000000000000000000000000000000000000
+       700ee74a28732eedefb1926e5557a613e00ffc91cc3d9b18e2f51d89055b9eb9
+       d52db33d671e9c012ecc5f594b12fd563e5cf1807fd161a863080398b78bda13;
+  0000000000000000000000002000000000000000000000000000000000000000
+       e6e8a4eae096448cecf973ce287a7ef8e9fa41de4c3b05501654edb2c1271af2
+       1fc805e11047c0d487a61fc552569975636ab111c186231bbf05b32c95d2ff45;
+  0000000000000000000000004000000000000000000000000000000000000000
+       1c1de2c45285d57eed9cd013370e3b8a57d12fcd0050ed324d641ef797fa6d57
+       1fb31c871cb66f8b0d651001bc2924b413075cb398d6a03d77b298e6b28d8bc7;
+  0000000000000000000000008000000000000000000000000000000000000000
+       c2e9773c4f7fa499d72af9a0487d4b02aa43ef91c5902875fd2c85c022a7be79
+       7f4575691fcbe4ac4ae9ad4f8e49d403d1d41eea43fba36c671e6a826fd16442;
+  0000000000000000000000000001000000000000000000000000000000000000
+       0ee9c279b05d527706f721ac45b2b75c55cd9b1906ccdcfbd29aca32f69053b3
+       1d7ee6cedb4c2c169a5d0e511b62772e4b40c4bc8940aecafaf2e1e09b5e79a1;
+  0000000000000000000000000002000000000000000000000000000000000000
+       278dbffbcb601500a725942fb302ba2ab0c6d206db5d7878979d7b2ad8d4d199
+       6f74aeda2cc6ee5704d685bec0de4363cb79679200f0ed5530a36e516ea86d68;
+  0000000000000000000000000004000000000000000000000000000000000000
+       e8c8c0fa175ebd8380573e7932d219a3f116d14da69693f2995471d9be202d05
+       5e1c3a0b22708722d1611b66af966d1f6d9f8faa851ddb01830b97e2d9bf383a;
+  0000000000000000000000000008000000000000000000000000000000000000
+       283d859298c1e323a493a2e949ddd4c2ffa4a5da29669b348b5a72ed8c8eb1d2
+       272552fb9fe36123cbcb0e43db68b2233336f6a84c99ebd01080c0eb508fc7f3;
+  0000000000000000000000000010000000000000000000000000000000000000
+       79125cca9c3c680a61d21951a4cf0b7230b578ce2e80fe838b337fb7c36a77a3
+       2ab45fadf08ebbcc5121b076806d50927df6310214f73aafb0081633cf98299d;
+  0000000000000000000000000020000000000000000000000000000000000000
+       6769fa85ec1c637bde75471d0b22903895ecae1462912caf6a6bc6251a58258e
+       a65b3b54d75e58eb478cfd6032d291f5bd46a8c8c5765fbb2487283e46c26de7;
+  0000000000000000000000000040000000000000000000000000000000000000
+       4e30e6abd785654640eca58ef491e13378f8526c2af3f51c0043e687bcb1c168
+       cc48a52ff696f88d51559c46494cd51dc3291266046c085fd51e9f8baa1e1e5a;
+  0000000000000000000000000080000000000000000000000000000000000000
+       96a57e2149916713b979265d60743727bb6b7aa91634dc415b408338329e82cc
+       ea571b458893e10883a717f3776b808cfdd26d9bec4cc64e16a72448c2211b48;
+  0000000000000000000000000000010000000000000000000000000000000000
+       e8883a8ef799dc1b6d2fe5ddd18acd3ae58b24e98e1e812494f8a74f4ae372be
+       93fa5ae2d6d71da3fdeed466453b7ad9f4ac8ea3aeded25a15c4bbd040018fe4;
+  0000000000000000000000000000020000000000000000000000000000000000
+       fbafbe69b71d604c13e1cb82292190c18cfa9bf6145714aec7249a56ddee4ca9
+       6336a21084584fb303718743e6e96f479c7fe0ddd8956ecf703fad72221d64f8;
+  0000000000000000000000000000040000000000000000000000000000000000
+       db9b68d716130e6b173cccb08de59eafb3af28019e87c152dc3ff5d5088e3b58
+       bb3fe5aef0a82c6adb2f68c9bf43548a06e7fa503ca61b48a946cdaf37e8f24e;
+  0000000000000000000000000000080000000000000000000000000000000000
+       9f7bc36611372d91d4b4c0cccc840759285cd03b3e2e27afe204ae448d0f9286
+       dbd6da143b4cbec22deebb4d50290a42299669dacf03fe2a2307968143d4fb7b;
+  0000000000000000000000000000100000000000000000000000000000000000
+       78d8a2300ad94cfef66b3164c731377ddb2e4b275d4e701391953432347b9223
+       50f62201950be294408f88bdb661cc3296c6be60d3012075a801b5c0834ae350;
+  0000000000000000000000000000200000000000000000000000000000000000
+       12e33f7ddcb2f8d174625428a62b88949f125ef8ed08fdaa354599949ca0ae66
+       06ff56ab47bc89455cf58af988b568b2ecfc06e7df27cf710a25022d87557da7;
+  0000000000000000000000000000400000000000000000000000000000000000
+       56eded2b02168d3bbeacf0d9daa6af71edc952a831840440039c498f4e7f7ca4
+       704dee5d192940b0a69ab883c75151d8d6cd140362b2c1654041f43f2069f4fa;
+  0000000000000000000000000000800000000000000000000000000000000000
+       755d75672e5539950e3738c9f08391595fe8666fa3630d850bc54f51db1c85e6
+       9be04b998cbd1d657d9eb034eaba6870641da53e310eade9dee5013a8c053790;
+  0000000000000000000000000000000100000000000000000000000000000000
+       59a5be52f38efc387f5681e5efee14564bc0124d21a853433576752ffa429c9d
+       2c8e95bc932d31e629cf4c519bfbc19b1356e82b24e4b0a0a3f0e7bff87cdb9e;
+  0000000000000000000000000000000200000000000000000000000000000000
+       6a8e931278edcf28e271b3af14ef2a4c3a32187f2e99a9eed8f8bf5cc9caf92f
+       bec4947e08bdce74baaa30e8067010ea1a5f0a510f3ded81e1531f7c70a579b8;
+  0000000000000000000000000000000400000000000000000000000000000000
+       ce10996b404a63f524caa19cb2bb9ab0278718cd618687588deb24dd0acae4e5
+       abee46ec2bd7acb5a6b81e03cabd1cd4c5b27255c0c53245bd1fc2b82fdd37ce;
+  0000000000000000000000000000000800000000000000000000000000000000
+       322f564e6e45b4d7a556e3e0d673c24762e6aa9558221939a6e207af108ef047
+       045bdd23eddffdd2e5fe6035781a4c3f67eb5063ae2c35c4f167524c359ef09b;
+  0000000000000000000000000000001000000000000000000000000000000000
+       c38a5f9c6637d72c43bdf52c75f8a01a5c017202825ff09eaf27bb6a5de32c9c
+       a362cf96447d76f38c0ce895b2fa6bd21a02d6fcee561bba4bd20e224ce24bfb;
+  0000000000000000000000000000002000000000000000000000000000000000
+       71f79d68098b9e011bb7c9400ddb9e3493dfa52fae11dd9ad77430857a136c68
+       cbeba998096d1bf54c3f5202d5b06c38a8f81f7f9a729c030bc916b43544f325;
+  0000000000000000000000000000004000000000000000000000000000000000
+       a877f654b01488d3bbe0104bf788a18c250a453f2068bc81f2f096ef5731bfe2
+       9081748a46ae87a2524c0b27af4d4af310d5384ec8e8bfd6bdec56f7e4060ba2;
+  0000000000000000000000000000008000000000000000000000000000000000
+       8ae90f0c8d8ccd1268ac98f999bda54594e219ed8cec617c13cea31a606db6b2
+       1fc23a6581656dc0a72abf427d6374ba7d3aff387493204e1036caf860ad0f86;
+  0000000000000000000000000000000001000000000000000000000000000000
+       b6d4e59d418667855067491c8df18244c64b1bfd728a3625161e47d4a32712d7
+       1f3752a6044179cdbc6b05ba5cb21c894be977699e1401eef6412a0397fd1287;
+  0000000000000000000000000000000002000000000000000000000000000000
+       bdb69d9fc2ed427ecb6848b5c2f9687c3e873271e8a3261073a05ebc4f75e244
+       023140291efee7ea2d02dc4b54d5d4cddee02c88767c33b72d0e028dd97633fc;
+  0000000000000000000000000000000004000000000000000000000000000000
+       925ea1f098046aeb00899bec3d4f97ae64290279272a9dd8ce9d79b6837b3ad0
+       370a2405d17683bcd5baa70c29d57f49f9847641fbd6884173e2adc11995f203;
+  0000000000000000000000000000000008000000000000000000000000000000
+       1349f44857d80fd3a0405217a8248339f70d227635af2411dc6c4214a42c2e2a
+       f6fe27b251602fc9c9e870f5cb4b62c43e3e875c47b775fb8d9f546b52807e02;
+  0000000000000000000000000000000010000000000000000000000000000000
+       74699f36e9636c3206287bbe13384e18ced1120706175c0a65576ea86776c612
+       dbe9d11b3884457e03b84deb23858d704169d7582a300c8673a7f544435dc3d3;
+  0000000000000000000000000000000020000000000000000000000000000000
+       b792ed127f2ea24411d063cdc2617d702230f3fb9d03387e3d0700777d97a70a
+       fdb09f976a749a232305946db9f7bbdb2429fecd28e584d937997446740622af;
+  0000000000000000000000000000000040000000000000000000000000000000
+       dcd987801779a92f86d879abdf28b9cf66f7d0318f487be0ce27c63a27fb5200
+       caad8eec3c351be1e60e70dfdf98de671d2ca5d3fbc21fd440713f55df8c69fd;
+  0000000000000000000000000000000080000000000000000000000000000000
+       bf85c351d0e74eb5430e55479b50d0fd827578e982ebc8e338f32116ef570e46
+       f81b47ebc5d2887a45aa67d0b7d0fc8a07146f30b37f1a036ce9fc236f0d7d00;
+  0000000000000000000000000000000000010000000000000000000000000000
+       6c6291cc83e0314b06e19ac68fc170b93e84609fa80ae0349e86cdffefe6a193
+       67ef3467e8e0b571c5d110ea08133e0156e486310d05e07eb3a9417e4749a3d6;
+  0000000000000000000000000000000000020000000000000000000000000000
+       6b71719c717d62a10a688fe8f9563571195edc246f7e8006380a1bb14dc3b8fc
+       b8189e40e802d55d545112e6cab102254477c52f7536d019e06512c83742975b;
+  0000000000000000000000000000000000040000000000000000000000000000
+       4a2086948673804f8a97a07b16b36c31096cc0610e2d240bf1fa440fac400f33
+       395dc8ec9ead16a9cee85b07e7da6b1475f525234bc4edf65ece264e72838ebd;
+  0000000000000000000000000000000000080000000000000000000000000000
+       ca82c08abf42285892485b0d4e4f3a5f5877ef51e0a501e3fce14e4a8b7efd06
+       1271158ab7223bf43fe3f689e9307aefe4233b46e864cac13d234544c0af18a7;
+  0000000000000000000000000000000000100000000000000000000000000000
+       e7a2d99bec6b59b14475e6a1a6fc28d5394ea5a8557882ae6e9e67d34b18c949
+       0ee608417c070fd9f04a73510cfb900f3773f010e074dfe70a333df6aff09d48;
+  0000000000000000000000000000000000200000000000000000000000000000
+       9ac8e222a63951e1b7c2e16012ac90436dcbbace3f0318d2aee3e0bef53d5950
+       bdd3b18e99e5fcae550234719e903e0ac7f83fde47ddb396b65eb8af1373d30a;
+  0000000000000000000000000000000000400000000000000000000000000000
+       7e48facca309371083f21cbc0bc25ed09d09e03f996f4dc023f54ef7217ded8d
+       8dcd9aef8e729df03810d6273f1f6125a35c797606030d653eab344320297a30;
+  0000000000000000000000000000000000800000000000000000000000000000
+       d1c032fab24525d378aed7266f49d5f7d03de6001ea531676f845fbd8578fa80
+       16c95820117c70da72373689b04c1e6f494b3f4c165d6aad39b5ba8bc8d5cf6c;
+  0000000000000000000000000000000000000100000000000000000000000000
+       904091d32d5265cea53274748694757fad2e1c22566b1908f4f9d35538e89b06
+       ad3b3c6e85d8afc210b3a22d1fa0c51076bd79c6641ed3481d1533ec7fe6b7b5;
+  0000000000000000000000000000000000000200000000000000000000000000
+       ca0521aec053c66badec9f3c89d952e0eb69afa9ea41080397071da57161b35a
+       6641463de2ee581e2748259471425e94d9fb9d79093e0cd0a19b96ec510d5de5;
+  0000000000000000000000000000000000000400000000000000000000000000
+       19fd13377a56d0aa15ac4e62b99eae76dde81f2ffecdc24504051da4b9652c76
+       3f1d6001995209adb152a06b48eec5025b3f755d8e2a01e4bd3b0b536f3ba333;
+  0000000000000000000000000000000000000800000000000000000000000000
+       37a40e8139fbcdba67429f72b56509f5af081173ec4bd18cb6e9e3a826bc83c0
+       35196621c8a1dacc251ebe5bed3f5763659303b6e54a10dca061c2f5517cc417;
+  0000000000000000000000000000000000001000000000000000000000000000
+       ab0439f8eb335ac24b73994949e1eebf0614eef32a7bdb497960791f8db18e82
+       36f36ee2dc7d53583645d308735dbd7a2c88f0a3f407e8bacc2a9737c63fd51e;
+  0000000000000000000000000000000000002000000000000000000000000000
+       104c04190e24ae90c2f87caf2cc314680a748cbbaef9298320dad36f660a243a
+       3cd0909e1251efd2c9b631abfb0ddffc751ad3c77ac022ac47dca42682159b14;
+  0000000000000000000000000000000000004000000000000000000000000000
+       337cf2622058e3b65d83499b927011407fd627c5e77d9e657fe1bb6a224478c0
+       a3f95204f3120e370abfe9115eb31f39f5db8a92aad8c525b903581069001acb;
+  0000000000000000000000000000000000008000000000000000000000000000
+       2b5bd6ccf9c26f31a167e7027426aae9865c0dfb14fb3dc6daeabeae5c1c8b69
+       5eab14eec32e833ad8cce68fe95d44c7cfdc997e0f5a8386817c3b679dd9771b;
+  0000000000000000000000000000000000000001000000000000000000000000
+       dc2541bdba0e4d40e8cb4fafc93d0a8a60a5530b3fe27b95f6a88be92f6f36c2
+       d25f0a8d66d9fed6790560b86b0d08677c65f72e090426c88cb18cd756965e7d;
+  0000000000000000000000000000000000000002000000000000000000000000
+       b545e6c9514c66196058a3c3a7289be91d5c5e21da87797e3373bf6e24f5d590
+       9c64e96615ada88bca95405fce376291d5ca05e23356b0ecb94983c1610d07a7;
+  0000000000000000000000000000000000000004000000000000000000000000
+       f34e2420486825bbe7a24b40c50a84c28c80e2f298c30f4f78bf27c0ed56afb1
+       cfdeec976acd4bf09bfa70ad96558e3198c1a4203784ceb5af21657c3a54c3df;
+  0000000000000000000000000000000000000008000000000000000000000000
+       ab041c33802ab7dca2d6d59863404616f94bf48ac727aed1a85f3b5aa4c6250a
+       1797812dff75debcdf59a7b1714d3db08f4b4830801cccd3ac74d37527d3d784;
+  0000000000000000000000000000000000000010000000000000000000000000
+       f943ca8fee60cc92aee5b0301fa25b129993817b9a1c75cf8528fecbb7563821
+       8c00b2753f4f23b48423836c28977481cb073f3c3693ea03d33db3b5b31f6ed1;
+  0000000000000000000000000000000000000020000000000000000000000000
+       b1fbd227465ccfa0e934080e315073d99faa55be4fd38e93d210db20f4cbcaf5
+       c4e7c620deedc6244fbbcd829105ada603825e64a044ed864c5ee465be50141d;
+  0000000000000000000000000000000000000040000000000000000000000000
+       a9341c312dd5c879b6b7305557080ac059eb7d48da0d044ce4c53d46ee682a77
+       efc45cb2d180e546a8e60450da7859233b04ecb5a21a11d517a6752fe5b56ba9;
+  0000000000000000000000000000000000000080000000000000000000000000
+       fc0d7e148270279e6a8a0bb30102642a7f1481fc2617341674319a8496b2483a
+       6b32c7813bfa42592b2558adf16918b1c56686e70b2fd6cf4d9c57ef4079ef4f;
+  0000000000000000000000000000000000000000010000000000000000000000
+       55702bc90512de5e92dc5106f128997ac822b95d89ea8e924bc329174da48ee8
+       e009220efb6aab4487ead7b8ef0b82843d16684ef57de55b2fbc2e981aae1c6e;
+  0000000000000000000000000000000000000000020000000000000000000000
+       3be68900844eed0843ad0b2ef6d0b683a3112ba3b8a35a52f40007104586ab85
+       b10b32f47822dac5b5db3d240bb2d8f05a408c2c20439563bd97e96a1f4ab84b;
+  0000000000000000000000000000000000000000040000000000000000000000
+       5c451eaa6c8e993e837371b4f231e93e2ae7407b930f07bd87ef5ba134d9f6fc
+       ff89a9dc0895b13c20a7af15ae8e860d74f9dce289c1f43bdb35025d7086490b;
+  0000000000000000000000000000000000000000080000000000000000000000
+       a8ce9c065e6c91129d0643c04cf73150df86bf2f5a1a947a1fbecb1aca90d26a
+       a1301654d68563bfb7f2110e5d9ef96635d24ba8b56320cd070b25b6be28623e;
+  0000000000000000000000000000000000000000100000000000000000000000
+       2aa48f6411a0ba5040eb83e2a2b20f14e93554953c8873e8879f355678badb0d
+       dbb22baa33905a9740d5ff475ed0517107f413690af9b95f717e4cdbace8405d;
+  0000000000000000000000000000000000000000200000000000000000000000
+       7965be05896fcc9b9dc334f9c2a43f813d5c248963e1317f798c4f9fc5f8e7fd
+       34125fee23f020155f248b4cc5dd4370ed530ca871be46fd93e7a006edfea7b8;
+  0000000000000000000000000000000000000000400000000000000000000000
+       1541c80be3e5c8e221540f92b631f360c5b0370223263e771b1b92d4fb73a453
+       a2bff0682b9d6e3eaf8d183efaec91667808f9d026ff20c1d65f7e6e2a4676a3;
+  0000000000000000000000000000000000000000800000000000000000000000
+       f283204496fe825836a3aa8377f4f2db5cfb14b41c6b9f5f53e565c852db6598
+       6dc375d702992c7e30ed6cd188fb27fd7a3c4e4c7fb2856f67244fe3c7f8b760;
+  0000000000000000000000000000000000000000000100000000000000000000
+       e234f1c1d7ccd4ce1ace58850dc28d2abc7e2dfd171877710704282a12bab9a0
+       8d51c164dc8ae5ec5bdfcc25fb1ee9a6d9cefa47abdb748143ec18b91c72fcad;
+  0000000000000000000000000000000000000000000200000000000000000000
+       4cb4412669289a6250900c8713f56cb57f5b962137b828b46a1b1dcb41bbbca0
+       2b1ea7bd9d0cd83de33ccc5415ba625c6c4d2bb211e5464c39b2bf9325aa446c;
+  0000000000000000000000000000000000000000000400000000000000000000
+       a6c52188edc54c3e88d4424ac378f85b690e1b6b46e552f4c855aa9e4e0b2c36
+       75e118baa53204bb91b283c80d3baf3e70c4cc204f25aa71ae6ebe0655010d9c;
+  0000000000000000000000000000000000000000000800000000000000000000
+       58449e523e08c99109ca6570b8bba4011a7cfb2203257e8b93d3131bb16219aa
+       b1f0f1f930fbe5566ae5ab46e7a6981ae14d51dedc62a4b1786c032d16cfb829;
+  0000000000000000000000000000000000000000001000000000000000000000
+       edcf56d94c31b0d201066b648da08d43e0ece64dfefd3a542852fb3f945ab216
+       122c6c4b6b019b18cb0e925d191f3599d9eee57eb7a6506fe1fac494f037327d;
+  0000000000000000000000000000000000000000002000000000000000000000
+       b178ca20a3bb67c4f34a816d1c4636cea7642cfa004cde16efe32a6c613c9eef
+       45912f3f092fd64dfaba7cd7abf0534fa7f8571d8d01949d5204223bba068166;
+  0000000000000000000000000000000000000000004000000000000000000000
+       d925287721da5f6117f951cddf410018ee8cd147f97305ba2f0aac26c1859312
+       f3878c9586205c2f92b27656df61bd94b00a01b86202079ca1926968a1b52c08;
+  0000000000000000000000000000000000000000008000000000000000000000
+       359f4ea466e0f07d6a0de61e99ff4e2007cc5dd90c59a1e4d0d5b46f03b5aa99
+       33816ce4fbfc40b806bd2bad025b9477b051dd55d2fddfe007287e66e1814afa;
+  0000000000000000000000000000000000000000000001000000000000000000
+       ae77a98a68d9462b74bdd4f7d124746e1c5765406cf1b9ef547d52f00b45d4d7
+       2d58c0e474a33f1957bddf17a850871ea050580f4f8d48380261189a271d4c01;
+  0000000000000000000000000000000000000000000002000000000000000000
+       0bf35dc3d5fdea4d60f14bd0759906c1625c44cbb754f4087645b551355844ee
+       acae4ab9b17e275e54968b1ef6a2422f3bb97eefa6b0007bce18e8162a8bfa50;
+  0000000000000000000000000000000000000000000004000000000000000000
+       4ed4cd19fedd9fce8b979f698f2f167909331a7ab8dffbb7fcb56a2c5afc1428
+       ddb8a8c89b629b0711f72b3328b22727e1c5965dce9b3843667e1b6492962416;
+  0000000000000000000000000000000000000000000008000000000000000000
+       6af47d0713e05fb4a2974110b0860baedd2597820ff5c600f9049d7d425ee100
+       2d0cf3e4db588dea89cabb0b0ad58acc1d0b83388fb6af32b367e21f7f14f41e;
+  0000000000000000000000000000000000000000000010000000000000000000
+       96a82f4432529492f6a8a17fcf155ef8a6bf11bb73a77d3dd8bf3e986ca3dbbd
+       d8fd1163036b81998a1e5e3ed3d787fe270f05b8095f0cb853a0b934b4016dbb;
+  0000000000000000000000000000000000000000000020000000000000000000
+       23e6baa1a8a67122a9855247124ec59a1dca649570c6a1a4fb089a76c81a6014
+       3583e5c1cc5e397b2b5864960caf7aa66ebe6467d4065e67008fa737c053a7a5;
+  0000000000000000000000000000000000000000000040000000000000000000
+       86118f4629dad8a873b1649b9c039fcd4dd8ba032b9f6819115c3af0d1b6595b
+       071740e3ca823edfdabfabc0dc10924348fbb023b6ddb344d4f42e9572de3e08;
+  0000000000000000000000000000000000000000000080000000000000000000
+       982d814b00c91517c08aa4c87087069c01c6a045cbcd3d7f26a4a1c6cc97d2b6
+       3d20e5791747d98b9ea3d2026594b8ce462c5ba6e62a1c361cf5fba5ca0f1d11;
+  0000000000000000000000000000000000000000000000010000000000000000
+       2dfb74f1332f7930be2ea7a1732ce3d56fb12d916d2796d1e1fba64f2e66ac20
+       4be4d901963da689112e1fc54d852a70c0f60b501b915cdc141fab94b43d0106;
+  0000000000000000000000000000000000000000000000020000000000000000
+       fe6cc968de80a13cb0e7a1fd4eeac2a1d1ddca48c53e2bd5f4230c4f51d1f4c0
+       8af8f0ce706f35fd089f8d8aa07d07d9a7015d4ecdc7e9548cd0f3992073aaa2;
+  0000000000000000000000000000000000000000000000040000000000000000
+       f8f84d21d697ff9862c223ed476722077f5865800c34d36a6560a0a975d90413
+       fb9e5f6b3e8f8e78f715226d808f98c389883d65e2c53aab4ab018fa941d28eb;
+  0000000000000000000000000000000000000000000000080000000000000000
+       b934372f8ad78e178eebbeba49db0466073fc8e29e78a232bbfffd59b9d72d65
+       95d2ff2f7e24735bcde0d3766c83a128104bbc8ac1944f3efbc3e174517d08ff;
+  0000000000000000000000000000000000000000000000100000000000000000
+       ef204271d3588603c5f43eacfde91e3306723c7f074fe2088ab95fcbb45eb6be
+       c14741e0daa9c84264b877e8a503ae78c6c7b2329f0bff9476ba2dad653ecf12;
+  0000000000000000000000000000000000000000000000200000000000000000
+       0515648007e5e5e8e37e9056a4f23232a07083fce238e2dd3853b3ab1734ea70
+       0f4f15ea46ccda314f7891ca7d0091a6215d341788a3acb732a93a14da0a0d18;
+  0000000000000000000000000000000000000000000000400000000000000000
+       67b53797fd010597b38fd94cf1686270f0992e6c6666e9ca4a105a61d510d9bd
+       28069c2ded2405e0ef95abeab23f36bd752b15119e4fa69b43d731624ce5178d;
+  0000000000000000000000000000000000000000000000800000000000000000
+       7a47769ca3509d8811e6c23c3d5adf38da76e8d481fa13afdf60813a8b59792b
+       eae7e513eb59d8ba54087cb66c7c00edfda452731b93f34698b477d234dd7faf;
+  0000000000000000000000000000000000000000000000000100000000000000
+       8dc1de423e5ae630989be11bcd4be30d3f62efe9d38fc26396b123810df2768f
+       f0c952d27a250c3f4d914d537fd04a8cdc6c057af35ba4410bab0ea89e6d7d54;
+  0000000000000000000000000000000000000000000000000200000000000000
+       48571b94f3f991ca6e992e60358fa4b3255999983d5f9b9b1268e61f3db3bde8
+       b889b82fb5f1e8d78eafee9275c889e23c7a2555d78487b9cc4f701d7d1f00e1;
+  0000000000000000000000000000000000000000000000000400000000000000
+       1e41bd7ebac2a488c52acd8a99b336469d9fc35c98d9cfff269a6b8e9377309b
+       11ec65507e8b6393c7f12023f8ce9f0985ff92b8a3ef9c78cb1f2883694878f3;
+  0000000000000000000000000000000000000000000000000800000000000000
+       b6eab1e877e719a42d935523dc8c904b35a30e3b02148944a6e46459e35c5f40
+       04da7f3786ccae4982a8e75aa55549a89708915b1c6f19613632cde018ff5269;
+  0000000000000000000000000000000000000000000000001000000000000000
+       925e5596d9660e28a1b6c1a9e33fc7beea001f1cdbaee6c6fa7938d66e4f2e7b
+       0473cfc0964e7b3f9b505789fefa176f735b564678ce0b89223c073175e685ff;
+  0000000000000000000000000000000000000000000000002000000000000000
+       ce02c8aab250c3d07e84fd4a8475c1cffd00a20b1f215df5feb3e93e287f6c46
+       7b9d26b50cdd0eb37a1c6cb01807017bb70760c2892b114a944b183e80392739;
+  0000000000000000000000000000000000000000000000004000000000000000
+       acab6f16ba40e29b015d0289c82f03f54baec63d322c1a70792094d229b2b17e
+       41e4f7bad8838666d798ed77a6d4129a4a97b7740611539d9a21064ec837072c;
+  0000000000000000000000000000000000000000000000008000000000000000
+       beaa65cfea3e972077a48ec8d99421a5cd6e234e2ede51c080d0d99ed5fdbc5c
+       b83d02d1b94ace563287cac9ef6b175a7cb60c84343976f97105c2d78aa1e683;
+  0000000000000000000000000000000000000000000000000001000000000000
+       9165a45f535f24531daaa5fed2621c91755e15ba9f85e57d848172c9846327b2
+       f496291c25156383b867c10bcf82466c138555bfd5fecfc9c01dc2e65aa43929;
+  0000000000000000000000000000000000000000000000000002000000000000
+       c17d79761600447acdaae4ec9398c1743a432e58752cc8082e45d842b43f0e66
+       e5ea6f466307a34d36ab278aaa884ec07a494ea17216eb405790320d8fa2fed4;
+  0000000000000000000000000000000000000000000000000004000000000000
+       d6868ca98e49ab85e60f5411b17d644b613f6101107c70f514b12d1b3e4133f5
+       1305d1b51ced2666839b11eed182da902e864a74e35e06e9d4137996ef50dba8;
+  0000000000000000000000000000000000000000000000000008000000000000
+       e35c518d1abdec18c07645ea79f07071c2967d1045ee804694dc5d43e96610ac
+       1908ede77ee9510ee12f3d3f516002356731e164a9ea4f63171550ee2ee90552;
+  0000000000000000000000000000000000000000000000000010000000000000
+       06eb73063502eda7c71d450742a79c9c7fa03f682efae6cb0b65f44e95fe4a74
+       31c5681726dfa952c0c2285aa56cab4eb107095337c624ea81ad277664b2a264;
+  0000000000000000000000000000000000000000000000000020000000000000
+       4e7269b1930a4415947740c02e07f5a648071b525ef02c169ed6464d8b27bb8d
+       6abc498904e605e1b5e28ea8628b55c7e5e029623f77cd462691d3a7fc278674;
+  0000000000000000000000000000000000000000000000000040000000000000
+       826a3104a79da8022158b60aa55187dbd1fb2bced56c4690560cc83fda92e492
+       d3fb967cae7452b867c88adc8a11e5b5b95989bdde92639ed95305ced7cfdc60;
+  0000000000000000000000000000000000000000000000000080000000000000
+       0b92142c4fdbc92e7156469124819ba920edc66c427430c017d6bb294085ac19
+       6f327c30503e8cd50af536583f510545511e8d70da1cc285bcce2d46f92d2b2a;
+  0000000000000000000000000000000000000000000000000000010000000000
+       c7b17c0628edb82798962e54e097372b3860bbc02b0cad3f87dfc81b3d25d93b
+       4ea78d7501f8fb379e7725fa971af497596116c475b4796ccbc7e10d1a2a21d9;
+  0000000000000000000000000000000000000000000000000000020000000000
+       f9286bb83357f5ba5e9fdd2c7944ca1d75d9d2375710a2894d282c85a1f94b7b
+       5293a298473e7efcde744290da3a51cb3c798cfdb1fc9a4c7aaf4f7b3008297b;
+  0000000000000000000000000000000000000000000000000000040000000000
+       64be8cf1fb77d638f68b6fd80b57f21adbc420b5e99d4227ac0ae6d82adb0f71
+       d9de4fa7124fdab3c5473ed50c41b53fe346ced59941d71a8191a8f6ade215d8;
+  0000000000000000000000000000000000000000000000000000080000000000
+       16e491e25d6f79d9a33018ae66f6a78a87e4ca6d4b225f26a70acf757eef8754
+       86fde1681d4c26c001abbc93e967065f985b607441d05683f971b05b7c5e556b;
+  0000000000000000000000000000000000000000000000000000100000000000
+       a499e877391ec0170d41b8e03af321fedbda237b675123018902af35d59acf9e
+       78e154919e5bceb7b20a4c6f94aec7014a4e03cba4fc668ed69644f20de31abe;
+  0000000000000000000000000000000000000000000000000000200000000000
+       8b058ddb6648ef4583b44e5332784c6872c52589fb2d1e7b107ff5ee64b59e6d
+       4a022b951253940108f3a795bc4f39ae3baa2cf656d3e2d520138853fba56a93;
+  0000000000000000000000000000000000000000000000000000400000000000
+       eb530cdefc2656bdae8734131668a5833ae26f131b2c8fb50999da0106591fcb
+       739475c5772aeede0aa39c19c120c20aca995eb3e7a90d4048b0a4e1efd7cd29;
+  0000000000000000000000000000000000000000000000000000800000000000
+       2eb1c5426bbd82ff9526b482d3dd71bf52af1cfb1fa7f68acc457b08429d0ddd
+       5ac3c96e0623ff40dc8dff86f1d4ddfb90312c1443243c89231b16efa79f0bdc;
+  0000000000000000000000000000000000000000000000000000000100000000
+       3b9b9773dac3e4954d4168945e276ca5c9e1008aff8be8034d0856868bcb7dca
+       65a19215b091c569c84da60a64b874091906c6c23fd975487d877e91a64e43c3;
+  0000000000000000000000000000000000000000000000000000000200000000
+       d09fb1b66db34ab57f57a2fc98945fd2b610ca739452954d3dc32e6d11b1cd08
+       7cc4d6e0660454281087046c740ae0cf3ade676dfbd2fa46d4d0f5ca1cf4fa5c;
+  0000000000000000000000000000000000000000000000000000000400000000
+       7d02fbc809080c5e21522ce33eae610a47f7c059433bbac3ac30c5637d8aa3ae
+       ee4b97a5049fbac0137eb688cd389bf104afb2ef754a30dc4e72e60267efbb0c;
+  0000000000000000000000000000000000000000000000000000000800000000
+       97e7a1f5b2c9d77294a3131298479c8240e33800f4e95b76462d3f0f9899abee
+       669f11d848792de5621440aa51b628b667f9fa28e6c43070215ca6b52da59760;
+  0000000000000000000000000000000000000000000000000000001000000000
+       92d91bc3b83ee7c8512c0dd87efad9952a41f38aaf3ff737b1bf232484b3ced6
+       6e417430040e5bdce9e6f4df84e09323e254e2c75b7ab7916dc5fc84f0dc7f2e;
+  0000000000000000000000000000000000000000000000000000002000000000
+       a201b9a8fe87c900acc1937c5fe32563f4f52ded3f9f7c484cad259adfd81a59
+       ce267b0cf6d5e06d6a980db8fbf00a6609f8e91ac1e0dd705b53428c8a69baa9;
+  0000000000000000000000000000000000000000000000000000004000000000
+       d84985bd7e97e581e034d5f7b27d96bb78719cbff19e37abf66395654714ea20
+       919b92ccce355fdb77913cddd41e0fcc3d7b468dc8f6406782953388dbf82927;
+  0000000000000000000000000000000000000000000000000000008000000000
+       506c7f563c6254e18d5b50e8c294a97a3634322709189dc2e6af7c1166cc846b
+       ec220577d30e07409eb06ab77477eb8a4d4357443fb64d739692458e82e5fd0e;
+  0000000000000000000000000000000000000000000000000000000001000000
+       671217631c0840c9c9828f78a714f1bb67b864d646efe8de3c432ac20d55f133
+       39064a3dee432a3632fe78fab64d637c933bad5d44e2118a1247dd10c51adb8d;
+  0000000000000000000000000000000000000000000000000000000002000000
+       c5e41aa3e2d7a37c82e7a41ef0db3c81fe9b9d2948dc5c1d7b8bd862142c5603
+       0eefaadfe8682f723c8b407d90da3dce9612965c770987ed1a0f1ea66745103c;
+  0000000000000000000000000000000000000000000000000000000004000000
+       762a716822e4798d1493f81f7daccbba1becbd4fbc4a478ee30e4aeaadb0b0c2
+       21e19764af6c956a9ca8c31f3344cb0fa30195bd868b524d8d8de89090944918;
+  0000000000000000000000000000000000000000000000000000000008000000
+       221e93fbe263c8a6c92a87c6492e7d17fee75a585cea8f311cd79f595b42495d
+       58dcbe9cc752afd2aa2008bc9f95c2e70d38fea1d5c3b87c1e6f29f9c0bc4373;
+  0000000000000000000000000000000000000000000000000000000010000000
+       72b80c94d6ff97f97e9f76e139c037a3fee9a53e48f0e57266e24761592cfbfd
+       1eb856387f0f0208987725a13f796cfe420ea65fd338fc594fee3667325add23;
+  0000000000000000000000000000000000000000000000000000000020000000
+       d147908d20daf77c962b21d4997f7b84fdbed2cb07cb06e0e59032641b9dcb3d
+       5fac3709cbc5b5f3ef21ae198d9234feb1a82ea4957684891877e2ef2b3c0332;
+  0000000000000000000000000000000000000000000000000000000040000000
+       7374263f1b8c9d4d21f52f1ec6f971d9dc7268a8af79ac1c1c535dc4dff5cbf8
+       241175e0afa2ed5af43ed388a818f128e6d99731dff319644fdb983951d8e765;
+  0000000000000000000000000000000000000000000000000000000080000000
+       752aeaa1cdbb7d024fe734668cd9f63d61ff4b335e7f42d0f545ab81b9b234fc
+       4ab2772f9d610f0d618828a10dcbf20ce04d4f78f71565a8379680ea225801ac;
+  0000000000000000000000000000000000000000000000000000000000010000
+       7ec933c4574148f27c412e2a4289def909ad7cefc54387dd5f0dd2c832488790
+       99e2a4d15571d1098f1defc1d29b07c40af145ebb2edf81258d5afccb97919d6;
+  0000000000000000000000000000000000000000000000000000000000020000
+       954bd7a24edf58f58ebe343632e606fe97936b2500658ff9b11ad67617d221b0
+       f63398643b341b0a948cf22f5e9fdeeb8fd4fe21a3d946cee2f365e75537fe1b;
+  0000000000000000000000000000000000000000000000000000000000040000
+       e65323be34b117fad1cd194caaa254c7ec53fd96b65430e5703ef4697c4596e9
+       dad3ec2e51bc681c018f9ebf6d137999d6234dd84958737bb438c3232d377187;
+  0000000000000000000000000000000000000000000000000000000000080000
+       4b4306c5d55af9bf63dcf7c7c20268ef10b372b59ac10695d2b83277ded2b85a
+       da842a5af1d93e0f945101c202771981b4bb7645d9a59bf0939cf7b35cf1de41;
+  0000000000000000000000000000000000000000000000000000000000100000
+       20b0a0a6c9fd63ee745798c9248c988b1aaa9dc976f783254711c57f755728e8
+       83bc5c2254747422499230ac0abdd29de42b8896a9abf47cae6811a5e7986325;
+  0000000000000000000000000000000000000000000000000000000000200000
+       92c046c878b2f54671c4287237e200388bc1b03807c0e961b6e8ad336d6b0dc3
+       517c911a62e8c951bd0bebdca4940a49bd0d34eca5d7fd42f53b63a674588ad7;
+  0000000000000000000000000000000000000000000000000000000000400000
+       07faa395104ee08dbe87821fe9f4bc657a0a026de98a1b7eafecdd0a0cd90950
+       b8dcfe3057cff32a8346fdda5cde697a0f5daa99073a12602a14fc2c098e8d37;
+  0000000000000000000000000000000000000000000000000000000000800000
+       7b66faef189ff1c27797957691d2a5393a51cc46d1fb35bbbdd9c18c5d6be3b0
+       30d0516447f18c0140c56a2d3839f19713b2777507afd01bcd3e2b5f3bf565a9;
+  0000000000000000000000000000000000000000000000000000000000000100
+       4a7db25fe6b7f7195642b302df9ae60721be3bc0a0c03c0bfc02774f0770672f
+       5e9e9a73d8482a46bed4f5a3d111f5128d7ce25b459cefa8dee41e8a20530cb0;
+  0000000000000000000000000000000000000000000000000000000000000200
+       a3666ad211b46b616702ba5460e2153563ce71527ca411720095408409c1c1eb
+       9b5b488a37a2639e60077e50b3cfc23e0ca6b15303ac57d6a861d27bce87f4a6;
+  0000000000000000000000000000000000000000000000000000000000000400
+       5621077387c09f1b7de44f33ee44726fb24d4f13faeb59888c94d6867c7b4989
+       0e01ed6bc6527eaff1dbce5ce7a23df23e6369f51c250ca01e757c7ea6d2b3de;
+  0000000000000000000000000000000000000000000000000000000000000800
+       6ac275dfd387f63219d26d8f2bef9e73e17c026ae17707ba80ccf24899a9db69
+       63d189cbd05260d003546c599da6d7b574fa0037104cf6300f9f5f5edd6eef02;
+  0000000000000000000000000000000000000000000000000000000000001000
+       d9f2fe1ca70220a4471cb888f5ce568012b30c31c485977f5bb3e0310195b5a8
+       e8a1128025fa4a2431858de3c7253371b487b2e49bfc477e9b5d6734e2d17d34;
+  0000000000000000000000000000000000000000000000000000000000002000
+       a3ab3112e4d31f85ebc84e7e43015c687276a54a96b77b462d2e1ec71b88fdae
+       cb586bb26463168f35f52a962e040278ea2e476ad53a6161599ebda329c46070;
+  0000000000000000000000000000000000000000000000000000000000004000
+       93bd82cdc5d4b50b83eb98b2ef0735c9d95f7aa82e857a76b033b13467eefd14
+       9b3955c74930f1448504dc3e1486e9f861d25f437dd8c2db6d67ca70b4a83014;
+  0000000000000000000000000000000000000000000000000000000000008000
+       9a47b3563a9a7ac67a73109c79dd36c0a4445dff6b0677ca76e30cbdbca7ba07
+       4063046b6cd73e682fce54e3ced24880627ff6ab50a9b9de367300ef07e9b9d3;
+  0000000000000000000000000000000000000000000000000000000000000001
+       1e21dcd5b4cb8628bca386ab818e8b64b693a784e38c1bfa01b82c9d95846083
+       30af87491adddc2f86988318c2e7ce9f4f4d19e84eef873ce0732599a097f3f5;
+  0000000000000000000000000000000000000000000000000000000000000002
+       f9aab3d341f85f5fd8cdee460a5667595483f277b0f79f7b6df89fdd35a134f5
+       16f23b237ea5c03cd5ff1304890453a8311c456a2935a65c73c99e3fc12bfb3b;
+  0000000000000000000000000000000000000000000000000000000000000004
+       935d4b978db6e8f84dad228410ff15093f40ed89e2a2f8d1cb8410643b74a039
+       f01d8a43f5ee23843f8df421f468bd2c052677b2a993256225f34966000ab693;
+  0000000000000000000000000000000000000000000000000000000000000008
+       fffaf07ed7971e764123fe4e7aa181de2b0b0ab8704ffd9b82ee49495dc1f920
+       8c3bbed3d1a15e2e5d203e7d964b9b481d42e945b28fab114435df28aea6b023;
+  0000000000000000000000000000000000000000000000000000000000000010
+       6e6d8318c270135985a84e3a2541053eb8b58fad367fdb2e81dbe723572421c4
+       aab06f5557fb72c450d68ec0b706c97d8e7e260f70db34e3ecd28ba5473c9268;
+  0000000000000000000000000000000000000000000000000000000000000020
+       e8d4277d5557864cf02d3f4cfdf4a998f82777e9fc4dfe06d856091634634141
+       6f6aaf2b2ea7ee54ba5e4c28de990437e17f685194c76160875acbb35bdf4d93;
+  0000000000000000000000000000000000000000000000000000000000000040
+       6e32a77e600cea713325d09408312bae15cd75d28d2c04a5f604990e65be3d89
+       de71f5f1814b9a73098ea50c4d3605bb764387f317ee2f08b90b88ada605c105;
+  0000000000000000000000000000000000000000000000000000000000000080
+       92128b45f2af927df41f3b200a872673a744956e2c58b0099f243b7911c50436
+       ce408d59a184170a267df8713a787464af6d75f5f46b8b64ddac88daabb50ecd;
+}
diff --git a/symm/t/rmd128 b/symm/t/rmd128
new file mode 100644 (file)
index 0000000..3dbac5f
--- /dev/null
@@ -0,0 +1,108 @@
+# Test vectors for RIPEMD-160
+#
+#
+# Taken from the authors' web pages.
+
+rmd128 {
+  ""                   cdf26213a150dc3ecb610f18f6b38b46;
+  "a"                  86be7afa339d0fc7cfc785e72f578d33;
+  "abc"                        c14a12199c66e4ba84636b0f69144c77;
+  "message digest"     9e327b3d6e523062afc1132d7df9d1b8;
+  "abcdefghijklmnopqrstuvwxyz"
+                       fd2aa607f71dc8f510714922b371834e;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+                       a1aa0689d0fafa2ddc22e88b49133a06;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+                       d1e959eb179c911faea4624c60c5c702;
+}
+
+rmd128-rep {
+  "1234567890" 8 3f45ef194732c2dbb2c4a2c769795fa3;
+  "a" 1000000 4a7f5723f954eba1216c9d8f6320431f;
+}
+
+# --- HMAC mode ---
+
+rmd128-hmac {
+  # --- Test vectors from RFC2286 ---
+
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       fbf61f9492aa4bbf81c172e84e0734db;
+
+  "what do ya want for nothing?"
+       4a656665
+       875f828862b6b334b427c55f9f7ff09b;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       09f0b2846d2f543da363cbec8d62a38d;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       bdbbd7cf03e44b5aa60af815be4d2294;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       e79808f24b25fd031c155f0d551d9a3a;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       dc732928de98104a1f59d373c150acbb;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       5c6bec96793e16d40690c237635f30c5;
+
+  # --- Test vectors from the RIPEMD160 home page ---
+
+  ""
+       00112233445566778899aabbccddeeff
+       ad9db2c1e22af9ab5ca9dbe5a86f67dc;
+  "a"
+       00112233445566778899aabbccddeeff
+       3bf448c762de00bcfa0310b11c0bde4c;
+  "abc"
+       00112233445566778899aabbccddeeff
+       f34ec0945f02b70b8603f89e1ce4c78c;
+  "message digest"
+       00112233445566778899aabbccddeeff
+       e8503a8aec2289d82aa0d8d445a06bdd;
+  "abcdefghijklmnopqrstuvwxyz"
+       00112233445566778899aabbccddeeff
+       ee880b735ce3126065de1699cc136199;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       00112233445566778899aabbccddeeff
+       794daf2e3bdeea2538638a5ced154434;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       00112233445566778899aabbccddeeff
+       3a06eef165b23625247800be23e232b6;
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+       00112233445566778899aabbccddeeff
+       9a4f0159c0952da43a8d466d46b0af58;
+
+  ""
+       0123456789abcdeffedcba9876543210
+       8931eeee56a6b257fd1ab5418183d826;
+  "a"
+       0123456789abcdeffedcba9876543210
+       dbbcf169ea7419d5ba7bd8eb3673ff2d;
+  "abc"
+       0123456789abcdeffedcba9876543210
+       2c4cd07d3162d6a0e338004d6b6fbc9a;
+  "message digest"
+       0123456789abcdeffedcba9876543210
+       75bfb25888f4bb77c77ae83ad0817447;
+  "abcdefghijklmnopqrstuvwxyz"
+       0123456789abcdeffedcba9876543210
+       b1b5dc0fcb7258758855dd1840fcdce4;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       0123456789abcdeffedcba9876543210
+       670d0f7a697b18f1a8ab7d2a2a00dbc1;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       0123456789abcdeffedcba9876543210
+       54e315fdb34a61c0475392e5c7852998;
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+       0123456789abcdeffedcba9876543210
+       ad04354d8aa2a623e72e3594ee3535c0;
+}
diff --git a/symm/t/rmd160 b/symm/t/rmd160
new file mode 100644 (file)
index 0000000..d6c7882
--- /dev/null
@@ -0,0 +1,109 @@
+# Test vectors for RIPEMD-160
+
+# --- Basic hash function ---
+#
+# Taken from http://wwww.esat.kuleuven.ac.be/~bosselae/ripemd160.html
+
+rmd160 {
+  ""                   9c1185a5c5e9fc54612808977ee8f548b2258d31;
+  "a"                  0bdc9d2d256b3ee9daae347be6f4dc835a467ffe;
+  "abc"                        8eb208f7e05d987a9b044a8e98c6b087f15a0bfc;
+  "message digest"     5d0689ef49d2fae572b881b123a85ffa21595f36;
+  "abcdefghijklmnopqrstuvwxyz"
+                       f71c27109c692c1b56bbdceb5b9d2865b3708dbc;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+                       12a053384a9c0c88e405a06c27dcf49ada62eb2b;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+                       b0e20b6e3116640286ed3a87a5713079b21f5189;
+}
+
+rmd160-rep {
+  "1234567890" 8 9b752e45573d4b39f4dbd3323cab82bf63326bfb;
+  "a" 1000000 52783243c1697bdbe16d37f97f68f08325dc1528;
+}
+
+# --- HMAC mode ---
+
+rmd160-hmac {
+  # --- Test vectors from RFC2286 ---
+
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668;
+
+  "what do ya want for nothing?"
+       4a656665
+       dda6c0213a485a9e24f4742064a7f033b43c4069;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       b0b105360de759960ab4f35298e116e295d8e7c1;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       7619693978f91d90539ae786500ff3d8e0518e39;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       6466ca07ac5eac29e1bd523e5ada7605b791fd8b;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       69ea60798d71616cce5fd0871e23754cd75d5a0a;
+
+  # --- From http://wwww.esat.kuleuven.ac.be/~bosselae/ripemd160.html ---
+
+  ""
+       00112233445566778899aabbccddeeff01234567
+       cf387677bfda8483e63b57e06c3b5ecd8b7fc055;
+  "a"
+       00112233445566778899aabbccddeeff01234567
+       0d351d71b78e36dbb7391c810a0d2b6240ddbafc;
+  "abc"
+       00112233445566778899aabbccddeeff01234567
+       f7ef288cb1bbcc6160d76507e0a3bbf712fb67d6;
+  "message digest"
+       00112233445566778899aabbccddeeff01234567
+       f83662cc8d339c227e600fcd636c57d2571b1c34;
+  "abcdefghijklmnopqrstuvwxyz"
+       00112233445566778899aabbccddeeff01234567
+       843d1c4eb880ac8ac0c9c95696507957d0155ddb;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       00112233445566778899aabbccddeeff01234567
+       60f5ef198a2dd5745545c1f0c47aa3fb5776f881;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       00112233445566778899aabbccddeeff01234567
+       e49c136a9e5627e0681b808a3b97e6a6e661ae79;
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+       00112233445566778899aabbccddeeff01234567
+       31be3cc98cee37b79b0619e3e1c2be4f1aa56e6c;
+
+  ""
+       0123456789abcdeffedcba987654321000112233
+       fe69a66c7423eea9c8fa2eff8d9dafb4f17a62f5;
+  "a"
+       0123456789abcdeffedcba987654321000112233
+       85743e899bc82dbfa36faaa7a25b7cfd372432cd;
+  "abc"
+       0123456789abcdeffedcba987654321000112233
+       6e4afd501fa6b4a1823ca3b10bd9aa0ba97ba182;
+  "message digest"
+       0123456789abcdeffedcba987654321000112233
+       2e066e624badb76a184c8f90fba053330e650e92;
+  "abcdefghijklmnopqrstuvwxyz"
+       0123456789abcdeffedcba987654321000112233
+       07e942aa4e3cd7c04dedc1d46e2e8cc4c741b3d9;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       0123456789abcdeffedcba987654321000112233
+       b6582318ddcfb67a53a67d676b8ad869aded629a;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       0123456789abcdeffedcba987654321000112233
+       f1be3ee877703140d34f97ea1ab3a07c141333e2;
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+       0123456789abcdeffedcba987654321000112233
+       85f164703e61a63131be7e45958e0794123904f9;
+}
diff --git a/symm/t/rmd256 b/symm/t/rmd256
new file mode 100644 (file)
index 0000000..c998667
--- /dev/null
@@ -0,0 +1,59 @@
+# Test vectors for RIPEMD-256
+
+# --- Basic hash function ---
+#
+# Taken from the authors' web pages.
+
+rmd256 {
+  ""
+       02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d;
+  "a"
+       f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925;
+  "abc"
+       afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65;
+  "message digest"
+       87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e;
+  "abcdefghijklmnopqrstuvwxyz"
+       649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8;
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+       06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd;
+}
+
+# --- HMAC mode ---
+#
+# I couldn't find any official test vectors.  These are therefore generated
+# using the Catacomb implementation.
+
+rmd256-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       c1829c0d5a203bbf6e874a721d55ffec22456f3a0987e30a4861a40cad5dc9e7;
+
+  "what do ya want for nothing?"
+       4a656665
+       932d3e799272765675dd63c33f8d2815ea38181494f43271dd52fde91392619f;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       a30051679681f54ad62088438a308c3dd38cc0eb2d352fbdcfb2811abf9c1e29;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       d55d1a9b2082105103d8331581d9522d17b4cce92e95f0f4654ce8da187ffbbb;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       cc8e435de509ef9a974cecb40cdecf55c8e6a22d5458e74cb7b0a306453ad67d;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       821543a295eccf093af9b461f630d7c49206fb2158e5ac89e73a02cf089528ed;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       ca26edc0129a781f1224cc6c9f655052f120edb5842bcfcf4b8d0f8b8be551bd;
+}
diff --git a/symm/t/rmd320 b/symm/t/rmd320
new file mode 100644 (file)
index 0000000..783bc7b
--- /dev/null
@@ -0,0 +1,59 @@
+# Test vectors for RIPEMD-320
+
+# --- Basic hash function ---
+#
+# Taken from the authors' web pages.
+
+rmd320 {
+  ""
+       22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8;
+  "a"
+       ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d;
+  "abc"
+       de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d;
+  "message digest"
+       3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197;
+  "abcdefghijklmnopqrstuvwxyz"
+       cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4;
+  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+       557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42;
+}
+
+# --- HMAC mode ---
+#
+# I couldn't find any official test vectors.  These are therefore generated
+# using the Catacomb implementation.
+
+rmd320-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       03ec929cb94837c2acd709d03f4a26c3e38c7cec4fe2f5caff3b64e168321c8591b1d3ffeb87b9f4;
+
+  "what do ya want for nothing?"
+       4a656665
+       e440b00b6326e4f7dad3a6591e8189e9708fc17e3cab306fc67efaf70947aad2ea89e28f79d03bd3;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       8c7ee84fb76703386f01f088cbe0ed9a694d6e0c9bfbe1c7785f56cafc5908db2e16afcb0721edae;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       714f482ff865edbbcbfb344948ce3c8b9d2308650f2f0ed2111a6983509c967416e092e9f6b307d0;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       f0b1c83e3cec672db53c259746de4d13841e01dd6266c360fda76f3197ac47582c5e9b59d7a8a7b9;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       a61c1123c1a23ffdd9af5fb28b62b95f989876ac322452f5e4f4470c25182ef4816aaec7f0377167;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       5e5d0fe86d7f8ff85108bbf75cf25dd99e8029237b93ff0d93fb779264a103082cc62ad8914feed3;
+}
diff --git a/symm/t/safer b/symm/t/safer
new file mode 100644 (file)
index 0000000..1279b75
--- /dev/null
@@ -0,0 +1,8 @@
+# Test vectors for SAFER
+
+# From HAC 7.114, and Richard de Moliner's implementation
+
+safer {
+  0807060504030201 0102030405060708 c8f29cdd87783ed9;
+  100f0e0d0c0b0a090807060504030201 0102030405060708 4a99b15cce9ada19;
+}
diff --git a/symm/t/safersk b/symm/t/safersk
new file mode 100644 (file)
index 0000000..ac83b5b
--- /dev/null
@@ -0,0 +1,8 @@
+# Test vectors for SAFER
+
+# From HAC 7.114, and Richard de Moliner's implementation
+
+safersk {
+  0102030405060708 0102030405060708 60d04ad7c49b8ded;
+  100f0e0d0c0b0a090807060504030201 0102030405060708 b260740f80d2445d;
+}
diff --git a/symm/t/seal b/symm/t/seal
new file mode 100644 (file)
index 0000000..c338c32
--- /dev/null
@@ -0,0 +1,6 @@
+# Test vectors for SEAL
+
+seal {
+  67452301efcdab8998badcfe10325476c3d2e1f0 0x013577af
+  9505a0379cc4849b051ebea40f537306fd97b05fbd3fa1f6cdde2c6c7ceefd81e7c3bd2aff9a20648322a100855067ef534b63c1e6599028d95eaba7eb010c48;
+}
similarity index 100%
rename from tests/serpent.aes
rename to symm/t/serpent.aes
diff --git a/symm/t/sha b/symm/t/sha
new file mode 100644 (file)
index 0000000..9ae4f4b
--- /dev/null
@@ -0,0 +1,61 @@
+# Test vectors for the SHA-1 hash function
+
+# --- Basic hash function ---
+#
+# Some of these are taken directly from the Secure Hash Standard
+# (FIPS 180-1).  Others were generated using the SSLeay implementation of
+# SHA-1.
+
+sha {
+  ""                   da39a3ee5e6b4b0d3255bfef95601890afd80709;
+  "a"                  86f7e437faa5a7fce15d1ddcb9eaeaea377667b8;
+  "abc"                        a9993e364706816aba3e25717850c26c9cd0d89d;
+  "message digest"     c12252ceda8be8994d5fa0290a47231c1d16aae3;
+  "abcdefghijklmnopqrstuvwxyz"
+                       32d10c7b8cf96570ca04ce37f2a19d84240d3a89;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+                       84983e441c3bd26ebaae4aa1f95129e5e54670f1;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+                       761c457bf73b14d27e9e9265c46f4b4dda11f940;
+}
+
+sha-rep {
+  "1234567890" 8       50abf5706a150990a08b2c5ea40fa0e585554732;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+" 23                   f74d36bf17ee23c46ec166a48a24da6ab999eaea;
+  "a" 1000000          34aa973cd4c4daa4f61eeb2bdbad27316534016f;
+}
+
+# --- HMAC mode ---
+#
+# Test vectors from RFC2202.
+
+sha-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       b617318655057264e28bc0b6fb378c8ef146be00;
+
+  "what do ya want for nothing?"
+       4a656665
+       effcdf6ae5eb2fa2d27416d5f184df9c259a7c79;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       125d7342b9ac11cd91a39af48aa17b4f63f175d3;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       4c9007f4026250c6bc8414f9bf50c86c2d7235da;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       4c1a03424b55e07fe7f27be1d58bb9324a9a5a04;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       aa4ae5e15272d00e95705637ce8a3b55ed402112;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       e8e99d0f45237d786d6bbaa7965c7808bbff1a91;
+}
diff --git a/symm/t/sha224 b/symm/t/sha224
new file mode 100644 (file)
index 0000000..35e1171
--- /dev/null
@@ -0,0 +1,72 @@
+# Test vectors for SHA-224
+
+# --- Basic hash function ---
+
+sha224 {
+
+  # --- Test vectors from the definition [FALSE] ---
+
+  "abc"
+       23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525;
+
+  # --- Other tests to trap regression ---
+
+  ""
+       d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f;
+  "a"
+       abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5;
+  "message digest"
+       2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb;
+  "abcdefghijklmnopqrstuvwxyz"
+       45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9;
+}
+
+sha224-rep {
+  "1234567890" 8
+       b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+" 23
+       5a86156c37c95ab356e003d569370580737794815f46de7f4834d634;
+  "a" 1000000
+       20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67;
+}
+
+# --- HMAC mode ---
+#
+# Autogenerated, unofficial.
+
+sha224-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       1abbc7c42cf4ca9f9d7b624564cb72d7b0945ea0a615095904a0fd34;
+
+  "what do ya want for nothing?"
+       4a656665
+       a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       5121d4bc8e43ee3ddcc2b0d312c110e961fc34b19ced1cce11c7a55c;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       0f081672137307d07aad12880537cd43f454823de00c038424741e17;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       9ed2eebc0ed23576efc815e9b5bc0d9257e36d13e4dd5d5f0c809b38;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       7358939e58683a448ac5065196d33191a1c1d33d4b8b0304dc60f5e0;
+}
diff --git a/symm/t/sha256 b/symm/t/sha256
new file mode 100644 (file)
index 0000000..f4561e8
--- /dev/null
@@ -0,0 +1,71 @@
+# Test vectors for SHA-256
+
+# --- Basic hash function ---
+
+sha256 {
+
+  # --- Test vectors from the definition ---
+
+  "abc"
+       ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1;
+
+  # --- Other tests to trap regression ---
+
+  ""
+       e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855;
+  "a"
+       ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb;
+  "message digest"
+       f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650;
+  "abcdefghijklmnopqrstuvwxyz"
+       71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0;
+}
+
+sha256-rep {
+  "1234567890" 8
+       f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+" 23 4804a2a4759acebe127b62ba651ae601a756ca0b509e4987498224acaffb0d98;
+  "a" 1000000
+       cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0;
+}
+
+# --- HMAC mode ---
+#
+# Autogenerated, unofficial.
+
+sha256-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       198a607eb44bfbc69903a0f1cf2bbdc5ba0aa3f3d9ae3c1c7a3b1696a0b68cf7;
+
+  "what do ya want for nothing?"
+       4a656665
+       5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       cdcb1220d1ecccea91e53aba3092f962e549fe6ce9ed7fdc43191fbde45c30b0;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       7546af01841fc09b1ab9c3749a5f1c17d4f589668a587b2700a9c97c1193cf42;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       6953025ed96f0c09f80a96f78e6538dbe2e7b820e3dd970e7ddd39091b32352f;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       6355ac22e890d0a3c8481a5ca4825bc884d3e7a1ff98a2fc2ac7d8e064c3b2e6;
+}
diff --git a/symm/t/sha384 b/symm/t/sha384
new file mode 100644 (file)
index 0000000..f3148fd
--- /dev/null
@@ -0,0 +1,72 @@
+# Test vectors for SHA-384
+
+# --- Basic hash function ---
+
+sha384 {
+
+  # --- Test vectors from the definition ---
+
+  "abc"
+       cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7;
+  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+       09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039;
+
+  # --- Other tests to trap regression ---
+
+  ""
+       38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b;
+  "a"
+       54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31;
+  "message digest"
+       473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5;
+  "abcdefghijklmnopqrstuvwxyz"
+       feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84;
+}
+
+sha384-rep {
+  "1234567890" 8
+       b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+" 23
+       f77d169c73427bd30cceff74f822a0209657dfb78c07980509bf8452a3c5d671b7198081898d0a0034e0f7151211fa0f;
+  "a" 1000000
+       9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985;
+}
+
+# --- HMAC mode ---
+#
+# Autogenerated, unofficial.
+
+sha384-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       b6a8d5636f5c6a7224f9977dcf7ee6c7fb6d0c48cbdee9737a959796489bddbc4c5df61d5b3297b4fb68dab9f1b582c2;
+
+  "what do ya want for nothing?"
+       4a656665
+       af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       809f439be00274321d4a538652164b53554a508184a0c3160353e3428597003d35914a18770f9443987054944b7c4b4a;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f30313233343536373839
+       b8405cddb33af1a68a1a71a8a4e6189a724fe28209671d701f7ecd4582d4db61b3a31ddca42a0db4efa2c5caf7a0482c;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       3b44c978360a9da6eba51d8186dd879bac52801ba2cba0afcb0f612f3305668accf4d5367a686e547426abfe7832f8ba;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       39cc73806611492e9179e2c23cebddd61c240b0b9c5a095db35f978d48642a1a49a2dde075f2b54cefbae7fe0aed4909;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Bearing In Mind That This Hash Has An Extraordinarily Large Block Size So The Standard Test Won't Work"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       f9ac83e56d205edb71774e0d1ee102330583c474020bcbe52f02384f6fdf09e7e8b75495d74eea4788c17e48e64d6888;
+}
diff --git a/symm/t/sha512 b/symm/t/sha512
new file mode 100644 (file)
index 0000000..dcf3f04
--- /dev/null
@@ -0,0 +1,73 @@
+# Test vectors for SHA-512
+
+# --- Basic hash function ---
+
+sha512 {
+
+  # --- Test vectors from the definition ---
+
+  "abc"
+       ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f;
+  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+       8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909;
+
+  # --- Other tests to trap regression ---
+
+  ""
+       cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e;
+  "a"
+       1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75;
+  "message digest"
+       107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c;
+  "abcdefghijklmnopqrstuvwxyz"
+       4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1;
+  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+       204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+       1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894;
+}
+
+sha512-rep {
+  "1234567890" 8
+       72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843;
+
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
+" 23
+       4def32cfb1107a104eae530fe04326a57e839a0bd9675f6770ff18d0b3b3ee2d4343bf99e9d54adc272617d49d0f61eab4b4bc177f9d2bac086cd2d902b5780e;
+  "a" 1000000
+       e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b;
+}
+
+# --- HMAC mode ---
+#
+# Autogenerated, unofficial.
+
+sha512-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0bb0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       bb969b8e6b99529a2e09757ef582257aed4f66cb62f1b32150b969eaa7dd683d46a776726cbf0f614f784cfa0759e84ba1d0baf07a1391ed998da6ea2fd7ff53;
+
+  "what do ya want for nothing?"
+       4a656665
+       164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       2ee7acd783624ca9398710f3ee05ae41b9f9b0510c87e49e586cc9bf961733d8623c7b55cebefccf02d5581acc1c9d5fb1ff68a1de45509fbe4da9a433922655;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f30313233343536373839
+       005a43d33fe40a285dc0947121984509698d4533519662c5eda2f8fac7a6b69f78ce84b61b1427d8dc88046aa1f35c6513b467185de195deb4dee3367b55d38d;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       54701368cc706f527661ec9617d506ab255890b7c0cd8318f2efcf2b1bfbac560a77c369bdc01220d652e79747c0fa465da176e34b0de91cf075db0a12ac0ab5;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       ae52fbcfb432b5963d1fa0b38a584554752d41f5b4de82483ec1f32de676ae708fc20ffa3bc6525f3d4115eda6b145bf123ed5acf6cbb0ee7f7bf625402609fd;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Bearing In Mind That This Hash Has An Extraordinarily Large Block Size So The Standard Test Won't Work"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       062d5553721e9512a061feaa8a236a5c2c5a45f25ed3ebe9c7337f3bc26b65d8ba3e1bd061b53fe45ac03800aeee4b48c6f2f3bd955c32991bd2bfaf2b1c05a3;
+}
diff --git a/symm/t/skipjack b/symm/t/skipjack
new file mode 100644 (file)
index 0000000..63ac0cb
--- /dev/null
@@ -0,0 +1,101 @@
+# Test vectors for Skipjack
+
+# --- From the Skipjack definition ---
+
+skipjack {
+
+  # --- The official Skipjack test vector ---
+  #
+  # It's a bit piss-poor that they only provide one test-vector here.
+
+  00998877665544332211 33221100ddccbbaa 2587cae27a12d300;
+
+  # --- From KEA test vectors ---
+  #
+  # The Skipjack algorithm is used by the KEA to derive the final key.
+  # Unfortunately, the test vectors given in the Skipjack/KEA spec don't
+  # match my (or anyone else's!) implementation.  These are the values
+  # which seem to be generally agreed.
+
+  e7496e99e4628b7f9ffb 99ccfe2b90fd550b 60a73d387b517fca;
+  e7496e99e4628b7f9ffb 60a73d387b517fca 24c90cb05d668b27;
+  e5caf4dcc70e55f1dd90 b71cb0d009af2765 64f4877ae68a8a62;
+  e5caf4dcc70e55f1dd90 64f4877ae68a8a62 fee778a838a601cd;
+
+  # --- These are the results expected from the KEA spec ---
+  #
+  # A `?' indicates that I don't know what that digit's meant to be.  I've
+  # derived the top 16 bits of the intermediate results from the spec.
+
+# e7496e99e4628b7f9ffb 99ccfe2b90fd550b 2f30????????????;
+# e7496e99e4628b7f9ffb 2f30???????????? 740839dee833add4;
+# e5caf4dcc70e55f1dd90 b71cb0d009af2765 8e27????????????;
+# e5caf4dcc70e55f1dd90 8e27???????????? 97fd1c6bd86bc439;
+
+  # --- Some more test vectors ---
+  #
+  # These are dreamed up by me.  The above tests don't actually exhaustively
+  # test the F-table.  There are 16 entries unaccounted for.  The keys and
+  # plaintexts were generated using fibrand with seed 0.
+
+  cde4bef260d7bcda1635 47d348b7551195e7 f17b3070144aebea;
+  7022907dd1dff7dac5c9 941d26d0c6eb14ad a055d02c5e0eae8d;
+  568f86edd1dc9268eeee 533285a6ed810c9b b4c22f4fb74c35dc;
+  689daaa9060d2d4b6003 062365b0a54364c7 08698d8786f80d16;
+  6c160f11896c4794846e cfa14a7130c9f137 d6db848b7cecdd39;
+
+  # --- And some more, posted to Usenet ---
+  #
+  # Message-id <8m7slq$1i1$1@hecate.umd.edu>
+
+  f8da02647722f7103adf 1ddf39abf5cd711e c92d22324c6b31ae;
+  82760ac137948821eee4 dd6c6cce8f83e69e e32877c1d9527fff;
+  843c1687d3cdca5fc5c3 beaacf177fa41a11 4745783f75b8861a;
+  ae870cd7ff33a995f7e5 c4c09f216c1bc60a 5c101636b8a57a72;
+  5ccbd913ea8b73bd6391 d3f814b000245856 b4fc0f8e54728f91;
+  f65e74cd599c68a40cc7 356ec7d93832329c 93b750608f5701f8;
+  aa106e46d7087c4e93dc 209ecf1c537ad56c d823d45510099e61;
+  a93f9789a20c3cc34fea 892eea9d64e17d66 0959e231b275d95f;
+  88b163cbd61616888899 991390fd760fc91b e7700209886767ae;
+  fb6cd1ff70487561df10 daebc947ddca9c9e e7cc49a56bd6a322;
+  5edc1ac0c4e7ef5f002c 6419ddefe2cd8f2e e48a05cf26e242fd;
+  8e3090c19aa32f94496a 322998ecbd068112 62c0e537b14df2c1;
+  b96e3fd46fa4263f9092 3aae2aee20da93cc 54d1e58a6b624d71;
+  9e6635baee28c5bce2bc 14311112ca11f727 5d0f235a9d221ce0;
+  04127ce16dc1b1726a66 300e4313e7ad6796 8e5b03522e68cbeb;
+  f0b89d75e979ccc9b172 09cd1c1accbe7797 572c9b4025a9134b;
+  f9bfc78798cbf1bcd4b5 31b30ca354af3cd8 8c959c904789fbda;
+  f43a51b4273bde27d2b0 08c59b0db99ec267 b7d7f5fa342988fb;
+  cd51f0a75aa73c48edd2 9784b1e3e7e60e60 763aa8ee109397b3;
+  b3319a3f6622aa726bb3 f65216373d4b43c7 0325600337b8ad3c;
+  493254c9596e993f5f9c cba4c1215d5d36ce 68e1c551c59108c0;
+  76150c2c3ced1c7ca021 82294851288e75cb 7eb6325d82a2096c;
+  7140d6c5486305872df6 c3a7b7e4a52e407b 2483f385a42ee3c6;
+  3c2c3901f0ee9a3b2b0e 1bfde32ab559e13a d6fa9db8685fd88a;
+  606a8b4bdfaae8a0ba51 d205f7486c782838 0330489170b85293;
+  7847a47a0fe79ab770ce d96ff1f7c7fc60e0 1f9b3301c9b2708c;
+  73b9ab0c36c99e91a891 241d4bde19a75f8f 2b86c57ffe168895;
+  a37f2ad5a85e170741f5 7be1b8d58321c619 5af7ceb3eed9dca1;
+  f7b0c2a8170e3c4e48b3 c9214ea01ec14948 1b587736e116c04b;
+  a1fc67e44eacacf4a902 e2a3091feb581588 f3ecf0f1789a3923;
+  f14430affc5fe82a9ae9 3cb466d301b60854 e8d114c20ffa1c79;
+  fd26df50486a4cd96d9b b0684f8a5e63d935 222903994d64fe3a;
+  a6d46d46ca287e1a332a ba1f37e88edec55f 91f2baad6fa0de55;
+  83c3f1cb8d06efc6196b e9fed8501b7a6579 83f9f08f89a854ee;
+  0edfa44c7d4a4ef0725e eb5ca8b3fa1fcdbb 2b1b6670a6be0324;
+  b8edcf167d99a711ccee b8b525c6382af277 211a695da473766f;
+  4f639e0d5a5d2ad7e9a4 9162e781ff683853 eb2976370d22ef22;
+  37e006256a4ae6d320c4 c9f23a20a39ded11 dba4c0ef0ea098c0;
+  e41d0bd25f931ba1d85c 5a6f12f32f7eefdf 923daee8000709f9;
+  fdf65bbc5fe600f3cd68 cad5414c1c64f194 d5771e78b6f1fe1e;
+  1c269af2ff166acb27ef 063a58a20b45378f 634f7a3861af97a1;
+  1179f64acb6122ccf649 08fbf42b4313347b 3a803a4bd0e8c3e6;
+  078c87265eb8da323e90 6d4ed0e9930532d1 f4fa372e7e1441a1;
+  2fff35f8eb774c843bb0 40b699812345661d 63a9197f7b75f53f;
+  09f77346a4393ce99856 22ed54626a51e505 e91a050a7481b3dd;
+  5b878e0b22a705acf8fb 0c489b66e2da531b 6e9370a91b994878;
+  9d72c1ab2092c1b10877 c64b10f8b191bc2c 5bdecded96d656c9;
+  72865f289725e1b55502 91fdf7236f85bdd6 1a5680e51736026f;
+  06e3c0e541f4aae6fe93 40009f8a465a9feb 0e7aace421bc79d8;
+  2ea09f1cc89e064f09bc 543208b05bfa3858 a95d87fad12c3593;
+}
diff --git a/symm/t/square b/symm/t/square
new file mode 100644 (file)
index 0000000..7b348e2
--- /dev/null
@@ -0,0 +1,523 @@
+# Test vectors for the Square block cipher
+
+square {
+  # --- From the reference implementation ---
+
+  000102030405060708090a0b0c0d0e0f
+       000102030405060708090a0b0c0d0e0f 7c3491d94994e70f0ec2e7a5ccb5a14f;
+
+  # --- From the validation data ---
+
+  80000000000000000000000000000000
+       00000000000000000000000000000000 05f8aafdefb4f5f9c751e5b36c8a37d8;
+  40000000000000000000000000000000
+       00000000000000000000000000000000 60affc9b2312b1397177251cc9296391;
+  20000000000000000000000000000000
+       00000000000000000000000000000000 d67b7e07c38f311446e16ddd9ea96ebe;
+  10000000000000000000000000000000
+       00000000000000000000000000000000 39207579067031706fab8c3a5c6e5524;
+  08000000000000000000000000000000
+       00000000000000000000000000000000 fc4f2602a3f6ac34f56906c2eeee40c5;
+  04000000000000000000000000000000
+       00000000000000000000000000000000 6f2431469f4a0866632216c59c18ff11;
+  02000000000000000000000000000000
+       00000000000000000000000000000000 c745f6f339d1bb9524e1b2d2b0dde843;
+  01000000000000000000000000000000
+       00000000000000000000000000000000 241e113a1bb5c32cc45d95d7734165aa;
+  00800000000000000000000000000000
+       00000000000000000000000000000000 5e16777211c67ae4609f6a47bf5df2c4;
+  00400000000000000000000000000000
+       00000000000000000000000000000000 272330139236c300cd161f0266b62494;
+  00200000000000000000000000000000
+       00000000000000000000000000000000 15115b9e29524325e7c992ead262ade8;
+  00100000000000000000000000000000
+       00000000000000000000000000000000 acdcce277b801ed53dfe0fc12f4c957b;
+  00080000000000000000000000000000
+       00000000000000000000000000000000 9cadb290cedd6f7ca6c10d42fe4c1a70;
+  00040000000000000000000000000000
+       00000000000000000000000000000000 d70d4c24ffbf3de6e6bd54ec03b8492a;
+  00020000000000000000000000000000
+       00000000000000000000000000000000 602455a418a99a942fed27123b9f73e6;
+  00010000000000000000000000000000
+       00000000000000000000000000000000 f239c4efd3729d43081544104378f0ea;
+  00008000000000000000000000000000
+       00000000000000000000000000000000 70259a9572990099ac563114074db3d2;
+  00004000000000000000000000000000
+       00000000000000000000000000000000 932d3644863b6377100c64f243445e7e;
+  00002000000000000000000000000000
+       00000000000000000000000000000000 47100bf12f2e1f718e9430f4127535be;
+  00001000000000000000000000000000
+       00000000000000000000000000000000 2ed60ffa71c162a53c3a8bba2b0b042b;
+  00000800000000000000000000000000
+       00000000000000000000000000000000 e2992d6bdc7c65b70b62685c0d84425c;
+  00000400000000000000000000000000
+       00000000000000000000000000000000 c552ca3d805e456f5239dd7956cacd71;
+  00000200000000000000000000000000
+       00000000000000000000000000000000 95b577c2ed3c2d9d96c2106e091b1f72;
+  00000100000000000000000000000000
+       00000000000000000000000000000000 3d550ae470bfb0306c3099c8d5a471d8;
+  00000080000000000000000000000000
+       00000000000000000000000000000000 fc13974afe73a92598aa95edcb2102e9;
+  00000040000000000000000000000000
+       00000000000000000000000000000000 ab0cf3a0cfef3aa3d10738523e624a1d;
+  00000020000000000000000000000000
+       00000000000000000000000000000000 72fea53144f673e283547f08da30bdda;
+  00000010000000000000000000000000
+       00000000000000000000000000000000 389fef99fa1a3dbf664673aa39d848d1;
+  00000008000000000000000000000000
+       00000000000000000000000000000000 041152bca8440e8de572dce9dcc88cdc;
+  00000004000000000000000000000000
+       00000000000000000000000000000000 845b37c1338a0ba0f295be273841b940;
+  00000002000000000000000000000000
+       00000000000000000000000000000000 e2e3a1c7998040ee6bd8714e65ebd8af;
+  00000001000000000000000000000000
+       00000000000000000000000000000000 0b2b34c480648dc91f938dd368464780;
+  00000000800000000000000000000000
+       00000000000000000000000000000000 96bad4a54376917044b1076727a91e2b;
+  00000000400000000000000000000000
+       00000000000000000000000000000000 dd8c3dff69c3fda2802dffcdef1b1631;
+  00000000200000000000000000000000
+       00000000000000000000000000000000 da45872e48af2f0ec7fc395d03ff9451;
+  00000000100000000000000000000000
+       00000000000000000000000000000000 b25194c0f1953f35bc4c0871cd2d4a40;
+  00000000080000000000000000000000
+       00000000000000000000000000000000 3e09af82736971f2847834082d6ec6f3;
+  00000000040000000000000000000000
+       00000000000000000000000000000000 fa75a64f778b914dc4b926626bc8b4c0;
+  00000000020000000000000000000000
+       00000000000000000000000000000000 d21542857f03f6a92cacd2e783e33e3e;
+  00000000010000000000000000000000
+       00000000000000000000000000000000 1ec0a5b9781c5e90b1e15731e0625c36;
+  00000000008000000000000000000000
+       00000000000000000000000000000000 e1c58917e586b6c46c46982fa303f14c;
+  00000000004000000000000000000000
+       00000000000000000000000000000000 72ecc0d267b445482924c9969de97a15;
+  00000000002000000000000000000000
+       00000000000000000000000000000000 a52af631193375dd59555e2753acde65;
+  00000000001000000000000000000000
+       00000000000000000000000000000000 033b8482c4010eb20a3edd4ba35a3db7;
+  00000000000800000000000000000000
+       00000000000000000000000000000000 56534a944796abdf51ad247b8c9ee9bb;
+  00000000000400000000000000000000
+       00000000000000000000000000000000 9eda6fd2cd4eabf8218b98a165e82b9e;
+  00000000000200000000000000000000
+       00000000000000000000000000000000 60043a7e110e1321bc41e4ac47d1f45e;
+  00000000000100000000000000000000
+       00000000000000000000000000000000 90e685c8f990cedeacc8a2bfc8e46ca2;
+  00000000000080000000000000000000
+       00000000000000000000000000000000 b9e77e32f721c0a7a02b50925311e834;
+  00000000000040000000000000000000
+       00000000000000000000000000000000 001d2fe95bb39ef0c3548307ea7580f3;
+  00000000000020000000000000000000
+       00000000000000000000000000000000 a5dd651290a063f4e7c5e714c9c398b4;
+  00000000000010000000000000000000
+       00000000000000000000000000000000 aa7b3b9f459ba0367ff2a332ef725da1;
+  00000000000008000000000000000000
+       00000000000000000000000000000000 a424f80b0048756879ed6343768bbe08;
+  00000000000004000000000000000000
+       00000000000000000000000000000000 ea4590786de7f8a68439b4616bf7e4b9;
+  00000000000002000000000000000000
+       00000000000000000000000000000000 7d15058fe884dcf0976105a816cf6366;
+  00000000000001000000000000000000
+       00000000000000000000000000000000 a07d1b74ae6a3f26a8a25e1e778a0d4a;
+  00000000000000800000000000000000
+       00000000000000000000000000000000 61f13db32828961c3e35d9b7ab77b57d;
+  00000000000000400000000000000000
+       00000000000000000000000000000000 0e2979112efb29754605011a358093fc;
+  00000000000000200000000000000000
+       00000000000000000000000000000000 a878c8a8a5230917c56f7eb74fdada25;
+  00000000000000100000000000000000
+       00000000000000000000000000000000 34343f73232790e6fa44d8f606a24de9;
+  00000000000000080000000000000000
+       00000000000000000000000000000000 d569b991761c26dde723cca0c262f195;
+  00000000000000040000000000000000
+       00000000000000000000000000000000 f1a0f35ada018c5df56ffe0dc95636bf;
+  00000000000000020000000000000000
+       00000000000000000000000000000000 b26af455039312e1206290a921459e1a;
+  00000000000000010000000000000000
+       00000000000000000000000000000000 594049c7e3a34e1b9bccefaf5e75b373;
+  00000000000000008000000000000000
+       00000000000000000000000000000000 4e4e037f07ff26e8e9065f26afedaf2d;
+  00000000000000004000000000000000
+       00000000000000000000000000000000 ddedc3ca10ec011ea24dd4566d21409c;
+  00000000000000002000000000000000
+       00000000000000000000000000000000 3660f51bb790f275a55aa435db6da193;
+  00000000000000001000000000000000
+       00000000000000000000000000000000 a9a7cfe07ea640498e832ae25e2906ed;
+  00000000000000000800000000000000
+       00000000000000000000000000000000 3863d1c222a36338ea6d402073341f42;
+  00000000000000000400000000000000
+       00000000000000000000000000000000 ced5dfdf8b5d1d60e9ad51830a7965a9;
+  00000000000000000200000000000000
+       00000000000000000000000000000000 4ffae5d7a5689a5584330cb0a5cc9cd2;
+  00000000000000000100000000000000
+       00000000000000000000000000000000 1dd688d47541463915f658bb656420b4;
+  00000000000000000080000000000000
+       00000000000000000000000000000000 ef3a1c1800dd3cda748fbdf17086ba4f;
+  00000000000000000040000000000000
+       00000000000000000000000000000000 f9aa9b3e76543ef12f7f8b87ce393328;
+  00000000000000000020000000000000
+       00000000000000000000000000000000 1813935bb67dc40dc37c68cc2999758a;
+  00000000000000000010000000000000
+       00000000000000000000000000000000 8c4916d59fce8eb913b128f2d7b3d464;
+  00000000000000000008000000000000
+       00000000000000000000000000000000 bb88da704c5ce031c61954efcae6ed2d;
+  00000000000000000004000000000000
+       00000000000000000000000000000000 4e463bceb0f52c3f722e2926c2bd04a3;
+  00000000000000000002000000000000
+       00000000000000000000000000000000 4a6181492a454604293396bbd21c4956;
+  00000000000000000001000000000000
+       00000000000000000000000000000000 801f29d5462365735a6ca7a64288f48c;
+  00000000000000000000800000000000
+       00000000000000000000000000000000 7933733c4daab746ef048edba2d05538;
+  00000000000000000000400000000000
+       00000000000000000000000000000000 4127c1d95431fd2632f2b5e5085a3dd8;
+  00000000000000000000200000000000
+       00000000000000000000000000000000 0588168ca7525333460c4030af266388;
+  00000000000000000000100000000000
+       00000000000000000000000000000000 32b3f193d7237b48883de002b3cbe1c3;
+  00000000000000000000080000000000
+       00000000000000000000000000000000 7ca557bc05b845a233c01412022da825;
+  00000000000000000000040000000000
+       00000000000000000000000000000000 54f11361ad6dfbb069be67536cc98d81;
+  00000000000000000000020000000000
+       00000000000000000000000000000000 a9df031b4e25e89f527efff89cb0beba;
+  00000000000000000000010000000000
+       00000000000000000000000000000000 7da4d0d6309906d935ba27ae00cfaf33;
+  00000000000000000000008000000000
+       00000000000000000000000000000000 e231ea0fec29d983d3236bb15e7cd1da;
+  00000000000000000000004000000000
+       00000000000000000000000000000000 fe1b963a4f596422a6cd7787f4ab3377;
+  00000000000000000000002000000000
+       00000000000000000000000000000000 848833f2f7a247d2e1d0c8614694139f;
+  00000000000000000000001000000000
+       00000000000000000000000000000000 630bb1dc4e60d3272b6b673bdb918b20;
+  00000000000000000000000800000000
+       00000000000000000000000000000000 500251a5c6ad5a6d2f218a3fd5765727;
+  00000000000000000000000400000000
+       00000000000000000000000000000000 d019ef316e84149cfd0e85665aa2fff5;
+  00000000000000000000000200000000
+       00000000000000000000000000000000 db0b5ac0e8ef011d710323fa3b8bb3a7;
+  00000000000000000000000100000000
+       00000000000000000000000000000000 207e46a533617374d2c9da0c92ffd620;
+  00000000000000000000000080000000
+       00000000000000000000000000000000 8273ca155249f9f1ad8cc2ca114984f3;
+  00000000000000000000000040000000
+       00000000000000000000000000000000 82a73a18aae84ad671e226470f246e1a;
+  00000000000000000000000020000000
+       00000000000000000000000000000000 3e0e1206e333917d4c250bd82fef6afd;
+  00000000000000000000000010000000
+       00000000000000000000000000000000 2182f67239be15c796439ea3791202e1;
+  00000000000000000000000008000000
+       00000000000000000000000000000000 486fb3fa7b1fe1a304cb4e8960c3c6bb;
+  00000000000000000000000004000000
+       00000000000000000000000000000000 c1de50e456c4308d5d70da141cef0b4f;
+  00000000000000000000000002000000
+       00000000000000000000000000000000 a623f24515a27cee3dad277429000218;
+  00000000000000000000000001000000
+       00000000000000000000000000000000 02fa5762f9cd90201565bce71140c6f4;
+  00000000000000000000000000800000
+       00000000000000000000000000000000 a643a0ca5154a7d10b251d562d58ea53;
+  00000000000000000000000000400000
+       00000000000000000000000000000000 48660e32b1c7ee7085e5b5e9f719c790;
+  00000000000000000000000000200000
+       00000000000000000000000000000000 a96366bb17b67e161fd8e33c3e1f3d2a;
+  00000000000000000000000000100000
+       00000000000000000000000000000000 5659ab825fc2de031a6998cacd741ff6;
+  00000000000000000000000000080000
+       00000000000000000000000000000000 1253e9e4079e9b573a73cf4ce08dc015;
+  00000000000000000000000000040000
+       00000000000000000000000000000000 28205442270c735d4ba79042dce81509;
+  00000000000000000000000000020000
+       00000000000000000000000000000000 98cfb10f3ed70bb82cc90597b463a1f6;
+  00000000000000000000000000010000
+       00000000000000000000000000000000 cab40433631fe3a272fc401255a58064;
+  00000000000000000000000000008000
+       00000000000000000000000000000000 abb041d85114da88e65e8bdcf1c67cc8;
+  00000000000000000000000000004000
+       00000000000000000000000000000000 00f0926f0f9eaa0a6238dfce79c8f596;
+  00000000000000000000000000002000
+       00000000000000000000000000000000 7c662d01b12d9845705b2bd4d7aef43d;
+  00000000000000000000000000001000
+       00000000000000000000000000000000 8f1cc7a0fbe7d70a894d09e12fb22bb8;
+  00000000000000000000000000000800
+       00000000000000000000000000000000 ebe03d0c6752d0edfebff879c33d8c07;
+  00000000000000000000000000000400
+       00000000000000000000000000000000 b74ce7f67bbd969e8ff8862d1fb1715c;
+  00000000000000000000000000000200
+       00000000000000000000000000000000 63ad5ea9d599ec848a40d489c0b85e8a;
+  00000000000000000000000000000100
+       00000000000000000000000000000000 4e4167f091ea5776e80fb2fca38c2a04;
+  00000000000000000000000000000080
+       00000000000000000000000000000000 dbf0cea3a5ed5b884ac13a2a62c32d51;
+  00000000000000000000000000000040
+       00000000000000000000000000000000 7e86285068a376a3b9fe8641a38e3f90;
+  00000000000000000000000000000020
+       00000000000000000000000000000000 aec1ef8d651a2cf7b5475fcc7fb7a81a;
+  00000000000000000000000000000010
+       00000000000000000000000000000000 fda539d910181ce1a1e1db4c3459600b;
+  00000000000000000000000000000008
+       00000000000000000000000000000000 f8072bf053d5b5163949ff0b9bb3f81a;
+  00000000000000000000000000000004
+       00000000000000000000000000000000 a31eb966d34ed6a6132a6b6e9128e997;
+  00000000000000000000000000000002
+       00000000000000000000000000000000 673aebbff82091a19e758ece151811d0;
+  00000000000000000000000000000001
+       00000000000000000000000000000000 369bdb6f102d6bfea7645b1a6753bf37;
+  80000000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ffd90e8a92a1b025108168714f7923f7;
+  40000000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 64e10ab587bc5d996cf2186c2ff2dd58;
+  20000000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 eaa404b51336a16c963735588b0b2a0c;
+  10000000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 51aaa1e37cb08cf5c6ec9241ac36b4c5;
+  08000000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c21b34c3c077b30add67d0e2e75e59ec;
+  04000000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f33ccd4771932f5e467552e93ae367ab;
+  02000000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b70b9f3a5814ddeb6d3549d88c5b4656;
+  01000000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 5c01c66e9bf9617b155d3902722ccadc;
+  00800000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 1f47def31d2e7e286172b38119fde307;
+  00400000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 bd3c2f005cf0eb5ef737c29f457ed549;
+  00200000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 1d409243f79ce876d13b0fdfea26ccf8;
+  00100000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b879e37c2f435b0cb941f74892c1476f;
+  00080000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 58c6a8884bf8b110c9127893976a9e4e;
+  00040000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 7a258ac14cb88a31432ba1b320d254f6;
+  00020000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ff382f1b4bbb54c9f42b73b256f80d25;
+  00010000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 0cef334bcbe5d38e23a9780d2e3e9097;
+  00008000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 3225e13778d2a3bab1eb375e034478c4;
+  00004000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4ef73320931377f64e296e49c286e5c9;
+  00002000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 adbf2c07f2f42eb7d92acc07f9df7a5f;
+  00001000000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 bfca14ad6925ddb4f563048db1c6b485;
+  00000800000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 63f01ea46c82dc3b1d81eac5e4f1d687;
+  00000400000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b2f6eb69ce81accc720e705146cfc2a2;
+  00000200000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 85b1ff06090504848fdda74dd830e960;
+  00000100000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 5bcb44ab29d7c31def58c902c2491333;
+  00000080000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4d982cbc7c1455cde7c0de3f83fcbc5e;
+  00000040000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 32f08276e0633e1d819fc6227e631503;
+  00000020000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e6bebd4cddc205399126bfda486ed37c;
+  00000010000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 afe39df4f356aea5f07069455010d9ce;
+  00000008000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 a8c7b2c1e8e1ade5e28e4104ff716ba5;
+  00000004000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 fbb3e4ca3e710a5bd94b50726de5fdb1;
+  00000002000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 2091d65d6fbb8672d84655f33dc1473a;
+  00000001000000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 9c74519acc53498333791febfd0e5e8b;
+  00000000800000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ed44022a82468ed54203b5863b63061f;
+  00000000400000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 eae325499a1a9e8e1bd4d6f018e65551;
+  00000000200000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b134fe1498d7a1d926d3a623ffa5723e;
+  00000000100000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 343f8d08a35c272c5cd4064a42a7b6d8;
+  00000000080000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 79230ea5d7f6b5d85922ed7679aebe08;
+  00000000040000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d3f799e3579c68e10fb1c770b1cbb7c7;
+  00000000020000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 90c24054dc24772ecd92a67a43335320;
+  00000000010000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 bf38cfda7b75a478fa73316801883d34;
+  00000000008000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4323a85f7921a4a1fc072b72b6b46f50;
+  00000000004000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 3e10218fdefd9a0b91d9032d793aecc8;
+  00000000002000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 66a759ec5e5cdd9c27a4e97ff0b5aab8;
+  00000000001000000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 3730876a26727d44a46404f69ba99f09;
+  00000000000800000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b277bd5a0e78eafc049bd9aa3393870f;
+  00000000000400000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 af05cdd3a6dd19fb0199933bdea3c20f;
+  00000000000200000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 0d962ec5f824d922924f3c39339fa934;
+  00000000000100000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 de695dab525ffebc039f63c3defb200b;
+  00000000000080000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f8ce4303ff6a523a60e3526a28c1c1de;
+  00000000000040000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c00c5250a33165254408992f6aa1fb97;
+  00000000000020000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 7e81d9c10bc3ac8fcac65079867183ff;
+  00000000000010000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 42f91fe46e5f6485973123b586cc2517;
+  00000000000008000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 0900c5c4bb963e1e421571056aeda9f0;
+  00000000000004000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 933312932700ef9c82333913782fc8fb;
+  00000000000002000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d78181179ac4cc05f38a1d134b29b70a;
+  00000000000001000000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 411b9bd8a8c3d3c9a2c375d28a336c4a;
+  00000000000000800000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 632433f8708bd47d6a083adbdf3a8982;
+  00000000000000400000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f037e3fcd3db611bd777420b8170df1b;
+  00000000000000200000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 31da207bfbdbb93157408ad2d7e559df;
+  00000000000000100000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 2837b13cb713b5fde1bc07cb7b2613d9;
+  00000000000000080000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c31906513814506753848c50ab7c8d13;
+  00000000000000040000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 014b54ca9f1d87c7711af20119b03afc;
+  00000000000000020000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 060903be7b215ee51fbce79205b0515a;
+  00000000000000010000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f91da002995fe07969ff63b8673fa75a;
+  00000000000000008000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 65a8b07ad4f77c8be4f27f975a42f2e7;
+  00000000000000004000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 31a157653449da846b5dade80e2f3ae8;
+  00000000000000002000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 1be98428352aeab7534e12463898bde5;
+  00000000000000001000000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 a7a50bec385145e784486d6d70552fbf;
+  00000000000000000800000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 eaacafae73701d566b24ab68350c4cb7;
+  00000000000000000400000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 deef8a7a5de90caaa0e3412356518d9a;
+  00000000000000000200000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 8d4373f4933353f589e42471ef35836c;
+  00000000000000000100000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 01436b7d351b9ff0fe85dab7ef77a020;
+  00000000000000000080000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 a6b2b93c4c6dafea4db5a4ecfee2c561;
+  00000000000000000040000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 7b0f7781683d890db4582d4399b07fab;
+  00000000000000000020000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 01c82b395331de265555d72df29c7efc;
+  00000000000000000010000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 5d9ba76d5b20b4b88b70b80c20c5e350;
+  00000000000000000008000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 92b2a69dd8a75d2edb01644a0b975c15;
+  00000000000000000004000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e2f6e46a2a899615969f4b751d55d57f;
+  00000000000000000002000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 97427298315d058eb2f7cdabd4a851c8;
+  00000000000000000001000000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 8f0f710a0cc1d6049ebb01974b76caad;
+  00000000000000000000800000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 2cf62d9d02afb40eed66fedb53c2db5c;
+  00000000000000000000400000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 fb215ab9ec3fafc5fd91cd9ad3cee2be;
+  00000000000000000000200000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4a37472335edaf7393a304d45a233085;
+  00000000000000000000100000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d22a878d2ca3a88f34acc92a4e26c738;
+  00000000000000000000080000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f1a95970638dcbc69c4675e895370904;
+  00000000000000000000040000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 1660060085c0e241f88462bffbe67602;
+  00000000000000000000020000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 a097acb2eb5f779090f886beae746ae1;
+  00000000000000000000010000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 9ffe05163407ba53b62a35d857f58bc6;
+  00000000000000000000008000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 dfed8392eec1b389cbc261faf97c5c9e;
+  00000000000000000000004000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d2c1b3159129d86959f3aa9b70219a74;
+  00000000000000000000002000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 98c043b2e86cff626abf5fbc745d98a6;
+  00000000000000000000001000000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 35c5aed481c801a0ca78842273e0186d;
+  00000000000000000000000800000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ddaac5c7f13943e80d2244a4a19e9980;
+  00000000000000000000000400000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 51dbf12fc81e5ffe9b1ce9963636205f;
+  00000000000000000000000200000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 38ee89874d644ccdf9694280a6c48182;
+  00000000000000000000000100000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c3bc93ca8e8800622c92c56b99262ae2;
+  00000000000000000000000080000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 dc2c2b7558f75b71a9db34e971892171;
+  00000000000000000000000040000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 609bd72078f92ae345dcde14e6aba0e0;
+  00000000000000000000000020000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 cabc8bdda6e1979199f5010c3f8b8a31;
+  00000000000000000000000010000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c993d659ba4426dc30f8dc7ea03cd2ee;
+  00000000000000000000000008000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 5dd47466cbb15dca1485e04231d7491c;
+  00000000000000000000000004000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e1351ce84ded187e0f5aab9bb7198387;
+  00000000000000000000000002000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e5222c68fda26e5e62929c70233ad097;
+  00000000000000000000000001000000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 78cc456147db73850328241bdff861c0;
+  00000000000000000000000000800000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4f10436e3ba4f38cd96744b897d5a136;
+  00000000000000000000000000400000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 12b698464abcb67c3956c5d1b9c62dfd;
+  00000000000000000000000000200000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 49de5db3e7d997c56dd2f82935e6617f;
+  00000000000000000000000000100000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 71ea115e54775680f16b1b9d7b2ee367;
+  00000000000000000000000000080000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 45b7e46c664a472af948b0c393f92af1;
+  00000000000000000000000000040000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 db3678b993ef5e48931b5bf84cece6eb;
+  00000000000000000000000000020000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 051c9a17d4ca77eabd8b9d9a1bce52d6;
+  00000000000000000000000000010000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e805aeeac134761ff7b3260bb4308a10;
+  00000000000000000000000000008000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 3301700109b460c7e41a51059f33004f;
+  00000000000000000000000000004000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d71f178093314e188bae26dde5a78927;
+  00000000000000000000000000002000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 31bb9cb46fbf607fcaa5932851899420;
+  00000000000000000000000000001000
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ea77bcd0ce469ab47a828dc6324c3651;
+  00000000000000000000000000000800
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e4596b0d33bdeb062a7ddb93e6efae94;
+  00000000000000000000000000000400
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 24d04f34b837461cd3b8d9c13afe6fe5;
+  00000000000000000000000000000200
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ffb68c9ae4d7d2642bf5bee57d2bd914;
+  00000000000000000000000000000100
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c008d35eb9de15700c0491319e6415f0;
+  00000000000000000000000000000080
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 92bfbbfcd2bbf54fff06af097893e9a3;
+  00000000000000000000000000000040
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d2475279191bc4da183ee2dba75fce6d;
+  00000000000000000000000000000020
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 7b8adf2ef0e1f5fbb19cbd4b8fab1426;
+  00000000000000000000000000000010
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 0b07b9c4385bdc86447f535e09a9f424;
+  00000000000000000000000000000008
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e7308875d8d6645719c076dd1660924b;
+  00000000000000000000000000000004
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 bc50d54a891d6102d0c02f471f1f0567;
+  00000000000000000000000000000002
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 2b14534ca7d9821a40b101035f681f0d;
+  00000000000000000000000000000001
+       0f1e2d3c4b5a69788796a5b4c3d2e1f0 69bd984641e0aa887bc23738f60070db;
+}
diff --git a/symm/t/tea b/symm/t/tea
new file mode 100644 (file)
index 0000000..9eec55d
--- /dev/null
@@ -0,0 +1,74 @@
+# Test vectors for TEA
+
+# --- Generated from Needham and Wheeler's original implementation ---
+
+tea {
+  00000000000000000000000000000000 0000000000000000 41ea3a0a94baa940;
+  ffffffffffffffffffffffffffffffff ffffffffffffffff 319bbefb016abdb2;
+  00112233445566778899aabbccddeeff 0123456789abcdef 126c6b92c0653a3e;
+  00112233445566778899aabbccddeeff 67452301efcdab89 d667cc4e10bf6eb0;
+  00112233445566778899aabbccddeeff b3e551c7d8378a6c db21fb2a3118e62d;
+  d94576cd1a5f99e4155dc7bec5d33df2 d51399607f7aa9d7 7d1eb12827ef2121;
+  07ef12bc9d06d7da20131116b665e335 10b233473624ccd3 ae694e579daeff54;
+  c6462b48afd604b75fcc455506ffd411 3b905e951e4fafe7 d9633fcf13c30394;
+  be195f703d6fec2232cd0890c981b27d 15b623d1fa2df9df 916ffcb1abaf086b;
+  5b8410f7a9eb92da120810c56fcaf8c9 7c1035940696d91d 460aa2db964b580c;
+  b85c9e26661889d0ff1054c6be27fdeb 90b245144895f3ad 87d7e95a5a4aa89a;
+  a8a1e956d54d238f6ceab186e7ec99ed 4ef2cfd120b8d4dc 1752f2ee188018de;
+  8bc4879201a96368927ecceee67024ee f6cb5353f4a1c432 7cfa8e0718d59807;
+  f1372d85d8c3d1a60df57eedf317ab81 215c080cf158a09b 3b85115e0d6c5a94;
+  017f01683f5e009d196feeaad385c5a9 568583061da98d0d cb0e345182f4bf0b;
+  281c932ddd3c364b09f1896007ffab03 0558b306316b0823 e7adf267c7d841c2;
+  c1e95465c7ef8eb04254d1a5463c6a43 fdcb2764303222c7 ed48b228c11e7bc6;
+  0f86dd6c96dd31164b656b0f25e4b411 eaddba89070ec46c 89fb864135a57e33;
+  fbacfb479ae21194c35b8184e58dd66e c6507bcf99b9c2a1 670da449ce74c658;
+  2eb36c4a9598d471700a1330070fffc9 c380b0f1c21d4d37 d84fe611431c0b5e;
+  0a7f48127091780617a1f534b3271bc9 e5b7c1517f24f298 4be47c656cef6ffc;
+  303fb24822a1b8a84d0ece77b86380ff d14ddf77fdda17bf 1cc73315c9f72ab1;
+  f04ebf798c193f199c1f532af383555b b9682750bb15caad 2b5f318fb66806b9;
+  200c0ce59717d5d9af6813cd207fee73 9706769a18a2d03d 8e17eeb5008dc0cb;
+  2828d51f98ae0b33f4de2b7fbd18a529 edb76c54847da59e dfa6c29beb40f9af;
+  61aaba6be48b0d0d14fe5d27fab852a4 178a49bafba53f23 c3bbce6715d90ce6;
+  2080e2409ba01c8532fc84403ee8c06a df4cdb61a5f38536 b4e6359c9d9458aa;
+  271ad15192c4d1204a4a2561e3db6ff7 7c944d08def34c0c 195c0e8f49761539;
+  c1e297c0c761777d8a76fff02d22b859 f4c76c1d47fe568f 551ca67c7756ff56;
+  23c807a2ef0a551f858fd52d125a47d8 cab16583e15d0074 de472175d55372c9;
+  9fa5d4d8cbdfcecd559e3ce88bf78ee1 97b05c60774164ad bc4bd30cb50da39b;
+  24f4e91083139099d663647a7ffac321 7017a263985b735c e47fdf06a51d8c24;
+  7cf8626de76d8462218ed5c9dc8acc26 15475a90df04cd29 4df54282eaafa235;
+  3c6ad7df17332a3e1e3de06007387357 87ca0aaccf146cc8 f7360f57cfcc09ac;
+  24237a762d8a89383a2949f5a0f5ec08 9268af048ecbae67 e98e428a9d1fee9c;
+  209a2833a39472d9720380ffb2f74761 af0062cd77a84ebd 44cd624b87cbee77;
+  22ebe7a30e8855b3b453a6e926d4f187 f922ca875b991a31 1e92c0c51185f7c7;
+  1b5e23ebd915c1fee59f57dd91af7347 b4ecc305c3dbd8e5 063d8f75a7a77501;
+  6c21d105515290da29339f142685c135 a4c2f6dc597d13ea bf8ffec7550a496b;
+  01f728a7433a47b13de34fcc08958449 3af7f1ae0f58ab1d bba581d07e51d8d6;
+  9a2d4c50337d3ec337673782fd385601 791d8da8cbb0bc94 7d9a4f0363b6085f;
+  b3b99747560e246bcd0cdc3fb33e4910 91778f2bd9233375 4b85b79a58b1321e;
+  4b269e2e8dbd68b94066c95244c3a195 abfb6a33e1471e96 53d089e9313e832d;
+  d10b956f675dc2276b6dd90442bece3e dbedddb6a1c15a21 b81739d49c10b4fd;
+  28f8fab7541766f6dafbaa5b6f3bd700 2c14d5097ab11f61 c018b6e3cca4095f;
+  2b61e60478fa0c0edb9531f26791eff9 b84c80b2d245fdfc 2301e2d68d241622;
+  a6bfb85fa91b8ca4197c8b502a62f972 3daadd7a9633e19b 65bc93b4dbbd652f;
+  94e76e54d37f932cbcc069de6bf26d52 02739eeb468450fd a477a7ec244f1e9f;
+  82760ea1560e8f9d1e35f20cad1f26cc 34aa5952b5a9110f 2564284b47152721;
+  3aba91211327585e0f1270b59ef9277b b584d6b34b638ba4 c829dc4da560211f;
+  727074f35cd523eb6f8aafbbf76fd5b1 f0e9268a27ab70c6 f24b80555fdcb67f;
+  6e0aa1c91ea6315a4a7dd297ac5936a4 47374080f27fbb30 6fdb64c32920c0a5;
+  63bd2d37271a250c8593b433188cffd0 776927909196eec5 57bca56240b39c0b;
+  dc7beb423c2053156329d7ab79f4d1d6 24c0adb3777860ad e040f57fe32f2158;
+  ed219454883709efe884bbc9d30507a3 587b1683dff7f178 e2c6512996117ba9;
+  40509fc5c565e9b9f3995f3bc5d5c1f4 719a39f2302a98aa b8a9f3ab1b68ac1f;
+  f9f10ed2bc0193605913475fd54d69ae e35b94e2940a8db0 b23358feb43a29aa;
+  23003c3fbe9661b6b9386748982ac3e2 d1dfd47fac22b9ff 4165de32289acf6a;
+  a2caa563c2f19b10fbac1427e2177858 f7743dfe957cc82b d88dcd158b0d81c2;
+  8bb42b6937d65eac506e8326356071af 690a0fa32113bf34 9095cce6d70da9d6;
+  219c7f982a0c352977b978b91fcb3c45 8fb4cb86db41ce30 c688b48de8ec7e14;
+  157ff76f22538eede0528c541dbe7815 ea6cd44f238be18f 35578556b38660fa;
+  346194289f6d865237cc673c45415003 71690fd4ba3d75de 719f1f0a6b316a58;
+  032c8c1624f7f300d8a58d151de52d78 3c0f1746798ed5b7 62c9adb10b265534;
+  019471106a5cd4ee3d1f627213649b80 558a8d7a4cdc0822 014521292dcbff85;
+  45aa90191c449dbf9c541fb476d1bf74 bfba3dfd06e77671 b6a6825c69d9d5eb;
+  c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d d33c2e41dd5da131;
+  af4f4615c7c298639b9728251991419f 1e268f9e710313b5 a9478f8cf88b7e10;
+}
similarity index 100%
rename from tests/tea-test.c
rename to symm/t/tea-test.c
diff --git a/symm/t/tiger b/symm/t/tiger
new file mode 100644 (file)
index 0000000..46a74e0
--- /dev/null
@@ -0,0 +1,62 @@
+# Test vectors for Tiger
+
+# --- The main hash ---
+#
+# These are taken from the reference implementation.
+
+tiger {
+  ""           3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3;
+  "abc"                2aab1484e8c158f2bfb8c5ff41b57a525129131c957b5f93;
+  "Tiger"      dd00230799f5009fec6debc838bb6a27df2b9d6f110c7937;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
+               f71c8583902afb879edfe610f82c0d4786a3a534504486b5;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789"
+               48ceeb6308b87d46e95d656112cdf18d97915f9765658957;
+  "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"
+               8a866829040a410c729ad23f5ada711603b3cdd357e4c15e;
+  "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge."
+               ce55a6afd591f5ebac547ff84f89227f9331dab0b611c889;
+  "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996."
+               631abdd103eb9a3d245b6dfd4d77b257fc7439501d1568dd;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
+               c54034e5b43eb8005848a7e0ae6aac76e4ff590ae715fd25;
+}
+
+# --- HMAC mode ---
+#
+# No test vectors available.  The HMAC implementation has not been tested
+# against an external reference.  The HMAC code is autogenerated anyway, and
+# ought to be reliable and correct.
+#
+# These test vectors are here to spot changes in behaviour rather than ensure
+# interoperability.
+
+tiger-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       0a402190741a498d6d4a09016b0895cb6419ff849b196137;
+
+  "what do ya want for nothing?"
+        4a656665
+        3a351b1dec6075d6290e68b604e553821edc39041b82da83;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+        e09ab076337fba2b5c4a83e9dbfb62993710992934f0946c;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+        0102030405060708090a0b0c0d0e0f10111213141516171819
+        a452fa58bdb38b70207c472c5ee54b1e40b1893e6d604b19;
+
+  "Test With Truncation"
+        0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+        95981aaf2303d232824c504cc51459ea8275734336e92b1a;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+        ebbb20db7af380b5dffff39f671e1224e994d840408a7941;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+        308ebb428666c75b50d0442fe008777f4c208c7fa6d5ce7c;
+}
similarity index 100%
rename from tests/twofish.aes
rename to symm/t/twofish.aes
diff --git a/symm/t/whirlpool b/symm/t/whirlpool
new file mode 100644 (file)
index 0000000..5647787
--- /dev/null
@@ -0,0 +1,64 @@
+# Test vectors for the Whirlpool hash function
+
+# --- Basic hash function ---
+#
+# Some of these are taken from the ISO test vectors from the Whirlpool
+# distribution.
+
+whirlpool {
+  ""
+    19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3;
+  "a"
+    8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42d11bc645413aeff63a42391a39145a591a92200d560195e53b478584fdae231a;
+  "abc"
+    4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c7181eebdb6c57e277d0e34957114cbd6c797fc9d95d8b582d225292076d4eef5;
+  "message digest"
+    378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b8421557659ef55c106b4b52ac5a4aaa692ed920052838f3362e86dbd37a8903e;
+  "abcdefghijklmnopqrstuvwxyz"
+    f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b08bf2a9251c30b6a0b8aae86177ab4a6f68f673e7207865d5d9819a3dba4eb3b;
+  "abcdbcdecdefdefgefghfghighijhijk"
+    2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c6916bdc8031bc5be1b7b947639fe050b56939baaa0adff9ae6745b7b181c3be3fd;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+    dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e08eba26629129d8fb7cb57211b9281a65517cc879d7b962142c65f5a7af01467;
+}
+
+whirlpool-rep {
+  "1234567890" 8
+    466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb6014294d5bd8df2a6c44e538cd047b2681a51a2c60481e88c5a20b2c2a80cf3a9a083b;
+  "a" 1000000
+    0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af51fc15490eddc47af32bb2b66c34ff9ad8c6008ad677f77126953b226e4ed8b01;
+}
+
+# --- HMAC mode ---
+#
+# Home-made test vectors, for regression.
+
+whirlpool-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       f300802099638aa1df411accbae11c2947fbcb2a4186f1c9bc6daa75dc3ad46dd89739ae5fb39b5c4afc098435c3ba0f7f55900e8c719711cbaee6d473eef0ba;
+
+  "what do ya want for nothing?"
+       4a656665
+       3d595ccd1d4f4cfd045af53ba7d5c8283fee6ded6eaf1269071b6b4ea64800056b5077c6a942cfa1221bd4e5aed791276e5dd46a407d2b8007163d3e7cd1de66;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       4fb33849b7d0268ab9f3bc90cfc6ca90639338c32bca959b7bc47a61f4d946ca6c6a227e97205a18fe676907ce78d0f8892fcf73f44da714cb210188b92cabc9;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       35bc33e2ed71e1cb01c140ddd3291ae3f84e9f0dce18005a1123df199983a211fe744b244449a1c093b17584069359bc6a95352271d78e2ef7a6f21dc28ab3c1;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       502a6d22d0f8e67196dfed2a9d9ef988714db9db2e2f0ad6c30e52eed830aa348ee98744ddd3ff1974c7fe275e078b79a6ba8c967c5a41b290f6edca01183b1a;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       dd90bd637cfcd27ca914c290f33402cf68576d6e70601af0295f6b9dafa9d988d8b8fb4fde8605ac544638158dba2baa90a2bf882546cd0b876d59ab3f18962e;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       faf529af18a0f569480fd001122bb446b32a3cf758c385cec4adad9c73c77327812e260b7082011a3eb1071e71a50e1c3d37a8963f8b6a64a31cc017db1d619c;
+}
diff --git a/symm/t/whirlpool256 b/symm/t/whirlpool256
new file mode 100644 (file)
index 0000000..b1b68c2
--- /dev/null
@@ -0,0 +1,64 @@
+# Test vectors for the Whirlpool hash function
+
+# --- Basic hash function ---
+#
+# Some of these are taken from the ISO test vectors from the Whirlpool
+# distribution.
+
+whirlpool256 {
+  ""
+    19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a7;
+  "a"
+    8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42;
+  "abc"
+    4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c;
+  "message digest"
+    378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b;
+  "abcdefghijklmnopqrstuvwxyz"
+    f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b;
+  "abcdbcdecdefdefgefghfghighijhijk"
+    2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c69;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+    dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e;
+}
+
+whirlpool256-rep {
+  "1234567890" 8
+    466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb601429;
+  "a" 1000000
+    0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af5;
+}
+
+# --- HMAC mode ---
+#
+# Home-made test vectors, for regression.
+
+whirlpool256-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       9ab3bbb27b85df2edc51f2e05c880560439547e7c2772f8cec6ae00bead0bd7e;
+
+  "what do ya want for nothing?"
+       4a656665
+       977fd7f1d53e8af854404262630bfac20269ab3fc2fccabecd8feaa05b8cdabb;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       6d418c9fe3d422200ea8cf7d0d73591ca5714f49c38907c80fc96b3934ab8fc2;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       e0a3553419a54385ce04435bbb2bbf1d69d7626d8fab4f60e87a84fab731caab;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       2a4f40079e618c3a8467dd1a284af43662f84b137d93d54e5623884a047f546f;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       17564185de7d845576f42fbdcd027073bca1a059931ce4a901ae8662ad19caf0;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       0bdc8bf26ff0a71201fbeef2d51f35bcbc3e8b0daeddedcbec2ca2b2e8f457b2;
+}
diff --git a/symm/t/xtea b/symm/t/xtea
new file mode 100644 (file)
index 0000000..be34740
--- /dev/null
@@ -0,0 +1,70 @@
+# Test vectors for XTEA
+
+# --- Generated from Needham and Wheeler's original implementation ---
+
+xtea {
+  00112233445566778899aabbccddeeff 0123456789abcdef b8bf2821622b5b30;
+  d94576cd1a5f99e4155dc7bec5d33df2 d51399607f7aa9d7 782e4e131c5ba746;
+  07ef12bc9d06d7da20131116b665e335 10b233473624ccd3 57733a1deece283e;
+  c6462b48afd604b75fcc455506ffd411 3b905e951e4fafe7 776f4965deb65775;
+  be195f703d6fec2232cd0890c981b27d 15b623d1fa2df9df 3bd5ad5c9ed6101e;
+  5b8410f7a9eb92da120810c56fcaf8c9 7c1035940696d91d 5f93fa1d06991415;
+  b85c9e26661889d0ff1054c6be27fdeb 90b245144895f3ad 6105bfb0947828b7;
+  a8a1e956d54d238f6ceab186e7ec99ed 4ef2cfd120b8d4dc 51fae58a10f7c3dd;
+  8bc4879201a96368927ecceee67024ee f6cb5353f4a1c432 550ad71ba8a34568;
+  f1372d85d8c3d1a60df57eedf317ab81 215c080cf158a09b 13d1e24ba9ff7b63;
+  017f01683f5e009d196feeaad385c5a9 568583061da98d0d 6439b1dfe2ecb541;
+  281c932ddd3c364b09f1896007ffab03 0558b306316b0823 c8f82fe4491a8917;
+  c1e95465c7ef8eb04254d1a5463c6a43 fdcb2764303222c7 244dbfa1d2c914e4;
+  0f86dd6c96dd31164b656b0f25e4b411 eaddba89070ec46c 5a4909646763454f;
+  fbacfb479ae21194c35b8184e58dd66e c6507bcf99b9c2a1 6f08ec714e8a7c18;
+  2eb36c4a9598d471700a1330070fffc9 c380b0f1c21d4d37 72d4d4bdf5c00585;
+  0a7f48127091780617a1f534b3271bc9 e5b7c1517f24f298 64374b40bb732354;
+  303fb24822a1b8a84d0ece77b86380ff d14ddf77fdda17bf 014f1e707d02c8d8;
+  f04ebf798c193f199c1f532af383555b b9682750bb15caad 9001d21b57ab5360;
+  200c0ce59717d5d9af6813cd207fee73 9706769a18a2d03d 835fd788c089fd45;
+  2828d51f98ae0b33f4de2b7fbd18a529 edb76c54847da59e b0c0125494d39ce9;
+  61aaba6be48b0d0d14fe5d27fab852a4 178a49bafba53f23 ade26742f25efbe1;
+  2080e2409ba01c8532fc84403ee8c06a df4cdb61a5f38536 9c895e72168b409e;
+  271ad15192c4d1204a4a2561e3db6ff7 7c944d08def34c0c b784e23e00b3b498;
+  c1e297c0c761777d8a76fff02d22b859 f4c76c1d47fe568f 62f9e58b0364b0b6;
+  23c807a2ef0a551f858fd52d125a47d8 cab16583e15d0074 4563be765e74653a;
+  9fa5d4d8cbdfcecd559e3ce88bf78ee1 97b05c60774164ad 714807767366854b;
+  24f4e91083139099d663647a7ffac321 7017a263985b735c cc68e1ed7f7c7832;
+  7cf8626de76d8462218ed5c9dc8acc26 15475a90df04cd29 416eab1ebc155782;
+  3c6ad7df17332a3e1e3de06007387357 87ca0aaccf146cc8 ded575554058ef42;
+  24237a762d8a89383a2949f5a0f5ec08 9268af048ecbae67 899b9b877106c764;
+  209a2833a39472d9720380ffb2f74761 af0062cd77a84ebd 26db40c151b74530;
+  22ebe7a30e8855b3b453a6e926d4f187 f922ca875b991a31 2763f255636a34c1;
+  1b5e23ebd915c1fee59f57dd91af7347 b4ecc305c3dbd8e5 fbbec8f5dbf4cefd;
+  6c21d105515290da29339f142685c135 a4c2f6dc597d13ea 7409829de05ae6d1;
+  01f728a7433a47b13de34fcc08958449 3af7f1ae0f58ab1d 950083fbd332a987;
+  9a2d4c50337d3ec337673782fd385601 791d8da8cbb0bc94 13f87f8d3326553f;
+  b3b99747560e246bcd0cdc3fb33e4910 91778f2bd9233375 2b1f2747b356e119;
+  4b269e2e8dbd68b94066c95244c3a195 abfb6a33e1471e96 8ce0dc718e757924;
+  d10b956f675dc2276b6dd90442bece3e dbedddb6a1c15a21 19df78dea26ea579;
+  28f8fab7541766f6dafbaa5b6f3bd700 2c14d5097ab11f61 3a6fd0a5fef50079;
+  2b61e60478fa0c0edb9531f26791eff9 b84c80b2d245fdfc f24ea37046b97a03;
+  a6bfb85fa91b8ca4197c8b502a62f972 3daadd7a9633e19b 4de5c07ea1564a64;
+  94e76e54d37f932cbcc069de6bf26d52 02739eeb468450fd 0d4ef5d93f419069;
+  82760ea1560e8f9d1e35f20cad1f26cc 34aa5952b5a9110f 7676f2746bfac3b7;
+  3aba91211327585e0f1270b59ef9277b b584d6b34b638ba4 2cfa1f17178df25d;
+  727074f35cd523eb6f8aafbbf76fd5b1 f0e9268a27ab70c6 609aee69ed6e2a8e;
+  6e0aa1c91ea6315a4a7dd297ac5936a4 47374080f27fbb30 5d86f6451024e051;
+  63bd2d37271a250c8593b433188cffd0 776927909196eec5 ec617cc3810e278c;
+  dc7beb423c2053156329d7ab79f4d1d6 24c0adb3777860ad 7f6f6083713a68ba;
+  ed219454883709efe884bbc9d30507a3 587b1683dff7f178 86a95a8f48fa13b0;
+  40509fc5c565e9b9f3995f3bc5d5c1f4 719a39f2302a98aa 503f9481c7049890;
+  f9f10ed2bc0193605913475fd54d69ae e35b94e2940a8db0 59bc9b0bd5004dae;
+  23003c3fbe9661b6b9386748982ac3e2 d1dfd47fac22b9ff 756ec1ac4fa8deac;
+  a2caa563c2f19b10fbac1427e2177858 f7743dfe957cc82b 57ae9c0144dbb9d3;
+  8bb42b6937d65eac506e8326356071af 690a0fa32113bf34 5136052b310e7038;
+  219c7f982a0c352977b978b91fcb3c45 8fb4cb86db41ce30 fa01561e5b9311ab;
+  157ff76f22538eede0528c541dbe7815 ea6cd44f238be18f 0c3f632af5cee432;
+  346194289f6d865237cc673c45415003 71690fd4ba3d75de c4448db8c1144435;
+  032c8c1624f7f300d8a58d151de52d78 3c0f1746798ed5b7 e1bfbd2a7d414c8a;
+  019471106a5cd4ee3d1f627213649b80 558a8d7a4cdc0822 c90e5257ea513ef8;
+  45aa90191c449dbf9c541fb476d1bf74 bfba3dfd06e77671 bc715327ada1b56b;
+  c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d 2b4195c3d67e3f99;
+  af4f4615c7c298639b9728251991419f 1e268f9e710313b5 2536ccd8fdfe30e1;
+}
similarity index 100%
rename from tests/xtea-test.c
rename to symm/t/xtea-test.c
diff --git a/symm/tea.c b/symm/tea.c
new file mode 100644 (file)
index 0000000..4832674
--- /dev/null
@@ -0,0 +1,122 @@
+/* -*-c-*-
+ *
+ * The Tiny Encryption Algorithm
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "paranoia.h"
+#include "tea.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet tea_keysz[] = { KSZ_RANGE, TEA_KEYSZ, 0, 16, 1 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @tea_init@ --- *
+ *
+ * Arguments:  @tea_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a TEA key buffer.  The key buffer must be 16
+ *             bytes long.
+ */
+
+void tea_init(tea_ctx *k, const void *buf, size_t sz)
+{
+  octet kb[16];
+  const octet *p;
+
+  KSZ_ASSERT(tea, sz);
+  if (sz >= sizeof(kb))
+    p = buf;
+  else {
+    memcpy(kb, buf, sz);
+    memset(kb + sz, 0, sizeof(kb) - sz);
+    p = kb;
+  }
+
+  k->ka = LOAD32(p +  0); k->kb = LOAD32(p +  4);
+  k->kc = LOAD32(p +  8); k->kd = LOAD32(p + 12);
+  k->r = 32;
+
+  if (p == kb)
+    BURN(kb);
+}
+
+/* --- @tea_eblk@, @tea_dblk@ --- *
+ *
+ * Arguments:  @const tea_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to teatination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define DELTA 0x9e3779b9
+
+void tea_eblk(const tea_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 y = s[0], z = s[1];
+  uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd;
+  uint32 n = 0;
+  unsigned i;
+
+  for (i = 0; i < k->r; i++) {
+    n += DELTA;
+    y = U32(y + (((z << 4) + ka) ^ (z + n) ^ ((z >> 5) + kb)));
+    z = U32(z + (((y << 4) + kc) ^ (y + n) ^ ((y >> 5) + kd)));
+  }
+  d[0] = y; d[1] = z;
+}
+
+void tea_dblk(const tea_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 y = s[0], z = s[1];
+  uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd;
+  uint32 n = DELTA * k->r;
+  unsigned i;
+
+  for (i = 0; i < k->r; i++) {
+    z = U32(z - (((y << 4) + kc) ^ (y + n) ^ ((y >> 5) + kd)));
+    y = U32(y - (((z << 4) + ka) ^ (z + n) ^ ((z >> 5) + kb)));
+    n -= DELTA;
+  }
+  d[0] = y; d[1] = z;
+}
+
+BLKC_TEST(TEA, tea)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/tea.h b/symm/tea.h
new file mode 100644 (file)
index 0000000..fdad8ac
--- /dev/null
@@ -0,0 +1,104 @@
+/* -*-c-*-
+ *
+ * The Tiny Encryption Algorithm
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Tiny Encryption Algorithm ----------------------------*
+ *
+ * TEA is an amazingly simple 64-round Feistel network.  It's tiny, fairly
+ * quick and surprisingly strong.  It was invented by David Wheeler and Roger
+ * Needham.  It's unpatented.  The keyspace is has only 126 effective bits,
+ * and there are related-key attacks.  If you want these fixed, use XTEA.
+ *
+ * This implementation uses big-endian byte order, following SCAN.
+ */
+
+#ifndef CATACOMB_TEA_H
+#define CATACOMB_TEA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define TEA_BLKSZ 8
+#define TEA_KEYSZ 16
+#define TEA_CLASS (N, B, 64)
+
+extern const octet tea_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct tea_ctx {
+  unsigned r;
+  uint32 ka, kb, kc, kd;
+} tea_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @tea_init@ --- *
+ *
+ * Arguments:  @tea_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a TEA key buffer.  The key buffer may be up to 16
+ *             bytes long.
+ */
+
+extern void tea_init(tea_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @tea_eblk@, @tea_dblk@ --- *
+ *
+ * Arguments:  @const tea_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to teatination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void tea_eblk(const tea_ctx */*k*/,
+                    const uint32 */*s*/, uint32 */*d*/);
+extern void tea_dblk(const tea_ctx */*k*/,
+                    const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/tiger-base.h b/symm/tiger-base.h
new file mode 100644 (file)
index 0000000..49e05ef
--- /dev/null
@@ -0,0 +1,118 @@
+/* -*-c-*-
+ *
+ * Common definitions for the Tiger hash function
+ *
+ * (c) 2000 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.
+ */
+
+#ifndef CATACOMB_TIGER_BASE_H
+#define CATACOMB_TIGER_BASE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Macros provided ---------------------------------------------------*/
+
+/* --- The guts of a single round --- */
+
+#define TIGER_ROUND(a, b, c, x, n, op) do {                            \
+  kludge64 _t;                                                         \
+  XOR64(c, c, x);                                                      \
+  _t =         s[0][U8(LO64(c) >>  0)];                                \
+  XOR64(_t, _t, s[1][U8(LO64(c) >> 16)]);                              \
+  XOR64(_t, _t, s[2][U8(HI64(c) >>  0)]);                              \
+  XOR64(_t, _t, s[3][U8(HI64(c) >> 16)]);                              \
+  SUB64(a, a, _t);                                                     \
+  _t =         s[3][U8(LO64(c) >>  8)];                                \
+  XOR64(_t, _t, s[2][U8(LO64(c) >> 24)]);                              \
+  XOR64(_t, _t, s[1][U8(HI64(c) >>  8)]);                              \
+  XOR64(_t, _t, s[0][U8(HI64(c) >> 24)]);                              \
+  ADD64(b, b, _t);                                                     \
+  LSL64_(_t, b, n);                                                    \
+  op##64(b, _t, b);                                                    \
+} while (0)
+
+/* --- One pass over the buffer --- */
+
+#define TIGER_PASS(a, b, c, x, n, op) do {                             \
+  TIGER_ROUND(a, b, c, x[0], n, op);                                   \
+  TIGER_ROUND(b, c, a, x[1], n, op);                                   \
+  TIGER_ROUND(c, a, b, x[2], n, op);                                   \
+  TIGER_ROUND(a, b, c, x[3], n, op);                                   \
+  TIGER_ROUND(b, c, a, x[4], n, op);                                   \
+  TIGER_ROUND(c, a, b, x[5], n, op);                                   \
+  TIGER_ROUND(a, b, c, x[6], n, op);                                   \
+  TIGER_ROUND(b, c, a, x[7], n, op);                                   \
+} while (0)
+
+/* --- A step in the `key schedule' --- */
+
+#define TIGER_KSTEP(a, b, c, d, op, n) do {                            \
+  kludge64 _u;                                                         \
+  XOR64(b, b, a);                                                      \
+  ADD64(c, c, b);                                                      \
+  CPL64(_u, b); op##64_(_u, _u, n); XOR64(_u, _u, c); SUB64(d, d, _u); \
+} while (0)
+
+/* --- The `key schedule' -- mangle the buffer --- */
+
+#define TIGER_KSCHED(x) do {                                           \
+  kludge64 _t;                                                         \
+                                                                       \
+  SET64(_t, 0xa5a5a5a5, 0xa5a5a5a5);                                   \
+  XOR64(_t, _t, x[7]); SUB64(x[0], x[0], _t);                          \
+  TIGER_KSTEP(x[0], x[1], x[2], x[3], LSL, 19);                                \
+  TIGER_KSTEP(x[3], x[4], x[5], x[6], LSR, 23);                                \
+  TIGER_KSTEP(x[6], x[7], x[0], x[1], LSL, 19);                                \
+  TIGER_KSTEP(x[1], x[2], x[3], x[4], LSR, 23);                                \
+  XOR64(x[5], x[5], x[4]);                                             \
+  ADD64(x[6], x[6], x[5]);                                             \
+  SET64(_t, 0x01234567, 0x89abcdef);                                   \
+  XOR64(_t, _t, x[6]); SUB64(x[7], x[7], _t);                          \
+} while (0)
+
+/* --- The Tiger compression function --- */
+
+#define TIGER_CORE(a, b, c, x) do {                                    \
+  kludge64 _a, _b, _c;                                                 \
+  _a = a, _b = b, _c = c;                                              \
+  TIGER_PASS(_a, _b, _c, x, 2, ADD);                                   \
+  TIGER_KSCHED(x);                                                     \
+  TIGER_PASS(_c, _a, _b, x, 3, SUB);                                   \
+  TIGER_KSCHED(x);                                                     \
+  TIGER_PASS(_b, _c, _a, x, 3, ADD);                                   \
+  XOR64(a, _a, a); SUB64(b, _b, b); ADD64(c, _c, c);                   \
+} while (0)
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/tiger-mktab.c b/symm/tiger-mktab.c
new file mode 100644 (file)
index 0000000..5029330
--- /dev/null
@@ -0,0 +1,151 @@
+/* -*-c-*-
+ *
+ * Generate S-boxes for the Tiger hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tiger-base.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+/*----- Static variables --------------------------------------------------*/
+
+static kludge64 s[4][256];
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- The basic Tiger compression function --- */
+
+static void tiger(kludge64 *x, kludge64 *ss)
+{
+  TIGER_CORE(ss[0], ss[1], ss[2], x);
+}
+
+/* --- The S-box generator --- */
+
+void gen(const char *buf, unsigned passes)
+{
+  kludge64 x[8], ss[3];
+  unsigned i, j, k, b;
+  unsigned q, n;
+  uint32 t;
+  const char *p;
+
+  for (i = 0; i < 256; i++) {
+    for (j = 0; j < 4; j++) {
+      uint32 z = 0x01010101 * i;
+      SET64(s[j][i], z, z);
+    }
+  }
+
+  SET64(ss[0], 0x01234567, 0x89abcdef);
+  SET64(ss[1], 0xfedcba98, 0x76543210);
+  SET64(ss[2], 0xf096a5b4, 0xc3b2e187);
+
+  q = 2;
+  for (i = 0; i < passes; i++) {
+    for (j = 0; j < 256; j++) {
+      for (k = 0; k < 4; k++) {
+       q++;
+       if (q == 3) {
+         q = 0;
+         for (p = buf, n = 0; n < 8; n++, p += 8)
+           LOAD64_L_(x[n], p);
+         tiger(x, ss);
+       }
+       for (b = 0; b < 32; b += 8) {
+         n = U8(LO64(ss[q]) >> b);
+         t = (LO64(s[k][j]) ^ LO64(s[k][n])) & (0xff << b);
+         SET64(s[k][j], HI64(s[k][j]), LO64(s[k][j]) ^ t);
+         SET64(s[k][n], HI64(s[k][n]), LO64(s[k][n]) ^ t);
+       }
+       for (b = 0; b < 32; b += 8) {
+         n = U8(HI64(ss[q]) >> b);
+         t = (HI64(s[k][j]) ^ HI64(s[k][n])) & (0xff << b);
+         SET64(s[k][j], HI64(s[k][j]) ^ t, LO64(s[k][j]));
+         SET64(s[k][n], HI64(s[k][n]) ^ t, LO64(s[k][n]));
+       }
+      }
+    }
+  }
+}
+
+int main(void)
+{
+  unsigned i, j;
+
+  gen("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham", 5);
+
+  fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * S-boxes for Tiger [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_TIGER_TAB_H\n\
+#define CATACOMB_TIGER_TAB_H\n\
+\n\
+#define TIGER_S {                                                      \\\n\
+  { ", stdout);
+
+  for (i = 0; i < 4; i++) {
+    for (j = 0; j < 256; j++) {
+#ifdef HAVE_UINT64
+      printf("{ 0x%016llxull }", s[i][j].i);
+#else
+      printf("{ 0x%08lx, 0x%08lx }",
+            (unsigned long)s[i][j].hi, (unsigned long)s[i][j].lo);
+#endif
+      if (j == 255) {
+       if (i == 3)
+         fputs(" }             \\\n}\n", stdout);
+       else
+         fputs(" },            \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (j % 2 == 1)
+       fputs(",                \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  fputs("\n#endif\n", stdout);
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/tiger.c b/symm/tiger.c
new file mode 100644 (file)
index 0000000..f9aa824
--- /dev/null
@@ -0,0 +1,173 @@
+/* -*-c-*-
+ *
+ * The Tiger hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash-def.h"
+#include "hash.h"
+#include "tiger.h"
+#include "tiger-tab.h"
+#include "tiger-base.h"
+
+/*----- S-boxes -----------------------------------------------------------*/
+
+static const kludge64 s[4][256] = TIGER_S;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @tiger_compress@ --- *
+ *
+ * Arguments:  @tiger_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                Tiger compression function.
+ */
+
+void tiger_compress(tiger_ctx *ctx, const void *sbuf)
+{
+  kludge64 x[8];
+  int i;
+  const octet *p;
+  for (i = 0, p = sbuf; i < 8; i++, p += 8)
+    LOAD64_L_(x[i], p);
+  TIGER_CORE(ctx->a, ctx->b, ctx->c, x);
+}
+
+/* --- @tiger_init@ --- *
+ *
+ * Arguments:  @tiger_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void tiger_init(tiger_ctx *ctx)
+{
+  SET64(ctx->a, 0x01234567, 0x89abcdef);
+  SET64(ctx->b, 0xfedcba98, 0x76543210);
+  SET64(ctx->c, 0xf096a5b4, 0xc3b2e187);
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+/* --- @tiger_set@ --- *
+ *
+ * Arguments:  @tiger_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 tiger_set(tiger_ctx *ctx, const void *buf, unsigned long count)
+{
+  const octet *p = buf;
+  LOAD64_L_(ctx->a, p +         0);
+  LOAD64_L_(ctx->b, p +         8);
+  LOAD64_L_(ctx->c, p + 16);
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @tiger_hash@ --- *
+ *
+ * Arguments:  @tiger_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 tiger_hash(tiger_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(TIGER, tiger, ctx, buf, sz);
+}
+
+/* --- @tiger_done@ --- *
+ *
+ * Arguments:  @tiger_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void tiger_done(tiger_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_PAD(TIGER, tiger, ctx, 0x01u, 0, 8);
+  STORE32_L(ctx->buf + TIGER_BUFSZ - 8, ctx->nl << 3);
+  STORE32_L(ctx->buf + TIGER_BUFSZ - 4, (ctx->nl >> 29) | (ctx->nh << 3));
+  tiger_compress(ctx, ctx->buf);
+  STORE64_L_(p +  0, ctx->a);
+  STORE64_L_(p +  8, ctx->b);
+  STORE64_L_(p + 16, ctx->c);
+}
+
+/* --- @tiger_state@ --- *
+ *
+ * Arguments:  @tiger_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 @tiger_set@.
+ */
+
+unsigned long tiger_state(tiger_ctx *ctx, void *state)
+{
+  octet *p = state;
+  STORE64_L_(p +  0, ctx->a);
+  STORE64_L_(p +  8, ctx->b);
+  STORE64_L_(p + 16, ctx->c);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(TIGER, tiger)
+
+/* --- Test code --- */
+
+HASH_TEST(TIGER, tiger)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/tiger.h b/symm/tiger.h
new file mode 100644 (file)
index 0000000..d705cd5
--- /dev/null
@@ -0,0 +1,158 @@
+/* -*-c-*-
+ *
+ * The Tiger hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Tiger hash function ----------------------------------*
+ *
+ * Tiger was designed by Eli Biham and Ross Anderson to be an efficient and
+ * secure hash function which worked well on 64-bit processors.  This
+ * implementation should work everywhere, but it'll be faster if real 64-bit
+ * arithmetic is available.
+ *
+ * I don't know of any really good analysis of Tiger.
+ */
+
+#ifndef CATACOMB_TIGER_H
+#define CATACOMB_TIGER_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define TIGER_BUFSZ 64
+#define TIGER_HASHSZ 24
+#define TIGER_STATESZ 24
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct tiger_ctx {
+  kludge64 a, b, c;                    /* Chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[TIGER_BUFSZ];              /* Accumulation buffer */
+} tiger_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @tiger_compress@ --- *
+ *
+ * Arguments:  @tiger_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                Tiger compression function.
+ */
+
+extern void tiger_compress(tiger_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @tiger_init@ --- *
+ *
+ * Arguments:  @tiger_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void tiger_init(tiger_ctx */*ctx*/);
+
+/* --- @tiger_set@ --- *
+ *
+ * Arguments:  @tiger_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 tiger_set(tiger_ctx */*ctx*/, const void */*buf*/,
+                   unsigned long /*count*/);
+
+/* --- @tiger_hash@ --- *
+ *
+ * Arguments:  @tiger_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 tiger_hash(tiger_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @tiger_done@ --- *
+ *
+ * Arguments:  @tiger_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 tiger_done(tiger_ctx */*ctx*/, void */*hash*/);
+
+/* --- @tiger_state@ --- *
+ *
+ * Arguments:  @tiger_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 @tiger_set@.
+ */
+
+extern unsigned long tiger_state(tiger_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash tiger;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/twofish-mktab.c b/symm/twofish-mktab.c
new file mode 100644 (file)
index 0000000..4453fbe
--- /dev/null
@@ -0,0 +1,411 @@
+/* -*-c-*-
+ *
+ * Build constant tables for Twofish
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct { octet t[4][16]; } t_tab;
+typedef struct { octet q[256]; } q_tab;
+
+/*----- Various Twofish tables --------------------------------------------*/
+
+/* --- The t-tables --- */
+
+static const t_tab qt0 = {{
+  { 0x8, 0x1, 0x7, 0xd, 0x6, 0xf, 0x3, 0x2,
+    0x0, 0xb, 0x5, 0x9, 0xe, 0xc, 0xa, 0x4 },
+  { 0xe, 0xc, 0xb, 0x8, 0x1, 0x2, 0x3, 0x5,
+    0xf, 0x4, 0xa, 0x6, 0x7, 0x0, 0x9, 0xd },
+  { 0xb, 0xa, 0x5, 0xe, 0x6, 0xd, 0x9, 0x0,
+    0xc, 0x8, 0xf, 0x3, 0x2, 0x4, 0x7, 0x1 },
+  { 0xd, 0x7, 0xf, 0x4, 0x1, 0x2, 0x6, 0xe,
+    0x9, 0xb, 0x3, 0x0, 0x8, 0x5, 0xc, 0xa }
+}};
+
+static const t_tab qt1 = {{
+  { 0x2, 0x8, 0xb, 0xd, 0xf, 0x7, 0x6, 0xe,
+    0x3, 0x1, 0x9, 0x4, 0x0, 0xa, 0xc, 0x5 },
+  { 0x1, 0xe, 0x2, 0xb, 0x4, 0xc, 0x3, 0x7,
+    0x6, 0xd, 0xa, 0x5, 0xf, 0x9, 0x0, 0x8 },
+  { 0x4, 0xc, 0x7, 0x5, 0x1, 0x6, 0x9, 0xa,
+    0x0, 0xe, 0xd, 0x8, 0x2, 0xb, 0x3, 0xf },
+  { 0xb, 0x9, 0x5, 0x1, 0xc, 0x3, 0xd, 0xe,
+    0x6, 0x4, 0x7, 0xf, 0x2, 0x0, 0x8, 0xa }
+}};
+
+static q_tab q0, q1;
+
+/* --- The MDS and Reed-Solomon matrices --- */
+
+static const octet mds[16] = {
+  0x01, 0xef, 0x5b, 0x5b,
+  0x5b, 0xef, 0xef, 0x01,
+  0xef, 0x5b, 0x01, 0xef,
+  0xef, 0x01, 0xef, 0x5b
+};
+
+static const octet rs[32] = {
+  0x01, 0xa4, 0x55, 0x87, 0x5a, 0x58, 0xdb, 0x9e,
+  0xa4, 0x56, 0x82, 0xf3, 0x1e, 0xc6, 0x68, 0xe5,
+  0x02, 0xa1, 0xfc, 0xc1, 0x47, 0xae, 0x3d, 0x19,
+  0xa4, 0x55, 0x87, 0x5a, 0x58, 0xdb, 0x9e, 0x03
+};
+
+/*----- Magic macros ------------------------------------------------------*/
+
+#define ROR4(x) ((((x) >> 1) | ((x) << 3)) & 15)
+
+/*----- Building and printing @q@ tables ----------------------------------*/
+
+/* --- @mkq@ --- *
+ *
+ * Arguments:  @q_tab *q@ = pointer to output @q@ table
+ *             @const t_tab *t@ = pointer to input @t@ table
+ *             @const char *name@ = name of @q@ table
+ *
+ * Returns:    ---
+ *
+ * Use:                Constructs a 256-entry @q@-table.
+ */
+
+static void mkq(q_tab *q, const t_tab *t, const char *name)
+{
+  int i;
+  int ok = 1;
+
+  /* --- Ensure the t-table is well-formed --- */
+
+  for (i = 0; i < 4; i++) {
+    octet f[16] = { 0 };
+    int j;
+
+    for (j = 0; j < 16; j++) {
+      if (f[t->t[i][j]]) {
+       fprintf(stderr, "duplicate %i in %s[%i] (col %i and %i)\n",
+               t->t[i][j], name, i, j, f[t->t[i][j]]);
+       ok = 0;
+      }
+      f[t->t[i][j]] = j;
+    }
+  }
+
+  if (!ok)
+    exit(EXIT_FAILURE);
+
+  /* --- Construct the @q@ table --- */
+
+  for (i = 0; i < 256; i++) {
+    int a = i >> 4, b = i & 15;
+    int aa = t->t[0][a ^ b], bb = t->t[1][a ^ ((a << 3) & 15) ^ ROR4(b)];
+    a = t->t[2][aa ^ bb], b = t->t[3][aa ^ ((aa << 3) & 15) ^ ROR4(bb)];
+    q->q[i] = a | (b << 4);
+  }
+
+  /* Consider testing @q@ for linear and differential properties here */
+}
+
+/* --- @printq@ --- *
+ *
+ * Arguments:  @const q_tab *t@ = pointer to table
+ *             @const char *name@ = pointer to table name
+ *
+ * Returns:    ---
+ *
+ * Use:                Prints a q table.
+ */
+
+static void printq(const q_tab *q, const char *name)
+{
+  int i;
+  int j;
+
+  printf("\
+#define TWOFISH_%s {                                                   \\\n\
+  ", name);
+  j = 0;
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", q->q[i]);
+    j = (j + 1) & 7;
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (j == 0)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+}
+
+/*----- %$\gf{2^8}$% arithmetic -------------------------------------------*/
+
+#define MDS_MOD 0x169
+#define RS_MOD 0x14d
+
+/* --- @mul@ --- *
+ *
+ * Arguments:  @unsigned x, y@ = polynomials over %$\gf{2^8}$%
+ *             @unsigned m@ = modulus
+ *
+ * Returns:    The product of two polynomials.
+ *
+ * Use:                Computes a product of polynomials, quite slowly.
+ */
+
+static unsigned mul(unsigned x, unsigned y, unsigned m)
+{
+  unsigned a = 0;
+  unsigned i;
+
+  for (i = 0; i < 8; i++) {
+    if (y & 1)
+      a ^= x;
+    y >>= 1;
+    x <<= 1;
+    if (x & 0x100)
+      x ^= m;
+  }
+
+  return (a);
+}
+
+/* --- @mmul@ --- *
+ *
+ * Arguments:  @octet *d@ = destination vector
+ *             @const octet *p@ = matrix of bytes
+ *             @const octet *q@ = vector from somewhere else
+ *             @size_t r@ = size of destination or number of rows in matrix
+ *             @size_t n@ = length of row and vector
+ *             @unsigned m@ = modulus polynomial
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes an inner product of matrices over the finite field
+ *             %$\gf{2^8}[x]/(m(x))$%.  This isn't particularly rapid.
+ */
+
+static void mmul(octet *d, const octet *p, const octet *q,
+                size_t r, size_t n, unsigned m)
+{
+  while (r) {
+    const octet *qq = q;
+    unsigned a = 0;
+    unsigned i;
+
+    for (i = 0; i < n; i++)
+      a ^= mul(*p++, *qq++, m);
+    *d++ = a;
+    r--;
+  }
+}
+
+/* --- @qrds@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    ---
+ *
+ * Use:                Prints the MDS/q table.
+ */
+
+static void qmds(void)
+{
+  uint32 t[4][256];
+  int i, j;
+  static const q_tab *q[4] = { &q1, &q0, &q1, &q0 };
+
+  for (i = 0; i < 4; i++) {
+    octet in[4] = { 0, 0, 0, 0 };
+    octet out[4];
+
+    for (j = 0; j < 256; j++) {
+      in[i] = q[i]->q[j];
+      mmul(out, mds, in, 4, 4, MDS_MOD);
+      t[i][j] = LOAD32_L(out);
+    }
+  }
+
+  puts("\
+/* --- Expanded MDS tables --- *\n\
+ *\n\
+ * The table contains output vectors for computing the result of pushing\n\
+ * bytes through appropriate @q@ tables and the MDS matrix.\n\
+ */\n\
+\n\
+#define TWOFISH_QMDS {                                                 \\");
+  for (i = 0; i < 4; i++) {
+    fputs("  { ", stdout);
+    for (j = 0; j < 256; j++) {
+      printf("0x%08lx", (unsigned long)t[i][j]);
+      if (j == 255) {
+       if (i == 3)
+         puts(" }                      \\\n}");
+       else
+         puts(" },                     \\\n\
+                                                                       \\");
+      } else if (j % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  putchar('\n');
+}
+
+/* --- @rslog@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    ---
+ *
+ * Use:                Produces the log and antilog tables for doing the RS
+ *             arithmetic efficiently.
+ */
+
+static void rslog(void)
+{
+  octet rslog[256];
+  octet rsexp[256];
+
+  unsigned x = 1;
+  unsigned i;
+
+  rslog[0] = 0;
+  for (i = 0; i < 255; i++) {
+    rslog[x] = i;
+    rsexp[i] = x;
+    x <<= 1;
+    if (x & 0x100)
+      x ^= RS_MOD;
+  }
+
+  x = 0;
+  for (i = 0; i < 32; i++) {
+    if (rslog[rs[i]] > x)
+      x = rslog[rs[i]];
+  }
+
+  fputs("\
+/* --- Reed-Solomon log tables --- *\n\
+ *\n\
+ * The Reed-Solomon multiplies are accelerated by using log tables.\n\
+ */\n\
+\n\
+#define TWOFISH_RSLOG {                                                        \\\n\
+  ", stdout);
+
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", rslog[i]);
+    if (i == 255)
+      puts("                   \\\n}\n");
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  fputs("\
+#define TWOFISH_RSEXP {                                                        \\\n\
+  ", stdout);
+
+  for (i = 0; i < 255 + x + 1; i++) {
+    printf("0x%02x", rsexp[i % 255]);
+    if (i == 255 + x)
+      puts("                                           \\\n}\n");
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  fputs("\
+/* --- Reed-Solomon matrix with log entries --- */\n\
+\n\
+#define TWOFISH_RS {                                                   \\\n\
+  ", stdout);
+
+  for (i = 0; i < 32; i++) {
+    printf("0x%02x", rslog[rs[i]]);
+    if (i == 31)
+      puts("                   \\\n}\n");
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+}
+
+/*----- Main program ------------------------------------------------------*/
+
+/* --- @main@ --- */
+
+int main(void)
+{
+  fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * Twofish q tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_TWOFISH_TAB_H\n\
+#define CATACOMB_TWOFISH_TAB_H\n\
+\n\
+", stdout);
+
+  /* --- The q tables --- */
+
+  puts("\
+/* --- Precomputed @q@ tables --- */\n\
+");
+  mkq(&q0, &qt0, "qt0");
+  mkq(&q1, &qt1, "qt1");
+  printq(&q0, "Q0");
+  printq(&q1, "Q1");
+
+  /* --- The MDS/q tables --- */
+
+  qmds();
+  rslog();
+
+  /* --- Done --- */
+
+  puts("#endif");
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/twofish.c b/symm/twofish.c
new file mode 100644 (file)
index 0000000..75e7491
--- /dev/null
@@ -0,0 +1,427 @@
+/* -*-c-*-
+ *
+ * Implementation of the Twofish cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "twofish.h"
+#include "twofish-tab.h"
+#include "paranoia.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet twofish_keysz[] = { KSZ_RANGE, TWOFISH_KEYSZ, 0, 32, 1 };
+
+/*----- Important tables --------------------------------------------------*/
+
+static const octet q0[256] = TWOFISH_Q0, q1[256] = TWOFISH_Q1;
+static const uint32 qmds[4][256] = TWOFISH_QMDS;
+static const octet rslog[] = TWOFISH_RSLOG, rsexp[] = TWOFISH_RSEXP;
+static const octet rs[32] = TWOFISH_RS;
+
+/*----- Key initialization ------------------------------------------------*/
+
+/* --- @h@ --- *
+ *
+ * Arguments:  @uint32 x@ = input to the function
+ *             @const uint32 *l@ = key values to mix in
+ *             @unsigned k@ = number of key values there are
+ *
+ * Returns:    The output of the function @h@.
+ *
+ * Use:                Implements the Twofish function @h@.
+ */
+
+static uint32 h(uint32 x, const uint32 *l, unsigned k)
+{
+  /* --- Apply a series of @q@ tables to an integer --- */
+
+# define Q(x, qa, qb, qc, qd)                                          \
+  ((qa[((x) >> 0) & 0xff] <<  0) |                                     \
+   (qb[((x) >> 8) & 0xff] <<  8) |                                     \
+   (qc[((x) >> 16) & 0xff] << 16) |                                    \
+   (qd[((x) >> 24) & 0xff] << 24))
+
+  /* --- Grind through the tables --- */
+
+  switch (k) {
+    case 4: x = Q(x, q1, q0, q0, q1) ^ l[3];
+    case 3: x = Q(x, q1, q1, q0, q0) ^ l[2];
+    case 2: x = Q(x, q0, q1, q0, q1) ^ l[1];
+           x = Q(x, q0, q0, q1, q1) ^ l[0];
+      break;
+  }
+
+#undef Q
+
+  /* --- Apply the MDS matrix --- */
+
+  return (qmds[0][U8(x >>  0)] ^ qmds[1][U8(x >>  8)] ^
+         qmds[2][U8(x >> 16)] ^ qmds[3][U8(x >> 24)]);
+}
+
+/* --- @twofish_initfk@ --- *
+ *
+ * Arguments:  @twofish_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *             @const twofish_fk *fk@ = family-key information
+ *
+ * Returns:    ---
+ *
+ * Use:                Does the underlying Twofish key initialization with family
+ *             key.  Pass in a family-key structure initialized to
+ *             all-bits-zero for a standard key schedule.
+ */
+
+void twofish_initfk(twofish_ctx *k, const void *buf, size_t sz,
+                   const twofish_fk *fk)
+{
+# define KMAX 4
+
+  uint32 mo[KMAX], me[KMAX];
+  octet s[4][KMAX];
+
+  /* --- Expand the key into the three word arrays --- */
+
+  {
+    size_t ssz;
+    const octet *p, *q;
+    octet b[32];
+    int i;
+
+    /* --- Sort out the key size --- */
+
+    KSZ_ASSERT(twofish, sz);
+    if (sz <= 16)
+      ssz = 16;
+    else if (sz <= 24)
+      ssz = 24;
+    else if (sz <= 32)
+      ssz = 32;
+    else
+      assert(((void)"This can't happen (bad key size in twofish_init)", 0));
+
+    /* --- Extend the key if necessary --- */
+
+    if (sz == ssz)
+      p = buf;
+    else {
+      memcpy(b, buf, sz);
+      memset(b + sz, 0, ssz - sz);
+      p = b;
+    }
+
+    /* --- Finally get the word count --- */
+
+    sz = ssz / 8;
+
+    /* --- Extract words from the key --- *
+     *
+     * The @s@ table, constructed using the Reed-Solomon matrix, is cut into
+     * sequences of bytes, since this is actually more useful for computing
+     * the S-boxes.
+     */
+
+    q = p;
+    for (i = 0; i < sz; i++) {
+      octet ss[4];
+      const octet *r = rs;
+      int j;
+
+      /* --- Extract the easy subkeys --- */
+
+      me[i] = LOAD32_L(q) ^ fk->t0[2 * i];
+      mo[i] = LOAD32_L(q + 4) ^ fk->t0[2 * i + 1];
+
+      /* --- Now do the Reed-Solomon thing --- */
+
+      for (j = 0; j < 4; j++) {
+       const octet *qq = q;
+       unsigned a = 0;
+       int k;
+
+       for (k = 0; k < 8; k++) {
+         unsigned char x = *qq ^ fk->t1[i * 8 + k];
+         if (x) a ^= rsexp[rslog[x] + *r];
+         qq++;
+         r++;
+       }
+
+       s[j][sz - 1 - i] = ss[j] = a;
+      }
+      q += 8;
+    }
+
+    /* --- Clear away the temporary buffer --- */
+
+    if (p == b)
+      BURN(b);
+  }
+
+  /* --- Construct the expanded key --- */
+
+  {
+    uint32 p = 0x01010101;
+    uint32 ip = 0;
+    int i;
+
+    for (i = 0; i < 40; i += 2) {
+      uint32 a, b;
+      a = h(ip, me, sz);
+      b = h(ip + p, mo, sz);
+      b = ROL32(b, 8);
+      a += b; b += a;
+      k->k[i] = U32(a);
+      k->k[i + 1] = ROL32(b, 9);
+      ip += 2 * p;
+    }
+
+    for (i = 0; i < 8; i++)
+      k->k[i] ^= fk->t23[i];
+    for (i = 8; i < 40; i += 2) {
+      k->k[i] ^= fk->t4[0];
+      k->k[i + 1] ^= fk->t4[1];
+    }
+  }
+
+  /* --- Construct the S-box tables --- */
+
+  {
+    unsigned i;
+    static const octet *q[4][KMAX + 1] = {
+      { q1, q0, q0, q1, q1 },
+      { q0, q0, q1, q1, q0 },
+      { q1, q1, q0, q0, q0 },
+      { q0, q1, q1, q0, q1 }
+    };
+
+    for (i = 0; i < 4; i++) {
+      unsigned j;
+      uint32 x;
+
+      for (j = 0; j < 256; j++) {
+       x = j;
+
+       /* --- Push the byte through the q tables --- */
+
+       switch (sz) {
+         case 4: x = q[i][4][x] ^ s[i][3];
+         case 3: x = q[i][3][x] ^ s[i][2];
+         case 2: x = q[i][2][x] ^ s[i][1];
+                 x = q[i][1][x] ^ s[i][0];
+           break;
+       }
+
+       /* --- Write it in the key schedule --- */
+
+       k->g[i][j] = qmds[i][x];
+      }
+    }
+  }
+
+  /* --- Clear everything away --- */
+
+  BURN(me);
+  BURN(mo);
+  BURN(s);
+}
+
+/* --- @twofish_init@ --- *
+ *
+ * Arguments:  @twofish_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Twofish key buffer.  Twofish accepts key sizes
+ *             of up to 256 bits (32 bytes).
+ */
+
+void twofish_init(twofish_ctx *k, const void *buf, size_t sz)
+{
+  static const twofish_fk fk = { { 0 } };
+  twofish_initfk(k, buf, sz, &fk);
+}
+
+/* --- @twofish_fkinit@ --- *
+ *
+ * Arguments:  @twofish_fk *fk@ = pointer to family key block
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a family-key buffer.  This implementation allows
+ *             family keys of any size acceptable to the Twofish algorithm.
+ */
+
+void twofish_fkinit(twofish_fk *fk, const void *buf, size_t sz)
+{
+  twofish_ctx k;
+  uint32 pt[4], ct[4];
+  const octet *kk;
+  unsigned i;
+
+  twofish_init(&k, buf, sz);
+
+  for (i = 0; i < 4; i++) pt[i] = (uint32)-1;
+  twofish_eblk(&k, pt, fk->t0 + 4);
+
+  kk = buf; sz /= 4;
+  for (i = 0; i < sz; i++) { fk->t0[i] = LOAD32_L(kk); kk += 4; }
+
+  for (i = 0; i < 4; i++) pt[i] = 0; twofish_eblk(&k, pt, ct);
+  for (i = 0; i < 4; i++) STORE32_L(fk->t1 + i * 4, ct[i]);
+  pt[0] = 1; twofish_eblk(&k, pt, ct);
+  for (i = 0; i < 4; i++) STORE32_L(fk->t1 + 4 + i * 4, ct[i]);
+
+  pt[0] = 2; twofish_eblk(&k, pt, fk->t23 + 0);
+  pt[0] = 3; twofish_eblk(&k, pt, fk->t23 + 4);
+  pt[0] = 4; twofish_eblk(&k, pt, ct);
+  fk->t4[0] = ct[0]; fk->t4[1] = ct[1];
+
+  BURN(k);
+}
+
+/*----- Main encryption ---------------------------------------------------*/
+
+/* --- Feistel function --- */
+
+#define GG(k, t0, t1, x, y, kk) do {                                   \
+  t0 = (k->g[0][U8(x >>         0)] ^                                          \
+       k->g[1][U8(x >>  8)] ^                                          \
+       k->g[2][U8(x >> 16)] ^                                          \
+       k->g[3][U8(x >> 24)]);                                          \
+  t1 = (k->g[1][U8(y >>         0)] ^                                          \
+       k->g[2][U8(y >>  8)] ^                                          \
+       k->g[3][U8(y >> 16)] ^                                          \
+       k->g[0][U8(y >> 24)]);                                          \
+  t0 += t1;                                                            \
+  t1 += t0;                                                            \
+  t0 += kk[0];                                                         \
+  t1 += kk[1];                                                         \
+} while (0)
+
+/* --- Round operations --- */
+
+#define EROUND(k, w, x, y, z, kk) do {                                 \
+  uint32 _t0, _t1;                                                     \
+  GG(k, _t0, _t1, w, x, kk);                                           \
+  kk += 2;                                                             \
+  y ^= _t0; y = ROR32(y, 1);                                           \
+  z = ROL32(z, 1); z ^= _t1;                                           \
+} while (0)
+
+#define DROUND(k, w, x, y, z, kk) do {                                 \
+  uint32 _t0, _t1;                                                     \
+  kk -= 2;                                                             \
+  GG(k, _t0, _t1, w, x, kk);                                           \
+  y = ROL32(y, 1); y ^= _t0;                                           \
+  z ^= _t1; z = ROR32(z, 1);                                           \
+} while (0)
+
+/* --- Complete encryption functions --- */
+
+#define EBLK(k, a, b, c, d, w, x, y, z) do {                           \
+  const uint32 *_kk = k->k + 8;                                                \
+  uint32 _a = a, _b = b, _c = c, _d = d;                               \
+  _a ^= k->k[0]; _b ^= k->k[1]; _c ^= k->k[2]; _d ^= k->k[3];          \
+  EROUND(k, _a, _b, _c, _d, _kk);                                      \
+  EROUND(k, _c, _d, _a, _b, _kk);                                      \
+  EROUND(k, _a, _b, _c, _d, _kk);                                      \
+  EROUND(k, _c, _d, _a, _b, _kk);                                      \
+  EROUND(k, _a, _b, _c, _d, _kk);                                      \
+  EROUND(k, _c, _d, _a, _b, _kk);                                      \
+  EROUND(k, _a, _b, _c, _d, _kk);                                      \
+  EROUND(k, _c, _d, _a, _b, _kk);                                      \
+  EROUND(k, _a, _b, _c, _d, _kk);                                      \
+  EROUND(k, _c, _d, _a, _b, _kk);                                      \
+  EROUND(k, _a, _b, _c, _d, _kk);                                      \
+  EROUND(k, _c, _d, _a, _b, _kk);                                      \
+  EROUND(k, _a, _b, _c, _d, _kk);                                      \
+  EROUND(k, _c, _d, _a, _b, _kk);                                      \
+  EROUND(k, _a, _b, _c, _d, _kk);                                      \
+  EROUND(k, _c, _d, _a, _b, _kk);                                      \
+  _c ^= k->k[4]; _d ^= k->k[5]; _a ^= k->k[6]; _b ^= k->k[7];          \
+  w = U32(_c); x = U32(_d); y = U32(_a); z = U32(_b);                  \
+} while (0)
+
+#define DBLK(k, a, b, c, d, w, x, y, z) do {                           \
+  const uint32 *_kk = k->k + 40;                                       \
+  uint32 _a = a, _b = b, _c = c, _d = d;                               \
+  _a ^= k->k[4]; _b ^= k->k[5]; _c ^= k->k[6]; _d ^= k->k[7];          \
+  DROUND(k, _a, _b, _c, _d, _kk);                                      \
+  DROUND(k, _c, _d, _a, _b, _kk);                                      \
+  DROUND(k, _a, _b, _c, _d, _kk);                                      \
+  DROUND(k, _c, _d, _a, _b, _kk);                                      \
+  DROUND(k, _a, _b, _c, _d, _kk);                                      \
+  DROUND(k, _c, _d, _a, _b, _kk);                                      \
+  DROUND(k, _a, _b, _c, _d, _kk);                                      \
+  DROUND(k, _c, _d, _a, _b, _kk);                                      \
+  DROUND(k, _a, _b, _c, _d, _kk);                                      \
+  DROUND(k, _c, _d, _a, _b, _kk);                                      \
+  DROUND(k, _a, _b, _c, _d, _kk);                                      \
+  DROUND(k, _c, _d, _a, _b, _kk);                                      \
+  DROUND(k, _a, _b, _c, _d, _kk);                                      \
+  DROUND(k, _c, _d, _a, _b, _kk);                                      \
+  DROUND(k, _a, _b, _c, _d, _kk);                                      \
+  DROUND(k, _c, _d, _a, _b, _kk);                                      \
+  _c ^= k->k[0]; _d ^= k->k[1]; _a ^= k->k[2]; _b ^= k->k[3];          \
+  w = U32(_c); x = U32(_d); y = U32(_a); z = U32(_b);                  \
+} while (0)
+
+/* --- @twofish_eblk@, @twofish_dblk@ --- *
+ *
+ * Arguments:  @const twofish_ctx *k@ = pointer to key block
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+void twofish_eblk(const twofish_ctx *k, const uint32 *s, uint32 *d)
+{
+  EBLK(k, s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]);
+}
+
+void twofish_dblk(const twofish_ctx *k, const uint32 *s, uint32 *d)
+{
+  DBLK(k, s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]);
+}
+
+BLKC_TEST(TWOFISH, twofish)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/twofish.h b/symm/twofish.h
new file mode 100644 (file)
index 0000000..328d00a
--- /dev/null
@@ -0,0 +1,143 @@
+/* -*-c-*-
+ *
+ * The Twofish block cipher
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Twofish block cipher ---------------------------------*
+ *
+ * Twofish was designed by Bruce Schneier, John Kelsey, Doug Whiting, David
+ * Wagner, Chris Hall and Niels Ferguson.  The algorithm is unpatented and
+ * free for anyone to use.  It was one of the five AES finalist algorithms.
+ *
+ * Twofish is a complex cipher offering various space and time tradeoffs.
+ * This implementation has a heavy key schedule and fast bulk encryption.
+ */
+
+#ifndef CATACOMB_TWOFISH_H
+#define CATACOMB_TWOFISH_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define TWOFISH_BLKSZ 16
+#define TWOFISH_KEYSZ 32
+#define TWOFISH_CLASS (N, L, 128)
+
+extern const octet twofish_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct twofish_ctx {
+  uint32 k[40];
+  uint32 g[4][256];
+} twofish_ctx;
+
+typedef struct twofish_fk {
+  uint32 t0[8], t23[8], t4[2];
+  octet t1[32];
+} twofish_fk;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @twofish_initfk@ --- *
+ *
+ * Arguments:  @twofish_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *             @const twofish_fk *fk@ = family-key information
+ *
+ * Returns:    ---
+ *
+ * Use:                Does the underlying Twofish key initialization with family
+ *             key.  Pass in a family-key structure initialized to
+ *             all-bits-zero for a standard key schedule.
+ */
+
+extern void twofish_initfk(twofish_ctx */*k*/, const void */*buf*/,
+                          size_t /*sz*/, const twofish_fk */*fk*/);
+
+/* --- @twofish_init@ --- *
+ *
+ * Arguments:  @twofish_ctx *k@ = pointer to key block to fill in
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a Twofish key buffer.  Twofish accepts keys of up
+ *             to 256 bits in length.
+ */
+
+extern void twofish_init(twofish_ctx */*k*/,
+                        const void */*buf*/, size_t /*sz*/);
+
+/* --- @twofish_fkinit@ --- *
+ *
+ * Arguments:  @twofish_fk *fk@ = pointer to family key block
+ *             @const void *buf@ = pointer to buffer of key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a family-key buffer.  This implementation allows
+ *             family keys of any size acceptable to the Twofish algorithm.
+ */
+
+extern void twofish_fkinit(twofish_fk */*fk*/,
+                          const void */*buf*/, size_t /*sz*/);
+
+/* --- @twofish_eblk@, @twofish_dblk@ --- *
+ *
+ * Arguments:  @const twofish_ctx *k@ = pointer to key block
+ *             @const uint32 s[4]@ = pointer to source block
+ *             @uint32 d[4]@ = pointer to destination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void twofish_eblk(const twofish_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*d*/);
+
+extern void twofish_dblk(const twofish_ctx */*k*/,
+                        const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/whirlpool-mktab.c b/symm/whirlpool-mktab.c
new file mode 100644 (file)
index 0000000..cac72bf
--- /dev/null
@@ -0,0 +1,231 @@
+/* -*-c-*-
+ *
+ * Generate tables for Whirlpool hash function
+ *
+ * (c) 2005 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Static variables --------------------------------------------------*/
+
+static const octet E[] = {
+  0x1, 0xb, 0x9, 0xc, 0xd, 0x6, 0xf, 0x3,
+  0xe, 0x8, 0x7, 0x4, 0xa, 0x2, 0x5, 0x0
+}, R[] = {
+  0x7, 0xc, 0xb, 0xd, 0xe, 0x4, 0x9, 0xf,
+  0x6, 0x3, 0x8, 0xa, 0x2, 0x5, 0x1, 0x0
+}, C[] = {
+  0x1, 0x1, 0x4, 0x1, 0x8, 0x5, 0x2, 0x9
+};
+
+static octet S[256], T[256][8], log[256], alog[256];
+
+/*----- Main code ---------------------------------------------------------*/
+
+#define S_MOD 0x11d
+
+static void logtable(void)
+{
+  unsigned i, x;
+
+  for (i = 0, x = 1; i < 255; i++) {
+    log[x] = i;
+    alog[i] = x;
+    x <<= 1;
+    if (x & 0x100) x ^= S_MOD;
+  }
+}
+
+static octet mul(octet x, octet y)
+  { if (!x || !y) return (0); return (alog[(log[x] + log[y]) % 255]); }
+
+static void sbox(void)
+{
+  unsigned i, j;
+  octet EI[16];
+  octet l, r, y;
+
+  for (i = 0; i < 16; i++) EI[E[i]] = i;
+  for (i = 0; i < 256; i++) {
+    l = (i >> 4) & 0xf;
+    r = (i >> 0) & 0xf;
+    l = E[l]; r = EI[r];
+    y = R[l ^ r];
+    l = E[l ^ y]; r = EI[r ^ y];
+    S[i] = (l << 4) | r;
+  }
+
+  for (i = 0; i < 256; i++) {
+    for (j = 0; j < 8; j++)
+      T[i][j] = mul(S[i], C[j]);
+  }
+}
+
+static unsigned long w32(int i, int j, int k)
+{
+  kludge64 x;
+  LOAD64_L_(x, T[j]);
+  ROL64_(x, x, i * 8);
+  return (k ? LO64(x) : HI64(x));
+}
+
+int main(void)
+{
+  int i, j;
+
+  puts("\
+/* -*-c-*-\n\
+ *\n\
+ * Whirlpool tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_WHIRLPOOL_TAB_H\n\
+#define CATACOMB_WHIRLPOOL_TAB_H\n\
+");
+
+  /* --- Write out the S-box --- */
+
+  logtable();
+  sbox();
+  fputs("\
+/* --- The byte substitution --- */\n\
+\n\
+#define WHIRLPOOL_S {                                                  \\\n\
+  ", stdout);
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", S[i]);
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Write out the key constant tables --- */
+
+  fputs("\
+/* --- The key generation constants --- */\n\
+\n\
+#define WHIRLPOOL_C {                                                  \\\n\
+  ", stdout);
+  for (i = 0; i < 10; i++) {
+    printf("X64(%08lx, %08lx)",
+          (unsigned long)LOAD32_L(&S[i * 8 + 4]),
+          (unsigned long)LOAD32_L(&S[i * 8 + 0]));
+    if (i == 9)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 2 == 1)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Write out the big T tables --- */
+
+  fputs("\
+/* --- The 64-bit big round tables --- */\n\
+\n\
+#define WHIRLPOOL_T {                                                  \\\n\
+  { ", stdout);
+  for (j = 0; j < 8; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("X64(%08lx, %08lx)", w32(j, i, 0), w32(j, i, 1));
+      if (i == 255) {
+       if (j == 7)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 2 == 1)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  /* --- Write out the smaller U and V tables --- */
+
+  fputs("\
+/* --- The 32-bit round tables --- */\n\
+\n\
+#define WHIRLPOOL_U {                                                  \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08lx", w32(j, i, 1));
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  fputs("\
+#define WHIRLPOOL_V {                                                  \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08lx", w32(j, i, 0));
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  /* --- Done --- */
+
+  puts("#endif");
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/whirlpool.c b/symm/whirlpool.c
new file mode 100644 (file)
index 0000000..4543287
--- /dev/null
@@ -0,0 +1,304 @@
+/* -*-c-*-
+ *
+ * Whirlpool hash function
+ *
+ * (c) 2005 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "whirlpool.h"
+#include "whirlpool-tab.h"
+
+#if defined(HAVE_UINT64)
+#  define USE64
+#endif
+
+/*----- Static variables --------------------------------------------------*/
+
+static const kludge64 C[10] = WHIRLPOOL_C;
+
+#ifdef USE64
+static const kludge64 T[8][256] = WHIRLPOOL_T;
+#else
+static const uint32 U[4][256] = WHIRLPOOL_U, V[4][256] = WHIRLPOOL_V;
+#endif
+
+/*----- Main code ---------------------------------------------------------*/
+
+#define DUMP(k, v) do {                                                        \
+  int i;                                                               \
+  printf("\n");                                                                \
+  for (i = 0; i < 8; i++)                                              \
+    printf("  %08x %08x         :  %08x %08x\n",                               \
+          HI64(k[i]), LO64(k[i]),                                      \
+          HI64(v[i]), LO64(v[i]));                                     \
+} while (0)
+
+#define OFFSET(i, n) (((i) + 16 - (n)) % 8)
+
+#ifdef USE64
+
+#define BYTE(x, j)                                                     \
+  U8((j) < 4 ?                                                         \
+    (LO64(x) >> ((j) * 8)) :                                           \
+    (HI64(x) >> ((j) * 8 - 32)))
+
+#define TT(v, i, j) T[j][BYTE(v[OFFSET(i, j)], j)]
+
+#define XROW(vv, v, i) do {                                            \
+  XOR64(vv[i], vv[i], TT(v, i, 1));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 2));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 3));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 4));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 5));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 6));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 7));                                    \
+} while (0)
+
+#define ROWZ(vv, v, i) do {                                            \
+  vv[i] = TT(v, i, 0);                                                 \
+  XROW(vv, v, i);                                                      \
+} while (0)
+
+#define ROWK(vv, v, i, k) do {                                         \
+  vv[i] = k;                                                           \
+  XOR64(vv[i], vv[i], TT(v, i, 0));                                    \
+  XROW(vv, v, i);                                                      \
+} while (0)
+
+#else
+
+#define BYTE(x, j) U8((x) >> (((j) & 3) * 8))
+
+#define UUL(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].lo, j)]
+#define VVL(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].lo, j)]
+#define UUH(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].hi, j)]
+#define VVH(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].hi, j)]
+
+#define XROW(vv, v, i) do {                                            \
+  vv[i].lo ^= UUL(v, i, 1); vv[i].hi ^= VVL(v, i, 1);                  \
+  vv[i].lo ^= UUL(v, i, 2); vv[i].hi ^= VVL(v, i, 2);                  \
+  vv[i].lo ^= UUL(v, i, 3); vv[i].hi ^= VVL(v, i, 3);                  \
+  vv[i].lo ^= VVH(v, i, 4); vv[i].hi ^= UUH(v, i, 4);                  \
+  vv[i].lo ^= VVH(v, i, 5); vv[i].hi ^= UUH(v, i, 5);                  \
+  vv[i].lo ^= VVH(v, i, 6); vv[i].hi ^= UUH(v, i, 6);                  \
+  vv[i].lo ^= VVH(v, i, 7); vv[i].hi ^= UUH(v, i, 7);                  \
+} while (0)
+
+#define ROWZ(vv, v, i) do {                                            \
+  vv[i].lo = UUL(v, i, 0);  vv[i].hi = VVL(v, i, 0);                   \
+  XROW(vv, v, i);                                                      \
+} while (0)
+
+#define ROWK(vv, v, i, k) do {                                         \
+  vv[i] = k;                                                           \
+  vv[i].lo ^= UUL(v, i, 0); vv[i].hi ^= VVL(v, i, 0);                  \
+  XROW(vv, v, i);                                                      \
+} while (0)
+
+#endif
+
+#define RHO(vv, v, kk, k) do {                                         \
+  ROWK(kk, k, 0, *c++);          ROWK(vv, v, 0, kk[0]);                        \
+  ROWZ(kk, k, 1);        ROWK(vv, v, 1, kk[1]);                        \
+  ROWZ(kk, k, 2);        ROWK(vv, v, 2, kk[2]);                        \
+  ROWZ(kk, k, 3);        ROWK(vv, v, 3, kk[3]);                        \
+  ROWZ(kk, k, 4);        ROWK(vv, v, 4, kk[4]);                        \
+  ROWZ(kk, k, 5);        ROWK(vv, v, 5, kk[5]);                        \
+  ROWZ(kk, k, 6);        ROWK(vv, v, 6, kk[6]);                        \
+  ROWZ(kk, k, 7);        ROWK(vv, v, 7, kk[7]);                        \
+} while (0)
+
+void whirlpool_compress(whirlpool_ctx *ctx, const void *sbuf)
+{
+  kludge64 m[8], k[8], kk[8], v[8], vv[8];
+  const kludge64 *c = C;
+  const octet *s = sbuf;
+  int i;
+
+  for (i = 0; i < 8; i++) {
+    LOAD64_L_(m[i], &s[i * 8]);
+    XOR64(v[i], m[i], ctx->s[i]);
+  }
+
+  RHO(vv, v, kk, ctx->s);
+  RHO(v, vv, k, kk);
+  RHO(vv, v, kk, k);
+  RHO(v, vv, k, kk);
+  RHO(vv, v, kk, k);
+  RHO(v, vv, k, kk);
+  RHO(vv, v, kk, k);
+  RHO(v, vv, k, kk);
+  RHO(vv, v, kk, k);
+  RHO(v, vv, k, kk);
+
+  for (i = 0; i < 8; i++) {
+    XOR64(ctx->s[i], ctx->s[i], m[i]);
+    XOR64(ctx->s[i], ctx->s[i], v[i]);
+  }
+}
+
+/* --- @whirlpool_init@, @whirlpool256_init@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void whirlpool_init(whirlpool_ctx *ctx)
+{
+  int i;
+
+  for (i = 0; i < 8; i++)
+    SET64(ctx->s[i], 0, 0);
+  ctx->off = 0;
+  ctx->nh = ctx->nl = 0;
+}
+
+/* --- @whirlpool_set@, @whirlpool256_set@ --- *
+ *
+ * Arguments:  @whirlpool_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 whirlpool_set(whirlpool_ctx *ctx, const void *buf, unsigned long count)
+{
+  const octet *p = buf;
+  int i;
+
+  for (i = 0; i < 8; i++) {
+    LOAD64_L_(ctx->s[i], p);
+    p += 8;
+  }
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @whirlpool_hash@, @whirlpool256_hash@ --- *
+ *
+ * Arguments:  @whirlpool_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 whirlpool_hash(whirlpool_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(WHIRLPOOL, whirlpool, ctx, buf, sz);
+}
+
+/* --- @whirlpool_done@, @whirlpool256_done@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+static void final(whirlpool_ctx *ctx)
+{
+  HASH_PAD(WHIRLPOOL, whirlpool, ctx, 0x80, 0, 32);
+  memset(ctx->buf + WHIRLPOOL_BUFSZ - 32, 0, 24);
+  STORE32(ctx->buf + WHIRLPOOL_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3));
+  STORE32(ctx->buf + WHIRLPOOL_BUFSZ - 4, ctx->nl << 3);
+  whirlpool_compress(ctx, ctx->buf);
+}
+
+void whirlpool_done(whirlpool_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  int i;
+
+  final(ctx);
+  for (i = 0; i < 8; i++) {
+    STORE64_L_(p, ctx->s[i]);
+    p += 8;
+  }
+}
+
+void whirlpool256_done(whirlpool256_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  int i;
+
+  final(ctx);
+  for (i = 0; i < 4; i++) {
+    STORE64_L_(p, ctx->s[i]);
+    p += 8;
+  }
+}
+
+/* --- @whirlpool_state@, @whirlpool256_state@ --- *
+ *
+ * Arguments:  @whirlpool_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 @whirlpool_set@.
+ */
+
+unsigned long whirlpool_state(whirlpool_ctx *ctx, void *state)
+{
+  octet *p = state;
+  int i;
+
+  for (i = 0; i < 8; i++) {
+    STORE64_L_(p, ctx->s[i]);
+    p += 8;
+  }
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(WHIRLPOOL, whirlpool)
+
+/* --- Test code --- */
+
+HASH_TEST(WHIRLPOOL, whirlpool)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/whirlpool.h b/symm/whirlpool.h
new file mode 100644 (file)
index 0000000..95b40dc
--- /dev/null
@@ -0,0 +1,175 @@
+/* -*-c-*-
+ *
+ * Implementation of the Whirlpool hash function
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Whirlpool hash function ------------------------------*
+ *
+ * Whirlpool was designed by Paulo Barreto and Vincent Rijmen.  Its
+ * compression function is based on similar ideas to Rijndael (also
+ * codesigned by Rijmen).
+ *
+ * Whirlpool256 is simply Whirlpool with its final output truncated to 256
+ * bits.  This is, I hope, about as good as a 256-bit hash function can get.
+ * It isn't vulnerable to the Kelsey-Schneier generic second-preimage attack
+ * against MD hash functions because of its larger internal state (see also
+ * Lucks).
+ */
+
+#ifndef CATACOMB_WHIRLPOOL_H
+#define CATACOMB_WHIRLPOOL_H
+#define CATACOMB_WHIRLPOOL256_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define WHIRLPOOL_BUFSZ 64
+#define WHIRLPOOL_HASHSZ 64
+#define WHIRLPOOL_STATESZ 64
+
+#define WHIRLPOOL256_BUFSZ 64
+#define WHIRLPOOL256_HASHSZ 32
+#define WHIRLPOOL256_STATESZ 64
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct whirlpool_ctx {
+  kludge64 s[8];                       /* Chaining variables */
+  uint32 nh, nl;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[WHIRLPOOL_BUFSZ];          /* Accumulation buffer */
+} whirlpool_ctx, whirlpool256_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @whirlpool_compress@, @whirlpool256_compress@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA-512 compression function.
+ */
+
+extern void whirlpool_compress(whirlpool_ctx */*ctx*/, const void */*sbuf*/);
+#define whirlpool256_compress whirlpool_compress
+
+/* --- @whirlpool_init@, @whirlpool256_init@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void whirlpool_init(whirlpool_ctx */*ctx*/);
+#define whirlpool256_init whirlpool_init
+
+/* --- @whirlpool_set@, @whirlpool256_set@ --- *
+ *
+ * Arguments:  @whirlpool_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 whirlpool_set(whirlpool_ctx */*ctx*/, const void */*buf*/,
+                         unsigned long /*count*/);
+#define whirlpool256_set whirlpool_set
+
+/* --- @whirlpool_hash@, @whirlpool256_hash@ --- *
+ *
+ * Arguments:  @whirlpool_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 whirlpool_hash(whirlpool_ctx */*ctx*/,
+                          const void */*buf*/, size_t /*sz*/);
+#define whirlpool256_hash whirlpool_hash
+
+/* --- @whirlpool_done@, @whirlpool256_done@ --- *
+ *
+ * Arguments:  @whirlpool_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 whirlpool_done(whirlpool_ctx */*ctx*/, void */*hash*/);
+extern void whirlpool256_done(whirlpool_ctx */*ctx*/, void */*hash*/);
+
+/* --- @whirlpool_state@, @whirlpool256_state@ --- *
+ *
+ * Arguments:  @whirlpool_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 @whirlpool_set@.
+ */
+
+extern unsigned long whirlpool_state(whirlpool_ctx */*ctx*/,
+                                    void */*state*/);
+#define whirlpool256_state whirlpool_state
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash whirlpool;
+extern const gchash whirlpool256;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/symm/whirlpool256.c b/symm/whirlpool256.c
new file mode 100644 (file)
index 0000000..48245f2
--- /dev/null
@@ -0,0 +1,12 @@
+/* -*-c-*-
+ *
+ * Stub code for Whirlpool-256
+ */
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "whirlpool256.h"
+
+GHASH_DEF(WHIRLPOOL256, whirlpool256)
+HASH_TEST(WHIRLPOOL256, whirlpool256)
diff --git a/symm/whirlpool256.h b/symm/whirlpool256.h
new file mode 100644 (file)
index 0000000..8091d74
--- /dev/null
@@ -0,0 +1,11 @@
+/* -*-c-*-
+ *
+ * Stub header for Whirlpool-256
+ */
+
+#ifndef CATACOMB_WHIRLPOOL256_H
+#define CATACOMB_WHIRLPOOL256_H
+
+#include "whirlpool.h"
+
+#endif
diff --git a/symm/xtea.c b/symm/xtea.c
new file mode 100644 (file)
index 0000000..7f95981
--- /dev/null
@@ -0,0 +1,120 @@
+/* -*-c-*-
+ *
+ * The Extended Tiny Encryption Algorithm
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "gcipher.h"
+#include "paranoia.h"
+#include "xtea.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet xtea_keysz[] = { KSZ_RANGE, XTEA_KEYSZ, 0, 16, 1 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @xtea_init@ --- *
+ *
+ * Arguments:  @xtea_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an XTEA key buffer.  The key buffer must be 16
+ *             bytes long.
+ */
+
+void xtea_init(xtea_ctx *k, const void *buf, size_t sz)
+{
+  octet kb[16];
+  const octet *p;
+
+  KSZ_ASSERT(xtea, sz);
+  if (sz >= sizeof(kb))
+    p = buf;
+  else {
+    memcpy(kb, buf, sz);
+    memset(kb + sz, 0, sizeof(kb) - sz);
+    p = kb;
+  }
+
+  k->k[0] = LOAD32(p + 0); k->k[1] = LOAD32(p +  4);
+  k->k[2] = LOAD32(p + 8); k->k[3] = LOAD32(p + 12);
+  k->r = 32;
+
+  if (p == kb)
+    BURN(kb);
+}
+
+/* --- @xtea_eblk@, @xtea_dblk@ --- *
+ *
+ * Arguments:  @const xtea_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to xteatination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+#define DELTA 0x9e3779b9
+
+void xtea_eblk(const xtea_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 y = s[0], z = s[1];
+  uint32 n = 0;
+  unsigned i;
+
+  for (i = 0; i < k->r; i++) {
+    y = U32(y + ((((z << 4) ^ (z >> 5)) + z) ^ (n + k->k[n & 3])));
+    n += DELTA;
+    z = U32(z + ((((y << 4) ^ (y >> 5)) + y) ^ (n + k->k[(n >> 11) & 3])));
+  }
+  d[0] = y; d[1] = z;
+}
+
+void xtea_dblk(const xtea_ctx *k, const uint32 *s, uint32 *d)
+{
+  uint32 y = s[0], z = s[1];
+  uint32 n = DELTA * k->r;
+  unsigned i;
+
+  for (i = 0; i < k->r; i++) {
+    z = U32(z - ((((y << 4) ^ (y >> 5)) + y) ^ (n + k->k[(n >> 11) & 3])));
+    n -= DELTA;
+    y = U32(y - ((((z << 4) ^ (z >> 5)) + z) ^ (n + k->k[n & 3])));
+  }
+  d[0] = y; d[1] = z;
+}
+
+BLKC_TEST(XTEA, xtea)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/symm/xtea.h b/symm/xtea.h
new file mode 100644 (file)
index 0000000..768a526
--- /dev/null
@@ -0,0 +1,104 @@
+/* -*-c-*-
+ *
+ * The Extended Tiny Encryption Algorithm
+ *
+ * (c) 2000 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.
+ */
+
+/*----- Notes on the Tiny Encryption Algorithm ----------------------------*
+ *
+ * XTEA is an amazingly simple 64-round Feistel network.  It's tiny, fairly
+ * quick and surprisingly strong.  It was invented by David Wheeler and Roger
+ * Needham.  It's unpatented.  XTEA is a new version of TEA, by the same
+ * designers, which fixes some weaknesses in TEA's key schedule.
+ *
+ * This implementation uses big-endian byte order, following SCAN.
+ */
+
+#ifndef CATACOMB_XTEA_H
+#define CATACOMB_XTEA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define XTEA_BLKSZ 8
+#define XTEA_KEYSZ 16
+#define XTEA_CLASS (N, B, 64)
+
+extern const octet xtea_keysz[];
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct xtea_ctx {
+  unsigned r;
+  uint32 k[4];
+} xtea_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @xtea_init@ --- *
+ *
+ * Arguments:  @xtea_ctx *k@ = pointer to key block
+ *             @const void *buf@ = pointer to key buffer
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an XTEA key buffer.  The key buffer may be up to
+ *             16 bytes long.
+ */
+
+extern void xtea_init(xtea_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
+
+/* --- @xtea_eblk@, @xtea_dblk@ --- *
+ *
+ * Arguments:  @const xtea_ctx *k@ = pointer to key block
+ *             @const uint32 s[2]@ = pointer to source block
+ *             @uint32 d[2]@ = pointer to xteatination block
+ *
+ * Returns:    ---
+ *
+ * Use:                Low-level block encryption and decryption.
+ */
+
+extern void xtea_eblk(const xtea_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+extern void xtea_dblk(const xtea_ctx */*k*/,
+                     const uint32 */*s*/, uint32 */*d*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/tea.c b/tea.c
deleted file mode 100644 (file)
index 4cb5ef8..0000000
--- a/tea.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/* -*-c-*-
- *
- * $Id: tea.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The Tiny Encryption Algorithm
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "paranoia.h"
-#include "tea.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet tea_keysz[] = { KSZ_RANGE, TEA_KEYSZ, 0, 16, 1 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @tea_init@ --- *
- *
- * Arguments:  @tea_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a TEA key buffer.  The key buffer must be 16
- *             bytes long.
- */
-
-void tea_init(tea_ctx *k, const void *buf, size_t sz)
-{
-  octet kb[16];
-  const octet *p;
-
-  KSZ_ASSERT(tea, sz);
-  if (sz >= sizeof(kb))
-    p = buf;
-  else {
-    memcpy(kb, buf, sz);
-    memset(kb + sz, 0, sizeof(kb) - sz);
-    p = kb;
-  }
-
-  k->ka = LOAD32(p +  0); k->kb = LOAD32(p +  4);
-  k->kc = LOAD32(p +  8); k->kd = LOAD32(p + 12);
-  k->r = 32;
-
-  if (p == kb)
-    BURN(kb);
-}
-
-/* --- @tea_eblk@, @tea_dblk@ --- *
- *
- * Arguments:  @const tea_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to teatination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define DELTA 0x9e3779b9
-
-void tea_eblk(const tea_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 y = s[0], z = s[1];
-  uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd;
-  uint32 n = 0;
-  unsigned i;
-
-  for (i = 0; i < k->r; i++) {
-    n += DELTA;
-    y = U32(y + (((z << 4) + ka) ^ (z + n) ^ ((z >> 5) + kb)));
-    z = U32(z + (((y << 4) + kc) ^ (y + n) ^ ((y >> 5) + kd)));
-  }
-  d[0] = y; d[1] = z;
-}
-
-void tea_dblk(const tea_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 y = s[0], z = s[1];
-  uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd;
-  uint32 n = DELTA * k->r;
-  unsigned i;
-
-  for (i = 0; i < k->r; i++) {
-    z = U32(z - (((y << 4) + kc) ^ (y + n) ^ ((y >> 5) + kd)));
-    y = U32(y - (((z << 4) + ka) ^ (z + n) ^ ((z >> 5) + kb)));
-    n -= DELTA;
-  }
-  d[0] = y; d[1] = z;
-}
-
-BLKC_TEST(TEA, tea)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/tea.h b/tea.h
deleted file mode 100644 (file)
index 6d96b90..0000000
--- a/tea.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*-c-*-
- *
- * $Id: tea.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The Tiny Encryption Algorithm
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Tiny Encryption Algorithm ----------------------------*
- *
- * TEA is an amazingly simple 64-round Feistel network.  It's tiny, fairly
- * quick and surprisingly strong.  It was invented by David Wheeler and Roger
- * Needham.  It's unpatented.  The keyspace is has only 126 effective bits,
- * and there are related-key attacks.  If you want these fixed, use XTEA.
- *
- * This implementation uses big-endian byte order, following SCAN.
- */
-
-#ifndef CATACOMB_TEA_H
-#define CATACOMB_TEA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define TEA_BLKSZ 8
-#define TEA_KEYSZ 16
-#define TEA_CLASS (N, B, 64)
-
-extern const octet tea_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct tea_ctx {
-  unsigned r;
-  uint32 ka, kb, kc, kd;
-} tea_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @tea_init@ --- *
- *
- * Arguments:  @tea_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a TEA key buffer.  The key buffer may be up to 16
- *             bytes long.
- */
-
-extern void tea_init(tea_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @tea_eblk@, @tea_dblk@ --- *
- *
- * Arguments:  @const tea_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to teatination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void tea_eblk(const tea_ctx */*k*/,
-                    const uint32 */*s*/, uint32 */*d*/);
-extern void tea_dblk(const tea_ctx */*k*/,
-                    const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/tests/.gitignore b/tests/.gitignore
deleted file mode 100644 (file)
index 8b605eb..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-cast256
-mars
-rijndael
-serpent
-tea-test
-twofish
-xtea-test
diff --git a/tests/bbs b/tests/bbs
deleted file mode 100644 (file)
index 7c46e0f..0000000
--- a/tests/bbs
+++ /dev/null
@@ -1,16 +0,0 @@
-# Test vectors for Blum-Blum-Shub generator
-#
-# $Id: bbs,v 1.2 2000/07/09 21:33:54 mdw Exp $
-
-bbs {
-  58618255351802153154518076227263324405595169368832105733339611861073310668957206153928098662820028322143309562326246028101842658621324089654810023510552099428926874474919949521150122806716423750640359105584279946965449493907636556236204117444242840921432253645386399913807490661488722966090824347967771475377
-  2
-  4a488784b0b74c53fe820e3416f67fb7f238898f711a8b5d3f3ea70b0ec264120b7bfaef30f841a979cb76ca9e9c6b01415e7618b5d6c4cc30db539852ca86d23b3527d566a76910d43ed9ba2b83596f3411354ae37c53cf0c2eab7e7e13ac7c58de83cbfd8b0a6b7cdcb7bcef92bf96a48e18124c2c21e7964a9b701b5ea4ab;
-}
-
-bbs-jump {
-  10300002644323831640029548502577413794096963710947992849414516873746495715149677373680896096678934650462228369293905743592335562158905193518665447759028003
-  8901308291494485065585437130459769427950766447948540080704500059827922533698081294071192603392538957644021072601596274962775430269633339980725226130767879
-  15
-  250;
-}
diff --git a/tests/blowfish b/tests/blowfish
deleted file mode 100644 (file)
index 9f7075e..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-# Test vectors for Blowfish
-#
-# $Id: blowfish,v 1.3 2001/04/29 17:38:07 mdw Exp $
-
-blowfish {
-
-  # --- Main block cipher ---
-  #
-  # Taken from Bruce Schneier's web pages, I think...
-
-  0000000000000000 0000000000000000 4ef997456198dd78;
-  ffffffffffffffff ffffffffffffffff 51866fd5b85ecb8a;
-  3000000000000000 1000000000000001 7d856f9a613063f2;
-  1111111111111111 1111111111111111 2466dd878b963c9d;
-  0123456789abcdef 1111111111111111 61f9c3802281b096;
-  1111111111111111 0123456789abcdef 7d0cc630afda1ec7;
-  0000000000000000 0000000000000000 4ef997456198dd78;
-  fedcba9876543210 0123456789abcdef 0aceab0fc6a0a28d;
-  7ca110454a1a6e57 01a1d6d039776742 59c68245eb05282b;
-  0131d9619dc1376e 5cd54ca83def57da b1b8cc0b250f09a0;
-  07a1133e4a0b2686 0248d43806f67172 1730e5778bea1da4;
-  3849674c2602319e 51454b582ddf440a a25e7856cf2651eb;
-  04b915ba43feb5b6 42fd443059577fa2 353882b109ce8f1a;
-  0113b970fd34f2ce 059b5e0851cf143a 48f4d0884c379918;
-  0170f175468fb5e6 0756d8e0774761d2 432193b78951fc98;
-  43297fad38e373fe 762514b829bf486a 13f04154d69d1ae5;
-  07a7137045da2a16 3bdd119049372802 2eedda93ffd39c79;
-  04689104c2fd3b2f 26955f6835af609a d887e0393c2da6e3;
-  37d06bb516cb7546 164d5e404f275232 5f99d04f5b163969;
-  1f08260d1ac2465e 6b056e18759f5cca 4a057a3b24d3977b;
-  584023641aba6176 004bd6ef09176062 452031c1e4fada8e;
-  025816164629b007 480d39006ee762f2 7555ae39f59b87bd;
-  49793ebc79b3258f 437540c8698f3cfa 53c55f9cb49fc019;
-  4fb05e1515ab73a7 072d43a077075292 7a8e7bfa937e89a3;
-  49e95d6d4ca229bf 02fe55778117f12a cf9c5d7a4986adb5;
-  018310dc409b26d6 1d9d5c5018f728c2 d1abb290658bc778;
-  1c587f1c13924fef 305532286d6f295a 55cb3774d13ef201;
-  0101010101010101 0123456789abcdef fa34ec4847b268b2;
-  1f1f1f1f0e0e0e0e 0123456789abcdef a790795108ea3cae;
-  e0fee0fef1fef1fe 0123456789abcdef c39e072d9fac631d;
-  0000000000000000 ffffffffffffffff 014933e0cdaff6e4;
-  ffffffffffffffff 0000000000000000 f21e9a77b71c49bc;
-  0123456789abcdef 0000000000000000 245946885754369a;
-  fedcba9876543210 ffffffffffffffff 6b5c5a9c5d9e0a5a;
-
-  # --- Key schedule test ---
-  #
-  # From wherever the previous tests came from.
-
-  f0
-       fedcba9876543210        f9ad597c49db005e;
-
-  f0e1
-       fedcba9876543210        e91d21c1d961a6d6;
-
-  f0e1d2
-       fedcba9876543210        e9c2b70a1bc65cf3;
-
-  f0e1d2c3
-       fedcba9876543210        be1e639408640f05;
-
-  f0e1d2c3b4
-       fedcba9876543210        b39e44481bdb1e6e;
-
-  f0e1d2c3b4a5
-       fedcba9876543210        9457aa83b1928c0d;
-
-  f0e1d2c3b4a596
-       fedcba9876543210        8bb77032f960629d;
-
-  f0e1d2c3b4a59687
-       fedcba9876543210        e87a244e2cc85e82;
-
-  f0e1d2c3b4a5968778
-       fedcba9876543210        15750e7a4f4ec577;
-
-  f0e1d2c3b4a596877869
-       fedcba9876543210        122ba70b3ab64ae0;
-
-  f0e1d2c3b4a5968778695a
-       fedcba9876543210        3a833c9affc537f6;
-
-  f0e1d2c3b4a5968778695a4b
-       fedcba9876543210        9409da87a90f6bf2;
-
-  f0e1d2c3b4a5968778695a4b3c
-       fedcba9876543210        884f80625060b8b4;
-
-  f0e1d2c3b4a5968778695a4b3c2d
-       fedcba9876543210        1f85031c19e11968;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e
-       fedcba9876543210        79d9373a714ca34f;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f
-       fedcba9876543210        93142887ee3be15c;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f00
-       fedcba9876543210        03429e838ce2d14b;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f0011
-       fedcba9876543210        a4299e27469ff67b;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f001122
-       fedcba9876543210        afd5aed1c1bc96a8;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f00112233
-       fedcba9876543210        10851c0e3858da9f;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344
-       fedcba9876543210        e6f51ed79b9db21f;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455
-       fedcba9876543210        64a6e14afd36b46f;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566
-       fedcba9876543210        80c7d7d45a5479ad;
-
-  f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677
-       fedcba9876543210        05044b62fa52d080;
-}
diff --git a/tests/cast128 b/tests/cast128
deleted file mode 100644 (file)
index dacd736..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# $Id: cast128,v 1.1 2000/06/17 12:11:49 mdw Exp $
-#
-# Test vectors for CAST128
-
-cast128 {
-  0123456712345678234567893456789a
-  0123456789abcdef
-  238b4fe5847e44b2;
-
-  01234567123456782345
-  0123456789abcdef
-  eb6a711a2c02271b;
-
-  0123456712
-  0123456789abcdef
-  7ac816d16e9b302e;
-}
diff --git a/tests/des b/tests/des
deleted file mode 100644 (file)
index 28cd9e8..0000000
--- a/tests/des
+++ /dev/null
@@ -1,64 +0,0 @@
-# Test vectors for DES
-#
-# $Id: des,v 1.2 2001/05/07 17:32:32 mdw Exp $
-
-des {
-  # --- 7-byte keys ---
-
-  00451338957377 4e6f772069732074 3fa40e8a984d4815;
-  b6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1;
-
-  # --- 8-byte keys ---
-
-  0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
-  0022446688aaccee 4e6f772069732074 3fa40e8a984d4815;
-  0123456789abcdef 68652074696d6520 6a271787ab8883f9;
-  0123456789abcdef 666f7220616c6c20 893d51ec4b563b53;
-  0123456789abcdef 0123456789abcde7 c95744256a5ed31d;
-  b763d297f70606fb 328da675ff5abd2c cd3e9f9b670671d1;
-
-  # --- Tests for all DES S-boxes ---
-
-  7ca110454a1a6e57 01a1d6d039776742 690f5b0d9a26939b;
-  0131d9619dc1376e 5cd54ca83def57da 7a389d10354bd271;
-  07a1133e4a0b2686 0248d43806f67172 868ebb51cab4599a;
-  3849674c2602319e 51454b582ddf440a 7178876e01f19b2a;
-  04b915ba43feb5b6 42fd443059577fa2 af37fb421f8c4095;
-  0113b970fd34f2ce 059b5e0851cf143a 86a560f10ec6d85b;
-  0170f175468fb5e6 0756d8e0774761d2 0cd3da020021dc09;
-  43297fad38e373fe 762514b829bf486a ea676b2cb7db2b7a;
-  07a7137045da2a16 3bdd119049372802 dfd64a815caf1a0f;
-  04689104c2fd3b2f 26955f6835af609a 5c513c9c4886c088;
-  37d06bb516cb7546 164d5e404f275232 0a2aeeae3ff4ab77;
-  1f08260d1ac2465e 6b056e18759f5cca ef1bf03e5dfa575a;
-  584023641aba6176 004bd6ef09176062 88bf0db6d70dee56;
-  025816164629b007 480d39006ee762f2 a1f9915541020b56;
-  49793ebc79b3258f 437540c8698f3cfa 6fbf1cafcffd0556;
-  4fb05e1515ab73a7 072d43a077075292 2f22e49bab7ca1ac;
-  49e95d6d4ca229bf 02fe55778117f12a 5a6b612cc26cce4a;
-  018310dc409b26d6 1d9d5c5018f728c2 5f4c038ed12b2e41;
-  1c587f1c13924fef 305532286d6f295a 63fac0d034d9f793;
-
-  # --- Rivest's test vector set ---
-
-  9474b8e8c73bca7d 9474b8e8c73bca7d 8da744e0c94e5e17;
-  8da744e0c94e5e17 0cdb25e3ba3c6d79 8da744e0c94e5e17;
-  0cdb25e3ba3c6d79 0cdb25e3ba3c6d79 4784c4ba5006081f;
-  4784c4ba5006081f 1cf1fc126f2ef842 4784c4ba5006081f;
-  1cf1fc126f2ef842 1cf1fc126f2ef842 e4be250042098d13;
-  e4be250042098d13 7bfc5dc6adb5797c e4be250042098d13;
-  7bfc5dc6adb5797c 7bfc5dc6adb5797c 1ab3b4d82082fb28;
-  1ab3b4d82082fb28 c1576a14de707097 1ab3b4d82082fb28;
-  c1576a14de707097 c1576a14de707097 739b68cd2e26782a;
-  739b68cd2e26782a 2a59f0c464506edb 739b68cd2e26782a;
-  2a59f0c464506edb 2a59f0c464506edb a5c39d4251f0a81e;
-  a5c39d4251f0a81e 7239ac9a6107ddb1 a5c39d4251f0a81e;
-  7239ac9a6107ddb1 7239ac9a6107ddb1 070cac8590241233;
-  070cac8590241233 78f87b6e3dfecf61 070cac8590241233;
-  78f87b6e3dfecf61 78f87b6e3dfecf61 95ec2578c2c433f0;
-  95ec2578c2c433f0 1b1a2ddb4c642438 95ec2578c2c433f0;
-
-  # --- The EFF answer to Matt Blaze's challenge ---
-
-  0e329232ea6d0d73 8787878787878787 0000000000000000;
-}
diff --git a/tests/des3 b/tests/des3
deleted file mode 100644 (file)
index 0f8b3d1..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# Test vectors for double and triple DES
-#
-# $Id: des3,v 1.1 1999/09/03 08:41:14 mdw Exp $
-
-des3 {
-  # --- Some simple single-DES things ---
-
-  00451338957377 4e6f772069732074 3fa40e8a984d4815;
-  b6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1;
-
-  0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
-  0123456789abcdef 68652074696d6520 6a271787ab8883f9;
-  0123456789abcdef 666f7220616c6c20 893d51ec4b563b53;
-  0123456789abcdef 0123456789abcde7 c95744256a5ed31d;
-
-  0045133895737700451338957377 4e6f772069732074 3fa40e8a984d4815;
-  b6c74cbf60c1fdb6c74cbf60c1fd 328da675ff5abd2c cd3e9f9b670671d1;
-
-  0123456789abcdef0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
-  0123456789abcdef0123456789abcdef 68652074696d6520 6a271787ab8883f9;
-  0123456789abcdef0123456789abcdef 666f7220616c6c20 893d51ec4b563b53;
-  0123456789abcdef0123456789abcdef 0123456789abcde7 c95744256a5ed31d;
-
-  004513389573770045133895737700451338957377
-       4e6f772069732074 3fa40e8a984d4815;
-  b6c74cbf60c1fdb6c74cbf60c1fdb6c74cbf60c1fd
-       328da675ff5abd2c cd3e9f9b670671d1;
-
-  0123456789abcdef0123456789abcdef0123456789abcdef
-       4e6f772069732074 3fa40e8a984d4815;
-  0123456789abcdef0123456789abcdef0123456789abcdef
-       68652074696d6520 6a271787ab8883f9;
-  0123456789abcdef0123456789abcdef0123456789abcdef
-       666f7220616c6c20 893d51ec4b563b53;
-  0123456789abcdef0123456789abcdef0123456789abcdef
-       0123456789abcde7 c95744256a5ed31d;
-
-  # --- Genuine longer keys ---
-
-  0123456789abcdeffedcba9876543210 0123456789abcde7 7f1d0a77826b8aff;
-  0123456789abcdeffedcba987654321089abcdef01234567
-       0123456789abcde7 de0b7c06ae5e0ed5;
-}
diff --git a/tests/desx b/tests/desx
deleted file mode 100644 (file)
index fd77fc4..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# Test vectors for DES
-#
-# $Id: desx,v 1.1 2001/04/03 19:36:51 mdw Exp $
-
-desx {
-  # --- From SCAN ---
-
-  0123456789abcdef1011121314151617
-    4445535864657378 d8fa5084fad4b35c;
-  01010101010101010123456789abcdef1011121314151617
-    94dbe082549a14ef 9011121314151617;
-
-  # --- 7-bit key tests ---
-
-  004513389573771011121314151617
-    4445535864657378 d8fa5084fad4b35c;
-  000000000000000123456789abcdef1011121314151617
-    94dbe082549a14ef 9011121314151617;
-
-  # --- Equivalence tests ---
-
-  00451338957377 4e6f772069732074 3fa40e8a984d4815;
-  0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
-}
diff --git a/tests/dsa b/tests/dsa
deleted file mode 100644 (file)
index d61f510..0000000
--- a/tests/dsa
+++ /dev/null
@@ -1,121 +0,0 @@
-# Test vectors for DSA
-#
-# $Id: dsa,v 1.5 2001/02/03 16:10:12 mdw Exp $
-
-# --- About the tests ---
-#
-# There's only one test vector from FIPS-186.  The others I've made up.  The
-# tests themselves are split into parameter generation, signature generation,
-# and verification.
-
-gen {
-  # --- One that I made up ---
-
-  bbac0ab63411435cb72f1f95b16ab94c92c34211 256
-  bbac0ab63411435cb72f1f95b16ab94c92c34221 10
-  0x84d192cd06ae59691897fa409da6198d5269325d
-  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
-  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e;
-
-  # --- FIPS-186 test vector ---
-
-  d5014e4b60ef2ba8b6211b4062ba3224e0427dd3 512
-  d5014e4b60ef2ba8b6211b4062ba3224e0427dd3 105
-  0xc773218c737ec8ee993b4f2ded30f48edace915f
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802;
-
-  # --- And a full-sized vector ---
-
-  d1a29e27dfe4d60124cc41a59e012ae690408acfc3266d07f4eaeefdc9f8c70d2d2a338d
-  1024
-  d1a29e27dfe4d60124cc41a59e012ae690408acfc3266d07f4eaeefdc9f8c70d2d2a338d
-  66
-  0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9
-  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
-  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014;
-}
-
-sign {
-  # --- Quick simple test ---
-
-  0x84d192cd06ae59691897fa409da6198d5269325d
-  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
-  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
-  0x1234 "An example message"
-  649b1058e0fe7ee849d3cb00b8ec3053ad0793b8
-  2718bf488b981992b164e664224dd00ca1ed4e1c
-  5c085679fbfa9ee806781bdbd86a67dbf14df640;
-
-  # --- The FIPS-186 test vector ---
-
-  0xc773218c737ec8ee993b4f2ded30f48edace915f
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
-  0x2070b3223dba372fde1c0ffc7b2e3b498b260614
-  "abc"
-  358dad571462710f50e254cf1a376b2bdeaadfbf
-  8bac1ab66410435cb7181f95b16ab97c92b341c0
-  41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
-
-  # --- 1024-bit modulus test ---
-
-  0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9
-  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
-  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
-  0x23a252f60bae4907a8ed5b6203e2b1da32848cd9
-  "A message signed with a 1024-bit DSA key."
-  12ccb231683a3d9c13dca6fe882349537eebfd03
-  2a301061ac185440fbf595f8f7d894158b8d1897
-  51aedaa73cb8d47e07281d14dda5ea8c0ddf7503;
-}
-
-verify-good {
-  # --- Simple test ----
-
-  0x84d192cd06ae59691897fa409da6198d5269325d
-  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
-  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
-  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47
-  "An example message"
-  2718bf488b981992b164e664224dd00ca1ed4e1c
-  5c085679fbfa9ee806781bdbd86a67dbf14df640;
-
-  # --- The FIPS-186 test vector ---
-
-  0xc773218c737ec8ee993b4f2ded30f48edace915f
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
-  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
-  "abc"
-  8bac1ab66410435cb7181f95b16ab97c92b341c0
-  41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
-
-  # --- 1024-bit modulus test ---
-
-  0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9
-  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
-  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
-  0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074
-  "A message signed with a 1024-bit DSA key."
-  2a301061ac185440fbf595f8f7d894158b8d1897
-  51aedaa73cb8d47e07281d14dda5ea8c0ddf7503;
-}
-
-verify-bad {
-  0xc773218c737ec8ee993b4f2ded30f48edace915f
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
-  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
-  "abd"
-  8bac1ab66410435cb7181f95b16ab97c92b341c0
-  41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
-
-  0xc773218c737ec8ee993b4f2ded30f48edace915f
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
-  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
-  "abc"
-  18bac1ab66410435cb7181f95b16ab97c92b341c0
-  41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
-}
diff --git a/tests/ec b/tests/ec
deleted file mode 100644 (file)
index b3c6e0e..0000000
--- a/tests/ec
+++ /dev/null
@@ -1,453 +0,0 @@
-# $Id$
-#
-# Elliptic curve tests
-
-check {
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    0;
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810"
-    -1;
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"
-    0;
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411,
-      0xdccf19d3e76abfa05d529c07575f54c94fa5fc9f3decc246"
-    0;
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    0;
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810"
-    -1;
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"
-    0;
-
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    0;
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810"
-    -1;
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"
-    0;
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411,
-      0xdccf19d3e76abfa05d529c07575f54c94fa5fc9f3decc246"
-    0;
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    0;
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794810"
-    -1;
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee"
-    0;
-
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1"
-    0;
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f0"
-    -1;
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    0;
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1"
-    0;
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f0"
-    -1;
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    0;
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0591168d4994637e8343e36,
-      0x7fa8423c5ae194b56cdf21998ad8a721ef1201b8c"
-    0;
-}
-
-find {
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811";
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1011 inf;
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411
-    "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411,
-      0x2330e62c1895405fa2ad63f8a8a0ab35b05a0360c2133db9";
-
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811";
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1011 inf;
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411
-    "0x188da80eb03090f67cbf20eb43a18801f4ff0afd82ff1411,
-      0x2330e62c1895405fa2ad63f8a8a0ab35b05a0360c2133db9";
-
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    0x3f0eba16286a2d57ea0991168d4994637e8343e36
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7";
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    0x310eba16386a2d57ea0591168d4997637e8745e36 inf;
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    0x3f0eba16286a2d57ea0591168d4994637e8343e36
-    "0x3f0eba16286a2d57ea0591168d4994637e8343e36,
-      0x7fa8423c5ae194b56cdf21998ad8a721ef1201b8c";
-}
-
-neg {
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1";
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1";
-}
-
-dbl {
-  "prime: 23 prime: 1, 1" "4, 0" inf;
-  "prime: 23 primeproj: 1, 1" "4, 0" inf;
-
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
-      0x49ed3be7f510e30e2462c517ad39038e493fc573c";
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
-      0x49ed3be7f510e30e2462c517ad39038e493fc573c";
-
-  "binpoly: 0x020000000000000000000000000000200000000000000001
-    bin: 0, 0x1ee9"
-    "0x18, 0xd"
-    "0x1bd555555555555555555555555554e8000000000000158,
-      0x14e999999999999999999999999998d7000000000001fe6";
-}
-
-add {
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
-
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
-
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
-      0x49ed3be7f510e30e2462c517ad39038e493fc573c"
-    "0x634000577f86aa315009d6f9b906691f6edd691fe,
-      0x235a3db7a94446301e666cafea5e12cb331f4a140";
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
-      0x49ed3be7f510e30e2462c517ad39038e493fc573c"
-    "0x634000577f86aa315009d6f9b906691f6edd691fe,
-      0x235a3db7a94446301e666cafea5e12cb331f4a140";
-}
-
-sub {
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x634000577f86aa315009d6f9b906691f6edd691fe,
-      0x235a3db7a94446301e666cafea5e12cb331f4a140"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
-      0x49ed3be7f510e30e2462c517ad39038e493fc573c";
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x634000577f86aa315009d6f9b906691f6edd691fe,
-      0x235a3db7a94446301e666cafea5e12cb331f4a140"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    "0x1aeb33fed9c49e0200a0c561ea66d5ab85bd4c2d4,
-      0x49ed3be7f510e30e2462c517ad39038e493fc573c";
-}
-
-mul {
-  "prime: 23 prime: 1, 1" "0, 1" 28 inf;
-  "prime: 23 prime: 1, 1" "0, 1" 29 "0, 1";
-  "prime: 23 primeproj: 1, 1" "0, 1" 28 inf;
-  "prime: 23 primeproj: 1, 1" "0, 1" 29 "0, 1";
-
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-     6277101735386680763835789423176059013767194773182842284080
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-     6277101735386680763835789423176059013767194773182842284081
-     inf;
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-     6277101735386680763835789423176059013767194773182842284080
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-  "prime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-     6277101735386680763835789423176059013767194773182842284081
-     inf;
-
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-     6277101735386680763835789423176059013767194773182842284080
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     prime: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-     6277101735386680763835789423176059013767194773182842284081
-     inf;
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-     6277101735386680763835789423176059013767194773182842284080
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-  "niceprime: 6277101735386680763835789423207666416083908700390324961279
-     primeproj: -3, 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-     6277101735386680763835789423176059013767194773182842284081
-     inf;
-
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    5846006549323611672814742442876390689256843201586
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0xd51fbc6c71a0094fa2cdd545b11c5c0c797324f1";
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    bin: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    5846006549323611672814742442876390689256843201587
-    inf;
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    5846006549323611672814742442876390689256843201586
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0xd51fbc6c71a0094fa2cdd545b11c5c0c797324f1";
-  "binpoly: 0x800000000000000000000000000000000000000c9
-    binproj: 1, 0x20a601907b8c953ca1481eb10512f78744a3205fd"
-    "0x3f0eba16286a2d57ea0991168d4994637e8343e36,
-      0x325f41d0ef702dc310254c42d65851a3b91471ac7"
-    5846006549323611672814742442876390689256843201587
-    inf;
-
-  "binpoly: 0x800000000000000000000000000000000000000c9; bin: 1, 1"
-    "0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8,
-      0x289070fb05d38ff58321f2e800536d538ccdaa3d9"
-    5846006549323611672814741753598448348329118574063
-    inf;
-  "binpoly: 0x800000000000000000000000000000000000000c9; binproj: 1, 1"
-    "0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8,
-      0x289070fb05d38ff58321f2e800536d538ccdaa3d9"
-    5846006549323611672814741753598448348329118574063
-    inf;
-}
diff --git a/tests/gdsa b/tests/gdsa
deleted file mode 100644 (file)
index 45df0b3..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-# $Id: gdsa,v 1.2 2004/04/08 01:36:16 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 { secp160r1 }" sha
-  0xaa374ffc3ce144e6b073307972cb6d57b2a4e982
-  "abc"
-  0x7b012db7681a3f28b9185c8b2ac5d528decd52da
-  0xce2873e5be449563391feb47ddcba2dc16379191
-  0x3480ec1371a091a464b31ce47df0cb8aa2d98b54;
-
-  "ec { sect163k1 }" sha
-  0x3a41434aa99c2ef40c8495b2ed9739cb2155a1e0d
-  "abc"
-  0xa40b301cc315c257d51d442234f5aff8189d2b6c
-  0x994d2c41aa30e52952aea8462370471b2b0a34ac
-  0x152f95ca15da1997a8c449e00cd2aa2accb988d7f;
-
-  ## This one's from P1363:
-  ##   http://grouper.ieee.org/groups/1363/P1363/testvector.txt
-  "ec { ansi-c2tnb191v1 }" sha
-  0x340562e1dda332f9d2aec168249b5696ee39d0ed4d03760f
-  "abc"
-  0x3eeace72b4919d991738d521879f787cb590aff8189d2b69
-  0x038e5a11fb55e4c65471dcd4998452b1e02d8af7099bb930
-  0x0c9a08c34468c244b4e5d6b21b3c68362807416020328b6e;
-
-  "ec { nist-p256 }" sha256
-  0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa
-  "An example message"
-  0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c
-  0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6
-  0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a;
-
-  # --- Test for over-long hash ---
-
-  "ec { sect131r1 }" sha
-  0x85bd9fd28a7e7f915891208fbb2b05c0
-  "An example message"
-  0xee98d38c001731403af6fbf77356f8ea
-  0x1cba36e768c0247d537a744b7ea62e3b9
-  0x216e5d02a0b1fb11d6d2fc4b383dcb168;
-}
-
-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 { secp160r1 }" sha
-  "0x51b4496fecc406ed0e75a24a3c03206251419dc0,
-    0xc28dcb4b73a514b468d793894f381ccc1756aa6c"
-  "abc"
-  0xce2873e5be449563391feb47ddcba2dc16379191
-  0x3480ec1371a091a464b31ce47df0cb8aa2d98b54
-  0;
-
-  "ec { sect163k1 }" sha
-  "0x037d529fa37e42195f10111127ffb2bb38644806bc,
-    0x0447026eee8b34157f3eb51be5185d2be0249ed776"
-  "abc"
-  0x994d2c41aa30e52952aea8462370471b2b0a34ac
-  0x152f95ca15da1997a8c449e00cd2aa2accb988d7f
-  0;
-
-  ## This one's from P1363:
-  ##   http://grouper.ieee.org/groups/1363/P1363/testvector.txt
-  "ec { ansi-c2tnb191v1 }" sha
-  "0x5de37e756bd55d72e3768cb396ffeb962614dea4ce28a2e7,
-    0x55c0e0e02f5fb132caf416ef85b229bbb8e1352003125ba1"
-  "abc"
-  0x038e5a11fb55e4c65471dcd4998452b1e02d8af7099bb930
-  0x0c9a08c34468c244b4e5d6b21b3c68362807416020328b6e
-  0;
-
-  "ec { nist-p256 }" sha256
-  "0xcc2aecbc5c5f6d72cd7b937279d72a732abcf880ea47e012ebec77ddbca6ed40,
-    0x90f99cd799abc0ea571d0e02bad80f8323050b1adbdbff50060b6e1e6ebd8611"
-  "An example message"
-  0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6
-  0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a
-  0;
-
-  # --- Test for over-long hash ---
-
-  "ec { sect131r1 }" sha
-  "0x2218ba2b57a7821be97c0015b797d82fe, 0x666aed14fd7a2abf867c6fa222ab26fcc"
-  "An example message"
-  0x1cba36e768c0247d537a744b7ea62e3b9
-  0x216e5d02a0b1fb11d6d2fc4b383dcb168
-  0;
-
-  "ec { sect131r1 }" sha
-  "0x2218ba2b57a7821be97c0015b797d82fe, 0x666aed14fd7a2abf867c6fa222ab26fcc"
-  "An example messag"
-  0x1cba36e768c0247d537a744b7ea62e3b9
-  0x216e5d02a0b1fb11d6d2fc4b383dcb168
-  -1;
-
-  "ec { nist-b163 }" sha512
-  "0x385a32536d1cb46d10cf3034a3dd39eb25e4f5123,
-    0x29ee1edfa37d0f306c4da17b8d883f01ce3be4d46"
-  "qpwmoeqpofaosdaspdpqoweopdoagnqornifnasd"
-  0x0231b6a807f6af1aee0598768b3fabb863d14a7f8d
-  0x01c2f638e9dffe03b562e48ca4e1a380cf8c3055f1
-  0;
-}
diff --git a/tests/gf b/tests/gf
deleted file mode 100644 (file)
index 88d94cd..0000000
--- a/tests/gf
+++ /dev/null
@@ -1,91 +0,0 @@
-# $Id$
-#
-# Test cases for higher-level binary poly arithmetic.
-
-add {
-  0 0 0;
-  1 1 0;
-  1 2 3;
-  4 5 1;
-  0x7fb838a8a0a95046b9d9d9fb4440f7bb
-    0xc1a7bd3b4e853fc92d4e1588719986aa
-    0xbe1f8593ee2c6f8f9497cc7335d97111;
-  0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b21
-    0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b22 3;
-}
-
-mul {
-  0 0 0;
-  1 0 0;
-  0 1 0;
-  1 1 1;
-  0x7fb838a8a0a95046b9d9d9fb4440f7bb
-    0xc1a7bd3b4e853fc92d4e1588719986aa
-    0x207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e;
-  0xc1a7bd3b4e853fc92d4e1588719986aa
-    0x283ed59f1226dcefa7ff0ef87ceff5d5
-    0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b22;
-  0xbe1f8593ee2c6f8f9497cc7335d97111
-    0x35a8e33503b3695be00528f8b82db931
-    0x1e2933215e1c3bba8d2b404d98f43086bfc6198a219b168f214042a5e7df6b21;
-}
-
-sqr {
-  0 0;
-  1 1;
-  3 5;
-  0x7fb838a8a0a95046b9d9d9fb4440f7bb
-    0x1555454005404440440044411100101445415141514155451010100055154545;
-  0x01f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3
-    0x0155004001541441551011510504111011050015141444454140511111554414010450154545041554440501455004140401514041104554415000450141144505;
-}
-
-div {
-  0 1 0 0;
-  0x207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e
-    0x7fb838a8a0a95046b9d9d9fb4440f7bb
-    0xc1a7bd3b4e853fc92d4e1588719986aa 0;
-  0x6e0e2a282a5411ae76767ed1103deef069ef4ed3a14ff24b
-    0x5385621c6661aaa35a24150d2c08332e
-    0x01c2334cc957151dc7
-    0x398c4111da6d06cdf3d83704ee403101;
-}
-
-exp {
-  4 0 1;
-  4 1 4;
-  0x7 2 0x15;
-  3 563 0xf000f000f000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000f000f000f;
-}
-
-irred {
-  0 0;
-  1 0;
-  2 1;
-  0xc1a7bd3b4e853fc92d4e1588719986aa 0;
-  0x800000000000000000000000000000000000000c9 1;
-  0x2000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001 1;
-}
-
-gcd {
-  0xc1a7bd3b4e853fc92d4e1588719986aa
-    0xbe1f8593ee2c6f8f9497cc7335d97111
-    3
-    0x283ed59f1226dcefa7ff0ef87ceff5d5
-    0x35a8e33503b3695be00528f8b82db931;
-  0xbe1f8593ee2c6f8f9497cc7335d97111
-    0xc1a7bd3b4e853fc92d4e1588719986aa
-    3
-    0x35a8e33503b3695be00528f8b82db931
-    0x283ed59f1226dcefa7ff0ef87ceff5d5;
-  0x800000000000000000000000000000000000000c9
-    4
-    1
-    1
-    0x20000000000000000000000000000000000000032;
-  0x800000000000000000000000000000000000000c9
-    0x3f0eba16286a2d57ea0991168d4994637e8343e36
-    1
-    0xa17e704470d80cb5a78f295db0ce543dda16a169
-    0x3c8c172e24598e90b9542e6b8f6571f54be572b50;
-}
diff --git a/tests/gfn b/tests/gfn
deleted file mode 100644 (file)
index 6586d50..0000000
--- a/tests/gfn
+++ /dev/null
@@ -1,34 +0,0 @@
-# $Id: gfn,v 1.2 2004/04/02 08:41:45 mdw Exp $
-#
-# Normal basis conversions
-
-gfn {
-  0x800000000000000000000000000000000000000c9
-  0x715169c109c612e390d347c748342bcd3b02a0bef
-  0 0;
-
-  0x800000000000000000000000000000000000000c9
-  0x715169c109c612e390d347c748342bcd3b02a0bef
-  1
-  0x7ffffffffffffffffffffffffffffffffffffffff;
-
-  0x800000000000000000000000000000000000000c9
-  0x715169c109c612e390d347c748342bcd3b02a0bef
-  0x2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8
-  0x05679b353caa46825fea2d3713ba450da0c2a4541;
-
-  0x20000000000000000000000000000000000000004000000000000000001
-  0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
-  0x066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad
-  0x1a003e0962d4f9a8e407c904a9538163adb825212600c7752ad52233279;
-
-  0x20000000000000000000000000000000000000004000000000000000001
-  0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
-  0x0fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b
-  0x18b863524b3cdfefb94f2784e0b116faac54404bc9162a363bab84a14c5;
-
-  0x20000000000000000000000000000000000000004000000000000000001
-  0x1499e398ac5d79e368559b35ca49bb7305da6c0390bcf9e2300253203c9
-  0x1006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052
-  0x04925df77bd8b8ff1a5ff519417822bfedf2bbd752644292c98c7af6e02;
-}
diff --git a/tests/gfreduce b/tests/gfreduce
deleted file mode 100644 (file)
index c7c474a..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-# $Id$
-#
-# Test efficient polynomial reduction
-
-reduce {
-         0x10000000
-  0x4509823098098435
-          0x8098435;
-  0x100000000000000050002
-    0x4509823098098435
-    0x4509823098098435;
-  0x100000000000000050002
-    0x450982309809843545609843098560803495
-    0x144f98a2f5cbc4773cfd;
-  0xb2ca471b0867d5fae2e4f27a2d2706da
-    0xf254423fef93d5d7a76ecf22c656c1352c53257875945d33
-    0x582f783fc210f72814780e69b0bd29ff;
-}
-
-modexp {
-  0x20000000000000000000000000000000000000000000000000000000000001001
-  0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  0
-  1;
-  0x20000000000000000000000000000000000000000000000000000000000001001
-  0x02
-  0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  1;
-  0x20000000000000000000000000000000000000000000000000000000000001001
-  0x435932098459080438094509845
-  0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  1;
-  0x10000000000000000000000000000000000000000003
-  0x02
-  0x0fffffffffffffffffffffffffffffffffffffffffff
-  1;
-  0x10000000000000000000000000000000000000000003
-  0x34235950984598345900983409845690805680985
-  0x0fffffffffffffffffffffffffffffffffffffffffff
-  1;
-
-  0x800000000000000000000000000000000000000c9
-  0x3f0eba16286a2d57ea0991168d4994637e8343e36
-  -1
-  0x3c8c172e24598e90b9542e6b8f6571f54be572b50;
-  0x800000000000000000000000000000000000000c9
-  0x3c8c172e24598e90b9542e6b8f6571f54be572b50
-  342345
-  0x3521fe2666efe92ca4eb160a286e0fd9427b84a62;
-  0x800000000000000000000000000000000000000c9
-  0x3f0eba16286a2d57ea0991168d4994637e8343e36
-  -342345
-  0x3521fe2666efe92ca4eb160a286e0fd9427b84a62;
-}
-
-sqrt {
-  0x20000000000000000000000000000000000000000000000000000000000001001
-  0x1f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3
-    0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa;
-  0x10000000000000000000000000000000000000000003
-    0x4594094509835690805698083560980459903450984
-    0x820291881a244a02840a2f8ece3f23f88f38bf0b3a;
-}
-
-halftrace {
-  0x20000000000000000000000000000000000000000000000000000000000001001
-  0x174e65c7d14a8ec286df8c7df17662f13f1d3563f13c8c63f23f5d0bd5d1b45cd
-   0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9d;
-}
-
-quadsolve {
-  0x20000000000000000000000000000000000000000000000000000000000001001
-  0x174e65c7d14a8ec286df8c7df17662f13f1d3563f13c8c63f23f5d0bd5d1b45cd
-   0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c;
-  0x10000000000000000000000000000000000000000003
-   0x3b818b447e90713da04f13c3b07cb5e2681d08e4700
-   0x27aa17c97dfa80bbdef9f91b243c6e6ddba1a223cac;
-  0x800000000000000000000000000000000000000c9
-    0x158fe327cc763a2fd7371ee80641ed1871a32aaa8
-    0x29ab0d7da05ffc3f1b3f97ac10e2092694aadbb7c;
-}
diff --git a/tests/gfx b/tests/gfx
deleted file mode 100644 (file)
index b26433d..0000000
--- a/tests/gfx
+++ /dev/null
@@ -1,529 +0,0 @@
-# Test vectors for low-level GF functions
-#
-# $Id: gfx,v 1.2 2004/03/21 22:52:06 mdw Exp $
-
-# --- Addition (and subtraction) ---
-
-add {
-  # --- Simple sanity tests ---
-
-  01 01 00;
-  02 02 00;
-  03 01 02;
-
-  # --- Random data tests ---
-
-  7fb838a8a0a95046b9d9d9fb4440f7bb
-    c1a7bd3b4e853fc92d4e1588719986aa
-    be1f8593ee2c6f8f9497cc7335d97111;
-  8d68905434b020ccb849e17a03a5c441
-    d2a104aaf523699c1cc7a93174d21d9c
-    5fc994fec1934950a48e484b7777d9dd;
-  027aa17c97dfa80bbdef9f91b243c6e6
-    ddba1a223cad8a39e9c986879ad21b75
-    dfc0bb5eab722232542619162891dd93;
-  d668328b2594570198fd840b4783f5d9
-    f474e9ef071c418acf1f71b9cccdd179
-    221cdb642288168b57e2f5b28b4e24a0;
-  509e024b27fb8b3655da3938d0c04f92
-    3fa219832f73843c0ae8c4f4715f633c
-    6f3c1bc808880f0a5f32fdcca19f2cae;
-  13e8b9d83c66bc5fa56e2debbab3c9c2
-    6bb190b76e090abd7f6375a6921ad17e
-    7859296f526fb6e2da0d584d28a918bc;
-  3c98c1fd7d6e4ff9adae43a38ed0f2b3
-    101f88d732a51bbe40080cabd06002
-    3c88de75aa5ceae213ee4baf250092b1;
-  2774d74b7453e63c2d314e0be52eaf79
-    54c0dc1a0bedbafcb0b707fe5e496a20
-    73b40b517fbe5cc09d8649f5bb67c559;
-  75b9d1662c48f8c40ee4e9b3138a0b59
-    0ca3e9d4c75a6e2b493d7efb8554e9f8
-    791a38b2eb1296ef47d9974896dee2a1;
-  501591c68468a7d8ecfcae3f419ecb52
-    b0ad24cd246361f779e8317e94977c57
-    e0b8b50ba00bc62f95149f41d509b705;
-  6fa69209a292924f04fb5b3469a1068b
-    d9a06e9ac90f02ad095ff84f30a9addd
-    b606fc936b9d90e20da4a37b5908ab56;
-  ce596f2830ab988dfa7dc0add68214af
-    860c30b9a27c7b2759666dd71ec578c3
-    48555f9192d7e3aaa31bad7ac8476c6c;
-  862361325b5f7a6b506b948d55697ce3
-    95142973169fbae5410a22bb88ca63ee
-    133748414dc0c08e1161b636dda31f0d;
-  237495a82a6755689df073af2a56f88c
-    ab46613ddf7787fd1be42272fcb1be44
-    8832f495f510d295861451ddd6e746c8;
-  6b2d8d2b513277cfb03d8a5731234a3d
-    9cc41fbd7189a3b5b0ff2f3746eb9bc6
-    f7e9929620bbd47a00c2a56077c8d1fb;
-  af7baf1a8ce5d42eca4353de181d085a
-    c59bde6136dda59a839605252d1dd390
-    6ae0717bba3871b449d556fb3500dbca;
-  566a7c0f9adc5a021c1759e2c80708c0
-    28d1c20f2b8613b5e1ba8e3005aef30f
-    7ebbbe00b15a49b7fdadd7d2cda9fbcf;
-  a7d716d198bf6bb3d32ba364f722de52
-    4c9a1fa66d2d0cf7935d45e83b9ce326
-    eb4d0977f59267444076e68cccbe3d74;
-  310d8bb131c4bed327529185c4d46db8
-    2742ea95019b5f186c3c848744743d4a
-    164f6124305fe1cb4b6e150280a050f2;
-  70f5bfbf5f18a3deef4230b875b3a0af
-    93c9240145720297b96a404941792a21
-    e33c9bbe1a6aa149562870f134ca8a8e;
-  1ff7c9eaebd3b76791632b609a962992
-    bc3aca2e99d965238d8433eafd717279
-    a3cd03c4720ad2441ce7188a67e75beb;
-  3d1693836d0964dea42c5e80a4307b6c
-    aed5dcd2e9e918e0ff9577f5ceb66256
-    93c34f5184e07c3e5bb929756a86193a;
-  35706029aec609b55c48ab09df59744e
-    6d9b5b4dbeb1779580cba9bbc9fb8921
-    58eb3b6410777e20dc8302b216a2fd6f;
-  7a166f842cc6c36c09508e2b23dbad97
-    01e3fc1cacc040e96217a7281a4273d2
-    7bf59398800683856b4729033999de45;
-  510ce80a4ab0f9eae5f6c3281e7506c5
-    06351138a1ecb6be56a84f1b28a26368
-    5739f932eb5c4f54b35e8c3336d765ad;
-  31bfc6590de44898c40c31bb3aaddebc
-    82b37993094c9ff6498c55ba1cced0f8
-    b30cbfca04a8d76e8d80640126630e44;
-  d00d48a90eb9e89586cc3566b28fa5ea
-    0f502f973c2f17ad79543b20a92f2905
-    df5d673e3296ff38ff980e461ba08cef;
-  df63dead9d7aea0d3fca68123b0812ae
-    ae059fd909978bc6b8824b04e113fa2a
-    7166417494ed61cb87482316da1be884;
-  4c982bd2b93a027fd08ad69227a51506
-    bdc1112c061be0756685473011c61067
-    f1593afebf21e20ab60f91a236630561;
-  dc241c84816a1a50a7ad21519e6abd3a
-    f2c4d8d96bf32d999fdc7c37cfddac67
-    2ee0c45dea9937c938715d6651b7115d;
-  a466ee3984566e4947a28704ecd99d2f
-    0a5e90153ae473c9bee43aafaec08446
-    ae387e2cbeb21d80f946bdab42191969;
-  8698e5d4eede21f8d4791d69fc4cfb22
-    7b4bb531b633dfcb80d9bd35e10d4f6b
-    fdd350e558edfe3354a0a05c1d41b449;
-  4d2462e835a51ee5be30ea2bc6abbb1b
-    fb36217f8dd0fe234bb7dcb778130156
-    b6124397b875e0c6f587369cbeb8ba4d;
-  abf5c76c26bf952d64667f5049bbe6b5
-    436fbd0ad52336b0c9d2987ac79d2909
-    e89a7a66f39ca39dadb4e72a8e26cfbc;
-  8943b34ab9bc6f6839c09a9852492238
-    38b2304265ac16c80f84be3d61a82628
-    b1f18308dc1079a0364424a533e10410;
-  ae2730b3374140b33de67be248766cc7
-    1831ce84d756a4bda1c1ee22ed047d61
-    b616fe37e017e40e9c2795c0a57211a6;
-  4a87ef0f6bc691cab6d79253876ca89e
-    c0c2f4c479ffc90aeafe0598a4ac4d4b
-    8a451bcb123958c05c2997cb23c0e5d5;
-  63b2aad38a2d3b4cf681d892ed460110
-    d707531874bbc8fa22a49fd26142c631
-    b4b5f9cbfe96f3b6d42547408c04c721;
-  f44ef4d8cd19e4f6f6264c59360de94e
-    eb619a0c5fb3c490d382ff4a5d47a0f9
-    1f2f6ed492aa206625a4b3136b4a49b7;
-  786fa5572011847269ba3f51db1226
-    a1c8ac92fa365013326e0daac2dce7b9
-    a1b0c337ad1641974007b7959307f59f;
-}
-
-mul {
-  # --- Simple sanity tests ---
-
-  00 05 00;
-  01 05 05;
-  05 01 05;
-  05 00 00;
-
-  # --- Random data tests ---
-
-  7fb838a8a0a95046b9d9d9fb4440f7bb
-    c1a7bd3b4e853fc92d4e1588719986aa
-    207ccad257b4ed64447158315bfb9aca5cbc5622cfb8fcbb1380eea1bc5c624e;
-  8d68905434b020ccb849e17a03a5c441
-    d2a104aaf523699c1cc7a93174d21d9c
-    6c75a24ff82d63e8f9425d862be997fd7517511b2563189a6f0a238b33e60a9c;
-  027aa17c97dfa80bbdef9f91b243c6e6
-    ddba1a223cad8a39e9c986879ad21b75
-    019d5567c392730cf1fbc627f1de7ff20438e649e5ba7e7299fcea4ad4c7ac5e;
-  d668328b2594570198fd840b4783f5d9
-    f474e9ef071c418acf1f71b9cccdd179
-    4a7d1a3b7b904b1b135cb89e6f37a38d7f20fcc9bd7b9ec9f0c38114d2a742e1;
-  509e024b27fb8b3655da3938d0c04f92
-    3fa219832f73843c0ae8c4f4715f633c
-    0c0ff0782f813600eda5b73c0d2deaf072ed8b9e98e94991bd2578b776063fb8;
-  13e8b9d83c66bc5fa56e2debbab3c9c2
-    6bb190b76e090abd7f6375a6921ad17e
-    0626e9a14f2ada51ad47ae2385248d361142636fed5f062be9fa0a0567f14c7c;
-  3c98c1fd7d6e4ff9adae43a38ed0f2b3
-    101f88d732a51bbe40080cabd06002
-    03cb092534c593a9f834c21f1af0da8e604c416ec14e3fca1a72ba4c2b4566;
-  2774d74b7453e63c2d314e0be52eaf79
-    54c0dc1a0bedbafcb0b707fe5e496a20
-    0b2dd510554c5442d5871586392f81d08322aa0cf052f64ee507d59ef730b520;
-  75b9d1662c48f8c40ee4e9b3138a0b59
-    0ca3e9d4c75a6e2b493d7efb8554e9f8
-    024ff62a8d33d8c51560088e304cc9b13ccec97899ba476083b86f8c1dc28fb8;
-  501591c68468a7d8ecfcae3f419ecb52
-    b0ad24cd246361f779e8317e94977c57
-    2728b02f09e5cfc78d1b5e45d0b65d58aa353e8e5a928dc80a3fd523b464291e;
-  6fa69209a292924f04fb5b3469a1068b
-    d9a06e9ac90f02ad095ff84f30a9addd
-    29e8250c13db619580291b6d03317cf82d3f97c58aa1dc247c4d4ad25870b80f;
-  ce596f2830ab988dfa7dc0add68214af
-    860c30b9a27c7b2759666dd71ec578c3
-    658c3e0257c6986e4d0b7fd1c2296182f48c395f7a01acdb623702a83c0be9b1;
-  862361325b5f7a6b506b948d55697ce3
-    95142973169fbae5410a22bb88ca63ee
-    49e7469f9f53f214425455d15b9b5cc6309617f18db3e02b98aabe1b134dbd72;
-  237495a82a6755689df073af2a56f88c
-    ab46613ddf7787fd1be42272fcb1be44
-    14a2fbfb8b9621a60325ba6fc7c979b0caa46c7a5ffb865d01859f058621c930;
-  6b2d8d2b513277cfb03d8a5731234a3d
-    9cc41fbd7189a3b5b0ff2f3746eb9bc6
-    31ff31cfbb97615558ec4becb92036b6b8715ab6df7ed6dc18caff6e0641d24e;
-  af7baf1a8ce5d42eca4353de181d085a
-    c59bde6136dda59a839605252d1dd390
-    7e281956a0ae84282a4a600a9a434bcca6f89a9a661f03ac47dcd20ef2b066a0;
-  566a7c0f9adc5a021c1759e2c80708c0
-    28d1c20f2b8613b5e1ba8e3005aef30f
-    0845bd0d5a46401395876a7992ee9762842ea8d7202222e29b973a042a703c40;
-  a7d716d198bf6bb3d32ba364f722de52
-    4c9a1fa66d2d0cf7935d45e83b9ce326
-    2e09cac5254876c45a7dacddd71f13b394ca8ab95413ab681f554c50737839ac;
-  310d8bb131c4bed327529185c4d46db8
-    2742ea95019b5f186c3c848744743d4a
-    06baa3a8c8864b5ea1f998b6138db08924f3a49ddf1ecc22fa93110323aac0b0;
-  70f5bfbf5f18a3deef4230b875b3a0af
-    93c9240145720297b96a404941792a21
-    3fc325d1e5c637ab818172e3fdb51be97a28903ee232125797ead652b391734f;
-  1ff7c9eaebd3b76791632b609a962992
-    bc3aca2e99d965238d8433eafd717279
-    0d78c92f0d674c76fd9e71ace29b1ca58da8a67530a148bcf8815b395de46ee2;
-  3d1693836d0964dea42c5e80a4307b6c
-    aed5dcd2e9e918e0ff9577f5ceb66256
-    185d9d9d173a78a2ea8a86cef12ac9a560f5c1fd96a3e40d47f2d34798d02ea8;
-  35706029aec609b55c48ab09df59744e
-    6d9b5b4dbeb1779580cba9bbc9fb8921
-    0aa132382fb96e788f85a52888a8ef7fa645e17dfaaf35444566c2a56584c38e;
-  7a166f842cc6c36c09508e2b23dbad97
-    01e3fc1cacc040e96217a7281a4273d2
-    567d64a30f28d71578a9ced5624a950fe065d706cf3318c80c3883f126c51e;
-  510ce80a4ab0f9eae5f6c3281e7506c5
-    06351138a1ecb6be56a84f1b28a26368
-    01e80b50adeebb3790d5249eb4170d093b88ab1d42d0737d3dad6825e181f0c8;
-  31bfc6590de44898c40c31bb3aaddebc
-    82b37993094c9ff6498c55ba1cced0f8
-    18a13563df977554b9d470e4c5009f7ec1c62f561a9cb2041a51e7af81e2f8a0;
-  d00d48a90eb9e89586cc3566b28fa5ea
-    0f502f973c2f17ad79543b20a92f2905
-    048955ee72a928a69b16cc80502568ece68198c8947935283c725a2e6f00c842;
-  df63dead9d7aea0d3fca68123b0812ae
-    ae059fd909978bc6b8824b04e113fa2a
-    706606ae02e140bbf3783da276f47110834defb48e89270797e86251e27369ec;
-  4c982bd2b93a027fd08ad69227a51506
-    bdc1112c061be0756685473011c61067
-    283989fcc502efa3d0006b67465f3ebe7950cac8d54daf45215e09bd6058ea52;
-  dc241c84816a1a50a7ad21519e6abd3a
-    f2c4d8d96bf32d999fdc7c37cfddac67
-    4ebfbaf107e1e74583f1a0c6de06f2a4c230c1a96329d8bac1d95d122ce8a266;
-  a466ee3984566e4947a28704ecd99d2f
-    0a5e90153ae473c9bee43aafaec08446
-    044e0764b72ad37e86d87cca3b32c4d6797a7a9b2e8ab414e0c33617d2113922;
-  8698e5d4eede21f8d4791d69fc4cfb22
-    7b4bb531b633dfcb80d9bd35e10d4f6b
-    3c8785b738a800087fb26dc2562ebd676188a1f5e3b60d51463172a5ef5906b6;
-  4d2462e835a51ee5be30ea2bc6abbb1b
-    fb36217f8dd0fe234bb7dcb778130156
-    3a1f7deaeed3275707c611b83b64b4514d9b8508ed4b0827a7001be9488af62a;
-  abf5c76c26bf952d64667f5049bbe6b5
-    436fbd0ad52336b0c9d2987ac79d2909
-    2b38ad58100db6e6bffc52c6e7622581cc5daf65c0b4f7b87dab8313af786e1d;
-  8943b34ab9bc6f6839c09a9852492238
-    38b2304265ac16c80f84be3d61a82628
-    1daa464b09e5db4bef2c404c1be1fb6d6e0c5911ee10a1d7eba409e33b26c6c0;
-  ae2730b3374140b33de67be248766cc7
-    1831ce84d756a4bda1c1ee22ed047d61
-    0f8cb866e66f56fdfd530784d441c8b37d6e0b2a87e3ea6a0a2d6f4387e076e7;
-  4a87ef0f6bc691cab6d79253876ca89e
-    c0c2f4c479ffc90aeafe0598a4ac4d4b
-    37d54041b0e7d641ee3495897524f1ef4a4dad9671261e4aa03fba0bfadb0cd2;
-  63b2aad38a2d3b4cf681d892ed460110
-    d707531874bbc8fa22a49fd26142c631
-    2e25fc4f13fd3839c0698ca373d24ca2bfe572ad3ae46a50c1294237d30c5210;
-  f44ef4d8cd19e4f6f6264c59360de94e
-    eb619a0c5fb3c490d382ff4a5d47a0f9
-    5f20a07a81d4ed9f3d1fd9fef61318d01a58ea810b12ae3976dbe6c2406b2a9e;
-  786fa5572011847269ba3f51db1226
-    a1c8ac92fa365013326e0daac2dce7b9
-    336397c17a1fde4e90cbb9113a5fcd48239d39fee0807e66f8622d97b144b6;
-}
-
-sqr {
-  # --- Simple sanity tests ---
-
-  00 00;
-  01 01;
-  03 05;
-
-  # --- Random data tests ---
-
-  7fb838a8a0a95046b9d9d9fb4440f7bb
-    1555454005404440440044411100101445415141514155451010100055154545;
-  c1a7bd3b4e853fc92d4e1588719986aa
-    5001441545510545105440110555504104511054011140401501414140144444;
-  8d68905434b020ccb849e17a03a5c441
-    4051144041001110051045000400505045401041540115440005441150101001;
-  d2a104aaf523699c1cc7a93174d21d9c
-    5104440100104444551104051441415001505015444105011510510401514150;
-  027aa17c97dfa80bbdef9f91b243c6e6
-    04154444011550411551554440004545515455415541014504100550145414;
-  ddba1a223cad8a39e9c986879ad21b75
-    5151454401440404055044514044054154415041401440154144510401451511;
-  d668328b2594570198fd840b4783f5d9
-    5114144005044045041141101115000141405551401000451015400555115141;
-  f474e9ef071c418acf1f71b9cccdd179
-    5510151054415455001501501001404450550155150145415050505151011541;
-  509e024b27fb8b3655da3938d0c04f92
-    1100415400041045041555454045051411115144054105405100500010554104;
-  3fa219832f73843c0ae8c4f4715f633c
-    0555440401414005045515054010055000445440501055101501115514050550;
-  13e8b9d83c66bc5fa56e2debbab3c9c2
-    0105544045415140055014144550115544111454045154454544450550415004;
-  6bb190b76e090abd7f6375a6921ad17e
-    1445450141004515145400410044455115551405151144144104014451011554;
-  3c98c1fd7d6e4ff9adae43a38ed0f2b3
-    0550414050015551155114541055554144514454100544054054510055044505;
-  101f88d732a51bbe40080cabd06002
-    010001554040511505044411014545541000004000504445510014000004;
-  2774d74b7453e63c2d314e0be52eaf79
-    0415151051151045151011055414055004510501105400455411045444551541;
-  54c0dc1a0bedbafcb0b707fe5e496a20
-    1110500051500144004554514544555045004515001555541154104114440400;
-  75b9d1662c48f8c40ee4e9b3138a0b59
-    1511454151011414045010405540501000545410544145050105404400451141;
-  0ca3e9d4c75a6e2b493d7efb8554e9f8
-    50440554415110501511441454044510410551155455454011111054415540;
-  501591c68468a7d8ecfcae3f419ecb52
-    1100011141015014401014404415514054505550445405551001415450451104;
-  b0ad24cd246361f779e8317e94977c57
-    4500445104105051041014051401551515415440050115544110411515501115;
-  6fa69209a292924f04fb5b3469a1068b
-    1455441441040041440441044104105500105545114505101441440100144045;
-  d9a06e9ac90f02ad095ff84f30a9addd
-    5141440014544144504100550004445100411155554010550500444144515151;
-  ce596f2830ab988dfa7dc0add68214af
-    5054114114550440050044454140405155441551500044515114400401104455;
-  860c30b9a27c7b2759666dd71ec578c3
-    4014005005004541440415501545041511411414145151150154501115405005;
-  862361325b5f7a6b506b948d55697ce3
-    4014040514010504114511551544144511001445411040511111144115505405;
-  95142973169fbae5410a22bb88ca63ee
-    4111011004411505011441554544541110010044040445454040504414055454;
-  237495a82a6755689df073af2a56f88c
-    0405151041114440044414151111144041515500150544550444111455404050;
-  ab46613ddf7787fd1be42272fcb1be44
-    4445101414010551515515154015555101455410040415045550450145541010;
-  6b2d8d2b513277cfb03d8a5731234a3d
-    1445045140510445110105041515505545000551404411150501040510440551;
-  9cc41fbd7189a3b5b0ff2f3746eb9bc6
-    4150501001554551150140414405451145005555045505151014544541455014;
-  af7baf1a8ce5d42eca4353de181d085a
-    4455154544550144405054115110045450441005110551540140015100401144;
-  c59bde6136dda59a839605252d1dd390
-    5011414551541401051451514411414440054114001104110451015151054100;
-  566a7c0f9adc5a021c1759e2c80708c0
-    1114144415500055414451501144000401500115114154045040001500405000;
-  28d1c20f2b8613b5e1ba8e3005aef30f
-    0440510150040055044540140105451154014544405405000011445455050055;
-  a7d716d198bf6bb3d32ba364f722de52
-    4415511501145101414045551445450551050445440514105515040451541104;
-  4c9a1fa66d2d0cf7935d45e83b9ce326
-    1050414401554414145104510050551541051151101154400545415054050414;
-  310d8bb131c4bed327529185c4d46db8
-    0501005140454501050150104554510504151104410140115010511014514540;
-  2742ea95019b5f186c3c848744743d4a
-    0415100454444111000141451155014014500550401040151010151005511044;
-  70f5bfbf5f18a3deef4230b875b3a0af
-    1500551145554555115501404405515454551004050045401511450544004455;
-  93c9240145720297b96a404941792a21
-    4105504104100001101115040004411545411444100010411001154104440401;
-
-  # --- Regression ---
-
-  01f081e69f45d3254530766ab98d55fa612c7bb27ea31bc2621d894be9c0b196b3
-    0155004001541441551011510504111011050015141444454140511111554414010450154545041554440501455004140401514041104554415000450141144505;
-}
-
-div {
-  # --- Random data tests ---
-
-  6e0e2a282a5411ae76767ed1103deef069ef4ed3a14ff24b
-    5385621c6661aaa35a24150d2c08332e
-    01c2334cc957151dc7
-    398c4111da6d06cdf3d83704ee403101;
-  785e80e9711074a8412abd48da670731ea
-    4c5d348767009ea85f25f7ea02ef7be7
-    01c4
-    0b17de61cc808487285b72f14fa23336;
-  d921e3736edd0d111e56c51cf4e4c343cd690dbaeb34194592ca2b80cc7e
-    c205a3c1faecfa3a74f7838e20c5678f
-    012492f38367090dbc739e8a15c414
-    34570d4431e79cc4d3ff2a583c3a56b2;
-  06e7333745e54278092c9fee2cd95768e4e343013e48fe88660cbdce
-    10f02ba313d1c57d8cf04fa2e760f19a
-    6c1708dd11c7305e9d0a1974
-    0dd6757486f880c40590ed673c22ddc6;
-  bf4adc5bd775679384d763216edc12157afec6eb4d2435a2fc793183fafadc
-    9ff35b5c87471da1e56600203f11ae65
-    014fd82ad3ab0ef9bda71f5d88ab3fe1
-    3b599b787383608d59ba518513d7d0d9;
-  0377c80101957a0c0044ee9ae96e8a7cc785a629c1
-    7ca5d5ef2a981b83417db75f9616e0ff
-    0b71080c88
-    2d21297ee7c68552c11b6199fa1d55b9;
-  1c92d440eb73a2cc5891f1881dc9d366271416b21947d3a98eb4dc5692
-    7afdf70aa9d3f0a02b238d08d14fb1d9
-    4c61f24d2263168cc50b2d3126
-    2674528444adc656d5bfe3915849a064;
-  0ae3f419ecb52b0ad24cd246361f779e8317e94977c576fa69209a292924f04f
-    b5b3469a1068bd9a06e9ac90f02ad095
-    13ecfde29e5a9f5ff20fae44744397d7
-    58be1a2775d5b0424b7e9ef4450e9e34;
-  613cc2a6b7773965bca0c2ae6237e9f702b75a0852be1830c2e689f1ec9d6599
-    b75c7b15e30e188d84c96d7de9ad41ae
-    e3c34ccd80ca28706fdcd10562bd60cd
-    466ece9c2f57ebe70b744c210507d37f;
-  3555a5f38e5450a5cc5a7eeb9504288aee23298fb8
-    8dd256a0a99d55a277c1cebca95be232
-    6fa74dc1f5
-    0fdf1eba1901a220dce11aff114ba7a2;
-  23309eefbbc3fe8df211397e58df223596c695a8993be7d81ec52b
-    9891a51ece620fdeb8c4d1dad87f979b
-    4be153fb895358027814ae
-    7d23cf0b5d1b872877af14ab1b35ea49;
-  0175cde357bdd78d4672ea176521a9ef0c0e842d62cdef309b6ed2
-    cd41cb0292968ee9c82b353e07cd6e2d
-    037f62f06af153d6ad8c01
-    3d1533e7afd150b592fb196354585cff;
-  8705d678b201c2300a347083cae184ed
-    786ea38c016bbcc3e9f5c5b4662fdaec
-    03
-    0fb632ecb1bd0774302a3e5f6091ebd9;
-  0195d1b27b916f29264d0fd33696867bc9aea2f41dce71931886c5d898e25f69
-    93a948c2e26a36dc13a1754a80cdaf8c
-    034aeb96693c049c2af77e1a7b277a5e
-    3d9d04738de1dc0a7654b8115a7ee1e1;
-  79090e88e87a94e1eb7f7ebe3147bdde846170
-    eb67415f279248028ae4052f72d48092
-    9686d1
-    7100e616ea381ee5d0b2ffb7a67ee942;
-  f254423fef93d5d7a76ecf22c656c1352c53257875945d33
-    b2ca471b0867d5fae2e4f27a2d2706da
-    01bad680bd4a0132ee
-    582f783fc210f72814780e69b0bd29ff;
-  c9bd4858bd014860f6d95dabb9a5d3d231
-    c1ff2aefeb9d6cc4ac6ae0c0535d8c13
-    011f
-    17949a58ebcb086a5350c3aceffbc4e0;
-  0b8915613beb2e89cdb36b69b7d62ef2b0197537793f71
-    242f42cdf08598d86d812a11c5647b75
-    56ddd25003c7e7
-    1aa0da3ff44f29eb5db54ea6a970dd5a;
-  e03c7f839598081d2c42f4e503484e7a4a219d0149561f3d5cbed8
-    6503cea0d8a0c6a227143d96d7cad509
-    02c53788cff1530e65640225
-    078acf15737c0320afbac57f23098cd5;
-  0165144c6d0637f8cb21bc8913188186376755bbd790566f32612993fec931
-    8ab74399da1f1a01a91521d73d12b0d9
-    02ed5b96b580b772606cb77ff49191
-    58d92bf9fb6f5fb9f0975b3e2f5ad1f8;
-  02b35947d2f507a817cb9e178bd6bcaa1d9054979482efb1ef
-    56cebd75069fe534091d8409575702cf
-    08114f9866c8343218
-    2504e1784d51b5c26cad8df6357b0567;
-  109978bc6b8824b04e113fa2a4c982bd2b93a027fd08ad69227a51506bdc11
-    12c061be0756685473011c61067dc241
-    012013fcb240a4d4f394c40f357c666b
-    040d8ec7359c8fa7cb6864bb6fe2b6ba;
-  0240b50d2853d690a8cf355e9d79626c6cb5f996cccfee3e1be7eed633
-    d233771cc22b3724a3d14382766cce97
-    07b0d38444572f483317b557d4
-    7b499146cd46dab3812cf4691d3bbe5f;
-  025e90153ae473c9bee43aafaec084468698e5d4eede21f8d4
-    791d69fc4cfb227b4bb531b633dfcb80
-    0d396769c6e551b981
-    0f0854faf0c35a4ffa142b21d0047354;
-  0de9af086a7b5a69231741ad28f72df187515e355dd8dfd9b10bfc6e87f1
-    1a5dbee5bbc0980ab55fae3b6135fca9
-    89b00eb8894915d87ca6943ac6fd
-    06fa712cefe56e4dddbccc3b389d7bc4;
-  12333fa824ddf35aa1b7de856a919b5864e94c3d63ce94
-    84c4a1d9a55cde37b41ce04d4c292491
-    257b652b91361c
-    6b6611dde69c73a3bdde7b6fd01d6748;
-  038b2304265ac16c80f84be3d61a82628ae2
-    730b3374140b33de67be248766cc7183
-    0864
-    1519f8ad4b7430e93c72ce04104d044e;
-  1d09aead497b4383dc45da08fac2950fde1e
-    d78d23956daf24a70ed9513d8185e988
-    2b5e
-    227af9cc9eff71a25a89d3a5f95fc5ee;
-  01ff9215d5fc0b3149589a96c76555a7145a7699ed03b125da8c0221ae0ea630
-    e97791f445493fa4c2858c63e89de9b1
-    027c8467e27a018bbb903b85aeeff4c1
-    79ff4a78de0c7c1a9a87d63368ddcf41;
-  033c9edec4c98b26c1bd29dd6c33418bf678921a705fe94ba8f4
-    1f200f0df4aae402308e4d3747ea3b62
-    2b085586f038a6997a7a
-    095479470eacc695a289163c245933c0;
-  01a8722b24be8d9404cc9b836ab0b739ee57ae60ed
-    0ba579d54afea4a7386c2ae3664c3d93
-    3e54693717
-    0619d78694ac997bedf949a21bf9a024;
-  112bf3440706f9935e8221356e908bdd1972bc0b7d4540a76c779d845f604fc2
-    2d27eaf11c8af56eab46d787c409293a
-    b779548b4b726be09029b5b6e414316b
-    1498f6cd6bbed85fe55529a41188ce9c;
-  5fbb399787dc1c088ae1b1a868a8fd68071662aebe6859d764d8c66d
-    0ae272c16095b2e0b88f60f0bb2c77c1
-    09593fefe3ac800d34fa59a9d1
-    022c8aa8970653e5946394aaf55db47c;
-  0ba36adf7f6695ffcaf3cb4f671fcf1167c79f
-    d24e71e6be0662a608ddaac25c3174b7
-    1836b1
-    5a783d61e236025be73de15c60fb1738;
-  28b2a0867669dbc51f86661c3a1f6a1d5565284547a3f4f2f934
-    22bd5df7bc0c1e6a863a1a1c448733e7
-    01540ca5dc8900d40c3dd7
-    0eb263f6f9b698becce9b975cac485b1;
-  15503e6802be9c85711f75250539c76426f91b77
-    91cc2ed96c4eee210ed0cb5251934085
-    2f2129de
-    5430a3c98a336b14edef0d41d93dfad1;
-  011816c74ce3765423825661feba199268be5453932b36d6
-    a8a09df55f7606d260f79ad1825ec8ac
-    02b46a057ab9b6d8
-    5d970c88da5e61edfcf5b0afb7112c76;
-  0e58c4591e74eede082861a82117d4d41239247c
-    22afdfd47592ee3f4e9777003ee9e7ad
-    7437cb93
-    0faa41dc7710ab02ea755b778975ffdb;
-  019717a6f636f25b0467f5ae365c2ba5b8
-    801bf58c5282787aec5c66702e80efd5
-    03
-    173bb862c174d38b531104a62faa95c7;
-  1af0354e3dfc333b46c5efa3354f8a0cb6bb41
-    8d59fafe11fd9b7a2f687a13696d4315
-    375fa9
-    1993cbf7dfda1e1ce89c043dc306dbdc;
-}
diff --git a/tests/gkcdsa b/tests/gkcdsa
deleted file mode 100644 (file)
index 314fe4a..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# $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/group b/tests/group
deleted file mode 100644 (file)
index dd09060..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-# $Id$
-#
-# Test group abstraction, and a bunch of other things.
-
-check {
-  "prime { 29, 7, 16 }" "ok";
-  "prime { 29, 6, 5 }" "not a subgroup";
-  "prime { 21, 2, 2 }" "p is not prime";
-  "prime { 29, 14, 9 }" "group order not prime";
-
-  "ec { secp224r1 }" "ok";
-
-  "prime { catacomb-ll-160-1024 }" "ok";
-
-  "ec {
-     prime:
-       0xdb7c2abf62e35e668076bead208b
-     primeproj:
-       0xdb7c2abf62e35e668076bead2088, 0x659ef8ba043916eede8911702b22
-     0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500
-     0xdb7c2abf62e35e7628dfac6561c5 * 1
-  }" "ok";
-
-  "ec {
-     prime:
-       0xdb7c2abf62e35e668076bead208b
-     primeproj:
-       0xdb7c2abf62e35e668076bead2088, 0x659ef8ba043916eede8911702b22
-       0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500
-       0xdb7c2abf62e35e7628dfac6561c5 * 2
-  }" "incorrect or ambiguous cofactor";
-
-  # --- This one's oakley-155 ---
-
-  "ec {
-    binpoly: 0x0800000000000000000000004000000000000001
-    binproj: 0, 0x7338F
-    0xaa089ae4666a422e714651ad9372213fa65a93,
-      0x12d29c630dda76010397809a6816be6d2ffa815
-    0xaaaaaaaaaaaaaaaaaab1fcf1e206f421a3ea1b * 12
-  }" "degree not prime";
-
-}
-
-checkelt {
-  "prime { 29, 7, 16 }" 16 0;
-  "prime { 29, 7, 16 }" 2 -1;
-
-  "ec { secp112r1 } "
-    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
-    0;
-
-  "ec {
-    binpoly: 0x0800000000000000000000004000000000000001
-    binproj: 0, 0x7338F
-    0xaa089ae4666a422e714651ad9372213fa65a93,
-      0x12d29c630dda76010397809a6816be6d2ffa815
-    0xaaaaaaaaaaaaaaaaaab1fcf1e206f421a3ea1b * 12
-  }"
-  "0x7b, 0x1c8"
-  -1;
-
-}
-
-mul {
-  "prime { 29, 7, 16 }" 8 7 27;
-
-  "prime { catacomb-ll-128-512 }"
-    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
-    32459289443738057373904596685867555624839649360339363831766212033645755638497600605981483758068704145575847399920657057013890131443911836862688141735006
-    3947634573386515057215934636174241616115542585724861166389751782289048647501330677434616929656928819642658111077814577650964230037753641582364366136933940;
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd";
-}
-
-sqr {
-  "prime { 29, 7, 16 }" 8 6;
-
-  "prime { catacomb-ll-128-512 }"
-    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
-    1140714521254648115393410274780412972862841854751618635120376750594285456137894804866135103112174518443866054055338095672091997366768745026933347678925721;
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-}
-
-inv {
-  "prime { 29, 7, 16 }" 9 13;
-
-  "prime { catacomb-ll-128-512 }"
-    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
-    5876676858790113051879264634636727534122591023949326683791506203503263391580079717512212895466773363712551406785344528808275608153699681298608650332072384;
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0xf8e6d46a003725879cefee1294db32298c06885ee186b7ee";
-}
-
-div {
-  "prime { 29, 7, 16 }" 9 5 25;
-
-  "prime { catacomb-ll-128-512 }"
-    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
-    1926426135381827210395257472845875618319108487720857260583372274154852182951667715700282388176779441854588992736540698662997833538400244234146123792411051
-    24069337702503046127918930405335466791703796668849861281722901639361967869381088162761943434867448224639537469251486209856612215080111132649928233405085;
-
-  "ec { nist-p192 }"
-    "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da,
-       0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd"
-     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-       0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888,
-       0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab";
-}
-
-exp {
-  "prime { 29, 7, 16 }" 3 12 16;
-
-  "prime { 29, 7, 16 }" 3 -12 20;
-
-  "prime { catacomb-ll-128-512 }"
-    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
-    147362842169670001895012880214773009850
-    5743039465765061017258257285641279669186626264432710496849307123351095219091264933384359874588390730293795471675184250790999035405886273905917889887366080;
-
-  "prime { catacomb-ll-128-512 }"
-    3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
-    -147362842169670001895012880214773009850
-    3548613102603269389984811279864031309564549180885835723408511495891024326106890973751615845620404633717662823827170012116865930893524976817060348977482376;
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    6277101735386680763835789423176059013767194773182842284081
-    inf;
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    3131675836296406071791252329528905062261497366991742517193
-    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
-      0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb";
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    3131675836296406071791252329528905062261497366991742517193
-    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
-      0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb";
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    -3131675836296406071791252329528905062261497366991742517193
-    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
-      0x3916ef6b34cbece1ac63c24da080cd97f107201fc5774904";
-}
-
-mexp-1 {
-  "prime { 29, 7, 16 }" 3 12 16;
-  "prime { 29, 7, 16 }" 3 -12 20;
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    3131675836296406071791252329528905062261497366991742517193
-    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
-      0xc6e91094cb34131e539c3db25f7f32670ef8dfe03a88b6fb";
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    -3131675836296406071791252329528905062261497366991742517193
-    "0x7f55059a125dd0d2b40dc3a712248b2848a5e5fa11111f71,
-      0x3916ef6b34cbece1ac63c24da080cd97f107201fc5774904";
-}
-
-mexp-2 {
-  "prime { 29, 7, 16 }" 3 12 8 2 9;
-  "prime { 29, 7, 16 }" 3 -12 8 2 4;
-
-  "prime { catacomb-ll-128-512 }"
-   3344609493517948819439808013094817124423784439045485500527919676470975342917009634212031124646834193243018749323077268170586751415510015906107400678608590
-   -147362842169670001895012880214773009850
-   130340428707563070626027539288099297037336608388990593367322442443880297841210613523501678207607756678300142264348927299637006055881968995671289567513600
-   91626412351157168611316239052073981423
-   1022777063245982511046303002728993765008184164346724419524981660559588777350492245381260023136750231183070065817596986237402046431653662723677455952067221;
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    -3131675836296406071791252329528905062261497366991742517193
-    "0xea711858c23d92f9964655910bc90a197a915e90111cf11b,
-      0x664189a1d8b2bb24f2b2ac64b19e2178118842e6ba9f4ad5"
-    1110875761630725856340142297645383444629395595869672555585
-    "0xaa25bb0bf38b06821e8641c1afb8bc078dbe11c3cf9bc97,
-       0xf1a4c09d621fb52736f6010ae90e9bc9771ac017a62098f9";
-}
-
-toint {
-  "prime { 29, 7, 16 }" 15 0 15;
-  "prime { 29, 7, 16 }" 0 0 0;
-
-  "ec { nist-p192 }" inf -1 0;
-
-  "ec { nist-p192 }"
-    "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
-      0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    0 602046282375688656758213480587526111916698976636884684818;
-}
-
-fromint {
-  "prime { 29, 7, 16 }" 15 0 15;
-  "prime { 29, 7, 16 }" 0 0 0;
-  "prime { 29, 7, 16 }" 39527306161272833161358334459 0 19;
-
-  "ec { nist-p192 }" 1 -1 inf;
-  "ec { nist-p192 }" 0
-    0 "0, 0x7b685605ee600cb363db5ea912f2bb5e3a0a2e0e60360f12";
-}
-
-toec {
-  "prime { 29, 7, 16 }" 0 -1 inf;
-  "ec { nist-p192 }" inf 0 inf;
-  "ec { secp112r1 }"
-    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
-    0
-    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500";
-}
-
-fromec {
-  "prime { 29, 7, 16 }" inf -1 0;
-  "prime { 29, 7, 16 }" "39527306161272833161358334459, 9" 0 19;
-
-  "ec { secp112r1 }" inf 0 inf;
-  "ec { nist-p192 }" "1, 5" -1 inf;
-
-  "ec { secp112r1 }"
-    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
-    0
-    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500";
-}
-
-tobuf {
-  "prime { 29, 7, 16 }" 22 -1 "00";
-  "prime { 29, 7, 16 }" 22 0 "000116";
-  "prime { 29, 7, 16 }" 0 -1 "0000";
-  "prime { 29, 7, 16 }" 0 0 "000100";
-
-  "ec { secp112r1 }" inf 0 "0000";
-  "ec { secp112r1 }"
-    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
-    0 "000e09487239995a5ee76b55f9c2f098000ea89ce5af8724c0a23e0e0ff77500";
-  "ec { nist-p192 }"
-    "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"
-    0 "00010000188497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed";
-}
-
-frombuf {
-  "prime { 29, 7, 16 }" "00" -1 0;
-  "prime { 29, 7, 16 }" "000116" 3 22;
-  "prime { 29, 7, 16 }" "00000e" 2 0;
-  "prime { 29, 7, 16 }" "000100ff" 3 0;
-
-  "ec { secp112r1 }" "0000" 2 inf;
-  "ec { secp112r1 }"
-    "000e09487239995a5ee76b55f9c2f098000ea89ce5af8724c0a23e0e0ff77500f00d"
-    32 "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500";
-  "ec { secp112r1 }" "0001000001001ee7" -1 inf;
-  "ec { nist-p192 }"
-    "00010000188497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0eddead"
-    29, "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed";
-}
-
-toraw {
-  "prime { 29, 7, 16 }" 22 -1 "";
-  "prime { 29, 7, 16 }" 22 0 "16";
-  "prime { 29, 7, 16 }" 0 -1 "";
-  "prime { 29, 7, 16 }" 0 0 "00";
-  "prime { 4294967311, 364289, 18767 }" 4285559121 0 "00ff707151";
-  "prime { 4294967311, 364289, 18767 }" 4285559121 -1 "ff707151";
-
-  "ec { secp112r1 }" inf 0 "00";
-  "ec { secp112r1 }"
-    "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500"
-    0 "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff77500";
-  "ec { nist-p192 }"
-    "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed"
-    0 "040000000000000000000000000000000000000000000000008497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed";
-}
-
-fromraw {
-  "prime { 29, 7, 16 }" "" -1 0;
-  "prime { 29, 7, 16 }" "160bad" 1 22;
-  "prime { 29, 7, 16 }" "00" 1 0;
-  "prime { 4294967311, 364289, 18767 }" "00ff707151e7c0" 5 4285559121;
-  "prime { 4294967311, 364289, 18767 }" "ff707151" -1 0;
-
-  "ec { secp112r1 }" "" -1 inf;
-  "ec { secp112r1 }" "00" 1 inf;
-  "ec { secp112r1 }"
-    "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff775" -1 inf;
-  "ec { secp112r1 }"
-    "0409487239995a5ee76b55f9c2f098a89ce5af8724c0a23e0e0ff77500"
-    29 "0x09487239995a5ee76b55f9c2f098, 0xa89ce5af8724c0a23e0e0ff77500";
-  "ec { nist-p192 }"
-    "070000000000000000000000000000000000000000000000008497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed00deadbeef"
-    49 "0, 0x8497a9fa119ff34c9c24a156ed0d44a0c5f5d1f19fc9f0ed";
-}
diff --git a/tests/has160 b/tests/has160
deleted file mode 100644 (file)
index ba3db65..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-# 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;
-}
diff --git a/tests/idea b/tests/idea
deleted file mode 100644 (file)
index ce947d3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-# Test vectors for IDEA
-#
-# $Id: idea,v 1.2 2000/07/15 17:48:15 mdw Exp $
-
-# --- Thin on the ground, these are ---
-
-idea {
-  00010002000300040005000600070008 0000000100020003 11fbed2b01986de5;
-  00000000000000000000000000000000 0000000000000000 0001000100000000;
-  000027ed8f5c3e8baf16560d14c90b43 0000abbf94ff8b5f cbbb2e6c05ee8c89;
-  000027ed8f5c3e8baf16560d14c90b43 6889f5647ab23d59 61d5397046f99637;
-  000027ed8f5c3e8baf16560d14c90b43 6c2e3617da2bac35 b2229067630f7045;
-  000027ed8f5c3e8baf16560d14c90b43 819440ca2065d112 c88600093b348575;
-  000027ed8f5c3e8baf16560d14c90b43 848f836780938169 4821b99f61acebb7;
-  000027ed8f5c3e8baf16560d14c90b43 ac4856242b121589 85c6b232294c2f27;
-  000027ed8f5c3e8baf16560d14c90b43 cbe465f232f9d85c b67ac767c0c06a55;
-  000027ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1320f99bfe052804;
-  000027ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 ef4899b48de5907c;
-  729a27ed8f5c3e8baf16560d14c90b43 0000abbf94ff8b5f 65861be574e1eab6;
-  729a27ed8f5c3e8baf16560d14c90b43 6889f5647ab23d59 f963468b52f45d4d;
-  729a27ed8f5c3e8baf16560d14c90b43 6c2e3617da2bac35 1569e0627007b12e;
-  729a27ed8f5c3e8baf16560d14c90b43 819440ca2065d112 264a8bba66959075;
-  729a27ed8f5c3e8baf16560d14c90b43 848f836780938169 d7e0468226d0fc56;
-  729a27ed8f5c3e8baf16560d14c90b43 ac4856242b121589 95cd92f44bacb72d;
-  729a27ed8f5c3e8baf16560d14c90b43 cbe465f232f9d85c bce24dc8d0961c44;
-  729a27ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1d0cb2af1654820a;
-  729a27ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 29358cc6c83828ae;
-}
diff --git a/tests/lcrand b/tests/lcrand
deleted file mode 100644 (file)
index 8ffd7ed..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Test vectors for linear congruential generator
-#
-# $Id: lcrand,v 1.3 2000/07/15 10:03:13 mdw Exp $
-
-lcrand {
-  # --- Standard stuff ---
-
-  0            271828183;
-  271828183    996300340;
-  996300340    228306184;
-  228306184    1171467301;
-  1171467301   3265426054;
-  3265426054   2636049353;
-  2636049353   3799512036;
-  3799512036   2414373801;
-  2414373801   1059474234;
-  1059474234   2734911993;
-  2734911993   239668818;
-  239668818    1752802481;
-  1752802481   34386946;
-  34386946     1344553049;
-  1344553049   1121833700;
-  1121833700   636134543;
-
-  # --- Particular outputs ---
-
-  2282233179   4294967290;
-  2624567577   0;
-  2966901975   1;
-
-  # --- Fixed point ---
-
-  3223959250   3223959250;
-}
diff --git a/tests/md2 b/tests/md2
deleted file mode 100644 (file)
index 8930253..0000000
--- a/tests/md2
+++ /dev/null
@@ -1,79 +0,0 @@
-# Test vectors for MD2 hash function
-#
-# $Id: md2,v 1.1 2001/02/21 20:03:23 mdw Exp $
-
-# --- Basic hash function ---
-#
-# Test vectors from RFC1319.  The last was generated using OpenSSL.
-
-md2 {
-  ""                   8350e5a3e24c153df2275c9f80692773;
-  "a"                  32ec01ec4a6dac72c0ab96fb34c0b5d1;
-  "abc"                        da853b0d3f88d99b30283a69e6ded6bb;
-  "message digest"     ab4f496bfb2a530b219ff33031fe06b0;
-  "abcdefghijklmnopqrstuvwxyz"
-                       4e8ddff3650292ab5a4108c3aa47940b;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-                       da33def2a42df13975352846c30338cd;
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
-                       d5976f79d83d3a0dc9806c3c66f3efd8;
-
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-"                      9bc05c2f44930f59882bb885a75b4c95;
-}
-
-# --- HMAC mode ---
-#
-# These are just regression tests, generated internally.
-
-md2-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       b524be0196e491ed44823746cd8923af;
-
-  "what do ya want for nothing?"
-       4a656665
-       292f9d34f9e311846de86c495d7adfa2;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       ff09238e4bded84b5490bc42cfd5c265;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       ea3181bf1cc387f12ed0637105fb219d;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       7177f2b3e5583078ee122f94fe3c784a;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       615b1c392f5aaeeeab7e82572e6395d5;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       df0b12810892f0c7559802d5c0ce1157;
-}
diff --git a/tests/md4 b/tests/md4
deleted file mode 100644 (file)
index 1439c35..0000000
--- a/tests/md4
+++ /dev/null
@@ -1,59 +0,0 @@
-# Test vectors for MD4 hash function
-#
-# $Id: md4,v 1.2 2000/07/15 10:03:13 mdw Exp $
-
-# --- Basic hash function ---
-#
-# Test vectors from RFC1186 and some others I generated using the reference
-# implementation.
-
-md4 {
-  ""                   31d6cfe0d16ae931b73c59d7e0c089c0;
-  "a"                  bde52cb31de33e46245e05fbdbd6fb24;
-  "abc"                        a448017aaf21d8525fc10ae87aa6729d;
-  "message digest"     d9130a8164549fe818874806e1c7014b;
-  "abcdefghijklmnopqrstuvwxyz"
-                       d79e1c308aa5bbcdeea8ed63df412da9;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-                       043f8582f241db351ce627e153e7f0e4;
-}
-
-# --- HMAC mode ---
-#
-# No test vectors available.  The HMAC implementation has not been tested
-# against an external reference.  However, MD4 isn't strong enough to make
-# a realistic MAC anyway, and use of md4-mac is thoroughly deprecated.  The
-# HMAC code is autogenerated anyway, and ought to be reliable and correct.
-#
-# These test vectors are here to spot changes in behaviour rather than ensure
-# interoperability.
-
-md4-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       90a79458f58f437e21f169cdba283da6;
-
-  "what do ya want for nothing?"
-       4a656665
-       be192c588a8e914d8a59b474a828128f;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       75e5fb6e71ca6dcdd9fca269a9a3cd9c;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       fb14cddf9efe11ad24033fc70f37bb9e;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       6306262f9ba0e83f9ce3f15aafc23be8;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       545b8f2577657042df628fbb98430d5f;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       0192f3442ad5d1ea5268306ab0d4962e;
-}
diff --git a/tests/md5 b/tests/md5
deleted file mode 100644 (file)
index d34918d..0000000
--- a/tests/md5
+++ /dev/null
@@ -1,80 +0,0 @@
-# Test vectors for MD5 hash function
-#
-# $Id: md5,v 1.3 2000/07/15 10:03:13 mdw Exp $
-
-# --- Basic hash function ---
-#
-# Test vectors from RFC1321 and some others I generated using the reference
-# implementation.
-
-md5 {
-  ""                   d41d8cd98f00b204e9800998ecf8427e;
-  "a"                  0cc175b9c0f1b6a831c399e269772661;
-  "abc"                        900150983cd24fb0d6963f7d28e17f72;
-  "message digest"     f96b697d7cb7938d525a2f31aaf161d0;
-  "abcdefghijklmnopqrstuvwxyz"
-                       c3fcd3d76192e4007dfb496cca67e13b;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-                       d174ab98d277d9f5a5611c2c9f419d9f;
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
-                       57edf4a22be3c955ac49da2e2107b67a;
-
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-"                      2b65a7ba4acd105ef2cb9adebd9f0bfa;
-}
-
-# --- HMAC mode ---
-#
-# Test vectors from RFC2104 and RFC2202.
-
-md5-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       9294727a3638bb1c13f48ef8158bfc9d;
-
-  "what do ya want for nothing?"
-       4a656665
-       750c783e6ab0b503eaa86e310a5db738;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       56be34521d144c88dbb8c733f0e8b3f6;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       697eaf0aca3a3aea3a75164746ffaa79;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       56461ef2342edc00f9bab995690efd4c;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       6f630fad67cda0ee1fb1f562db3aa53e;
-}
diff --git a/tests/mp b/tests/mp
deleted file mode 100644 (file)
index 0fbaf06..0000000
--- a/tests/mp
+++ /dev/null
@@ -1,328 +0,0 @@
-# Test vectors for MP functions
-#
-# $Id$
-
-add {
-  5 4 9; 5 -4 1; -5 4 -1; -5 -4 -9;
-  0xffffffff 1 0x100000000;
-}
-
-sub {
-  5 4 1; 5 -4 9; -5 4 -9; -5 -4 -1;
-  4 5 -1; 4 -5 9; -4 5 -9; -4 -5 1;
-}
-
-mul {
-  5 4 20; -5 4 -20; 5 -4 -20; -5 -4 20;
-  0x10000 0x10000 0x100000000;
-}
-
-div {
-  9 4 2 1; -9 4 -3 3; 9 -4 -3 -3; -9 -4 2 -1;
-  -3 6277101735386680763835789423207666416083908700390324961279
-    -1 6277101735386680763835789423207666416083908700390324961276;
-  3131675836296406071791252329528905062261497366991742517193
-    1110875761630725856340142297645383444629395595869672555585
-    2 909924313034954359110967734238138173002706175252397406023;
-  3131675836296406071791252329528905062261497366991742517193
-    53
-    59088223326347284373419855274130284193613157867768726739 26;
-  1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919
-  776259046150354467565459065629240877815667024717257156601175597451483119974551053629334726938295821221455003840144432114575401859459023171316363806515641491872190410445098144254585345658296587683734775881559921685818610503605288959
-  2 1;
-}
-
-exp {
-  4 0 1;
-  4 1 4;
-  7 2 49;
-  3 564 124849745640593184256214502788000232711984346194239284918599169775251467106591187580476305077269760425019686159071753053924227569816588462643229463821875763427430576080998505780547826368760514503807579784278708008217584939464444237989070811887584423210788916656247499281;
-}
-
-bin2c {
-  and 5 3 1;
-  or 5 3 7;
-  xor 5 3 6;
-  1111 0 0 -1;
-  or 45 -7 -3;
-  xor 0x343cd5 -0x6a49c -0x32984f;
-}
-
-lsr2c {
-  -1 5 -1;
-  1 5 0;
-  -6 2 -2;
-  5 0 5;
-  -4 0 -4;
-  7 2 1;
- -7 2 -2;
-  -7 20 -1;
-}
-
-lsl2c {
-  -1 5 -32;
-  5 0 5;
-  -4 0 -4;
-  7 2 28;
-  -7 2 -28;
-  0xc0000000 1 0x180000000;
-  -0xc0000000 1 -0x180000000;
-  -1 32 -0x100000000;
-}
-
-setbit {
-  0 40 0x10000000000;
-  0x87348 40 0x10000087348;
-  5 1 7;
-  7 1 7;
-  -3 1 -1;
-}
-
-clrbit {
-  0x10000000000 40 0;
-  0x87348 40 0x87348;
-  5 1 5;
-  7 1 5;
-  -1 1 -3;
-}
-
-neg {
-  0 0;
-  15 -15;
-  -15 15;
-}
-
-odd {
-  1 0 1;
-  2 1 1;
-  4 2 1;
-  12 2 3;
-  0x10000000000000 52 1;
-  0x10000000400000 22 0x40000001;
-}
-
-sqrt {
-  0 0;
-  1 1;
-  4 2;
-  9 3;
- 16 4;
- 99 9;
-100 10;
-101 10;
-120 10;
-121 11;
-
-10106623487257186586 3179091613;
-14565040310136678240 3816417208;
-}
-
-gcd {
-  # --- Simple tests ---
-
-  16 12 4 -11 15;
-  12 16 4 -1 1;
-  693 609 21 -7 8;
-  4398082908043 90980984098081324 1 -32483863573352089 1570292150447;
-
-  # --- Negative argument tests ---
-
-  16 -12 4 -11 -15;
-  -16 12 4 11 15;
-  -12 -16 4 1 -1;
-  -12 16 4 1 1;
-  -693 609 21 7 8;
-  693 -609 21 -7 -8;
-
-  # --- Zero argument tests ---
-
-  15 0 15 1 0;
-  0 15 15 0 1;
-  -5 0 5 -1 0;
-  0 -5 5 0 -1;
-  0 0 0 0 0;
-
-  # --- Random number tests ---
-
-  829561629303257626084392170900075 32498098450983560651904114638965
-    5 -29340810037249902802634060204608 748967211613630574419802053172497;
-
-  5509672937670943767152343650729669537671508
-  398326674296699796695672966992514673531
-  17
-  -4158709420138833210339208344965073815
-  57523460582278135926717203882531035926727;
-
-  324098408098290809832490802984098208098324
-  23430980840982340982098409823089098443
-  1
-  -4158709420138833210339208344965073815
-  57523460582278135926717203882531035926727;
-
-  # --- RSA test ---
-  #
-  # The first number is (p - 1)(q - 1) from `mpmont'.  The second is a
-  # random number (it's actually prime, but that doesn't matter) which I
-  # can use as an RSA encryption exponent.  The last is the partner
-  # decryption exponent, produced using the extended GCD algorithm.
-
-  665251164384574309450646977867043764321191240895546832784045453360
-  5945908509680983480596809586040589085680968709809890671
-  1
-  -4601007896041464028712478963832994007038251361995647370
-  514778499400157641662814932021958856708417966520837469125919104431;
-
-  # --- Misery ---
-  #
-  # Some bugs discovered during RSA testing.
-
-  100000423751500546004561515884626739136961367515520675987004088469753859696407139054406989735113827981148062449057870561788973142250811838720214530386151198455545176591384352343648452329042764530196327665219224050630680827543991306749402959935685172017409062967157813233001567797128414009962262840951763040181
-  44895767034162990997987303986882660674722497505237491649296190658571471979065889234144353811843706629535512848235473808330181517421970135930320187227697512315919757806204341545022714991717913006031724818461724742069401359454784533576615919680949125073761586043027941204059690093447093117249681641020785611986
-  1
-  -44146175664861261172356293340716833133750232401287328189797639296698679436925232375473973898100363205157703913050824405116878299310008848005045714833814493992539429428295945643439440068026313232881493081836812480325977761600303456915493177366981470223898994906470419007730670657168179659899713837827764669213
-  98330790743257232930640417364963717704786040860302439189781385170246412183980882564239377268174203679366339563908361674571088519452885615348465535190260914996055274486493192655677181637142116473172979503236297658204730543049175626205461452256333155750566288282331419748434569978343545573401114593095927172889;
-
-  44895767034162990997987303986882660674722497505237491649296190658571471979065889234144353811843706629535512848235473808330181517421970135930320187227697512315919757806204341545022714991717913006031724818461724742069401359454784533576615919680949125073761586043027941204059690093447093117249681641020785611986
-  100000423751500546004561515884626739136961367515520675987004088469753859696407139054406989735113827981148062449057870561788973142250811838720214530386151198455545176591384352343648452329042764530196327665219224050630680827543991306749402959935685172017409062967157813233001567797128414009962262840951763040181
-  1
-  -1669633008243313073921098519663021432175326655218236797222703299507447512426256490167612466939624301781722885149508887217884622797926223371748995195890283459489902104891159687971270691900648057023348161982926392425950284494815680543941507679352016266842774684826393484566997818784868436561148247855835867292
-  749591369301729825631010646165827540972265103950163459498551361872792542140656858670379913743343424377808935184649403213303218111961287925274472393883018323380328377908395901583274923691599773150231736624912261743423597854481076661122742313967654849862591136557522196329019436278913457349967803193020942773;
-
-  # --- Some other bugs ---
-
-  19504439280113284806725522136967618725661733412699408177537810327183285842670
-  1
-  1
-  0
-  1;
-}
-
-modinv {
-  5 9 2;
-  15 64 47;
-  564566436 546457643 408896426;
-}
-
-jacobi {
-  4 5 1;
-  6 7 -1;
-  15 27 0;
-  2132498039840981 98729378979237498798347932749951 1;
-  98729378979237498798347932749951 2132498039840981 1;
-
-  # --- Kronecker extension ---
-
-  0 0 0;
-  1 0 1;
-  -1 0 -1;
-  2 0 0;
-
-  2132498039840981 197458757958474997596695865499902 -1;
-  98729378979237498798347932749951 4264996079681962 1;
-  98729378979237498798347932749951 -4264996079681962 1;
-  -98729378979237498798347932749951 -4264996079681962 -1;
-
-  # --- Random tests made by PARI/gp ---
-
-  22 -19 -1;
-  48 -37 1;
-  -13 29 1;
-  -19 2 -1;
-  -43 31 1;
-  -12 -7 -1;
-  -14 -34 0;
-  -30 -29 -1;
-  25 26 1;
-  -27 20 -1;
-  -5 -45 0;
-  9 -42 0;
-  -51 -3 0;
-  -39 35 -1;
-  37 30 1;
-  13 18 -1;
-  -28 6 0;
-  -49 -15 1;
-  -1 1 1;
-  -9 13 1;
-  -47 44 -1;
-  -14 -30 0;
-  37 -36 1;
-  45 9 0;
-  -29 30 -1;
-  49 49 0;
-  -27 -10 -1;
-  -35 -25 0;
-  17 14 -1;
-  -35 29 1;
-  -1 33 1;
-  38 -11 1;
-  3 -24 0;
-  5 -25 0;
-  -31 22 -1;
-  40 30 0;
-  -43 26 -1;
-  -22 10 0;
-  11 -29 -1;
-  40 -18 0;
-}
-
-modsqrt {
-  1 3 1;
-  4 5 2;
-  9775592058107450692 13391974640168007623 3264570455655810730;
-  8155671698868891620 10189552848261357803 2073812183305821596;
-  3248339460720824413 8976233780911635437 1220523478429582717;
-  3447751741648956439 10155704720805654949 2812971608818169892;
-  1453601744816463433 3095659104519735473 1260511572497628526;
-  3366261317119810224 3756232416311497601 610261287187759737;
-  3869491397135339653 5762828162167967567 2788500156455085147;
-  660864223630638896 1729533840094059799 671335997718840076;
-}
-
-modexp {
-
-  # --- Montgomery exponentiation ---
-
-  435365332435654643667 8745435676786567758678547
-    4325987397987458979875737589783
-    2439674515119108242643169132064;
-  0xfffffffdfffffffffffffffffffffffe 0 0xfffffffdffffffffffffffffffffffff 1;
-  1804289383 -8939035539979879765 8939489893434234331 6139425926295484741;
-
-  # --- Barrett exponentiation ---
-
-  435365332435654643667 8745435676786567758678547
-    4325987397987458979875737589782
-    2425191520487853884024972777945;
-}
-
-factorial {
-  0 1;
-  1 1;
-  2 2;
-  3 6;
-  4 24;
-  5 120;
-  30 265252859812191058636308480000000;
-  100 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000;
-  500
-   1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
-}
-
-fibonacci {
-  -20 -6765;
-  -19 4181;
-  -10 -55;
-  -9 34;
-  -2 -1;
-  -1 1;
-  0 0;
-  1 1;
-  2 1;
-  5 5;
-  10 55;
-  19 4181;
-  20 6765;
-  100 354224848179261915075;
-  1000 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875;
-}
diff --git a/tests/mpbarrett b/tests/mpbarrett
deleted file mode 100644 (file)
index 801b091..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-# Test vectors for Barrett modular reduction
-#
-# $Id$
-
-mpbarrett-reduce {
-  17 11 6;
-  -17 11 5;
-
-  0x8ab316d0d1a2e88535cf77c1172881ead70d592c59e9c5fbc16e4b0c4dc49481
-  0x18ca3bf7ee3c6d7bab3f144b015ccc6c25472843d346b461
-  0x02c1815029b766b96ad4507dc1af8151307961c6d161d065;
-
-  0x8117d1663ee63341eb8faeff304549f0f8b32d587acc2fd5597ea6a31625881d
-  0xdc85df77dfb61876805623bcbed325b99d00c2cd65c252c879
-  0x395da02e8a6c66476467c4e04f328d8208cc411e3d1e96e14c;
-
-  0x63791966f2ad44a6df11bcc87c6b7c2400c74e69f7e3ca02fcac12b3bf56238b
-  0xa49e473b8f7539d89cdb002d73182558773eec10db93cc6049d8c5533e
-  0x65caf6833baa118b53c7bdc44a831605ca382b5993beead59f3971d13f;
-
-  0x9ca438db3e0f79305987292e8ec6174e6c313f7904ebb35a349a700e3ae63a37
-  0xb24c93d499c7073b8f7aac718c1f12da1a8fc8bccdd47b49
-  0x46393cb15e38cbbc8a85698151a113f28081b4c8f6ed232e;
-
-  0x8214fd17858a4a913015412b5331eb9654faeb5156a674b1e5f6550a68957146
-  0xc4f0ebaad6c0ee0111c57667ea8e0a254f3068f212949e20ededa89a7da6
-  0x3fde916ba21d19414d4316041420ca59d8b01aa2acf3f3ef106245c1915c;
-
-  0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa
-  0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773
-  0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6;
-
-  0xae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c
-  0xc33c890f030644d88cc65f8ccf99c625c9b9fa21d4eb153e52ef89df54130855
-  0xae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c;
-
-  0x65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc
-  0xd8a1d326fee87d55f39f15b5b2cfe71f5146083928
-  0x859c41164983547c03134b99530e25a0f874315964;
-
-  -0x65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc
-  0xd8a1d326fee87d55f39f15b5b2cfe71f5146083928
-  0x53059210b56528d9f08bca1c5fc1c17e58d1d6dfc4;
-}
-
-mpbarrett-exp {
-  4325987397987458979875737589783
-  435365332435654643667
-  8745435676786567758678547
-  2439674515119108242643169132064;
-
-  8939489893434234331 1804289383 454353454354565 6139425926295484741;
-  8939489893434234331 1804289383 8939489893434234330 1;
-
-  # --- Negative exponents ---
-
-  0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1;
-  8939489893434234331 1804289383 -8939035539979879765 6139425926295484741;
-
-  # --- DSA public key derivation ---
-
-  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
-  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
-  0x1234
-  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47;
-
-  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
-  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
-  0x23a252f60bae4907a8ed5b6203e2b1da32848cd9
-  0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074;
-
-  # --- Quick RSA test ---
-
-  905609324890967090294090970600361            # This is p
-  3
-  905609324890967090294090970600360            # This is (p - 1)
-  1;                                           # Fermat test: p is prime
-
-  734589569806680985408670989082927            # This is q
-  5
-  734589569806680985408670989082926            # And this is (q - 1)
-  1;                                           # Fermat again: q is prime
-
-  # --- Encrypt a message ---
-  #
-  # The public and private exponents are from the GCD test.  The message
-  # is just obvious.  The modulus is the product of the two primes above.
-
-  665251164384574309450646977867045404520085938543622535546005136647
-  123456789012345678901234567890123456789012345678901234567890
-  5945908509680983480596809586040589085680968709809890671
-  25906467774034212974484417859588980567136610347807401817990462701;
-
-  # --- And decrypt it again ---
-
-  665251164384574309450646977867045404520085938543622535546005136647
-  25906467774034212974484417859588980567136610347807401817990462701
-  514778499400157641662814932021958856708417966520837469125919104431
-  123456789012345678901234567890123456789012345678901234567890;
-
-  # --- Strange bug ---
-  #
-  # Strange memory corruption bug causing mpbarrett_reduce to hang.
-  # Seems to have vanished on a clean rebuild so maybe this was just build
-  # fluff or something.  Leave it here to pick up regression.
-
-  30916300184138066757562815127455898754391418637651479989257882011612153138316483396290143656363307389355307404813205623380378799585065876990874918745873480056891738964426752
-  2 44329
-  10975270953088118598390528358454369816072092233138947812823085741431681835772475760228604878294514156761050649439713085882651077696501584961485141097470430535290622475239424;
-}
-
-# --- Simultaneous exponentiation ---
-
-mexp-1 {
-  4325987397987458979875737589783
-  435365332435654643667
-  8745435676786567758678547
-  2439674515119108242643169132064;
-}
-
-mexp-2 {
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
-  0xbf655bd046f0b35ec791b004804afcbb8ef7d69d
-  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
-  0x821a926312e97adeabcc8d082b5278978a2df4b0
-  0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e;
-
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
-  0xbf655bd046f0b35ec791b004804afcbb8ef7d69d
-  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
-  -0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adabb090e849367fc31d4c6a97bac0b4be56a79a0de0
-  0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e;
-}
diff --git a/tests/mpcrt b/tests/mpcrt
deleted file mode 100644 (file)
index 65a3c3d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# Test vectors for Chinese Remainder Theorem solution (Gauss's algorithm)
-#
-# $Id: mpcrt,v 1.2 2000/07/09 21:33:54 mdw Exp $
-
-crt-1 {
-  1 5 1;
-  3498243289823 4534543545463431 3498243289823;
-}
-
-crt-2 {
-  3 7 7 13 59;
-  39845 435435221 43534545 32423423467 13736097689153284731;
-
-  2200541929485233317342398 498459898455435345676576793
-  13046769915260439091721075347560767438958354488807168684311588308214063361125238823412234206191582332588 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493526197
- 14756532044160797319048143986538019326281096778844833416304858521742332925502855547148214406728673769162624068049034315018936294558;
-}
-
-crt-4 {
-  2 5 1 7 3 11 8 13 2192;
-}
diff --git a/tests/mpint b/tests/mpint
deleted file mode 100644 (file)
index 49157ba..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-# Test vectors for conversion between MP ints and C ints
-#
-# $Id: mpint,v 1.4 2002/01/13 19:51:34 mdw Exp $
-
-# The tests look messy because I'm fighting with atoi here as well as the
-# integer conversion routines I'm trying to test.
-
-fromuint {
-  0 0;
-  1 1;
-  -5 0xfffffffb;
-  0x7ffff 0x7ffff;
-  0x80000 0x80000;
-  0xfffff 0xfffff;
-  0x7fffffff 0x7fffffff;
-  0x80000000 0x80000000;               # Bastard torture test
-  0xffffffff 0xffffffff;
-}
-
-fromint {
-  0 0;
-  1 1;
-  -5 -5;
-  0x7ffff 0x7ffff;
-  0x80000 0x80000;
-  0xfffff 0xfffff;
-  0x7fffffff 0x7fffffff;
-  -0x80000000 -0x80000000;             # Bastard torture test
-}
-
-touint {
-  0 0;
-  1 1;
-  -5 -5;
-  0x7ffff 0x7ffff;
-  0x80000 0x80000;
-  0xfffff 0xfffff;
-  0x7fffffff 0x7fffffff;
-  0x80000000 -0x80000000;              # Bastard torture test
-  0xffffffff 0xffffffff;
-}
-
-toint {
-  0 0;
-  1 1;
-  -5 -5;
-  0x7ffff 0x7ffff;
-  0x80000 0x80000;
-  0xfffff 0xfffff;
-  0x7fffffff 0x7fffffff;
-  -0x80000000 -0x80000000;             # Bastard torture test
-}
diff --git a/tests/mpmont b/tests/mpmont
deleted file mode 100644 (file)
index a541508..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-# Test vectors for Montgomery reduction
-#
-# $Id$
-
-create {
-  340809809850981098423498794792349    # m
-  266454859                            # -m^{-1} mod b
-  130655606683780235388773757767708    # R mod m
-  237786678640282040194246459306177;   # R^2 mod m
-}
-
-mul {
-  43289823545
-  234324324
-  6456542564
-  10807149256;
-
-  51518627314818829164222247085233898246715229794943812733936714788310185005015428803253311691709787911812368198649776769324928993075889524373913555618270874746833913595051625422038974326537979654635530320271853851973343513053953211672797425464186157719021174955241645388345195723368057041032310152242301620397
-  7041548659011846562361842096561083537784928869240554198760844555642215260669458833049231069318370838770180094409088437631986867239713464317243824963669990014087444248250948204574690463940534304651099653802302150197753463246181762684347288736386534346725039618007392334267637262008343417972878515511486456037
-  21451817224897484023627307128311082613304580637202546848860538836010530320943159719981586919811151828606838777812233053319458755053306547823820900602281867134174742586071226220962576712633552196944784360512851517812225731562588375896089193406088239903885470354101095713609394462435076126493339021945199401247
-  48192532305912989641372170084506981675917951543147719789775743631071830656350879578731578070582102149232280305157616093002880139716311910835926678896882798493523792373475521651115163420137602661060123597773253524671874189844988793471524978853764238038494563159505836018994860909028653670132922744758133798212;
-}
-
-exp {
-  4325987397987458979875737589783
-  435365332435654643667
-  8745435676786567758678547
-  2439674515119108242643169132064;
-
-  # --- Bizarre bug ---
-  #
-  # This was caused by omission of the test-and-subtract step in the
-  # Montgomery reduction.
-
-  8939489893434234331 1804289383 454353454354565 6139425926295484741;
-  8939489893434234331 1804289383 8939489893434234330 1;
-
-  # --- Negative and zero exponents ---
-
-  0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1;
-  8939489893434234331 1804289383 -8939035539979879765 6139425926295484741;
-
-  # --- DSA public key derivation ---
-
-  0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5
-  0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
-  0x1234
-  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47;
-
-  0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7
-  0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
-  0x23a252f60bae4907a8ed5b6203e2b1da32848cd9
-  0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074;
-
-  # --- Quick RSA test ---
-
-  905609324890967090294090970600361            # This is p
-  3
-  905609324890967090294090970600360            # This is (p - 1)
-  1;                                           # Fermat test: p is prime
-
-  734589569806680985408670989082927            # This is q
-  5
-  734589569806680985408670989082926            # And this is (q - 1)
-  1;                                           # Fermat again: q is prime
-
-  # --- Encrypt a message ---
-  #
-  # The public and private exponents are from the GCD test.  The message
-  # is just obvious.  The modulus is the product of the two primes above.
-
-  665251164384574309450646977867045404520085938543622535546005136647
-  123456789012345678901234567890123456789012345678901234567890
-  5945908509680983480596809586040589085680968709809890671
-  25906467774034212974484417859588980567136610347807401817990462701;
-
-  # --- And decrypt it again ---
-
-  665251164384574309450646977867045404520085938543622535546005136647
-  25906467774034212974484417859588980567136610347807401817990462701
-  514778499400157641662814932021958856708417966520837469125919104431
-  123456789012345678901234567890123456789012345678901234567890;
-
-  # --- Regression ---
-
-  3986624077014487421577005607434178981611827907415414229383186257799185035259267946499319317546248903815958429965343062841026732183070884484415037389112766124480881891335541864933360040451772640848433986354946570483859801429553601029855169093153120649968457991955067742589996787220443833463413655161718521778024152687493646856649224308444934694934177848997119462792993163729623894124424825605063456003809024630116233635811919734143467917391222413748618664640084816819791040047135721631646389562380726980090637225607902904093720467390446340147754975063914238763877962986901317873962501987398883284691263121949707967483
-  2169501609694605731113683435915932024263931111070470928071742781553833481227229665038394569450673541955381439893533586899516369125587996614390351130855433932967123352056637148142399218614659226596196082977912512097782590337133839376057748669786776861900003976657975002808400242688631641605350346310303557783077961976578644612942618488786721156576047036803063809499458142391930097492829437793780428298460587910313123127299017105180518995858168981798364124607742910479678852164938149352363613709839015911625193499208078080300810729238501127706236236987807659841302058153641198634312186169690290317377895433013774581020
-  51190650099377934681679689372059155651634030541122059023228371179527051284414
-  2182336244564627050476203952083643687109210844491929333865487949231032236266424033053219865356293652087346833773990958617081657598928894294027838097457060132084513275728637155311686562443969707442331856969523833049082440569661820589637161378175422424940183890787723213162895088451684485064228413121825045190532424942855250521728705814032313019282814300698512615465322506857392325469773301168485302267577566759375501214494771698910873834970265937979350795050000891405548412798945017578510891723221844676960980502437259841806090144299798005080365645221451715661064400809603224286845878809241930399832108000526121054958;
-}
-
-# --- Simultaneous exponentiation ---
-
-mexp-1 {
-  4325987397987458979875737589783
-  435365332435654643667
-  8745435676786567758678547
-  2439674515119108242643169132064;
-}
-
-mexp-2 {
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
-  0xbf655bd046f0b35ec791b004804afcbb8ef7d69d
-  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
-  0x821a926312e97adeabcc8d082b5278978a2df4b0
-  0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e;
-
-  0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291
-  0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
-  0xbf655bd046f0b35ec791b004804afcbb8ef7d69d
-  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
-  -0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adabb090e849367fc31d4c6a97bac0b4be56a79a0de0
-  0x2fc6cb9ac3be0eac3daf02eefb96fca3846708a28dd05730165fe50942f7f07edfef8e52fcb9369e3814aa24607e80475d0e61ad461d6b16b6cec5baae58946e;
-}
diff --git a/tests/mpreduce b/tests/mpreduce
deleted file mode 100644 (file)
index 16cd81f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-# $Id$
-#
-# Tests for efficient reduction
-
-reduce {
-  0xc000 0x16cb3 0xacb3;
-  0x8000 0x345545 0x5545;
-
-  0xfffef 0x100000 0x11;
-
-  0x1ffffffe 0x26fc6567 0x6fc6569;
-  0x3ffffffe 0x45445dc0 0x5445dc2;
-  0x7ffffffe 0xd4827a70 0x54827a72;
-
-  0x72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773
-  0x367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa
-  0x08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6;
-
-  0xfffffffdffffffffffffffffffffffff
-  0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b
-  0xa019c198b9d9d9fb4440f7bc415ff5e4;
-}
-
-modexp {
-  0xfffffffdffffffffffffffffffffffff 0xfffffffdfffffffffffffffffffffffe 0 1;
-  0xfffffffdffffffffffffffffffffffff 2
-    0xfffffffdfffffffffffffffffffffffe 1;
-  0xfffffffdffffffffffffffffffffffff 2
-    0xfffffffdfffffffffffffffffffffffd
-    0x7fffffff000000000000000000000000;
-  8939489893434234331 1804289383
-    -8939035539979879765 6139425926295484741;
-}
diff --git a/tests/mptext b/tests/mptext
deleted file mode 100644 (file)
index ed9fb6a..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-# Test vectors for MP textual I/O
-#
-# $Id: mptext,v 1.12 2002/10/19 11:59:04 mdw Exp $
-
-mptext-ascii {
-  # --- Perfectly valid things ---
-
-  10 0                                 10 0 "";
-  0 0                                  10 0 "";
-  10 52                                        10 52 "";
-  10 654365464655464577673765769678    10 654365464655464577673765769678 "";
-  10 654365464655464577673765769678    16 8425e6d06f272b9a2d73ed1ce "";
-  10 596569802840985608098409867       8 366570443501403714657464766613 "";
-  16 8425E6D06F272B9A2D73ED1CE         10 654365464655464577673765769678 "";
-  0 654365464655464577673765769678     16 8425e6d06f272b9a2d73ed1ce "";
-  0 16_8425E6D06F272B9A2D73ED1CE       10 654365464655464577673765769678 "";
-  0 -0x8425E6D06F272B9A2D73ED1CE       10 -654365464655464577673765769678 "";
-  0 -8_366570443501403714657464766613  10 -596569802840985608098409867 "";
-  8 -366570443501403714657464766613    10 -596569802840985608098409867 "";
-  0 0366570443501403714657464766613    10 596569802840985608098409867 "";
-
-  # --- Bogus things ---
-
-  10 "" 0 0 "";                        # Empty string fails
-  10 foo 0 0 "foo";            # Non-numeric character
-  10 134f 10 134 "f";          # Stop parsing when reaching `f'
-  4 12345 10 27 "45";          # Stop parsing when reaching `4'
-  0 63_ 10 63 "_";             # 37 is an invalid base, so stop at `_'
-  0 36_ 0 0 "";                        # 36 is a valid base, so restart and fail
-
-  # --- Big bases ---
-
-  62 0 10 0 "";
-  10 0 62 0 "";
-  36 A 10 10 "";
-  36 Z 10 35 "";
-  37 A 10 36 "";
-  10 36 37 A "";
-  62 Z 10 61 "";
-
-  0 36_a 10 10 "";
-  0 36_A 10 10 "";
-  0 37_A 10 36 "";
-
-  0 0x10 10 16 "";
-  0 0o10 10 8 "";
-  0 0b10 10 2 "";
-  0 010 10 8 "";
-
-  # --- Word-boundary tests for binary-radix translation ---
-
-  0 0                                  16 0 "";
-  8 1234567012                         8 1234567012 "";
-  8 12345670123                                8 12345670123 "";
-  8 123456701234                       8 123456701234 "";
-
-  16 1234567                           16 1234567 "";
-  16 12345678                          16 12345678 "";
-  16 123456789                         16 123456789 "";
-
-  10 -4009356060                       16 -eef9eb1c "";
-
-  # --- Cussidness ---
-
-  0 -0                                 10 0 "";
-
-  # --- Bugs ---
-
-  16 84d192cd06ae59691897fa409da6198d5269325d
-  16 84d192cd06ae59691897fa409da6198d5269325d "";
-
-  16 -9802d5c5d5a73f9d4e694a8920f95231b4017f3ec6a4654ace3fa3d85879e5964dade0e051d57f13c275dab1df3da5331f39271efb2792d1dad4460fd5eb5c21fbf355456f523e5631e623074ff9b3e85cf5e0a9336c8d8b8621b24c4e625800ee0152d12c8e22658a66ade38cb4453ab6e4958114717355186649a6cc20d9f5ae2207f99814965035072a9f2121c8f9dd22ab134181378906291aae97287b62a2f592bbceb4198c9cd78e1968bf1e16865c3c6ce9c777232f186b5da240a24523a07faca9de44eba510c91917e099372e67a6a66e93fe7aaefcb9c5485e1a889eae721ab6407586880a95575a968b43bdf50323627aa0fcddfa4e198b0008
-  10 -74959454570640520505374182178324326240748657042677990093617716411759477136824854815262670168473667077524864904515489090301434501507378472350618141578200289566815110468728966378289347050752371322168328511598641143081017162500179880923097593329564317427467179672704707842937085621549781627579801356509572397210965270406925309382945647493757499822518272539171346319468210919037390479279679328187057939609889863122790083219768061816093131875491575840052493376341193028052061557296969558099473333023971577236615940525630787016398581105441977909848659239970133974969366933817929047771871736452423855320657946133173829640 "";
-
-  10 687036505685680036980563991304827689190226068191165515873309582371531653761560838357887565473014960851061079052387145199258972778940173525017542879674305252823453991900595437468144352005006881129612951699750949026636206282574720840178116341517038998609517724307448384647380133273761360084019113505091720961437658149042479826982973196933684563380877276612883608481996579884762706391098995123384485837872544276099219443948234067623442105312332114374763392077663374681230289067615025968182722516808457505932863951619224171887832194148545132638772027329666389477813640620737624951105503846166715576529533580414958055708947608220960395455545922617914622611716584821091744228076205865701038484061060900340103461251087987631583104425599437283952841086221737575051158322973751353914369450945591184550003693808660890173148206999627057352641910478408389852121815588924208719373851205997267929487223022997903565246821511833717944887785333763131071163649350968541111796906733695518487580626938892775883629672280655177072837819344983336811201072380418330154409415723975489649421805372088286721361996667976678161505679350285875598457893785891475462099191282531966080162136450154198672623485698300307676277037616099696441730508788295411634665370788798384809584417102543248560317224205079917990766513568040641690632751952309869792602319263342525778046078743231821682847703178976601855555261436480615639995150308874740741630953255447186244703692652027199198662385455033073594432232250325046519267763604243367272471024553800469955272676941568451192546782745963075159357666087761637705388608592656535848292947073782242206595438203903079185128849386496430347274188109070907185471363018498891836986716946253163675821471661778024303689714601286352436391739170368727508436484115845640636653283093361670039386061546795520151041150800979484160765783927564359393959237330742523328888527872599693558141880251962681735003114604660394550415472363991770499647732372855076408144546777820449665557724138072899691283182780416000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-  10 687036505685680036980563991304827689190226068191165515873309582371531653761560838357887565473014960851061079052387145199258972778940173525017542879674305252823453991900595437468144352005006881129612951699750949026636206282574720840178116341517038998609517724307448384647380133273761360084019113505091720961437658149042479826982973196933684563380877276612883608481996579884762706391098995123384485837872544276099219443948234067623442105312332114374763392077663374681230289067615025968182722516808457505932863951619224171887832194148545132638772027329666389477813640620737624951105503846166715576529533580414958055708947608220960395455545922617914622611716584821091744228076205865701038484061060900340103461251087987631583104425599437283952841086221737575051158322973751353914369450945591184550003693808660890173148206999627057352641910478408389852121815588924208719373851205997267929487223022997903565246821511833717944887785333763131071163649350968541111796906733695518487580626938892775883629672280655177072837819344983336811201072380418330154409415723975489649421805372088286721361996667976678161505679350285875598457893785891475462099191282531966080162136450154198672623485698300307676277037616099696441730508788295411634665370788798384809584417102543248560317224205079917990766513568040641690632751952309869792602319263342525778046078743231821682847703178976601855555261436480615639995150308874740741630953255447186244703692652027199198662385455033073594432232250325046519267763604243367272471024553800469955272676941568451192546782745963075159357666087761637705388608592656535848292947073782242206595438203903079185128849386496430347274188109070907185471363018498891836986716946253163675821471661778024303689714601286352436391739170368727508436484115845640636653283093361670039386061546795520151041150800979484160765783927564359393959237330742523328888527872599693558141880251962681735003114604660394550415472363991770499647732372855076408144546777820449665557724138072899691283182780416000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 "";
-}
-
-mptext-bin-in {
-  -10 010203040506070809 10 123456789 "";
-  -100 01172d4359 10 123456789 "";
-  -90 09124709 10 6713199 "";
-}
-
-mptext-bin-out {
-  10 123456789 -10 010203040506070809 "";
-  10 123456789 -100 01172d4359 "";
-  10 6713199 -90 09124709 "";
-  10 0 -10 00 "";
-}
diff --git a/tests/mpx b/tests/mpx
deleted file mode 100644 (file)
index e30e91a..0000000
--- a/tests/mpx
+++ /dev/null
@@ -1,890 +0,0 @@
-# Test vectors for low-level MP functions
-#
-# $Id: mpx,v 1.12 2004/04/01 12:50:41 mdw Exp $
-
-# --- Load-store tests ---
-#
-# The test loads each number, as both big- and little-endian, and compares it
-# against the original octet version using a different method.  It then
-# stores the value to another octet array and compares.  This is done for
-# various sizes of MP, to ensure that truncation works correctly.
-
-load-store {
-  "";
-  00;
-  0123;
-  0123456789abcdef0123456789abcdef0123456789ab;
-  00000123456789abcdef01234789abcdef0123456789ab;
-  0123456789abcdef23456789abcdef0123456789ab0000;
-  80f8c5606bff51bac932859a4fb6331c4023b32b65cd95f4edc1d1c919fcc078;
-  522f8b1de257972a25ec49c9ff56340e2684e847ef2fa4d5714d7c8d454e90f6;
-}
-
-# --- Two's complement tests ---
-
-2cb {
-  "" "";
-  00 00;
-  000000 00000000000000000000;
-  01 ff;
-  0123456789abcdef fedcba9876543211;
-  0123456789abcdef fffffffedcba9876543211;
-  0100000000 ffffff00000000;
-  00000000c1a4bc4b ffffffff3e5b43b5;
-  ffffffff3e5b43b5 00000000c1a4bc4b;
-}
-
-2cl {
-  "" "";
-  00 00;
-  000000 00000000000000000000;
-  01 ff;
-  efcdab8967452301 1132547698badcfe;
-  efcdab8967452301 1132547698badcfeffffffff;
-  0000000001 00000000ffffffff;
-  4bbca4c100000000 b5435b3effffffff;
-  b5435b3effffffff 4bbca4c100000000;
-}
-
-# --- Shift tests ---
-
-lsl {
-  # --- Simple sanity checks ---
-
-  01 2 04;
-  01 4 10;
-
-  7 -1 0;
-
-  # --- Copy shifts ---
-
-  01 0 01;
-  0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef;
-
-  # --- Single bit shifts ---
-
-  01 1 02;
-  ff000000 1 01fe000000;
-
-  # --- Word-size shifts (assumes 32-bit words) ---
-
-  0123456789abcdef0123456789abcdef 32
-  0123456789abcdef0123456789abcdef00000000;
-
-  # --- Random tests ---
-
-  13bbec3a734e0b8b5155600b0826b913 90
-  4eefb0e9cd382e2d4555802c209ae44c0000000000000000000000;
-
-  d6ca6a99fe49b256f80e9643e2bd4f3e 80
-  d6ca6a99fe49b256f80e9643e2bd4f3e00000000000000000000;
-
-  c94784b40d54de614084915915531ddc 59
-  064a3c25a06aa6f30a04248ac8aa98eee000000000000000;
-
-  a63c314a39cc37f950b3d530c95ead00 84
-  0a63c314a39cc37f950b3d530c95ead00000000000000000000000;
-
-  842d03a339f5004cfd311e2bb23216ac 62
-  210b40e8ce7d40133f4c478aec8c85ab0000000000000000;
-
-  9a8e659739bf9ee7aa908b7c058c5e7e 123
-  04d4732cb9cdfcf73d54845be02c62f3f0000000000000000000000000000000;
-
-  287f5774f212db87bcd83a1bbb7b1ad5 6
-  0a1fd5dd3c84b6e1ef360e86eedec6b540;
-
-  ec1739174d9d4438d3093cf378605a5c 63
-  760b9c8ba6cea21c69849e79bc302d2e0000000000000000;
-
-  3dfa8ad6a60a783639d05aa5fbfd993d 46
-  0f7ea2b5a9829e0d8e7416a97eff664f400000000000;
-
-  e4e93a80b6d25b34c23aca3a0d06d76c 63
-  72749d405b692d9a611d651d06836bb60000000000000000;
-
-  5a4cf5becb4b64a1a31637c91b6415fd 102
-  16933d6fb2d2d92868c58df246d9057f40000000000000000000000000;
-
-  d92f60928b67416c1e20bd9e09026115 69
-  1b25ec12516ce82d83c417b3c1204c22a00000000000000000;
-
-  eae78f56200d7734f7eb68479fe09d51 18
-  03ab9e3d588035dcd3dfada11e7f8275440000;
-
-  4c9c215ead951513d969d66614016f6e 28
-  04c9c215ead951513d969d66614016f6e0000000;
-
-  5cb1e4d625eac0393644fe6a7e3ff788 33
-  b963c9ac4bd580726c89fcd4fc7fef1000000000;
-
-  68b23795968766c77b1897c88a5d6ba8 78
-  1a2c8de565a1d9b1dec625f222975aea00000000000000000000;
-
-  3d96cd168c74f9015afb691d629f3f6d 72
-  3d96cd168c74f9015afb691d629f3f6d000000000000000000;
-
-  38fa8f63dc426399e0f9b5c01231e02c 95
-  1c7d47b1ee2131ccf07cdae00918f016000000000000000000000000;
-
-  90176b493061899ec95677ccc58b8cdf 78
-  2405dad24c186267b2559df33162e337c0000000000000000000;
-
-  0706e95da68f32a4231ab184d16cbff7 33
-  0e0dd2bb4d1e654846356309a2d97fee00000000;
-}
-
-lslc {
-  # --- Simple sanity checks ---
-
-  01 2 07;
-  01 4 1f;
-
-  7 -1 0;
-
-  # --- Copy shifts ---
-
-  01 0 01;
-  0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef;
-
-  # --- Single bit shifts ---
-
-  01 1 03;
-  ff000000 1 01fe000001;
-
-  # --- Word-size shifts (assumes 32-bit words) ---
-
-  0123456789abcdef0123456789abcdef 32
-  0123456789abcdef0123456789abcdefffffffff;
-
-  # --- Random tests ---
-
-  13bbec3a734e0b8b5155600b0826b913 90
-  4eefb0e9cd382e2d4555802c209ae44fffffffffffffffffffffff;
-
-  d6ca6a99fe49b256f80e9643e2bd4f3e 80
-  d6ca6a99fe49b256f80e9643e2bd4f3effffffffffffffffffff;
-
-  c94784b40d54de614084915915531ddc 59
-  064a3c25a06aa6f30a04248ac8aa98eee7ffffffffffffff;
-
-  a63c314a39cc37f950b3d530c95ead00 84
-  0a63c314a39cc37f950b3d530c95ead00fffffffffffffffffffff;
-
-  842d03a339f5004cfd311e2bb23216ac 62
-  210b40e8ce7d40133f4c478aec8c85ab3fffffffffffffff;
-
-  9a8e659739bf9ee7aa908b7c058c5e7e 123
-  04d4732cb9cdfcf73d54845be02c62f3f7ffffffffffffffffffffffffffffff;
-
-  287f5774f212db87bcd83a1bbb7b1ad5 6
-  0a1fd5dd3c84b6e1ef360e86eedec6b57f;
-
-  ec1739174d9d4438d3093cf378605a5c 63
-  760b9c8ba6cea21c69849e79bc302d2e7fffffffffffffff;
-
-  3dfa8ad6a60a783639d05aa5fbfd993d 46
-  0f7ea2b5a9829e0d8e7416a97eff664f7fffffffffff;
-
-  e4e93a80b6d25b34c23aca3a0d06d76c 63
-  72749d405b692d9a611d651d06836bb67fffffffffffffff;
-
-  5a4cf5becb4b64a1a31637c91b6415fd 102
-  16933d6fb2d2d92868c58df246d9057f7fffffffffffffffffffffffff;
-
-  d92f60928b67416c1e20bd9e09026115 69
-  1b25ec12516ce82d83c417b3c1204c22bfffffffffffffffff;
-
-  eae78f56200d7734f7eb68479fe09d51 18
-  03ab9e3d588035dcd3dfada11e7f827547ffff;
-
-  4c9c215ead951513d969d66614016f6e 28
-  04c9c215ead951513d969d66614016f6efffffff;
-
-  5cb1e4d625eac0393644fe6a7e3ff788 33
-  b963c9ac4bd580726c89fcd4fc7fef11ffffffff;
-
-  68b23795968766c77b1897c88a5d6ba8 78
-  1a2c8de565a1d9b1dec625f222975aea3fffffffffffffffffff;
-
-  3d96cd168c74f9015afb691d629f3f6d 72
-  3d96cd168c74f9015afb691d629f3f6dffffffffffffffffff;
-
-  38fa8f63dc426399e0f9b5c01231e02c 95
-  1c7d47b1ee2131ccf07cdae00918f0167fffffffffffffffffffffff;
-
-  90176b493061899ec95677ccc58b8cdf 78
-  2405dad24c186267b2559df33162e337ffffffffffffffffffff;
-
-  0706e95da68f32a4231ab184d16cbff7 33
-  0e0dd2bb4d1e654846356309a2d97fefffffffff;
-}
-
-lsr {
-  # --- Simple sanity checks ---
-
-  04 2 01;
-  10 4 01;
-  7 -1 0;
-  7 32 0;
-
-  # --- Copy shifts ---
-
-  01 0 01;
-  0123456789abcdef0123456789abcdef 0 0123456789abcdef0123456789abcdef;
-
-  # --- Single bit shifts ---
-
-  02 1 01;
-  01fe000000 1 ff000000;
-
-  # --- Word-size shifts (assumes 32-bit words) ---
-
-  0123456789abcdef0123456789abcdef 32
-  0123456789abcdef01234567;
-
-  # --- Random tests ---
-
-  eb4f57af83f78c0d67b3a6ad84e62378 120
-  eb;
-
-  c6a207d80522139f1fe168028d6afa8c 45
-  0635103ec029109cf8ff0b;
-
-  6027a129cf726a80445bf42a310ecd30 51
-  0c04f42539ee4d50088b;
-
-  fb0cc20512774733c783bfea0ea3b503 36
-  0fb0cc20512774733c783bfe;
-
-  4f9884d0ec9fc9e3be6ac15382803eaa 107
-  09f310;
-
-  e47895de118466ac7b16188284b35fb9 55
-  01c8f12bbc2308cd58f6;
-
-  22dfd1386bd2a5c4b6da0d619485e735 10
-  08b7f44e1af4a9712db68358652179;
-
-  489fab826eb8ce9f41084c2b4ea3bb25 117
-  0244;
-
-  f6f7735e7d89edfa05482a6b19b1d7b6 53
-  07b7bb9af3ec4f6fd02a;
-
-  bd4eda78b316190a28840f382a90bc63 80
-  bd4eda78b316;
-
-  af9f01ddcecf1d21b0af4c318df98e4f 39
-  015f3e03bb9d9e3a43615e98;
-
-  64d53464e8524ef2529389b14f2b9940 19
-  0c9aa68c9d0a49de4a52713629e5;
-
-  ce49d3be79896131d044f41274ff13ee 99
-  19c93a77;
-
-  25a05fcae2ed3d9e2486cd633bd51070 18
-  096817f2b8bb4f678921b358cef5;
-
-  8a29be64acc97626d097231c4f3df4aa 82
-  228a6f992b32;
-
-  ac27fc4590675fb16ecfbf774dc8e591 14
-  02b09ff116419d7ec5bb3efddd3723;
-
-  b72f02eb26b965133db98adcedfe1e37 44
-  0b72f02eb26b965133db98;
-
-  afc634103a039f37b8f9f98b1d94ac85 52
-  0afc634103a039f37b8f;
-
-  f670a78a3801b81e0a00e5b5deb81a47 57
-  7b3853c51c00dc0f05;
-
-  3a1d23d0d00fa4e165ba2b54eccd8f8d 92
-  03a1d23d0d;
-}
-
-# --- Arithmetic tests ---
-#
-# For each of the fundamental operations, there's a sequence of simple tests
-# which ensure that the functions are working even slightly correctly.  Then
-# there are some tests aimed at limit conditions in the algorithm.  Finally,
-# some random tests dreamed up by the Perl script `mpx-gen.pl' are given.
-
-uadd {
-
-  # --- Simple sanity checks ---
-
-  00 00 00;
-  00 01 01;
-  01 00 01;
-
-  # --- Carry propagation tests ---
-
-    ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-                                                         01
-  0100000000000000000000000000000000000000000000000000000000;
-
-                                                         01
-    ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-  0100000000000000000000000000000000000000000000000000000000;
-
-    7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f80
-    80808080808080808080808080808080
-  0100000000000000000000000000000000;
-
-  # --- Random data tests ---
-
-  272724be3cc4179a4b387bcd1acf24e1107be9bbb4dbd68408303df3537c83e0
-  c80ff7173b00d75c83bb38948118fecd9c16ec3bc2d5d051057a1ad8dbfa3349
-  ef371bd577c4eef6cef3b4619be823aeac92d5f777b1a6d50daa58cc2f76b729;
-
-  257099bff6868847d89969cfc691e1f5e0af7516360493a8dae919704eea7385
-  b4408b380c648d50175dfa8b9c1d8aa68f71f67b540045ed3f92f2aa19145cb2
-  d9b124f802eb1597eff7645b62af6c9c70216b918a04d9961a7c0c1a67fed037;
-
-  11978446632ed887ce26aeabf9997a9ae9600da7cb6d431e6ab5dc932b427eec
-  652931ca2eb81d3113453615d16e60de08b3777a6060d7f1775c916253b1e666
-  76c0b61091e6f5b8e16be4c1cb07db78f21385222bce1b0fe2126df57ef46552;
-
-  73d3697b4f886a8b242c21cb39151055937f36a6000849d0d1e526ce666a7d52
-  209e8d770ab7352e5441f74af428a2e9b791dabb655fd78d8a722055e896d7fe
-  9471f6f25a3f9fb9786e19162d3db33f4b1111616568215e5c5747244f015550;
-
-  3e47ae33e633861903e0960b1ef8c8c8900a659cb3e03a1cf1ba04eed5e3f93d
-  b844b1b685b21fce078e0db2b960e22dd1e81aac33062b6d9ed1ab68b8cbbd67
-  f68c5fea6be5a5e70b6ea3bdd859aaf661f28048e6e6658a908bb0578eafb6a4;
-
-  23156b15f2b9a6598b6703cda3177d7432016bb388989d5e33a5cb8778aca38f
-  77197a3167c282ed511bf0eb865be89624e4b5e1e9dd4b7d44acd59d41287639
-  9a2ee5475a7c2946dc82f4b92973660a56e621957275e8db7852a124b9d519c8;
-
-  ed61746de1ab76f33cf25878088b24a389d79ecd65df792954a5788a887982a7
-  b673af9ad91712c6d64f05cc14fbd503b04345aca5695ef26cad9ca1f1460496
-  01a3d52408bac289ba13415e441d86f9a73a1ae47a0b48d81bc153152c79bf873d;
-
-  46a147c2b345b5ba782b600d1811975cd6a75b9bb6fa6db6bd8c594ecead30b3
-  3dff366370a27aef1ec46b32c4946f90ef75c7263f71703be87074ba18705391
-  84a07e2623e830a996efcb3fdca606edc61d22c1f66bddf2a5fcce08e71d8444;
-
-  a1756514e2f8c5805538ad1b85bafebeb1d4ba9c61d19fbf2f286518eeac08fe
-  4646f60744b71c5d7e2a5f66250e0295fc6ddf5acae1f2397ad37403a6881e24
-  e7bc5b1c27afe1ddd3630c81aac90154ae4299f72cb391f8a9fbd91c95342722;
-
-  cf5f959a7c1d3d0027f62303d4a517bd5acadde74db6f18bee67aed2ee1bbb23
-  76e38874ce5c3b7fe616b20f2ace6cf550190d9bad4b2fd80bf6deaff8a329c5
-  0146431e0f4a7978800e0cd512ff7384b2aae3eb82fb022163fa5e8d82e6bee4e8;
-
-  1dee3d9ad0cc6212e5843a57d736fad4675c422efbbac6d625a0f45ee90b7d73
-  d6df29c49292fe633ec60e597d0c5688eb0ba6c134b7c041689fed3e72535c55
-  f4cd675f635f6076244a48b15443515d5267e8f0307287178e40e19d5b5ed9c8;
-
-  3ba228e4e40cb50141845ae8b7318b43c6643765ace7ce83a069f1787ece6058
-  06b3792dbbde4db5f47be20035524962224fdaa18be7dd9eda23f1671e6ad33d
-  4255a2129feb02b736003ce8ec83d4a5e8b4120738cfac227a8de2df9d393395;
-
-  e7ff758bb68a5a6106962113f72f9705dc0641ad029741f7c57a5320d030ad32
-  7fd185b393c432dba9892a0b67aa12a85be6e1643cdfe8404963fe92f4f668bb
-  0167d0fb3f4a4e8d3cb01f4b1f5ed9a9ae37ed23113f772a380ede51b3c52715ed;
-
-  a5bb634cb6ffda70661189874605f802cc34a8960a137130f238638d9a9e72c1
-  ddccdab554733987e04a5aa8674b5eba27f594f37cdec51b3b5745dfa159aab7
-  0183883e020b7313f8465be42fad5156bcf42a3d8986f2364c2d8fa96d3bf81d78;
-
-  76888f3fc82690a4681e30b5f94efd08d03b7eb1c814ed01cde866847e3c75a4
-  78d0869abb1b1fafc582ccd8bb0c27d7ba51de9832d3b0cd8ca366d27d268788
-  ef5915da8341b0542da0fd8eb45b24e08a8d5d49fae89dcf5a8bcd56fb62fd2c;
-
-  24fbb9214449c926753d15573ca07552ff219c97c43824182a6dbabed6872610
-  be3795a426052f168129345d33c6dded8ae8de0e0cbdbcc7c2b3f3386031b548
-  e3334ec56a4ef83cf66649b4706753408a0a7aa5d0f5e0dfed21adf736b8db58;
-
-  97b74ea8ef087496a84b73ee7d8713a13a511f40cc9a19f613a10891774fbc9a
-  fe8dd31272be1f79ee524d736c7fbd3a2c1718b918b072025612a1f2176cf53b
-  01964521bb61c69410969dc161ea06d0db666837f9e54a8bf869b3aa838ebcb1d5;
-
-  66a6b572a25f6f97ec5b7e7e393bfd686b69c083cd673feab076b9923133a46a
-  e7b501c43dafc08bc521b15be8a1ca9dffe174c282111ea9eb0bac34fd0584b7
-  014e5bb736e00f3023b17d2fda21ddc8066b4b35464f785e949b8265c72e392921;
-
-  59a803f729f14d54c35de20cdf9ce5b8e2f430016448c80e9d3e2ec608f8bd67
-  7a5a9cf43d1d70e200c5bc7baf4dad57e5892866bb3ced09eb0ed096214509b3
-  d402a0eb670ebe36c4239e888eea9310c87d58681f85b518884cff5c2a3dc71a;
-
-  d26914575527153ca24945f0e83df5b0480c8840e1e6807b71d008068b082c7d
-  281c235d8f8773649c75baba0c302f99f3c526c971cf3daf976deba0bdb3f38f
-  fa8537b4e4ae88a13ebf00aaf46e254a3bd1af0a53b5be2b093df3a748bc200c;
-}
-
-usub {
-
-  # --- Simple sanity tests ---
-
-  01 00 01;
-  02 01 01;
-  05 03 02;
-
-  # --- Carry propagation tests ---
-
-  0100000000 01 ffffffff;
-  010000000000000000 01 ffffffffffffffff;
-
-  # --- Random data tests ---
-
-  a024729f63161b8fbb711008eb863b9e2044a77ccc7bccf19437471e51a4beec
-  9239ec16929055e3a156768fa1432c56d997ba51c1efbed4c791f062d95641a5
-  0dea8688d085c5ac1a1a99794a430f4746aced2b0a8c0e1ccca556bb784e7d47;
-
-  8ab8ea06c7afbdfe6636590f748fdd376a2dd9c708e7923541e134687fbfd526
-  8896da6b7c98b78a0ea2c9cae23d7065a94daea56d1c919a7db2583da936bd8d
-  02220f9b4b17067457938f4492526cd1c0e02b219bcb009ac42edc2ad6891799;
-
-  fedfecaf26399ad6eda68c7c5cada4aed095e82182e3df696cae47e521c382a4
-  7510069be2896480db0beedc6c5497e79bd7ac5e9fc14bf9ca460c7f99aa6834
-  89cfe61343b03656129a9d9ff0590cc734be3bc2e322936fa2683b6588191a70;
-
-  ffb81ed18909fda98730e146735c21d3914122faf84882dc688237371825739b
-  d7eb8f85d95888d2c4dc7b9fbbe689e2ce529f8870b2487ce28d192ef3ac2317
-  27cc8f4bafb174d6c25465a6b77597f0c2ee837287963a5f85f51e0824795084;
-
-  c3c2c77bc0867d30c58c1eb786ab7feed60f9e0e2dcfd6ed97725fff364c7b5b
-  a936ff836dd8dd063ab05e4fc7176e8c05a45ddaa7f701e4184b4fd371ce968a
-  1a8bc7f852ada02a8adbc067bf941162d06b403385d8d5097f27102bc47de4d1;
-
-  ef76a6e2dc6ba3317dcec6e338a20cf12eb852388204efe290a3b1536f6b198b
-  3eb8d18b7903d682d713859f258ddbc13aae32392a4267b0cd1481c036ab5baf
-  b0bdd5576367ccaea6bb41441314312ff40a1fff57c28831c38f2f9338bfbddc;
-
-  5cf09a0f0488a077e2983b4a854c28fc7a11f7befc196824f7990fadacfc26db
-  0f46fbc396b81c512b7a0ec003759de05a967101a3ec50b7cbf84f42708f396c
-  4da99e4b6dd08426b71e2c8a81d68b1c1f7b86bd582d176d2ba0c06b3c6ced6f;
-
-  ea9b202602ad3219e3d3a8fbaf042c3cec8a3d7f16923855b0ae67b8ebf57b50
-  850568cdebe8fe9f91c3d8bb4bc525158bd8590b235f46d6d556bf969e2f24f4
-  6595b75816c4337a520fd040633f072760b1e473f332f17edb57a8224dc6565c;
-
-  fab03a9f849f408b4af55746316f8e3a81c6359b3c3ba1ebd1d8b9e7a983a03b
-  a60ecaf59c0c7d0ce3ef4d6d9006880efc9c6e0edcafbf7291b009e7b3cb03e4
-  54a16fa9e892c37e670609d8a169062b8529c78c5f8be2794028affff5b89c57;
-
-  ef7de9bf497c4c47d323a379a42789925606f700e786622b280aec1ee6e13901
-  8a4197e881f1d2f6a09296e6d826ea628aec658b4bf7e9c436ab7e70746c4c87
-  653c51d6c78a795132910c92cc009f2fcb1a91759b8e7866f15f6dae7274ec7a;
-
-  9cf0d943545ee18ca59af6f547cfb45de41b1d52c996f482728fe68993d3a966
-  58ad4b10fc09cf4f4f4a1488e36ed3beb0a2a9e8c8ec042aba113b2144ff1939
-  44438e325855123d5650e26c6460e09f3378736a00aaf057b87eab684ed4902d;
-
-  3e0e637d1f4ff5b6d58549f8011ae0a885bbdcb5c478777417e6293c108c7c0c
-  09e06b0b986110817123a2a5aad0c178bac3005315628424d849216a43b71ac4
-  342df87186eee5356461a752564a1f2fcaf8dc62af15f34f3f9d07d1ccd56148;
-
-  c3b4cb636f76027a876150753e266774af9350d3e68713adcc39cff5e389e285
-  a4abec0b5d38bc91310f3b9e3e12d0c4af2984ba710a6309544340ac3c94e121
-  1f08df58123d45e9565214d7001396b00069cc19757cb0a477f68f49a6f50164;
-
-  175402d43706fcdb3caf41cd8de6822447e39f3a0ed2f00d4d315a1cc03b5bfa
-  0ffd7d0692776dbce6e112902472edba5ec4c1500412d9bcd24472da90889b7e
-  075685cda48f8f1e55ce2f3d69739469e91eddea0ac016507aece7422fb2c07c;
-
-  f6060bfae1e558606d44496967e0eafe805e6f60d1c4a8f886574c9d6c6989da
-  e933391716ffc61eda9c547e7bdd41799ecc56e05178ebd7e2068d32467aace6
-  0cd2d2e3cae5924192a7f4eaec03a984e1921880804bbd20a450bf6b25eedcf4;
-
-  cfd8ba6b7173b72451f370c7a7dad7754ea2323e52f622c1490ff2d3ccf5753e
-  b4e23f1700a3fe1d5f0465cf3666235f1c7460ffebce87c8b8d551ceab09ed1b
-  1af67b5470cfb906f2ef0af87174b416322dd13e67279af8903aa10521eb8823;
-
-  ebf9500e9cda50607204618fa6cf2f29f2e0af023237034f1a3e72787364370d
-  0e826c97712e73f32d850d4cf63925fe8c8ed86396350432b9971900a4068cbe
-  dd76e3772babdc6d447f5442b096092b6651d69e9c01ff1c60a75977cf5daa4f;
-
-  c4f9d29310ea767aa8dd0af418447dd3dc2c220c48591f99b6dbf0521f7a5640
-  6d72f5441ca9dbafcbf4db9701d6c667c1d5376251de09468e3efbf1fb04cd95
-  5786dd4ef4409acadce82f5d166db76c1a56eaa9f67b1653289cf460247588ab;
-
-  91af1ae9122ba385deae3f9b478c8270a2d2221396fb3639b44e06e3a1ae9817
-  08966b342d42332d2155fe03fef2d3f84b415d1fda1168a5c63d0f9b86b77cce
-  8918afb4e4e97058bd5841974899ae785790c4f3bce9cd93ee10f7481af71b49;
-
-  976e1fa5146093d794691c63d1aff7ceb5851bb6196909eb51fbe4640829b208
-  1e8a3a0a9050c307cd94a65793371f88eebe42ae8893b1ff984357d597c884d1
-  78e3e59a840fd0cfc6d4760c3e78d845c6c6d90790d557ebb9b88c8e70612d37;
-}
-
-umul {
-
-  # --- Simple sanity tests ---
-
-  01 00 00;
-  00 01 00;
-  01 45 45;
-  45 01 45;
-
-  # --- Random tests ---
-
-  4162c300b3e157e9cd1301d499c20121
-  10549901fc6dcb85882440087bd398ff
-  042bc7ac8fe08ceefb098f286cdd84fd037906ead144324e361c488a221db7df;
-
-  f4c0a35591d6567a3ead2846f4350141
-  58bb07247f8a7591b7acfa727118ad8d
-  54d507b0e32175976a30766da14de0726a8ffbdc7ef0291a7389759422229dcd;
-
-  5d0965f58c9d794ca477ca2349900193
-  2cbff5f50dbae1965e3aec1108c36d17
-  104360ec53eef2e669285143dc0d01c9ccf31a77dc302bf8d45356feb794bb35;
-
-  1a438b12e1babb4c68ae4606694fd1be
-  5bac6d40fdea39c2f1f6ce285f028d36
-  0967b3069413a0fac34c03fdf67e2f5187232be344bbc6011849688052d7e414;
-
-  59e648d1f656407efc7c9b622de6bc6f
-  0dd07d6e4dc035816236aa0cd512e424
-  04d9e8da01ea1a42b1b9670a4a14694cd104406f346a0598b65e0ae58f135b9c;
-
-  55c69d7a662a945e6a535911e7abdfc4
-  9883a7ea2c89f5a873b5bae63cf5ac73
-  331a0a66497eb713fb09b260f8774aa97765c13bb040d7917a4b7cb9a321350c;
-
-  bb15812991a5a01c6e803475d5f2f1c8
-  66782adade0952e8ab51a2fda6a5f611
-  4ae262dc95488914177d07869caf42dd008ecfc3c092df3007fca8702f603e48;
-
-  b06a37683348e8e46ccd954ff0348a82
-  e158b834e442cf83aa863dde751525b7
-  9b4a7e266b977f83598e6288efafd0f517d9658a2bda86adec7e1835143dccee;
-
-  b7f66a5ca27d276bdbad5995aac0f676
-  8f05519b9acbe85369aad7a865a0bc5e
-  66c677de9ba98e4c527c86b80ad1485c41782c3e0be53dba2f547fa0ff992754;
-
-  b7f43225f41056548b095f359b6a3b83
-  966a8ba6772991700ead0e01bde39120
-  6c15a4d835ec2367ec41c566ce63a098c496aec8a5b041fc7c91e6601525a360;
-
-  87277faca81e1bb28e0e24e4bbf5e8c3
-  5f126e08716855110489045453e69dcc
-  3231633f7a7eb05793df2c7761d793a634faeb021fda1a404f05b2edefe71264;
-
-  3358074e192e79ba42c186ead80404a9
-  dc1df51ac8c3328107638e83b17f777a
-  2c25a8688faf32cb8b1d4b454cd4a2ad1130df69188cd2ec44cc8806f8ebc78a;
-
-  7ad1d7a04f7588af0ff7bf29c13533c9
-  0785d4d4d5f1d25aa6dcf744662ab2d6
-  039bf2064b716e3befa638d510131596518b1d91833200ba19ae6aff15750c06;
-
-  8b8a4c2ef785abd1607b663b3088e37c
-  fcc67dfa767e06d97cfd5341ded07e42
-  89c854a034d2cc29ebb34f379d6a74a9996d261774b1e7ba965e98204001adf8;
-
-  1c9ea6a1b9aba96124dd8abfd3dd78b1
-  93ecdfc3f4c188819e777f082b77e4c6
-  108994f4961164206f1a97cc0f39edc29faf2bad99d164fc60c06ccff20ffce6;
-
-  c6d9a8a4760fffb11ac2d38b62f62a89
-  c0989f4e8aabd21f7a2b38ec27afb783
-  9599cb75abf86c37db000858bd671992ecde9d440cc765855287391f8f06b31b;
-
-  5d48ba3dba86c0e9d3922cab8d88c5b7
-  5186010a8c3fc4e3499534669a13f219
-  1db4d7602500cc34de718d5892f79db44096a6c6705cf6e9ca8b438cdfd74cdf;
-
-  d009f15fd77915f113e471884e464462
-  cad68bffeb24842cc083f5496b10e36a
-  a4d6328ac530f0615ca3b0aebeaf104960e120609c58710eee206cc3f3db3694;
-
-  343f0033e5648741936c20439bf044c3
-  9b26545821fb1270515566d970e566bb
-  1fa9f7b01c40607bdc8f554e57555de879784cdb1eebfcc3a75918d27656ec71;
-
-  08d95fc1d6dd6b9423c7bb033598df0c
-  6c03f5958677efd383509141bf257375
-  03bbd76f19ba19e3f255c24063f6384d4ac913d9e582392589a525195bcc547c;
-
-  # --- Karatsuba regression ---
-  #
-  # This bug was caused by kmul (a) choosing the split point too low on
-  # odd-sized inputs and (b) not allocating enough workspace.
-
-  21a9269d7b8b63cf18faa933b3c868ba1e8cb3f00b57e197709abf96eeb9bf12e8fe22b3
-  0144c992b68e3ca712678215d5bc968702ccfea17717737ba501a38d26fa5091ba
-  2ab495f91afd7c36f85ece6fd58577f995de88d62a98a07c6d9e3500ae67b0f100bc709d1f30894662774d0cadfba091788c427cc6f4bacb26e42cf92f6e4494e03c990e;
-
-  # --- Larger number tests for Karatsuba ---
-
-  416e63549e2cf08fb225058b3545cb4a47cbf9
-  de38c473c27f7bdef02a084192b3e17f435cf7
-  38cc3c7f360737411df7b52a222a3672c6e0d39f0a868479176a6143e1129d44d5aa61be493f;
-
-  aa20b1355073f21c57530d2f90bc40e47ac463
-  8315dfa60e97ff3dab7a6f61fcec2cd5b6f127
-  571d43fda6ce14a78534ac72c50b58738d62630766a59a7cec1a63433e499b1b5eac5ef71e15;
-
-  f641594177c8c364d922c659a8f7ae0460c7d74b266c8cc258ad5f
-  5948dd29fc5172c37c31da6957779a1bebe452d8deba26c5d3d390
-  55e2cf27aa49f938584dca4044d944077e226206c6f8c7688e8760f3b5c106413fd0ef4b63a97991da86fd113ff4822a41f76913d270;
-
-  a4170f55dfa135c4bdd3a921a8c1567eebc6b799fb62b0dd27b089
-  7b7d619e07a5d01427348c05605f67196b2923b074787c375977ac
-  4f277232c75290f0c5fed384dba2aaa23fe4a360ea63ee45fb6c0134b36a09a9163f3c767d498b8dcd31e5deaef386d4a9b7d85b4b0c;
-
-  250e7a0c7035df81429572d3f772720e723b710d54b9eb5f16814117980f0559bf12b82e00c5b3904e
-  1be3c88b01ce53a70c12f74dcc247823846ac6c06a9cb41b86794900006045f05e29da23b81523aa9f
-  04097fbcf75616fef7b6b91680963f7e0cf1bf72bc5f453e46136fc92b20ae8a30d7ae7965f8271de854442b93562ebaa9ee09fba4a7b79ef8b26718b12424419dc301496dc0d6cfb04e4f7a3a3729046c72;
-
-  af3148a72dcf1340f6b5a3b2fc1cacd7e6f9e60a13de5c91c37bb850f0e930683c2dc96882a9f62b76
-  48603cc656908b34c70ed826da8c3414d5845100f53cb6f9f370a4c7708a9b8ffd787537048f89493a
-  3187b8818bf644805c880d189bbf606ca23e01431cf5b3b633db48a1202aa346f6a0e3958c7264fa1de2d92660345e820f4f3659cf0040a28fb9b725f7ab83610c9c056062326f776ce871696eede0507ebc;
-
-  0b1cc934a2f6244b93c8ac10881de20349d133642ac19fa0be3acacbf4429d0ec7bbad2f41534a693647b7c02e683cde249e36f008fb68e96de65c8a268eb1ea
-  12444899c13f0ee85a4f47024f06d8a5746f0d9fec02e57c6d87a7bba17c1454fe6387bff5b96e38ce6142b9eebe249865c52b617b8966e6f93b16f612a91155
-  cafcf1ea9f16a56f9ac4635d58992a789c51b6d7e53b5e1d8b59d5c1850c5c6ac2297839af44b29d5cf440772f98fd9d090ccec2d56adeb113bd3459d620b0b02679b72f3170ea8e2bd4486eebf2496d8be01cfe86923e5bbeb6f91582dfb95c6ef0a52cbc068081dc363b31dbd2ed80e3267d973ea39f82e276002eab9cb2;
-
-  3ba5a9c550b8cf6c3b87cc106b6551221a0dc90ac193ebcc526e4e5f53cf012fa6e05b155dcb3c4c0e1a90a01062a67ec434f6744195349194770711ea836a8b
-  54f04f121d22db842523e9bf75727d5b0e9ef17e6d727918894927fade87ceeb2106684c4af7c49653425e29f7a91abf8adec4de2ca499df2534644397e454ac
-  13ca59703f4c087c16a9a7bc7022904a37a469c1d0fd9fa7ffabe8f7d887fe1572c0bf5c75fde6913b565f8106bba9c26c9bbce190a9b8967112d74c0ac3d4ff9d2a385b96833e3c456d5601c74d8d2c9fff35abc60e7cc15d7c680f20757c13a415f1b8fbe3c6c32434aa36c528473dd20ea39f0e5ee22d1cd23040900d3164;
-
-  # --- More Karatsuba bugs ---
-
-  3fef06998b0ddd140e01527426ea409b2b9e640f223dfd652229fd17eb99d44f6be6d4935505df676f48c8fcbfe2d5096345d6509267aa40c54d427f0cce45cd0f8fa7e4a22492d7ed4ffa45e3c0e5e3c25c841943fb2cecd6ee9275ae93c4e15e2d9f8f317c44c541ed52a6338b0fb9f7f7f4dea78cf7ef5201837c00a6d4d2
-  0260acc6378341b2b894dacab3a44b914f19292bb32898b155584a406161bb04ad9c14db20888dfcdab613b368b5c699305c4e9b226d90f9523fbcb6293407bd2bb18bf7bdba8539fb577f19b72124c2d83a2bc31f44366e917ddc705085b79fe9e0df0e98e4f6ae3df63d9b321382c18b95de1dc4d1db93b3092c9c6f8c9764
-  9802d5c5d5a73f9d4e694a8920f951ce4bfe80c13a35cd5332a556136b83495a2e9b4d2ed53aae1218d2e1c41349311f86b1ee1f2ad5cd3c5b264e8e68906ca45bd7d0fc8e8a5a9648f458cecba41fd0848a04f506bb11ddb378f3214085cf865ba5533cfd73b28b1e12784f447b156f59a3b68e6ec68303ddfce59ce33ca386ff3316e6a5e6f9b4201682aa9e59a6d7cb9315a492457640acca19fc7dc3a25a316fea9a0f1d32838b7f911650647f996551263c2d001fa1c720753afca316c7137300ff93f2ddd2846ce14c55d0ead626f681bd11707f9674905396a9bc9a889eae721ab6407586880a95575a968b43bdf50323627aa0fcddfa4e198b0008;
-}
-
-usqr {
-
-  # --- Sanity check tests ---
-
-  00 00;
-  01 01;
-  02 04;
-  ff fe01;
-
-  # --- Random tests ---
-
-  d573446554727d0f05ad3ccd03665c2f
-  b1f903b723d65fefeb935ef5c50ab18da09777b28b8a093adab73a5cb0a5d0a1;
-
-  27ed6604397ef6acdb3f1906e5c0be25
-  063a313b55fe82206c4e69624c2afd726dcf52c1efc9d0f81c948907f6baf159;
-
-  869593eda5bbb87109593218d3c99f86
-  46c0ee42519e3a8ce80f19b6bd60332254e1e144350898d77e803ce2c7d3ba24;
-
-  94edc3ffcbd975677c95b44e7f4a8164
-  56a3c77441629088100fea8b3e510352c9904877e9705b9e150e7b004735ef10;
-
-  4a3b7b546f9f15a09bd35d6de3b33f82
-  1586711ee4ddaaf121f7e4311d3e182948ed5569def0257e099be8d66b8d3e04;
-
-  adf038609b8f95940806994831db9409
-  762e8d9c53ce25e6641019bd974169acd1aa3e95968b13e80c97d2120f006851;
-
-  337e87847e2ddf24444fac6f64c6cc66
-  0a5ba888786f7db6d9c28a7482545e31ce687996024edfdc05ae3a8480fab8a4;
-
-  0b2c882b8a7dcad93cffc77be4436e62
-  7cdb72d54cb539de9fc55d68b9ca4731ad6b1bef79fd0dd12c9c8d86e45d84;
-
-  298a1b9f23f7e77dc288c177a492843c
-  06bd875ac41323efd9b958064f96e74d84faf58a2c43f4bec525750ff8bdee10;
-
-  f58345742a51bd04c80b3791a688871e
-  eb74864080bb96f90ac10021b82af6ea9acd21af8b8c103739a14c06bf30a784;
-
-  0c720ed1384848bc57e6f92cd98541cd
-  9ae434d07874574a5702724fcaf6d27f5686744f03aa444afe9762f9ebbe29;
-
-  37e91e1c9a3f237a08dda2e6919dbfa8
-  0c35ff381de29f85eb03c278ca9623be8603ac9f744c826d08e91630f38c1e40;
-
-  8b270d9328ea8561db59a8ac4e651d05
-  4ba36eb2f1fd6b0cbd6f71ac36aabe1be53e21ae9afd4c9ce1715456f53c2219;
-
-  5e64af22a077e8832538dc9ff235bea0
-  22ce1836b8b5c880ea1e00f95f339ee776d8edda0563e498c98f726efc31e400;
-
-  8e6d67cd33ac976b183475e54afdb715
-  4f3d8de934283d046ebdb7263c73978e60c2e68179cb3edf79c266dd867107b9;
-
-  27f566956e3fa7141088402630e929e8
-  063cb07f0ab7d5d22828664724da2dd261c14526d80f7760aa04b4f44f2c2240;
-
-  e26c74de93a02296693ee98e552d5524
-  c843ac4bcdcdc37c3ef17997e8d013d1d4ecff5a58a22e2be50d1e80f2f8ed10;
-
-  ca53baed02dd4ba78cf7a3963b438395
-  9fe83e60c6b25a7b58d1f84a5905081769b4c5b5c9b1d63a5bec2110d19fd4b9;
-
-  d6e517000ade8ef62963e890a472d530
-  b463cf763a508b234fbf75a75781c97b5a9963b8f8456d23d05a2aa81048e900;
-
-  c4245e0ce04fe1151ca17eb8aeb6e3e3
-  9647b52e4da6dc80171bd5495ab519835e871bf915ee7e59f1fe2ac165a05b49;
-
-  # --- Large tests for Karatsuba ---
-
-  8390d2dfc9770526e8c4820e1cccca0e8e19d2
-  439d89bef1a65f537e59e74590df3ef10b7e78066ac2af7b5c910e1929de102b491b9f92b044;
-
-  26c4cb564d57970bc3dd00c0c1690c7f1a2e9a
-  05df03a59c9e6ab7bfed79ff8f32811303e46f94c2e8d9abcab5bdac1040e7fdaf5a4bc3b4a4;
-
-  599b3cceca39690c06425127a95b84310cddef
-  1f5d4e6a797662648e4b09abeee439415b76cae52e7cf9db1a54b7f99afb9c00b6130cce8521;
-
-  485b65b3d5edb34810402943ccfbe37a137f8f
-  147389d69e9730f86b04a1782fd15611e6f8dc2e99abc812be0cb82efb2a1ad538aa7ac931e1;
-
-  5a243e54da1f87a8fe23c8b0988b3574aa77c1fe620a5d25b8e03295aebe6c6e135a17
-  1fbd80f54068ba081e793c1aad443094416a75e2e708337618e4ff02ca9dd26bad87cdc0f758342df39a56625c956c971b1f7f18f7d3cb6a1880a574bb7b06a6ca4a431e2e11;
-
-  f5c57a7610feec56586de369136ee25aaf5d3861ad80033410c410658332ca856e4cce
-  ebf394bbb0d2d75ba78b75ae018c77f417cc1c67f0aa587d070980386e14f2b59d9a580d8d483b4df7f6a8d4a44ec8786a87d1da031bb5c288c3afc65d931471786c2412f5c4;
-
-  5bc4457e00bcacf257200a96eadf90359cbd9f6a2c2c69b5ea2e4c5d3939f0ce100c06
-  20e51fe210546e478bfb9d2b0418df921974417799951533f317498439caed52a75c4c66db81910b3fc4f4fb3711cc25f2b4ef151a2023b6e52e64e1d5b7dffb0b9b29509024;
-
-  4b51f1e0a9206173d39a0f1f4eea558dbd9d1ca2d41671b2d27b1b77391e76504e14c0
-  16291df497ccc32ee92a9037b78ff10828c2645dfbf91541f3a0d963892d59c5cd966ffe1e1ebb2dfe6f434fae44da11ae2d2357876b711feba596612c102b8905c8a6ae9000;
-
-  10f63541b2bc5a7d241f887d0b3d182dc473a06c4fb275259112b2fecc9455d7b1eb5b2e9b5c3646c35121d05f1ae99f1ad990c7f0e48b002bd5fdd253c68b56
-  011fb3729baf522bcaed9a966645754804b2cc80168de9f93544e17d5b6d6b81c516f68b72580257f15e3f95bc6eec22608c3055de04051598bf4a76975d111a59d6b02a2fc42de65926cee5d5b97b6c7fc85e00dd59bfdac2c95bc80b7657582b2853244e55b507594a83d5bd87b7a83016dbbc104ce596bdaaed6d98de80e4;
-
-  9e40b3c041505a5e266109f752d85ae3abcbdd28bfc70bbb2c7228bc1564ea893cdda0350689610b74babfe45b14da9708f28c22e3999c841fc70075dd0535cb
-  61d3ee3baef64371ce0416d3f5a6e687903413ad06e85ebbffb9ea0ae9e8cc290fe9dc1cec429e0a294b18121ee29755baf4306861e092e5c1f1def03953f559766787a222368b64594b7be2eeea0698d1fc630446714e681210b5a66e0433b6c43038c0ff213cd14fc0a1fb71789d57b097ab44d859f8bc912f2a89a33baef9;
-
-  d35af50f523d29f53bf0126ccddf4f3052ddb44eeaead360b5f36aad902ba105a921880cefb12caf5e1b3719a40596732d265e996e491f82ca2edf08adca131e
-  ae7f10487aecfa7f91217020f96a1cb00d81545deaf9730daa2c7113e84e76c7e54a1b14971d26750816a696d55622ae1dbd56befdc12a656e66e1d10e87c3bc209e0903635784af6d48a4d7ec84634efb91b7efbfff724bb50ace7d4684d2e72eb7eef84ed5cfd14a7602ceded675da541646febcaa285396b23338b8c57784;
-
-  3df659f884c6a31c5b332efc44fbd70fea46b81adb241fc651af038380f8c476a471f06382ebe55eba339d84edb33a03002ac505d93c61a42ba20e36a691c287
-  0eff53f178849510a118db72c5620423c2991365b06e8caa76300f3df554cf8830c9833f6ec1d33c850b1bb380e33a486a9963b63b5228229fd7e9bdd308bc810aa5e74ccc0e65a2af40c9a287c67e69e841495b0221110f35ed6319bda0dcb0b02174b666df4766eea05481f6a80fe4b93a06fe475d58ae3002303904bee331;
-}
-
-udiv {
-
-  # --- Simple tests ---
-
-  09 04 02 01;
-  ffe3 01 ffe3 00;
-  cdef fedc 00 cdef;
-
-  # --- Random tests ---
-
-  8ab316d0d1a2e88535cf77c1172881ead70d592c59e9c5fbc16e4b0c4dc49481
-  18ca3bf7ee3c6d7bab3f144b015ccc6c25472843d346b461
-  059850f995ddeb799c
-  02c1815029b766b96ad4507dc1af8151307961c6d161d065;
-
-  8117d1663ee63341eb8faeff304549f0f8b32d587acc2fd5597ea6a31625881d
-  dc85df77dfb61876805623bcbed325b99d00c2cd65c252c879
-  95dc734282eb19
-  395da02e8a6c66476467c4e04f328d8208cc411e3d1e96e14c;
-
-  63791966f2ad44a6df11bcc87c6b7c2400c74e69f7e3ca02fcac12b3bf56238b
-  a49e473b8f7539d89cdb002d73182558773eec10db93cc6049d8c5533e
-  9ab11a
-  65caf6833baa118b53c7bdc44a831605ca382b5993beead59f3971d13f;
-
-  9ca438db3e0f79305987292e8ec6174e6c313f7904ebb35a349a700e3ae63a37
-  b24c93d499c7073b8f7aac718c1f12da1a8fc8bccdd47b49
-  e0e779304869fdc1
-  46393cb15e38cbbc8a85698151a113f28081b4c8f6ed232e;
-
-  8214fd17858a4a913015412b5331eb9654faeb5156a674b1e5f6550a68957146
-  c4f0ebaad6c0ee0111c57667ea8e0a254f3068f212949e20ededa89a7da6
-  a917
-  3fde916ba21d19414d4316041420ca59d8b01aa2acf3f3ef106245c1915c;
-
-  55a487a70935360158bd55542eb46271f90f7312e77344c4ca6a580a80810612
-  8996dd0613f846
-  9f58fe011d73a8750454d9bffb55906e9bcf563e0c48b5b608
-  4cfd95e3e17fe2;
-
-  6a13e1be50ecdd7011f9ced42269615efb38fcd3e5477bc57377138cf1ff9519
-  fda103ff99ff21
-  6b11bf2670bf080ef7c5aa0fa5989324e88e3e581c0e7507ba
-  717db69e0d501f;
-
-  367aa8f5ba9ac4e8e2ea198b8af2c3b3081deab392ffc05715783b245a62a6fa
-  72e2c37447f8bca34c4a39b130ea8e5c9a7d8b54564aa88ea773
-  7965572732ac
-  08e8c03ebf398c63d71d8fd7ca4ece12367a8dde180ca650afb6;
-
-  6da07a0a1f9a7dd93e1f82be23fd5e7814b84fc74d4566dd83914adf368c1689
-  3cc71e64
-  01cdc15d7d825955c50ccca72fc5a16f9a7dd04363b12d8354d3088e51
-  299000e5;
-
-  001f5d985f594315d8c58f2d654304c8417f683b65d6d3246b89960e5f6c133c
-  5bbc034d956a17998a30a3
-  5787e7e94449592b493486bd9a323f939ad9bfde
-  1298fecf49a80ad72148e2;
-
-  ae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c
-  c33c890f030644d88cc65f8ccf99c625c9b9fa21d4eb153e52ef89df54130855
-  00
-  ae2d84438ac6643fc601c1634351aa75b284fecbbe5faf3a132be9dd1a326e6c;
-
-  65901dcdad8dd0625d4d158f99b666fee10480d1df15e3bdac640584b9b746bc
-  d8a1d326fee87d55f39f15b5b2cfe71f5146083928
-  7805090edf620d22dac08f
-  859c41164983547c03134b99530e25a0f874315964;
-
-  5d9e7037d70e822c2ce4b3d93f3e20d437a047aa94103296cc041e1b7ea0d9ae
-  d2b14235853f6bac6fdba208897d
-  71c036bc8940293745e65c49f9b0bc1a8aa3
-  700473d994c1cd61ab24f661ed17;
-
-  3a826450bde36cf03de1d6829f7e21af52beb2655e2c902ed634f84e135b241c
-  3023b54e1deda493ad0b4558
-  01372549e716f70dd3c6bb31f193682b7a9355a7fc
-  04359aabd8bfdf8dd3ce797c;
-
-  bdcfd9593348eb1567377e0d4f4bfe8a26acac14b56f7dfd82beddb4f11c2373
-  1f0356b60ad66f4fd7dda57cfc6d1aa374108bd4841127c8
-  061ed1e07aff1c094d
-  0e313b6052859863725786d1459434762ccad8540bad244b;
-
-  293be875d1251920e18102446ceec021da8d8d24aabe49c5911d19ddc3db516d
-  b66e4ce3aa7390a9d888c5d22176bea5c36ae962ae8f252cdf3642556641271c
-  00
-  293be875d1251920e18102446ceec021da8d8d24aabe49c5911d19ddc3db516d;
-
-  5f1085256c5fb856ceab16f2372b6b7024c7d1fcfa7039a0555bb1496c0bc92b
-  c46c1fcd4a8a9cb91775f901af0ab42e39015e09fc737ae2011899b34322cd
-  7b
-  b091ddc98f1f09e065684e681146ddef6429ce2e24bd95bed4df704aca10ac;
-
-  82ea5bd086409cf3681e55e6133626ce9579db9eb01a0411db9c8521c3c66c2c
-  605a13a7d4b75f1094260227cd4cab
-  015bd5405d6bfd4571e54bc47a1b089abfd7
-  3074a3c84ec3bfa32e0db1b349738f;
-
-  3b68662228026ec9e9be8206d3226edd265552a3dbe15a7aa399eba05a69a6c3
-  a0f4265e8f59474132846bfb15
-  5e7d40f138e2a107a52f85a0eb6f92a1c3ec97
-  1508f62d27e7fad09e3d423160;
-
-  82a5058150e570c9eef1f4e5d55d3cf261de28a17f4735caec8bb38e1813978a
-  620d87bb63872a40fc2092b0ed7d3ec4b648be41
-  0155177e99a8a5113226ff8270
-  2ea2205327e66d75990cc999fc2380883ee4591a;
-
-  # --- Bugs ---
-
-  1a923b3406cbe81b093ce418f6a73107f504502b2e3d1b200762fcf6062723de405cab0aea00000000000000000000000000000000
-  184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000
-  0117d3db34ad005954459be9abedd0e5deb4ea0000000000000000
-  00;
-
-  ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff
-  7fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31d1b107fffffffffffffff
-  02 01;
-
-  26737e 0ffffc 02 067386;
-}
diff --git a/tests/mpx-gen b/tests/mpx-gen
deleted file mode 100755 (executable)
index e53b1d6..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-#! /usr/bin/awk -f
-#
-# $Id: mpx-gen,v 1.2 1999/12/10 23:26:51 mdw Exp $
-#
-# Generate test vectors for MPX testing
-
-# --- Generate an `l'-byte hex number ---
-
-function r(l,  i, s, x)
-{
-  if (!l) l = len;
-  s = "";
-  for (i = 0; i < l; i++) {
-    x = int(rand() * 256);
-    s = s sprintf("%02X", x);
-  }
-  return (s);
-}
-
-# --- Main code ---
-
-BEGIN {
-
-  # --- Initialization ---
-
-  i = 1;
-  if (i in ARGV) len = ARGV[i++]; else len = 32;
-  if (i in ARGV) op = ARGV[i++]; else op = "+";
-  if (i in ARGV) rep = ARGV[i++]; else rep = 1;
-
-  # --- Output filters ---
-  #
-  # This is complicated.  `bc' emits numbers split over multiple lines with
-  # backslashes.  It also doesn't pad to an even number of digits, which the
-  # test rig is expecting, or use lower-case, which looks nicer.
-  #
-  # The first bit matches a line ending with a backslash.  If it finds one,
-  # it appends the next line, removes the backslash/newline pair, and loops
-  # around to the top.
-  #
-  # The next substitution translates the whole kaboodle into lower-case.
-  #
-  # The next one looks for an off number of hex digits and prepends a zero if
-  # it finds one.
-  #
-  # The one after that just indents by two spaces. The final one sticks a
-  # semicolon on the end.
-
-  bc = "bc | sed '\
-:top\n\
-/\\\\$/ {\n\
-  N\n\
-  s/\\\\\\\n\
-//;\n\
-  b top;\n\
-}\n\
-y/ABCDEF/abcdef/\n\
-s/^[0-9a-f]\\([0-9a-f][0-9a-f]\\)*$/0&/\n\
-s/^/  /\n\
-$ s/$/;/'";
-  out = "sed 'y/ABCDEF/abcdef/; s/^/  /'"
-
-  # --- Main code ---
-
-  srand();
-
-  while (rep--) {
-    x = r();
-
-    print "obase = 16" | bc;
-    print "ibase = 16" | bc;
-
-    # --- Shifting operations ---
-
-    if (op == "<<" || op == ">>") {
-      y = int(rand() * len * 4) + int(rand() * len * 4);
-      rop = (op == "<<" ? "*" : "/");
-      z = sprintf("%X", y);
-      print x, y | out;
-      print x, rop, "(2 ^ " z ")" | bc;
-    }
-
-    # --- Division ---
-
-    else if (op == "/") {
-      ylen = int(rand() * len) + 1;
-      y = r(ylen);
-      print x | out;
-      print y | out;
-      print x, "/", y | bc;
-      print x, "%", y | bc;
-    }
-
-    # --- Squaring ---
-
-    else if (op == "2") {
-      print x | out;
-      print x, "*", x | bc;
-    }
-
-    # --- Other operations ---
-
-    else {
-      y = r();
-      if (op == "-" && x < y) {
-       t = x; x = y; y = t;
-      }
-      print x | out;
-      print y | out;
-      print x, op, y | bc;
-    }
-
-    close(out);
-    close(bc);
-    if (rep)
-      print;
-  }
-
-  exit 0;
-}
diff --git a/tests/noekeon b/tests/noekeon
deleted file mode 100644 (file)
index c9ae935..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# $Id: noekeon,v 1.1 2001/05/08 22:17:42 mdw Exp $
-#
-# Test vectors for Noekeon
-
-noekeon {
-  00000000000000000000000000000000
-    00000000000000000000000000000000 ba6933819299c71699a99f08f678178b;
-  ffffffffffffffffffffffffffffffff
-    ffffffffffffffffffffffffffffffff 52f88a7b283c1f7bdf7b6faa5011c7d8;
-  ba6933819299c71699a99f08f678178b
-    52f88a7b283c1f7bdf7b6faa5011c7d8 5096f2bfc82ae6e2d9495515c277fa70;
-}
diff --git a/tests/pgen b/tests/pgen
deleted file mode 100644 (file)
index 6e78dee..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# Test vectors for prime number finder
-#
-# $Id: pgen,v 1.2 2001/06/16 13:20:46 mdw Exp $
-
-pgen {
-  2 2;
-  3 3;
-  245 251;
-
-  4294967295 4294967311;
-
-  # --- These can take a little while ---
-
-  498459898455435345676576789 498459898455435345676576793;
-  40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493525769 40831929843180254171317254073271577309351168965431122042755102715326515941762786951037109689522493526197;
-  166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520173 166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520257;
-}
-
-primep {
-  -5 0;
-  -1 0;
-  0 0;
-  1 0;
-  2 1;
-  3 1;
-  4 0;
-  40301809 1;
-  40301811 0;
-}
-
-primeiter {
-  0 2 3 5 7 11;
-  2 2 3 5 7 11;
-  3 3 5 7 11 13;
-  4 5 7 11 13 17;
-
-  2309 2309 2311 2333 2339 2341;
-  7878 7879 7883 7901 7907 7919;
-  7879 7879 7883 7901 7907 7919;
-}
diff --git a/tests/rc2 b/tests/rc2
deleted file mode 100644 (file)
index d6f9e74..0000000
--- a/tests/rc2
+++ /dev/null
@@ -1,15 +0,0 @@
-# Test vectors for RC2
-#
-# $Id: rc2,v 1.1 2000/06/17 12:11:49 mdw Exp $
-
-rc2 {
-   0000000000000000 63 0000000000000000 ebb773f993278eff;
-   ffffffffffffffff 64 ffffffffffffffff 278b27e42e2f0d49;
-   3000000000000000 64 1000000000000001 30649edf9be7d2c2;
-   88 64 0000000000000000 61a8a244adacccf0;
-   88bca90e90875a 64 0000000000000000 6ccf4308974c267f;
-   88bca90e90875a7f0f79c384627bafb2 64 0000000000000000 1a807d272bbe5db1;
-   88bca90e90875a7f0f79c384627bafb2 128 0000000000000000 2269552ab0f85ca6;
-   88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e 129
-   0000000000000000 5b78d3a43dfff1f1;
-}
diff --git a/tests/rc4 b/tests/rc4
deleted file mode 100644 (file)
index 374430d..0000000
--- a/tests/rc4
+++ /dev/null
@@ -1,28 +0,0 @@
-# Test vectors for RC4
-#
-# $Id: rc4,v 1.1 1999/09/03 08:41:14 mdw Exp $
-
-# --- Note about these test vectors ---
-#
-# These test vectors come from two places: the Usenet article confirming that
-# the alleged RC4 source is interoperable with the BSAFE version, and some
-# tests I performed with the RC4-in-a-signature Perl version.  Some testing
-# with the SSLeay version shows that for an all-zero key I'm compatible, but
-# with any other I'm not.  Since I pass the Usenet test vectors (which I
-# found in the SSLeay sources!), and I'm compatible with at least one other
-# implementation, I'm happy that I'm in the right here.
-
-rc4-encrypt {
-  0123456789abcdef     0123456789abcdef        75b7878099e0c596;
-  0123456789abcdef
-       010101010101010101010101010101010101010101
-       7595c3e6114a09780c4ad452338e1ffd9a1be9498f;
-}
-
-rc4-generate {
-  00                   0       de188941a3375d3a8a061e67576e926d;
-  01fe23dc45ba6798     0       643ded26ae29c15cda4f2b96d66baf2c;
-  08192a3b4c5d6e7f     1024    abb3a32a2ba4d409752923aa4032be16;
-  0123456789abcdef     0       7494c2e7104b0879;
-  ef012345             0       d6a141a7ec3c38dfbd61;
-}
diff --git a/tests/rc5 b/tests/rc5
deleted file mode 100644 (file)
index 340354f..0000000
--- a/tests/rc5
+++ /dev/null
@@ -1,17 +0,0 @@
-# Test vectors for RC5-32/12
-#
-# $Id: rc5,v 1.1 1999/09/03 08:41:14 mdw Exp $
-
-# --- Main cipher test vectors ---
-#
-# Taken from `The RC5 Encryption Algorithm' by Rivest.  Important: the
-# test vectors given in the paper are given as 32-bit words, not bytes, so
-# since RC5 is little-endian they need to be swapped here.
-
-rc5 {
-  00000000000000000000000000000000 0000000000000000 21a5dbee154b8f6d;
-  915f4619be41b2516355a50110a9ce91 21a5dbee154b8f6d f7c013ac5b2b8952;
-  783348e75aeb0f2fd7b169bb8dc16787 f7c013ac5b2b8952 2f42b3b70369fc92;
-  dc49db1375a5584f6485b413b5f12baf 2f42b3b70369fc92 65c178b284d197cc;
-  5269f149d41ba0152497574d7f153125 65c178b284d197cc eb44e415da319824;
-}
diff --git a/tests/rijndael192 b/tests/rijndael192
deleted file mode 100644 (file)
index 49898cb..0000000
+++ /dev/null
@@ -1,2886 +0,0 @@
-# $Id: rijndael192,v 1.2 2001/06/16 13:23:19 mdw Exp $
-#
-# Test vectors for Rijndael
-
-rijndael192 {
-  01000000000000000000000000000000
-       023a67f4591abd1dc00c5abebebe0397a3b347451ad3112d
-       7ff75c2eeefa7f368c8a8b4520696533bff5aba750f61004;
-  02000000000000000000000000000000
-       506a186359362e62a58444f018f882194d728766ca6ff976
-       6288af2dd607059b760ec2ae99287ff4f5f135350c6533b3;
-  04000000000000000000000000000000
-       ca5c42150025d70706f9df66c6a149878f99b02d80d24af6
-       2740c22885fa7f6979eed72c31254719f75097913d55d089;
-  08000000000000000000000000000000
-       03ebd2ad4e4c4b8767eef082e0671b8a40aa83205dd2cd7d
-       50d067dfe60008dcff6c8f6011a56b04297a0886b818fdb3;
-  10000000000000000000000000000000
-       c8b526b380f2b8ddf60ad4527b585b36bc886f915906f34a
-       ee2550dd5a911da2bb85424687b6d06e18607d9800822a8b;
-  20000000000000000000000000000000
-       b5fe0634f8cc42cad26dd7448ed44288ff054435747606ac
-       fabc0ae4d9eb26ed89375f1e24215540b37d106c3f4429b3;
-  40000000000000000000000000000000
-       2a8b55370b58585cd5c545065c1236876c25f7227043f697
-       9a2efe9a23f99898519dfc86bd82ac51311356e96a744e4c;
-  80000000000000000000000000000000
-       225d2952c570bd85c57b60bdf0d7813cee77f88eb94b9fe0
-       66391730c52594f80fdf06e5da751aad9613767c8a7dbc12;
-  00010000000000000000000000000000
-       4ebb41c4aeee673f8a24dca03806b456d7f0371f59ad215d
-       e20e4d661c9411afca8208e71c2245954316b17d355cc87f;
-  00020000000000000000000000000000
-       1ece0d84de9d85f599c043e81ed0d0788b0300dc720806f1
-       8b58730dc35a5b8b679a38662163bbf61f4bcb963d67c0c9;
-  00040000000000000000000000000000
-       0acbe6c5eb0b944562a37976acdeaaa343d28c1023805af2
-       77ab5a554203d92b600fe57510c081be22d9a0474158fa0c;
-  00080000000000000000000000000000
-       41be3904653a1575e5b06c44aea5d2136df8f9ccd7f42897
-       84ddaa529a9e0c24bb4437fd7c59d126e9f3a2fd144747a8;
-  00100000000000000000000000000000
-       1f64e3968eecb4f75248981ee4afe469df2506d85373244e
-       c0e3387b78dc708656ce32cb56ba8f3a7481db57b2e2f31c;
-  00200000000000000000000000000000
-       4aa4faa759d8ae50e22eb0c8d9a35a5ac45d8c321e7945a8
-       f912da323759360ab2a17b8903a3995ba1fd286b4f5c0428;
-  00400000000000000000000000000000
-       ef444349c97db6ced680f42fb6c5be12b6093315d9735c99
-       a8e88259daf069ab83caf0827dd8a70aec60763343f1d5e8;
-  00800000000000000000000000000000
-       52d311d50f4b8dadb35e14061d24b77128f5fd8f1a4408cc
-       830b1649d46496e4e3379c6af09ef3a2db387234e20e0f8a;
-  00000100000000000000000000000000
-       e7bcd07378c8fa7412cdca4747b825586c1d1db42cb9e3f5
-       f646e68c39285ce45d564195ab947cef8f842e83a0039311;
-  00000200000000000000000000000000
-       2d6f4c9d74fa658286d89ac21a293b0dbfa23a8b5509d22f
-       ecab2eb6d811c3c5cbb7ca9697039c0183deba100bd857ef;
-  00000400000000000000000000000000
-       553847fabc37d17234bd17f7d9306530bf778143642aaf86
-       6b4c872d23f5e2055dd7b7dfb5e4b7e9e2ca030a4248d033;
-  00000800000000000000000000000000
-       940ab6a034bee50736899c4d635156aca5417be2643202a6
-       7518c4af96fa52e3c0b00b874d394c4aa633d0cba04ef54c;
-  00001000000000000000000000000000
-       fac2d9c5408abd20b4cb620b4e9ae56f94d5c4a1d5875dd1
-       cb766e2a037a343083229141d004ba100c4f33de8e064961;
-  00002000000000000000000000000000
-       b4e037145cfe062329702825eef3c0187602e7c81b196d01
-       f307dab2d4b0c4e95024e95bf869da3759038799142e7a4e;
-  00004000000000000000000000000000
-       faf4093cecf9b49b79ac867cb8eb254f4e6b1cdc0fa8d2e1
-       c5a7383e7e51e02872407a34099bffbd43e2369e5b3c4bfb;
-  00008000000000000000000000000000
-       13226b07eb7e44d65c4eac727e788fc246c71b7877150716
-       74cd36201eb1e07da6d7f7a922fb4cc9bb76e13b1f770fbe;
-  00000001000000000000000000000000
-       a4d115e01be2e296dc61104749f5cf13e1b0660b619901da
-       6cd992b789f2e6bcae1fc4c54e31983a91cfe80221065d45;
-  00000002000000000000000000000000
-       c177c0361498f3b8162b8a1e4791d393c90f9be62af73a0d
-       8fea60d9cc0b31580e42a55bf633d926458eab2269e284c3;
-  00000004000000000000000000000000
-       b3fa237d5af3b8b030559f59b22394b94d8b71fe7c499896
-       090181d182605dc6d04734312631193af9ba97a41e36cd6d;
-  00000008000000000000000000000000
-       d43a7d6e1c6e6bd70ddf057df51171968f135cc628c87aee
-       a83d729f48beaad53c4703edf669cc3b8172b1f3815826ea;
-  00000010000000000000000000000000
-       d4a801587858558d74174ec9bf5af46357cb6b509c1cd3c6
-       3c8d553aad2e9e9b57012b8b624864282605a202e770988b;
-  00000020000000000000000000000000
-       a244142ed94451165b1b284659dd09bf19522d8ede74fa50
-       56a4918a03a03e7522287f2697058a5a4568ee1044abb7a5;
-  00000040000000000000000000000000
-       256c7215a7a1f6277efd963ac44f273a67331722a35733a6
-       772bad0f5ba9b17a70db868fa6c94e894332da2be4188990;
-  00000080000000000000000000000000
-       0180a9b501ffa92c8d82f9a6841762c0a999f075374ba5ed
-       b2866da4615cd4dc433537c2946f8892b44f3bd0b2c4dd72;
-  00000000010000000000000000000000
-       74094fb2efc7ad295a4e59e6f3cc4bca98f9ca9426f1dc7d
-       66e1d8c5b64590a10887d4f30d593e21a988ccc2cb0c56f3;
-  00000000020000000000000000000000
-       e0f2350c0bc86af716d0e3a4a43f7226642e41247cc365a8
-       47a078702ce531d10d0ee151761fbba5e8b62354fa78b6f2;
-  00000000040000000000000000000000
-       422af1fef9c1b8c8a0ef3b62abb1318556ed6fc1f66a9d87
-       b334db883014ca79f7822e91203840185153bb845171cf62;
-  00000000080000000000000000000000
-       94112b3e064fbe4658252cd678a689e30989d9801f8026bc
-       9960c684f52a14396a807b1457b55a6e8805adbd2cad3ea7;
-  00000000100000000000000000000000
-       9cdaf684882ddd6dc44fa74b080f6a3b63fa4ddf2a8708f2
-       9640e06263fcdc7f42e8364b6832202026b715b1d604802b;
-  00000000200000000000000000000000
-       c138345c90c2823c192bb0a347baa310068951f512554d95
-       f0b31139a5e0d808349a5897341ceab6d1c92ad0db7efa56;
-  00000000400000000000000000000000
-       8ea80f74f49292759317b0b4a1bd488edc883616c04c8920
-       3e2a07a682bf608ec4f94faaac7049323435e17bdf8ce8bf;
-  00000000800000000000000000000000
-       d170aa41a6e50b8b2738de41f189cf9991eaade3dbd5dec5
-       4b0901022f4449e5fca714fb4a08524c0b33632a704ed726;
-  00000000000100000000000000000000
-       9a308261c52d829caacc1b70eb47049a598a4702e22aad0a
-       0bcd79778982f5797fb92d16d7e772e624a65e15dde0dcee;
-  00000000000200000000000000000000
-       40cff4c8c86429193aa94de96b2719a99f60cbca577980f5
-       47ed4c47df14c5a14290faf23855088bb0fd75d8f209f276;
-  00000000000400000000000000000000
-       ba4d0f077f721f3939f1389d44a86fcd7f2591b94c9e9080
-       adf066342c154cf5c2fb2609be3126b1bfa8098d8be8f1c4;
-  00000000000800000000000000000000
-       4c635236910df9d5d1a6ed65c7252a72fb20a716bb64d9b8
-       ee98a1c2c6a9c9590f626f4b7f685c8575da477a356d557b;
-  00000000001000000000000000000000
-       fd3fb55926f16ac3c458669f23a4647fb771ccaa49cafb4b
-       c3757d955b8944c8dfb62e77cf643f6d8b58261916aec7b6;
-  00000000002000000000000000000000
-       ab5289cafd68c2bd7facced12251962f7be2b30a99945c9f
-       92f2d77a9f0dd409bf737cda459d7d3dce6e407dba592858;
-  00000000004000000000000000000000
-       050c239f2157e5355525ffe4557e54b2c8838a68899707cf
-       c3317fdb7edf02d7b43ff293346977da2a22108748574302;
-  00000000008000000000000000000000
-       287c55a9636fd7123dd9851cf5c27c73f3f3a165a4b5ab31
-       ef8d185840b9f6f057792cecc2880366dbee7e5b56a38fd5;
-  00000000000001000000000000000000
-       cc76fb5b7e8316d4c74e1df3f913139e739d9f30e0e320b9
-       9dd58b054a33098f0228bc6b05712e9c7a50add7868a2f96;
-  00000000000002000000000000000000
-       aa21dae2afdb95ad368f9c1babf2769407cb6d7975d41257
-       3591625006cb3c2bda175be3f715a6ed63d59261a3182f5d;
-  00000000000004000000000000000000
-       8cc0d35698def74ded8c1d8222b67e543af62f9627978c80
-       4829e5802b83b5614b58d68305aa94f06aaf37a0c0c4ed5e;
-  00000000000008000000000000000000
-       da702b5e9b3c7ce13681b3e1a38ae1babd06a0ba46612f63
-       9d162f4850b8b4e4b1a01213138c1f22c863e32c12539a87;
-  00000000000010000000000000000000
-       486599f86813923735d14c4308f142eb8a57086a8507255b
-       40b857e962dfe1f9d1dd46b69ab4f5ff7faf34b407623c3c;
-  00000000000020000000000000000000
-       82f7da5f0379e2cb4e3b58a03ca3de256b282dce73285090
-       1bf3d369ccd413ad0f95a1928715fb8ed55aeb2e9d93f2cc;
-  00000000000040000000000000000000
-       3a2ccdf7ca733ef507a485ab20c62cf6fb13cd1281008b49
-       335d30e28232b4bc1dff9de3a4a9faebd4b5accc3cd2eac6;
-  00000000000080000000000000000000
-       5129bfb136556242d24c0a69d1b471e39bef4502dcc6ab63
-       0e7f709d8e65ecdeccf0f8f51e1eadd4deb33218ca96133d;
-  00000000000000010000000000000000
-       bb55b9b172f5102a71d27564fb441ad75ef525e3c7b95569
-       2fe4ac5360626eff86d72d472cff3428f0891f2e708c1fc0;
-  00000000000000020000000000000000
-       29e121d9d060b4cb1a8b985514642d2ae657d1bee74622af
-       330a0002c3bb7bdd1141085283a2390d50b992667e9c7a2e;
-  00000000000000040000000000000000
-       1eab5cf16eaed7787fdca7a4a13f02e89e838e28fee07574
-       f351daecc945e7f4fb609f83b30f4a5f96d8d453770235a1;
-  00000000000000080000000000000000
-       1d1c207423b291e4faa33ba5511d99fa0a1d6217dfb01503
-       f8d4232565a6ec23973b2814fe0d4b0d795df4afb24646bc;
-  00000000000000100000000000000000
-       428cd893c5c48447e67a5a78ced4e75b9424d26162396397
-       df261879c0edbb80b244a8f95c319bd2f09db2fd24e46664;
-  00000000000000200000000000000000
-       d559589331a70000a25b0bdcc69edfadacca1a42e26858c8
-       408b5610b79984e6b95c48b6b370c670b054a7f4218bf388;
-  00000000000000400000000000000000
-       4b3ae76b7fd6acc18a44eb946daa6bb70d58086904f61243
-       926965c763cbb68699d3e77aa76acebff7be816b27cdae87;
-  00000000000000800000000000000000
-       c5fb0e875cc5f0d3b8e3056be3c1fef7cb653c2d357de33f
-       acad4ba4b859549071b491f07e7f90d50ff1e9aaf9d4c566;
-  00000000000000000100000000000000
-       50f32b167426251526e8f63bab0d615e016e03058902fe4f
-       e899b8984e8f6e7203c364181d89439c3bac8e60914d5644;
-  00000000000000000200000000000000
-       54418fd49d84a2e725f99459c10454af6e408b945e108275
-       cbda143f3ee4dab705f1a91bc941054ffd0ad144d50368b7;
-  00000000000000000400000000000000
-       6117166e773302a1b3d21e869407c18a13655033d5ca007b
-       bbb97e4178dbe65c25ec8002b53ef7932c4ae1cfb947918c;
-  00000000000000000800000000000000
-       f89ddf74283be908896c62bc18feaa8d305e9ae4278233ce
-       2089a78434cf69651c06cf00dbe89bb6b446e4f3db6ce8e5;
-  00000000000000001000000000000000
-       03af049da485a4b4ddb468bf3261c38aad2a71c96f990a22
-       46146187446746bbf8dcc71cb5c583506244c1468a015144;
-  00000000000000002000000000000000
-       aa70df415bd87335969b4fb3c363529061a3da319ef2d890
-       a63e67308c4b7f2b33f279bee222a9869446c8c0c250cf06;
-  00000000000000004000000000000000
-       dad7d93b5a7bff63476de8b3d20190a29f28eecc88495d3d
-       9839a4942c8f69283e91eca22ffd198a4a79e68ec07e578f;
-  00000000000000008000000000000000
-       59d603166b649e9be642bd3ccbc03f7d9abb3e89aaf0f1c6
-       8686e6909dcd9f787f9fa180a46d1d433bf2721a238faab1;
-  00000000000000000001000000000000
-       7bb6311899138ae33f095f79487a8c1ff8efc0a1ba1c0844
-       69e02af433d3d1234a315658f80f6dbad8339e77b894a3bf;
-  00000000000000000002000000000000
-       27112725333fed86f93b09ac882e54cc2c625de0970a56c0
-       d840315b675f117468782d16dd143961e972a62733ab5b12;
-  00000000000000000004000000000000
-       798b2230146a75a46854e26ed0cb07419e79ac176059f223
-       f543a2dffe039126eacbb3c5253d3e0656df5886aa7dc934;
-  00000000000000000008000000000000
-       fdf295ab966e035dc8d9c6a7d378aa1fed50f85e09afc9fd
-       1e353b843bfdfb8e04196ebc2a2fba0e6ac7651aec3034a8;
-  00000000000000000010000000000000
-       4b9bb076f6e3b227ff27210398252df65e9e2fe255b13992
-       e42c1d4b04422a38c1dc7a4bc241ee1f4b9aa5a2aa42047e;
-  00000000000000000020000000000000
-       f45fa1b841562f0d20769390f1dafd13324bf86216565f5e
-       7e96c285bffe97be47ea277140b179e92daa6a13647905b4;
-  00000000000000000040000000000000
-       de745e5baa6ac8a095898d562c187de0064d23c9b748a115
-       10cf435b1841a119ef753a471f57261af2d137b2eef59c81;
-  00000000000000000080000000000000
-       ca3c51b2670418b4ec09ffce8f626bbe891b266446f89853
-       fb5c6a49a40e79c468ae275331230e37f5e47c3a10159d58;
-  00000000000000000000010000000000
-       0a9529d7ca30fca5081c364376c766fa5cb0a488bff9f638
-       149db4dddd0c11aef1e7ffe76286351b2212a17771bb3bba;
-  00000000000000000000020000000000
-       ac80ed034867425e0482cd34ee6666ff8ed09cad5901c0c9
-       3a4cc4d2888134ad2d77ef262a222c79b66d93226209e6ec;
-  00000000000000000000040000000000
-       c01846df500d6d9da7755fee30847e2b6e5ef2af29fb768d
-       234eee5672c9964bfaeff3d7612ad7796d52630dc86bca96;
-  00000000000000000000080000000000
-       c15f53accfc0d88ab029139dd65019fa6003b7afe2bd4e54
-       a0d7bfcdeb22254d8ea42219368656569742324922a9ee6d;
-  00000000000000000000100000000000
-       ff213f49aee42eac2aa72d7a29e7ab41aa7f586012e9f97f
-       f17c2e5990d08495dc94764f8e85c51851a4f413b581584c;
-  00000000000000000000200000000000
-       25cae6c9325a23f04d3f14e8c2c2d2e7cf47f4245a813568
-       e2f0783438ad7bd9a4f84b1b3a895c05714c514dac819bb1;
-  00000000000000000000400000000000
-       22870931c60c3752f5eb3408f4f4f311ecc94d45746334b3
-       6b62d15ad6d4d9a0bcf4f718fa02fcd154922ae0eabb53ba;
-  00000000000000000000800000000000
-       c08edd588aefb0162ed5a83866b4125c4763187fa2c3a0ec
-       06c5641d79eb161bac7db67e4563298fb255ba9d19795081;
-  00000000000000000000000100000000
-       a27d1bf8dd539451b9c1be660a658551358e0d5e24afc3b9
-       7676d1200c042937af0775b682b8a079e537e09ed0aa4683;
-  00000000000000000000000200000000
-       985703a552bf2ef0f0b13cdfdcea1b5f0e8aa26dd0a2df73
-       7c2f3cd5a37195e38378625ba3dcc0331b5f541a8ab99782;
-  00000000000000000000000400000000
-       6ec0cf3e2eebe473928c8816aacafa30697d2f1886216355
-       74cd8be145dae8057f60216a73c5facedb9f4e82e0bd65cb;
-  00000000000000000000000800000000
-       616f098bebcbf2ed4b706c97bf2515c3b0816deb15de4059
-       d15e35c97769885b1a3d35e8e1fe85b693ec2c8744417bfa;
-  00000000000000000000001000000000
-       e8dd7dbcf07d102c7eaaade8d9024829251e934d0da9d7aa
-       e3999556264744496ad4d86d445457888419bbe8871d7b4d;
-  00000000000000000000002000000000
-       1fa50547af8d9f2d55028008536f066753c17fc8e2d44057
-       4acb79c912d344fae3419ef5700aa6a3d883184f34e5d59e;
-  00000000000000000000004000000000
-       92eeebbe20902b4c0a5f890399c32c243e89d8ed91332e3e
-       e46625fbad57eb9c626e2125cf248e269332527015dcd3e3;
-  00000000000000000000008000000000
-       cdbf15c739d3fc86f9420eedf6a0956502a4a733217102f4
-       81c056e8176355317af92ba38e40fd5c26f907b285f840ea;
-  00000000000000000000000001000000
-       2d349f3bd80ff88f4eee644682b62fd1eb719b9c81b816f6
-       9d44dd091630b3772cb94b8c652a15df0474881371f0b04e;
-  00000000000000000000000002000000
-       6c53dac01503d4ea8e2da6e54403fd20c1f5a1f967732cde
-       4c17e967bb54e474f3e323d4f0e18ce40e44ea61c2338cd4;
-  00000000000000000000000004000000
-       1991e580e4801fc43a1aaef646626306f5b86f93bc114393
-       7237846ab5e292d29a7f115d0b10530720a1d5ea7c5aedf2;
-  00000000000000000000000008000000
-       89c2a0916aaf1f36b54c0ac5f74a2cf7ae2d151e9ba39b22
-       fdb640c3275ac44815c50f2d872e28060501598e7e9947ea;
-  00000000000000000000000010000000
-       5c052c84dea984ffd5703103883523da2208e3bfa1e06649
-       5e97c772783c94a50d288284afa25295f877e5c29d174529;
-  00000000000000000000000020000000
-       89dd0a9f15abb0e943d4bd0eb37e9280cb046c88999a5f14
-       b8979c6cd28d05d20e4b3ea5ef472ae7d62a2470014f6e7c;
-  00000000000000000000000040000000
-       fe7ded8a12dcd5bae797cc30cd0596052ef5a56c0924f199
-       30272a00835e69223739d31e66a87ee9810c3181cafa4c5a;
-  00000000000000000000000080000000
-       5a856f3220f42525eb711f1895eb09403fddbebfff60851a
-       ac07c9e6190701a516d89034e9af0229a2ea8bd42ec699aa;
-  00000000000000000000000000010000
-       ae67448d9fc57e487a4bab448208035dc06ffae8b5e9e8f4
-       693ce9e015e6f445bab0613cf858e152baf438c76bea9239;
-  00000000000000000000000000020000
-       349b4b3daff60002fead10f7f11f1ba69a7142c2256214a3
-       b24cef9c0a98b607339f148be6af519555fdb8d59237e06f;
-  00000000000000000000000000040000
-       0d3724d48fbd0b053b9594042107bd4b91bdcd98a6fa14f9
-       ac041956dca2caab9d5e40d344a5ff2e02e48cc638be7058;
-  00000000000000000000000000080000
-       29bb7572498bf205d1939c754ba87e3a4f1a2c866bff4377
-       c2b627375f0020f1e01df599ccd0c9afef8f72f2fc8c432c;
-  00000000000000000000000000100000
-       79898e51f8e2ff9303d2eaf1c113d4be2d7fd73c4f29c1d4
-       02ff562fdf5ba2e325a7daa8e77485d261bf798a70562492;
-  00000000000000000000000000200000
-       91ab2704db9e0cb20236885aa1812677767f29887a3825f9
-       945703d5a2ed4c7fbc46641a86b1c4ae52e2b6ae86370b7e;
-  00000000000000000000000000400000
-       d15999107c2747d3df7e21240b729cafaf32e45ff2e2eb94
-       0621fbacd6f9e17748a251d9ce0f6279c0b4f76de76ca07a;
-  00000000000000000000000000800000
-       3022e256e1700e1b38860e08860de7ee7011a471744c4a28
-       5d0cea63850c605346b1bbde1277bd04e9a7ea67dcb95a0c;
-  00000000000000000000000000000100
-       c41bad6d44d9b3ddb77289d0bc75728ea32d21174989429d
-       daf7d221677be4c01c524941b43a6583b736f59485c37f9e;
-  00000000000000000000000000000200
-       c244e345c8771efc91cf85737fbbe0e7f9fe1ad53727bda8
-       0e45be68828f5dbe2cec1eb6631dd455f9f742ec1c6d5734;
-  00000000000000000000000000000400
-       ea91f3b274796e1a463d3263acf96d8192c927d1fa66b022
-       53a6eb98500423e77e4a17fe1e936500a3411d9d194ee941;
-  00000000000000000000000000000800
-       b955548cb651e31e94102068eccd141d55333cbb3e34946d
-       07af2dbc8c097871dd3ceabb8645a164f445226eac474927;
-  00000000000000000000000000001000
-       7f7864177e868e5e4a07a99252eadd43b0529bf5b9b05013
-       2746566baca5f019ff0eea70d3eb82278398c9e9926c3883;
-  00000000000000000000000000002000
-       55cafc87e6ce1e903805d23153711dc8c7e8d269e19be3eb
-       7946dffc2d8ab6a40a397f81eedb2568c6df9f0b06391d82;
-  00000000000000000000000000004000
-       95bd56e986ab583193786c37328d4dde20e62b0d39c19b9c
-       1f261cbca6aa0875c3b610990236178251d2865b5033ea5f;
-  00000000000000000000000000008000
-       21b185e2c61a750a4dbc47d1af6cf3b47f56ceb362d785b5
-       ce8b0dd60ba2d9b6e2582aa6b262cdc674d96848a67641fe;
-  00000000000000000000000000000001
-       e7d5e316da3127f89538a3b2d24e5f7e8006557dcb03b5e5
-       d41ee11b4115c2e2155c0bc35b31d8c38e2282d17ef5ab4b;
-  00000000000000000000000000000002
-       dc4a61888202b8e52a97af475726e545372aa67912ca8cb1
-       c4c595fbf14bd2e4f55acff059c17c243ebbb6e979713bd0;
-  00000000000000000000000000000004
-       c4306af68bbe3af8b223151aa99c94488c8107fbfdd3b680
-       d15a72460ab5a62385c5db730fce1ddd02ca531d250b114d;
-  00000000000000000000000000000008
-       5c33a8ad6ca05fc247427b898126e4ab9fd05ed334e14c68
-       8f887594d5f3a14aba879167d605d2ca84abd2aa60ca85dc;
-  00000000000000000000000000000010
-       d8abe4455e58859d84b0594f2804f77f15ad38887e29d705
-       407f2f3751880efd85de8ba315f222712df2674f20c9baa4;
-  00000000000000000000000000000020
-       20b5cc79b89b41aaef175caf0975d6d8f2be320075b8cfbc
-       6b366acae30d75bf715a67703cf61e349229015e3587ec05;
-  00000000000000000000000000000040
-       3cb706cb93bc33a1fe6b1a68c9c902d187b6c57abee350dc
-       a1d213280eb276238acf137f2ef7b15216b571f42c9dce58;
-  00000000000000000000000000000080
-       7654351a040718ddd3d7fb2cd9af802c17e7db0e7a6cfaf5
-       ee3058937fc02624cc4ec6d19a7c8d3a655c6e8fc8c12622;
-  0100000000000000000000000000000000000000
-       d0b1960db19a85a7a77e46229b9f985139829c3aa120c3ae
-       c642be9d84e9f449586f6329a6d0783aafc5b9a71d5fdfcf;
-  0200000000000000000000000000000000000000
-       fbed0648eebac5ad6af9c89f04c759f5b3caaaf2fc77b33a
-       e2f666ffea4b816c59587f2cc5c4007a6e797c66c20d454d;
-  0400000000000000000000000000000000000000
-       c5310bb95af7c9a72af7fe845bcfc5944f98606f21d7d414
-       91ddc7e0d5626d0929262a339e488e7b80b59c748b99d96d;
-  0800000000000000000000000000000000000000
-       2c22bb4931178c38b575e8a697e774f4b6cc49163b4fc863
-       a29c3dfc98b1061718a8b858b582badd3565354c7dfa11e4;
-  1000000000000000000000000000000000000000
-       004b667ecd93b6cf8120b4d13f63cc8676f25669cfd54198
-       e61ac997edc61a530e21d3fa92597765bf8088eeb044378b;
-  2000000000000000000000000000000000000000
-       cac87cd9c6a8336a855d7fa479a41348615befe661bccd5f
-       3c4de80c174170a85b453b0245b40090c62d7c733e691cd3;
-  4000000000000000000000000000000000000000
-       271170c80822719aa7abc308af71bff47220c9c0e1d0af10
-       6adc1a35f39600a3ded1dfa8db6f54d06975f3df17410963;
-  8000000000000000000000000000000000000000
-       c799a3e1f803ebf7674e82af4e130a1edb80fff06b36913e
-       5255a39bc0b3903213e8af99c129481a1a91546435a0b9f4;
-  0001000000000000000000000000000000000000
-       7f5dd7178fc11e33e75039cd3b31c3ba715669a2d97fd67d
-       ea9f8cfdfbf79ffc004244db67a186188761b94dcb680ede;
-  0002000000000000000000000000000000000000
-       890342e3bab9d5c12af0eb1147adf72ced3c858a36666765
-       fb317078fc5a6f72cd05ed99754244c1d832bce05b495ce9;
-  0004000000000000000000000000000000000000
-       4dc89624333568e75ad013d4777641293110c8293a4564eb
-       5c215202bce7ac289462ee973b208517a100effc3f045037;
-  0008000000000000000000000000000000000000
-       eb39a4f0a41388595563ca25220d2ba33e8827e6886dee50
-       6c3cbd45e11b03f217232c6e8f412b2d45626fcbecbbd046;
-  0010000000000000000000000000000000000000
-       c3768a3a08cde5986f31f19adeb5637c2517e4b793e75c8e
-       e16c0fd6a2460933f758b736979efb34a9c35df0b58c290c;
-  0020000000000000000000000000000000000000
-       c4ad863e851697c80ed0607192c54debcf7c66fa38c4a4af
-       7907d69fb955ab18bf7c198454c6d8d15e4226b08e322ad6;
-  0040000000000000000000000000000000000000
-       d2090fd250ba63f3a708140e11ef64f8afcff45dc70cef3f
-       dd4c891a83c86dd31eb4973dd3948a94d1fbbe6f03fc26c6;
-  0080000000000000000000000000000000000000
-       110a9f65db98d165f6d71f8350ab602f4b2039e162744741
-       54d10329bfcb29cd51fbcabda51e28a5d2009694353a43f6;
-  0000010000000000000000000000000000000000
-       a8c1ba8a548e6f3ed996445f62845dcc078495a6cf9739cc
-       6a2fe74b53328830ba707a56c80935b74dec32a312c5f6f2;
-  0000020000000000000000000000000000000000
-       94c0028f97319ac431e83414b6c660939b11047f310854b7
-       46a1a901558c6bbb0f8be8662095454d9decbcfa416557da;
-  0000040000000000000000000000000000000000
-       cb4c1feaab04ab5a6bd70259afafd3bee103ec9f90a5150a
-       270e073e9de7d0f5c887b62093e705b6457d0eb070b3c68b;
-  0000080000000000000000000000000000000000
-       b9d1993a3ea9b0f635d37edcb4c5ce7bdaccf5be5cb7bf02
-       8400b07b3cb30c941e468274b10c77ba3d853c418c2efa15;
-  0000100000000000000000000000000000000000
-       b4ab6fb85ee6b43cf76adc45644eecee472abcdad771604d
-       97133160d397d761ded692085318c15285392e4887563703;
-  0000200000000000000000000000000000000000
-       7367a4de601e0bf5244fb989a03fc80ed93d3141424b9477
-       c3085f4757b45152825ea9197538a5797bb15b374231992b;
-  0000400000000000000000000000000000000000
-       8e97f0e67b27ace30dc30a4ae45670c1378dc2b5bbe12400
-       c9a494ceb0d7e51eefc737a9ca0e8af490be4e6a5ed1ce6b;
-  0000800000000000000000000000000000000000
-       2713deee079aabbabc432a62e260b8d9291e98595dc86623
-       e6ef22a2af39e8cc4415dcf216b7a998b98a7d240e2c3e07;
-  0000000100000000000000000000000000000000
-       3dfd7ba2b48e4ffd7c0885552dbab3133c2757683fd817a9
-       7e98b7592893cf2253c1b393e5dacbb233dc803589421eaf;
-  0000000200000000000000000000000000000000
-       2ea177197993e7c293ce7a59bd3deef17485c206dd19195d
-       f1758101cddd487e37c8e5b179cc2d90f15adaa047c61a90;
-  0000000400000000000000000000000000000000
-       8fb6036b6580c04c433fb07d0760fef91bba85272739c0c0
-       11c2bc53cfc7fde6fdccefe4f20dba513c465b092194a3a4;
-  0000000800000000000000000000000000000000
-       703784863ff9e7e3c09fa9bf128ea31dbd2b8b4f5cb99e36
-       936d221d1f0c14b6f01cb3028873895e5b24d16f0031ab8f;
-  0000001000000000000000000000000000000000
-       5a69ea7cc7fa7302fcbd1ac2d07dc7c6621ee0aff1d018a4
-       41c2343b468dcccc3ccfda966cc9ba78d8d57083ae27f29a;
-  0000002000000000000000000000000000000000
-       c89944b86c5edf216c8a8f8e58eb307bd311e11e66ee4ebe
-       b38dc49125243cc11781df4559f9d84640a7338403236c85;
-  0000004000000000000000000000000000000000
-       3c669450967f16dda82835eaa8cd3877fa8de68ddd5c59b1
-       278e188e35f3c26eb8bff5c03a5b266f0f51aaa4a603081d;
-  0000008000000000000000000000000000000000
-       9823a5e5bdb3ca2edc47618be7ba9ca742d5f0d2198047d3
-       21a333410512108c86dc7950ab1abe701a9e3d856e6d9269;
-  0000000001000000000000000000000000000000
-       981fa376decb5e95a92b842e2dee03c562d8ebde0c8d6cc6
-       370eb81d50ef15a799ca481521a24966d033da29486007cd;
-  0000000002000000000000000000000000000000
-       44b698fa4f4f6bf89fc66a23abb6145d9713908bb03705d5
-       fe70a9986d13fbf73500352f742708a29eba0f80d324843d;
-  0000000004000000000000000000000000000000
-       fee1b9fad13700816390e29880a83233e7b90cf183cd3527
-       0c8ab7fceeeb439397c095de04ae56eb867499360c6033ab;
-  0000000008000000000000000000000000000000
-       31defe3570475738ce89f436ab737800c6a59fce561372b7
-       d78ea1624b5ed5cce49a46ead9237bbb48b90327db11c74f;
-  0000000010000000000000000000000000000000
-       652a17e6b330a95d8237cfa2356e47c295585ba7666fd7f4
-       f85f595cc857f48461b889a0ca7f6245866e45946f5c8522;
-  0000000020000000000000000000000000000000
-       a658d408b3856df66df0e5026173ae70627a649b836c5011
-       38ccb2e915fdfa02fdc9b19a8fa446b538559c6d74af7f97;
-  0000000040000000000000000000000000000000
-       84ce7b3fab5d81b85e00681ed7b2ea130c53e405233408f6
-       92d8342bebfc338cec2bb424174d7951ce2ad5407211a53a;
-  0000000080000000000000000000000000000000
-       17a24739d92ed5f4f09f886a435af20a3f786bceeb86293c
-       f51ef9e9d4841d25699f1199bf1b66d3f54e1e1b91e91482;
-  0000000000010000000000000000000000000000
-       eaa616b384519b85852137c3f4ee61b6b48a2eba21d566d9
-       9e58a0b7cb6d0872f9882cb52abf91ccd7978367ff6228e9;
-  0000000000020000000000000000000000000000
-       ebd576de80da794a234a8be925c69e88bede65f64d7225bb
-       aede5cc115eff89d20b3ecde8d4e03a7935d368c20c837c4;
-  0000000000040000000000000000000000000000
-       4090b3588edef6e689399495eea36b33fb23104527e353ed
-       5295d7a3f7ec90d084282a1a0eb82d6cff90ac2a25f6d3db;
-  0000000000080000000000000000000000000000
-       947b834b466d2f3d92ef9512c3e450f0b578e9ac3be212e7
-       eff671d27f5e2af474962fa0f66b63276b24e484c66be17b;
-  0000000000100000000000000000000000000000
-       e611b6a6801fdb802ba7499c39a966bbd8b8410f79ddfada
-       357c82dda476be8ad41b40e2269ad52baa9d806c2143f84c;
-  0000000000200000000000000000000000000000
-       86e67d84b15f9f40a0fff739679044f91b0ed0376a1095ad
-       d72da9a06dc17ce4fcb24d51b804262513573c799a57b130;
-  0000000000400000000000000000000000000000
-       c19000056d359565e51b7a3de313c57ff2bb35d76393acc4
-       e5bd4cbffd461144135051d8555128786a9e106d063a6993;
-  0000000000800000000000000000000000000000
-       2570f1f193ad3a0d2314158dd137347dd99690a6b886bc5c
-       0146f5cc2c6b14652e8aa52d1c4733ba5e367a57109c5bf4;
-  0000000000000100000000000000000000000000
-       7526b9f746fbf4396e5663ba52f5bfa682b0501fbd36b5bc
-       107ae0fa5444fec8cc7d0f01eafa3eb0fffd7c34ac6869bd;
-  0000000000000200000000000000000000000000
-       abbd3dbd4a1864fc20f7226f563a7f5098ff273cc8bf6576
-       fd12b3b1749e8469a8ec879560b583e2dd88784db4c25879;
-  0000000000000400000000000000000000000000
-       e281a5fd1b6a7aaeef32e40482d6291aa697cffa21dc27a9
-       0cef0579d12fdce29f96f135be671012502db1f95a55f8f0;
-  0000000000000800000000000000000000000000
-       abff457652774b07fdc99738bac8ec162a01b73f8a71b126
-       970ff7ab84f483c9f1e73567d7f38163363b14850fad8834;
-  0000000000001000000000000000000000000000
-       1d75fbd8451f22a0b0a4a9c62ac6a5716511600bc76e8378
-       6be81dfd6a58e989c4a7d5f1f8fa22f36b079894564434e8;
-  0000000000002000000000000000000000000000
-       362b88b73e2cd980d5d78d3b7c591fa0b1e70a9ed5eba7a5
-       7f3c71fecac4105cee4c489c01f975a232402c4635b515fa;
-  0000000000004000000000000000000000000000
-       a76d84d4eeb86444c3a948c0a798b9dd2778a96e30e61aba
-       992557baa0a7dd9a06007681153f98f02c19d6de76d898fd;
-  0000000000008000000000000000000000000000
-       667c962b1ba89807b086fa168e80aeee355e825176e212eb
-       785d4ed06bcdb3f0fd2cb716ee9a1a3c462fc9b51e305082;
-  0000000000000001000000000000000000000000
-       c0ce233a95f06506ecc20c9d94ec5c6c757b4c5b0727d492
-       157a5a7d1e8e91495bba18085d26338a3b1463d4e9db858e;
-  0000000000000002000000000000000000000000
-       85b69eb5d5b732a8bb0b1a9b3693116f983675785aedff22
-       c6fea81b9347c9e7567fbad82d5b8912bbb76dba8f4a29d8;
-  0000000000000004000000000000000000000000
-       2795aa156ddfa00c39642ab05e286c964ed00633bd60c5f6
-       b7aedfef19724e4782a10536428547040ff7f59c8767f2d3;
-  0000000000000008000000000000000000000000
-       86a2b6fb19ca72c2958a6569aaabc0d7d1f2d7dcd2b5b61e
-       39130045632a3ee79eca91f2f29056c887192ce4436614ad;
-  0000000000000010000000000000000000000000
-       38a0281fc43a1c8719f255c575a9b1dea32a4c81e2d4a934
-       24a434c2d65df7b788bf3bf0664a22928ce07df667017502;
-  0000000000000020000000000000000000000000
-       8c8bd4434261667e10c6e5527640e4be2fd50112c27604a4
-       95c7dc7d90348e480db9cef4b640dbc62f4bd76714cbdca5;
-  0000000000000040000000000000000000000000
-       7a20a0e0bdc0ce07559e7e247fe27b2e57a3a2bfd1ac0964
-       ce680c2c69f4951a45434e164644c36dec6abb246bd4f1b9;
-  0000000000000080000000000000000000000000
-       cbf7402991a61ead1dfa657b8688ec6b1d3755f1c12d975c
-       5bc02ef2adf14ec62187882da764fb4bcd8837eaa3f8014c;
-  0000000000000000010000000000000000000000
-       e4218125dc4a288d9bcb43710ec3029f0a5d631dfe401b47
-       ae21a4b216e530a6ab6c14c8d1c728db79109ec58cf93a0f;
-  0000000000000000020000000000000000000000
-       1c7038534568125aac9c0b8f3cf3df6b5c409f47d6cf7a36
-       5b87e5ab0f97669d705271c435c4e070712bd16f2c5d2e68;
-  0000000000000000040000000000000000000000
-       10d92270537442d4b847b42107047bc05239ef1ca981e89a
-       931bc9341a445caea1a5088b2b4121e8f8ef085a86075715;
-  0000000000000000080000000000000000000000
-       cb5438433b829ea6a99da8216785cf60b99ceb0923b9571f
-       f239aad41f8d994e8019211e64520780dea454282a625568;
-  0000000000000000100000000000000000000000
-       720dd5511ad848d9c25861488223d168fe72bcb22918fda2
-       c39891cba3b1e61e71101f3dfb2e72b1bed9866050dcc11a;
-  0000000000000000200000000000000000000000
-       f0b450e144ae3ca96a39f8ec440bd9cd20bb77deda9307e6
-       0da749458faef5ceb6192c90857a7aa5bd010fdc57799dfb;
-  0000000000000000400000000000000000000000
-       01e54bdceb03d02c43f7a24495c462287bdc2bd34ea16e0c
-       89cba811c829d32dc1bd8e3302c13415dc9676975cb8ea60;
-  0000000000000000800000000000000000000000
-       47207ea139f08fc11911585ac7b449116552db41f111c437
-       798c17318213280bdc778c2e761913983673079ef8d74230;
-  0000000000000000000100000000000000000000
-       bddc51901a7f6556334147d54051bb50ddfc42b4ea97d1d0
-       07c366e28a2cca1cf218b56e12277e18c7ddc698f2ac48ec;
-  0000000000000000000200000000000000000000
-       c2e65edfbb87317b24d411449ed48f323b12ccc1d5a5b7ff
-       fd99a7ce5d3e82b466e1b5396a0fac675678d17237b6d52b;
-  0000000000000000000400000000000000000000
-       30a8d0ef4c28908b2f18b2bb9848eae86269ac525798ae76
-       c36b40691fb3860ed243d7c4ca22dbe6300b84dfc91f541a;
-  0000000000000000000800000000000000000000
-       d2bfc99db253d16a9b3da4c77b4d8ae6ce5a82388ad113c2
-       5a005838a2a9713b8384cbb052ff742664f69a24260a03d4;
-  0000000000000000001000000000000000000000
-       2a916a4edd73e4dca0a529a08b8f9d29e437edaa9ea50bb0
-       bc202d61c79a55eed0cc2489c4ba4c7b5bdaccf3e6404dba;
-  0000000000000000002000000000000000000000
-       bf7879a48b750f7b9392746617c768581f3b21b231ce81e3
-       67560a5ac0f6d75e0b9e0c81e006d685923d80bdfc75c064;
-  0000000000000000004000000000000000000000
-       fd436ed32f95d1682008a0faff041f4793f67fadbef3645d
-       ad24e531f725780b4e2a33c01e1cab0c278bcb6f40edc186;
-  0000000000000000008000000000000000000000
-       524a9d2ffc5a0261bb2db2158632b886966ac2935c05c0d8
-       e9615c9cede6feaf6877611d633c2454d3acdde2ae2ceb4c;
-  0000000000000000000001000000000000000000
-       a6a9f7b07ba8db6b135bddcebf9f137b46c21366c742b3c8
-       2f54bbdf8a289de06c20837df3752765970d582f7cfbb5ed;
-  0000000000000000000002000000000000000000
-       af9c61ac592907f8526a96bb7b6fb146c5a069aee0775b07
-       c79a6ccbc8d009fc3358646fee5236fe6b739f02f2bb5a86;
-  0000000000000000000004000000000000000000
-       0ac8672af776f5e1ca0fe859501d3676b5358f9b22f856e8
-       f113bbcafb23ccc325b906522b4058e6cb26fcf24abf6658;
-  0000000000000000000008000000000000000000
-       498b0116b3767b651da3b7d4ec2d513305d1260826d3c166
-       862fd18cd2fa16ae249b66066db3cb871fb1571678bfc82b;
-  0000000000000000000010000000000000000000
-       bdc25d6e937f2e889fd774cab71fc86b2898652c44406193
-       e48d25b9e80fe5bee1fa7e6480c9f4502fd0d5e1534f7748;
-  0000000000000000000020000000000000000000
-       978a52ba33b411f1dd33ccb5f9fa7978014ff0877a8ae115
-       9710fffcc51af2e428f5a4da72ab1fd721be7ad3aaeef40a;
-  0000000000000000000040000000000000000000
-       a79c6dc139e5d91b27102f5fa0f1b8e6482fa96fecb021dd
-       15605d2943c8c9d182208e4db05075e132e451086a9b609a;
-  0000000000000000000080000000000000000000
-       321eac9f621e2ac12cbe8b5d5d1a75fc03f6c16371374934
-       548803f109cf611d2e7ec0e87098e27b2c149194ed832352;
-  0000000000000000000000010000000000000000
-       50117692ce6e19e23d553a4266cc3458f8b05e02c7dec8c9
-       6c83e70eebb0018f4d6e229404e39688bd07666f6733b560;
-  0000000000000000000000020000000000000000
-       ff480a631e43dfdab88f31f20699a113d7a6ff04d8f33bab
-       a1485a58f6d8c01604dadfda7d03d7717a8dd2c2d20a074e;
-  0000000000000000000000040000000000000000
-       23e5ca641b9b76fee53eb3f8783a24030dccfdacefc8ef29
-       d4a1f481e845a6025b3bc9901a003e2a3b4a6ea49e8ebdbf;
-  0000000000000000000000080000000000000000
-       e06841bfb58278e02eef5c29cf5d05c00274e18bb34d967b
-       70097b468635250585a96b9d81f1d54cab338095c33b954a;
-  0000000000000000000000100000000000000000
-       853d124cdc7b138c9b17798a4f1aaa343bc179c7aebfbaa9
-       59b5ca04ffb3d7277c0e0505e8be581641f233e7824d5e11;
-  0000000000000000000000200000000000000000
-       5998176bd90c122ed78911aa5948a5ad2a07df42cc41e967
-       bf577dc495b1f12096a3c1503d1c3a1263895dfc9669a2dd;
-  0000000000000000000000400000000000000000
-       d11f16da1b85b6b7f91fd0c4e24122c9169b45fcc0f630f2
-       03d6401fd083a0700a06a243c8cee99c0966e61230c70901;
-  0000000000000000000000800000000000000000
-       24d65de955a156e8253055f73589da884636a0c5058bf6b4
-       e89aa9e074432b437f15b56f6d38a7fcb24cbb208337dd01;
-  0000000000000000000000000100000000000000
-       4b93290373c2747ab475d7f4992477727b21391f0cb42739
-       959d181d009c0d0898a694b8d850647d76961f611682ea7c;
-  0000000000000000000000000200000000000000
-       93fff47d6977a99536ab313546ba940048841fba7a5fd9eb
-       f8769c05212e6d6d4093fbd80ea4559513b3d18f62ed698c;
-  0000000000000000000000000400000000000000
-       c8070ba52cb08c0f814b025d10071efaa91babd0a3a8a1bd
-       fa1c2ca6ecc071ecb923ccadc0f69acb701daef5f56f1936;
-  0000000000000000000000000800000000000000
-       0a3ce83ede05ef4dc7095fa9234e419fc31acf8696e9cb1a
-       b6fdefc344f34cfff5b2e2e4afa00f426607f4ec1f727eff;
-  0000000000000000000000001000000000000000
-       4dc5c361823d632dcc5813096d9e0ec1e0f797d303d75e7a
-       f156ae67015b18cb6ecda9e03c6558a67b89834a175e5e77;
-  0000000000000000000000002000000000000000
-       ab85aa11008c58f59b58019794a2b480cf51aade35a2d269
-       9c2821ffb2e3dc84b9608d607133e4b34e35643de130442e;
-  0000000000000000000000004000000000000000
-       87dc8d3de6852d06a9712bd570873c1620800ffd01e35b17
-       0fbe6f80f9306e00330a42a9d7e57cc68c0d992b70d9e982;
-  0000000000000000000000008000000000000000
-       606855c5e2af7d73a759c740552e82ccb6cebe5509d6b8e7
-       78e8ab0a55e16027dacacf1de95a31f9cfe73bbb17aeacd9;
-  0000000000000000000000000001000000000000
-       a739b8e8bd92be110edb4378a58e0ccd15d564093f303750
-       124ef1013fa8a440375625eb3d056d78bbeab4f5e808783a;
-  0000000000000000000000000002000000000000
-       58ec509a6c549d855602a8ebe8cd3e81be9125f7df70a84c
-       fd3f5db70bb2eba772ec550e30b2b3e5d51aea15ec0f2e3d;
-  0000000000000000000000000004000000000000
-       447c79e0983fb296711c2fff964122ed7ed11292c018d2e2
-       83e12d4da49d463333fe370cd180c683ba65f9145a76aa18;
-  0000000000000000000000000008000000000000
-       be55d4ffe6d7cca90032c0808f58bb3b1713e19b1151ac0b
-       9514f1e6c4e615dc11d0e4f9a25646f2d3361fd038bd8cad;
-  0000000000000000000000000010000000000000
-       b2288fec987471fff2d3625f55630630c6344b720e2f9d17
-       f7eb7d549d9279701f73b30ac5747fb2caadf10af6967bc2;
-  0000000000000000000000000020000000000000
-       f4092ee2b5f070731b2d68a0acf2dfd5caff8b7302f00eea
-       181be1b17f1bb5df53c76582bc5f460fd90eca3f273f004f;
-  0000000000000000000000000040000000000000
-       7421b7fae0482f6cf39682fcf32a7c23377f46d15e5d2fab
-       bebc8fdcaae6d0891571abba31fd6b5525e3825689951ff4;
-  0000000000000000000000000080000000000000
-       6a0271edebc4ee46a837798b8a11e11fc9dd37f5eac9cea5
-       f88c774103bfd9656cad11ad4b2ff3246a79271f9bd319e3;
-  0000000000000000000000000000010000000000
-       7e7790676f13b58bff48031105e4b0e0ddea47e227cab1b6
-       95e30e5b38892f17c26315287bb12011906932ef6888c307;
-  0000000000000000000000000000020000000000
-       e1f369e67be60abe334c75c254bd5f819d15397e52ce1991
-       5e08e9923dcac610c4f228b1feac23bc6e0ee8f2880625d3;
-  0000000000000000000000000000040000000000
-       5da337bd8a553d4a311d9cd0d00cd8c1292a248704f08e67
-       be4b68b824170d0a635b10c1dadb2a69146f5a9ff9c45d7a;
-  0000000000000000000000000000080000000000
-       f36268dc83dad1fb42ac11a70d2b04c3074caf05f0d28e4b
-       93e3bdb8ae0c1283991383131f42785aa6c13efac96a4ac2;
-  0000000000000000000000000000100000000000
-       f509a4aaa4dd6d33c58f09517fd61b0a3e173981cee23328
-       0d3acc8d01a95faa7bae199eadb1b7f0a6799cc193a36b87;
-  0000000000000000000000000000200000000000
-       f06206eb3ca9d5b3a97ce33c86ab3ec88e025396414965f4
-       06c48b3173b95040a1b30b80892f28205bc3073c06af9690;
-  0000000000000000000000000000400000000000
-       d94cd93f0aa42e7aadc3fe5134a75e22901a277a9a8b8914
-       d040857811c9e9ba2b1d13842e74a2aa3242e8b92106d648;
-  0000000000000000000000000000800000000000
-       de0fcacadfd215ef8ad575bdaa2fc3530d913a03801a7e93
-       142c97486e896f09f6694b3fb82fc7e6da00fe9882351ad4;
-  0000000000000000000000000000000100000000
-       416e67c9024af80ce9084c854109b4d78fca84cffd481f3c
-       b9a534a054aa28ae408d293652388f7dc8782441dae29783;
-  0000000000000000000000000000000200000000
-       1967362294f80c18835408ec52e69b4863a0e463f759a6f0
-       95e7f20d718ffc48412abc598fad1826697b7545c8e3e0af;
-  0000000000000000000000000000000400000000
-       1ce4ad11f24cf2785769f676ecfd2cd5479766bb09236f8c
-       ae02eac15efa0b102722ec4b393323c3f9b4299ec8d62ed6;
-  0000000000000000000000000000000800000000
-       e3c9df7ae6d132da795747f26daf2a538776ed4694636419
-       9c6012e67ff701322397ad7a374116289b3b1e35277812ac;
-  0000000000000000000000000000001000000000
-       f4faf834e3aa92af4178e31d770e7ebf70bebcab1752c561
-       f6fe6c69c4227663ce35b7abb77b78df395f2ebf8523cf28;
-  0000000000000000000000000000002000000000
-       d667bdd9f5967cc525310fefc616998b4705ed09714a55df
-       efb98baf6fe8946fe39778606ae2fa874502918c0885ff8e;
-  0000000000000000000000000000004000000000
-       830e96038280527632cbc228474953ec407956662ecd1e7f
-       bc1b15c2f9951c77111f6aca5fc75222615e4a12287edc86;
-  0000000000000000000000000000008000000000
-       6afe6de17fbd8260c7dce898f26d002a6359800bb5789c23
-       f3c39e7caa6be7d346d62eccf9e1d20a4df2f2c52f0c4c2e;
-  0000000000000000000000000000000001000000
-       6eb5d0fab61828d24ae3323d3018f65400c8c3c0ded66ded
-       5a585a0bf790d36ca04f6e3db2a8240bde8674bf26d0bcc5;
-  0000000000000000000000000000000002000000
-       279323d7c326dfe129bab246202e23158e24abf280e04a5e
-       721cf1d8e73cad3c3ab65d34cd83fc131acb73161d33ee18;
-  0000000000000000000000000000000004000000
-       6e74528189d18b5d8de86975b2272b708dc62f912bb1f90e
-       8e2431350408e2394201afeed37957886df2ec97eb5a872e;
-  0000000000000000000000000000000008000000
-       0e4780dbee0c09822f67da8b98aced5440e3641fc8c80d4b
-       5049f512c2cb135fb8842351a8cb5502bfb9895914494497;
-  0000000000000000000000000000000010000000
-       b40751d42e542a27240b1c25d17d088fdf35357a8e606b65
-       0e9feaceb106eafffd46da59acfd588c91510fdb60f6c101;
-  0000000000000000000000000000000020000000
-       ccdf33f8a14357509960e96ffd707d34d6e125593c470b22
-       da36d09446c89b49417909efc8ab9b8884a82676d0083b27;
-  0000000000000000000000000000000040000000
-       7b51094cfa2d2972b921feb7bc4910af27329e6417eab51e
-       4af16a9cd82694f045f72a419bac4b36c8f4d1ba7b6d7853;
-  0000000000000000000000000000000080000000
-       8912b55eabcae2fd33cc24d48c77e9ea91ad17637fcc4e9a
-       ecdedb7cb770eb34f181e7f4e168d3cb97a62eda8a93a71d;
-  0000000000000000000000000000000000010000
-       4da00b91551750c9e42920ca30cb60c6800614cdd94478f8
-       a1fb6aac2ba91f1db16292fba881ec25ec5139a05bef8360;
-  0000000000000000000000000000000000020000
-       1ac4f21d876b643c6a4e7dbde96f5b46871988c089075722
-       957f88bb33b20c12a264f47f483a7319275351c5beae257c;
-  0000000000000000000000000000000000040000
-       cf0e9847cf96d79d483634b86b9d946163fc7f75ad200380
-       090dcf1b1e3d1614b9a81368ae7494eaebafa78f7c8ee545;
-  0000000000000000000000000000000000080000
-       8776c8edab400e4e107458c529119fb645ed0232c13ef316
-       c190562aa4f0e4a8a0b142d3842e16a1e4145a865533f820;
-  0000000000000000000000000000000000100000
-       5364915ad601a7b24e7fa93224e0f890c1b19976ef727604
-       8fb3df4ab244c50af5acdd8273bbdd5ee22433978a1eb577;
-  0000000000000000000000000000000000200000
-       ac3f6c09935979c1c7ed97fb57b6b4effc7ae93007905959
-       65d4b7f38a928a43be02d8c01e6de2709e2eafe4cbdf00d3;
-  0000000000000000000000000000000000400000
-       6531fb35b522582fd8e344b4967d4fd96f3f028df9b8a0f0
-       433d474f5759f5a6268d21ff330185eefd7581fb417824ad;
-  0000000000000000000000000000000000800000
-       cddb346f0a62dab089d9d08e5728c390528341a65207762a
-       15a50b1d5b86af3bbc2d769639d1863187e6abf155550d85;
-  0000000000000000000000000000000000000100
-       76a743ed49c15a6ae22baed339d3b3de0538d9dd9a5fad03
-       2f81d127787c8b56417ec1b0eeed0bedf24dfaaa5fc101a9;
-  0000000000000000000000000000000000000200
-       959c1be8dc4a8d23c065d0af24ac881204f64c6ac6f39649
-       e5535e583d915bcc451d04d40f88d00d531eab1e74a85936;
-  0000000000000000000000000000000000000400
-       60f09275f915ecd4753a88c14f310627a68c85b0059cc7cd
-       f2eb6f33261a6f1521acf10950689cf8300ea1f7dd02c455;
-  0000000000000000000000000000000000000800
-       a582a3a84d722b1888eef5459d744f4c9bf0f254393eade3
-       5171c29052d8aa3d3bed54ed6013e5bf27f0ca0c256e5df0;
-  0000000000000000000000000000000000001000
-       5075b276fc0c1b44b34c2d7103a321119dfd5ca9858f5ebd
-       c3e543ed7b34b725a060380f5f351859b5cd34c3655c1bb8;
-  0000000000000000000000000000000000002000
-       76ecbfce581f71b255f56aa7118900ca55482a1402d508ac
-       16f238cab43a3e15aa8bdb6546bf4907171d6062faf6d51e;
-  0000000000000000000000000000000000004000
-       48c37ef151bd87c3c8af4b33d2cce7007aeb511e4c9eea95
-       b78ed418a8749a58fd1fa8eccd28ed1ce220682caae446b4;
-  0000000000000000000000000000000000008000
-       efbc6f0100835c8051fa95f338915f80004763efd684f982
-       e88cad94409c47ee2fb48fea7996afd75780fdc66f55e145;
-  0000000000000000000000000000000000000001
-       8f537350f5a94603ac84b105dad1ce2b27e775b251ffcaf1
-       ccf28017b1b6d8e853094535b78c0c533ca88d3119f88130;
-  0000000000000000000000000000000000000002
-       73bf403e90243af00ae3573bf26cbbfaf22bfc64c25042ba
-       842c8b6edfd5470e1261b53cf3f495c03e7ffbf747917b03;
-  0000000000000000000000000000000000000004
-       b2e7d8fb0bb71f3543285e36b768726cdbad667cd415fedc
-       cae46b71316c769290340cdfc99c9751fcdf53a911e75700;
-  0000000000000000000000000000000000000008
-       391c06d7329a903e22f310c602d86877dd921f82e15173be
-       e2b1e5114f1648ba3449d564fb1ee26d7c325630777a6ae5;
-  0000000000000000000000000000000000000010
-       b54aa87e67f0e182a88660fe8df6a34dc2fb021fc80e372a
-       30d3fcde749a306eb9d5aad0527c7e187449beb5a0b4e2a1;
-  0000000000000000000000000000000000000020
-       003bc47785839c9c0d915eddb61b2eefb3e474c86cccd321
-       388746b96cc6ccadf4f86e0a98baa5dcf6d2c777195a8b07;
-  0000000000000000000000000000000000000040
-       c737e23e4813ee5321ac10198e108ad3cb59dc35a46aa4e2
-       987655569a6d6c797b7c432b8711c1c4a29c95c8849fbb6f;
-  0000000000000000000000000000000000000080
-       2ea5c63608597b7da53a2ceed973943951552fffd89c0101
-       1d6673cdb23e07fd73fb0f325b98a9d7640a118e170b20ae;
-  010000000000000000000000000000000000000000000000
-       950227a0e0af4be87ad9923642ae064a989f7bd41783a808
-       9d1b35004e09dc8a26c67a60c358a299cfd493a5825d2bfc;
-  020000000000000000000000000000000000000000000000
-       e06478bdbb64dfc81293d20b3babe451119c00a57abc32d5
-       5cba681dc30a6350b640f6ff5d82b9a59ef4724cceacd6a8;
-  040000000000000000000000000000000000000000000000
-       9e2a31deb5c28e271d69790d7dde1fc96b5e2f727ba863d7
-       383972aa8b8a05beacfd3cca26b84ea7e658f0a161c44307;
-  080000000000000000000000000000000000000000000000
-       e7248873cbe00a5eb07d18a36dd1551e1de656f175795b68
-       72c76c4142011ef65b3ee4d1d92845dec5d24c09b8e15ea6;
-  100000000000000000000000000000000000000000000000
-       bc6a56d706b865d0d0bb17f6f56a946b19b6463823b50705
-       5856456857fe3829df5ae6ce9c1559e2ec272e2023bed389;
-  200000000000000000000000000000000000000000000000
-       fc9f70464be8294b04c3092a09815ca7cbd9e4007e35a6e7
-       1873b51c4e65ef63ea2ad3ab7bbe2933c53607c2f4f822ad;
-  400000000000000000000000000000000000000000000000
-       9252b21b6ee8ad2618bbbb0624fc077c593422d73c205172
-       3fa2ea516e55274a6eeffc125729b4f323395a9375fabe20;
-  800000000000000000000000000000000000000000000000
-       23ff2420dc5bfa41b4c1e02c9724c8356973ee4c29900941
-       eb5c441b2c65f801f3781c59bcfba202ccca06a5a0daace2;
-  000100000000000000000000000000000000000000000000
-       21bb39d0e07a104683fcabcbf086ae38505f21119eb69eb5
-       317efbc320dc245436f65995b9555a70567061f15b882765;
-  000200000000000000000000000000000000000000000000
-       5faa02f914a0d07a3ef66ad9b85dd7292cfca0e96b41b18f
-       ac6668e2d5bc13abf89ab4ef5ba02e4893c63453fe6cdfd1;
-  000400000000000000000000000000000000000000000000
-       fd2edab89c53584e62d29154ae3eb025eda061a2094d1c55
-       074cae6a1865c11c8a740c06500f972946ef3f7cfca6c784;
-  000800000000000000000000000000000000000000000000
-       1200e02bfb0d2994eee80495fe6f8db63f480f23b06943ae
-       665960dec953660aa472689e099663ea2e9281bc0ec42b70;
-  001000000000000000000000000000000000000000000000
-       d7680b371b3db05b0fd319e98c4fb48faa5147c24fb8dc98
-       f0faf1fe00730c1795fbc5865cf67def50d494e9b0e40085;
-  002000000000000000000000000000000000000000000000
-       0ba73097866cf7add6a87d76db9512a2965f43a59842dc9c
-       867abf83d19cda8d1c980c008be09eb6d3fd4c2a3aefe157;
-  004000000000000000000000000000000000000000000000
-       0efdd7ae03dd5d0586093ce70bb56933d277cf262a708e53
-       15828719856c5b9f77c12dace0afd8bf79de06c99b18ca32;
-  008000000000000000000000000000000000000000000000
-       f8aa22bf8e9b805311ea0cfeb6633a4d333c25df26a44086
-       d24bebb6a79cf48786be0aa33e3f0d904f4c1c256ce5284e;
-  000001000000000000000000000000000000000000000000
-       bd4971c056be4d3e3a7a7f727700ab237838abe0cb8006c7
-       ab9a06b02608dc9824147e4fae22347564145cc72acf6d63;
-  000002000000000000000000000000000000000000000000
-       47dd63c99f11d04f002c78b4a9f7e87e6a95103f6b952088
-       ad3844299f2996c7124618b420a5d20476f8724a1a2a554f;
-  000004000000000000000000000000000000000000000000
-       c23a8c3c1c99c1094e0e33ea48a795e457124f219a7ca076
-       1756e14debebb81278d38a6e1e030c41ab3ad10db3723956;
-  000008000000000000000000000000000000000000000000
-       4e51df50080c1c5ead84794c7f8c0b6af24eb44940230a54
-       6ffad11649a0460c565e360be1d922b3882760bf6f6cdb0a;
-  000010000000000000000000000000000000000000000000
-       94544aa77e6f2e88130f6d882ce6d41b92805e8a33bbf758
-       afbfa3504fa60b0c174dc726c32e36cf044730b03de81da9;
-  000020000000000000000000000000000000000000000000
-       4fcde9e30ebe03a1f724f6b00d806273582e1cdfc15ff147
-       80558bc2b6f44c7ba7d6640d99278f274b2290e3d574e93f;
-  000040000000000000000000000000000000000000000000
-       2fc3569fa2e00eef7c411f2b469869e37982de1d4a6e6a6d
-       6adb474171dac11f836848dc4753239335b91b1f5e1392fc;
-  000080000000000000000000000000000000000000000000
-       fc5b0abf6a26469cbc8b64bd73322994717393eef4fcfb9d
-       3c2acabbf67983924899ccfc1d003cd931f4808fd2aba192;
-  000000010000000000000000000000000000000000000000
-       4c72a0fc014cb5ca4e85b0871f3fce111bfeb1ee212bc3f3
-       ef0ba0a4ccfef260c42884b03ca09c7bbd022b3c69d2efaf;
-  000000020000000000000000000000000000000000000000
-       723a6062b95c8e17cd63441dc3542103ef5b62b2ee67f696
-       0a0c19d7009f4984767aac9284ee75784b632ff2b8b0165e;
-  000000040000000000000000000000000000000000000000
-       00f433db06d51a81037b312e1687b90668b14b5c87019e79
-       2769bcb9e372babe64498035c9ca6d385e713f2c62da9830;
-  000000080000000000000000000000000000000000000000
-       c00a26a106c43e944d8012181e873d57658bd3efbef46926
-       beb3b2eeb0e4cf7af92ab9eedab0afaceda36a4d158fc060;
-  000000100000000000000000000000000000000000000000
-       2b6af19499046a72002bb08321899ea1196e43a3445dc66a
-       53355ad208629b72a6b63955ea29d96f8625ef065d7bfbfb;
-  000000200000000000000000000000000000000000000000
-       b8bd2b3ca21a4e9c46f3a6ee8283c629e51ad868be5da5eb
-       099fb4ee85dd16e2adb3a8392721eddef3284ebe72a629fc;
-  000000400000000000000000000000000000000000000000
-       e7a823381ecefd169648af7cdebe27bdd33575997b16c9ea
-       2087cb8faf6e0f87bfd483bef04ae0aa84b7faf1d66c3067;
-  000000800000000000000000000000000000000000000000
-       10bf2538f02d13d5d6df68708a1a875152c8253a189c44a6
-       d7c45cd1b7df5ee240c9e19d9a875c99d06bffd5b58249e0;
-  000000000100000000000000000000000000000000000000
-       d60033a9a4020d3be5214edc136c993f05a04a3e8ea5c8a4
-       25b00716396a5cc3c54215e42da5c2642073d967fc26dbee;
-  000000000200000000000000000000000000000000000000
-       c69e4ed75ca48419d526e5997f9634d1cc230c49158907d5
-       b8eedcc2227f3593df72a78ed1100394eb65f9098b5eb4f1;
-  000000000400000000000000000000000000000000000000
-       9dd47ff28851b4da258c41aedadb4d407e39dcf8421fe2fe
-       913ceb307bd491e5a5e7c6945c7b3ccf2b30571beeab889e;
-  000000000800000000000000000000000000000000000000
-       245dadd57e5ea520d0319892ecb964fc7d7d75ac259196e5
-       06ed9325638f5f233cc3c6687e966d18d13a2376a7d0d2e3;
-  000000001000000000000000000000000000000000000000
-       4b88b385ae2ce90610c3de9942359182b23cf96617b01a50
-       1789bd30c366f57f606c139d7dc7c00bd6999994bc225eba;
-  000000002000000000000000000000000000000000000000
-       ced8575125b759ba6fb81c4cf51b309f1199038471b1034f
-       4d3bb5964432e95176d2438ae186c9ecd0aba9b71899b85b;
-  000000004000000000000000000000000000000000000000
-       2d74c25a841900a8b9a663b0ef0dbb1e24a4950eb06445e3
-       e766ee906e42ad9fbde3aeb74fdc464fc3eb72c87bef45cb;
-  000000008000000000000000000000000000000000000000
-       20f7f88a12d40f3cb6b592008dec36ee508387a7870e8ba0
-       68f515a58c25941d27fc209666df7caac05c6ac143a883dd;
-  000000000001000000000000000000000000000000000000
-       9c95399291b0d3202663fd9f6ee972975c862cedbf2461e3
-       cd0987b7da9744e475b9a457e34330216858240559c3758c;
-  000000000002000000000000000000000000000000000000
-       877cf0278449adf691b20d5b453d891951a1d1e8eb03c47c
-       5b16a43b032ca092aaa101ce8d0daf61894d53075fe02768;
-  000000000004000000000000000000000000000000000000
-       bae2c00d2a033ad2acd8719acfb01332aaf91987a84b046d
-       b9f4306305a262b7a8341f8bd9a30722b18479e8a722c030;
-  000000000008000000000000000000000000000000000000
-       3a8b7c986f313adf30c17005fc8f4e4783cc7efbabb45b0e
-       80c005616ccd2e26d65e3b9d6b3284218a90448b59d6a4c1;
-  000000000010000000000000000000000000000000000000
-       fd95f34a972382c5c78e702b777c873040970ec04477a9b7
-       0f8ef6fab119411fcac25d7794514f6879ccadfbbdcf1737;
-  000000000020000000000000000000000000000000000000
-       0e76cd58cca1993794ee6fd9537271c337844d69317a3064
-       0187210213980e21d629cf30ce5702e6c3a78fbec1847c30;
-  000000000040000000000000000000000000000000000000
-       7cc71eda22e83901a5e7d5d0fc5a2dd1a9a74c25146406ed
-       040739cf452779ac78d307c96dc0298e34f9ed95b4bddce2;
-  000000000080000000000000000000000000000000000000
-       34a0f031a22247f0583237ab3084581ea0cd8df336723285
-       3a9ec82043173a791c04b9b8be7ffb35118bf09e3d2ee0ff;
-  000000000000010000000000000000000000000000000000
-       0b6cf14a5abe2dd979c268d5145083b48889d69df0d37708
-       991b6be8eee496149a181200b1fd081e437a9b5fc0cac4e0;
-  000000000000020000000000000000000000000000000000
-       08cc9b13e27d4cd3e3d7563eef1dbba235abec2a418f1852
-       ae9edb5746fdacfa76de58675cbbd24a4a7e77d96fbe7b6c;
-  000000000000040000000000000000000000000000000000
-       824c0dec5d6a4df429da24bb8e2fc8a4372bb92074a2727a
-       8f0715b035222ee533b0981f01550e8e5a9e24412d9ddfb4;
-  000000000000080000000000000000000000000000000000
-       68c15e06234437eeb45d5108e8259a70e13258dbab25b697
-       8d177379a2039c1a7843ad87fc6ee1393a4cee80a2751141;
-  000000000000100000000000000000000000000000000000
-       1001198aada4c22c4dc1d84fa1e010cd54835e132f22dfeb
-       b8cd530fe6ca419cfd7bb8081845fcde53b2adedbd801018;
-  000000000000200000000000000000000000000000000000
-       9ee54d6bc7e24d0c738ddfb263e5b63fa26811b76b578409
-       7f7446709375b8e32d8f0fc000eac04f0b1b82a3125cdf96;
-  000000000000400000000000000000000000000000000000
-       85c19ef941156968fe05f7fb61bbec5122012fa0fd4bc828
-       7168634d5b191ffacd2f8e4928119d68627bd4b027db18c5;
-  000000000000800000000000000000000000000000000000
-       2e644758b3e889cdaf5c845e4ed308be6a3eea514f893e6f
-       d077d2ee5cc8d36b632d4e983578d6bc894ed2006b57b466;
-  000000000000000100000000000000000000000000000000
-       d86c637f816b37de534d296fe76092971f47418fe1250959
-       b15790c9ab783aac93d8944f77eb9d0d3ef9fecac04a2918;
-  000000000000000200000000000000000000000000000000
-       864954a4c173fcf64b26cd5f046a1c7a05d1c947e054f155
-       4fb4609c1b2739d513358c7bcf38385f1d90431c60437b6f;
-  000000000000000400000000000000000000000000000000
-       7429d917ca0f35eedf754a3dfc87fa86efb1c7d67297343b
-       7c66f4fc42a427a5175cbb09feac1aea770471a8566ea04f;
-  000000000000000800000000000000000000000000000000
-       3782aa7d7eb154ed5d96a1cba095ddab7d2446cfc02928bc
-       1e6d44ca07547ad0916761154378d997b27c06f4162dcf9a;
-  000000000000001000000000000000000000000000000000
-       a668c27906252b42c57223bf1041b4474a265e456e2b2ecd
-       3560a2b61ac784e7a96ef52262e6dc91e50518c9fac3b4b0;
-  000000000000002000000000000000000000000000000000
-       c84f1667f91ee7bdfc4354dc978f0d7cb7bdbf8851a26120
-       c7e80fbe3e6f54d7b6e5d8b678c95da1836ee1f51d9433ae;
-  000000000000004000000000000000000000000000000000
-       29292efb39b4bcf42c932f53d49b14c97594be6e0b3433f1
-       37073c3c11ddb32e01fdfd49f6eb19b2b651fa9243a77376;
-  000000000000008000000000000000000000000000000000
-       55fada32dbb1f89e56aa524e1fd89d54b43c4df2bc223e4b
-       d6d58bfc7a97a059494c17ef3affdf7d3e1702e78ca36062;
-  000000000000000001000000000000000000000000000000
-       ccd662881392daf3ff1ed0021b38e19d8ab8d01a2bf58700
-       336934b6f95645d246b72d600bd366a77d312065ff9ecfe8;
-  000000000000000002000000000000000000000000000000
-       922bf0e21bef2411ae54cd3cc6d5eb7a9ecfadb1db60fc5e
-       88d77b89f6936f6249cd1128bbd9ca6625fcb1fc3a08a251;
-  000000000000000004000000000000000000000000000000
-       f687602ca24ca63d2a29a2767278dc6548520317451902e5
-       55d57692a413659d964e04914e6256bf92155c60c99bb55e;
-  000000000000000008000000000000000000000000000000
-       b5f8969d59419a804c80468b2a9de9c79516a0799abac18c
-       c1057e3f43e1ebaf15d380a7e0e6de243f7f2fa3950e4c99;
-  000000000000000010000000000000000000000000000000
-       e04bc9f8b61a4f9de92ae6244c7b2a4e08f6c3e3f1448f33
-       0f8fde70f9e667cf2e9ceaffbac28d2e209ea2abcbbb8a77;
-  000000000000000020000000000000000000000000000000
-       e971da1f557584cf07135aca681908701acdaf839e3712d4
-       09acbfeb972d8a06fbf34de6c82365c23d999cd74647abff;
-  000000000000000040000000000000000000000000000000
-       bda162e322c262b9d35b36e0e46a23676014fe48429f5cdc
-       aa5b0598386fb110a46a87c8fbcaeb516de28ea2ed7f8d20;
-  000000000000000080000000000000000000000000000000
-       fd9ed1383cec0c64be074a4d57ddf0afe49e5ad2c009fe66
-       fa16f08eef73e9de97deb09eb19f332ea42193d110bd8404;
-  000000000000000000010000000000000000000000000000
-       27f427404340f50680538b37b52c848743366495fc402563
-       abaa5141060bf1bf3134136e0b0b141ab248d2ddb9ff063d;
-  000000000000000000020000000000000000000000000000
-       ae41da022c6449e1e8a428ec9b889ffdb8a437d6480a0c81
-       15abc9a52c7469e98ce02e534753cc84f76cae07acddc082;
-  000000000000000000040000000000000000000000000000
-       f0b9b3502228b1f620038dad3f8851b141a294c1248d68ab
-       b76b98012d904ebba304ae707227df9950522a6d5d4461a8;
-  000000000000000000080000000000000000000000000000
-       60ffd6930e94706f169e7067ae595c5e8e0ddf0b77db2829
-       3e8e2ac1f42519bdf5bec90400c716fae98a1be517fd4792;
-  000000000000000000100000000000000000000000000000
-       de5aea72327f9a7b74a5f80fda52e2157b22ea92e14adca2
-       55d09602919f23cdab77f5c03bc381a6bb318b8468f21c8d;
-  000000000000000000200000000000000000000000000000
-       0b5ab5730b4974b1eb97cf228b330248a095259668378c80
-       268cf5bc198bc91b6644663d29ba29f90916737b513b54a2;
-  000000000000000000400000000000000000000000000000
-       c7fda4b796b2152eee8141d57bad874253c307c6458ba9bd
-       0211fccf6da981c4e1de0f8b8fe3e1dc12e57d0ba2c4bd45;
-  000000000000000000800000000000000000000000000000
-       0ccf6e36230d2a3fcf1c3166362811bcebbf84ab4c6266dd
-       d185d6a587f704393c58c0808b9054aba16b27c46129afdd;
-  000000000000000000000100000000000000000000000000
-       d0eb3bac789ca548310b28febf4ebe3a8730edc80788e322
-       72d5147984e036a42b7b803b1ab7e8de83a5bfaaed63eb93;
-  000000000000000000000200000000000000000000000000
-       f1f9a72096a0d35a3bde4203b234d6fd8fe7cee52c73d3b2
-       45b9e1ac776727e325b3d07cdcb8c7950586be2ba64a7e20;
-  000000000000000000000400000000000000000000000000
-       a0f475abb02d86fca05f4ee38a4b96f1671edc37e4921789
-       92e568e95bb7da1bd9c413d3c506edd480ca5a2022145e18;
-  000000000000000000000800000000000000000000000000
-       c2cb82eb6202462faffbe17860caf958127837bb56679d26
-       84a77a9c5053d7b382937ae4058a0c2c8e0cae806750047b;
-  000000000000000000001000000000000000000000000000
-       f69a70aaa3145b6648b244b0cfe95e258de12960733fef39
-       8e1d6e60c18153a420586a9525a8a35a0e01c33d445d394c;
-  000000000000000000002000000000000000000000000000
-       ce821767e1c5200f6e949eac5d032365a021002376f286ba
-       66c57c2559bff8bb523acf8308a6e87d48507287f78d5fb2;
-  000000000000000000004000000000000000000000000000
-       25a78a2f37beea632aba391e99c8ee0cbd895861704b0508
-       7837958ca54303afcf6497fbfc3feab75fa8dacbb2da0271;
-  000000000000000000008000000000000000000000000000
-       424443625ccf703366b5006c2a06a5844107afeaca134291
-       67d5149bf0ef07975a81fbb90367b0c388c71706a71b57de;
-  000000000000000000000001000000000000000000000000
-       0c4b5edc7c9af09602270ecfcb227a08c3eb41e8e743c46f
-       38451d3e127ced080e76deac3a2608e4ba9c6f64858986f9;
-  000000000000000000000002000000000000000000000000
-       3806f72a054c5cae45b69837bf2ed1cf3d95f548ceb6ab8c
-       bf3a0b3586be379283cc846f0e2f7a726667f22b4bd8073d;
-  000000000000000000000004000000000000000000000000
-       53acb46560bcc190fae42c7a64bf9dc3523d6e039a6a2362
-       1662cc1720996bb8a3af6255e767b3197904d036ffc66bf6;
-  000000000000000000000008000000000000000000000000
-       02f3e87b459d0f8b9efc00443a035552f21f114b7b85f451
-       a9b157c5bfa6119d89b2c205b7a1f9742865b4c1e7f64501;
-  000000000000000000000010000000000000000000000000
-       8c5505d686afcdecb2260e057ac8f325657df05bf9b05966
-       5ec81b79d35ba3280ea12e5b043b3e31e268829e3d563eff;
-  000000000000000000000020000000000000000000000000
-       55cb50e1caf5c71429c98f03714b692ea31b1c43cae13b34
-       c889fdec89a6a1495614efaf5af9ba6defb5a56452ddf97a;
-  000000000000000000000040000000000000000000000000
-       a738befdbe5ca885c080949c0c6d20ae12673cc7d20f8f83
-       b6a93ddc7d3c794fc40483401e90d67841b9f5354e14c5ee;
-  000000000000000000000080000000000000000000000000
-       ad437b56deab48e58dbac0415241c21f1e58f9697810c86e
-       5f39077bf328fac90226b173cd437ef53ecb7a98e0cd4439;
-  000000000000000000000000010000000000000000000000
-       bea057a143e4fca512bc0a7905a92efde0403dfc766633d0
-       e22ff885888f579985075b711375ab522d0f44def0571561;
-  000000000000000000000000020000000000000000000000
-       52ae9040cda27f5ee7fe1414b48401560faa8141518dc3d8
-       ca197b53ddce530fdd18c70d16cfb3ebcfabaf86f28a3593;
-  000000000000000000000000040000000000000000000000
-       6bb619e1ad95c1cae465758158d3eb2f49eeb6fdf72f46b6
-       87c5624f8f1cd1ebef2de00f71c5747bd1b62abdba15326d;
-  000000000000000000000000080000000000000000000000
-       6420252af652e672b66ba8b28241d159e9ba6359c5c9b917
-       090a8bc5603faff86b116c11c4934bf8f5c1aaa119fd4b04;
-  000000000000000000000000100000000000000000000000
-       1761ffce62135461d02a5426b1c31ba1e693ab9a12aa68e6
-       82d92d00ab3f980a7b07e7fa4edd44dcda5b0f57cf6911ad;
-  000000000000000000000000200000000000000000000000
-       8f05ebc8491092d047674a6c6b984e95076dbcbc476ee825
-       66a587a3f6a816a6fc8c5ae7945b26f5386a156fd886e8a3;
-  000000000000000000000000400000000000000000000000
-       b5b04bb84c64d7d82a9a6627b45e2d730e619261ccaf8612
-       0b258b61b0732a06f0b3b1e6128461525f14b93edcf6e65b;
-  000000000000000000000000800000000000000000000000
-       94efc3bae8b030363dc12b9d98f462a53e669bab96a04bd6
-       d19b3eee10c9305677102f713cc0e44dd94b38b586e66c85;
-  000000000000000000000000000100000000000000000000
-       44f615f33c33876b0a7f5eaf4e5194228138486b7bb661d8
-       324dd74ce8e0b2353f6b0956d90db45d0ba174348fbe8009;
-  000000000000000000000000000200000000000000000000
-       ab1ee468f066b46ee35ff4cf3b061e0b032c11316e829294
-       0b9fe8ce0e6ec4775aba86a76e6f15b01139c55952356e45;
-  000000000000000000000000000400000000000000000000
-       ff5f9a1310f1972c3e2ff648f5c7a3c253910b6f4c9cec98
-       ce4364ba24319ee0e1d7b47207ed8fd704d41284f857aafd;
-  000000000000000000000000000800000000000000000000
-       67547ca22ec3022cd81a011d8a36f081e6e6665d53d59615
-       3eab5b8d3cb573b7cd71dfd69f8865da04e88bed2c22fcc4;
-  000000000000000000000000001000000000000000000000
-       43a0b4632e7b5746206f24fcc0cc5c02abedccf93209a90c
-       86f8af1e716badbcc467b179e06f84c4a0b7050b3d381646;
-  000000000000000000000000002000000000000000000000
-       84e3a90828dc4d3a965e6a2ab5d0aa532aab68bd6dc61171
-       780e5dae9e9d1f276da173517a11d0b70daafbafef4ec191;
-  000000000000000000000000004000000000000000000000
-       a59916e1e69488af5c2315227ae07a1fd29c7e88316de33d
-       dd0a3a126707ea8a9b19b2bca7d6c6f91e4288707da624b3;
-  000000000000000000000000008000000000000000000000
-       5bb210f3f571f79c7b6020cd4076feecebce67313fd4e92c
-       5dd34c33bd75b5cc2712c284f06ebd0771f03bbe6a0933ef;
-  000000000000000000000000000001000000000000000000
-       16377666962332f0d015c24a8a64c8fba0a6b0026448df2d
-       4dc232f7602f414acd74682fc955cd7a39e965277ab13f73;
-  000000000000000000000000000002000000000000000000
-       88a0800a751e61a4cf3556fc09a5e2267f012c48125f9b6f
-       0fae8ad675be20c5cf2811f31e013754e20600d789d0d366;
-  000000000000000000000000000004000000000000000000
-       536255493cd9b75e93b7b3d8a22b9a5250f5715da602c2a8
-       eb03a459e1ecfcf80d8c869a0800d10d9bf0eb16deb0feb0;
-  000000000000000000000000000008000000000000000000
-       d23dab5d3651b9b3d90315939175223e6e3dd8f06c87b2f4
-       bc59d143168febd05f77d5edc352db18040573e5e90c1b97;
-  000000000000000000000000000010000000000000000000
-       a991cf922b451c1eeb6052888c28b5c51371101c15ac05e6
-       10467d595653eca2298f0fb16b0260e79c2f6bfc1fe0b9bd;
-  000000000000000000000000000020000000000000000000
-       a54de96886108612191972a6c17cc10f2fe3b218433cb6e9
-       19ade54eb641c24ef2cf34831b80002993d1f584f5126112;
-  000000000000000000000000000040000000000000000000
-       4df1ea44dc58b80b0d4ffb6440a023175f0de0ca13e5b20f
-       3b73e209e5db273ea076697eb09a23d75a06763c95ddfa52;
-  000000000000000000000000000080000000000000000000
-       f8266b0377535bdeb855801f5815c1c51e6de75d9372c249
-       8f3b81b9b8daa6b9134c358fd69df65d682a2bb1e3897653;
-  000000000000000000000000000000010000000000000000
-       96712bf387a2bd8915be3400cfe50c9edba2a03e24e9da7e
-       bdcee44e3c128f80ab846ceebd787775d7d12a8c0c4b1b7f;
-  000000000000000000000000000000020000000000000000
-       86e7bd89620da09a32041eed8dc60f4df1708c674baf7d9f
-       7ac5acbe1e3549204cd4940e4189424dc800a37e3bf49645;
-  000000000000000000000000000000040000000000000000
-       cb943d6a0c33f4d6fc0856026a2e0f8b8b15572789cc156b
-       3e16f341f83c585e427dee9184d650a00206454148fe2c47;
-  000000000000000000000000000000080000000000000000
-       15abf241bbb3e72ffc263366ccfe5c42b8afa0e615246fa2
-       1bbc37453d729fa3f560cdcefafa5bec04097b34f04e69e0;
-  000000000000000000000000000000100000000000000000
-       e3a2fbaf70c336c960076e25901b08ea70f00cfbdb678c99
-       6199c398d7970a32a506c58e7deaef154b08bd660cda65dd;
-  000000000000000000000000000000200000000000000000
-       4ba54ce0040ef1780a0286d10ac5cf13f563d688c214080a
-       e2d23bc27ecd4508c2b934c201410ec11ccf581738f9deb6;
-  000000000000000000000000000000400000000000000000
-       81953955d6a216c4be8a3dc461783a0af5edc5f4291f4edf
-       858b1e9cd5c1b34c7df03a68aa618a046e9870f3edd2be08;
-  000000000000000000000000000000800000000000000000
-       46be627870c3f043209d65725bf2a546aee9d2dc6d355f03
-       6d35d794d51108c1828114d73df644f5e537523567ba3866;
-  000000000000000000000000000000000100000000000000
-       6081001224d8a1b4062908a261bab7dc4dcbadefb31c47fb
-       e62bd23c4597a7fa473c3fae0d3b499cdfbb81a3cf2ff46e;
-  000000000000000000000000000000000200000000000000
-       9cd0184802fb4297083c8fe4289a50b0b54daf57ce7d3c7f
-       f08cf7cef963531dd323b2d85ee2e57956eefb463813e810;
-  000000000000000000000000000000000400000000000000
-       cd2a4132daaadd45eef34602ab287ab35da3216d7e0c2201
-       18bd53d544503fbbfe63fc730f9ea3f83a92a075b9c731b1;
-  000000000000000000000000000000000800000000000000
-       7dd4dab1cceab233b8f440e7c798d926d6672fae111b97a6
-       0155e424ee93cbeb18f5de8353fac06917061248e64a1db0;
-  000000000000000000000000000000001000000000000000
-       2bebc540b952ee15d29456eeb9754bbfd6d14dd4df9ee357
-       4a6e99f2277d6436c5f76ed6143a0a5e0871842134a67f9b;
-  000000000000000000000000000000002000000000000000
-       c599a8f74e66cc416087a2c232debb1b9ca96ef0eecf7692
-       deb16181993fbe042307dea974ae92137f39a6107a6cd52c;
-  000000000000000000000000000000004000000000000000
-       1ed3a61376f1e6730127787de72c37ba58d748acdad988b5
-       4b4d63ad13b6e936379710f9f1c9d5c01a3884713e2323c4;
-  000000000000000000000000000000008000000000000000
-       e976691853eee2c466e8d9ecac6f2be9dd4d119250e9687b
-       a9d8242d5171109459a60bf382bf5542278a0fafd6a31c33;
-  000000000000000000000000000000000001000000000000
-       817d9313109eac3b60bc647e881f9fd77296b7fd5521a4fa
-       083fe0e8e375636af03941ea797f9a5a7798cfab8b260e19;
-  000000000000000000000000000000000002000000000000
-       3609713a1383562d139c62be8b46b22814c52d0498bd0743
-       31cac650c1affaeac478b5cc8145e5afff54f9c486803fb6;
-  000000000000000000000000000000000004000000000000
-       b6da3ad2f7b51786fb5a1e52cdeaccfbeddc948211e1fd6c
-       afb15f06a78e82084de6200f85b0f7ba6c9f80ee34fbff8b;
-  000000000000000000000000000000000008000000000000
-       30e517ce758f7bfd6d50c44802880144b2f0b37052cc5efb
-       3183baf097aa12da6830fb3781b803f32e8f89f01cd9d25e;
-  000000000000000000000000000000000010000000000000
-       c561eb0df785893728c7ab68541ee65b5de5f0def12f1570
-       92f0838b81ecc63bd92162455803a4865f3771af19d0cfd0;
-  000000000000000000000000000000000020000000000000
-       d5fd1003a7018381ade31fe9ce9a64126ee798d2a2ec8733
-       7336952580c0fd50af4df8939122ccb98963c88631f4e74e;
-  000000000000000000000000000000000040000000000000
-       99d96e0cdccd1a71a29a6e15441a2d3a25a0718ea84c2726
-       04c80e68b0f9daeddbf4a243332a2a9c03684811420318dd;
-  000000000000000000000000000000000080000000000000
-       5c123dbda2b026c444fc873e2884e7c733642451b8c58bea
-       e4a1520b9dbb0580eadd7e983e5f7ffca560a2aa69cb4acd;
-  000000000000000000000000000000000000010000000000
-       aa82a0f119dd67acec85d42d52866a18fc250f5b063bbc67
-       e01b60199b085ecb412d68b2b4fc65b5ea827a6f5e2a7b85;
-  000000000000000000000000000000000000020000000000
-       e3d91efce207edf5a3f0c5412c517ca2caf860fb80c75a23
-       5b79bb6bd28b687eb07afe51566ea4b1a791aa9620734a22;
-  000000000000000000000000000000000000040000000000
-       120d205dc675f1585fa3b9cf92627e7644be58785b0ab209
-       98f71325ccdd857d0eac2bcd8e6201ea042569d2b06dc82f;
-  000000000000000000000000000000000000080000000000
-       ecc047da556e6c5ea7c195ed3c5386f60dd3b95537e41aed
-       b21cb8440842e4bde27ee84bfcbf0ee0bc8b8b3ad88455e2;
-  000000000000000000000000000000000000100000000000
-       9c595d82e523573893ef08454be25082e3e2dfdbe71f6634
-       e040f8c529241507b3f450b48f1f05605c1566443dfae0e3;
-  000000000000000000000000000000000000200000000000
-       35f4e989da7d064611287588d3566eb092c87405cbdc6873
-       913e8b1818b9f317ac16b02ff0226c0d7749d40612eb5a6b;
-  000000000000000000000000000000000000400000000000
-       8efaff57d270546c21d4728e904409ebf9d19d86ba797a1b
-       4423538d5d87cfb5c636b71801ed86751b722779545a73e0;
-  000000000000000000000000000000000000800000000000
-       38f285b482c3d66af4e661a07a3e6069143cad4dc1e3e804
-       6f1184beb0f6f27e0e2389d84bc6df3d54a51bd1c6336b8b;
-  000000000000000000000000000000000000000100000000
-       9ab7f76f277e7c5e9e437d44506feac61c20c40c50d4f4a6
-       f5c357f4d66b8e96f8245c41324e8645cfa9953dcb2f4b70;
-  000000000000000000000000000000000000000200000000
-       6077ee198eee87d2ab2bc968f4f594b7db9070b367409f9d
-       8e3e4e0f06c954bf256d3ff91852e1b2b392665c4385d9e2;
-  000000000000000000000000000000000000000400000000
-       dd9d75908bbdc05e2cfb8df5d1db68ccce7bbe7f121eacc2
-       78082c854cd92adbc3c37daee124d4d9a7d97b9c6c7ff4d9;
-  000000000000000000000000000000000000000800000000
-       41e7465edc8a9d8bc8f4eded1405c82d2fe9dd6232807b95
-       3a4701a2768128fdd2dbf43278039f36226d0f32401c2f46;
-  000000000000000000000000000000000000001000000000
-       c08c6119ee2a2197f963a599bd65b0590ef5a519e33c636e
-       977467c483d31158e24a00e7057e9122d84b8c29df6a40bc;
-  000000000000000000000000000000000000002000000000
-       af0bc2d846a385793ff0719690346f88e8906d59d731b053
-       5961660b15037b718ca51d2162edbc423c42ff094c3a74c2;
-  000000000000000000000000000000000000004000000000
-       00fb58016823ff21666d4834be7777977c39dc524831f78d
-       16f43859a26050bab89f24747aa2f159f7f952a4f7d0b423;
-  000000000000000000000000000000000000008000000000
-       8888994bacf06498d6c65514458e0dcd5c47a89096431c97
-       84d3b8542bce25195af4c2c2db5278afb5c090980e978d84;
-  000000000000000000000000000000000000000001000000
-       5c09111b5f1d7071f9ff25551b298c3ce446aa3413097e62
-       583739a94482dd2d485b26f9eb11466298b1ad5c1acb1204;
-  000000000000000000000000000000000000000002000000
-       04aec49c4fb80d6561c745f51784f4f3d31547bd4de5a94c
-       e7f83b28e61a9eb7929382f435c7113a3110a08c7cb69634;
-  000000000000000000000000000000000000000004000000
-       8391493f0cff3eedcb9fe1bdd422793ee5e124d343b375f0
-       2d9e4938f6c4c337b943809490c1b6ff3c843bb0bff1dded;
-  000000000000000000000000000000000000000008000000
-       6d1246c48d1683a7fd7329c85ba193d285192c8831176913
-       32f271fc06af76ab98807731b3a47eeac2a107c02cf30196;
-  000000000000000000000000000000000000000010000000
-       3cd9d97a17d77d3f3e9edb8d72032b5f655f948b32f59e00
-       5d7c293fa62a9a1f91b0baef7efd96f8e35188f75cd8a331;
-  000000000000000000000000000000000000000020000000
-       cfcc2990da7be7df288d8be5f9be1deff14637612107ab29
-       e381e161b0b8bf30d3b28575c72f5605a83d5ea4d23a34b5;
-  000000000000000000000000000000000000000040000000
-       ac740d1ff0eacc8d57f042f7835ad95a80edcd3fdf28371b
-       7ccb5ead7d391d393d19ce552040dd00ee411901f82f53ed;
-  000000000000000000000000000000000000000080000000
-       177a0fcbbe76481f473a27bf63aaf2ab9d127e399a3c73c2
-       e21338988039b5aebe5cb3d5b632250b9801271a117440cc;
-  000000000000000000000000000000000000000000010000
-       96ca2977c2f58083155573e55b681ac307b40e601652836b
-       678a557c88b2e1df13ac012a7104d40d33349b981db71476;
-  000000000000000000000000000000000000000000020000
-       0e7ba2f3476c82f01ab7fdc7203ad2cfca591ecc829d8409
-       daab2f21fd15fdc90a7cb7a6a56a0d0c6942ae2b86113373;
-  000000000000000000000000000000000000000000040000
-       b309f8daf59f74bac80f710fe07350f899bb1492f24e1425
-       aadd706e551425657e4e8d5138a8d13337d53346885b2ecc;
-  000000000000000000000000000000000000000000080000
-       2d392f58a4b220211b884f4287ad76c9f9515ec47c284290
-       9aa9a624109b06d5722df543b3b0e105052ad578b54e47d1;
-  000000000000000000000000000000000000000000100000
-       cccb9eb8fc84365765163c40bd24b6bb51a45e7345bd7a14
-       6d9e8097f75b13cb808d2c44efaa556a56aa7c9ab8106563;
-  000000000000000000000000000000000000000000200000
-       78a5d8d79b63dc0324761e93b76a7c79d6455539ffa6f088
-       8b6df918ec48a084ee472612bf14b3611a9a9c10660f31a7;
-  000000000000000000000000000000000000000000400000
-       c8240b82b4e438074aac4a34be3d0b01b3b7a5c1746f5dd0
-       5c4650702bfc551e85a269d7f97fd98d49db0f45f40ea608;
-  000000000000000000000000000000000000000000800000
-       e6880f3681fdc188ceab24c0c1cb3f90357fd05130687b07
-       f53ef53b6216d61118877eee6f9406f076a9b8bf4b31ad9b;
-  000000000000000000000000000000000000000000000100
-       c734620cda2c3f3b71d8195949898c8740acb8444fa9e1e3
-       2083e8448b090301f991ac6687179d6773c128dee6aff608;
-  000000000000000000000000000000000000000000000200
-       2f67eb665331c85869ce51b067c6e6e94cc8ab45fc71407c
-       b61d957135c33783e803e9e535702f2818c21ff62be94c51;
-  000000000000000000000000000000000000000000000400
-       d590b7a848006f402461a88874eb9b5d9add7ec80c81b154
-       febf425ef71bc535730788b70bcc2833e08accaeae7e9ee6;
-  000000000000000000000000000000000000000000000800
-       b02090c689481635b33f992e13b59eea15aaf9f25b778979
-       417ed646b20cbab90952020eee8069dbe00f18d2572f8d72;
-  000000000000000000000000000000000000000000001000
-       ff1e358c8bd643176d87f75c2175c4b66ab1ffaf0079c012
-       b06d3d892f6d85bf268276d7102d7471eaca99b16260a39c;
-  000000000000000000000000000000000000000000002000
-       57d86ced26040b7dc14c2f47cbce1f5c70398ec902d6d484
-       d8ea3cdcc2566d14f6d996971796161e493677cbad536027;
-  000000000000000000000000000000000000000000004000
-       1cbd6500cb1061ae856e10557c84f085d340b5ac6394de48
-       0fdb3c9f37cd7b03b4ad10a5a090afaabc9eb6e623721af1;
-  000000000000000000000000000000000000000000008000
-       18975b942cfdbe8391c4e2a96e03df6cc3d44d1be1fdb697
-       86f3a467cd9b71208dd75efb91fc77a1dcc25dd45a6002f6;
-  000000000000000000000000000000000000000000000001
-       806011240d6c13fab000555504cc68fa756d5c0cd85d2933
-       7793edb94f67a425483b90cc7b869880143272ee85ca2ad3;
-  000000000000000000000000000000000000000000000002
-       3d04d556fbf1d4dd76fa97215fe58c170d0198c19d5a0b8e
-       850321dd6927deef53ce43fcdd07df6a3aa1fbe0d26026d6;
-  000000000000000000000000000000000000000000000004
-       b1a243ffdbccf642800db3cd11beb064a2674f49ae9c6550
-       850c7c28e1d1dd64373ddb8388755325671fd7cdf34fdd2d;
-  000000000000000000000000000000000000000000000008
-       3705ff7df146cebda207c1fc2348252f28156b752e9cd167
-       418592dcaf9178228f66511810bfed87e7ac9d2a138d741e;
-  000000000000000000000000000000000000000000000010
-       a4597f7b0bc5b5cd53bbc04d644901b385d2c5d03aa0e363
-       f1f007c32f306ef45e0f78c24bbdf7507a62e44861c1d579;
-  000000000000000000000000000000000000000000000020
-       3f2e6b8d77db0bb0f4dc09f8b3f5ef841b65f389194865ae
-       d50dcc3d890fac6c458ffe6334a2ecfe329f9ccac8bcd609;
-  000000000000000000000000000000000000000000000040
-       db05a0aed5d55023dee7dd6671cbcf71cfbb29c10c4babd2
-       8925fce6cf19f3b2f34d61b894b213a8c59e69a3993cfdb4;
-  000000000000000000000000000000000000000000000080
-       4c73cdb5851ef5a107ae0acc485cfe49f23051ada2cfba2b
-       dc81803c4aba313b5bf42236e208b8bf66d62810ec0a8fc8;
-  01000000000000000000000000000000000000000000000000000000
-       e466a171f30130c5886045ab035a744b80a63cf10ad50670
-       7d0a3d9a3ad5af4590a18eab995623914ab2377cfe35d3be;
-  02000000000000000000000000000000000000000000000000000000
-       3979486436134c0b0d1cbf612b6745e7a43038c176e50759
-       dc0c555a7b1425e8d83ae80934676ece2a2f8a654196dbe7;
-  04000000000000000000000000000000000000000000000000000000
-       517b1b4b00e143a73e315298830e0fd8f0692549b4efa53f
-       b47ae72ce84e68257377022abb9cbb566e58c501e1ae8956;
-  08000000000000000000000000000000000000000000000000000000
-       197c1cc090ee4f199c5573cfa65f6bc84ab8957fc8c2be23
-       a56f67e2313fcd2fdf621da945eef4e31a8fd9d0445b1b66;
-  10000000000000000000000000000000000000000000000000000000
-       d59e9e6be1cefd6881df7772eeb46295e7c6ef787264ea73
-       9c9bbcab22f66a437538d795d041399093f694c669b2f559;
-  20000000000000000000000000000000000000000000000000000000
-       de47466a965a4d5d92eed3b856591fbb787ce6863da4d8f6
-       94a4c31a6e8418b46529e547d7a9aa0e1d2962a63eee5654;
-  40000000000000000000000000000000000000000000000000000000
-       36dbd72833a532f365e6be111aafe17c2fd49f21f4eaad76
-       6327e174d21ea698cf34bffe36672e7ffa931abb615148aa;
-  80000000000000000000000000000000000000000000000000000000
-       c10d857d362ebe177aa6b240bb27340b0ad2b283cbaaa84f
-       184d05e1651645e67d0d42eea84f4a8c56972014aeab4602;
-  00010000000000000000000000000000000000000000000000000000
-       b23943ae799651f7219dad8ead93d03c4eed373f6389b117
-       ff33f2564db3a027b45f2652ac244eff9d5641212fe33a33;
-  00020000000000000000000000000000000000000000000000000000
-       9126da9f43bbdbd9216f40c2414236438b5520304f21b2fd
-       f7c8bc04d48f4b18f44044f6a5175b67e5a0369475e38840;
-  00040000000000000000000000000000000000000000000000000000
-       d73e01f210826c0205aaad28db4cb341804a696f1b683a14
-       47632f2712f7d9a63c7fb8c1462279e3c5d824ecfe35d3d3;
-  00080000000000000000000000000000000000000000000000000000
-       3a8a518775a687bcd6245cd6e8504765275b7c9df76817b7
-       884f7908451106aa852323dee7b353a4b1686cc7f74b738f;
-  00100000000000000000000000000000000000000000000000000000
-       c054a470e6d41003d3b20ba165d391cdc934138b55ad957d
-       2ff8dd62427119acf5427b73db572167f953f778b5536a3b;
-  00200000000000000000000000000000000000000000000000000000
-       ac86f7a300e3f4b248c17113ab2a5ff0ec5aa11c26f7e9cf
-       f391deaba561f263728c3810c4246bb850a38c22c3d0ff22;
-  00400000000000000000000000000000000000000000000000000000
-       ed1cc342bb9b9f0463f8254343f79ef3ff75359bf78c6a06
-       e657015d282084ec74214fb5926eacebe91b2b0818cd96c2;
-  00800000000000000000000000000000000000000000000000000000
-       275083f0158e81bbdb5bddd8471d4346d2dc2dfdeda59d17
-       85405f2ff391329b38a6bcbaec9890fd5f6c27c43c4d42ae;
-  00000100000000000000000000000000000000000000000000000000
-       5d875aebf5496ef91d1fb5fd6b7c10ca3472ac04190fb5a5
-       30f8d4f4e34ded31074ab7bdd98cdee6995f363361dfb67a;
-  00000200000000000000000000000000000000000000000000000000
-       ea05609c5f54d16590cbf9bee2fa008f60aac96ed40148ae
-       0356240ac83e1f2874e37d5577009d79cea8ab677d05d35e;
-  00000400000000000000000000000000000000000000000000000000
-       241a143eb59063bcf573483f0453cd3b7c20613e976e1677
-       584f0cef868af6aae2474278099ecf8d9af01d1b540c1853;
-  00000800000000000000000000000000000000000000000000000000
-       8d642d6c2ddeb938e63fe0da1f84700ae21c35317652dcf8
-       e692d249d7c24d32555f7a69d88980e56b33e95659ea5182;
-  00001000000000000000000000000000000000000000000000000000
-       abe335a44913c306c289a66bdc6551dfaf69febea41c73f1
-       669f21ff2d1979cf255d0f357d477f62a2c376e2f7e49ee4;
-  00002000000000000000000000000000000000000000000000000000
-       88ace268351b45c9ad63579ad01f5631fc6ac91d5de6ef19
-       065b1d6414049be6fd09ae8f4cf9101e625ac3781f146a3e;
-  00004000000000000000000000000000000000000000000000000000
-       a6d8ec0b3de91563f75df992e97a5f8565333056dbeb5495
-       c56801660652b4d8973edeec960f6c606f553af746e7fb36;
-  00008000000000000000000000000000000000000000000000000000
-       a159457dde64aa20ffb81591e52a684c4f01f224d77de994
-       2ce28f10c61918f29a4ced6d5969aad3e26397d68b273e3a;
-  00000001000000000000000000000000000000000000000000000000
-       0658da014d05ae4231fb93096483492482ee0ce8495a482d
-       945a27517e687cd2fd0d03c57dbdea162b4fe10d05081869;
-  00000002000000000000000000000000000000000000000000000000
-       85ca27e90b91de2e400a59c00ed82116302cd2a1367c3411
-       fb1858e39f2cf75d36fc308270510d9710fc6bab72fb3162;
-  00000004000000000000000000000000000000000000000000000000
-       fc60f7ea828f3813eba9d5136a34ce868510a6f5c9d61124
-       74fa96b782f8e68a9b93c82ff428feaaa66a75331df5e98d;
-  00000008000000000000000000000000000000000000000000000000
-       49a4c0b759451a9047440e8ba0670a750a69f92aab520c26
-       4e1631c860ed0a4a9917983f15f889383860921298bf76f6;
-  00000010000000000000000000000000000000000000000000000000
-       090c2326593b51e1dc6d59542c8ec15d2f60302371489e36
-       8f961912ca14f7208c5608eea98208eea9d45255e5f4c900;
-  00000020000000000000000000000000000000000000000000000000
-       04f1eb6340739f6c37e3b0571b1d41553adfb376053ce64d
-       242c48e139838ae26843e54dc149b154bf3e8c490fe0f1e8;
-  00000040000000000000000000000000000000000000000000000000
-       ad61378d9b886d236a585a35749caf40552a018246cd8203
-       ea01b68642d2988df8d124f74dafa6abf853b017d4cb5496;
-  00000080000000000000000000000000000000000000000000000000
-       5291f7145b376f42de91b492a803c3da552d1bf3cae38f74
-       1bbcbcd28382cb960e12663fa17ce99d8fd996480afdacc8;
-  00000000010000000000000000000000000000000000000000000000
-       3283a8ad59723b954c26d32641e1aca7ecc37cad79757fb1
-       331cd49fd0def48a4c449efbcb35b3ee20552fc441300884;
-  00000000020000000000000000000000000000000000000000000000
-       1e9b00edfb67ee5e7e72d5bde45c69dda0f0b9f145ba376a
-       b11264164e9e70271ea379123bba996844d8224b2c4a5792;
-  00000000040000000000000000000000000000000000000000000000
-       891d65411edc72bfad04c2b32dc4f3daa46fdbcdf2295b7e
-       7019b3daf1d8d054ced0c9b41903c328cef85eb8b30490ed;
-  00000000080000000000000000000000000000000000000000000000
-       a692a308739c497d2fbc905d2c1212d9ba02b5c896330480
-       87747a33be359d180b13c7c2da559adae20d7e3fa677d80a;
-  00000000100000000000000000000000000000000000000000000000
-       a646d48b3a7570c884b7d20b3ec1910062742ea29f9b87db
-       6dba393a5c0c22f991052587f2d03cbd6fa1b97032ce8d70;
-  00000000200000000000000000000000000000000000000000000000
-       b9980daa0335682e0d5f943db1d63f76a5afba294b00c894
-       6dcff8118dbd4938d98327457b611b78bc6fc3858308d44e;
-  00000000400000000000000000000000000000000000000000000000
-       5a6d143a6bbe108a8e865d262700c5e3d681a864c9bf2889
-       bb00e78a312810a37d218fe1e898e34ba684df92d5df8a80;
-  00000000800000000000000000000000000000000000000000000000
-       27b44c0f87ac23ff95a31e1b328d928a1c08104a3d67a9a2
-       2d2fc5dacb8cc5cb49812ff3fb4c4dc710b27126aca8af6d;
-  00000000000100000000000000000000000000000000000000000000
-       52a8962f43e282225863b45fcbdca1c7970d05cdee3661ae
-       0138f4025e6f693f784e26c368f3e99bfc912da83619df70;
-  00000000000200000000000000000000000000000000000000000000
-       9d778e66c779bab53e8bd4cba07121af23a00a64f2d69033
-       74818f00faeb596041c9f60ecf7fd36ce6ca568bea39cc20;
-  00000000000400000000000000000000000000000000000000000000
-       541065c87d92ba58c18ae8220da27a8d54ad7741989ad6c8
-       4c5ed522130b99c5d54d6c9d500e04646deafd63003904ef;
-  00000000000800000000000000000000000000000000000000000000
-       2f20f79d4c2b14d94977d1079c3c94c781df42adf3d6901f
-       ff0efe5eeb85df42c23a1c7cb86b3ef67a423f7dfe4a8ebd;
-  00000000001000000000000000000000000000000000000000000000
-       2e5c45b439d98cde7dd553cc7f6d55867792f2b97d4096fa
-       432b23888d0e8efa3ca6e7770a9b70add2d31113d187cd15;
-  00000000002000000000000000000000000000000000000000000000
-       dc84f5bf78bed0ec4011a808b3ccba862ffe18c6bd0af093
-       8a7df628ccdb8d0d9527d0ac6a2a37cc3496ce920a6549af;
-  00000000004000000000000000000000000000000000000000000000
-       a8950cd163f3bcef61d2fd66c2c84a7069498f1a4480fa9b
-       a52e41655dcb9f4419b3aafdeb1b388fdea9ede2eb71d55e;
-  00000000008000000000000000000000000000000000000000000000
-       48ec823bb0601d23644fecaf15522422ebfc773c6741921d
-       a9f9ecb94e7a4a0f6196d9f585f981529aadf5b1ee13c5aa;
-  00000000000001000000000000000000000000000000000000000000
-       4a360f8b6fb99125be62dda9f47fc5568119ab2e76dcb2da
-       a2bb0963d479e76d1f32a7e724ca64982093d519649a2676;
-  00000000000002000000000000000000000000000000000000000000
-       5628f1141e35d240bcf5ec4bfadb44376b82edc1c1821181
-       00fe7d461f3b521fe1d76fdfcfaee8b2f95be74121660550;
-  00000000000004000000000000000000000000000000000000000000
-       6b7e5c402de45b783cbf0bc2a922f034d93d41dd69a02d98
-       4e64fb1db55e3b0c622002306567bd38068dff297b8caddf;
-  00000000000008000000000000000000000000000000000000000000
-       2a0a0ac9f03ce1be0f6a913cca6f12dafb4ee79af1173aea
-       da2b5561384eedd083365dbfdbac266556f306779654a946;
-  00000000000010000000000000000000000000000000000000000000
-       1c1b4df7b4f126620df92c52fbcc07d7b8a5aa44f3e5f1ab
-       46626e5971070b4cd57d5b49f3b3e228e2dbd1b9798e79ed;
-  00000000000020000000000000000000000000000000000000000000
-       5682d5056b30cd7b84911adaf1af2af99fb16fe82beed222
-       a62abeb1341cb2cc15a3947ce8b571d2b48ebc7365072e2b;
-  00000000000040000000000000000000000000000000000000000000
-       f20e8c97b521ed21e72686e503b30412060626094e2569ae
-       caa011296fd4dc935074560a2608c9e1db2848ae25f4395d;
-  00000000000080000000000000000000000000000000000000000000
-       461dcc25da2c567f2c330d1ba39172451f8b0c1e4575623b
-       e4a8929a202cd9cf07a3a914d900eda1a1aa79dfe332fef6;
-  00000000000000010000000000000000000000000000000000000000
-       179913568dd00f3c3e6638fff80b19078f605d2989b40f4e
-       98901d6c7f82903c81fb45e93a8d70b2126a40465cc82536;
-  00000000000000020000000000000000000000000000000000000000
-       01d0dd28e61252d14ec58b782dc7c777f3e88a652014bb84
-       71802a1c775ec9574b443f5ff43868d8df47620e291aa4be;
-  00000000000000040000000000000000000000000000000000000000
-       0f6ebfa8809b841679990649948d76b1d79ec12ece1f4751
-       69f01483dd242bf68434e66b66fb25ee6115664ce75850ba;
-  00000000000000080000000000000000000000000000000000000000
-       089df5d6f5a4f9967693d8872da3808eccabe037cae99337
-       95ce5e283ee609b6d62bbeb996d3c99bc11e66250f2884d0;
-  00000000000000100000000000000000000000000000000000000000
-       da907941cc5d4349988756b71b3d625ffa68f36ddb5b76d1
-       ab0b6cfc89a17453f0a7e76216d4c134d8385732e8b7ea9a;
-  00000000000000200000000000000000000000000000000000000000
-       61ff06d4942fd9296587bdfba1e8e27d42d7701ac7efb31c
-       69f0acaa8622c8d71497ed99f646d033d81b943cf2da78f4;
-  00000000000000400000000000000000000000000000000000000000
-       6bd9b77d87473a6501421f565884cc9bca0ff6cdbd8608cf
-       c25e725bddaead2ac2c854d645565cff9d13a49325318470;
-  00000000000000800000000000000000000000000000000000000000
-       779ee5f0fe88dc65da96ffda43e5bbd77fc34efa0eea92d3
-       1d32b8d6e4ca8735ff8489f3316e5dde7eae25346199436d;
-  00000000000000000100000000000000000000000000000000000000
-       dfe0750917dfced0bfdce54668950a91b3697636a7f622da
-       785410a4bd7246c3f351ec3c17dd4fbea179d282bd3edd35;
-  00000000000000000200000000000000000000000000000000000000
-       d88b50720ac2b514d8e32766e4c10f52099b7c9dbdfa4639
-       ee78f304793920cd1996322df67166ccce319c7b79aedbca;
-  00000000000000000400000000000000000000000000000000000000
-       40297cfb793bc7411ac6a38c2f5e35f13e076c96e3ba8cd7
-       8b19a2d7268324413e76dbef51d544522afcfdb234a80b79;
-  00000000000000000800000000000000000000000000000000000000
-       bf474a47de1427ffc76f22f85fdcb322eceb654b82ae1476
-       c1107b5c9aea17142905e7423c03ada55b4de08d68551412;
-  00000000000000001000000000000000000000000000000000000000
-       5430fc20a9a834d033b1931d41c692682a389b6bd68abfb2
-       d5007648b6b5c9b3ce44fe8c8261af3509f2854bf12bca03;
-  00000000000000002000000000000000000000000000000000000000
-       dc814d7cafd842955d624394a5885e9900fb48302c02079d
-       a8507e6a2969200463221a3d8baa430a65dff06e495d54f7;
-  00000000000000004000000000000000000000000000000000000000
-       eec73ecf6bda3f4dda70ddac567649e3acae53c79973d91a
-       43eb2159dde1ef21d0fdfe7d0313f5d608b12ae157c0175c;
-  00000000000000008000000000000000000000000000000000000000
-       b31185b8c7a09b6c8431604c9d73a92cb0e368af1e109593
-       1621f258ac6562bf15900e46ee38ce54d17fa998a6718126;
-  00000000000000000001000000000000000000000000000000000000
-       861599547a7005f367bcf4bb2d7e77d23ae864dc0a97f3a4
-       e81d4a8675c7805ae2ddfc663db35f050decd5bfd14f89dd;
-  00000000000000000002000000000000000000000000000000000000
-       4fa5147d9ec4057b649f7cff1202fc99cae58e1aefccdab9
-       064b3918cd10ce4f246d3f79ff52e3fb20f770f07e942b01;
-  00000000000000000004000000000000000000000000000000000000
-       35eaeba3a19c8fcbe86181577734db4cc2ae23a0035fe2be
-       6338c7f38226401f0a4c72c5c4a43a14ffcf0724f7cc579e;
-  00000000000000000008000000000000000000000000000000000000
-       843eb5da5349484b83b951550554fbcffca7c80861860b84
-       1d127da43d43487a2221c36ee63ba71f75e6e7254307037d;
-  00000000000000000010000000000000000000000000000000000000
-       39864279e3c8580727d48936a1620cf01667f76e3c300498
-       137a5254e5815de51641a5d15b2691b31e08512537427e3d;
-  00000000000000000020000000000000000000000000000000000000
-       c6d896c129ea56b02c159cade2a6cbbc974ec04ffb4f538b
-       e546edaf391396e7c5cfacf94cf37ff79ca56a0418872860;
-  00000000000000000040000000000000000000000000000000000000
-       f35dfbaa8f13910ba7f3a9de5a9fd6f36d8dd8a444fd3144
-       b3882f070df1375e3e84e933de4e4372ccd8dd84923d228f;
-  00000000000000000080000000000000000000000000000000000000
-       ea26fbac4c2c5e46100785a99008d4ae890ad258918aa18b
-       768ec538c5f61bad6e7b49ae664ccd4ad481c8c37f317b31;
-  00000000000000000000010000000000000000000000000000000000
-       477c6bc073748fc4c0511b0d1e180315530037ef71cb4026
-       7d8bdebdcf35e2c38c6d9d19bf97f6fa76e75a3f9ae22e9a;
-  00000000000000000000020000000000000000000000000000000000
-       655699d22c61a253572cd6d4df64d4fab06874c340e95783
-       7cd5f30366d96ce31338f5438263c887d4698a2d1f826509;
-  00000000000000000000040000000000000000000000000000000000
-       accdb0fada298f97c199b0b75ebec0f8eda6c819a322cc84
-       839916db991581426da7dad428a2ce1f1fdfe0e94551e45c;
-  00000000000000000000080000000000000000000000000000000000
-       710b2db656a99904896580bc97453f7af6d40326f8ccfa0f
-       a02c312babab962db4503415f05d52b2f30bfcc35869f08b;
-  00000000000000000000100000000000000000000000000000000000
-       b09a7b21b66ea4e6409b36515c849ab0c89cd4793b86aad7
-       25d64c7e387e9f7fb9bcae80fcb95e60ee764b4b91f5a623;
-  00000000000000000000200000000000000000000000000000000000
-       961df75dd24a7f370750a17c2025867442411790e604c7d5
-       762b027acee1b991b90b83f9d918f2f74e84383f425c64a9;
-  00000000000000000000400000000000000000000000000000000000
-       d9a3a55ac9d2517b149b2a6981a1123c0d9b4abe03982e03
-       cd43bb557f2674593b8692472f225fb4c7f5f207ea1ebcf6;
-  00000000000000000000800000000000000000000000000000000000
-       3d42aaf1230930786e7febf219ff6c90759295547a2c0e9f
-       3a00b929fe7dd2f848d9078fe862bdc1abfb0b242f2709a7;
-  00000000000000000000000100000000000000000000000000000000
-       4dc0cb0a3d1ab6fffab767a4ef3d47f029d9f035192d7dc8
-       a10e7b96eda011b4b927bce0d98b6822540b9b7521a22b57;
-  00000000000000000000000200000000000000000000000000000000
-       5b23eaf61681e3574a8a097d763a3cd828626b749851ce7c
-       fb624ad9a049613c27011972f01dc669560322040aa7c4af;
-  00000000000000000000000400000000000000000000000000000000
-       f6db6f3ddbab5d3228812a70fba910ed17ef493b8cec3ca9
-       dc3c24735d9fa10c848f9b09a9fd8514ea4c1a576f8ef4d8;
-  00000000000000000000000800000000000000000000000000000000
-       07f9b15343927460366de4a9ac3f819566e670f4b58a00d3
-       bb6bfb31664ac99f9af977589ada9831b121ad90466375dc;
-  00000000000000000000001000000000000000000000000000000000
-       a305415baba5afdae40a6f9a1b6e8e3232e143a7f1138c6e
-       5d4109fa28245a22bd6c812016617e1aaa21c9e5b5cdf87e;
-  00000000000000000000002000000000000000000000000000000000
-       74cd6460d4ac168edb0e544890907cd954c24c468ed87848
-       0ce59ed2694fe93103eafe67f702b32dd5545e5fa53b261c;
-  00000000000000000000004000000000000000000000000000000000
-       4cf6e84f95eda559ec34c93a2e4ad35325e0885642d4dab5
-       6e8d542ff0d468d44331de0482b9f483ef1e81afce8556c9;
-  00000000000000000000008000000000000000000000000000000000
-       223fbd1515d17968e6365920d08afefc8dcc1b7aa1a48a94
-       846cd8e79252fddc2bd9dc79047d55c96158dd9834e79e43;
-  00000000000000000000000001000000000000000000000000000000
-       3d42cf134f2ce3f69168b13b9104bf20e720aa1ca5db3abb
-       076f0dc3b495de14b6626ef3986cf70fcc62c73101b3c00b;
-  00000000000000000000000002000000000000000000000000000000
-       62964b3de5a5f29fb46af05e22e604adc0ddd469023572a3
-       b53b2d9fddfd2e9ea18258fcc56afdefacb68000766cb625;
-  00000000000000000000000004000000000000000000000000000000
-       ce9999154c2cb7cac5bff38080d9cb5bf7e25e48469907a7
-       126fb43d45542ca289681f8a96f1eca1f78065dc3d563476;
-  00000000000000000000000008000000000000000000000000000000
-       c316c04b5351c4a9ab217b997403bdcd4b6b0cdbeeb61020
-       8359e9725a86108c9e9df165c8db8dfd97ef0c0d5ecf8700;
-  00000000000000000000000010000000000000000000000000000000
-       037524620d481439f805bd9b97f564fc54fad6d68ebf6d37
-       1a3ce3addd3aa06fe3c0851bb36d6484d00b71e2f7f24f93;
-  00000000000000000000000020000000000000000000000000000000
-       678374857cc068a2a29348279f2a9ec8edfecc0cd658defc
-       b22c3aaefa728e55ac29d4b624eae74248f3f983029b4b30;
-  00000000000000000000000040000000000000000000000000000000
-       dc8f9708feef6e43a07c93abff90668180ab88838767164f
-       d3afd33038af52da8546589a263cc81dad1d99d156b321a5;
-  00000000000000000000000080000000000000000000000000000000
-       6eac02f84c3e0ac288f692dcbef8ae12cab31fbd53d97397
-       2ad2aaafe7a7ac392fad7a0287fa2f2d2681dab726bf44a6;
-  00000000000000000000000000010000000000000000000000000000
-       efe7d7c2bf9e3822761cdac372165820b9ab2ec899424e8a
-       cb3757944a16a71ec99813133ed5745459defd3bbce8bc73;
-  00000000000000000000000000020000000000000000000000000000
-       48b83fc1b61f1f635033c366f9ada4d79966f82a68764c7b
-       0844cda500c0ddeaeed7b63f2223877838f379aa7504661f;
-  00000000000000000000000000040000000000000000000000000000
-       842e81ad0e1d515d7cab6f58288c30357dbc621387091fae
-       9afa55ddff3b59ff3a6d3b52d011ea090cbd32b56f25ecd8;
-  00000000000000000000000000080000000000000000000000000000
-       de27653b243a814cfeeb90eef9d612ab98224704e328923f
-       093aab7b15166c45d7381decbdb00d3fcc62e59d6d3fbc59;
-  00000000000000000000000000100000000000000000000000000000
-       80199c47a849f02460357ba7c920b4f91007ccc3572f8a95
-       975554126ac6b55767e57be44de8141f83d2c6e88371c207;
-  00000000000000000000000000200000000000000000000000000000
-       18214d1c20eb598db7ef9e19f66b41be9a3c6a28a2a06c09
-       36d76057e43f8033756217742d563bd811e1130b9273a3ab;
-  00000000000000000000000000400000000000000000000000000000
-       b02556b90f7846ed7ef080a17b6131cc6e34de764fedf66f
-       c5a1433480f37105516a2903fbf4a2cadf94061dad71dc47;
-  00000000000000000000000000800000000000000000000000000000
-       67f22905a1db5aa9dbc49b92986a0e6a76f555b26fa844cb
-       9197f321a515351baf650e1375ccf1d0964653e35e4f2f3c;
-  00000000000000000000000000000100000000000000000000000000
-       e684a0b52b370cb0d1a56313d388a136108c642d3b39bc9d
-       62943cc6636002312b13fa373109f4291ccfaa872da2ee77;
-  00000000000000000000000000000200000000000000000000000000
-       5a4dda4fc12d0c760398b47169e470f74446acb791559bc6
-       0bcd3206810ee183fee9b0bb838efa857d695ca3e7ed1253;
-  00000000000000000000000000000400000000000000000000000000
-       9fc13edf3cd388716e9f4e1494d8a0a96281dc961d4548a3
-       a26ac7726848e147e7ced7cca7e4503ee20f42705fcfc755;
-  00000000000000000000000000000800000000000000000000000000
-       86f93d79f1f26b011541ae929aa31b9a4c84e8c4d880d5f9
-       c967183176facd949e28f687f2086f29a6b6c955d64b6178;
-  00000000000000000000000000001000000000000000000000000000
-       2dda65d35ba60b691738ab14de4aa36c4ab68618547f1b4f
-       0db07d9558e660576689ff6572d2af9edd01452072c50fb6;
-  00000000000000000000000000002000000000000000000000000000
-       90a296d7040d9ee0fd061caddf8e617c536560e397e9725c
-       69a73a1e466811b91368ca4791ac75045174f24c389aca14;
-  00000000000000000000000000004000000000000000000000000000
-       466cf4d9755f99cfe79a8d73f0e9274e266e6acae13155f7
-       83b4f7458050bfe285c60e56424314fd6b01a6194fba4960;
-  00000000000000000000000000008000000000000000000000000000
-       93d678400420bd1d482812485d96fdb170b4f055e1bf98a4
-       400aefb2a3dcdda2e48195eca5b600eed2a4c6c70db3a20f;
-  00000000000000000000000000000001000000000000000000000000
-       61a2973e5424ba1c6d3e276569114d4ebdfadf198bdeb004
-       12957492fc5e51fb9f87b5f263486bd6e9030ca493e40b1a;
-  00000000000000000000000000000002000000000000000000000000
-       38e6ce3158f5b500a01c1920345e2680695993ac084b84a9
-       1e11bdc8bc76b33ce64300760fc35e8bca2b8f7f8f708287;
-  00000000000000000000000000000004000000000000000000000000
-       b8d2cf2220f5ab4797feab4ac9bd35cbd2564dcfb099b5e6
-       3f66306393714717cc65e6a61242cc809c1a7c56f03ca87b;
-  00000000000000000000000000000008000000000000000000000000
-       2b402e5af6ef5af420416bf1f5a2ac86576443db7e33974d
-       61313e285d7928b69426ac7310ee16c80138c71adb9acf2e;
-  00000000000000000000000000000010000000000000000000000000
-       002baae76bcd86eda5bc78d008ba23b0d2e772ff31004297
-       ac9e2599d3b76610df2a492191e54ae52f2d1fd0583eb4b5;
-  00000000000000000000000000000020000000000000000000000000
-       bc03714729c9d4d276860ca7654dc3ff0956f84e1bbb9efe
-       90ea6fccf1b49e1dcde379e04fdc02ffe00e30e07d5fed1b;
-  00000000000000000000000000000040000000000000000000000000
-       aa901e454ded6dd58dfeb8204b59bad80b570ccf24cbb23d
-       22b08dc3430cb5ceca63a8a9b39ae41d6fd3dfcf95a1c88c;
-  00000000000000000000000000000080000000000000000000000000
-       b5e0906965a567b3784924265066b5a1756bf0cebd39518c
-       bb18608dc7c7fe6f59d011573234a4208a227f341bdd786f;
-  00000000000000000000000000000000010000000000000000000000
-       ae8b977065e3abf413f592cdefa3d2da660649f0e2f5a94c
-       82899bc15e3efebe9338ac27ee29ea69dccfecd7e649af51;
-  00000000000000000000000000000000020000000000000000000000
-       a0b0a11f8461d83fa6fa785cba312b64367555de2759d4e5
-       0daffded48564ebbe98f69964b4959ea0aebe5a28a3d5a58;
-  00000000000000000000000000000000040000000000000000000000
-       fa55efcb4c907fcef36a43f6c2608639b56ce2effad4f6d2
-       fb02f2826bf087101311832eb00d57a1d771d705ef70e337;
-  00000000000000000000000000000000080000000000000000000000
-       1cc3544ae7b7c2737b6bd7e2ac832d681434326a556df8fc
-       083d876d584412e85543eeee4512f059636c21f7bde4d3f9;
-  00000000000000000000000000000000100000000000000000000000
-       1d4fa6dc25e6fd24a5ff13a30f63e783860c6c671ef428c4
-       90863553710ecfbec99e8b2b415b4e4f71dd88f6ebce7e38;
-  00000000000000000000000000000000200000000000000000000000
-       45beef6f77bfaa83e25df7fd33806a7dc63175fc25c8a29e
-       39fe2f8bfcc92b89431b08d5d9e3788f92fd10b9d5e18e70;
-  00000000000000000000000000000000400000000000000000000000
-       28043c18a7e18389d6d73860977e2cb0c9cd282a267c5b72
-       17cb6c2df1e9b9fa149d0f0785f8f2f263da16ecf1935d89;
-  00000000000000000000000000000000800000000000000000000000
-       4765dfba04c731becb1085f02d4f5eda72689f4bae916ea3
-       5d3068aebac8cb3cf5516b77384dc3416e2b5e8c982bbdd6;
-  00000000000000000000000000000000000100000000000000000000
-       46f68d6acada331052225f714a5729c8116d19076f00ce44
-       e7d20a3ca6208e5f407aa0f94f79bdcf82ad79592a079ff6;
-  00000000000000000000000000000000000200000000000000000000
-       82b3c9ade76a91b3672754877beb7f1a2c87daec16b8667b
-       13edc9289453530b65339df5c6c82c0a31d9e0b90e3ac873;
-  00000000000000000000000000000000000400000000000000000000
-       f36b6f67f121d8bb7f5de602902a9110abc7ff403913f3e6
-       4407a45e633e76537036fece0a3c71c0f15b88027b3303e1;
-  00000000000000000000000000000000000800000000000000000000
-       03deea8338479826f1687012b30423234a36163e4aad49e6
-       9f7f6b5f8dd376aa0716651283ae9f0908f0cb4b34b771bb;
-  00000000000000000000000000000000001000000000000000000000
-       e853a06b951d48565445889b4e320bfe1c6b9084720cd142
-       aae2e8c15f771e0ed58f8a92ef4da29759c38de9565ea06e;
-  00000000000000000000000000000000002000000000000000000000
-       9d1546729f32d2188be60529b218bd703736f74e9f432d35
-       201f67b0162aced8172d99e73ab0a182154f3615f2e28f4f;
-  00000000000000000000000000000000004000000000000000000000
-       07e669da1d9c8e593fda3ced0eb617708f2ac422d43c45ac
-       1cd97e6d08da27f0daa041282df010e0f43908d8dd36b9c0;
-  00000000000000000000000000000000008000000000000000000000
-       6bf530e97b29ece372e7ba9a7831dfbf56d66936e773ff19
-       fa8388bd4a8c495383efebcc1416fd38a139db06a1729f4b;
-  00000000000000000000000000000000000001000000000000000000
-       5d83bb98570d03ed7b6e5288911100680abe75d88c9ec453
-       51b426c7cfa0c0b178ed9def654b7e777164c7c1d945d394;
-  00000000000000000000000000000000000002000000000000000000
-       4747797b044c2fc06cc39bdc2ed894585aad485e039b4988
-       79a1b62a586d5a72bbb16ed12d7b6692fd5526872388ce8e;
-  00000000000000000000000000000000000004000000000000000000
-       9f79507a0960c45fa87e8f83cc6699a4932ba4c15791bcdb
-       4a055efe90785b26b43cba08efbffd9de944028147f471f9;
-  00000000000000000000000000000000000008000000000000000000
-       cb56d08085757939b6542b8a6b80caac7508683cae4752e4
-       73a4795fa9184b465d6a6c3fbb3afee1d77daf4a9b4617af;
-  00000000000000000000000000000000000010000000000000000000
-       765cbda6115109ee35dd5132d1467963c8d01c98c45c3453
-       02c719a0f74edba7975927b1854d3508b8f3ac1208c197ba;
-  00000000000000000000000000000000000020000000000000000000
-       0209e8466c40204db5fdd3359b27e40920c79c1c63c6f030
-       9ffb260428629704470a539de1daa6f7afd55bd0aa2ba9ed;
-  00000000000000000000000000000000000040000000000000000000
-       5738c3f833379616dc030b4000f32d672d30fe2246aac454
-       5b92b0ac5fd6fc2fa16f09c3b561300423f6d85e30e3cb26;
-  00000000000000000000000000000000000080000000000000000000
-       f7675f3bba2be50634a853bba205f33616eba5716513e28c
-       5da69b1cb28398302f5896aefe2013ca82d0435550770288;
-  00000000000000000000000000000000000000010000000000000000
-       d3589f775c28ad54dbc5b3f5fac58c7f714b02a76c724212
-       570c32b8036aea0148294b6e3a7f7645716f4a34a7d391b9;
-  00000000000000000000000000000000000000020000000000000000
-       b3cbc1dcf7bafd4831b3008d60d90bb94ce50ad0cd633bf4
-       d12cfaf58ebb31eb52c15279b6dc2288d403c5095801bf96;
-  00000000000000000000000000000000000000040000000000000000
-       a4fbc80a9d9e447197727034ebe3b15160cbc7cd9f269fc2
-       199b46bf2f636e5cf1ec0f1941a82d8b6d64e1b663894942;
-  00000000000000000000000000000000000000080000000000000000
-       0c6ebfc561c10d994fd1475a2a3675341f7593f9f66cad31
-       6a8e9c8aa02e39174dbbde841585d9e874730a52d61649ba;
-  00000000000000000000000000000000000000100000000000000000
-       25bdd9705ce78a156f3776455ddc4581aa1aec50684936c9
-       ccbe10b3b46d201f199b58c3d19d1f9638d2886e7ce0478c;
-  00000000000000000000000000000000000000200000000000000000
-       613f897e927225132429762e4dda85c607abba9a858c8996
-       f76e01e51cea715d0dff5d54736c93bdfbf019c78a0bdd1b;
-  00000000000000000000000000000000000000400000000000000000
-       65e343dc8bb79912567a55f71e99b3feaf3ee50c427c6143
-       f0d0a8cb38b9d35d3b6aa98d14c323458dcd13e1ce4a7772;
-  00000000000000000000000000000000000000800000000000000000
-       be901e27296d7b03a1a7b96f1cd04fe3082ceae9efc53a5e
-       359b7c239f049c9643aae5cf2d928dbcd5b05a4cee9ac27c;
-  00000000000000000000000000000000000000000100000000000000
-       c4707ac4f4b93bcf32243d79dd30ec29ab7f36fabc2febce
-       c70cff93a2465945e80ff266fa22d2680caa09f4d3679f65;
-  00000000000000000000000000000000000000000200000000000000
-       d30d652d01d6935233b1c345293f0936146cfd487a2601a6
-       0b752affdb6fb51a9e4811e71bcd057d0c586feb5f992e9d;
-  00000000000000000000000000000000000000000400000000000000
-       c5ecb03f48abf44cfa91c989948e4a211a0a8843a74154f5
-       3fc154fc54f79ecdbdfeea0e394341f4f0b9947eacf35ef1;
-  00000000000000000000000000000000000000000800000000000000
-       eac3e4e82fd8888c86cd00b70624420bc40a329308291941
-       643b0abd39245647ecd9b49028267e84a3fa5f4c1528e9a0;
-  00000000000000000000000000000000000000001000000000000000
-       ba153e4e10b7e393efcac79f73f7a6a78717e866110a6c18
-       98e9a632cb6e6ce3b28f461d51d2f95fcb476f25259338a7;
-  00000000000000000000000000000000000000002000000000000000
-       2f5e5111f2c6689c1b7922f13b77bc21d1dcfa0548a365e3
-       7381da06831dad907c647f476b6b7acaa1c4f8bf39f906b2;
-  00000000000000000000000000000000000000004000000000000000
-       29289bc290af03cb098c53e68749b16d5622d3db2f3011eb
-       8844a8e6f3c043c0a6e1ad0c7f2aeea959e314cc794d7481;
-  00000000000000000000000000000000000000008000000000000000
-       2a2993ed185b84670e2bb7aba5ccb4144bff86ca3c3e37ef
-       76d2ab7bf99472ca115b666c932e90d21df5cb555e2d7985;
-  00000000000000000000000000000000000000000001000000000000
-       44a7149685be83061a8141f9f86fb598a2d2489af958237c
-       12d9cd9df6be396ecf0dcb2eea70261db337379379a56b41;
-  00000000000000000000000000000000000000000002000000000000
-       2a54c1eb6658e329179fa565fe8e70dcd325148c764f3278
-       6da20c81af891dc85b8b42aaa370c490e2342d401ed8b36b;
-  00000000000000000000000000000000000000000004000000000000
-       d002d417bb650e197d87823051824f0060127a5d9a80cde2
-       b6858026aee1cefb44780100c66666a157ef41771be03d5f;
-  00000000000000000000000000000000000000000008000000000000
-       c87daae7c988751a47c8b2defef5662711bffcda2b04c68d
-       b9f0df2039ed2a5645162dda2143829d5c4d6e6a3ce2bd66;
-  00000000000000000000000000000000000000000010000000000000
-       82c21873ca16ff6e831d9a630dc8edeef5c0e45233d9e653
-       10115819eb20be42ca003cf7b313446ffb522e1fd1e3878c;
-  00000000000000000000000000000000000000000020000000000000
-       d9209dc4bc41a359f42281e85ae7a815a372ee810992f297
-       38a198719939dd10ff3f978a6ccd182f8a2a7ce6c79f6d45;
-  00000000000000000000000000000000000000000040000000000000
-       7772821616ba97f2cd390075d0d207742eed03e4ef9ae8fa
-       4ba5d91e1ce3f521d1365157de2adc666222c222ec2d3227;
-  00000000000000000000000000000000000000000080000000000000
-       4c49fbe58fa73f8f6984924ee2feb30c11af06b6127c23e8
-       4a5c4b2cf401cdc8a8d42fa2c04065aa52f351b20b60df20;
-  00000000000000000000000000000000000000000000010000000000
-       af551b0b91cc045e718974bdb030e0f2c70c512aa2ea1032
-       a1649d4e580003a845693e8b25388a7b9789126e672548c8;
-  00000000000000000000000000000000000000000000020000000000
-       877e0d6ba70f8642e068805a01abc9f66f6ca53371ee07e0
-       9bad4b2043b8ca9d9045dcad8d3b85c1e7c312f54c93d465;
-  00000000000000000000000000000000000000000000040000000000
-       737a994ba01e24ff5a87cfc942c7e398b9fe8f5c36480f7f
-       206781c03a35312079afa8630dfef2597c886e9a8d6668d7;
-  00000000000000000000000000000000000000000000080000000000
-       f3699997c4c0df71ca34541d9326d4439ea2b6dd194ede4a
-       c9b558da91f88f4fb0f1ae1c462102cef0a0f03b5e001cfc;
-  00000000000000000000000000000000000000000000100000000000
-       258e1e16d13ce49d113eed5aa036400fa1967e8f9e3f2a52
-       8b3e40554cc38790919fbac7dc1ad86334e4df9c2a50078a;
-  00000000000000000000000000000000000000000000200000000000
-       edec557cf03cf9bfa8694c02a366ec44d552bd9034eba4fa
-       905b8240be31313ead25d8380c55f6d1a0df89179884b494;
-  00000000000000000000000000000000000000000000400000000000
-       a655d39d3d8b773c9fdde7c9ad2fe5f8967800a621b91aa7
-       23f9a1388e522b6b7eec35c9f1c027385f2f74aa8d9feaf1;
-  00000000000000000000000000000000000000000000800000000000
-       11ba6f9a3cdb2a23aa1b923c797b5ec61b8f67aecc8218bd
-       f2994709f5fdf5edca503eb14a1b237c272cd7a16c4bb072;
-  00000000000000000000000000000000000000000000000100000000
-       9f6c02ee484726800d87ee458e3c69fd4b44f3a93714a791
-       e489a54780e1d8facf73b69d02dbe550ba970997f292993f;
-  00000000000000000000000000000000000000000000000200000000
-       d11f7985dc2c25d01e3a830c612875b27459321fee2de1e2
-       cb5311c276aa3b8092c9a63b569d6b2c6f5738ed264029fa;
-  00000000000000000000000000000000000000000000000400000000
-       f3fa791265d231b06bf42f5d120edc44c080ae541f58043e
-       0dd8b041c1a3dcd2e9f79fa6b027ebf3aedfed442c4139e4;
-  00000000000000000000000000000000000000000000000800000000
-       21ac1c566d8473defc012313319fc2d8da50af71121186be
-       b39f67818cf2269e439ccf386aa13dd404ff5233b9345e61;
-  00000000000000000000000000000000000000000000001000000000
-       316273fc4a0b6ddd90574335fb8a0a20ed0a0104e70e9a1f
-       832163f88a2b62a4aaf619fea36cfa56d8979011bbb8fda6;
-  00000000000000000000000000000000000000000000002000000000
-       00b5c352659ab100326d110075c041f8217976ed3821547f
-       fb48516c09d9593945e71a141fccaa663e8df96a44eb9327;
-  00000000000000000000000000000000000000000000004000000000
-       6bc65cafae23e4394e970f4679861a2aafeaefe19633bb51
-       875173998a5e5ea76517c0b0a229219e0a5f3700d1fb75ac;
-  00000000000000000000000000000000000000000000008000000000
-       71d385beb370fc18c1d7173cb75b3b1f15d30d8e3ccc7cbf
-       1902091418ff8923ae4d4ea42fe9ce406a2cc5a394def524;
-  00000000000000000000000000000000000000000000000001000000
-       960d8a3ececaae6e42d47d39fea65aa3ecf2d5ab7140944a
-       a981274234e998b241ef58d3424055faa7f701c312b7f958;
-  00000000000000000000000000000000000000000000000002000000
-       5cefd34143969f72981162d8d10bf719973e9fbe7e9492f2
-       0ddeebd6797292c2f539f8f0a82dc646f42cedbe163f89e9;
-  00000000000000000000000000000000000000000000000004000000
-       f70b2d5be4989f4e7711d02c0bc03a7e1a8f8cc605e3a853
-       f7778358e0e77f7f7ef7ed5c41005f49ec91e4d45c3d8495;
-  00000000000000000000000000000000000000000000000008000000
-       89957ec9016662bfedfcb4872c182e648edf00dc59012050
-       b425631c3d6d683c8183590c99058c18c9c3d4cf56d10500;
-  00000000000000000000000000000000000000000000000010000000
-       01edcc0af8796870f0cbc9ca12d1beeae0a693fcec632a3c
-       f848bbcb8b7710c805d884ce13c231f7d83ff63444065406;
-  00000000000000000000000000000000000000000000000020000000
-       960fe2a9d448e5b2ab8dd99ec58a6c07c40b5af464631c34
-       55ae3aa987bdd74c63fd3b0cb5818557dc4f2b886a73d880;
-  00000000000000000000000000000000000000000000000040000000
-       ab20af3c5b1df2a2d9eea9a2c524bbc83fd1195103f76856
-       1826890675b9f2cd2b2af4b1fa67fea727f2b036bbd82d66;
-  00000000000000000000000000000000000000000000000080000000
-       c2261c4fa3ab84dd38c7ec512ac972a05e29b6ed65852e29
-       f941c28063eba8408762134ca5c6132a2854c545d7a64377;
-  00000000000000000000000000000000000000000000000000010000
-       3d9da2d2eaeb97d162cd86f1bb343deda244a304ed9232c0
-       77aaa14ed3e383a2e6c4455797ce6d683a20e280d5ec9ab8;
-  00000000000000000000000000000000000000000000000000020000
-       9a121137759cfcfe9167b57727df46bf5b8d35e54e813ab7
-       2536cd77c22795c50384c0ffb3c667b13ec99de25b8cc659;
-  00000000000000000000000000000000000000000000000000040000
-       8c308d1e799e8e4e483c0ed00a4468d06932c66c7fa66b4e
-       db1b00bb64b9011494de6a0605dd496d5ff97a89f7928490;
-  00000000000000000000000000000000000000000000000000080000
-       ef3da9e874c3c3abe1b6ce46bc78107e5bd6e5d4223c07d8
-       6c942783ad9307f21b698970e99be812ce10bec7282a809f;
-  00000000000000000000000000000000000000000000000000100000
-       e3465e5da4ac75dd663bbe7f59cea84db1d4cd987b659a1d
-       ebd3d5e7fd0495a999cce1d056b0e694cfd1167d277e41f3;
-  00000000000000000000000000000000000000000000000000200000
-       9e115d1a939d05b6a970dcbb27a1d29182117ae6f90a6b8f
-       7a0a4b5b59c7594fac6801ddc6b20ff56e6842ca0ff395d0;
-  00000000000000000000000000000000000000000000000000400000
-       eae903ee25f7c95a7384f4516e88d89ec8423789b8abeffd
-       1442520d0cd4a9342da833f247446e08e200369637db11fc;
-  00000000000000000000000000000000000000000000000000800000
-       134cb0fcb97808665bb77439cc40fcc189067eb89f8965dd
-       b101aa60872909d82906bc746f64d174b8eb2ad70ecf1abc;
-  00000000000000000000000000000000000000000000000000000100
-       2fdf734b5a69c30be8214ad46a0327487d97fa2f694b6f6b
-       87340c26b15fecebe01b98b3b86d3b0d434855c0d747c85a;
-  00000000000000000000000000000000000000000000000000000200
-       17c9d9be32dfb06cfbd47e8467d7464d85366a42fa7b1121
-       71065364320dc8ebf10abc71915b9a37fe13fbe8012be9cf;
-  00000000000000000000000000000000000000000000000000000400
-       b242f3fc2bbfbe89a3f0ca2605244b692ee7d96fca5ec3e5
-       ba5c15f7e1dea1c4c02d81b446b6b97e91d3f27acc3ece9c;
-  00000000000000000000000000000000000000000000000000000800
-       1389f6dbb847264179557e2a635c3f0cd843f5b82a457cf6
-       064d9fb5d2409e24bbeba7e45c4c57156c4fb11f373e76ca;
-  00000000000000000000000000000000000000000000000000001000
-       42f828955b36c547dfbad0c56d6b4d2f623ef52ef7fa2738
-       3e80ab94606fef79fec3d3bfcb8707d9726cbe27233cb419;
-  00000000000000000000000000000000000000000000000000002000
-       e23e23434169161071da977b4620dbe5beb6fa04b47b432d
-       9c1963564bf7a6473027442cb42cef4ef2e248090be98c2b;
-  00000000000000000000000000000000000000000000000000004000
-       e30e30336add2c54af49b3f2d172c5c151eb7dccd049f423
-       b8d3c3935a0470147bff00344d0a9ca5ebd06ea22bfd2d6c;
-  00000000000000000000000000000000000000000000000000008000
-       299e23a4828145c8c2bb7db4819b175ffd57ed50af2db5ae
-       791ff2f9a6f0dc8bee326d9eadd920da1edc5d2a17d327d8;
-  00000000000000000000000000000000000000000000000000000001
-       37de5c10c2e92a137264787163cb8ae954d81933dcf9cecc
-       29ecfaa7a976d0b3dc7edd2066cefe484ad12f9aead252f7;
-  00000000000000000000000000000000000000000000000000000002
-       0442bd68ddf0523120c45e5b858520cc025719fd408d757c
-       373a1aa3eac3bb1b5a96a20e8e65bc41c5894deb725e27c5;
-  00000000000000000000000000000000000000000000000000000004
-       4a6cd629968c0b125350dc0ff1ab3a603c0b93e9a3e56c1d
-       03779efb521048c170b78c8502b166d9fa5813527e504e13;
-  00000000000000000000000000000000000000000000000000000008
-       f4d8d2f1b211988847b5313b5fefb87ad44d824767c22cad
-       647f58392ce955573d3f741ffb51ec3cffb6fdb662996ab6;
-  00000000000000000000000000000000000000000000000000000010
-       980a235b4a173431de984f8210de069493a85242bf14f269
-       1b4e10e4fbba7103e91b9977a6e4f492f04318e3aaba2419;
-  00000000000000000000000000000000000000000000000000000020
-       647f56d74ca28c355462bedce39dc1dd85dad8aa5b1307a1
-       534a6e7b84c5303539ad359bf6c0603f29106f6333df6bf7;
-  00000000000000000000000000000000000000000000000000000040
-       da74d3bc915e164c185021b9085367232a1e10b8d063186b
-       86caf736c5ddc7b3e4c15644a19334fb805ac1d869a88866;
-  00000000000000000000000000000000000000000000000000000080
-       7343f4e043fd65520bd2d84e8c3edb26e617a654f05bf05c
-       e31bf2ac0a70d475260de31778ed39005cec782018514932;
-  0100000000000000000000000000000000000000000000000000000000000000
-       9f5070b134d17734e035f8382ad4c1f61f83a6a9a0667e1e
-       6c64f62e4376d0e962ece7e1aae286ddb0deca287e90b156;
-  0200000000000000000000000000000000000000000000000000000000000000
-       3749a578adb8406d74022aa37e419f6a1fc561da5d11f163
-       c59fb6c711df8e2ab61e9acaf513da8f1c76b91c272a6726;
-  0400000000000000000000000000000000000000000000000000000000000000
-       c8c990a321ea2a6a87066981b4982e89accabb0cbae03efb
-       b7502857ce96c6e469bfedcd3dc8eeb3f0326358bc076618;
-  0800000000000000000000000000000000000000000000000000000000000000
-       73e3d8ac9ed3560c15322b54e30ab8d2c2162f029663c79f
-       260b56cace6aef56377acf544c6899c81eff1a27c5d36f82;
-  1000000000000000000000000000000000000000000000000000000000000000
-       738f42325ef664ec8928bc526abec512b8ea953e33ed0006
-       2090089fd9fcc5aed2612744712dae81c09ff05e5e4d615e;
-  2000000000000000000000000000000000000000000000000000000000000000
-       e8f4aac282194e7e31743aa524f7d9b004d2e63e0a30511b
-       3b6c4ff45cf657d73bfe0ff0725b594a97d75a4cd02eebc9;
-  4000000000000000000000000000000000000000000000000000000000000000
-       6ca217b943cef2c7e222e163bfec73c9f2a5b5674a39955c
-       359b596401604ba4f686b1f81dfbc33e6333a6ab054d9b5d;
-  8000000000000000000000000000000000000000000000000000000000000000
-       ac011f99d6766074346e8155ac4a132558775649391ef793
-       21a191c34b73b95fdec1b26477ba3711c668e7e03b9e72fd;
-  0001000000000000000000000000000000000000000000000000000000000000
-       1bf0e285f67aff5b9e50c33f72819e4954345c81d4bf4d70
-       82e9cf04f361e790544077fded5dc925866c0f6598016e62;
-  0002000000000000000000000000000000000000000000000000000000000000
-       7af6bdf52d8cb70ad56ba7ca466315e9431c9be251059915
-       ab68dab956704aa49dc6938771e720d53afb6c001a9c45dc;
-  0004000000000000000000000000000000000000000000000000000000000000
-       6b64c2b68c3a70c98a3a27d73fde094efc351355708bb8e5
-       b3e7e648edbdce4024fe88afd65bcf79756146f37ba2b523;
-  0008000000000000000000000000000000000000000000000000000000000000
-       bafc3238aebf8a428a560cf351d235dbde917cc1743c94c4
-       2bd0b7ab6759ca6461974b402f77287d4047b6c580ed057e;
-  0010000000000000000000000000000000000000000000000000000000000000
-       e3c12e9c2d584133495b3ad8a93a18303809cae7ac8a5c35
-       01f1f0781ab946f016082703b7a5f0a8e2538e6399fb2a27;
-  0020000000000000000000000000000000000000000000000000000000000000
-       15b55c96181a311f3f7f74f1eb85acd21405e577c99ce7e6
-       7be214ae039f75aff28c25e1693d9509b95e7702100136bd;
-  0040000000000000000000000000000000000000000000000000000000000000
-       ef286b5b57c90b082099f1ba63d66b831c2636dbf89284de
-       405ff3ab609cad17a727f3a32a728176f60738ee93ea4ce3;
-  0080000000000000000000000000000000000000000000000000000000000000
-       6a9f9a517d801e276faed59b37815a0543470f62ddcb36d0
-       6cfd80ee554662542fa45f8619fa8596a5b0fa90207c6e3a;
-  0000010000000000000000000000000000000000000000000000000000000000
-       2c65e60021dce4ab35356c77e3a8d9d489b229961214d45c
-       84fb478f9555f964aa1c963c796afc08249dfa483cea11a5;
-  0000020000000000000000000000000000000000000000000000000000000000
-       6290778c236da149367eff1a881fb693e5fc1577b911bd50
-       fed8ace2fa769e2e59191c11af5981610c7f1d1cd16a63c0;
-  0000040000000000000000000000000000000000000000000000000000000000
-       f3a53dab4a1b2ee51c925c64b80509168fe2c4a39f89eb9b
-       fb14272d3dd9a4a43c3c77edcb2ee13d1c0cf5736c100e3f;
-  0000080000000000000000000000000000000000000000000000000000000000
-       37853db27afa67b912d92274f952fe6cffcea6749c9cf346
-       5c3738ff494ec6280aa714196e4285d78ad3efe97dcbd993;
-  0000100000000000000000000000000000000000000000000000000000000000
-       de4ee75f7a008440578d541a9e9beae7ae6f2ce540682a51
-       aa01dc968b1c9c699098297c7a6230ed03e9d1f8930fba2e;
-  0000200000000000000000000000000000000000000000000000000000000000
-       ec682371507c5eacf5b1c6510338f9979c93480dfeb327a4
-       00a05844fa3d11d1ecfab19b2fed0d6eaebe4265a89c2214;
-  0000400000000000000000000000000000000000000000000000000000000000
-       e1e5590bbbd38ba2e79d7f674c1446517c0fb92ea29d4b08
-       d3e5d1af3b1798d750976f6744baa274a9ecf75c44efe46e;
-  0000800000000000000000000000000000000000000000000000000000000000
-       121dadba2540831650bab205a38ede0f515ffaee7788932b
-       2ae7182cd02fda62b2fca3aa1459f88ba131f5037734d486;
-  0000000100000000000000000000000000000000000000000000000000000000
-       bfcf69c073a8f4110b4f2506e422d57ac27336ca35fc55b7
-       9b92c327f8d3a10f0294570ce6dbad15e63828cce97ff2e2;
-  0000000200000000000000000000000000000000000000000000000000000000
-       f9e64438a44d994229bfc83934b5900cd3742508d8c1e3f4
-       a91cde6622ae50df47b3efb44188211a9cb855dd13f196e0;
-  0000000400000000000000000000000000000000000000000000000000000000
-       02bc24f93a54d95614eb323e668dbb078db65376f8222669
-       12e0a8abaf64c61b674b1e7e80245c8486d0b8b958d23d63;
-  0000000800000000000000000000000000000000000000000000000000000000
-       38fd0dd2508ccaaf72e404c3aa6197ecdebc6bccc2906e35
-       e7178e54aba498545f12beab6f4566d0af8ddd737e1094f9;
-  0000001000000000000000000000000000000000000000000000000000000000
-       6c2bdfe67c48ab3cb5e107ef3bad9aaaf4b7815775e31441
-       51dfedda78ac4f3bd74de1129075f40b6489e7dcef913c8f;
-  0000002000000000000000000000000000000000000000000000000000000000
-       9996e38570d89d1e4c716d17d2d18cace32196b32b13dd4f
-       4d69155a61196d98ba7d4c3760cb5b42ca7826433f767477;
-  0000004000000000000000000000000000000000000000000000000000000000
-       2e5f7b788f621e6e00e568a5d6f6366a204be180a4150c1c
-       ef2f1ced4c859dc6abe9a7797f94474a8c5cc738524cb51c;
-  0000008000000000000000000000000000000000000000000000000000000000
-       225d5651c62b76b58162ee3565c87920e73f8b26874b5834
-       51d5591d45055db3213c2037ea19d19e3f30c57930cb408c;
-  0000000001000000000000000000000000000000000000000000000000000000
-       778f01b3f568dc1cc0190d8a9d45f046ad0d7bd0a2e83bd5
-       a659640486d774d149cfa752fe07f16839ad0a4e0965023e;
-  0000000002000000000000000000000000000000000000000000000000000000
-       07469341cf3d3fa4f1e4503d51b2147eecece66e55a4aacf
-       0f4db2767bcdce2479987e1dee35bce57d3f0c1f064e8388;
-  0000000004000000000000000000000000000000000000000000000000000000
-       fbb5a12272515cb6cef56c3394497f17c295a8168ab7cf52
-       79e3d684921c85b2aee19fd542fd0e326d06db185ed4b2eb;
-  0000000008000000000000000000000000000000000000000000000000000000
-       23b46f278eab2f8cdad836b7a0805cdb5705959dfad8a8f6
-       47e50febaeb4948f0f08b02d8f00ff84b1a4e28741b84be1;
-  0000000010000000000000000000000000000000000000000000000000000000
-       755fc8fb5a4247070161365d075fdca9c315f7ecb9638c5b
-       c0a7a431c614f79e0efa949a89b0a1d3a44b726f75cca6df;
-  0000000020000000000000000000000000000000000000000000000000000000
-       d1777c337f61776201449d5dda39dd3acf48b521ea993028
-       10e87a928e0ef507398afe7f1d3de0cfe3be585831d6b8fa;
-  0000000040000000000000000000000000000000000000000000000000000000
-       ed33aa1685adb27dbc81bff9211d9199feb400b8084362b2
-       c75e37d353c1cf37451eeb3739c92d3111e5e6a95c3f6a1f;
-  0000000080000000000000000000000000000000000000000000000000000000
-       bc37576aeb1bf24f50806c7b96cc3ebedf64f5d444238cfe
-       ee28dd6263ba7f0cdc8588aeb27563e83dd26a66c519a3ff;
-  0000000000010000000000000000000000000000000000000000000000000000
-       18a038c2820a8f3e7df91219c8937a403fc5b04476b5b00d
-       9e3908a1ed2c0d5b7d8ca231a0e9d965c5bedd70c2e91782;
-  0000000000020000000000000000000000000000000000000000000000000000
-       266d38db2332f7b5aac71f5e9c4f201abb66e07d3e0f33c6
-       aa256588a4aa4bee6595a18b9083ebd7b4e33adb2f7f3112;
-  0000000000040000000000000000000000000000000000000000000000000000
-       4e456d28fdb91a55600a0f0a940ff6a23e99a7ace2302257
-       7faaa8ceac5fdb90aa67d0cbfc3ba885c19236ccede0267c;
-  0000000000080000000000000000000000000000000000000000000000000000
-       b7e154b0cef10b51c0c37d92d1ee18f87e9c034bef605109
-       b953b77fc877b9877c566c04077eba7de5ce3712302f5bec;
-  0000000000100000000000000000000000000000000000000000000000000000
-       23076ca9ba4b66fd5dad468e32b6aabd89157dd9484de084
-       afe987cc7c00e457432b4343130c0efab5ab5bde088a8b09;
-  0000000000200000000000000000000000000000000000000000000000000000
-       ba9528c919d59237d542419e822ea53d44d7709ed8831393
-       a46e0010238e90da8a824c99e48ddd516b53d1b58babfb67;
-  0000000000400000000000000000000000000000000000000000000000000000
-       a45c47b8b5d93ac468ce2698c4bb818d18cddd27d3c90ef1
-       05d4636e0dc06295cf47fbe08564a1a890d42be50da9a712;
-  0000000000800000000000000000000000000000000000000000000000000000
-       009e53d4f953ad0a4e3a6f424958319f9b0ebcd4eb32e6b7
-       b26f95360e1f006e78c56c7bdb60aa517c08b6b353ef3954;
-  0000000000000100000000000000000000000000000000000000000000000000
-       60beab9429813d3bbc70a65f440af15b1bcec02ab53e3b17
-       25eb48a26dc3ec9d67440f4adfaeebf3c851cfb774f5d9fd;
-  0000000000000200000000000000000000000000000000000000000000000000
-       8446b9d837207ac194d094bfa5768dad1bc7ac62b507d6f6
-       b93872a3955bfcb3a085def48e48ad7468172a3ef1381296;
-  0000000000000400000000000000000000000000000000000000000000000000
-       b18d63b9b8f957da2cb1d8315958058f607ee9aa10803040
-       f8fa5297afba5460f910507495a4aa3c03c08ccbe658173a;
-  0000000000000800000000000000000000000000000000000000000000000000
-       8569811b5e86046299507b8f1ca054bbd291997c92120b1e
-       56b1179f4e1abf339b12b0c9a05b428171dd207e2f90e9ee;
-  0000000000001000000000000000000000000000000000000000000000000000
-       b2641a18af6dd774a608b6b7a498b5962ea67f5b52807803
-       7a7e0f1cf78a9fa1421196d03455525341514b24dcbbccb8;
-  0000000000002000000000000000000000000000000000000000000000000000
-       5ee40a1926ada020139789a195f1d7fcfd8339a5905d8c91
-       bcf4d04a361be5738498700a057b6a767af995b1ae9cc990;
-  0000000000004000000000000000000000000000000000000000000000000000
-       97fc38aa8fb864828a1f8ae469219da97ecc1d352fd8478b
-       fbb3e38a2e3ae33ce7cbd0d9ef4278ecbbca11e5571a21b3;
-  0000000000008000000000000000000000000000000000000000000000000000
-       ba1314e36083bcbb1f01a1b0dcee1c5167d95058d03cb298
-       9c1f480bafe7df16d6ee5d5e44296998acbed57fa981cc8d;
-  0000000000000001000000000000000000000000000000000000000000000000
-       d1c445fbbb6c11b248816ee124502e8d9a44750df0288c84
-       bde77bc4f65398b2e4385be1e459925ab0b29fad2e2ec1c0;
-  0000000000000002000000000000000000000000000000000000000000000000
-       91e1b29bac8b3004b7e0a3c4df1f49131b73cf7ee9daf237
-       e6838a7e1686dedfb4f590be43684645a9b1b4d41178368c;
-  0000000000000004000000000000000000000000000000000000000000000000
-       a618c81acb2f8ffa633fae6f430d849213633f506ecfb4a9
-       4fb027cf52b913a04d493a225be16d06e8bdd2e335a59f11;
-  0000000000000008000000000000000000000000000000000000000000000000
-       425ac642bdb172b0d8af9b5e8733b4138f9a8b73c53e78df
-       fafc2c7ef14412e28b3091420e524b7a617fcb79fd7a2333;
-  0000000000000010000000000000000000000000000000000000000000000000
-       bb83697c816b291cbeacef56116984f1bcac5d1185a96046
-       94ef1fed71ae8838ea5dcd1fd87df10aa5dfdaf7247b20f5;
-  0000000000000020000000000000000000000000000000000000000000000000
-       b9a35b83d2fc63f3a59889ed2464ad35fe2304bc8b243620
-       c072779c8f7c58b5e54f87de26ff3e8c9bcbddcd843d0ec3;
-  0000000000000040000000000000000000000000000000000000000000000000
-       d5ea0b3466ac121ad1117536c22443eb6206c8f0cb129db8
-       2d3e46147b3d926b59e2d3d848a519ae9d0dab3002c7a447;
-  0000000000000080000000000000000000000000000000000000000000000000
-       efa22fd1dbb1fd3fe8b4713b358382a3ebfb7971d71c619b
-       db33941cff2f3ba57574a6babe30d3a2482fa5fabe541248;
-  0000000000000000010000000000000000000000000000000000000000000000
-       ec54918b940cca8540c84dfb4951115e41eea879f69226e7
-       c3f4bbd94a5f8ab825e14d399d1d63b419b920a985eb537c;
-  0000000000000000020000000000000000000000000000000000000000000000
-       882f20f80febf9a64f8513d9da4a84ed12230066759e0baf
-       171124ee711829702478c993e0a69614a5fa6abe5693c757;
-  0000000000000000040000000000000000000000000000000000000000000000
-       999b241ea0f1f9d8291458bc1706019f2a62597d2e08e808
-       afaa8b4bed7aec429f62ef6bd157ea1b0cca67b539d35f8c;
-  0000000000000000080000000000000000000000000000000000000000000000
-       9d1c95595d1c8b43b32dcbd7d157ed0cc500beceb9ad7dfb
-       cfbc5738f8c2d1fe1489aeb853e7afe75d3228e820e5d1f8;
-  0000000000000000100000000000000000000000000000000000000000000000
-       939c98efb6a332bd0d106b0ad73c7bea3b27509089a9b3ed
-       f8ddedef92e523ba101a8cbc3f5910457b4c10f632ea8c1b;
-  0000000000000000200000000000000000000000000000000000000000000000
-       62260cb25a9c5f13da85ba16c781315e00fcf91a14ecfe7d
-       4a81f4764d73cff0c6c598bb14d03dbe7456d84480b3d97b;
-  0000000000000000400000000000000000000000000000000000000000000000
-       d13026196c4648cf6eb48ab504801dceb09c184da5d02206
-       ffdd66bf5a8ef884b365ff79cb468a07483ce1af9c781ad6;
-  0000000000000000800000000000000000000000000000000000000000000000
-       1950354058a14fa13adea19ad18be46eaeae9d314400ecc7
-       3911826bb13fb45bcee0680c2e2988d22c404120b67174a4;
-  0000000000000000000100000000000000000000000000000000000000000000
-       cab6747886cacbd533a4a28581622772ca4026b7735cfd62
-       1e03b32dbe480ae229b614d23e1d0ca3b4089d622b525960;
-  0000000000000000000200000000000000000000000000000000000000000000
-       c258d3ab881322905a693d6eb560b14c93c6e1f1ace6cba3
-       ca58904c0affa64dc2fc1fd744de880eb86876a93c30c04e;
-  0000000000000000000400000000000000000000000000000000000000000000
-       d059b736116667cfd8f94e294252ccc57adfb59c7f2a5f39
-       2f3e359bb0ae9d420049351b1b256049f61ba52996f08036;
-  0000000000000000000800000000000000000000000000000000000000000000
-       8b8c9610ae81e48055eec551f0d52cc552b12753c6bb7924
-       fc2c7edfce13b888076c6b8932a76c00aed86dc34bcb04a9;
-  0000000000000000001000000000000000000000000000000000000000000000
-       95f736d9848960fe82200410199208bc50bff3776e7d800a
-       01da25ce699dad03299a6b2f02422deb0296463df7976a1a;
-  0000000000000000002000000000000000000000000000000000000000000000
-       348e25a9a47f7371785c033e858054e8b84b4aca450330bf
-       46e40e1b342b0197a6c9823810b563ab162a4afff3ef8d3c;
-  0000000000000000004000000000000000000000000000000000000000000000
-       398d57d71fbbc564ba40316a04a78661be30188d8a00a9c2
-       1dc6b4d53c6cb47c518a07e6caf6aebb60879202c2902404;
-  0000000000000000008000000000000000000000000000000000000000000000
-       8c2ce222b3845769ac1b5c6087a4a78767bb7b5b6db0b844
-       386089aa0f982dab5aec5ce3c0d6c22e57850ef5dad854d5;
-  0000000000000000000001000000000000000000000000000000000000000000
-       367067c67a278f8da0b6d95e01e1300c4ce4dc4564643a1a
-       d9f7b526134055e0863b763367ef09c4999b3d3f7478f2fc;
-  0000000000000000000002000000000000000000000000000000000000000000
-       c4531ccef569e7ac3fe27aee4f9413a5ea932d077eafe749
-       f8617cd036e260fcf3cfcfd7227ae8ec3823dc1806a5186c;
-  0000000000000000000004000000000000000000000000000000000000000000
-       b23ab66b0a48a91976906f145c49acf72cfa24a718e29d43
-       db0602809ba65f935b2b761ac68698f44ab52e3073318480;
-  0000000000000000000008000000000000000000000000000000000000000000
-       84e2f169348f9c12292bae0e4a411c04bbae0dae1010c6fe
-       abb60974909b46172f0ff9f8d3e0c1ac90e354ef5d8d4b96;
-  0000000000000000000010000000000000000000000000000000000000000000
-       178f1df13876d9aabf1d7567a9ac8548033ab879cea6c62d
-       e8275ded5d48c972e53d5542d039c3c0643bc221ec7ba6af;
-  0000000000000000000020000000000000000000000000000000000000000000
-       df2371204f0d5fb0d345feacc299424b1f09c4fdfe740b29
-       1d7867481c4958a1e96b74d7564fab9081826baaef1c0bc1;
-  0000000000000000000040000000000000000000000000000000000000000000
-       85f193b35e480c86febd733e3d73c5e533f5af5fa670464c
-       aa297d5e92606023fcd76ff39b447bd6f8b528d2eb8aa389;
-  0000000000000000000080000000000000000000000000000000000000000000
-       3c7e3ef5b75bdd8c4ebf0ab567fa9dfab7b14f65465d5202
-       2d1d772ca4e8c4627d10252c17f8de9fe4eb5f2410036f8f;
-  0000000000000000000000010000000000000000000000000000000000000000
-       7946c21f3ec9019663b088701ec2fe303a91473d66166c07
-       e0781ca73a7ba4da909faabd4ac41a9d2a04aee40741a362;
-  0000000000000000000000020000000000000000000000000000000000000000
-       bdc80943ef24005d2b2b9cf4a622cdeee6052c94028be903
-       c1a5cf266e621e1dc67f7d95e8d4a0352abbe6906e2509a3;
-  0000000000000000000000040000000000000000000000000000000000000000
-       a363dfe9c29405923502bb20f0ca9433d2bd2e935bd158c6
-       73ecbaa847e33990a348518355d24250d78ba4bfe0cc6ec5;
-  0000000000000000000000080000000000000000000000000000000000000000
-       91a79788d280aa0f726e81b5e120fd0d175e9f835196013f
-       417a49bc83ff1cae0de19f5469644fdcff16a19b0c48e2ca;
-  0000000000000000000000100000000000000000000000000000000000000000
-       4899462607deead1c0bd532d7aca9b707ab2e7fe0e29b590
-       a81d309f9faf421664ba046616b4dc07c918d857d3d84905;
-  0000000000000000000000200000000000000000000000000000000000000000
-       0aaae126611efd36cfaabc703328ce88567f1e1ae8d98ab9
-       642e95674700002ad5aa27d465b538e764fe7bd9c14c73aa;
-  0000000000000000000000400000000000000000000000000000000000000000
-       89518487c389f394664d1db1e9110d4f31ee5a30ab504538
-       9096525261c9c51132a575c2fa95ec45b126d1978b3c8f0f;
-  0000000000000000000000800000000000000000000000000000000000000000
-       48a115999ac4106147c25c8af6490e3f864fe07a4aa0814b
-       6034cf7c5049884a7251bfe1e908db7ae5a242bd7528cb80;
-  0000000000000000000000000100000000000000000000000000000000000000
-       f4a37d22f6ccc6807c77a2b00892c34f751e6af9d507b7f2
-       f05a07fe2964989df5de5c5568f0cc2a4cc385a0046653a8;
-  0000000000000000000000000200000000000000000000000000000000000000
-       504eb8d6d794ad17fb17701daa68a27909c10b07db35d59c
-       04d1a5d0a25f37c358ad1544a61c35e3b27bb8e872a66657;
-  0000000000000000000000000400000000000000000000000000000000000000
-       df0ad9ae9ea8203f839254c51201e4badf59280ec5791f21
-       60d514f1dc0ae5f0041b7dc951c2b7878620178f6cdf40b5;
-  0000000000000000000000000800000000000000000000000000000000000000
-       f134b86ddc24cedefa5919802e2ee4a1b8b3dfdbd6d4707f
-       a2a6684093c8fc7fda6d78137007ed72ae90c2bdd5457351;
-  0000000000000000000000001000000000000000000000000000000000000000
-       c1227e56f680ff943c4a6eae53aa8c47603dc225a0770151
-       20a18398e209070d630fd66253f8198d838c133fb8b2877d;
-  0000000000000000000000002000000000000000000000000000000000000000
-       618aed56a6e67024f44a5182f8b3a0429f1f816e40d36940
-       f4a5ef442826ecf4f7b51af42c67ca6efa9eeb05c950d0e1;
-  0000000000000000000000004000000000000000000000000000000000000000
-       993f917a093d0593ffef2ee61717769d0310a338971ad5c3
-       633c510c65b17337fa6600f7b8c587f06cdbce7eed021dcf;
-  0000000000000000000000008000000000000000000000000000000000000000
-       d08c7506bc96104784ffd62989f3e7f14b7941408aff19a9
-       4ef7c78afbe041881669a436f0b3a2c175bd1872d417f427;
-  0000000000000000000000000001000000000000000000000000000000000000
-       e4c926c1c6af627ff4aea8915cbddf2d51fea4f8efbc84f7
-       297dc1f8f2f34488496c0a7315c434545c2c356da2f2b8a8;
-  0000000000000000000000000002000000000000000000000000000000000000
-       a1d9f20b38fc8ff10284673b5401b340d3606374c0705387
-       538fac79ea64656d7b752ea715238b7168b7fc3e3c307e79;
-  0000000000000000000000000004000000000000000000000000000000000000
-       48a83c0d5aaa75c08186e0c3b43c12359d64ef6c5b51178f
-       ae4c16dbfd40480fec24032f13ce1ce1ee236785754befa4;
-  0000000000000000000000000008000000000000000000000000000000000000
-       98c9f42280dbba13cc6058bcb1fc101f535c17ceadb39384
-       97c2fcd700e5ba4010191d1a2bf39b94ef26c1f10eb5dea4;
-  0000000000000000000000000010000000000000000000000000000000000000
-       6e5185272ea765f9c63e084aceb39635fc7064c5500933a4
-       789c9eef18191c6eb37ff8bc61737be04cdb38074cf16342;
-  0000000000000000000000000020000000000000000000000000000000000000
-       f1a2076d13ea103ec3bc2a7981628b6c46b7e05ea2b8cff0
-       1c960f47235aa3c2f7db928c79eef79c1abb58df32be0519;
-  0000000000000000000000000040000000000000000000000000000000000000
-       2a25e1c3d40e114369c652f39101b149ad121e1e297568f0
-       39a862fc9c7501571eebb68fda325a20bfbc18b8d1dc06a2;
-  0000000000000000000000000080000000000000000000000000000000000000
-       4c368f98b55ba57c8a9f50143c85ba209f46b19a287fe96d
-       805862de2dbfb0b5fc8522fe1775db56cae5d782c5ed78fb;
-  0000000000000000000000000000010000000000000000000000000000000000
-       a0c97c9e66701e6478fb012dc563dcbb1f5c6da5ab22e1c7
-       7deb07741bae22c3a4e245df6f6f0ea157e8c2fe11277248;
-  0000000000000000000000000000020000000000000000000000000000000000
-       c1aff5f111b93662f2101a991dc73b3c6ae24a7305ffe5dc
-       0c4cda55e6b291dff5fd90fa1b5fec0d74e2658a9fb8be12;
-  0000000000000000000000000000040000000000000000000000000000000000
-       2f7e8a0ccc58df1c6241c31911d531e9990eb7849c9dd986
-       57a80345e95f8e8f0c235e56e34b0b92bb6c3f7d1da32f1d;
-  0000000000000000000000000000080000000000000000000000000000000000
-       22bea653be4b485e68b8579537213762f44e42f6d810a498
-       7c4fb10db02107f924884cc1813fafc08800fd616c7463f3;
-  0000000000000000000000000000100000000000000000000000000000000000
-       d7542072c23ba5a53a81ef80fd2e18a4fa4e797ff6600040
-       2a7bf2b00a0e7248f754fa91239b22954286887269c33386;
-  0000000000000000000000000000200000000000000000000000000000000000
-       67cdb364f19b764b08f2fbe24e0d8f5045cd24643068dbb5
-       bdcb57ef947437c8607c456b12a0e35dee06a72ddc6b39bc;
-  0000000000000000000000000000400000000000000000000000000000000000
-       4b69f9d96da82a8e111ba914616b8181351b6c7378c398ab
-       c3c93b51b1523b3d5cff783005bc32aebb490df5dffbf54e;
-  0000000000000000000000000000800000000000000000000000000000000000
-       9cd63826b5c968a2b91637f08960fff1db80be3e5f4e1b10
-       37e40726553084bf60ccfa589cd5a7ad328a9d2731b07c22;
-  0000000000000000000000000000000100000000000000000000000000000000
-       9e35e64ebdb49e1eee17085264da59b066e3bbe33369e668
-       e700e349d9ba81dc389c9ea47ae3397d2021cbb0a1dc3f50;
-  0000000000000000000000000000000200000000000000000000000000000000
-       d01966c6c3c1743b53cd852ed40141a122f10191b1c31a86
-       cbb249292e1f8720ed8bd068e08d00e58b5b6ded6db35967;
-  0000000000000000000000000000000400000000000000000000000000000000
-       5d22197b1f31e555244767a519cf1612dcb1e0c389dc5e85
-       6c356e034f76f45d77eac2372b1b8d13fe37a9793267579f;
-  0000000000000000000000000000000800000000000000000000000000000000
-       7a6346dd4b48c8e2578dc9e44cef59b355e745603ad70e56
-       e0ad6bfb7dd04c50408813e9ffc253a786a79f322270e3c7;
-  0000000000000000000000000000001000000000000000000000000000000000
-       cd6744a38f58ff1565c63b618f6d4602f48424ef96cba9fe
-       223ebbfcee0d2261dcac64d4457563e8662cead4f842f885;
-  0000000000000000000000000000002000000000000000000000000000000000
-       e7181dde8f2bb5257724386d775d816db6ba1788840b2ef3
-       ce12f93c38f34c761b6290ab661bea7a94d7bedcce619c42;
-  0000000000000000000000000000004000000000000000000000000000000000
-       35144d4cd483e6ff784cdaba5d8fe43457400002e50652b5
-       c9d58b472c45d4a0bc60c5f068babd4761119b8411392863;
-  0000000000000000000000000000008000000000000000000000000000000000
-       49e3852d9ebf4a20761f9e3cc5af7079f92434f3cc0498bc
-       b5111d55ae21a4dd1d94208eb1e2bddc2121792c0865ea1c;
-  0000000000000000000000000000000001000000000000000000000000000000
-       b5be1b964131cf4bcc472ff83c7175747c0a8142a1b592cf
-       82bd1f73170e94ea2dd2533fcb2e10b86d223ab573b7acb5;
-  0000000000000000000000000000000002000000000000000000000000000000
-       436643b8310b2f8012fff1718d811445febcb62174eeaf89
-       4d73981253903319bbf05beaf81b161b5eda9da17a6c465f;
-  0000000000000000000000000000000004000000000000000000000000000000
-       26fe5bba90ad70222b6e0dfb3f910225dfd1d94e8a6eeeb1
-       e50c6fed998ff52d18c1cfaef6486c7dda0353d609893ed2;
-  0000000000000000000000000000000008000000000000000000000000000000
-       167ca811688841bbc017aef57f046c72c89cfb105675abd6
-       474b913d96b3065573859d90259e7170ed086c7e85e6f833;
-  0000000000000000000000000000000010000000000000000000000000000000
-       2241fe3b5601c4f8691132f7fef47b2a705ee925419fb2b8
-       e4f6a1a195420d5be230460d72cb10e0d5fa98e3473dcddb;
-  0000000000000000000000000000000020000000000000000000000000000000
-       f73edb64726d1038febe1182d24c9df9ac4c2e44d27350a1
-       d023f50e6c5815af9f68c18fa011c72a0ac1de37ba50052d;
-  0000000000000000000000000000000040000000000000000000000000000000
-       414f12c0bd23b6541fe25e485c99ce83c5d29d5284c6d635
-       b9be932cebc3b0451aca78b190970be486bff89022dbdef8;
-  0000000000000000000000000000000080000000000000000000000000000000
-       9cb48ce5c9bbf7cdf172e72b8ef47ee0b9954d4d83f64e85
-       ddbad8bb1b68dbe0d1c2377a9f851cdd40941f1e8b17a72e;
-  0000000000000000000000000000000000010000000000000000000000000000
-       9ad04eb679eb45041adb6e18229ab8ef134f96b9ec4efa8e
-       af91847fd9a9b0853b5adc3952ec93b729931bafac0960c5;
-  0000000000000000000000000000000000020000000000000000000000000000
-       7fdf8d84ca1f1ef75921d13340a8613a4abce59f8e6719a0
-       048a8092055d9bc71038c2adc3fc74a9941b1bad6bb0d748;
-  0000000000000000000000000000000000040000000000000000000000000000
-       3bb8a2eede247347d3293a7827b935696db66633154f6eb8
-       6da269df5b0af347a91ef471261dc6aae07939d7562dd17e;
-  0000000000000000000000000000000000080000000000000000000000000000
-       76cdee34adbfe476b19f218ad192ff91cc764594ea84e9e9
-       b89d091dbfdd454d3de741971939aa47c84b65e5601ed69e;
-  0000000000000000000000000000000000100000000000000000000000000000
-       a5be84ab2131cc15fe88214e692c2a1c93649c302935f68e
-       74a065159a3a25b7beab96afda6cb4a15f0f0974650825d2;
-  0000000000000000000000000000000000200000000000000000000000000000
-       a1c10a2b8f9117b9c7d2bb4a4b8fb19ad5862a070afb8f34
-       11b10a5b03c2e735c20aa91c796a30e1e5012eea5d17a2fb;
-  0000000000000000000000000000000000400000000000000000000000000000
-       f30f479b09b7078984a91a14766ca5331ca54f237e832e00
-       2754d3cdeb587cacac85e5b9bc2a8df745b72ae84c83e30b;
-  0000000000000000000000000000000000800000000000000000000000000000
-       f15256ae559de534a46259c458ed699763917bb67c42caa5
-       998dda9353cad5811b4d26b418d2c36ac8241cf9162afcb2;
-  0000000000000000000000000000000000000100000000000000000000000000
-       e9dd34edf9072580a9e6bf92f517160410c41b28056a8acd
-       0dbf466153aff0de4e09a06fac89bde833afca483a514c02;
-  0000000000000000000000000000000000000200000000000000000000000000
-       a3af6ddf33c781ddce6b0033eb3afe64149b1e22c3298b6d
-       8d18a7ab3755354db7ce3336d2ad1870d83f84efbabf3f1e;
-  0000000000000000000000000000000000000400000000000000000000000000
-       943acab0e9cf4ec9267798ec18e96ea9c4953d194d06572e
-       2ce3b4bf975ef64655d8bf4e56016cb2889016c1884d649d;
-  0000000000000000000000000000000000000800000000000000000000000000
-       b150a772fa4e01a865d822ad9f08e192a2f09e10ba815686
-       d4e5f4ca1ab70dd9ba5b5af2efaa89b3a273cc13dd63bc5b;
-  0000000000000000000000000000000000001000000000000000000000000000
-       685d0a283480caadd55b2866fb4a0a41b6c7cd10a178c267
-       4e8943a076e33ac2517b897f25f5e1b946a421676d59866f;
-  0000000000000000000000000000000000002000000000000000000000000000
-       6adb8fb9971688de77028f21a600d2ec2e7ea7469aa68f49
-       d25f5e79e204a87897d24530d30e7fd55f852298fe41b993;
-  0000000000000000000000000000000000004000000000000000000000000000
-       34e213c058fa256f43ce41f0a636f04d6de70d66fe58fd7b
-       b5a6056e1a9fe00af39fc4f6dcc737bfaaf953b94c3d7d62;
-  0000000000000000000000000000000000008000000000000000000000000000
-       acfa06bba285a64d49b3e40fa21a87807bab2e1b8be93dc5
-       9c607c350a79fcb9c3c08482a9899662911dd9d78241e5af;
-  0000000000000000000000000000000000000001000000000000000000000000
-       af8fe6e769d9a9de9103857c73cfc48caf07a0a162a9c84e
-       badb8bf3e3901514c364d5ab4fd71dbb4adafc33a57e0dbb;
-  0000000000000000000000000000000000000002000000000000000000000000
-       03e0acc3efbcef91c181e6b725efe6d5988aa3fcf2d97918
-       3562afdb394cb6c829361868d3fe9e2a795dc73d6650c385;
-  0000000000000000000000000000000000000004000000000000000000000000
-       deefc043580767155330551bbb6aefbfeb83f2a53645534a
-       c8162770dbda0fc2e009cbc088d52b75e0c5b3d8c3aa935d;
-  0000000000000000000000000000000000000008000000000000000000000000
-       ee46ee36468537d3eb9a8712e6ac1658c502a2ee5f3b9dab
-       9f7aa36fec8e73e4e31f29bae48a0484eae73f9b1afa9eb1;
-  0000000000000000000000000000000000000010000000000000000000000000
-       f724e6422f7b27fcb8f589d2c1303a57c1a029486a5049a9
-       04ba1444c6b13adef4ca56bfd9723f32813dd2e96f7fd03f;
-  0000000000000000000000000000000000000020000000000000000000000000
-       3fa0e90f02790b3a69e7c89a13d6237f2673e06ee8350c6c
-       68709de5c53ea86e2ddf950a5f9accf42013439e1528ffc2;
-  0000000000000000000000000000000000000040000000000000000000000000
-       dd0a534025a9e27706db2a670c60f0b02dfc511b1b96bfd3
-       195469451086eeeec709c9906f70dbb4b1f69bafbf3764b0;
-  0000000000000000000000000000000000000080000000000000000000000000
-       a4da0b9a38fef97bc79f467b2f3377e146dc3b15803892d8
-       1a60ea09b20c6f489204d8118b122c5867833c7ef3bfae13;
-  0000000000000000000000000000000000000000010000000000000000000000
-       4ce7a4c772c8f9ef1e4fd4702305e22a16658796d594c785
-       2bc89b262839d2e7c5a4d6c6d54d2c12c3b6f393f74911c5;
-  0000000000000000000000000000000000000000020000000000000000000000
-       f8bbca32a6f4757c7f11f4135ab07d44abcf888c01104279
-       92f67af3b9e25a74c087616ff87b74940ef2e13bdee48a8f;
-  0000000000000000000000000000000000000000040000000000000000000000
-       d7a63b5010a345f136e5410666d62c0d0db6c72a14cb0e40
-       480a96adbe7e4e18fb726976e153421b959e118d53db9782;
-  0000000000000000000000000000000000000000080000000000000000000000
-       1e73ce2be743ce28821a6f9fa91746ec106e6027ee10813d
-       4c295b3a21cc9e8fcc591dde212cfd4813bc12add97b6c5d;
-  0000000000000000000000000000000000000000100000000000000000000000
-       3eaf2b1202ae5b92708c0ebac3f190c3716ef8c42f7e3eb1
-       5cd7adf3e81c0d0362b0b2d6ff1ba5a8c2bd1adae8e3750d;
-  0000000000000000000000000000000000000000200000000000000000000000
-       5fe4c2d04550aed6b268726c60e2a3bdaee377ce8dded8f0
-       3c1c3483e260bec348c8e0efde742b41d16f75054171b1ca;
-  0000000000000000000000000000000000000000400000000000000000000000
-       4571854265e30e3b8f55932f432def3e8c817608c600871f
-       290bbe7940b15a6f592caf95508152e4016adb9a5ad04a90;
-  0000000000000000000000000000000000000000800000000000000000000000
-       a1955f1a9e1c293f46422688b749ddaedac0de5392039212
-       2eadf68986a238b85ab9576d1fe2fb8dc0c166f574ba2019;
-  0000000000000000000000000000000000000000000100000000000000000000
-       c0382ec488cb6cd0ab2ed8079e57229ca27219138da9ca68
-       ed3ebf43bc1b7b5f4ee91e71d07b2cb4eb3f661cfc31b8ab;
-  0000000000000000000000000000000000000000000200000000000000000000
-       22eeabdba671f4cfe635b615c4cb4f759263bd01ee087152
-       8d38f4ef0fd7b17469f70779e40c45a58b862d81bcfbe619;
-  0000000000000000000000000000000000000000000400000000000000000000
-       10da653a6533ea959ac42304fee9983a673ff5fa6e5fe9c3
-       9f253744a1337662c662f359128b5446ea5d9f24c0bd9ec1;
-  0000000000000000000000000000000000000000000800000000000000000000
-       ab7f47fcb791cfe0d6fe82904f63653e747b8930bed679d4
-       862e7a3bd1cad80aeeec6510428e173529e4fd5b1385b8f7;
-  0000000000000000000000000000000000000000001000000000000000000000
-       2fcd824a19c499683a7c43edd5f5e930d5ada53282ab92b5
-       ba1f9df708477b5e0ffafa8e17af2c78b45ea8dc9f960ce0;
-  0000000000000000000000000000000000000000002000000000000000000000
-       8ac9cec56baa8ac099a09910199e1bd22b8a12b35b9825ad
-       1ab5db73d52b33050688969f6048d74c1f39e1a019481850;
-  0000000000000000000000000000000000000000004000000000000000000000
-       a2970217cd733f9e3a2fba569b5c69549b1d85fa0762065e
-       ae252ce23450578857e504ec52b91a452a44ee6e284e2fd2;
-  0000000000000000000000000000000000000000008000000000000000000000
-       f13b417168c5175dc741d3abff665b90323806d25a7ffd1c
-       c95a2a90eec8869f2d9c3274fc5c23ada2d19576ff61ee70;
-  0000000000000000000000000000000000000000000001000000000000000000
-       5fe138aee8e0a7ae229395928700fa9a37f51ae1ce8a7d9e
-       16bc8db3599524e304c3b1315c953e244bf106019952f465;
-  0000000000000000000000000000000000000000000002000000000000000000
-       072a6b141853fcd7c03087fb051ca86c2999e287a19acc06
-       6e39c731cafc7ab8cc4302937a6eb2f48d5b69f59a8ab6c9;
-  0000000000000000000000000000000000000000000004000000000000000000
-       6e61abf961c86ab5d8ff5fdc86fd254077c50b20831af694
-       db7d8555b0499464c07e8046d2424702977304ea2ed3dfdf;
-  0000000000000000000000000000000000000000000008000000000000000000
-       c554b1f1bb02a20c71ccc3a5844cbdaab6ac6065f1981773
-       3ab9f2337b4b69e8cc3074bed8ec371642f191e4a504238e;
-  0000000000000000000000000000000000000000000010000000000000000000
-       51b3412d7e6cdfa87026451d611b398963ed0f7914be657e
-       8b4c78acb1464f76d7217ec4420c84ed8914426b96e995f5;
-  0000000000000000000000000000000000000000000020000000000000000000
-       4e2b6793fbcb06050191865e6cd61abdd7f3cb3cfa0a198a
-       40587eccc2c8c15bd735fc22c776f16c18c019fb7b4b04d9;
-  0000000000000000000000000000000000000000000040000000000000000000
-       9e32130b3039abe1c5e5b26c41e633218e7e17be20463769
-       52e3af3dd33eb613e5022c26a0e97b3a43d983db2dd3d8ed;
-  0000000000000000000000000000000000000000000080000000000000000000
-       c18d4991afb0f844fe4430eb4ceef9600f0707f526d50cb1
-       60f22bca3934262d0d4d8f8118df4325b2440a2cefec2c8a;
-  0000000000000000000000000000000000000000000000010000000000000000
-       ba1c2f2d4855d9bffc68849e061cb23af605aad9e1ca459d
-       3f9c6666ca2497aba5f22dc6d49efdb97e63b7e05de5f3e6;
-  0000000000000000000000000000000000000000000000020000000000000000
-       a58dadf4b734ba815d34bb5fc543b46db3b427f2f4d89c3b
-       b0c10ef8e3a3ff48c57b8f1b60d0b10b5b4f2121167e8d1e;
-  0000000000000000000000000000000000000000000000040000000000000000
-       34b7ba1db271bde528765d75773f5956464b714d9c994878
-       a0e25defbe4b845460e20fdb066c63a1e4593c63e88b6b8c;
-  0000000000000000000000000000000000000000000000080000000000000000
-       cf5cc81f0e5924e5c7503f919f137c50a7f59c664a36f278
-       0e3b9fcea7afbbb9c756a53d04c8dc3930bdbbc219b92e0b;
-  0000000000000000000000000000000000000000000000100000000000000000
-       809712627c15317a1ff6a5a53a9af3726209d3dc74f281af
-       9e4ede48a23fa258a1c7550087bcbf7cbc1a0239b35900cf;
-  0000000000000000000000000000000000000000000000200000000000000000
-       6dda715bb1227452f50923799bf245029bee7eb6a6203b41
-       4987a0919df53153f00e23d8eb5cc95b873c0ad9b40f3c46;
-  0000000000000000000000000000000000000000000000400000000000000000
-       baa6dffbedd6c9bd75b929d444800382a3fd330d43eefb50
-       06f07bfa7811fed5de8eb93a5c2b28ca90558c62e4821ebb;
-  0000000000000000000000000000000000000000000000800000000000000000
-       9327fe772c60b53dfc5e11c56bad70b6321acdcd88beec99
-       86f5bbbd94e1ceb8cf9b07fecd13bcba73ae64951c37e637;
-  0000000000000000000000000000000000000000000000000100000000000000
-       3395521584ec93e8579797d3a966bd1c2380a66f95982be7
-       4383715ed3d034f970662395f3d1f0c5d14a9cc926c5cd02;
-  0000000000000000000000000000000000000000000000000200000000000000
-       f9d37ca7294d832210c1e653e441007b56381b1af68ab0fa
-       e1cd78182664abe5ad64c6188a901ac00e8006ac7176d0fb;
-  0000000000000000000000000000000000000000000000000400000000000000
-       25adde24141811ca576c77e10c61b07e9ba9fb023cd8bd9c
-       e04f17ea502b9ab5b0f1c7ac16affb150df42cccd56152e5;
-  0000000000000000000000000000000000000000000000000800000000000000
-       8903e96a3fcb869b6ed8ebd05b41d15eeea0b1b8c175fd1a
-       aa89b098ff1dad397e3ac31c21cfdcaf1889a704e9ea946a;
-  0000000000000000000000000000000000000000000000001000000000000000
-       fcbd400b1a05a47c9ea7f1c4e52403a6bdaeae6c2a6048cc
-       761b1b18c0637dfd6d55d87a4f113b68af688f81f8d4f5fe;
-  0000000000000000000000000000000000000000000000002000000000000000
-       88c39912dd77f2510290e9b32fdff085e167a338862d6766
-       7bcd793c08afc09b27b95aceb0d9616d7fd66335020e55ef;
-  0000000000000000000000000000000000000000000000004000000000000000
-       51208b60bc0f91bfe1054342a73ade654872554eed23c450
-       426a4e6f17ae2f29a35133cc6300736b32b5679c8780165e;
-  0000000000000000000000000000000000000000000000008000000000000000
-       003625a0bb5f162b18bab7b498553bd1ee67b969a504f533
-       ff852ceabb97d9928cbc671b3987a21d0622bf480f9857c9;
-  0000000000000000000000000000000000000000000000000001000000000000
-       9a776d5d249c627fd74d868ca2e5f30f9578e7dc3c1b4e49
-       713cf88deca40e521d15324aca994976f1d970ed4f118906;
-  0000000000000000000000000000000000000000000000000002000000000000
-       47b7a8e4643e9ba7917144b787496f6e08a7c03e17ae9c6b
-       17f02b23ced0669a67d6fd22870f8f60937c956c7aed718b;
-  0000000000000000000000000000000000000000000000000004000000000000
-       09702bdb907f135f8ac4564319bb91e0272c5f49f63d6c2c
-       04cedb6f979d648ec677348f46b3b6d2e491b3c735791ec2;
-  0000000000000000000000000000000000000000000000000008000000000000
-       859421e35f2789869f2bc401e802a7a2e5a3dd671d0dd761
-       d4430b200d778d764b57e4abbd9b6f2a0bebd6d4ca76dfcc;
-  0000000000000000000000000000000000000000000000000010000000000000
-       ce6f45b33b4517f6de34eec218103ab52e2f7c9ee5c3d5a7
-       5aa67eb1b6382cc16467d12322af504d4a7c5c6883fe7551;
-  0000000000000000000000000000000000000000000000000020000000000000
-       55e3dca7d6904f0bd898779f77eb57cb670777f8e5840821
-       dc0b2bd616b31cc061911a30121130880221b4c3b49942dc;
-  0000000000000000000000000000000000000000000000000040000000000000
-       29bcce433a0f89958c85cfe3d4acfcf9d2392c25c75e638d
-       5cd8ef967295257dc0fc379f496f484961ee297633e64cec;
-  0000000000000000000000000000000000000000000000000080000000000000
-       735d4826ff04c760e49504fae1a49ff1070648d3c7d0170c
-       28961576dbd22448001631547726e7cb517df4fa6d9e486d;
-  0000000000000000000000000000000000000000000000000000010000000000
-       a4522ada107ea62be6bf5b5bf160b4c75e15f6ef0d16595e
-       b45177640fd710089c014d55a72101fc7f973bf462f6e0e2;
-  0000000000000000000000000000000000000000000000000000020000000000
-       42298f9e5660dde82a88fd096bfadb44aa0ce8615f5e2ea1
-       c24ccf0957f55d4b9390672e525622b9453092176e5feb6a;
-  0000000000000000000000000000000000000000000000000000040000000000
-       371b0a87d047cad422619a1ab8bbf8d2421625c36eb54734
-       154be268071b1b7d6548bf3933ce23e892dd4ef599e3cd7c;
-  0000000000000000000000000000000000000000000000000000080000000000
-       1b3a0995a3ea458e99eca6ce81d8d2943d3ce4036f280185
-       5e1eaae31384cca72fe15cb928e7247a289569759c92f347;
-  0000000000000000000000000000000000000000000000000000100000000000
-       75bf29ac66c69352ae6cc00493f8e448e3d568327b9cf474
-       543795ab540b32b3248a0d6518e6c3b865eeaebb36e5802b;
-  0000000000000000000000000000000000000000000000000000200000000000
-       5a0399a8cb30b225742bc5cdb7b19c2e090bb1e195a66791
-       c76ef9568728d4ddd5520ee9876a73ca72123eaf9ed79751;
-  0000000000000000000000000000000000000000000000000000400000000000
-       d18c12e6527e6e0f607a6babc9848f54082c3bc3bae5828a
-       dc5d12790a1da64c1976d0b8d6d66d9874f0b887444ec537;
-  0000000000000000000000000000000000000000000000000000800000000000
-       870a20d71492d99531323a86994e43af13c7519bd2527e6c
-       02d19d7b5cc70a320bdcfdd41f9921ffe0d6742644399c52;
-  0000000000000000000000000000000000000000000000000000000100000000
-       54b0a108605642493ce135710d562de7c32889b831abf8f2
-       654df69490c47dd5fff15effb5cb315585ae64cf6d8a69d2;
-  0000000000000000000000000000000000000000000000000000000200000000
-       a59695a3fa53bc16c5ca7fa67f939076ae5c60fe454556ec
-       528c3c4bd121d39056898a0034b596a433c8e70a509274f8;
-  0000000000000000000000000000000000000000000000000000000400000000
-       b2035a4f13eed6a75ff080223dc8e342de3d213c294c9b2b
-       823cf02821214fd46d9a8a8def8920b8fd02043a90915754;
-  0000000000000000000000000000000000000000000000000000000800000000
-       7e6009fc5a9a4bcb932fba990f5b27279ddf357a71f4f8fb
-       a18b1ee4c68c9b9db4b9351c147bdbc901af12d956eef5c5;
-  0000000000000000000000000000000000000000000000000000001000000000
-       2ea14149be04b3f717bd70eecd2c263da8bb87513c7a3a35
-       65f1bef465ed26b40bf1ffb916cbf111ce5d5549eb19a401;
-  0000000000000000000000000000000000000000000000000000002000000000
-       82560beaf44f02d49699d4288779c46b26e1449b3d347e1f
-       ad005df53b419cd35042f844834157cad6ff20b9820c58ec;
-  0000000000000000000000000000000000000000000000000000004000000000
-       4f16682c365b3b245e2ac0851460e935d293ee25ed63b926
-       f155888b05d06adb3b212c988978b509c819ccffce05a3cb;
-  0000000000000000000000000000000000000000000000000000008000000000
-       65130d454a144c68a45274fb5a34000e47bda215d7ef794e
-       7dc0c4ad2951417bceb94b84224e2392ea24e878db411d70;
-  0000000000000000000000000000000000000000000000000000000001000000
-       b229d4e287009b3bfaadc07ef82c7dcb23aa3efd3ccad210
-       0d391fe98acba6abb8fed9caadddc59cc933b07eecf98879;
-  0000000000000000000000000000000000000000000000000000000002000000
-       e997bd8285b6ac3f3f14fbc98e8a6f2d7f310eb250a1d3ea
-       374efdbadf8a357324705281c621abd460fa3bd5818898a7;
-  0000000000000000000000000000000000000000000000000000000004000000
-       e88323084406260258f70be1a98be9f175bd33dba86dc309
-       f689401325a73fe8d162b13d808a4027360d85594700776e;
-  0000000000000000000000000000000000000000000000000000000008000000
-       5c877129c311d257a8b929cdce288c8c41d29f48c7f09645
-       766bc49677fa50b1a9089308c82f973b16250d8ce85fb972;
-  0000000000000000000000000000000000000000000000000000000010000000
-       3847656ab3097dbdb9f850b3eaede060015145dfebe081b0
-       c824634dbe6bcc4e3c0e4814267577d0a8e88e6484956e47;
-  0000000000000000000000000000000000000000000000000000000020000000
-       d6722ced938f45256e6bfac3209d8afc3332bfc4b9728f6e
-       510d68ab75eb49f7aa970e4c8d4458f26c76da52b97d9c2f;
-  0000000000000000000000000000000000000000000000000000000040000000
-       e46d2ddbc9e9cd7668f0345ecb38f4b9d033e6277c770339
-       754eaf9252e18b20b04528133b5513d0b45eb610332bbbee;
-  0000000000000000000000000000000000000000000000000000000080000000
-       6b179b4be801c3c22c67820b4a0602da09b36a0b4003e19b
-       594fbe016179a0c60e814192aa5acf26b8c7263288e5e6ef;
-  0000000000000000000000000000000000000000000000000000000000010000
-       d3b5ae53b5bbed9e11806475fb8e892abad4d0df57d37432
-       925c57438355e2ed191f44a62ef5d233e736d533c384b23b;
-  0000000000000000000000000000000000000000000000000000000000020000
-       3c69bd1198742f571ba466d75f33e2f8875bca181e7c5060
-       2cbce555cb50bfbc7f03b5cae522dcc9e3a6f652d7f95ee7;
-  0000000000000000000000000000000000000000000000000000000000040000
-       faf5577aa967ce1b528cb3183d311a4a01fe0bcb8eff52eb
-       359c1f635ba4aeea1496961d0acea82f8b287e6c333c631f;
-  0000000000000000000000000000000000000000000000000000000000080000
-       17a59ff4260e682c5fd265c4c8cbb1f2394df520878d54e7
-       bd62dc2010bb988cd034dc3471b8771c1e83cada3160a162;
-  0000000000000000000000000000000000000000000000000000000000100000
-       cb77f4cacf18f51a20b2b2a9424df516ca09da86df7e060c
-       8f21087d1f761b40dc9fdc48591725f6c3ab8c996da2e69f;
-  0000000000000000000000000000000000000000000000000000000000200000
-       efbb6a40a6bb6a73f2b00fe2672d9d9c418be6077d05d6d0
-       11556df337561494f1a88048287e274b091fdc8c3248fdaf;
-  0000000000000000000000000000000000000000000000000000000000400000
-       482e51026536799a4adde4ed551b5b37bd946806f72a1e84
-       5c83416d574c4d4fa9f844a8bbf2502a2e423e9333ba5c09;
-  0000000000000000000000000000000000000000000000000000000000800000
-       3f2aba49c1d122f4fcb3fcaca344b48526426a3a11792420
-       bc2446d092a3cb6c47d34d6b8dc6504e71faf9cab27d5af5;
-  0000000000000000000000000000000000000000000000000000000000000100
-       d64b82bf6776e07d16dad6b610bc5ccd1566a340d5439920
-       9f0ec7057d88a8b9a1d7f37e8ae54ddc286143aded0b727d;
-  0000000000000000000000000000000000000000000000000000000000000200
-       10ac120667f6cc8fb3eb5e4fca09393e4d752378c1ff3aff
-       84fffb34309cd0f900753a880af05503913925a676ccf8bb;
-  0000000000000000000000000000000000000000000000000000000000000400
-       913aba9a2ee4d9cdbfd723b02acd5fdbcecdba6e5ee9fba5
-       a6935a6a0f5be5e36a5ddd2489a849723bbf32193b352276;
-  0000000000000000000000000000000000000000000000000000000000000800
-       2096ad29e264550d7f50f5225b174de08c4e33407e229ef8
-       322b672ed96a11c24452ab02e5bbfcbd8d2c055dd4ff1502;
-  0000000000000000000000000000000000000000000000000000000000001000
-       e2fa3c20c1c3697f0fbef257014f4a0851c7a424287f58b6
-       3dcf94cfeeec73127384a8dc89d1de1791c2bffa516848e3;
-  0000000000000000000000000000000000000000000000000000000000002000
-       25d94a019001c3a4fd30bd51206497e094942ae9691215ec
-       c52be65c97df81a1cdf06760d79bdfa04a8a11024535c51a;
-  0000000000000000000000000000000000000000000000000000000000004000
-       20acbb4cb8509b255bf293e116b32d01a284c10402387352
-       f98ab11ac1e9fd49d644292f7e70d78bc8528c5c85afb7a9;
-  0000000000000000000000000000000000000000000000000000000000008000
-       b61f153afbed502f9e64d13a25107529e614e39b992d3d22
-       f720e227475a727d1e3f9ee9bc7d3ba079ce32d076a2cbd9;
-  0000000000000000000000000000000000000000000000000000000000000001
-       1621dca63b7555e070a05b5a265a0ab530a79e71542ed333
-       220384f259384d523e7b0328739f608d976b2498cf77c7cf;
-  0000000000000000000000000000000000000000000000000000000000000002
-       35ed02357b26181864f5de07718913a33ed9fab93d845302
-       c7f8b065f6bd6d800c8881040c68828189979be2c86abe64;
-  0000000000000000000000000000000000000000000000000000000000000004
-       e0cbbdcc0724419ab098dc25606c6277160215eb3a166b5b
-       106d2fc9c5e5d2f8a7e6ba7db2a4e1927adc2ab6a26d20aa;
-  0000000000000000000000000000000000000000000000000000000000000008
-       2879e25e570e536c936c8bcd66bd780047b73d53922933ea
-       c3cf14d55169ad5281175057db3a614351dd78ca57c9ada1;
-  0000000000000000000000000000000000000000000000000000000000000010
-       45ed18e18449285fdf874b675784b18d412e504075c61fcd
-       bfb1f7d80745dd69a5fd479fe14c449ebd1ff19501c42ccf;
-  0000000000000000000000000000000000000000000000000000000000000020
-       3ccc94e3f12a3e2e4321e397300aa6444ec21526098b0eaa
-       0ac9c1ae854812f92615b3fc45e65c945f3e1ceb8efd4a9a;
-  0000000000000000000000000000000000000000000000000000000000000040
-       f300d3a47eb7d9bf3215140c894b4e8888040541424e4c11
-       74587eb6e7f9b2ecf7bcd8f63948ad0417f439f8596ad52e;
-  0000000000000000000000000000000000000000000000000000000000000080
-       df6e46c2dbf69f357bbe22bf604efca58a7352a18f41a7ad
-       1d5fa8d85dc2428dabb69eb4c9cea7180f2fa554eadb9dc4;
-}
diff --git a/tests/rijndael256 b/tests/rijndael256
deleted file mode 100644 (file)
index dd93096..0000000
+++ /dev/null
@@ -1,2886 +0,0 @@
-# $Id: rijndael256,v 1.2 2001/06/16 13:23:19 mdw Exp $
-#
-# Test vectors for Rijndael
-
-rijndael256 {
-  01000000000000000000000000000000
-       0d166d15e764fb6bc005df25b169d93f1cc03580e9dd4a19c4bd7cd32e6ca03b
-       a8dcbf6ab9a5d693428c82d2de78a4fecd75573d00d25a1cd7723a3897521c4c;
-  02000000000000000000000000000000
-       ba36af55f2b81650aabe5f1496e0675bf42979ccbe66ce7e9dc42269c8a40378
-       710168005b92abf4e5fc36d9ae0aab11a872720aef853e37d7a929bf4ae023e1;
-  04000000000000000000000000000000
-       79c77f01ae4a137b07fcc8be95693b7157b55aa02bfab77bc0ebbf7b383dfd9f
-       1b82ae9934d5fd2ee151529c7cf17ee653ad859b80d1ab1a02b31f23e17c1526;
-  08000000000000000000000000000000
-       ce6c53e5ceb51d313d95c7831966807d25eac9fbadd3802f7bfbff4f9cf2dd51
-       1263853b8b7f61e02cc9568c6e925b79375a1d7212277bbb44e15aa5874842f3;
-  10000000000000000000000000000000
-       be529de8125596ed7ef7621e6fa1ea17343eb9b3c34181484e09af18dcc8343b
-       f91c5fd5f8fe1692a9cd403531ee7643ffd91de0a8238e3263f361c22b31bac2;
-  20000000000000000000000000000000
-       62bcd58193cc12ed08ce4a5b51d3a679678a1561be6a805e69e1f1b2da45e7c8
-       9d1ee83ac951bece4f9535b1f4d461b99960b0021be3b8d4c8d20521ed3978c6;
-  40000000000000000000000000000000
-       ababd0ea311aea38cb364d367c27462d7c7c874cd8138dab3d8331d90c483e2a
-       e360e0bfc704c664550069c9c675304dd24121be987dd76b7e718f8a1aa2277b;
-  80000000000000000000000000000000
-       93b811f0e3bf6c0b00d4f8002783ce01c24ac3671dc198805aba8846dfebb288
-       1726d2a0c6d4d7078322b48824071fc4c6226b8a10bdd8d09bd6b90d5cff9812;
-  00010000000000000000000000000000
-       8b9328500908af71236b5ed841a9e177fac26c81034dffb99e89753de0aeb4d0
-       1ae78759e134dbeebbea45fe9a0a66174264a1efe55a87569fe1a1568a28544d;
-  00020000000000000000000000000000
-       c5c7c19175d9ab800bf358d066f0da2e86fd20ee6ba4e5cfec1e8b1932b42466
-       7b0069d82b61439e71a7cc911d3253f71efc8da14244dddaf323283c9c99c123;
-  00040000000000000000000000000000
-       a5a088b14f876b6291f5a92993540f972012b6e8a0eaf2ab0adaca3b3410c888
-       ca33da2e73e8a8f62fb2b6c23f59a54363fff8bb3c806c6c71e1c22b6f90c81e;
-  00080000000000000000000000000000
-       9c482dd8e9e514270d153a310d4179166391ccc10ff594133d2b023c307fc951
-       3e0d22a6e0dc4c5952b417ca6edcab1edf6438fece9e4d05a409d0adde7331b3;
-  00100000000000000000000000000000
-       cbb011e00200dc67a685963f6dd64373b87eee0e1db3c2c3b9f31a290682c7e4
-       4a71ca431d8e66467b67a5dda1c759f4e5a70eb6fa990d8621fc8c107ecc31ed;
-  00200000000000000000000000000000
-       c134cbc298d7fc2a3df295534c5b51a810999bc66c64ce5810086ac896af12aa
-       e21d816bd83eb2ccee4c12c0060a07b5a9b1f52639e957db1ba3c94b0d1ef5d9;
-  00400000000000000000000000000000
-       00d96bf86467d8eecc800930d9ab0511252f62ddf77a2c6fcf560ec64a99992e
-       8f8cb84f6ec8a751a2c52140d1aaccffd75be6f0750c0f4300d8a95be1497d13;
-  00800000000000000000000000000000
-       dfbc41532baf8d1ee9c00f40cb9dd9c9970949d182a651af9809ef097d9f95b5
-       adeaba98648d76d63be914a169821e4b6b816965082a56c64a2600cd0b0ab1b3;
-  00000100000000000000000000000000
-       3ec45f406e61c9c862add48b59e2193a9e044d8450dcf06ec9781ea54b25770d
-       0cb3cb766c1b3af62594b5beb5f794c537fca3ef3a7aa34c19965d194d616590;
-  00000200000000000000000000000000
-       5f63e9e91b5cf923dffa47b0430c9c5741e36bbbf2f7561e5e4522a9dd086f59
-       c8d48dfaddd6db42fb88d5e5a774d796ca0ccbd2aea63ed8af958be542577c60;
-  00000400000000000000000000000000
-       aaa49691c18a878cae6d8ef28cea273d39a85d65ac6656efadba875d4de8dd7e
-       ab5274393cec473dda0b9b0d150c3119a6c7c7c5f546bbfd48be3fec8e0b5ceb;
-  00000800000000000000000000000000
-       a7a1884e2e0ff36211f92ececf5d10a026f0d7fca3ec36bb4fdb3dc39c8b0286
-       ffdddaf16fce3a8ee9ffaefec4f86d0a12b153b1642147201fa93f0165d95786;
-  00001000000000000000000000000000
-       ca7d8e1fbc8de0b208ef96a731cde9e71447c7976a7b4b70f6c6670c3683825d
-       373578f19f83d5af1ba61e156754fe0b8210d75b3b94e4ea7c94d51f2c6db580;
-  00002000000000000000000000000000
-       82e91aea18e826867c8df83eb68d783f70792019c350859c4c6eddc40017aeb9
-       01ebc069581ee246b6f49707ea3d5e0f7b22665c40f111963d2e42f45c937f95;
-  00004000000000000000000000000000
-       46acbcffb692d63566c52fd7f0ec13199b07b747c75d5edbf1a3f684b51f634c
-       3c1563b0cc61be41ff454b2b1b4f7dd9b102efd860a6e60a245391629963440e;
-  00008000000000000000000000000000
-       0ed05e750de5f56965775ce44dec375ab74d16c9537df755ec21402b3a10d0ce
-       662e2d66cbc1a9018e142430e5fa0093dc5aa33d99e225944fc651d0234424de;
-  00000001000000000000000000000000
-       bba5a7e1d984cb9c1c37f664632649363524e1e2206ece1d998fcc2706545d7b
-       889def781d00c866e878bec6965ff82def729be52611d0b805ebdc97541a63a9;
-  00000002000000000000000000000000
-       99da531198516629a6c5625c483bd08ad864b54914efd29982737f6572076b55
-       40ea49fa08ecaf017df5e73f9ecca8c24bfddd40327add7407badeb51d551f21;
-  00000004000000000000000000000000
-       9c7e2c74e8a14ef12e6a8106608bc3e70206ebd402457cca671e6804ad55648f
-       5eef85026cd49329caa947624c88c91e27f817f8d01768b98d121a69d9cade76;
-  00000008000000000000000000000000
-       53e1750bc3bf2cfd3ee05caff29cd98c56cb32ffb75548c8b3482a266b4a1067
-       6236cf6d9974e50472854642a529c86ef62599e4172e3bf5d12909721a6e606d;
-  00000010000000000000000000000000
-       2cf3f5109eab2d3c501f70b3ae1fd8c744f1c1dfa41f34921f55a3547c76110f
-       6b9f52bd5d1ab2d483a614f590f571b1f086aa63bfd0c197c02d514d03a7f695;
-  00000020000000000000000000000000
-       81e041228896707809dec23dc43f023ad3a8b741fb097158de5abdd9e8e63e2a
-       bd80f493cba17cbfd79870c1fd0f7052ebcb07d19f3b7101e6ee9a64691b0e33;
-  00000040000000000000000000000000
-       df020d98627cda7f93bdda5f2544b46530b645ab1c619583a8d34ece8f0402e2
-       d56f8c7d45ced4bd015c413b5076cd494ebf0ee3c6564b1c8980b6db9f8ef18d;
-  00000080000000000000000000000000
-       3f2a2e2d05337597567e45ffff3644d1b78d446e54113961a282c63693137ddf
-       ed749629bc2a4d3a97a678bc810913458dc7f06d181e6c2ce232b01da705cc59;
-  00000000010000000000000000000000
-       7276b5b02da780407cbe4a9feb17230e308d01d37c2d50b2f357d2c25342736e
-       da1d5b5238aa6516f1bc3982e6a22d18a404645edd961251d8242fbc639ef442;
-  00000000020000000000000000000000
-       94df6723a4b7e8a3c548a794ae9dd2d44c2596e6a2b313f4caee48b2dab60d0c
-       9b760a577ba48b855d2787253507b5405745ada1060c99ce476c3cd5863015b6;
-  00000000040000000000000000000000
-       b0942965db151da90df6354e57d78c3b0e6c31e624c610dc018d3e1411c13239
-       5c37701aa5d1d0b1681ec86eafbb59f8acca725816ec73edc7ff34a68b1414a1;
-  00000000080000000000000000000000
-       4193eb057627735cfa1e3a6b1ff107898c1df42499bdbdb50999808a4443c616
-       2048e754d9481745d95a3e6b4d54cd7b3ca5c09fcc27f22a6bb3b411e4213ac9;
-  00000000100000000000000000000000
-       6496cb3d2a6d1927a86aeb9a81838b7782554d67dd17da1eb55d86e680f18a67
-       bf66014d7eb0b274ca931b913b1a792f9b303b6cb1581914f7d12ad92cfdfdb9;
-  00000000200000000000000000000000
-       5f2e0aad9d2b66428bd14e92e04ba45c1b2c4d8a3626af7e14ba88ed30a939b0
-       53359f5e143fc6c5ed119106f09ed6020c07a840f37c881a19fbb664a2932912;
-  00000000400000000000000000000000
-       b7ac23c7ea16038b23ff99fd8471a66173c72992009d67c136ce635b6c9d9a0f
-       9c1a45cf93c6c3eaa67f56c6fb0004ff9182d4c76cebb113a297a6786bc3a7e8;
-  00000000800000000000000000000000
-       6af8fbcd1498dbaf169b3c6cbf99c0d954f0a6074a391b50ceb179a25b76a4d8
-       4f6042a77083581ff33c731111d3040fb551a9139bedf5266b83e0bdf5f4e9f8;
-  00000000000100000000000000000000
-       66af8d706d38d51808409619ee4672ad39c45025094bff004dcab2d29057ae9f
-       5866f66669833af9565097ab80f6b7ab00acc862e71767cf94e7c59dc0645ec4;
-  00000000000200000000000000000000
-       6839cd0cbbd72732d67074d3573594cc7db1285aff8e8c2fbb8eac3d0e22b3f7
-       d5df2fc8ccd2699e5af63b16538339487a94145dc1ed775fbb852b368106dc15;
-  00000000000400000000000000000000
-       4a2afabea926caf55464e6508976960589b0681c0f0c42f6dabde37b3f2c2d7b
-       8b17b2bdb951c39d359b5ffbfe5fd62fc5cf948652429c43b3a580a044fc2202;
-  00000000000800000000000000000000
-       75ae68f8e02256da8395c00d1a79a398914aab74c1aeb6a1fd49ffa1e25115b5
-       182317ac645d381058cfb6582eed55afd1c41a01c1ae6984f475c1c9829b51fc;
-  00000000001000000000000000000000
-       371cda9a5c73b8faf952ce65d226947fb69d22412669709a3759279e3b652b30
-       3d4b5768c554b31a48a8f2493aba5267e7ae2825a224e7fe296dfb2cd18826f4;
-  00000000002000000000000000000000
-       ee23c425adef80ebdde63fe7a6191d8065d719c3d24fc8939956225a3e4d9e57
-       67aa7cca219754c484451c80e76329984eacb8a664bd122ee7c81133f0448bb5;
-  00000000004000000000000000000000
-       781a2bfdcf0f59ff6feb06131eaadec6b3f86febd94e875be5b88262d9a61e61
-       90e87594d441c52f3b940079b3144b16efbb7da652f85ded012e72df45c5f947;
-  00000000008000000000000000000000
-       619835ea64b097c90af092514b6fdd58a5773f4492148463c98a2422e6d29ed8
-       94cff55bfec62839a98e2099bf70024bfa3f36ee382d79273da4cffd2af262c3;
-  00000000000001000000000000000000
-       089af763aad8339e9a9019899dac708f9edd78d984d42105b218191e4547ef1b
-       8f5400c80a1a6944e1494e72823013571bc53a7a0da4ca876a34aa3fc923e431;
-  00000000000002000000000000000000
-       e8da39299778df8feabfc548421775fc8ec1d473bc24397281c1b494fe35bd97
-       ba3a2f4ad75c1a36d8ce2488d80d9a7c37886f0f25cefa6f906c1d3c97028c9c;
-  00000000000004000000000000000000
-       1b6dea579c09a10ff8296c9d2fb29ffaef89169a901f48a1de8d1867e71bed1d
-       306fc026f4f82433051bc469f6b4dbab3840332f6069a91df2cd5f8fa71779d5;
-  00000000000008000000000000000000
-       84ccdeb939ed5ac41671c7c60404991c4411b5ece49d01401a10a3b906381777
-       5ac3702f5a3b7d54d5cd6f60fb5ba7f4eef23aac98c068f706042c91f7b9c8dc;
-  00000000000010000000000000000000
-       f05402b141f7578d2e7190d607ed24c60d169c798c36dbf510f57c106b4796a3
-       d7853ee992f541e06ec1bfae4e0ce59cd02ec65130dd2c5b25164325ff72a89f;
-  00000000000020000000000000000000
-       c225cd7a41b66da52a753fd620c04655e1f5028857f5004617228d0a79677ccc
-       44534e3a429b02d1280c784bc3d43d3f3f7d68a5c1e4bec773bba7fede5b539e;
-  00000000000040000000000000000000
-       5b02c15dfeacdac4a847dbde35f251aaffc17704bf8727a5ad53f84d0315a405
-       b9520766f0f67abb9e3a879239650cc41d90716560d83f6c2115e62c67ff9bd4;
-  00000000000080000000000000000000
-       397b5b0ad0d8540d90b96a293e9e3ebffbb2ab2272c93f5c854a1316cc45fa00
-       effc84efef486e591669f535d5cef87b0cbb224b7e33e0068b4d058a8a81b4d0;
-  00000000000000010000000000000000
-       1e8942d564866774f20a8abe42694994b281278037f373b5c867115bfc8500ad
-       052566319e8cfe1627f10d5ec55ec4eb50cd1b8e82c7bc9859f7b1ede1d2822f;
-  00000000000000020000000000000000
-       b71ca147cb496c3c65099a87e63026aa51d044ce55145adb861f1d473c1d856b
-       d08a2b0bc7ad08d1ff0a4b7f5c285ea9df8b7583536dd58f8d184f9c7a657909;
-  00000000000000040000000000000000
-       c048a83a291148835727a9792e7864550e71812eed389d97c8bace4246ea75dd
-       0af26c6f1f02650ab2532756ae34d59d8580310cc4c3c26f147ff1197a6e09eb;
-  00000000000000080000000000000000
-       4d425145fd1166ade64ccfd5e52734ebbdc31ad4512f74e4a7e5e3e0d24dc18d
-       35855dfc6ae18052f682b171895f775aa94c293dee1512635f1ed5216fb96558;
-  00000000000000100000000000000000
-       9ea4fddb10565fbcd92c352fc81fea49a755a3b64e98ace666f81f42678c33ee
-       e8e17030571a18fb74a91d93c8d2907a5befb7f0695770d203965b25984c9238;
-  00000000000000200000000000000000
-       48059d5828c995e546f8bc6579a167c9ce53d6fde10cf3b7d923be137093aba3
-       4bb16948d4126f77882f10aa89876c55b80b390fd516eef2fb1db6c1527b28c8;
-  00000000000000400000000000000000
-       d3a5ff5dc944cd7944103104173b40aab097ffd6973f7cde14a001c522818872
-       247d0b74d7149225a6c05f832fd51e221730ee857b34671a4b9509cb2e2bd4da;
-  00000000000000800000000000000000
-       2883cdec39ade0aefa06f3d046ceefb87df0dbaa79e978af5828c429d4fcdcfe
-       7ad775fd0742338854dd747b5381637ca5260c90e3954774cb4a2ae8c5a0b92d;
-  00000000000000000100000000000000
-       8d09a89b9bd6428d8461d17682b84cec190cd76a230fbaad63179ae678106aa1
-       11762fa2295143bccbb767f201dc866258bc600c7ba012fbe8caa8fcbf493790;
-  00000000000000000200000000000000
-       e57182f9cfe9d9d189e3d679c02e5102fbc6b7fa449357739bc7ad2c7b479214
-       2203765631ddd429485e18f78dfde1b869195f81d8366f352faf8d48dac3a7ad;
-  00000000000000000400000000000000
-       29e7e527c65204a7a21ca5db7b9a4d9e3341a1af894ec0773de2f3dae3d3143e
-       b87c10b138e84a56de01841ed2f73b15d192500e89337e964025ebf6f6387297;
-  00000000000000000800000000000000
-       b6a6752bc5bee6d41ccc022092cc46b27145fe2902091c054363cfb472d48b81
-       43352f812f48951dc628216466304c09d1f03b19d807eef29a3f720378777241;
-  00000000000000001000000000000000
-       278b6c69b23d755bda9eb003a50fe7a928a38d7c9b85eb71692c79d7e0f0800b
-       dcf964dfdd2ced07b2aa36622f1fd8b7d222d02f9acdf1c1acfbdff9a0199b59;
-  00000000000000002000000000000000
-       cc50d65a6a9184a5f14102010cb4600393da166d264a605150b1c0718f1e04a8
-       c22ee130cb19ece6ba705757d6a416abb709c691898293d31eb66a72ebf81549;
-  00000000000000004000000000000000
-       c0ce6ea99eeb4674828fcd37fb65e7c2af9ea924a19d121a7f940a026fd2dc40
-       315be95dd9b189d192c5c9333a145d8897af5ad256ff8026fdde53f841b99756;
-  00000000000000008000000000000000
-       f5fc52f270dc27f07ad2780891d9995c914f8931dc45f6a1fe423fa5fcfd4a1a
-       f3d2d39afaae2eb6bb9cfc255ca09ed8c46152e75d13f6e2e9f818a94b9a729d;
-  00000000000000000001000000000000
-       c5e467ab0c5dadbacba076637d3ef4a54d1f086612b970b78f562980324e2d31
-       9f1e48b2dbd80ab69f76fc5e827653dbaef521afb5d6949351ebbc31f82c0a65;
-  00000000000000000002000000000000
-       34abac049584a4d1e29bdb7c08ff7ca43dea973e6bbf196ff470d43712610a9d
-       676e22e0c042aab946ee5d009cac02b91c104bf324526c39e6b3a8ce57734ff6;
-  00000000000000000004000000000000
-       701c6d175096e7e8ad4187c1b592cf81db897a54fddbb542152c7d50b3f1b81a
-       77119d05608366998aa3b08e473f4bfaf9e694bc15c15f73e8f33b3fadffbea9;
-  00000000000000000008000000000000
-       4e98b3ace7c111c1e81f6f2b407a934877a1c08fd0dfa9eb80698d985d68fe23
-       83c58c3066f0c4feff1d4d5a098afd3521e30fd8a0ee221a80671ab1c17f40b5;
-  00000000000000000010000000000000
-       e1b4125ee35b0e69f1aac9556596147bc526647375781e1926732976a77f7550
-       a341567706ab2a2cb79adcbccd39c81eea1e36e1e0eb8f118a9fbc502eeaf105;
-  00000000000000000020000000000000
-       e479c9546ebfad858cb2353808aaf1a51b1473f229f81e13e1b5dc7cc7fef349
-       572915a2eeb3dba77a3596075313d43709e01baff1e591bcbaa209703d3a0bff;
-  00000000000000000040000000000000
-       6ca46d724403120fa8517f40a36eaa1759653b2d91cc9107c2328602d04ace40
-       4785180fd5f43b9941ba27ef0ef72eefddc77c9dd6ad7ea0f11211b8b55e3025;
-  00000000000000000080000000000000
-       32b9348cbb3eebcafdb4716b69b73b0677e1e5e3e6e68758615809fd06a15368
-       22d90cef816242b9dcc7fb7fa644eaf9643da10bb1136cf6788178aac1e532a9;
-  00000000000000000000010000000000
-       c3ed54670a25cba194830476ffb2f5d765d5dcf476235a0e7df9f405a8679771
-       caaf44da13d9a6a68c162810196a8de1facb747efee5d73d0916da3c4828382e;
-  00000000000000000000020000000000
-       7e20b32d7ff48cd1be4108dcee7c9e61c99d3d23a79c770a3aa10853e04b0dd2
-       75779c17a8ef0d15cb1eb48decdf3d8c3823eea7c8e75b8b2393b898c4c0ca6e;
-  00000000000000000000040000000000
-       43adf9131d705d4a66e300af90ce15d82574e71ca62988ccf4cd03a460518889
-       fdbc8f6097b19e5ce90411f88acd3002d27270de234d79d8808b950f65e3921c;
-  00000000000000000000080000000000
-       93f2c1b9a55a325d39e769b23da246865f66e15f25dd6f84f44e58ecdadd2091
-       06db50bf315c02892d1bbb304b63ad876b8123cb87a9d1c4b1681abac4a6230d;
-  00000000000000000000100000000000
-       39bcb5eb623be3e37858c37e7ee77a56f7983b4ae246658264b760e77242437e
-       ce60286ff551c33f6a96510bbd33632721db632291c54543b641b0de5d0045a6;
-  00000000000000000000200000000000
-       b1e70576e01c1f029dd9b309670bc41161bb13888b1c93c6f8a0fd2f5a6e7fc3
-       45e345d2b2610909dc837aaaf07d58117189369c8e3bfc5b718457083a61346a;
-  00000000000000000000400000000000
-       dc8af5dde236c0d2a18ad310a21abab9549a54c4b3f16d6e3433578f35f04322
-       94580e73b2ecb615c73fced8aa1b14180068b8a1aebd3b677e1d37c21df4abc0;
-  00000000000000000000800000000000
-       53823c917b2dade044551689d7f703fa83f31237af4f4687016c4ec13f435993
-       1bef0d32e4ee66c805f793553852ec7b803b300c5434215cceabd276fedea323;
-  00000000000000000000000100000000
-       2c5d0e5a610cc3dafc0ea2340d8340667a7870ffeaa2b88056ce23c93131f9cc
-       5e73c45a4318ac800e3459af74eb3fa7a2010b3bbd53c9bcd51613fc63cc79b2;
-  00000000000000000000000200000000
-       118d26d3c0856588f39d2f654eff64ded5e93fd1900e85abbec0a2c25cfce7d0
-       20d1d578de49459eb928acf39f46dc28089dd3972e57818e0a49f46c6d0576d2;
-  00000000000000000000000400000000
-       c1253993f9b3f51578f16f5766161b3ff425cf569432121dad3eb9623b9ebcf7
-       9acbaa6aa62d50751f95583545dc3b83c235e18a2b868f4d866e86417c75a22a;
-  00000000000000000000000800000000
-       538012f59baf81597c561b999827d7e177542fda70c9b8a20180042cf49f0511
-       088a9449af39cc0b2a88863fa939f31c8730e696ae260a286e8e5f725167e725;
-  00000000000000000000001000000000
-       8e058aa747ad629433aef87fa710053792c9ecfd6f04f749aaf97bfe280707ae
-       70add57b59bd76f07688c0d9753dc6576301471052885ca8bfce36a8ae17a7dc;
-  00000000000000000000002000000000
-       54eea8fd10d61d8b8edd62f26c4bfc47a1b444210c1550c7860cf558de3f3e02
-       d22c759d1cf0da43c9ad0cc3ab34fd4c0d24dd4f0a12050af976705422abae39;
-  00000000000000000000004000000000
-       b117f239922fa9d89f9a0d77d212f54a82c20b14d2031892a1215ab70dac40b6
-       e9f9ec1886337f55d43ed990227687c796aaf978af708ca6ed2308e4b706a2a5;
-  00000000000000000000008000000000
-       bd17e0f86d1043e1f48b5e3bd2267bb9d1834d4c710207deb618b9786610c0e2
-       e251c120f7141aa0942b275c26e487212849330a798f392229a2b4909b97e9de;
-  00000000000000000000000001000000
-       62a328c617554b9382aac406ecaa84370fc28c0b600711ea2ec5d132231913d6
-       568c846b732c9ec98cf437fe67a223a7e7b63d42b20e57fe95572a2fc6cbda10;
-  00000000000000000000000002000000
-       41242d5ab9cdf29b78ad952fe5a967918df393d64613df7145adc5f540ac163c
-       87b5af373d78b9edc963cfa1f2b88a55143fe2996403cf6b12ba4d2a4de0dd95;
-  00000000000000000000000004000000
-       8d075e35e0cb14e23310bb213e59c416d35bcdfa548b7e4a45ef159c10635532
-       57392072b104f59f65043656c14ddaf32ac366f0cdbedffa7c5482be297da5b3;
-  00000000000000000000000008000000
-       01a45d81b5100e5d8971525bf21993c8d18d637b17d91b5d704c54cf081ddc60
-       73790c7237a1eecf35349452f60d4c934dec2a3f42f4bcc4939e63245bb97882;
-  00000000000000000000000010000000
-       09843cdeef62a0420a74674575790d67934f88dcb8492a6f15aff243c8e15e4f
-       dc36416b1f0a13a0270816309d20507c6479f735acb3b35c0e5700c5349d07f0;
-  00000000000000000000000020000000
-       31612d05a352c54e516e379767c096a79a1c4234bd17d4f46c73205980561b8f
-       9370ac5d3c467aa1f55b94fdf7b396c2f2c425d65e49a225d4a12354d586e2d9;
-  00000000000000000000000040000000
-       ca61064d6edd95e3aebb9ad2ebf54d515272ecf033e146c7501a240aefb1f026
-       68c498a69f4546f60242658595a81dbb0eff031e29bffb9263411f8d346e6836;
-  00000000000000000000000080000000
-       f126d3c9eadd62db15cd371ba858acad93d9c0905c3e956566dbd1e5fbe4e43b
-       0dc0eb6ca4d30b01f19db8d9484cbc92af194cb9cc5e698af8f9bee1a08a2f19;
-  00000000000000000000000000010000
-       1f4b3e99d260d36d735f79f453108bd7ebf8746af1f39348adc65d59af6a29a1
-       8a50046878a62f10557d8e94bfeeb1a26ba39a9a5a76881ca056deb54082db16;
-  00000000000000000000000000020000
-       b4f573c9327db5e44aa95583f188849edd8454c6f31eb18765de7142ff91420a
-       74890b23d53da33244da9f908d4812d27677a294c61e3d29d7dd495f394201a4;
-  00000000000000000000000000040000
-       e52d19603539f17a03ea93ca700b9eeb5a9d23de423d4631787c1572dec40780
-       b97b5d286cdefb8d83cf18e6c1912adc34522bb6488e7abce2cbf743851743de;
-  00000000000000000000000000080000
-       3abdcaa1600a946271ca2ba7fe9c7290b5f90adc1978e0cd5348747b118cbecb
-       f740e693758e1e5626bbd773a0a42a967a540498f250312d862579f7da3b534c;
-  00000000000000000000000000100000
-       77411d75f740551a003ecd086d4563c881714a79d053f1d99120dd742d002fe3
-       8cb92110e3a28d7c42852b6e1e16f31c08693879ee68c8eee020ed9466904b82;
-  00000000000000000000000000200000
-       09338341baf259f56644c919461974c3b7c81e3347d983545a993239bf051f62
-       1697fb4786570b99034fa0bbec3111b1d2765ad4f21492721b797ac485844630;
-  00000000000000000000000000400000
-       728b0b2d9086928d19bbd761bbd18ce018114f9a357fc719416629be99d569ee
-       bfb243eb7dba6ceb8fcbfa948b91d438a9ac80c960adaea75af7de45fc3cd519;
-  00000000000000000000000000800000
-       213be2a825b5694f131d20465a490f8805cce1b471ade0fef8ae05d473d888c3
-       fe381bc82b11191ae1ba5e0e526bc64eef8a69052805c532ddfdf7a68f26c6cc;
-  00000000000000000000000000000100
-       0918a9151b01813bbb43772707ed48e88464966f41581a23d1422e936b6e5dae
-       65b87265aeefe0e04cdf2917a51f7c46b96b95645d4b4f8ddc40fe9de229e1e0;
-  00000000000000000000000000000200
-       d684c064f8ff906797e3c1046bd1dd19f1defa5a33292947081c35cb8c2dc0fe
-       0e4fc41d8e7761c4e75c62da50b762820e396c794ec02386f96ab6ae4f1bdee5;
-  00000000000000000000000000000400
-       568310b144f484cb6468d0140ed4d3ad6da518960f79660c7ac827f065f8f9bc
-       ac82171949984f7dd3d23417b98cee5ba45cf9e67bc2682c134ed58828f29ef3;
-  00000000000000000000000000000800
-       3478b762b87196cf1f12e19dbbfa8b9f7ae89c5ba32ade4b9e292f40bed5daac
-       f455d1be4bd6c9d8f2ba12ee2506ec58774f51c61c434fd29bd307703909f9fc;
-  00000000000000000000000000001000
-       61b4393bc414920b4cd28f1b62bd7d14ce09750ad2d5fa055d7264808bb49021
-       3c6b3f7410e47215bcf5649ec69aa2aea42593d18ef388f60ad8c1a74a159aae;
-  00000000000000000000000000002000
-       76ce612f9d8530ea654509986ba4a0645df0d0b80e10e2b12e6a4cb702f95c2a
-       c0d96527fe806580b6be5d69156b82dc48bbd4b12d4990993d40cafac328f24f;
-  00000000000000000000000000004000
-       72d9661f54335be3bf33f58b0691ec93c9a609c17f0fa2dfbec2447eb34e767b
-       e93447fc36f2f9d37e2cb768c89db3516d2101efe05d0c3b22223a1ccda827e3;
-  00000000000000000000000000008000
-       8e021165e98627b217339085ae839f83eac9175aff22755ad7f74ebaa20fc5b6
-       5d2972b74ff22287c8d6e4e970bba73ef9fee1e4fef6ab2b99d89266369d5069;
-  00000000000000000000000000000001
-       dc73ffab02254f4b2284ffd856e2919e87fc0b9527d57b9e3bf61a31d03b81dd
-       635008b2f0fa61c84f18d7a35a7a7348a962f913d1c9b2b4a5254d571da005a7;
-  00000000000000000000000000000002
-       4afecb963e1c36d3136cc4f4daf50e6bff15f54267917b3351678e4600523aa6
-       7fa9d1013537692d705c5182b9091c05966dca86d0028e14189116c19f000260;
-  00000000000000000000000000000004
-       9f4b44c46e94743c924e4d8cc858d6283e60143cc0874a1937306a75052fe73b
-       b6024707af59bbbb0615bac2ca2a33da7b06f1073959f2c40c3959bfe97393b5;
-  00000000000000000000000000000008
-       63876e05b127c60c29841b6ca86ebd18fef4dda37a6a3406e043b26bef1c3e22
-       a14ec552b38c9dc86fcd937f6e9693728fb6a2fb7d3d58171cc0ea566917ff0a;
-  00000000000000000000000000000010
-       9edb39dd3c860b44b0b9c8c3ad0409c4d5d46ab9da835790caa0dee5fc52f638
-       500c304547307d1fe152c11064fec74c57ce41f6aab2b169c2f16f6d08fe64c7;
-  00000000000000000000000000000020
-       d8a17909a21e577f2e328d71016f71de512b713fea91321410a115be5acdf642
-       41f6f55e0f5f58366cf9545cd5468e2d4959ea3e68dfe86ab05bffff37e9b7c5;
-  00000000000000000000000000000040
-       e6b771c2479f884e6b02273538b9c801699b85cf9becab29c5fd6a0cadabe4cd
-       73ab7c6f4490bdc9db345fd394569b6ecb8a645e0d3d96f6b04ed878f24c399e;
-  00000000000000000000000000000080
-       0f2643a424943fb1911fd77fbda4bddec8e2c7e0fef23aeed6229717f6fe08cb
-       cc23471cfdb0baa7a388ad9117c1f18762ef40c169b31ea08d045cb79499f78c;
-  0100000000000000000000000000000000000000
-       8070a4f0b3cb8b5c98a481a434bcd1f9fbe57a6bd2234f65d3b13837669d0123
-       ff5afd2824da440e1db01ece9ffffdf0f385dde8d53e1d2bcc105cc6ef9da6e7;
-  0200000000000000000000000000000000000000
-       d6eb96497103e048ac9c11cb94a715d02eeadf278cbeab8fad0cb6a0ec5b0cbc
-       bbe61f08d13b874806e69dd218276e5063e7f1f751f5925db4589e4c3da1e297;
-  0400000000000000000000000000000000000000
-       59d339d55b08d800ac4ca97c8d86a5e7c1aaee0c7e65ffa266927b3405d60e98
-       96f4751d5ef02128272f745f849b156b1ae4e9b0644a5067fce133d27c60d732;
-  0800000000000000000000000000000000000000
-       de5325a11316c25fe1b91e65f79d3c6a22b828c4964f23fc45e633f15a87d595
-       079c540a230618dfe713e1829b8c7e93b0e158daecbc960bebadb82320efa77b;
-  1000000000000000000000000000000000000000
-       596f017382966b3627b1f25542af544e84ba96d8fd3a8aeb70144ebf31542388
-       59c9bcd67749151c8298766fb67942b6f7eae3cf18a4360fdb712cd5e75bdd7e;
-  2000000000000000000000000000000000000000
-       b7949a04ac3f445ce916cb9e09a05f9806ca7f0566c08f8f0dcceb97c46d1b95
-       f7f160bb58a6190f3c070f2cac35b8ee30849382870b34b705e4f7dd308fa403;
-  4000000000000000000000000000000000000000
-       3c881dd73e0144100351026376ce0a6a1941f10c03fa89ff2428d8826cbf1903
-       7aefa4b489a42ac86c105d410f5979fcae26792159419768cfd6aa1fc80a6f34;
-  8000000000000000000000000000000000000000
-       b32024da4d4bf274e91d9bc3fe46dc22e69c8b4a63d64c7b25e670f7c03c8bfa
-       8e14c8584620b3d9782e828cacf93af391de629ef9c5befe7da320ad6f9f8b36;
-  0001000000000000000000000000000000000000
-       0f4214c4d1bee959bc8c28d62cce6dad19939f6f860d23c635bbe5f384f12cff
-       6008e0537b75cd2014da4133cd7712759fa1643be44533e1b2a03dc54e2290b2;
-  0002000000000000000000000000000000000000
-       3ec7603e6690a95b44d45c6fde7fc3a78aa7b6eed2bfb895edb615a46867a7d1
-       f8fa68c2908dd06a866a2c4fa3badee7c599a096346716ab31a7561db7788e25;
-  0004000000000000000000000000000000000000
-       52dfd065752448ecb5ec6b0d6cf8fb9f8e8a49e2102e8ff7c37d5b3dde9c0a28
-       b1f3f4bf235dff66f32faa679ebfd5b325611ba7d3f8fc51d9913e12f14de3f5;
-  0008000000000000000000000000000000000000
-       3687e56d4ddb4747cc5bd9d87d788741762c70d9788726b5cf55212994138b9c
-       81515cb2c8263971f764fb31fea9bf985b8407f30fe10c58ba520806832e6e73;
-  0010000000000000000000000000000000000000
-       d3b22949ce07d1f3d987af325246b02d4ee0e7a25ac7ba10d9fc3b92733fb076
-       448dccbba85ba4427e57bf048c2edccb826188767fa6223cce97709c3f3bf0bd;
-  0020000000000000000000000000000000000000
-       d6d1af9d789c6e91d1843d9ca3a45a0b7acbe96a94653bed6745d3c664d372ac
-       c32c33ab9df34036b5d18dff8fe15e57b3b290b0b734417035e68bb6661f2d17;
-  0040000000000000000000000000000000000000
-       bd8dc5a89393dfe78f81b85ba045b2d7a2035e38bb21f44b3ce1b15c617da6f2
-       d0a5f64dfa590de17e3fd7b9fde24de1418221879c0465ff2e9b8528d3cd4c1c;
-  0080000000000000000000000000000000000000
-       6e53761d95b891678bfa2f193b92d41b83e8c20532f35558be5038e0e85a0e8b
-       ca8bf1a499c9993cd56e17e5db838f99ee6e29d0f4ba6b0d684f543b71d7a489;
-  0000010000000000000000000000000000000000
-       43ed0aca7101f8fb1495a03ced519942c69f4504f2be3509ab35c0be0de4cc2f
-       b4536eea97929db21b08fe4ea78d3069f286234e2e287a3097480538bac74b62;
-  0000020000000000000000000000000000000000
-       da9389cf54ee87ca918aa30b99a37f50f67e2ee8d27f15cacb4f74fbb1455844
-       28dca73c0a5b6500370aa766fd03b596ef1ad7cc27843ea83c846a258c595024;
-  0000040000000000000000000000000000000000
-       61a6288bad6f3a91a68752814a0c8acefc56b94b4c45b282d3ae3ef6029e0490
-       8b8433d94c9e6b4df405d6d3214889231efb191e1d3aec05081f982f32054841;
-  0000080000000000000000000000000000000000
-       d7141bfb37d834afa650bb1d7839b34d1ae0ddd517864ca48b310b53dba1a47c
-       f68a00c3126b04a87d6a9ff061fc5c8a2d0e66ac263094fd3f081c14412c4a73;
-  0000100000000000000000000000000000000000
-       8ed10898964b362405b3996a4a6ba087330190e6bca03990e3218a33411783f5
-       baab2232f4ca0ed0f54fdb2b0f73f8433c9af741034117f9f5d2cd10615941c4;
-  0000200000000000000000000000000000000000
-       89d7ef42eab86d3209b67353e76da8d8063c91447f916f91378a627a49a0e459
-       2a517f1fdd3019a3d026d9f3a47545ee96634ac8e13b1064a57f82218628039d;
-  0000400000000000000000000000000000000000
-       009ac31bd1a5117e0368fdc254230a92cfbadd5984fedfe684b3ad18d0489f41
-       a5d26e2813bc41a4e9c40af519b72ac6b2a2188c8b89c77a410b6fc732c41581;
-  0000800000000000000000000000000000000000
-       1270970a59191c419b2de4003db3467cf453ad79ee93ccd5ec06da794a0174a3
-       99e4e43c3199b6f493fa633303ec08942b6991188b987900ff3b39699f7b6485;
-  0000000100000000000000000000000000000000
-       ef02c43eac97a89b7f0ffd491a031dead11231530abaf2ac6b2ade53e2f742be
-       8a74dc87527389474c1399ac4b7f4c47522d8b93df856c96c129456e5bcfa0d8;
-  0000000200000000000000000000000000000000
-       66efd72c1ad170588847c1ac5f1e957e38e4e40eb891bb75093ee03d19339141
-       8a822f512118c172bf832680ccb9e0e867e04ee2022db6a27d98ed56ea9069a0;
-  0000000400000000000000000000000000000000
-       cdd36ee6c5cf010b1b093b8f5e0d91d742af7a32b6e98f9ba412c1d523687e5b
-       92f8d1fa8d6eda70f7c404088b519cbcd3f31a755b74a7c4474ae4eca952c7ce;
-  0000000800000000000000000000000000000000
-       99576731bb509c8f2789eca8269cb7d200e7e7c487a59586e7ca065c6947c844
-       c4041960f5ffca9c75a7d27f5865fab9f2c8c536ad6408d191470f2e0d6ce33d;
-  0000001000000000000000000000000000000000
-       a49eced3ac57b8733ac330b477469b8d0d127edbb76c8b928ef8f3f6e7a844ad
-       c048e5899e9eaac8ef454098a4bb1a48e0cf58a06d4f1f19f490452e43c23888;
-  0000002000000000000000000000000000000000
-       6372e04bdbf3f8d4998cf16dcb310a17d4257042c2ab5f31ce7d75a7c4477ce5
-       e6eb8f3eb48465f368a434ea0e66a5d1bd4a8bcb3cc665a48f9e20d6c15e2d8d;
-  0000004000000000000000000000000000000000
-       aa3bf81795afc567b3860441ba542fadbe778b837d89972e419d9dea5f886cbf
-       2fe69f415c844ef3ead9e86620844dfdc9af44c0133e5655130fd53e59b9052a;
-  0000008000000000000000000000000000000000
-       8a5c212066e91da99ccd0a8ae0fa1c7f232ff503fdf33d84a6311d421c8a6e32
-       a2d43b8ed9c582f1ec1b7867b74c81c17450698fb8c2e2333e4a7fb9986180aa;
-  0000000001000000000000000000000000000000
-       e65a5b5f8bf7395960e4150e682c586156617280b5dfa259310491ebbe5bffa5
-       473a1e953ea38940e3d84df3ba7b6fefbb7bdf7302a9a9d959d088aa56fc439f;
-  0000000002000000000000000000000000000000
-       215237bc89cf72610eb50cc2f788fb66f5dcf5a36b11148d25f87d3fda60432e
-       e1e465d5d23f00aac475c9021a5dabd753c292e6e0670d8db8e5e2519476c3df;
-  0000000004000000000000000000000000000000
-       521741c91ad5fde0abe8ddca960ca3535041fdb1e6446194e63d1930e7c96be3
-       32611c8c38cc3a0df330bdfc4ad7366287ab2c22dedd6a852e63eea38e84192f;
-  0000000008000000000000000000000000000000
-       dd7eb22684ae6346df02da61fabe51ff32fe48e5c2f276976054c7fb400ca640
-       8702b65a7d1b61b5843dfe394cead041a481f9ddb368187b60291730d7132b7f;
-  0000000010000000000000000000000000000000
-       5fd0b1e839354deea2b44c7811c94c81a8153e6bbfed98d4e744b02fc965bb5f
-       3c6bec05f5cdb092483cecb0f7996d3aecbdb8f7d738bbfcae9d25a210d3b94e;
-  0000000020000000000000000000000000000000
-       39c6626868026b6a15c5ccfa2f83dda7018b6f2f576de8cdf009d84008fc726e
-       b7e8ff789bee4bdab1fc6c75c73d83dc3cbc1d60c232f54c4dd946470b7f0b8b;
-  0000000040000000000000000000000000000000
-       c945f53f19eed324dd2035a90014bfeee3c46216f26e7b74978dbeca03765dc7
-       38b825729109c791dc588f392f448085ae8da62feae27adb5d667b7006fb1edd;
-  0000000080000000000000000000000000000000
-       ce0d4ce7c9a8c7ccd6ea6e5d433c4d7db4663542a7d1c90dd431e552045f5155
-       c50ca8e102497116dbb78c0bfeb0e39939b5aa59bb7cac8f127ff9f693f7b124;
-  0000000000010000000000000000000000000000
-       dd675ec3415137b62955dc917d348109c45c85de9c60095f94539dc9cbfde9e6
-       f26014ef5bebf40dab8052592070a3a2f0eb6fac1b0627a8cad7c8fd19511e41;
-  0000000000020000000000000000000000000000
-       cc5398fb1486ee124e32221736c765e88006f8e0f31f65e337f0703241497896
-       e8527d10755dc5ed2512898102fa37a952e12d5a9cf99ca663c4f8aa556107ae;
-  0000000000040000000000000000000000000000
-       ba7a51cbdfcb2b3b9bf200cd0a5c7998c5753f861ca0d2591c7df18319b0780a
-       6a5aa39bd5e4856eff8ce57422623aeb5c5fc7099c6d59e0b8d1f47040f833bc;
-  0000000000080000000000000000000000000000
-       f8b7f1b3006cfe461b183397ff4ca13eaaf8c34528f48eac5514614eef979d2b
-       c276a602c32cb0a9f15d45a70f606272179ff0b13e804fc3290d14cea182d555;
-  0000000000100000000000000000000000000000
-       8ba47e063938c6cadd65fc3db823e83edde887175d6103417f2648a86ecfa38f
-       f2b45766823ad20d89b12b1eb65ea10ac1f4ca042408f775e82c3a86c7d870ca;
-  0000000000200000000000000000000000000000
-       82f0a8825caedbaef6991dd7cc33d8a22757b4b65186bbb70dd274486bfdc6e9
-       e98621489d27a3f8ffafa5f60c454f5b43073fa13b7b1e44cf5b42c1f410b757;
-  0000000000400000000000000000000000000000
-       c748b58d58bd39b77224713354f8abe888a55813cedbd581c811edb61f6ea33e
-       0341ef9ecee1633e77d1d8152dbc4b536cf1d5106e279f99bdefc7f65b002dd1;
-  0000000000800000000000000000000000000000
-       cb1703a29bfa0d5f8e074f8c8efad1c3f99c3c9d56270a3b0b223d792414a6a5
-       153618a5aa9ce0a5640c395dbd5c65fc78ec091d9268083bf1a8ea6309572237;
-  0000000000000100000000000000000000000000
-       da0eb94b57b73ce632f0e096e8b9657a8df2a7602ff80f33bd23621b3a9011bc
-       84946c36ac9e6ee65c9f39aeada388f91304420de373b45eb9899941e2059bd9;
-  0000000000000200000000000000000000000000
-       28593a296d86d90b64ccf70ad60d0806c194a49477369151d8d1b1f534a73ccc
-       f4a5b4c8f1d7a01e23b7695421e91f864044ca51b3d6e946eda4dccc66bbde88;
-  0000000000000400000000000000000000000000
-       5432743ae99f48de5c2c943b81b4c994e7af4a9df102302bce61e51da7b7b1f0
-       cabeb087d68155a0ebfd81f81ea7a0451347e8bf2b409e4d3db752de191edaa6;
-  0000000000000800000000000000000000000000
-       c68b1f8b2e568b015ae4684c81d28e1dc4f2bf15ea8637043589555e59fea56c
-       3c7c59a6b7446857459e8c2812f318c99d6f2eb8afdc8f7cf3fe79b9e43ebe6f;
-  0000000000001000000000000000000000000000
-       1e2ce4d6fd55f7b624b05e5ceea3915ec6f061229fc5897fb5ccbd2041477968
-       eb6ff717f26c66672b5c99bb95c0604d812a70360e361cfc1ed6f67226f2f738;
-  0000000000002000000000000000000000000000
-       882b04a32f0ae1ee1c03856d4997bf168482eb9e3c66db15caa3a5ff61f92663
-       a28f92837893ca7cdaeb5afb82ec7808d6c0aa734a81c4f9e8c207211fc00dd3;
-  0000000000004000000000000000000000000000
-       0e6d2c813dbcf23cd711ecda6066bb9d03a9babe2f6471d683494b58c0788d44
-       4c601b1e752c45492e42f54e5eb528bd884a242a96bb8a638d9b92201ebb3707;
-  0000000000008000000000000000000000000000
-       6e697fe8636b48bea38357c377f999c717fa7ab055a124b20868098aec8def00
-       cabcf9f62a30e5a27df4064af20a3d6f0db35f915f556fc9c349f41575f97247;
-  0000000000000001000000000000000000000000
-       9bb65307fb501877e3ada81442cde498d1e05d7cb5deaf88ff1f0b6db92da4a1
-       c7972bfb8c66bee89a3cae24999a2671a661bb5e3591f811749725c31e95daeb;
-  0000000000000002000000000000000000000000
-       4b1c3460a94891e4f8708feda342f8c13de4f500ecf890c23b54614f759c351f
-       3dccf6aafd9acc0a52003729bc92cf541c72f1175408aef6754c07308f3186f9;
-  0000000000000004000000000000000000000000
-       237f3b1b70bebf261fadf4fbc61f4aed6b2f7d41fd0bc3b8701ec87f0ace3b73
-       9b575ace6a7d3614985498611990b61cc6fede975d36c08b48f083a2eda498b2;
-  0000000000000008000000000000000000000000
-       55819dc855dc272f8e813f473d0be9f7b0ee777581c68236fd55ba7cfd7fad54
-       01e96efb1cf82aef7bb041c59e16696a196fd263376d478d12d5c21f8b76bf38;
-  0000000000000010000000000000000000000000
-       46a9e2ece5c6a61677e9fa44e91c15ce095e6c2af0e66e3daaca8be8f55bc072
-       9d1d1717693d05487a24e6c0824c07ad87c0490e6a29de6332e5aa0130311fa8;
-  0000000000000020000000000000000000000000
-       9163353b13ab53a5f0cb758072b96891fb46d429da59ef58cda3ba1a9a2162e0
-       2a939e32e660b6cbd4ec22903b3eb454acabe834e59ce753bbb566bda8e5745d;
-  0000000000000040000000000000000000000000
-       53653c0563d023d51c758273c7ffff07897ed19015f2b352543711805f25d2a2
-       638a9f6d0768463b2716ca71fa1c3ef0a758cc2f47e0d3c3afcb50202f251ee3;
-  0000000000000080000000000000000000000000
-       7b1d6650b48a58d529d174d40c34ece0c4725893508723c9e110306f12d2769a
-       09a5fc3739cd6e79e94e250eceef8a31bdb30ecb4f4f47e18f9a3645e82e2642;
-  0000000000000000010000000000000000000000
-       92fcbceb6fba200a50f039637b8afda2c5d4a06efdc98e6094a986d0eeee92ef
-       08250f4cc12c732a3b1a82411ec4a8604bf119f69b07072961758780c7db87e4;
-  0000000000000000020000000000000000000000
-       82af5330a7aa9696a6be8129342b9b1bbace0b879ca107b5184c0902793efa49
-       c286bf6ab754af7f16244b9de2566e9442e13919b2d699d62f52d384362f6331;
-  0000000000000000040000000000000000000000
-       93e0bf62136720977660e0eabd4694514371b3b54a27027dccdfbff5aac51f34
-       29955264c6c52f5fc3c5475f4f6d478f1b17618585097b9fdeae091bdb9e8446;
-  0000000000000000080000000000000000000000
-       69563766cc3b858a015e0655cc056ac5356ac37f3561495fab6a012ea62276b1
-       41bda0a8164a083e3caac42fb15d94247181034d2ade38a1b4399eaaac07cbd5;
-  0000000000000000100000000000000000000000
-       ef0523a9b2ca36ad2b3b9bd9c2209a1ab8c8dd205e48140d577de7ac0fae02f6
-       5f3f8b6b15d822ff9d852c701294d5c1bc2e5e20c4da9e56dc2ae6f1ab33c084;
-  0000000000000000200000000000000000000000
-       0df666c1b2d781312887e6d30f21f12e6e2d4dfc2bdc0b5484f85d35c091a453
-       87a7fe3652e203d98ec75f3c61afbd47f8fe2f50505860a093a7aee292366d10;
-  0000000000000000400000000000000000000000
-       99d1b163bd4fdd4bed820ddd6f4b5b8fa0f1590a97117956570a1a0fa075c473
-       24e6a698f9880e19447971c1de0d598472d66df54ccb88624369af5339e4627d;
-  0000000000000000800000000000000000000000
-       8a76142c207334f1482a7b748f48fd583e34ecc52c33ca6938a10afe9fdabc43
-       8311c7ba99465892df7554b6c06740333d4f4e79496b6bff747d87bb3f88f780;
-  0000000000000000000100000000000000000000
-       1db97ea24610af47d6b4a43c2ef0b031a81547d98723e46aaec6d8b4e29c2d8e
-       ead758aa4b4ce689d61f7705ebdaff4334bb882e8286fd6655398a8f5013449f;
-  0000000000000000000200000000000000000000
-       38f0302fc696e3e644a4c58400b050275c75dd77880b7c81b48bc49f5eec4566
-       fbf97ae99430d0582c8818945aafaa9d08516a56150d96842c67a69aeb6f79db;
-  0000000000000000000400000000000000000000
-       e10afdea821dcc504167b562bb1abacebf03a183a29a85593f51aa83463ccf42
-       1a60ae0e1289cb5477717f4bc7fb936b91d2018a7121f29db751b5ab9c739657;
-  0000000000000000000800000000000000000000
-       f8178e6e47dd9e38fa46d139e9da92320ccc56580ca6790e6739d98a16cbff2b
-       4d5274c530a947a0475c0581f946897e2b4f9e01cfd5e9edd5f00109724d63ef;
-  0000000000000000001000000000000000000000
-       057dad112fab7e5e2f13bfe3692d29cf7231169ba5456837384e1d3178d44399
-       493491ac15958b53294afddbcbdeeacb34f1862c38f0f8514b3190d494611dea;
-  0000000000000000002000000000000000000000
-       32783556b2a205849744b683e3c1cb67a4546671d51adb868f2abc741d277ddf
-       8b7ed6253816d59663a99df68a9c4437ac9ad45c2d400097e69c1492f5a26ef1;
-  0000000000000000004000000000000000000000
-       192b1eceb03afbee8bce727185baf599c1e281b6819b219f7c604646362ef507
-       21c826646e076e934f521cdb6933b547e1f58a1005eb492d768a8abf545f99eb;
-  0000000000000000008000000000000000000000
-       151ac1d0c9497bf7905ac32c3bee78042c1cf57d144b33563c0d524197e1684f
-       532ae17f1858e56b4fc1c3442a3eb5aceb9c38dbf6c8373740d2c70ace135610;
-  0000000000000000000001000000000000000000
-       43d263d71480616fc8d3ee5f26a7b4322f64c52e2eb08bf45da98a501379d42f
-       10915428d4d72172524b0af0a985b857b11fb208305fc96bcb0bc5da329e5a4e;
-  0000000000000000000002000000000000000000
-       b93915219589225d93000fcb969ae487a545f909fc74b6eefae8ead8697f4a94
-       2071b90c399dacf0251cd331d008b40d75c5fef91e76c2319ab297226cfbb751;
-  0000000000000000000004000000000000000000
-       63304c37894c70bb5d871c7cebd6a03e5e63f4e1d0ce0149c287f148d2b43bce
-       5d7fcfed1eb5cc9052d66c073e9817db944323b90f2e60871781078aeb23cc33;
-  0000000000000000000008000000000000000000
-       56f9602f84bb4c0c7d7cbcf427a401fa8c063edead092d93a27ecedbbc080238
-       683821a05f317992c6ed3dcc523d147872ee872552fd4d9935e72cb6880c8ffd;
-  0000000000000000000010000000000000000000
-       a36adff7f8c3aafad248f0c875e959212b533e09747a95c89b6443487b426be8
-       2028682f6b9482f668e55b06144ce444d4bfffdbdb119b2552bb2ceccfdbad5c;
-  0000000000000000000020000000000000000000
-       76131f29b957f35e6b776ea6a737199b00f945ecfd146443de23d1c68434209d
-       1f40950024d089bc682ee4b0fb5fbe079f988058993f3d3ff928cf087cb99dbc;
-  0000000000000000000040000000000000000000
-       6589aac4967d58ae26372b64a7fe4741ed93ad4bf7fbe61f147c0bb21056d95b
-       5bcc6be06b77e64e4f04ab552a0035c664be7c6ebb2a781e7156cce573e2856e;
-  0000000000000000000080000000000000000000
-       c6ad32c723a34b02cfab4f5f9d5b6f14d2a27655620fff9650c5f496271594e2
-       64dcacef6699660227dad31c50c1752711dfd4df95efd2918391371cbdb19f6b;
-  0000000000000000000000010000000000000000
-       637460f7bd663081a501baf9fbd8f910d32b74f95532c73d2931cc1c70b6f61c
-       6611acee8bd7dc914cb5b2310aa37c44041d2d16d2c6f66493d7d0364ea0d137;
-  0000000000000000000000020000000000000000
-       2498e35499439986614f26286ced257b12145afa582093f2df311a6eb768a3ad
-       552f96f75bc0d3c7995970c9785cec08d1e6a848906604d7ca1410caa09110b8;
-  0000000000000000000000040000000000000000
-       08d3d5cfaacdfd78f5890e84ebffa55f6a30b332d09aa99f9a39c57b1a6e64c5
-       bdb53e5e22c6dfa1a7ee078c6dde02f999d36a8d2bbb4bd6d8d63344b50d7f19;
-  0000000000000000000000080000000000000000
-       6cfe9b516cf7e08a58d825e13c4602c1c878297b993fcfe48398e8d6db759940
-       38f793f71c6896b2ae6bd730a548210cbd9345ba211180de67385a6be2aad623;
-  0000000000000000000000100000000000000000
-       eeb6ee8db37ba7df8caa911e25dc2fa0077b3931780d2ce06d4a15e89a2c859c
-       f4755374b79e4a32021ef5a228d8eda5e7aafebd43f4c6bad599e957e3b1adf2;
-  0000000000000000000000200000000000000000
-       6ba41750ef7da69feb66952b1ed18b75e20086c0bab3481d8211a686f317166d
-       278cdb6ba1b4a9b624564a5a76a713887abdeca0ece63a6f0aeca268d8ada97c;
-  0000000000000000000000400000000000000000
-       872c1762ef5842c8c9f7117ead43024f8ad0734be8d1dfb48b2be8fae98cd374
-       7cf31344e19d4886a0b36cc6b4777658216be3a32048e89dda78470379c0c653;
-  0000000000000000000000800000000000000000
-       5263be92980bc943839a9024fb1140864999ff02fe7ddaaa35d3d89f9f345c13
-       9a9012f7b455a4b8c50d5917fb5969723b70ab3e0cf18cfd5a1b841aa6c0e1ff;
-  0000000000000000000000000100000000000000
-       451146802e160f788555b58164ff946820a782bce9ae691a2969fcb250b66773
-       1f85560430ebcb39c18ad9bb8dc49c0b1e1d730bf8cb43121a8c94a62daf56a4;
-  0000000000000000000000000200000000000000
-       83a737dc4f27d59528e688c55a52e4c44d518dbbccbf81bde212b87e9c63bd53
-       9fb8cee4a538fe0add8823986f50ee648c36504c1ef9054b748cc437ff31d25e;
-  0000000000000000000000000400000000000000
-       83154c350ea26c88f23c2585c4c1ce85f7febba6ccec68b960f2bd2ae6284c15
-       9243e796bbe38ca38d0d517116510236b81b5e84d662a059c9834cd57eb2408a;
-  0000000000000000000000000800000000000000
-       78f73dc4ddcd6357d1cb4fd1e61d2456cc37d84babbf5a6e70f9609ff9527602
-       e0f9f54c77861caefe4ba8ea6a870a5831cdb61ff0658ae74177562676c049b4;
-  0000000000000000000000001000000000000000
-       24203a6fcd8ea87e057f38fa775d88c1caaafcd57982d97ed5fa6b99a2814e10
-       7d327425d003904c745509c265bd70ace892a7ad23496f335386af2b3fd8a2c8;
-  0000000000000000000000002000000000000000
-       832c6e20ac336d8d215c1b618870c33857ff4e616df40dba963cc422f9cbd3b4
-       ad1f44b624941028a116896f053305978f382b85ae3b24330fbbb328fc835cd7;
-  0000000000000000000000004000000000000000
-       b68daadcf692eb67c1a69e854424f45a3cc07fb7c042563ce5db29811909fa5d
-       4e62699870105da1c27da11a482a5c79f174881179d3448d9518547b12341eb7;
-  0000000000000000000000008000000000000000
-       af03141ab732bbae48789b2efd96995ef50977d07a7d9ee741cdc1440904c599
-       8b295745e425a4b798d230f62adf6cf8ed49183098666157987fccddec8f0113;
-  0000000000000000000000000001000000000000
-       b69d0bbfed16b59a8772777e09c866fb51391d77552a32d8a971678776e97a08
-       1cb999bb1e7e9dd64a64302e09447755ee9c1744139de4cdbd61088bc17fc24c;
-  0000000000000000000000000002000000000000
-       5c982237e3d812369a5084f68792b88f33fdb8278bab9c069572c4d2d4e8b1fe
-       7a4c0dbbeaae1b31858f8a8e4628b56ef552d738301b4462ffd682af0d26e871;
-  0000000000000000000000000004000000000000
-       b502c31e76e20b5cced9f96fcf49e786b477dae329aa612edc58c8c4b310c881
-       3dc3b0f31b61c28bf208b35ad68715ae247a8bd3ece8c6d38f4d03281e0eaae2;
-  0000000000000000000000000008000000000000
-       1cf7cb0fe06fb987e82a7097abebff97b074e00d32ca59e259bb64baf610b932
-       a8f685fdb0fd2a5090ccc7d7635431954e6eb4b58ca2110fe691562800725f89;
-  0000000000000000000000000010000000000000
-       0fec5eeeffe04cab0fff3d6cae817db15a4151fe22a6e3ccccdb2e56b36c3ad9
-       7df075f7326a189ce1f5ed3b8428731f67d743e2bbb3037043aefc55a401b534;
-  0000000000000000000000000020000000000000
-       3ea8f911b282f21db8709031e607c193b4604a8b44ec36be34cf0eac039346ae
-       1ea420045663890821dd21eff43b2fbb86568519bdef2a13dc2d141c05e36830;
-  0000000000000000000000000040000000000000
-       8a84fd4bc516cb8fc163352c8fd600c8f1a07861f052964727d61a91d155e7a6
-       3b8683901243ba7aa8705259365f64ff8daa64604c34bedbf4d655c20ec28b99;
-  0000000000000000000000000080000000000000
-       de1e1860d637140cbc270026885c391982d0855c7177106b1a38103d3cb5d956
-       21c1f9266ef014b9bb8f9b9fbb884679d1e411f96e1173ece0609fa01cb0b16a;
-  0000000000000000000000000000010000000000
-       4e62340d4fe3b25f02522336c45b8f18b5944d41a72e0af43e2c1dbf4c32a504
-       185c48576c96afd58a5209a255a7324f850fc9a3be04080f9a744a5da8ab71c9;
-  0000000000000000000000000000020000000000
-       9c44e17c60b2e4a25454659dc72aa415c4701d1c31170d9d403a2f16adc6521a
-       092e70d956ecd2c938d1ab9b95588dcbb1fed47a6cbef019cb538c1bce1b20fb;
-  0000000000000000000000000000040000000000
-       c60d7ec161b0ae0e347bcba7755c40cdf150d67901070ac4698f1d7c593e6d33
-       1892f5f715f53024bf4b04aed4605e34539b21260ead7e00c4fede1b58f3f3f5;
-  0000000000000000000000000000080000000000
-       7b4709c2543c6c98e858392f44244e3a4606e5459910badafbca6422762af235
-       fa8b0b95b7d3897667c8798b5288bea05b8585264f1067592e70584d45e54468;
-  0000000000000000000000000000100000000000
-       f6a82f150ce106cd0b67c6251144cd0934623f64a7c0c02cf20f88c5b81b8f9f
-       d08611f1a55c0fa0022732787866879f6057bcb0d3bd8be4950de988f2703b5b;
-  0000000000000000000000000000200000000000
-       036d8796288546f6c8faa0137f542b79232b1f710f00d993bdd209d608b2a983
-       0e4ee8dbde805bd218495fb6e0c012da36af3118fe3abcead1cb9b1d0d9ad7e8;
-  0000000000000000000000000000400000000000
-       93bf0d046d56227e10a60b6724d8195732ac7497dafbc5f0415aec8f721feab3
-       508975892533164bd482c18d17b1190de8ac5c603e22dc78dc033dd56d70e498;
-  0000000000000000000000000000800000000000
-       92242df9e82635f00fd079b03fb3e4ed2e479076a756daf823ef97e067bc0a9d
-       e52168fc1c39bcdaecc13f07ad602234f0d6fec3ab60edcc2703b2ebd9a428a8;
-  0000000000000000000000000000000100000000
-       f20f59b1d2d69ab79957d62fa9a683180b95d772f33205637f3bd211a570c182
-       ba077c245b7cb7030d882130b15298bcbf15f4dcdf2df67865687956f2d68f8f;
-  0000000000000000000000000000000200000000
-       0c5eb80aa685a53d856cadb59327c84b33379abcc06329cc10af1096ab8e9454
-       8d8ef3a1486b1ba3e3423ee8e188036bd06a73abc506cfdde791de57f35818e0;
-  0000000000000000000000000000000400000000
-       c1b93bce555e86197fbe389b926c37d918d88bbf3d704496986c0cf3bd959840
-       3a7a664d89b1acdb853c6bba7c7de3322545bf58971c93f2b8c9085d3734e31a;
-  0000000000000000000000000000000800000000
-       b9ad33f00c7029630ff7db4528327cdccc612b607e63faf35978fd27810f345b
-       291fda0e13c6a6aa8354acd6be229759e97a52cfffb3956dc6a1dae438e26565;
-  0000000000000000000000000000001000000000
-       3f7e83921a8fda45c6681ceea340a1bed22ef6ed784fa8ec0301cff998bef05a
-       bba9ed3d86edc3e850c58372960a340aa75046aeb845b53ac521b8b05800ae48;
-  0000000000000000000000000000002000000000
-       d504cbfa2d69cbf0108df37bd476fc93db12df17eac4a10f52c5d9e8560b7a93
-       81b71096f284866b1423cd41da22f003afacab0911f08c98a23bc508866a2d82;
-  0000000000000000000000000000004000000000
-       ca5c7b0f2e05939fb7b30358930f2db8461c4a8735971b7d0ecb429ad519e9ab
-       a7b781dd1aaa84c9ea0fc8977f9ebab91af4910197205e5fdf90568e51106c2c;
-  0000000000000000000000000000008000000000
-       96e9e78698c3eb928ac8bf2a6572d1c153f6311d3d250115e502ded03dfc2e74
-       e20aabbb2137804b4493fe7b17e3b9331592f8f44ed1903d1d1209b26fbe9a5d;
-  0000000000000000000000000000000001000000
-       07334423e99b879202679cc4e3f674a82a731d02ceb5e74cab08c90b6228f0ae
-       74458c222e857b9033a9f0453f366f4ad8b4cdae922b8a80e46aacbdd6f647bb;
-  0000000000000000000000000000000002000000
-       68c3f9679c7a21ca77da909fe45578928bea63c882d577d08049a05103efcd56
-       3d0ef4fd9b8359f4aeb1031c31508876e8f0ef38f8613bf027823e9aeb005445;
-  0000000000000000000000000000000004000000
-       be2bf2722cd6eab12cf20d28cbed792662bc26f0b92295e53411267d4c72cebf
-       2187e559b2130dae8142fb0757341c0a1e6df31508e6a19aba5ab2cbb0a9c872;
-  0000000000000000000000000000000008000000
-       cc30e166ad1cf014644af5c3b6c65b45fa594e5e371e404388e8c051e7dfa4a2
-       fbd37c904a34800318acec016ed34c12de8d8d1241256d4a96a1ef02d707d53a;
-  0000000000000000000000000000000010000000
-       c3b8c49a86a432001397415ccc1eea4d77c5e7b1e6b8dc208d69f2865a6b8678
-       de5469250f0cc42d2e202f29af0e13b31ae5acc68fd5107819880d3db6e0b8ce;
-  0000000000000000000000000000000020000000
-       c169eabc1437d7301865ffe544bffe0767cc733500d6a67cef204f6078d58328
-       4c09cd0d212dd836a6e4af52c5fb1ee851f5cb07465e5f592fb8024d1b0c1dc6;
-  0000000000000000000000000000000040000000
-       758c11f8fe1f10f109d8df4790de952c900afc7a985c6844195a86c66bb0780c
-       6985483375dab29f2c9ddf2e4acfaf9ec9ec0b90d0ff59a51f76901449125973;
-  0000000000000000000000000000000080000000
-       c818f59d0447e726d2839c82a4c12360f7ff8012d84bbc1a367cdb2299457199
-       d1e7b740f3c2549929ba0d3210f259df6ef2322e9ee4d6f317ea4fc8ec4d2998;
-  0000000000000000000000000000000000010000
-       3aec597f7d31483f810f14fcddf9be067f56080a048a9e3b4098e6e28918a800
-       7e85288628803f83717499b69f17adcd5a66ad8dac68d0851db8eafcdab3cb08;
-  0000000000000000000000000000000000020000
-       0b6e2edb89d22c535a5a68e75ebcb0087ef1f236d2a2266a9d543d6adf24f479
-       ac7fee6480f401eb8902005f7b8d512094017f3caacb8249082606c36d98d51e;
-  0000000000000000000000000000000000040000
-       da610e5a8a7a85ea2b84bbcf3b40098290a15d4ab3bdf91d7e21fa524937c783
-       477e7784dedbaab64f19ea69b8761c66d5da3c5cb51551dff47e3fa0c68fefdb;
-  0000000000000000000000000000000000080000
-       0e8f5819b7a66f25281862c132d5f339cfd0fd4ac4f91c14f226ac0033dd1117
-       42352ac10368ccd3b833fec7b048741501711ab1036dc7d159e150055a11586b;
-  0000000000000000000000000000000000100000
-       f546da839861af04600c9417e0fe884b8c1b6f4a9a9d36c4da7b6ee24ff3c4f3
-       c543450e77a3e87a7be1d6233b79b3e42597228f0e08c4f833622194f64afa71;
-  0000000000000000000000000000000000200000
-       f4dd95284ab89c6c53d7ae177d25aa3739dc721ac0870c2793f3723b6e093363
-       48118b3d2203906c7b319273f372bddae10266d0d8065e636cf0bfd747c7c984;
-  0000000000000000000000000000000000400000
-       14094297b5bed9c5d7651a2787c232c9c9089f542b76f39b264c1b591c4f2e18
-       09a61a1aef6ad53d3e2b6e93389a279752f78c62bcf530b7cf0c1f3bd3e3b529;
-  0000000000000000000000000000000000800000
-       212101a1952ec6158effde6a7d48a4929304fdeab258257266530262a8ad48f3
-       f991e1ad77a2e13b92906767da523e4d057eeaa263794a087a02bb0339972b9a;
-  0000000000000000000000000000000000000100
-       ec652827a0f5cbec1068ec4193a152e4a80d797867646412d18367645db6df2d
-       033741b62e08f79b8d6192c93775508f23100fc3a4f35c3073cb7130a5211abe;
-  0000000000000000000000000000000000000200
-       646046dc56a8b7a4186e481ebf943949eccbe7147e0220de8dd05fa656e92dbc
-       cb5e4fef77193f8256bfc49a91e001a036582e2e3eff8173b27af708b7e8480d;
-  0000000000000000000000000000000000000400
-       bae05fa0ca832ff9875fb1c886d8ec8eac6b730bd2427b9cfa8696d3ab3cf5b2
-       aa4ea07107c3b1cc519fbecddf7c966aab50188cdd0d46bc866b19e882deab36;
-  0000000000000000000000000000000000000800
-       1f8b6b9b95efdc182d35f1ec5104489893c70bf1fe7ccaa67ae55ceca5152981
-       100e51e4e6d5a44653b9c51ba6c9f070bea9d470bf1ee0faeee1d05122cdde50;
-  0000000000000000000000000000000000001000
-       c1703da3b5c222872d09d493d03d07e36e6d04e8901a248ce5fc620c5dafc381
-       f282d2b589be28bf64c3f8a454be2101322666b3c7b71369496d630cb5c5fdb3;
-  0000000000000000000000000000000000002000
-       e76669b223af08035c5deb05e10666ad09a99af191a3ff30bbb7202b65a25033
-       15240875b0e1b9427a28e2123f85f74a1b5924e3600453ee45556bb328e8e941;
-  0000000000000000000000000000000000004000
-       511c0362a229d88ba90a523f862d35c0305b08dcf4b9e37bbe2efcb0dea8e6fb
-       e8eb57458b73a15d4eea4dbfc95dfe99ea52b7f07cb3964d1c0caa83de2fefde;
-  0000000000000000000000000000000000008000
-       45d00f70b107ec873736a23b9ec02b78e68c6ffbbda1778e4a96d01d42b20eae
-       f5d0539741362a0c93861d3c167aebc148a5b34fb3299e600abce538bef5fc5e;
-  0000000000000000000000000000000000000001
-       41ef971618e7923106427505bc765943909724f81c8bc9b0de756867d40b444b
-       8bb9e4dcab530ed4e491e020b59ceaefdac18d23ed01acde992f20f44dc74004;
-  0000000000000000000000000000000000000002
-       2536ff6dd06c356f864fd003738e87a81c5bfb44bb7714838c5d068300abea93
-       291f63a30d86a1aa7347a9483d8cba05eb27375c43adc7fddb0ea9bc50e5a794;
-  0000000000000000000000000000000000000004
-       55dbca7e091006fe395367c4250fec2d1b994aacdf8026072d1f3d92fc7475f6
-       da7cf09785d9b6792e20dea6dce0fd4e65bf87cf47ac674a83588f3642d6d50a;
-  0000000000000000000000000000000000000008
-       f662573e1d83a2b58697b4f1923396b7d89c56fbcb21a5a3834232c8c0451f57
-       b6f749429a2d9ba1b479cfc96886c679c7431b93a95b87f9187680c1a7b7c792;
-  0000000000000000000000000000000000000010
-       a398f5779517a7db0f56007407f9cff857fd68803441d31bb6a4752a77dd3495
-       89ccf7cfec665a5dccbdef72ebb60388a3e2a892d6030574bfa92f4e61efe6ba;
-  0000000000000000000000000000000000000020
-       58a9c4323b56584a8d5378d2004c1d6f491752ab9f1b750b9745f6b5f4c21cca
-       acd8d6b0c04002442e0c3c983fe656d5cc54c2782c60d867cf7445cb57feef1d;
-  0000000000000000000000000000000000000040
-       98303a1f445013eb3be40cff0d6f4395501b83b825d4897520aacd6a36703962
-       1d92ad624dd448b62117c533e70c0d13ea5b3a66310a979edff479a50b99ea17;
-  0000000000000000000000000000000000000080
-       11c40125db6ef51d57e603b8beec27babde3fe9ab63fc52a0cf7f76854c936b3
-       b9dc8672196f58cbcc5708f68f510d6f908b8a7cc0df0ff83d3a7c8303e78777;
-  010000000000000000000000000000000000000000000000
-       f9e96db294715055a91833db0fb33e9c91b54bede26f9a06abdab80a60311e1a
-       90b679951b11be0bea2a87a3eb8c22f42bfd07e51f33362a1ac0d7bd959b5191;
-  020000000000000000000000000000000000000000000000
-       0c38a41f055332c76457a13f95ba264155c979c9124b5dde77318c49d1f4c01b
-       405919405dc48814b279e93f34899237ad9ff2f2aaab9a4d7b04d5572a34c541;
-  040000000000000000000000000000000000000000000000
-       1dae71958a2d1f4c332bd9f343abb658590e874b4bb4ab807773e95bb42cf82b
-       a87bef2e0ce41b11221e01b86192f0eca8c89fe36b119933e832d9b317abe3e4;
-  080000000000000000000000000000000000000000000000
-       a77d1b5d96eef9626430b7e785c2be959a590145b9a61bcb9fb5044f3b923908
-       c9cb7b952ad619267f7a7ba9420f6e3933d66c3a3bd4c4ae3229bc2b462db40a;
-  100000000000000000000000000000000000000000000000
-       c1eada4d6ace84fc75d62263d98c696e2df8207bd62981d48abd2523dde36862
-       db58cc33ea77f996d3d7688c7b6072a5e7d17ab605ecc15437b5bbd4dcdc5b99;
-  200000000000000000000000000000000000000000000000
-       8b76cf095a4d226114ce825b21d0548fe181ac262ce014fea4d3a4245abeacb4
-       17584d0428af390a9d0f8c51a493870f7feafea51c183ffd9594fc1e7f41d8a0;
-  400000000000000000000000000000000000000000000000
-       386b7fb85d0c186aed83e7c88ace5d6246ec46fcc3ba61b5e92da090a0754071
-       17d13a676e2a474b6ebfb05c4011cdbaeab55275c5f702b2c40c772a76b08339;
-  800000000000000000000000000000000000000000000000
-       874247921bb170b486c9e211aaf4f27133550367d8d759894b9e429ebe34908e
-       ff52d5217ebff26f8f5be14884fc05a9771997a062892f75700ec9d0f4d1173f;
-  000100000000000000000000000000000000000000000000
-       399895248799ad09b0e0a870717c7093e959e07b7ebe416cabdcfb57286a4f34
-       e3702614230bc36ef9b87cb99d79aa4cdd9e9d18d18ba4ca94f250ebdf04d890;
-  000200000000000000000000000000000000000000000000
-       392524e09fc57d2bfa227523fef0bad4155ea55f8a848464b7b7c005f6130579
-       9d595d7b010214a82e295f3440a682601764080288a2bef2fc208f9ed728110d;
-  000400000000000000000000000000000000000000000000
-       f49c44ceca01eb2d6ca71ae5b9363445261b39be75c75f0c054c1de37d95ed5a
-       b1de2734994d1d0d8b0ec0057ba4fbfcc1fb6ac30620c327c9161c18ea91e942;
-  000800000000000000000000000000000000000000000000
-       ff5b158392cdff642112789624b80d177aff782cc1a0ded6ef5a6da5230abbf2
-       a844ebaf2b4f0c005d5e0345f7b3268a401181cfca767970bbec2c65e739ee1d;
-  001000000000000000000000000000000000000000000000
-       eee541e6da8eb4d6ea2d0bfe3eaf5c29df99da4b258190ba5da5da8e8ca97819
-       04e41aaeaa28c8e1c7e113e3cc1734121fc73804d9aa9ca4ffe8ddc896eb723f;
-  002000000000000000000000000000000000000000000000
-       89f6a98d1287e78538d98345aeef5ea194a30bdd61d708010f3a3e8abe347774
-       1ccae829fff9e409ddac526fa4b4393fb9b91783d8ec6ff842321b830979e4ef;
-  004000000000000000000000000000000000000000000000
-       ceeebaa4ef1833984f356d6cbac91c98b032f8179a2f0ebb078b45d361059b6d
-       57c5a1d7c45a9cb0cb1ca9832f23d598cb253512372406d791539b5ba788936f;
-  008000000000000000000000000000000000000000000000
-       12455456daf8787770ef743ccda298d054122db7520cd1bcfb87d81da2b94aad
-       4a849587efe4291325f12ab50cefdf56cfea5e2137851021cabcd8e93230b3c1;
-  000001000000000000000000000000000000000000000000
-       07ebcbd8034e24f2af24d3722dc24e897756aafe2f6c7b22174b319dda5753a4
-       85d342b06d631f4975fc5ce6b7c6839cfe3a5d3837a132aa977a631719233573;
-  000002000000000000000000000000000000000000000000
-       e5c7b3af8f548c6684e5026f317cb0e3a27fe8c0550a5527cc9dac57ce767143
-       f215844a8622bac9330dcaa70e0fd34bf732a9556a6f653d798b48f23659a643;
-  000004000000000000000000000000000000000000000000
-       348bdff0e8f4b4490b2ae937b1ea6ae55a05301efd0342787184e8b8fe98f561
-       1f71659657bc15ce1c9e3d2a6e7a78fc0c8d337899b9268eb3bfe0b6326c2bc7;
-  000008000000000000000000000000000000000000000000
-       f72265f6266e5e3d810f5a65540206134d7e6f0b61335b646a5cea952986e5f0
-       1afa3d7fd71b74805878066b66cdbbe1151d64324ab82ffa6541a5e43622bb2b;
-  000010000000000000000000000000000000000000000000
-       71fb92a42e7522fc907b549b8e21be2f5e20f926eb1db7e551196c4c6f9fd49a
-       ed2e6b920912cb498db549b149bd50d7dee9c2065643968fdcf6144e79e60ca5;
-  000020000000000000000000000000000000000000000000
-       31d89b14ae2f205e80b1ea8bb265781350078058040cfd6cfa007e590a0d2975
-       8b57df307a928b8f04640d5602a31077f62538d711dedb4b0684a1f20d65ac57;
-  000040000000000000000000000000000000000000000000
-       ac0fc0e2bfff393b95228ec598d065969643d940bce158b882c4214dea7afece
-       34eecde2a39bb9c4714f1f071f152c0058d1eecd56cdbdda05e747b0bc6b807f;
-  000080000000000000000000000000000000000000000000
-       b8379d824ecdc66d335d64670d4fd20d3d1a2f632c845d9630688ddd5c64a661
-       9332b14faf54b15574702406ec02a7500defaa0de2a53ec1ad906ad8e6158e63;
-  000000010000000000000000000000000000000000000000
-       55adce8670eb35789c2b4f3c3f2a3c461b1a88131cb4bde0a54d3f4c886216fe
-       de33b8f153920f6f4a3fcea1b31618990d933db5a20828b143e5349e85384f0f;
-  000000020000000000000000000000000000000000000000
-       0e72d86ce21c254b393a2078c148cc6158d33ebc471e74ea9e7edf7bf936218c
-       7d19909092cff079bfa3854e6753967012a66277cb65771cec208e379c671f9c;
-  000000040000000000000000000000000000000000000000
-       6c5d6c93ef13bde1eb5f205ab7379e9764aa5cb4bce63fd68bddebf71ac6d750
-       64bc9c9bb728abb28fd2da7f958c16d120269d103e406aa17107a4d7f8d1b4ba;
-  000000080000000000000000000000000000000000000000
-       290a101970cb6dacbd175f3ca67860e10cc5ffa6e7829a40df0cc04345744de7
-       f0d4fb87d679b178dd0fb39d754e35638266ddd66f61d616419c867c52398c38;
-  000000100000000000000000000000000000000000000000
-       2c9c6a93c3c41f66cae82a912625b939203193e4cd0bc67dcc1ab882af0fb2a8
-       00307a8c0c9904b84973bd324a8397c4aa159176f0ba3cf4771f40a652151342;
-  000000200000000000000000000000000000000000000000
-       061dd076bec69c3870f387a1d74a5a506e0ae64912b850829113b9db9988e869
-       029977f0d27d81a985781061a05477fb032c7a5b6bea7365510be2ce8e3611fc;
-  000000400000000000000000000000000000000000000000
-       99e9d96e330e25d7d4d74a82232a6012c7b0332ac209985fa99a3eb4cdae4285
-       045480ead04b22fd287620db1e4b333d7d191fddca5539cd9ddb1b5ac51ba37d;
-  000000800000000000000000000000000000000000000000
-       1b3b4e1eb2ceaded0eb41e2d4ae3169df36d87db3fc7c6c5df7e06c27e68c60a
-       4b7087216d8396b8274fddc2fa2c300eac624313e62eb924e09eb6f608895aa4;
-  000000000100000000000000000000000000000000000000
-       ddbc04456d25f8af3cbd2fdf819256750c07fede724710b370b767ab6f3e777b
-       80e07a753961ac4a46dbc1f3c2ac510ee59a4e6c06672e67acdb2f9d393947ea;
-  000000000200000000000000000000000000000000000000
-       355e89d48b6ad74e2c253432722b3896ae7296c9e83e76f14e78b0f7e5fc8580
-       5d0307032aa30386ebf5f07b4a05175b4d3f460c95599b9de4a5098d645754bf;
-  000000000400000000000000000000000000000000000000
-       a692bb60016d3849f8e31b5c1956f809264aa39ee0096120e3c04466b4b72e0c
-       0183ff6d49c4bf650117e1ed085ab2b3d2d4614209db86689c98d9b859b3a5a6;
-  000000000800000000000000000000000000000000000000
-       a1f561c977e24c5da0b75ea3706804b868223245259dcb6350eef44ceda2c248
-       2a4d332bd753a98daa3e3d4cc3fce08319b0aee1b6a710af18f6604e6cacce51;
-  000000001000000000000000000000000000000000000000
-       d60a120d9cd41286c8a39d0a177c75304383017cf1fcc07cdaaf8a69290e7ea1
-       b1c53a187c59bb9490c50a8f10cc3ca1c6a5a3970a059d461318ba7a32b1e8da;
-  000000002000000000000000000000000000000000000000
-       57bf964c24d87f4e1bc0c301d912b61ce9244022f0b566ffb0c0f2e6acde4ffa
-       bfc70c61151cf16bfc039483b8a00f3906a2d151c44b9e684d0195e0794c2862;
-  000000004000000000000000000000000000000000000000
-       08af63069dc10fbf50e649321cd8b1ee039b7691fd6399d81e3565edf94b8193
-       54de4c85b5666702354f8ec087cbc0640faaf8e8d6c304ffbc21aa439943cd18;
-  000000008000000000000000000000000000000000000000
-       a77e3c5155aae9fe9baa0fb81cf9b2b60a70d9adf420844e9f8b01883706550a
-       403b00473e00a57ef3822d0bb6d75a99963974ffddacb9d4e5baa9ba47deaf2f;
-  000000000001000000000000000000000000000000000000
-       a667891d3c97262683fa83a7b781d6f6b987888dcfe9f6b58b4ea8bbfc22eb26
-       fca3b57ec70df2d5093ca93b2235be57883e1dc46f11a9eae73e047f1d2c5cfc;
-  000000000002000000000000000000000000000000000000
-       1af42c0f7468eb361d4f56f3e5f45f5daeb1c2a25666804d685f1584d5ba30e9
-       decc0c6bf3e04078c839acd2a62a4184aa1a1097a630a4e40012e9beaaf26a0d;
-  000000000004000000000000000000000000000000000000
-       c15c4ae428c067595c5fbcc12bae69ad529b7b114d30274a70a0a51e4f87a7aa
-       f02e1d8e8fe536918a9e62bf48195e8e45f8daad77718d78f223acbb8b8390d6;
-  000000000008000000000000000000000000000000000000
-       fe4a31645836d26c668ae9348047765294d707d38587c30e31493e3b9efbd239
-       021cfc4d6d24bff9ed344a57a62b9e9adc0fe0fb8b0d2a4723ef756126fe28c7;
-  000000000010000000000000000000000000000000000000
-       2bb1292e04c105a871dcf6a366745441995c46e94ade34d4f7ef353e3732fb12
-       8edc70cc753d1a7499063ca76a49c49ecac4797045b9acef9bf93b363e1baef4;
-  000000000020000000000000000000000000000000000000
-       af7539c5952da58d8074de796697cbde1a991e0216edaf51ea363734035fc41a
-       f39beaecd22482bd6e1851c739a1a8de9d11c3d9c11a4cdb45f3bc0010cbe5b3;
-  000000000040000000000000000000000000000000000000
-       bfaa17172e854602a411f39bfe808176a30726ab4139799c2ae294bfac9066df
-       edaaf454146e8d399df89babdb13498cf57ec6419d6faa51a8493fe3f55e968a;
-  000000000080000000000000000000000000000000000000
-       52280d21e201c397e77d527e62c85c23cc479fc81dfa10e19fb9d1ae84fe582a
-       c906c9878e2e36ed742c8ad5e39357e0188c0e5a59fa9d6c0cdc5831457deca9;
-  000000000000010000000000000000000000000000000000
-       ea223c68adf66b076da0eec9f38467139bfc51a4056650c25b1604fc7009b983
-       7ea0c34ab6f734dd80f82709f23a7ea3b3a426b2d2561d839eea4b33114d8e11;
-  000000000000020000000000000000000000000000000000
-       9fa09dba1210f7cff3b54575cff0e91706f96ddee75d625dd98b55058c04641b
-       707785567fd0c4d6982267bbedee319bb65be7e40cebef299b051edc5ee19674;
-  000000000000040000000000000000000000000000000000
-       0462dc1e6dbac8d94b9b3f6f36909ee367cd21fe348a37f8eb149ecf77459c15
-       6f7287e3838fd23a5de96afa60eeb3e3eac80346645cb729849cf06e4574f93f;
-  000000000000080000000000000000000000000000000000
-       5bb868af6de2f9814b2d53de8c4eb53597ef6bd7ad1a130b0f006b1e71b6f344
-       3e882386e07775def74428bfbeb380ddde3526cffa40ed4fcc0e98642dc9d29f;
-  000000000000100000000000000000000000000000000000
-       2e5ad6aa5701ad5cfb42c92f6e1142cc2e0dd24d57a28430d3c4aba7818a11a0
-       bf294d4623f8e6c683b29cbf1ebcf82338210199efdce2485f0c096b40bd3535;
-  000000000000200000000000000000000000000000000000
-       6ddac861bd903abb303e8d7faa58939f6949bbcaa60341c2b9e2f32254154e61
-       ce0f3955956a0e9b92d0611bb7d400bc782a61d688790a7293821accd4dd3ab8;
-  000000000000400000000000000000000000000000000000
-       6c34fb5023d0cbed7e5fe09bca96c261a22706ad118e4f8e813fdf578f6a9222
-       4d53255e814b9e35f5fada8f444266a11450e21fc8cdc11841071cbaa7392b17;
-  000000000000800000000000000000000000000000000000
-       1d9e348d053585d72af0d606e2a9792646fb591ec72c39e73895100c538e929f
-       6cbdde875e20309dcd32d18fe4c31c98274f10cc88811a14db03b002d1651bad;
-  000000000000000100000000000000000000000000000000
-       624c21fc425a9fa178eb5d8346050301d655bdf9e948fa79dd2b659122ae5864
-       fd411dad007bc21eb90442ffa404e205a4c6037dfec390ca055c2d1ba0d835fa;
-  000000000000000200000000000000000000000000000000
-       05a695c429b54c6ac459fec77cdf33a0e44d5d1f4dc6679fb4d1f3d07b35c984
-       ec983376a5c111ea502fb4accc49d7d465f1645b747192969ffdb7ddda5769fe;
-  000000000000000400000000000000000000000000000000
-       eb0221e48c3562cacc4c31e2dd24cfc04aff04addc4751d747033be31d7ff0b9
-       6d7d733c19b709ff780ea3d71e47faa447fae866c5bf76089abf4c09bf6e7f15;
-  000000000000000800000000000000000000000000000000
-       852be3267c18c0a005af19266019311e17ae0a266688398def4fe1a6d0f5ff8e
-       6ad20d62c5ca5be801698d6f43654c4e8b895a5bdd7bc1d7d9ea04d876f8bf54;
-  000000000000001000000000000000000000000000000000
-       2ad2d89c102216f17a52aee77b8e812d1d0102ab13c65fba559cab28682300fa
-       9b95e0998f7112dab5de7f64457634205d654ea4ec4a32076ba30cafb218f801;
-  000000000000002000000000000000000000000000000000
-       f61d03a67d0209e4986cd503c3a0d6d5314563e11a473d7fbd5fe4d913eccd05
-       a3c39a8321366853d78f1ffef9e2df9b09abe5a0d67fa0b0c0b02a653c23a8e1;
-  000000000000004000000000000000000000000000000000
-       8053b9bb606dd5f3e6fb5ba949485fb0be1bf2f3be881ef57d8ff653a7a2ad97
-       29c8a343460b0eded72a0f80b0b266899424195a8b3f5662abae0d58286c2517;
-  000000000000008000000000000000000000000000000000
-       a52ab95b69c30484126546b9151f9fea89b6d479391b097c9f636abe89b123b8
-       1f76b1e1d8e7eb427115a8e7fb239e461f67bacece83e576979623f86badd31f;
-  000000000000000001000000000000000000000000000000
-       a7ce6c6eac537320138e72f4ed71b57497132c19f58a3a0e864ccfee8f13e243
-       f31e719aa7b0aed4e324c1406fb38c7b574706555561fb57ed4fd59565b285a5;
-  000000000000000002000000000000000000000000000000
-       db419afa205c8ec1b824f9ab843f1bc377062337149291e559600148604b93cf
-       b54b0859085a9a0581286feaa0d2375f0e73ee1d306803f405021050406f6760;
-  000000000000000004000000000000000000000000000000
-       c97eb377cd16f86cd7efde7438d678933d5a76cb0cbf4938b00756b42d3986fa
-       5535c0c0f43ef9b8b78b532ba60fcdc5dec4428ad62fd36af221378e13b59cd2;
-  000000000000000008000000000000000000000000000000
-       9c379451bacebe09fe466301cbd2f15be7637a6d992b7e67ad25efa503e19da2
-       e8ed8e2367fda7b029bdcc7fea10bfff2fb9ee44017f63794fa45464e60e906d;
-  000000000000000010000000000000000000000000000000
-       d806c06a1f28c1a7a03d11529e298069f38713d0113255cd7260fe11dccd2459
-       0a6d37fc381c2cfdea6d2dcd4ee9873da18c46d028fead0861e3c0ed6d4afae4;
-  000000000000000020000000000000000000000000000000
-       3e26ea35664eb065ea94e6c8536af313c938b01a4ddb2145c907321084d1effd
-       3d7efc858d2c97fc00f2f0edf39d38e5ec673c99de7238f704b809140e3698a9;
-  000000000000000040000000000000000000000000000000
-       c21ed702582aa1d8259b2c892c6b4a0c55aee1382fb64d4c9ef218a8bd8fc0f2
-       b71a4d0e405d55d5001e92bc2cbdb822b65cf12501b8186943fd471568d82b42;
-  000000000000000080000000000000000000000000000000
-       0595bf54addfb813ce8cf9a40a072e1eac4022f848bf4a9955617e1fa4a64f0d
-       a888376775afac427e11eaf788eee2854e2c3dbb03a2116e3f082a24459e79e3;
-  000000000000000000010000000000000000000000000000
-       f7c300b01efb460b636c7af17379662cd501c7e6a0c7b86315127ba7a20f238d
-       ad9876d442b0e84db1eb82d3c3f98f768cb4243107d05ce90952f4afb89e3206;
-  000000000000000000020000000000000000000000000000
-       7922dbdb167fb4c155e062c0d5aa8b2868b893ca2cae86df02c776871b48a8ac
-       ae3720bf2f5b7a2fc753e87251e810e3c5d3e0960a4cf6c1985a2a0e7838ce03;
-  000000000000000000040000000000000000000000000000
-       8c8a5188f9ea500e7ba44d0c5c5296292b602bea998940826972ac75a55d19fd
-       75bacb58ec93ed5ce9c57a4830e0385998c3c92b6284601461e7ccfa234673b5;
-  000000000000000000080000000000000000000000000000
-       855b265da2e77cec64a7c96360221ad7c08bc343ffc173ace59cf2c1f94d7248
-       6967ef1cfebbc0ad1f54833c93232d5623abe3f2a34e0a24b9688783c3a9e5a1;
-  000000000000000000100000000000000000000000000000
-       81db501d3f871e765776d8d7750860c36ca39a73baea80df76168436e1dc282c
-       b12600493e0d643ad4c5bce38f4ff6170d582228eb9f4fab66eef8b1e6e60399;
-  000000000000000000200000000000000000000000000000
-       69fa38fc792f646a679f2c69f886f1e46d0d98ae7648b7ad51bd3d92ef09e2ab
-       2ca758e5230bb97262bf6ca5c4ddd5d3fc8f566561b297bc139cea05cecd517c;
-  000000000000000000400000000000000000000000000000
-       07fa8e571b3b715b7adb4a0c1a42a0f5617db1ab04a3ad9d6e3f99dc392643ed
-       fadeeb6d2032e571c2461e588e7efea5e38b2214ec23fe7b4a7b60c512e8a66a;
-  000000000000000000800000000000000000000000000000
-       d86ba78cf143fc53aa651f018248c67331e69be66a33b44b3dac4f3f86b293bd
-       e91b1044bd8bed5ae2cfb269d6fdbd229cc6c5a0cc560acddaff1fcc7dcc939b;
-  000000000000000000000100000000000000000000000000
-       4474e5926f15e979554b25ee62ca5895d69ba5f7b7264d52e936a5d7e218b7d1
-       da76d56dd52888a891d31d09a2698d6605e279d90ae2f55bdc01775dd816e433;
-  000000000000000000000200000000000000000000000000
-       5cf87fb984e1765a31e392dad79752549f6f9537aa800671cdbb0d89cb9ee6f7
-       309de2c3260c2a08340ce164b7cd17ff93d1939f3949fd5dbf46f75c5f13861e;
-  000000000000000000000400000000000000000000000000
-       fdef588c63309dab2aa804e9d897034fc81b6f1d168cb3f9976eb5a6dfdc52b8
-       83564b42d78039e88afc04e3f34b8863e7f94b4dfcc8c8c22e22f7dd17a9650b;
-  000000000000000000000800000000000000000000000000
-       dc29b2dc786b940f80371a1b1994e59cc5ea72348f1415dc9b9cb13af8acc81b
-       0656387e108812013b668a343044ed99e7239bc1c4e8e2698e8cb7998993b1da;
-  000000000000000000001000000000000000000000000000
-       309bd7d5cc9be260f1b43a255989368fa3a0fe7451c982fc7393b6bc6c784f60
-       b1327d75358cefb96216f21b4432b1b603ef504186470991c12e21f4d42c609a;
-  000000000000000000002000000000000000000000000000
-       2a4899c9dc7dfdccc936fb1308b9b43c8df1eb6537fdd1b5084b44c71905d71a
-       50b7d28d9599ec0558f1cdb5bd28b223585b7d7f4e3a11c2f63941d99baf82a9;
-  000000000000000000004000000000000000000000000000
-       8413c2819f780bb3a7d51aa0144d74dcc8f66f2db12a5e2dd739df4002355aff
-       8a15145629c86c5c699ce2a012ee46dff8d81d86f08c5d9b7580d30558adb269;
-  000000000000000000008000000000000000000000000000
-       ab65bb89011ff73cd9aab4fc39f31853f3214768a6a0fec7454551dfc1c67648
-       c92067f0ed0db296e72556344a39ee1e85f3690e568a47ec635b6a38935699f2;
-  000000000000000000000001000000000000000000000000
-       6ef6fcb11ce017ae7067d34547b1e996d045b193281ea44245a348708d896bd7
-       5d85c3700c5cc45a069469a7039f84334f7f068de6b5bb9c76c2af5345eba955;
-  000000000000000000000002000000000000000000000000
-       a748292aa251b84a1a518074dc24d42c9a491752d2c2c12511b2e6bab39c7157
-       03bf62836deb2ebffe32fcafe5db76b8a6e1ce3f411dcaa429fd14d0c86df3a1;
-  000000000000000000000004000000000000000000000000
-       44a8fdd43b3829bfa1290f00d3f796d1a4340d81221c0b1e0428bdc16960558a
-       96f6822810f9d3851b97c08616ff80f5f6810486347890cc682d551e34cc6655;
-  000000000000000000000008000000000000000000000000
-       44fd0991d1c3e30e50af350e41c0676b016478fd9ec4c9c66b5fbb6fd0c9eab7
-       921055ef1b383f9de45cda31c5ca372ba5ac67918305cc1817dadf8346380644;
-  000000000000000000000010000000000000000000000000
-       6535a47b9ff05940f35e68f6830b1edd6c1a3cca3c69008d77cfbc90813f2c70
-       7b3b359c5ea3575d730a4d6c206ae731f59cc538d7e7ea7065c16adad980eae1;
-  000000000000000000000020000000000000000000000000
-       9bf44b4910301b9f2e6ef3841a6bee5733b34459acff031c39b9ebca609a9ab7
-       dc57249ff0a59f590d2d1ab020e3beba7e95598c75bd0567055285e44de4fc5c;
-  000000000000000000000040000000000000000000000000
-       dae9a5b164e39be36b1acbbb357d414486098d20de2634d16cb9d04d0b5c5b9e
-       0a0877b39f37f8a142fda7618e6c4a06fe02921461264fb7f0a68de184d2af64;
-  000000000000000000000080000000000000000000000000
-       5e90bed387aab9681116b7f1e2fdbb47fffffcd40c35856c25ea58b452339129
-       318899c5f84a5ea7de2b391b4cd069ac2f341a820a3ab3241058d21018d5de59;
-  000000000000000000000000010000000000000000000000
-       e89f195b0e9bb3d7487aa791f436e5757e22ad78a5c525c367476383b88923b7
-       751b55b6122f2ca9459abeb94d4a65188ecb7a02ff43cfe10ad4adf68a9ddac1;
-  000000000000000000000000020000000000000000000000
-       0906b6674e6538ea82a33a89a47ffce4fbb489e6c2efdb5d1b99031fd4c5f99a
-       a75f0ccb1495e7cf617a8aa9ea4ede5a2665ffbda0c4e7328a86395485f0d852;
-  000000000000000000000000040000000000000000000000
-       9f58ae0629353e100d7e769c61b53516bb2a0c6b843c3d54dcb8049cc98d1446
-       0298031326cbecc865a64b254af3c187f97c7fc1370c48a67fe137985eba00ad;
-  000000000000000000000000080000000000000000000000
-       6e65f3a436d028afa3cf36e14fbb09484c6d60c656d405530da442fc3a95827e
-       4d44aa7d331fddc2b173191d70836ac2062093823e88f42418b1b2b624be7d2f;
-  000000000000000000000000100000000000000000000000
-       0d84cffdcf30d929475439e5ac19e65414b1a987c17d39ac5fdcd1f88fdbea61
-       bb2c7066132af737383955b50aafc2629f62ae9a0906cf063af6950c7d93edb8;
-  000000000000000000000000200000000000000000000000
-       aa89078f9b49ba132929b8cdc17f0c72f03485a3f30145eae08a37b8077b1e7a
-       bf3d4ea78a22782aa1978b42b88fc58ab4594bce39dad5b564c9603d9f18bcc5;
-  000000000000000000000000400000000000000000000000
-       d54d3dfdffaeab5ece06009b61de0b631d2503251e08f5d946439dc3e23c93c5
-       eb4e97cd5fb0ade077a1e463b46642785d5df66693ca3cafe4073148d4ecd8d6;
-  000000000000000000000000800000000000000000000000
-       2546c7077b11fda1d13fc0a58757bf47408f4fa6801c6240a31b0821d7294bbd
-       7d6f42de54cd407eed7ffd603a9cf2e2e03d5bfa3f7a2a1adff261292f5e30a0;
-  000000000000000000000000000100000000000000000000
-       2f8eb8d9a3f973e0657700dd113b1fe4a124979e54206ee368c04b5507539ae2
-       65398aa3cc2250c82a47a3812637c270959613211682d1d14fe9f70524e72df1;
-  000000000000000000000000000200000000000000000000
-       cd7604e207e7e65de5458e56b470deb55562d2fd0f7de38468badb7d30c1107e
-       04e11299732ac33fbfafd8b73ea585ad11202a865c4d633c25e690580b527654;
-  000000000000000000000000000400000000000000000000
-       d0f99bf98c30dcfaac9a4f14693febd6e44eed176f86d7a9b7d0ff38f7ef9b10
-       eb250f8278f8602594b53456dab86a4714943910985144ad7e1044877949c9a1;
-  000000000000000000000000000800000000000000000000
-       20078dcf344356d93c8874fb3ba99fa55446d9082e96981d6e4b0bf25241dfcf
-       1ef8439de2abc9ee2a524e76eb98773c851de2272e9ff82872de69120dba2e3f;
-  000000000000000000000000001000000000000000000000
-       6ecbc7d196fd0ec594426f8ef67f04e3fb0b187616403c3d770f07ef83e839f6
-       74f801a04bdfc3aa70c62c8111989822e36dd3954a18c03817b4958900ea6fc8;
-  000000000000000000000000002000000000000000000000
-       bb295bdde6c445e83709b56a027ac1491e3da32d1e27a2d40d4c604e534cf5bb
-       091799a866abd7ebf18e6ac9421d394b1247deaf31e8a65ea3ea5156b78ffd67;
-  000000000000000000000000004000000000000000000000
-       34d2916c9570990e5a2ce1f8fd3f4d92fd55227835ae79729494c2a56f3181ad
-       bd9dc29b42443bdf687aad6aeb0de8dcac403e13f40dfab97d289f5d8905d68a;
-  000000000000000000000000008000000000000000000000
-       6e8e0e6a1bcab3b9c4914c1b7dbad41180fd39f4077920381e6e5d43ae29056b
-       d331837650a86a752e106d56056d34f6c60daee1f2ca2f5d32fa3d4c4b11f590;
-  000000000000000000000000000001000000000000000000
-       d15117718cda91b580c8ee37b7e92a92aafb1bacef081c8dc4efe8d9035cc3cc
-       dc40f2cba1490588030c77a2deba609aefda9dbb2de7caa20a27dc78b0d6a35d;
-  000000000000000000000000000002000000000000000000
-       85e78f287d6dc01f23c5a7e0f3a79f7cec29705c18210ae5da37a5e787c7b900
-       4b0f88ed23950fcd28af65ed71b102b108dddf354464430823ac654c89f8146e;
-  000000000000000000000000000004000000000000000000
-       674696bdfb8b749f045e4901d5327e907608abc8a441acc85298c4ec38207d7f
-       cc25d43dc704c71f4e18d3bc796c5d12db5771d929aac483f51b11923ad032bb;
-  000000000000000000000000000008000000000000000000
-       f59b32955794603eec1664d94b565126b08f689979381d4d7371a1f02d5939bc
-       f6a18c580d6b019f0ccf24d0585b612a9d0194292880c2bcd329b16d32d32eaf;
-  000000000000000000000000000010000000000000000000
-       8331de42dd7f34562c261a24c4206206fd2f7c82077daaf793a8c13cb7736658
-       64d0688016e1fbaa84efa02d12f38becf1cc3b49af8095c645e006245d04e7a3;
-  000000000000000000000000000020000000000000000000
-       33f329a6f1febd546b8dfe981052f456f1cf068257d61e4215d0270b731cf416
-       8a1bbc62bdff88601e65eacb63f3b81188df1715dc75e46e80e8d4bad7d080be;
-  000000000000000000000000000040000000000000000000
-       e13972f07f517f8e11951b51107feb546906c2c9c9fedded414c099e65ac612b
-       e0cd462d9c2676ccb8f3395ee3793469dbd0ee8bfe9b70ecc64c1a3a7cbc1afb;
-  000000000000000000000000000080000000000000000000
-       30dc82438a0c01fe8916bd3d50ba378ba74c7902fe123850134bd254de36010f
-       b49612b958bd2f20a3662304ca13b856c325fad90020638ed5824963a8e047fc;
-  000000000000000000000000000000010000000000000000
-       8bfc581db5e81ad346b934c1567c30409d0f7260895d7ff5900791730d3a780a
-       fe79bea87199dda2ed990add427118e574a293bcfb9a7cb74dac47ceeca73c19;
-  000000000000000000000000000000020000000000000000
-       074c4229882668f1d1b2fc749d8a839f23d247e01efd86bc569422904fe86499
-       420687e93a67c0b5c4e4c4f39f596f314ac56a18f1fdf78a671b50465d200f89;
-  000000000000000000000000000000040000000000000000
-       c60780f4ac3b1507ce3d9e899af33930a44aea6cfa09ea11df9894f06d54286b
-       9fda5c99d571f89a8b5a38f4fac48c5c21ddc91fedc481a951a8d1fa6956bdb8;
-  000000000000000000000000000000080000000000000000
-       fc3f7afe9eab56e59f7ac6aac5255e74dcac9a467887fb1e047531aa6b7c946d
-       200436b4ccbab5f0cf2d8f6987364e88c650e5c432372a30d9aa9bb6e1c2665d;
-  000000000000000000000000000000100000000000000000
-       bd0f3ea9e305732b6f99f6d27d4e29cfedf59b3e6b24052ce0fac6b055ec9eec
-       57ac440ffebd1a3babc1b39aa1c19bcc9086f3a841190949d3fd70387a69435d;
-  000000000000000000000000000000200000000000000000
-       b06265193cdafe2055c504f94068ba76858ce5e8c1723ce078821158c653051b
-       7457c97d616c01e642a7608045444fa985ce002df0a8b87033a31fa4110c742d;
-  000000000000000000000000000000400000000000000000
-       5478345da67f4dd32024104c5c0eb13cf4165f29ad5f0c946e35eb44a6a4e97e
-       0e56f1fb7c9245ac5fcd148ec00511ed693a82a2390deabfcf2f7525a4bcc0e4;
-  000000000000000000000000000000800000000000000000
-       9f583a1aaab317311422672cb6a29c036551d7653bc11274a53c50aa28958310
-       e381e3727134a1ab4dbb3944447d869cfcb9cd8baf5472f1ea55d0c3911b2aab;
-  000000000000000000000000000000000100000000000000
-       ef31cb4447629b94a8c2bf6c2479e8d0fca2a9c3bed40506bdd009b859c1a234
-       2be2a20df00a0b9473601282902595bd30960b6eebff3eccd2772047e91bbbfa;
-  000000000000000000000000000000000200000000000000
-       822f1e0b80d284ab77242e6ea6a31c7b9478fbeccd019640bd790721b94fc602
-       f81e837b98de88119be6906594a26b93342990a9e432808df9bc3ff8f794fbc7;
-  000000000000000000000000000000000400000000000000
-       1b048b3da8ac57c867d65c7054771b0e0f0160b7a389b9cd0c2a4c2230ecee02
-       14d4fe78bb906ab8a1174bcb83b11dc828e284f7799be720784d2c8c8c9b60e4;
-  000000000000000000000000000000000800000000000000
-       6d572bb0230a9c543f278d4e44d25f07a3e337fb6bfb62443cbf9f63d54d3d23
-       ec8fbf1c617dfce2e2888692f4233252500f6370f9ba9aba9976346f0b45db5d;
-  000000000000000000000000000000001000000000000000
-       8f0737b4a2c72a5401388a64943d931cca5100f896ffaacab6bc6857163cb364
-       4961e5c5d4983ffcefa36d2d31f013b55d339192be61f2d7d525c9514851b9a6;
-  000000000000000000000000000000002000000000000000
-       865fc49a982f200c0ce91ca8389997385cea07d2054e215624ba915da86ab56e
-       9f9f408687229eebcf6d6b11a2b0e0983f8166fa538fdabbf24b5faf7a5729f0;
-  000000000000000000000000000000004000000000000000
-       a265014d381bf64416498ec6cd0d8280fcccff8ad00a8af1b87ffb279a5f44db
-       0f96100cad1c7d79f2c7d266c2676a1aa04e507613cdfc88a9a5b032749a6849;
-  000000000000000000000000000000008000000000000000
-       69c3ce6588db62df37606f44388b5d743e9589338f479a42b1994a8649b35353
-       03e557b5d65d9ce0ed50e2e77365e6dac2c5534dd29ea0ff6d6f3191ecdf3ff3;
-  000000000000000000000000000000000001000000000000
-       3abdda974690d01044e1283d277823fa099234b137298cd9edf814c7df994f1d
-       0624991cab7a0f9eaf650bfe2329966038ccff5599c66af5fbf77ab2a7028ee9;
-  000000000000000000000000000000000002000000000000
-       ae97a705ea10bf85929124addd1d620aadd98c35157e1ec67827243a013a1a55
-       1f33262e18666311dc61128867b31a015996924ea43a468fac7f06421b117a79;
-  000000000000000000000000000000000004000000000000
-       1b11cc975752a04198e012614cc5a52c7570af58acd7a52cd479ff25f422a84d
-       036163f34610434f92b23d88b6b9abab66dbcdcb1b3681ab63f8126ff5f3ceca;
-  000000000000000000000000000000000008000000000000
-       726d34090d8de7bd8892b9e20cdd176e425b49147ff02714e13e3ba4c0176094
-       cd95775f2b5274867a6485b92d8fb68c43e5b18dae52cf2a9aecdf82fa2756e5;
-  000000000000000000000000000000000010000000000000
-       438b7eb9e29d625f827dbea30ee486dea4b8fba4432b35b3f1f598a49d1e3efb
-       f27446705c795d27c75f4e152c40979f838a577485e87154ad49e141f3906bad;
-  000000000000000000000000000000000020000000000000
-       b3e751e53ca877bb58140b3830ed6ca88828ee8eedc414e46f4530368559724e
-       1ef875af1f5a2bb7b3705060dca18a0bbd2944e9510d1cec7d5dca01fd030abc;
-  000000000000000000000000000000000040000000000000
-       0d85bc30d372bc51fec89036f8dc2a9a0c44dc732a35dc986c3308aa732dbfc6
-       41e311175cf4715f3a63de6e9d09a8f1e1ed35c7dff4ce55452dff184c67ccfb;
-  000000000000000000000000000000000080000000000000
-       2911634025868ff4d90af8f03797e04facdc14c995031b8c1d399a8fb54f7945
-       a23be5413808deebd664fb8bf8a44616086bd9fcd7012a6b019a288f179a61e0;
-  000000000000000000000000000000000000010000000000
-       dd1c1f9aa7639f84405b4ee50a0af7c1da71bc4ca4d7a84037390039073926c1
-       1cecf7f9da8b89b1793380b3ec02a069dbf91804af70248783c6eac500e72b54;
-  000000000000000000000000000000000000020000000000
-       357fb20348241fab58252324b651366750f5fa3cda129beb249fd55c520ee8fa
-       7943f92bda9aa429f4c67f6c60fb64f467eac75cf674f24c7e7d2b96afe230ae;
-  000000000000000000000000000000000000040000000000
-       08933e7505bc9dafaa5cd4742c4321dfeed5eab0db0e8a06922f66e9b2f1d449
-       80060d8f8c9c4e78eb37a9a0ab618a212a18b809b653ba6fba4f9223a895fd55;
-  000000000000000000000000000000000000080000000000
-       1a75b005be0c2e4d5ecfd57407a92c1261cb94edc3fdb86201e4122d10f178b4
-       68507c27736ef6d31e5c4abfad5e6494659724880f0e14f7cd92e4f81780216e;
-  000000000000000000000000000000000000100000000000
-       4168cb291d201eff8f05e4266aa8a1f458cb66e3b01ce233ffb41f8aa6e9a12b
-       db84289b819e513d5116ca4aeb480616a03d7804b41e4125b03de8cb3852d6d0;
-  000000000000000000000000000000000000200000000000
-       44a8f5928c2dc60ce18587c8f558258d0a5718773644b028fdc86d3aea135a4e
-       0fa47daf31ccc8ec352c84e860b704b52dea2f15969bd08ed94063edaa5eb891;
-  000000000000000000000000000000000000400000000000
-       be7aa43951c4bee8cb3d2fd3a4869f498bf59994128cc3fa0abe0c9a317ca562
-       8c8f3694ff0333cae80183e03542e563a3bc3c25dd36c016300987445b1c0385;
-  000000000000000000000000000000000000800000000000
-       279595b2e3d27000ad59360b237948d578dbfe442129ce09c963ea2467883447
-       5b0366c4833db132340334597fa4ae42c9591952639e86c7a5c5aaa67eeff61f;
-  000000000000000000000000000000000000000100000000
-       3d0e6083f6dd8af24aa64f4f95c02de180ff34db8a5967bf47a38f048ba1907f
-       e16eb2abd16c38a5a13461b1992bf3622545c338c06bddff3c31ff4f11bfd7f0;
-  000000000000000000000000000000000000000200000000
-       7184ce9462840f4f061fd8ab9053c7074a6a3fcaaf1bb7c660cf0237770f16cf
-       19919262f08dab0f920541fdeb8f12b7a01e2f4350c9e42bf08819fa3d7cdbed;
-  000000000000000000000000000000000000000400000000
-       7e6d7e42393e2e8cf0dd13f0f8c175796c07312be0d038162018f9f059192bb6
-       222f78b280402f19ad7ef8fff7bb9baa080925eac811f9d07a0e2625b8d0d3f9;
-  000000000000000000000000000000000000000800000000
-       ea6608f32a44501ad7d272ae5d4a02ba172c0da0d2ebbe99e6acc74d782b0a25
-       d9b0c977617742962071dd97d359a589f323442201ed8c049ddd19986d6a7e59;
-  000000000000000000000000000000000000001000000000
-       ac34522fa1a172f61671921a073eebcccffea629c88c3efb024def587e85815c
-       5cbaed86ba8d85fe7a1b7598344b467fc75c425bca2e057e4d29583c1339e2df;
-  000000000000000000000000000000000000002000000000
-       8ef6979bc1593327ddf83f3582ca3089bd28441d603a68438b6b8963d5d5be7a
-       2f35459f0fe78ed10cc345dbe5bda63ca032064173ea2222d8a44183efad70a1;
-  000000000000000000000000000000000000004000000000
-       e7137bbea6d5f12f35607bc208a48f9af232ba192552783ec1f1cb2ed9390abe
-       400a562793f9a5340981d297af0bf0cef8ddd966b4245192676aceb0b830cd29;
-  000000000000000000000000000000000000008000000000
-       0c10c073d596ebf8e92b9df89659d7e395c9755f0bde20386da97e61e28edcd4
-       1c16a91cabc951a2cad46336e8b8d63e442bde79569c953ca9040638fe7a6854;
-  000000000000000000000000000000000000000001000000
-       f2c778bed0cab8b49b63bbd4cd2e4b3839737629c76af97e41256fb5a51fb135
-       c459e872e3d85d83bd6c02678ce707d4b55cf8baaa990a1bce85297089777032;
-  000000000000000000000000000000000000000002000000
-       48ea086a4b426c28b7a789f863d6078fa557c8075f151bb376c19b0333c7617f
-       3619d9a633fd99cd676764ebf0bde6392726c71c09edf1cdf6a83082043c8837;
-  000000000000000000000000000000000000000004000000
-       88887c189b997032785c0211647d16f01dee57453dd8ae457904181346e3387c
-       a01ea4e80af98fd522c73f363fe1f67ca74b2f550cca01e1a831a371818f0a67;
-  000000000000000000000000000000000000000008000000
-       d1cc08438475d0a365e113a4f6cd2b3f8dd0fd16f11a7a91a24d7d57bc299a76
-       5211117b058e16a42041313422e59b867c25234913f19ce0d3e8ba2c83a1b604;
-  000000000000000000000000000000000000000010000000
-       a08d0c7258596d8ac11e99955d27dc5e58c1a94f3122821cb62bb7750f8c86a2
-       828f22a04c97d1608bff3c343450975b321b1f1078f4b8bb8e392bfc3d6ada6b;
-  000000000000000000000000000000000000000020000000
-       cfa3d2646ed862a2f5e1a0012446f25b320368f817a9f6aa34679e8256b31713
-       18ed4648e98ef43131ea244158d550f391d10aff20a786b49a7206e0cb810a17;
-  000000000000000000000000000000000000000040000000
-       9f3a7d42e935c1f2e486976714115dad69a44ab16a251d2ee8d59f09f752d43e
-       9d28bedbe24fdb9b7d428a5bf6f290a0d3fcd4c5d3083e8dad1deed29278352b;
-  000000000000000000000000000000000000000080000000
-       5c99b3f3fe50e3d2337417eda4801ebac775bb7505ca0dc7d42bae82ae9ab9af
-       8f3d15786baead2a7a7a821f651b2cdb354da45133f8f41886362285e8ae0303;
-  000000000000000000000000000000000000000000010000
-       465980c12032bfaff4119e7a258e0d9c9d10ebdd694c594eceb203e3b44ce3ae
-       9a2ba16d5bbaef21e0c7c28cfbab685e91840ed1c6c7e2d9afc52110f000543a;
-  000000000000000000000000000000000000000000020000
-       72a31c0f8e054b278ebd35af35661bb0bb23890d62bc4ff567883e8d6df3a64b
-       d5a094453f00fbd672acc45fc68ca31e00260b6fb0bad3e6c1adf2a6cb873a5a;
-  000000000000000000000000000000000000000000040000
-       51ee7d952e9d6ab691ae0af0cd24daa737043475b208ff66adb3fa5c09f3647f
-       36a7317d1f7e27f7cbe2745adfdc49ddbff3e6406da0f0bf79b5b64877ee94fa;
-  000000000000000000000000000000000000000000080000
-       03d5fefc307c92f49299cb1561e8925e4b333530d1d39e6576d999d6b18e9566
-       c80301e64d2a3c192dba0fa08c12a1ce1410185174b5e97f1b7e124418566dc4;
-  000000000000000000000000000000000000000000100000
-       02b1c0b7e3d4c64bedd8ca69dbca551dbb34c54007c70dfeecc64f40ec689040
-       7d9f113f627086a13dbae2a8d59a60f0d9c59693dc38db1262a6cf63ce1e161f;
-  000000000000000000000000000000000000000000200000
-       31aec9854efd20aa692d58e5f35f9715aa6744763e80a2b84c52e7746024e4f0
-       e298bc6d65a88ef0dda69e3cdf8f39ec836881da986c94aa8e55ebeee896f376;
-  000000000000000000000000000000000000000000400000
-       b6b7b784d08b13e5e9bc1de7c580a2a84bf0ce0863ace791eaaa5c448e419b12
-       a7f496e466a7d3a93f52a704b165bf1798f159d1fad3e3d33cda5551e6e81b33;
-  000000000000000000000000000000000000000000800000
-       7edbb0b8915926a8a2e8fee143b729415135b88414a2009f0d5d1c0683973534
-       21b1c8e53b342159b8bf091b43534ee08f4584ab504dbcdab6ef108edd7addf7;
-  000000000000000000000000000000000000000000000100
-       66b011b48e7c4d63065e119be7d76dc2fe5f4832892e521b3919a567f28d78cd
-       883378f113fb173d55e21afac17b6bcc13c5b825b7b39c4587e36a7bf56d33f5;
-  000000000000000000000000000000000000000000000200
-       36b722f7c39d54cb3b5fd4a891b3895d6da18a6206cd9228b5f890a04a732d2b
-       5ae23efac307c817a93408eaab3c71fb182b8c339c6ecd86a04dac2ea551974c;
-  000000000000000000000000000000000000000000000400
-       8c62713ee186f9c9b85d3b39433a8fc48005e4b772243e2c59a0b6c9c5f8d945
-       fd48ec5913d2c5a24898454ee7d127a2b3faafeaa51f1eb6bfddfdd89f29f55a;
-  000000000000000000000000000000000000000000000800
-       6cb6e49700ea40fc2250f75122c7658603d210b28fd5a7d330e7eb7270571b92
-       faa3c13c45e6a6058fc008d29710e17df435ca6fe03c802390e66a1f5d35f448;
-  000000000000000000000000000000000000000000001000
-       e209f79562f3acae829c8ac46326527581961f6a9c50efaacf05cfc299770d3d
-       47fa35bd28db056ad2c960ffbf195b6726b8ba70d0e1036deb00191e1007bc73;
-  000000000000000000000000000000000000000000002000
-       039ac5fc8be0833d2b344b501949b94965ee8ca968d41f799bdf4788c69dc9ff
-       ea9f5b28839e0ce7da245f22957bfaa6f23aa9e91797f94ba41c563ff207eb24;
-  000000000000000000000000000000000000000000004000
-       f8b3de78e36105f66bfb9030186225b551c54719d03a327e477a15cdae4c442a
-       558f352e51df92eaf816878a8117507571e77ed0af9196f621172ab63c57e96b;
-  000000000000000000000000000000000000000000008000
-       a95ec4094654e78134ebfcd6d99696b59ad8922953c88d4676e690235a07bec0
-       0904f4197e14bf542f25be01e01f2902e389f872389040754b4150ce17e8a8b3;
-  000000000000000000000000000000000000000000000001
-       e4e55a685ce73b8e8c38484cc3a095ec77d79d4213bd7e8509e634cd22794e76
-       e52aea0a67ffce6c423f49f19799b5cc144430a97a4a11cb81a15325ba58182b;
-  000000000000000000000000000000000000000000000002
-       e82db75f9ac6e522e32c0bb59d526efb83041531ca7f8c10b50206fa1f5c0f95
-       afff3847b075d3ba60d574c58dd38734e585c6835e7080ee22dd11fbaad76187;
-  000000000000000000000000000000000000000000000004
-       11c10caddec7e7df6e2b3cead72466db28943603073b181c54586cd97668913d
-       4892b31c3728824d569af42be89c87986ec1d7e3ba680d77269b6d66a8674a87;
-  000000000000000000000000000000000000000000000008
-       8b10fe1f2dd03e24b962a91d341424db2fb31a98e99cc36ece76fce644e7626f
-       42f3a523c2108ffcc693ac50991144dee446980819ca6748337b75212f426d7f;
-  000000000000000000000000000000000000000000000010
-       268ca8eee4d8bbecea331da0299a3c7722ecc81f6d9e0f360365ae115be736e4
-       b39d8ee9b20baf88f8073d5c50091a4ac02e050680ec0483f13896fbd08ee022;
-  000000000000000000000000000000000000000000000020
-       dcb7c3ee50078883fc516b99f8ddda0cacd6df989d7408b90ba4b79ca9aeee25
-       a306a8182bf7d39636b924b1398bfd4a3eb54ca10a2a92deb6394ae6ae5635d2;
-  000000000000000000000000000000000000000000000040
-       3e8bbb3bdd23331becabe027092f9600030a29cf101d49a0645fb19839aba819
-       3d0ef0e093c0df6b7a6efaa547dbf7f96c77a195e7f32791c02e8d6d84bbd999;
-  000000000000000000000000000000000000000000000080
-       3001310564521f5f6cc2ff5138270e2b01c98f1e0e0df104f218a7bbd4c528cb
-       ca56375249968d85431fda8a0f5a94a676f725730eb2387673e8e2196530d40a;
-  01000000000000000000000000000000000000000000000000000000
-       2464195fdfbc0fc81a28fb4f56453d5bcc3641a478bb8e217a12e81d209a0d69
-       764217beaa547cdc74d61dddb77759fa4a46818fd71b77ef19a66ec61bad44ec;
-  02000000000000000000000000000000000000000000000000000000
-       e093cbcd15d9d26d2299aa256ac0ffa9479e82a7e6921c22330459282c643640
-       2d6e17704b89f170344a816657e838141938dfcb7710fbd748230abd423a8327;
-  04000000000000000000000000000000000000000000000000000000
-       bfc89ff49188394972ac2fcc77e4275e8b7e190ad88ec18dd46cde1e8d08fb3a
-       240721b9d03626e7222eb91b29b1b56effaa86b815c8041ab46f92fd86ef6fa3;
-  08000000000000000000000000000000000000000000000000000000
-       4f8fae102a0f00b1ea06377d3d331df3b492d4038a01467998878f9ca6101860
-       2b928f67b786b6977666abcc44bec615d27ac4ee3f6e3e0620a32174b0428d08;
-  10000000000000000000000000000000000000000000000000000000
-       1580bccabd91d69db6608f185b39e46bb8c2822fdb63f55fcfbfda08897217d1
-       db3cffd2dd7293de5ac9b47dc91e8c8c12a4890e67a5ff9399821dc7282e3125;
-  20000000000000000000000000000000000000000000000000000000
-       6b99c58f03c9ade53b87383363db9b60a1cc3ef8b81b13c146b2f3356becde35
-       f77668010fc0f6ab4438ba294b19a62756316746da733e22eb9432e4b8d92665;
-  40000000000000000000000000000000000000000000000000000000
-       e711df4d46fa41caaaa9ef1db1abe8fa9d73fcfc2c8f7bc0bcaf238d88acf2f0
-       f923b9ffc408776d2e79903cf46bd57b4243142de89554a6c42c535469f4afb5;
-  80000000000000000000000000000000000000000000000000000000
-       6a3a9121b368c3513dd88522b3a9d1fecc6403f30eb1dfafabdb2467db85c4b0
-       ffc4cc0d9b92617db41d1d9e1f71ea3962f57624f85c06cc774e0789bad7d70e;
-  00010000000000000000000000000000000000000000000000000000
-       4cb64c389bcf6ff3c15f28ccf61486e2aace7c54492d2e52f91672fc1ef68c38
-       c12c3d78af5ed1c2a1b8f03127a2b183ad5876c181ddaf0b55b7d275b1270406;
-  00020000000000000000000000000000000000000000000000000000
-       39e2ac45e699af272119c0f264488b382a93468433ffb73066e1b052f0b95114
-       e4859a08895657b444b0a92cd027ad01b2045cafc91d5a58a70d4881df7f749d;
-  00040000000000000000000000000000000000000000000000000000
-       be12959b811b7990538165d11ad379332c729f72666c2d177bff7c6585c4fdcc
-       2da68a259c2a68a877d5387f01faa64ab6a537e11e2e4620b4edc957dadfc1c0;
-  00080000000000000000000000000000000000000000000000000000
-       bd27f6928a39f0404957f340701b23f529af3a4ddcaf3176f7e5b78f31027cef
-       9df676b4ad16eef5fc3d9074ef1fd0286dbb7714679449b8059a86187013cfd7;
-  00100000000000000000000000000000000000000000000000000000
-       0f6c337b825811e0f4afc216133a38726cfb6d6de0da7bb8f33961a2c21be234
-       14b48beec8faeccb9500285799ef73532853b8c7cf630d64ad934884eff923d5;
-  00200000000000000000000000000000000000000000000000000000
-       96b9131980599233f75d381de365ee5d71706e880840e6f97365628a1929fd32
-       651b53f4d5f76fc3eead20ef4f8bdfce994a9f4411d9ed9d9a82e2d39966295b;
-  00400000000000000000000000000000000000000000000000000000
-       90131368532a05827eaf2ae0c7f7486def928c0cc3c97364fb3a33ecdce76a41
-       1070e529c583863ea11745c08ad3511e25f00fb1f6566e9a65d15c4c5b9db9f0;
-  00800000000000000000000000000000000000000000000000000000
-       9e194d490e2e1a13f067736c1b4c02babbaff92656b39f2cbfbf79bcef509d32
-       d68bf125bc9d18f357263378f1418d0407554c006bea0d57fce3284ebb23e996;
-  00000100000000000000000000000000000000000000000000000000
-       9edaf8d2affd9975fc6edc4d7551d745f3ef5c1c2e9b6e866ecac4370718f00d
-       11538a9cfde310ee1af5b1bdb89fdf7235b65f06804c1717b50a3a7bada18be9;
-  00000200000000000000000000000000000000000000000000000000
-       699a6253b34d53c925a3ca885546ff6f075ec5f8f2512556f5c9939dbc66521d
-       94fae63abb388be332f694d27344004f9cff783d7e0efcaccf6869622f1a7a21;
-  00000400000000000000000000000000000000000000000000000000
-       c8fa8a591d52dfbdd4de31dc5e7e2e34c1116f9136872d482adacf6c4ae5ea4b
-       d5a6965f1bb3023d6fd54c871732bec898a322a815adc5ef4ee92fbba3292ca4;
-  00000800000000000000000000000000000000000000000000000000
-       755e57fa2b60ea3d49217a983e01ecd990b9f801b4bd418ed9218b0e0ab6aedc
-       4dd53d0bce528d27e721a7e57dc1cc996de9fe7a1a9b68bb166e4ca3883273d8;
-  00001000000000000000000000000000000000000000000000000000
-       d7fcd3441c6e19f5fe50a13e8df8efeb313ea4c3d5c98a4d0218a15d2fba0501
-       03b82200d043d05cd925deb405da6fe465da86a542a99138286dd3c15180b11e;
-  00002000000000000000000000000000000000000000000000000000
-       5c2aa4b1da995bdb48012fb3597f0c293ad32d35ef0b1d18818389bf293c06f4
-       5cb31ce813dabc594db8769257f0f8d6f56228968032ec3faa6089959fd312b9;
-  00004000000000000000000000000000000000000000000000000000
-       b492eb88b267d7e8d5b2c4f627e0134f0948dc958c3f9c3b9d53cef81d395fe9
-       c17fe250e789278e9f00eb8c4031415a534797685eb90b531e6034b72bf11a45;
-  00008000000000000000000000000000000000000000000000000000
-       b37285ea7dbf2e60444ff339c6675efcc427f8fa6d0dbd4ec23f0936b60a1f36
-       a18f8cec0b0886c08e43b9ebac17c592b95e87e8eda9dbedd9d05982f8769e0b;
-  00000001000000000000000000000000000000000000000000000000
-       5cc14e4f6ef530df34196f17746dd9b10e10890beac586e16603b0a28754538d
-       8397bdd286cc5961b1414830586eb2114cbbe9f626ac355da9596861320277c7;
-  00000002000000000000000000000000000000000000000000000000
-       18c5f953553658bfe311783c54e1d3b988b7e13e5b1a05ff7b725a1b3fb97815
-       14f9a5aa033cfc16b02ef4d7749e136521607a74e1d874d18b257ea98078376c;
-  00000004000000000000000000000000000000000000000000000000
-       986ed4e41b1925be50769c2b9f3bf9c42060e69f4825b0b27eab36628f43e727
-       0ba3f96bba6070ab9f18a6a8a3bd38db4174456c0eacc8c52ec067d8f0baf138;
-  00000008000000000000000000000000000000000000000000000000
-       29dc264f8b38836ca14e4635397a48a18a489adce20717d417c004cf39c9444f
-       971c02c844cc79d7464f0b7ae3ebeb6ba461d1c257ae052127d6c35dacc7931f;
-  00000010000000000000000000000000000000000000000000000000
-       23c02c0924ece0eca2b9a113953f86926c7db6973ef792b7ad30ac5146bc8c1e
-       d5b1e384a939c12b9eea540dd46dcadf861831a2eebce73b0ae8de42bd83504a;
-  00000020000000000000000000000000000000000000000000000000
-       a8001a31579cd64e94ebd9e4a18818749bb0f0fc01ebeb456b8c0e065142c220
-       f124e79fcf5f18fe452ee9e6593b1b2b3ecd0f68a8faecdc09c04ff179b9b01a;
-  00000040000000000000000000000000000000000000000000000000
-       1f01e394b147f07da857c34896d8dee3f7888042e609ab70df48268ca31dcc5a
-       04d77d393666c558f69724357158eb7bfbbb05a8a38c5f5b48e082d2ddf39ff6;
-  00000080000000000000000000000000000000000000000000000000
-       ba3d2f96d7bd899d2d6142369471c133bdf1ab5a9a584745538c78631b095aa4
-       1f008bc2a6ae865927fa85b29a2c45304f09b8275e5ecfb62eb44ca5244b0937;
-  00000000010000000000000000000000000000000000000000000000
-       8fe14f887a1b802593b62ee61d7bd8f2733db0babcd41652ac1185d2d18f578a
-       1103c814cf73455d6dd34ba8846b724fb00d6cbfeca562bc97d118f4cad784d4;
-  00000000020000000000000000000000000000000000000000000000
-       8f767cb1db48efa0a1c5d642152edd3a050a1114facc07cd41409bcac7147f58
-       c08e42a5019bbe1275375549b91dd15819b71b8a7592152cf8d94e964860535b;
-  00000000040000000000000000000000000000000000000000000000
-       82b7a2e84536cc2d2758df01658bae073b29b11339f212e320a3d7de2b14971e
-       20aec4d43c582e1cef05b6e268b61a2f9633221ca785943ea7885f690242cd00;
-  00000000080000000000000000000000000000000000000000000000
-       76ac83b90aea0742f8ade2be9b160a297d8fe8b98daa5c54b4be2e44fb88cc21
-       18d1c8486e2b6f25e3f0164c2c0417af50f2438431deb4d4965f0cdf8cbb39d8;
-  00000000100000000000000000000000000000000000000000000000
-       0c2e937c9717fdd4868c019ee1bdddcc7ff68d5df4bf8175a59c13fe9ffa9ec3
-       1c754234c085b09ee98fe2049b0722502e0edc5508cca7190eaafaf90df3d310;
-  00000000200000000000000000000000000000000000000000000000
-       acc18876ae7cc4f1a183357d04e461987b1208b2b99f8d77a5544a07bd8fe89e
-       9f73b6c96743fdf8e1dc88e0022a45e19349ca3ec2bd691f2e5d5b08114c99f1;
-  00000000400000000000000000000000000000000000000000000000
-       88ad33df55b990c06a2d16d9978913c23b287c7b1e220c42477c46104503a766
-       f0042fdfa21c7405dbb441051b9e0f9a31e6f007a0a8fa43f97c86eae96acd38;
-  00000000800000000000000000000000000000000000000000000000
-       a3579b6a7d1d0efb2ff2cdfcf23612c9b2650beda7a67cc46e1844ed0dd12e69
-       1ab34729d9777a4009e98a196bce38d4431729e5ea6901824c50bcfb49b657e6;
-  00000000000100000000000000000000000000000000000000000000
-       966dab579c1d3702ddbe8656f9240b4efc6704391715442a66bec541456b5710
-       06345acc4e0e9682b21f66a220fada9b4f6d82504d3b73c8f6c89311dfcb1352;
-  00000000000200000000000000000000000000000000000000000000
-       12e01acdffc14a9fa3bddfb492bc348bc0c95eebbaabd17948113e63ace4c51d
-       9d40be7abc07a4cdd77219952ec81d8e1ef8178df21a2cbc927587c116c5e08d;
-  00000000000400000000000000000000000000000000000000000000
-       1f9f2968843c0133d070e8f0617a545b55fbd9a659e1ba9be16313d7e24a33f5
-       1eb163f3918a775d7c2cf6bad06d42359d9e4d0f0596822bb90d0db104156652;
-  00000000000800000000000000000000000000000000000000000000
-       1f007682755a014c1b88d7b541b296c7cf6613e2d5644517a49e0caab2f84392
-       eaa620472fc4f60a17390cdabe5a9410646b2754f26d6490bd89d8bd14d63824;
-  00000000001000000000000000000000000000000000000000000000
-       8071f28971756eac7456c7e41a8157cad949b67902f67b0186cb5ff521814381
-       7b3b7fd81181c132321b9e97ccfbe4983aab6c72dcde30e9172271de5ffcde90;
-  00000000002000000000000000000000000000000000000000000000
-       b7c03ef5de01672dd35370e37f77309ca808868dff56bbb094f9b0ac7c37872e
-       653410001ff58bd0701ec54a5302c5dd95994b6fdcb271447477dc1d35f32b28;
-  00000000004000000000000000000000000000000000000000000000
-       5057644476a033599dfc0b2dfe388660dae6c40828a464c931623997a3b2b1de
-       dcc23d1e17bceedee546c8452cdcfc43dfe3a36f0623371066a857a592b44c87;
-  00000000008000000000000000000000000000000000000000000000
-       cc9d90401fa604d973e99f78ea9d9e0945344f4098d2307f7402956de7ca915c
-       d877bc8623e95266ed10ed810f144ea4f7889636f63b36b478819200b06b2dc0;
-  00000000000001000000000000000000000000000000000000000000
-       270edd6834636fc90df711b57e4ec2a70c66189d9f149b8c6691ee901dd76c97
-       776b8906523e21663f84527687791c7f625a3eb1d456d430711212bfa0b36ff0;
-  00000000000002000000000000000000000000000000000000000000
-       c8d389b72ccbf5df09926294aa3a548cc07fe5693ddb4a4e69f82f736399fbf7
-       5177a1928aa122ff0281da5954ec854b2fafc3065b9d636f08bf7c6892054894;
-  00000000000004000000000000000000000000000000000000000000
-       99cdf287f3a952867f4aca8fca230fdd2799829786a09a778df717200910f704
-       3369a095516c39906e537b571b36537076baf3e00e634ce403017204cdc8a2cb;
-  00000000000008000000000000000000000000000000000000000000
-       23613557e1e34d83b979d4740aacf64ff2e7c353418d351932af432b4c3feac0
-       84bb895e1e113c431bcdd2f3bb02259efdc882fdca482085f64bb3490217e143;
-  00000000000010000000000000000000000000000000000000000000
-       1fddf34a6c90b4d87235c5851c031e9c6c9608c22b6bcd1f1988211f8025d381
-       4687c0880f5e092eb50faef790418e0dd5ef304b7e52cd7733cbf60c29e336a1;
-  00000000000020000000000000000000000000000000000000000000
-       7a448bca6c19369a549a89ce4c077fac787ff47683238cbde1bf4109d66fe10d
-       f5814b2ecb0954cd18dd3e633bc67890f30350c7fa2a4e2ed7fda17c4c224572;
-  00000000000040000000000000000000000000000000000000000000
-       6fae8a02043b344c817ab30fdc3709eadfd9dc3e50a260ad4ceb503f0dda2ca7
-       3a167f36f5c524677eb0acb05c715e614573e2c0a685a7e30bb9b111df493c9c;
-  00000000000080000000000000000000000000000000000000000000
-       8dc4aedcc4b4e7b7f96ba908e1ddcf7f07d8d26db0f599c5228404fa2e5e7fce
-       244309f24c16fd9ac28cb4c01c7354833be4d339754b8439d61c88afb7082679;
-  00000000000000010000000000000000000000000000000000000000
-       dd772809159b566a07beb6411bfb77d8511601aa33886ff217f3d6bea6b0348a
-       512926d3ded3f02d9aff5795050f2d1b8c0a7be7f7ed31b3ba085acc7d54ed8c;
-  00000000000000020000000000000000000000000000000000000000
-       d74853e986ef4ed4fe6e23538677a9b1800fd309e46d7cadc0be6ebce447fa58
-       6fe50d1ee521a88ae60582ec2e89acf5bb55dc13db2c5f45b01f2e95b4c3469f;
-  00000000000000040000000000000000000000000000000000000000
-       3e4b0bcf8c7de8760cc7262618235b6c76807130470bd84928652849bf2c424a
-       88823ee8d85199139edd4f77810ba859047ceb0cc640d10a9eb418c08280bd8c;
-  00000000000000080000000000000000000000000000000000000000
-       f417f0dec902322fb3754d0b5f1e841837549ac42efaa46d2c31cbd5cdb7bbbb
-       4da04434a336e640bda841c17baab0c0e71f048c092782019016ca6fb89d8e72;
-  00000000000000100000000000000000000000000000000000000000
-       e6a2f06bbd9b5d79ea935d8d53cf2098a4a838229e4b257258d5978c850f7086
-       9087fb1b85be7c7cf4fc0c3b89da6e36c7256190477b7d6a74fd1833c19bbbad;
-  00000000000000200000000000000000000000000000000000000000
-       1ccda6c45abbc6010a3267ee4e43af80f52499a819fd9bbb4c3df8a063fe0881
-       fa616cfd0404f965e3fec16148c60189850611b2d28f87dd1fea7f53218a53b4;
-  00000000000000400000000000000000000000000000000000000000
-       4e98a243a3167f35843ce0ead838066ed5747725daa3298eb97fadfeb2a47b8b
-       13b78a61908c40108d7bdae03e85ddf8d164ad161a6de1ca1f0e51a9d04010a9;
-  00000000000000800000000000000000000000000000000000000000
-       1bf5711f13594876f995324a6f688ef78fae8ba70ea49c175a27ef75ec85493d
-       6e3cdb2bbcc44b41b6e307fa774296889b4b5e92ba079789f60e9006b04d13cf;
-  00000000000000000100000000000000000000000000000000000000
-       442d9ba00e7313b035ab128ba863df68c0a19f1a7e572198086d7f79744cd088
-       02bdecf5b7f72546612d60fa301e01abbfbbfe27b4710d26f0c5bd50ed50dbd3;
-  00000000000000000200000000000000000000000000000000000000
-       246185ae4fd65b354b04f4fa186d700c49d3d9f5018a917a31042af8e33be63d
-       a9264216ce3b8a5ed76ce229955191d9ff66391b9792979dfa5d7c1fbbaf9c22;
-  00000000000000000400000000000000000000000000000000000000
-       1515f8b044f42fcbc8f04ac3ee3b89ce56e87f98b72134225603777fd1d66c88
-       3cedbc3b1cf63d957f2366876810213b778aaefd83f5c889dfebea8c35d2d4b3;
-  00000000000000000800000000000000000000000000000000000000
-       037337c0a20e54350483349a393194c5ce8f0104f3bbf2e9cdbdb4f8c93b4eb4
-       a52ee568f98bcdc658f48700b7b6062d2951a110bf0f3e48548325ab9212be1d;
-  00000000000000001000000000000000000000000000000000000000
-       9afcb8f2fb0c8f7957bfe3972ab4831c47c35f1deb5f01674637bcf4d0626d6e
-       7239fe3b5aab7daeca3c9016771b1ef6e67b3e3eddda777e12e8657b3f84336a;
-  00000000000000002000000000000000000000000000000000000000
-       abf8f708cf84184fa21b16ce492317060ba039e0815f186b162efdb47be5ca34
-       03a023c9dd6ce45f68000261b0ee2f1a8fb549c8469bf539a785feca009d289c;
-  00000000000000004000000000000000000000000000000000000000
-       115090529147724bb2280029f146ca67d19feb98e1d68991e3557b7f31c65731
-       e4db5a302db7910a999a6b04d5302132b3f1a21d416f4d70d2ca6c9500b4658c;
-  00000000000000008000000000000000000000000000000000000000
-       f8c24f3510ab36e692191e520edd4b8f7ca62e4c38976ca74f5b45fe75f0336d
-       0a20e557bf3112da79d211fafce885b2d2857270912da2301466294ab9bb6bb8;
-  00000000000000000001000000000000000000000000000000000000
-       006d35fbc723cf42718e015af9aa85a58785fcf5139f031de5913f4a4c9cee1f
-       79d9972f8ef149e5bdb2aea1855694834e88bc28d97f7506fd016e63984a3b09;
-  00000000000000000002000000000000000000000000000000000000
-       b6a8633cfd175b9d20f60805043ae68cd2e4b19d7306af279a476a1467147162
-       ac59474a091105832d53ca2ad5e4ef74ba1c7e227bd484d582523c8e8814062f;
-  00000000000000000004000000000000000000000000000000000000
-       be3e898c1f7be5fea90ea6dba94fb56d73af2540130004c2beec5244d402f219
-       2e091331eacada55955eaa588b2d7a0b60cccb37bd8ac7c1c29d5567adb7d0c7;
-  00000000000000000008000000000000000000000000000000000000
-       3173147bf3d87cfdaca80b6eb38a83f935844f04cbadae7f1de427533de75e13
-       fd7dc829a4cdca020ef6529b6f556393640d97049ae1c0ad75bd202f09cd3557;
-  00000000000000000010000000000000000000000000000000000000
-       597eedc7cd929393f4c1293f2dc579fa4f2afe807d5a2fb5bd0a896439be3183
-       e8c9cfc002d3eb8da47c8528600f0947d6049d34f6e1b1fb0c2e1fcf2691c3c4;
-  00000000000000000020000000000000000000000000000000000000
-       d3e7c0f4191f1a9fc7f2aa84a60daf5162b8b591cb44e7af87738378f7804c23
-       2cf8bedf4b3a75974868365f6b5baaa8c4594812130330352f3edbc791a01892;
-  00000000000000000040000000000000000000000000000000000000
-       35e398c0d94aac9865c5c693f3763923f32555817648121efdc2ecfc35fc354a
-       395e5543d4a31c9539f5c0a62a407abccc8fa71f52c075d5ddd927ad17e56fa2;
-  00000000000000000080000000000000000000000000000000000000
-       50ddee1bdc4c0f8f0d0c3bdb456a6e0a30c71b1e08d247841eda50a85c761ebb
-       6926a97fe085da68d6527a538644790ca8f8a4c68f3ecf49c3cf876a53d97479;
-  00000000000000000000010000000000000000000000000000000000
-       cf136f837e9c0078534bb9fcfef063fbac5dd5b7eda010502e4aed7819745a28
-       9b1a9914ba2586855e1f108998000010796c128ec5e822c3c49f1483ea7da01c;
-  00000000000000000000020000000000000000000000000000000000
-       dafd823ea2231a3d6590214a7bc68b9ea6159daad95778f44f3c287476b24e36
-       47906dd563422e0aee32cfb8b7cccf6c27c33e07189ab94dbfdb3fb348076c13;
-  00000000000000000000040000000000000000000000000000000000
-       2ea591c02005a5a83c6a5fd17025aee427825c07ecda07b78bc540013256314b
-       79af8d2a7eb63c32ce27f241dac9162dde7cb6bf0430a1ac59689807c98c3b6b;
-  00000000000000000000080000000000000000000000000000000000
-       340b58195ae4140093e1224f811e8e01fefbb3a61f87aba168836442c42fa094
-       4cde591cfdc70d3c8ad8f7fa942a84f5416c3758aab6c685e1c4cb9389a9aab2;
-  00000000000000000000100000000000000000000000000000000000
-       2ab8b78dff91d272586a56a661ac935a75ca0ec6c2dc6bef69b2d27889499aa2
-       3da491825757927a27b452da2e8e72e5525264af26739977392968c0351a90f9;
-  00000000000000000000200000000000000000000000000000000000
-       a151a348620cfe87d074baa730916f8eb8373970261759c8079b0a88eeff2741
-       e7d0a61a9258933ce905ff235b0287f215cada2453030a5c5aacbfe8fd93a4cd;
-  00000000000000000000400000000000000000000000000000000000
-       68185b88fd6b8ebe0ec150d966f3d48e03c51e5fbbf61d272bddc84003951168
-       e74bada25673f8bb50492cbed8b197af930133b104da958ed64f47b5dd61e68b;
-  00000000000000000000800000000000000000000000000000000000
-       8ca43156c06749fcce60d345cea15ecdca2cdea81b1bdf82025900fc856dd365
-       fd4c9ddd669d86d2298f5ef817e4516f8848a541d0eb4375eb2ea06eb1c3d681;
-  00000000000000000000000100000000000000000000000000000000
-       722563e1f5a521e0084ae6699bdbcef49147bc2db9d08eca8a155a91eff9e707
-       2053cb249b323faae9778c1bff22eec9759a6d04f67487197004fc6cf790e1e1;
-  00000000000000000000000200000000000000000000000000000000
-       3abf333bef3ae7f4f7c92a57195f758f1d116ee9c40978c24f435152b511ad98
-       417aabbc6aff1f7dd197c89c16fbcb87ca9b121dd19d21501723feb8a339dfac;
-  00000000000000000000000400000000000000000000000000000000
-       2a1a82d29a6c710fb7d35b1b66aa836ae340d4a9cfcefc5045a954d5988fad3b
-       64d9d9567db3b4372cff3be7c789a8bc6451311fe0ad9e527edd2c6a3e97820d;
-  00000000000000000000000800000000000000000000000000000000
-       92748e1df36ce322398858729265955801e70528990c15e102e1bfc6949126ec
-       944ec92f07e11a517fdcff7a41c72c02a3be354a2e3fd92cc2b6c03ae35a5738;
-  00000000000000000000001000000000000000000000000000000000
-       93a79e8843e5e49a7c61b9adbf5869b70a24b1786f2a476dc9b2b4b7a6d6147c
-       b44c96b6fc150dea743d84a3406926377ed403eb619b870ce414ad0bed5c6149;
-  00000000000000000000002000000000000000000000000000000000
-       613f858f69b87d4f2ea1287d2817ff708af8ca2292388c60ff64bbf772ad0014
-       9e98afbf45a14662e33355be5aac0e67a93389037ef6e04d72cd53c9f2091b4a;
-  00000000000000000000004000000000000000000000000000000000
-       26a5c693be3a5082796dea97f05cc2da9a8e1d3ef60e810d104d2105ebf81b63
-       f8765cb141bb16f91a002fbf0996a7b0ff8889c4545e2625bb870103ed996f7d;
-  00000000000000000000008000000000000000000000000000000000
-       6d6ae36d361da7f12442c0c5a389f6aa4967d9e1b538512ccc4f86058270d714
-       4a5be549a0f0b646e97933d3b4d645a0552e3b1b9d5474950ba154b3fb243f6e;
-  00000000000000000000000001000000000000000000000000000000
-       cd97ad2ab79d5e6893bc8676fc1756902033f5e502f48723e0c8f1bd636fd5ed
-       702acc3d216d71a16db827a4e53b16629923fe73b2f5ad3b5147c9d40b043841;
-  00000000000000000000000002000000000000000000000000000000
-       69bfe6dbf88d693e34ba867a3faae2a545c630c033a168fbad9a000b0a3d63c9
-       8c11ba612c0113627f0703c930a595f03b132c77677385b2f55eb951295b50bd;
-  00000000000000000000000004000000000000000000000000000000
-       474504641ebd7e5e886cfac4e8ab717829d7afc4653051a7ec4cb6136c5725cf
-       2f671c3f45b8f697207dd3edfdcbd228fbace746bc9982b107eac863a755a645;
-  00000000000000000000000008000000000000000000000000000000
-       403c4c767ab1fed06a95d0a42e6fb058092996c1e7f9cd74023bd7f7f5e65cc9
-       c767847b6384b478668f053277ed1e655e0e0822d6504a73c2a97adb344c0c50;
-  00000000000000000000000010000000000000000000000000000000
-       be00a382ce11f4b574bfff2e48e622d25d709fa043d2fc7c8ecdce33a6ca7272
-       a8a42c740d6fce54fa53651fb2b0cb0d8888d8999bde23cf6f5b42c8e2d1297b;
-  00000000000000000000000020000000000000000000000000000000
-       823eba2a58a9c7a43b4781255bb178a00ec401692a9f3cb64eb6b86146a89c3b
-       27e4c00de764619ff0956cdc0599bb20e92d2e39e2f6a5461311b357ba5acdfc;
-  00000000000000000000000040000000000000000000000000000000
-       1b9c442bfd36d7b57e185468b3fceb4b928718b24e8fe9618648119df1d75345
-       7d89665bc3883b2d57e3eb097f3f66289e08c21ecc3d641dc2ee301be9a0b7a1;
-  00000000000000000000000080000000000000000000000000000000
-       e52301462399a0fc87356c8d3015aef445c71699a0016598756a1a89ba3f717b
-       884a598ffbbb2a2ffc52fdcc89b46ea399ac6f46e73bafc7a851a6fbab090165;
-  00000000000000000000000000010000000000000000000000000000
-       02429ab56ca22bccd71cc987d3d38b99bc6144e2c70e2bbd1158a9c8020c17da
-       9a2f84e0a9669cb81d36359adef338a98a82da479028e3dd8485adbd89d05bb0;
-  00000000000000000000000000020000000000000000000000000000
-       124eda8fdf5c7db30c8223cecc62cc5cd66c26cd29b4d0ea304f277c77fbb6ee
-       442969316b10b8bfb2a65611b09a098910deb26468ac2fa906087f4c85e634c7;
-  00000000000000000000000000040000000000000000000000000000
-       52d01eb026e4dcea52de1a1f1435fc008d246693f38ef05f1957dee04b1e7a8e
-       3153ae837aab345e33a38cb4d4e7277dbec1fc15fba9a5d9124dde3d4681ca8b;
-  00000000000000000000000000080000000000000000000000000000
-       5e15dfa8d87cde6e726bec2aab6d7c23d059af8ea25fbdfe349f9ee20d1fa3b6
-       ce57c0f4eda33d4a4f89336649d50334ee4cbba06c2e3e61ab7a9406507b5a74;
-  00000000000000000000000000100000000000000000000000000000
-       dc9fa20173488d514672039328f6d51b58f8e08468543cdc74840178ecfda865
-       7faa9670311e55c500d83c0dad131081666d5e3efae876d5d4aceebb108caea2;
-  00000000000000000000000000200000000000000000000000000000
-       18f4ceb5efe6105f7557cfad6a335da2a84939887aa9ea69bd72aefe2c2e5d94
-       782f9a52b35d7966ab285611567cc7ab48fea542533da985dbc14945c4fcdd72;
-  00000000000000000000000000400000000000000000000000000000
-       770c3b2300ffdfad2c87e1b06245d4dae9c0bf98c8a0ed071c94356e24b35cb4
-       cecf717190bdd7b0e9bded5bf59751254f10563f16e4d4e8439e69bc7a269aab;
-  00000000000000000000000000800000000000000000000000000000
-       54c6058fe589f2fdee3379bfba956f77f6d752501e76ebc124d65ef45bb407a1
-       e269e946d75ef8fcdd9ced031c21f7d14a4640b7fbf34d45236c2cef1e6e5df9;
-  00000000000000000000000000000100000000000000000000000000
-       22628fc8d9ccc487132ce5b75fc6e16d729412de93b644c9152d216587f57eff
-       1b4c46083ed8c87b31820641c90a5891f82397582d827dc7e53ed4690f12f8df;
-  00000000000000000000000000000200000000000000000000000000
-       4c4c2b14336eeffe279cbbf23bcdff9f77e73e7e2b01f27ecceca8adc189b3cf
-       9368b0e82b3bac88ae4d521a8a834f53ef6040f120c4e40513a5cf3f7f13b930;
-  00000000000000000000000000000400000000000000000000000000
-       30d18017f87290383852b0ecd0a8b284c85a590073c4aabceb860b6b59edfab1
-       fe477785fb346cc1f00550f7ae473f0d6c7406ecd2b85774ec9d70057bb30ada;
-  00000000000000000000000000000800000000000000000000000000
-       30897b2e3c37ad2ad3d990e71a5a5d87fb696e43430200b63840b6a90ff6f687
-       6564eadc218e0753d51b472c3b8a16f6ace1f08ca436fc43d4ab566423063056;
-  00000000000000000000000000001000000000000000000000000000
-       6b86652d2308db067793d8efbabc60c248487a662844d65731c9f352a0b11082
-       cbd3b17629ec688bf2404446edc156cf2dae31b7d9e251212fa6e720a16caf0d;
-  00000000000000000000000000002000000000000000000000000000
-       902742d8e4b5a14e5b2f6444cd5770169d82b4a084a754b334cd25cea9c4ed81
-       b80ad89010cc9ce05d6d7976205c975e1a6c5dc5134d2a67dd0c984591ad8615;
-  00000000000000000000000000004000000000000000000000000000
-       7c820a4af9bc911ba3f5848386da8219e0b46d39ce42dec61cde449f348159aa
-       dee9870c0c8fed693fa8354d3bac82102bbd56eab88b8127e4cd706be81c70b7;
-  00000000000000000000000000008000000000000000000000000000
-       6eae2da5a59fc6b3f482c8807fc30add517914fce8b45d346e19b03680f7a08c
-       3d8170b8496ae73d6be7e048e61c9a21072ef2023e2b76a744f2012c3a7cc3bd;
-  00000000000000000000000000000001000000000000000000000000
-       dc5e94f0a7bce3155d87e4e5a274a4bdd20b6268a78265ab00d8f0aba23b9a31
-       ba700f0a95807925d6e72db3eada829f80050470b8f13db0a7f9528eae284e06;
-  00000000000000000000000000000002000000000000000000000000
-       409bca4c7a1cc9d627010605c790802a9e91e08d6c7febaf6ff507c441b83c3f
-       df58babb7a632afc991ef13c3ff7f647ed1e073c027225ed5e713235328ad697;
-  00000000000000000000000000000004000000000000000000000000
-       7c0429fd417a0023263089551cc9a497c6aa70aaa7f7dd1f07d3b760524a41b7
-       dc5b1bf2dc4280dc044c094d4eeab87c9c54b8d1977fabfa3376c0f07ce2042c;
-  00000000000000000000000000000008000000000000000000000000
-       a287c270e99030621f52acf1588bb8e0aac7dc1859c49e331aad589ea94426c1
-       0d9779c3cb59c8589c6a336c9c459ce19d3db33697815b3a459996d24e950701;
-  00000000000000000000000000000010000000000000000000000000
-       06923622b8250acedbdff5cad2f88a8327d7e07ceff7a40520eef9ba4ca7c7a7
-       d4738c1a3aa671759b15fe887963eee5782fb1eda3421ee372a5217315e832e9;
-  00000000000000000000000000000020000000000000000000000000
-       52660b96d56a3032a48e3c1ccca1ce1fafffd43b05d96e8ecda1123898cca637
-       c5d66379ce7c299d4a1958bfde3b035d7e07af1bd640511fb12637ba7a28ed8c;
-  00000000000000000000000000000040000000000000000000000000
-       b7bc824845abe7aded1676ebeb1b5db28f7eda76830da2348c873d1d1bda24e8
-       a3c9daf34c78459933f3d113eca779b8f0e412a140c04430d8c0369697c4f762;
-  00000000000000000000000000000080000000000000000000000000
-       b9b434ddbd0d969547f4e575819e2012d3429bc172cccad53ffafe9fae9eff87
-       38ebcfba6197d3dabc8dcc1bc22ceefafcd9734f2b0c2f91728480e35bc43d92;
-  00000000000000000000000000000000010000000000000000000000
-       2058aadc3e731b05017d412a720696d297ce2975efc4bd202011d3aa43d12ed0
-       3ca5d92cca0b200af76f87b19ca01c328e44b4ce171d8444a42ea529c4586bfd;
-  00000000000000000000000000000000020000000000000000000000
-       d351e7ecdd3aa6c0826526115dee7a6064988947a22728073ad5d85c77bbc934
-       62fc94852584bee32bd1977fbf330e782385bad2fff9acfd2e62183a5b07d52c;
-  00000000000000000000000000000000040000000000000000000000
-       4af5b6af3be9dc3516f7d0785c3211b8c86486b6d171d8653a603903bd592cba
-       1815168c3e0c51a6c52848fa4c0c2459b1149854dfe234ea15e9c67be9fb9766;
-  00000000000000000000000000000000080000000000000000000000
-       d19f4e25914afa257fe634f5b88909444c4670540dd0775b67eba234441a78cf
-       ff79f959dd28be8a30311b64a9a47f9836966f0effcf80f003144a562ede9dc7;
-  00000000000000000000000000000000100000000000000000000000
-       4664cd40879d3e2cf76b67e617ad300b071758be8dcdf76b2d2c3ef3f4538c53
-       c4cb7520809efae915b15fdf7d45ff8df6c506e522d72dbaf576e6c724135df5;
-  00000000000000000000000000000000200000000000000000000000
-       69fc75db35df38c50e9400caa21e4255adefd3932f01830f79bbe438c5c341f3
-       4e67c1fcb607d92f3107b3f7a84e02c7c2424b59a7beed3e4ad07435fca755b1;
-  00000000000000000000000000000000400000000000000000000000
-       a6db7bc42c9a02150177bcdcbff996d4e63639367de8a3459d5a422c0a391a60
-       390e3998a3a6b2e5a99719ca25e065ed20162053efd9e64574a679b0b5d9d66a;
-  00000000000000000000000000000000800000000000000000000000
-       409ec85f059ce5969f275f36bcec4b7d623a4e2dd6ac4f68abd8d5d7a0a422e7
-       5ad305c93905815c67ed4c67208c50350e71c48ef9c4b4d2fe846dcac41a6cf7;
-  00000000000000000000000000000000000100000000000000000000
-       59a81ede728ccae99bedba5ee8d3ac4499579316ae5f7109e2656c558a7a0733
-       2307ba4eba7da1e4a566e99eeebdecff041fed0f1549c595b14230fca2a1164b;
-  00000000000000000000000000000000000200000000000000000000
-       0c6b0f0151ae8ee876698da2eac5eac9ba1227e13e98336a93fe3793274a43d4
-       f3baa2841495261d6b156a5886578662bcbcd13fd68ac542cd03f4331273f847;
-  00000000000000000000000000000000000400000000000000000000
-       f510f5e9b370b1b34a4cde599cef0b80c4f657688239f3de82a12376140fd934
-       7ee1e4a96f8b73817a2b57e3e4d0982cb92e05ebb06348681d097d7f55cf12cd;
-  00000000000000000000000000000000000800000000000000000000
-       d7b38ec40b465126d428dad054a190a25bde83fe1f2ae87db9dc3adcc0bb660f
-       04d42fb3907165cd7c1d75da7087da71ba524cbfee56fed771f16dc3e8e176b7;
-  00000000000000000000000000000000001000000000000000000000
-       414f693e93a088ab8bb5cf5049d6f3ac67e654e786fce08559dfcd96dc6a3b23
-       ccc0fdf2941815dd9c050fd1c9d1e9414492912cdee277465583384a15d761d9;
-  00000000000000000000000000000000002000000000000000000000
-       00a7a468282dd455b469ed76c0d67e0f507a53bbc7fd1941e8bd600bea43b982
-       4c8795a55684958d392aea1409dd01020912380b5c81bc868629ccf393594930;
-  00000000000000000000000000000000004000000000000000000000
-       d1bff2f245ce0690ba74588794d7306c934ec83dd8d7811493726c95822a899c
-       856c5179cdae63a65f1b107e0859a1ac790b014746a7bc7bb4385bfc9fff1630;
-  00000000000000000000000000000000008000000000000000000000
-       d873980acedd7383fdb371beabef1cd1fbb5dadd665f2f118262ad539a118153
-       59a325d64f1e454646459c72f81b797d534a6f8f0ccccc38a8ff47298f1dcb9e;
-  00000000000000000000000000000000000001000000000000000000
-       d8c4dd99bfdc3bc0d25516a7980651bb545077500e01e3b543cd72ca97844486
-       f0334ce2c74691e3aa5fbc12a25d5d6a14fef43bd4df05a2f3f2c9b34d4f2c44;
-  00000000000000000000000000000000000002000000000000000000
-       f6959bea04ef9ce9e73c363959e28ab6404e8dbca900dd2284f2b848a109f768
-       81f4bfd5b8b0df8b32299d101d339ef40f9655962916b5219145ae074338bf40;
-  00000000000000000000000000000000000004000000000000000000
-       411c1c715da711eaba6972e77e408d6f5a76371d10dc7a165f2150c89154db7a
-       3d1b85da27fd34e9ffacf8703b958073366ed819459b1a153db135e4a5835ed0;
-  00000000000000000000000000000000000008000000000000000000
-       c57d8cec898496dfa1331457c00b2d1962c1df9788d36f155ab8b94e985aff15
-       92e1ca0643703a1bfc56842a4d6f87d2acf0ae3dc58935fcba5d847aab6bf920;
-  00000000000000000000000000000000000010000000000000000000
-       c16ad6e1a87c475ddc84d7664f11932debeed6d987cd05e9c6fc493b0a68e261
-       3c984416b43aa267eb6e0c6a68f8a41ee2a34e14d93839ec47d2b256289b4827;
-  00000000000000000000000000000000000020000000000000000000
-       cc414cc5970efd4418917369edcffce4be969ef4fd721b376e85f9eb1ea7d483
-       fffe4d5022ba7bf9feb0d5e8c8a87df1a49dc2353edf5a2b9cb66863cfd64661;
-  00000000000000000000000000000000000040000000000000000000
-       b2c9d7c5d8ff0bb054ab8f440915839840e7c9489ac78045fd1b49e0581809cf
-       6b0de74a81dbc155fb23b033b45f6b3eb6256fca7fbffb4fcf0ddfadc177659d;
-  00000000000000000000000000000000000080000000000000000000
-       d68ceb6c0de43d2a62284fc86b872f6686ed0ee6710539cc295fa290d46f3d17
-       3f70e4f08444b9bb7d03552aa0272fcdf3f30803e2608cb299c2880e63f7e24a;
-  00000000000000000000000000000000000000010000000000000000
-       c6dfe5c3e64ec36a7c043ffe4b119f4cb7e40acf0d1b61fd12bde9f8253f6387
-       abd8bc56bc0d4c5d136fcb6af803493efc80f0f0d00fe47ec4dd70d455ab04bf;
-  00000000000000000000000000000000000000020000000000000000
-       c75facc882297be6c90d4d00bc8acc443c112d7f58a20f819a987fdb01ee14df
-       2aedc8d591536166b58e3bb5fca7e63b348357762912aa6a83458186ef315c34;
-  00000000000000000000000000000000000000040000000000000000
-       43113d85e6094d67cd03a9111397b014557a6850a8d796e16736cfc40fe0621e
-       89730f25612fa04d00a1cc4732efeebba1b80c993238786386cfce09bf10359d;
-  00000000000000000000000000000000000000080000000000000000
-       60794b89b36592975d54a0448e7708e6017d4027fa3891b0335cad062ffe8db4
-       0d3401a2c417efe1859b4b165e676a7a5ac031a89094a0173bf46529e0078adb;
-  00000000000000000000000000000000000000100000000000000000
-       6bdfe911c6703becfeb5c205f11d2aecc6a81dc22c365b48c1929a81dc67f32c
-       61c6c80e40ab88b27bfbbf703522570fd971e8af2b460ea72ec59a92b3701558;
-  00000000000000000000000000000000000000200000000000000000
-       24dbbd8de57a959b62a1668e29ebc7514c71ade4fd64c40b482bc98057d77b34
-       671e53090529d3258abd0349e9ec5ecbd0506d211d6228f4e2babcc68699e5ed;
-  00000000000000000000000000000000000000400000000000000000
-       cf4174ad172064185cb5c1774f08f4e47767579f5ccf71a87e622605041ee5e7
-       8617dee6d4146da406e826d90003fd4f3a77a566d21b8e45649aac687450da4e;
-  00000000000000000000000000000000000000800000000000000000
-       016f5989221bbcab0a3cc90a99f6e1f21c9cce56249855bea90eb6b0e3ff925b
-       cf450821f51f1c80221821fd04d9676d3a81f9c003b692a33d21f21d7054e6c0;
-  00000000000000000000000000000000000000000100000000000000
-       00d2fdd6d13ecbde57f8346b651c3d21fac7c08c0d5624d27b77f70583a58c21
-       89de016c263121254e78dbc2df605a71de36313d855994e9ebdc45556e721749;
-  00000000000000000000000000000000000000000200000000000000
-       c5d03f396dc1b171f23ed0a25571c3f3bd773bb887aac4ba4320afa817e9b460
-       c223bee85f757c23c67c009f1b0912d4370315f91cdcbde866c35ed0e205a848;
-  00000000000000000000000000000000000000000400000000000000
-       701df4f85e7de8ab8887806541c49911f6c0f3038751d9c109216059df06cacd
-       a5e35984cfce2a1000a593cfb80f79e6e8c38d5791bb7e96344bfd3dfbea88b9;
-  00000000000000000000000000000000000000000800000000000000
-       b58876deb62a3c880f51acb743ad9eaa2119321e096d591b06f3dbca6ef924d1
-       829c940bfc3409ec73391740d7652466113ba5a5b03118376c726351747b8b34;
-  00000000000000000000000000000000000000001000000000000000
-       b6bdcc6d4af946d02f2ce1f8c04df35f1c1790a663ca40bcb57697d780365439
-       99624b3c7338e8f23faf22b4a89deee5fa8bf7022903db3fa36c6f9957a819a1;
-  00000000000000000000000000000000000000002000000000000000
-       79d9fcfd5ddb19aa8a8eb84496eed8fc1d815f7fbfef3162273fb108bf230da5
-       9534a0ae4ba8babe4308789f732f6197c6867d222ccbc2eaa064d598a4c24ee8;
-  00000000000000000000000000000000000000004000000000000000
-       c6c6b524090066e3b3cf196fba642cb3f8c5aa63e734b47d45279e7debcbcb4c
-       ff20409e1bd929705cfc445c37924f4b2b9151b08839c53b464eb68a807f977b;
-  00000000000000000000000000000000000000008000000000000000
-       4c14e7b11e9c079bdaf893fc1e6dfbc38f205e04373760e06afb6c5fefcfdaf4
-       a01f116e3bef972205aabe1494f76b70f1c6372b74f79f4a23904c58b1b51fb3;
-  00000000000000000000000000000000000000000001000000000000
-       2ab3bb7f3211b75c80b01b15ded624e8046bfcac7c5f88ded7d5e5e030992b95
-       374d7ca16d59e8b6b128b7035caded032134dacc94c88b549e3891282e92cac3;
-  00000000000000000000000000000000000000000002000000000000
-       06bc1a54e4a68178acc810f2f9144d01fe6724ebf72225b67a0b138df10dc6fa
-       27f3b1d7e61cd1c3b73f72e367a9a4f6fa4010c94a2cfe173850d832e45e89d7;
-  00000000000000000000000000000000000000000004000000000000
-       f9c484b67e531856f5134b4ada1a231f6f66e6a1d383fbb1e7fe7a7399a39918
-       f4c1eaaed3e8c5e62c5573b0779afcbd197aefc1cf881392e00659e0749b2256;
-  00000000000000000000000000000000000000000008000000000000
-       8e00b017b4c601c6ab9e606f19e1210ca98b5cf020a2874fbed90f3e9ee0af9b
-       2998fbafa21326c14cc0eccf3db5bca7daa744a086e58adbd15537576a5129a5;
-  00000000000000000000000000000000000000000010000000000000
-       7fd2a56e82a8a82c0ab027ccfb68acf4b894bcaf0c03ceab68ad3f198d9336e1
-       0ea3d8f711178f80f559bc8f4402dfbe51c6dae84e3fba861050513c4b63f8d6;
-  00000000000000000000000000000000000000000020000000000000
-       12eb27967c9c4c286496836bff364450b767e969aa8b53f7dcc1101cdc535eb8
-       b30dc7c5d8e4bfb50f29b1be19fd953c6f6d6250ec2f1b9a1fb4b457d928e98d;
-  00000000000000000000000000000000000000000040000000000000
-       1630f9a365245fb0b5f8684e3b467ac06d34651076feff3f6718a9c37a1b58c6
-       3240790bc28be631963ea289f5a3266f65bbf0f86e169751cf7512e4c12419d1;
-  00000000000000000000000000000000000000000080000000000000
-       8cfd772627622c4ddd26eea011ed6160ede81e488b3c651d4526a34449921724
-       5081e4d0a86395debd81de249553a4936a510f15d07c031cad7caa563ebe0668;
-  00000000000000000000000000000000000000000000010000000000
-       2bb3f8ff8c4fe0f4e66073bb662cc09311adf20fb22d6464b4d778250b542537
-       69f83515e69eecadeec5eab86e2f0bbf11ba2bad521a6f21da06ac02331db838;
-  00000000000000000000000000000000000000000000020000000000
-       fc635cbb01ae965a24eb7e27c1f20b45fd2f2722918ecd8eb362bb52216ba279
-       0a97f58b8cecbb100f67b8d4d46ba01a8f68d6b4c7bd06e28ffdedd28e46f076;
-  00000000000000000000000000000000000000000000040000000000
-       b35aea1e5f09265b3b7b6748baaaa97ff46d7118491875464590bceec70b93cc
-       962374c521986b0cd478f4353c06a28a1203da79cb98a198f3523206b22606ed;
-  00000000000000000000000000000000000000000000080000000000
-       89e462fe5d5c5325c5ee9252c73530692c6c29a1a3c7f389f83d533ca1b1a83e
-       dfd663c857be90d098b8170eaeeb7ed8a6948c8a314a74599691335a8a18c2b8;
-  00000000000000000000000000000000000000000000100000000000
-       47d9c74cf8b7148a6427408e3aeb790b355bf02b447bc57c6f8c05b7c51ee8be
-       28e4223e24ad191369fffebf62c84059c519f49018427b41bb8b67ee9c820222;
-  00000000000000000000000000000000000000000000200000000000
-       ff3ce376a28ece62a73a9c00a6ffc69767e836a8a17b49b824a4ad20c0ff0a21
-       630c092e5521f6041ede8c61e73678198e19fb339a04daf94f9f923854f3d7ef;
-  00000000000000000000000000000000000000000000400000000000
-       fadd0fbf5f7d4eca5fc145d4aa79f7f529950335b9d45d592f3eab084c4e883d
-       0f9c8706d1385a2f0ad3a0407460f86def321d3ec5072694ee0272740a12427a;
-  00000000000000000000000000000000000000000000800000000000
-       cd6248d7199c68291a4d828f24d534f6fa28e4b8706974f439e28625cf8e2310
-       b9cde77e2e12ea77ef2ee43e153a26bf09071198249550603c63c7709ec6d090;
-  00000000000000000000000000000000000000000000000100000000
-       bdc4b06d8fc5e5d3b3285ab19e1210271170c1ca306b61c888230f1d1a6b4c11
-       2e393090c2212bc3e2ae80d367d4a0821dbc121a0b4b7efb989f980918fc3412;
-  00000000000000000000000000000000000000000000000200000000
-       2e0b37d02fafd0b335c0e3da36d1b67ad4ff988f2dccf9dfa5722247133f71f7
-       52e68f282e5c041eb7c8d8bef21ef3c7ac045101b3f32211507f781f0f347815;
-  00000000000000000000000000000000000000000000000400000000
-       327e75a7c2c7df51c76632e55ce0f3e54ca2cce1ca5bf9bc4dab9bb4c68713de
-       49bb9922ddff6cd9b917a2697b399c7f0cd803a0f9ef25bbd06cad0c8a97d2e4;
-  00000000000000000000000000000000000000000000000800000000
-       d95ad5b34ade4fd38e6c02bce505bef6454349dfe71aaaeeea53daf6944c76ef
-       5774340daa33bf6056a6f415c82df4e48da319997b38664fc2a9dc0acbe03212;
-  00000000000000000000000000000000000000000000001000000000
-       a52178fc875cd004eed999610933fe8db73387b935d06ea14abdaffd7d870452
-       a1a6144b8ab070d6a8cde942e6443e72bee40937eb89c3760c94f5fa74c1a6b4;
-  00000000000000000000000000000000000000000000002000000000
-       588d9c2260a9ecfa95da0f3ae80ed811fdadc55a6b19ca178d705ddb4f7827fd
-       e21dd6f24a2344b05df56af868b16c9566c3e93562894bcd82a945ba514c5a87;
-  00000000000000000000000000000000000000000000004000000000
-       d15499d0351be2608940d7460b38cefdf5ee7503fce68579fe3a186bae4e5998
-       95d149362856e80e436470d08205d79591520d67694178863d929c1283d5a541;
-  00000000000000000000000000000000000000000000008000000000
-       0bb9403874309bdac289a847e6be5642e67f71443097d7c1cc9e0787b6c4252e
-       600cacd782749f2f91a3a26a67ebe9d31593fd520a8046f5a60cface42853a89;
-  00000000000000000000000000000000000000000000000001000000
-       9b9613f244651fd3dbfebbb6dc96b52b1a771aae0b6f4bfb7d71342a0462b013
-       44d70fcdc3c9308e2e6229b2214bf6fa9ac83fa7d3dc0b7a29f2c5f3ec090b1f;
-  00000000000000000000000000000000000000000000000002000000
-       259d92266dc21f7d30e7070a48a58a0a739ef71aa4e0c1bf919df19bba0c6e35
-       aebd1c82b24831566492dd4b424b824fe95a52c44aa1cca0b5542e1090cc1fa9;
-  00000000000000000000000000000000000000000000000004000000
-       27be0b934efa113d8c8101dd8d56c4076398c8d6e7977f347e23749b5a73f313
-       ba77447b42e23157c2ee9b4c0037f4c9ea37a9a22e9abe2a23f94d3bddafba82;
-  00000000000000000000000000000000000000000000000008000000
-       f5430f15301470f840f91e7b75ea4cc7395b43f1edfe9bab362e8939969484a0
-       ba43279cb5c71882e6c3ea7a43e456e6e5c8fd15310e38f1a8537f52993e1b5b;
-  00000000000000000000000000000000000000000000000010000000
-       d3fe3b4294f674572da05aa1617fecde382a03e2a429a7f5257c8aa906057091
-       7a033fd229116872c2c1a18b74fc37213c903e59ccbf0d382a946fc4204967d9;
-  00000000000000000000000000000000000000000000000020000000
-       68645bb3921c1c55b0ee6e262e71b654cb8236f1844dc8b83eb012659a1db873
-       c8375d6b2755a13d69f6d2027211bc5a331d0bddf05ad8a79244eafd075e07a2;
-  00000000000000000000000000000000000000000000000040000000
-       ea6fa9dce63e87a3aec87ca45455b89ebd39631a914824edce01560edd20f6df
-       1b37c1283b94e96ce366845d3b9bdbb067a489c33c00345e310a2c9086c987c2;
-  00000000000000000000000000000000000000000000000080000000
-       b4398d7d35ac622252854e8e113cba5a8946ce716e3858105e4261cefdff24dd
-       2d6c9392643deb1174875897917c864d9e75e9eb22dc83f754cba0605f800265;
-  00000000000000000000000000000000000000000000000000010000
-       57ec1c68ee07d85bc8ed73c0ee1c0b3d7b17ee95094a1b027d00e3359bdc68cc
-       76693250618daf58a86d6b7dcea6f4cde1663615cc771996f2bab17cee73c4cd;
-  00000000000000000000000000000000000000000000000000020000
-       1939a6b965e7e13d46f888ceb7f41bff97a46a6ace11d3786097761e47c0d4ee
-       4783bd9c5b469d4a03fde86a90fab3dd73d009004d333771155889bc19fed805;
-  00000000000000000000000000000000000000000000000000040000
-       887c0455fa369ad1a63a89fe53f5c1f1f873e36673a554c19d3251ca1f401781
-       90697bd7073e82b723503b0fb86c3106d6d4d39036e9e8741b9d76f79dca96c9;
-  00000000000000000000000000000000000000000000000000080000
-       09ed519fdf745461e1fb8e10471c54d52f3455fb7aa6db264b2757b02829ed41
-       e36c4cfbbc607b301a28f6c0f96774722d7dfbfedde89e97674438ed31fc424c;
-  00000000000000000000000000000000000000000000000000100000
-       61b58f25174e379b185ce40c08717b11460e6839c1dc0d0a7430a9f367960376
-       eb6bcedc9b1a70fbb749f9535f59d60dde1a6a3de6cf21d083bb43b696d0d455;
-  00000000000000000000000000000000000000000000000000200000
-       98e164ed01ec6f3a53ec5eb1d7930aa8f7689ef6d3b3f5359618d53a6f291180
-       539a4febceefe3e49cc2dd3100b1873ec5a6b03c04544bd9930e213bcf79c5f4;
-  00000000000000000000000000000000000000000000000000400000
-       e9956f811053405dffb566909338e93bec1c4ba2a02cc5c6bba8def3570ddf29
-       8aea5d2e8e322dbc2454e236228a6661c2e49bec36749e784398b8afde823e69;
-  00000000000000000000000000000000000000000000000000800000
-       423e3d2da9cf293c881cbabc625ebc58eb58f68cbfdf74eca77d0c85def81286
-       138283360cc8db7f3cb1845cc2d7e3dd55698564c62ff10cefacbc7e754bda0d;
-  00000000000000000000000000000000000000000000000000000100
-       459fb60e8f40da7efdd66d01a15959a3ceecda42ae8bae622510e92bd4374c43
-       058ffc8eb9c8c74755f80ff096b1ddd1f9ec9746fdd63f81fe94f5aaff3a4455;
-  00000000000000000000000000000000000000000000000000000200
-       d56a4841787cdb240d452797278e2065d92d94284b60ac78bb0d90775dbc9172
-       6414921eac73dba768b88d3753b4b61bee16ea189676d58c85f758cd4a04891f;
-  00000000000000000000000000000000000000000000000000000400
-       ea53b043630e6f958784f0f7dc6354418901f654c4b06ff40ab6c4909f917ff3
-       50eba9af77a57a86c497ac90e535e47645a967e5a678735e9db13175da4eaddd;
-  00000000000000000000000000000000000000000000000000000800
-       d7f30fa8111469c48de76fe0d1148ff48675cdfddca0ac977330d094ff796b81
-       eaa3b53439f65b9d8b47a24ac6ff75a66e93aab097670ccf484197c868a0216f;
-  00000000000000000000000000000000000000000000000000001000
-       aef29399dee534bd8ff17b1b2057787a151255bd76bfce66f6344194009935fd
-       7489520edaff91fca342b7a90edfe649756e561662f41db5b12fbecf99219897;
-  00000000000000000000000000000000000000000000000000002000
-       ff1026c8390f4688f025b03a0758bf56c2ae84c580ade19c22332eb5dabb2d65
-       44c179aa7070f032236520142146813b55a0a9a58209d3e869b8969e66935073;
-  00000000000000000000000000000000000000000000000000004000
-       43a11b9a09783a0d7d079eecff5933c84b52f96efe0e38a21cb97b6410663128
-       2216c885bc941c655dd6d0ba0b32944c2e501823cf9b5322b51827445b74ff7d;
-  00000000000000000000000000000000000000000000000000008000
-       b8af4aa7c1fe35b031ee050dbd2d247091f173179686ef8d0659446d643f2e14
-       73044c40077491735fc44b1471a94c5585d0b267971270e18a54b67954e52a80;
-  00000000000000000000000000000000000000000000000000000001
-       896855032d11655c16bd94f994b8f47e2f82be1c0b3a296bfcb18e0a1e9b4edc
-       75ce1a2f4d77d032b86cd65dbfd97936e82d76f16f87247e1a9fd39b95307577;
-  00000000000000000000000000000000000000000000000000000002
-       0082359d931ab3fc8791ea89c01e74d7a6ad0e40c7a0fc369055c28f8714c679
-       648955a8ddf7ac11dff9967156faa35f1e5bb74eb92e395099575b87799ff709;
-  00000000000000000000000000000000000000000000000000000004
-       7bbd0fa76452768bdd69cd448b13b28f1ffd689df6e4f4c0c0201924078a702c
-       3e9efedff4cf93e8bd34c4a1a8f06916410fa99d326a4ba831aec1c1d9c7d60f;
-  00000000000000000000000000000000000000000000000000000008
-       5cf1e70d83b64b87b5b4533a0d0974a871fce3d68b085587e4434d1789c5a036
-       2cb01ab75e4ac0d2d248b1e2fe2c3a43cbb99a90ca7485357eff8f4bcf001ea6;
-  00000000000000000000000000000000000000000000000000000010
-       15ad3287e48777b536309c26f3d4cd928f9f11c2d88eed60e4ee42151a78ad6b
-       135d93ca9bd490f23afd619476cb934e42f7b383cde0c5db99503b3fe325b34b;
-  00000000000000000000000000000000000000000000000000000020
-       7206c6beb79aafd394150835d6f2bccf7d7454b6c5b80afe0c8afc311430226f
-       95373efb0b18c40fd7a2c98bf86805c0b8e6d964e12e025df90f1f63e631abb8;
-  00000000000000000000000000000000000000000000000000000040
-       34adfd7c6b2ba94580eea815dc441161d91e427412f54c42df398360f43074b7
-       635bd00a91fe3410088ee2dafce819f26a2f44e194fc39732cb56ac470536592;
-  00000000000000000000000000000000000000000000000000000080
-       bd56867e5c02612bd20abce0a51c8c0a9a5c3ebe27af33b743d22f1862bc9b40
-       393bc6a1c9cef4829b5586e99952006b7e4af3056df28511fee2902eb5d30940;
-  0100000000000000000000000000000000000000000000000000000000000000
-       e15988e471d6475f8094d5704775b2ea578ada4ccd7fb6bdda530b250688c0a7
-       9b4c62614948194ec5e0d4672100f4cf032166ee1bad7d12ac3c3c292992bb01;
-  0200000000000000000000000000000000000000000000000000000000000000
-       384fca7c5554145250796aba74422059a6152117b9bbf50b492d8dcc4fcd9fa9
-       dc2c3521c82fa8613489e815af3bf6bff23a61a31e136870e7b88df6d2c9ef50;
-  0400000000000000000000000000000000000000000000000000000000000000
-       12390d4e80fbb7ee99c80a68175dcc167177486d618d1baa5009587cd2543496
-       7ca3a28cffaf1d2d71aefcacb467f7176bf23325406236a468f9a2b75ca67eba;
-  0800000000000000000000000000000000000000000000000000000000000000
-       8c43057345f8ee64b5e04daff7d9758b663e27d9249c68401e17650d38418597
-       75c3b729c8e8da036b60b63af24fc564a3a4ac1eb2e92fd59158474f744c5a12;
-  1000000000000000000000000000000000000000000000000000000000000000
-       2b7e0219d0d2dfff42597690df40e53c8bae17d0d363eb001636f91658fd4d78
-       ed444d40e243dce63b77c45a4eb89fc5a0af2bab390e32903c7ed80ebe3fd989;
-  2000000000000000000000000000000000000000000000000000000000000000
-       c0af2ffcdb963b3f836f09d07dd7529ca029baf32d683a030d8b70f64115319e
-       81adeaea6574660ebf126d45700aa212d7df72cfb15ac7320544f901c87b364a;
-  4000000000000000000000000000000000000000000000000000000000000000
-       bdab381ffe13374b4c0fb2befb836b2a5676f551d9879230574063a7da33f55e
-       b73c6979db28f0090352ead9194481458c53a75716e82eec0d392f80cd7f414d;
-  8000000000000000000000000000000000000000000000000000000000000000
-       059590c11ad59af788160a3dd52ba242f35e9d7c9ac2716732d45892fb7e311e
-       1cf8b9d052386a37bad7006fcf1a5ed0b2ca509fa9b408d164928465b7df55ec;
-  0001000000000000000000000000000000000000000000000000000000000000
-       2f59734e38211765d309b8885c0d7f12802adcfd236259e710b60f215b17e91f
-       b7543107d7a8d59fc58ccb5bf9cc9cd3b0aab40b936519018321e67ee4212f3b;
-  0002000000000000000000000000000000000000000000000000000000000000
-       b459777f2e4be5802ec40b675b180cb7362d58849b5a1002e9006d684803d1a1
-       263e0b651894b849ebcdda7de136f12c2b417864d0bab6d752676645aa44663c;
-  0004000000000000000000000000000000000000000000000000000000000000
-       dded78e34b5117415696866ab8277777298ba600ef8ebb0a833ada9f0fb14abb
-       048cfb659677a1f6021da5cbbe7c045a6630d62c12354ba889f16dfae298f0cc;
-  0008000000000000000000000000000000000000000000000000000000000000
-       23f9f9b2c9a37dbb2c46156eb1e369247bc9e3ab18b392d900933fdb2319dcb4
-       b9116aea9a465f603f0d0b5f2b432bbe2eb8b5b7150cd41c88df744d1d157458;
-  0010000000000000000000000000000000000000000000000000000000000000
-       00d9408d7012e74b3587b5549ee41a45150149b07a71b11b5a6787d0180405c1
-       efb7ea812e9772898305defb02e62520cb5518f11bc7d1cb72aecb2a230786e8;
-  0020000000000000000000000000000000000000000000000000000000000000
-       0e1acef35626a60c99bb971a72fbdb80d40adb9e1566e522f03d0d9781abb92b
-       39e66a48d565bc75e2e307de3555f1bb2161fab013186e827ef720b5e67af7e6;
-  0040000000000000000000000000000000000000000000000000000000000000
-       147cade7c9326104bf45afe6b8c180cd7a8a45ed9e1798846af473f241424325
-       c8b47d8c7fc71f2650dc9fcd2e76656486f7f2cf79d4fc3e5b0397bf19a268f0;
-  0080000000000000000000000000000000000000000000000000000000000000
-       e435935752dcf49c03afe77b217af4fe8bfe3b83be1f237e80b1c5396aa60635
-       ad3294a5729d4b56f5cbe417867b2895150207493091ca5b2da71661a837ea45;
-  0000010000000000000000000000000000000000000000000000000000000000
-       2b0962a7233ae8f0f0c6f82d96f1fb6788b57cea3e20b18d21c01fb20c523e45
-       e282636fae01bffda7e59095c3b46c85ee2df7e2f3f4eb5e9c423459dd085ae4;
-  0000020000000000000000000000000000000000000000000000000000000000
-       150ec1d69180c1f65fd412fabc62eeb80146a46fd5fd7a7035c887da5d712812
-       95aefd097ac6ca69d1dc282ae7ccda8409ef4ec0a4e8d7e052a52313c3d5fea2;
-  0000040000000000000000000000000000000000000000000000000000000000
-       f21b883c84743f00ae25aa937c88eeff2820c8b7ec16f485d811fd58f5758710
-       5ceab4fbe84572e441c6d31bab9c213a29aeda39b5369cd5a036f0d5d3052ed4;
-  0000080000000000000000000000000000000000000000000000000000000000
-       e3790ad0decf178ff259a5c7340f944c253551a0e2a0efeacfafe6cb49774d8a
-       93ce491989013119060c84df54e1ccf3627ce8149ff44100c08b903ec868dc29;
-  0000100000000000000000000000000000000000000000000000000000000000
-       3eecc58989f78b6969f687ee0aa2c1230af4bb0efd5e26008e798b802996b458
-       55fb0121a5c2f72d1c830f431ae990c24071ddd60fe7ed997d92f433aa53e66c;
-  0000200000000000000000000000000000000000000000000000000000000000
-       ccef63e7caef39a6ade4da89f2fa47f4132fd354b4d594dffcd40db73171b787
-       baf36d6cd4920d94301b649592ba1e990742357ea55191c40538a761fde817a2;
-  0000400000000000000000000000000000000000000000000000000000000000
-       d39bc7cd53aeafe63933d8bb7130a1d2fc85bf58bf76cda3683349a5257e5feb
-       4e8a84d2bc89a1b2ffd5fe2e8ad3c5315bbaa5be3e9688291fdea97b19ec425d;
-  0000800000000000000000000000000000000000000000000000000000000000
-       a3d929cdd10fa4b13adc1df77dcaaf9348cd8993305d3ade70ccec50d2747d88
-       ae241bb3dad4d6400c3d3ecf5587ff814f71708d9d85003b461ed4f714bc2830;
-  0000000100000000000000000000000000000000000000000000000000000000
-       641578d6f15bb8f26e1a4e96b798f7f7e1dd592ffcd472f4af3bb90292835e38
-       8b66ed19f74864e216e4c1962326876c3d015c84f368992a51a3a7c66809c8d5;
-  0000000200000000000000000000000000000000000000000000000000000000
-       81f3b791c83a0dc0da90a8e5b1460033240aafc65663b5ef8ae4b0988acc3070
-       4ba6a9d06282dd9854b5e75e3989a550a37c1a00c12199ea5c859f47408186b6;
-  0000000400000000000000000000000000000000000000000000000000000000
-       59359a60897c5d84c7c3a2cfc44408a9a07f3020d2b7c5f1eaf41fd08aa482c1
-       836e0c9e8c3a7974cc99bd938a7c9c596d21d1fc7e8674321b1faebb9aafe0e6;
-  0000000800000000000000000000000000000000000000000000000000000000
-       fd2541c2421b5a58f8e9c89f9bd93a3f214690c86a30505050809f0e17965ec5
-       52b5f31bec989a9c167fb3bda2d145ed912e656435e4c2720b109c4161ea6499;
-  0000001000000000000000000000000000000000000000000000000000000000
-       a7870f4f9859f4c90747cd5a3175576969893f21f80644a85ca361c64c2760e5
-       c025483295777b1b75c3f4c1311c1621d40ef55a8a74dd0f85afc16c33141731;
-  0000002000000000000000000000000000000000000000000000000000000000
-       e7ae0b42a64b89f72741ff01fa56ed16cb405d7de6af172da31d28b6624394e1
-       a3bbf26da16b92b30f5be3f1b5a4b82ca60fa12330f546f6dbe21692397e6007;
-  0000004000000000000000000000000000000000000000000000000000000000
-       bea4feb7093ed08d59b1a9e367ccd59c81ac315e4fa6bff4dcda083a54ce7713
-       e17743b422ba9726647323c9d863b28f672f0635965bdc5e99fd713a890fa807;
-  0000008000000000000000000000000000000000000000000000000000000000
-       bd7d0e194ab34c866664434679054a512ff4520c382a2c16164e3b92579986ea
-       2b901d39fe9d3ad0f151be728cc8bf052a5cad3fd622da0bce99df60f5d0b900;
-  0000000001000000000000000000000000000000000000000000000000000000
-       26221c4832d8daaa40a4cdf52027ad389342882b578d50690bebc93df5bfae86
-       906cbda011d3f989b85301d147e5f89c16e0d5f5236ee549f463d8e7c1230ab9;
-  0000000002000000000000000000000000000000000000000000000000000000
-       aaf7fd79a7ee0cf2622f61a7dde9ddd110cf585989f9fbcaba4bf8c87f97a6ca
-       9221202cf78d38d22b97d3634615cdd7a1b327d0cf2edaf7ba665e2ddc98ffb9;
-  0000000004000000000000000000000000000000000000000000000000000000
-       ea7e4e250134fd0a6d57d45877fc13e83bd8eae4bd096371ac85d09b634888b3
-       3295b4d323d829813a3c0bc074075c3e133979d02137237ddf6abaa52c3d6633;
-  0000000008000000000000000000000000000000000000000000000000000000
-       3944e76bdaec5b16c8c76c7e06452163f22ce79092bd9e3a024aa5c208eaa795
-       6f8a8a7b2dddfc1018cb4e0b7757f3e1444514c3ea056ce0cae81b8701de92f9;
-  0000000010000000000000000000000000000000000000000000000000000000
-       3b4c4ac914d85958a0b5e7b8876575573681f0b313cfc0fb7f444c9e7e268615
-       312e801156e12476a12b20be7468806e9f28bd00e3c0647ba9220be6167045fa;
-  0000000020000000000000000000000000000000000000000000000000000000
-       91bef844e50dfbc56fd6e2f3b7bdaa1276c316876dc81e1d6403ca7d91dd0e3c
-       e9dc7208167be2abed48d00beb3b9859b9e4eea2b54ae8c8bf78d59f5fdf6bd6;
-  0000000040000000000000000000000000000000000000000000000000000000
-       9e024081abac727a02f619c51ce63bed18745597dce3b48ede6f61f808bf9dc4
-       2c6eebd23f08b4e8a9ba12c04ffe281c6fd241a1bfffd7850bca3e8e9b258c1c;
-  0000000080000000000000000000000000000000000000000000000000000000
-       1659ebf81126d5ab0ebda35420c9be79e92a439b50660ba62dbcaa62ebbb6bce
-       30972cf1c7ff5ca04ad0636279a0a6e4c9fe9a41af9d3d357f286fc68ebb0a6a;
-  0000000000010000000000000000000000000000000000000000000000000000
-       114312df5056368e8facf69d0dafd7f99954ba6188579e70eca4daaf63a4bf8d
-       6ed87684e24e9e8c80e7a974280a4a7210b2fb50578cff2e87f3c4f86eec23b6;
-  0000000000020000000000000000000000000000000000000000000000000000
-       bb6e664338c2483b6619919cff1cbd4a133e9bd461184b040fdbf08711a53c0c
-       5a6a0f2f51d127d55e7659c4cfb59a4e17d329bc299ab38e18e3140c562596dc;
-  0000000000040000000000000000000000000000000000000000000000000000
-       a467e32c18c448d11324ef06f11efe402e7b8a9411ca83e52ae20a82eb5df7a6
-       84c2e9f00dcc6856f70ccc51f498d85679c79240f371937fd4179c5c45b0cf25;
-  0000000000080000000000000000000000000000000000000000000000000000
-       0eac2d63862bf03c7d9acbb84b3ec60624a40941764d1fa716d6e08f5039f114
-       dc89b1858f887d16f98b1f068e27f7d46dbb8a0df469541423d0c811298f00ef;
-  0000000000100000000000000000000000000000000000000000000000000000
-       97537e552910025fade2073196f52788773bbae3ce6c7b1fcc72b55ff7ef3f0b
-       49d9bb818972c65f846c31dd70412de0a193fdeacaf609dd401e929b23914e9a;
-  0000000000200000000000000000000000000000000000000000000000000000
-       9408c086b3246cdd588066e449a9be69377a74c14b1f00994ff2094af3747861
-       74bc32c2914794908ac3ef670a00f9dd28e0037add9eaacfe07da756042b050c;
-  0000000000400000000000000000000000000000000000000000000000000000
-       7ad5a463142244224dd5abd8342df7126e0156d92af07aa012d63b5f1b44fb6e
-       d82d65ada9a01bd4e9b3e79fe2d15a2075c392865b647e357099b3f1d61c92f1;
-  0000000000800000000000000000000000000000000000000000000000000000
-       6d65afe3a94c84045bfe3b6aa7b159c68a64464a71f4b5a25de424d4b8cf7d3b
-       b80da8204dbe46d527b120b4b025c01541f6d51bf962303cc276f8610558aeed;
-  0000000000000100000000000000000000000000000000000000000000000000
-       afaedc6195d899fd7a085f180ffcaa940345956b194d340a2deee29c0dd2d971
-       7b88861666b09d3dd874eee025910267da0de663f3762fba0d5183ac81b59a24;
-  0000000000000200000000000000000000000000000000000000000000000000
-       6ca33fb495f9b49ab2434c86bd50f1c68bf627fb423d5785d9a94557bb789a32
-       dda8002e8a2c6ae938a347121e2e6a191b11a47fe0f2609d8df6504eabadcd4c;
-  0000000000000400000000000000000000000000000000000000000000000000
-       048745f71e427f377631cf8b93d762ed69b23d5ce92cf88bbbd1c39d83c50962
-       9b467d9f35a61cad87273246229d0a666e7d37b4a3c3ee48e89f7316b59f9258;
-  0000000000000800000000000000000000000000000000000000000000000000
-       199409ed0f69f84c55ff5816d48f78d7b9ba691a2f4c9d41f38f20e01cab00fc
-       8168a685bce08ec00ab7e7fbc20dad4cf1a9af5ca3cc7fe72ab7a770bdac10da;
-  0000000000001000000000000000000000000000000000000000000000000000
-       130e28c699dce84779ddfaea0a45be76cbbf3fd14a9c71b50c9ced5eb2cf6edf
-       9d17f71aca5b6175d82e6a7bad34a8d21a4bc1bc404462807035c0c855033865;
-  0000000000002000000000000000000000000000000000000000000000000000
-       4a376dc814c679fb3fae93836a06bad1cd77db067f76ccfe60987559ed4b7cbc
-       26932158e76eaf55cfba5398b06d11ce6c88b078aaead0ddedf5e5b2505d5ed6;
-  0000000000004000000000000000000000000000000000000000000000000000
-       5a04e963f90bbd5bdb3f616f3d52f23dccbc4652fa313de5d1fbf70c829f6261
-       0c65c4f4d6adbfbeb91488a00e16e978a75dcdaa4ed9302148aead46d3f8e8a0;
-  0000000000008000000000000000000000000000000000000000000000000000
-       f4efa7971e1b1cbd41d9ccc7c84b46ca24781c118409fdc8d86ff3825c033e85
-       0393c2f10ddc2c93911de8c22b192dc78be826d84405beb42e5cce91e0234620;
-  0000000000000001000000000000000000000000000000000000000000000000
-       aab379abcb48184edc2400e7942943710acaf92763cb82368779535b2fc1f3b3
-       b29bde1e9b5ec2d359a8be97db7bcaa7bde9f2c3e88c6536b3a58d62bd7c1501;
-  0000000000000002000000000000000000000000000000000000000000000000
-       308e739a98aef258e547d0bcd9e204da0f2c7d983383650506e66e9dbd9b0857
-       9089ef809029209d37c2895b5f098e38d68ecaaef8c2d6fcc04d72928b921c59;
-  0000000000000004000000000000000000000000000000000000000000000000
-       1f7a8bef337a14785dee818be84bc9350fe1951a9a6272f797ea1f5e71a1b022
-       39148fbdfc0e0acf1f30123f11b67d72651b0d87b0e8541c9c232f07e2f93549;
-  0000000000000008000000000000000000000000000000000000000000000000
-       4f0c06166efdb1bece929d31c2981e96b4a5935f1c314e4ec0b10c0c761c8f7f
-       68cf4918507324eecf2cf991b5731b368a1c6bef35fd1f1c940929b1e45b1332;
-  0000000000000010000000000000000000000000000000000000000000000000
-       7714ca9fa1ea7c235585ade167931ea4435a61d1d983aad7dd5452b0a291befb
-       32f56751d799fe84ce7075cfe927fdb57bbe7e06eb9c88dfe4b14497a3d8d6d9;
-  0000000000000020000000000000000000000000000000000000000000000000
-       cb00fdf9a48bb507803079638584ba025d303d2b0cd5b81de2b644a61ac5d891
-       fd821a3c9d6d04bd07a28669046eb4a7764de97e056f0aed9356d06046365ccd;
-  0000000000000040000000000000000000000000000000000000000000000000
-       7af41ede49449402d065d70e9617be50ea74283c639f75a4dcd794950a2ad075
-       a9126f01a04a287ba196d148de77256dd86b41a4937fea307e19c40dbdbb253b;
-  0000000000000080000000000000000000000000000000000000000000000000
-       b5736b632b346a2210ecdeb95a0337903449fe2154ba97da8ac5213a5cca2453
-       a4a924f69ed450c80e1c090b327b75ae8c900bc0530bc580ad9096545e60dc4b;
-  0000000000000000010000000000000000000000000000000000000000000000
-       305cce4b3deadb80ca17a1f06bf1a8dcce2d1d66f2c25e7b2703062460f0b7e2
-       9071f39206f73eb7e1af21cbfdcc006a017521078254de35af24593f093ebae5;
-  0000000000000000020000000000000000000000000000000000000000000000
-       17fb9295d4f1e2c6717227dc01503b953dd54b327029b8577480a4e87d7ca1c0
-       cae92b888cc88e686a780206dcbd4d301e03ed5258fe0d8df01c8d8b9d6c63b2;
-  0000000000000000040000000000000000000000000000000000000000000000
-       27cb60b2e45fe4d7580ecab6446613dd2e9c773ba905a724458c51a2dcc1425b
-       a57c7f3c84048bac329e1e463f0c7226c51c9e6549d3379b78c89176ec316d08;
-  0000000000000000080000000000000000000000000000000000000000000000
-       893d82ceaf9116fd2b78f36c570da29b84d7fea87ee8f0f6678652879b8d50c6
-       f3f98c24d5c885055d318006e2cdff776412208b714d286cade4d3541686e281;
-  0000000000000000100000000000000000000000000000000000000000000000
-       f8dce549ef52a9912c8aa83f82c818dad9252b7f9711c828179329141e3de5d0
-       819acfd983335211dc97948e599fa664319a9c589ee11c181c5c0780d379d77d;
-  0000000000000000200000000000000000000000000000000000000000000000
-       2915e806c01c17a353729c6c3f943b9c34e9cfaeef6becae2935d471a34f0940
-       548123fe86f653b4b0a10e361369be8f0863b4b5f15c34d7ca2e48e9e25d1b5e;
-  0000000000000000400000000000000000000000000000000000000000000000
-       d9a23e63ca5828b15fe38ad7e48d44659263d27f0390af84066154585087e771
-       b26569bb88ab49ee647671a9cfd14764d60efa99e7aed11ee373af93ed061f22;
-  0000000000000000800000000000000000000000000000000000000000000000
-       1d24835d30eb9201019d8444bb92f2598bcb1ed42346acf53810e4aa8788ff73
-       8e0c78cbee01d9ee871f2457743ef0362c15d9c93d23a12626c4e80623903181;
-  0000000000000000000100000000000000000000000000000000000000000000
-       a0cecac4bfd7aa747230a7c795997255068dbbba5997633ead02ffb3454619e6
-       018a38a0e5ca7db27847e3eb2854a4d6a64c0a41b3c59cc3d38ea58ec25dc93b;
-  0000000000000000000200000000000000000000000000000000000000000000
-       f9a9da5740a32c62bcda5efca357870d8725965abc40aaf260a18fd4ac42aa43
-       1eca828dee97965f8e8d7c1b0e87125f8f9ac3b6bee8b0b730bf3afc905cd19a;
-  0000000000000000000400000000000000000000000000000000000000000000
-       4d2aa6eae1040cd338063d6cb66911fc026027db5a53b91b3612d11b2be3f710
-       c749d747ca70eb7bbe5a160bf61c1e1f573366a473943ccb60129e46ff757792;
-  0000000000000000000800000000000000000000000000000000000000000000
-       21b0debd7ab6d7149c058c9d69f466f9480b9ad20a59e807c9186496023f7b79
-       eb1556e90beab9b3b1c5f9e520de345877a2ec446f0976f76bba0e11fe056186;
-  0000000000000000001000000000000000000000000000000000000000000000
-       612a8d66984e3e664af0daeae9bd903e04f63a761123d7536639d027ced1d682
-       1577663f2b58aed2fa1b2eb87d1e86d8af977ff7439c52d4947a29f7f3ea2605;
-  0000000000000000002000000000000000000000000000000000000000000000
-       b502222789a36d5a9a245c0fff70ea43c2e96e5fb57fb81510aab99f80c35a32
-       0303b621ed6b340068159fdb857eb2a5479dfa6183604730b72d01233fd71586;
-  0000000000000000004000000000000000000000000000000000000000000000
-       3df5c158a338ceaff80de71a2918dcf210ea5001716256b445c82ac4691f1fc0
-       af811728f6e887608a5b6795b8ac6b07ab68ef95394effbf6d46b50418a77a46;
-  0000000000000000008000000000000000000000000000000000000000000000
-       39b25d1e214df0a0283bce92879f056beac64269f127b0494c5e8fd4ac4b6ac4
-       5e3e7c6d0dc7ade448def91c280287733a78bba5fc3f636f9d8a6552b0142b7d;
-  0000000000000000000001000000000000000000000000000000000000000000
-       00fadb701238f00fbb1d1096d3e451bed024b66aa9274760dab49ddac5c3946d
-       020e78dc0f6e465fe54cc7257f547f1b48e908bf6052d7e3a5f55b58cdd507aa;
-  0000000000000000000002000000000000000000000000000000000000000000
-       d1c21ccbcddba34b3862b0d3c0e11e309458ad69d5ba1d42fbf33f8d8a592eb7
-       8427323b69e874b89fd3c981244e6c1a98e9baafc9cd7699028b54d5a80c4bf7;
-  0000000000000000000004000000000000000000000000000000000000000000
-       e783e2f80223d3bac0e249c4af0fdd6f765199defa2831e1285aa7969cd57c63
-       44935fe4ef59a0979502daba5dfc7c16ec69c1af8af85a3fd8bebd486929ea5e;
-  0000000000000000000008000000000000000000000000000000000000000000
-       27bcfbd734964e7fc8a634b2ce3fa63ee453235af33b689fdcb47d6aaca6a6df
-       df37ee8f5ca3e21e7948163c9a189852f7df18b117e4743dbba2c770f670b8eb;
-  0000000000000000000010000000000000000000000000000000000000000000
-       a66846baae257774b4cdbf9ed5257c9c18c070836e35d580b95e2a7b961ff402
-       d77a334ad77df938ce6042c2c06c868c507b298c59010a47eafee4203c9f47f0;
-  0000000000000000000020000000000000000000000000000000000000000000
-       0dbac39c772bbe1c52105d00fa32d51a03191ed6707e175680397623e793e9bd
-       0efe80fdaff4975cdcbaf28286917ad218a6bfe685fc5bdf616a40e2171297ff;
-  0000000000000000000040000000000000000000000000000000000000000000
-       8db6613e226d37bb68c89e455efc591f7e2b7b7da543c3be7d9058105ccc2388
-       0d74d3b700d64545bf4a06f0625edf7d7e3a8828de3b6c95ca42e1e5b19a06fb;
-  0000000000000000000080000000000000000000000000000000000000000000
-       abb71c9c7f39df0dc16a00939f50759ab116eaf2024b7e690c0469fd9c6477a4
-       b2432584bf1f12c9f50b9f51db6ec5082cbfbaa85202d903fd3c790a7e8c3008;
-  0000000000000000000000010000000000000000000000000000000000000000
-       f0a0ee6776fc98821b1695e6b253eb7eb3055f779fade81bae006e98f6dfe53a
-       4e38aa14fe50a3ede3998e72a989dc77300dd5e216b4b41fd23dae7d59cbad7f;
-  0000000000000000000000020000000000000000000000000000000000000000
-       c24fb46f0f7d123468c9e4ec68fccc7eb4986e44c8110733d1268c124f238711
-       d0aa9dc510363f80f3bd100f4fd816faf90e32b941b8e5501a171edd01ea91d3;
-  0000000000000000000000040000000000000000000000000000000000000000
-       cbaee780343e98edb69d95e50fe41cadf820f8e7959bb0f2580a14014df68335
-       0b13c8fd89a314d72478401f4e39d5817a9a98103ab45a458f8d23b2ebd4353d;
-  0000000000000000000000080000000000000000000000000000000000000000
-       06b5fd3436cb561d100e3d1034d4c790a35e3e634fe76ccb028112818c581ddd
-       2238d8f8aade266f01cd8f189bb04ce9fb8c2f30b5290a6011f2ea392cb5d716;
-  0000000000000000000000100000000000000000000000000000000000000000
-       b0d0316c92cf2844091b87d25ebefb5a0dfe2d60782962b7f65cf974ffc5394d
-       7e6a4fdae611b25c6d62fae841a2a8b0dd5ed0f56ee0b652b2233624e9e55717;
-  0000000000000000000000200000000000000000000000000000000000000000
-       a0687fcebbfc5d0ffc70dfd89701eae4dcc0e0897a61f7d02f3a200e1fbc0195
-       52991b10dda46ae9a31210dd90e997745dd7a45d6782f621baec5e1b09c652ac;
-  0000000000000000000000400000000000000000000000000000000000000000
-       7885103c2ddbdb34f21679c908148b48affd3030f33135ae6aeab813d76e4c7d
-       32662258f351ed45638fbd08f4a9ece8cbf4259973336276ef51883445b067f5;
-  0000000000000000000000800000000000000000000000000000000000000000
-       1d166eb905ee23d8608ba8df50d9ec70a29423bd25cc87cdacd5d8b3df321535
-       587b6f652ee658e4ffa3a16b95d717bf692eddb0f85fea3498ed89e2debbd053;
-  0000000000000000000000000100000000000000000000000000000000000000
-       8470559686b1ce1f8297a3a2b32087cdcad147773001dd844fb4fc61bc0fe45f
-       29ed1711366d01a87565165de5cdd0c817ab620aae1573be16d28cd51cd0e8cd;
-  0000000000000000000000000200000000000000000000000000000000000000
-       45c7e02ac7f22af7a8fa1b6dba56ecba6be159a7a4537cc34d5970a0aab038c7
-       477d6fa3adbad6057928cbcba71d116fbadc96bec9ebcf5f1bdedd39e32d1cb0;
-  0000000000000000000000000400000000000000000000000000000000000000
-       162c6b51feb10bf69bcc8fe12859b447b03af9c63d12239f1ad5ac948f3763d7
-       643e17074976de5a5ce66320e5ec38b631016e2d3caabe52f0ba8e56a9d0badf;
-  0000000000000000000000000800000000000000000000000000000000000000
-       f9299e0e09e8e4d408da8f4dc9e15c11b8d8e4708ca5c73bfc8714cbe42b9457
-       b64579adcf37e3bdb652e15fd7221d9bb23a149b9d0cd1bb621aa60fbbea3374;
-  0000000000000000000000001000000000000000000000000000000000000000
-       700ee74a28732eedefb1926e5557a613e00ffc91cc3d9b18e2f51d89055b9eb9
-       d52db33d671e9c012ecc5f594b12fd563e5cf1807fd161a863080398b78bda13;
-  0000000000000000000000002000000000000000000000000000000000000000
-       e6e8a4eae096448cecf973ce287a7ef8e9fa41de4c3b05501654edb2c1271af2
-       1fc805e11047c0d487a61fc552569975636ab111c186231bbf05b32c95d2ff45;
-  0000000000000000000000004000000000000000000000000000000000000000
-       1c1de2c45285d57eed9cd013370e3b8a57d12fcd0050ed324d641ef797fa6d57
-       1fb31c871cb66f8b0d651001bc2924b413075cb398d6a03d77b298e6b28d8bc7;
-  0000000000000000000000008000000000000000000000000000000000000000
-       c2e9773c4f7fa499d72af9a0487d4b02aa43ef91c5902875fd2c85c022a7be79
-       7f4575691fcbe4ac4ae9ad4f8e49d403d1d41eea43fba36c671e6a826fd16442;
-  0000000000000000000000000001000000000000000000000000000000000000
-       0ee9c279b05d527706f721ac45b2b75c55cd9b1906ccdcfbd29aca32f69053b3
-       1d7ee6cedb4c2c169a5d0e511b62772e4b40c4bc8940aecafaf2e1e09b5e79a1;
-  0000000000000000000000000002000000000000000000000000000000000000
-       278dbffbcb601500a725942fb302ba2ab0c6d206db5d7878979d7b2ad8d4d199
-       6f74aeda2cc6ee5704d685bec0de4363cb79679200f0ed5530a36e516ea86d68;
-  0000000000000000000000000004000000000000000000000000000000000000
-       e8c8c0fa175ebd8380573e7932d219a3f116d14da69693f2995471d9be202d05
-       5e1c3a0b22708722d1611b66af966d1f6d9f8faa851ddb01830b97e2d9bf383a;
-  0000000000000000000000000008000000000000000000000000000000000000
-       283d859298c1e323a493a2e949ddd4c2ffa4a5da29669b348b5a72ed8c8eb1d2
-       272552fb9fe36123cbcb0e43db68b2233336f6a84c99ebd01080c0eb508fc7f3;
-  0000000000000000000000000010000000000000000000000000000000000000
-       79125cca9c3c680a61d21951a4cf0b7230b578ce2e80fe838b337fb7c36a77a3
-       2ab45fadf08ebbcc5121b076806d50927df6310214f73aafb0081633cf98299d;
-  0000000000000000000000000020000000000000000000000000000000000000
-       6769fa85ec1c637bde75471d0b22903895ecae1462912caf6a6bc6251a58258e
-       a65b3b54d75e58eb478cfd6032d291f5bd46a8c8c5765fbb2487283e46c26de7;
-  0000000000000000000000000040000000000000000000000000000000000000
-       4e30e6abd785654640eca58ef491e13378f8526c2af3f51c0043e687bcb1c168
-       cc48a52ff696f88d51559c46494cd51dc3291266046c085fd51e9f8baa1e1e5a;
-  0000000000000000000000000080000000000000000000000000000000000000
-       96a57e2149916713b979265d60743727bb6b7aa91634dc415b408338329e82cc
-       ea571b458893e10883a717f3776b808cfdd26d9bec4cc64e16a72448c2211b48;
-  0000000000000000000000000000010000000000000000000000000000000000
-       e8883a8ef799dc1b6d2fe5ddd18acd3ae58b24e98e1e812494f8a74f4ae372be
-       93fa5ae2d6d71da3fdeed466453b7ad9f4ac8ea3aeded25a15c4bbd040018fe4;
-  0000000000000000000000000000020000000000000000000000000000000000
-       fbafbe69b71d604c13e1cb82292190c18cfa9bf6145714aec7249a56ddee4ca9
-       6336a21084584fb303718743e6e96f479c7fe0ddd8956ecf703fad72221d64f8;
-  0000000000000000000000000000040000000000000000000000000000000000
-       db9b68d716130e6b173cccb08de59eafb3af28019e87c152dc3ff5d5088e3b58
-       bb3fe5aef0a82c6adb2f68c9bf43548a06e7fa503ca61b48a946cdaf37e8f24e;
-  0000000000000000000000000000080000000000000000000000000000000000
-       9f7bc36611372d91d4b4c0cccc840759285cd03b3e2e27afe204ae448d0f9286
-       dbd6da143b4cbec22deebb4d50290a42299669dacf03fe2a2307968143d4fb7b;
-  0000000000000000000000000000100000000000000000000000000000000000
-       78d8a2300ad94cfef66b3164c731377ddb2e4b275d4e701391953432347b9223
-       50f62201950be294408f88bdb661cc3296c6be60d3012075a801b5c0834ae350;
-  0000000000000000000000000000200000000000000000000000000000000000
-       12e33f7ddcb2f8d174625428a62b88949f125ef8ed08fdaa354599949ca0ae66
-       06ff56ab47bc89455cf58af988b568b2ecfc06e7df27cf710a25022d87557da7;
-  0000000000000000000000000000400000000000000000000000000000000000
-       56eded2b02168d3bbeacf0d9daa6af71edc952a831840440039c498f4e7f7ca4
-       704dee5d192940b0a69ab883c75151d8d6cd140362b2c1654041f43f2069f4fa;
-  0000000000000000000000000000800000000000000000000000000000000000
-       755d75672e5539950e3738c9f08391595fe8666fa3630d850bc54f51db1c85e6
-       9be04b998cbd1d657d9eb034eaba6870641da53e310eade9dee5013a8c053790;
-  0000000000000000000000000000000100000000000000000000000000000000
-       59a5be52f38efc387f5681e5efee14564bc0124d21a853433576752ffa429c9d
-       2c8e95bc932d31e629cf4c519bfbc19b1356e82b24e4b0a0a3f0e7bff87cdb9e;
-  0000000000000000000000000000000200000000000000000000000000000000
-       6a8e931278edcf28e271b3af14ef2a4c3a32187f2e99a9eed8f8bf5cc9caf92f
-       bec4947e08bdce74baaa30e8067010ea1a5f0a510f3ded81e1531f7c70a579b8;
-  0000000000000000000000000000000400000000000000000000000000000000
-       ce10996b404a63f524caa19cb2bb9ab0278718cd618687588deb24dd0acae4e5
-       abee46ec2bd7acb5a6b81e03cabd1cd4c5b27255c0c53245bd1fc2b82fdd37ce;
-  0000000000000000000000000000000800000000000000000000000000000000
-       322f564e6e45b4d7a556e3e0d673c24762e6aa9558221939a6e207af108ef047
-       045bdd23eddffdd2e5fe6035781a4c3f67eb5063ae2c35c4f167524c359ef09b;
-  0000000000000000000000000000001000000000000000000000000000000000
-       c38a5f9c6637d72c43bdf52c75f8a01a5c017202825ff09eaf27bb6a5de32c9c
-       a362cf96447d76f38c0ce895b2fa6bd21a02d6fcee561bba4bd20e224ce24bfb;
-  0000000000000000000000000000002000000000000000000000000000000000
-       71f79d68098b9e011bb7c9400ddb9e3493dfa52fae11dd9ad77430857a136c68
-       cbeba998096d1bf54c3f5202d5b06c38a8f81f7f9a729c030bc916b43544f325;
-  0000000000000000000000000000004000000000000000000000000000000000
-       a877f654b01488d3bbe0104bf788a18c250a453f2068bc81f2f096ef5731bfe2
-       9081748a46ae87a2524c0b27af4d4af310d5384ec8e8bfd6bdec56f7e4060ba2;
-  0000000000000000000000000000008000000000000000000000000000000000
-       8ae90f0c8d8ccd1268ac98f999bda54594e219ed8cec617c13cea31a606db6b2
-       1fc23a6581656dc0a72abf427d6374ba7d3aff387493204e1036caf860ad0f86;
-  0000000000000000000000000000000001000000000000000000000000000000
-       b6d4e59d418667855067491c8df18244c64b1bfd728a3625161e47d4a32712d7
-       1f3752a6044179cdbc6b05ba5cb21c894be977699e1401eef6412a0397fd1287;
-  0000000000000000000000000000000002000000000000000000000000000000
-       bdb69d9fc2ed427ecb6848b5c2f9687c3e873271e8a3261073a05ebc4f75e244
-       023140291efee7ea2d02dc4b54d5d4cddee02c88767c33b72d0e028dd97633fc;
-  0000000000000000000000000000000004000000000000000000000000000000
-       925ea1f098046aeb00899bec3d4f97ae64290279272a9dd8ce9d79b6837b3ad0
-       370a2405d17683bcd5baa70c29d57f49f9847641fbd6884173e2adc11995f203;
-  0000000000000000000000000000000008000000000000000000000000000000
-       1349f44857d80fd3a0405217a8248339f70d227635af2411dc6c4214a42c2e2a
-       f6fe27b251602fc9c9e870f5cb4b62c43e3e875c47b775fb8d9f546b52807e02;
-  0000000000000000000000000000000010000000000000000000000000000000
-       74699f36e9636c3206287bbe13384e18ced1120706175c0a65576ea86776c612
-       dbe9d11b3884457e03b84deb23858d704169d7582a300c8673a7f544435dc3d3;
-  0000000000000000000000000000000020000000000000000000000000000000
-       b792ed127f2ea24411d063cdc2617d702230f3fb9d03387e3d0700777d97a70a
-       fdb09f976a749a232305946db9f7bbdb2429fecd28e584d937997446740622af;
-  0000000000000000000000000000000040000000000000000000000000000000
-       dcd987801779a92f86d879abdf28b9cf66f7d0318f487be0ce27c63a27fb5200
-       caad8eec3c351be1e60e70dfdf98de671d2ca5d3fbc21fd440713f55df8c69fd;
-  0000000000000000000000000000000080000000000000000000000000000000
-       bf85c351d0e74eb5430e55479b50d0fd827578e982ebc8e338f32116ef570e46
-       f81b47ebc5d2887a45aa67d0b7d0fc8a07146f30b37f1a036ce9fc236f0d7d00;
-  0000000000000000000000000000000000010000000000000000000000000000
-       6c6291cc83e0314b06e19ac68fc170b93e84609fa80ae0349e86cdffefe6a193
-       67ef3467e8e0b571c5d110ea08133e0156e486310d05e07eb3a9417e4749a3d6;
-  0000000000000000000000000000000000020000000000000000000000000000
-       6b71719c717d62a10a688fe8f9563571195edc246f7e8006380a1bb14dc3b8fc
-       b8189e40e802d55d545112e6cab102254477c52f7536d019e06512c83742975b;
-  0000000000000000000000000000000000040000000000000000000000000000
-       4a2086948673804f8a97a07b16b36c31096cc0610e2d240bf1fa440fac400f33
-       395dc8ec9ead16a9cee85b07e7da6b1475f525234bc4edf65ece264e72838ebd;
-  0000000000000000000000000000000000080000000000000000000000000000
-       ca82c08abf42285892485b0d4e4f3a5f5877ef51e0a501e3fce14e4a8b7efd06
-       1271158ab7223bf43fe3f689e9307aefe4233b46e864cac13d234544c0af18a7;
-  0000000000000000000000000000000000100000000000000000000000000000
-       e7a2d99bec6b59b14475e6a1a6fc28d5394ea5a8557882ae6e9e67d34b18c949
-       0ee608417c070fd9f04a73510cfb900f3773f010e074dfe70a333df6aff09d48;
-  0000000000000000000000000000000000200000000000000000000000000000
-       9ac8e222a63951e1b7c2e16012ac90436dcbbace3f0318d2aee3e0bef53d5950
-       bdd3b18e99e5fcae550234719e903e0ac7f83fde47ddb396b65eb8af1373d30a;
-  0000000000000000000000000000000000400000000000000000000000000000
-       7e48facca309371083f21cbc0bc25ed09d09e03f996f4dc023f54ef7217ded8d
-       8dcd9aef8e729df03810d6273f1f6125a35c797606030d653eab344320297a30;
-  0000000000000000000000000000000000800000000000000000000000000000
-       d1c032fab24525d378aed7266f49d5f7d03de6001ea531676f845fbd8578fa80
-       16c95820117c70da72373689b04c1e6f494b3f4c165d6aad39b5ba8bc8d5cf6c;
-  0000000000000000000000000000000000000100000000000000000000000000
-       904091d32d5265cea53274748694757fad2e1c22566b1908f4f9d35538e89b06
-       ad3b3c6e85d8afc210b3a22d1fa0c51076bd79c6641ed3481d1533ec7fe6b7b5;
-  0000000000000000000000000000000000000200000000000000000000000000
-       ca0521aec053c66badec9f3c89d952e0eb69afa9ea41080397071da57161b35a
-       6641463de2ee581e2748259471425e94d9fb9d79093e0cd0a19b96ec510d5de5;
-  0000000000000000000000000000000000000400000000000000000000000000
-       19fd13377a56d0aa15ac4e62b99eae76dde81f2ffecdc24504051da4b9652c76
-       3f1d6001995209adb152a06b48eec5025b3f755d8e2a01e4bd3b0b536f3ba333;
-  0000000000000000000000000000000000000800000000000000000000000000
-       37a40e8139fbcdba67429f72b56509f5af081173ec4bd18cb6e9e3a826bc83c0
-       35196621c8a1dacc251ebe5bed3f5763659303b6e54a10dca061c2f5517cc417;
-  0000000000000000000000000000000000001000000000000000000000000000
-       ab0439f8eb335ac24b73994949e1eebf0614eef32a7bdb497960791f8db18e82
-       36f36ee2dc7d53583645d308735dbd7a2c88f0a3f407e8bacc2a9737c63fd51e;
-  0000000000000000000000000000000000002000000000000000000000000000
-       104c04190e24ae90c2f87caf2cc314680a748cbbaef9298320dad36f660a243a
-       3cd0909e1251efd2c9b631abfb0ddffc751ad3c77ac022ac47dca42682159b14;
-  0000000000000000000000000000000000004000000000000000000000000000
-       337cf2622058e3b65d83499b927011407fd627c5e77d9e657fe1bb6a224478c0
-       a3f95204f3120e370abfe9115eb31f39f5db8a92aad8c525b903581069001acb;
-  0000000000000000000000000000000000008000000000000000000000000000
-       2b5bd6ccf9c26f31a167e7027426aae9865c0dfb14fb3dc6daeabeae5c1c8b69
-       5eab14eec32e833ad8cce68fe95d44c7cfdc997e0f5a8386817c3b679dd9771b;
-  0000000000000000000000000000000000000001000000000000000000000000
-       dc2541bdba0e4d40e8cb4fafc93d0a8a60a5530b3fe27b95f6a88be92f6f36c2
-       d25f0a8d66d9fed6790560b86b0d08677c65f72e090426c88cb18cd756965e7d;
-  0000000000000000000000000000000000000002000000000000000000000000
-       b545e6c9514c66196058a3c3a7289be91d5c5e21da87797e3373bf6e24f5d590
-       9c64e96615ada88bca95405fce376291d5ca05e23356b0ecb94983c1610d07a7;
-  0000000000000000000000000000000000000004000000000000000000000000
-       f34e2420486825bbe7a24b40c50a84c28c80e2f298c30f4f78bf27c0ed56afb1
-       cfdeec976acd4bf09bfa70ad96558e3198c1a4203784ceb5af21657c3a54c3df;
-  0000000000000000000000000000000000000008000000000000000000000000
-       ab041c33802ab7dca2d6d59863404616f94bf48ac727aed1a85f3b5aa4c6250a
-       1797812dff75debcdf59a7b1714d3db08f4b4830801cccd3ac74d37527d3d784;
-  0000000000000000000000000000000000000010000000000000000000000000
-       f943ca8fee60cc92aee5b0301fa25b129993817b9a1c75cf8528fecbb7563821
-       8c00b2753f4f23b48423836c28977481cb073f3c3693ea03d33db3b5b31f6ed1;
-  0000000000000000000000000000000000000020000000000000000000000000
-       b1fbd227465ccfa0e934080e315073d99faa55be4fd38e93d210db20f4cbcaf5
-       c4e7c620deedc6244fbbcd829105ada603825e64a044ed864c5ee465be50141d;
-  0000000000000000000000000000000000000040000000000000000000000000
-       a9341c312dd5c879b6b7305557080ac059eb7d48da0d044ce4c53d46ee682a77
-       efc45cb2d180e546a8e60450da7859233b04ecb5a21a11d517a6752fe5b56ba9;
-  0000000000000000000000000000000000000080000000000000000000000000
-       fc0d7e148270279e6a8a0bb30102642a7f1481fc2617341674319a8496b2483a
-       6b32c7813bfa42592b2558adf16918b1c56686e70b2fd6cf4d9c57ef4079ef4f;
-  0000000000000000000000000000000000000000010000000000000000000000
-       55702bc90512de5e92dc5106f128997ac822b95d89ea8e924bc329174da48ee8
-       e009220efb6aab4487ead7b8ef0b82843d16684ef57de55b2fbc2e981aae1c6e;
-  0000000000000000000000000000000000000000020000000000000000000000
-       3be68900844eed0843ad0b2ef6d0b683a3112ba3b8a35a52f40007104586ab85
-       b10b32f47822dac5b5db3d240bb2d8f05a408c2c20439563bd97e96a1f4ab84b;
-  0000000000000000000000000000000000000000040000000000000000000000
-       5c451eaa6c8e993e837371b4f231e93e2ae7407b930f07bd87ef5ba134d9f6fc
-       ff89a9dc0895b13c20a7af15ae8e860d74f9dce289c1f43bdb35025d7086490b;
-  0000000000000000000000000000000000000000080000000000000000000000
-       a8ce9c065e6c91129d0643c04cf73150df86bf2f5a1a947a1fbecb1aca90d26a
-       a1301654d68563bfb7f2110e5d9ef96635d24ba8b56320cd070b25b6be28623e;
-  0000000000000000000000000000000000000000100000000000000000000000
-       2aa48f6411a0ba5040eb83e2a2b20f14e93554953c8873e8879f355678badb0d
-       dbb22baa33905a9740d5ff475ed0517107f413690af9b95f717e4cdbace8405d;
-  0000000000000000000000000000000000000000200000000000000000000000
-       7965be05896fcc9b9dc334f9c2a43f813d5c248963e1317f798c4f9fc5f8e7fd
-       34125fee23f020155f248b4cc5dd4370ed530ca871be46fd93e7a006edfea7b8;
-  0000000000000000000000000000000000000000400000000000000000000000
-       1541c80be3e5c8e221540f92b631f360c5b0370223263e771b1b92d4fb73a453
-       a2bff0682b9d6e3eaf8d183efaec91667808f9d026ff20c1d65f7e6e2a4676a3;
-  0000000000000000000000000000000000000000800000000000000000000000
-       f283204496fe825836a3aa8377f4f2db5cfb14b41c6b9f5f53e565c852db6598
-       6dc375d702992c7e30ed6cd188fb27fd7a3c4e4c7fb2856f67244fe3c7f8b760;
-  0000000000000000000000000000000000000000000100000000000000000000
-       e234f1c1d7ccd4ce1ace58850dc28d2abc7e2dfd171877710704282a12bab9a0
-       8d51c164dc8ae5ec5bdfcc25fb1ee9a6d9cefa47abdb748143ec18b91c72fcad;
-  0000000000000000000000000000000000000000000200000000000000000000
-       4cb4412669289a6250900c8713f56cb57f5b962137b828b46a1b1dcb41bbbca0
-       2b1ea7bd9d0cd83de33ccc5415ba625c6c4d2bb211e5464c39b2bf9325aa446c;
-  0000000000000000000000000000000000000000000400000000000000000000
-       a6c52188edc54c3e88d4424ac378f85b690e1b6b46e552f4c855aa9e4e0b2c36
-       75e118baa53204bb91b283c80d3baf3e70c4cc204f25aa71ae6ebe0655010d9c;
-  0000000000000000000000000000000000000000000800000000000000000000
-       58449e523e08c99109ca6570b8bba4011a7cfb2203257e8b93d3131bb16219aa
-       b1f0f1f930fbe5566ae5ab46e7a6981ae14d51dedc62a4b1786c032d16cfb829;
-  0000000000000000000000000000000000000000001000000000000000000000
-       edcf56d94c31b0d201066b648da08d43e0ece64dfefd3a542852fb3f945ab216
-       122c6c4b6b019b18cb0e925d191f3599d9eee57eb7a6506fe1fac494f037327d;
-  0000000000000000000000000000000000000000002000000000000000000000
-       b178ca20a3bb67c4f34a816d1c4636cea7642cfa004cde16efe32a6c613c9eef
-       45912f3f092fd64dfaba7cd7abf0534fa7f8571d8d01949d5204223bba068166;
-  0000000000000000000000000000000000000000004000000000000000000000
-       d925287721da5f6117f951cddf410018ee8cd147f97305ba2f0aac26c1859312
-       f3878c9586205c2f92b27656df61bd94b00a01b86202079ca1926968a1b52c08;
-  0000000000000000000000000000000000000000008000000000000000000000
-       359f4ea466e0f07d6a0de61e99ff4e2007cc5dd90c59a1e4d0d5b46f03b5aa99
-       33816ce4fbfc40b806bd2bad025b9477b051dd55d2fddfe007287e66e1814afa;
-  0000000000000000000000000000000000000000000001000000000000000000
-       ae77a98a68d9462b74bdd4f7d124746e1c5765406cf1b9ef547d52f00b45d4d7
-       2d58c0e474a33f1957bddf17a850871ea050580f4f8d48380261189a271d4c01;
-  0000000000000000000000000000000000000000000002000000000000000000
-       0bf35dc3d5fdea4d60f14bd0759906c1625c44cbb754f4087645b551355844ee
-       acae4ab9b17e275e54968b1ef6a2422f3bb97eefa6b0007bce18e8162a8bfa50;
-  0000000000000000000000000000000000000000000004000000000000000000
-       4ed4cd19fedd9fce8b979f698f2f167909331a7ab8dffbb7fcb56a2c5afc1428
-       ddb8a8c89b629b0711f72b3328b22727e1c5965dce9b3843667e1b6492962416;
-  0000000000000000000000000000000000000000000008000000000000000000
-       6af47d0713e05fb4a2974110b0860baedd2597820ff5c600f9049d7d425ee100
-       2d0cf3e4db588dea89cabb0b0ad58acc1d0b83388fb6af32b367e21f7f14f41e;
-  0000000000000000000000000000000000000000000010000000000000000000
-       96a82f4432529492f6a8a17fcf155ef8a6bf11bb73a77d3dd8bf3e986ca3dbbd
-       d8fd1163036b81998a1e5e3ed3d787fe270f05b8095f0cb853a0b934b4016dbb;
-  0000000000000000000000000000000000000000000020000000000000000000
-       23e6baa1a8a67122a9855247124ec59a1dca649570c6a1a4fb089a76c81a6014
-       3583e5c1cc5e397b2b5864960caf7aa66ebe6467d4065e67008fa737c053a7a5;
-  0000000000000000000000000000000000000000000040000000000000000000
-       86118f4629dad8a873b1649b9c039fcd4dd8ba032b9f6819115c3af0d1b6595b
-       071740e3ca823edfdabfabc0dc10924348fbb023b6ddb344d4f42e9572de3e08;
-  0000000000000000000000000000000000000000000080000000000000000000
-       982d814b00c91517c08aa4c87087069c01c6a045cbcd3d7f26a4a1c6cc97d2b6
-       3d20e5791747d98b9ea3d2026594b8ce462c5ba6e62a1c361cf5fba5ca0f1d11;
-  0000000000000000000000000000000000000000000000010000000000000000
-       2dfb74f1332f7930be2ea7a1732ce3d56fb12d916d2796d1e1fba64f2e66ac20
-       4be4d901963da689112e1fc54d852a70c0f60b501b915cdc141fab94b43d0106;
-  0000000000000000000000000000000000000000000000020000000000000000
-       fe6cc968de80a13cb0e7a1fd4eeac2a1d1ddca48c53e2bd5f4230c4f51d1f4c0
-       8af8f0ce706f35fd089f8d8aa07d07d9a7015d4ecdc7e9548cd0f3992073aaa2;
-  0000000000000000000000000000000000000000000000040000000000000000
-       f8f84d21d697ff9862c223ed476722077f5865800c34d36a6560a0a975d90413
-       fb9e5f6b3e8f8e78f715226d808f98c389883d65e2c53aab4ab018fa941d28eb;
-  0000000000000000000000000000000000000000000000080000000000000000
-       b934372f8ad78e178eebbeba49db0466073fc8e29e78a232bbfffd59b9d72d65
-       95d2ff2f7e24735bcde0d3766c83a128104bbc8ac1944f3efbc3e174517d08ff;
-  0000000000000000000000000000000000000000000000100000000000000000
-       ef204271d3588603c5f43eacfde91e3306723c7f074fe2088ab95fcbb45eb6be
-       c14741e0daa9c84264b877e8a503ae78c6c7b2329f0bff9476ba2dad653ecf12;
-  0000000000000000000000000000000000000000000000200000000000000000
-       0515648007e5e5e8e37e9056a4f23232a07083fce238e2dd3853b3ab1734ea70
-       0f4f15ea46ccda314f7891ca7d0091a6215d341788a3acb732a93a14da0a0d18;
-  0000000000000000000000000000000000000000000000400000000000000000
-       67b53797fd010597b38fd94cf1686270f0992e6c6666e9ca4a105a61d510d9bd
-       28069c2ded2405e0ef95abeab23f36bd752b15119e4fa69b43d731624ce5178d;
-  0000000000000000000000000000000000000000000000800000000000000000
-       7a47769ca3509d8811e6c23c3d5adf38da76e8d481fa13afdf60813a8b59792b
-       eae7e513eb59d8ba54087cb66c7c00edfda452731b93f34698b477d234dd7faf;
-  0000000000000000000000000000000000000000000000000100000000000000
-       8dc1de423e5ae630989be11bcd4be30d3f62efe9d38fc26396b123810df2768f
-       f0c952d27a250c3f4d914d537fd04a8cdc6c057af35ba4410bab0ea89e6d7d54;
-  0000000000000000000000000000000000000000000000000200000000000000
-       48571b94f3f991ca6e992e60358fa4b3255999983d5f9b9b1268e61f3db3bde8
-       b889b82fb5f1e8d78eafee9275c889e23c7a2555d78487b9cc4f701d7d1f00e1;
-  0000000000000000000000000000000000000000000000000400000000000000
-       1e41bd7ebac2a488c52acd8a99b336469d9fc35c98d9cfff269a6b8e9377309b
-       11ec65507e8b6393c7f12023f8ce9f0985ff92b8a3ef9c78cb1f2883694878f3;
-  0000000000000000000000000000000000000000000000000800000000000000
-       b6eab1e877e719a42d935523dc8c904b35a30e3b02148944a6e46459e35c5f40
-       04da7f3786ccae4982a8e75aa55549a89708915b1c6f19613632cde018ff5269;
-  0000000000000000000000000000000000000000000000001000000000000000
-       925e5596d9660e28a1b6c1a9e33fc7beea001f1cdbaee6c6fa7938d66e4f2e7b
-       0473cfc0964e7b3f9b505789fefa176f735b564678ce0b89223c073175e685ff;
-  0000000000000000000000000000000000000000000000002000000000000000
-       ce02c8aab250c3d07e84fd4a8475c1cffd00a20b1f215df5feb3e93e287f6c46
-       7b9d26b50cdd0eb37a1c6cb01807017bb70760c2892b114a944b183e80392739;
-  0000000000000000000000000000000000000000000000004000000000000000
-       acab6f16ba40e29b015d0289c82f03f54baec63d322c1a70792094d229b2b17e
-       41e4f7bad8838666d798ed77a6d4129a4a97b7740611539d9a21064ec837072c;
-  0000000000000000000000000000000000000000000000008000000000000000
-       beaa65cfea3e972077a48ec8d99421a5cd6e234e2ede51c080d0d99ed5fdbc5c
-       b83d02d1b94ace563287cac9ef6b175a7cb60c84343976f97105c2d78aa1e683;
-  0000000000000000000000000000000000000000000000000001000000000000
-       9165a45f535f24531daaa5fed2621c91755e15ba9f85e57d848172c9846327b2
-       f496291c25156383b867c10bcf82466c138555bfd5fecfc9c01dc2e65aa43929;
-  0000000000000000000000000000000000000000000000000002000000000000
-       c17d79761600447acdaae4ec9398c1743a432e58752cc8082e45d842b43f0e66
-       e5ea6f466307a34d36ab278aaa884ec07a494ea17216eb405790320d8fa2fed4;
-  0000000000000000000000000000000000000000000000000004000000000000
-       d6868ca98e49ab85e60f5411b17d644b613f6101107c70f514b12d1b3e4133f5
-       1305d1b51ced2666839b11eed182da902e864a74e35e06e9d4137996ef50dba8;
-  0000000000000000000000000000000000000000000000000008000000000000
-       e35c518d1abdec18c07645ea79f07071c2967d1045ee804694dc5d43e96610ac
-       1908ede77ee9510ee12f3d3f516002356731e164a9ea4f63171550ee2ee90552;
-  0000000000000000000000000000000000000000000000000010000000000000
-       06eb73063502eda7c71d450742a79c9c7fa03f682efae6cb0b65f44e95fe4a74
-       31c5681726dfa952c0c2285aa56cab4eb107095337c624ea81ad277664b2a264;
-  0000000000000000000000000000000000000000000000000020000000000000
-       4e7269b1930a4415947740c02e07f5a648071b525ef02c169ed6464d8b27bb8d
-       6abc498904e605e1b5e28ea8628b55c7e5e029623f77cd462691d3a7fc278674;
-  0000000000000000000000000000000000000000000000000040000000000000
-       826a3104a79da8022158b60aa55187dbd1fb2bced56c4690560cc83fda92e492
-       d3fb967cae7452b867c88adc8a11e5b5b95989bdde92639ed95305ced7cfdc60;
-  0000000000000000000000000000000000000000000000000080000000000000
-       0b92142c4fdbc92e7156469124819ba920edc66c427430c017d6bb294085ac19
-       6f327c30503e8cd50af536583f510545511e8d70da1cc285bcce2d46f92d2b2a;
-  0000000000000000000000000000000000000000000000000000010000000000
-       c7b17c0628edb82798962e54e097372b3860bbc02b0cad3f87dfc81b3d25d93b
-       4ea78d7501f8fb379e7725fa971af497596116c475b4796ccbc7e10d1a2a21d9;
-  0000000000000000000000000000000000000000000000000000020000000000
-       f9286bb83357f5ba5e9fdd2c7944ca1d75d9d2375710a2894d282c85a1f94b7b
-       5293a298473e7efcde744290da3a51cb3c798cfdb1fc9a4c7aaf4f7b3008297b;
-  0000000000000000000000000000000000000000000000000000040000000000
-       64be8cf1fb77d638f68b6fd80b57f21adbc420b5e99d4227ac0ae6d82adb0f71
-       d9de4fa7124fdab3c5473ed50c41b53fe346ced59941d71a8191a8f6ade215d8;
-  0000000000000000000000000000000000000000000000000000080000000000
-       16e491e25d6f79d9a33018ae66f6a78a87e4ca6d4b225f26a70acf757eef8754
-       86fde1681d4c26c001abbc93e967065f985b607441d05683f971b05b7c5e556b;
-  0000000000000000000000000000000000000000000000000000100000000000
-       a499e877391ec0170d41b8e03af321fedbda237b675123018902af35d59acf9e
-       78e154919e5bceb7b20a4c6f94aec7014a4e03cba4fc668ed69644f20de31abe;
-  0000000000000000000000000000000000000000000000000000200000000000
-       8b058ddb6648ef4583b44e5332784c6872c52589fb2d1e7b107ff5ee64b59e6d
-       4a022b951253940108f3a795bc4f39ae3baa2cf656d3e2d520138853fba56a93;
-  0000000000000000000000000000000000000000000000000000400000000000
-       eb530cdefc2656bdae8734131668a5833ae26f131b2c8fb50999da0106591fcb
-       739475c5772aeede0aa39c19c120c20aca995eb3e7a90d4048b0a4e1efd7cd29;
-  0000000000000000000000000000000000000000000000000000800000000000
-       2eb1c5426bbd82ff9526b482d3dd71bf52af1cfb1fa7f68acc457b08429d0ddd
-       5ac3c96e0623ff40dc8dff86f1d4ddfb90312c1443243c89231b16efa79f0bdc;
-  0000000000000000000000000000000000000000000000000000000100000000
-       3b9b9773dac3e4954d4168945e276ca5c9e1008aff8be8034d0856868bcb7dca
-       65a19215b091c569c84da60a64b874091906c6c23fd975487d877e91a64e43c3;
-  0000000000000000000000000000000000000000000000000000000200000000
-       d09fb1b66db34ab57f57a2fc98945fd2b610ca739452954d3dc32e6d11b1cd08
-       7cc4d6e0660454281087046c740ae0cf3ade676dfbd2fa46d4d0f5ca1cf4fa5c;
-  0000000000000000000000000000000000000000000000000000000400000000
-       7d02fbc809080c5e21522ce33eae610a47f7c059433bbac3ac30c5637d8aa3ae
-       ee4b97a5049fbac0137eb688cd389bf104afb2ef754a30dc4e72e60267efbb0c;
-  0000000000000000000000000000000000000000000000000000000800000000
-       97e7a1f5b2c9d77294a3131298479c8240e33800f4e95b76462d3f0f9899abee
-       669f11d848792de5621440aa51b628b667f9fa28e6c43070215ca6b52da59760;
-  0000000000000000000000000000000000000000000000000000001000000000
-       92d91bc3b83ee7c8512c0dd87efad9952a41f38aaf3ff737b1bf232484b3ced6
-       6e417430040e5bdce9e6f4df84e09323e254e2c75b7ab7916dc5fc84f0dc7f2e;
-  0000000000000000000000000000000000000000000000000000002000000000
-       a201b9a8fe87c900acc1937c5fe32563f4f52ded3f9f7c484cad259adfd81a59
-       ce267b0cf6d5e06d6a980db8fbf00a6609f8e91ac1e0dd705b53428c8a69baa9;
-  0000000000000000000000000000000000000000000000000000004000000000
-       d84985bd7e97e581e034d5f7b27d96bb78719cbff19e37abf66395654714ea20
-       919b92ccce355fdb77913cddd41e0fcc3d7b468dc8f6406782953388dbf82927;
-  0000000000000000000000000000000000000000000000000000008000000000
-       506c7f563c6254e18d5b50e8c294a97a3634322709189dc2e6af7c1166cc846b
-       ec220577d30e07409eb06ab77477eb8a4d4357443fb64d739692458e82e5fd0e;
-  0000000000000000000000000000000000000000000000000000000001000000
-       671217631c0840c9c9828f78a714f1bb67b864d646efe8de3c432ac20d55f133
-       39064a3dee432a3632fe78fab64d637c933bad5d44e2118a1247dd10c51adb8d;
-  0000000000000000000000000000000000000000000000000000000002000000
-       c5e41aa3e2d7a37c82e7a41ef0db3c81fe9b9d2948dc5c1d7b8bd862142c5603
-       0eefaadfe8682f723c8b407d90da3dce9612965c770987ed1a0f1ea66745103c;
-  0000000000000000000000000000000000000000000000000000000004000000
-       762a716822e4798d1493f81f7daccbba1becbd4fbc4a478ee30e4aeaadb0b0c2
-       21e19764af6c956a9ca8c31f3344cb0fa30195bd868b524d8d8de89090944918;
-  0000000000000000000000000000000000000000000000000000000008000000
-       221e93fbe263c8a6c92a87c6492e7d17fee75a585cea8f311cd79f595b42495d
-       58dcbe9cc752afd2aa2008bc9f95c2e70d38fea1d5c3b87c1e6f29f9c0bc4373;
-  0000000000000000000000000000000000000000000000000000000010000000
-       72b80c94d6ff97f97e9f76e139c037a3fee9a53e48f0e57266e24761592cfbfd
-       1eb856387f0f0208987725a13f796cfe420ea65fd338fc594fee3667325add23;
-  0000000000000000000000000000000000000000000000000000000020000000
-       d147908d20daf77c962b21d4997f7b84fdbed2cb07cb06e0e59032641b9dcb3d
-       5fac3709cbc5b5f3ef21ae198d9234feb1a82ea4957684891877e2ef2b3c0332;
-  0000000000000000000000000000000000000000000000000000000040000000
-       7374263f1b8c9d4d21f52f1ec6f971d9dc7268a8af79ac1c1c535dc4dff5cbf8
-       241175e0afa2ed5af43ed388a818f128e6d99731dff319644fdb983951d8e765;
-  0000000000000000000000000000000000000000000000000000000080000000
-       752aeaa1cdbb7d024fe734668cd9f63d61ff4b335e7f42d0f545ab81b9b234fc
-       4ab2772f9d610f0d618828a10dcbf20ce04d4f78f71565a8379680ea225801ac;
-  0000000000000000000000000000000000000000000000000000000000010000
-       7ec933c4574148f27c412e2a4289def909ad7cefc54387dd5f0dd2c832488790
-       99e2a4d15571d1098f1defc1d29b07c40af145ebb2edf81258d5afccb97919d6;
-  0000000000000000000000000000000000000000000000000000000000020000
-       954bd7a24edf58f58ebe343632e606fe97936b2500658ff9b11ad67617d221b0
-       f63398643b341b0a948cf22f5e9fdeeb8fd4fe21a3d946cee2f365e75537fe1b;
-  0000000000000000000000000000000000000000000000000000000000040000
-       e65323be34b117fad1cd194caaa254c7ec53fd96b65430e5703ef4697c4596e9
-       dad3ec2e51bc681c018f9ebf6d137999d6234dd84958737bb438c3232d377187;
-  0000000000000000000000000000000000000000000000000000000000080000
-       4b4306c5d55af9bf63dcf7c7c20268ef10b372b59ac10695d2b83277ded2b85a
-       da842a5af1d93e0f945101c202771981b4bb7645d9a59bf0939cf7b35cf1de41;
-  0000000000000000000000000000000000000000000000000000000000100000
-       20b0a0a6c9fd63ee745798c9248c988b1aaa9dc976f783254711c57f755728e8
-       83bc5c2254747422499230ac0abdd29de42b8896a9abf47cae6811a5e7986325;
-  0000000000000000000000000000000000000000000000000000000000200000
-       92c046c878b2f54671c4287237e200388bc1b03807c0e961b6e8ad336d6b0dc3
-       517c911a62e8c951bd0bebdca4940a49bd0d34eca5d7fd42f53b63a674588ad7;
-  0000000000000000000000000000000000000000000000000000000000400000
-       07faa395104ee08dbe87821fe9f4bc657a0a026de98a1b7eafecdd0a0cd90950
-       b8dcfe3057cff32a8346fdda5cde697a0f5daa99073a12602a14fc2c098e8d37;
-  0000000000000000000000000000000000000000000000000000000000800000
-       7b66faef189ff1c27797957691d2a5393a51cc46d1fb35bbbdd9c18c5d6be3b0
-       30d0516447f18c0140c56a2d3839f19713b2777507afd01bcd3e2b5f3bf565a9;
-  0000000000000000000000000000000000000000000000000000000000000100
-       4a7db25fe6b7f7195642b302df9ae60721be3bc0a0c03c0bfc02774f0770672f
-       5e9e9a73d8482a46bed4f5a3d111f5128d7ce25b459cefa8dee41e8a20530cb0;
-  0000000000000000000000000000000000000000000000000000000000000200
-       a3666ad211b46b616702ba5460e2153563ce71527ca411720095408409c1c1eb
-       9b5b488a37a2639e60077e50b3cfc23e0ca6b15303ac57d6a861d27bce87f4a6;
-  0000000000000000000000000000000000000000000000000000000000000400
-       5621077387c09f1b7de44f33ee44726fb24d4f13faeb59888c94d6867c7b4989
-       0e01ed6bc6527eaff1dbce5ce7a23df23e6369f51c250ca01e757c7ea6d2b3de;
-  0000000000000000000000000000000000000000000000000000000000000800
-       6ac275dfd387f63219d26d8f2bef9e73e17c026ae17707ba80ccf24899a9db69
-       63d189cbd05260d003546c599da6d7b574fa0037104cf6300f9f5f5edd6eef02;
-  0000000000000000000000000000000000000000000000000000000000001000
-       d9f2fe1ca70220a4471cb888f5ce568012b30c31c485977f5bb3e0310195b5a8
-       e8a1128025fa4a2431858de3c7253371b487b2e49bfc477e9b5d6734e2d17d34;
-  0000000000000000000000000000000000000000000000000000000000002000
-       a3ab3112e4d31f85ebc84e7e43015c687276a54a96b77b462d2e1ec71b88fdae
-       cb586bb26463168f35f52a962e040278ea2e476ad53a6161599ebda329c46070;
-  0000000000000000000000000000000000000000000000000000000000004000
-       93bd82cdc5d4b50b83eb98b2ef0735c9d95f7aa82e857a76b033b13467eefd14
-       9b3955c74930f1448504dc3e1486e9f861d25f437dd8c2db6d67ca70b4a83014;
-  0000000000000000000000000000000000000000000000000000000000008000
-       9a47b3563a9a7ac67a73109c79dd36c0a4445dff6b0677ca76e30cbdbca7ba07
-       4063046b6cd73e682fce54e3ced24880627ff6ab50a9b9de367300ef07e9b9d3;
-  0000000000000000000000000000000000000000000000000000000000000001
-       1e21dcd5b4cb8628bca386ab818e8b64b693a784e38c1bfa01b82c9d95846083
-       30af87491adddc2f86988318c2e7ce9f4f4d19e84eef873ce0732599a097f3f5;
-  0000000000000000000000000000000000000000000000000000000000000002
-       f9aab3d341f85f5fd8cdee460a5667595483f277b0f79f7b6df89fdd35a134f5
-       16f23b237ea5c03cd5ff1304890453a8311c456a2935a65c73c99e3fc12bfb3b;
-  0000000000000000000000000000000000000000000000000000000000000004
-       935d4b978db6e8f84dad228410ff15093f40ed89e2a2f8d1cb8410643b74a039
-       f01d8a43f5ee23843f8df421f468bd2c052677b2a993256225f34966000ab693;
-  0000000000000000000000000000000000000000000000000000000000000008
-       fffaf07ed7971e764123fe4e7aa181de2b0b0ab8704ffd9b82ee49495dc1f920
-       8c3bbed3d1a15e2e5d203e7d964b9b481d42e945b28fab114435df28aea6b023;
-  0000000000000000000000000000000000000000000000000000000000000010
-       6e6d8318c270135985a84e3a2541053eb8b58fad367fdb2e81dbe723572421c4
-       aab06f5557fb72c450d68ec0b706c97d8e7e260f70db34e3ecd28ba5473c9268;
-  0000000000000000000000000000000000000000000000000000000000000020
-       e8d4277d5557864cf02d3f4cfdf4a998f82777e9fc4dfe06d856091634634141
-       6f6aaf2b2ea7ee54ba5e4c28de990437e17f685194c76160875acbb35bdf4d93;
-  0000000000000000000000000000000000000000000000000000000000000040
-       6e32a77e600cea713325d09408312bae15cd75d28d2c04a5f604990e65be3d89
-       de71f5f1814b9a73098ea50c4d3605bb764387f317ee2f08b90b88ada605c105;
-  0000000000000000000000000000000000000000000000000000000000000080
-       92128b45f2af927df41f3b200a872673a744956e2c58b0099f243b7911c50436
-       ce408d59a184170a267df8713a787464af6d75f5f46b8b64ddac88daabb50ecd;
-}
diff --git a/tests/rmd128 b/tests/rmd128
deleted file mode 100644 (file)
index c82b25d..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-# Test vectors for RIPEMD-160
-#
-# $Id: rmd128,v 1.3 2004/03/21 22:44:36 mdw Exp $
-
-# --- Basic hash function ---
-#
-# Taken from the authors' web pages.
-
-rmd128 {
-  ""                   cdf26213a150dc3ecb610f18f6b38b46;
-  "a"                  86be7afa339d0fc7cfc785e72f578d33;
-  "abc"                        c14a12199c66e4ba84636b0f69144c77;
-  "message digest"     9e327b3d6e523062afc1132d7df9d1b8;
-  "abcdefghijklmnopqrstuvwxyz"
-                       fd2aa607f71dc8f510714922b371834e;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-                       a1aa0689d0fafa2ddc22e88b49133a06;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-                       d1e959eb179c911faea4624c60c5c702;
-}
-
-rmd128-rep {
-  "1234567890" 8 3f45ef194732c2dbb2c4a2c769795fa3;
-  "a" 1000000 4a7f5723f954eba1216c9d8f6320431f;
-}
-
-# --- HMAC mode ---
-
-rmd128-hmac {
-  # --- Test vectors from RFC2286 ---
-
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       fbf61f9492aa4bbf81c172e84e0734db;
-
-  "what do ya want for nothing?"
-       4a656665
-       875f828862b6b334b427c55f9f7ff09b;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       09f0b2846d2f543da363cbec8d62a38d;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       bdbbd7cf03e44b5aa60af815be4d2294;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       e79808f24b25fd031c155f0d551d9a3a;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       dc732928de98104a1f59d373c150acbb;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       5c6bec96793e16d40690c237635f30c5;
-
-  # --- Test vectors from the RIPEMD160 home page ---
-
-  ""
-       00112233445566778899aabbccddeeff
-       ad9db2c1e22af9ab5ca9dbe5a86f67dc;
-  "a"
-       00112233445566778899aabbccddeeff
-       3bf448c762de00bcfa0310b11c0bde4c;
-  "abc"
-       00112233445566778899aabbccddeeff
-       f34ec0945f02b70b8603f89e1ce4c78c;
-  "message digest"
-       00112233445566778899aabbccddeeff
-       e8503a8aec2289d82aa0d8d445a06bdd;
-  "abcdefghijklmnopqrstuvwxyz"
-       00112233445566778899aabbccddeeff
-       ee880b735ce3126065de1699cc136199;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       00112233445566778899aabbccddeeff
-       794daf2e3bdeea2538638a5ced154434;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       00112233445566778899aabbccddeeff
-       3a06eef165b23625247800be23e232b6;
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
-       00112233445566778899aabbccddeeff
-       9a4f0159c0952da43a8d466d46b0af58;
-
-  ""
-       0123456789abcdeffedcba9876543210
-       8931eeee56a6b257fd1ab5418183d826;
-  "a"
-       0123456789abcdeffedcba9876543210
-       dbbcf169ea7419d5ba7bd8eb3673ff2d;
-  "abc"
-       0123456789abcdeffedcba9876543210
-       2c4cd07d3162d6a0e338004d6b6fbc9a;
-  "message digest"
-       0123456789abcdeffedcba9876543210
-       75bfb25888f4bb77c77ae83ad0817447;
-  "abcdefghijklmnopqrstuvwxyz"
-       0123456789abcdeffedcba9876543210
-       b1b5dc0fcb7258758855dd1840fcdce4;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       0123456789abcdeffedcba9876543210
-       670d0f7a697b18f1a8ab7d2a2a00dbc1;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       0123456789abcdeffedcba9876543210
-       54e315fdb34a61c0475392e5c7852998;
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
-       0123456789abcdeffedcba9876543210
-       ad04354d8aa2a623e72e3594ee3535c0;
-}
diff --git a/tests/rmd160 b/tests/rmd160
deleted file mode 100644 (file)
index 1bd3a77..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-# Test vectors for RIPEMD-160
-#
-# $Id: rmd160,v 1.4 2004/03/21 22:44:36 mdw Exp $
-
-# --- Basic hash function ---
-#
-# Taken from http://wwww.esat.kuleuven.ac.be/~bosselae/ripemd160.html
-
-rmd160 {
-  ""                   9c1185a5c5e9fc54612808977ee8f548b2258d31;
-  "a"                  0bdc9d2d256b3ee9daae347be6f4dc835a467ffe;
-  "abc"                        8eb208f7e05d987a9b044a8e98c6b087f15a0bfc;
-  "message digest"     5d0689ef49d2fae572b881b123a85ffa21595f36;
-  "abcdefghijklmnopqrstuvwxyz"
-                       f71c27109c692c1b56bbdceb5b9d2865b3708dbc;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-                       12a053384a9c0c88e405a06c27dcf49ada62eb2b;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-                       b0e20b6e3116640286ed3a87a5713079b21f5189;
-}
-
-rmd160-rep {
-  "1234567890" 8 9b752e45573d4b39f4dbd3323cab82bf63326bfb;
-  "a" 1000000 52783243c1697bdbe16d37f97f68f08325dc1528;
-}
-
-# --- HMAC mode ---
-
-rmd160-hmac {
-  # --- Test vectors from RFC2286 ---
-
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668;
-
-  "what do ya want for nothing?"
-       4a656665
-       dda6c0213a485a9e24f4742064a7f033b43c4069;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       b0b105360de759960ab4f35298e116e295d8e7c1;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       7619693978f91d90539ae786500ff3d8e0518e39;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       6466ca07ac5eac29e1bd523e5ada7605b791fd8b;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       69ea60798d71616cce5fd0871e23754cd75d5a0a;
-
-  # --- From http://wwww.esat.kuleuven.ac.be/~bosselae/ripemd160.html ---
-
-  ""
-       00112233445566778899aabbccddeeff01234567
-       cf387677bfda8483e63b57e06c3b5ecd8b7fc055;
-  "a"
-       00112233445566778899aabbccddeeff01234567
-       0d351d71b78e36dbb7391c810a0d2b6240ddbafc;
-  "abc"
-       00112233445566778899aabbccddeeff01234567
-       f7ef288cb1bbcc6160d76507e0a3bbf712fb67d6;
-  "message digest"
-       00112233445566778899aabbccddeeff01234567
-       f83662cc8d339c227e600fcd636c57d2571b1c34;
-  "abcdefghijklmnopqrstuvwxyz"
-       00112233445566778899aabbccddeeff01234567
-       843d1c4eb880ac8ac0c9c95696507957d0155ddb;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       00112233445566778899aabbccddeeff01234567
-       60f5ef198a2dd5745545c1f0c47aa3fb5776f881;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       00112233445566778899aabbccddeeff01234567
-       e49c136a9e5627e0681b808a3b97e6a6e661ae79;
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
-       00112233445566778899aabbccddeeff01234567
-       31be3cc98cee37b79b0619e3e1c2be4f1aa56e6c;
-
-  ""
-       0123456789abcdeffedcba987654321000112233
-       fe69a66c7423eea9c8fa2eff8d9dafb4f17a62f5;
-  "a"
-       0123456789abcdeffedcba987654321000112233
-       85743e899bc82dbfa36faaa7a25b7cfd372432cd;
-  "abc"
-       0123456789abcdeffedcba987654321000112233
-       6e4afd501fa6b4a1823ca3b10bd9aa0ba97ba182;
-  "message digest"
-       0123456789abcdeffedcba987654321000112233
-       2e066e624badb76a184c8f90fba053330e650e92;
-  "abcdefghijklmnopqrstuvwxyz"
-       0123456789abcdeffedcba987654321000112233
-       07e942aa4e3cd7c04dedc1d46e2e8cc4c741b3d9;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       0123456789abcdeffedcba987654321000112233
-       b6582318ddcfb67a53a67d676b8ad869aded629a;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       0123456789abcdeffedcba987654321000112233
-       f1be3ee877703140d34f97ea1ab3a07c141333e2;
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
-       0123456789abcdeffedcba987654321000112233
-       85f164703e61a63131be7e45958e0794123904f9;
-}
diff --git a/tests/rmd256 b/tests/rmd256
deleted file mode 100644 (file)
index bc4d976..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-# Test vectors for RIPEMD-256
-#
-# $Id: rmd256,v 1.2 2000/07/15 10:03:13 mdw Exp $
-
-# --- Basic hash function ---
-#
-# Taken from the authors' web pages.
-
-rmd256 {
-  ""
-       02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d;
-  "a"
-       f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925;
-  "abc"
-       afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65;
-  "message digest"
-       87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e;
-  "abcdefghijklmnopqrstuvwxyz"
-       649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8;
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
-       06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd;
-}
-
-# --- HMAC mode ---
-#
-# I couldn't find any official test vectors.  These are therefore generated
-# using the Catacomb implementation.
-
-rmd256-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       c1829c0d5a203bbf6e874a721d55ffec22456f3a0987e30a4861a40cad5dc9e7;
-
-  "what do ya want for nothing?"
-       4a656665
-       932d3e799272765675dd63c33f8d2815ea38181494f43271dd52fde91392619f;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       a30051679681f54ad62088438a308c3dd38cc0eb2d352fbdcfb2811abf9c1e29;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       d55d1a9b2082105103d8331581d9522d17b4cce92e95f0f4654ce8da187ffbbb;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       cc8e435de509ef9a974cecb40cdecf55c8e6a22d5458e74cb7b0a306453ad67d;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       821543a295eccf093af9b461f630d7c49206fb2158e5ac89e73a02cf089528ed;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       ca26edc0129a781f1224cc6c9f655052f120edb5842bcfcf4b8d0f8b8be551bd;
-}
diff --git a/tests/rmd320 b/tests/rmd320
deleted file mode 100644 (file)
index 82bbc4a..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-# Test vectors for RIPEMD-320
-#
-# $Id: rmd320,v 1.2 2000/07/15 10:03:13 mdw Exp $
-
-# --- Basic hash function ---
-#
-# Taken from the authors' web pages.
-
-rmd320 {
-  ""
-       22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8;
-  "a"
-       ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d;
-  "abc"
-       de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d;
-  "message digest"
-       3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197;
-  "abcdefghijklmnopqrstuvwxyz"
-       cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4;
-  "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
-       557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42;
-}
-
-# --- HMAC mode ---
-#
-# I couldn't find any official test vectors.  These are therefore generated
-# using the Catacomb implementation.
-
-rmd320-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       03ec929cb94837c2acd709d03f4a26c3e38c7cec4fe2f5caff3b64e168321c8591b1d3ffeb87b9f4;
-
-  "what do ya want for nothing?"
-       4a656665
-       e440b00b6326e4f7dad3a6591e8189e9708fc17e3cab306fc67efaf70947aad2ea89e28f79d03bd3;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       8c7ee84fb76703386f01f088cbe0ed9a694d6e0c9bfbe1c7785f56cafc5908db2e16afcb0721edae;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       714f482ff865edbbcbfb344948ce3c8b9d2308650f2f0ed2111a6983509c967416e092e9f6b307d0;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       f0b1c83e3cec672db53c259746de4d13841e01dd6266c360fda76f3197ac47582c5e9b59d7a8a7b9;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       a61c1123c1a23ffdd9af5fb28b62b95f989876ac322452f5e4f4470c25182ef4816aaec7f0377167;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       5e5d0fe86d7f8ff85108bbf75cf25dd99e8029237b93ff0d93fb779264a103082cc62ad8914feed3;
-}
diff --git a/tests/rsa b/tests/rsa
deleted file mode 100644 (file)
index 9534d73..0000000
--- a/tests/rsa
+++ /dev/null
@@ -1,393 +0,0 @@
-# $Id$
-#
-# Test vectors for the completely mad RSA infrastructure tests
-
-p1sig-pad {
-  # nbits msg rc result eparam
-  256 "616263" 0
-    0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263
-    "cc22cc";
-  129 "616263" 0 0x0001ffffffffffffffff00cc22cc616263 "cc22cc";
-  128 "616263" -1 0 "cc22cc";
-}
-
-p1sig-priv {
-  # n e d msg rc result eparam
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001
-    0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9
-    "616263" 0
-    0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26
-    "cc22cc";
-
-  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
-    0x10001
-    0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81
-    "a9993e364706816aba3e25717850c26c9cd0d89d" 0
-    0x0f642606b7aaf99ff4bb5853c51e31a02c58d8c1c33f3c584d4edc58b08a16d5dc8064b6e198edcc4dc06666171a113619d7da16dfd96cebfdb5cc5050af6fab3d9f2ca8b8d6ece1d513fabc98a11fe37892fcf0827ea2e792427a69b3523504f46c55ed8af9a1c59687ca73c4baad7235a1a3faedec14f95ddfa8d0554739a8
-     "3021300906052b0e03021a05000414";
-}
-
-p1vrf-pad {
-  # nbits sig msg rc result eparam
-  256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263
-    "" 3 "616263" "cc22cc";
-  256 0x0101ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263
-    "" -1 "" "cc22cc";
-  256 0x0002ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616263
-    "" -1 "" "cc22cc";
-  256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff01cc22cc616263
-    "" -1 "" "cc22cc";
-  256 0x0001ffffffffffffffff00cc22ccffffffffffffffffffffff00cc22cc616263
-    "" 18 "ffffffffffffffffffffff00cc22cc616263" "cc22cc";
-  256 0x0001ffffffffffffff00cc22ccffffffffffffffffffffffff00cc22cc616263
-    "" -1 "" "cc22cc";
-  256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc21cc616263
-    "" -1 "" "cc22cc";
-  256 0x0001ffffffffffffffffffffffffffffffffffffffffffffff00cc22cc616262
-    "" 3 "616262" "cc22cc";
-  129 0x0001ffffffffffffffff00cc22cc616263 "" 3 "616263" "cc22cc";
-  128 0x0001ffffffffffffff00cc22cc616263 "" -1 "" "cc22cc";
-}
-
-p1vrf-pub {
-  # n e sig msg rc result eparam
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001
-    0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26
-    "" 3 "616263" "cc22cc";
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001
-    0xc484642d0e4dc4a4424d22410456dbdd9275b5c157d6974a66bee9aa02501c26
-    "616263" 0 "" "cc22cc";
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001
-    0x27654c24f4ffefffc3bef7be8ae469db3069407702391eeb551ce9544621b63a
-    "" 18 "ffffffffffffffffffffff00cc22cc616263" "cc22cc";
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001
-    0xd980f3047ab74bc4e7bb99eeb17fcc657f50ee26146b7f2a9f982ef2f44cba
-    "" -1 "" "cc22cc";
-
-  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
-    0x10001
-    0x0f642606b7aaf99ff4bb5853c51e31a02c58d8c1c33f3c584d4edc58b08a16d5dc8064b6e198edcc4dc06666171a113619d7da16dfd96cebfdb5cc5050af6fab3d9f2ca8b8d6ece1d513fabc98a11fe37892fcf0827ea2e792427a69b3523504f46c55ed8af9a1c59687ca73c4baad7235a1a3faedec14f95ddfa8d0554739a8
-    "" 20 "a9993e364706816aba3e25717850c26c9cd0d89d"
-     "3021300906052b0e03021a05000414";
-}
-
-p1enc-pad {
-  # nbits msg rc ct eparam
-  256 "616263" 0
-    0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263 "";
-  105 "616263" 0
-    0x0002efbd98524ad6419b00616263 "";
-  104 "616263" -1 0 "";
-}
-
-p1enc-pub {
-  # n e msg rc ct eparam
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001 "616263" 0
-    0x8f20a0fc778b7c55567f41c344d39bfcdaca04fd475f2290dc05c236585a68ca "";
-
-  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
-    0x10001
-    "616263"
-    0
-    0xaf91f5abf4766348eaaff1e8e5561b10bc1e3b15b6dff221869389a70d371d649b6cf78c5444f5d03a9feac12d5741cbc340e09d112063b1486568fca7c59b4c90604f0b6243eccc18901afa9001fc5f669108ebc75d6713e28d4a081723184332d4fb2ca391e3247a76c85323e66352d60c0a6ce8240af6f0583058820b1e32
-    "";
-}
-
-p1dec-pad {
-  # nbits msg rc pt eparam
-  256 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263
-    3 "616263" "";
-  105 0x0002efbd98524ad6419b00616263
-    3 "616263" "";
-  104 0x0002efbd98524ad64100616263
-    -1 "" "";
-  256 0x0002efbdfc524ad6419b00537a59b42a4662918436d6e0e4804b6b1000616263
-    21 "537a59b42a4662918436d6e0e4804b6b1000616263" "";
-  256 0x0002efbdfc524ad6419b00537a59b42a4662918436d6e0e4804b6b1000616263
-    3 "616263" "537a59b42a4662918436d6e0e4804b6b1000";
-  256 0x0102efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263
-    -1 "" "";
-  256 0x0001efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263
-    -1 "" "";
-  256 0x0002efbdfc524ad6419b65537a59b42a4662918436d6e0e4804b6b1000616263
-    3 "616263" "";
-  256 0x0002efbdfc524ad6410065537a59b42a4662918436d6e0e4804b6b1000616263
-    -1 "" "";
-}
-
-p1dec-priv {
-  # p e d msg rc pt eparam
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001
-    0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9
-    0x8f20a0fc778b7c55567f41c344d39bfcdaca04fd475f2290dc05c236585a68ca
-    3 "616263" "";
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001
-    0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9
-    0x19d6408010f0c2722b44cd4d5e006b6ffaa634aa225d727fa37c7c6ec29c5155
-    21 "537a59b42a4662918436d6e0e4804b6b1000616263" "";
-  0xccbd3b508e1ac2ed16f0f85adfec8d17ad525018307e613e0ee3aa4652b7ceb3
-    0x10001
-    0x1fd9da85ec2d8ea09abe8f2c7804916853ac1f05189b657af9b294f73c515bf9~
-    0x952aa4893cd2620e4942f449529ea2f7105b9d67e041a676259fb986bc507b7d
-    -1 "" "";
-
-  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
-    0x10001
-    0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81
-    0xaf91f5abf4766348eaaff1e8e5561b10bc1e3b15b6dff221869389a70d371d649b6cf78c5444f5d03a9feac12d5741cbc340e09d112063b1486568fca7c59b4c90604f0b6243eccc18901afa9001fc5f669108ebc75d6713e28d4a081723184332d4fb2ca391e3247a76c85323e66352d60c0a6ce8240af6f0583058820b1e32
-    3 "616263" "";
-}
-
-oaepenc-pad {
-  # nbits msg rc ct mgf hash eparam
-  1024 "616263" 0
-    0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffed
-    sha-mgf sha "";
-}
-
-oaepdec-pad {
-  # nbits msg rc pt mgf hash eparam
-  1024
-    0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffed
-    3 "616263" sha-mgf sha "";
-  1024
-    0x151709bd895ba510b5b3de3293c6de93adbb20cb065dcfbe3b2ca60aa39e458b30d14406eba05f0e479ddff40f554aba11da533c6d98df0321164c986807e8019c6918896817f37700a46c7fd71741a7692fcbd443952b67c32b838a576332b3bc1bab002fe3c941e9150d08b539908ef7f1901ac1246065c8520ac1beffec
-    -1 "" sha-mgf sha "";
-}
-
-oaepenc-pub {
-  # n e msg rc ct mgf hash eparam
-  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
-    0x10001
-    "616263"
-    0
-    0xa5c94083e56aeff3490a4abd63251b332a26cca0e521815af5d2915b2422fbc7e672c8e67c3dea8c355e0b999a1f8acc905cc4437a6ddc5a7d6f54489436bd24922f83d75629d2cb92a7963d010727ef8981c3c01971962f454e42d54996e74617022d7513505fef7b1f7d5dbdeccc4673594d01f943236e4439b3175c3f801b
-    sha-mgf sha "";
-}
-
-oaepdec-priv {
-  # n e d msg rc pt mgf hash eparam
-  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
-    0x10001
-    0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81
-    0x6ae9901c7c40104b38e10097bd42212afd437867ee4c72e7e81d7486b8721aeab493be40e3bd4335bef05c76bba1a2e30795e76fe04517d5f8fa87d16756002b061674594cb85c32b96c3a690e135d64923bd7551c45b6b89ebb89941377ce02d5c801feb33c20ebacf8dd6d6bd44d4f29bc2ff4dca35db52da545ef97733955
-    3 "616263" sha-mgf sha "";
-  0xb6dd0145ada7547bba5db3a35d34e612a8d73e93c33c720f4e4506428cacc6861b2143ed3a0683394fd94cfab8ab66a024161e9c9c1848d50627b3ac46de6d1b1d73ae7b5540b3df65c53aed9d4bdf1f86c8ddacfaf608823bb3d307d89d4c8bb11b5198f9851a519538787cd054ced98734daa2f7f2dc5b51c8c02ea8c362ff
-    0x10001
-    0xbee578ae84da6a17c0369191b97bbfb33b0f7904488c9185e8efa5d953820abd7515051461beeabea9dcefbfcd8921598c528b2272d1e7367b7676db222091443944672d439fe4cc75f4f9f0594a0b19a8c634fc7f88d0f16e08ec9a95f1f0c3c03ad467a2d7db37428c145cd26b8796264de2f2209a3c09f54fa51de689b81
-    0x6ae9901c7c40104b38e10097bd42212afd437867ee4c72e7e81d7486b8721aeab493be40e3bd4335bef05c76bba1a2e30795e76fe04517d5f8fa87d16756002b061674594cb85c32b96c3a690e135d64923bd7551c45b6b89ebb89941377ce02d5c801feb33c20ebacf8dd6d6bd44d4f29bc2ff4dca35db52da545ef97733954
-    -1 "" sha-mgf sha "";
-}
-
-psssig-pad {
-  # nbits msg rc result mgf hash saltsz
-  256 "a9993e364706816aba3e25717850c26c9cd0d89d" 0
-    0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
-    sha-mgf sha 10;
-  256 "a9993e364706816aba3e25717850c26c9cd0d89d" -1
-    0 sha-mgf sha 20;
-  273 "a9993e364706816aba3e25717850c26c9cd0d89d" 0
-    0xb5c91e4c0c00aaaffba7d581011366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
-    sha-mgf sha 10;
-
-  1024 "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0
-    0x2d22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc
-    sha-mgf sha 20;
-  1025 "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0
-    0xad22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc
-    sha-mgf sha 20;
-  1024 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-  1025 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-  1026 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-  1027 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-  1028 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0x559bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-  1029 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-  1030 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-  1031 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0x2d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-  1032 "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0
-    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    sha256-mgf sha256 32;
-
-  2048 "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" 0
-    0x106373ce481fe7e268a5a66f8b281e17719e23e1fa5f9d6bdfb2da5451a3fe7afab07969d8acdb904c723830280f78124717e87edf05a58626e191281b9c82edeceb02d1fc8dfab7d3e941ef3a13ea27ea51609e47dd727a784f66dc189fb8527093060ee5f982f7072e3f8a5fac4edcadd9ff107d6c8a99e9b52680a046b6f984c323afbb194e94bf2ab014804e791af59b254c164ef24af7c726b314a127febc4d026c700cbe08076d4e63be94581f6b353adbd3c754864d314f0039b3c7cae177c8be11a426358d523a1f0c97a0626aa9d565751229d488d96e168e7305cdc3d256401e6b865c246d686f0d8a673603038c464a60753dcd2b0f2a552514bc
-    sha256-mgf sha256 32;
-}
-
-pssvrf-pad {
-  # nbits sig msg rc result mgf hash saltsz
-  256
-    0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
-    "a9993e364706816aba3e25717850c26c9cd0d89d" 0 "" sha-mgf sha 10;
-  256
-    0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
-    "a9993e364706816aba3e25717850c26c9cd0d89e" -1 "" sha-mgf sha 10;
-  256
-    0x3426a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bd
-    "a9993e364706816aba3e25717850c26c9cd0d89d" -1 "" sha-mgf sha 10;
-  256
-    0x3526a2a3e34a2ea4b6831d1366f0477cf42d9b98fddf692f3d14f9b8a168e4bc
-    "a9993e364706816aba3e25717850c26c9cd0d89d" -1 "" sha-mgf sha 10;
-
-  1024
-    0x2d22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc
-    "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 ""
-    sha-mgf sha 20;
-  1025
-    0xad22499324a1428e11201e9103ba63a5be9812e104b789a128214c05e767ceae82a51ce2f13cf907183dfa3b5bfe998be503d6c99cecb32e2b488028ece05e0caf479c254a5cd823bb5ad529a0152dab4dcdd4746718e8720f6b7a46b1056d9a0bc6ce95c99ce914886ff80c3a3c5abcc4b4a4346e77722de7b318c1750e3abc
-    "fda74fa48306a43dda32e18d95e2b3b1e3edc172" 0 ""
-    sha-mgf sha 20;
-  1024
-    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-  1025
-    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fdd4987e9f2d57a3ae237d126d87c53f50db3641f9cab66739970843fe9182ff6ebcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-  1026
-    0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-  1027
-    0x159bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-  1028
-    0x559bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-  1029
-    0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-  1030
-    0xd59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-  1031
-    0x2d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-  1032
-    0x6d59bc4a479db6990a56909b9077e87f29473f88203c830c1ef6f160cd48e537a178992e98663de4fe2c5c31bbe49764484a46bdc1f5bd243f010c698614fc3acac3cd35cb3474dd4b3b4e6a5b53742823f319fcb203f2b7739ce25d3073af94bcb4b0a690ede55ffe88ceb8c946766fa4fb3343f0c15bfb1d1ee07212c49dd5bc
-    "9a741f76c050657815eadefc360e8cd191edd49f66ecbdedd048a364d8ef5e86" 0 ""
-    sha256-mgf sha256 32;
-
-  768
-    0x3314e642649adf696651f34108408fab0e770a617a3f7d44d981add5ca88841dc57d531bb885075f150b93e96f6e7580e18b98e1ece12826bbfe4d92dec1bc05c2e95ea362e08dd4cbf162b4abff6a9ed26b822d986ec32bdd698d162262abbc
-    "2923be84e16cd6ae529049f1f1bbe9ebb3a6db3c" 0 ""
-    sha-mgf sha 20;
-  1024
-    0x29d14565cf1ad3966ad25ff10aa825c2adeb31cc431a9a388ee53afef2ea2bc3c40b54523fd6bec5d7eabbea2b969e25d1bd62086834ccc48f256d876a4065214ac4343dfba87091563921299adee851e9d0dfba8db14ae6972cc8ce569f32c01db77d291279a82c30220faa16d83b1740cb535aa7f594905d7c91122f67ffbc
-    "1cdbae32209a50ee407836fd124932f69e7d49dc" 0 ""
-    sha-mgf sha 20;
-  768
-    0x1de4193d961d4c2f5737656c910d9d5262b09d463a0b8c7c426f92f91ea8db83be870d68ab125af488bef0596b15fb2416b2836c08bc6af31ee3c215c817c9c17ee84d813dc712676c86d4c41e69074eb1646fdc80c8a59e4bad819af27104bc
-    "b2eac9cc53bf67d6bf14d67e2ddc8e6683ef574961ff698f61cdd11e9d9c1672" 0 ""
-    sha256-mgf sha256 32;
-  1024
-    0xb9317ad66af4a49e3d2e987c340e776ed3b7496d311813fd6374e743fd5156630453541fc82733b4c0fd44a869e8c541ede9692ea6deb7cd52dbb4fb66b0f5a9a07e84e886ee5520faadf4fc7d646f1987bf19ad3d669dd9df57eec3de510148a6d349b8626c20ffb6d95f09c0af54b276626da745502e9c2bb5496e1a29bc
-    "0515073b33821f187092da6454ceb1853e6915f8466a0496730ed9162f6768d4" 0 ""
-    sha256-mgf sha256 32;
-  1025
-    0x0a9228b191158744e277bd223ada3c227429e5d64884007a748d74abca2d55358c1bb21cdf2666589ffd6cdfd458c877620009ebace86e7fc88c6d0acb99e5432f1af5705908e332e1a071e3700f0a0310b531589e79fd40922f0780b239cdd489816be7fdee9f6353f7f9f182abf873eb32e83586011fce20ae957bc66728bc
-    "a90b87978c2ff1151d9a95c19be1c07ee9a89aa786c2b554bf9ae7d923d15590" 0 ""
-    sha256-mgf sha256 32;
-  1026
-    0x016ecc969a03557d5fb257119251316ec4d8630d66bd6c18e93bc5c69a3a1d68431cd298f92db41a5f017874f05054224da5d75c012855febdf801c77145c8067c714c5c218f555b1e335a73f3ca6228a9723fa074173c7941200526c3a8ad81bb25427c84bdf82052021590cb5fd6aa44d052734b9112d1063276995572300ebc
-    "cbc2033f4107840f1405651b2861c9c5e72c8e463608dcf3a88dfebef2eb71ff" 0 ""
-    sha256-mgf sha256 32;
-  1027
-    0x031a071405323cf4ef20cc186ca5edc492fa2a7158565275d1d7cce302dcb10853625822b6887ab61c0713c332eb188b708690dee268ecc1e8b07f34106a1437246034347340bb65f39d8f002fe6ad5d826cce3c44d121924ba2a2fe265200523940b2f60918202839190fd4c50960be706863daf99b34cf7a152f720cbd9a2bbc
-    "6653330bcba1105e4cec034c73e605b4310eaaadcfd5b0ca27ffd89d144df479" 0 ""
-    sha256-mgf sha256 32;
-  1028
-    0x032e267380b21f98eb301bfd28c95af795a29864dfd801146c6878d9755669a6a8ef0090c574d5e7b716e4bf32128787db838c1df23fa418406e124fe4c031e706e31e27982810561d0c77d391b7718a2dd12b583987fe1c3c07436d457e039c3f4a6bbc2b6e765670762138ec2f22c3b1ce84ff422c08479f90abeb39986abdbc
-    "d5cfd3a195ce5abe65272af607ada1be65a6b4c9c0693234092c4d018f1756c6" 0 ""
-    sha256-mgf sha256 32;
-  1029
-    0x034a4f060407d55bea14998785fef3dc09240b2145350d7aaa8e7b0114ba531209e8a5d9cfa1f8c364f21a94d302968a0ba7905ac188da019da0b68c27e42bf513bde915eaf96a91f300a32bbd723cdf66510f1ecb964ed807679dacf7ada3903e7234167bd3dc49e8b59749a396dcdc3f06d3751d0b58216d1ea3760fface17bc
-    "608f6e3c7bf45b628a8a8f275cf7e5874a3b329b614084c6c3b1a7304a10ee75" 0 ""
-    sha256-mgf sha256 32;
-  1030
-    0x0aab7297cc92ae458f1d4d3b275eab7b2c65af1a7ab4fde8f5ff78b21474751b3b245f9b32b3c7d22ca677ccc882957cfdf3583372a8038918c27e9efd9743e6673d935ade4d3a4c3029c81c56d9a900e3f403de752d816d2e224621db32baf716b7625598aae00a336df65970076a2421e82925b9496b45e889f3b91ff5c100bc
-    "0d2bb614ecbbb82f73e2517e7d1dd884d31f01be506b16d6432183191518982b" 0 ""
-    sha256-mgf sha256 32;
-  1031
-    0x0a1a81c6c71b542db6ce4aac600e96d5280f31dc6d91d201a0a83f3c2fb9a1baebf0d77b5aadd2358de635eca6f802a3adfe33c4e32e321276e102bb74dbb23aafcd8ca3806abd496a55c88223478a21ce0ee9946b93d0f94dcff307f0f33e41b3ab282016b7cda40bd8a3b1a909fb9396afff909f9bb6e44a3d70240e9ec9eabc
-    "f25b81a07f5ccb1d36e949740255d2ac1a0bf7a92623405ba333b9358868ade1" 0 ""
-    sha256-mgf sha256 32;
-
-# This one's WRONG!
-#  1024
-#    0x696c23c434d74b91841724d0cca8318938551593969a8c31468377335252f2e18cbc11902b09ea494297ac729872b459d852018bc0634e95f9a1e80f09b55b321a1cc3b5f5f8c66a6bc91f42f154c6b4406606f3e9dda02eefe343cd80436a09e013a6e6b1190d222279e6f790223c315f367f3a212ff6f1c838c728c7fafabc
-#    "29d7a859cc0dea26ed554e8084d92bf837b8edd57aa05c4efa9f21fc3c36858e81b07dbfeeb1e485e912078bc6ec66e2" 0 ""
-#    sha384-mgf sha384 48;
-
-  2048
-    0x7a14b3a1fbf3371d6a607e3a401b43937f77d1f0960f0caee52c3a962d097cbcf7659ee7a26d7da421bfdf650c02a275f7c839eccdb77eb8bd73e807f251a9b8dcf6c7bbde426e1cd2b05f5e0ca53d4a2e7487f56bde022384d581208489a835b0e4f23aa713497d7ad0b1ba3a0d3fdf1798e40f5add1ab96c1ca17006138941b87fa1bc7bdb93c49befa6e2e4cdf6a144e55525d14f995ebbc452f8dd31ee07ddee8935454e5d484132e3799978eeb15f66444e342e425ca456c4ed13e3504e1dfef8d29de9086e027958a0ab7975f642f8d061c94b379b2ddf8b5f5540f2c94a9f50ce509d9bc7f21c8e5cbca7c783c78b2a8235f4ec536b129e6f105d3bbc
-    "a744b33e02b80487b63022dde456dd617b6e3d8c5ce7c467bc2ff2ffc9cc0f1390a924111ead4b41e592283f62f5b8aefda9492b3151ca80ec2e451a3935aabe" 0 ""
-    sha512-mgf sha512 64;
-
-  2048
-    0x106373ce481fe7e268a5a66f8b281e17719e23e1fa5f9d6bdfb2da5451a3fe7afab07969d8acdb904c723830280f78124717e87edf05a58626e191281b9c82edeceb02d1fc8dfab7d3e941ef3a13ea27ea51609e47dd727a784f66dc189fb8527093060ee5f982f7072e3f8a5fac4edcadd9ff107d6c8a99e9b52680a046b6f984c323afbb194e94bf2ab014804e791af59b254c164ef24af7c726b314a127febc4d026c700cbe08076d4e63be94581f6b353adbd3c754864d314f0039b3c7cae177c8be11a426358d523a1f0c97a0626aa9d565751229d488d96e168e7305cdc3d256401e6b865c246d686f0d8a673603038c464a60753dcd2b0f2a552514bc
-    "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884" 0 ""
-    sha256-mgf sha256 32;
-}
-
-psssig-priv {
-  # n e d msg rc sig mgf hash saltsz
-  0x6af87c8c97ae0c7668bc361ff1c358198309c80cd8a74a6d9d9cc846ea63ede9
-    0x10001
-    0x30ec4a0a5854d733a5ddc3e3584469f0a7d4b1f0cb38b8cfb04483c68b77a01
-    "a9993e364706816aba3e25717850c26c9cd0d89d" 0
-    0x2b484543397da31ca7aaf774c4b19acd69eb8bc230b6d98a2ae10798793bd53f
-    sha-mgf sha 10;
-
-  0x560e64d28a2352ab7930aeb78fede05837b4fb868f0e6920d3108bcd57c8fe019d20d5df7ccc1ba15b5b0f850282739f3c76f0f592e2120573551c0146c3cd6d165cfd3bedfdc131bed468f0b36a7f07d47caf5ec83c0790354fba9f5027394618fa1a342b752a028addc86765061ca680d748190befe34d0f4032ad5639b148d033c3b3914f0b4ef9a1a7e167bdfe22a7954a8542286f562c226c393d48a91a1b7843831f8133e7214d65a5874954ecd8b10002dfe9847f5e8061cfb77d2b5defc6ce63d553aa79d1fe75e90fab2fdb78f55d8348063717a6335367d8316070a44847a49ba53be57f44bc6d6108aecbe0efbf81a2b51cbe98407166d89e89a9
-    0x10001
-    0x27f0e74fa6a8ad5a83d59a09fd85f10dd0d131baaad40bec1dba3cc0d24129cf72efc60443e671de8ac9b162d11eddee26c0a7a6bb052d4b155407baf9eeaffe351674bc6781d2b4b576ddbbf5f1f4429c974047f4149488148e4c365c1bd063ddfcdac3a2f5eec91e4dc091689c95189c8d0edbfd23da722e25643ffa58ad94ec06f6ab21fc8805b09066ffe3849e2d5536cf8a7385e62526989605c9fefbd9092ddb51bd887ee71cababab3a150b34d7de54d01c19987438bef4672208418e51bf49cdbe1825f16e2764c58aab339afbb4f673914646d2a191fec4f7a503e512841a2cccdc8852c0f348b8aedea3123747d20c3c580c38b438ef5fde3608bf
-    "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884"
-    0
-    0x35fcbf7c5a69bd892dbf2ee88e53e40fe58ecddb4cf7c8885b228bfa9c24730ac554e20c65d82fc98d67a7805343450b1712a5f8c5ed6970c4310e06f65a9758d33e1c9dedec7178507da977a5ab76635d9f824b136abb855210caf851700bb57eb3aef7de61b217ae79ee4d6ad7c1a94279d9f8a425e06a0e4024d4c5b709ce1af6d09a26ce346f0a7eb36675fdbe1367f3d040ab7e18235b8090f91c355ee07425e3f4adf302e741be55959ac0f31075ccf1beef20e2f90693a82a30a48969c5ef32bc779ce84961b6a8d3ae0228cc520e2c644067bae96f14d90ceda2c8d00c97de3895d434a001d3cca244777fba4e0f5b5ed01c103842652c6402d2525b
-    sha256-mgf sha256 32;
-}
-
-pssvrf-pub {
-  # n e sig msg rc result mgf hash saltsz
-  0x6af87c8c97ae0c7668bc361ff1c358198309c80cd8a74a6d9d9cc846ea63ede9
-    0x10001
-    0x2b484543397da31ca7aaf774c4b19acd69eb8bc230b6d98a2ae10798793bd53f
-    "a9993e364706816aba3e25717850c26c9cd0d89d" 0 "" sha-mgf sha 10;
-
-  0x560e64d28a2352ab7930aeb78fede05837b4fb868f0e6920d3108bcd57c8fe019d20d5df7ccc1ba15b5b0f850282739f3c76f0f592e2120573551c0146c3cd6d165cfd3bedfdc131bed468f0b36a7f07d47caf5ec83c0790354fba9f5027394618fa1a342b752a028addc86765061ca680d748190befe34d0f4032ad5639b148d033c3b3914f0b4ef9a1a7e167bdfe22a7954a8542286f562c226c393d48a91a1b7843831f8133e7214d65a5874954ecd8b10002dfe9847f5e8061cfb77d2b5defc6ce63d553aa79d1fe75e90fab2fdb78f55d8348063717a6335367d8316070a44847a49ba53be57f44bc6d6108aecbe0efbf81a2b51cbe98407166d89e89a9
-    0x10001
-    0x35fcbf7c5a69bd892dbf2ee88e53e40fe58ecddb4cf7c8885b228bfa9c24730ac554e20c65d82fc98d67a7805343450b1712a5f8c5ed6970c4310e06f65a9758d33e1c9dedec7178507da977a5ab76635d9f824b136abb855210caf851700bb57eb3aef7de61b217ae79ee4d6ad7c1a94279d9f8a425e06a0e4024d4c5b709ce1af6d09a26ce346f0a7eb36675fdbe1367f3d040ab7e18235b8090f91c355ee07425e3f4adf302e741be55959ac0f31075ccf1beef20e2f90693a82a30a48969c5ef32bc779ce84961b6a8d3ae0228cc520e2c644067bae96f14d90ceda2c8d00c97de3895d434a001d3cca244777fba4e0f5b5ed01c103842652c6402d2525b
-    "12f1c8bb1c560ae3f3b0fcb1ae918af64947a95c4c53e81551280ffc2e842884"
-    0 ""
-    sha256-mgf sha256 32;
-}
diff --git a/tests/safer b/tests/safer
deleted file mode 100644 (file)
index 36149a0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# $Id: safer,v 1.1 2001/04/29 17:37:38 mdw Exp $
-#
-# Test vectors for SAFER
-
-# From HAC 7.114, and Richard de Moliner's implementation
-
-safer {
-  0807060504030201 0102030405060708 c8f29cdd87783ed9;
-  100f0e0d0c0b0a090807060504030201 0102030405060708 4a99b15cce9ada19;
-}
diff --git a/tests/safersk b/tests/safersk
deleted file mode 100644 (file)
index d1ea05a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# $Id: safersk,v 1.1 2001/04/29 17:37:38 mdw Exp $
-#
-# Test vectors for SAFER
-
-# From HAC 7.114, and Richard de Moliner's implementation
-
-safersk {
-  0102030405060708 0102030405060708 60d04ad7c49b8ded;
-  100f0e0d0c0b0a090807060504030201 0102030405060708 b260740f80d2445d;
-}
diff --git a/tests/seal b/tests/seal
deleted file mode 100644 (file)
index 7c48095..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Test vectors for SEAL
-#
-# $Id: seal,v 1.1 2000/06/17 12:11:49 mdw Exp $
-
-seal {
-  67452301efcdab8998badcfe10325476c3d2e1f0 0x013577af
-  9505a0379cc4849b051ebea40f537306fd97b05fbd3fa1f6cdde2c6c7ceefd81e7c3bd2aff9a20648322a100855067ef534b63c1e6599028d95eaba7eb010c48;
-}
diff --git a/tests/sha b/tests/sha
deleted file mode 100644 (file)
index 841c96c..0000000
--- a/tests/sha
+++ /dev/null
@@ -1,63 +0,0 @@
-# Test vectors for the SHA-1 hash function
-#
-# $Id: sha,v 1.6 2004/04/21 00:38:42 mdw Exp $
-
-# --- Basic hash function ---
-#
-# Some of these are taken directly from the Secure Hash Standard
-# (FIPS 180-1).  Others were generated using the SSLeay implementation of
-# SHA-1.
-
-sha {
-  ""                   da39a3ee5e6b4b0d3255bfef95601890afd80709;
-  "a"                  86f7e437faa5a7fce15d1ddcb9eaeaea377667b8;
-  "abc"                        a9993e364706816aba3e25717850c26c9cd0d89d;
-  "message digest"     c12252ceda8be8994d5fa0290a47231c1d16aae3;
-  "abcdefghijklmnopqrstuvwxyz"
-                       32d10c7b8cf96570ca04ce37f2a19d84240d3a89;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-                       84983e441c3bd26ebaae4aa1f95129e5e54670f1;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-                       761c457bf73b14d27e9e9265c46f4b4dda11f940;
-}
-
-sha-rep {
-  "1234567890" 8       50abf5706a150990a08b2c5ea40fa0e585554732;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-" 23                   f74d36bf17ee23c46ec166a48a24da6ab999eaea;
-  "a" 1000000          34aa973cd4c4daa4f61eeb2bdbad27316534016f;
-}
-
-# --- HMAC mode ---
-#
-# Test vectors from RFC2202.
-
-sha-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       b617318655057264e28bc0b6fb378c8ef146be00;
-
-  "what do ya want for nothing?"
-       4a656665
-       effcdf6ae5eb2fa2d27416d5f184df9c259a7c79;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       125d7342b9ac11cd91a39af48aa17b4f63f175d3;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       4c9007f4026250c6bc8414f9bf50c86c2d7235da;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       4c1a03424b55e07fe7f27be1d58bb9324a9a5a04;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       aa4ae5e15272d00e95705637ce8a3b55ed402112;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       e8e99d0f45237d786d6bbaa7965c7808bbff1a91;
-}
diff --git a/tests/sha224 b/tests/sha224
deleted file mode 100644 (file)
index 5d9a759..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# $Id: sha224,v 1.2 2004/04/21 00:38:42 mdw Exp $
-#
-# Test vectors for SHA-224
-
-# --- Basic hash function ---
-
-sha224 {
-
-  # --- Test vectors from the definition [FALSE] ---
-
-  "abc"
-       23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525;
-
-  # --- Other tests to trap regression ---
-
-  ""
-       d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f;
-  "a"
-       abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5;
-  "message digest"
-       2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb;
-  "abcdefghijklmnopqrstuvwxyz"
-       45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9;
-}
-
-sha224-rep {
-  "1234567890" 8
-       b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-" 23
-       5a86156c37c95ab356e003d569370580737794815f46de7f4834d634;
-  "a" 1000000
-       20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67;
-}
-
-# --- HMAC mode ---
-#
-# Autogenerated, unofficial.
-
-sha224-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       1abbc7c42cf4ca9f9d7b624564cb72d7b0945ea0a615095904a0fd34;
-
-  "what do ya want for nothing?"
-       4a656665
-       a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       5121d4bc8e43ee3ddcc2b0d312c110e961fc34b19ced1cce11c7a55c;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       0f081672137307d07aad12880537cd43f454823de00c038424741e17;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       9ed2eebc0ed23576efc815e9b5bc0d9257e36d13e4dd5d5f0c809b38;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       7358939e58683a448ac5065196d33191a1c1d33d4b8b0304dc60f5e0;
-}
diff --git a/tests/sha256 b/tests/sha256
deleted file mode 100644 (file)
index d00ca14..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-# $Id: sha256,v 1.3 2004/04/21 00:38:42 mdw Exp $
-#
-# Test vectors for SHA-256
-
-# --- Basic hash function ---
-
-sha256 {
-
-  # --- Test vectors from the definition ---
-
-  "abc"
-       ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1;
-
-  # --- Other tests to trap regression ---
-
-  ""
-       e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855;
-  "a"
-       ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb;
-  "message digest"
-       f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650;
-  "abcdefghijklmnopqrstuvwxyz"
-       71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0;
-}
-
-sha256-rep {
-  "1234567890" 8
-       f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-" 23 4804a2a4759acebe127b62ba651ae601a756ca0b509e4987498224acaffb0d98;
-  "a" 1000000
-       cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0;
-}
-
-# --- HMAC mode ---
-#
-# Autogenerated, unofficial.
-
-sha256-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       198a607eb44bfbc69903a0f1cf2bbdc5ba0aa3f3d9ae3c1c7a3b1696a0b68cf7;
-
-  "what do ya want for nothing?"
-       4a656665
-       5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       cdcb1220d1ecccea91e53aba3092f962e549fe6ce9ed7fdc43191fbde45c30b0;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       7546af01841fc09b1ab9c3749a5f1c17d4f589668a587b2700a9c97c1193cf42;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       6953025ed96f0c09f80a96f78e6538dbe2e7b820e3dd970e7ddd39091b32352f;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       6355ac22e890d0a3c8481a5ca4825bc884d3e7a1ff98a2fc2ac7d8e064c3b2e6;
-}
diff --git a/tests/sha384 b/tests/sha384
deleted file mode 100644 (file)
index 13ad630..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# $Id: sha384,v 1.4 2004/04/21 00:38:42 mdw Exp $
-#
-# Test vectors for SHA-384
-
-# --- Basic hash function ---
-
-sha384 {
-
-  # --- Test vectors from the definition ---
-
-  "abc"
-       cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7;
-  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
-       09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039;
-
-  # --- Other tests to trap regression ---
-
-  ""
-       38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b;
-  "a"
-       54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31;
-  "message digest"
-       473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5;
-  "abcdefghijklmnopqrstuvwxyz"
-       feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84;
-}
-
-sha384-rep {
-  "1234567890" 8
-       b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-" 23
-       f77d169c73427bd30cceff74f822a0209657dfb78c07980509bf8452a3c5d671b7198081898d0a0034e0f7151211fa0f;
-  "a" 1000000
-       9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985;
-}
-
-# --- HMAC mode ---
-#
-# Autogenerated, unofficial.
-
-sha384-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       b6a8d5636f5c6a7224f9977dcf7ee6c7fb6d0c48cbdee9737a959796489bddbc4c5df61d5b3297b4fb68dab9f1b582c2;
-
-  "what do ya want for nothing?"
-       4a656665
-       af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       809f439be00274321d4a538652164b53554a508184a0c3160353e3428597003d35914a18770f9443987054944b7c4b4a;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f30313233343536373839
-       b8405cddb33af1a68a1a71a8a4e6189a724fe28209671d701f7ecd4582d4db61b3a31ddca42a0db4efa2c5caf7a0482c;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       3b44c978360a9da6eba51d8186dd879bac52801ba2cba0afcb0f612f3305668accf4d5367a686e547426abfe7832f8ba;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       39cc73806611492e9179e2c23cebddd61c240b0b9c5a095db35f978d48642a1a49a2dde075f2b54cefbae7fe0aed4909;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Bearing In Mind That This Hash Has An Extraordinarily Large Block Size So The Standard Test Won't Work"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       f9ac83e56d205edb71774e0d1ee102330583c474020bcbe52f02384f6fdf09e7e8b75495d74eea4788c17e48e64d6888;
-}
diff --git a/tests/sha512 b/tests/sha512
deleted file mode 100644 (file)
index f0cebb9..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-# $Id: sha512,v 1.4 2004/04/21 00:38:42 mdw Exp $
-#
-# Test vectors for SHA-512
-
-# --- Basic hash function ---
-
-sha512 {
-
-  # --- Test vectors from the definition ---
-
-  "abc"
-       ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f;
-  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
-       8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909;
-
-  # --- Other tests to trap regression ---
-
-  ""
-       cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e;
-  "a"
-       1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75;
-  "message digest"
-       107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c;
-  "abcdefghijklmnopqrstuvwxyz"
-       4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1;
-  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-       204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-       1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894;
-}
-
-sha512-rep {
-  "1234567890" 8
-       72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843;
-
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-" 23
-       4def32cfb1107a104eae530fe04326a57e839a0bd9675f6770ff18d0b3b3ee2d4343bf99e9d54adc272617d49d0f61eab4b4bc177f9d2bac086cd2d902b5780e;
-  "a" 1000000
-       e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b;
-}
-
-# --- HMAC mode ---
-#
-# Autogenerated, unofficial.
-
-sha512-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0bb0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       bb969b8e6b99529a2e09757ef582257aed4f66cb62f1b32150b969eaa7dd683d46a776726cbf0f614f784cfa0759e84ba1d0baf07a1391ed998da6ea2fd7ff53;
-
-  "what do ya want for nothing?"
-       4a656665
-       164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       2ee7acd783624ca9398710f3ee05ae41b9f9b0510c87e49e586cc9bf961733d8623c7b55cebefccf02d5581acc1c9d5fb1ff68a1de45509fbe4da9a433922655;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f30313233343536373839
-       005a43d33fe40a285dc0947121984509698d4533519662c5eda2f8fac7a6b69f78ce84b61b1427d8dc88046aa1f35c6513b467185de195deb4dee3367b55d38d;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       54701368cc706f527661ec9617d506ab255890b7c0cd8318f2efcf2b1bfbac560a77c369bdc01220d652e79747c0fa465da176e34b0de91cf075db0a12ac0ab5;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       ae52fbcfb432b5963d1fa0b38a584554752d41f5b4de82483ec1f32de676ae708fc20ffa3bc6525f3d4115eda6b145bf123ed5acf6cbb0ee7f7bf625402609fd;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data Bearing In Mind That This Hash Has An Extraordinarily Large Block Size So The Standard Test Won't Work"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       062d5553721e9512a061feaa8a236a5c2c5a45f25ed3ebe9c7337f3bc26b65d8ba3e1bd061b53fe45ac03800aeee4b48c6f2f3bd955c32991bd2bfaf2b1c05a3;
-}
diff --git a/tests/skipjack b/tests/skipjack
deleted file mode 100644 (file)
index a646803..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-# $Id: skipjack,v 1.3 2000/08/04 23:24:01 mdw Exp $
-#
-# Test vectors for Skipjack
-
-# --- From the Skipjack definition ---
-
-skipjack {
-
-  # --- The official Skipjack test vector ---
-  #
-  # It's a bit piss-poor that they only provide one test-vector here.
-
-  00998877665544332211 33221100ddccbbaa 2587cae27a12d300;
-
-  # --- From KEA test vectors ---
-  #
-  # The Skipjack algorithm is used by the KEA to derive the final key.
-  # Unfortunately, the test vectors given in the Skipjack/KEA spec don't
-  # match my (or anyone else's!) implementation.  These are the values
-  # which seem to be generally agreed.
-
-  e7496e99e4628b7f9ffb 99ccfe2b90fd550b 60a73d387b517fca;
-  e7496e99e4628b7f9ffb 60a73d387b517fca 24c90cb05d668b27;
-  e5caf4dcc70e55f1dd90 b71cb0d009af2765 64f4877ae68a8a62;
-  e5caf4dcc70e55f1dd90 64f4877ae68a8a62 fee778a838a601cd;
-
-  # --- These are the results expected from the KEA spec ---
-  #
-  # A `?' indicates that I don't know what that digit's meant to be.  I've
-  # derived the top 16 bits of the intermediate results from the spec.
-
-# e7496e99e4628b7f9ffb 99ccfe2b90fd550b 2f30????????????;
-# e7496e99e4628b7f9ffb 2f30???????????? 740839dee833add4;
-# e5caf4dcc70e55f1dd90 b71cb0d009af2765 8e27????????????;
-# e5caf4dcc70e55f1dd90 8e27???????????? 97fd1c6bd86bc439;
-
-  # --- Some more test vectors ---
-  #
-  # These are dreamed up by me.  The above tests don't actually exhaustively
-  # test the F-table.  There are 16 entries unaccounted for.  The keys and
-  # plaintexts were generated using fibrand with seed 0.
-
-  cde4bef260d7bcda1635 47d348b7551195e7 f17b3070144aebea;
-  7022907dd1dff7dac5c9 941d26d0c6eb14ad a055d02c5e0eae8d;
-  568f86edd1dc9268eeee 533285a6ed810c9b b4c22f4fb74c35dc;
-  689daaa9060d2d4b6003 062365b0a54364c7 08698d8786f80d16;
-  6c160f11896c4794846e cfa14a7130c9f137 d6db848b7cecdd39;
-
-  # --- And some more, posted to Usenet ---
-  #
-  # Message-id <8m7slq$1i1$1@hecate.umd.edu>
-
-  f8da02647722f7103adf 1ddf39abf5cd711e c92d22324c6b31ae;
-  82760ac137948821eee4 dd6c6cce8f83e69e e32877c1d9527fff;
-  843c1687d3cdca5fc5c3 beaacf177fa41a11 4745783f75b8861a;
-  ae870cd7ff33a995f7e5 c4c09f216c1bc60a 5c101636b8a57a72;
-  5ccbd913ea8b73bd6391 d3f814b000245856 b4fc0f8e54728f91;
-  f65e74cd599c68a40cc7 356ec7d93832329c 93b750608f5701f8;
-  aa106e46d7087c4e93dc 209ecf1c537ad56c d823d45510099e61;
-  a93f9789a20c3cc34fea 892eea9d64e17d66 0959e231b275d95f;
-  88b163cbd61616888899 991390fd760fc91b e7700209886767ae;
-  fb6cd1ff70487561df10 daebc947ddca9c9e e7cc49a56bd6a322;
-  5edc1ac0c4e7ef5f002c 6419ddefe2cd8f2e e48a05cf26e242fd;
-  8e3090c19aa32f94496a 322998ecbd068112 62c0e537b14df2c1;
-  b96e3fd46fa4263f9092 3aae2aee20da93cc 54d1e58a6b624d71;
-  9e6635baee28c5bce2bc 14311112ca11f727 5d0f235a9d221ce0;
-  04127ce16dc1b1726a66 300e4313e7ad6796 8e5b03522e68cbeb;
-  f0b89d75e979ccc9b172 09cd1c1accbe7797 572c9b4025a9134b;
-  f9bfc78798cbf1bcd4b5 31b30ca354af3cd8 8c959c904789fbda;
-  f43a51b4273bde27d2b0 08c59b0db99ec267 b7d7f5fa342988fb;
-  cd51f0a75aa73c48edd2 9784b1e3e7e60e60 763aa8ee109397b3;
-  b3319a3f6622aa726bb3 f65216373d4b43c7 0325600337b8ad3c;
-  493254c9596e993f5f9c cba4c1215d5d36ce 68e1c551c59108c0;
-  76150c2c3ced1c7ca021 82294851288e75cb 7eb6325d82a2096c;
-  7140d6c5486305872df6 c3a7b7e4a52e407b 2483f385a42ee3c6;
-  3c2c3901f0ee9a3b2b0e 1bfde32ab559e13a d6fa9db8685fd88a;
-  606a8b4bdfaae8a0ba51 d205f7486c782838 0330489170b85293;
-  7847a47a0fe79ab770ce d96ff1f7c7fc60e0 1f9b3301c9b2708c;
-  73b9ab0c36c99e91a891 241d4bde19a75f8f 2b86c57ffe168895;
-  a37f2ad5a85e170741f5 7be1b8d58321c619 5af7ceb3eed9dca1;
-  f7b0c2a8170e3c4e48b3 c9214ea01ec14948 1b587736e116c04b;
-  a1fc67e44eacacf4a902 e2a3091feb581588 f3ecf0f1789a3923;
-  f14430affc5fe82a9ae9 3cb466d301b60854 e8d114c20ffa1c79;
-  fd26df50486a4cd96d9b b0684f8a5e63d935 222903994d64fe3a;
-  a6d46d46ca287e1a332a ba1f37e88edec55f 91f2baad6fa0de55;
-  83c3f1cb8d06efc6196b e9fed8501b7a6579 83f9f08f89a854ee;
-  0edfa44c7d4a4ef0725e eb5ca8b3fa1fcdbb 2b1b6670a6be0324;
-  b8edcf167d99a711ccee b8b525c6382af277 211a695da473766f;
-  4f639e0d5a5d2ad7e9a4 9162e781ff683853 eb2976370d22ef22;
-  37e006256a4ae6d320c4 c9f23a20a39ded11 dba4c0ef0ea098c0;
-  e41d0bd25f931ba1d85c 5a6f12f32f7eefdf 923daee8000709f9;
-  fdf65bbc5fe600f3cd68 cad5414c1c64f194 d5771e78b6f1fe1e;
-  1c269af2ff166acb27ef 063a58a20b45378f 634f7a3861af97a1;
-  1179f64acb6122ccf649 08fbf42b4313347b 3a803a4bd0e8c3e6;
-  078c87265eb8da323e90 6d4ed0e9930532d1 f4fa372e7e1441a1;
-  2fff35f8eb774c843bb0 40b699812345661d 63a9197f7b75f53f;
-  09f77346a4393ce99856 22ed54626a51e505 e91a050a7481b3dd;
-  5b878e0b22a705acf8fb 0c489b66e2da531b 6e9370a91b994878;
-  9d72c1ab2092c1b10877 c64b10f8b191bc2c 5bdecded96d656c9;
-  72865f289725e1b55502 91fdf7236f85bdd6 1a5680e51736026f;
-  06e3c0e541f4aae6fe93 40009f8a465a9feb 0e7aace421bc79d8;
-  2ea09f1cc89e064f09bc 543208b05bfa3858 a95d87fad12c3593;
-}
diff --git a/tests/square b/tests/square
deleted file mode 100644 (file)
index 360d56b..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-# $Id: square,v 1.1 2000/07/15 20:51:59 mdw Exp $
-#
-# Test vectors for the Square block cipher
-
-square {
-  # --- From the reference implementation ---
-
-  000102030405060708090a0b0c0d0e0f
-       000102030405060708090a0b0c0d0e0f 7c3491d94994e70f0ec2e7a5ccb5a14f;
-
-  # --- From the validation data ---
-
-  80000000000000000000000000000000
-       00000000000000000000000000000000 05f8aafdefb4f5f9c751e5b36c8a37d8;
-  40000000000000000000000000000000
-       00000000000000000000000000000000 60affc9b2312b1397177251cc9296391;
-  20000000000000000000000000000000
-       00000000000000000000000000000000 d67b7e07c38f311446e16ddd9ea96ebe;
-  10000000000000000000000000000000
-       00000000000000000000000000000000 39207579067031706fab8c3a5c6e5524;
-  08000000000000000000000000000000
-       00000000000000000000000000000000 fc4f2602a3f6ac34f56906c2eeee40c5;
-  04000000000000000000000000000000
-       00000000000000000000000000000000 6f2431469f4a0866632216c59c18ff11;
-  02000000000000000000000000000000
-       00000000000000000000000000000000 c745f6f339d1bb9524e1b2d2b0dde843;
-  01000000000000000000000000000000
-       00000000000000000000000000000000 241e113a1bb5c32cc45d95d7734165aa;
-  00800000000000000000000000000000
-       00000000000000000000000000000000 5e16777211c67ae4609f6a47bf5df2c4;
-  00400000000000000000000000000000
-       00000000000000000000000000000000 272330139236c300cd161f0266b62494;
-  00200000000000000000000000000000
-       00000000000000000000000000000000 15115b9e29524325e7c992ead262ade8;
-  00100000000000000000000000000000
-       00000000000000000000000000000000 acdcce277b801ed53dfe0fc12f4c957b;
-  00080000000000000000000000000000
-       00000000000000000000000000000000 9cadb290cedd6f7ca6c10d42fe4c1a70;
-  00040000000000000000000000000000
-       00000000000000000000000000000000 d70d4c24ffbf3de6e6bd54ec03b8492a;
-  00020000000000000000000000000000
-       00000000000000000000000000000000 602455a418a99a942fed27123b9f73e6;
-  00010000000000000000000000000000
-       00000000000000000000000000000000 f239c4efd3729d43081544104378f0ea;
-  00008000000000000000000000000000
-       00000000000000000000000000000000 70259a9572990099ac563114074db3d2;
-  00004000000000000000000000000000
-       00000000000000000000000000000000 932d3644863b6377100c64f243445e7e;
-  00002000000000000000000000000000
-       00000000000000000000000000000000 47100bf12f2e1f718e9430f4127535be;
-  00001000000000000000000000000000
-       00000000000000000000000000000000 2ed60ffa71c162a53c3a8bba2b0b042b;
-  00000800000000000000000000000000
-       00000000000000000000000000000000 e2992d6bdc7c65b70b62685c0d84425c;
-  00000400000000000000000000000000
-       00000000000000000000000000000000 c552ca3d805e456f5239dd7956cacd71;
-  00000200000000000000000000000000
-       00000000000000000000000000000000 95b577c2ed3c2d9d96c2106e091b1f72;
-  00000100000000000000000000000000
-       00000000000000000000000000000000 3d550ae470bfb0306c3099c8d5a471d8;
-  00000080000000000000000000000000
-       00000000000000000000000000000000 fc13974afe73a92598aa95edcb2102e9;
-  00000040000000000000000000000000
-       00000000000000000000000000000000 ab0cf3a0cfef3aa3d10738523e624a1d;
-  00000020000000000000000000000000
-       00000000000000000000000000000000 72fea53144f673e283547f08da30bdda;
-  00000010000000000000000000000000
-       00000000000000000000000000000000 389fef99fa1a3dbf664673aa39d848d1;
-  00000008000000000000000000000000
-       00000000000000000000000000000000 041152bca8440e8de572dce9dcc88cdc;
-  00000004000000000000000000000000
-       00000000000000000000000000000000 845b37c1338a0ba0f295be273841b940;
-  00000002000000000000000000000000
-       00000000000000000000000000000000 e2e3a1c7998040ee6bd8714e65ebd8af;
-  00000001000000000000000000000000
-       00000000000000000000000000000000 0b2b34c480648dc91f938dd368464780;
-  00000000800000000000000000000000
-       00000000000000000000000000000000 96bad4a54376917044b1076727a91e2b;
-  00000000400000000000000000000000
-       00000000000000000000000000000000 dd8c3dff69c3fda2802dffcdef1b1631;
-  00000000200000000000000000000000
-       00000000000000000000000000000000 da45872e48af2f0ec7fc395d03ff9451;
-  00000000100000000000000000000000
-       00000000000000000000000000000000 b25194c0f1953f35bc4c0871cd2d4a40;
-  00000000080000000000000000000000
-       00000000000000000000000000000000 3e09af82736971f2847834082d6ec6f3;
-  00000000040000000000000000000000
-       00000000000000000000000000000000 fa75a64f778b914dc4b926626bc8b4c0;
-  00000000020000000000000000000000
-       00000000000000000000000000000000 d21542857f03f6a92cacd2e783e33e3e;
-  00000000010000000000000000000000
-       00000000000000000000000000000000 1ec0a5b9781c5e90b1e15731e0625c36;
-  00000000008000000000000000000000
-       00000000000000000000000000000000 e1c58917e586b6c46c46982fa303f14c;
-  00000000004000000000000000000000
-       00000000000000000000000000000000 72ecc0d267b445482924c9969de97a15;
-  00000000002000000000000000000000
-       00000000000000000000000000000000 a52af631193375dd59555e2753acde65;
-  00000000001000000000000000000000
-       00000000000000000000000000000000 033b8482c4010eb20a3edd4ba35a3db7;
-  00000000000800000000000000000000
-       00000000000000000000000000000000 56534a944796abdf51ad247b8c9ee9bb;
-  00000000000400000000000000000000
-       00000000000000000000000000000000 9eda6fd2cd4eabf8218b98a165e82b9e;
-  00000000000200000000000000000000
-       00000000000000000000000000000000 60043a7e110e1321bc41e4ac47d1f45e;
-  00000000000100000000000000000000
-       00000000000000000000000000000000 90e685c8f990cedeacc8a2bfc8e46ca2;
-  00000000000080000000000000000000
-       00000000000000000000000000000000 b9e77e32f721c0a7a02b50925311e834;
-  00000000000040000000000000000000
-       00000000000000000000000000000000 001d2fe95bb39ef0c3548307ea7580f3;
-  00000000000020000000000000000000
-       00000000000000000000000000000000 a5dd651290a063f4e7c5e714c9c398b4;
-  00000000000010000000000000000000
-       00000000000000000000000000000000 aa7b3b9f459ba0367ff2a332ef725da1;
-  00000000000008000000000000000000
-       00000000000000000000000000000000 a424f80b0048756879ed6343768bbe08;
-  00000000000004000000000000000000
-       00000000000000000000000000000000 ea4590786de7f8a68439b4616bf7e4b9;
-  00000000000002000000000000000000
-       00000000000000000000000000000000 7d15058fe884dcf0976105a816cf6366;
-  00000000000001000000000000000000
-       00000000000000000000000000000000 a07d1b74ae6a3f26a8a25e1e778a0d4a;
-  00000000000000800000000000000000
-       00000000000000000000000000000000 61f13db32828961c3e35d9b7ab77b57d;
-  00000000000000400000000000000000
-       00000000000000000000000000000000 0e2979112efb29754605011a358093fc;
-  00000000000000200000000000000000
-       00000000000000000000000000000000 a878c8a8a5230917c56f7eb74fdada25;
-  00000000000000100000000000000000
-       00000000000000000000000000000000 34343f73232790e6fa44d8f606a24de9;
-  00000000000000080000000000000000
-       00000000000000000000000000000000 d569b991761c26dde723cca0c262f195;
-  00000000000000040000000000000000
-       00000000000000000000000000000000 f1a0f35ada018c5df56ffe0dc95636bf;
-  00000000000000020000000000000000
-       00000000000000000000000000000000 b26af455039312e1206290a921459e1a;
-  00000000000000010000000000000000
-       00000000000000000000000000000000 594049c7e3a34e1b9bccefaf5e75b373;
-  00000000000000008000000000000000
-       00000000000000000000000000000000 4e4e037f07ff26e8e9065f26afedaf2d;
-  00000000000000004000000000000000
-       00000000000000000000000000000000 ddedc3ca10ec011ea24dd4566d21409c;
-  00000000000000002000000000000000
-       00000000000000000000000000000000 3660f51bb790f275a55aa435db6da193;
-  00000000000000001000000000000000
-       00000000000000000000000000000000 a9a7cfe07ea640498e832ae25e2906ed;
-  00000000000000000800000000000000
-       00000000000000000000000000000000 3863d1c222a36338ea6d402073341f42;
-  00000000000000000400000000000000
-       00000000000000000000000000000000 ced5dfdf8b5d1d60e9ad51830a7965a9;
-  00000000000000000200000000000000
-       00000000000000000000000000000000 4ffae5d7a5689a5584330cb0a5cc9cd2;
-  00000000000000000100000000000000
-       00000000000000000000000000000000 1dd688d47541463915f658bb656420b4;
-  00000000000000000080000000000000
-       00000000000000000000000000000000 ef3a1c1800dd3cda748fbdf17086ba4f;
-  00000000000000000040000000000000
-       00000000000000000000000000000000 f9aa9b3e76543ef12f7f8b87ce393328;
-  00000000000000000020000000000000
-       00000000000000000000000000000000 1813935bb67dc40dc37c68cc2999758a;
-  00000000000000000010000000000000
-       00000000000000000000000000000000 8c4916d59fce8eb913b128f2d7b3d464;
-  00000000000000000008000000000000
-       00000000000000000000000000000000 bb88da704c5ce031c61954efcae6ed2d;
-  00000000000000000004000000000000
-       00000000000000000000000000000000 4e463bceb0f52c3f722e2926c2bd04a3;
-  00000000000000000002000000000000
-       00000000000000000000000000000000 4a6181492a454604293396bbd21c4956;
-  00000000000000000001000000000000
-       00000000000000000000000000000000 801f29d5462365735a6ca7a64288f48c;
-  00000000000000000000800000000000
-       00000000000000000000000000000000 7933733c4daab746ef048edba2d05538;
-  00000000000000000000400000000000
-       00000000000000000000000000000000 4127c1d95431fd2632f2b5e5085a3dd8;
-  00000000000000000000200000000000
-       00000000000000000000000000000000 0588168ca7525333460c4030af266388;
-  00000000000000000000100000000000
-       00000000000000000000000000000000 32b3f193d7237b48883de002b3cbe1c3;
-  00000000000000000000080000000000
-       00000000000000000000000000000000 7ca557bc05b845a233c01412022da825;
-  00000000000000000000040000000000
-       00000000000000000000000000000000 54f11361ad6dfbb069be67536cc98d81;
-  00000000000000000000020000000000
-       00000000000000000000000000000000 a9df031b4e25e89f527efff89cb0beba;
-  00000000000000000000010000000000
-       00000000000000000000000000000000 7da4d0d6309906d935ba27ae00cfaf33;
-  00000000000000000000008000000000
-       00000000000000000000000000000000 e231ea0fec29d983d3236bb15e7cd1da;
-  00000000000000000000004000000000
-       00000000000000000000000000000000 fe1b963a4f596422a6cd7787f4ab3377;
-  00000000000000000000002000000000
-       00000000000000000000000000000000 848833f2f7a247d2e1d0c8614694139f;
-  00000000000000000000001000000000
-       00000000000000000000000000000000 630bb1dc4e60d3272b6b673bdb918b20;
-  00000000000000000000000800000000
-       00000000000000000000000000000000 500251a5c6ad5a6d2f218a3fd5765727;
-  00000000000000000000000400000000
-       00000000000000000000000000000000 d019ef316e84149cfd0e85665aa2fff5;
-  00000000000000000000000200000000
-       00000000000000000000000000000000 db0b5ac0e8ef011d710323fa3b8bb3a7;
-  00000000000000000000000100000000
-       00000000000000000000000000000000 207e46a533617374d2c9da0c92ffd620;
-  00000000000000000000000080000000
-       00000000000000000000000000000000 8273ca155249f9f1ad8cc2ca114984f3;
-  00000000000000000000000040000000
-       00000000000000000000000000000000 82a73a18aae84ad671e226470f246e1a;
-  00000000000000000000000020000000
-       00000000000000000000000000000000 3e0e1206e333917d4c250bd82fef6afd;
-  00000000000000000000000010000000
-       00000000000000000000000000000000 2182f67239be15c796439ea3791202e1;
-  00000000000000000000000008000000
-       00000000000000000000000000000000 486fb3fa7b1fe1a304cb4e8960c3c6bb;
-  00000000000000000000000004000000
-       00000000000000000000000000000000 c1de50e456c4308d5d70da141cef0b4f;
-  00000000000000000000000002000000
-       00000000000000000000000000000000 a623f24515a27cee3dad277429000218;
-  00000000000000000000000001000000
-       00000000000000000000000000000000 02fa5762f9cd90201565bce71140c6f4;
-  00000000000000000000000000800000
-       00000000000000000000000000000000 a643a0ca5154a7d10b251d562d58ea53;
-  00000000000000000000000000400000
-       00000000000000000000000000000000 48660e32b1c7ee7085e5b5e9f719c790;
-  00000000000000000000000000200000
-       00000000000000000000000000000000 a96366bb17b67e161fd8e33c3e1f3d2a;
-  00000000000000000000000000100000
-       00000000000000000000000000000000 5659ab825fc2de031a6998cacd741ff6;
-  00000000000000000000000000080000
-       00000000000000000000000000000000 1253e9e4079e9b573a73cf4ce08dc015;
-  00000000000000000000000000040000
-       00000000000000000000000000000000 28205442270c735d4ba79042dce81509;
-  00000000000000000000000000020000
-       00000000000000000000000000000000 98cfb10f3ed70bb82cc90597b463a1f6;
-  00000000000000000000000000010000
-       00000000000000000000000000000000 cab40433631fe3a272fc401255a58064;
-  00000000000000000000000000008000
-       00000000000000000000000000000000 abb041d85114da88e65e8bdcf1c67cc8;
-  00000000000000000000000000004000
-       00000000000000000000000000000000 00f0926f0f9eaa0a6238dfce79c8f596;
-  00000000000000000000000000002000
-       00000000000000000000000000000000 7c662d01b12d9845705b2bd4d7aef43d;
-  00000000000000000000000000001000
-       00000000000000000000000000000000 8f1cc7a0fbe7d70a894d09e12fb22bb8;
-  00000000000000000000000000000800
-       00000000000000000000000000000000 ebe03d0c6752d0edfebff879c33d8c07;
-  00000000000000000000000000000400
-       00000000000000000000000000000000 b74ce7f67bbd969e8ff8862d1fb1715c;
-  00000000000000000000000000000200
-       00000000000000000000000000000000 63ad5ea9d599ec848a40d489c0b85e8a;
-  00000000000000000000000000000100
-       00000000000000000000000000000000 4e4167f091ea5776e80fb2fca38c2a04;
-  00000000000000000000000000000080
-       00000000000000000000000000000000 dbf0cea3a5ed5b884ac13a2a62c32d51;
-  00000000000000000000000000000040
-       00000000000000000000000000000000 7e86285068a376a3b9fe8641a38e3f90;
-  00000000000000000000000000000020
-       00000000000000000000000000000000 aec1ef8d651a2cf7b5475fcc7fb7a81a;
-  00000000000000000000000000000010
-       00000000000000000000000000000000 fda539d910181ce1a1e1db4c3459600b;
-  00000000000000000000000000000008
-       00000000000000000000000000000000 f8072bf053d5b5163949ff0b9bb3f81a;
-  00000000000000000000000000000004
-       00000000000000000000000000000000 a31eb966d34ed6a6132a6b6e9128e997;
-  00000000000000000000000000000002
-       00000000000000000000000000000000 673aebbff82091a19e758ece151811d0;
-  00000000000000000000000000000001
-       00000000000000000000000000000000 369bdb6f102d6bfea7645b1a6753bf37;
-  80000000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ffd90e8a92a1b025108168714f7923f7;
-  40000000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 64e10ab587bc5d996cf2186c2ff2dd58;
-  20000000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 eaa404b51336a16c963735588b0b2a0c;
-  10000000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 51aaa1e37cb08cf5c6ec9241ac36b4c5;
-  08000000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c21b34c3c077b30add67d0e2e75e59ec;
-  04000000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f33ccd4771932f5e467552e93ae367ab;
-  02000000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b70b9f3a5814ddeb6d3549d88c5b4656;
-  01000000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 5c01c66e9bf9617b155d3902722ccadc;
-  00800000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 1f47def31d2e7e286172b38119fde307;
-  00400000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 bd3c2f005cf0eb5ef737c29f457ed549;
-  00200000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 1d409243f79ce876d13b0fdfea26ccf8;
-  00100000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b879e37c2f435b0cb941f74892c1476f;
-  00080000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 58c6a8884bf8b110c9127893976a9e4e;
-  00040000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 7a258ac14cb88a31432ba1b320d254f6;
-  00020000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ff382f1b4bbb54c9f42b73b256f80d25;
-  00010000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 0cef334bcbe5d38e23a9780d2e3e9097;
-  00008000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 3225e13778d2a3bab1eb375e034478c4;
-  00004000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4ef73320931377f64e296e49c286e5c9;
-  00002000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 adbf2c07f2f42eb7d92acc07f9df7a5f;
-  00001000000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 bfca14ad6925ddb4f563048db1c6b485;
-  00000800000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 63f01ea46c82dc3b1d81eac5e4f1d687;
-  00000400000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b2f6eb69ce81accc720e705146cfc2a2;
-  00000200000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 85b1ff06090504848fdda74dd830e960;
-  00000100000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 5bcb44ab29d7c31def58c902c2491333;
-  00000080000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4d982cbc7c1455cde7c0de3f83fcbc5e;
-  00000040000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 32f08276e0633e1d819fc6227e631503;
-  00000020000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e6bebd4cddc205399126bfda486ed37c;
-  00000010000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 afe39df4f356aea5f07069455010d9ce;
-  00000008000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 a8c7b2c1e8e1ade5e28e4104ff716ba5;
-  00000004000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 fbb3e4ca3e710a5bd94b50726de5fdb1;
-  00000002000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 2091d65d6fbb8672d84655f33dc1473a;
-  00000001000000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 9c74519acc53498333791febfd0e5e8b;
-  00000000800000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ed44022a82468ed54203b5863b63061f;
-  00000000400000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 eae325499a1a9e8e1bd4d6f018e65551;
-  00000000200000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b134fe1498d7a1d926d3a623ffa5723e;
-  00000000100000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 343f8d08a35c272c5cd4064a42a7b6d8;
-  00000000080000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 79230ea5d7f6b5d85922ed7679aebe08;
-  00000000040000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d3f799e3579c68e10fb1c770b1cbb7c7;
-  00000000020000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 90c24054dc24772ecd92a67a43335320;
-  00000000010000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 bf38cfda7b75a478fa73316801883d34;
-  00000000008000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4323a85f7921a4a1fc072b72b6b46f50;
-  00000000004000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 3e10218fdefd9a0b91d9032d793aecc8;
-  00000000002000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 66a759ec5e5cdd9c27a4e97ff0b5aab8;
-  00000000001000000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 3730876a26727d44a46404f69ba99f09;
-  00000000000800000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 b277bd5a0e78eafc049bd9aa3393870f;
-  00000000000400000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 af05cdd3a6dd19fb0199933bdea3c20f;
-  00000000000200000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 0d962ec5f824d922924f3c39339fa934;
-  00000000000100000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 de695dab525ffebc039f63c3defb200b;
-  00000000000080000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f8ce4303ff6a523a60e3526a28c1c1de;
-  00000000000040000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c00c5250a33165254408992f6aa1fb97;
-  00000000000020000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 7e81d9c10bc3ac8fcac65079867183ff;
-  00000000000010000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 42f91fe46e5f6485973123b586cc2517;
-  00000000000008000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 0900c5c4bb963e1e421571056aeda9f0;
-  00000000000004000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 933312932700ef9c82333913782fc8fb;
-  00000000000002000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d78181179ac4cc05f38a1d134b29b70a;
-  00000000000001000000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 411b9bd8a8c3d3c9a2c375d28a336c4a;
-  00000000000000800000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 632433f8708bd47d6a083adbdf3a8982;
-  00000000000000400000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f037e3fcd3db611bd777420b8170df1b;
-  00000000000000200000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 31da207bfbdbb93157408ad2d7e559df;
-  00000000000000100000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 2837b13cb713b5fde1bc07cb7b2613d9;
-  00000000000000080000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c31906513814506753848c50ab7c8d13;
-  00000000000000040000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 014b54ca9f1d87c7711af20119b03afc;
-  00000000000000020000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 060903be7b215ee51fbce79205b0515a;
-  00000000000000010000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f91da002995fe07969ff63b8673fa75a;
-  00000000000000008000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 65a8b07ad4f77c8be4f27f975a42f2e7;
-  00000000000000004000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 31a157653449da846b5dade80e2f3ae8;
-  00000000000000002000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 1be98428352aeab7534e12463898bde5;
-  00000000000000001000000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 a7a50bec385145e784486d6d70552fbf;
-  00000000000000000800000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 eaacafae73701d566b24ab68350c4cb7;
-  00000000000000000400000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 deef8a7a5de90caaa0e3412356518d9a;
-  00000000000000000200000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 8d4373f4933353f589e42471ef35836c;
-  00000000000000000100000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 01436b7d351b9ff0fe85dab7ef77a020;
-  00000000000000000080000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 a6b2b93c4c6dafea4db5a4ecfee2c561;
-  00000000000000000040000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 7b0f7781683d890db4582d4399b07fab;
-  00000000000000000020000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 01c82b395331de265555d72df29c7efc;
-  00000000000000000010000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 5d9ba76d5b20b4b88b70b80c20c5e350;
-  00000000000000000008000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 92b2a69dd8a75d2edb01644a0b975c15;
-  00000000000000000004000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e2f6e46a2a899615969f4b751d55d57f;
-  00000000000000000002000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 97427298315d058eb2f7cdabd4a851c8;
-  00000000000000000001000000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 8f0f710a0cc1d6049ebb01974b76caad;
-  00000000000000000000800000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 2cf62d9d02afb40eed66fedb53c2db5c;
-  00000000000000000000400000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 fb215ab9ec3fafc5fd91cd9ad3cee2be;
-  00000000000000000000200000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4a37472335edaf7393a304d45a233085;
-  00000000000000000000100000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d22a878d2ca3a88f34acc92a4e26c738;
-  00000000000000000000080000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 f1a95970638dcbc69c4675e895370904;
-  00000000000000000000040000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 1660060085c0e241f88462bffbe67602;
-  00000000000000000000020000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 a097acb2eb5f779090f886beae746ae1;
-  00000000000000000000010000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 9ffe05163407ba53b62a35d857f58bc6;
-  00000000000000000000008000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 dfed8392eec1b389cbc261faf97c5c9e;
-  00000000000000000000004000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d2c1b3159129d86959f3aa9b70219a74;
-  00000000000000000000002000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 98c043b2e86cff626abf5fbc745d98a6;
-  00000000000000000000001000000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 35c5aed481c801a0ca78842273e0186d;
-  00000000000000000000000800000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ddaac5c7f13943e80d2244a4a19e9980;
-  00000000000000000000000400000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 51dbf12fc81e5ffe9b1ce9963636205f;
-  00000000000000000000000200000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 38ee89874d644ccdf9694280a6c48182;
-  00000000000000000000000100000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c3bc93ca8e8800622c92c56b99262ae2;
-  00000000000000000000000080000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 dc2c2b7558f75b71a9db34e971892171;
-  00000000000000000000000040000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 609bd72078f92ae345dcde14e6aba0e0;
-  00000000000000000000000020000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 cabc8bdda6e1979199f5010c3f8b8a31;
-  00000000000000000000000010000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c993d659ba4426dc30f8dc7ea03cd2ee;
-  00000000000000000000000008000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 5dd47466cbb15dca1485e04231d7491c;
-  00000000000000000000000004000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e1351ce84ded187e0f5aab9bb7198387;
-  00000000000000000000000002000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e5222c68fda26e5e62929c70233ad097;
-  00000000000000000000000001000000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 78cc456147db73850328241bdff861c0;
-  00000000000000000000000000800000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 4f10436e3ba4f38cd96744b897d5a136;
-  00000000000000000000000000400000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 12b698464abcb67c3956c5d1b9c62dfd;
-  00000000000000000000000000200000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 49de5db3e7d997c56dd2f82935e6617f;
-  00000000000000000000000000100000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 71ea115e54775680f16b1b9d7b2ee367;
-  00000000000000000000000000080000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 45b7e46c664a472af948b0c393f92af1;
-  00000000000000000000000000040000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 db3678b993ef5e48931b5bf84cece6eb;
-  00000000000000000000000000020000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 051c9a17d4ca77eabd8b9d9a1bce52d6;
-  00000000000000000000000000010000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e805aeeac134761ff7b3260bb4308a10;
-  00000000000000000000000000008000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 3301700109b460c7e41a51059f33004f;
-  00000000000000000000000000004000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d71f178093314e188bae26dde5a78927;
-  00000000000000000000000000002000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 31bb9cb46fbf607fcaa5932851899420;
-  00000000000000000000000000001000
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ea77bcd0ce469ab47a828dc6324c3651;
-  00000000000000000000000000000800
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e4596b0d33bdeb062a7ddb93e6efae94;
-  00000000000000000000000000000400
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 24d04f34b837461cd3b8d9c13afe6fe5;
-  00000000000000000000000000000200
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 ffb68c9ae4d7d2642bf5bee57d2bd914;
-  00000000000000000000000000000100
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 c008d35eb9de15700c0491319e6415f0;
-  00000000000000000000000000000080
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 92bfbbfcd2bbf54fff06af097893e9a3;
-  00000000000000000000000000000040
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 d2475279191bc4da183ee2dba75fce6d;
-  00000000000000000000000000000020
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 7b8adf2ef0e1f5fbb19cbd4b8fab1426;
-  00000000000000000000000000000010
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 0b07b9c4385bdc86447f535e09a9f424;
-  00000000000000000000000000000008
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 e7308875d8d6645719c076dd1660924b;
-  00000000000000000000000000000004
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 bc50d54a891d6102d0c02f471f1f0567;
-  00000000000000000000000000000002
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 2b14534ca7d9821a40b101035f681f0d;
-  00000000000000000000000000000001
-       0f1e2d3c4b5a69788796a5b4c3d2e1f0 69bd984641e0aa887bc23738f60070db;
-}
diff --git a/tests/sslprf b/tests/sslprf
deleted file mode 100644 (file)
index b24813d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# $Id: sslprf,v 1.1 2001/04/06 22:05:11 mdw Exp $
-#
-# SSL pseudo-random function
-
-sslprf {
-  # --- Generated using SSLeay ---
-
-  4837879a5040b1499a9cae62747e4857b090a0334683d8492d1d87933b58fa07523d4b8d0df762b62caddf7ac1304cd9 3ace3cb1ee080975da0dc748207c2bc0eb995746d0b37ab4789932a32ec5347b3ace3cb100000000b28539b8285cbc37622b65d8efcba4ad13eb42712c47d6f5 c15e3166e8a743e6b5da7d9cbcc08c2e4107887a70f2a4e16b54243276c48894569f2916c6cb610bb84b766b7283dca0a346fcce41683ec01f06c17e91758d5d31fbd1ca0a7d75b909035f04786f41efde988d20f5d1fecad337a3a23a16fde1beae5400bc3f357c;
-
-  53a82e555607a83890bfc633ff7f1d9ecc7d225f450dff3a8d46dd370033968fc456ae8b6fe3639c71fa2ba9d0f798aa 3ace3ca4ac5e36c228a5ce350f22261eadacdc48873b317843061aa679ed15e63ace3ca4000000009ba10a4a1837535a372de6784f037f6cc36c3113cdcc1465 798b2f8eee4cd6b35a220f8d446672762e8dd53bae7bd773877a1dfe0aa446b4274bafd546e94b1bbe4c2d56a6e60d06871b117a7d562859f36ce2082def1c134b1c117022fe449b2da85e6d2c8e763bec6e35889a315d8686e391c277377beb037dd91accddacd1;
-}
diff --git a/tests/tea b/tests/tea
deleted file mode 100644 (file)
index 492d21c..0000000
--- a/tests/tea
+++ /dev/null
@@ -1,76 +0,0 @@
-# $Id: tea,v 1.2 2000/08/16 17:57:14 mdw Exp $
-#
-# Test vectors for TEA
-
-# --- Generated from Needham and Wheeler's original implementation ---
-
-tea {
-  00000000000000000000000000000000 0000000000000000 41ea3a0a94baa940;
-  ffffffffffffffffffffffffffffffff ffffffffffffffff 319bbefb016abdb2;
-  00112233445566778899aabbccddeeff 0123456789abcdef 126c6b92c0653a3e;
-  00112233445566778899aabbccddeeff 67452301efcdab89 d667cc4e10bf6eb0;
-  00112233445566778899aabbccddeeff b3e551c7d8378a6c db21fb2a3118e62d;
-  d94576cd1a5f99e4155dc7bec5d33df2 d51399607f7aa9d7 7d1eb12827ef2121;
-  07ef12bc9d06d7da20131116b665e335 10b233473624ccd3 ae694e579daeff54;
-  c6462b48afd604b75fcc455506ffd411 3b905e951e4fafe7 d9633fcf13c30394;
-  be195f703d6fec2232cd0890c981b27d 15b623d1fa2df9df 916ffcb1abaf086b;
-  5b8410f7a9eb92da120810c56fcaf8c9 7c1035940696d91d 460aa2db964b580c;
-  b85c9e26661889d0ff1054c6be27fdeb 90b245144895f3ad 87d7e95a5a4aa89a;
-  a8a1e956d54d238f6ceab186e7ec99ed 4ef2cfd120b8d4dc 1752f2ee188018de;
-  8bc4879201a96368927ecceee67024ee f6cb5353f4a1c432 7cfa8e0718d59807;
-  f1372d85d8c3d1a60df57eedf317ab81 215c080cf158a09b 3b85115e0d6c5a94;
-  017f01683f5e009d196feeaad385c5a9 568583061da98d0d cb0e345182f4bf0b;
-  281c932ddd3c364b09f1896007ffab03 0558b306316b0823 e7adf267c7d841c2;
-  c1e95465c7ef8eb04254d1a5463c6a43 fdcb2764303222c7 ed48b228c11e7bc6;
-  0f86dd6c96dd31164b656b0f25e4b411 eaddba89070ec46c 89fb864135a57e33;
-  fbacfb479ae21194c35b8184e58dd66e c6507bcf99b9c2a1 670da449ce74c658;
-  2eb36c4a9598d471700a1330070fffc9 c380b0f1c21d4d37 d84fe611431c0b5e;
-  0a7f48127091780617a1f534b3271bc9 e5b7c1517f24f298 4be47c656cef6ffc;
-  303fb24822a1b8a84d0ece77b86380ff d14ddf77fdda17bf 1cc73315c9f72ab1;
-  f04ebf798c193f199c1f532af383555b b9682750bb15caad 2b5f318fb66806b9;
-  200c0ce59717d5d9af6813cd207fee73 9706769a18a2d03d 8e17eeb5008dc0cb;
-  2828d51f98ae0b33f4de2b7fbd18a529 edb76c54847da59e dfa6c29beb40f9af;
-  61aaba6be48b0d0d14fe5d27fab852a4 178a49bafba53f23 c3bbce6715d90ce6;
-  2080e2409ba01c8532fc84403ee8c06a df4cdb61a5f38536 b4e6359c9d9458aa;
-  271ad15192c4d1204a4a2561e3db6ff7 7c944d08def34c0c 195c0e8f49761539;
-  c1e297c0c761777d8a76fff02d22b859 f4c76c1d47fe568f 551ca67c7756ff56;
-  23c807a2ef0a551f858fd52d125a47d8 cab16583e15d0074 de472175d55372c9;
-  9fa5d4d8cbdfcecd559e3ce88bf78ee1 97b05c60774164ad bc4bd30cb50da39b;
-  24f4e91083139099d663647a7ffac321 7017a263985b735c e47fdf06a51d8c24;
-  7cf8626de76d8462218ed5c9dc8acc26 15475a90df04cd29 4df54282eaafa235;
-  3c6ad7df17332a3e1e3de06007387357 87ca0aaccf146cc8 f7360f57cfcc09ac;
-  24237a762d8a89383a2949f5a0f5ec08 9268af048ecbae67 e98e428a9d1fee9c;
-  209a2833a39472d9720380ffb2f74761 af0062cd77a84ebd 44cd624b87cbee77;
-  22ebe7a30e8855b3b453a6e926d4f187 f922ca875b991a31 1e92c0c51185f7c7;
-  1b5e23ebd915c1fee59f57dd91af7347 b4ecc305c3dbd8e5 063d8f75a7a77501;
-  6c21d105515290da29339f142685c135 a4c2f6dc597d13ea bf8ffec7550a496b;
-  01f728a7433a47b13de34fcc08958449 3af7f1ae0f58ab1d bba581d07e51d8d6;
-  9a2d4c50337d3ec337673782fd385601 791d8da8cbb0bc94 7d9a4f0363b6085f;
-  b3b99747560e246bcd0cdc3fb33e4910 91778f2bd9233375 4b85b79a58b1321e;
-  4b269e2e8dbd68b94066c95244c3a195 abfb6a33e1471e96 53d089e9313e832d;
-  d10b956f675dc2276b6dd90442bece3e dbedddb6a1c15a21 b81739d49c10b4fd;
-  28f8fab7541766f6dafbaa5b6f3bd700 2c14d5097ab11f61 c018b6e3cca4095f;
-  2b61e60478fa0c0edb9531f26791eff9 b84c80b2d245fdfc 2301e2d68d241622;
-  a6bfb85fa91b8ca4197c8b502a62f972 3daadd7a9633e19b 65bc93b4dbbd652f;
-  94e76e54d37f932cbcc069de6bf26d52 02739eeb468450fd a477a7ec244f1e9f;
-  82760ea1560e8f9d1e35f20cad1f26cc 34aa5952b5a9110f 2564284b47152721;
-  3aba91211327585e0f1270b59ef9277b b584d6b34b638ba4 c829dc4da560211f;
-  727074f35cd523eb6f8aafbbf76fd5b1 f0e9268a27ab70c6 f24b80555fdcb67f;
-  6e0aa1c91ea6315a4a7dd297ac5936a4 47374080f27fbb30 6fdb64c32920c0a5;
-  63bd2d37271a250c8593b433188cffd0 776927909196eec5 57bca56240b39c0b;
-  dc7beb423c2053156329d7ab79f4d1d6 24c0adb3777860ad e040f57fe32f2158;
-  ed219454883709efe884bbc9d30507a3 587b1683dff7f178 e2c6512996117ba9;
-  40509fc5c565e9b9f3995f3bc5d5c1f4 719a39f2302a98aa b8a9f3ab1b68ac1f;
-  f9f10ed2bc0193605913475fd54d69ae e35b94e2940a8db0 b23358feb43a29aa;
-  23003c3fbe9661b6b9386748982ac3e2 d1dfd47fac22b9ff 4165de32289acf6a;
-  a2caa563c2f19b10fbac1427e2177858 f7743dfe957cc82b d88dcd158b0d81c2;
-  8bb42b6937d65eac506e8326356071af 690a0fa32113bf34 9095cce6d70da9d6;
-  219c7f982a0c352977b978b91fcb3c45 8fb4cb86db41ce30 c688b48de8ec7e14;
-  157ff76f22538eede0528c541dbe7815 ea6cd44f238be18f 35578556b38660fa;
-  346194289f6d865237cc673c45415003 71690fd4ba3d75de 719f1f0a6b316a58;
-  032c8c1624f7f300d8a58d151de52d78 3c0f1746798ed5b7 62c9adb10b265534;
-  019471106a5cd4ee3d1f627213649b80 558a8d7a4cdc0822 014521292dcbff85;
-  45aa90191c449dbf9c541fb476d1bf74 bfba3dfd06e77671 b6a6825c69d9d5eb;
-  c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d d33c2e41dd5da131;
-  af4f4615c7c298639b9728251991419f 1e268f9e710313b5 a9478f8cf88b7e10;
-}
diff --git a/tests/tiger b/tests/tiger
deleted file mode 100644 (file)
index 7679aa4..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-# $Id: tiger,v 1.1 2000/07/15 10:17:19 mdw Exp $
-#
-# Test vectors for Tiger
-
-# --- The main hash ---
-#
-# These are taken from the reference implementation.
-
-tiger {
-  ""           3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3;
-  "abc"                2aab1484e8c158f2bfb8c5ff41b57a525129131c957b5f93;
-  "Tiger"      dd00230799f5009fec6debc838bb6a27df2b9d6f110c7937;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
-               f71c8583902afb879edfe610f82c0d4786a3a534504486b5;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789"
-               48ceeb6308b87d46e95d656112cdf18d97915f9765658957;
-  "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"
-               8a866829040a410c729ad23f5ada711603b3cdd357e4c15e;
-  "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge."
-               ce55a6afd591f5ebac547ff84f89227f9331dab0b611c889;
-  "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996."
-               631abdd103eb9a3d245b6dfd4d77b257fc7439501d1568dd;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
-               c54034e5b43eb8005848a7e0ae6aac76e4ff590ae715fd25;
-}
-
-# --- HMAC mode ---
-#
-# No test vectors available.  The HMAC implementation has not been tested
-# against an external reference.  The HMAC code is autogenerated anyway, and
-# ought to be reliable and correct.
-#
-# These test vectors are here to spot changes in behaviour rather than ensure
-# interoperability.
-
-tiger-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       0a402190741a498d6d4a09016b0895cb6419ff849b196137;
-
-  "what do ya want for nothing?"
-        4a656665
-        3a351b1dec6075d6290e68b604e553821edc39041b82da83;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-        e09ab076337fba2b5c4a83e9dbfb62993710992934f0946c;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-        0102030405060708090a0b0c0d0e0f10111213141516171819
-        a452fa58bdb38b70207c472c5ee54b1e40b1893e6d604b19;
-
-  "Test With Truncation"
-        0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-        95981aaf2303d232824c504cc51459ea8275734336e92b1a;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-        ebbb20db7af380b5dffff39f671e1224e994d840408a7941;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-        308ebb428666c75b50d0442fe008777f4c208c7fa6d5ce7c;
-}
diff --git a/tests/tlsprf b/tests/tlsprf
deleted file mode 100644 (file)
index bcbbb5c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# $Id: tlsprf,v 1.2 2001/04/06 22:06:01 mdw Exp $
-#
-# TLS pseudo-random function
-
-tlsprf {
-  # --- Generated using SSLeay ---
-
-  3bfcccfb9e0bf44585b7a5ffcc7ff3b27be9462d5190664b96613a089f21c06e6f4788e3a963683d5cddea86982682dc 7365727665722066696e697368656416da63a061e9dee1884336c7345060d39d8d5fb7cd42a6b15bdd4eda44890edc41137ffe 4975842aca48f758ede77403;
-
-  3bfcccfb9e0bf44585b7a5ffcc7ff3b27be9462d5190664b96613a089f21c06e6f4788e3a963683d5cddea86982682dc 6b657920657870616e73696f6e3acb7aca624a68136e34e262b3e813ea234662db262a2c5791986fbe101707f7201dca6e8c753a5f2d8be10a69e08577ff9d6ec92d8c3ed17be5ef40f029ad11 be41fda006e5fc3423589714c374f7de3a8bc1315610a419acdf62aee16462dcec00aa5ca4e1d615a3d0b87a4cf10bc9cfc3509f2a9a879708092ce0bd54cc12b3fa2238569a8327cbd314f779f653783f5119a81986e49750b4e300e6cbbebcc782a65cc72f302c;
-}
diff --git a/tests/whirlpool b/tests/whirlpool
deleted file mode 100644 (file)
index 5f2383e..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-# Test vectors for the Whirlpool hash function
-#
-# $Id: sha 2187 2004-09-04 07:50:08Z mdw $
-
-# --- Basic hash function ---
-#
-# Some of these are taken from the ISO test vectors from the Whirlpool
-# distribution.
-
-whirlpool {
-  ""
-    19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3;
-  "a"
-    8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42d11bc645413aeff63a42391a39145a591a92200d560195e53b478584fdae231a;
-  "abc"
-    4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c7181eebdb6c57e277d0e34957114cbd6c797fc9d95d8b582d225292076d4eef5;
-  "message digest"
-    378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b8421557659ef55c106b4b52ac5a4aaa692ed920052838f3362e86dbd37a8903e;
-  "abcdefghijklmnopqrstuvwxyz"
-    f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b08bf2a9251c30b6a0b8aae86177ab4a6f68f673e7207865d5d9819a3dba4eb3b;
-  "abcdbcdecdefdefgefghfghighijhijk"
-    2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c6916bdc8031bc5be1b7b947639fe050b56939baaa0adff9ae6745b7b181c3be3fd;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-    dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e08eba26629129d8fb7cb57211b9281a65517cc879d7b962142c65f5a7af01467;
-}
-
-whirlpool-rep {
-  "1234567890" 8
-    466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb6014294d5bd8df2a6c44e538cd047b2681a51a2c60481e88c5a20b2c2a80cf3a9a083b;
-  "a" 1000000
-    0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af51fc15490eddc47af32bb2b66c34ff9ad8c6008ad677f77126953b226e4ed8b01;
-}
-
-# --- HMAC mode ---
-#
-# Home-made test vectors, for regression.
-
-whirlpool-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       f300802099638aa1df411accbae11c2947fbcb2a4186f1c9bc6daa75dc3ad46dd89739ae5fb39b5c4afc098435c3ba0f7f55900e8c719711cbaee6d473eef0ba;
-
-  "what do ya want for nothing?"
-       4a656665
-       3d595ccd1d4f4cfd045af53ba7d5c8283fee6ded6eaf1269071b6b4ea64800056b5077c6a942cfa1221bd4e5aed791276e5dd46a407d2b8007163d3e7cd1de66;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       4fb33849b7d0268ab9f3bc90cfc6ca90639338c32bca959b7bc47a61f4d946ca6c6a227e97205a18fe676907ce78d0f8892fcf73f44da714cb210188b92cabc9;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       35bc33e2ed71e1cb01c140ddd3291ae3f84e9f0dce18005a1123df199983a211fe744b244449a1c093b17584069359bc6a95352271d78e2ef7a6f21dc28ab3c1;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       502a6d22d0f8e67196dfed2a9d9ef988714db9db2e2f0ad6c30e52eed830aa348ee98744ddd3ff1974c7fe275e078b79a6ba8c967c5a41b290f6edca01183b1a;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       dd90bd637cfcd27ca914c290f33402cf68576d6e70601af0295f6b9dafa9d988d8b8fb4fde8605ac544638158dba2baa90a2bf882546cd0b876d59ab3f18962e;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       faf529af18a0f569480fd001122bb446b32a3cf758c385cec4adad9c73c77327812e260b7082011a3eb1071e71a50e1c3d37a8963f8b6a64a31cc017db1d619c;
-}
diff --git a/tests/whirlpool256 b/tests/whirlpool256
deleted file mode 100644 (file)
index 968777c..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-# Test vectors for the Whirlpool hash function
-#
-# $Id: sha 2187 2004-09-04 07:50:08Z mdw $
-
-# --- Basic hash function ---
-#
-# Some of these are taken from the ISO test vectors from the Whirlpool
-# distribution.
-
-whirlpool256 {
-  ""
-    19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a7;
-  "a"
-    8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42;
-  "abc"
-    4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c;
-  "message digest"
-    378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b;
-  "abcdefghijklmnopqrstuvwxyz"
-    f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b;
-  "abcdbcdecdefdefgefghfghighijhijk"
-    2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c69;
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-    dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e;
-}
-
-whirlpool256-rep {
-  "1234567890" 8
-    466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb601429;
-  "a" 1000000
-    0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af5;
-}
-
-# --- HMAC mode ---
-#
-# Home-made test vectors, for regression.
-
-whirlpool256-hmac {
-  "Hi There"
-       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
-       9ab3bbb27b85df2edc51f2e05c880560439547e7c2772f8cec6ae00bead0bd7e;
-
-  "what do ya want for nothing?"
-       4a656665
-       977fd7f1d53e8af854404262630bfac20269ab3fc2fccabecd8feaa05b8cdabb;
-
-  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       6d418c9fe3d422200ea8cf7d0d73591ca5714f49c38907c80fc96b3934ab8fc2;
-
-  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
-       0102030405060708090a0b0c0d0e0f10111213141516171819
-       e0a3553419a54385ce04435bbb2bbf1d69d7626d8fab4f60e87a84fab731caab;
-
-  "Test With Truncation"
-       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
-       2a4f40079e618c3a8467dd1a284af43662f84b137d93d54e5623884a047f546f;
-
-  "Test Using Larger Than Block-Size Key - Hash Key First"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       17564185de7d845576f42fbdcd027073bca1a059931ce4a901ae8662ad19caf0;
-
-  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-       0bdc8bf26ff0a71201fbeef2d51f35bcbc3e8b0daeddedcbec2ca2b2e8f457b2;
-}
diff --git a/tests/xtea b/tests/xtea
deleted file mode 100644 (file)
index fcc68b9..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-# $Id: xtea,v 1.1 2000/07/15 13:44:32 mdw Exp $
-#
-# Test vectors for XTEA
-
-# --- Generated from Needham and Wheeler's original implementation ---
-
-xtea {
-  00112233445566778899aabbccddeeff 0123456789abcdef b8bf2821622b5b30;
-  d94576cd1a5f99e4155dc7bec5d33df2 d51399607f7aa9d7 782e4e131c5ba746;
-  07ef12bc9d06d7da20131116b665e335 10b233473624ccd3 57733a1deece283e;
-  c6462b48afd604b75fcc455506ffd411 3b905e951e4fafe7 776f4965deb65775;
-  be195f703d6fec2232cd0890c981b27d 15b623d1fa2df9df 3bd5ad5c9ed6101e;
-  5b8410f7a9eb92da120810c56fcaf8c9 7c1035940696d91d 5f93fa1d06991415;
-  b85c9e26661889d0ff1054c6be27fdeb 90b245144895f3ad 6105bfb0947828b7;
-  a8a1e956d54d238f6ceab186e7ec99ed 4ef2cfd120b8d4dc 51fae58a10f7c3dd;
-  8bc4879201a96368927ecceee67024ee f6cb5353f4a1c432 550ad71ba8a34568;
-  f1372d85d8c3d1a60df57eedf317ab81 215c080cf158a09b 13d1e24ba9ff7b63;
-  017f01683f5e009d196feeaad385c5a9 568583061da98d0d 6439b1dfe2ecb541;
-  281c932ddd3c364b09f1896007ffab03 0558b306316b0823 c8f82fe4491a8917;
-  c1e95465c7ef8eb04254d1a5463c6a43 fdcb2764303222c7 244dbfa1d2c914e4;
-  0f86dd6c96dd31164b656b0f25e4b411 eaddba89070ec46c 5a4909646763454f;
-  fbacfb479ae21194c35b8184e58dd66e c6507bcf99b9c2a1 6f08ec714e8a7c18;
-  2eb36c4a9598d471700a1330070fffc9 c380b0f1c21d4d37 72d4d4bdf5c00585;
-  0a7f48127091780617a1f534b3271bc9 e5b7c1517f24f298 64374b40bb732354;
-  303fb24822a1b8a84d0ece77b86380ff d14ddf77fdda17bf 014f1e707d02c8d8;
-  f04ebf798c193f199c1f532af383555b b9682750bb15caad 9001d21b57ab5360;
-  200c0ce59717d5d9af6813cd207fee73 9706769a18a2d03d 835fd788c089fd45;
-  2828d51f98ae0b33f4de2b7fbd18a529 edb76c54847da59e b0c0125494d39ce9;
-  61aaba6be48b0d0d14fe5d27fab852a4 178a49bafba53f23 ade26742f25efbe1;
-  2080e2409ba01c8532fc84403ee8c06a df4cdb61a5f38536 9c895e72168b409e;
-  271ad15192c4d1204a4a2561e3db6ff7 7c944d08def34c0c b784e23e00b3b498;
-  c1e297c0c761777d8a76fff02d22b859 f4c76c1d47fe568f 62f9e58b0364b0b6;
-  23c807a2ef0a551f858fd52d125a47d8 cab16583e15d0074 4563be765e74653a;
-  9fa5d4d8cbdfcecd559e3ce88bf78ee1 97b05c60774164ad 714807767366854b;
-  24f4e91083139099d663647a7ffac321 7017a263985b735c cc68e1ed7f7c7832;
-  7cf8626de76d8462218ed5c9dc8acc26 15475a90df04cd29 416eab1ebc155782;
-  3c6ad7df17332a3e1e3de06007387357 87ca0aaccf146cc8 ded575554058ef42;
-  24237a762d8a89383a2949f5a0f5ec08 9268af048ecbae67 899b9b877106c764;
-  209a2833a39472d9720380ffb2f74761 af0062cd77a84ebd 26db40c151b74530;
-  22ebe7a30e8855b3b453a6e926d4f187 f922ca875b991a31 2763f255636a34c1;
-  1b5e23ebd915c1fee59f57dd91af7347 b4ecc305c3dbd8e5 fbbec8f5dbf4cefd;
-  6c21d105515290da29339f142685c135 a4c2f6dc597d13ea 7409829de05ae6d1;
-  01f728a7433a47b13de34fcc08958449 3af7f1ae0f58ab1d 950083fbd332a987;
-  9a2d4c50337d3ec337673782fd385601 791d8da8cbb0bc94 13f87f8d3326553f;
-  b3b99747560e246bcd0cdc3fb33e4910 91778f2bd9233375 2b1f2747b356e119;
-  4b269e2e8dbd68b94066c95244c3a195 abfb6a33e1471e96 8ce0dc718e757924;
-  d10b956f675dc2276b6dd90442bece3e dbedddb6a1c15a21 19df78dea26ea579;
-  28f8fab7541766f6dafbaa5b6f3bd700 2c14d5097ab11f61 3a6fd0a5fef50079;
-  2b61e60478fa0c0edb9531f26791eff9 b84c80b2d245fdfc f24ea37046b97a03;
-  a6bfb85fa91b8ca4197c8b502a62f972 3daadd7a9633e19b 4de5c07ea1564a64;
-  94e76e54d37f932cbcc069de6bf26d52 02739eeb468450fd 0d4ef5d93f419069;
-  82760ea1560e8f9d1e35f20cad1f26cc 34aa5952b5a9110f 7676f2746bfac3b7;
-  3aba91211327585e0f1270b59ef9277b b584d6b34b638ba4 2cfa1f17178df25d;
-  727074f35cd523eb6f8aafbbf76fd5b1 f0e9268a27ab70c6 609aee69ed6e2a8e;
-  6e0aa1c91ea6315a4a7dd297ac5936a4 47374080f27fbb30 5d86f6451024e051;
-  63bd2d37271a250c8593b433188cffd0 776927909196eec5 ec617cc3810e278c;
-  dc7beb423c2053156329d7ab79f4d1d6 24c0adb3777860ad 7f6f6083713a68ba;
-  ed219454883709efe884bbc9d30507a3 587b1683dff7f178 86a95a8f48fa13b0;
-  40509fc5c565e9b9f3995f3bc5d5c1f4 719a39f2302a98aa 503f9481c7049890;
-  f9f10ed2bc0193605913475fd54d69ae e35b94e2940a8db0 59bc9b0bd5004dae;
-  23003c3fbe9661b6b9386748982ac3e2 d1dfd47fac22b9ff 756ec1ac4fa8deac;
-  a2caa563c2f19b10fbac1427e2177858 f7743dfe957cc82b 57ae9c0144dbb9d3;
-  8bb42b6937d65eac506e8326356071af 690a0fa32113bf34 5136052b310e7038;
-  219c7f982a0c352977b978b91fcb3c45 8fb4cb86db41ce30 fa01561e5b9311ab;
-  157ff76f22538eede0528c541dbe7815 ea6cd44f238be18f 0c3f632af5cee432;
-  346194289f6d865237cc673c45415003 71690fd4ba3d75de c4448db8c1144435;
-  032c8c1624f7f300d8a58d151de52d78 3c0f1746798ed5b7 e1bfbd2a7d414c8a;
-  019471106a5cd4ee3d1f627213649b80 558a8d7a4cdc0822 c90e5257ea513ef8;
-  45aa90191c449dbf9c541fb476d1bf74 bfba3dfd06e77671 bc715327ada1b56b;
-  c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d 2b4195c3d67e3f99;
-  af4f4615c7c298639b9728251991419f 1e268f9e710313b5 2536ccd8fdfe30e1;
-}
diff --git a/tiger-base.h b/tiger-base.h
deleted file mode 100644 (file)
index 6b6a81e..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/* -*-c-*-
- *
- * $Id: tiger-base.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Common definitions for the Tiger hash function
- *
- * (c) 2000 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.
- */
-
-#ifndef CATACOMB_TIGER_BASE_H
-#define CATACOMB_TIGER_BASE_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-/*----- Macros provided ---------------------------------------------------*/
-
-/* --- The guts of a single round --- */
-
-#define TIGER_ROUND(a, b, c, x, n, op) do {                            \
-  kludge64 _t;                                                         \
-  XOR64(c, c, x);                                                      \
-  _t =         s[0][U8(LO64(c) >>  0)];                                \
-  XOR64(_t, _t, s[1][U8(LO64(c) >> 16)]);                              \
-  XOR64(_t, _t, s[2][U8(HI64(c) >>  0)]);                              \
-  XOR64(_t, _t, s[3][U8(HI64(c) >> 16)]);                              \
-  SUB64(a, a, _t);                                                     \
-  _t =         s[3][U8(LO64(c) >>  8)];                                \
-  XOR64(_t, _t, s[2][U8(LO64(c) >> 24)]);                              \
-  XOR64(_t, _t, s[1][U8(HI64(c) >>  8)]);                              \
-  XOR64(_t, _t, s[0][U8(HI64(c) >> 24)]);                              \
-  ADD64(b, b, _t);                                                     \
-  LSL64_(_t, b, n);                                                    \
-  op##64(b, _t, b);                                                    \
-} while (0)
-
-/* --- One pass over the buffer --- */
-
-#define TIGER_PASS(a, b, c, x, n, op) do {                             \
-  TIGER_ROUND(a, b, c, x[0], n, op);                                   \
-  TIGER_ROUND(b, c, a, x[1], n, op);                                   \
-  TIGER_ROUND(c, a, b, x[2], n, op);                                   \
-  TIGER_ROUND(a, b, c, x[3], n, op);                                   \
-  TIGER_ROUND(b, c, a, x[4], n, op);                                   \
-  TIGER_ROUND(c, a, b, x[5], n, op);                                   \
-  TIGER_ROUND(a, b, c, x[6], n, op);                                   \
-  TIGER_ROUND(b, c, a, x[7], n, op);                                   \
-} while (0)
-
-/* --- A step in the `key schedule' --- */
-
-#define TIGER_KSTEP(a, b, c, d, op, n) do {                            \
-  kludge64 _u;                                                         \
-  XOR64(b, b, a);                                                      \
-  ADD64(c, c, b);                                                      \
-  CPL64(_u, b); op##64_(_u, _u, n); XOR64(_u, _u, c); SUB64(d, d, _u); \
-} while (0)
-
-/* --- The `key schedule' -- mangle the buffer --- */
-
-#define TIGER_KSCHED(x) do {                                           \
-  kludge64 _t;                                                         \
-                                                                       \
-  SET64(_t, 0xa5a5a5a5, 0xa5a5a5a5);                                   \
-  XOR64(_t, _t, x[7]); SUB64(x[0], x[0], _t);                          \
-  TIGER_KSTEP(x[0], x[1], x[2], x[3], LSL, 19);                                \
-  TIGER_KSTEP(x[3], x[4], x[5], x[6], LSR, 23);                                \
-  TIGER_KSTEP(x[6], x[7], x[0], x[1], LSL, 19);                                \
-  TIGER_KSTEP(x[1], x[2], x[3], x[4], LSR, 23);                                \
-  XOR64(x[5], x[5], x[4]);                                             \
-  ADD64(x[6], x[6], x[5]);                                             \
-  SET64(_t, 0x01234567, 0x89abcdef);                                   \
-  XOR64(_t, _t, x[6]); SUB64(x[7], x[7], _t);                          \
-} while (0)
-
-/* --- The Tiger compression function --- */
-
-#define TIGER_CORE(a, b, c, x) do {                                    \
-  kludge64 _a, _b, _c;                                                 \
-  _a = a, _b = b, _c = c;                                              \
-  TIGER_PASS(_a, _b, _c, x, 2, ADD);                                   \
-  TIGER_KSCHED(x);                                                     \
-  TIGER_PASS(_c, _a, _b, x, 3, SUB);                                   \
-  TIGER_KSCHED(x);                                                     \
-  TIGER_PASS(_b, _c, _a, x, 3, ADD);                                   \
-  XOR64(a, _a, a); SUB64(b, _b, b); ADD64(c, _c, c);                   \
-} while (0)
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/tiger-mktab.c b/tiger-mktab.c
deleted file mode 100644 (file)
index 222c523..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/* -*-c-*-
- *
- * $Id: tiger-mktab.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * Generate S-boxes for the Tiger hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "tiger-base.h"
-
-/*----- Data structures ---------------------------------------------------*/
-
-/*----- Static variables --------------------------------------------------*/
-
-static kludge64 s[4][256];
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- The basic Tiger compression function --- */
-
-static void tiger(kludge64 *x, kludge64 *ss)
-{
-  TIGER_CORE(ss[0], ss[1], ss[2], x);
-}
-
-/* --- The S-box generator --- */
-
-void gen(const char *buf, unsigned passes)
-{
-  kludge64 x[8], ss[3];
-  unsigned i, j, k, b;
-  unsigned q, n;
-  uint32 t;
-  const char *p;
-
-  for (i = 0; i < 256; i++) {
-    for (j = 0; j < 4; j++) {
-      uint32 z = 0x01010101 * i;
-      SET64(s[j][i], z, z);
-    }
-  }
-
-  SET64(ss[0], 0x01234567, 0x89abcdef);
-  SET64(ss[1], 0xfedcba98, 0x76543210);
-  SET64(ss[2], 0xf096a5b4, 0xc3b2e187);
-
-  q = 2;
-  for (i = 0; i < passes; i++) {
-    for (j = 0; j < 256; j++) {
-      for (k = 0; k < 4; k++) {
-       q++;
-       if (q == 3) {
-         q = 0;
-         for (p = buf, n = 0; n < 8; n++, p += 8)
-           LOAD64_L_(x[n], p);
-         tiger(x, ss);
-       }
-       for (b = 0; b < 32; b += 8) {
-         n = U8(LO64(ss[q]) >> b);
-         t = (LO64(s[k][j]) ^ LO64(s[k][n])) & (0xff << b);
-         SET64(s[k][j], HI64(s[k][j]), LO64(s[k][j]) ^ t);
-         SET64(s[k][n], HI64(s[k][n]), LO64(s[k][n]) ^ t);
-       }
-       for (b = 0; b < 32; b += 8) {
-         n = U8(HI64(ss[q]) >> b);
-         t = (HI64(s[k][j]) ^ HI64(s[k][n])) & (0xff << b);
-         SET64(s[k][j], HI64(s[k][j]) ^ t, LO64(s[k][j]));
-         SET64(s[k][n], HI64(s[k][n]) ^ t, LO64(s[k][n]));
-       }
-      }
-    }
-  }
-}
-
-int main(void)
-{
-  unsigned i, j;
-
-  gen("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham", 5);
-
-  fputs("\
-/* -*-c-*-\n\
- *\n\
- * S-boxes for Tiger [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_TIGER_TAB_H\n\
-#define CATACOMB_TIGER_TAB_H\n\
-\n\
-#define TIGER_S {                                                      \\\n\
-  { ", stdout);
-
-  for (i = 0; i < 4; i++) {
-    for (j = 0; j < 256; j++) {
-#ifdef HAVE_UINT64
-      printf("{ 0x%016llxull }", s[i][j].i);
-#else
-      printf("{ 0x%08lx, 0x%08lx }",
-            (unsigned long)s[i][j].hi, (unsigned long)s[i][j].lo);
-#endif
-      if (j == 255) {
-       if (i == 3)
-         fputs(" }             \\\n}\n", stdout);
-       else
-         fputs(" },            \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (j % 2 == 1)
-       fputs(",                \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  fputs("\n#endif\n", stdout);
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/tiger.c b/tiger.c
deleted file mode 100644 (file)
index 87f3ca9..0000000
--- a/tiger.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* -*-c-*-
- *
- * $Id: tiger.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The Tiger hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash-def.h"
-#include "hash.h"
-#include "tiger.h"
-#include "tiger-tab.h"
-#include "tiger-base.h"
-
-/*----- S-boxes -----------------------------------------------------------*/
-
-static const kludge64 s[4][256] = TIGER_S;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @tiger_compress@ --- *
- *
- * Arguments:  @tiger_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                Tiger compression function.
- */
-
-void tiger_compress(tiger_ctx *ctx, const void *sbuf)
-{
-  kludge64 x[8];
-  int i;
-  const octet *p;
-  for (i = 0, p = sbuf; i < 8; i++, p += 8)
-    LOAD64_L_(x[i], p);
-  TIGER_CORE(ctx->a, ctx->b, ctx->c, x);
-}
-
-/* --- @tiger_init@ --- *
- *
- * Arguments:  @tiger_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void tiger_init(tiger_ctx *ctx)
-{
-  SET64(ctx->a, 0x01234567, 0x89abcdef);
-  SET64(ctx->b, 0xfedcba98, 0x76543210);
-  SET64(ctx->c, 0xf096a5b4, 0xc3b2e187);
-  ctx->off = 0;
-  ctx->nl = ctx->nh = 0;
-}
-
-/* --- @tiger_set@ --- *
- *
- * Arguments:  @tiger_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 tiger_set(tiger_ctx *ctx, const void *buf, unsigned long count)
-{
-  const octet *p = buf;
-  LOAD64_L_(ctx->a, p +         0);
-  LOAD64_L_(ctx->b, p +         8);
-  LOAD64_L_(ctx->c, p + 16);
-  ctx->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @tiger_hash@ --- *
- *
- * Arguments:  @tiger_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 tiger_hash(tiger_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(TIGER, tiger, ctx, buf, sz);
-}
-
-/* --- @tiger_done@ --- *
- *
- * Arguments:  @tiger_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-void tiger_done(tiger_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  HASH_PAD(TIGER, tiger, ctx, 0x01u, 0, 8);
-  STORE32_L(ctx->buf + TIGER_BUFSZ - 8, ctx->nl << 3);
-  STORE32_L(ctx->buf + TIGER_BUFSZ - 4, (ctx->nl >> 29) | (ctx->nh << 3));
-  tiger_compress(ctx, ctx->buf);
-  STORE64_L_(p +  0, ctx->a);
-  STORE64_L_(p +  8, ctx->b);
-  STORE64_L_(p + 16, ctx->c);
-}
-
-/* --- @tiger_state@ --- *
- *
- * Arguments:  @tiger_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 @tiger_set@.
- */
-
-unsigned long tiger_state(tiger_ctx *ctx, void *state)
-{
-  octet *p = state;
-  STORE64_L_(p +  0, ctx->a);
-  STORE64_L_(p +  8, ctx->b);
-  STORE64_L_(p + 16, ctx->c);
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(TIGER, tiger)
-
-/* --- Test code --- */
-
-HASH_TEST(TIGER, tiger)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/tiger.h b/tiger.h
deleted file mode 100644 (file)
index 78e83f2..0000000
--- a/tiger.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/* -*-c-*-
- *
- * $Id: tiger.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The Tiger hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Tiger hash function ----------------------------------*
- *
- * Tiger was designed by Eli Biham and Ross Anderson to be an efficient and
- * secure hash function which worked well on 64-bit processors.  This
- * implementation should work everywhere, but it'll be faster if real 64-bit
- * arithmetic is available.
- *
- * I don't know of any really good analysis of Tiger.
- */
-
-#ifndef CATACOMB_TIGER_H
-#define CATACOMB_TIGER_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define TIGER_BUFSZ 64
-#define TIGER_HASHSZ 24
-#define TIGER_STATESZ 24
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct tiger_ctx {
-  kludge64 a, b, c;                    /* Chaining variables */
-  uint32 nl, nh;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[TIGER_BUFSZ];              /* Accumulation buffer */
-} tiger_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @tiger_compress@ --- *
- *
- * Arguments:  @tiger_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                Tiger compression function.
- */
-
-extern void tiger_compress(tiger_ctx */*ctx*/, const void */*sbuf*/);
-
-/* --- @tiger_init@ --- *
- *
- * Arguments:  @tiger_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void tiger_init(tiger_ctx */*ctx*/);
-
-/* --- @tiger_set@ --- *
- *
- * Arguments:  @tiger_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 tiger_set(tiger_ctx */*ctx*/, const void */*buf*/,
-                   unsigned long /*count*/);
-
-/* --- @tiger_hash@ --- *
- *
- * Arguments:  @tiger_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 tiger_hash(tiger_ctx */*ctx*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @tiger_done@ --- *
- *
- * Arguments:  @tiger_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 tiger_done(tiger_ctx */*ctx*/, void */*hash*/);
-
-/* --- @tiger_state@ --- *
- *
- * Arguments:  @tiger_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 @tiger_set@.
- */
-
-extern unsigned long tiger_state(tiger_ctx */*ctx*/, void */*state*/);
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash tiger;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/tlsprf.c b/tlsprf.c
deleted file mode 100644 (file)
index 04c4c25..0000000
--- a/tlsprf.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/* -*-c-*-
- *
- * $Id: tlsprf.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The TLS pseudo-random function
- *
- * (c) 2001 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/alloc.h>
-#include <mLib/dstr.h>
-#include <mLib/sub.h>
-
-#include "arena.h"
-#include "gmac.h"
-#include "grand.h"
-#include "paranoia.h"
-#include "tlsprf.h"
-
-/*----- The data expansion function ---------------------------------------*/
-
-/* --- @tlsdx_init@ --- *
- *
- * Arguments:  @tlsdx_ctx *c@ = pointer to a context
- *             @gmac *m@ = pointer to a generic MAC instance
- *             @const void *sd@ = pointer to the seed block
- *             @size_t sdsz@ = size of the seed block
- *
- * Returns:    ---
- *
- * Use:                Initializes a context for the TLS data expansion function.
- *             This doesn't take ownership of the MAC instance or the seed
- *             memory, nor does it allocate copies.
- */
-
-void tlsdx_init(tlsdx_ctx *c, gmac *m, const void *sd, size_t sdsz)
-{
-  c->k = m;
-  c->hashsz = GM_CLASS(c->k)->hashsz;
-  c->sd = sd; c->sdsz = sdsz;
-
-  c->i = GM_INIT(c->k);
-  GH_HASH(c->i, sd, sdsz);
-  c->ai = GH_DONE(c->i, 0);
-  c->o = GM_INIT(c->k);
-  GH_HASH(c->o, c->ai, c->hashsz);
-  GH_HASH(c->o, sd, sdsz);
-  c->p = GH_DONE(c->o, 0);
-  c->sz = c->hashsz;
-}
-
-/* --- @tlsdx_encrypt@ --- *
- *
- * Arguments:  @tlsdx_ctx *c@ = pointer to a context
- *             @const void *src@ = pointer to source data
- *             @void *dest@ = pointer to destination buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    ---
- *
- * Use:                Encrypts data using the TLS data expansion function.  If the
- *             destination pointer is null, the generator is spun and no
- *             output is produced; if the source pointer is null, raw output
- *             from the generator is written; otherwise, the source data is
- *             XORed with the generator output.
- */
-
-void tlsdx_encrypt(tlsdx_ctx *c, const void *src, void *dest, size_t sz)
-{
-  const octet *s = src;
-  octet *d = dest;
-  ghash *h;
-  size_t i;
-  size_t n;
-
-  while (sz) {
-    if (c->sz)
-      n = c->sz;
-    else {
-      h = GM_INIT(c->k);
-      GH_HASH(h, c->ai, c->hashsz);
-      c->ai = GH_DONE(h, 0);
-      GH_DESTROY(c->i);
-      c->i = h;
-      GH_DESTROY(c->o);
-      h = c->o = GM_INIT(c->k);
-      GH_HASH(h, c->ai, c->hashsz);
-      GH_HASH(h, c->sd, c->sdsz);
-      c->p = GH_DONE(h, 0);
-      c->sz = n = c->hashsz;
-    }
-    if (n > sz)
-      n = sz;
-    if (d) {
-      if (!s)
-       memcpy(d, c->p, n);
-      else {
-       for (i = 0; i < n; i++) d[i] = s[i] ^ c->p[i];
-       s += n;
-      }
-      d += n;
-    }
-    c->p += n;
-    c->sz -= n;
-    sz -= n;
-  }
-}
-
-/* --- @tlsdx_free@ --- *
- *
- * Arguments:  @tlsdx_ctx *c@ = pointer to the context block
- *
- * Returns:    ---
- *
- * Use:                Frees a context for the TLS data expansion function
- */
-
-void tlsdx_free(tlsdx_ctx *c)
-{
-  GH_DESTROY(c->i);
-  GH_DESTROY(c->o);
-}
-
-/* --- Generic random number generator --- */
-
-typedef struct dx_grctx {
-  grand r;
-  grand_ops ops;
-  tlsdx_ctx dx;
-} dx_grctx;
-
-static void dx_grdestroy(grand *r)
-{
-  dx_grctx *g = (dx_grctx *)r;
-  xfree((char *)g->ops.name);
-  xfree((octet *)g->dx.sd);
-  g->dx.k->ops->destroy(g->dx.k);
-  tlsdx_free(&g->dx);
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static void dx_seed(dx_grctx *g, const void *p, size_t sz)
-{
-  octet *q;
-  xfree((octet *)g->dx.sd);
-  g->dx.sd = q = xmalloc(sz);
-  memcpy(q, p, sz);
-  g->dx.sdsz = sz;
-}
-
-static int dx_grmisc(grand *r, unsigned op, ...)
-{
-  dx_grctx *g = (dx_grctx *)r;
-  va_list ap;
-  int rc = 0;
-  uint32 i;
-  octet buf[4];
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDBLOCK:
-       case GRAND_SEEDRAND:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT:
-      i = va_arg(ap, unsigned);
-      STORE32(buf, i);
-      dx_seed(g, buf, sizeof(buf));
-      break;
-    case GRAND_SEEDUINT32:
-      i = va_arg(ap, uint32);
-      STORE32(buf, i);
-      dx_seed(g, buf, sizeof(buf));
-      break;
-    case GRAND_SEEDBLOCK: {
-      const void *p = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      dx_seed(g, p, sz);
-    } break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      octet buf[16];
-      rr->ops->fill(rr, buf, sizeof(buf));
-      dx_seed(g, buf, sizeof(buf));
-    } break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static octet dx_grbyte(grand *r)
-{
-  dx_grctx *g = (dx_grctx *)r;
-  octet o;
-  tlsdx_encrypt(&g->dx, 0, &o, 1);
-  return (o);
-}
-
-static uint32 dx_grword(grand *r)
-{
-  dx_grctx *g = (dx_grctx *)r;
-  octet b[4];
-  tlsdx_encrypt(&g->dx, 0, &b, sizeof(b));
-  return (LOAD32(b));
-}
-
-static void dx_grfill(grand *r, void *p, size_t sz)
-{
-  dx_grctx *g = (dx_grctx *)r;
-  tlsdx_encrypt(&g->dx, 0, p, sz);
-}
-
-static const grand_ops dx_grops = {
-  "<tlsdx-dummy>",
-  GRAND_CRYPTO, 0,
-  dx_grmisc, dx_grdestroy,
-  dx_grword, dx_grbyte, dx_grword, grand_range, dx_grfill
-};
-
-/* ---@tlsdx_rand@ --- *
- *
- * Arguments:  @const gcmac *mc@ = MAC function to use
- *             @const void *k@ = pointer to the key material
- *             @size_t ksz@ = size of the key material
- *             @const void *sd@ = pointer to the seed material
- *             @size_t sdsz@ = size of the seed material
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a generic generator which does TLS data expansion.
- */
-
-grand *tlsdx_rand(const gcmac *mc, const void *k, size_t ksz,
-                 const void *sd, size_t sdsz)
-{
-  dx_grctx *g = S_CREATE(dx_grctx);
-  dstr d = DSTR_INIT;
-  gmac *m = GM_KEY(mc, k, ksz);
-  octet *q = xmalloc(sdsz);
-  memcpy(q, sd, sdsz);
-  dstr_putf(&d, "tlsdx(%s)", mc->name);
-  g->ops = dx_grops;
-  g->ops.name = xstrdup(d.buf);
-  g->r.ops = &g->ops;
-  dstr_destroy(&d);
-  tlsdx_init(&g->dx, m, q, sdsz);
-  return (&g->r);
-}
-
-/* --- The actual very paranoid PRF ---------------------------------------*/
-
-/* --- @tlsprf_init@ --- *
- *
- * Arguments:  @tlsprf_ctx *c@ = pointer to context block
- *             @const gcmac *mcx, *mcy@ = left and right MAC functions
- *             @const void *k@ = pointer to the key material
- *             @size_t ksz@ = size of the key material
- *             @const void *sd@ = pointer to the seed material
- *             @size_t sdsz@ = size of the seed material
- *
- * Returns:    ---
- *
- * Use:                Initializes a TLS PRF context.
- */
-
-void tlsprf_init(tlsprf_ctx *c, const gcmac *mcx, const gcmac *mcy,
-                const void *k, size_t ksz, const void *sd, size_t sdsz)
-{
-  size_t n = (ksz + 1)/2;
-  const octet *kk = k;
-  tlsdx_init(&c->px, mcx->key(kk, n), sd, sdsz);
-  tlsdx_init(&c->py, mcy->key(kk + ksz - n, n), sd, sdsz);
-}
-
-/* --- @tlsprf_encrypt@ --- *
- *
- * Arguments:  @tlsprf_ctx *c@ = pointer to a context
- *             @const void *src@ = pointer to source data
- *             @void *dest@ = pointer to destination buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    ---
- *
- * Use:                Encrypts data using the TLS pseudo-random function.  If the
- *             destination pointer is null, the generator is spun and no
- *             output is produced; if the source pointer is null, raw output
- *             from the generator is written; otherwise, the source data is
- *             XORed with the generator output.
- */
-
-void tlsprf_encrypt(tlsprf_ctx *c, const void *src, void *dest, size_t sz)
-{
-  tlsdx_encrypt(&c->px, src, dest, sz);
-  tlsdx_encrypt(&c->py, dest, dest, sz);
-}
-
-/* --- @tlsprf_free@ --- *
- *
- * Arguments:  @tlsprf_ctx *c@ = pointer to a context
- *
- * Returns:    ---
- *
- * Use:                Frees a TLS PRF context.
- */
-
-void tlsprf_free(tlsprf_ctx *c)
-{
-  c->px.k->ops->destroy(c->px.k);
-  c->py.k->ops->destroy(c->py.k);
-  tlsdx_free(&c->px);
-  tlsdx_free(&c->py);
-}
-
-/* --- Generic random number generator --- */
-
-typedef struct prf_grctx {
-  grand r;
-  grand_ops ops;
-  tlsprf_ctx prf;
-} prf_grctx;
-
-static void prf_grdestroy(grand *r)
-{
-  prf_grctx *g = (prf_grctx *)r;
-  xfree((char *)g->ops.name);
-  xfree((octet *)g->prf.px.sd);
-  tlsprf_free(&g->prf);
-  BURN(*g);
-  S_DESTROY(g);
-}
-
-static void prf_seed(prf_grctx *g, const void *p, size_t sz)
-{
-  octet *q;
-
-  xfree((octet *)g->prf.px.sz);
-  g->prf.px.sd = g->prf.py.sd = q = xmalloc(sz);
-  memcpy(q, p, sz);
-  g->prf.px.sdsz = g->prf.py.sdsz = sz;
-}
-
-static int prf_grmisc(grand *r, unsigned op, ...)
-{
-  prf_grctx *g = (prf_grctx *)r;
-  va_list ap;
-  int rc = 0;
-  uint32 i;
-  octet buf[4];
-  va_start(ap, op);
-
-  switch (op) {
-    case GRAND_CHECK:
-      switch (va_arg(ap, unsigned)) {
-       case GRAND_CHECK:
-       case GRAND_SEEDINT:
-       case GRAND_SEEDUINT32:
-       case GRAND_SEEDBLOCK:
-       case GRAND_SEEDRAND:
-         rc = 1;
-         break;
-       default:
-         rc = 0;
-         break;
-      }
-      break;
-    case GRAND_SEEDINT:
-      i = va_arg(ap, unsigned);
-      STORE32(buf, i);
-      prf_seed(g, buf, sizeof(buf));
-      break;
-    case GRAND_SEEDUINT32:
-      i = va_arg(ap, uint32);
-      STORE32(buf, i);
-      prf_seed(g, buf, sizeof(buf));
-      break;
-    case GRAND_SEEDBLOCK: {
-      const void *p = va_arg(ap, const void *);
-      size_t sz = va_arg(ap, size_t);
-      prf_seed(g, p, sz);
-    } break;
-    case GRAND_SEEDRAND: {
-      grand *rr = va_arg(ap, grand *);
-      octet buf[16];
-      rr->ops->fill(rr, buf, sizeof(buf));
-      prf_seed(g, buf, sizeof(buf));
-    } break;
-    default:
-      GRAND_BADOP;
-      break;
-  }
-
-  va_end(ap);
-  return (rc);
-}
-
-static octet prf_grbyte(grand *r)
-{
-  prf_grctx *g = (prf_grctx *)r;
-  octet o;
-  tlsprf_encrypt(&g->prf, 0, &o, 1);
-  return (o);
-}
-
-static uint32 prf_grword(grand *r)
-{
-  prf_grctx *g = (prf_grctx *)r;
-  octet b[4];
-  tlsprf_encrypt(&g->prf, 0, &b, sizeof(b));
-  return (LOAD32(b));
-}
-
-static void prf_grfill(grand *r, void *p, size_t sz)
-{
-  prf_grctx *g = (prf_grctx *)r;
-  tlsprf_encrypt(&g->prf, 0, p, sz);
-}
-
-static const grand_ops prf_grops = {
-  "<tlsprf-dummy>",
-  GRAND_CRYPTO, 0,
-  prf_grmisc, prf_grdestroy,
-  prf_grword, prf_grbyte, prf_grword, grand_range, prf_grfill
-};
-
-/* ---@tlsprf_rand@ --- *
- *
- * Arguments:  @const gcmac *mcx, *mcy@ = MAC function to use
- *             @const void *k@ = pointer to the key material
- *             @size_t ksz@ = size of the key material
- *             @const void *sd@ = pointer to the seed material
- *             @size_t sdsz@ = size of the seed material
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a generic generator which does TLS data expansion.
- */
-
-grand *tlsprf_rand(const gcmac *mcx, const gcmac *mcy,
-                  const void *k, size_t ksz, const void *sd, size_t sdsz)
-{
-  prf_grctx *g = S_CREATE(prf_grctx);
-  dstr d = DSTR_INIT;
-  octet *q = xmalloc(sdsz);
-  memcpy(q, sd, sdsz);
-  dstr_putf(&d, "tlsprf(%s,%s)", mcx->name, mcy->name);
-  g->ops = prf_grops;
-  g->ops.name = xstrdup(d.buf);
-  g->r.ops = &g->ops;
-  dstr_destroy(&d);
-  tlsprf_init(&g->prf, mcx, mcy, k, ksz, q, sdsz);
-  return (&g->r);
-}
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-#include <string.h>
-
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#include "sha-hmac.h"
-#include "md5-hmac.h"
-
-static int v_generate(dstr *v)
-{
-  grand *g;
-  dstr d = DSTR_INIT;
-  int ok = 1;
-
-  g = tlsprf_rand(&md5_hmac, &sha_hmac,
-                 v[0].buf, v[0].len, v[1].buf, v[1].len);
-  dstr_ensure(&d, v[2].len);
-  d.len = v[2].len;
-  g->ops->fill(g, d.buf, d.len);
-  g->ops->destroy(g);
-  if (memcmp(v[2].buf, d.buf, d.len) != 0) {
-    ok = 0;
-    printf("\nfail tlsprf:"
-          "\n\tkey        = ");
-    type_hex.dump(&v[0], stdout);
-    printf("\n\tseed      = "); type_hex.dump(&v[1], stdout);
-    printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
-    printf("\n\tcalculated = "); type_hex.dump(&d, stdout);
-    putchar('\n');
-  }
-  return (ok);
-}
-
-static test_chunk defs[] = {
-  { "tlsprf", v_generate, { &type_hex, &type_hex, &type_hex, 0 } },
-  { 0, 0, { 0 } }
-};
-
-int main(int argc, char *argv[])
-{
-  test_run(argc, argv, defs, SRCDIR"/tests/tlsprf");
-  return (0);
-}
-
-#endif
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/tlsprf.h b/tlsprf.h
deleted file mode 100644 (file)
index 0a702b5..0000000
--- a/tlsprf.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* -*-c-*-
- *
- * $Id: tlsprf.h,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The TLS pseudo-random function
- *
- * (c) 2001 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.
- */
-
-#ifndef CATACOMB_TLSPRF_H
-#define CATACOMB_TLSPRF_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#ifndef CATACOMB_GMAC_H
-#  include "gmac.h"
-#endif
-
-#ifndef CATACOMB_GRAND_H
-#  include "grand.h"
-#endif
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct tlsdx_ctx {
-  gmac *k;                             /* The MAC key to use */
-  size_t hashsz;                       /* Size of hash outputs */
-  ghash *i, *o;                                /* Inner and outer hash contexts */
-  const octet *sd;                     /* Pointer to seed buffer */
-  size_t sdsz;                         /* Size of the seed buffer */
-  octet *p;                            /* Pointer to buffered output */
-  size_t sz;                           /* Bytes remaining in buffer */
-  octet *ai;                           /* Pointer to inner result */
-} tlsdx_ctx;
-
-typedef struct tlsprf_ctx {
-  tlsdx_ctx px, py;
-} tlsprf_ctx;
-
-/*----- The data expansion function ---------------------------------------*/
-
-/* --- @tlsdx_init@ --- *
- *
- * Arguments:  @tlsdx_ctx *c@ = pointer to a context
- *             @gmac *m@ = pointer to a generic MAC instance
- *             @const void *sd@ = pointer to the seed block
- *             @size_t sdsz@ = size of the seed block
- *
- * Returns:    ---
- *
- * Use:                Initializes a context for the TLS data expansion function.
- *             This doesn't take ownership of the MAC instance or the seed
- *             memory, nor does it allocate copies.
- */
-
-extern void tlsdx_init(tlsdx_ctx */*c*/, gmac */*m*/,
-                      const void */*sd*/, size_t /*sdsz*/);
-
-/* --- @tlsdx_encrypt@ --- *
- *
- * Arguments:  @tlsdx_ctx *c@ = pointer to a context
- *             @const void *src@ = pointer to source data
- *             @void *dest@ = pointer to destination buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    ---
- *
- * Use:                Encrypts data using the TLS data expansion function.  If the
- *             destination pointer is null, the generator is spun and no
- *             output is produced; if the source pointer is null, raw output
- *             from the generator is written; otherwise, the source data is
- *             XORed with the generator output.
- */
-
-extern void tlsdx_encrypt(tlsdx_ctx */*c*/, const void */*src*/,
-                         void */*dest*/, size_t /*sz*/);
-
-/* --- @tlsdx_free@ --- *
- *
- * Arguments:  @tlsdx_ctx *c@ = pointer to the context block
- *
- * Returns:    ---
- *
- * Use:                Frees a context for the TLS data expansion function
- */
-
-extern void tlsdx_free(tlsdx_ctx */*c*/);
-
-/* ---@tlsdx_rand@ --- *
- *
- * Arguments:  @const gcmac *mc@ = MAC function to use
- *             @const void *k@ = pointer to the key material
- *             @size_t ksz@ = size of the key material
- *             @const void *sd@ = pointer to the seed material
- *             @size_t sdsz@ = size of the seed material
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a generic generator which does TLS data expansion.
- */
-
-extern grand *tlsdx_rand(const gcmac */*mc*/,
-                        const void */*k*/, size_t /*ksz*/,
-                        const void */*sd*/, size_t /*sdsz*/);
-
-/* --- The actual very paranoid PRF ---------------------------------------*/
-
-/* --- @tlsprf_init@ --- *
- *
- * Arguments:  @tlsprf_ctx *c@ = pointer to context block
- *             @const gcmac *mcx, *mcy@ = left and right MAC functions
- *             @const void *k@ = pointer to the key material
- *             @size_t ksz@ = size of the key material
- *             @const void *sd@ = pointer to the seed material
- *             @size_t sdsz@ = size of the seed material
- *
- * Returns:    ---
- *
- * Use:                Initializes a TLS PRF context.
- */
-
-extern void tlsprf_init(tlsprf_ctx */*c*/,
-                       const gcmac */*mcx*/, const gcmac */*mcy*/,
-                       const void */*k*/, size_t /*ksz*/,
-                       const void */*sd*/, size_t /*sdsz*/);
-
-/* --- @tlsprf_encrypt@ --- *
- *
- * Arguments:  @tlsprf_ctx *c@ = pointer to a context
- *             @const void *src@ = pointer to source data
- *             @void *dest@ = pointer to destination buffer
- *             @size_t sz@ = size of buffer
- *
- * Returns:    ---
- *
- * Use:                Encrypts data using the TLS pseudo-random function.  If the
- *             destination pointer is null, the generator is spun and no
- *             output is produced; if the source pointer is null, raw output
- *             from the generator is written; otherwise, the source data is
- *             XORed with the generator output.
- */
-
-extern void tlsprf_encrypt(tlsprf_ctx */*c*/,
-                          const void */*src*/, void */*dest*/,
-                          size_t /*sz*/);
-
-/* --- @tlsprf_free@ --- *
- *
- * Arguments:  @tlsprf_ctx *c@ = pointer to a context
- *
- * Returns:    ---
- *
- * Use:                Frees a TLS PRF context.
- */
-
-extern void tlsprf_free(tlsprf_ctx */*c*/);
-
-/* ---@tlsprf_rand@ --- *
- *
- * Arguments:  @const gcmac *mcx, *mcy@ = MAC function to use
- *             @const void *k@ = pointer to the key material
- *             @size_t ksz@ = size of the key material
- *             @const void *sd@ = pointer to the seed material
- *             @size_t sdsz@ = size of the seed material
- *
- * Returns:    Pointer to generic random number generator interface.
- *
- * Use:                Creates a generic generator which does TLS data expansion.
- */
-
-extern grand *tlsprf_rand(const gcmac */*mcx*/, const gcmac */*mcy*/,
-                         const void */*k*/, size_t /*ksz*/,
-                         const void */*sd*/, size_t /*sdsz*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/twofish-mktab.c b/twofish-mktab.c
deleted file mode 100644 (file)
index 1a31463..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-/* -*-c-*-
- *
- * $Id: twofish-mktab.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Build constant tables for Twofish
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/bits.h>
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct { octet t[4][16]; } t_tab;
-typedef struct { octet q[256]; } q_tab;
-
-/*----- Various Twofish tables --------------------------------------------*/
-
-/* --- The t-tables --- */
-
-static const t_tab qt0 = {{
-  { 0x8, 0x1, 0x7, 0xd, 0x6, 0xf, 0x3, 0x2,
-    0x0, 0xb, 0x5, 0x9, 0xe, 0xc, 0xa, 0x4 },
-  { 0xe, 0xc, 0xb, 0x8, 0x1, 0x2, 0x3, 0x5,
-    0xf, 0x4, 0xa, 0x6, 0x7, 0x0, 0x9, 0xd },
-  { 0xb, 0xa, 0x5, 0xe, 0x6, 0xd, 0x9, 0x0,
-    0xc, 0x8, 0xf, 0x3, 0x2, 0x4, 0x7, 0x1 },
-  { 0xd, 0x7, 0xf, 0x4, 0x1, 0x2, 0x6, 0xe,
-    0x9, 0xb, 0x3, 0x0, 0x8, 0x5, 0xc, 0xa }
-}};
-
-static const t_tab qt1 = {{
-  { 0x2, 0x8, 0xb, 0xd, 0xf, 0x7, 0x6, 0xe,
-    0x3, 0x1, 0x9, 0x4, 0x0, 0xa, 0xc, 0x5 },
-  { 0x1, 0xe, 0x2, 0xb, 0x4, 0xc, 0x3, 0x7,
-    0x6, 0xd, 0xa, 0x5, 0xf, 0x9, 0x0, 0x8 },
-  { 0x4, 0xc, 0x7, 0x5, 0x1, 0x6, 0x9, 0xa,
-    0x0, 0xe, 0xd, 0x8, 0x2, 0xb, 0x3, 0xf },
-  { 0xb, 0x9, 0x5, 0x1, 0xc, 0x3, 0xd, 0xe,
-    0x6, 0x4, 0x7, 0xf, 0x2, 0x0, 0x8, 0xa }
-}};
-
-static q_tab q0, q1;
-
-/* --- The MDS and Reed-Solomon matrices --- */
-
-static const octet mds[16] = {
-  0x01, 0xef, 0x5b, 0x5b,
-  0x5b, 0xef, 0xef, 0x01,
-  0xef, 0x5b, 0x01, 0xef,
-  0xef, 0x01, 0xef, 0x5b
-};
-
-static const octet rs[32] = {
-  0x01, 0xa4, 0x55, 0x87, 0x5a, 0x58, 0xdb, 0x9e,
-  0xa4, 0x56, 0x82, 0xf3, 0x1e, 0xc6, 0x68, 0xe5,
-  0x02, 0xa1, 0xfc, 0xc1, 0x47, 0xae, 0x3d, 0x19,
-  0xa4, 0x55, 0x87, 0x5a, 0x58, 0xdb, 0x9e, 0x03
-};
-
-/*----- Magic macros ------------------------------------------------------*/
-
-#define ROR4(x) ((((x) >> 1) | ((x) << 3)) & 15)
-
-/*----- Building and printing @q@ tables ----------------------------------*/
-
-/* --- @mkq@ --- *
- *
- * Arguments:  @q_tab *q@ = pointer to output @q@ table
- *             @const t_tab *t@ = pointer to input @t@ table
- *             @const char *name@ = name of @q@ table
- *
- * Returns:    ---
- *
- * Use:                Constructs a 256-entry @q@-table.
- */
-
-static void mkq(q_tab *q, const t_tab *t, const char *name)
-{
-  int i;
-  int ok = 1;
-
-  /* --- Ensure the t-table is well-formed --- */
-
-  for (i = 0; i < 4; i++) {
-    octet f[16] = { 0 };
-    int j;
-
-    for (j = 0; j < 16; j++) {
-      if (f[t->t[i][j]]) {
-       fprintf(stderr, "duplicate %i in %s[%i] (col %i and %i)\n",
-               t->t[i][j], name, i, j, f[t->t[i][j]]);
-       ok = 0;
-      }
-      f[t->t[i][j]] = j;
-    }
-  }
-
-  if (!ok)
-    exit(EXIT_FAILURE);
-
-  /* --- Construct the @q@ table --- */
-
-  for (i = 0; i < 256; i++) {
-    int a = i >> 4, b = i & 15;
-    int aa = t->t[0][a ^ b], bb = t->t[1][a ^ ((a << 3) & 15) ^ ROR4(b)];
-    a = t->t[2][aa ^ bb], b = t->t[3][aa ^ ((aa << 3) & 15) ^ ROR4(bb)];
-    q->q[i] = a | (b << 4);
-  }
-
-  /* Consider testing @q@ for linear and differential properties here */
-}
-
-/* --- @printq@ --- *
- *
- * Arguments:  @const q_tab *t@ = pointer to table
- *             @const char *name@ = pointer to table name
- *
- * Returns:    ---
- *
- * Use:                Prints a q table.
- */
-
-static void printq(const q_tab *q, const char *name)
-{
-  int i;
-  int j;
-
-  printf("\
-#define TWOFISH_%s {                                                   \\\n\
-  ", name);
-  j = 0;
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", q->q[i]);
-    j = (j + 1) & 7;
-    if (i == 255)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (j == 0)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-}
-
-/*----- %$\gf{2^8}$% arithmetic -------------------------------------------*/
-
-#define MDS_MOD 0x169
-#define RS_MOD 0x14d
-
-/* --- @mul@ --- *
- *
- * Arguments:  @unsigned x, y@ = polynomials over %$\gf{2^8}$%
- *             @unsigned m@ = modulus
- *
- * Returns:    The product of two polynomials.
- *
- * Use:                Computes a product of polynomials, quite slowly.
- */
-
-static unsigned mul(unsigned x, unsigned y, unsigned m)
-{
-  unsigned a = 0;
-  unsigned i;
-
-  for (i = 0; i < 8; i++) {
-    if (y & 1)
-      a ^= x;
-    y >>= 1;
-    x <<= 1;
-    if (x & 0x100)
-      x ^= m;
-  }
-
-  return (a);
-}
-
-/* --- @mmul@ --- *
- *
- * Arguments:  @octet *d@ = destination vector
- *             @const octet *p@ = matrix of bytes
- *             @const octet *q@ = vector from somewhere else
- *             @size_t r@ = size of destination or number of rows in matrix
- *             @size_t n@ = length of row and vector
- *             @unsigned m@ = modulus polynomial
- *
- * Returns:    ---
- *
- * Use:                Computes an inner product of matrices over the finite field
- *             %$\gf{2^8}[x]/(m(x))$%.  This isn't particularly rapid.
- */
-
-static void mmul(octet *d, const octet *p, const octet *q,
-                size_t r, size_t n, unsigned m)
-{
-  while (r) {
-    const octet *qq = q;
-    unsigned a = 0;
-    unsigned i;
-
-    for (i = 0; i < n; i++)
-      a ^= mul(*p++, *qq++, m);
-    *d++ = a;
-    r--;
-  }
-}
-
-/* --- @qrds@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    ---
- *
- * Use:                Prints the MDS/q table.
- */
-
-static void qmds(void)
-{
-  uint32 t[4][256];
-  int i, j;
-  static const q_tab *q[4] = { &q1, &q0, &q1, &q0 };
-
-  for (i = 0; i < 4; i++) {
-    octet in[4] = { 0, 0, 0, 0 };
-    octet out[4];
-
-    for (j = 0; j < 256; j++) {
-      in[i] = q[i]->q[j];
-      mmul(out, mds, in, 4, 4, MDS_MOD);
-      t[i][j] = LOAD32_L(out);
-    }
-  }
-
-  puts("\
-/* --- Expanded MDS tables --- *\n\
- *\n\
- * The table contains output vectors for computing the result of pushing\n\
- * bytes through appropriate @q@ tables and the MDS matrix.\n\
- */\n\
-\n\
-#define TWOFISH_QMDS {                                                 \\");
-  for (i = 0; i < 4; i++) {
-    fputs("  { ", stdout);
-    for (j = 0; j < 256; j++) {
-      printf("0x%08lx", (unsigned long)t[i][j]);
-      if (j == 255) {
-       if (i == 3)
-         puts(" }                      \\\n}");
-       else
-         puts(" },                     \\\n\
-                                                                       \\");
-      } else if (j % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  putchar('\n');
-}
-
-/* --- @rslog@ --- *
- *
- * Arguments:  ---
- *
- * Returns:    ---
- *
- * Use:                Produces the log and antilog tables for doing the RS
- *             arithmetic efficiently.
- */
-
-static void rslog(void)
-{
-  octet rslog[256];
-  octet rsexp[256];
-
-  unsigned x = 1;
-  unsigned i;
-
-  rslog[0] = 0;
-  for (i = 0; i < 255; i++) {
-    rslog[x] = i;
-    rsexp[i] = x;
-    x <<= 1;
-    if (x & 0x100)
-      x ^= RS_MOD;
-  }
-
-  x = 0;
-  for (i = 0; i < 32; i++) {
-    if (rslog[rs[i]] > x)
-      x = rslog[rs[i]];
-  }
-
-  fputs("\
-/* --- Reed-Solomon log tables --- *\n\
- *\n\
- * The Reed-Solomon multiplies are accelerated by using log tables.\n\
- */\n\
-\n\
-#define TWOFISH_RSLOG {                                                        \\\n\
-  ", stdout);
-
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", rslog[i]);
-    if (i == 255)
-      puts("                   \\\n}\n");
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  fputs("\
-#define TWOFISH_RSEXP {                                                        \\\n\
-  ", stdout);
-
-  for (i = 0; i < 255 + x + 1; i++) {
-    printf("0x%02x", rsexp[i % 255]);
-    if (i == 255 + x)
-      puts("                                           \\\n}\n");
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  fputs("\
-/* --- Reed-Solomon matrix with log entries --- */\n\
-\n\
-#define TWOFISH_RS {                                                   \\\n\
-  ", stdout);
-
-  for (i = 0; i < 32; i++) {
-    printf("0x%02x", rslog[rs[i]]);
-    if (i == 31)
-      puts("                   \\\n}\n");
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-}
-
-/*----- Main program ------------------------------------------------------*/
-
-/* --- @main@ --- */
-
-int main(void)
-{
-  fputs("\
-/* -*-c-*-\n\
- *\n\
- * Twofish q tables [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_TWOFISH_TAB_H\n\
-#define CATACOMB_TWOFISH_TAB_H\n\
-\n\
-", stdout);
-
-  /* --- The q tables --- */
-
-  puts("\
-/* --- Precomputed @q@ tables --- */\n\
-");
-  mkq(&q0, &qt0, "qt0");
-  mkq(&q1, &qt1, "qt1");
-  printq(&q0, "Q0");
-  printq(&q1, "Q1");
-
-  /* --- The MDS/q tables --- */
-
-  qmds();
-  rslog();
-
-  /* --- Done --- */
-
-  puts("#endif");
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/twofish.c b/twofish.c
deleted file mode 100644 (file)
index ad4882f..0000000
--- a/twofish.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/* -*-c-*-
- *
- * $Id: twofish.c,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * Implementation of the Twofish cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "twofish.h"
-#include "twofish-tab.h"
-#include "paranoia.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet twofish_keysz[] = { KSZ_RANGE, TWOFISH_KEYSZ, 0, 32, 1 };
-
-/*----- Important tables --------------------------------------------------*/
-
-static const octet q0[256] = TWOFISH_Q0, q1[256] = TWOFISH_Q1;
-static const uint32 qmds[4][256] = TWOFISH_QMDS;
-static const octet rslog[] = TWOFISH_RSLOG, rsexp[] = TWOFISH_RSEXP;
-static const octet rs[32] = TWOFISH_RS;
-
-/*----- Key initialization ------------------------------------------------*/
-
-/* --- @h@ --- *
- *
- * Arguments:  @uint32 x@ = input to the function
- *             @const uint32 *l@ = key values to mix in
- *             @unsigned k@ = number of key values there are
- *
- * Returns:    The output of the function @h@.
- *
- * Use:                Implements the Twofish function @h@.
- */
-
-static uint32 h(uint32 x, const uint32 *l, unsigned k)
-{
-  /* --- Apply a series of @q@ tables to an integer --- */
-
-# define Q(x, qa, qb, qc, qd)                                          \
-  ((qa[((x) >> 0) & 0xff] <<  0) |                                     \
-   (qb[((x) >> 8) & 0xff] <<  8) |                                     \
-   (qc[((x) >> 16) & 0xff] << 16) |                                    \
-   (qd[((x) >> 24) & 0xff] << 24))
-
-  /* --- Grind through the tables --- */
-
-  switch (k) {
-    case 4: x = Q(x, q1, q0, q0, q1) ^ l[3];
-    case 3: x = Q(x, q1, q1, q0, q0) ^ l[2];
-    case 2: x = Q(x, q0, q1, q0, q1) ^ l[1];
-           x = Q(x, q0, q0, q1, q1) ^ l[0];
-      break;
-  }
-
-#undef Q
-
-  /* --- Apply the MDS matrix --- */
-
-  return (qmds[0][U8(x >>  0)] ^ qmds[1][U8(x >>  8)] ^
-         qmds[2][U8(x >> 16)] ^ qmds[3][U8(x >> 24)]);
-}
-
-/* --- @twofish_initfk@ --- *
- *
- * Arguments:  @twofish_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *             @const twofish_fk *fk@ = family-key information
- *
- * Returns:    ---
- *
- * Use:                Does the underlying Twofish key initialization with family
- *             key.  Pass in a family-key structure initialized to
- *             all-bits-zero for a standard key schedule.
- */
-
-void twofish_initfk(twofish_ctx *k, const void *buf, size_t sz,
-                   const twofish_fk *fk)
-{
-# define KMAX 4
-
-  uint32 mo[KMAX], me[KMAX];
-  octet s[4][KMAX];
-
-  /* --- Expand the key into the three word arrays --- */
-
-  {
-    size_t ssz;
-    const octet *p, *q;
-    octet b[32];
-    int i;
-
-    /* --- Sort out the key size --- */
-
-    KSZ_ASSERT(twofish, sz);
-    if (sz <= 16)
-      ssz = 16;
-    else if (sz <= 24)
-      ssz = 24;
-    else if (sz <= 32)
-      ssz = 32;
-    else
-      assert(((void)"This can't happen (bad key size in twofish_init)", 0));
-
-    /* --- Extend the key if necessary --- */
-
-    if (sz == ssz)
-      p = buf;
-    else {
-      memcpy(b, buf, sz);
-      memset(b + sz, 0, ssz - sz);
-      p = b;
-    }
-
-    /* --- Finally get the word count --- */
-
-    sz = ssz / 8;
-
-    /* --- Extract words from the key --- *
-     *
-     * The @s@ table, constructed using the Reed-Solomon matrix, is cut into
-     * sequences of bytes, since this is actually more useful for computing
-     * the S-boxes.
-     */
-
-    q = p;
-    for (i = 0; i < sz; i++) {
-      octet ss[4];
-      const octet *r = rs;
-      int j;
-
-      /* --- Extract the easy subkeys --- */
-
-      me[i] = LOAD32_L(q) ^ fk->t0[2 * i];
-      mo[i] = LOAD32_L(q + 4) ^ fk->t0[2 * i + 1];
-
-      /* --- Now do the Reed-Solomon thing --- */
-
-      for (j = 0; j < 4; j++) {
-       const octet *qq = q;
-       unsigned a = 0;
-       int k;
-
-       for (k = 0; k < 8; k++) {
-         unsigned char x = *qq ^ fk->t1[i * 8 + k];
-         if (x) a ^= rsexp[rslog[x] + *r];
-         qq++;
-         r++;
-       }
-
-       s[j][sz - 1 - i] = ss[j] = a;
-      }
-      q += 8;
-    }
-
-    /* --- Clear away the temporary buffer --- */
-
-    if (p == b)
-      BURN(b);
-  }
-
-  /* --- Construct the expanded key --- */
-
-  {
-    uint32 p = 0x01010101;
-    uint32 ip = 0;
-    int i;
-
-    for (i = 0; i < 40; i += 2) {
-      uint32 a, b;
-      a = h(ip, me, sz);
-      b = h(ip + p, mo, sz);
-      b = ROL32(b, 8);
-      a += b; b += a;
-      k->k[i] = U32(a);
-      k->k[i + 1] = ROL32(b, 9);
-      ip += 2 * p;
-    }
-
-    for (i = 0; i < 8; i++)
-      k->k[i] ^= fk->t23[i];
-    for (i = 8; i < 40; i += 2) {
-      k->k[i] ^= fk->t4[0];
-      k->k[i + 1] ^= fk->t4[1];
-    }
-  }
-
-  /* --- Construct the S-box tables --- */
-
-  {
-    unsigned i;
-    static const octet *q[4][KMAX + 1] = {
-      { q1, q0, q0, q1, q1 },
-      { q0, q0, q1, q1, q0 },
-      { q1, q1, q0, q0, q0 },
-      { q0, q1, q1, q0, q1 }
-    };
-
-    for (i = 0; i < 4; i++) {
-      unsigned j;
-      uint32 x;
-
-      for (j = 0; j < 256; j++) {
-       x = j;
-
-       /* --- Push the byte through the q tables --- */
-
-       switch (sz) {
-         case 4: x = q[i][4][x] ^ s[i][3];
-         case 3: x = q[i][3][x] ^ s[i][2];
-         case 2: x = q[i][2][x] ^ s[i][1];
-                 x = q[i][1][x] ^ s[i][0];
-           break;
-       }
-
-       /* --- Write it in the key schedule --- */
-
-       k->g[i][j] = qmds[i][x];
-      }
-    }
-  }
-
-  /* --- Clear everything away --- */
-
-  BURN(me);
-  BURN(mo);
-  BURN(s);
-}
-
-/* --- @twofish_init@ --- *
- *
- * Arguments:  @twofish_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Twofish key buffer.  Twofish accepts key sizes
- *             of up to 256 bits (32 bytes).
- */
-
-void twofish_init(twofish_ctx *k, const void *buf, size_t sz)
-{
-  static const twofish_fk fk = { { 0 } };
-  twofish_initfk(k, buf, sz, &fk);
-}
-
-/* --- @twofish_fkinit@ --- *
- *
- * Arguments:  @twofish_fk *fk@ = pointer to family key block
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a family-key buffer.  This implementation allows
- *             family keys of any size acceptable to the Twofish algorithm.
- */
-
-void twofish_fkinit(twofish_fk *fk, const void *buf, size_t sz)
-{
-  twofish_ctx k;
-  uint32 pt[4], ct[4];
-  const octet *kk;
-  unsigned i;
-
-  twofish_init(&k, buf, sz);
-
-  for (i = 0; i < 4; i++) pt[i] = (uint32)-1;
-  twofish_eblk(&k, pt, fk->t0 + 4);
-
-  kk = buf; sz /= 4;
-  for (i = 0; i < sz; i++) { fk->t0[i] = LOAD32_L(kk); kk += 4; }
-
-  for (i = 0; i < 4; i++) pt[i] = 0; twofish_eblk(&k, pt, ct);
-  for (i = 0; i < 4; i++) STORE32_L(fk->t1 + i * 4, ct[i]);
-  pt[0] = 1; twofish_eblk(&k, pt, ct);
-  for (i = 0; i < 4; i++) STORE32_L(fk->t1 + 4 + i * 4, ct[i]);
-
-  pt[0] = 2; twofish_eblk(&k, pt, fk->t23 + 0);
-  pt[0] = 3; twofish_eblk(&k, pt, fk->t23 + 4);
-  pt[0] = 4; twofish_eblk(&k, pt, ct);
-  fk->t4[0] = ct[0]; fk->t4[1] = ct[1];
-
-  BURN(k);
-}
-
-/*----- Main encryption ---------------------------------------------------*/
-
-/* --- Feistel function --- */
-
-#define GG(k, t0, t1, x, y, kk) do {                                   \
-  t0 = (k->g[0][U8(x >>         0)] ^                                          \
-       k->g[1][U8(x >>  8)] ^                                          \
-       k->g[2][U8(x >> 16)] ^                                          \
-       k->g[3][U8(x >> 24)]);                                          \
-  t1 = (k->g[1][U8(y >>         0)] ^                                          \
-       k->g[2][U8(y >>  8)] ^                                          \
-       k->g[3][U8(y >> 16)] ^                                          \
-       k->g[0][U8(y >> 24)]);                                          \
-  t0 += t1;                                                            \
-  t1 += t0;                                                            \
-  t0 += kk[0];                                                         \
-  t1 += kk[1];                                                         \
-} while (0)
-
-/* --- Round operations --- */
-
-#define EROUND(k, w, x, y, z, kk) do {                                 \
-  uint32 _t0, _t1;                                                     \
-  GG(k, _t0, _t1, w, x, kk);                                           \
-  kk += 2;                                                             \
-  y ^= _t0; y = ROR32(y, 1);                                           \
-  z = ROL32(z, 1); z ^= _t1;                                           \
-} while (0)
-
-#define DROUND(k, w, x, y, z, kk) do {                                 \
-  uint32 _t0, _t1;                                                     \
-  kk -= 2;                                                             \
-  GG(k, _t0, _t1, w, x, kk);                                           \
-  y = ROL32(y, 1); y ^= _t0;                                           \
-  z ^= _t1; z = ROR32(z, 1);                                           \
-} while (0)
-
-/* --- Complete encryption functions --- */
-
-#define EBLK(k, a, b, c, d, w, x, y, z) do {                           \
-  const uint32 *_kk = k->k + 8;                                                \
-  uint32 _a = a, _b = b, _c = c, _d = d;                               \
-  _a ^= k->k[0]; _b ^= k->k[1]; _c ^= k->k[2]; _d ^= k->k[3];          \
-  EROUND(k, _a, _b, _c, _d, _kk);                                      \
-  EROUND(k, _c, _d, _a, _b, _kk);                                      \
-  EROUND(k, _a, _b, _c, _d, _kk);                                      \
-  EROUND(k, _c, _d, _a, _b, _kk);                                      \
-  EROUND(k, _a, _b, _c, _d, _kk);                                      \
-  EROUND(k, _c, _d, _a, _b, _kk);                                      \
-  EROUND(k, _a, _b, _c, _d, _kk);                                      \
-  EROUND(k, _c, _d, _a, _b, _kk);                                      \
-  EROUND(k, _a, _b, _c, _d, _kk);                                      \
-  EROUND(k, _c, _d, _a, _b, _kk);                                      \
-  EROUND(k, _a, _b, _c, _d, _kk);                                      \
-  EROUND(k, _c, _d, _a, _b, _kk);                                      \
-  EROUND(k, _a, _b, _c, _d, _kk);                                      \
-  EROUND(k, _c, _d, _a, _b, _kk);                                      \
-  EROUND(k, _a, _b, _c, _d, _kk);                                      \
-  EROUND(k, _c, _d, _a, _b, _kk);                                      \
-  _c ^= k->k[4]; _d ^= k->k[5]; _a ^= k->k[6]; _b ^= k->k[7];          \
-  w = U32(_c); x = U32(_d); y = U32(_a); z = U32(_b);                  \
-} while (0)
-
-#define DBLK(k, a, b, c, d, w, x, y, z) do {                           \
-  const uint32 *_kk = k->k + 40;                                       \
-  uint32 _a = a, _b = b, _c = c, _d = d;                               \
-  _a ^= k->k[4]; _b ^= k->k[5]; _c ^= k->k[6]; _d ^= k->k[7];          \
-  DROUND(k, _a, _b, _c, _d, _kk);                                      \
-  DROUND(k, _c, _d, _a, _b, _kk);                                      \
-  DROUND(k, _a, _b, _c, _d, _kk);                                      \
-  DROUND(k, _c, _d, _a, _b, _kk);                                      \
-  DROUND(k, _a, _b, _c, _d, _kk);                                      \
-  DROUND(k, _c, _d, _a, _b, _kk);                                      \
-  DROUND(k, _a, _b, _c, _d, _kk);                                      \
-  DROUND(k, _c, _d, _a, _b, _kk);                                      \
-  DROUND(k, _a, _b, _c, _d, _kk);                                      \
-  DROUND(k, _c, _d, _a, _b, _kk);                                      \
-  DROUND(k, _a, _b, _c, _d, _kk);                                      \
-  DROUND(k, _c, _d, _a, _b, _kk);                                      \
-  DROUND(k, _a, _b, _c, _d, _kk);                                      \
-  DROUND(k, _c, _d, _a, _b, _kk);                                      \
-  DROUND(k, _a, _b, _c, _d, _kk);                                      \
-  DROUND(k, _c, _d, _a, _b, _kk);                                      \
-  _c ^= k->k[0]; _d ^= k->k[1]; _a ^= k->k[2]; _b ^= k->k[3];          \
-  w = U32(_c); x = U32(_d); y = U32(_a); z = U32(_b);                  \
-} while (0)
-
-/* --- @twofish_eblk@, @twofish_dblk@ --- *
- *
- * Arguments:  @const twofish_ctx *k@ = pointer to key block
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-void twofish_eblk(const twofish_ctx *k, const uint32 *s, uint32 *d)
-{
-  EBLK(k, s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]);
-}
-
-void twofish_dblk(const twofish_ctx *k, const uint32 *s, uint32 *d)
-{
-  DBLK(k, s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]);
-}
-
-BLKC_TEST(TWOFISH, twofish)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/twofish.h b/twofish.h
deleted file mode 100644 (file)
index 65007db..0000000
--- a/twofish.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* -*-c-*-
- *
- * $Id: twofish.h,v 1.5 2004/04/08 01:36:15 mdw Exp $
- *
- * The Twofish block cipher
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Twofish block cipher ---------------------------------*
- *
- * Twofish was designed by Bruce Schneier, John Kelsey, Doug Whiting, David
- * Wagner, Chris Hall and Niels Ferguson.  The algorithm is unpatented and
- * free for anyone to use.  It was one of the five AES finalist algorithms.
- *
- * Twofish is a complex cipher offering various space and time tradeoffs.
- * This implementation has a heavy key schedule and fast bulk encryption.
- */
-
-#ifndef CATACOMB_TWOFISH_H
-#define CATACOMB_TWOFISH_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define TWOFISH_BLKSZ 16
-#define TWOFISH_KEYSZ 32
-#define TWOFISH_CLASS (N, L, 128)
-
-extern const octet twofish_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct twofish_ctx {
-  uint32 k[40];
-  uint32 g[4][256];
-} twofish_ctx;
-
-typedef struct twofish_fk {
-  uint32 t0[8], t23[8], t4[2];
-  octet t1[32];
-} twofish_fk;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @twofish_initfk@ --- *
- *
- * Arguments:  @twofish_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *             @const twofish_fk *fk@ = family-key information
- *
- * Returns:    ---
- *
- * Use:                Does the underlying Twofish key initialization with family
- *             key.  Pass in a family-key structure initialized to
- *             all-bits-zero for a standard key schedule.
- */
-
-extern void twofish_initfk(twofish_ctx */*k*/, const void */*buf*/,
-                          size_t /*sz*/, const twofish_fk */*fk*/);
-
-/* --- @twofish_init@ --- *
- *
- * Arguments:  @twofish_ctx *k@ = pointer to key block to fill in
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a Twofish key buffer.  Twofish accepts keys of up
- *             to 256 bits in length.
- */
-
-extern void twofish_init(twofish_ctx */*k*/,
-                        const void */*buf*/, size_t /*sz*/);
-
-/* --- @twofish_fkinit@ --- *
- *
- * Arguments:  @twofish_fk *fk@ = pointer to family key block
- *             @const void *buf@ = pointer to buffer of key material
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes a family-key buffer.  This implementation allows
- *             family keys of any size acceptable to the Twofish algorithm.
- */
-
-extern void twofish_fkinit(twofish_fk */*fk*/,
-                          const void */*buf*/, size_t /*sz*/);
-
-/* --- @twofish_eblk@, @twofish_dblk@ --- *
- *
- * Arguments:  @const twofish_ctx *k@ = pointer to key block
- *             @const uint32 s[4]@ = pointer to source block
- *             @uint32 d[4]@ = pointer to destination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void twofish_eblk(const twofish_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*d*/);
-
-extern void twofish_dblk(const twofish_ctx */*k*/,
-                        const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/vars.am b/vars.am
new file mode 100644 (file)
index 0000000..de79545
--- /dev/null
+++ b/vars.am
@@ -0,0 +1,102 @@
+### -*-makefile-*-
+###
+### Common definitions for build scripts
+###
+### (c) 2013 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.
+
+###--------------------------------------------------------------------------
+### Miscellaneous useful definitions.
+
+## Some convenient abbreviations for file suffixes.
+e                       = $(EXEEXT)
+o                       = $(OBJEXT)
+t                       = t$e
+
+## Installation directories.
+archincludedir          = $(pkglibdir)/include
+
+###--------------------------------------------------------------------------
+### Initial values of common variables.
+
+EXTRA_DIST              =
+CLEANFILES              =
+DISTCLEANFILES          =
+MAINTAINERCLEANFILES    =
+SUFFIXES                =
+TESTS                   =
+BUILT_SOURCES           =
+
+noinst_PROGRAMS                 =
+pkginclude_HEADERS      =
+nodist_pkginclude_HEADERS =
+archinclude_HEADERS     =
+nodist_archinclude_HEADERS =
+
+###--------------------------------------------------------------------------
+### Standard configuration substitutions.
+
+## Substitute tags in files.
+confsubst = $(top_srcdir)/config/confsubst
+
+SUBSTITUTIONS = \
+               prefix=$(prefix) exec_prefix=$(exec_prefix) \
+               libdir=$(libdir) includedir=$(includedir) \
+               PACKAGE=$(PACKAGE) VERSION=$(VERSION) \
+               CATACOMB_LIBS="$(CATACOMB_LIBS)"
+
+V_SUBST = $(V_SUBST_$(V))
+V_SUBST_ = $(V_SUBST_$(AM_DEFAULT_VERBOSITY))
+V_SUBST_0 = @echo "  SUBST  $@";
+SUBST = $(V_SUBST)$(confsubst)
+
+###--------------------------------------------------------------------------
+### Include path.
+
+CATACOMB_INCLUDES       = \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/base \
+       -I$(top_srcdir)/key \
+       -I$(top_srcdir)/math \
+       -I$(top_builddir)/math \
+       -I$(top_srcdir)/misc \
+       -I$(top_srcdir)/pub \
+       -I$(top_srcdir)/rand \
+       -I$(top_srcdir)/symm \
+       -I$(top_srcdir)/symm/modes -I$(top_builddir)/symm/modes
+
+AM_CPPFLAGS             = $(CATACOMB_INCLUDES)
+
+###--------------------------------------------------------------------------
+### Testing.
+
+SUFFIXES               += .c .$t .to
+.c.to:
+       $(AM_V_CC)$(COMPILE) -c -DTEST_RIG -DSRCDIR=\"$(srcdir)\" $< -o $@
+.to.$t: libcatacomb.la
+       $(AM_V_CCLD)$(LINK) $< \
+               $(TEST_LIBS) $(top_builddir)/libcatacomb.la \
+               $(mLib_LIBS) $(CATACOMB_LIBS) $(LIBS)
+.PRECIOUS: %.to
+CLEANFILES             += *.to *.$t
+
+###----- That's all, folks --------------------------------------------------
diff --git a/whirlpool-mktab.c b/whirlpool-mktab.c
deleted file mode 100644 (file)
index 75f7bb2..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Generate tables for Whirlpool hash function
- *
- * (c) 2005 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mLib/bits.h>
-
-/*----- Static variables --------------------------------------------------*/
-
-static const octet E[] = {
-  0x1, 0xb, 0x9, 0xc, 0xd, 0x6, 0xf, 0x3,
-  0xe, 0x8, 0x7, 0x4, 0xa, 0x2, 0x5, 0x0
-}, R[] = {
-  0x7, 0xc, 0xb, 0xd, 0xe, 0x4, 0x9, 0xf,
-  0x6, 0x3, 0x8, 0xa, 0x2, 0x5, 0x1, 0x0
-}, C[] = {
-  0x1, 0x1, 0x4, 0x1, 0x8, 0x5, 0x2, 0x9
-};
-
-static octet S[256], T[256][8], log[256], alog[256];
-
-/*----- Main code ---------------------------------------------------------*/
-
-#define S_MOD 0x11d
-
-static void logtable(void)
-{
-  unsigned i, x;
-
-  for (i = 0, x = 1; i < 255; i++) {
-    log[x] = i;
-    alog[i] = x;
-    x <<= 1;
-    if (x & 0x100) x ^= S_MOD;
-  }
-}
-
-static octet mul(octet x, octet y)
-  { if (!x || !y) return (0); return (alog[(log[x] + log[y]) % 255]); }
-
-static void sbox(void)
-{
-  unsigned i, j;
-  octet EI[16];
-  octet l, r, y;
-
-  for (i = 0; i < 16; i++) EI[E[i]] = i;
-  for (i = 0; i < 256; i++) {
-    l = (i >> 4) & 0xf;
-    r = (i >> 0) & 0xf;
-    l = E[l]; r = EI[r];
-    y = R[l ^ r];
-    l = E[l ^ y]; r = EI[r ^ y];
-    S[i] = (l << 4) | r;
-  }
-
-  for (i = 0; i < 256; i++) {
-    for (j = 0; j < 8; j++)
-      T[i][j] = mul(S[i], C[j]);
-  }
-}
-
-static unsigned long w32(int i, int j, int k)
-{
-  kludge64 x;
-  LOAD64_L_(x, T[j]);
-  ROL64_(x, x, i * 8);
-  return (k ? LO64(x) : HI64(x));
-}
-
-int main(void)
-{
-  int i, j;
-
-  puts("\
-/* -*-c-*-\n\
- *\n\
- * Whirlpool tables [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_WHIRLPOOL_TAB_H\n\
-#define CATACOMB_WHIRLPOOL_TAB_H\n\
-");
-
-  /* --- Write out the S-box --- */
-
-  logtable();
-  sbox();
-  fputs("\
-/* --- The byte substitution --- */\n\
-\n\
-#define WHIRLPOOL_S {                                                  \\\n\
-  ", stdout);
-  for (i = 0; i < 256; i++) {
-    printf("0x%02x", S[i]);
-    if (i == 255)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 8 == 7)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  /* --- Write out the key constant tables --- */
-
-  fputs("\
-/* --- The key generation constants --- */\n\
-\n\
-#define WHIRLPOOL_C {                                                  \\\n\
-  ", stdout);
-  for (i = 0; i < 10; i++) {
-    printf("X64(%08lx, %08lx)",
-          (unsigned long)LOAD32_L(&S[i * 8 + 4]),
-          (unsigned long)LOAD32_L(&S[i * 8 + 0]));
-    if (i == 9)
-      fputs("                  \\\n}\n\n", stdout);
-    else if (i % 2 == 1)
-      fputs(",                 \\\n  ", stdout);
-    else
-      fputs(", ", stdout);
-  }
-
-  /* --- Write out the big T tables --- */
-
-  fputs("\
-/* --- The 64-bit big round tables --- */\n\
-\n\
-#define WHIRLPOOL_T {                                                  \\\n\
-  { ", stdout);
-  for (j = 0; j < 8; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("X64(%08lx, %08lx)", w32(j, i, 0), w32(j, i, 1));
-      if (i == 255) {
-       if (j == 7)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 2 == 1)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  /* --- Write out the smaller U and V tables --- */
-
-  fputs("\
-/* --- The 32-bit round tables --- */\n\
-\n\
-#define WHIRLPOOL_U {                                                  \\\n\
-  { ", stdout);
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("0x%08lx", w32(j, i, 1));
-      if (i == 255) {
-       if (j == 3)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  fputs("\
-#define WHIRLPOOL_V {                                                  \\\n\
-  { ", stdout);
-  for (j = 0; j < 4; j++) {
-    for (i = 0; i < 256; i++) {
-      printf("0x%08lx", w32(j, i, 0));
-      if (i == 255) {
-       if (j == 3)
-         fputs(" }                     \\\n}\n\n", stdout);
-       else
-         fputs(" },                    \\\n\
-                                                                       \\\n\
-  { ", stdout);
-      } else if (i % 4 == 3)
-       fputs(",                        \\\n    ", stdout);
-      else
-       fputs(", ", stdout);
-    }
-  }
-
-  /* --- Done --- */
-
-  puts("#endif");
-
-  if (fclose(stdout)) {
-    fprintf(stderr, "error writing data\n");
-    exit(EXIT_FAILURE);
-  }
-
-  return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/whirlpool.c b/whirlpool.c
deleted file mode 100644 (file)
index 48e6e97..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Whirlpool hash function
- *
- * (c) 2005 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "whirlpool.h"
-#include "whirlpool-tab.h"
-
-#if defined(HAVE_UINT64)
-#  define USE64
-#endif
-
-/*----- Static variables --------------------------------------------------*/
-
-static const kludge64 C[10] = WHIRLPOOL_C;
-
-#ifdef USE64
-static const kludge64 T[8][256] = WHIRLPOOL_T;
-#else
-static const uint32 U[4][256] = WHIRLPOOL_U, V[4][256] = WHIRLPOOL_V;
-#endif
-
-/*----- Main code ---------------------------------------------------------*/
-
-#define DUMP(k, v) do {                                                        \
-  int i;                                                               \
-  printf("\n");                                                                \
-  for (i = 0; i < 8; i++)                                              \
-    printf("  %08x %08x         :  %08x %08x\n",                               \
-          HI64(k[i]), LO64(k[i]),                                      \
-          HI64(v[i]), LO64(v[i]));                                     \
-} while (0)
-
-#define OFFSET(i, n) (((i) + 16 - (n)) % 8)
-
-#ifdef USE64
-
-#define BYTE(x, j)                                                     \
-  U8((j) < 4 ?                                                         \
-    (LO64(x) >> ((j) * 8)) :                                           \
-    (HI64(x) >> ((j) * 8 - 32)))
-
-#define TT(v, i, j) T[j][BYTE(v[OFFSET(i, j)], j)]
-
-#define XROW(vv, v, i) do {                                            \
-  XOR64(vv[i], vv[i], TT(v, i, 1));                                    \
-  XOR64(vv[i], vv[i], TT(v, i, 2));                                    \
-  XOR64(vv[i], vv[i], TT(v, i, 3));                                    \
-  XOR64(vv[i], vv[i], TT(v, i, 4));                                    \
-  XOR64(vv[i], vv[i], TT(v, i, 5));                                    \
-  XOR64(vv[i], vv[i], TT(v, i, 6));                                    \
-  XOR64(vv[i], vv[i], TT(v, i, 7));                                    \
-} while (0)
-
-#define ROWZ(vv, v, i) do {                                            \
-  vv[i] = TT(v, i, 0);                                                 \
-  XROW(vv, v, i);                                                      \
-} while (0)
-
-#define ROWK(vv, v, i, k) do {                                         \
-  vv[i] = k;                                                           \
-  XOR64(vv[i], vv[i], TT(v, i, 0));                                    \
-  XROW(vv, v, i);                                                      \
-} while (0)
-
-#else
-
-#define BYTE(x, j) U8((x) >> (((j) & 3) * 8))
-
-#define UUL(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].lo, j)]
-#define VVL(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].lo, j)]
-#define UUH(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].hi, j)]
-#define VVH(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].hi, j)]
-
-#define XROW(vv, v, i) do {                                            \
-  vv[i].lo ^= UUL(v, i, 1); vv[i].hi ^= VVL(v, i, 1);                  \
-  vv[i].lo ^= UUL(v, i, 2); vv[i].hi ^= VVL(v, i, 2);                  \
-  vv[i].lo ^= UUL(v, i, 3); vv[i].hi ^= VVL(v, i, 3);                  \
-  vv[i].lo ^= VVH(v, i, 4); vv[i].hi ^= UUH(v, i, 4);                  \
-  vv[i].lo ^= VVH(v, i, 5); vv[i].hi ^= UUH(v, i, 5);                  \
-  vv[i].lo ^= VVH(v, i, 6); vv[i].hi ^= UUH(v, i, 6);                  \
-  vv[i].lo ^= VVH(v, i, 7); vv[i].hi ^= UUH(v, i, 7);                  \
-} while (0)
-
-#define ROWZ(vv, v, i) do {                                            \
-  vv[i].lo = UUL(v, i, 0);  vv[i].hi = VVL(v, i, 0);                   \
-  XROW(vv, v, i);                                                      \
-} while (0)
-
-#define ROWK(vv, v, i, k) do {                                         \
-  vv[i] = k;                                                           \
-  vv[i].lo ^= UUL(v, i, 0); vv[i].hi ^= VVL(v, i, 0);                  \
-  XROW(vv, v, i);                                                      \
-} while (0)
-
-#endif
-
-#define RHO(vv, v, kk, k) do {                                         \
-  ROWK(kk, k, 0, *c++);          ROWK(vv, v, 0, kk[0]);                        \
-  ROWZ(kk, k, 1);        ROWK(vv, v, 1, kk[1]);                        \
-  ROWZ(kk, k, 2);        ROWK(vv, v, 2, kk[2]);                        \
-  ROWZ(kk, k, 3);        ROWK(vv, v, 3, kk[3]);                        \
-  ROWZ(kk, k, 4);        ROWK(vv, v, 4, kk[4]);                        \
-  ROWZ(kk, k, 5);        ROWK(vv, v, 5, kk[5]);                        \
-  ROWZ(kk, k, 6);        ROWK(vv, v, 6, kk[6]);                        \
-  ROWZ(kk, k, 7);        ROWK(vv, v, 7, kk[7]);                        \
-} while (0)
-
-void whirlpool_compress(whirlpool_ctx *ctx, const void *sbuf)
-{
-  kludge64 m[8], k[8], kk[8], v[8], vv[8];
-  const kludge64 *c = C;
-  const octet *s = sbuf;
-  int i;
-
-  for (i = 0; i < 8; i++) {
-    LOAD64_L_(m[i], &s[i * 8]);
-    XOR64(v[i], m[i], ctx->s[i]);
-  }
-
-  RHO(vv, v, kk, ctx->s);
-  RHO(v, vv, k, kk);
-  RHO(vv, v, kk, k);
-  RHO(v, vv, k, kk);
-  RHO(vv, v, kk, k);
-  RHO(v, vv, k, kk);
-  RHO(vv, v, kk, k);
-  RHO(v, vv, k, kk);
-  RHO(vv, v, kk, k);
-  RHO(v, vv, k, kk);
-
-  for (i = 0; i < 8; i++) {
-    XOR64(ctx->s[i], ctx->s[i], m[i]);
-    XOR64(ctx->s[i], ctx->s[i], v[i]);
-  }
-}
-
-/* --- @whirlpool_init@, @whirlpool256_init@ --- *
- *
- * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-void whirlpool_init(whirlpool_ctx *ctx)
-{
-  int i;
-
-  for (i = 0; i < 8; i++)
-    SET64(ctx->s[i], 0, 0);
-  ctx->off = 0;
-  ctx->nh = ctx->nl = 0;
-}
-
-/* --- @whirlpool_set@, @whirlpool256_set@ --- *
- *
- * Arguments:  @whirlpool_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 whirlpool_set(whirlpool_ctx *ctx, const void *buf, unsigned long count)
-{
-  const octet *p = buf;
-  int i;
-
-  for (i = 0; i < 8; i++) {
-    LOAD64_L_(ctx->s[i], p);
-    p += 8;
-  }
-  ctx->off = 0;
-  ctx->nl = U32(count);
-  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
-}
-
-/* --- @whirlpool_hash@, @whirlpool256_hash@ --- *
- *
- * Arguments:  @whirlpool_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 whirlpool_hash(whirlpool_ctx *ctx, const void *buf, size_t sz)
-{
-  HASH_BUFFER(WHIRLPOOL, whirlpool, ctx, buf, sz);
-}
-
-/* --- @whirlpool_done@, @whirlpool256_done@ --- *
- *
- * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
- *             @void *hash@ = pointer to output buffer
- *
- * Returns:    ---
- *
- * Use:                Returns the hash of the data read so far.
- */
-
-static void final(whirlpool_ctx *ctx)
-{
-  HASH_PAD(WHIRLPOOL, whirlpool, ctx, 0x80, 0, 32);
-  memset(ctx->buf + WHIRLPOOL_BUFSZ - 32, 0, 24);
-  STORE32(ctx->buf + WHIRLPOOL_BUFSZ - 8, (ctx->nl >> 29) | (ctx->nh << 3));
-  STORE32(ctx->buf + WHIRLPOOL_BUFSZ - 4, ctx->nl << 3);
-  whirlpool_compress(ctx, ctx->buf);
-}
-
-void whirlpool_done(whirlpool_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  int i;
-
-  final(ctx);
-  for (i = 0; i < 8; i++) {
-    STORE64_L_(p, ctx->s[i]);
-    p += 8;
-  }
-}
-
-void whirlpool256_done(whirlpool256_ctx *ctx, void *hash)
-{
-  octet *p = hash;
-  int i;
-
-  final(ctx);
-  for (i = 0; i < 4; i++) {
-    STORE64_L_(p, ctx->s[i]);
-    p += 8;
-  }
-}
-
-/* --- @whirlpool_state@, @whirlpool256_state@ --- *
- *
- * Arguments:  @whirlpool_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 @whirlpool_set@.
- */
-
-unsigned long whirlpool_state(whirlpool_ctx *ctx, void *state)
-{
-  octet *p = state;
-  int i;
-
-  for (i = 0; i < 8; i++) {
-    STORE64_L_(p, ctx->s[i]);
-    p += 8;
-  }
-  return (ctx->nl | ((ctx->nh << 16) << 16));
-}
-
-/* --- Generic interface --- */
-
-GHASH_DEF(WHIRLPOOL, whirlpool)
-
-/* --- Test code --- */
-
-HASH_TEST(WHIRLPOOL, whirlpool)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/whirlpool.h b/whirlpool.h
deleted file mode 100644 (file)
index eb29a16..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Implementation of the Whirlpool hash function
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Whirlpool hash function ------------------------------*
- *
- * Whirlpool was designed by Paulo Barreto and Vincent Rijmen.  Its
- * compression function is based on similar ideas to Rijndael (also
- * codesigned by Rijmen).
- *
- * Whirlpool256 is simply Whirlpool with its final output truncated to 256
- * bits.  This is, I hope, about as good as a 256-bit hash function can get.
- * It isn't vulnerable to the Kelsey-Schneier generic second-preimage attack
- * against MD hash functions because of its larger internal state (see also
- * Lucks).
- */
-
-#ifndef CATACOMB_WHIRLPOOL_H
-#define CATACOMB_WHIRLPOOL_H
-#define CATACOMB_WHIRLPOOL256_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#ifndef CATACOMB_GHASH_H
-#  include "ghash.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define WHIRLPOOL_BUFSZ 64
-#define WHIRLPOOL_HASHSZ 64
-#define WHIRLPOOL_STATESZ 64
-
-#define WHIRLPOOL256_BUFSZ 64
-#define WHIRLPOOL256_HASHSZ 32
-#define WHIRLPOOL256_STATESZ 64
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct whirlpool_ctx {
-  kludge64 s[8];                       /* Chaining variables */
-  uint32 nh, nl;                       /* Byte count so far */
-  unsigned off;                                /* Offset into buffer */
-  octet buf[WHIRLPOOL_BUFSZ];          /* Accumulation buffer */
-} whirlpool_ctx, whirlpool256_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @whirlpool_compress@, @whirlpool256_compress@ --- *
- *
- * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
- *             @const void *sbuf@ = pointer to buffer of appropriate size
- *
- * Returns:    ---
- *
- * Use:                SHA-512 compression function.
- */
-
-extern void whirlpool_compress(whirlpool_ctx */*ctx*/, const void */*sbuf*/);
-#define whirlpool256_compress whirlpool_compress
-
-/* --- @whirlpool_init@, @whirlpool256_init@ --- *
- *
- * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block to initialize
- *
- * Returns:    ---
- *
- * Use:                Initializes a context block ready for hashing.
- */
-
-extern void whirlpool_init(whirlpool_ctx */*ctx*/);
-#define whirlpool256_init whirlpool_init
-
-/* --- @whirlpool_set@, @whirlpool256_set@ --- *
- *
- * Arguments:  @whirlpool_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 whirlpool_set(whirlpool_ctx */*ctx*/, const void */*buf*/,
-                         unsigned long /*count*/);
-#define whirlpool256_set whirlpool_set
-
-/* --- @whirlpool_hash@, @whirlpool256_hash@ --- *
- *
- * Arguments:  @whirlpool_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 whirlpool_hash(whirlpool_ctx */*ctx*/,
-                          const void */*buf*/, size_t /*sz*/);
-#define whirlpool256_hash whirlpool_hash
-
-/* --- @whirlpool_done@, @whirlpool256_done@ --- *
- *
- * Arguments:  @whirlpool_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 whirlpool_done(whirlpool_ctx */*ctx*/, void */*hash*/);
-extern void whirlpool256_done(whirlpool_ctx */*ctx*/, void */*hash*/);
-
-/* --- @whirlpool_state@, @whirlpool256_state@ --- *
- *
- * Arguments:  @whirlpool_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 @whirlpool_set@.
- */
-
-extern unsigned long whirlpool_state(whirlpool_ctx */*ctx*/,
-                                    void */*state*/);
-#define whirlpool256_state whirlpool_state
-
-/*----- Generic hash interface --------------------------------------------*/
-
-extern const gchash whirlpool;
-extern const gchash whirlpool256;
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif
diff --git a/whirlpool256.c b/whirlpool256.c
deleted file mode 100644 (file)
index 38fe665..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Stub code for Whirlpool-256
- */
-
-#include "ghash.h"
-#include "ghash-def.h"
-#include "hash.h"
-#include "whirlpool256.h"
-
-GHASH_DEF(WHIRLPOOL256, whirlpool256)
-HASH_TEST(WHIRLPOOL256, whirlpool256)
diff --git a/whirlpool256.h b/whirlpool256.h
deleted file mode 100644 (file)
index 171d886..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*-c-*-
- *
- * $Id$
- *
- * Stub header for Whirlpool-256
- */
-
-#ifndef CATACOMB_WHIRLPOOL256_H
-#define CATACOMB_WHIRLPOOL256_H
-
-#include "whirlpool.h"
-
-#endif
diff --git a/xtea.c b/xtea.c
deleted file mode 100644 (file)
index 13cb7fd..0000000
--- a/xtea.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/* -*-c-*-
- *
- * $Id: xtea.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
- *
- * The Extended Tiny Encryption Algorithm
- *
- * (c) 2000 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "paranoia.h"
-#include "xtea.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet xtea_keysz[] = { KSZ_RANGE, XTEA_KEYSZ, 0, 16, 1 };
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @xtea_init@ --- *
- *
- * Arguments:  @xtea_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes an XTEA key buffer.  The key buffer must be 16
- *             bytes long.
- */
-
-void xtea_init(xtea_ctx *k, const void *buf, size_t sz)
-{
-  octet kb[16];
-  const octet *p;
-
-  KSZ_ASSERT(xtea, sz);
-  if (sz >= sizeof(kb))
-    p = buf;
-  else {
-    memcpy(kb, buf, sz);
-    memset(kb + sz, 0, sizeof(kb) - sz);
-    p = kb;
-  }
-
-  k->k[0] = LOAD32(p + 0); k->k[1] = LOAD32(p +  4);
-  k->k[2] = LOAD32(p + 8); k->k[3] = LOAD32(p + 12);
-  k->r = 32;
-
-  if (p == kb)
-    BURN(kb);
-}
-
-/* --- @xtea_eblk@, @xtea_dblk@ --- *
- *
- * Arguments:  @const xtea_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to xteatination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-#define DELTA 0x9e3779b9
-
-void xtea_eblk(const xtea_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 y = s[0], z = s[1];
-  uint32 n = 0;
-  unsigned i;
-
-  for (i = 0; i < k->r; i++) {
-    y = U32(y + ((((z << 4) ^ (z >> 5)) + z) ^ (n + k->k[n & 3])));
-    n += DELTA;
-    z = U32(z + ((((y << 4) ^ (y >> 5)) + y) ^ (n + k->k[(n >> 11) & 3])));
-  }
-  d[0] = y; d[1] = z;
-}
-
-void xtea_dblk(const xtea_ctx *k, const uint32 *s, uint32 *d)
-{
-  uint32 y = s[0], z = s[1];
-  uint32 n = DELTA * k->r;
-  unsigned i;
-
-  for (i = 0; i < k->r; i++) {
-    z = U32(z - ((((y << 4) ^ (y >> 5)) + y) ^ (n + k->k[(n >> 11) & 3])));
-    n -= DELTA;
-    y = U32(y - ((((z << 4) ^ (z >> 5)) + z) ^ (n + k->k[n & 3])));
-  }
-  d[0] = y; d[1] = z;
-}
-
-BLKC_TEST(XTEA, xtea)
-
-/*----- That's all, folks -------------------------------------------------*/
diff --git a/xtea.h b/xtea.h
deleted file mode 100644 (file)
index 9e40b1e..0000000
--- a/xtea.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*-c-*-
- *
- * $Id: xtea.h,v 1.4 2004/04/08 01:36:15 mdw Exp $
- *
- * The Extended Tiny Encryption Algorithm
- *
- * (c) 2000 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.
- */
-
-/*----- Notes on the Tiny Encryption Algorithm ----------------------------*
- *
- * XTEA is an amazingly simple 64-round Feistel network.  It's tiny, fairly
- * quick and surprisingly strong.  It was invented by David Wheeler and Roger
- * Needham.  It's unpatented.  XTEA is a new version of TEA, by the same
- * designers, which fixes some weaknesses in TEA's key schedule.
- *
- * This implementation uses big-endian byte order, following SCAN.
- */
-
-#ifndef CATACOMB_XTEA_H
-#define CATACOMB_XTEA_H
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <stddef.h>
-
-#include <mLib/bits.h>
-
-/*----- Magical numbers ---------------------------------------------------*/
-
-#define XTEA_BLKSZ 8
-#define XTEA_KEYSZ 16
-#define XTEA_CLASS (N, B, 64)
-
-extern const octet xtea_keysz[];
-
-/*----- Data structures ---------------------------------------------------*/
-
-typedef struct xtea_ctx {
-  unsigned r;
-  uint32 k[4];
-} xtea_ctx;
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @xtea_init@ --- *
- *
- * Arguments:  @xtea_ctx *k@ = pointer to key block
- *             @const void *buf@ = pointer to key buffer
- *             @size_t sz@ = size of key material
- *
- * Returns:    ---
- *
- * Use:                Initializes an XTEA key buffer.  The key buffer may be up to
- *             16 bytes long.
- */
-
-extern void xtea_init(xtea_ctx */*k*/, const void */*buf*/, size_t /*sz*/);
-
-/* --- @xtea_eblk@, @xtea_dblk@ --- *
- *
- * Arguments:  @const xtea_ctx *k@ = pointer to key block
- *             @const uint32 s[2]@ = pointer to source block
- *             @uint32 d[2]@ = pointer to xteatination block
- *
- * Returns:    ---
- *
- * Use:                Low-level block encryption and decryption.
- */
-
-extern void xtea_eblk(const xtea_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-extern void xtea_dblk(const xtea_ctx */*k*/,
-                     const uint32 */*s*/, uint32 */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif