2 * DES and 3DES-EDE ciphers
4 * Modifications to LibTomCrypt implementation:
5 * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Alternatively, this software may be distributed under the terms of BSD
14 * See README and COPYING for more details.
23 * This implementation is based on a DES implementation included in
24 * LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd
28 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
30 * LibTomCrypt is a library that provides various cryptographic
31 * algorithms in a highly modular and flexible manner.
33 * The library is free for all purposes without any express
36 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
40 DES code submitted by Dobes Vandermeer
44 ((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \
45 (((unsigned long) (x) & 0xFFFFFFFFUL) >> \
46 (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
48 (((((unsigned long) (x) & 0xFFFFFFFFUL) >> \
49 (unsigned long) ((y) & 31)) | \
50 ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \
54 static const u32 bytebit[8] =
56 0200, 0100, 040, 020, 010, 04, 02, 01
59 static const u32 bigbyte[24] =
61 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL,
62 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL,
63 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL,
64 0x800UL, 0x400UL, 0x200UL, 0x100UL,
65 0x80UL, 0x40UL, 0x20UL, 0x10UL,
66 0x8UL, 0x4UL, 0x2UL, 0x1L
69 /* Use the key schedule specific in the standard (ANSI X3.92-1981) */
71 static const u8 pc1[56] = {
72 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
73 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
74 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
75 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
78 static const u8 totrot[16] = {
85 static const u8 pc2[48] = {
86 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
87 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
88 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
89 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
93 static const u32 SP1[64] =
95 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
96 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
97 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
98 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
99 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
100 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
101 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
102 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
103 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
104 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
105 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
106 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
107 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
108 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
109 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
110 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
113 static const u32 SP2[64] =
115 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
116 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
117 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
118 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
119 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
120 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
121 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
122 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
123 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
124 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
125 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
126 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
127 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
128 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
129 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
130 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
133 static const u32 SP3[64] =
135 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
136 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
137 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
138 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
139 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
140 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
141 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
142 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
143 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
144 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
145 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
146 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
147 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
148 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
149 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
150 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
153 static const u32 SP4[64] =
155 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
156 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
157 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
158 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
159 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
160 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
161 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
162 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
163 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
164 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
165 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
166 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
167 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
168 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
169 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
170 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
173 static const u32 SP5[64] =
175 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
176 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
177 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
178 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
179 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
180 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
181 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
182 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
183 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
184 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
185 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
186 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
187 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
188 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
189 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
190 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
193 static const u32 SP6[64] =
195 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
196 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
197 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
198 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
199 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
200 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
201 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
202 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
203 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
204 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
205 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
206 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
207 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
208 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
209 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
210 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
213 static const u32 SP7[64] =
215 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
216 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
217 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
218 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
219 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
220 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
221 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
222 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
223 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
224 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
225 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
226 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
227 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
228 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
229 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
230 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
233 static const u32 SP8[64] =
235 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
236 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
237 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
238 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
239 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
240 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
241 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
242 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
243 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
244 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
245 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
246 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
247 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
248 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
249 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
250 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
254 static void cookey(const u32 *raw1, u32 *keyout)
262 for (i = 0; i < 16; i++, raw1++) {
264 *cook = (*raw0 & 0x00fc0000L) << 6;
265 *cook |= (*raw0 & 0x00000fc0L) << 10;
266 *cook |= (*raw1 & 0x00fc0000L) >> 10;
267 *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
268 *cook = (*raw0 & 0x0003f000L) << 12;
269 *cook |= (*raw0 & 0x0000003fL) << 16;
270 *cook |= (*raw1 & 0x0003f000L) >> 4;
271 *cook++ |= (*raw1 & 0x0000003fL);
274 os_memcpy(keyout, dough, sizeof(dough));
278 static void deskey(const u8 *key, int decrypt, u32 *keyout)
280 u32 i, j, l, m, n, kn[32];
281 u8 pc1m[56], pcr[56];
283 for (j = 0; j < 56; j++) {
287 ((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
290 for (i = 0; i < 16; i++) {
297 for (j = 0; j < 28; j++) {
298 l = j + (u32) totrot[i];
302 pcr[j] = pc1m[l - 28];
304 for (/* j = 28 */; j < 56; j++) {
305 l = j + (u32) totrot[i];
309 pcr[j] = pc1m[l - 28];
311 for (j = 0; j < 24; j++) {
312 if ((int) pcr[(int) pc2[j]] != 0)
314 if ((int) pcr[(int) pc2[j + 24]] != 0)
323 static void desfunc(u32 *block, const u32 *keys)
325 u32 work, right, leftt;
331 work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
333 leftt ^= (work << 4);
335 work = ((leftt >> 16) ^ right) & 0x0000ffffL;
337 leftt ^= (work << 16);
339 work = ((right >> 2) ^ leftt) & 0x33333333L;
341 right ^= (work << 2);
343 work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
345 right ^= (work << 8);
347 right = ROLc(right, 1);
348 work = (leftt ^ right) & 0xaaaaaaaaL;
352 leftt = ROLc(leftt, 1);
354 for (cur_round = 0; cur_round < 8; cur_round++) {
355 work = RORc(right, 4) ^ *keys++;
356 leftt ^= SP7[work & 0x3fL]
357 ^ SP5[(work >> 8) & 0x3fL]
358 ^ SP3[(work >> 16) & 0x3fL]
359 ^ SP1[(work >> 24) & 0x3fL];
360 work = right ^ *keys++;
361 leftt ^= SP8[ work & 0x3fL]
362 ^ SP6[(work >> 8) & 0x3fL]
363 ^ SP4[(work >> 16) & 0x3fL]
364 ^ SP2[(work >> 24) & 0x3fL];
366 work = RORc(leftt, 4) ^ *keys++;
367 right ^= SP7[ work & 0x3fL]
368 ^ SP5[(work >> 8) & 0x3fL]
369 ^ SP3[(work >> 16) & 0x3fL]
370 ^ SP1[(work >> 24) & 0x3fL];
371 work = leftt ^ *keys++;
372 right ^= SP8[ work & 0x3fL]
373 ^ SP6[(work >> 8) & 0x3fL]
374 ^ SP4[(work >> 16) & 0x3fL]
375 ^ SP2[(work >> 24) & 0x3fL];
378 right = RORc(right, 1);
379 work = (leftt ^ right) & 0xaaaaaaaaL;
382 leftt = RORc(leftt, 1);
383 work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
385 leftt ^= (work << 8);
387 work = ((leftt >> 2) ^ right) & 0x33333333L;
389 leftt ^= (work << 2);
390 work = ((right >> 16) ^ leftt) & 0x0000ffffL;
392 right ^= (work << 16);
393 work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
395 right ^= (work << 4);
402 /* wpa_supplicant/hostapd specific wrapper */
404 void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
406 u8 pkey[8], next, tmp;
410 /* Add parity bits to the key */
412 for (i = 0; i < 7; i++) {
414 pkey[i] = (tmp >> i) | next | 1;
415 next = tmp << (7 - i);
421 work[0] = WPA_GET_BE32(clear);
422 work[1] = WPA_GET_BE32(clear + 4);
424 WPA_PUT_BE32(cypher, work[0]);
425 WPA_PUT_BE32(cypher + 4, work[1]);
427 os_memset(pkey, 0, sizeof(pkey));
428 os_memset(ek, 0, sizeof(ek));
437 void des3_key_setup(const u8 *key, struct des3_key_s *dkey)
439 deskey(key, 0, dkey->ek[0]);
440 deskey(key + 8, 1, dkey->ek[1]);
441 deskey(key + 16, 0, dkey->ek[2]);
443 deskey(key, 1, dkey->dk[2]);
444 deskey(key + 8, 0, dkey->dk[1]);
445 deskey(key + 16, 1, dkey->dk[0]);
449 void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt)
453 work[0] = WPA_GET_BE32(plain);
454 work[1] = WPA_GET_BE32(plain + 4);
455 desfunc(work, key->ek[0]);
456 desfunc(work, key->ek[1]);
457 desfunc(work, key->ek[2]);
458 WPA_PUT_BE32(crypt, work[0]);
459 WPA_PUT_BE32(crypt + 4, work[1]);
463 void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain)
467 work[0] = WPA_GET_BE32(crypt);
468 work[1] = WPA_GET_BE32(crypt + 4);
469 desfunc(work, key->dk[0]);
470 desfunc(work, key->dk[1]);
471 desfunc(work, key->dk[2]);
472 WPA_PUT_BE32(plain, work[0]);
473 WPA_PUT_BE32(plain + 4, work[1]);