1/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10 */
11/**********************************************************************\
12* To commemorate the 1996 RSA Data Security Conference, the following  *
13* code is released into the public domain by its author.  Prost!       *
14*                                                                      *
15* This cipher uses 16-bit words and little-endian byte ordering.       *
16* I wonder which processor it was optimized for?                       *
17*                                                                      *
18* Thanks to CodeView, SoftIce, and D86 for helping bring this code to  *
19* the public.                                                          *
20\**********************************************************************/
21#include <tomcrypt.h>
22
23/**
24  @file rc2.c
25  Implementation of RC2
26*/
27
28#ifdef RC2
29
30const struct ltc_cipher_descriptor rc2_desc = {
31   "rc2",
32   12, 8, 128, 8, 16,
33   &rc2_setup,
34   &rc2_ecb_encrypt,
35   &rc2_ecb_decrypt,
36   &rc2_test,
37   &rc2_done,
38   &rc2_keysize,
39   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
40};
41
42/* 256-entry permutation table, probably derived somehow from pi */
43static const unsigned char permute[256] = {
44        217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157,
45        198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162,
46         23,154, 89,245,135,179, 79, 19, 97, 69,109,141,  9,129,125, 50,
47        189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130,
48         84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220,
49         18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38,
50        111,191, 14,218, 70,105,  7, 87, 39,242, 29,155,188,148, 67,  3,
51        248, 17,199,246,144,239, 62,231,  6,195,213, 47,200,102, 30,215,
52          8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42,
53        150, 26,210,113, 90, 21, 73,116, 75,159,208, 94,  4, 24,164,236,
54        194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57,
55        153,124, 58,133, 35,184,180,122,252,  2, 54, 91, 37, 85,151, 49,
56         45, 93,250,152,227,138,146,174,  5,223, 41, 16,103,108,186,201,
57        211,  0,230,207,225,158,168, 44, 99, 22,  1, 63, 88,226,137,169,
58         13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46,
59        197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173
60};
61
62 /**
63    Initialize the RC2 block cipher
64    @param key The symmetric key you wish to pass
65    @param keylen The key length in bytes
66    @param num_rounds The number of rounds desired (0 for default)
67    @param skey The key in as scheduled by this function.
68    @return CRYPT_OK if successful
69 */
70int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
71{
72   unsigned *xkey = skey->rc2.xkey;
73   unsigned char tmp[128];
74   unsigned T8, TM;
75   int i, bits;
76
77   LTC_ARGCHK(key  != NULL);
78   LTC_ARGCHK(skey != NULL);
79
80   if (keylen < 8 || keylen > 128) {
81      return CRYPT_INVALID_KEYSIZE;
82   }
83
84   if (num_rounds != 0 && num_rounds != 16) {
85      return CRYPT_INVALID_ROUNDS;
86   }
87
88   for (i = 0; i < keylen; i++) {
89       tmp[i] = key[i] & 255;
90   }
91
92    /* Phase 1: Expand input key to 128 bytes */
93    if (keylen < 128) {
94        for (i = keylen; i < 128; i++) {
95            tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255];
96        }
97    }
98
99    /* Phase 2 - reduce effective key size to "bits" */
100    bits = keylen<<3;
101    T8   = (unsigned)(bits+7)>>3;
102    TM   = (255 >> (unsigned)(7 & -bits));
103    tmp[128 - T8] = permute[tmp[128 - T8] & TM];
104    for (i = 127 - T8; i >= 0; i--) {
105        tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]];
106    }
107
108    /* Phase 3 - copy to xkey in little-endian order */
109    for (i = 0; i < 64; i++) {
110        xkey[i] =  (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8);
111    }
112
113#ifdef LTC_CLEAN_STACK
114    zeromem(tmp, sizeof(tmp));
115#endif
116
117    return CRYPT_OK;
118}
119
120/**********************************************************************\
121* Encrypt an 8-byte block of plaintext using the given key.            *
122\**********************************************************************/
123/**
124  Encrypts a block of text with RC2
125  @param pt The input plaintext (8 bytes)
126  @param ct The output ciphertext (8 bytes)
127  @param skey The key as scheduled
128  @return CRYPT_OK if successful
129*/
130#ifdef LTC_CLEAN_STACK
131static int _rc2_ecb_encrypt( const unsigned char *pt,
132                            unsigned char *ct,
133                            symmetric_key *skey)
134#else
135int rc2_ecb_encrypt( const unsigned char *pt,
136                            unsigned char *ct,
137                            symmetric_key *skey)
138#endif
139{
140    unsigned *xkey;
141    unsigned x76, x54, x32, x10, i;
142
143    LTC_ARGCHK(pt  != NULL);
144    LTC_ARGCHK(ct != NULL);
145    LTC_ARGCHK(skey   != NULL);
146
147    xkey = skey->rc2.xkey;
148
149    x76 = ((unsigned)pt[7] << 8) + (unsigned)pt[6];
150    x54 = ((unsigned)pt[5] << 8) + (unsigned)pt[4];
151    x32 = ((unsigned)pt[3] << 8) + (unsigned)pt[2];
152    x10 = ((unsigned)pt[1] << 8) + (unsigned)pt[0];
153
154    for (i = 0; i < 16; i++) {
155        x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF;
156        x10 = ((x10 << 1) | (x10 >> 15));
157
158        x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF;
159        x32 = ((x32 << 2) | (x32 >> 14));
160
161        x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF;
162        x54 = ((x54 << 3) | (x54 >> 13));
163
164        x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF;
165        x76 = ((x76 << 5) | (x76 >> 11));
166
167        if (i == 4 || i == 10) {
168            x10 = (x10 + xkey[x76 & 63]) & 0xFFFF;
169            x32 = (x32 + xkey[x10 & 63]) & 0xFFFF;
170            x54 = (x54 + xkey[x32 & 63]) & 0xFFFF;
171            x76 = (x76 + xkey[x54 & 63]) & 0xFFFF;
172        }
173    }
174
175    ct[0] = (unsigned char)x10;
176    ct[1] = (unsigned char)(x10 >> 8);
177    ct[2] = (unsigned char)x32;
178    ct[3] = (unsigned char)(x32 >> 8);
179    ct[4] = (unsigned char)x54;
180    ct[5] = (unsigned char)(x54 >> 8);
181    ct[6] = (unsigned char)x76;
182    ct[7] = (unsigned char)(x76 >> 8);
183
184    return CRYPT_OK;
185}
186
187#ifdef LTC_CLEAN_STACK
188int rc2_ecb_encrypt( const unsigned char *pt,
189                            unsigned char *ct,
190                            symmetric_key *skey)
191{
192    int err = _rc2_ecb_encrypt(pt, ct, skey);
193    burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5);
194    return err;
195}
196#endif
197
198/**********************************************************************\
199* Decrypt an 8-byte block of ciphertext using the given key.           *
200\**********************************************************************/
201/**
202  Decrypts a block of text with RC2
203  @param ct The input ciphertext (8 bytes)
204  @param pt The output plaintext (8 bytes)
205  @param skey The key as scheduled
206  @return CRYPT_OK if successful
207*/
208#ifdef LTC_CLEAN_STACK
209static int _rc2_ecb_decrypt( const unsigned char *ct,
210                            unsigned char *pt,
211                            symmetric_key *skey)
212#else
213int rc2_ecb_decrypt( const unsigned char *ct,
214                            unsigned char *pt,
215                            symmetric_key *skey)
216#endif
217{
218    unsigned x76, x54, x32, x10;
219    unsigned *xkey;
220    int i;
221
222    LTC_ARGCHK(pt  != NULL);
223    LTC_ARGCHK(ct != NULL);
224    LTC_ARGCHK(skey   != NULL);
225
226    xkey = skey->rc2.xkey;
227
228    x76 = ((unsigned)ct[7] << 8) + (unsigned)ct[6];
229    x54 = ((unsigned)ct[5] << 8) + (unsigned)ct[4];
230    x32 = ((unsigned)ct[3] << 8) + (unsigned)ct[2];
231    x10 = ((unsigned)ct[1] << 8) + (unsigned)ct[0];
232
233    for (i = 15; i >= 0; i--) {
234        if (i == 4 || i == 10) {
235            x76 = (x76 - xkey[x54 & 63]) & 0xFFFF;
236            x54 = (x54 - xkey[x32 & 63]) & 0xFFFF;
237            x32 = (x32 - xkey[x10 & 63]) & 0xFFFF;
238            x10 = (x10 - xkey[x76 & 63]) & 0xFFFF;
239        }
240
241        x76 = ((x76 << 11) | (x76 >> 5));
242        x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF;
243
244        x54 = ((x54 << 13) | (x54 >> 3));
245        x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF;
246
247        x32 = ((x32 << 14) | (x32 >> 2));
248        x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF;
249
250        x10 = ((x10 << 15) | (x10 >> 1));
251        x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF;
252    }
253
254    pt[0] = (unsigned char)x10;
255    pt[1] = (unsigned char)(x10 >> 8);
256    pt[2] = (unsigned char)x32;
257    pt[3] = (unsigned char)(x32 >> 8);
258    pt[4] = (unsigned char)x54;
259    pt[5] = (unsigned char)(x54 >> 8);
260    pt[6] = (unsigned char)x76;
261    pt[7] = (unsigned char)(x76 >> 8);
262
263    return CRYPT_OK;
264}
265
266#ifdef LTC_CLEAN_STACK
267int rc2_ecb_decrypt( const unsigned char *ct,
268                            unsigned char *pt,
269                            symmetric_key *skey)
270{
271    int err = _rc2_ecb_decrypt(ct, pt, skey);
272    burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int));
273    return err;
274}
275#endif
276
277/**
278  Performs a self-test of the RC2 block cipher
279  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
280*/
281int rc2_test(void)
282{
283 #ifndef LTC_TEST
284    return CRYPT_NOP;
285 #else
286   static const struct {
287        int keylen;
288        unsigned char key[16], pt[8], ct[8];
289   } tests[] = {
290
291   { 8,
292     { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
294     { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
295     { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 }
296
297   },
298   { 16,
299     { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
300       0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 },
301     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
302     { 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 }
303   }
304  };
305    int x, y, err;
306    symmetric_key skey;
307    unsigned char tmp[2][8];
308
309    for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
310        zeromem(tmp, sizeof(tmp));
311        if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
312           return err;
313        }
314
315        rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey);
316        rc2_ecb_decrypt(tmp[0], tmp[1], &skey);
317
318        if (XMEMCMP(tmp[0], tests[x].ct, 8) != 0 || XMEMCMP(tmp[1], tests[x].pt, 8) != 0) {
319           return CRYPT_FAIL_TESTVECTOR;
320        }
321
322      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
323      for (y = 0; y < 8; y++) tmp[0][y] = 0;
324      for (y = 0; y < 1000; y++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey);
325      for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey);
326      for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
327    }
328    return CRYPT_OK;
329   #endif
330}
331
332/** Terminate the context
333   @param skey    The scheduled key
334*/
335void rc2_done(symmetric_key *skey)
336{
337}
338
339/**
340  Gets suitable key size
341  @param keysize [in/out] The length of the recommended key (in bytes).  This function will store the suitable size back in this variable.
342  @return CRYPT_OK if the input key size is acceptable.
343*/
344int rc2_keysize(int *keysize)
345{
346   LTC_ARGCHK(keysize != NULL);
347   if (*keysize < 8) {
348       return CRYPT_INVALID_KEYSIZE;
349   } else if (*keysize > 128) {
350       *keysize = 128;
351   }
352   return CRYPT_OK;
353}
354
355#endif
356
357
358
359
360/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/rc2.c,v $ */
361/* $Revision: 1.12 $ */
362/* $Date: 2006/11/08 23:01:06 $ */
363