Mercurial > pidgin.yaz
comparison libpurple/cipher.c @ 31667:076d62344ede
broke des and des3 out to ciphers/des.c
author | Gary Kramlich <grim@reaperworld.com> |
---|---|
date | Mon, 14 Feb 2011 06:51:10 +0000 |
parents | 3af51303d45c |
children | 2b041e31b825 |
comparison
equal
deleted
inserted
replaced
31666:3af51303d45c | 31667:076d62344ede |
---|---|
118 | 118 |
119 return TRUE; | 119 return TRUE; |
120 } | 120 } |
121 #endif | 121 #endif |
122 | 122 |
123 /****************************************************************************** | |
124 * DES | |
125 *****************************************************************************/ | |
126 | |
127 typedef struct _des_ctx | |
128 { | |
129 guint32 encrypt_subkeys[32]; | |
130 guint32 decrypt_subkeys[32]; | |
131 } des_ctx[1]; | |
132 | |
133 /* | |
134 * The s-box values are permuted according to the 'primitive function P' | |
135 */ | |
136 static const guint32 sbox1[64] = | |
137 { | |
138 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, | |
139 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, | |
140 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, | |
141 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, | |
142 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, | |
143 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, | |
144 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, | |
145 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002 | |
146 }; | |
147 | |
148 static const guint32 sbox2[64] = | |
149 { | |
150 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, | |
151 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, | |
152 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, | |
153 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, | |
154 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, | |
155 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, | |
156 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, | |
157 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000 | |
158 }; | |
159 | |
160 static const guint32 sbox3[64] = | |
161 { | |
162 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, | |
163 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, | |
164 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, | |
165 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, | |
166 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, | |
167 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, | |
168 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, | |
169 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100 | |
170 }; | |
171 | |
172 static const guint32 sbox4[64] = | |
173 { | |
174 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, | |
175 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, | |
176 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, | |
177 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, | |
178 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, | |
179 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, | |
180 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, | |
181 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040 | |
182 }; | |
183 | |
184 static const guint32 sbox5[64] = | |
185 { | |
186 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, | |
187 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, | |
188 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, | |
189 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, | |
190 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, | |
191 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, | |
192 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, | |
193 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080 | |
194 }; | |
195 | |
196 static const guint32 sbox6[64] = | |
197 { | |
198 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, | |
199 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, | |
200 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, | |
201 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, | |
202 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, | |
203 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, | |
204 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, | |
205 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008 | |
206 }; | |
207 | |
208 static const guint32 sbox7[64] = | |
209 { | |
210 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, | |
211 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, | |
212 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, | |
213 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, | |
214 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, | |
215 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, | |
216 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, | |
217 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001 | |
218 }; | |
219 | |
220 static const guint32 sbox8[64] = | |
221 { | |
222 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, | |
223 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, | |
224 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, | |
225 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, | |
226 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, | |
227 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, | |
228 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, | |
229 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800 | |
230 }; | |
231 | |
232 | |
233 | |
234 /* | |
235 * * These two tables are part of the 'permuted choice 1' function. | |
236 * * In this implementation several speed improvements are done. | |
237 * */ | |
238 static const guint32 leftkey_swap[16] = | |
239 { | |
240 0x00000000, 0x00000001, 0x00000100, 0x00000101, | |
241 0x00010000, 0x00010001, 0x00010100, 0x00010101, | |
242 0x01000000, 0x01000001, 0x01000100, 0x01000101, | |
243 0x01010000, 0x01010001, 0x01010100, 0x01010101 | |
244 }; | |
245 | |
246 static const guint32 rightkey_swap[16] = | |
247 { | |
248 0x00000000, 0x01000000, 0x00010000, 0x01010000, | |
249 0x00000100, 0x01000100, 0x00010100, 0x01010100, | |
250 0x00000001, 0x01000001, 0x00010001, 0x01010001, | |
251 0x00000101, 0x01000101, 0x00010101, 0x01010101, | |
252 }; | |
253 | |
254 | |
255 | |
256 /* | |
257 * Numbers of left shifts per round for encryption subkey schedule | |
258 * To calculate the decryption key scheduling we just reverse the | |
259 * ordering of the subkeys so we can omit the table for decryption | |
260 * subkey schedule. | |
261 */ | |
262 static const guint8 encrypt_rotate_tab[16] = | |
263 { | |
264 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 | |
265 }; | |
266 | |
267 /* | |
268 * Macro to swap bits across two words | |
269 **/ | |
270 #define DO_PERMUTATION(a, temp, b, offset, mask) \ | |
271 temp = ((a>>offset) ^ b) & mask; \ | |
272 b ^= temp; \ | |
273 a ^= temp<<offset; | |
274 | |
275 | |
276 /* | |
277 * This performs the 'initial permutation' for the data to be encrypted or decrypted | |
278 **/ | |
279 #define INITIAL_PERMUTATION(left, temp, right) \ | |
280 DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ | |
281 DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ | |
282 DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ | |
283 DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ | |
284 DO_PERMUTATION(left, temp, right, 1, 0x55555555) | |
285 | |
286 | |
287 /* | |
288 * The 'inverse initial permutation' | |
289 **/ | |
290 #define FINAL_PERMUTATION(left, temp, right) \ | |
291 DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ | |
292 DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ | |
293 DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ | |
294 DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ | |
295 DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) | |
296 | |
297 | |
298 /* | |
299 * A full DES round including 'expansion function', 'sbox substitution' | |
300 * and 'primitive function P' but without swapping the left and right word. | |
301 **/ | |
302 #define DES_ROUND(from, to, work, subkey) \ | |
303 work = ((from<<1) | (from>>31)) ^ *subkey++; \ | |
304 to ^= sbox8[ work & 0x3f ]; \ | |
305 to ^= sbox6[ (work>>8) & 0x3f ]; \ | |
306 to ^= sbox4[ (work>>16) & 0x3f ]; \ | |
307 to ^= sbox2[ (work>>24) & 0x3f ]; \ | |
308 work = ((from>>3) | (from<<29)) ^ *subkey++; \ | |
309 to ^= sbox7[ work & 0x3f ]; \ | |
310 to ^= sbox5[ (work>>8) & 0x3f ]; \ | |
311 to ^= sbox3[ (work>>16) & 0x3f ]; \ | |
312 to ^= sbox1[ (work>>24) & 0x3f ]; | |
313 | |
314 | |
315 /* | |
316 * Macros to convert 8 bytes from/to 32bit words | |
317 **/ | |
318 #define READ_64BIT_DATA(data, left, right) \ | |
319 left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ | |
320 right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; | |
321 | |
322 #define WRITE_64BIT_DATA(data, left, right) \ | |
323 data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ | |
324 data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ | |
325 data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ | |
326 data[6] = (right >> 8) &0xff; data[7] = right &0xff; | |
327 | |
328 | |
329 | |
330 | |
331 | |
332 | |
333 /* | |
334 * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for | |
335 * 16 encryption rounds. | |
336 * To calculate subkeys for decryption the caller | |
337 * have to reorder the generated subkeys. | |
338 * | |
339 * rawkey: 8 Bytes of key data | |
340 * subkey: Array of at least 32 guint32s. Will be filled | |
341 * with calculated subkeys. | |
342 * | |
343 **/ | |
344 static void | |
345 des_key_schedule (const guint8 * rawkey, guint32 * subkey) | |
346 { | |
347 guint32 left, right, work; | |
348 int round; | |
349 | |
350 READ_64BIT_DATA (rawkey, left, right) | |
351 | |
352 DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) | |
353 DO_PERMUTATION (right, work, left, 0, 0x10101010) | |
354 | |
355 left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) | |
356 | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) | |
357 | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) | |
358 | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4); | |
359 | |
360 left &= 0x0fffffff; | |
361 | |
362 right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) | |
363 | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) | |
364 | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) | |
365 | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4); | |
366 | |
367 right &= 0x0fffffff; | |
368 | |
369 for (round = 0; round < 16; ++round) | |
370 { | |
371 left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; | |
372 right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; | |
373 | |
374 *subkey++ = ((left << 4) & 0x24000000) | |
375 | ((left << 28) & 0x10000000) | |
376 | ((left << 14) & 0x08000000) | |
377 | ((left << 18) & 0x02080000) | |
378 | ((left << 6) & 0x01000000) | |
379 | ((left << 9) & 0x00200000) | |
380 | ((left >> 1) & 0x00100000) | |
381 | ((left << 10) & 0x00040000) | |
382 | ((left << 2) & 0x00020000) | |
383 | ((left >> 10) & 0x00010000) | |
384 | ((right >> 13) & 0x00002000) | |
385 | ((right >> 4) & 0x00001000) | |
386 | ((right << 6) & 0x00000800) | |
387 | ((right >> 1) & 0x00000400) | |
388 | ((right >> 14) & 0x00000200) | |
389 | (right & 0x00000100) | |
390 | ((right >> 5) & 0x00000020) | |
391 | ((right >> 10) & 0x00000010) | |
392 | ((right >> 3) & 0x00000008) | |
393 | ((right >> 18) & 0x00000004) | |
394 | ((right >> 26) & 0x00000002) | |
395 | ((right >> 24) & 0x00000001); | |
396 | |
397 *subkey++ = ((left << 15) & 0x20000000) | |
398 | ((left << 17) & 0x10000000) | |
399 | ((left << 10) & 0x08000000) | |
400 | ((left << 22) & 0x04000000) | |
401 | ((left >> 2) & 0x02000000) | |
402 | ((left << 1) & 0x01000000) | |
403 | ((left << 16) & 0x00200000) | |
404 | ((left << 11) & 0x00100000) | |
405 | ((left << 3) & 0x00080000) | |
406 | ((left >> 6) & 0x00040000) | |
407 | ((left << 15) & 0x00020000) | |
408 | ((left >> 4) & 0x00010000) | |
409 | ((right >> 2) & 0x00002000) | |
410 | ((right << 8) & 0x00001000) | |
411 | ((right >> 14) & 0x00000808) | |
412 | ((right >> 9) & 0x00000400) | |
413 | ((right) & 0x00000200) | |
414 | ((right << 7) & 0x00000100) | |
415 | ((right >> 7) & 0x00000020) | |
416 | ((right >> 3) & 0x00000011) | |
417 | ((right << 2) & 0x00000004) | |
418 | ((right >> 21) & 0x00000002); | |
419 } | |
420 } | |
421 | |
422 | |
423 | |
424 /* | |
425 * Fill a DES context with subkeys calculated from a 64bit key. | |
426 * Does not check parity bits, but simply ignore them. | |
427 * Does not check for weak keys. | |
428 **/ | |
429 static void | |
430 des_set_key (PurpleCipherContext *context, const guchar * key) | |
431 { | |
432 struct _des_ctx *ctx = purple_cipher_context_get_data(context); | |
433 int i; | |
434 | |
435 des_key_schedule (key, ctx->encrypt_subkeys); | |
436 | |
437 for(i=0; i<32; i+=2) | |
438 { | |
439 ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; | |
440 ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; | |
441 } | |
442 } | |
443 | |
444 | |
445 | |
446 /* | |
447 * Electronic Codebook Mode DES encryption/decryption of data according | |
448 * to 'mode'. | |
449 **/ | |
450 static int | |
451 des_ecb_crypt (struct _des_ctx *ctx, const guint8 * from, guint8 * to, int mode) | |
452 { | |
453 guint32 left, right, work; | |
454 guint32 *keys; | |
455 | |
456 keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; | |
457 | |
458 READ_64BIT_DATA (from, left, right) | |
459 INITIAL_PERMUTATION (left, work, right) | |
460 | |
461 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
462 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
463 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
464 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
465 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
466 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
467 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
468 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
469 | |
470 FINAL_PERMUTATION (right, work, left) | |
471 WRITE_64BIT_DATA (to, right, left) | |
472 | |
473 return 0; | |
474 } | |
475 | |
476 static gint | |
477 des_encrypt(PurpleCipherContext *context, const guchar data[], | |
478 size_t len, guchar output[], size_t *outlen) { | |
479 int offset = 0; | |
480 int i = 0; | |
481 int tmp; | |
482 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
483 while(offset+8<=len) { | |
484 des_ecb_crypt(purple_cipher_context_get_data(context), | |
485 data+offset, | |
486 output+offset, | |
487 0); | |
488 offset+=8; | |
489 } | |
490 *outlen = len; | |
491 if(offset<len) { | |
492 *outlen += len - offset; | |
493 tmp = offset; | |
494 while(tmp<len) { | |
495 buf[i++] = data[tmp]; | |
496 tmp++; | |
497 } | |
498 des_ecb_crypt(purple_cipher_context_get_data(context), | |
499 buf, | |
500 output+offset, | |
501 0); | |
502 } | |
503 return 0; | |
504 } | |
505 | |
506 static gint | |
507 des_decrypt(PurpleCipherContext *context, const guchar data[], | |
508 size_t len, guchar output[], size_t *outlen) { | |
509 int offset = 0; | |
510 int i = 0; | |
511 int tmp; | |
512 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
513 while(offset+8<=len) { | |
514 des_ecb_crypt(purple_cipher_context_get_data(context), | |
515 data+offset, | |
516 output+offset, | |
517 1); | |
518 offset+=8; | |
519 } | |
520 *outlen = len; | |
521 if(offset<len) { | |
522 *outlen += len - offset; | |
523 tmp = offset; | |
524 while(tmp<len) { | |
525 buf[i++] = data[tmp]; | |
526 tmp++; | |
527 } | |
528 des_ecb_crypt(purple_cipher_context_get_data(context), | |
529 buf, | |
530 output+offset, | |
531 1); | |
532 } | |
533 return 0; | |
534 } | |
535 | |
536 static void | |
537 des_init(PurpleCipherContext *context, gpointer extra) { | |
538 struct _des_ctx *mctx; | |
539 mctx = g_new0(struct _des_ctx, 1); | |
540 purple_cipher_context_set_data(context, mctx); | |
541 } | |
542 | |
543 static void | |
544 des_uninit(PurpleCipherContext *context) { | |
545 struct _des_ctx *des_context; | |
546 | |
547 des_context = purple_cipher_context_get_data(context); | |
548 memset(des_context, 0, sizeof(*des_context)); | |
549 | |
550 g_free(des_context); | |
551 des_context = NULL; | |
552 } | |
553 | |
554 static PurpleCipherOps DESOps = { | |
555 NULL, /* Set option */ | |
556 NULL, /* Get option */ | |
557 des_init, /* init */ | |
558 NULL, /* reset */ | |
559 des_uninit, /* uninit */ | |
560 NULL, /* set iv */ | |
561 NULL, /* append */ | |
562 NULL, /* digest */ | |
563 des_encrypt, /* encrypt */ | |
564 des_decrypt, /* decrypt */ | |
565 NULL, /* set salt */ | |
566 NULL, /* get salt size */ | |
567 des_set_key, /* set key */ | |
568 NULL, /* get key size */ | |
569 NULL, /* set batch mode */ | |
570 NULL, /* get batch mode */ | |
571 NULL, /* get block size */ | |
572 NULL /* set key with len */ | |
573 }; | |
574 | |
575 /****************************************************************************** | |
576 * Triple-DES | |
577 *****************************************************************************/ | |
578 | |
579 typedef struct _des3_ctx | |
580 { | |
581 PurpleCipherBatchMode mode; | |
582 guchar iv[8]; | |
583 /* First key for encryption */ | |
584 struct _des_ctx key1; | |
585 /* Second key for decryption */ | |
586 struct _des_ctx key2; | |
587 /* Third key for encryption */ | |
588 struct _des_ctx key3; | |
589 } des3_ctx[1]; | |
590 | |
591 /* | |
592 * Fill a DES3 context with subkeys calculated from 3 64bit key. | |
593 * Does not check parity bits, but simply ignore them. | |
594 * Does not check for weak keys. | |
595 **/ | |
596 static void | |
597 des3_set_key(PurpleCipherContext *context, const guchar * key) | |
598 { | |
599 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
600 int i; | |
601 | |
602 des_key_schedule (key + 0, ctx->key1.encrypt_subkeys); | |
603 des_key_schedule (key + 8, ctx->key2.encrypt_subkeys); | |
604 des_key_schedule (key + 16, ctx->key3.encrypt_subkeys); | |
605 | |
606 for (i = 0; i < 32; i += 2) | |
607 { | |
608 ctx->key1.decrypt_subkeys[i] = ctx->key1.encrypt_subkeys[30-i]; | |
609 ctx->key1.decrypt_subkeys[i+1] = ctx->key1.encrypt_subkeys[31-i]; | |
610 ctx->key2.decrypt_subkeys[i] = ctx->key2.encrypt_subkeys[30-i]; | |
611 ctx->key2.decrypt_subkeys[i+1] = ctx->key2.encrypt_subkeys[31-i]; | |
612 ctx->key3.decrypt_subkeys[i] = ctx->key3.encrypt_subkeys[30-i]; | |
613 ctx->key3.decrypt_subkeys[i+1] = ctx->key3.encrypt_subkeys[31-i]; | |
614 } | |
615 } | |
616 | |
617 static gint | |
618 des3_ecb_encrypt(struct _des3_ctx *ctx, const guchar data[], | |
619 size_t len, guchar output[], size_t *outlen) | |
620 { | |
621 int offset = 0; | |
622 int i = 0; | |
623 int tmp; | |
624 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
625 while (offset + 8 <= len) { | |
626 des_ecb_crypt(&ctx->key1, | |
627 data+offset, | |
628 output+offset, | |
629 0); | |
630 des_ecb_crypt(&ctx->key2, | |
631 output+offset, | |
632 buf, | |
633 1); | |
634 des_ecb_crypt(&ctx->key3, | |
635 buf, | |
636 output+offset, | |
637 0); | |
638 offset += 8; | |
639 } | |
640 *outlen = len; | |
641 if (offset < len) { | |
642 *outlen += len - offset; | |
643 tmp = offset; | |
644 memset(buf, 0, 8); | |
645 while (tmp < len) { | |
646 buf[i++] = data[tmp]; | |
647 tmp++; | |
648 } | |
649 des_ecb_crypt(&ctx->key1, | |
650 buf, | |
651 output+offset, | |
652 0); | |
653 des_ecb_crypt(&ctx->key2, | |
654 output+offset, | |
655 buf, | |
656 1); | |
657 des_ecb_crypt(&ctx->key3, | |
658 buf, | |
659 output+offset, | |
660 0); | |
661 } | |
662 return 0; | |
663 } | |
664 | |
665 static gint | |
666 des3_cbc_encrypt(struct _des3_ctx *ctx, const guchar data[], | |
667 size_t len, guchar output[], size_t *outlen) | |
668 { | |
669 int offset = 0; | |
670 int i = 0; | |
671 int tmp; | |
672 guint8 buf[8]; | |
673 memcpy(buf, ctx->iv, 8); | |
674 while (offset + 8 <= len) { | |
675 for (i = 0; i < 8; i++) | |
676 buf[i] ^= data[offset + i]; | |
677 des_ecb_crypt(&ctx->key1, | |
678 buf, | |
679 output+offset, | |
680 0); | |
681 des_ecb_crypt(&ctx->key2, | |
682 output+offset, | |
683 buf, | |
684 1); | |
685 des_ecb_crypt(&ctx->key3, | |
686 buf, | |
687 output+offset, | |
688 0); | |
689 memcpy(buf, output+offset, 8); | |
690 offset += 8; | |
691 } | |
692 *outlen = len; | |
693 if (offset < len) { | |
694 *outlen += len - offset; | |
695 tmp = offset; | |
696 i = 0; | |
697 while (tmp < len) { | |
698 buf[i++] ^= data[tmp]; | |
699 tmp++; | |
700 } | |
701 des_ecb_crypt(&ctx->key1, | |
702 buf, | |
703 output+offset, | |
704 0); | |
705 des_ecb_crypt(&ctx->key2, | |
706 output+offset, | |
707 buf, | |
708 1); | |
709 des_ecb_crypt(&ctx->key3, | |
710 buf, | |
711 output+offset, | |
712 0); | |
713 } | |
714 return 0; | |
715 } | |
716 | |
717 static gint | |
718 des3_encrypt(PurpleCipherContext *context, const guchar data[], | |
719 size_t len, guchar output[], size_t *outlen) | |
720 { | |
721 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
722 | |
723 if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { | |
724 return des3_ecb_encrypt(ctx, data, len, output, outlen); | |
725 } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { | |
726 return des3_cbc_encrypt(ctx, data, len, output, outlen); | |
727 } else { | |
728 g_return_val_if_reached(0); | |
729 } | |
730 | |
731 return 0; | |
732 } | |
733 | |
734 static gint | |
735 des3_ecb_decrypt(struct _des3_ctx *ctx, const guchar data[], | |
736 size_t len, guchar output[], size_t *outlen) | |
737 { | |
738 int offset = 0; | |
739 int i = 0; | |
740 int tmp; | |
741 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
742 while (offset + 8 <= len) { | |
743 /* NOTE: Apply key in reverse */ | |
744 des_ecb_crypt(&ctx->key3, | |
745 data+offset, | |
746 output+offset, | |
747 1); | |
748 des_ecb_crypt(&ctx->key2, | |
749 output+offset, | |
750 buf, | |
751 0); | |
752 des_ecb_crypt(&ctx->key1, | |
753 buf, | |
754 output+offset, | |
755 1); | |
756 offset+=8; | |
757 } | |
758 *outlen = len; | |
759 if (offset < len) { | |
760 *outlen += len - offset; | |
761 tmp = offset; | |
762 memset(buf, 0, 8); | |
763 while (tmp < len) { | |
764 buf[i++] = data[tmp]; | |
765 tmp++; | |
766 } | |
767 des_ecb_crypt(&ctx->key3, | |
768 buf, | |
769 output+offset, | |
770 1); | |
771 des_ecb_crypt(&ctx->key2, | |
772 output+offset, | |
773 buf, | |
774 0); | |
775 des_ecb_crypt(&ctx->key1, | |
776 buf, | |
777 output+offset, | |
778 1); | |
779 } | |
780 return 0; | |
781 } | |
782 | |
783 static gint | |
784 des3_cbc_decrypt(struct _des3_ctx *ctx, const guchar data[], | |
785 size_t len, guchar output[], size_t *outlen) | |
786 { | |
787 int offset = 0; | |
788 int i = 0; | |
789 int tmp; | |
790 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
791 guint8 link[8]; | |
792 memcpy(link, ctx->iv, 8); | |
793 while (offset + 8 <= len) { | |
794 des_ecb_crypt(&ctx->key3, | |
795 data+offset, | |
796 output+offset, | |
797 1); | |
798 des_ecb_crypt(&ctx->key2, | |
799 output+offset, | |
800 buf, | |
801 0); | |
802 des_ecb_crypt(&ctx->key1, | |
803 buf, | |
804 output+offset, | |
805 1); | |
806 for (i = 0; i < 8; i++) | |
807 output[offset + i] ^= link[i]; | |
808 memcpy(link, data + offset, 8); | |
809 offset+=8; | |
810 } | |
811 *outlen = len; | |
812 if(offset<len) { | |
813 *outlen += len - offset; | |
814 tmp = offset; | |
815 memset(buf, 0, 8); | |
816 i = 0; | |
817 while(tmp<len) { | |
818 buf[i++] = data[tmp]; | |
819 tmp++; | |
820 } | |
821 des_ecb_crypt(&ctx->key3, | |
822 buf, | |
823 output+offset, | |
824 1); | |
825 des_ecb_crypt(&ctx->key2, | |
826 output+offset, | |
827 buf, | |
828 0); | |
829 des_ecb_crypt(&ctx->key1, | |
830 buf, | |
831 output+offset, | |
832 1); | |
833 for (i = 0; i < 8; i++) | |
834 output[offset + i] ^= link[i]; | |
835 } | |
836 return 0; | |
837 } | |
838 | |
839 static gint | |
840 des3_decrypt(PurpleCipherContext *context, const guchar data[], | |
841 size_t len, guchar output[], size_t *outlen) | |
842 { | |
843 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
844 | |
845 if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { | |
846 return des3_ecb_decrypt(ctx, data, len, output, outlen); | |
847 } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { | |
848 return des3_cbc_decrypt(ctx, data, len, output, outlen); | |
849 } else { | |
850 g_return_val_if_reached(0); | |
851 } | |
852 | |
853 return 0; | |
854 } | |
855 | |
856 static void | |
857 des3_set_batch(PurpleCipherContext *context, PurpleCipherBatchMode mode) | |
858 { | |
859 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
860 | |
861 ctx->mode = mode; | |
862 } | |
863 | |
864 static PurpleCipherBatchMode | |
865 des3_get_batch(PurpleCipherContext *context) | |
866 { | |
867 struct _des3_ctx *ctx = purple_cipher_context_get_data(context); | |
868 | |
869 return ctx->mode; | |
870 } | |
871 | |
872 static void | |
873 des3_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) | |
874 { | |
875 struct _des3_ctx *ctx; | |
876 | |
877 g_return_if_fail(len == 8); | |
878 | |
879 ctx = purple_cipher_context_get_data(context); | |
880 | |
881 memcpy(ctx->iv, iv, len); | |
882 } | |
883 | |
884 static void | |
885 des3_init(PurpleCipherContext *context, gpointer extra) | |
886 { | |
887 struct _des3_ctx *mctx; | |
888 mctx = g_new0(struct _des3_ctx, 1); | |
889 purple_cipher_context_set_data(context, mctx); | |
890 } | |
891 | |
892 static void | |
893 des3_uninit(PurpleCipherContext *context) | |
894 { | |
895 struct _des3_ctx *des3_context; | |
896 | |
897 des3_context = purple_cipher_context_get_data(context); | |
898 memset(des3_context, 0, sizeof(*des3_context)); | |
899 | |
900 g_free(des3_context); | |
901 des3_context = NULL; | |
902 } | |
903 | |
904 static PurpleCipherOps DES3Ops = { | |
905 NULL, /* Set option */ | |
906 NULL, /* Get option */ | |
907 des3_init, /* init */ | |
908 NULL, /* reset */ | |
909 des3_uninit, /* uninit */ | |
910 des3_set_iv, /* set iv */ | |
911 NULL, /* append */ | |
912 NULL, /* digest */ | |
913 des3_encrypt, /* encrypt */ | |
914 des3_decrypt, /* decrypt */ | |
915 NULL, /* set salt */ | |
916 NULL, /* get salt size */ | |
917 des3_set_key, /* set key */ | |
918 NULL, /* get key size */ | |
919 des3_set_batch, /* set batch mode */ | |
920 des3_get_batch, /* get batch mode */ | |
921 NULL, /* get block size */ | |
922 NULL /* set key with len */ | |
923 }; | |
924 | |
925 /******************************************************************************* | 123 /******************************************************************************* |
926 * Structs | 124 * Structs |
927 ******************************************************************************/ | 125 ******************************************************************************/ |
928 struct _PurpleCipher { | 126 struct _PurpleCipher { |
929 gchar *name; /**< Internal name - used for searching */ | 127 gchar *name; /**< Internal name - used for searching */ |
1108 /* This are implemented in the purple-ciphers sublibrary built in the ciphers | 306 /* This are implemented in the purple-ciphers sublibrary built in the ciphers |
1109 * directory. We could put a header file in there, but it's less hassle for | 307 * directory. We could put a header file in there, but it's less hassle for |
1110 * the developer to just add it here since they have to register it here as | 308 * the developer to just add it here since they have to register it here as |
1111 * well. | 309 * well. |
1112 */ | 310 */ |
311 PurpleCipherOps *purple_des_cipher_get_ops(); | |
312 PurpleCipherOps *purple_des3_cipher_get_ops(); | |
1113 PurpleCipherOps *purple_hmac_cipher_get_ops(); | 313 PurpleCipherOps *purple_hmac_cipher_get_ops(); |
1114 PurpleCipherOps *purple_md4_cipher_get_ops(); | 314 PurpleCipherOps *purple_md4_cipher_get_ops(); |
1115 PurpleCipherOps *purple_md5_cipher_get_ops(); | 315 PurpleCipherOps *purple_md5_cipher_get_ops(); |
1116 PurpleCipherOps *purple_rc4_cipher_get_ops(); | 316 PurpleCipherOps *purple_rc4_cipher_get_ops(); |
1117 PurpleCipherOps *purple_sha1_cipher_get_ops(); | 317 PurpleCipherOps *purple_sha1_cipher_get_ops(); |
1135 purple_ciphers_register_cipher("md5", purple_md5_cipher_get_ops()); | 335 purple_ciphers_register_cipher("md5", purple_md5_cipher_get_ops()); |
1136 purple_ciphers_register_cipher("sha1", purple_sha1_cipher_get_ops()); | 336 purple_ciphers_register_cipher("sha1", purple_sha1_cipher_get_ops()); |
1137 purple_ciphers_register_cipher("sha256", purple_sha256_cipher_get_ops()); | 337 purple_ciphers_register_cipher("sha256", purple_sha256_cipher_get_ops()); |
1138 purple_ciphers_register_cipher("md4", purple_md4_cipher_get_ops()); | 338 purple_ciphers_register_cipher("md4", purple_md4_cipher_get_ops()); |
1139 purple_ciphers_register_cipher("hmac", purple_hmac_cipher_get_ops()); | 339 purple_ciphers_register_cipher("hmac", purple_hmac_cipher_get_ops()); |
1140 purple_ciphers_register_cipher("des", &DESOps); | 340 purple_ciphers_register_cipher("des", purple_des_cipher_get_ops()); |
1141 purple_ciphers_register_cipher("des3", &DES3Ops); | 341 purple_ciphers_register_cipher("des3", purple_des3_cipher_get_ops()); |
1142 purple_ciphers_register_cipher("rc4", purple_rc4_cipher_get_ops()); | 342 purple_ciphers_register_cipher("rc4", purple_rc4_cipher_get_ops()); |
1143 } | 343 } |
1144 | 344 |
1145 void | 345 void |
1146 purple_ciphers_uninit() { | 346 purple_ciphers_uninit() { |