3 * $Id: safer.c,v 1.1 2001/04/29 17:37:35 mdw Exp $
5 * The SAFER block cipher
7 * (c) 2001 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.1 2001/04/29 17:37:35 mdw
34 * Added SAFER block cipher.
38 /*----- Header files ------------------------------------------------------*/
43 #include <mLib/bits.h>
49 #include "safer-tab.h"
51 /*----- Global variables --------------------------------------------------*/
53 const octet safer_keysz
[] = { KSZ_SET
, 8, 16, 0 };
55 /*----- Important tables --------------------------------------------------*/
57 static const octet s
[265] = SAFER_S
, si
[256] = SAFER_SI
;
59 /*----- Main code ---------------------------------------------------------*/
61 /* --- @safer_setup@ --- *
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
71 * Use: Initializes an SAFER expanded key. A default number of
72 * rounds is chosen, based on the key length.
80 static void init(struct ksched
*t
, const octet
*k
)
86 static void init_sk(struct ksched
*t
, const octet
*k
)
91 for (x
= 0, i
= 0; i
< 8; x
^= k
[i
++])
97 static void next(struct ksched
*t
, octet
*k
)
103 for (i
= 0; i
< 8; i
++)
104 k
[i
] += s
[s
[U8(9*t
->i
+ i
+ 1)]];
107 for (i
= 0; i
< 8; i
++)
108 t
->x
[i
] = ROL8(t
->x
[i
], 3);
112 static void next_sk(struct ksched
*t
, octet
*k
)
118 memcpy(k
, t
->x
+ i
, 8);
120 memcpy(k
, t
->x
+ i
, 9 - i
);
121 memcpy(k
+ 9 - i
, t
->x
, i
- 1);
124 for (i
= 0; i
< 8; i
++)
125 k
[i
] += s
[s
[U8(9*t
->i
+ i
+ 1)]];
128 for (i
= 0; i
< 9; i
++)
129 t
->x
[i
] = ROL8(t
->x
[i
], 3);
133 void safer_setup(safer_ctx
*k
, unsigned r
, unsigned f
,
134 const void *buf
, size_t sz
)
136 struct ksched ka
, kb
;
137 void (*in
)(struct ksched
*, const octet
*);
138 void (*nx
)(struct ksched
*, octet
*);
141 assert(r
<= SAFER_MAXROUNDS
);
142 KSZ_ASSERT(safer
, sz
);
153 in(&ka
, sz
== 8 ? buf
: (const octet
*)buf
+ 8);
158 nx(&ka
, kk
); nx(&kb
, 0); kk
+= 8;
159 nx(&kb
, kk
); nx(&ka
, 0); kk
+= 8;
162 nx(&ka
, kk
); kk
+= 8;
165 /* --- @safer_init@, @safersk_init@ --- *
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
173 * Use: Initializes an SAFER expanded key. A default number of
174 * rounds is chosen, based on the key length.
177 void safer_init(safer_ctx
*k
, const void *buf
, size_t sz
)
179 safer_setup(k
, sz
== 8 ?
6 : 10, 0, buf
, sz
);
182 void safersk_init(safer_ctx
*k
, const void *buf
, size_t sz
)
184 safer_setup(k
, sz
== 8 ?
8 : 10, SAFER_SK
, buf
, sz
);
187 /* --- @safer_eblk@, @safer_dblk@ --- *
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
195 * Use: Low-level block encryption and decryption.
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); \
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); \
210 #define F(x, y) y += x, x += y
211 #define G(x, y) x -= y, y -= x
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); \
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); \
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++; \
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)]; \
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++; \
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; \
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)]; \
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; \
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); \
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); \
265 void safer_eblk(const safer_ctx
*k
, const uint32
*src
, uint32
*dst
)
267 octet a
, b
, c
, d
, e
, f
, g
, h
;
269 const octet
*kk
= k
->k
;
271 UNPACK(src
, a
, b
, c
, d
, e
, f
, g
, h
);
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
);
280 KXA(kk
, a
, b
, c
, d
, e
, f
, g
, h
);
281 PACK(dst
, a
, b
, c
, d
, e
, f
, g
,h
);
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
);
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
);
297 void safer_dblk(const safer_ctx
*k
, const uint32
*src
, uint32
*dst
)
299 octet a
, b
, c
, d
, e
, f
, g
, h
;
301 const octet
*kk
= k
->k
+ 16 * r
+ 8;
305 UNPACK(src
, a
, b
, c
, d
, e
, f
, g
, h
);
306 KXS(kk
, a
, b
, c
, d
, e
, f
, g
, h
);
309 UNPACK(src
, a
, e
, b
, f
, c
, g
, d
, h
);
310 KXS(kk
, a
, e
, b
, f
, c
, g
, d
, h
);
314 UNPACK(src
, a
, c
, e
, g
, b
, d
, f
, h
);
315 KXS(kk
, a
, c
, e
, g
, b
, d
, f
, h
);
317 DROUND(kk
, a
, e
, b
, f
, c
, g
, d
, h
);
319 DROUND(kk
, a
, b
, c
, d
, e
, f
, g
, h
);
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
);
328 PACK(dst
, a
, b
, c
, d
, e
, f
, g
, h
);
331 BLKC_TEST(SAFER
, safer
)
333 /*----- That's all, folks -------------------------------------------------*/