/src/pidgin/libpurple/ciphers/des.c
Line | Count | Source |
1 | | /* |
2 | | * purple |
3 | | * |
4 | | * Purple is the legal property of its developers, whose names are too numerous |
5 | | * to list here. Please refer to the COPYRIGHT file distributed with this |
6 | | * source distribution. |
7 | | * |
8 | | * Original des taken from gpg |
9 | | * |
10 | | * des.c - DES and Triple-DES encryption/decryption Algorithm |
11 | | * Copyright (C) 1998 Free Software Foundation, Inc. |
12 | | * |
13 | | * Please see below for more legal information! |
14 | | * |
15 | | * According to the definition of DES in FIPS PUB 46-2 from December 1993. |
16 | | * For a description of triple encryption, see: |
17 | | * Bruce Schneier: Applied Cryptography. Second Edition. |
18 | | * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. |
19 | | * |
20 | | * This file is part of GnuPG. |
21 | | * |
22 | | * This program is free software; you can redistribute it and/or modify |
23 | | * it under the terms of the GNU General Public License as published by |
24 | | * the Free Software Foundation; either version 2 of the License, or |
25 | | * (at your option) any later version. |
26 | | * |
27 | | * This program is distributed in the hope that it will be useful, |
28 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
29 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
30 | | * GNU General Public License for more details. |
31 | | * |
32 | | * You should have received a copy of the GNU General Public License |
33 | | * along with this program; if not, write to the Free Software |
34 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
35 | | */ |
36 | | #include <cipher.h> |
37 | | |
38 | | /****************************************************************************** |
39 | | * DES |
40 | | *****************************************************************************/ |
41 | | typedef struct _des_ctx |
42 | | { |
43 | | guint32 encrypt_subkeys[32]; |
44 | | guint32 decrypt_subkeys[32]; |
45 | | } des_ctx[1]; |
46 | | |
47 | | /* |
48 | | * The s-box values are permuted according to the 'primitive function P' |
49 | | */ |
50 | | static const guint32 sbox1[64] = |
51 | | { |
52 | | 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, |
53 | | 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, |
54 | | 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, |
55 | | 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, |
56 | | 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, |
57 | | 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, |
58 | | 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, |
59 | | 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002 |
60 | | }; |
61 | | |
62 | | static const guint32 sbox2[64] = |
63 | | { |
64 | | 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, |
65 | | 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, |
66 | | 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, |
67 | | 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, |
68 | | 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, |
69 | | 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, |
70 | | 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, |
71 | | 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000 |
72 | | }; |
73 | | |
74 | | static const guint32 sbox3[64] = |
75 | | { |
76 | | 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, |
77 | | 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, |
78 | | 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, |
79 | | 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, |
80 | | 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, |
81 | | 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, |
82 | | 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, |
83 | | 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100 |
84 | | }; |
85 | | |
86 | | static const guint32 sbox4[64] = |
87 | | { |
88 | | 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, |
89 | | 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, |
90 | | 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, |
91 | | 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, |
92 | | 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, |
93 | | 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, |
94 | | 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, |
95 | | 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040 |
96 | | }; |
97 | | |
98 | | static const guint32 sbox5[64] = |
99 | | { |
100 | | 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, |
101 | | 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, |
102 | | 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, |
103 | | 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, |
104 | | 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, |
105 | | 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, |
106 | | 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, |
107 | | 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080 |
108 | | }; |
109 | | |
110 | | static const guint32 sbox6[64] = |
111 | | { |
112 | | 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, |
113 | | 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, |
114 | | 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, |
115 | | 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, |
116 | | 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, |
117 | | 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, |
118 | | 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, |
119 | | 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008 |
120 | | }; |
121 | | |
122 | | static const guint32 sbox7[64] = |
123 | | { |
124 | | 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, |
125 | | 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, |
126 | | 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, |
127 | | 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, |
128 | | 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, |
129 | | 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, |
130 | | 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, |
131 | | 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001 |
132 | | }; |
133 | | |
134 | | static const guint32 sbox8[64] = |
135 | | { |
136 | | 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, |
137 | | 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, |
138 | | 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, |
139 | | 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, |
140 | | 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, |
141 | | 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, |
142 | | 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, |
143 | | 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800 |
144 | | }; |
145 | | |
146 | | |
147 | | /* |
148 | | * * These two tables are part of the 'permuted choice 1' function. |
149 | | * * In this implementation several speed improvements are done. |
150 | | * */ |
151 | | static const guint32 leftkey_swap[16] = |
152 | | { |
153 | | 0x00000000, 0x00000001, 0x00000100, 0x00000101, |
154 | | 0x00010000, 0x00010001, 0x00010100, 0x00010101, |
155 | | 0x01000000, 0x01000001, 0x01000100, 0x01000101, |
156 | | 0x01010000, 0x01010001, 0x01010100, 0x01010101 |
157 | | }; |
158 | | |
159 | | static const guint32 rightkey_swap[16] = |
160 | | { |
161 | | 0x00000000, 0x01000000, 0x00010000, 0x01010000, |
162 | | 0x00000100, 0x01000100, 0x00010100, 0x01010100, |
163 | | 0x00000001, 0x01000001, 0x00010001, 0x01010001, |
164 | | 0x00000101, 0x01000101, 0x00010101, 0x01010101, |
165 | | }; |
166 | | |
167 | | |
168 | | /* |
169 | | * Numbers of left shifts per round for encryption subkey schedule |
170 | | * To calculate the decryption key scheduling we just reverse the |
171 | | * ordering of the subkeys so we can omit the table for decryption |
172 | | * subkey schedule. |
173 | | */ |
174 | | static const guint8 encrypt_rotate_tab[16] = |
175 | | { |
176 | | 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 |
177 | | }; |
178 | | |
179 | | /* |
180 | | * Macro to swap bits across two words |
181 | | **/ |
182 | | #define DO_PERMUTATION(a, temp, b, offset, mask) \ |
183 | 0 | temp = ((a>>offset) ^ b) & mask; \ |
184 | 0 | b ^= temp; \ |
185 | 0 | a ^= temp<<offset; |
186 | | |
187 | | |
188 | | /* |
189 | | * This performs the 'initial permutation' for the data to be encrypted or decrypted |
190 | | **/ |
191 | | #define INITIAL_PERMUTATION(left, temp, right) \ |
192 | 0 | DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ |
193 | 0 | DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ |
194 | 0 | DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ |
195 | 0 | DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ |
196 | 0 | DO_PERMUTATION(left, temp, right, 1, 0x55555555) |
197 | | |
198 | | |
199 | | /* |
200 | | * The 'inverse initial permutation' |
201 | | **/ |
202 | | #define FINAL_PERMUTATION(left, temp, right) \ |
203 | 0 | DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ |
204 | 0 | DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ |
205 | 0 | DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ |
206 | 0 | DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ |
207 | 0 | DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) |
208 | | |
209 | | |
210 | | /* |
211 | | * A full DES round including 'expansion function', 'sbox substitution' |
212 | | * and 'primitive function P' but without swapping the left and right word. |
213 | | **/ |
214 | | #define DES_ROUND(from, to, work, subkey) \ |
215 | 0 | work = ((from<<1) | (from>>31)) ^ *subkey++; \ |
216 | 0 | to ^= sbox8[ work & 0x3f ]; \ |
217 | 0 | to ^= sbox6[ (work>>8) & 0x3f ]; \ |
218 | 0 | to ^= sbox4[ (work>>16) & 0x3f ]; \ |
219 | 0 | to ^= sbox2[ (work>>24) & 0x3f ]; \ |
220 | 0 | work = ((from>>3) | (from<<29)) ^ *subkey++; \ |
221 | 0 | to ^= sbox7[ work & 0x3f ]; \ |
222 | 0 | to ^= sbox5[ (work>>8) & 0x3f ]; \ |
223 | 0 | to ^= sbox3[ (work>>16) & 0x3f ]; \ |
224 | 0 | to ^= sbox1[ (work>>24) & 0x3f ]; |
225 | | |
226 | | |
227 | | /* |
228 | | * Macros to convert 8 bytes from/to 32bit words |
229 | | **/ |
230 | | #define READ_64BIT_DATA(data, left, right) \ |
231 | 0 | left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ |
232 | 0 | right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; |
233 | | |
234 | | #define WRITE_64BIT_DATA(data, left, right) \ |
235 | 0 | data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ |
236 | 0 | data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ |
237 | 0 | data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ |
238 | 0 | data[6] = (right >> 8) &0xff; data[7] = right &0xff; |
239 | | |
240 | | |
241 | | /* |
242 | | * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for |
243 | | * 16 encryption rounds. |
244 | | * To calculate subkeys for decryption the caller |
245 | | * have to reorder the generated subkeys. |
246 | | * |
247 | | * rawkey: 8 Bytes of key data |
248 | | * subkey: Array of at least 32 guint32s. Will be filled |
249 | | * with calculated subkeys. |
250 | | * |
251 | | **/ |
252 | | static void |
253 | | des_key_schedule (const guint8 * rawkey, guint32 * subkey) |
254 | 0 | { |
255 | 0 | guint32 left, right, work; |
256 | 0 | int round; |
257 | |
|
258 | 0 | READ_64BIT_DATA (rawkey, left, right) |
259 | |
|
260 | 0 | DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) |
261 | 0 | DO_PERMUTATION (right, work, left, 0, 0x10101010) |
262 | |
|
263 | 0 | left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) |
264 | 0 | | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) |
265 | 0 | | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) |
266 | 0 | | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4); |
267 | |
|
268 | 0 | left &= 0x0fffffff; |
269 | |
|
270 | 0 | right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) |
271 | 0 | | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) |
272 | 0 | | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) |
273 | 0 | | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4); |
274 | |
|
275 | 0 | right &= 0x0fffffff; |
276 | |
|
277 | 0 | for (round = 0; round < 16; ++round) |
278 | 0 | { |
279 | 0 | left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; |
280 | 0 | right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; |
281 | |
|
282 | 0 | *subkey++ = ((left << 4) & 0x24000000) |
283 | 0 | | ((left << 28) & 0x10000000) |
284 | 0 | | ((left << 14) & 0x08000000) |
285 | 0 | | ((left << 18) & 0x02080000) |
286 | 0 | | ((left << 6) & 0x01000000) |
287 | 0 | | ((left << 9) & 0x00200000) |
288 | 0 | | ((left >> 1) & 0x00100000) |
289 | 0 | | ((left << 10) & 0x00040000) |
290 | 0 | | ((left << 2) & 0x00020000) |
291 | 0 | | ((left >> 10) & 0x00010000) |
292 | 0 | | ((right >> 13) & 0x00002000) |
293 | 0 | | ((right >> 4) & 0x00001000) |
294 | 0 | | ((right << 6) & 0x00000800) |
295 | 0 | | ((right >> 1) & 0x00000400) |
296 | 0 | | ((right >> 14) & 0x00000200) |
297 | 0 | | (right & 0x00000100) |
298 | 0 | | ((right >> 5) & 0x00000020) |
299 | 0 | | ((right >> 10) & 0x00000010) |
300 | 0 | | ((right >> 3) & 0x00000008) |
301 | 0 | | ((right >> 18) & 0x00000004) |
302 | 0 | | ((right >> 26) & 0x00000002) |
303 | 0 | | ((right >> 24) & 0x00000001); |
304 | |
|
305 | 0 | *subkey++ = ((left << 15) & 0x20000000) |
306 | 0 | | ((left << 17) & 0x10000000) |
307 | 0 | | ((left << 10) & 0x08000000) |
308 | 0 | | ((left << 22) & 0x04000000) |
309 | 0 | | ((left >> 2) & 0x02000000) |
310 | 0 | | ((left << 1) & 0x01000000) |
311 | 0 | | ((left << 16) & 0x00200000) |
312 | 0 | | ((left << 11) & 0x00100000) |
313 | 0 | | ((left << 3) & 0x00080000) |
314 | 0 | | ((left >> 6) & 0x00040000) |
315 | 0 | | ((left << 15) & 0x00020000) |
316 | 0 | | ((left >> 4) & 0x00010000) |
317 | 0 | | ((right >> 2) & 0x00002000) |
318 | 0 | | ((right << 8) & 0x00001000) |
319 | 0 | | ((right >> 14) & 0x00000808) |
320 | 0 | | ((right >> 9) & 0x00000400) |
321 | 0 | | ((right) & 0x00000200) |
322 | 0 | | ((right << 7) & 0x00000100) |
323 | 0 | | ((right >> 7) & 0x00000020) |
324 | 0 | | ((right >> 3) & 0x00000011) |
325 | 0 | | ((right << 2) & 0x00000004) |
326 | 0 | | ((right >> 21) & 0x00000002); |
327 | 0 | } |
328 | 0 | } |
329 | | |
330 | | |
331 | | /* |
332 | | * Fill a DES context with subkeys calculated from a 64bit key. |
333 | | * Does not check parity bits, but simply ignore them. |
334 | | * Does not check for weak keys. |
335 | | **/ |
336 | | static void |
337 | | des_set_key (PurpleCipherContext *context, const guchar * key) |
338 | 0 | { |
339 | 0 | struct _des_ctx *ctx = purple_cipher_context_get_data(context); |
340 | 0 | int i; |
341 | |
|
342 | 0 | des_key_schedule (key, ctx->encrypt_subkeys); |
343 | |
|
344 | 0 | for(i=0; i<32; i+=2) |
345 | 0 | { |
346 | 0 | ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; |
347 | 0 | ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; |
348 | 0 | } |
349 | 0 | } |
350 | | |
351 | | |
352 | | /* |
353 | | * Electronic Codebook Mode DES encryption/decryption of data according |
354 | | * to 'mode'. |
355 | | **/ |
356 | | static int |
357 | | des_ecb_crypt (struct _des_ctx *ctx, const guint8 * from, guint8 * to, int mode) |
358 | 0 | { |
359 | 0 | guint32 left, right, work; |
360 | 0 | guint32 *keys; |
361 | |
|
362 | 0 | keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; |
363 | |
|
364 | 0 | READ_64BIT_DATA (from, left, right) |
365 | 0 | INITIAL_PERMUTATION (left, work, right) |
366 | |
|
367 | 0 | DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
368 | 0 | DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
369 | 0 | DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
370 | 0 | DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
371 | 0 | DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
372 | 0 | DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
373 | 0 | DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
374 | 0 | DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
375 | |
|
376 | 0 | FINAL_PERMUTATION (right, work, left) |
377 | 0 | WRITE_64BIT_DATA (to, right, left) |
378 | |
|
379 | 0 | return 0; |
380 | 0 | } |
381 | | |
382 | | static gint |
383 | | des_encrypt(PurpleCipherContext *context, const guchar data[], |
384 | | size_t len, guchar output[], size_t *outlen) |
385 | 0 | { |
386 | 0 | int offset = 0; |
387 | 0 | int i = 0; |
388 | 0 | int tmp; |
389 | 0 | guint8 buf[8] = {0,0,0,0,0,0,0,0}; |
390 | 0 | while(offset+8<=len) { |
391 | 0 | des_ecb_crypt(purple_cipher_context_get_data(context), |
392 | 0 | data+offset, |
393 | 0 | output+offset, |
394 | 0 | 0); |
395 | 0 | offset+=8; |
396 | 0 | } |
397 | 0 | *outlen = len; |
398 | 0 | if(offset<len) { |
399 | 0 | *outlen += len - offset; |
400 | 0 | tmp = offset; |
401 | 0 | while(tmp<len) { |
402 | 0 | buf[i++] = data[tmp]; |
403 | 0 | tmp++; |
404 | 0 | } |
405 | 0 | des_ecb_crypt(purple_cipher_context_get_data(context), |
406 | 0 | buf, |
407 | 0 | output+offset, |
408 | 0 | 0); |
409 | 0 | } |
410 | 0 | return 0; |
411 | 0 | } |
412 | | |
413 | | static gint |
414 | | des_decrypt(PurpleCipherContext *context, const guchar data[], |
415 | | size_t len, guchar output[], size_t *outlen) |
416 | 0 | { |
417 | 0 | int offset = 0; |
418 | 0 | int i = 0; |
419 | 0 | int tmp; |
420 | 0 | guint8 buf[8] = {0,0,0,0,0,0,0,0}; |
421 | 0 | while(offset+8<=len) { |
422 | 0 | des_ecb_crypt(purple_cipher_context_get_data(context), |
423 | 0 | data+offset, |
424 | 0 | output+offset, |
425 | 0 | 1); |
426 | 0 | offset+=8; |
427 | 0 | } |
428 | 0 | *outlen = len; |
429 | 0 | if(offset<len) { |
430 | 0 | *outlen += len - offset; |
431 | 0 | tmp = offset; |
432 | 0 | while(tmp<len) { |
433 | 0 | buf[i++] = data[tmp]; |
434 | 0 | tmp++; |
435 | 0 | } |
436 | 0 | des_ecb_crypt(purple_cipher_context_get_data(context), |
437 | 0 | buf, |
438 | 0 | output+offset, |
439 | 0 | 1); |
440 | 0 | } |
441 | 0 | return 0; |
442 | 0 | } |
443 | | |
444 | | static void |
445 | 0 | des_init(PurpleCipherContext *context, gpointer extra) { |
446 | 0 | struct _des_ctx *mctx; |
447 | 0 | mctx = g_new0(struct _des_ctx, 1); |
448 | 0 | purple_cipher_context_set_data(context, mctx); |
449 | 0 | } |
450 | | |
451 | | static void |
452 | 0 | des_uninit(PurpleCipherContext *context) { |
453 | 0 | struct _des_ctx *des_context; |
454 | |
|
455 | 0 | des_context = purple_cipher_context_get_data(context); |
456 | 0 | memset(des_context, 0, sizeof(*des_context)); |
457 | |
|
458 | 0 | g_free(des_context); |
459 | 0 | des_context = NULL; |
460 | 0 | } |
461 | | |
462 | | static PurpleCipherOps DESOps = { |
463 | | NULL, /* Set option */ |
464 | | NULL, /* Get option */ |
465 | | des_init, /* init */ |
466 | | NULL, /* reset */ |
467 | | des_uninit, /* uninit */ |
468 | | NULL, /* set iv */ |
469 | | NULL, /* append */ |
470 | | NULL, /* digest */ |
471 | | des_encrypt, /* encrypt */ |
472 | | des_decrypt, /* decrypt */ |
473 | | NULL, /* set salt */ |
474 | | NULL, /* get salt size */ |
475 | | des_set_key, /* set key */ |
476 | | NULL, /* get key size */ |
477 | | NULL, /* set batch mode */ |
478 | | NULL, /* get batch mode */ |
479 | | NULL, /* get block size */ |
480 | | NULL /* set key with len */ |
481 | | }; |
482 | | |
483 | | /****************************************************************************** |
484 | | * Triple-DES |
485 | | *****************************************************************************/ |
486 | | |
487 | | typedef struct _des3_ctx |
488 | | { |
489 | | PurpleCipherBatchMode mode; |
490 | | guchar iv[8]; |
491 | | /* First key for encryption */ |
492 | | struct _des_ctx key1; |
493 | | /* Second key for decryption */ |
494 | | struct _des_ctx key2; |
495 | | /* Third key for encryption */ |
496 | | struct _des_ctx key3; |
497 | | } des3_ctx[1]; |
498 | | |
499 | | /* |
500 | | * Fill a DES3 context with subkeys calculated from 3 64bit key. |
501 | | * Does not check parity bits, but simply ignore them. |
502 | | * Does not check for weak keys. |
503 | | **/ |
504 | | static void |
505 | | des3_set_key(PurpleCipherContext *context, const guchar * key) |
506 | 0 | { |
507 | 0 | struct _des3_ctx *ctx = purple_cipher_context_get_data(context); |
508 | 0 | int i; |
509 | |
|
510 | 0 | des_key_schedule (key + 0, ctx->key1.encrypt_subkeys); |
511 | 0 | des_key_schedule (key + 8, ctx->key2.encrypt_subkeys); |
512 | 0 | des_key_schedule (key + 16, ctx->key3.encrypt_subkeys); |
513 | |
|
514 | 0 | for (i = 0; i < 32; i += 2) |
515 | 0 | { |
516 | 0 | ctx->key1.decrypt_subkeys[i] = ctx->key1.encrypt_subkeys[30-i]; |
517 | 0 | ctx->key1.decrypt_subkeys[i+1] = ctx->key1.encrypt_subkeys[31-i]; |
518 | 0 | ctx->key2.decrypt_subkeys[i] = ctx->key2.encrypt_subkeys[30-i]; |
519 | 0 | ctx->key2.decrypt_subkeys[i+1] = ctx->key2.encrypt_subkeys[31-i]; |
520 | 0 | ctx->key3.decrypt_subkeys[i] = ctx->key3.encrypt_subkeys[30-i]; |
521 | 0 | ctx->key3.decrypt_subkeys[i+1] = ctx->key3.encrypt_subkeys[31-i]; |
522 | 0 | } |
523 | 0 | } |
524 | | |
525 | | static gint |
526 | | des3_ecb_encrypt(struct _des3_ctx *ctx, const guchar data[], |
527 | | size_t len, guchar output[], size_t *outlen) |
528 | 0 | { |
529 | 0 | int offset = 0; |
530 | 0 | int i = 0; |
531 | 0 | int tmp; |
532 | 0 | guint8 buf[8] = {0,0,0,0,0,0,0,0}; |
533 | 0 | while (offset + 8 <= len) { |
534 | 0 | des_ecb_crypt(&ctx->key1, |
535 | 0 | data+offset, |
536 | 0 | output+offset, |
537 | 0 | 0); |
538 | 0 | des_ecb_crypt(&ctx->key2, |
539 | 0 | output+offset, |
540 | 0 | buf, |
541 | 0 | 1); |
542 | 0 | des_ecb_crypt(&ctx->key3, |
543 | 0 | buf, |
544 | 0 | output+offset, |
545 | 0 | 0); |
546 | 0 | offset += 8; |
547 | 0 | } |
548 | 0 | *outlen = len; |
549 | 0 | if (offset < len) { |
550 | 0 | *outlen += len - offset; |
551 | 0 | tmp = offset; |
552 | 0 | memset(buf, 0, 8); |
553 | 0 | while (tmp < len) { |
554 | 0 | buf[i++] = data[tmp]; |
555 | 0 | tmp++; |
556 | 0 | } |
557 | 0 | des_ecb_crypt(&ctx->key1, |
558 | 0 | buf, |
559 | 0 | output+offset, |
560 | 0 | 0); |
561 | 0 | des_ecb_crypt(&ctx->key2, |
562 | 0 | output+offset, |
563 | 0 | buf, |
564 | 0 | 1); |
565 | 0 | des_ecb_crypt(&ctx->key3, |
566 | 0 | buf, |
567 | 0 | output+offset, |
568 | 0 | 0); |
569 | 0 | } |
570 | 0 | return 0; |
571 | 0 | } |
572 | | |
573 | | static gint |
574 | | des3_cbc_encrypt(struct _des3_ctx *ctx, const guchar data[], |
575 | | size_t len, guchar output[], size_t *outlen) |
576 | 0 | { |
577 | 0 | int offset = 0; |
578 | 0 | int i = 0; |
579 | 0 | int tmp; |
580 | 0 | guint8 buf[8]; |
581 | 0 | memcpy(buf, ctx->iv, 8); |
582 | 0 | while (offset + 8 <= len) { |
583 | 0 | for (i = 0; i < 8; i++) |
584 | 0 | buf[i] ^= data[offset + i]; |
585 | |
|
586 | 0 | des_ecb_crypt(&ctx->key1, |
587 | 0 | buf, |
588 | 0 | output+offset, |
589 | 0 | 0); |
590 | 0 | des_ecb_crypt(&ctx->key2, |
591 | 0 | output+offset, |
592 | 0 | buf, |
593 | 0 | 1); |
594 | 0 | des_ecb_crypt(&ctx->key3, |
595 | 0 | buf, |
596 | 0 | output+offset, |
597 | 0 | 0); |
598 | 0 | memcpy(buf, output+offset, 8); |
599 | 0 | offset += 8; |
600 | 0 | } |
601 | 0 | *outlen = len; |
602 | 0 | if (offset < len) { |
603 | 0 | *outlen += len - offset; |
604 | 0 | tmp = offset; |
605 | 0 | i = 0; |
606 | 0 | while (tmp < len) { |
607 | 0 | buf[i++] ^= data[tmp]; |
608 | 0 | tmp++; |
609 | 0 | } |
610 | 0 | des_ecb_crypt(&ctx->key1, |
611 | 0 | buf, |
612 | 0 | output+offset, |
613 | 0 | 0); |
614 | 0 | des_ecb_crypt(&ctx->key2, |
615 | 0 | output+offset, |
616 | 0 | buf, |
617 | 0 | 1); |
618 | 0 | des_ecb_crypt(&ctx->key3, |
619 | 0 | buf, |
620 | 0 | output+offset, |
621 | 0 | 0); |
622 | 0 | } |
623 | 0 | return 0; |
624 | 0 | } |
625 | | |
626 | | static gint |
627 | | des3_encrypt(PurpleCipherContext *context, const guchar data[], |
628 | | size_t len, guchar output[], size_t *outlen) |
629 | 0 | { |
630 | 0 | struct _des3_ctx *ctx = purple_cipher_context_get_data(context); |
631 | |
|
632 | 0 | if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { |
633 | 0 | return des3_ecb_encrypt(ctx, data, len, output, outlen); |
634 | 0 | } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { |
635 | 0 | return des3_cbc_encrypt(ctx, data, len, output, outlen); |
636 | 0 | } else { |
637 | 0 | g_return_val_if_reached(0); |
638 | 0 | } |
639 | | |
640 | 0 | return 0; |
641 | 0 | } |
642 | | |
643 | | static gint |
644 | | des3_ecb_decrypt(struct _des3_ctx *ctx, const guchar data[], |
645 | | size_t len, guchar output[], size_t *outlen) |
646 | 0 | { |
647 | 0 | int offset = 0; |
648 | 0 | int i = 0; |
649 | 0 | int tmp; |
650 | 0 | guint8 buf[8] = {0,0,0,0,0,0,0,0}; |
651 | 0 | while (offset + 8 <= len) { |
652 | | /* NOTE: Apply key in reverse */ |
653 | 0 | des_ecb_crypt(&ctx->key3, |
654 | 0 | data+offset, |
655 | 0 | output+offset, |
656 | 0 | 1); |
657 | 0 | des_ecb_crypt(&ctx->key2, |
658 | 0 | output+offset, |
659 | 0 | buf, |
660 | 0 | 0); |
661 | 0 | des_ecb_crypt(&ctx->key1, |
662 | 0 | buf, |
663 | 0 | output+offset, |
664 | 0 | 1); |
665 | 0 | offset+=8; |
666 | 0 | } |
667 | 0 | *outlen = len; |
668 | 0 | if (offset < len) { |
669 | 0 | *outlen += len - offset; |
670 | 0 | tmp = offset; |
671 | 0 | memset(buf, 0, 8); |
672 | 0 | while (tmp < len) { |
673 | 0 | buf[i++] = data[tmp]; |
674 | 0 | tmp++; |
675 | 0 | } |
676 | 0 | des_ecb_crypt(&ctx->key3, |
677 | 0 | buf, |
678 | 0 | output+offset, |
679 | 0 | 1); |
680 | 0 | des_ecb_crypt(&ctx->key2, |
681 | 0 | output+offset, |
682 | 0 | buf, |
683 | 0 | 0); |
684 | 0 | des_ecb_crypt(&ctx->key1, |
685 | 0 | buf, |
686 | 0 | output+offset, |
687 | 0 | 1); |
688 | 0 | } |
689 | 0 | return 0; |
690 | 0 | } |
691 | | |
692 | | static gint |
693 | | des3_cbc_decrypt(struct _des3_ctx *ctx, const guchar data[], |
694 | | size_t len, guchar output[], size_t *outlen) |
695 | 0 | { |
696 | 0 | int offset = 0; |
697 | 0 | int i = 0; |
698 | 0 | int tmp; |
699 | 0 | guint8 buf[8] = {0,0,0,0,0,0,0,0}; |
700 | 0 | guint8 link[8]; |
701 | 0 | memcpy(link, ctx->iv, 8); |
702 | 0 | while (offset + 8 <= len) { |
703 | 0 | des_ecb_crypt(&ctx->key3, |
704 | 0 | data+offset, |
705 | 0 | output+offset, |
706 | 0 | 1); |
707 | 0 | des_ecb_crypt(&ctx->key2, |
708 | 0 | output+offset, |
709 | 0 | buf, |
710 | 0 | 0); |
711 | 0 | des_ecb_crypt(&ctx->key1, |
712 | 0 | buf, |
713 | 0 | output+offset, |
714 | 0 | 1); |
715 | 0 | for (i = 0; i < 8; i++) |
716 | 0 | output[offset + i] ^= link[i]; |
717 | 0 | memcpy(link, data + offset, 8); |
718 | 0 | offset+=8; |
719 | 0 | } |
720 | 0 | *outlen = len; |
721 | 0 | if(offset<len) { |
722 | 0 | *outlen += len - offset; |
723 | 0 | tmp = offset; |
724 | 0 | memset(buf, 0, 8); |
725 | 0 | i = 0; |
726 | 0 | while(tmp<len) { |
727 | 0 | buf[i++] = data[tmp]; |
728 | 0 | tmp++; |
729 | 0 | } |
730 | 0 | des_ecb_crypt(&ctx->key3, |
731 | 0 | buf, |
732 | 0 | output+offset, |
733 | 0 | 1); |
734 | 0 | des_ecb_crypt(&ctx->key2, |
735 | 0 | output+offset, |
736 | 0 | buf, |
737 | 0 | 0); |
738 | 0 | des_ecb_crypt(&ctx->key1, |
739 | 0 | buf, |
740 | 0 | output+offset, |
741 | 0 | 1); |
742 | 0 | for (i = 0; i < 8; i++) |
743 | 0 | output[offset + i] ^= link[i]; |
744 | 0 | } |
745 | 0 | return 0; |
746 | 0 | } |
747 | | |
748 | | static gint |
749 | | des3_decrypt(PurpleCipherContext *context, const guchar data[], |
750 | | size_t len, guchar output[], size_t *outlen) |
751 | 0 | { |
752 | 0 | struct _des3_ctx *ctx = purple_cipher_context_get_data(context); |
753 | |
|
754 | 0 | if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { |
755 | 0 | return des3_ecb_decrypt(ctx, data, len, output, outlen); |
756 | 0 | } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { |
757 | 0 | return des3_cbc_decrypt(ctx, data, len, output, outlen); |
758 | 0 | } else { |
759 | 0 | g_return_val_if_reached(0); |
760 | 0 | } |
761 | | |
762 | 0 | return 0; |
763 | 0 | } |
764 | | |
765 | | static void |
766 | | des3_set_batch(PurpleCipherContext *context, PurpleCipherBatchMode mode) |
767 | 0 | { |
768 | 0 | struct _des3_ctx *ctx = purple_cipher_context_get_data(context); |
769 | |
|
770 | 0 | ctx->mode = mode; |
771 | 0 | } |
772 | | |
773 | | static PurpleCipherBatchMode |
774 | | des3_get_batch(PurpleCipherContext *context) |
775 | 0 | { |
776 | 0 | struct _des3_ctx *ctx = purple_cipher_context_get_data(context); |
777 | |
|
778 | 0 | return ctx->mode; |
779 | 0 | } |
780 | | |
781 | | static void |
782 | | des3_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) |
783 | 0 | { |
784 | 0 | struct _des3_ctx *ctx; |
785 | |
|
786 | 0 | g_return_if_fail(len == 8); |
787 | | |
788 | 0 | ctx = purple_cipher_context_get_data(context); |
789 | |
|
790 | 0 | memcpy(ctx->iv, iv, len); |
791 | 0 | } |
792 | | |
793 | | static void |
794 | | des3_init(PurpleCipherContext *context, gpointer extra) |
795 | 0 | { |
796 | 0 | struct _des3_ctx *mctx; |
797 | 0 | mctx = g_new0(struct _des3_ctx, 1); |
798 | 0 | purple_cipher_context_set_data(context, mctx); |
799 | 0 | } |
800 | | |
801 | | static void |
802 | | des3_uninit(PurpleCipherContext *context) |
803 | 0 | { |
804 | 0 | struct _des3_ctx *des3_context; |
805 | |
|
806 | 0 | des3_context = purple_cipher_context_get_data(context); |
807 | 0 | memset(des3_context, 0, sizeof(*des3_context)); |
808 | |
|
809 | 0 | g_free(des3_context); |
810 | 0 | des3_context = NULL; |
811 | 0 | } |
812 | | |
813 | | static PurpleCipherOps DES3Ops = { |
814 | | NULL, /* Set option */ |
815 | | NULL, /* Get option */ |
816 | | des3_init, /* init */ |
817 | | NULL, /* reset */ |
818 | | des3_uninit, /* uninit */ |
819 | | des3_set_iv, /* set iv */ |
820 | | NULL, /* append */ |
821 | | NULL, /* digest */ |
822 | | des3_encrypt, /* encrypt */ |
823 | | des3_decrypt, /* decrypt */ |
824 | | NULL, /* set salt */ |
825 | | NULL, /* get salt size */ |
826 | | des3_set_key, /* set key */ |
827 | | NULL, /* get key size */ |
828 | | des3_set_batch, /* set batch mode */ |
829 | | des3_get_batch, /* get batch mode */ |
830 | | NULL, /* get block size */ |
831 | | NULL /* set key with len */ |
832 | | }; |
833 | | |
834 | | /****************************************************************************** |
835 | | * Registration |
836 | | *****************************************************************************/ |
837 | | PurpleCipherOps * |
838 | 0 | purple_des_cipher_get_ops(void) { |
839 | 0 | return &DESOps; |
840 | 0 | } |
841 | | |
842 | | PurpleCipherOps * |
843 | 0 | purple_des3_cipher_get_ops(void) { |
844 | 0 | return &DES3Ops; |
845 | 0 | } |
846 | | |