xref: /openbmc/linux/crypto/des_generic.c (revision 96de0e252cedffad61b3cb5e05662c591898e69a)
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 
34 struct des_ctx {
35 	u32 expkey[DES_EXPKEY_WORDS];
36 };
37 
38 struct des3_ede_ctx {
39 	u32 expkey[DES3_EDE_EXPKEY_WORDS];
40 };
41 
42 /* Lookup tables for key expansion */
43 
44 static 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 
79 static 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 
114 static 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 
376 static 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 
395 static 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 
414 static 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 
433 static 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 
452 static 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 
471 static 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 
490 static 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 
509 static 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  */
637 static 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  */
719 static 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 
786 static 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 
808 static 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 
831 static 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  */
867 static 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 
889 static 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 
920 static 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 
951 static 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 
967 static 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 
983 MODULE_ALIAS("des3_ede");
984 
985 static 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);
996 out:
997 	return ret;
998 }
999 
1000 static void __exit fini(void)
1001 {
1002 	crypto_unregister_alg(&des3_ede_alg);
1003 	crypto_unregister_alg(&des_alg);
1004 }
1005 
1006 module_init(init);
1007 module_exit(fini);
1008 
1009 MODULE_LICENSE("GPL");
1010 MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
1011 MODULE_AUTHOR("Dag Arne Osvik <da@osvik.no>");
1012 MODULE_ALIAS("des");
1013