1 /* Modified for SILC. -Pekka */
3 /* This is an independent implementation of the encryption algorithm: */
5 /* RC6 by Ron Rivest and RSA Labs */
7 /* which is a candidate algorithm in the Advanced Encryption Standard */
8 /* programme of the US National Institute of Standards and Technology. */
10 /* Copyright in this implementation is held by Dr B R Gladman but I */
11 /* hereby give permission for its free direct or derivative use subject */
12 /* to acknowledgment of its origin and compliance with any conditions */
13 /* that the originators of the algorithm place on its exploitation. */
15 /* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
17 /* Timing data for RC6 (rc6.c)
20 Key Setup: 1632 cycles
21 Encrypt: 270 cycles = 94.8 mbits/sec
22 Decrypt: 226 cycles = 113.3 mbits/sec
23 Mean: 248 cycles = 103.2 mbits/sec
26 Key Setup: 1885 cycles
27 Encrypt: 267 cycles = 95.9 mbits/sec
28 Decrypt: 235 cycles = 108.9 mbits/sec
29 Mean: 251 cycles = 102.0 mbits/sec
32 Key Setup: 1877 cycles
33 Encrypt: 270 cycles = 94.8 mbits/sec
34 Decrypt: 227 cycles = 112.8 mbits/sec
35 Mean: 249 cycles = 103.0 mbits/sec
39 #include "silcincludes.h"
43 * SILC Crypto API for RC6
46 /* Sets the key for the cipher. */
48 SILC_CIPHER_API_SET_KEY(rc6)
50 rc6_set_key((RC6Context *)context, (unsigned int *)key, keylen);
54 /* Sets the string as a new key for the cipher. The string is first
55 hashed and then used as a new key. */
57 SILC_CIPHER_API_SET_KEY_WITH_STRING(rc6)
62 /* Encrypts with the cipher in CBC mode. Source and destination buffers
63 maybe one and same. */
65 SILC_CIPHER_API_ENCRYPT_CBC(rc6)
67 unsigned int *in, *out, *tiv;
71 in = (unsigned int *)src;
72 out = (unsigned int *)dst;
73 tiv = (unsigned int *)iv;
75 tmp[0] = in[0] ^ tiv[0];
76 tmp[1] = in[1] ^ tiv[1];
77 tmp[2] = in[2] ^ tiv[2];
78 tmp[3] = in[3] ^ tiv[3];
79 rc6_encrypt((RC6Context *)context, tmp, out);
83 for (i = 16; i < len; i += 16) {
84 tmp[0] = in[0] ^ out[0 - 4];
85 tmp[1] = in[1] ^ out[1 - 4];
86 tmp[2] = in[2] ^ out[2 - 4];
87 tmp[3] = in[3] ^ out[3 - 4];
88 rc6_encrypt((RC6Context *)context, tmp, out);
101 /* Decrypts with the cipher in CBC mode. Source and destination buffers
102 maybe one and same. */
104 SILC_CIPHER_API_DECRYPT_CBC(rc6)
106 unsigned int *in, *out, *tiv;
107 unsigned int tmp[4], tmp2[4];
110 in = (unsigned int *)src;
111 out = (unsigned int *)dst;
112 tiv = (unsigned int *)iv;
118 rc6_decrypt((RC6Context *)context, in, out);
126 for (i = 16; i < len; i += 16) {
135 rc6_decrypt((RC6Context *)context, in, out);
152 /* Returns the size of the cipher context. */
154 SILC_CIPHER_API_CONTEXT_LEN(rc6)
156 return sizeof(RC6Context);
160 #define f_rnd(i,a,b,c,d) \
161 u = rotl(d * (d + d + 1), 5); \
162 t = rotl(b * (b + b + 1), 5); \
163 a = rotl(a ^ t, u) + l_key[i]; \
164 c = rotl(c ^ u, t) + l_key[i + 1]
166 #define i_rnd(i,a,b,c,d) \
167 u = rotl(d * (d + d + 1), 5); \
168 t = rotl(b * (b + b + 1), 5); \
169 c = rotr(c - l_key[i + 1], t) ^ u; \
170 a = rotr(a - l_key[i], u) ^ t
172 /* initialise the key schedule from the user supplied key */
174 u4byte *rc6_set_key(RC6Context *ctx,
175 const u4byte in_key[], const u4byte key_len)
177 u4byte i, j, k, a, b, l[8], t;
178 u4byte *l_key = ctx->l_key;
180 l_key[0] = 0xb7e15163;
182 for(k = 1; k < 44; ++k)
184 l_key[k] = l_key[k - 1] + 0x9e3779b9;
186 for(k = 0; k < key_len / 32; ++k)
190 t = (key_len / 32) - 1; // t = (key_len / 32);
194 for(k = 0; k < 132; ++k)
195 { a = rotl(l_key[i] + a + b, 3); b += a;
196 b = rotl(l[j] + b, b);
197 l_key[i] = a; l[j] = b;
198 i = (i == 43 ? 0 : i + 1); // i = (i + 1) % 44;
199 j = (j == t ? 0 : j + 1); // j = (j + 1) % t;
205 /* encrypt a block of text */
207 void rc6_encrypt(RC6Context *ctx,
208 const u4byte in_blk[4], u4byte out_blk[4])
211 u4byte *l_key = ctx->l_key;
213 a = in_blk[0]; b = in_blk[1] + l_key[0];
214 c = in_blk[2]; d = in_blk[3] + l_key[1];
216 f_rnd( 2,a,b,c,d); f_rnd( 4,b,c,d,a);
217 f_rnd( 6,c,d,a,b); f_rnd( 8,d,a,b,c);
218 f_rnd(10,a,b,c,d); f_rnd(12,b,c,d,a);
219 f_rnd(14,c,d,a,b); f_rnd(16,d,a,b,c);
220 f_rnd(18,a,b,c,d); f_rnd(20,b,c,d,a);
221 f_rnd(22,c,d,a,b); f_rnd(24,d,a,b,c);
222 f_rnd(26,a,b,c,d); f_rnd(28,b,c,d,a);
223 f_rnd(30,c,d,a,b); f_rnd(32,d,a,b,c);
224 f_rnd(34,a,b,c,d); f_rnd(36,b,c,d,a);
225 f_rnd(38,c,d,a,b); f_rnd(40,d,a,b,c);
227 out_blk[0] = a + l_key[42]; out_blk[1] = b;
228 out_blk[2] = c + l_key[43]; out_blk[3] = d;
231 /* decrypt a block of text */
233 void rc6_decrypt(RC6Context *ctx,
234 const u4byte in_blk[4], u4byte out_blk[4])
237 u4byte *l_key = ctx->l_key;
239 d = in_blk[3]; c = in_blk[2] - l_key[43];
240 b = in_blk[1]; a = in_blk[0] - l_key[42];
242 i_rnd(40,d,a,b,c); i_rnd(38,c,d,a,b);
243 i_rnd(36,b,c,d,a); i_rnd(34,a,b,c,d);
244 i_rnd(32,d,a,b,c); i_rnd(30,c,d,a,b);
245 i_rnd(28,b,c,d,a); i_rnd(26,a,b,c,d);
246 i_rnd(24,d,a,b,c); i_rnd(22,c,d,a,b);
247 i_rnd(20,b,c,d,a); i_rnd(18,a,b,c,d);
248 i_rnd(16,d,a,b,c); i_rnd(14,c,d,a,b);
249 i_rnd(12,b,c,d,a); i_rnd(10,a,b,c,d);
250 i_rnd( 8,d,a,b,c); i_rnd( 6,c,d,a,b);
251 i_rnd( 4,b,c,d,a); i_rnd( 2,a,b,c,d);
253 out_blk[3] = d - l_key[1]; out_blk[2] = c;
254 out_blk[1] = b - l_key[0]; out_blk[0] = a;