Mercurial > dropbear
comparison rc5.c @ 0:d7da3b1e1540 libtomcrypt
put back the 0.95 makefile which was inadvertently merged over
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 31 May 2004 18:21:40 +0000 |
parents | |
children | 5d99163f7e32 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d7da3b1e1540 |
---|---|
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, [email protected], http://libtomcrypt.org | |
10 */ | |
11 | |
12 /* RC5 code by Tom St Denis */ | |
13 | |
14 #include "mycrypt.h" | |
15 | |
16 #ifdef RC5 | |
17 | |
18 const struct _cipher_descriptor rc5_desc = | |
19 { | |
20 "rc5", | |
21 2, | |
22 8, 128, 8, 12, | |
23 &rc5_setup, | |
24 &rc5_ecb_encrypt, | |
25 &rc5_ecb_decrypt, | |
26 &rc5_test, | |
27 &rc5_keysize | |
28 }; | |
29 | |
30 static const ulong32 stab[50] = { | |
31 0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, | |
32 0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, | |
33 0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, | |
34 0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, | |
35 0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, | |
36 0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL, 0xe96a3d2fUL, 0x87a1b6e8UL, 0x25d930a1UL, 0xc410aa5aUL, | |
37 0x62482413UL, 0x007f9dccUL | |
38 }; | |
39 | |
40 #ifdef CLEAN_STACK | |
41 static int _rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) | |
42 #else | |
43 int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) | |
44 #endif | |
45 { | |
46 ulong32 L[64], *S, A, B, i, j, v, s, t, l; | |
47 | |
48 _ARGCHK(skey != NULL); | |
49 _ARGCHK(key != NULL); | |
50 | |
51 /* test parameters */ | |
52 if (num_rounds == 0) { | |
53 num_rounds = rc5_desc.default_rounds; | |
54 } | |
55 | |
56 if (num_rounds < 12 || num_rounds > 24) { | |
57 return CRYPT_INVALID_ROUNDS; | |
58 } | |
59 | |
60 /* key must be between 64 and 1024 bits */ | |
61 if (keylen < 8 || keylen > 128) { | |
62 return CRYPT_INVALID_KEYSIZE; | |
63 } | |
64 | |
65 skey->rc5.rounds = num_rounds; | |
66 S = skey->rc5.K; | |
67 | |
68 /* copy the key into the L array */ | |
69 for (A = i = j = 0; i < (ulong32)keylen; ) { | |
70 A = (A << 8) | ((ulong32)(key[i++] & 255)); | |
71 if ((i & 3) == 0) { | |
72 L[j++] = BSWAP(A); | |
73 A = 0; | |
74 } | |
75 } | |
76 | |
77 if ((keylen & 3) != 0) { | |
78 A <<= (ulong32)((8 * (4 - (keylen&3)))); | |
79 L[j++] = BSWAP(A); | |
80 } | |
81 | |
82 /* setup the S array */ | |
83 t = (ulong32)(2 * (num_rounds + 1)); | |
84 memcpy(S, stab, t * sizeof(*S)); | |
85 | |
86 /* mix buffer */ | |
87 s = 3 * MAX(t, j); | |
88 l = j; | |
89 for (A = B = i = j = v = 0; v < s; v++) { | |
90 A = S[i] = ROL(S[i] + A + B, 3); | |
91 B = L[j] = ROL(L[j] + A + B, (A+B)); | |
92 if (++i == t) { i = 0; } | |
93 if (++j == l) { j = 0; } | |
94 } | |
95 return CRYPT_OK; | |
96 } | |
97 | |
98 #ifdef CLEAN_STACK | |
99 int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) | |
100 { | |
101 int x; | |
102 x = _rc5_setup(key, keylen, num_rounds, skey); | |
103 burn_stack(sizeof(ulong32) * 122 + sizeof(int)); | |
104 return x; | |
105 } | |
106 #endif | |
107 | |
108 #ifdef CLEAN_STACK | |
109 static void _rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) | |
110 #else | |
111 void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) | |
112 #endif | |
113 { | |
114 ulong32 A, B, *K; | |
115 int r; | |
116 _ARGCHK(key != NULL); | |
117 _ARGCHK(pt != NULL); | |
118 _ARGCHK(ct != NULL); | |
119 | |
120 LOAD32L(A, &pt[0]); | |
121 LOAD32L(B, &pt[4]); | |
122 A += key->rc5.K[0]; | |
123 B += key->rc5.K[1]; | |
124 K = key->rc5.K + 2; | |
125 | |
126 if ((key->rc5.rounds & 1) == 0) { | |
127 for (r = 0; r < key->rc5.rounds; r += 2) { | |
128 A = ROL(A ^ B, B) + K[0]; | |
129 B = ROL(B ^ A, A) + K[1]; | |
130 A = ROL(A ^ B, B) + K[2]; | |
131 B = ROL(B ^ A, A) + K[3]; | |
132 K += 4; | |
133 } | |
134 } else { | |
135 for (r = 0; r < key->rc5.rounds; r++) { | |
136 A = ROL(A ^ B, B) + K[0]; | |
137 B = ROL(B ^ A, A) + K[1]; | |
138 K += 2; | |
139 } | |
140 } | |
141 STORE32L(A, &ct[0]); | |
142 STORE32L(B, &ct[4]); | |
143 } | |
144 | |
145 #ifdef CLEAN_STACK | |
146 void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) | |
147 { | |
148 _rc5_ecb_encrypt(pt, ct, key); | |
149 burn_stack(sizeof(ulong32) * 2 + sizeof(int)); | |
150 } | |
151 #endif | |
152 | |
153 #ifdef CLEAN_STACK | |
154 static void _rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key) | |
155 #else | |
156 void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key) | |
157 #endif | |
158 { | |
159 ulong32 A, B, *K; | |
160 int r; | |
161 _ARGCHK(key != NULL); | |
162 _ARGCHK(pt != NULL); | |
163 _ARGCHK(ct != NULL); | |
164 | |
165 LOAD32L(A, &ct[0]); | |
166 LOAD32L(B, &ct[4]); | |
167 K = key->rc5.K + (key->rc5.rounds << 1); | |
168 | |
169 if ((key->rc5.rounds & 1) == 0) { | |
170 K -= 2; | |
171 for (r = key->rc5.rounds - 1; r >= 0; r -= 2) { | |
172 B = ROR(B - K[3], A) ^ A; | |
173 A = ROR(A - K[2], B) ^ B; | |
174 B = ROR(B - K[1], A) ^ A; | |
175 A = ROR(A - K[0], B) ^ B; | |
176 K -= 4; | |
177 } | |
178 } else { | |
179 for (r = key->rc5.rounds - 1; r >= 0; r--) { | |
180 B = ROR(B - K[1], A) ^ A; | |
181 A = ROR(A - K[0], B) ^ B; | |
182 K -= 2; | |
183 } | |
184 } | |
185 A -= key->rc5.K[0]; | |
186 B -= key->rc5.K[1]; | |
187 STORE32L(A, &pt[0]); | |
188 STORE32L(B, &pt[4]); | |
189 } | |
190 | |
191 #ifdef CLEAN_STACK | |
192 void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key) | |
193 { | |
194 _rc5_ecb_decrypt(ct, pt, key); | |
195 burn_stack(sizeof(ulong32) * 2 + sizeof(int)); | |
196 } | |
197 #endif | |
198 | |
199 int rc5_test(void) | |
200 { | |
201 #ifndef LTC_TEST | |
202 return CRYPT_NOP; | |
203 #else | |
204 static const struct { | |
205 unsigned char key[16], pt[8], ct[8]; | |
206 } tests[] = { | |
207 { | |
208 { 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51, | |
209 0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 }, | |
210 { 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d }, | |
211 { 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 } | |
212 }, | |
213 { | |
214 { 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f, | |
215 0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 }, | |
216 { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 }, | |
217 { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 } | |
218 }, | |
219 { | |
220 { 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f, | |
221 0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf }, | |
222 { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }, | |
223 { 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc } | |
224 } | |
225 }; | |
226 unsigned char tmp[2][8]; | |
227 int x, y, err; | |
228 symmetric_key key; | |
229 | |
230 for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { | |
231 /* setup key */ | |
232 if ((err = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) { | |
233 return err; | |
234 } | |
235 | |
236 /* encrypt and decrypt */ | |
237 rc5_ecb_encrypt(tests[x].pt, tmp[0], &key); | |
238 rc5_ecb_decrypt(tmp[0], tmp[1], &key); | |
239 | |
240 /* compare */ | |
241 if (memcmp(tmp[0], tests[x].ct, 8) != 0 || memcmp(tmp[1], tests[x].pt, 8) != 0) { | |
242 return CRYPT_FAIL_TESTVECTOR; | |
243 } | |
244 | |
245 /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ | |
246 for (y = 0; y < 8; y++) tmp[0][y] = 0; | |
247 for (y = 0; y < 1000; y++) rc5_ecb_encrypt(tmp[0], tmp[0], &key); | |
248 for (y = 0; y < 1000; y++) rc5_ecb_decrypt(tmp[0], tmp[0], &key); | |
249 for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; | |
250 } | |
251 return CRYPT_OK; | |
252 #endif | |
253 } | |
254 | |
255 int rc5_keysize(int *desired_keysize) | |
256 { | |
257 _ARGCHK(desired_keysize != NULL); | |
258 if (*desired_keysize < 8) { | |
259 return CRYPT_INVALID_KEYSIZE; | |
260 } else if (*desired_keysize > 128) { | |
261 *desired_keysize = 128; | |
262 } | |
263 return CRYPT_OK; | |
264 } | |
265 | |
266 #endif | |
267 | |
268 | |
269 |