chiark / gitweb /
hashsum.c: Document `--progress' in the `--help' display.
[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 -------------------------------------------------*/