New file.
[u/mdw/catacomb] / safer.c
1 /* -*-c-*-
2 *
3 * $Id: safer.c,v 1.1 2001/04/29 17:37:35 mdw Exp $
4 *
5 * The SAFER block cipher
6 *
7 * (c) 2001 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30 /*----- Revision history --------------------------------------------------*
31 *
32 * $Log: safer.c,v $
33 * Revision 1.1 2001/04/29 17:37:35 mdw
34 * Added SAFER block cipher.
35 *
36 */
37
38 /*----- Header files ------------------------------------------------------*/
39
40 #include <assert.h>
41 #include <stdio.h>
42
43 #include <mLib/bits.h>
44
45 #include "blkc.h"
46 #include "gcipher.h"
47 #include "paranoia.h"
48 #include "safer.h"
49 #include "safer-tab.h"
50
51 /*----- Global variables --------------------------------------------------*/
52
53 const octet safer_keysz[] = { KSZ_SET, 8, 16, 0 };
54
55 /*----- Important tables --------------------------------------------------*/
56
57 static const octet s[265] = SAFER_S, si[256] = SAFER_SI;
58
59 /*----- Main code ---------------------------------------------------------*/
60
61 /* --- @safer_setup@ --- *
62 *
63 * Arguments: @safer_ctx *k@ = pointer to context to initialize
64 * @unsigned r@ = number of rounds wanted
65 * @unsigned f@ = various other flags
66 * @const void *buf@ = pointer to key material
67 * @size_t sz@ = size of key material in bytes
68 *
69 * Returns: ---
70 *
71 * Use: Initializes an SAFER expanded key. A default number of
72 * rounds is chosen, based on the key length.
73 */
74
75 struct ksched {
76 unsigned i;
77 octet x[9];
78 };
79
80 static void init(struct ksched *t, const octet *k)
81 {
82 memcpy(t->x, k, 8);
83 t->i = 1;
84 }
85
86 static void init_sk(struct ksched *t, const octet *k)
87 {
88 unsigned i;
89 octet x;
90 memcpy(t->x, k, 8);
91 for (x = 0, i = 0; i < 8; x ^= k[i++])
92 ;
93 t->x[8] = x;
94 t->i = 1;
95 }
96
97 static void next(struct ksched *t, octet *k)
98 {
99 unsigned i;
100 if (k) {
101 memcpy(k, t->x, 8);
102 if (t->i > 1) {
103 for (i = 0; i < 8; i++)
104 k[i] += s[s[U8(9*t->i + i + 1)]];
105 }
106 }
107 for (i = 0; i < 8; i++)
108 t->x[i] = ROL8(t->x[i], 3);
109 t->i++;
110 }
111
112 static void next_sk(struct ksched *t, octet *k)
113 {
114 unsigned i;
115 i = (t->i - 1)%9;
116 if (k) {
117 if (i < 2)
118 memcpy(k, t->x + i, 8);
119 else {
120 memcpy(k, t->x + i, 9 - i);
121 memcpy(k + 9 - i, t->x, i - 1);
122 }
123 if (t->i > 1) {
124 for (i = 0; i < 8; i++)
125 k[i] += s[s[U8(9*t->i + i + 1)]];
126 }
127 }
128 for (i = 0; i < 9; i++)
129 t->x[i] = ROL8(t->x[i], 3);
130 t->i++;
131 }
132
133 void safer_setup(safer_ctx *k, unsigned r, unsigned f,
134 const void *buf, size_t sz)
135 {
136 struct ksched ka, kb;
137 void (*in)(struct ksched *, const octet *);
138 void (*nx)(struct ksched *, octet *);
139 octet *kk;
140
141 assert(r <= SAFER_MAXROUNDS);
142 KSZ_ASSERT(safer, sz);
143
144 if (f & SAFER_SK) {
145 in = init_sk;
146 nx = next_sk;
147 } else {
148 in = init;
149 nx = next;
150 }
151
152 in(&kb, buf);
153 in(&ka, sz == 8 ? buf : (const octet *)buf + 8);
154
155 k->r = r;
156 kk = k->k;
157 while (r) {
158 nx(&ka, kk); nx(&kb, 0); kk += 8;
159 nx(&kb, kk); nx(&ka, 0); kk += 8;
160 r--;
161 }
162 nx(&ka, kk); kk += 8;
163 }
164
165 /* --- @safer_init@, @safersk_init@ --- *
166 *
167 * Arguments: @safer_ctx *k@ = pointer to context to initialize
168 * @const void *buf@ = pointer to key material
169 * @size_t sz@ = size of key material in bytes
170 *
171 * Returns: ---
172 *
173 * Use: Initializes an SAFER expanded key. A default number of
174 * rounds is chosen, based on the key length.
175 */
176
177 void safer_init(safer_ctx *k, const void *buf, size_t sz)
178 {
179 safer_setup(k, sz == 8 ? 6 : 10, 0, buf, sz);
180 }
181
182 void safersk_init(safer_ctx *k, const void *buf, size_t sz)
183 {
184 safer_setup(k, sz == 8 ? 8 : 10, SAFER_SK, buf, sz);
185 }
186
187 /* --- @safer_eblk@, @safer_dblk@ --- *
188 *
189 * Arguments: @const safer_ctx *k@ = pointer to SAFER context
190 * @const uint32 s[2]@ = pointer to source block
191 * @const uint32 d[2]@ = pointer to destination block
192 *
193 * Returns: ---
194 *
195 * Use: Low-level block encryption and decryption.
196 */
197
198 #define UNPACK(src, a, b, c, d, e, f, g, h) do { \
199 a = U8(src[0] >> 24); b = U8(src[0] >> 16); \
200 c = U8(src[0] >> 8); d = U8(src[0] >> 0); \
201 e = U8(src[1] >> 24); f = U8(src[1] >> 16); \
202 g = U8(src[1] >> 8); h = U8(src[1] >> 0); \
203 } while (0)
204
205 #define PACK(dst, a, b, c, d, e, f, g, h) do { \
206 dst[0] = (U8(a) << 24) | (U8(b) << 16) | (U8(c) << 8) | U8(d); \
207 dst[1] = (U8(e) << 24) | (U8(f) << 16) | (U8(g) << 8) | U8(h); \
208 } while (0)
209
210 #define F(x, y) y += x, x += y
211 #define G(x, y) x -= y, y -= x
212
213 #define PHT(a, b, c, d, e, f, g, h) do { \
214 F(a, b); F(c, d); F(e, f); F(g, h); \
215 F(a, c); F(e, g); F(b, d); F(f, h); \
216 F(a, e); F(b, f); F(c, g); F(d, h); \
217 } while (0)
218 #define IPHT(a, b, c, d, e, f, g, h) do { \
219 G(a, e); G(b, f); G(c, g); G(d, h); \
220 G(a, c); G(e, g); G(b, d); G(f, h); \
221 G(a, b); G(c, d); G(e, f); G(g, h); \
222 } while (0)
223
224 #define KXA(k, a, b, c, d, e, f, g, h) do { \
225 a ^= *k++; b += *k++; c += *k++; d ^= *k++; \
226 e ^= *k++; f += *k++; g += *k++; h ^= *k++; \
227 } while (0)
228 #define SUB(a, b, c, d, e, f, g, h) do { \
229 a = s[U8(a)]; b = si[U8(b)]; c = si[U8(c)]; d = s[U8(d)]; \
230 e = s[U8(e)]; f = si[U8(f)]; g = si[U8(g)]; h = s[U8(h)]; \
231 } while (0)
232 #define KAX(k, a, b, c, d, e, f, g, h) do { \
233 a += *k++; b ^= *k++; c ^= *k++; d += *k++; \
234 e += *k++; f ^= *k++; g ^= *k++; h += *k++; \
235 } while (0)
236
237 #define KXS(k, a, b, c, d, e, f, g, h) do { \
238 h ^= *--k; g -= *--k; f -= *--k; e ^= *--k; \
239 d ^= *--k; c -= *--k; b -= *--k; a ^= *--k; \
240 } while (0)
241 #define ISUB(a, b, c, d, e, f, g, h) do { \
242 a = si[U8(a)]; b = s[U8(b)]; c = s[U8(c)]; d = si[U8(d)]; \
243 e = si[U8(e)]; f = s[U8(f)]; g = s[U8(g)]; h = si[U8(h)]; \
244 } while (0)
245 #define KSX(k, a, b, c, d, e, f, g, h) do { \
246 h -= *--k; g ^= *--k; f ^= *--k; e -= *--k; \
247 d -= *--k; c ^= *--k; b ^= *--k; a -= *--k; \
248 } while (0)
249
250 #define EROUND(k, a, b, c, d, e, f, g, h) do { \
251 KXA(k, a, b, c, d, e, f, g, h); \
252 SUB(a, b, c, d, e, f, g, h); \
253 KAX(k, a, b, c, d, e, f, g, h); \
254 PHT(a, b, c, d, e, f, g, h); \
255 } while (0)
256
257 #define DROUND(k, a, b, c, d, e, f, g, h) do { \
258 IPHT(a, b, c, d, e, f, g, h); \
259 KSX(k, a, b, c, d, e, f, g, h); \
260 ISUB(a, b, c, d, e, f, g, h); \
261 KXS(k, a, b, c, d, e, f, g, h); \
262 } while (0)
263
264
265 void safer_eblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
266 {
267 octet a, b, c, d, e, f, g, h;
268 unsigned r = k->r;
269 const octet *kk = k->k;
270
271 UNPACK(src, a, b, c, d, e, f, g, h);
272 while (r >= 3) {
273 EROUND(kk, a, b, c, d, e, f, g, h);
274 EROUND(kk, a, e, b, f, c, g, d, h);
275 EROUND(kk, a, c, e, g, b, d, f, h);
276 r -= 3;
277 }
278 switch (r) {
279 case 0:
280 KXA(kk, a, b, c, d, e, f, g, h);
281 PACK(dst, a, b, c, d, e, f, g ,h);
282 break;
283 case 1:
284 EROUND(kk, a, b, c, d, e, f, g, h);
285 KXA(kk, a, e, b, f, c, g, d, h);
286 PACK(dst, a, e, b, f, c, g, d, h);
287 break;
288 case 2:
289 EROUND(kk, a, b, c, d, e, f, g, h);
290 EROUND(kk, a, e, b, f, c, g, d, h);
291 KXA(kk, a, c, e, g, b, d, f, h);
292 PACK(dst, a, c, e, g, b, d, f, h);
293 break;
294 }
295 }
296
297 void safer_dblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
298 {
299 octet a, b, c, d, e, f, g, h;
300 unsigned r = k->r;
301 const octet *kk = k->k + 16 * r + 8;
302 switch (r%3) {
303 default:
304 case 0:
305 UNPACK(src, a, b, c, d, e, f, g, h);
306 KXS(kk, a, b, c, d, e, f, g, h);
307 break;
308 case 1:
309 UNPACK(src, a, e, b, f, c, g, d, h);
310 KXS(kk, a, e, b, f, c, g, d, h);
311 r--;
312 goto one_round;
313 case 2:
314 UNPACK(src, a, c, e, g, b, d, f, h);
315 KXS(kk, a, c, e, g, b, d, f, h);
316 r -= 2;
317 DROUND(kk, a, e, b, f, c, g, d, h);
318 one_round:
319 DROUND(kk, a, b, c, d, e, f, g, h);
320 break;
321 }
322 while (r) {
323 DROUND(kk, a, c, e, g, b, d, f, h);
324 DROUND(kk, a, e, b, f, c, g, d, h);
325 DROUND(kk, a, b, c, d, e, f, g, h);
326 r -= 3;
327 }
328 PACK(dst, a, b, c, d, e, f, g, h);
329 }
330
331 BLKC_TEST(SAFER, safer)
332
333 /*----- That's all, folks -------------------------------------------------*/