1e28a4053SRui Paulo /*
2e28a4053SRui Paulo * DES and 3DES-EDE ciphers
3e28a4053SRui Paulo *
4e28a4053SRui Paulo * Modifications to LibTomCrypt implementation:
5e28a4053SRui Paulo * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
6e28a4053SRui Paulo *
7f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license.
8f05cddf9SRui Paulo * See README for more details.
9e28a4053SRui Paulo */
10e28a4053SRui Paulo
11e28a4053SRui Paulo #include "includes.h"
12e28a4053SRui Paulo
13e28a4053SRui Paulo #include "common.h"
14e28a4053SRui Paulo #include "crypto.h"
15e28a4053SRui Paulo #include "des_i.h"
16e28a4053SRui Paulo
17e28a4053SRui Paulo /*
18e28a4053SRui Paulo * This implementation is based on a DES implementation included in
19e28a4053SRui Paulo * LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd
20e28a4053SRui Paulo * coding style.
21e28a4053SRui Paulo */
22e28a4053SRui Paulo
23e28a4053SRui Paulo /* LibTomCrypt, modular cryptographic library -- Tom St Denis
24e28a4053SRui Paulo *
25e28a4053SRui Paulo * LibTomCrypt is a library that provides various cryptographic
26e28a4053SRui Paulo * algorithms in a highly modular and flexible manner.
27e28a4053SRui Paulo *
28e28a4053SRui Paulo * The library is free for all purposes without any express
29e28a4053SRui Paulo * guarantee it works.
30e28a4053SRui Paulo *
31e28a4053SRui Paulo * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
32e28a4053SRui Paulo */
33e28a4053SRui Paulo
34e28a4053SRui Paulo /**
35e28a4053SRui Paulo DES code submitted by Dobes Vandermeer
36e28a4053SRui Paulo */
37e28a4053SRui Paulo
38e28a4053SRui Paulo #define ROLc(x, y) \
39e28a4053SRui Paulo ((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \
40e28a4053SRui Paulo (((unsigned long) (x) & 0xFFFFFFFFUL) >> \
41e28a4053SRui Paulo (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
42e28a4053SRui Paulo #define RORc(x, y) \
43e28a4053SRui Paulo (((((unsigned long) (x) & 0xFFFFFFFFUL) >> \
44e28a4053SRui Paulo (unsigned long) ((y) & 31)) | \
45e28a4053SRui Paulo ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \
46e28a4053SRui Paulo 0xFFFFFFFFUL)
47e28a4053SRui Paulo
48e28a4053SRui Paulo
49e28a4053SRui Paulo static const u32 bytebit[8] =
50e28a4053SRui Paulo {
51e28a4053SRui Paulo 0200, 0100, 040, 020, 010, 04, 02, 01
52e28a4053SRui Paulo };
53e28a4053SRui Paulo
54e28a4053SRui Paulo static const u32 bigbyte[24] =
55e28a4053SRui Paulo {
56e28a4053SRui Paulo 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL,
57e28a4053SRui Paulo 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL,
58e28a4053SRui Paulo 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL,
59e28a4053SRui Paulo 0x800UL, 0x400UL, 0x200UL, 0x100UL,
60e28a4053SRui Paulo 0x80UL, 0x40UL, 0x20UL, 0x10UL,
61e28a4053SRui Paulo 0x8UL, 0x4UL, 0x2UL, 0x1L
62e28a4053SRui Paulo };
63e28a4053SRui Paulo
64e28a4053SRui Paulo /* Use the key schedule specific in the standard (ANSI X3.92-1981) */
65e28a4053SRui Paulo
66e28a4053SRui Paulo static const u8 pc1[56] = {
67e28a4053SRui Paulo 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
68e28a4053SRui Paulo 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
69e28a4053SRui Paulo 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
70e28a4053SRui Paulo 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
71e28a4053SRui Paulo };
72e28a4053SRui Paulo
73e28a4053SRui Paulo static const u8 totrot[16] = {
74e28a4053SRui Paulo 1, 2, 4, 6,
75e28a4053SRui Paulo 8, 10, 12, 14,
76e28a4053SRui Paulo 15, 17, 19, 21,
77e28a4053SRui Paulo 23, 25, 27, 28
78e28a4053SRui Paulo };
79e28a4053SRui Paulo
80e28a4053SRui Paulo static const u8 pc2[48] = {
81e28a4053SRui Paulo 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
82e28a4053SRui Paulo 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
83e28a4053SRui Paulo 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
84e28a4053SRui Paulo 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
85e28a4053SRui Paulo };
86e28a4053SRui Paulo
87e28a4053SRui Paulo
88e28a4053SRui Paulo static const u32 SP1[64] =
89e28a4053SRui Paulo {
90e28a4053SRui Paulo 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
91e28a4053SRui Paulo 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
92e28a4053SRui Paulo 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
93e28a4053SRui Paulo 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
94e28a4053SRui Paulo 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
95e28a4053SRui Paulo 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
96e28a4053SRui Paulo 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
97e28a4053SRui Paulo 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
98e28a4053SRui Paulo 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
99e28a4053SRui Paulo 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
100e28a4053SRui Paulo 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
101e28a4053SRui Paulo 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
102e28a4053SRui Paulo 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
103e28a4053SRui Paulo 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
104e28a4053SRui Paulo 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
105e28a4053SRui Paulo 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
106e28a4053SRui Paulo };
107e28a4053SRui Paulo
108e28a4053SRui Paulo static const u32 SP2[64] =
109e28a4053SRui Paulo {
110e28a4053SRui Paulo 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
111e28a4053SRui Paulo 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
112e28a4053SRui Paulo 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
113e28a4053SRui Paulo 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
114e28a4053SRui Paulo 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
115e28a4053SRui Paulo 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
116e28a4053SRui Paulo 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
117e28a4053SRui Paulo 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
118e28a4053SRui Paulo 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
119e28a4053SRui Paulo 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
120e28a4053SRui Paulo 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
121e28a4053SRui Paulo 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
122e28a4053SRui Paulo 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
123e28a4053SRui Paulo 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
124e28a4053SRui Paulo 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
125e28a4053SRui Paulo 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
126e28a4053SRui Paulo };
127e28a4053SRui Paulo
128e28a4053SRui Paulo static const u32 SP3[64] =
129e28a4053SRui Paulo {
130e28a4053SRui Paulo 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
131e28a4053SRui Paulo 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
132e28a4053SRui Paulo 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
133e28a4053SRui Paulo 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
134e28a4053SRui Paulo 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
135e28a4053SRui Paulo 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
136e28a4053SRui Paulo 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
137e28a4053SRui Paulo 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
138e28a4053SRui Paulo 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
139e28a4053SRui Paulo 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
140e28a4053SRui Paulo 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
141e28a4053SRui Paulo 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
142e28a4053SRui Paulo 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
143e28a4053SRui Paulo 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
144e28a4053SRui Paulo 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
145e28a4053SRui Paulo 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
146e28a4053SRui Paulo };
147e28a4053SRui Paulo
148e28a4053SRui Paulo static const u32 SP4[64] =
149e28a4053SRui Paulo {
150e28a4053SRui Paulo 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
151e28a4053SRui Paulo 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
152e28a4053SRui Paulo 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
153e28a4053SRui Paulo 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
154e28a4053SRui Paulo 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
155e28a4053SRui Paulo 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
156e28a4053SRui Paulo 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
157e28a4053SRui Paulo 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
158e28a4053SRui Paulo 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
159e28a4053SRui Paulo 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
160e28a4053SRui Paulo 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
161e28a4053SRui Paulo 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
162e28a4053SRui Paulo 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
163e28a4053SRui Paulo 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
164e28a4053SRui Paulo 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
165e28a4053SRui Paulo 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
166e28a4053SRui Paulo };
167e28a4053SRui Paulo
168e28a4053SRui Paulo static const u32 SP5[64] =
169e28a4053SRui Paulo {
170e28a4053SRui Paulo 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
171e28a4053SRui Paulo 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
172e28a4053SRui Paulo 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
173e28a4053SRui Paulo 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
174e28a4053SRui Paulo 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
175e28a4053SRui Paulo 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
176e28a4053SRui Paulo 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
177e28a4053SRui Paulo 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
178e28a4053SRui Paulo 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
179e28a4053SRui Paulo 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
180e28a4053SRui Paulo 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
181e28a4053SRui Paulo 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
182e28a4053SRui Paulo 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
183e28a4053SRui Paulo 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
184e28a4053SRui Paulo 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
185e28a4053SRui Paulo 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
186e28a4053SRui Paulo };
187e28a4053SRui Paulo
188e28a4053SRui Paulo static const u32 SP6[64] =
189e28a4053SRui Paulo {
190e28a4053SRui Paulo 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
191e28a4053SRui Paulo 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
192e28a4053SRui Paulo 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
193e28a4053SRui Paulo 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
194e28a4053SRui Paulo 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
195e28a4053SRui Paulo 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
196e28a4053SRui Paulo 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
197e28a4053SRui Paulo 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
198e28a4053SRui Paulo 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
199e28a4053SRui Paulo 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
200e28a4053SRui Paulo 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
201e28a4053SRui Paulo 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
202e28a4053SRui Paulo 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
203e28a4053SRui Paulo 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
204e28a4053SRui Paulo 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
205e28a4053SRui Paulo 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
206e28a4053SRui Paulo };
207e28a4053SRui Paulo
208e28a4053SRui Paulo static const u32 SP7[64] =
209e28a4053SRui Paulo {
210e28a4053SRui Paulo 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
211e28a4053SRui Paulo 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
212e28a4053SRui Paulo 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
213e28a4053SRui Paulo 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
214e28a4053SRui Paulo 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
215e28a4053SRui Paulo 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
216e28a4053SRui Paulo 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
217e28a4053SRui Paulo 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
218e28a4053SRui Paulo 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
219e28a4053SRui Paulo 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
220e28a4053SRui Paulo 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
221e28a4053SRui Paulo 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
222e28a4053SRui Paulo 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
223e28a4053SRui Paulo 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
224e28a4053SRui Paulo 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
225e28a4053SRui Paulo 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
226e28a4053SRui Paulo };
227e28a4053SRui Paulo
228e28a4053SRui Paulo static const u32 SP8[64] =
229e28a4053SRui Paulo {
230e28a4053SRui Paulo 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
231e28a4053SRui Paulo 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
232e28a4053SRui Paulo 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
233e28a4053SRui Paulo 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
234e28a4053SRui Paulo 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
235e28a4053SRui Paulo 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
236e28a4053SRui Paulo 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
237e28a4053SRui Paulo 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
238e28a4053SRui Paulo 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
239e28a4053SRui Paulo 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
240e28a4053SRui Paulo 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
241e28a4053SRui Paulo 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
242e28a4053SRui Paulo 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
243e28a4053SRui Paulo 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
244e28a4053SRui Paulo 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
245e28a4053SRui Paulo 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
246e28a4053SRui Paulo };
247e28a4053SRui Paulo
248e28a4053SRui Paulo
cookey(const u32 * raw1,u32 * keyout)249e28a4053SRui Paulo static void cookey(const u32 *raw1, u32 *keyout)
250e28a4053SRui Paulo {
251e28a4053SRui Paulo u32 *cook;
252e28a4053SRui Paulo const u32 *raw0;
253e28a4053SRui Paulo u32 dough[32];
254e28a4053SRui Paulo int i;
255e28a4053SRui Paulo
256e28a4053SRui Paulo cook = dough;
257e28a4053SRui Paulo for (i = 0; i < 16; i++, raw1++) {
258e28a4053SRui Paulo raw0 = raw1++;
259e28a4053SRui Paulo *cook = (*raw0 & 0x00fc0000L) << 6;
260e28a4053SRui Paulo *cook |= (*raw0 & 0x00000fc0L) << 10;
261e28a4053SRui Paulo *cook |= (*raw1 & 0x00fc0000L) >> 10;
262e28a4053SRui Paulo *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
263e28a4053SRui Paulo *cook = (*raw0 & 0x0003f000L) << 12;
264e28a4053SRui Paulo *cook |= (*raw0 & 0x0000003fL) << 16;
265e28a4053SRui Paulo *cook |= (*raw1 & 0x0003f000L) >> 4;
266e28a4053SRui Paulo *cook++ |= (*raw1 & 0x0000003fL);
267e28a4053SRui Paulo }
268e28a4053SRui Paulo
269e28a4053SRui Paulo os_memcpy(keyout, dough, sizeof(dough));
270e28a4053SRui Paulo }
271e28a4053SRui Paulo
272e28a4053SRui Paulo
deskey(const u8 * key,int decrypt,u32 * keyout)273e28a4053SRui Paulo static void deskey(const u8 *key, int decrypt, u32 *keyout)
274e28a4053SRui Paulo {
275e28a4053SRui Paulo u32 i, j, l, m, n, kn[32];
276e28a4053SRui Paulo u8 pc1m[56], pcr[56];
277e28a4053SRui Paulo
278e28a4053SRui Paulo for (j = 0; j < 56; j++) {
279e28a4053SRui Paulo l = (u32) pc1[j];
280e28a4053SRui Paulo m = l & 7;
281e28a4053SRui Paulo pc1m[j] = (u8)
282e28a4053SRui Paulo ((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
283e28a4053SRui Paulo }
284e28a4053SRui Paulo
285e28a4053SRui Paulo for (i = 0; i < 16; i++) {
286e28a4053SRui Paulo if (decrypt)
287e28a4053SRui Paulo m = (15 - i) << 1;
288e28a4053SRui Paulo else
289e28a4053SRui Paulo m = i << 1;
290e28a4053SRui Paulo n = m + 1;
291e28a4053SRui Paulo kn[m] = kn[n] = 0L;
292e28a4053SRui Paulo for (j = 0; j < 28; j++) {
293e28a4053SRui Paulo l = j + (u32) totrot[i];
294e28a4053SRui Paulo if (l < 28)
295e28a4053SRui Paulo pcr[j] = pc1m[l];
296e28a4053SRui Paulo else
297e28a4053SRui Paulo pcr[j] = pc1m[l - 28];
298e28a4053SRui Paulo }
299e28a4053SRui Paulo for (/* j = 28 */; j < 56; j++) {
300e28a4053SRui Paulo l = j + (u32) totrot[i];
301e28a4053SRui Paulo if (l < 56)
302e28a4053SRui Paulo pcr[j] = pc1m[l];
303e28a4053SRui Paulo else
304e28a4053SRui Paulo pcr[j] = pc1m[l - 28];
305e28a4053SRui Paulo }
306e28a4053SRui Paulo for (j = 0; j < 24; j++) {
307e28a4053SRui Paulo if ((int) pcr[(int) pc2[j]] != 0)
308e28a4053SRui Paulo kn[m] |= bigbyte[j];
309e28a4053SRui Paulo if ((int) pcr[(int) pc2[j + 24]] != 0)
310e28a4053SRui Paulo kn[n] |= bigbyte[j];
311e28a4053SRui Paulo }
312e28a4053SRui Paulo }
313e28a4053SRui Paulo
314e28a4053SRui Paulo cookey(kn, keyout);
315e28a4053SRui Paulo }
316e28a4053SRui Paulo
317e28a4053SRui Paulo
desfunc(u32 * block,const u32 * keys)318e28a4053SRui Paulo static void desfunc(u32 *block, const u32 *keys)
319e28a4053SRui Paulo {
320e28a4053SRui Paulo u32 work, right, leftt;
321e28a4053SRui Paulo int cur_round;
322e28a4053SRui Paulo
323e28a4053SRui Paulo leftt = block[0];
324e28a4053SRui Paulo right = block[1];
325e28a4053SRui Paulo
326e28a4053SRui Paulo work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
327e28a4053SRui Paulo right ^= work;
328e28a4053SRui Paulo leftt ^= (work << 4);
329e28a4053SRui Paulo
330e28a4053SRui Paulo work = ((leftt >> 16) ^ right) & 0x0000ffffL;
331e28a4053SRui Paulo right ^= work;
332e28a4053SRui Paulo leftt ^= (work << 16);
333e28a4053SRui Paulo
334e28a4053SRui Paulo work = ((right >> 2) ^ leftt) & 0x33333333L;
335e28a4053SRui Paulo leftt ^= work;
336e28a4053SRui Paulo right ^= (work << 2);
337e28a4053SRui Paulo
338e28a4053SRui Paulo work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
339e28a4053SRui Paulo leftt ^= work;
340e28a4053SRui Paulo right ^= (work << 8);
341e28a4053SRui Paulo
342e28a4053SRui Paulo right = ROLc(right, 1);
343e28a4053SRui Paulo work = (leftt ^ right) & 0xaaaaaaaaL;
344e28a4053SRui Paulo
345e28a4053SRui Paulo leftt ^= work;
346e28a4053SRui Paulo right ^= work;
347e28a4053SRui Paulo leftt = ROLc(leftt, 1);
348e28a4053SRui Paulo
349e28a4053SRui Paulo for (cur_round = 0; cur_round < 8; cur_round++) {
350e28a4053SRui Paulo work = RORc(right, 4) ^ *keys++;
351e28a4053SRui Paulo leftt ^= SP7[work & 0x3fL]
352e28a4053SRui Paulo ^ SP5[(work >> 8) & 0x3fL]
353e28a4053SRui Paulo ^ SP3[(work >> 16) & 0x3fL]
354e28a4053SRui Paulo ^ SP1[(work >> 24) & 0x3fL];
355e28a4053SRui Paulo work = right ^ *keys++;
356e28a4053SRui Paulo leftt ^= SP8[ work & 0x3fL]
357e28a4053SRui Paulo ^ SP6[(work >> 8) & 0x3fL]
358e28a4053SRui Paulo ^ SP4[(work >> 16) & 0x3fL]
359e28a4053SRui Paulo ^ SP2[(work >> 24) & 0x3fL];
360e28a4053SRui Paulo
361e28a4053SRui Paulo work = RORc(leftt, 4) ^ *keys++;
362e28a4053SRui Paulo right ^= SP7[ work & 0x3fL]
363e28a4053SRui Paulo ^ SP5[(work >> 8) & 0x3fL]
364e28a4053SRui Paulo ^ SP3[(work >> 16) & 0x3fL]
365e28a4053SRui Paulo ^ SP1[(work >> 24) & 0x3fL];
366e28a4053SRui Paulo work = leftt ^ *keys++;
367e28a4053SRui Paulo right ^= SP8[ work & 0x3fL]
368e28a4053SRui Paulo ^ SP6[(work >> 8) & 0x3fL]
369e28a4053SRui Paulo ^ SP4[(work >> 16) & 0x3fL]
370e28a4053SRui Paulo ^ SP2[(work >> 24) & 0x3fL];
371e28a4053SRui Paulo }
372e28a4053SRui Paulo
373e28a4053SRui Paulo right = RORc(right, 1);
374e28a4053SRui Paulo work = (leftt ^ right) & 0xaaaaaaaaL;
375e28a4053SRui Paulo leftt ^= work;
376e28a4053SRui Paulo right ^= work;
377e28a4053SRui Paulo leftt = RORc(leftt, 1);
378e28a4053SRui Paulo work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
379e28a4053SRui Paulo right ^= work;
380e28a4053SRui Paulo leftt ^= (work << 8);
381e28a4053SRui Paulo /* -- */
382e28a4053SRui Paulo work = ((leftt >> 2) ^ right) & 0x33333333L;
383e28a4053SRui Paulo right ^= work;
384e28a4053SRui Paulo leftt ^= (work << 2);
385e28a4053SRui Paulo work = ((right >> 16) ^ leftt) & 0x0000ffffL;
386e28a4053SRui Paulo leftt ^= work;
387e28a4053SRui Paulo right ^= (work << 16);
388e28a4053SRui Paulo work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
389e28a4053SRui Paulo leftt ^= work;
390e28a4053SRui Paulo right ^= (work << 4);
391e28a4053SRui Paulo
392e28a4053SRui Paulo block[0] = right;
393e28a4053SRui Paulo block[1] = leftt;
394e28a4053SRui Paulo }
395e28a4053SRui Paulo
396e28a4053SRui Paulo
397e28a4053SRui Paulo /* wpa_supplicant/hostapd specific wrapper */
398e28a4053SRui Paulo
des_encrypt(const u8 * clear,const u8 * key,u8 * cypher)399*85732ac8SCy Schubert int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
400e28a4053SRui Paulo {
401e28a4053SRui Paulo u8 pkey[8], next, tmp;
402e28a4053SRui Paulo int i;
403e28a4053SRui Paulo u32 ek[32], work[2];
404e28a4053SRui Paulo
405e28a4053SRui Paulo /* Add parity bits to the key */
406e28a4053SRui Paulo next = 0;
407e28a4053SRui Paulo for (i = 0; i < 7; i++) {
408e28a4053SRui Paulo tmp = key[i];
409e28a4053SRui Paulo pkey[i] = (tmp >> i) | next | 1;
410e28a4053SRui Paulo next = tmp << (7 - i);
411e28a4053SRui Paulo }
412e28a4053SRui Paulo pkey[i] = next | 1;
413e28a4053SRui Paulo
414e28a4053SRui Paulo deskey(pkey, 0, ek);
415e28a4053SRui Paulo
416e28a4053SRui Paulo work[0] = WPA_GET_BE32(clear);
417e28a4053SRui Paulo work[1] = WPA_GET_BE32(clear + 4);
418e28a4053SRui Paulo desfunc(work, ek);
419e28a4053SRui Paulo WPA_PUT_BE32(cypher, work[0]);
420e28a4053SRui Paulo WPA_PUT_BE32(cypher + 4, work[1]);
421e28a4053SRui Paulo
422e28a4053SRui Paulo os_memset(pkey, 0, sizeof(pkey));
423e28a4053SRui Paulo os_memset(ek, 0, sizeof(ek));
424*85732ac8SCy Schubert return 0;
425e28a4053SRui Paulo }
426e28a4053SRui Paulo
427e28a4053SRui Paulo
des_key_setup(const u8 * key,u32 * ek,u32 * dk)428e28a4053SRui Paulo void des_key_setup(const u8 *key, u32 *ek, u32 *dk)
429e28a4053SRui Paulo {
430e28a4053SRui Paulo deskey(key, 0, ek);
431e28a4053SRui Paulo deskey(key, 1, dk);
432e28a4053SRui Paulo }
433e28a4053SRui Paulo
434e28a4053SRui Paulo
des_block_encrypt(const u8 * plain,const u32 * ek,u8 * crypt)435e28a4053SRui Paulo void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt)
436e28a4053SRui Paulo {
437e28a4053SRui Paulo u32 work[2];
438e28a4053SRui Paulo work[0] = WPA_GET_BE32(plain);
439e28a4053SRui Paulo work[1] = WPA_GET_BE32(plain + 4);
440e28a4053SRui Paulo desfunc(work, ek);
441e28a4053SRui Paulo WPA_PUT_BE32(crypt, work[0]);
442e28a4053SRui Paulo WPA_PUT_BE32(crypt + 4, work[1]);
443e28a4053SRui Paulo }
444e28a4053SRui Paulo
445e28a4053SRui Paulo
des_block_decrypt(const u8 * crypt,const u32 * dk,u8 * plain)446e28a4053SRui Paulo void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain)
447e28a4053SRui Paulo {
448e28a4053SRui Paulo u32 work[2];
449e28a4053SRui Paulo work[0] = WPA_GET_BE32(crypt);
450e28a4053SRui Paulo work[1] = WPA_GET_BE32(crypt + 4);
451e28a4053SRui Paulo desfunc(work, dk);
452e28a4053SRui Paulo WPA_PUT_BE32(plain, work[0]);
453e28a4053SRui Paulo WPA_PUT_BE32(plain + 4, work[1]);
454e28a4053SRui Paulo }
455e28a4053SRui Paulo
456e28a4053SRui Paulo
des3_key_setup(const u8 * key,struct des3_key_s * dkey)457e28a4053SRui Paulo void des3_key_setup(const u8 *key, struct des3_key_s *dkey)
458e28a4053SRui Paulo {
459e28a4053SRui Paulo deskey(key, 0, dkey->ek[0]);
460e28a4053SRui Paulo deskey(key + 8, 1, dkey->ek[1]);
461e28a4053SRui Paulo deskey(key + 16, 0, dkey->ek[2]);
462e28a4053SRui Paulo
463e28a4053SRui Paulo deskey(key, 1, dkey->dk[2]);
464e28a4053SRui Paulo deskey(key + 8, 0, dkey->dk[1]);
465e28a4053SRui Paulo deskey(key + 16, 1, dkey->dk[0]);
466e28a4053SRui Paulo }
467e28a4053SRui Paulo
468e28a4053SRui Paulo
des3_encrypt(const u8 * plain,const struct des3_key_s * key,u8 * crypt)469e28a4053SRui Paulo void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt)
470e28a4053SRui Paulo {
471e28a4053SRui Paulo u32 work[2];
472e28a4053SRui Paulo
473e28a4053SRui Paulo work[0] = WPA_GET_BE32(plain);
474e28a4053SRui Paulo work[1] = WPA_GET_BE32(plain + 4);
475e28a4053SRui Paulo desfunc(work, key->ek[0]);
476e28a4053SRui Paulo desfunc(work, key->ek[1]);
477e28a4053SRui Paulo desfunc(work, key->ek[2]);
478e28a4053SRui Paulo WPA_PUT_BE32(crypt, work[0]);
479e28a4053SRui Paulo WPA_PUT_BE32(crypt + 4, work[1]);
480e28a4053SRui Paulo }
481e28a4053SRui Paulo
482e28a4053SRui Paulo
des3_decrypt(const u8 * crypt,const struct des3_key_s * key,u8 * plain)483e28a4053SRui Paulo void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain)
484e28a4053SRui Paulo {
485e28a4053SRui Paulo u32 work[2];
486e28a4053SRui Paulo
487e28a4053SRui Paulo work[0] = WPA_GET_BE32(crypt);
488e28a4053SRui Paulo work[1] = WPA_GET_BE32(crypt + 4);
489e28a4053SRui Paulo desfunc(work, key->dk[0]);
490e28a4053SRui Paulo desfunc(work, key->dk[1]);
491e28a4053SRui Paulo desfunc(work, key->dk[2]);
492e28a4053SRui Paulo WPA_PUT_BE32(plain, work[0]);
493e28a4053SRui Paulo WPA_PUT_BE32(plain + 4, work[1]);
494e28a4053SRui Paulo }
495