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