Coverage Report

Created: 2026-02-14 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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