Initial import.
authormdw <mdw>
Fri, 3 Sep 1999 08:41:14 +0000 (08:41 +0000)
committermdw <mdw>
Fri, 3 Sep 1999 08:41:14 +0000 (08:41 +0000)
70 files changed:
.cvsignore [new file with mode: 0644]
.links [new file with mode: 0644]
.skelrc [new file with mode: 0644]
Makefile.m4 [new file with mode: 0644]
acconfig.h [new file with mode: 0644]
bf_ikey.h [new file with mode: 0644]
blkc.h [new file with mode: 0644]
blowfish.c [new file with mode: 0644]
blowfish.h [new file with mode: 0644]
cbc.h [new file with mode: 0644]
cfb.h [new file with mode: 0644]
configure.in [new file with mode: 0644]
daftstory.h [new file with mode: 0644]
des-base.c [new file with mode: 0644]
des-base.h [new file with mode: 0644]
des-mktab.c [new file with mode: 0644]
des.c [new file with mode: 0644]
des.h [new file with mode: 0644]
des3.c [new file with mode: 0644]
des3.h [new file with mode: 0644]
ecb.h [new file with mode: 0644]
genmodes [new file with mode: 0755]
hash.h [new file with mode: 0644]
hmac.h [new file with mode: 0644]
idea.c [new file with mode: 0644]
idea.h [new file with mode: 0644]
key.1 [new file with mode: 0644]
key.c [new file with mode: 0644]
key.h [new file with mode: 0644]
keyring.5 [new file with mode: 0644]
keyutil.c [new file with mode: 0644]
md4.c [new file with mode: 0644]
md4.h [new file with mode: 0644]
md5.c [new file with mode: 0644]
md5.h [new file with mode: 0644]
mp.c [new file with mode: 0644]
mp.h [new file with mode: 0644]
mpscan.c [new file with mode: 0644]
mpscan.h [new file with mode: 0644]
mptypes.h [new file with mode: 0644]
mpx.c [new file with mode: 0644]
mpx.h [new file with mode: 0644]
noise.c [new file with mode: 0644]
noise.h [new file with mode: 0644]
ofb.h [new file with mode: 0644]
papers/.cvsignore [new file with mode: 0644]
papers/crypto.sty [new file with mode: 0644]
papers/rand.tex [new file with mode: 0644]
paranoia.h [new file with mode: 0644]
rand.c [new file with mode: 0644]
rand.h [new file with mode: 0644]
rc4.c [new file with mode: 0644]
rc4.h [new file with mode: 0644]
rc5.c [new file with mode: 0644]
rc5.h [new file with mode: 0644]
rmd160.c [new file with mode: 0644]
rmd160.h [new file with mode: 0644]
setup [new file with mode: 0755]
sha.c [new file with mode: 0644]
sha.h [new file with mode: 0644]
tests/blowfish [new file with mode: 0644]
tests/des [new file with mode: 0644]
tests/des3 [new file with mode: 0644]
tests/idea [new file with mode: 0644]
tests/md4 [new file with mode: 0644]
tests/md5 [new file with mode: 0644]
tests/rc4 [new file with mode: 0644]
tests/rc5 [new file with mode: 0644]
tests/rmd160 [new file with mode: 0644]
tests/sha [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..ed9b81e
--- /dev/null
@@ -0,0 +1,57 @@
+Makefile.am
+Makefile.in
+_mpdiv.c
+aclocal.m4
+blowfish-cbc.c
+blowfish-cbc.h
+blowfish-cfb.c
+blowfish-cfb.h
+blowfish-ecb.c
+blowfish-ecb.h
+blowfish-ofb.c
+blowfish-ofb.h
+build
+config.h.in
+configure
+des-cbc.c
+des-cbc.h
+des-cfb.c
+des-cfb.h
+des-ecb.c
+des-ecb.h
+des-ofb.c
+des-ofb.h
+des3-cbc.c
+des3-cbc.h
+des3-cfb.c
+des3-cfb.h
+des3-ecb.c
+des3-ecb.h
+des3-ofb.c
+des3-ofb.h
+des_sp.h
+idea-cbc.c
+idea-cbc.h
+idea-cfb.c
+idea-cfb.h
+idea-ecb.c
+idea-ecb.h
+idea-ofb.c
+idea-ofb.h
+md4-hmac.c
+md4-hmac.h
+md5-hmac.c
+md5-hmac.h
+rc5-cbc.c
+rc5-cbc.h
+rc5-cfb.c
+rc5-cfb.h
+rc5-ecb.c
+rc5-ecb.h
+rc5-ofb.c
+rc5-ofb.h
+rmd160-hmac.c
+rmd160-hmac.h
+sha-hmac.c
+sha-hmac.h
+stamp-h.in
diff --git a/.links b/.links
new file mode 100644 (file)
index 0000000..a4f5a17
--- /dev/null
+++ b/.links
@@ -0,0 +1,6 @@
+COPYING.LIB
+install-sh
+missing
+mkinstalldirs
+getdate.y
+getdate.h
diff --git a/.skelrc b/.skelrc
new file mode 100644 (file)
index 0000000..4847795
--- /dev/null
+++ b/.skelrc
@@ -0,0 +1,9 @@
+;;; -*-emacs-lisp-*-
+
+(setq skel-alist
+      (append
+       '((author . "Straylight/Edgeware")
+        (licence-text . "[[lgpl]]")
+        (full-title . "Catacomb")
+        (library . "Catacomb"))
+       skel-alist))
diff --git a/Makefile.m4 b/Makefile.m4
new file mode 100644 (file)
index 0000000..06e1b7d
--- /dev/null
@@ -0,0 +1,173 @@
+## -*-makefile-*-
+##
+## $Id: Makefile.m4,v 1.1 1999/09/03 08:41:11 mdw Exp $
+##
+## Makefile 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.
+
+##----- Revision history ----------------------------------------------------
+##
+## $Log: Makefile.m4,v $
+## Revision 1.1  1999/09/03 08:41:11  mdw
+## Initial import.
+##
+## The `CVS' directory can't be hardlinked.  Don't worry about this
+## overmuch.
+##
+##
+
+AUTOMAKE_OPTIONS = foreign
+
+archincludedir = $(libdir)/catacomb/include
+
+## --- List handling macros ---
+##
+## List handling is nice, usually.  Unfortunately, I based this design on
+## TeX list macros rather than anything sensible...
+
+define(`_', `define(`_item', $1)define(`_item_2', $2)emit`'')
+define(`adorn', `pushdef(`emit', `$1`'_item`'$3')$2`'popdef(`emit')')
+define(`join',
+`pushdef(`emit', `adorn(``_(''_item`$2', `$3', ``)'')`'')$1`'popdef(`emit')')
+define(`addsuffix', `adorn(`', `$1', `$2')')
+define(`lit', `adorn(`', `$1', `')')
+define(`nl', `
+')
+
+define(`allwithsuffix',
+`addsuffix(`$1', `$3') addsuffix(`$2', `$3') dnl
+addsuffix(join(`$1', `-', `$2'), `$3')')
+
+## --- Autogenerated source files ---
+
+define(`ciphers', `_(des) _(des3) _(blowfish) _(idea) _(rc5)')
+define(`cipher_modes', `_(ecb) _(cbc) _(cfb) _(ofb)')
+
+define(`hashes', `_(md5) _(md4) _(rmd160) _(sha)')
+define(`hash_modes', `_(hmac)')
+
+MODES = \
+       adorn(`$(srcdir)/', join(`ciphers', `-', `cipher_modes'), `.c') \
+       adorn(`$(srcdir)/', join(`ciphers', `-', `cipher_modes'), `.h') \
+       adorn(`$(srcdir)/', join(`hashes', `-', `hash_modes'), `.c') \
+       adorn(`$(srcdir)/', join(`hashes', `-', `hash_modes'), `.h')
+
+$(MODES): $(srcdir)/genmodes
+
+archinclude_HEADERS = mptypes.h
+
+mptypes.h: mptypes
+       des_sp.h \
+       ./mptypes >mptypes.h
+
+BUILT_SOURCES = \
+       getdate.c \
+       addsuffix(join(`ciphers', `-', `cipher_modes'), `.c') \
+       addsuffix(join(`ciphers', `-', `cipher_modes'), `.h') \
+INCLUDES = -I$(srcdir)/..
+       addsuffix(join(`hashes', `-', `hash_modes'), `.c') \
+       addsuffix(join(`hashes', `-', `hash_modes'), `.h')
+include_HEADERS = \
+libcatacomb_la_LDFLAGS = -version-info 0:4:0
+## Middle number is the patchlevel.  Final number is the minor version.  The
+## difference between the first and last numbers is major version.
+
+define(`emit', `$1.h ')
+pkginclude_HEADERS = \
+       paranoia.h \
+       blkc.h hash.h \
+       mpx.h mpw.h mpscan.h mparena.h mp.h mptext.h mpmont.h \
+       ptab.h pgen.h rabin.h \
+       dsa.h dh.h \
+       allwithsuffix(`ciphers', `cipher_modes', `.h') \
+libcatacomb_a_SOURCES = \
+
+define(`emit', `$1.c ')
+libcatacomb_la_SOURCES = \
+       des-base.c des-base.h des_sp.h bf_ikey.h daftstory.h \
+       ptab.c pgen.c rabin.c \
+       dsa-sign.c dsa-verify.c dsa-gen.c \
+       dh-prime.c \
+       addsuffix(join(`ciphers', `-', `cipher_modes'), `.c') \
+noinst_PROGRAMS = des-mktab
+LDADD = libcatacomb.a ../mLib/libmLib.a
+## --- Utility programs ---
+noinst_PROGRAMS = des-mktab mptypes
+LDADD = libcatacomb.a
+bin_SCRIPTS = catacomb-config
+noinst_PROGRAMS = des-mktab genprimes mptypes
+LDADD = libcatacomb.la
+genprimes_SOURCES = genprimes.c
+genprimes_LDADD =
+
+mptypes_SOURCES = mptypes.c
+mptypes_LDADD =
+
+## --- Documentation ---
+
+man_MANS = key.1 keyring.5
+
+## --- Other handy definitions ---
+       @ln $(srcdir)/tests/* $(distdir)/tests
+EXTRA_DIST = Makefile.m4 genmodes $(man_MANS)
+
+dist-hook:
+       @ln getdate.c $(distdir) || ln $(srcdir)/getdate.c $(distdir) || true
+       @mkdir $(distdir)/tests
+       @ln $(srcdir)/tests/* $(distdir)/tests || true
+       @rm -f $(distdir)/tests/*~
+TESTS = \
+       rc4.t \
+       addsuffix(join(`ciphers', `-', `cipher_modes'), `.t') \
+       addsuffix(join(`hashes', `-', `hash_modes'), `.t') \
+       addsuffix(`ciphers', `.t') addsuffix(`hashes', `.t')
+       $(COMPILE) -DTEST_RIG -DSRCDIR=\"$(srcdir)\" \
+         $(srcdir)/$1.c libcatacomb.a ../mLib/libmLib.a -o $1.t')
+
+`$1.t: $1.c libcatacomb.a
+       $(COMPILE) -DTEST_RIG -DSRCDIR=\"$(srcdir)\" $(srcdir)/$1.c libcatacomb.a $(LIBS) -o $1.t')
+       $1.t)dnl
+$1.t: $1.c libcatacomb.la
+
+adorn(`nl`'CTESTRIG(', `ciphers', `)')
+adorn(`nl`'CTESTRIG(', `hashes', `)')
+CLEANFILES = *.t
+adorn(`nl`'CTESTRIG(', join(`hashes', `-', `hash_modes'), `)')
+CTESTRIG(dsa-verify)
+CLEANFILES = *.t mptypes.h
+TESTS = testprogs
+
+CLEANFILES = *.t mptypes.h des_sp.h ptab.c ptab.h
+
+## --- Makefile building (haha!) ---
+
+$(srcdir)/Makefile.am: $(srcdir)/Makefile.m4
+       m4 $(srcdir)/Makefile.m4 >$(srcdir)/Makefile.am
+       $(MODES) $(srcdir)/des_sp.h \
+       $(srcdir)/getdate.c getdate.c
+       $(srcdir)/Makefile.am \
+       $(srcdir)/getdate.c getdate.c \
+       $(MODES)
+
+##----- That's all, folks ---------------------------------------------------
diff --git a/acconfig.h b/acconfig.h
new file mode 100644 (file)
index 0000000..b8e2eb5
--- /dev/null
@@ -0,0 +1,68 @@
+/* -*-c-*-
+ *
+ * $Id: acconfig.h,v 1.1 1999/09/03 08:41:11 mdw Exp $
+ *
+ * Configuration header 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: acconfig.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef ACCONFIG_H
+#define ACCONFIG_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Autoconfiguration data --------------------------------------------*/
+@TOP@
+
+/* Package and version number.  */
+#define PACKAGE "catacomb"
+#define VERSION "1.0.0"
+
+/* If it's not provided already, define to be a signed integer type capable
+ * of representing any object size.  (If in doubt, make it an `int'.)  */
+#undef ssize_t
+
+/* If not provided already, define to be whatever your system uses for
+ * representing time.  (Probably `long'.)  */
+#undef time_t
+
+@BOTTOM@
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/bf_ikey.h b/bf_ikey.h
new file mode 100644 (file)
index 0000000..9d602fb
--- /dev/null
+++ b/bf_ikey.h
@@ -0,0 +1,324 @@
+/* -*-c-*-
+ *
+ * $Id: bf_ikey.h,v 1.1 1999/09/03 08:41:11 mdw Exp $
+ *
+ * Blowfish initial key data
+ *
+ * (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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: bf_ikey.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef BF_IKEY_H
+#define BF_IKEY_H
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define BLOWFISH_IKEY {                                                        \
+                                                                       \
+  /* --- P-array of round-specific subkeys --- */                      \
+                                                                       \
+  { 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,                    \
+    0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,                    \
+    0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,                    \
+    0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,                    \
+    0x9216d5d9, 0x8979fb1b },                                          \
+                                                                       \
+  /* --- First S-box --- */                                            \
+                                                                       \
+  { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,                    \
+    0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,                    \
+    0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,                    \
+    0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,                    \
+    0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,                    \
+    0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,                    \
+    0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,                    \
+    0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,                    \
+    0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,                    \
+    0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,                    \
+    0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,                    \
+    0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,                    \
+    0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,                    \
+    0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,                    \
+    0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,                    \
+    0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,                    \
+    0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,                    \
+    0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,                    \
+    0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,                    \
+    0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,                    \
+    0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,                    \
+    0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,                    \
+    0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,                    \
+    0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,                    \
+    0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,                    \
+    0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,                    \
+    0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,                    \
+    0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,                    \
+    0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,                    \
+    0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,                    \
+    0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,                    \
+    0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,                    \
+    0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,                    \
+    0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,                    \
+    0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,                    \
+    0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,                    \
+    0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,                    \
+    0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,                    \
+    0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,                    \
+    0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,                    \
+    0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,                    \
+    0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,                    \
+    0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,                    \
+    0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,                    \
+    0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,                    \
+    0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,                    \
+    0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,                    \
+    0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,                    \
+    0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,                    \
+    0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,                    \
+    0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,                    \
+    0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,                    \
+    0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,                    \
+    0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,                    \
+    0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,                    \
+    0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,                    \
+    0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,                    \
+    0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,                    \
+    0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,                    \
+    0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,                    \
+    0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,                    \
+    0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,                    \
+    0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,                    \
+    0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a },                  \
+                                                                       \
+  /* --- Second S-box --- */                                           \
+                                                                       \
+  { 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,                    \
+    0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,                    \
+    0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,                    \
+    0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,                    \
+    0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,                    \
+    0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,                    \
+    0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,                    \
+    0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,                    \
+    0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,                    \
+    0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,                    \
+    0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,                    \
+    0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,                    \
+    0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,                    \
+    0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,                    \
+    0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,                    \
+    0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,                    \
+    0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,                    \
+    0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,                    \
+    0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,                    \
+    0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,                    \
+    0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,                    \
+    0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,                    \
+    0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,                    \
+    0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,                    \
+    0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,                    \
+    0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,                    \
+    0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,                    \
+    0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,                    \
+    0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,                    \
+    0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,                    \
+    0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,                    \
+    0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,                    \
+    0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,                    \
+    0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,                    \
+    0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,                    \
+    0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,                    \
+    0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,                    \
+    0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,                    \
+    0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,                    \
+    0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,                    \
+    0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,                    \
+    0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,                    \
+    0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,                    \
+    0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,                    \
+    0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,                    \
+    0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,                    \
+    0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,                    \
+    0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,                    \
+    0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,                    \
+    0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,                    \
+    0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,                    \
+    0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,                    \
+    0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,                    \
+    0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,                    \
+    0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,                    \
+    0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,                    \
+    0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,                    \
+    0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,                    \
+    0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,                    \
+    0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,                    \
+    0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,                    \
+    0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,                    \
+    0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,                    \
+    0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 },                  \
+                                                                       \
+  /* --- Third S-box --- */                                            \
+                                                                       \
+  { 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,                    \
+    0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,                    \
+    0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,                    \
+    0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,                    \
+    0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,                    \
+    0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,                    \
+    0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,                    \
+    0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,                    \
+    0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,                    \
+    0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,                    \
+    0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,                    \
+    0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,                    \
+    0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,                    \
+    0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,                    \
+    0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,                    \
+    0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,                    \
+    0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,                    \
+    0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,                    \
+    0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,                    \
+    0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,                    \
+    0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,                    \
+    0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,                    \
+    0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,                    \
+    0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,                    \
+    0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,                    \
+    0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,                    \
+    0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,                    \
+    0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,                    \
+    0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,                    \
+    0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,                    \
+    0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,                    \
+    0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,                    \
+    0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,                    \
+    0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,                    \
+    0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,                    \
+    0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,                    \
+    0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,                    \
+    0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,                    \
+    0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,                    \
+    0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,                    \
+    0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,                    \
+    0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,                    \
+    0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,                    \
+    0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,                    \
+    0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,                    \
+    0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,                    \
+    0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,                    \
+    0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,                    \
+    0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,                    \
+    0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,                    \
+    0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,                    \
+    0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,                    \
+    0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,                    \
+    0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,                    \
+    0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,                    \
+    0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,                    \
+    0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,                    \
+    0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,                    \
+    0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,                    \
+    0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,                    \
+    0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,                    \
+    0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,                    \
+    0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,                    \
+    0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 },                  \
+                                                                       \
+  /* --- Fourth and final S-box --- */                                 \
+                                                                       \
+  { 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,                    \
+    0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,                    \
+    0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,                    \
+    0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,                    \
+    0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,                    \
+    0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,                    \
+    0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,                    \
+    0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,                    \
+    0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,                    \
+    0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,                    \
+    0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,                    \
+    0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,                    \
+    0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,                    \
+    0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,                    \
+    0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,                    \
+    0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,                    \
+    0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,                    \
+    0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,                    \
+    0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,                    \
+    0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,                    \
+    0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,                    \
+    0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,                    \
+    0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,                    \
+    0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,                    \
+    0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,                    \
+    0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,                    \
+    0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,                    \
+    0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,                    \
+    0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,                    \
+    0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,                    \
+    0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,                    \
+    0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,                    \
+    0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,                    \
+    0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,                    \
+    0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,                    \
+    0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,                    \
+    0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,                    \
+    0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,                    \
+    0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,                    \
+    0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,                    \
+    0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,                    \
+    0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,                    \
+    0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,                    \
+    0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,                    \
+    0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,                    \
+    0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,                    \
+    0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,                    \
+    0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,                    \
+    0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,                    \
+    0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,                    \
+    0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,                    \
+    0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,                    \
+    0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,                    \
+    0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,                    \
+    0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,                    \
+    0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,                    \
+    0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,                    \
+    0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,                    \
+    0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,                    \
+    0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,                    \
+    0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,                    \
+    0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,                    \
+    0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,                    \
+    0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 }                   \
+}
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#endif
diff --git a/blkc.h b/blkc.h
new file mode 100644 (file)
index 0000000..e7f5518
--- /dev/null
+++ b/blkc.h
@@ -0,0 +1,281 @@
+/* -*-c-*-
+ *
+ * $Id: blkc.h,v 1.1 1999/09/03 08:41:11 mdw Exp $
+ *
+ * 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: blkc.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef BLKC_H
+#define BLKC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#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))
+
+/* --- 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, int _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++; )                               \
+
+/* --- 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_128(PRE, decl, op, guts)                             \
+  BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);)
+
+#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_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_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 <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define BLKC_TEST(PRE, pre)                                            \
+                                                                       \
+static int 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);                                                         \
+}                                                                      \
+                                                                       \
+static test_chunk defs[] = {                                           \
+  { #pre, verify, { &type_hex, &type_hex, &type_hex, 0 } },            \
+  { #pre "-sched", 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_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/blowfish.c b/blowfish.c
new file mode 100644 (file)
index 0000000..16c862e
--- /dev/null
@@ -0,0 +1,208 @@
+/* -*-c-*-
+ *
+ * $Id: blowfish.c,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: blowfish.c,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "blowfish.h"
+#include "bf_ikey.h"
+#include "blkc.h"
+#include "paranoia.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+static blowfish_ctx ikey = BLOWFISH_IKEY;
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define ROUND(k, x, y, r)                                              \
+  ((x) ^= (k)->p[(r)],                                                 \
+   (y) ^= (((((k)->s0[((x) >> 24) & MASK8]) +                          \
+            ((k)->s1[((x) >> 16) & MASK8])) ^                          \
+           ((k)->s2[((x) >>  8) & MASK8])) +                           \
+          ((k)->s3[((x) >>  0) & MASK8])))
+
+#define EBLK(k, a, b, c, d) do {                                       \
+  uint32 _x = (a);                                                     \
+  uint32 _y = (b);                                                     \
+  ROUND((k), _x, _y,  0);                                              \
+  ROUND((k), _y, _x,  1);                                              \
+  ROUND((k), _x, _y,  2);                                              \
+  ROUND((k), _y, _x,  3);                                              \
+  ROUND((k), _x, _y,  4);                                              \
+  ROUND((k), _y, _x,  5);                                              \
+  ROUND((k), _x, _y,  6);                                              \
+  ROUND((k), _y, _x,  7);                                              \
+  ROUND((k), _x, _y,  8);                                              \
+  ROUND((k), _y, _x,  9);                                              \
+  ROUND((k), _x, _y, 10);                                              \
+  ROUND((k), _y, _x, 11);                                              \
+  ROUND((k), _x, _y, 12);                                              \
+  ROUND((k), _y, _x, 13);                                              \
+  ROUND((k), _x, _y, 14);                                              \
+  ROUND((k), _y, _x, 15);                                              \
+  (c) = _y ^ (k)->p[17];                                               \
+  (d) = _x ^ (k)->p[16];                                               \
+} while (0)
+
+#define DBLK(k, a, b, c, d) do {                                       \
+  uint32 _x = (a);                                                     \
+  uint32 _y = (b);                                                     \
+  ROUND((k), _x, _y, 17);                                              \
+  ROUND((k), _y, _x, 16);                                              \
+  ROUND((k), _x, _y, 15);                                              \
+  ROUND((k), _y, _x, 14);                                              \
+  ROUND((k), _x, _y, 13);                                              \
+  ROUND((k), _y, _x, 12);                                              \
+  ROUND((k), _x, _y, 11);                                              \
+  ROUND((k), _y, _x, 10);                                              \
+  ROUND((k), _x, _y,  9);                                              \
+  ROUND((k), _y, _x,  8);                                              \
+  ROUND((k), _x, _y,  7);                                              \
+  ROUND((k), _y, _x,  6);                                              \
+  ROUND((k), _x, _y,  5);                                              \
+  ROUND((k), _y, _x,  4);                                              \
+  ROUND((k), _x, _y,  3);                                              \
+  ROUND((k), _y, _x,  2);                                              \
+  (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)
+{
+  /* --- 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
new file mode 100644 (file)
index 0000000..9f4fb56
--- /dev/null
@@ -0,0 +1,113 @@
+/* -*-c-*-
+ *
+ * $Id: blowfish.h,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: blowfish.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+/*----- 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 BLOWFISH_H
+#define 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 0
+#define BLOWFISH_CLASS (N, B, 64)
+
+/*----- 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/cbc.h b/cbc.h
new file mode 100644 (file)
index 0000000..66979de
--- /dev/null
+++ b/cbc.h
@@ -0,0 +1,521 @@
+/* -*-c-*-
+ *
+ * $Id: cbc.h,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: cbc.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef CBC_H
+#define CBC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#ifndef BLKC_H
+#  include "blkc.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)                                             \
+                                                                       \
+typedef struct pre ## _cbcctx {                                                \
+  pre ## _ctx ctx;                     /* Underlying cipher context */ \
+  uint32 iv[PRE ## _BLKSZ / 4];                /* Previous ciphertext or IV */ \
+} pre ## _cbcctx;                                                      \
+                                                                       \
+extern void pre ## _cbcgetiv(const pre ## _cbcctx */*ctx*/,            \
+                            void */*iv*/);                             \
+                                                                       \
+extern void pre ## _cbcsetiv(pre ## _cbcctx */*ctx*/,                  \
+                            const void */*iv*/);                       \
+                                                                       \
+extern void pre ## _cbcsetkey(pre ## _cbcctx */*ctx*/,                 \
+                             const pre ## _ctx */*k*/);                \
+                                                                       \
+extern void pre ## _cbcinit(pre ## _cbcctx */*ctx*/,                   \
+                           const void */*key*/, size_t /*sz*/,         \
+                           const void */*iv*/);                        \
+                                                                       \
+extern void pre ## _cbcencrypt(pre ## _cbcctx */*ctx*/,                        \
+                              const void */*src*/, void */*dest*/,     \
+                              size_t /*sz*/);                          \
+                                                                       \
+extern void pre ## _cbcdecrypt(pre ## _cbcctx */*ctx*/,                        \
+                              const void */*src*/, void */*dest*/,     \
+                              size_t /*sz*/);                          \
+
+/* --- @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 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);                                       \
+    for (i = 0; i < sz; i++)                                           \
+      d[i] = b[i] ^ s[i];                                              \
+    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) {             \
+    BLKC_XLOAD(PRE, ctx->iv, s);                                       \
+    pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv);                         \
+    BLKC_STORE(PRE, d, ctx->iv);                                       \
+    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];                                            \
+    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.                                                          \
+     */                                                                        \
+                                                                       \
+    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.                                               \
+     */                                                                        \
+                                                                       \
+    s += PRE ## _BLKSZ;                                                        \
+    d += PRE ## _BLKSZ;                                                        \
+    for (i = 0; i < sz; i++) {                                         \
+      register octet x = b[i];                                         \
+      b[i] ^= s[i];                                                    \
+      d[i] = x;                                                                \
+    }                                                                  \
+    BLKC_LOAD(PRE, ctx->iv, b);                                                \
+    pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv);                         \
+    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:                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 ## _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;                                                              \
+}                                                                      \
+                                                                       \
+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/cfb.h b/cfb.h
new file mode 100644 (file)
index 0000000..0719934
--- /dev/null
+++ b/cfb.h
@@ -0,0 +1,477 @@
+/* -*-c-*-
+ *
+ * $Id: cfb.h,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: cfb.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef CFB_H
+#define CFB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#ifndef BLKC_H
+#  include "blkc.h"
+#endif
+
+#ifndef PARANOIA_H
+#  include "paranoia.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)                                             \
+                                                                       \
+typedef struct pre ## _cfbctx {                                                \
+  pre ## _ctx ctx;                     /* Underlying cipher context */ \
+  int off;                             /* Offset into @iv@ buffer */   \
+  octet iv[PRE ## _BLKSZ];             /* Previous ciphertext or IV */ \
+} pre ## _cfbctx;                                                      \
+                                                                       \
+extern void pre ## _cfbgetiv(const pre ## _cfbctx */*ctx*/,            \
+                            void */*iv*/);                             \
+                                                                       \
+extern void pre ## _cfbsetiv(pre ## _cfbctx */*ctx*/,                  \
+                            const void */*iv*/);                       \
+                                                                       \
+extern void pre ## _cfbbdry(pre ## _cfbctx */*ctx*/);                  \
+                                                                       \
+extern void pre ## _cfbsetkey(pre ## _cfbctx */*ctx*/,                 \
+                             const pre ## _ctx */*k*/);                \
+                                                                       \
+extern void pre ## _cfbinit(pre ## _cfbctx */*ctx*/,                   \
+                           const void */*key*/, size_t /*sz*/,         \
+                           const void */*iv*/);                        \
+                                                                       \
+extern void pre ## _cfbencrypt(pre ## _cfbctx */*ctx*/,                        \
+                              const void */*src*/, void */*dest*/,     \
+                              size_t /*sz*/);                          \
+                                                                       \
+extern void pre ## _cfbdecrypt(pre ## _cfbctx */*ctx*/,                        \
+                              const void */*src*/, void */*dest*/,     \
+                              size_t /*sz*/);                          \
+
+
+/* --- @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;                                                       \
+  int off = ctx->off;                                                  \
+  int 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)             \
+{                                                                      \
+  uint32 niv[PRE ## _BLKSZ / 4];                                       \
+  BLKC_LOAD(PRE, niv, iv);                                             \
+  pre ## _eblk(&ctx->ctx, niv, niv);                                   \
+  BLKC_STORE(PRE, ctx->iv, niv);                                       \
+  ctx->off = 0;                                                                \
+}                                                                      \
+                                                                       \
+/* --- @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)                              \
+{                                                                      \
+  octet iv[PRE ## _BLKSZ];                                             \
+  pre ## _cfbgetiv(ctx, iv);                                           \
+  pre ## _cfbsetiv(ctx, iv);                                           \
+  BURN(iv);                                                            \
+}                                                                      \
+                                                                       \
+/* --- @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;                                                       \
+}                                                                      \
+                                                                       \
+/* --- @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 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;                                                     \
+  int 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;                                                \
+    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;                                                          \
+      BLKC_XLOAD(PRE, iv, s);                                          \
+      BLKC_STORE(PRE, d, iv);                                          \
+      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;                                      \
+      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:                Encrypts a block with a block cipher in CFB 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 ## _cfbdecrypt(pre ## _cfbctx *ctx,                           \
+                       const void *src, void *dest,                    \
+                       size_t sz)                                      \
+{                                                                      \
+  const octet *s = src;                                                        \
+  octet *d = dest;                                                     \
+  int 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;                                                              \
+}                                                                      \
+                                                                       \
+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/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..4893b92
--- /dev/null
@@ -0,0 +1,95 @@
+dnl -*-fundamental-*-
+dnl
+dnl $Id: configure.in,v 1.1 1999/09/03 08:41:11 mdw Exp $
+dnl
+dnl Autoconfiguration for Catacomb
+dnl
+dnl (c) 1999 Straylight/Edgeware
+dnl
+
+dnl ----- Licensing notice --------------------------------------------------
+dnl
+dnl This file is part of Catacomb.
+dnl
+dnl Catacomb is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU Library General Public License as
+dnl published by the Free Software Foundation; either version 2 of the
+dnl License, or (at your option) any later version.
+dnl 
+dnl Catacomb is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU Library General Public License for more details.
+dnl 
+dnl You should have received a copy of the GNU Library General Public
+dnl License along with Catacomb; if not, write to the Free
+dnl Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+dnl MA 02111-1307, USA.
+
+dnl ----- Revision history --------------------------------------------------
+dnl
+dnl $Log: configure.in,v $
+dnl Revision 1.1  1999/09/03 08:41:11  mdw
+dnl Initial import.
+dnl
+dnl Revision 1.1  1999/09/03 08:41:11  mdw
+dnl Initial import.
+dnl
+
+AM_INIT_AUTOMAKE(catacomb, 1.0.0pre1)
+
+AC_INIT(blkc.h)
+AM_INIT_AUTOMAKE(catacomb, 1.0.0pre2)
+AM_CONFIG_HEADER(config.h)
+
+dnl --- Make sure I can compile and build libraries ---
+
+AC_PROG_CC
+AC_CHECK_PROG(AR, ar, ar)
+AC_PROG_RANLIB
+mdw_MLIB
+
+AC_PROG_YACC
+
+dnl --- Actually, I assume these exist anyway ---
+
+AC_CHECK_HEADERS(unistd.h)
+AC_HEADER_STDC
+
+dnl --- Check for various important system types ---
+
+AC_TYPE_PID_T
+
+dnl --- Tedious check for ssize_t ---
+dnl
+dnl glibc-2 puts ssize_t in a strange place.
+
+AC_CACHE_CHECK(for ssize_t, cat_cv_type_ssize_t,
+[AC_EGREP_CPP(ssize_t,
+[#include <sys/types.h>
+#if HAVE_UNISTD_H
+#inlcude <unistd.h>
+#endif
+#if STDC_HEADERS
+#include <stddef.h>
+#include <stdlib.h>
+#endif],
+cat_cv_type_ssize_t=yes, cat_cv_type_ssize_t=no)])
+if test $cat_cv_type_ssize_t = no; then
+  AC_DEFINE(ssize_t, int)
+fi
+AC_TYPE_UID_T
+AC_CHECK_TYPE(time_t, long)
+mdw_TYPE_SSIZE_T
+
+dnl --- Can I call `initgroups'? ---
+dnl
+dnl This is used in noise-gathering.
+
+AC_CHECK_FUNCS(setgroups)
+AC_OUTPUT(Makefile)
+dnl --- Done ---
+
+AC_OUTPUT(Makefile catacomb-config)
+
+dnl ----- That's all, folks -------------------------------------------------
diff --git a/daftstory.h b/daftstory.h
new file mode 100644 (file)
index 0000000..8715cdc
--- /dev/null
@@ -0,0 +1,86 @@
+/* -*-c-*-
+ *
+ * $Id: daftstory.h,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: daftstory.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef DAFTSTORY_H
+#define 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 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
new file mode 100644 (file)
index 0000000..73246b6
--- /dev/null
@@ -0,0 +1,49 @@
+/* -*-c-*-
+ *
+ * $Id: des-base.c,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: des-base.c,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "des-base.h"
+#include "des_sp.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+uint32 des_sp[8][64] = DES_SP;
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/des-base.h b/des-base.h
new file mode 100644 (file)
index 0000000..dd4fdb7
--- /dev/null
@@ -0,0 +1,166 @@
+/* -*-c-*-
+ *
+ * $Id: des-base.h,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: des-base.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef DES_BASE_H
+#define DES_BASE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- External data -----------------------------------------------------*/
+
+extern 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
new file mode 100644 (file)
index 0000000..07cff39
--- /dev/null
@@ -0,0 +1,279 @@
+/* -*-c-*-
+ *
+ * $Id: des-mktab.c,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: des-mktab.c,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+/*----- Static variables --------------------------------------------------*/
+
+/* --- S boxes --- */
+
+static 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(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("\
+/* DES SP table (generated) */\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", stdout);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/des.c b/des.c
new file mode 100644 (file)
index 0000000..cb73a8e
--- /dev/null
+++ b/des.c
@@ -0,0 +1,263 @@
+/* -*-c-*-
+ *
+ * $Id: des.c,v 1.1 1999/09/03 08:41:11 mdw Exp $
+ *
+ * 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: des.c,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+/*----- 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"
+
+/*----- 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_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;
+  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.
+   */
+
+  assert(((void)"DES key must be 56 or 64 bits", sz == 7 || sz == 8));
+
+  if (sz == 8) {
+    const octet *p = buf;
+    x = LOAD32(p); y = LOAD32(p + 4);
+  } else {
+    const octet *p = buf;
+    x = LOAD32(p);
+    x = (x & 0xfe000000) | ((x & 0x01fffff0) >> 1);
+    x = (x & 0xfffe0000) | ((x & 0x0001fff8) >> 1);
+    x = (x & 0xfffffe00) | ((x & 0x000001fc) >> 1);
+    y = LOAD32(p + 3) << 1; /* Note: misaligned */
+    y = (y & 0x000000fe) | ((y & 0x1fffff00) << 1);
+    y = (y & 0x0000fefe) | ((y & 0x3fff0000) << 1);
+    y = (y & 0x00fefefe) | ((y & 0x7f000000) << 1);
+  }
+
+  /* --- Permute using the pointless PC1 --- */
+
+  {
+    uint32 ka[2];
+    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
new file mode 100644 (file)
index 0000000..857cec3
--- /dev/null
+++ b/des.h
@@ -0,0 +1,116 @@
+/* -*-c-*-
+ *
+ * $Id: des.h,v 1.1 1999/09/03 08:41:11 mdw Exp $
+ *
+ * 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: des.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+/*----- 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 DES_H
+#define 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)
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct des_ctx {
+  uint32 k[32];
+} des_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @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
new file mode 100644 (file)
index 0000000..281d8ea
--- /dev/null
+++ b/des3.c
@@ -0,0 +1,123 @@
+/* -*-c-*-
+ *
+ * $Id: des3.c,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: des3.c,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+/*----- 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"
+
+/*----- 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;
+
+  assert(((void)("des3 key length must be one of 7, 8, 14, 16, 21 or 24"),
+               (sz % 7 == 0 || sz % 8 == 0) && sz < 25));
+
+  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
new file mode 100644 (file)
index 0000000..ce57ac9
--- /dev/null
+++ b/des3.h
@@ -0,0 +1,116 @@
+/* -*-c-*-
+ *
+ * $Id: des3.h,v 1.1 1999/09/03 08:41:11 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: des3.h,v $
+ * Revision 1.1  1999/09/03 08:41:11  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef DES3_H
+#define 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 DES_H
+#  include "des.h"
+#endif
+
+/*----- Magical numbers ---------------------------------------------------*/
+
+#define DES3_BLKSZ 8
+#define DES3_KEYSZ 21
+#define DES3_CLASS (N, B, 64)
+
+/*----- 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/ecb.h b/ecb.h
new file mode 100644 (file)
index 0000000..1027591
--- /dev/null
+++ b/ecb.h
@@ -0,0 +1,440 @@
+/* -*-c-*-
+ *
+ * $Id: ecb.h,v 1.1 1999/09/03 08:41:12 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: ecb.h,v $
+ * Revision 1.1  1999/09/03 08:41:12  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef ECB_H
+#define ECB_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#ifndef BLKC_H
+#  include "blkc.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)                                             \
+                                                                       \
+typedef struct pre ## _ecbctx {                                                \
+  pre ## _ctx ctx;                     /* Underlying cipher context */ \
+} pre ## _ecbctx;                                                      \
+                                                                       \
+extern void pre ## _ecbsetkey(pre ## _ecbctx */*ctx*/,                 \
+                             const pre ## _ctx */*k*/);                \
+                                                                       \
+extern void pre ## _ecbinit(pre ## _ecbctx */*ctx*/,                   \
+                           const void */*key*/, size_t /*sz*/,         \
+                           const void */*iv*/);                        \
+                                                                       \
+extern void pre ## _ecbencrypt(pre ## _ecbctx */*ctx*/,                        \
+                              const void */*src*/, void */*dest*/,     \
+                              size_t /*sz*/);                          \
+                                                                       \
+extern void pre ## _ecbdecrypt(pre ## _ecbctx */*ctx*/,                        \
+                              const void */*src*/, void */*dest*/,     \
+                              size_t /*sz*/);                          \
+
+/* --- @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];                                       \
+    BLKC_LOAD(PRE, x, s);                                              \
+    pre ## _eblk(&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 --- *                                           \
+     *                                                                 \
+     * 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.     \
+     */                                                                        \
+                                                                       \
+    BLKC_LOAD(PRE, x, s);                                              \
+    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.                                               \
+     */                                                                        \
+                                                                       \
+    s += PRE ## _BLKSZ;                                                        \
+    d += PRE ## _BLKSZ;                                                        \
+    for (i = 0; i < sz; i++) {                                         \
+      register octet y = b[i];                                         \
+      b[i] = s[i];                                                     \
+      d[i] = y;                                                                \
+    }                                                                  \
+    BLKC_LOAD(PRE, x, b);                                              \
+    pre ## _eblk(&ctx->ctx, x, x);                                     \
+    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:                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 ## _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;                                                              \
+}                                                                      \
+                                                                       \
+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/genmodes b/genmodes
new file mode 100755 (executable)
index 0000000..48175ce
--- /dev/null
+++ b/genmodes
@@ -0,0 +1,50 @@
+#! /bin/sh
+
+baselist=$1
+extlist=$2
+
+for i in $baselist; do
+  I=`echo "$i" | tr -d '\n' | tr a-z A-Z | tr -c a-zA-Z0-9 _`
+  for j in $extlist; do
+    J=`echo "$j" | tr -d '\n' | tr a-z A-Z | tr -c a-zA-Z0-9 _`
+    guard="${I}_${J}_H"
+    cat >$i-$j.h <<EOF
+/* -*-c-*-
+ *
+ * $i-$j.h [generated]
+ */
+
+#ifndef $guard
+#define $guard
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+#ifndef ${J}_H
+#  include "$j.h"
+#endif
+
+#ifndef ${I}_H
+#  include "$i.h"
+#endif
+
+${J}_DECL($I, $i)
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
+EOF
+    cat >$i-$j.c <<EOF
+/* -*-c-*-
+ *
+ * $i-$j.h [generated]
+ */
+
+#include "$i-$j.h"
+${J}_DEF($I, $i)
+EOF
+  done
+done
diff --git a/hash.h b/hash.h
new file mode 100644 (file)
index 0000000..5d43bfb
--- /dev/null
+++ b/hash.h
@@ -0,0 +1,234 @@
+/* -*-c-*-
+ *
+ * $Id: hash.h,v 1.1 1999/09/03 08:41:12 mdw Exp $
+ *
+ * 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: hash.h,v $
+ * Revision 1.1  1999/09/03 08:41:12  mdw
+ * Initial import.
+ *
+ */
+
+#ifndef HASH_H
+#define 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 --- */                            \
+                                                                       \
+  _bctx->count += _bsz;                                                        \
+                                                                       \
+  /* --- 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->count << 3);          \
+  STORE32_L(_mctx->buf + PRE##_BUFSZ - 4, _mctx->count >> 29);         \
+  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_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 test_chunk defs[] = {                                           \
+  { #pre, verify, { &type_string, &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/hmac.h b/hmac.h
new file mode 100644 (file)
index 0000000..8849258
--- /dev/null
+++ b/hmac.h
@@ -0,0 +1,321 @@
+/* -*-c-*-
+ *
+ * $Id: hmac.h,v 1.1 1999/09/03 08:41:12 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: hmac.h,v $
+ * Revision 1.1  1999/09/03 08:41:12  mdw
+ * Initial import.
+ *
+ */
+
+/*----- 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.  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 HMAC_H
+#define HMAC_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#ifndef PARANOIA_H
+#  include "paranoia.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)                                            \
+                                                                       \
+typedef struct pre##_mackey {                                          \
+  octet ochain[PRE##_HASHSZ];          /* Chaining for outer hash */   \
+  unsigned long ocount;                        /* Byte count for outer hash */ \
+  octet ichain[PRE##_HASHSZ];          /* Chaining for inner hash */   \
+  unsigned long icount;                        /* Byte count for inner hash */ \
+} pre##_mackey;                                                                \
+                                                                       \
+typedef struct pre##_macctx {                                          \
+  pre##_ctx ctx;                       /* Context for main hashing */  \
+  octet chain[PRE##_HASHSZ];           /* Chaining for outer hash */   \
+  unsigned long count;                 /* Byte count for outer hash */ \
+} pre##_macctx;                                                                \
+                                                                       \
+extern void pre##_nmac(pre##_mackey */*key*/,                          \
+                      const void */*ok*/, const void */*ik*/);         \
+                                                                       \
+extern void pre##_hmac(pre##_mackey */*key*/,                          \
+                      const void */*k*/, size_t /*sz*/);               \
+                                                                       \
+extern void pre##_macinit(pre##_macctx */*ctx*/,                       \
+                         const pre##_mackey */*key*/);                 \
+                                                                       \
+extern void pre##_mac(pre##_macctx */*ctx*/,                           \
+                     const void */*buf*/, size_t /*sz*/);              \
+                                                                       \
+extern void pre##_macdone(pre##_macctx */*ctx*/, void */*mac*/);
+
+/* --- @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)                                             \
+                                                                       \
+/* --- @pre_nmac@ --- *                                                        \
+ *                                                                     \
+ * 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##_nmac(pre##_mackey *key, const void *ok, const void *ik)     \
+{                                                                      \
+  memcpy(key->ochain, ok, PRE##_HASHSZ);                               \
+  memcpy(key->ichain, ik, PRE##_HASHSZ);                               \
+  key->ocount = key->icount = 0;                                       \
+}                                                                      \
+                                                                       \
+/* --- @pre_hmac@ --- *                                                        \
+ *                                                                     \
+ * 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##_hmac(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_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##_HASHSZ);                       \
+  ctx->count = key->ocount;                                            \
+  pre##_set(&ctx->ctx, key->ichain, key->icount);                      \
+}                                                                      \
+                                                                       \
+/* --- @pre_mac@ --- *                                                 \
+ *                                                                     \
+ * 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##_mac(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);                                          \
+}                                                                      \
+                                                                       \
+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 <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##_hmac(&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##_mac(&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/idea.c b/idea.c
new file mode 100644 (file)
index 0000000..f554bf4
--- /dev/null
+++ b/idea.c
@@ -0,0 +1,276 @@
+/* -*-c-*-
+ *
+ * $Id: idea.c,v 1.1 1999/09/03 08:41:12 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: idea.c,v $
+ * Revision 1.1  1999/09/03 08:41:12  mdw
+ * Initial import.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "idea.h"
+
+/*----- 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;
+
+  for (;;) {
+    uint32 q, r, t;
+    if (!(r = m % n))
+      break;
+    q = m / n;
+    m = n; n = 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.
+ */
+
+#define MUL(x, y) do {                                                 \
+  uint32 _mx, _my = (y);                                               \
+  if ((_mx = U16(x)) == 0)                                             \
+    (x) = 1 - _my;                                                     \
+  else if (_my == 0)                                                   \
+    (x) = 1 - _mx;                                                     \
+  else {                                                               \
+    _my *= _mx;                                                                \
+    _mx = U16(_my); _my >>= 16;                                                \
+    if (_mx < _my)                                                     \
+      (x) = _mx - _my + 1;                                             \
+    else                                                               \
+      (x) = _mx - _my;                                                 \
+  }                                                                    \
+} 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)
+{
+  assert(((void)"IDEA key must be 128 bits", sz == IDEA_KEYSZ));
+
+  /* --- 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) = (U16(_a) << 16) | U16(_c);                                     \
+  (d) = (U16(_b) << 16) | 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
new file mode 100644 (file)
index 0000000..5d26a57
--- /dev/null
+++ b/idea.h
@@ -0,0 +1,119 @@
+/* -*-c-*-
+ *
+ * $Id: idea.h,v 1.1 1999/09/03 08:41:12 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.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: idea.h,v $
+ * Revision 1.1  1999/09/03 08:41:12  mdw
+ * Initial import.
+ *
+ */
+
+/*----- 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 IDEA_H
+#define 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)
+
+/*----- 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/key.1 b/key.1
new file mode 100644 (file)
index 0000000..cbac9bc
--- /dev/null
+++ b/key.1
@@ -0,0 +1,245 @@
+.\" -*-nroff-*-
+.TH key 1 "5 June 1999" Catacomb
+.SH NAME
+key \- simple key management system
+.SH SYNOPSIS
+.B key
+.RB [ \-k
+.IR keyring ]
+.I command
+.PP
+where
+.I command
+is one of:
+.PP
+.B add
+.RB [ \-b
+.IR bits ]
+.RB [ \-e
+.IR expire ]
+.RB [ \-c
+.IR comment ]
+.I type
+.IR attr ...
+.br
+.B expire
+.IR keyid ...
+.br
+.B delete
+.IR keyid ...
+.br
+.B setattr
+.I keyid
+.IR attr ...
+.br
+.B list
+.RB [ \-qv ]
+.br
+.B tidy
+.br
+.B extract
+.I file
+.IR keyid ...
+.br
+.B merge
+.I file
+.SH DESCRIPTION
+The
+.B key
+command performs useful operations on Catacomb keyring files.  It
+provides a number of subcommands, by which the various operations may be
+carried out.
+.SS "Global options"
+Before the command name,
+.I "global options"
+may be given.  The following global options are supported:
+.TP
+.B "\-h, \-\-help"
+Writes a brief summary of
+.BR key 's
+various options to standard output, and
+returns a successful exit status.
+.TP
+.B "\-v, \-\-version"
+Writes the program's version number to standard output, and returns a
+successful exit status.
+.TP
+.B "\-u, \-\-usage"
+Writes a very terse command line summary to standard output, and returns
+a successful exit status.
+.TP
+.BI "\-k, \-\-keyring=" file
+Names the keyring file which
+.B key
+is to process.  The default keyring, used if this option doesn't specify
+one, is the file named
+.B keyring
+in the current directory.  The keyring must be stored in a regular file:
+pipes, sockets, devices etc. are not allowed.
+The
+.B key
+program attempts to lock the keyring before accessing it, using
+.BR fcntl (2)
+locking.  It will however time out after a short while (10 seconds) and
+report a failure.
+.SS Concepts
+In addition to the actual key data itself, a Catacomb key has a number
+of other pieces of information attached to it:
+.TP
+.B keyid
+Every key has a 32-bit identifying number, written in hexadecimal.  The
+keyid is derived from the actual key contents (although knowledge of a
+key's keyid doesn't help one to guess the key itself).  Applications use
+keyids to refer to specific keys.  A
+.I deleted
+key cannot be looked up by keyid.
+.TP
+.B type
+A key's type string describes what the key may be used for.  The type
+string is arbitrary, except that it may not contain whitespace
+characters.  Applications use key types to obtain an arbitrary but
+suitable key for some purpose.  An
+.I expired
+key cannot be looked up by type, but may be looked up by keyid.
+.TP
+.B "expiry time"
+Most keys expire after a certain amount of time.  Once a key has
+expired, it will no longer be chosen as a result of a lookup by key
+type.  However, it is not deleted until its deletion time is also
+reached.
+.TP
+.B "deletion time"
+A key's deletion time is the latest expiry time of any of the objects
+which require that key.  For example, a key used for authenticating
+cryptographic cookies should have its deletion time set to the longest
+expiry time of any of the cookies it can authenticate.  A key is never
+deleted until it has also expired.  Once a key has expired
+.I and
+its deletion time is passed, it can no longer be referred to by
+applications, and will be removed from the keyring next time it's
+written to disk.
+.TP
+.B comment
+A key may be given a comment when it's created.  The comment is for the
+benefit of users, and isn't interpreted by applications at all.
+(Hopefully.)
+.TP
+.B attributes
+A key as zero or more name/value pairs.  The names and values are
+arbitrary strings, except they may not contain null bytes.  Some
+attributes may have meaning for particular applications or key types;
+others may be assigned global meanings in future.
+.SH "COMMAND REFERENCE"
+.SS add
+The
+.B add
+command creates a new key and adds it to the keyring.  The command
+accepts the following options:
+.TP
+.BI "\-b, \-\-bits=" bits
+The length of the key to generate, in bits.  The default, if this option
+is not supplied, is 128 bits.  The bit length must be nonzero, and must
+be a multiple of 8.
+.TP
+.BI "\-e, \-\-expire=" expire
+The expiry date for the generated key.  This may be the string
+.RB ` forever '
+if the key should never expire automatically, or any date acceptable to
+the
+.BR getdate (3)
+library function.  Briefly,
+.B getdate
+understands absolute dates such as
+.RB ` 1999-08-02 '
+or
+.RB ` "August 2nd, 1999" ',
+and (perhaps more usefully) relative dates such as
+.RB ` "+2 weeks" '.
+The default is to allow a 2 week expiry, which isn't useful.
+.TP
+.BI "\-c, \-\-comment=" comment
+Sets a comment for the key.  The default is not to attach a comment.
+.PP
+The key's type is given by the required
+.I type
+argument.  Following the type are zero or more attributes, which are
+attached to the key in the same way as for the
+.B setattr
+command.
+.PP
+The
+.B key
+program only generates random bitstrings, which are suitable for most
+symmetric algorithms but not for public key cryptography.  Generating
+keys for more exotic algorithms is a feature which will be added later.
+The keys are generated using the Catacomb random number generator, using
+the
+.B rand_goodbits
+function.  The Catacomb generator is believed to be strong.
+.SS expire
+Forces keys to immediately expire.  An expired key is not chosen when a
+program requests a key by its type.  The keys to expire are listed by
+their
+.IR keyid s.
+.SS delete
+Deletes keys immediately.  The keys to delete are listed by their
+.IR keyid s.
+Be careful when deleting keys.  It might be a better idea
+to expire keys rather than deleting them.
+.SS setattr
+Attaches attributes to a key.  The key to which the attributes should be
+attached is given by its
+.IR keyid .
+Each attribute has the form
+.IB name = value\fR.
+An attribute can be deleted by assigning it an empty value.  Although
+the keyring file format is capable of representing an attribute with an
+empty value as distinct from a nonexistant attribute, this interface
+does not allow empty attributes to be set.
+.SS list
+Lists the keys in the keyring.  A couple of options are supported:
+.TP
+.B "\-v, \-\-verbose"
+Increases the amount of information displayed for each key.  Repeat for
+a greater effect.
+.TP
+.B "\-q, \-\-quiet"
+Decreases the amount of information displayed for each key.  Each use
+cancels a
+.RB ` \-v '
+option.
+.PP
+By default, a single line of output is generated for each, showing
+keyids, types, expiry and deletion dates, and comments.  Additional
+.RB ` \-v '
+options show more information, such as the exact time of day for expiry
+and deletion, key attributes, and a hex dump of the actual key data.
+.SS tidy
+Simply reads the keyring from file and writes it back again.  This has
+the effect of removing any deleted keys from the file.
+.SS extract
+Writes a selection of keys to the named
+.IR file ,
+which may be
+.RB ` \- '
+to designate standard output.  The keys to extract are listed by their
+.IR keyid s.
+The output is a valid keyring file.
+.SS merge
+Merges the keys from the named
+.IR file ,
+which may be
+.RB ` \- '
+to designate standard input, with the keyring.  Keys already in the
+keyring are not overwritten: you must explicitly remove them first if
+you want them to be replaced during the merge.
+.SH BUGS
+The ability to generate keys for specific algorithms ought to be added,
+for DES (setting the parity bits correctly), RSA, ElGamal and DSA, at
+the very least.  (None of these systems are actually implemented in
+Catacomb at the moment, however.)
+.SH "SEE ALSO"
+.BR keyring (5).
+.SH AUTHOR
+Mark Wooding, <mdw@nsict.org>
+
diff --git a/key.c b/key.c
new file mode 100644 (file)
index 0000000..9ffa98b
--- /dev/null
+++ b/key.c
@@ -0,0 +1,1077 @@
+/* -*-c-*-
+ *
+ * $Id: key.c,v 1.1 1999/09/03 08:41:12 mdw Exp $
+ *
+ * Simple key management
+ *
+ * (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 Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: key.c,v $
+ * Revision 1.1  1999/09/03 08:41:12  mdw
+ * Initial import.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <mLib/alloc.h>
+#include <mLib/base64.h>
+#include <mLib/bits.h>
+#include <mLib/crc32.h>
+#include <mLib/dstr.h>
+#include <mLib/hash.h>
+#include <mLib/lock.h>
+#include <mLib/report.h>
+#include <mLib/str.h>
+#include <mLib/sub.h>
+#include <mLib/sym.h>
+#include <mLib/url.h>
+
+#include "key.h"
+
+/*----- Useful macros -----------------------------------------------------*/
+
+#define KEY_PARANOID
+#define NOTHING
+
+#ifdef KEY_PARANOID
+#  define KEY_WRITE(f, func, val) do {                                 \
+     if (!(f)->f & KF_WRITE) {                                         \
+       moan(#func " [caller error]: keyfile is readonly");             \
+       errno = EROFS;                                                  \
+       return val;                                                     \
+     }                                           &