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