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