--- /dev/null
+/* -*-c-*-
+ *
+ * Build combined S-P tables for DES
+ *
+ * (c) 1999 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+
+/*----- Static variables --------------------------------------------------*/
+
+/* --- S boxes --- */
+
+static const char s[8][4][16] = {
+
+ /* --- S1 --- */
+
+ { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },
+ { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },
+ { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },
+ { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } },
+
+ /* --- S2 --- */
+
+ { { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
+ { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },
+ { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },
+ { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } },
+
+ /* --- S3 --- */
+
+ { { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
+ { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },
+ { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },
+ { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } },
+
+ /* --- S4 --- */
+
+ { { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
+ { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },
+ { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },
+ { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } },
+
+ /* --- S5 --- */
+
+ { { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
+ { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 },
+ { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },
+ { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } },
+
+ /* --- S6 --- */
+
+ { { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
+ { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },
+ { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },
+ { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } },
+
+ /* --- S7 --- */
+
+ { { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
+ { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },
+ { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },
+ { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } },
+
+ /* --- S8 --- */
+
+ { { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
+ { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },
+ { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },
+ { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } }
+};
+
+/* --- P table --- */
+
+static char p[32] = {
+ 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
+ 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
+};
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @unique@ --- *
+ *
+ * Arguments: @const char *t@ = pointer to table
+ * @int base@ = base of the data
+ * @int sz@ = number of elements
+ * @const char *name@ = name of this table
+ * @...@ = things to fill in
+ *
+ * Returns: Zero if it failed, nonzero if it didn't.
+ *
+ * Use: Validates a table. All the elements must be in range and
+ * unique.
+ */
+
+static int unique(const char *t, int base, int sz, const char *name, ...)
+{
+ char u[32];
+ char nbuf[128];
+ int i;
+ int ok = 1;
+
+ {
+ va_list ap;
+ va_start(ap, name);
+ vsprintf(nbuf, name, ap);
+ va_end(ap);
+ }
+
+ if (sz > sizeof(u)) {
+ fprintf(stderr, "internal error: table `%s' too large\n", nbuf);
+ exit(EXIT_FAILURE);
+ }
+ memset(u, 0, sizeof(u));
+ for (i = 0; i < sz; i++) {
+ int x = t[i] - base;
+ if (x >= sz) {
+ fprintf(stderr, "validation error: %i too big (index %i) in %s\n",
+ x + base, i, nbuf);
+ ok = 0;
+ } else if (u[x]) {
+ fprintf(stderr, "validation error: duplicate %i (index %i) in %s\n",
+ x + base, i, nbuf);
+ ok = 0;
+ }
+ u[x] = 1;
+ }
+ for (i = 0; i < sz; i++) {
+ if (!u[i]) {
+ fprintf(stderr, "validation error: missing %i in %s\n",
+ i + base, nbuf);
+ ok = 0;
+ }
+ }
+
+ return (ok);
+}
+
+/* --- @validate@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: Only if everything's OK.
+ *
+ * Use: Validates the tables. A bit. Not much at all...
+ */
+
+static void validate(void)
+{
+ int i, j;
+ int ok = 1;
+
+ for (i = 0; i < 8; i++) for (j = 0; j < 4; j++)
+ if (!unique(s[i][j], 0, 16, "sbox %i, row %i", i, j)) ok = 0;
+ if (!unique(p, 1, 32, "p")) ok = 0;
+ if (!ok)
+ exit(EXIT_FAILURE);
+}
+
+/* --- @permute@ --- *
+ *
+ * Arguments: @unsigned long x@ = value to permute
+ *
+ * Returns: Permuted version of @x@.
+ *
+ * Use: Permutes a number. The result is the input value after
+ * having been spewed through the @P@ permutation, and then
+ * (and this is important) rotated left one place.
+ */
+
+static unsigned long permute(unsigned long x)
+{
+ unsigned long y = 0;
+ unsigned i;
+
+ for (i = 0; i < 32; i++) {
+ if (x & (1 << (32 - p[i])))
+ y |= (1 << (31 - i));
+ }
+ return (ROL32(y, 1));
+}
+
+/* --- @mangle@ --- *
+ *
+ * Arguments: @const char s[4][16]@ = an s-box
+ * @unsigned long ss[64]@ = output buffer
+ * @int bitoff@ = bit offset to use
+ *
+ * Returns: ---
+ *
+ * Use: Mangles the s-box. Specifically, the bizarre indexing is
+ * transformed into something sensible, and the result is
+ * permuted according to the @p@ table.
+ */
+
+static void mangle(const char s[4][16], unsigned long *ss, int bitoff)
+{
+ unsigned i;
+ for (i = 0; i < 64; i++) {
+ unsigned row = ((i & 0x20) >> 4) | (i & 0x01);
+ unsigned col = (i & 0x1e) >> 1;
+ ss[i] = permute(s[row][col] << bitoff);
+ }
+}
+
+/* --- @main@ --- */
+
+int main(void)
+{
+ int i, j;
+ unsigned long ss[64];
+ const char *sep;
+
+ validate();
+
+ fputs("\
+/* -*-c-*-\n\
+ *\n\
+ * DES tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_DES_TAB_H\n\
+#define CATACOMB_DES_TAB_H\n\
+\n\
+#define DES_SP { \\\n\
+", stdout);
+ for (i = 0; i < 8; i++) {
+ mangle(s[i], ss, 28 - 4 * i);
+ printf("\
+ \\\n\
+ /* --- SP[%i] --- */ \\\n\
+ \\\n\
+", i);
+ sep = " { ";
+ for (j = 0; j < 64; j++) {
+ printf("%s0x%08lx", sep, ss[j]);
+ if (j % 4 == 3)
+ sep = ", \\\n ";
+ else
+ sep = ", ";
+ }
+ printf(" }%s \\\n", i == 7 ? "" : ",");
+ }
+ fputs("\
+}\n\
+\n\
+#endif\n\
+", stdout);
+
+ if (fclose(stdout)) {
+ fprintf(stderr, "error writing data\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/