--- /dev/null
+/* -*-c-*-
+ *
+ * $Id: cast256.c,v 1.1 2000/06/17 10:49:14 mdw Exp $
+ *
+ * The CAST-256 block cipher
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: cast256.c,v $
+ * Revision 1.1 2000/06/17 10:49:14 mdw
+ * New cipher.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+#include "blkc.h"
+#include "cast-base.h"
+#include "cast256.h"
+#include "gcipher.h"
+#include "paranoia.h"
+
+/*----- Global variables --------------------------------------------------*/
+
+const octet cast256_keysz[] = { KSZ_RANGE, CAST256_KEYSZ, 0, 32, 1 };
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @cast256_init@ --- *
+ *
+ * Arguments: @cast128_ctx *k@ = pointer to key block to fill in
+ * @const void *buf@ = pointer to buffer of key material
+ * @size_t sz@ = size of key material
+ *
+ * Returns: ---
+ *
+ * Use: Initializes a CAST-256 key buffer. CAST-256 accepts
+ * 256-bit keys or shorter.
+ */
+
+void cast256_init(cast256_ctx *k, const void *buf, size_t sz)
+{
+ const octet *p = buf;
+ uint32 kk[8];
+ uint32 *km;
+ octet *kr;
+ unsigned i, j;
+ uint32 a, b, c, d, e, f, g, h;
+ uint32 m;
+ unsigned r;
+
+ /* --- Fiddle with the key size --- */
+
+ KSZ_ASSERT(cast256, sz);
+
+ /* --- Read the key into the array --- */
+
+ i = 0;
+ b = 32; a = 0;
+ for (;;) {
+ if (!sz)
+ break;
+ b -= 8;
+ a |= ((uint32)*p++ << b);
+ sz--;
+ if (b == 0) {
+ kk[i++] = a;
+ if (i == 8)
+ break;
+ a = 0;
+ b = 32;
+ }
+ }
+
+ for (; i < 8; i++) {
+ kk[i] = a;
+ a = 0;
+ }
+
+ /* --- Read the key words out --- */
+
+ a = kk[0]; b = kk[1]; c = kk[2]; d = kk[3];
+ e = kk[4]; f = kk[5]; g = kk[6]; h = kk[7];
+
+#define ROOT2 0x5a827999
+#define ROOT3 0x6ed9eba1
+
+ m = ROOT2;
+ r = 19;
+
+ km = k->km;
+ kr = k->kr;
+ for (i = 0; i < 12; i++) {
+ for (j = 0; j < 2; j++) {
+ CAST_R1(m, r, g, h); m += ROOT3; r = (r + 17) & 0x1f;
+ CAST_R2(m, r, f, g); m += ROOT3; r = (r + 17) & 0x1f;
+ CAST_R3(m, r, e, f); m += ROOT3; r = (r + 17) & 0x1f;
+ CAST_R1(m, r, d, e); m += ROOT3; r = (r + 17) & 0x1f;
+ CAST_R2(m, r, c, d); m += ROOT3; r = (r + 17) & 0x1f;
+ CAST_R3(m, r, b, c); m += ROOT3; r = (r + 17) & 0x1f;
+ CAST_R1(m, r, a, b); m += ROOT3; r = (r + 17) & 0x1f;
+ CAST_R2(m, r, h, a); m += ROOT3; r = (r + 17) & 0x1f;
+ }
+ km[0] = h; km[1] = f; km[2] = d; km[3] = b;
+ kr[0] = a & 0x1f; kr[1] = c & 0x1f; kr[2] = e & 0x1f; kr[3] = g & 0x1f;
+ km += 4; kr += 4;
+ }
+}
+
+/* --- @cast256_eblk@, @cast256_dblk@ --- *
+ *
+ * Arguments: @const cast256_ctx *k@ = pointer to key block
+ * @const uint32 s[2]@ = pointer to source block
+ * @uint32 d[2]@ = pointer to destination block
+ *
+ * Returns: ---
+ *
+ * Use: Low-level block encryption and decryption.
+ */
+
+#define Q0(k, r, a, b, c, d) do { \
+ CAST_R1(k[0], r[0], c, d); \
+ CAST_R2(k[1], r[1], b, c); \
+ CAST_R3(k[2], r[2], a, b); \
+ CAST_R1(k[3], r[3], d, a); \
+} while (0)
+
+#define Q1(k, r, a, b, c, d) do { \
+ CAST_R1(k[3], r[3], d, a); \
+ CAST_R3(k[2], r[2], a, b); \
+ CAST_R2(k[1], r[1], b, c); \
+ CAST_R1(k[0], r[0], c, d); \
+} while (0)
+
+void cast256_eblk(const cast256_ctx *k, const uint32 *s, uint32 *d)
+{
+ uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
+ const uint32 *km = k->km;
+ const octet *kr = k->kr;
+
+ Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q0(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+
+ Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+ Q1(km, kr, aa, bb, cc, dd); km += 4; kr += 4;
+
+ d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
+}
+
+void cast256_dblk(const cast256_ctx *k, const uint32 *s, uint32 *d)
+{
+ uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
+ const uint32 *km = k->km + 48;
+ const octet *kr = k->kr + 48;
+
+ km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q0(km, kr, aa, bb, cc, dd);
+
+ km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+ km -= 4; kr -= 4; Q1(km, kr, aa, bb, cc, dd);
+
+ d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
+}
+
+BLKC_TEST(CAST256, cast256)
+
+/*----- That's all, folks -------------------------------------------------*/