chiark / gitweb /
cc.h: Reorder the declarations.
[catacomb] / rc2.c
1 /* -*-c-*-
2  *
3  * $Id: rc2.c,v 1.3 2004/04/08 01:36:15 mdw Exp $
4  *
5  * The RC2 block cipher
6  *
7  * (c) 2000 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 "rc2.h"
41 #include "rc2-tab.h"
42
43 /*----- Global variables --------------------------------------------------*/
44
45 const octet rc2_keysz[] = { KSZ_RANGE, RC2_KEYSZ, 1, 128, 1 };
46
47 /*----- Important tables --------------------------------------------------*/
48
49 static const octet pi[256] = RC2_PI;
50
51 /*----- Main code ---------------------------------------------------------*/
52
53 /* --- @rc2_braindamage@ --- *
54  *
55  * Arguments:   @rc2_ctx *k@ = pointer to context to initialize
56  *              @const void *buf@ = pointer to key material
57  *              @size_t sz@ = size of key material in bytes
58  *              @unsigned eb@ = desired effective key size, in bits
59  *
60  * Returns:     ---
61  *
62  * Use:         Initializes an RC2 expanded key, and braindamages it to the
63  *              requested effective key size.  This is here for compatibility
64  *              reasons.  You should be using @rc2_init@ in normal code,
65  *              which doesn't actually apply braindamage.
66  */
67
68 void rc2_braindamage(rc2_ctx *k, const void *buf, size_t sz, unsigned eb)
69 {
70   unsigned t8;
71   uint16 tm;
72   unsigned i;
73   uint16 *kk;
74   octet l[128];
75
76   KSZ_ASSERT(rc2, sz);
77
78   /* --- Compute the braindamage parameters --- */
79
80   t8 = (eb + 7) / 8;
81   tm = 0xff & ((1 << (8 + eb - 8 * t8)) - 1);
82
83   /* --- Copy and expand the initial key --- */
84
85   if (sz > sizeof(l))
86     sz = sizeof(l);
87   memcpy(l, buf, sz);
88
89   for (i = sz; i < sizeof(l); i++)
90     l[i] = pi[U8(l[i - 1] + l[i - sz])];
91
92   /* --- Braindamage the key --- */
93
94   i = sizeof(l) - t8;
95   l[i] = pi[l[i] & tm];
96   while (i) {
97     i--;
98     l[i] = pi[U8(l[i + 1] ^ l[i + t8])];
99   }
100
101   /* --- Write it to the key block --- */
102
103   kk = k->k;
104   for (i = 0; i < sizeof(l); i += 2)
105     *kk++ = LOAD16_L(l + i);
106   BURN(l);
107 }
108
109 /* --- @rc2_init@ --- *
110  *
111  * Arguments:   @rc2_ctx *k@ = pointer to context to initialize
112  *              @const void *buf@ = pointer to key material
113  *              @size_t sz@ = size of key material in bytes
114  *
115  * Returns:     ---
116  *
117  * Use:         Initializes an RC2 expanded key.  The effective key size is
118  *              set to be equal to the real key size, in bits.
119  */
120
121 void rc2_init(rc2_ctx *k, const void *buf, size_t sz)
122 {
123   rc2_braindamage(k, buf, sz, sz * 8);
124 }
125
126 /*----- Encryption and decryption -----------------------------------------*/
127
128 #define MIX(a, b, c, d, r, kk) do {                                     \
129   a += *kk++ + (d & c) + (~d & b);                                      \
130   a = ROL16(a, r);                                                      \
131 } while (0)
132
133 #define MASH(a, d, k) do {                                              \
134   a += k[d & 63];                                                       \
135 } while (0)
136
137 #define UNMIX(a, b, c, d, r, kk) do {                                   \
138   a = ROR16(a, r);                                                      \
139   a -= *--kk + (d & c) + (~d & b);                                      \
140 } while (0)
141
142 #define UNMASH(a, d, k) do {                                            \
143   a -= k[d & 63];                                                       \
144 } while (0)
145
146 /* --- @rc2_eblk@, @rc2_dblk@ --- *
147  *
148  * Arguments:   @const rc2_ctx *k@ = pointer to RC2 context
149  *              @const uint32 s[2]@ = pointer to source block
150  *              @const uint32 d[2]@ = pointer to destination block
151  *
152  * Returns:     ---
153  *
154  * Use:         Low-level block encryption and decryption.
155  */
156
157 void rc2_eblk(const rc2_ctx *k, const uint32 *s, uint32 *dst)
158 {
159   uint16 a = U16(s[0] >>  0), b = U16(s[0] >> 16);
160   uint16 c = U16(s[1] >>  0), d = U16(s[1] >> 16);
161   const uint16 *kk = k->k;
162
163   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
164   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
165   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
166   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
167   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
168   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
169   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
170   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
171   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
172   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
173   MASH(a, d, k->k); MASH(b, a, k->k);
174   MASH(c, b, k->k); MASH(d, c, k->k);
175   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
176   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
177   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
178   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
179   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
180   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
181   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
182   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
183   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
184   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
185   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
186   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
187   MASH(a, d, k->k); MASH(b, a, k->k);
188   MASH(c, b, k->k); MASH(d, c, k->k);
189   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
190   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
191   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
192   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
193   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
194   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
195   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
196   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
197   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
198   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
199
200   dst[0] = a | (b << 16); dst[1] = c | (d << 16);
201 }
202
203 void rc2_dblk(const rc2_ctx *k, const uint32 *s, uint32 *dst)
204 {
205   uint16 a = U16(s[0] >>  0), b = U16(s[0] >> 16);
206   uint16 c = U16(s[1] >>  0), d = U16(s[1] >> 16);
207   const uint16 *kk = k->k + 64;
208
209   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
210   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
211   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
212   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
213   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
214   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
215   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
216   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
217   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
218   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
219   UNMASH(d, c, k->k); UNMASH(c, b, k->k);
220   UNMASH(b, a, k->k); UNMASH(a, d, k->k);
221   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
222   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
223   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
224   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
225   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
226   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
227   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
228   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
229   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
230   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
231   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
232   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
233   UNMASH(d, c, k->k); UNMASH(c, b, k->k);
234   UNMASH(b, a, k->k); UNMASH(a, d, k->k);
235   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
236   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
237   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
238   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
239   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
240   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
241   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
242   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
243   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
244   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
245
246   dst[0] = a | (b << 16); dst[1] = c | (d << 16);
247 }
248
249 /*----- Custom test rig ---------------------------------------------------*
250  *
251  * I need to test the braindamage feature.
252  */
253
254 #ifdef TEST_RIG
255
256 #include <mLib/quis.h>
257 #include <mLib/testrig.h>
258
259 static int verify(dstr *v)
260 {
261   rc2_ctx k;
262   uint32 p[RC2_BLKSZ / 4];
263   uint32 c[RC2_BLKSZ / 4];
264   uint32 d[RC2_BLKSZ / 4];
265   dstr b = DSTR_INIT;
266   unsigned bd = *(unsigned *)v[1].buf;
267   int ok = 1;
268
269   /* --- Initialize the key buffer --- */
270
271   dstr_ensure(&b, RC2_BLKSZ);
272   b.len = RC2_BLKSZ;
273   rc2_braindamage(&k, v[0].buf, v[0].len, bd);
274   BLKC_LOAD(RC2, p, v[2].buf);
275   BLKC_LOAD(RC2, c, v[3].buf);
276
277   /* --- Test encryption --- */
278
279   BLKC_MOVE(RC2, d, p);
280   rc2_eblk(&k, d, d);
281   BLKC_STORE(RC2, b.buf, d);
282   if (memcmp(b.buf, v[3].buf, RC2_BLKSZ)) {
283     ok = 0;
284     printf("\nfail encryption:"
285            "\n\tkey        = ");
286     type_hex.dump(&v[0], stdout);
287     printf("\n\tbraindamage= %u", bd);
288     printf("\n\tplaintext  = "); type_hex.dump(&v[2], stdout);
289     printf("\n\texpected   = "); type_hex.dump(&v[3], stdout);
290     printf("\n\tcalculated = "); type_hex.dump(&b, stdout);
291     putchar('\n');
292   }
293
294   /* --- Test decryption --- */
295
296   BLKC_MOVE(RC2, d, c);
297   rc2_dblk(&k, d, d);
298   BLKC_STORE(RC2, b.buf, d);
299   if (memcmp(b.buf, v[2].buf, RC2_BLKSZ)) {
300     ok = 0;
301     printf("\nfail decryption:"
302            "\n\tkey        = ");
303     type_hex.dump(&v[0], stdout);
304     printf("\n\tbraindamage= %u", bd);
305     printf("\n\tciphertext = "); type_hex.dump(&v[3], stdout);
306     printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
307     printf("\n\tcalculated = "); type_hex.dump(&b, stdout);
308     putchar('\n');
309   }
310
311   /* --- Return --- */
312
313   return (ok);
314 }
315
316 static test_chunk defs[] = {
317   { "rc2", verify, { &type_hex, &type_int, &type_hex, &type_hex, 0 } },
318   { 0, 0, { 0 } }
319 };
320
321 int main(int argc, char *argv[])
322 {
323   test_run(argc, argv, defs, SRCDIR"/tests/rc2");
324   return (0);
325 }
326
327 #endif
328
329 /*----- That's all, folks -------------------------------------------------*/