libpurple/ciphers/descipher.c

changeset 38413
e35c6b6ca094
parent 38412
e25c73450414
child 38414
3892b306732f
equal deleted inserted replaced
38412:e25c73450414 38413:e35c6b6ca094
1 /*
2 * Original des taken from gpg
3 *
4 * des.c - DES encryption/decryption Algorithm
5 * Copyright (C) 1998 Free Software Foundation, Inc.
6 *
7 * Please see below for more legal information!
8 *
9 * According to the definition of DES in FIPS PUB 46-2 from December 1993.
10 * For a description of triple encryption, see:
11 * Bruce Schneier: Applied Cryptography. Second Edition.
12 * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff.
13 *
14 * Purple is the legal property of its developers, whose names are too numerous
15 * to list here. Please refer to the COPYRIGHT file distributed with this
16 * source distribution.
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
31 */
32 #include "internal.h"
33 #include "glibcompat.h"
34
35 #include "descipher.h"
36 #include "enums.h"
37
38 #include <string.h>
39
40 /******************************************************************************
41 * Structs
42 *****************************************************************************/
43 #define PURPLE_DES_CIPHER_GET_PRIVATE(obj) \
44 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherPrivate))
45
46 typedef struct {
47 guint32 encrypt_subkeys[32];
48 guint32 decrypt_subkeys[32];
49 } PurpleDESCipherPrivate;
50
51 /******************************************************************************
52 * Enums
53 *****************************************************************************/
54 enum {
55 PROP_NONE,
56 PROP_KEY,
57 PROP_LAST,
58 };
59
60 /******************************************************************************
61 * Globals
62 *****************************************************************************/
63 static GObjectClass *parent_class = NULL;
64 static GParamSpec *properties[PROP_LAST];
65
66 /*
67 * The s-box values are permuted according to the 'primitive function P'
68 */
69 static guint32 sbox1[64] = {
70 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202,
71 0x00000002, 0x00008000, 0x00000200, 0x00808200, 0x00808202, 0x00000200,
72 0x00800202, 0x00808002, 0x00800000, 0x00000002, 0x00000202, 0x00800200,
73 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
74 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202,
75 0x00008202, 0x00800000, 0x00008000, 0x00808202, 0x00000002, 0x00808000,
76 0x00808200, 0x00800000, 0x00800000, 0x00000200, 0x00808002, 0x00008000,
77 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
78 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202,
79 0x00008202, 0x00808200, 0x00000202, 0x00800200, 0x00800200, 0x00000000,
80 0x00008002, 0x00008200, 0x00000000, 0x00808002
81 };
82
83 static guint32 sbox2[64] = {
84 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010,
85 0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000,
86 0x40004000, 0x00080000, 0x00000010, 0x40080010, 0x00084000, 0x00080010,
87 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
88 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000,
89 0x40080000, 0x00004010, 0x00000000, 0x00084010, 0x40080010, 0x00080000,
90 0x40004010, 0x40080000, 0x40084000, 0x00004000, 0x40080000, 0x40004000,
91 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
92 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010,
93 0x40000010, 0x00080010, 0x00084000, 0x00000000, 0x40004000, 0x00004010,
94 0x40000000, 0x40080010, 0x40084010, 0x00084000
95 };
96
97 static guint32 sbox3[64] = {
98 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000,
99 0x00010104, 0x04000100, 0x00010004, 0x04000004, 0x04000004, 0x00010000,
100 0x04010104, 0x00010004, 0x04010000, 0x00000104, 0x04000000, 0x00000004,
101 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
102 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104,
103 0x00000100, 0x04000000, 0x04010100, 0x04000000, 0x00010004, 0x00000104,
104 0x00010000, 0x04010100, 0x04000100, 0x00000000, 0x00000100, 0x00010004,
105 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
106 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104,
107 0x00010100, 0x04000004, 0x04010000, 0x04000104, 0x00000104, 0x04010000,
108 0x00010104, 0x00000004, 0x04010004, 0x00010100
109 };
110
111 static guint32 sbox4[64] = {
112 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040,
113 0x80400000, 0x80001000, 0x00000000, 0x00401000, 0x00401000, 0x80401040,
114 0x80000040, 0x00000000, 0x00400040, 0x80400000, 0x80000000, 0x00001000,
115 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
116 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040,
117 0x80401040, 0x80000040, 0x00400040, 0x80400000, 0x00401000, 0x80401040,
118 0x80000040, 0x00000000, 0x00000000, 0x00401000, 0x00001040, 0x00400040,
119 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
120 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000,
121 0x00401040, 0x80400040, 0x80001000, 0x00001040, 0x00400000, 0x80401000,
122 0x00000040, 0x00400000, 0x00001000, 0x00401040
123 };
124
125 static guint32 sbox5[64] = {
126 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080,
127 0x20000000, 0x01040000, 0x20040080, 0x00040000, 0x01000080, 0x20040080,
128 0x21000080, 0x21040000, 0x00040080, 0x20000000, 0x01000000, 0x20040000,
129 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
130 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000,
131 0x21000000, 0x00040080, 0x00040000, 0x21000080, 0x00000080, 0x01000000,
132 0x20000000, 0x01040000, 0x21000080, 0x20040080, 0x01000080, 0x20000000,
133 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
134 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000,
135 0x20040000, 0x21000000, 0x00040080, 0x01000080, 0x20000080, 0x00040000,
136 0x00000000, 0x20040000, 0x01040080, 0x20000080
137 };
138
139 static guint32 sbox6[64] = {
140 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008,
141 0x10202008, 0x00200000, 0x10002000, 0x00202008, 0x00200000, 0x10000008,
142 0x00200008, 0x10002000, 0x10000000, 0x00002008, 0x00000000, 0x00200008,
143 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
144 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000,
145 0x10202000, 0x10000000, 0x10002000, 0x00000008, 0x10200008, 0x00202000,
146 0x10202008, 0x00200000, 0x00002008, 0x10000008, 0x00200000, 0x10002000,
147 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
148 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000,
149 0x10200000, 0x00202008, 0x00002000, 0x00200008, 0x10002008, 0x00000000,
150 0x10202000, 0x10000000, 0x00200008, 0x10002008
151 };
152
153 static guint32 sbox7[64] = {
154 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401,
155 0x00100401, 0x02100400, 0x02100401, 0x00100000, 0x00000000, 0x02000001,
156 0x00000001, 0x02000000, 0x02100001, 0x00000401, 0x02000400, 0x00100401,
157 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
158 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001,
159 0x02000000, 0x00100400, 0x02000000, 0x00100400, 0x00100000, 0x02000401,
160 0x02000401, 0x02100001, 0x02100001, 0x00000001, 0x00100001, 0x02000000,
161 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
162 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000,
163 0x00000001, 0x02100401, 0x00000000, 0x00100401, 0x02100000, 0x00000400,
164 0x02000001, 0x02000400, 0x00000400, 0x00100001
165 };
166
167 static guint32 sbox8[64] = {
168 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820,
169 0x00000020, 0x08000000, 0x00020020, 0x08020000, 0x08020820, 0x00020800,
170 0x08020800, 0x00020820, 0x00000800, 0x00000020, 0x08020000, 0x08000020,
171 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
172 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800,
173 0x00020820, 0x00020000, 0x00020820, 0x00020000, 0x08020800, 0x00000800,
174 0x00000020, 0x08020020, 0x00000800, 0x00020820, 0x08000800, 0x00000020,
175 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
176 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800,
177 0x08000820, 0x00000000, 0x08020820, 0x00020800, 0x00020800, 0x00000820,
178 0x00000820, 0x00020020, 0x08000000, 0x08020800
179 };
180
181 /*
182 * These two tables are part of the 'permuted choice 1' function.
183 * In this implementation several speed improvements are done.
184 */
185 static guint32 leftkey_swap[16] = {
186 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001,
187 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101,
188 0x01010000, 0x01010001, 0x01010100, 0x01010101
189 };
190
191 static guint32 rightkey_swap[16] = {
192 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100,
193 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001,
194 0x00000101, 0x01000101, 0x00010101, 0x01010101,
195 };
196
197 /*
198 * Numbers of left shifts per round for encryption subkey schedule
199 * To calculate the decryption key scheduling we just reverse the
200 * ordering of the subkeys so we can omit the table for decryption
201 * subkey schedule.
202 */
203 static guint8 encrypt_rotate_tab[16] = {
204 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
205 };
206
207
208 /******************************************************************************
209 * Helpers
210 *****************************************************************************/
211 /*
212 * Macro to swap bits across two words
213 */
214 #define DO_PERMUTATION(a, temp, b, offset, mask) \
215 temp = ((a>>offset) ^ b) & mask; \
216 b ^= temp; \
217 a ^= temp<<offset;
218
219 /*
220 * This performs the 'initial permutation' for the data to be encrypted or
221 * decrypted
222 */
223 #define INITIAL_PERMUTATION(left, temp, right) \
224 DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \
225 DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \
226 DO_PERMUTATION(right, temp, left, 2, 0x33333333) \
227 DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \
228 DO_PERMUTATION(left, temp, right, 1, 0x55555555)
229
230 /*
231 * The 'inverse initial permutation'
232 */
233 #define FINAL_PERMUTATION(left, temp, right) \
234 DO_PERMUTATION(left, temp, right, 1, 0x55555555) \
235 DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \
236 DO_PERMUTATION(right, temp, left, 2, 0x33333333) \
237 DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \
238 DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)
239
240 /*
241 * A full DES round including 'expansion function', 'sbox substitution'
242 * and 'primitive function P' but without swapping the left and right word.
243 */
244 #define DES_ROUND(from, to, work, subkey) \
245 work = ((from<<1) | (from>>31)) ^ *subkey++; \
246 to ^= sbox8[ work & 0x3f ]; \
247 to ^= sbox6[ (work>>8) & 0x3f ]; \
248 to ^= sbox4[ (work>>16) & 0x3f ]; \
249 to ^= sbox2[ (work>>24) & 0x3f ]; \
250 work = ((from>>3) | (from<<29)) ^ *subkey++; \
251 to ^= sbox7[ work & 0x3f ]; \
252 to ^= sbox5[ (work>>8) & 0x3f ]; \
253 to ^= sbox3[ (work>>16) & 0x3f ]; \
254 to ^= sbox1[ (work>>24) & 0x3f ];
255
256
257 /*
258 * Macros to convert 8 bytes from/to 32bit words
259 */
260 #define READ_64BIT_DATA(data, left, right) \
261 left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \
262 right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
263
264 #define WRITE_64BIT_DATA(data, left, right) \
265 data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \
266 data[2] = (left >> 8) &0xff; data[3] = left &0xff; \
267 data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \
268 data[6] = (right >> 8) &0xff; data[7] = right &0xff;
269
270 /******************************************************************************
271 * Cipher Stuff
272 *****************************************************************************/
273 /*
274 * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for
275 * 16 encryption rounds.
276 * To calculate subkeys for decryption the caller
277 * have to reorder the generated subkeys.
278 *
279 * rawkey: 8 Bytes of key data
280 * subkey: Array of at least 32 guint32s. Will be filled
281 * with calculated subkeys.
282 *
283 */
284 static void
285 purple_des_cipher_key_schedule(const guint8 * rawkey, guint32 * subkey) {
286 guint32 left, right, work;
287 int round;
288
289 READ_64BIT_DATA (rawkey, left, right)
290
291 DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f)
292 DO_PERMUTATION (right, work, left, 0, 0x10101010)
293
294 left = (leftkey_swap[(left >> 0) & 0xf] << 3)
295 | (leftkey_swap[(left >> 8) & 0xf] << 2)
296 | (leftkey_swap[(left >> 16) & 0xf] << 1)
297 | (leftkey_swap[(left >> 24) & 0xf] )
298 | (leftkey_swap[(left >> 5) & 0xf] << 7)
299 | (leftkey_swap[(left >> 13) & 0xf] << 6)
300 | (leftkey_swap[(left >> 21) & 0xf] << 5)
301 | (leftkey_swap[(left >> 29) & 0xf] << 4);
302
303 left &= 0x0fffffff;
304
305 right = (rightkey_swap[(right >> 1) & 0xf] << 3)
306 | (rightkey_swap[(right >> 9) & 0xf] << 2)
307 | (rightkey_swap[(right >> 17) & 0xf] << 1)
308 | (rightkey_swap[(right >> 25) & 0xf] )
309 | (rightkey_swap[(right >> 4) & 0xf] << 7)
310 | (rightkey_swap[(right >> 12) & 0xf] << 6)
311 | (rightkey_swap[(right >> 20) & 0xf] << 5)
312 | (rightkey_swap[(right >> 28) & 0xf] << 4);
313
314 right &= 0x0fffffff;
315
316 for (round = 0; round < 16; ++round) {
317 left = ((left << encrypt_rotate_tab[round]) |
318 (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
319 right = ((right << encrypt_rotate_tab[round]) |
320 (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
321
322 *subkey++ = ((left << 4) & 0x24000000)
323 | ((left << 28) & 0x10000000)
324 | ((left << 14) & 0x08000000)
325 | ((left << 18) & 0x02080000)
326 | ((left << 6) & 0x01000000)
327 | ((left << 9) & 0x00200000)
328 | ((left >> 1) & 0x00100000)
329 | ((left << 10) & 0x00040000)
330 | ((left << 2) & 0x00020000)
331 | ((left >> 10) & 0x00010000)
332 | ((right >> 13) & 0x00002000)
333 | ((right >> 4) & 0x00001000)
334 | ((right << 6) & 0x00000800)
335 | ((right >> 1) & 0x00000400)
336 | ((right >> 14) & 0x00000200)
337 | (right & 0x00000100)
338 | ((right >> 5) & 0x00000020)
339 | ((right >> 10) & 0x00000010)
340 | ((right >> 3) & 0x00000008)
341 | ((right >> 18) & 0x00000004)
342 | ((right >> 26) & 0x00000002)
343 | ((right >> 24) & 0x00000001);
344
345 *subkey++ = ((left << 15) & 0x20000000)
346 | ((left << 17) & 0x10000000)
347 | ((left << 10) & 0x08000000)
348 | ((left << 22) & 0x04000000)
349 | ((left >> 2) & 0x02000000)
350 | ((left << 1) & 0x01000000)
351 | ((left << 16) & 0x00200000)
352 | ((left << 11) & 0x00100000)
353 | ((left << 3) & 0x00080000)
354 | ((left >> 6) & 0x00040000)
355 | ((left << 15) & 0x00020000)
356 | ((left >> 4) & 0x00010000)
357 | ((right >> 2) & 0x00002000)
358 | ((right << 8) & 0x00001000)
359 | ((right >> 14) & 0x00000808)
360 | ((right >> 9) & 0x00000400)
361 | ((right) & 0x00000200)
362 | ((right << 7) & 0x00000100)
363 | ((right >> 7) & 0x00000020)
364 | ((right >> 3) & 0x00000011)
365 | ((right << 2) & 0x00000004)
366 | ((right >> 21) & 0x00000002);
367 }
368 }
369
370 /*
371 * Fill a DES context with subkeys calculated from a 64bit key.
372 * Does not check parity bits, but simply ignore them.
373 * Does not check for weak keys.
374 */
375 static void
376 purple_des_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) {
377 PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher);
378 PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher);
379 int i;
380
381 g_return_if_fail(len == 8);
382
383 purple_des_cipher_key_schedule(key, priv->encrypt_subkeys);
384
385 for(i = 0; i < 32; i += 2) {
386 priv->decrypt_subkeys[i] = priv->encrypt_subkeys[30 - i];
387 priv->decrypt_subkeys[i + 1] = priv->encrypt_subkeys[31 - i];
388 }
389
390 g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_KEY]);
391 }
392
393 static size_t
394 purple_des_cipher_get_key_size(PurpleCipher *cipher)
395 {
396 return 8;
397 }
398
399 /*
400 * Electronic Codebook Mode DES encryption/decryption of data according to
401 * 'mode'.
402 */
403 int
404 purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to,
405 int mode)
406 {
407 guint32 left, right, work;
408 guint32 *keys;
409 PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher);
410
411 keys = mode ? priv->decrypt_subkeys :
412 priv->encrypt_subkeys;
413
414 READ_64BIT_DATA (from, left, right)
415 INITIAL_PERMUTATION (left, work, right)
416
417 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
418 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
419 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
420 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
421 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
422 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
423 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
424 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
425
426 FINAL_PERMUTATION (right, work, left)
427 WRITE_64BIT_DATA (to, right, left)
428
429 return 0;
430 }
431
432 static ssize_t
433 purple_des_cipher_encrypt(PurpleCipher *cipher, const guchar input[],
434 size_t in_len, guchar output[], size_t out_size)
435 {
436 PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher);
437
438 gsize offset = 0;
439 int i = 0;
440 gsize tmp;
441 guint8 buf[8] = {0,0,0,0,0,0,0,0};
442 gsize out_len;
443
444 g_return_val_if_fail(out_size >= in_len, -1);
445
446 while(offset + 8 <= in_len) {
447 purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 0);
448 offset += 8;
449 }
450
451 out_len = in_len;
452
453 if(offset<in_len) {
454 g_return_val_if_fail(in_len >= offset, -1);
455 out_len += in_len - offset;
456 g_return_val_if_fail(out_size >= out_len, -1);
457 tmp = offset;
458 while(tmp<in_len) {
459 buf[i++] = input[tmp];
460 tmp++;
461 }
462
463 purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 0);
464 }
465
466 return out_len;
467 }
468
469 static ssize_t
470 purple_des_cipher_decrypt(PurpleCipher *cipher, const guchar input[],
471 size_t in_len, guchar output[], size_t out_size)
472 {
473 PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher);
474
475 gsize offset = 0;
476 int i = 0;
477 gsize tmp;
478 guint8 buf[8] = {0,0,0,0,0,0,0,0};
479 gsize out_len;
480
481 g_return_val_if_fail(out_size >= in_len, -1);
482
483 while(offset + 8 <= in_len) {
484 purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 1);
485 offset += 8;
486 }
487
488 out_len = in_len;
489 if(offset<in_len) {
490 g_return_val_if_fail(in_len >= offset, -1);
491 out_len += in_len - offset;
492 g_return_val_if_fail(out_size >= out_len, -1);
493 tmp = offset;
494 while(tmp<in_len) {
495 buf[i++] = input[tmp];
496 tmp++;
497 }
498
499 purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 1);
500 }
501
502 return out_len;
503 }
504
505 /******************************************************************************
506 * Object Stuff
507 *****************************************************************************/
508 static void
509 purple_des_cipher_set_property(GObject *obj, guint param_id,
510 const GValue *value, GParamSpec *pspec)
511 {
512 PurpleCipher *cipher = PURPLE_CIPHER(obj);
513
514 switch(param_id) {
515 case PROP_KEY:
516 purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value),
517 purple_des_cipher_get_key_size(cipher));
518 break;
519 default:
520 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
521 break;
522 }
523 }
524
525 static void
526 purple_des_cipher_class_init(PurpleDESCipherClass *klass)
527 {
528 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
529 PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass);
530
531 parent_class = g_type_class_peek_parent(klass);
532
533 obj_class->set_property = purple_des_cipher_set_property;
534
535 cipher_class->encrypt = purple_des_cipher_encrypt;
536 cipher_class->decrypt = purple_des_cipher_decrypt;
537 cipher_class->set_key = purple_des_cipher_set_key;
538 cipher_class->get_key_size = purple_des_cipher_get_key_size;
539
540 g_type_class_add_private(klass, sizeof(PurpleDESCipherPrivate));
541
542 properties[PROP_KEY] = g_param_spec_string("key", "key", "key", NULL,
543 G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
544
545 g_object_class_install_properties(obj_class, PROP_LAST, properties);
546 }
547
548 /******************************************************************************
549 * API
550 *****************************************************************************/
551 GType
552 purple_des_cipher_get_type(void) {
553 static GType type = 0;
554
555 if(type == 0) {
556 static const GTypeInfo info = {
557 .class_size = sizeof(PurpleDESCipherClass),
558 .class_init = (GClassInitFunc)purple_des_cipher_class_init,
559 .instance_size = sizeof(PurpleDESCipher),
560 .instance_init = (GInstanceInitFunc)purple_cipher_reset,
561 };
562
563 type = g_type_register_static(PURPLE_TYPE_CIPHER,
564 "PurpleDESCipher",
565 &info, 0);
566 }
567
568 return type;
569 }
570
571 /**
572 * purple_des_cipher_new:
573 *
574 * Creates a new #PurpleCipher instance which implements the DES block cipher.
575 *
576 * Return Value: The new DES implementation of #PurpleCipher.
577 */
578 PurpleCipher *
579 purple_des_cipher_new(void) {
580 return g_object_new(PURPLE_TYPE_DES_CIPHER, NULL);
581 }

mercurial