055a5f6a5387055b7d9182e222299f8a4703495d
[u/mdw/catacomb] / symm / safer.c
1 /* -*-c-*-
2 *
3 * The SAFER block cipher
4 *
5 * (c) 2001 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 <assert.h>
31 #include <stdio.h>
32
33 #include <mLib/bits.h>
34
35 #include "blkc.h"
36 #include "gcipher.h"
37 #include "paranoia.h"
38 #include "safer.h"
39 #include "safer-tab.h"
40
41 /*----- Global variables --------------------------------------------------*/
42
43 const octet safer_keysz[] = { KSZ_SET, 8, 16, 0 };
44
45 /*----- Important tables --------------------------------------------------*/
46
47 static const octet s[265] = SAFER_S, si[256] = SAFER_SI;
48
49 /*----- Main code ---------------------------------------------------------*/
50
51 /* --- @safer_setup@ --- *
52 *
53 * Arguments: @safer_ctx *k@ = pointer to context to initialize
54 * @unsigned r@ = number of rounds wanted
55 * @unsigned f@ = various other flags
56 * @const void *buf@ = pointer to key material
57 * @size_t sz@ = size of key material in bytes
58 *
59 * Returns: ---
60 *
61 * Use: Initializes an SAFER expanded key. A default number of
62 * rounds is chosen, based on the key length.
63 */
64
65 struct ksched {
66 unsigned i;
67 octet x[9];
68 };
69
70 static void init(struct ksched *t, const octet *k)
71 {
72 memcpy(t->x, k, 8);
73 t->i = 1;
74 }
75
76 static void init_sk(struct ksched *t, const octet *k)
77 {
78 unsigned i;
79 octet x;
80 memcpy(t->x, k, 8);
81 for (x = 0, i = 0; i < 8; x ^= k[i++])
82 ;
83 t->x[8] = x;
84 t->i = 1;
85 }
86
87 static void next(struct ksched *t, octet *k)
88 {
89 unsigned i;
90 if (k) {
91 memcpy(k, t->x, 8);
92 if (t->i > 1) {
93 for (i = 0; i < 8; i++)
94 k[i] += s[s[U8(9*t->i + i + 1)]];
95 }
96 }
97 for (i = 0; i < 8; i++)
98 t->x[i] = ROL8(t->x[i], 3);
99 t->i++;
100 }
101
102 static void next_sk(struct ksched *t, octet *k)
103 {
104 unsigned i;
105 i = (t->i - 1)%9;
106 if (k) {
107 if (i < 2)
108 memcpy(k, t->x + i, 8);
109 else {
110 memcpy(k, t->x + i, 9 - i);
111 memcpy(k + 9 - i, t->x, i - 1);
112 }
113 if (t->i > 1) {
114 for (i = 0; i < 8; i++)
115 k[i] += s[s[U8(9*t->i + i + 1)]];
116 }
117 }
118 for (i = 0; i < 9; i++)
119 t->x[i] = ROL8(t->x[i], 3);
120 t->i++;
121 }
122
123 void safer_setup(safer_ctx *k, unsigned r, unsigned f,
124 const void *buf, size_t sz)
125 {
126 struct ksched ka, kb;
127 void (*in)(struct ksched *, const octet *);
128 void (*nx)(struct ksched *, octet *);
129 octet *kk;
130
131 assert(r <= SAFER_MAXROUNDS);
132 KSZ_ASSERT(safer, sz);
133
134 if (f & SAFER_SK) {
135 in = init_sk;
136 nx = next_sk;
137 } else {
138 in = init;
139 nx = next;
140 }
141
142 in(&kb, buf);
143 in(&ka, sz == 8 ? buf : (const octet *)buf + 8);
144
145 k->r = r;
146 kk = k->k;
147 while (r) {
148 nx(&ka, kk); nx(&kb, 0); kk += 8;
149 nx(&kb, kk); nx(&ka, 0); kk += 8;
150 r--;
151 }
152 nx(&ka, kk); kk += 8;
153 }
154
155 /* --- @safer_init@, @safersk_init@ --- *
156 *
157 * Arguments: @safer_ctx *k@ = pointer to context to initialize
158 * @const void *buf@ = pointer to key material
159 * @size_t sz@ = size of key material in bytes
160 *
161 * Returns: ---
162 *
163 * Use: Initializes an SAFER expanded key. A default number of
164 * rounds is chosen, based on the key length.
165 */
166
167 void safer_init(safer_ctx *k, const void *buf, size_t sz)
168 {
169 safer_setup(k, sz == 8 ? 6 : 10, 0, buf, sz);
170 }
171
172 void safersk_init(safer_ctx *k, const void *buf, size_t sz)
173 {
174 safer_setup(k, sz == 8 ? 8 : 10, SAFER_SK, buf, sz);
175 }
176
177 /* --- @safer_eblk@, @safer_dblk@ --- *
178 *
179 * Arguments: @const safer_ctx *k@ = pointer to SAFER context
180 * @const uint32 s[2]@ = pointer to source block
181 * @const uint32 d[2]@ = pointer to destination block
182 *
183 * Returns: ---
184 *
185 * Use: Low-level block encryption and decryption.
186 */
187
188 #define UNPACK(src, a, b, c, d, e, f, g, h) do { \
189 a = U8(src[0] >> 24); b = U8(src[0] >> 16); \
190 c = U8(src[0] >> 8); d = U8(src[0] >> 0); \
191 e = U8(src[1] >> 24); f = U8(src[1] >> 16); \
192 g = U8(src[1] >> 8); h = U8(src[1] >> 0); \
193 } while (0)
194
195 #define PACK(dst, a, b, c, d, e, f, g, h) do { \
196 dst[0] = (U8(a) << 24) | (U8(b) << 16) | (U8(c) << 8) | U8(d); \
197 dst[1] = (U8(e) << 24) | (U8(f) << 16) | (U8(g) << 8) | U8(h); \
198 } while (0)
199
200 #define F(x, y) y += x, x += y
201 #define G(x, y) x -= y, y -= x
202
203 #define PHT(a, b, c, d, e, f, g, h) do { \
204 F(a, b); F(c, d); F(e, f); F(g, h); \
205 F(a, c); F(e, g); F(b, d); F(f, h); \
206 F(a, e); F(b, f); F(c, g); F(d, h); \
207 } while (0)
208 #define IPHT(a, b, c, d, e, f, g, h) do { \
209 G(a, e); G(b, f); G(c, g); G(d, h); \
210 G(a, c); G(e, g); G(b, d); G(f, h); \
211 G(a, b); G(c, d); G(e, f); G(g, h); \
212 } while (0)
213
214 #define KXA(k, a, b, c, d, e, f, g, h) do { \
215 a ^= *k++; b += *k++; c += *k++; d ^= *k++; \
216 e ^= *k++; f += *k++; g += *k++; h ^= *k++; \
217 } while (0)
218 #define SUB(a, b, c, d, e, f, g, h) do { \
219 a = s[U8(a)]; b = si[U8(b)]; c = si[U8(c)]; d = s[U8(d)]; \
220 e = s[U8(e)]; f = si[U8(f)]; g = si[U8(g)]; h = s[U8(h)]; \
221 } while (0)
222 #define KAX(k, a, b, c, d, e, f, g, h) do { \
223 a += *k++; b ^= *k++; c ^= *k++; d += *k++; \
224 e += *k++; f ^= *k++; g ^= *k++; h += *k++; \
225 } while (0)
226
227 #define KXS(k, a, b, c, d, e, f, g, h) do { \
228 h ^= *--k; g -= *--k; f -= *--k; e ^= *--k; \
229 d ^= *--k; c -= *--k; b -= *--k; a ^= *--k; \
230 } while (0)
231 #define ISUB(a, b, c, d, e, f, g, h) do { \
232 a = si[U8(a)]; b = s[U8(b)]; c = s[U8(c)]; d = si[U8(d)]; \
233 e = si[U8(e)]; f = s[U8(f)]; g = s[U8(g)]; h = si[U8(h)]; \
234 } while (0)
235 #define KSX(k, a, b, c, d, e, f, g, h) do { \
236 h -= *--k; g ^= *--k; f ^= *--k; e -= *--k; \
237 d -= *--k; c ^= *--k; b ^= *--k; a -= *--k; \
238 } while (0)
239
240 #define EROUND(k, a, b, c, d, e, f, g, h) do { \
241 KXA(k, a, b, c, d, e, f, g, h); \
242 SUB(a, b, c, d, e, f, g, h); \
243 KAX(k, a, b, c, d, e, f, g, h); \
244 PHT(a, b, c, d, e, f, g, h); \
245 } while (0)
246
247 #define DROUND(k, a, b, c, d, e, f, g, h) do { \
248 IPHT(a, b, c, d, e, f, g, h); \
249 KSX(k, a, b, c, d, e, f, g, h); \
250 ISUB(a, b, c, d, e, f, g, h); \
251 KXS(k, a, b, c, d, e, f, g, h); \
252 } while (0)
253
254
255 void safer_eblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
256 {
257 octet a, b, c, d, e, f, g, h;
258 unsigned r = k->r;
259 const octet *kk = k->k;
260
261 UNPACK(src, a, b, c, d, e, f, g, h);
262 while (r >= 3) {
263 EROUND(kk, a, b, c, d, e, f, g, h);
264 EROUND(kk, a, e, b, f, c, g, d, h);
265 EROUND(kk, a, c, e, g, b, d, f, h);
266 r -= 3;
267 }
268 switch (r) {
269 case 0:
270 KXA(kk, a, b, c, d, e, f, g, h);
271 PACK(dst, a, b, c, d, e, f, g ,h);
272 break;
273 case 1:
274 EROUND(kk, a, b, c, d, e, f, g, h);
275 KXA(kk, a, e, b, f, c, g, d, h);
276 PACK(dst, a, e, b, f, c, g, d, h);
277 break;
278 case 2:
279 EROUND(kk, a, b, c, d, e, f, g, h);
280 EROUND(kk, a, e, b, f, c, g, d, h);
281 KXA(kk, a, c, e, g, b, d, f, h);
282 PACK(dst, a, c, e, g, b, d, f, h);
283 break;
284 }
285 }
286
287 void safer_dblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
288 {
289 octet a, b, c, d, e, f, g, h;
290 unsigned r = k->r;
291 const octet *kk = k->k + 16 * r + 8;
292 switch (r%3) {
293 default:
294 case 0:
295 UNPACK(src, a, b, c, d, e, f, g, h);
296 KXS(kk, a, b, c, d, e, f, g, h);
297 break;
298 case 1:
299 UNPACK(src, a, e, b, f, c, g, d, h);
300 KXS(kk, a, e, b, f, c, g, d, h);
301 r--;
302 goto one_round;
303 case 2:
304 UNPACK(src, a, c, e, g, b, d, f, h);
305 KXS(kk, a, c, e, g, b, d, f, h);
306 r -= 2;
307 DROUND(kk, a, e, b, f, c, g, d, h);
308 one_round:
309 DROUND(kk, a, b, c, d, e, f, g, h);
310 break;
311 }
312 while (r) {
313 DROUND(kk, a, c, e, g, b, d, f, h);
314 DROUND(kk, a, e, b, f, c, g, d, h);
315 DROUND(kk, a, b, c, d, e, f, g, h);
316 r -= 3;
317 }
318 PACK(dst, a, b, c, d, e, f, g, h);
319 }
320
321 BLKC_TEST(SAFER, safer)
322
323 /*----- That's all, folks -------------------------------------------------*/