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