7dad026d3b45340a9692bd9cc54cb4ae444fb0bd
[u/mdw/catacomb] / symm / des-mktab.c
1 /* -*-c-*-
2 *
3 * Build combined S-P tables for DES
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <mLib/bits.h>
36
37 /*----- Static variables --------------------------------------------------*/
38
39 /* --- S boxes --- */
40
41 static const char s[8][4][16] = {
42
43 /* --- S1 --- */
44
45 { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },
46 { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },
47 { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },
48 { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } },
49
50 /* --- S2 --- */
51
52 { { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
53 { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },
54 { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },
55 { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } },
56
57 /* --- S3 --- */
58
59 { { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
60 { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },
61 { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },
62 { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } },
63
64 /* --- S4 --- */
65
66 { { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
67 { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },
68 { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },
69 { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } },
70
71 /* --- S5 --- */
72
73 { { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
74 { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 },
75 { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },
76 { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } },
77
78 /* --- S6 --- */
79
80 { { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
81 { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },
82 { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },
83 { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } },
84
85 /* --- S7 --- */
86
87 { { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
88 { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },
89 { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },
90 { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } },
91
92 /* --- S8 --- */
93
94 { { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
95 { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },
96 { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },
97 { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } }
98 };
99
100 /* --- P table --- */
101
102 static char p[32] = {
103 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
104 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
105 };
106
107 /*----- Main code ---------------------------------------------------------*/
108
109 /* --- @unique@ --- *
110 *
111 * Arguments: @const char *t@ = pointer to table
112 * @int base@ = base of the data
113 * @int sz@ = number of elements
114 * @const char *name@ = name of this table
115 * @...@ = things to fill in
116 *
117 * Returns: Zero if it failed, nonzero if it didn't.
118 *
119 * Use: Validates a table. All the elements must be in range and
120 * unique.
121 */
122
123 static int unique(const char *t, int base, int sz, const char *name, ...)
124 {
125 char u[32];
126 char nbuf[128];
127 int i;
128 int ok = 1;
129
130 {
131 va_list ap;
132 va_start(ap, name);
133 vsprintf(nbuf, name, ap);
134 va_end(ap);
135 }
136
137 if (sz > sizeof(u)) {
138 fprintf(stderr, "internal error: table `%s' too large\n", nbuf);
139 exit(EXIT_FAILURE);
140 }
141 memset(u, 0, sizeof(u));
142 for (i = 0; i < sz; i++) {
143 int x = t[i] - base;
144 if (x >= sz) {
145 fprintf(stderr, "validation error: %i too big (index %i) in %s\n",
146 x + base, i, nbuf);
147 ok = 0;
148 } else if (u[x]) {
149 fprintf(stderr, "validation error: duplicate %i (index %i) in %s\n",
150 x + base, i, nbuf);
151 ok = 0;
152 }
153 u[x] = 1;
154 }
155 for (i = 0; i < sz; i++) {
156 if (!u[i]) {
157 fprintf(stderr, "validation error: missing %i in %s\n",
158 i + base, nbuf);
159 ok = 0;
160 }
161 }
162
163 return (ok);
164 }
165
166 /* --- @validate@ --- *
167 *
168 * Arguments: ---
169 *
170 * Returns: Only if everything's OK.
171 *
172 * Use: Validates the tables. A bit. Not much at all...
173 */
174
175 static void validate(void)
176 {
177 int i, j;
178 int ok = 1;
179
180 for (i = 0; i < 8; i++) for (j = 0; j < 4; j++)
181 if (!unique(s[i][j], 0, 16, "sbox %i, row %i", i, j)) ok = 0;
182 if (!unique(p, 1, 32, "p")) ok = 0;
183 if (!ok)
184 exit(EXIT_FAILURE);
185 }
186
187 /* --- @permute@ --- *
188 *
189 * Arguments: @unsigned long x@ = value to permute
190 *
191 * Returns: Permuted version of @x@.
192 *
193 * Use: Permutes a number. The result is the input value after
194 * having been spewed through the @P@ permutation, and then
195 * (and this is important) rotated left one place.
196 */
197
198 static unsigned long permute(unsigned long x)
199 {
200 unsigned long y = 0;
201 unsigned i;
202
203 for (i = 0; i < 32; i++) {
204 if (x & (1 << (32 - p[i])))
205 y |= (1 << (31 - i));
206 }
207 return (ROL32(y, 1));
208 }
209
210 /* --- @mangle@ --- *
211 *
212 * Arguments: @const char s[4][16]@ = an s-box
213 * @unsigned long ss[64]@ = output buffer
214 * @int bitoff@ = bit offset to use
215 *
216 * Returns: ---
217 *
218 * Use: Mangles the s-box. Specifically, the bizarre indexing is
219 * transformed into something sensible, and the result is
220 * permuted according to the @p@ table.
221 */
222
223 static void mangle(const char s[4][16], unsigned long *ss, int bitoff)
224 {
225 unsigned i;
226 for (i = 0; i < 64; i++) {
227 unsigned row = ((i & 0x20) >> 4) | (i & 0x01);
228 unsigned col = (i & 0x1e) >> 1;
229 ss[i] = permute(s[row][col] << bitoff);
230 }
231 }
232
233 /* --- @main@ --- */
234
235 int main(void)
236 {
237 int i, j;
238 unsigned long ss[64];
239 const char *sep;
240
241 validate();
242
243 fputs("\
244 /* -*-c-*-\n\
245 *\n\
246 * DES tables [generated]\n\
247 */\n\
248 \n\
249 #include \"des-base.h\"\n\
250 \n\
251 const uint32 des_sp[8][64] = {\n\
252 ", stdout);
253 for (i = 0; i < 8; i++) {
254 mangle(s[i], ss, 28 - 4 * i);
255 printf("\n /* --- SP[%i] --- */\n\n", i);
256 sep = " { ";
257 for (j = 0; j < 64; j++) {
258 printf("%s0x%08lx", sep, ss[j]);
259 if (j % 4 == 3)
260 sep = ",\n ";
261 else
262 sep = ", ";
263 }
264 printf(" }%s\n", i == 7 ? "" : ",");
265 }
266 fputs("};\n", stdout);
267
268 if (fclose(stdout)) {
269 fprintf(stderr, "error writing data\n");
270 exit(EXIT_FAILURE);
271 }
272
273 return (0);
274 }
275
276 /*----- That's all, folks -------------------------------------------------*/