chiark / gitweb /
Version bump.
[catacomb] / rc2.c
1 /* -*-c-*-
2  *
3  * $Id: rc2.c,v 1.1 2000/06/17 11:54:34 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 /*----- Revision history --------------------------------------------------* 
31  *
32  * $Log: rc2.c,v $
33  * Revision 1.1  2000/06/17 11:54:34  mdw
34  * New cipher.
35  *
36  */
37
38 /*----- Header files ------------------------------------------------------*/
39
40 #include <assert.h>
41 #include <stdio.h>
42
43 #include <mLib/bits.h>
44
45 #include "blkc.h"
46 #include "gcipher.h"
47 #include "paranoia.h"
48 #include "rc2.h"
49
50 /*----- Global variables --------------------------------------------------*/
51
52 const octet rc2_keysz[] = { KSZ_RANGE, RC2_KEYSZ, 1, 128, 1 };
53
54 /*----- Important tables --------------------------------------------------*/
55
56 static const octet pi[] = {
57   0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,
58   0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
59   0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
60   0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
61   0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,
62   0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
63   0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,
64   0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
65   0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
66   0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
67   0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,
68   0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
69   0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,
70   0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
71   0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
72   0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
73   0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,
74   0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
75   0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,
76   0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
77   0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
78   0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
79   0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,
80   0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
81   0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,
82   0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
83   0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
84   0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
85   0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
86   0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
87   0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,
88   0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
89 };
90
91 /*----- Main code ---------------------------------------------------------*/
92
93 /* --- @rc2_braindamage@ --- *
94  *
95  * Arguments:   @rc2_ctx *k@ = pointer to context to initialize
96  *              @const void *buf@ = pointer to key material
97  *              @size_t sz@ = size of key material in bytes
98  *              @unsigned eb@ = desired effective key size, in bits
99  *
100  * Returns:     ---
101  *
102  * Use:         Initializes an RC2 expanded key, and braindamages it to the
103  *              requested effective key size.  This is here for compatibility
104  *              reasons.  You should be using @rc2_init@ in normal code,
105  *              which doesn't actually apply braindamage.
106  */
107
108 void rc2_braindamage(rc2_ctx *k, const void *buf, size_t sz, unsigned eb)
109 {
110   unsigned t8;
111   uint16 tm;
112   unsigned i;
113   uint16 *kk;
114   octet l[128];
115
116   KSZ_ASSERT(rc2, sz);
117
118   /* --- Compute the braindamage parameters --- */
119
120   t8 = (eb + 7) / 8;
121   tm = 0xff & ((1 << (8 + eb - 8 * t8)) - 1);
122
123   /* --- Copy and expand the initial key --- */
124
125   if (sz > sizeof(l))
126     sz = sizeof(l);
127   memcpy(l, buf, sz);
128
129   for (i = sz; i < sizeof(l); i++)
130     l[i] = pi[U8(l[i - 1] + l[i - sz])];
131
132   /* --- Braindamage the key --- */
133
134   i = sizeof(l) - t8;
135   l[i] = pi[l[i] & tm];
136   while (i) {
137     i--;
138     l[i] = pi[U8(l[i + 1] ^ l[i + t8])];
139   }
140
141   /* --- Write it to the key block --- */
142
143   kk = k->k;
144   for (i = 0; i < sizeof(l); i += 2)
145     *kk++ = LOAD16_L(l + i);
146   BURN(l);
147 }
148
149 /* --- @rc2_init@ --- *
150  *
151  * Arguments:   @rc2_ctx *k@ = pointer to context to initialize
152  *              @const void *buf@ = pointer to key material
153  *              @size_t sz@ = size of key material in bytes
154  *
155  * Returns:     ---
156  *
157  * Use:         Initializes an RC2 expanded key.  The effective key size is
158  *              set to be equal to the real key size, in bits.
159  */
160
161 void rc2_init(rc2_ctx *k, const void *buf, size_t sz)
162 {
163   rc2_braindamage(k, buf, sz, sz * 8);
164 }
165
166 /*----- Encryption and decryption -----------------------------------------*/
167
168 #define MIX(a, b, c, d, r, kk) do {                                     \
169   a += *kk++ + (d & c) + (~d & b);                                      \
170   a = ROL16(a, r);                                                      \
171 } while (0)
172
173 #define MASH(a, d, k) do {                                              \
174   a += k[d & 63];                                                       \
175 } while (0)
176
177 #define UNMIX(a, b, c, d, r, kk) do {                                   \
178   a = ROR16(a, r);                                                      \
179   a -= *--kk + (d & c) + (~d & b);                                      \
180 } while (0)
181
182 #define UNMASH(a, d, k) do {                                            \
183   a -= k[d & 63];                                                       \
184 } while (0)
185
186 /* --- @rc2_eblk@, @rc2_dblk@ --- *
187  *
188  * Arguments:   @const rc2_ctx *k@ = pointer to RC2 context
189  *              @const uint32 s[2]@ = pointer to source block
190  *              @const uint32 d[2]@ = pointer to destination block
191  *
192  * Returns:     ---
193  *
194  * Use:         Low-level block encryption and decryption.
195  */
196
197 void rc2_eblk(const rc2_ctx *k, const uint32 *s, uint32 *dst)
198 {
199   uint16 a = U16(s[0] >>  0), b = U16(s[0] >> 16);
200   uint16 c = U16(s[1] >>  0), d = U16(s[1] >> 16);
201   const uint16 *kk = k->k;
202
203   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
204   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
205   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
206   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
207   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
208   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
209   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
210   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
211   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
212   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
213   MASH(a, d, k->k); MASH(b, a, k->k);
214   MASH(c, b, k->k); MASH(d, c, k->k);
215   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
216   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
217   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
218   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
219   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
220   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
221   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
222   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
223   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
224   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
225   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
226   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
227   MASH(a, d, k->k); MASH(b, a, k->k);
228   MASH(c, b, k->k); MASH(d, c, k->k);
229   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
230   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
231   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
232   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
233   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
234   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
235   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
236   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
237   MIX(a, b, c, d, 1, kk); MIX(b, c, d, a, 2, kk);
238   MIX(c, d, a, b, 3, kk); MIX(d, a, b, c, 5, kk);
239
240   dst[0] = a | (b << 16); dst[1] = c | (d << 16);
241 }
242
243 void rc2_dblk(const rc2_ctx *k, const uint32 *s, uint32 *dst)
244 {
245   uint16 a = U16(s[0] >>  0), b = U16(s[0] >> 16);
246   uint16 c = U16(s[1] >>  0), d = U16(s[1] >> 16);
247   const uint16 *kk = k->k + 64;
248
249   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
250   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
251   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
252   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
253   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
254   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
255   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
256   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
257   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
258   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
259   UNMASH(d, c, k->k); UNMASH(c, b, k->k);
260   UNMASH(b, a, k->k); UNMASH(a, d, k->k);
261   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
262   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
263   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
264   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
265   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
266   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
267   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
268   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
269   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
270   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
271   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
272   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
273   UNMASH(d, c, k->k); UNMASH(c, b, k->k);
274   UNMASH(b, a, k->k); UNMASH(a, d, k->k);
275   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
276   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
277   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
278   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
279   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
280   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
281   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
282   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
283   UNMIX(d, a, b, c, 5, kk); UNMIX(c, d, a, b, 3, kk);
284   UNMIX(b, c, d, a, 2, kk); UNMIX(a, b, c, d, 1, kk);
285
286   dst[0] = a | (b << 16); dst[1] = c | (d << 16);
287 }
288
289 /*----- Custom test rig ---------------------------------------------------*
290  *
291  * I need to test the braindamage feature.
292  */
293
294 #ifdef TEST_RIG
295
296 #include <mLib/quis.h>
297 #include <mLib/testrig.h>
298
299 static int verify(dstr *v)
300 {
301   rc2_ctx k;
302   uint32 p[RC2_BLKSZ / 4];
303   uint32 c[RC2_BLKSZ / 4];
304   uint32 d[RC2_BLKSZ / 4];
305   dstr b = DSTR_INIT;
306   unsigned bd = *(unsigned *)v[1].buf;
307   int ok = 1;
308
309   /* --- Initialize the key buffer --- */
310
311   dstr_ensure(&b, RC2_BLKSZ);
312   b.len = RC2_BLKSZ;
313   rc2_braindamage(&k, v[0].buf, v[0].len, bd);
314   BLKC_LOAD(RC2, p, v[2].buf);
315   BLKC_LOAD(RC2, c, v[3].buf);
316
317   /* --- Test encryption --- */
318
319   BLKC_MOVE(RC2, d, p);
320   rc2_eblk(&k, d, d);
321   BLKC_STORE(RC2, b.buf, d);
322   if (memcmp(b.buf, v[3].buf, RC2_BLKSZ)) {
323     ok = 0;
324     printf("\nfail encryption:"
325            "\n\tkey        = ");
326     type_hex.dump(&v[0], stdout);
327     printf("\n\tbraindamage= %u", bd);
328     printf("\n\tplaintext  = "); type_hex.dump(&v[2], stdout);
329     printf("\n\texpected   = "); type_hex.dump(&v[3], stdout);
330     printf("\n\tcalculated = "); type_hex.dump(&b, stdout);
331     putchar('\n');
332   }
333
334   /* --- Test decryption --- */
335
336   BLKC_MOVE(RC2, d, c);
337   rc2_dblk(&k, d, d);
338   BLKC_STORE(RC2, b.buf, d);
339   if (memcmp(b.buf, v[2].buf, RC2_BLKSZ)) {
340     ok = 0;
341     printf("\nfail decryption:"
342            "\n\tkey        = ");
343     type_hex.dump(&v[0], stdout);
344     printf("\n\tbraindamage= %u", bd);
345     printf("\n\tciphertext = "); type_hex.dump(&v[3], stdout);
346     printf("\n\texpected   = "); type_hex.dump(&v[2], stdout);
347     printf("\n\tcalculated = "); type_hex.dump(&b, stdout);
348     putchar('\n');
349   }
350
351   /* --- Return --- */
352
353   return (ok);
354 }
355
356 static test_chunk defs[] = {
357   { "rc2", verify, { &type_hex, &type_int, &type_hex, &type_hex, 0 } },
358   { 0, 0, { 0 } }
359 };
360
361 int main(int argc, char *argv[])
362 {
363   test_run(argc, argv, defs, SRCDIR"/tests/rc2");
364   return (0);
365 }
366
367 #endif
368
369 /*----- That's all, folks -------------------------------------------------*/