1/*
2 * Cryptographic API.
3 *
4 * DES & Triple DES EDE Cipher Algorithms.
5 *
6 * Copyright (c) 2005 Dag Arne Osvik <da@osvik.no>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 */
14
15#include <asm/byteorder.h>
16#include <linux/bitops.h>
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/errno.h>
20#include <linux/crypto.h>
21#include <linux/types.h>
22
23#define DES_KEY_SIZE		8
24#define DES_EXPKEY_WORDS	32
25#define DES_BLOCK_SIZE		8
26
27#define DES3_EDE_KEY_SIZE	(3 * DES_KEY_SIZE)
28#define DES3_EDE_EXPKEY_WORDS	(3 * DES_EXPKEY_WORDS)
29#define DES3_EDE_BLOCK_SIZE	DES_BLOCK_SIZE
30
31#define ROL(x, r) ((x) = rol32((x), (r)))
32#define ROR(x, r) ((x) = ror32((x), (r)))
33
34struct des_ctx {
35	u32 expkey[DES_EXPKEY_WORDS];
36};
37
38struct des3_ede_ctx {
39	u32 expkey[DES3_EDE_EXPKEY_WORDS];
40};
41
42/* Lookup tables for key expansion */
43
44static const u8 pc1[256] = {
45	0x00, 0x00, 0x40, 0x04, 0x10, 0x10, 0x50, 0x14,
46	0x04, 0x40, 0x44, 0x44, 0x14, 0x50, 0x54, 0x54,
47	0x02, 0x02, 0x42, 0x06, 0x12, 0x12, 0x52, 0x16,
48	0x06, 0x42, 0x46, 0x46, 0x16, 0x52, 0x56, 0x56,
49	0x80, 0x08, 0xc0, 0x0c, 0x90, 0x18, 0xd0, 0x1c,
50	0x84, 0x48, 0xc4, 0x4c, 0x94, 0x58, 0xd4, 0x5c,
51	0x82, 0x0a, 0xc2, 0x0e, 0x92, 0x1a, 0xd2, 0x1e,
52	0x86, 0x4a, 0xc6, 0x4e, 0x96, 0x5a, 0xd6, 0x5e,
53	0x20, 0x20, 0x60, 0x24, 0x30, 0x30, 0x70, 0x34,
54	0x24, 0x60, 0x64, 0x64, 0x34, 0x70, 0x74, 0x74,
55	0x22, 0x22, 0x62, 0x26, 0x32, 0x32, 0x72, 0x36,
56	0x26, 0x62, 0x66, 0x66, 0x36, 0x72, 0x76, 0x76,
57	0xa0, 0x28, 0xe0, 0x2c, 0xb0, 0x38, 0xf0, 0x3c,
58	0xa4, 0x68, 0xe4, 0x6c, 0xb4, 0x78, 0xf4, 0x7c,
59	0xa2, 0x2a, 0xe2, 0x2e, 0xb2, 0x3a, 0xf2, 0x3e,
60	0xa6, 0x6a, 0xe6, 0x6e, 0xb6, 0x7a, 0xf6, 0x7e,
61	0x08, 0x80, 0x48, 0x84, 0x18, 0x90, 0x58, 0x94,
62	0x0c, 0xc0, 0x4c, 0xc4, 0x1c, 0xd0, 0x5c, 0xd4,
63	0x0a, 0x82, 0x4a, 0x86, 0x1a, 0x92, 0x5a, 0x96,
64	0x0e, 0xc2, 0x4e, 0xc6, 0x1e, 0xd2, 0x5e, 0xd6,
65	0x88, 0x88, 0xc8, 0x8c, 0x98, 0x98, 0xd8, 0x9c,
66	0x8c, 0xc8, 0xcc, 0xcc, 0x9c, 0xd8, 0xdc, 0xdc,
67	0x8a, 0x8a, 0xca, 0x8e, 0x9a, 0x9a, 0xda, 0x9e,
68	0x8e, 0xca, 0xce, 0xce, 0x9e, 0xda, 0xde, 0xde,
69	0x28, 0xa0, 0x68, 0xa4, 0x38, 0xb0, 0x78, 0xb4,
70	0x2c, 0xe0, 0x6c, 0xe4, 0x3c, 0xf0, 0x7c, 0xf4,
71	0x2a, 0xa2, 0x6a, 0xa6, 0x3a, 0xb2, 0x7a, 0xb6,
72	0x2e, 0xe2, 0x6e, 0xe6, 0x3e, 0xf2, 0x7e, 0xf6,
73	0xa8, 0xa8, 0xe8, 0xac, 0xb8, 0xb8, 0xf8, 0xbc,
74	0xac, 0xe8, 0xec, 0xec, 0xbc, 0xf8, 0xfc, 0xfc,
75	0xaa, 0xaa, 0xea, 0xae, 0xba, 0xba, 0xfa, 0xbe,
76	0xae, 0xea, 0xee, 0xee, 0xbe, 0xfa, 0xfe, 0xfe
77};
78
79static const u8 rs[256] = {
80	0x00, 0x00, 0x80, 0x80, 0x02, 0x02, 0x82, 0x82,
81	0x04, 0x04, 0x84, 0x84, 0x06, 0x06, 0x86, 0x86,
82	0x08, 0x08, 0x88, 0x88, 0x0a, 0x0a, 0x8a, 0x8a,
83	0x0c, 0x0c, 0x8c, 0x8c, 0x0e, 0x0e, 0x8e, 0x8e,
84	0x10, 0x10, 0x90, 0x90, 0x12, 0x12, 0x92, 0x92,
85	0x14, 0x14, 0x94, 0x94, 0x16, 0x16, 0x96, 0x96,
86	0x18, 0x18, 0x98, 0x98, 0x1a, 0x1a, 0x9a, 0x9a,
87	0x1c, 0x1c, 0x9c, 0x9c, 0x1e, 0x1e, 0x9e, 0x9e,
88	0x20, 0x20, 0xa0, 0xa0, 0x22, 0x22, 0xa2, 0xa2,
89	0x24, 0x24, 0xa4, 0xa4, 0x26, 0x26, 0xa6, 0xa6,
90	0x28, 0x28, 0xa8, 0xa8, 0x2a, 0x2a, 0xaa, 0xaa,
91	0x2c, 0x2c, 0xac, 0xac, 0x2e, 0x2e, 0xae, 0xae,
92	0x30, 0x30, 0xb0, 0xb0, 0x32, 0x32, 0xb2, 0xb2,
93	0x34, 0x34, 0xb4, 0xb4, 0x36, 0x36, 0xb6, 0xb6,
94	0x38, 0x38, 0xb8, 0xb8, 0x3a, 0x3a, 0xba, 0xba,
95	0x3c, 0x3c, 0xbc, 0xbc, 0x3e, 0x3e, 0xbe, 0xbe,
96	0x40, 0x40, 0xc0, 0xc0, 0x42, 0x42, 0xc2, 0xc2,
97	0x44, 0x44, 0xc4, 0xc4, 0x46, 0x46, 0xc6, 0xc6,
98	0x48, 0x48, 0xc8, 0xc8, 0x4a, 0x4a, 0xca, 0xca,
99	0x4c, 0x4c, 0xcc, 0xcc, 0x4e, 0x4e, 0xce, 0xce,
100	0x50, 0x50, 0xd0, 0xd0, 0x52, 0x52, 0xd2, 0xd2,
101	0x54, 0x54, 0xd4, 0xd4, 0x56, 0x56, 0xd6, 0xd6,
102	0x58, 0x58, 0xd8, 0xd8, 0x5a, 0x5a, 0xda, 0xda,
103	0x5c, 0x5c, 0xdc, 0xdc, 0x5e, 0x5e, 0xde, 0xde,
104	0x60, 0x60, 0xe0, 0xe0, 0x62, 0x62, 0xe2, 0xe2,
105	0x64, 0x64, 0xe4, 0xe4, 0x66, 0x66, 0xe6, 0xe6,
106	0x68, 0x68, 0xe8, 0xe8, 0x6a, 0x6a, 0xea, 0xea,
107	0x6c, 0x6c, 0xec, 0xec, 0x6e, 0x6e, 0xee, 0xee,
108	0x70, 0x70, 0xf0, 0xf0, 0x72, 0x72, 0xf2, 0xf2,
109	0x74, 0x74, 0xf4, 0xf4, 0x76, 0x76, 0xf6, 0xf6,
110	0x78, 0x78, 0xf8, 0xf8, 0x7a, 0x7a, 0xfa, 0xfa,
111	0x7c, 0x7c, 0xfc, 0xfc, 0x7e, 0x7e, 0xfe, 0xfe
112};
113
114static const u32 pc2[1024] = {
115	0x00000000, 0x00000000, 0x00000000, 0x00000000,
116	0x00040000, 0x00000000, 0x04000000, 0x00100000,
117	0x00400000, 0x00000008, 0x00000800, 0x40000000,
118	0x00440000, 0x00000008, 0x04000800, 0x40100000,
119	0x00000400, 0x00000020, 0x08000000, 0x00000100,
120	0x00040400, 0x00000020, 0x0c000000, 0x00100100,
121	0x00400400, 0x00000028, 0x08000800, 0x40000100,
122	0x00440400, 0x00000028, 0x0c000800, 0x40100100,
123	0x80000000, 0x00000010, 0x00000000, 0x00800000,
124	0x80040000, 0x00000010, 0x04000000, 0x00900000,
125	0x80400000, 0x00000018, 0x00000800, 0x40800000,
126	0x80440000, 0x00000018, 0x04000800, 0x40900000,
127	0x80000400, 0x00000030, 0x08000000, 0x00800100,
128	0x80040400, 0x00000030, 0x0c000000, 0x00900100,
129	0x80400400, 0x00000038, 0x08000800, 0x40800100,
130	0x80440400, 0x00000038, 0x0c000800, 0x40900100,
131	0x10000000, 0x00000000, 0x00200000, 0x00001000,
132	0x10040000, 0x00000000, 0x04200000, 0x00101000,
133	0x10400000, 0x00000008, 0x00200800, 0x40001000,
134	0x10440000, 0x00000008, 0x04200800, 0x40101000,
135	0x10000400, 0x00000020, 0x08200000, 0x00001100,
136	0x10040400, 0x00000020, 0x0c200000, 0x00101100,
137	0x10400400, 0x00000028, 0x08200800, 0x40001100,
138	0x10440400, 0x00000028, 0x0c200800, 0x40101100,
139	0x90000000, 0x00000010, 0x00200000, 0x00801000,
140	0x90040000, 0x00000010, 0x04200000, 0x00901000,
141	0x90400000, 0x00000018, 0x00200800, 0x40801000,
142	0x90440000, 0x00000018, 0x04200800, 0x40901000,
143	0x90000400, 0x00000030, 0x08200000, 0x00801100,
144	0x90040400, 0x00000030, 0x0c200000, 0x00901100,
145	0x90400400, 0x00000038, 0x08200800, 0x40801100,
146	0x90440400, 0x00000038, 0x0c200800, 0x40901100,
147	0x00000200, 0x00080000, 0x00000000, 0x00000004,
148	0x00040200, 0x00080000, 0x04000000, 0x00100004,
149	0x00400200, 0x00080008, 0x00000800, 0x40000004,
150	0x00440200, 0x00080008, 0x04000800, 0x40100004,
151	0x00000600, 0x00080020, 0x08000000, 0x00000104,
152	0x00040600, 0x00080020, 0x0c000000, 0x00100104,
153	0x00400600, 0x00080028, 0x08000800, 0x40000104,
154	0x00440600, 0x00080028, 0x0c000800, 0x40100104,
155	0x80000200, 0x00080010, 0x00000000, 0x00800004,
156	0x80040200, 0x00080010, 0x04000000, 0x00900004,
157	0x80400200, 0x00080018, 0x00000800, 0x40800004,
158	0x80440200, 0x00080018, 0x04000800, 0x40900004,
159	0x80000600, 0x00080030, 0x08000000, 0x00800104,
160	0x80040600, 0x00080030, 0x0c000000, 0x00900104,
161	0x80400600, 0x00080038, 0x08000800, 0x40800104,
162	0x80440600, 0x00080038, 0x0c000800, 0x40900104,
163	0x10000200, 0x00080000, 0x00200000, 0x00001004,
164	0x10040200, 0x00080000, 0x04200000, 0x00101004,
165	0x10400200, 0x00080008, 0x00200800, 0x40001004,
166	0x10440200, 0x00080008, 0x04200800, 0x40101004,
167	0x10000600, 0x00080020, 0x08200000, 0x00001104,
168	0x10040600, 0x00080020, 0x0c200000, 0x00101104,
169	0x10400600, 0x00080028, 0x08200800, 0x40001104,
170	0x10440600, 0x00080028, 0x0c200800, 0x40101104,
171	0x90000200, 0x00080010, 0x00200000, 0x00801004,
172	0x90040200, 0x00080010, 0x04200000, 0x00901004,
173	0x90400200, 0x00080018, 0x00200800, 0x40801004,
174	0x90440200, 0x00080018, 0x04200800, 0x40901004,
175	0x90000600, 0x00080030, 0x08200000, 0x00801104,
176	0x90040600, 0x00080030, 0x0c200000, 0x00901104,
177	0x90400600, 0x00080038, 0x08200800, 0x40801104,
178	0x90440600, 0x00080038, 0x0c200800, 0x40901104,
179	0x00000002, 0x00002000, 0x20000000, 0x00000001,
180	0x00040002, 0x00002000, 0x24000000, 0x00100001,
181	0x00400002, 0x00002008, 0x20000800, 0x40000001,
182	0x00440002, 0x00002008, 0x24000800, 0x40100001,
183	0x00000402, 0x00002020, 0x28000000, 0x00000101,
184	0x00040402, 0x00002020, 0x2c000000, 0x00100101,
185	0x00400402, 0x00002028, 0x28000800, 0x40000101,
186	0x00440402, 0x00002028, 0x2c000800, 0x40100101,
187	0x80000002, 0x00002010, 0x20000000, 0x00800001,
188	0x80040002, 0x00002010, 0x24000000, 0x00900001,
189	0x80400002, 0x00002018, 0x20000800, 0x40800001,
190	0x80440002, 0x00002018, 0x24000800, 0x40900001,
191	0x80000402, 0x00002030, 0x28000000, 0x00800101,
192	0x80040402, 0x00002030, 0x2c000000, 0x00900101,
193	0x80400402, 0x00002038, 0x28000800, 0x40800101,
194	0x80440402, 0x00002038, 0x2c000800, 0x40900101,
195	0x10000002, 0x00002000, 0x20200000, 0x00001001,
196	0x10040002, 0x00002000, 0x24200000, 0x00101001,
197	0x10400002, 0x00002008, 0x20200800, 0x40001001,
198	0x10440002, 0x00002008, 0x24200800, 0x40101001,
199	0x10000402, 0x00002020, 0x28200000, 0x00001101,
200	0x10040402, 0x00002020, 0x2c200000, 0x00101101,
201	0x10400402, 0x00002028, 0x28200800, 0x40001101,
202	0x10440402, 0x00002028, 0x2c200800, 0x40101101,
203	0x90000002, 0x00002010, 0x20200000, 0x00801001,
204	0x90040002, 0x00002010, 0x24200000, 0x00901001,
205	0x90400002, 0x00002018, 0x20200800, 0x40801001,
206	0x90440002, 0x00002018, 0x24200800, 0x40901001,
207	0x90000402, 0x00002030, 0x28200000, 0x00801101,
208	0x90040402, 0x00002030, 0x2c200000, 0x00901101,
209	0x90400402, 0x00002038, 0x28200800, 0x40801101,
210	0x90440402, 0x00002038, 0x2c200800, 0x40901101,
211	0x00000202, 0x00082000, 0x20000000, 0x00000005,
212	0x00040202, 0x00082000, 0x24000000, 0x00100005,
213	0x00400202, 0x00082008, 0x20000800, 0x40000005,
214	0x00440202, 0x00082008, 0x24000800, 0x40100005,
215	0x00000602, 0x00082020, 0x28000000, 0x00000105,
216	0x00040602, 0x00082020, 0x2c000000, 0x00100105,
217	0x00400602, 0x00082028, 0x28000800, 0x40000105,
218	0x00440602, 0x00082028, 0x2c000800, 0x40100105,
219	0x80000202, 0x00082010, 0x20000000, 0x00800005,
220	0x80040202, 0x00082010, 0x24000000, 0x00900005,
221	0x80400202, 0x00082018, 0x20000800, 0x40800005,
222	0x80440202, 0x00082018, 0x24000800, 0x40900005,
223	0x80000602, 0x00082030, 0x28000000, 0x00800105,
224	0x80040602, 0x00082030, 0x2c000000, 0x00900105,
225	0x80400602, 0x00082038, 0x28000800, 0x40800105,
226	0x80440602, 0x00082038, 0x2c000800, 0x40900105,
227	0x10000202, 0x00082000, 0x20200000, 0x00001005,
228	0x10040202, 0x00082000, 0x24200000, 0x00101005,
229	0x10400202, 0x00082008, 0x20200800, 0x40001005,
230	0x10440202, 0x00082008, 0x24200800, 0x40101005,
231	0x10000602, 0x00082020, 0x28200000, 0x00001105,
232	0x10040602, 0x00082020, 0x2c200000, 0x00101105,
233	0x10400602, 0x00082028, 0x28200800, 0x40001105,
234	0x10440602, 0x00082028, 0x2c200800, 0x40101105,
235	0x90000202, 0x00082010, 0x20200000, 0x00801005,
236	0x90040202, 0x00082010, 0x24200000, 0x00901005,
237	0x90400202, 0x00082018, 0x20200800, 0x40801005,
238	0x90440202, 0x00082018, 0x24200800, 0x40901005,
239	0x90000602, 0x00082030, 0x28200000, 0x00801105,
240	0x90040602, 0x00082030, 0x2c200000, 0x00901105,
241	0x90400602, 0x00082038, 0x28200800, 0x40801105,
242	0x90440602, 0x00082038, 0x2c200800, 0x40901105,
243
244	0x00000000, 0x00000000, 0x00000000, 0x00000000,
245	0x00000000, 0x00000008, 0x00080000, 0x10000000,
246	0x02000000, 0x00000000, 0x00000080, 0x00001000,
247	0x02000000, 0x00000008, 0x00080080, 0x10001000,
248	0x00004000, 0x00000000, 0x00000040, 0x00040000,
249	0x00004000, 0x00000008, 0x00080040, 0x10040000,
250	0x02004000, 0x00000000, 0x000000c0, 0x00041000,
251	0x02004000, 0x00000008, 0x000800c0, 0x10041000,
252	0x00020000, 0x00008000, 0x08000000, 0x00200000,
253	0x00020000, 0x00008008, 0x08080000, 0x10200000,
254	0x02020000, 0x00008000, 0x08000080, 0x00201000,
255	0x02020000, 0x00008008, 0x08080080, 0x10201000,
256	0x00024000, 0x00008000, 0x08000040, 0x00240000,
257	0x00024000, 0x00008008, 0x08080040, 0x10240000,
258	0x02024000, 0x00008000, 0x080000c0, 0x00241000,
259	0x02024000, 0x00008008, 0x080800c0, 0x10241000,
260	0x00000000, 0x01000000, 0x00002000, 0x00000020,
261	0x00000000, 0x01000008, 0x00082000, 0x10000020,
262	0x02000000, 0x01000000, 0x00002080, 0x00001020,
263	0x02000000, 0x01000008, 0x00082080, 0x10001020,
264	0x00004000, 0x01000000, 0x00002040, 0x00040020,
265	0x00004000, 0x01000008, 0x00082040, 0x10040020,
266	0x02004000, 0x01000000, 0x000020c0, 0x00041020,
267	0x02004000, 0x01000008, 0x000820c0, 0x10041020,
268	0x00020000, 0x01008000, 0x08002000, 0x00200020,
269	0x00020000, 0x01008008, 0x08082000, 0x10200020,
270	0x02020000, 0x01008000, 0x08002080, 0x00201020,
271	0x02020000, 0x01008008, 0x08082080, 0x10201020,
272	0x00024000, 0x01008000, 0x08002040, 0x00240020,
273	0x00024000, 0x01008008, 0x08082040, 0x10240020,
274	0x02024000, 0x01008000, 0x080020c0, 0x00241020,
275	0x02024000, 0x01008008, 0x080820c0, 0x10241020,
276	0x00000400, 0x04000000, 0x00100000, 0x00000004,
277	0x00000400, 0x04000008, 0x00180000, 0x10000004,
278	0x02000400, 0x04000000, 0x00100080, 0x00001004,
279	0x02000400, 0x04000008, 0x00180080, 0x10001004,
280	0x00004400, 0x04000000, 0x00100040, 0x00040004,
281	0x00004400, 0x04000008, 0x00180040, 0x10040004,
282	0x02004400, 0x04000000, 0x001000c0, 0x00041004,
283	0x02004400, 0x04000008, 0x001800c0, 0x10041004,
284	0x00020400, 0x04008000, 0x08100000, 0x00200004,
285	0x00020400, 0x04008008, 0x08180000, 0x10200004,
286	0x02020400, 0x04008000, 0x08100080, 0x00201004,
287	0x02020400, 0x04008008, 0x08180080, 0x10201004,
288	0x00024400, 0x04008000, 0x08100040, 0x00240004,
289	0x00024400, 0x04008008, 0x08180040, 0x10240004,
290	0x02024400, 0x04008000, 0x081000c0, 0x00241004,
291	0x02024400, 0x04008008, 0x081800c0, 0x10241004,
292	0x00000400, 0x05000000, 0x00102000, 0x00000024,
293	0x00000400, 0x05000008, 0x00182000, 0x10000024,
294	0x02000400, 0x05000000, 0x00102080, 0x00001024,
295	0x02000400, 0x05000008, 0x00182080, 0x10001024,
296	0x00004400, 0x05000000, 0x00102040, 0x00040024,
297	0x00004400, 0x05000008, 0x00182040, 0x10040024,
298	0x02004400, 0x05000000, 0x001020c0, 0x00041024,
299	0x02004400, 0x05000008, 0x001820c0, 0x10041024,
300	0x00020400, 0x05008000, 0x08102000, 0x00200024,
301	0x00020400, 0x05008008, 0x08182000, 0x10200024,
302	0x02020400, 0x05008000, 0x08102080, 0x00201024,
303	0x02020400, 0x05008008, 0x08182080, 0x10201024,
304	0x00024400, 0x05008000, 0x08102040, 0x00240024,
305	0x00024400, 0x05008008, 0x08182040, 0x10240024,
306	0x02024400, 0x05008000, 0x081020c0, 0x00241024,
307	0x02024400, 0x05008008, 0x081820c0, 0x10241024,
308	0x00000800, 0x00010000, 0x20000000, 0x00000010,
309	0x00000800, 0x00010008, 0x20080000, 0x10000010,
310	0x02000800, 0x00010000, 0x20000080, 0x00001010,
311	0x02000800, 0x00010008, 0x20080080, 0x10001010,
312	0x00004800, 0x00010000, 0x20000040, 0x00040010,
313	0x00004800, 0x00010008, 0x20080040, 0x10040010,
314	0x02004800, 0x00010000, 0x200000c0, 0x00041010,
315	0x02004800, 0x00010008, 0x200800c0, 0x10041010,
316	0x00020800, 0x00018000, 0x28000000, 0x00200010,
317	0x00020800, 0x00018008, 0x28080000, 0x10200010,
318	0x02020800, 0x00018000, 0x28000080, 0x00201010,
319	0x02020800, 0x00018008, 0x28080080, 0x10201010,
320	0x00024800, 0x00018000, 0x28000040, 0x00240010,
321	0x00024800, 0x00018008, 0x28080040, 0x10240010,
322	0x02024800, 0x00018000, 0x280000c0, 0x00241010,
323	0x02024800, 0x00018008, 0x280800c0, 0x10241010,
324	0x00000800, 0x01010000, 0x20002000, 0x00000030,
325	0x00000800, 0x01010008, 0x20082000, 0x10000030,
326	0x02000800, 0x01010000, 0x20002080, 0x00001030,
327	0x02000800, 0x01010008, 0x20082080, 0x10001030,
328	0x00004800, 0x01010000, 0x20002040, 0x00040030,
329	0x00004800, 0x01010008, 0x20082040, 0x10040030,
330	0x02004800, 0x01010000, 0x200020c0, 0x00041030,
331	0x02004800, 0x01010008, 0x200820c0, 0x10041030,
332	0x00020800, 0x01018000, 0x28002000, 0x00200030,
333	0x00020800, 0x01018008, 0x28082000, 0x10200030,
334	0x02020800, 0x01018000, 0x28002080, 0x00201030,
335	0x02020800, 0x01018008, 0x28082080, 0x10201030,
336	0x00024800, 0x01018000, 0x28002040, 0x00240030,
337	0x00024800, 0x01018008, 0x28082040, 0x10240030,
338	0x02024800, 0x01018000, 0x280020c0, 0x00241030,
339	0x02024800, 0x01018008, 0x280820c0, 0x10241030,
340	0x00000c00, 0x04010000, 0x20100000, 0x00000014,
341	0x00000c00, 0x04010008, 0x20180000, 0x10000014,
342	0x02000c00, 0x04010000, 0x20100080, 0x00001014,
343	0x02000c00, 0x04010008, 0x20180080, 0x10001014,
344	0x00004c00, 0x04010000, 0x20100040, 0x00040014,
345	0x00004c00, 0x04010008, 0x20180040, 0x10040014,
346	0x02004c00, 0x04010000, 0x201000c0, 0x00041014,
347	0x02004c00, 0x04010008, 0x201800c0, 0x10041014,
348	0x00020c00, 0x04018000, 0x28100000, 0x00200014,
349	0x00020c00, 0x04018008, 0x28180000, 0x10200014,
350	0x02020c00, 0x04018000, 0x28100080, 0x00201014,
351	0x02020c00, 0x04018008, 0x28180080, 0x10201014,
352	0x00024c00, 0x04018000, 0x28100040, 0x00240014,
353	0x00024c00, 0x04018008, 0x28180040, 0x10240014,
354	0x02024c00, 0x04018000, 0x281000c0, 0x00241014,
355	0x02024c00, 0x04018008, 0x281800c0, 0x10241014,
356	0x00000c00, 0x05010000, 0x20102000, 0x00000034,
357	0x00000c00, 0x05010008, 0x20182000, 0x10000034,
358	0x02000c00, 0x05010000, 0x20102080, 0x00001034,
359	0x02000c00, 0x05010008, 0x20182080, 0x10001034,
360	0x00004c00, 0x05010000, 0x20102040, 0x00040034,
361	0x00004c00, 0x05010008, 0x20182040, 0x10040034,
362	0x02004c00, 0x05010000, 0x201020c0, 0x00041034,
363	0x02004c00, 0x05010008, 0x201820c0, 0x10041034,
364	0x00020c00, 0x05018000, 0x28102000, 0x00200034,
365	0x00020c00, 0x05018008, 0x28182000, 0x10200034,
366	0x02020c00, 0x05018000, 0x28102080, 0x00201034,
367	0x02020c00, 0x05018008, 0x28182080, 0x10201034,
368	0x00024c00, 0x05018000, 0x28102040, 0x00240034,
369	0x00024c00, 0x05018008, 0x28182040, 0x10240034,
370	0x02024c00, 0x05018000, 0x281020c0, 0x00241034,
371	0x02024c00, 0x05018008, 0x281820c0, 0x10241034
372};
373
374/* S-box lookup tables */
375
376static const u32 S1[64] = {
377	0x01010400, 0x00000000, 0x00010000, 0x01010404,
378	0x01010004, 0x00010404, 0x00000004, 0x00010000,
379	0x00000400, 0x01010400, 0x01010404, 0x00000400,
380	0x01000404, 0x01010004, 0x01000000, 0x00000004,
381	0x00000404, 0x01000400, 0x01000400, 0x00010400,
382	0x00010400, 0x01010000, 0x01010000, 0x01000404,
383	0x00010004, 0x01000004, 0x01000004, 0x00010004,
384	0x00000000, 0x00000404, 0x00010404, 0x01000000,
385	0x00010000, 0x01010404, 0x00000004, 0x01010000,
386	0x01010400, 0x01000000, 0x01000000, 0x00000400,
387	0x01010004, 0x00010000, 0x00010400, 0x01000004,
388	0x00000400, 0x00000004, 0x01000404, 0x00010404,
389	0x01010404, 0x00010004, 0x01010000, 0x01000404,
390	0x01000004, 0x00000404, 0x00010404, 0x01010400,
391	0x00000404, 0x01000400, 0x01000400, 0x00000000,
392	0x00010004, 0x00010400, 0x00000000, 0x01010004
393};
394
395static const u32 S2[64] = {
396	0x80108020, 0x80008000, 0x00008000, 0x00108020,
397	0x00100000, 0x00000020, 0x80100020, 0x80008020,
398	0x80000020, 0x80108020, 0x80108000, 0x80000000,
399	0x80008000, 0x00100000, 0x00000020, 0x80100020,
400	0x00108000, 0x00100020, 0x80008020, 0x00000000,
401	0x80000000, 0x00008000, 0x00108020, 0x80100000,
402	0x00100020, 0x80000020, 0x00000000, 0x00108000,
403	0x00008020, 0x80108000, 0x80100000, 0x00008020,
404	0x00000000, 0x00108020, 0x80100020, 0x00100000,
405	0x80008020, 0x80100000, 0x80108000, 0x00008000,
406	0x80100000, 0x80008000, 0x00000020, 0x80108020,
407	0x00108020, 0x00000020, 0x00008000, 0x80000000,
408	0x00008020, 0x80108000, 0x00100000, 0x80000020,
409	0x00100020, 0x80008020, 0x80000020, 0x00100020,
410	0x00108000, 0x00000000, 0x80008000, 0x00008020,
411	0x80000000, 0x80100020, 0x80108020, 0x00108000
412};
413
414static const u32 S3[64] = {
415	0x00000208, 0x08020200, 0x00000000, 0x08020008,
416	0x08000200, 0x00000000, 0x00020208, 0x08000200,
417	0x00020008, 0x08000008, 0x08000008, 0x00020000,
418	0x08020208, 0x00020008, 0x08020000, 0x00000208,
419	0x08000000, 0x00000008, 0x08020200, 0x00000200,
420	0x00020200, 0x08020000, 0x08020008, 0x00020208,
421	0x08000208, 0x00020200, 0x00020000, 0x08000208,
422	0x00000008, 0x08020208, 0x00000200, 0x08000000,
423	0x08020200, 0x08000000, 0x00020008, 0x00000208,
424	0x00020000, 0x08020200, 0x08000200, 0x00000000,
425	0x00000200, 0x00020008, 0x08020208, 0x08000200,
426	0x08000008, 0x00000200, 0x00000000, 0x08020008,
427	0x08000208, 0x00020000, 0x08000000, 0x08020208,
428	0x00000008, 0x00020208, 0x00020200, 0x08000008,
429	0x08020000, 0x08000208, 0x00000208, 0x08020000,
430	0x00020208, 0x00000008, 0x08020008, 0x00020200
431};
432
433static const u32 S4[64] = {
434	0x00802001, 0x00002081, 0x00002081, 0x00000080,
435	0x00802080, 0x00800081, 0x00800001, 0x00002001,
436	0x00000000, 0x00802000, 0x00802000, 0x00802081,
437	0x00000081, 0x00000000, 0x00800080, 0x00800001,
438	0x00000001, 0x00002000, 0x00800000, 0x00802001,
439	0x00000080, 0x00800000, 0x00002001, 0x00002080,
440	0x00800081, 0x00000001, 0x00002080, 0x00800080,
441	0x00002000, 0x00802080, 0x00802081, 0x00000081,
442	0x00800080, 0x00800001, 0x00802000, 0x00802081,
443	0x00000081, 0x00000000, 0x00000000, 0x00802000,
444	0x00002080, 0x00800080, 0x00800081, 0x00000001,
445	0x00802001, 0x00002081, 0x00002081, 0x00000080,
446	0x00802081, 0x00000081, 0x00000001, 0x00002000,
447	0x00800001, 0x00002001, 0x00802080, 0x00800081,
448	0x00002001, 0x00002080, 0x00800000, 0x00802001,
449	0x00000080, 0x00800000, 0x00002000, 0x00802080
450};
451
452static const u32 S5[64] = {
453	0x00000100, 0x02080100, 0x02080000, 0x42000100,
454	0x00080000, 0x00000100, 0x40000000, 0x02080000,
455	0x40080100, 0x00080000, 0x02000100, 0x40080100,
456	0x42000100, 0x42080000, 0x00080100, 0x40000000,
457	0x02000000, 0x40080000, 0x40080000, 0x00000000,
458	0x40000100, 0x42080100, 0x42080100, 0x02000100,
459	0x42080000, 0x40000100, 0x00000000, 0x42000000,
460	0x02080100, 0x02000000, 0x42000000, 0x00080100,
461	0x00080000, 0x42000100, 0x00000100, 0x02000000,
462	0x40000000, 0x02080000, 0x42000100, 0x40080100,
463	0x02000100, 0x40000000, 0x42080000, 0x02080100,
464	0x40080100, 0x00000100, 0x02000000, 0x42080000,
465	0x42080100, 0x00080100, 0x42000000, 0x42080100,
466	0x02080000, 0x00000000, 0x40080000, 0x42000000,
467	0x00080100, 0x02000100, 0x40000100, 0x00080000,
468	0x00000000, 0x40080000, 0x02080100, 0x40000100
469};
470
471static const u32 S6[64] = {
472	0x20000010, 0x20400000, 0x00004000, 0x20404010,
473	0x20400000, 0x00000010, 0x20404010, 0x00400000,
474	0x20004000, 0x00404010, 0x00400000, 0x20000010,
475	0x00400010, 0x20004000, 0x20000000, 0x00004010,
476	0x00000000, 0x00400010, 0x20004010, 0x00004000,
477	0x00404000, 0x20004010, 0x00000010, 0x20400010,
478	0x20400010, 0x00000000, 0x00404010, 0x20404000,
479	0x00004010, 0x00404000, 0x20404000, 0x20000000,
480	0x20004000, 0x00000010, 0x20400010, 0x00404000,
481	0x20404010, 0x00400000, 0x00004010, 0x20000010,
482	0x00400000, 0x20004000, 0x20000000, 0x00004010,
483	0x20000010, 0x20404010, 0x00404000, 0x20400000,
484	0x00404010, 0x20404000, 0x00000000, 0x20400010,
485	0x00000010, 0x00004000, 0x20400000, 0x00404010,
486	0x00004000, 0x00400010, 0x20004010, 0x00000000,
487	0x20404000, 0x20000000, 0x00400010, 0x20004010
488};
489
490static const u32 S7[64] = {
491	0x00200000, 0x04200002, 0x04000802, 0x00000000,
492	0x00000800, 0x04000802, 0x00200802, 0x04200800,
493	0x04200802, 0x00200000, 0x00000000, 0x04000002,
494	0x00000002, 0x04000000, 0x04200002, 0x00000802,
495	0x04000800, 0x00200802, 0x00200002, 0x04000800,
496	0x04000002, 0x04200000, 0x04200800, 0x00200002,
497	0x04200000, 0x00000800, 0x00000802, 0x04200802,
498	0x00200800, 0x00000002, 0x04000000, 0x00200800,
499	0x04000000, 0x00200800, 0x00200000, 0x04000802,
500	0x04000802, 0x04200002, 0x04200002, 0x00000002,
501	0x00200002, 0x04000000, 0x04000800, 0x00200000,
502	0x04200800, 0x00000802, 0x00200802, 0x04200800,
503	0x00000802, 0x04000002, 0x04200802, 0x04200000,
504	0x00200800, 0x00000000, 0x00000002, 0x04200802,
505	0x00000000, 0x00200802, 0x04200000, 0x00000800,
506	0x04000002, 0x04000800, 0x00000800, 0x00200002
507};
508
509static const u32 S8[64] = {
510	0x10001040, 0x00001000, 0x00040000, 0x10041040,
511	0x10000000, 0x10001040, 0x00000040, 0x10000000,
512	0x00040040, 0x10040000, 0x10041040, 0x00041000,
513	0x10041000, 0x00041040, 0x00001000, 0x00000040,
514	0x10040000, 0x10000040, 0x10001000, 0x00001040,
515	0x00041000, 0x00040040, 0x10040040, 0x10041000,
516	0x00001040, 0x00000000, 0x00000000, 0x10040040,
517	0x10000040, 0x10001000, 0x00041040, 0x00040000,
518	0x00041040, 0x00040000, 0x10041000, 0x00001000,
519	0x00000040, 0x10040040, 0x00001000, 0x00041040,
520	0x10001000, 0x00000040, 0x10000040, 0x10040000,
521	0x10040040, 0x10000000, 0x00040000, 0x10001040,
522	0x00000000, 0x10041040, 0x00040040, 0x10000040,
523	0x10040000, 0x10001000, 0x10001040, 0x00000000,
524	0x10041040, 0x00041000, 0x00041000, 0x00001040,
525	0x00001040, 0x00040040, 0x10000000, 0x10041000
526};
527
528/* Encryption components: IP, FP, and round function */
529
530#define IP(L, R, T)		\
531	ROL(R, 4);		\
532	T  = L;			\
533	L ^= R;			\
534	L &= 0xf0f0f0f0;	\
535	R ^= L;			\
536	L ^= T;			\
537	ROL(R, 12);		\
538	T  = L;			\
539	L ^= R;			\
540	L &= 0xffff0000;	\
541	R ^= L;			\
542	L ^= T;			\
543	ROR(R, 14);		\
544	T  = L;			\
545	L ^= R;			\
546	L &= 0xcccccccc;	\
547	R ^= L;			\
548	L ^= T;			\
549	ROL(R, 6);		\
550	T  = L;			\
551	L ^= R;			\
552	L &= 0xff00ff00;	\
553	R ^= L;			\
554	L ^= T;			\
555	ROR(R, 7);		\
556	T  = L;			\
557	L ^= R;			\
558	L &= 0xaaaaaaaa;	\
559	R ^= L;			\
560	L ^= T;			\
561	ROL(L, 1);
562
563#define FP(L, R, T)		\
564	ROR(L, 1);		\
565	T  = L;			\
566	L ^= R;			\
567	L &= 0xaaaaaaaa;	\
568	R ^= L;			\
569	L ^= T;			\
570	ROL(R, 7);		\
571	T  = L;			\
572	L ^= R;			\
573	L &= 0xff00ff00;	\
574	R ^= L;			\
575	L ^= T;			\
576	ROR(R, 6);		\
577	T  = L;			\
578	L ^= R;			\
579	L &= 0xcccccccc;	\
580	R ^= L;			\
581	L ^= T;			\
582	ROL(R, 14);		\
583	T  = L;			\
584	L ^= R;			\
585	L &= 0xffff0000;	\
586	R ^= L;			\
587	L ^= T;			\
588	ROR(R, 12);		\
589	T  = L;			\
590	L ^= R;			\
591	L &= 0xf0f0f0f0;	\
592	R ^= L;			\
593	L ^= T;			\
594	ROR(R, 4);
595
596#define ROUND(L, R, A, B, K, d)					\
597	B = K[0];			A = K[1];	K += d;	\
598	B ^= R;				A ^= R;			\
599	B &= 0x3f3f3f3f;		ROR(A, 4);		\
600	L ^= S8[0xff & B];		A &= 0x3f3f3f3f;	\
601	L ^= S6[0xff & (B >> 8)];	B >>= 16;		\
602	L ^= S7[0xff & A];					\
603	L ^= S5[0xff & (A >> 8)];	A >>= 16;		\
604	L ^= S4[0xff & B];					\
605	L ^= S2[0xff & (B >> 8)];				\
606	L ^= S3[0xff & A];					\
607	L ^= S1[0xff & (A >> 8)];
608
609/*
610 * PC2 lookup tables are organized as 2 consecutive sets of 4 interleaved
611 * tables of 128 elements.  One set is for C_i and the other for D_i, while
612 * the 4 interleaved tables correspond to four 7-bit subsets of C_i or D_i.
613 *
614 * After PC1 each of the variables a,b,c,d contains a 7 bit subset of C_i
615 * or D_i in bits 7-1 (bit 0 being the least significant).
616 */
617
618#define T1(x) pt[2 * (x) + 0]
619#define T2(x) pt[2 * (x) + 1]
620#define T3(x) pt[2 * (x) + 2]
621#define T4(x) pt[2 * (x) + 3]
622
623#define PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a))
624
625/*
626 * Encryption key expansion
627 *
628 * RFC2451: Weak key checks SHOULD be performed.
629 *
630 * FIPS 74:
631 *
632 *   Keys having duals are keys which produce all zeros, all ones, or
633 *   alternating zero-one patterns in the C and D registers after Permuted
634 *   Choice 1 has operated on the key.
635 *
636 */
637static unsigned long ekey(u32 *pe, const u8 *k)
638{
639	/* K&R: long is at least 32 bits */
640	unsigned long a, b, c, d, w;
641	const u32 *pt = pc2;
642
643	d = k[4]; d &= 0x0e; d <<= 4; d |= k[0] & 0x1e; d = pc1[d];
644	c = k[5]; c &= 0x0e; c <<= 4; c |= k[1] & 0x1e; c = pc1[c];
645	b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b];
646	a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a];
647
648	pe[15 * 2 + 0] = PC2(a, b, c, d); d = rs[d];
649	pe[14 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
650	pe[13 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
651	pe[12 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
652	pe[11 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
653	pe[10 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
654	pe[ 9 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
655	pe[ 8 * 2 + 0] = PC2(d, a, b, c); c = rs[c];
656	pe[ 7 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
657	pe[ 6 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
658	pe[ 5 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
659	pe[ 4 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
660	pe[ 3 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
661	pe[ 2 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
662	pe[ 1 * 2 + 0] = PC2(c, d, a, b); b = rs[b];
663	pe[ 0 * 2 + 0] = PC2(b, c, d, a);
664
665	/* Check if first half is weak */
666	w  = (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]);
667
668	/* Skip to next table set */
669	pt += 512;
670
671	d = k[0]; d &= 0xe0; d >>= 4; d |= k[4] & 0xf0; d = pc1[d + 1];
672	c = k[1]; c &= 0xe0; c >>= 4; c |= k[5] & 0xf0; c = pc1[c + 1];
673	b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1];
674	a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1];
675
676	/* Check if second half is weak */
677	w |= (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]);
678
679	pe[15 * 2 + 1] = PC2(a, b, c, d); d = rs[d];
680	pe[14 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
681	pe[13 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
682	pe[12 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
683	pe[11 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
684	pe[10 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
685	pe[ 9 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
686	pe[ 8 * 2 + 1] = PC2(d, a, b, c); c = rs[c];
687	pe[ 7 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
688	pe[ 6 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
689	pe[ 5 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
690	pe[ 4 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
691	pe[ 3 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
692	pe[ 2 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
693	pe[ 1 * 2 + 1] = PC2(c, d, a, b); b = rs[b];
694	pe[ 0 * 2 + 1] = PC2(b, c, d, a);
695
696	/* Fixup: 2413 5768 -> 1357 2468 */
697	for (d = 0; d < 16; ++d) {
698		a = pe[2 * d];
699		b = pe[2 * d + 1];
700		c = a ^ b;
701		c &= 0xffff0000;
702		a ^= c;
703		b ^= c;
704		ROL(b, 18);
705		pe[2 * d] = a;
706		pe[2 * d + 1] = b;
707	}
708
709	/* Zero if weak key */
710	return w;
711}
712
713/*
714 * Decryption key expansion
715 *
716 * No weak key checking is performed, as this is only used by triple DES
717 *
718 */
719static void dkey(u32 *pe, const u8 *k)
720{
721	/* K&R: long is at least 32 bits */
722	unsigned long a, b, c, d;
723	const u32 *pt = pc2;
724
725	d = k[4]; d &= 0x0e; d <<= 4; d |= k[0] & 0x1e; d = pc1[d];
726	c = k[5]; c &= 0x0e; c <<= 4; c |= k[1] & 0x1e; c = pc1[c];
727	b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b];
728	a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a];
729
730	pe[ 0 * 2] = PC2(a, b, c, d); d = rs[d];
731	pe[ 1 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
732	pe[ 2 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
733	pe[ 3 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
734	pe[ 4 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
735	pe[ 5 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
736	pe[ 6 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
737	pe[ 7 * 2] = PC2(d, a, b, c); c = rs[c];
738	pe[ 8 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
739	pe[ 9 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
740	pe[10 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
741	pe[11 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
742	pe[12 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
743	pe[13 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
744	pe[14 * 2] = PC2(c, d, a, b); b = rs[b];
745	pe[15 * 2] = PC2(b, c, d, a);
746
747	/* Skip to next table set */
748	pt += 512;
749
750	d = k[0]; d &= 0xe0; d >>= 4; d |= k[4] & 0xf0; d = pc1[d + 1];
751	c = k[1]; c &= 0xe0; c >>= 4; c |= k[5] & 0xf0; c = pc1[c + 1];
752	b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1];
753	a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1];
754
755	pe[ 0 * 2 + 1] = PC2(a, b, c, d); d = rs[d];
756	pe[ 1 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
757	pe[ 2 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
758	pe[ 3 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
759	pe[ 4 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
760	pe[ 5 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
761	pe[ 6 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
762	pe[ 7 * 2 + 1] = PC2(d, a, b, c); c = rs[c];
763	pe[ 8 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
764	pe[ 9 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
765	pe[10 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
766	pe[11 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
767	pe[12 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
768	pe[13 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
769	pe[14 * 2 + 1] = PC2(c, d, a, b); b = rs[b];
770	pe[15 * 2 + 1] = PC2(b, c, d, a);
771
772	/* Fixup: 2413 5768 -> 1357 2468 */
773	for (d = 0; d < 16; ++d) {
774		a = pe[2 * d];
775		b = pe[2 * d + 1];
776		c = a ^ b;
777		c &= 0xffff0000;
778		a ^= c;
779		b ^= c;
780		ROL(b, 18);
781		pe[2 * d] = a;
782		pe[2 * d + 1] = b;
783	}
784}
785
786static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
787		      unsigned int keylen)
788{
789	struct des_ctx *dctx = crypto_tfm_ctx(tfm);
790	u32 *flags = &tfm->crt_flags;
791	u32 tmp[DES_EXPKEY_WORDS];
792	int ret;
793
794	/* Expand to tmp */
795	ret = ekey(tmp, key);
796
797	if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
798		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
799		return -EINVAL;
800	}
801
802	/* Copy to output */
803	memcpy(dctx->expkey, tmp, sizeof(dctx->expkey));
804
805	return 0;
806}
807
808static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
809{
810	struct des_ctx *ctx = crypto_tfm_ctx(tfm);
811	const u32 *K = ctx->expkey;
812	const __le32 *s = (const __le32 *)src;
813	__le32 *d = (__le32 *)dst;
814	u32 L, R, A, B;
815	int i;
816
817	L = le32_to_cpu(s[0]);
818	R = le32_to_cpu(s[1]);
819
820	IP(L, R, A);
821	for (i = 0; i < 8; i++) {
822		ROUND(L, R, A, B, K, 2);
823		ROUND(R, L, A, B, K, 2);
824	}
825	FP(R, L, A);
826
827	d[0] = cpu_to_le32(R);
828	d[1] = cpu_to_le32(L);
829}
830
831static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
832{
833	struct des_ctx *ctx = crypto_tfm_ctx(tfm);
834	const u32 *K = ctx->expkey + DES_EXPKEY_WORDS - 2;
835	const __le32 *s = (const __le32 *)src;
836	__le32 *d = (__le32 *)dst;
837	u32 L, R, A, B;
838	int i;
839
840	L = le32_to_cpu(s[0]);
841	R = le32_to_cpu(s[1]);
842
843	IP(L, R, A);
844	for (i = 0; i < 8; i++) {
845		ROUND(L, R, A, B, K, -2);
846		ROUND(R, L, A, B, K, -2);
847	}
848	FP(R, L, A);
849
850	d[0] = cpu_to_le32(R);
851	d[1] = cpu_to_le32(L);
852}
853
854/*
855 * RFC2451:
856 *
857 *   For DES-EDE3, there is no known need to reject weak or
858 *   complementation keys.  Any weakness is obviated by the use of
859 *   multiple keys.
860 *
861 *   However, if the first two or last two independent 64-bit keys are
862 *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
863 *   same as DES.  Implementers MUST reject keys that exhibit this
864 *   property.
865 *
866 */
867static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
868			   unsigned int keylen)
869{
870	const u32 *K = (const u32 *)key;
871	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
872	u32 *expkey = dctx->expkey;
873	u32 *flags = &tfm->crt_flags;
874
875	if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
876		     !((K[2] ^ K[4]) | (K[3] ^ K[5]))))
877	{
878		*flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
879		return -EINVAL;
880	}
881
882	ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
883	dkey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
884	ekey(expkey, key);
885
886	return 0;
887}
888
889static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
890{
891	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
892	const u32 *K = dctx->expkey;
893	const __le32 *s = (const __le32 *)src;
894	__le32 *d = (__le32 *)dst;
895	u32 L, R, A, B;
896	int i;
897
898	L = le32_to_cpu(s[0]);
899	R = le32_to_cpu(s[1]);
900
901	IP(L, R, A);
902	for (i = 0; i < 8; i++) {
903		ROUND(L, R, A, B, K, 2);
904		ROUND(R, L, A, B, K, 2);
905	}
906	for (i = 0; i < 8; i++) {
907		ROUND(R, L, A, B, K, 2);
908		ROUND(L, R, A, B, K, 2);
909	}
910	for (i = 0; i < 8; i++) {
911		ROUND(L, R, A, B, K, 2);
912		ROUND(R, L, A, B, K, 2);
913	}
914	FP(R, L, A);
915
916	d[0] = cpu_to_le32(R);
917	d[1] = cpu_to_le32(L);
918}
919
920static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
921{
922	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
923	const u32 *K = dctx->expkey + DES3_EDE_EXPKEY_WORDS - 2;
924	const __le32 *s = (const __le32 *)src;
925	__le32 *d = (__le32 *)dst;
926	u32 L, R, A, B;
927	int i;
928
929	L = le32_to_cpu(s[0]);
930	R = le32_to_cpu(s[1]);
931
932	IP(L, R, A);
933	for (i = 0; i < 8; i++) {
934		ROUND(L, R, A, B, K, -2);
935		ROUND(R, L, A, B, K, -2);
936	}
937	for (i = 0; i < 8; i++) {
938		ROUND(R, L, A, B, K, -2);
939		ROUND(L, R, A, B, K, -2);
940	}
941	for (i = 0; i < 8; i++) {
942		ROUND(L, R, A, B, K, -2);
943		ROUND(R, L, A, B, K, -2);
944	}
945	FP(R, L, A);
946
947	d[0] = cpu_to_le32(R);
948	d[1] = cpu_to_le32(L);
949}
950
951static struct crypto_alg des_alg = {
952	.cra_name		=	"des",
953	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
954	.cra_blocksize		=	DES_BLOCK_SIZE,
955	.cra_ctxsize		=	sizeof(struct des_ctx),
956	.cra_module		=	THIS_MODULE,
957	.cra_alignmask		=	3,
958	.cra_list		=	LIST_HEAD_INIT(des_alg.cra_list),
959	.cra_u			=	{ .cipher = {
960	.cia_min_keysize	=	DES_KEY_SIZE,
961	.cia_max_keysize	=	DES_KEY_SIZE,
962	.cia_setkey		=	des_setkey,
963	.cia_encrypt		=	des_encrypt,
964	.cia_decrypt		=	des_decrypt } }
965};
966
967static struct crypto_alg des3_ede_alg = {
968	.cra_name		=	"des3_ede",
969	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
970	.cra_blocksize		=	DES3_EDE_BLOCK_SIZE,
971	.cra_ctxsize		=	sizeof(struct des3_ede_ctx),
972	.cra_module		=	THIS_MODULE,
973	.cra_alignmask		=	3,
974	.cra_list		=	LIST_HEAD_INIT(des3_ede_alg.cra_list),
975	.cra_u			=	{ .cipher = {
976	.cia_min_keysize	=	DES3_EDE_KEY_SIZE,
977	.cia_max_keysize	=	DES3_EDE_KEY_SIZE,
978	.cia_setkey		=	des3_ede_setkey,
979	.cia_encrypt		=	des3_ede_encrypt,
980	.cia_decrypt		=	des3_ede_decrypt } }
981};
982
983MODULE_ALIAS("des3_ede");
984
985static int __init init(void)
986{
987	int ret = 0;
988
989	ret = crypto_register_alg(&des_alg);
990	if (ret < 0)
991		goto out;
992
993	ret = crypto_register_alg(&des3_ede_alg);
994	if (ret < 0)
995		crypto_unregister_alg(&des_alg);
996out:
997	return ret;
998}
999
1000static void __exit fini(void)
1001{
1002	crypto_unregister_alg(&des3_ede_alg);
1003	crypto_unregister_alg(&des_alg);
1004}
1005
1006module_init(init);
1007module_exit(fini);
1008
1009MODULE_LICENSE("GPL");
1010MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
1011MODULE_AUTHOR("Dag Arne Osvik <da@osvik.no>");
1012