1214501Srpaulo/*
2214501Srpaulo * DES and 3DES-EDE ciphers
3214501Srpaulo *
4214501Srpaulo * Modifications to LibTomCrypt implementation:
5214501Srpaulo * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
6214501Srpaulo *
7252726Srpaulo * This software may be distributed under the terms of the BSD license.
8252726Srpaulo * See README for more details.
9214501Srpaulo */
10214501Srpaulo
11214501Srpaulo#include "includes.h"
12214501Srpaulo
13214501Srpaulo#include "common.h"
14214501Srpaulo#include "crypto.h"
15214501Srpaulo#include "des_i.h"
16214501Srpaulo
17214501Srpaulo/*
18214501Srpaulo * This implementation is based on a DES implementation included in
19214501Srpaulo * LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd
20214501Srpaulo * coding style.
21214501Srpaulo */
22214501Srpaulo
23214501Srpaulo/* LibTomCrypt, modular cryptographic library -- Tom St Denis
24214501Srpaulo *
25214501Srpaulo * LibTomCrypt is a library that provides various cryptographic
26214501Srpaulo * algorithms in a highly modular and flexible manner.
27214501Srpaulo *
28214501Srpaulo * The library is free for all purposes without any express
29214501Srpaulo * guarantee it works.
30214501Srpaulo *
31214501Srpaulo * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
32214501Srpaulo */
33214501Srpaulo
34214501Srpaulo/**
35214501Srpaulo  DES code submitted by Dobes Vandermeer
36214501Srpaulo*/
37214501Srpaulo
38214501Srpaulo#define ROLc(x, y) \
39214501Srpaulo	((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \
40214501Srpaulo	  (((unsigned long) (x) & 0xFFFFFFFFUL) >> \
41214501Srpaulo	   (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
42214501Srpaulo#define RORc(x, y) \
43214501Srpaulo	(((((unsigned long) (x) & 0xFFFFFFFFUL) >> \
44214501Srpaulo	   (unsigned long) ((y) & 31)) | \
45214501Srpaulo	  ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \
46214501Srpaulo	 0xFFFFFFFFUL)
47214501Srpaulo
48214501Srpaulo
49214501Srpaulostatic const u32 bytebit[8] =
50214501Srpaulo{
51214501Srpaulo	0200, 0100, 040, 020, 010, 04, 02, 01
52214501Srpaulo};
53214501Srpaulo
54214501Srpaulostatic const u32 bigbyte[24] =
55214501Srpaulo{
56214501Srpaulo	0x800000UL,  0x400000UL,  0x200000UL,  0x100000UL,
57214501Srpaulo	0x80000UL,   0x40000UL,   0x20000UL,   0x10000UL,
58214501Srpaulo	0x8000UL,    0x4000UL,    0x2000UL,    0x1000UL,
59214501Srpaulo	0x800UL,     0x400UL,     0x200UL,     0x100UL,
60214501Srpaulo	0x80UL,      0x40UL,      0x20UL,      0x10UL,
61214501Srpaulo	0x8UL,       0x4UL,       0x2UL,       0x1L
62214501Srpaulo};
63214501Srpaulo
64214501Srpaulo/* Use the key schedule specific in the standard (ANSI X3.92-1981) */
65214501Srpaulo
66214501Srpaulostatic const u8 pc1[56] = {
67214501Srpaulo	56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,
68214501Srpaulo	 9,  1, 58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35,
69214501Srpaulo	62, 54, 46, 38, 30, 22, 14,  6, 61, 53, 45, 37, 29, 21,
70214501Srpaulo	13,  5, 60, 52, 44, 36, 28, 20, 12,  4, 27, 19, 11,  3
71214501Srpaulo};
72214501Srpaulo
73214501Srpaulostatic const u8 totrot[16] = {
74214501Srpaulo	1,   2,  4,  6,
75214501Srpaulo	8,  10, 12, 14,
76214501Srpaulo	15, 17, 19, 21,
77214501Srpaulo	23, 25, 27, 28
78214501Srpaulo};
79214501Srpaulo
80214501Srpaulostatic const u8 pc2[48] = {
81214501Srpaulo	13, 16, 10, 23,  0,  4,      2, 27, 14,  5, 20,  9,
82214501Srpaulo	22, 18, 11,  3, 25,  7,     15,  6, 26, 19, 12,  1,
83214501Srpaulo	40, 51, 30, 36, 46, 54,     29, 39, 50, 44, 32, 47,
84214501Srpaulo	43, 48, 38, 55, 33, 52,     45, 41, 49, 35, 28, 31
85214501Srpaulo};
86214501Srpaulo
87214501Srpaulo
88214501Srpaulostatic const u32 SP1[64] =
89214501Srpaulo{
90214501Srpaulo	0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
91214501Srpaulo	0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
92214501Srpaulo	0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
93214501Srpaulo	0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
94214501Srpaulo	0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
95214501Srpaulo	0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
96214501Srpaulo	0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
97214501Srpaulo	0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
98214501Srpaulo	0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
99214501Srpaulo	0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
100214501Srpaulo	0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
101214501Srpaulo	0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
102214501Srpaulo	0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
103214501Srpaulo	0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
104214501Srpaulo	0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
105214501Srpaulo	0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
106214501Srpaulo};
107214501Srpaulo
108214501Srpaulostatic const u32 SP2[64] =
109214501Srpaulo{
110214501Srpaulo	0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
111214501Srpaulo	0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
112214501Srpaulo	0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
113214501Srpaulo	0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
114214501Srpaulo	0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
115214501Srpaulo	0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
116214501Srpaulo	0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
117214501Srpaulo	0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
118214501Srpaulo	0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
119214501Srpaulo	0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
120214501Srpaulo	0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
121214501Srpaulo	0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
122214501Srpaulo	0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
123214501Srpaulo	0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
124214501Srpaulo	0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
125214501Srpaulo	0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
126214501Srpaulo};
127214501Srpaulo
128214501Srpaulostatic const u32 SP3[64] =
129214501Srpaulo{
130214501Srpaulo	0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
131214501Srpaulo	0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
132214501Srpaulo	0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
133214501Srpaulo	0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
134214501Srpaulo	0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
135214501Srpaulo	0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
136214501Srpaulo	0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
137214501Srpaulo	0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
138214501Srpaulo	0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
139214501Srpaulo	0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
140214501Srpaulo	0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
141214501Srpaulo	0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
142214501Srpaulo	0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
143214501Srpaulo	0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
144214501Srpaulo	0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
145214501Srpaulo	0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
146214501Srpaulo};
147214501Srpaulo
148214501Srpaulostatic const u32 SP4[64] =
149214501Srpaulo{
150214501Srpaulo	0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
151214501Srpaulo	0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
152214501Srpaulo	0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
153214501Srpaulo	0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
154214501Srpaulo	0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
155214501Srpaulo	0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
156214501Srpaulo	0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
157214501Srpaulo	0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
158214501Srpaulo	0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
159214501Srpaulo	0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
160214501Srpaulo	0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
161214501Srpaulo	0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
162214501Srpaulo	0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
163214501Srpaulo	0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
164214501Srpaulo	0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
165214501Srpaulo	0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
166214501Srpaulo};
167214501Srpaulo
168214501Srpaulostatic const u32 SP5[64] =
169214501Srpaulo{
170214501Srpaulo	0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
171214501Srpaulo	0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
172214501Srpaulo	0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
173214501Srpaulo	0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
174214501Srpaulo	0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
175214501Srpaulo	0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
176214501Srpaulo	0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
177214501Srpaulo	0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
178214501Srpaulo	0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
179214501Srpaulo	0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
180214501Srpaulo	0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
181214501Srpaulo	0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
182214501Srpaulo	0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
183214501Srpaulo	0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
184214501Srpaulo	0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
185214501Srpaulo	0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
186214501Srpaulo};
187214501Srpaulo
188214501Srpaulostatic const u32 SP6[64] =
189214501Srpaulo{
190214501Srpaulo	0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
191214501Srpaulo	0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
192214501Srpaulo	0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
193214501Srpaulo	0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
194214501Srpaulo	0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
195214501Srpaulo	0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
196214501Srpaulo	0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
197214501Srpaulo	0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
198214501Srpaulo	0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
199214501Srpaulo	0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
200214501Srpaulo	0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
201214501Srpaulo	0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
202214501Srpaulo	0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
203214501Srpaulo	0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
204214501Srpaulo	0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
205214501Srpaulo	0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
206214501Srpaulo};
207214501Srpaulo
208214501Srpaulostatic const u32 SP7[64] =
209214501Srpaulo{
210214501Srpaulo	0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
211214501Srpaulo	0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
212214501Srpaulo	0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
213214501Srpaulo	0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
214214501Srpaulo	0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
215214501Srpaulo	0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
216214501Srpaulo	0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
217214501Srpaulo	0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
218214501Srpaulo	0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
219214501Srpaulo	0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
220214501Srpaulo	0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
221214501Srpaulo	0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
222214501Srpaulo	0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
223214501Srpaulo	0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
224214501Srpaulo	0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
225214501Srpaulo	0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
226214501Srpaulo};
227214501Srpaulo
228214501Srpaulostatic const u32 SP8[64] =
229214501Srpaulo{
230214501Srpaulo	0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
231214501Srpaulo	0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
232214501Srpaulo	0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
233214501Srpaulo	0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
234214501Srpaulo	0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
235214501Srpaulo	0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
236214501Srpaulo	0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
237214501Srpaulo	0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
238214501Srpaulo	0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
239214501Srpaulo	0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
240214501Srpaulo	0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
241214501Srpaulo	0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
242214501Srpaulo	0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
243214501Srpaulo	0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
244214501Srpaulo	0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
245214501Srpaulo	0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
246214501Srpaulo};
247214501Srpaulo
248214501Srpaulo
249214501Srpaulostatic void cookey(const u32 *raw1, u32 *keyout)
250214501Srpaulo{
251214501Srpaulo	u32 *cook;
252214501Srpaulo	const u32 *raw0;
253214501Srpaulo	u32 dough[32];
254214501Srpaulo	int i;
255214501Srpaulo
256214501Srpaulo	cook = dough;
257214501Srpaulo	for (i = 0; i < 16; i++, raw1++) {
258214501Srpaulo		raw0 = raw1++;
259214501Srpaulo		*cook    = (*raw0 & 0x00fc0000L) << 6;
260214501Srpaulo		*cook   |= (*raw0 & 0x00000fc0L) << 10;
261214501Srpaulo		*cook   |= (*raw1 & 0x00fc0000L) >> 10;
262214501Srpaulo		*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
263214501Srpaulo		*cook    = (*raw0 & 0x0003f000L) << 12;
264214501Srpaulo		*cook   |= (*raw0 & 0x0000003fL) << 16;
265214501Srpaulo		*cook   |= (*raw1 & 0x0003f000L) >> 4;
266214501Srpaulo		*cook++ |= (*raw1 & 0x0000003fL);
267214501Srpaulo	}
268214501Srpaulo
269214501Srpaulo	os_memcpy(keyout, dough, sizeof(dough));
270214501Srpaulo}
271214501Srpaulo
272214501Srpaulo
273214501Srpaulostatic void deskey(const u8 *key, int decrypt, u32 *keyout)
274214501Srpaulo{
275214501Srpaulo	u32 i, j, l, m, n, kn[32];
276214501Srpaulo	u8 pc1m[56], pcr[56];
277214501Srpaulo
278214501Srpaulo	for (j = 0; j < 56; j++) {
279214501Srpaulo		l = (u32) pc1[j];
280214501Srpaulo		m = l & 7;
281214501Srpaulo		pc1m[j] = (u8)
282214501Srpaulo			((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
283214501Srpaulo	}
284214501Srpaulo
285214501Srpaulo	for (i = 0; i < 16; i++) {
286214501Srpaulo		if (decrypt)
287214501Srpaulo			m = (15 - i) << 1;
288214501Srpaulo		else
289214501Srpaulo			m = i << 1;
290214501Srpaulo		n = m + 1;
291214501Srpaulo		kn[m] = kn[n] = 0L;
292214501Srpaulo		for (j = 0; j < 28; j++) {
293214501Srpaulo			l = j + (u32) totrot[i];
294214501Srpaulo			if (l < 28)
295214501Srpaulo				pcr[j] = pc1m[l];
296214501Srpaulo			else
297214501Srpaulo				pcr[j] = pc1m[l - 28];
298214501Srpaulo		}
299214501Srpaulo		for (/* j = 28 */; j < 56; j++) {
300214501Srpaulo			l = j + (u32) totrot[i];
301214501Srpaulo			if (l < 56)
302214501Srpaulo				pcr[j] = pc1m[l];
303214501Srpaulo			else
304214501Srpaulo				pcr[j] = pc1m[l - 28];
305214501Srpaulo		}
306214501Srpaulo		for (j = 0; j < 24; j++) {
307214501Srpaulo			if ((int) pcr[(int) pc2[j]] != 0)
308214501Srpaulo				kn[m] |= bigbyte[j];
309214501Srpaulo			if ((int) pcr[(int) pc2[j + 24]] != 0)
310214501Srpaulo				kn[n] |= bigbyte[j];
311214501Srpaulo		}
312214501Srpaulo	}
313214501Srpaulo
314214501Srpaulo	cookey(kn, keyout);
315214501Srpaulo}
316214501Srpaulo
317214501Srpaulo
318214501Srpaulostatic void desfunc(u32 *block, const u32 *keys)
319214501Srpaulo{
320214501Srpaulo	u32 work, right, leftt;
321214501Srpaulo	int cur_round;
322214501Srpaulo
323214501Srpaulo	leftt = block[0];
324214501Srpaulo	right = block[1];
325214501Srpaulo
326214501Srpaulo	work = ((leftt >> 4)  ^ right) & 0x0f0f0f0fL;
327214501Srpaulo	right ^= work;
328214501Srpaulo	leftt ^= (work << 4);
329214501Srpaulo
330214501Srpaulo	work = ((leftt >> 16) ^ right) & 0x0000ffffL;
331214501Srpaulo	right ^= work;
332214501Srpaulo	leftt ^= (work << 16);
333214501Srpaulo
334214501Srpaulo	work = ((right >> 2)  ^ leftt) & 0x33333333L;
335214501Srpaulo	leftt ^= work;
336214501Srpaulo	right ^= (work << 2);
337214501Srpaulo
338214501Srpaulo	work = ((right >> 8)  ^ leftt) & 0x00ff00ffL;
339214501Srpaulo	leftt ^= work;
340214501Srpaulo	right ^= (work << 8);
341214501Srpaulo
342214501Srpaulo	right = ROLc(right, 1);
343214501Srpaulo	work = (leftt ^ right) & 0xaaaaaaaaL;
344214501Srpaulo
345214501Srpaulo	leftt ^= work;
346214501Srpaulo	right ^= work;
347214501Srpaulo	leftt = ROLc(leftt, 1);
348214501Srpaulo
349214501Srpaulo	for (cur_round = 0; cur_round < 8; cur_round++) {
350214501Srpaulo		work  = RORc(right, 4) ^ *keys++;
351214501Srpaulo		leftt ^= SP7[work        & 0x3fL]
352214501Srpaulo			^ SP5[(work >>  8) & 0x3fL]
353214501Srpaulo			^ SP3[(work >> 16) & 0x3fL]
354214501Srpaulo			^ SP1[(work >> 24) & 0x3fL];
355214501Srpaulo		work  = right ^ *keys++;
356214501Srpaulo		leftt ^= SP8[ work        & 0x3fL]
357214501Srpaulo			^  SP6[(work >>  8) & 0x3fL]
358214501Srpaulo			^  SP4[(work >> 16) & 0x3fL]
359214501Srpaulo			^  SP2[(work >> 24) & 0x3fL];
360214501Srpaulo
361214501Srpaulo		work = RORc(leftt, 4) ^ *keys++;
362214501Srpaulo		right ^= SP7[ work        & 0x3fL]
363214501Srpaulo			^  SP5[(work >>  8) & 0x3fL]
364214501Srpaulo			^  SP3[(work >> 16) & 0x3fL]
365214501Srpaulo			^  SP1[(work >> 24) & 0x3fL];
366214501Srpaulo		work  = leftt ^ *keys++;
367214501Srpaulo		right ^= SP8[ work        & 0x3fL]
368214501Srpaulo			^  SP6[(work >>  8) & 0x3fL]
369214501Srpaulo			^  SP4[(work >> 16) & 0x3fL]
370214501Srpaulo			^  SP2[(work >> 24) & 0x3fL];
371214501Srpaulo	}
372214501Srpaulo
373214501Srpaulo	right = RORc(right, 1);
374214501Srpaulo	work = (leftt ^ right) & 0xaaaaaaaaL;
375214501Srpaulo	leftt ^= work;
376214501Srpaulo	right ^= work;
377214501Srpaulo	leftt = RORc(leftt, 1);
378214501Srpaulo	work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
379214501Srpaulo	right ^= work;
380214501Srpaulo	leftt ^= (work << 8);
381214501Srpaulo	/* -- */
382214501Srpaulo	work = ((leftt >> 2) ^ right) & 0x33333333L;
383214501Srpaulo	right ^= work;
384214501Srpaulo	leftt ^= (work << 2);
385214501Srpaulo	work = ((right >> 16) ^ leftt) & 0x0000ffffL;
386214501Srpaulo	leftt ^= work;
387214501Srpaulo	right ^= (work << 16);
388214501Srpaulo	work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
389214501Srpaulo	leftt ^= work;
390214501Srpaulo	right ^= (work << 4);
391214501Srpaulo
392214501Srpaulo	block[0] = right;
393214501Srpaulo	block[1] = leftt;
394214501Srpaulo}
395214501Srpaulo
396214501Srpaulo
397214501Srpaulo/* wpa_supplicant/hostapd specific wrapper */
398214501Srpaulo
399214501Srpaulovoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
400214501Srpaulo{
401214501Srpaulo	u8 pkey[8], next, tmp;
402214501Srpaulo	int i;
403214501Srpaulo	u32 ek[32], work[2];
404214501Srpaulo
405214501Srpaulo	/* Add parity bits to the key */
406214501Srpaulo	next = 0;
407214501Srpaulo	for (i = 0; i < 7; i++) {
408214501Srpaulo		tmp = key[i];
409214501Srpaulo		pkey[i] = (tmp >> i) | next | 1;
410214501Srpaulo		next = tmp << (7 - i);
411214501Srpaulo	}
412214501Srpaulo	pkey[i] = next | 1;
413214501Srpaulo
414214501Srpaulo	deskey(pkey, 0, ek);
415214501Srpaulo
416214501Srpaulo	work[0] = WPA_GET_BE32(clear);
417214501Srpaulo	work[1] = WPA_GET_BE32(clear + 4);
418214501Srpaulo	desfunc(work, ek);
419214501Srpaulo	WPA_PUT_BE32(cypher, work[0]);
420214501Srpaulo	WPA_PUT_BE32(cypher + 4, work[1]);
421214501Srpaulo
422214501Srpaulo	os_memset(pkey, 0, sizeof(pkey));
423214501Srpaulo	os_memset(ek, 0, sizeof(ek));
424214501Srpaulo}
425214501Srpaulo
426214501Srpaulo
427214501Srpaulovoid des_key_setup(const u8 *key, u32 *ek, u32 *dk)
428214501Srpaulo{
429214501Srpaulo	deskey(key, 0, ek);
430214501Srpaulo	deskey(key, 1, dk);
431214501Srpaulo}
432214501Srpaulo
433214501Srpaulo
434214501Srpaulovoid des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt)
435214501Srpaulo{
436214501Srpaulo	u32 work[2];
437214501Srpaulo	work[0] = WPA_GET_BE32(plain);
438214501Srpaulo	work[1] = WPA_GET_BE32(plain + 4);
439214501Srpaulo	desfunc(work, ek);
440214501Srpaulo	WPA_PUT_BE32(crypt, work[0]);
441214501Srpaulo	WPA_PUT_BE32(crypt + 4, work[1]);
442214501Srpaulo}
443214501Srpaulo
444214501Srpaulo
445214501Srpaulovoid des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain)
446214501Srpaulo{
447214501Srpaulo	u32 work[2];
448214501Srpaulo	work[0] = WPA_GET_BE32(crypt);
449214501Srpaulo	work[1] = WPA_GET_BE32(crypt + 4);
450214501Srpaulo	desfunc(work, dk);
451214501Srpaulo	WPA_PUT_BE32(plain, work[0]);
452214501Srpaulo	WPA_PUT_BE32(plain + 4, work[1]);
453214501Srpaulo}
454214501Srpaulo
455214501Srpaulo
456214501Srpaulovoid des3_key_setup(const u8 *key, struct des3_key_s *dkey)
457214501Srpaulo{
458214501Srpaulo	deskey(key, 0, dkey->ek[0]);
459214501Srpaulo	deskey(key + 8, 1, dkey->ek[1]);
460214501Srpaulo	deskey(key + 16, 0, dkey->ek[2]);
461214501Srpaulo
462214501Srpaulo	deskey(key, 1, dkey->dk[2]);
463214501Srpaulo	deskey(key + 8, 0, dkey->dk[1]);
464214501Srpaulo	deskey(key + 16, 1, dkey->dk[0]);
465214501Srpaulo}
466214501Srpaulo
467214501Srpaulo
468214501Srpaulovoid des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt)
469214501Srpaulo{
470214501Srpaulo	u32 work[2];
471214501Srpaulo
472214501Srpaulo	work[0] = WPA_GET_BE32(plain);
473214501Srpaulo	work[1] = WPA_GET_BE32(plain + 4);
474214501Srpaulo	desfunc(work, key->ek[0]);
475214501Srpaulo	desfunc(work, key->ek[1]);
476214501Srpaulo	desfunc(work, key->ek[2]);
477214501Srpaulo	WPA_PUT_BE32(crypt, work[0]);
478214501Srpaulo	WPA_PUT_BE32(crypt + 4, work[1]);
479214501Srpaulo}
480214501Srpaulo
481214501Srpaulo
482214501Srpaulovoid des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain)
483214501Srpaulo{
484214501Srpaulo	u32 work[2];
485214501Srpaulo
486214501Srpaulo	work[0] = WPA_GET_BE32(crypt);
487214501Srpaulo	work[1] = WPA_GET_BE32(crypt + 4);
488214501Srpaulo	desfunc(work, key->dk[0]);
489214501Srpaulo	desfunc(work, key->dk[1]);
490214501Srpaulo	desfunc(work, key->dk[2]);
491214501Srpaulo	WPA_PUT_BE32(plain, work[0]);
492214501Srpaulo	WPA_PUT_BE32(plain + 4, work[1]);
493214501Srpaulo}
494