1 /*
2 * des.c
3 *
4 * core source file for DES-150 library
5 * Make key schedule from DES key.
6 * Encrypt/Decrypt one 8-byte block.
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12 #include "des.h"
13 #include "blapii.h"
14 #include <stddef.h> /* for ptrdiff_t */
15 /* #define USE_INDEXING 1 */
16
17 /*
18 * The tables below are the 8 sbox functions, with the 6-bit input permutation
19 * and the 32-bit output permutation pre-computed.
20 * They are shifted circularly to the left 3 bits, which removes 2 shifts
21 * and an or from each round by reducing the number of sboxes whose
22 * indices cross word broundaries from 2 to 1.
23 */
24
25 static const HALF SP[8][64] = {
26 /* Box S1 */
27 { 0x04041000, 0x00000000, 0x00040000, 0x04041010,
28 0x04040010, 0x00041010, 0x00000010, 0x00040000,
29 0x00001000, 0x04041000, 0x04041010, 0x00001000,
30 0x04001010, 0x04040010, 0x04000000, 0x00000010,
31 0x00001010, 0x04001000, 0x04001000, 0x00041000,
32 0x00041000, 0x04040000, 0x04040000, 0x04001010,
33 0x00040010, 0x04000010, 0x04000010, 0x00040010,
34 0x00000000, 0x00001010, 0x00041010, 0x04000000,
35 0x00040000, 0x04041010, 0x00000010, 0x04040000,
36 0x04041000, 0x04000000, 0x04000000, 0x00001000,
37 0x04040010, 0x00040000, 0x00041000, 0x04000010,
38 0x00001000, 0x00000010, 0x04001010, 0x00041010,
39 0x04041010, 0x00040010, 0x04040000, 0x04001010,
40 0x04000010, 0x00001010, 0x00041010, 0x04041000,
41 0x00001010, 0x04001000, 0x04001000, 0x00000000,
42 0x00040010, 0x00041000, 0x00000000, 0x04040010 },
43 /* Box S2 */
44 { 0x00420082, 0x00020002, 0x00020000, 0x00420080,
45 0x00400000, 0x00000080, 0x00400082, 0x00020082,
46 0x00000082, 0x00420082, 0x00420002, 0x00000002,
47 0x00020002, 0x00400000, 0x00000080, 0x00400082,
48 0x00420000, 0x00400080, 0x00020082, 0x00000000,
49 0x00000002, 0x00020000, 0x00420080, 0x00400002,
50 0x00400080, 0x00000082, 0x00000000, 0x00420000,
51 0x00020080, 0x00420002, 0x00400002, 0x00020080,
52 0x00000000, 0x00420080, 0x00400082, 0x00400000,
53 0x00020082, 0x00400002, 0x00420002, 0x00020000,
54 0x00400002, 0x00020002, 0x00000080, 0x00420082,
55 0x00420080, 0x00000080, 0x00020000, 0x00000002,
56 0x00020080, 0x00420002, 0x00400000, 0x00000082,
57 0x00400080, 0x00020082, 0x00000082, 0x00400080,
58 0x00420000, 0x00000000, 0x00020002, 0x00020080,
59 0x00000002, 0x00400082, 0x00420082, 0x00420000 },
60 /* Box S3 */
61 { 0x00000820, 0x20080800, 0x00000000, 0x20080020,
62 0x20000800, 0x00000000, 0x00080820, 0x20000800,
63 0x00080020, 0x20000020, 0x20000020, 0x00080000,
64 0x20080820, 0x00080020, 0x20080000, 0x00000820,
65 0x20000000, 0x00000020, 0x20080800, 0x00000800,
66 0x00080800, 0x20080000, 0x20080020, 0x00080820,
67 0x20000820, 0x00080800, 0x00080000, 0x20000820,
68 0x00000020, 0x20080820, 0x00000800, 0x20000000,
69 0x20080800, 0x20000000, 0x00080020, 0x00000820,
70 0x00080000, 0x20080800, 0x20000800, 0x00000000,
71 0x00000800, 0x00080020, 0x20080820, 0x20000800,
72 0x20000020, 0x00000800, 0x00000000, 0x20080020,
73 0x20000820, 0x00080000, 0x20000000, 0x20080820,
74 0x00000020, 0x00080820, 0x00080800, 0x20000020,
75 0x20080000, 0x20000820, 0x00000820, 0x20080000,
76 0x00080820, 0x00000020, 0x20080020, 0x00080800 },
77 /* Box S4 */
78 { 0x02008004, 0x00008204, 0x00008204, 0x00000200,
79 0x02008200, 0x02000204, 0x02000004, 0x00008004,
80 0x00000000, 0x02008000, 0x02008000, 0x02008204,
81 0x00000204, 0x00000000, 0x02000200, 0x02000004,
82 0x00000004, 0x00008000, 0x02000000, 0x02008004,
83 0x00000200, 0x02000000, 0x00008004, 0x00008200,
84 0x02000204, 0x00000004, 0x00008200, 0x02000200,
85 0x00008000, 0x02008200, 0x02008204, 0x00000204,
86 0x02000200, 0x02000004, 0x02008000, 0x02008204,
87 0x00000204, 0x00000000, 0x00000000, 0x02008000,
88 0x00008200, 0x02000200, 0x02000204, 0x00000004,
89 0x02008004, 0x00008204, 0x00008204, 0x00000200,
90 0x02008204, 0x00000204, 0x00000004, 0x00008000,
91 0x02000004, 0x00008004, 0x02008200, 0x02000204,
92 0x00008004, 0x00008200, 0x02000000, 0x02008004,
93 0x00000200, 0x02000000, 0x00008000, 0x02008200 },
94 /* Box S5 */
95 { 0x00000400, 0x08200400, 0x08200000, 0x08000401,
96 0x00200000, 0x00000400, 0x00000001, 0x08200000,
97 0x00200401, 0x00200000, 0x08000400, 0x00200401,
98 0x08000401, 0x08200001, 0x00200400, 0x00000001,
99 0x08000000, 0x00200001, 0x00200001, 0x00000000,
100 0x00000401, 0x08200401, 0x08200401, 0x08000400,
101 0x08200001, 0x00000401, 0x00000000, 0x08000001,
102 0x08200400, 0x08000000, 0x08000001, 0x00200400,
103 0x00200000, 0x08000401, 0x00000400, 0x08000000,
104 0x00000001, 0x08200000, 0x08000401, 0x00200401,
105 0x08000400, 0x00000001, 0x08200001, 0x08200400,
106 0x00200401, 0x00000400, 0x08000000, 0x08200001,
107 0x08200401, 0x00200400, 0x08000001, 0x08200401,
108 0x08200000, 0x00000000, 0x00200001, 0x08000001,
109 0x00200400, 0x08000400, 0x00000401, 0x00200000,
110 0x00000000, 0x00200001, 0x08200400, 0x00000401 },
111 /* Box S6 */
112 { 0x80000040, 0x81000000, 0x00010000, 0x81010040,
113 0x81000000, 0x00000040, 0x81010040, 0x01000000,
114 0x80010000, 0x01010040, 0x01000000, 0x80000040,
115 0x01000040, 0x80010000, 0x80000000, 0x00010040,
116 0x00000000, 0x01000040, 0x80010040, 0x00010000,
117 0x01010000, 0x80010040, 0x00000040, 0x81000040,
118 0x81000040, 0x00000000, 0x01010040, 0x81010000,
119 0x00010040, 0x01010000, 0x81010000, 0x80000000,
120 0x80010000, 0x00000040, 0x81000040, 0x01010000,
121 0x81010040, 0x01000000, 0x00010040, 0x80000040,
122 0x01000000, 0x80010000, 0x80000000, 0x00010040,
123 0x80000040, 0x81010040, 0x01010000, 0x81000000,
124 0x01010040, 0x81010000, 0x00000000, 0x81000040,
125 0x00000040, 0x00010000, 0x81000000, 0x01010040,
126 0x00010000, 0x01000040, 0x80010040, 0x00000000,
127 0x81010000, 0x80000000, 0x01000040, 0x80010040 },
128 /* Box S7 */
129 { 0x00800000, 0x10800008, 0x10002008, 0x00000000,
130 0x00002000, 0x10002008, 0x00802008, 0x10802000,
131 0x10802008, 0x00800000, 0x00000000, 0x10000008,
132 0x00000008, 0x10000000, 0x10800008, 0x00002008,
133 0x10002000, 0x00802008, 0x00800008, 0x10002000,
134 0x10000008, 0x10800000, 0x10802000, 0x00800008,
135 0x10800000, 0x00002000, 0x00002008, 0x10802008,
136 0x00802000, 0x00000008, 0x10000000, 0x00802000,
137 0x10000000, 0x00802000, 0x00800000, 0x10002008,
138 0x10002008, 0x10800008, 0x10800008, 0x00000008,
139 0x00800008, 0x10000000, 0x10002000, 0x00800000,
140 0x10802000, 0x00002008, 0x00802008, 0x10802000,
141 0x00002008, 0x10000008, 0x10802008, 0x10800000,
142 0x00802000, 0x00000000, 0x00000008, 0x10802008,
143 0x00000000, 0x00802008, 0x10800000, 0x00002000,
144 0x10000008, 0x10002000, 0x00002000, 0x00800008 },
145 /* Box S8 */
146 { 0x40004100, 0x00004000, 0x00100000, 0x40104100,
147 0x40000000, 0x40004100, 0x00000100, 0x40000000,
148 0x00100100, 0x40100000, 0x40104100, 0x00104000,
149 0x40104000, 0x00104100, 0x00004000, 0x00000100,
150 0x40100000, 0x40000100, 0x40004000, 0x00004100,
151 0x00104000, 0x00100100, 0x40100100, 0x40104000,
152 0x00004100, 0x00000000, 0x00000000, 0x40100100,
153 0x40000100, 0x40004000, 0x00104100, 0x00100000,
154 0x00104100, 0x00100000, 0x40104000, 0x00004000,
155 0x00000100, 0x40100100, 0x00004000, 0x00104100,
156 0x40004000, 0x00000100, 0x40000100, 0x40100000,
157 0x40100100, 0x40000000, 0x00100000, 0x40004100,
158 0x00000000, 0x40104100, 0x00100100, 0x40000100,
159 0x40100000, 0x40004000, 0x40004100, 0x00000000,
160 0x40104100, 0x00104000, 0x00104000, 0x00004100,
161 0x00004100, 0x00100100, 0x40000000, 0x40104000 }
162 };
163
164 static const HALF PC2[8][64] = {
165 /* table 0 */
166 { 0x00000000, 0x00001000, 0x04000000, 0x04001000,
167 0x00100000, 0x00101000, 0x04100000, 0x04101000,
168 0x00008000, 0x00009000, 0x04008000, 0x04009000,
169 0x00108000, 0x00109000, 0x04108000, 0x04109000,
170 0x00000004, 0x00001004, 0x04000004, 0x04001004,
171 0x00100004, 0x00101004, 0x04100004, 0x04101004,
172 0x00008004, 0x00009004, 0x04008004, 0x04009004,
173 0x00108004, 0x00109004, 0x04108004, 0x04109004,
174 0x08000000, 0x08001000, 0x0c000000, 0x0c001000,
175 0x08100000, 0x08101000, 0x0c100000, 0x0c101000,
176 0x08008000, 0x08009000, 0x0c008000, 0x0c009000,
177 0x08108000, 0x08109000, 0x0c108000, 0x0c109000,
178 0x08000004, 0x08001004, 0x0c000004, 0x0c001004,
179 0x08100004, 0x08101004, 0x0c100004, 0x0c101004,
180 0x08008004, 0x08009004, 0x0c008004, 0x0c009004,
181 0x08108004, 0x08109004, 0x0c108004, 0x0c109004 },
182 /* table 1 */
183 { 0x00000000, 0x00002000, 0x80000000, 0x80002000,
184 0x00000008, 0x00002008, 0x80000008, 0x80002008,
185 0x00200000, 0x00202000, 0x80200000, 0x80202000,
186 0x00200008, 0x00202008, 0x80200008, 0x80202008,
187 0x20000000, 0x20002000, 0xa0000000, 0xa0002000,
188 0x20000008, 0x20002008, 0xa0000008, 0xa0002008,
189 0x20200000, 0x20202000, 0xa0200000, 0xa0202000,
190 0x20200008, 0x20202008, 0xa0200008, 0xa0202008,
191 0x00000400, 0x00002400, 0x80000400, 0x80002400,
192 0x00000408, 0x00002408, 0x80000408, 0x80002408,
193 0x00200400, 0x00202400, 0x80200400, 0x80202400,
194 0x00200408, 0x00202408, 0x80200408, 0x80202408,
195 0x20000400, 0x20002400, 0xa0000400, 0xa0002400,
196 0x20000408, 0x20002408, 0xa0000408, 0xa0002408,
197 0x20200400, 0x20202400, 0xa0200400, 0xa0202400,
198 0x20200408, 0x20202408, 0xa0200408, 0xa0202408 },
199 /* table 2 */
200 { 0x00000000, 0x00004000, 0x00000020, 0x00004020,
201 0x00080000, 0x00084000, 0x00080020, 0x00084020,
202 0x00000800, 0x00004800, 0x00000820, 0x00004820,
203 0x00080800, 0x00084800, 0x00080820, 0x00084820,
204 0x00000010, 0x00004010, 0x00000030, 0x00004030,
205 0x00080010, 0x00084010, 0x00080030, 0x00084030,
206 0x00000810, 0x00004810, 0x00000830, 0x00004830,
207 0x00080810, 0x00084810, 0x00080830, 0x00084830,
208 0x00400000, 0x00404000, 0x00400020, 0x00404020,
209 0x00480000, 0x00484000, 0x00480020, 0x00484020,
210 0x00400800, 0x00404800, 0x00400820, 0x00404820,
211 0x00480800, 0x00484800, 0x00480820, 0x00484820,
212 0x00400010, 0x00404010, 0x00400030, 0x00404030,
213 0x00480010, 0x00484010, 0x00480030, 0x00484030,
214 0x00400810, 0x00404810, 0x00400830, 0x00404830,
215 0x00480810, 0x00484810, 0x00480830, 0x00484830 },
216 /* table 3 */
217 { 0x00000000, 0x40000000, 0x00000080, 0x40000080,
218 0x00040000, 0x40040000, 0x00040080, 0x40040080,
219 0x00000040, 0x40000040, 0x000000c0, 0x400000c0,
220 0x00040040, 0x40040040, 0x000400c0, 0x400400c0,
221 0x10000000, 0x50000000, 0x10000080, 0x50000080,
222 0x10040000, 0x50040000, 0x10040080, 0x50040080,
223 0x10000040, 0x50000040, 0x100000c0, 0x500000c0,
224 0x10040040, 0x50040040, 0x100400c0, 0x500400c0,
225 0x00800000, 0x40800000, 0x00800080, 0x40800080,
226 0x00840000, 0x40840000, 0x00840080, 0x40840080,
227 0x00800040, 0x40800040, 0x008000c0, 0x408000c0,
228 0x00840040, 0x40840040, 0x008400c0, 0x408400c0,
229 0x10800000, 0x50800000, 0x10800080, 0x50800080,
230 0x10840000, 0x50840000, 0x10840080, 0x50840080,
231 0x10800040, 0x50800040, 0x108000c0, 0x508000c0,
232 0x10840040, 0x50840040, 0x108400c0, 0x508400c0 },
233 /* table 4 */
234 { 0x00000000, 0x00000008, 0x08000000, 0x08000008,
235 0x00040000, 0x00040008, 0x08040000, 0x08040008,
236 0x00002000, 0x00002008, 0x08002000, 0x08002008,
237 0x00042000, 0x00042008, 0x08042000, 0x08042008,
238 0x80000000, 0x80000008, 0x88000000, 0x88000008,
239 0x80040000, 0x80040008, 0x88040000, 0x88040008,
240 0x80002000, 0x80002008, 0x88002000, 0x88002008,
241 0x80042000, 0x80042008, 0x88042000, 0x88042008,
242 0x00080000, 0x00080008, 0x08080000, 0x08080008,
243 0x000c0000, 0x000c0008, 0x080c0000, 0x080c0008,
244 0x00082000, 0x00082008, 0x08082000, 0x08082008,
245 0x000c2000, 0x000c2008, 0x080c2000, 0x080c2008,
246 0x80080000, 0x80080008, 0x88080000, 0x88080008,
247 0x800c0000, 0x800c0008, 0x880c0000, 0x880c0008,
248 0x80082000, 0x80082008, 0x88082000, 0x88082008,
249 0x800c2000, 0x800c2008, 0x880c2000, 0x880c2008 },
250 /* table 5 */
251 { 0x00000000, 0x00400000, 0x00008000, 0x00408000,
252 0x40000000, 0x40400000, 0x40008000, 0x40408000,
253 0x00000020, 0x00400020, 0x00008020, 0x00408020,
254 0x40000020, 0x40400020, 0x40008020, 0x40408020,
255 0x00001000, 0x00401000, 0x00009000, 0x00409000,
256 0x40001000, 0x40401000, 0x40009000, 0x40409000,
257 0x00001020, 0x00401020, 0x00009020, 0x00409020,
258 0x40001020, 0x40401020, 0x40009020, 0x40409020,
259 0x00100000, 0x00500000, 0x00108000, 0x00508000,
260 0x40100000, 0x40500000, 0x40108000, 0x40508000,
261 0x00100020, 0x00500020, 0x00108020, 0x00508020,
262 0x40100020, 0x40500020, 0x40108020, 0x40508020,
263 0x00101000, 0x00501000, 0x00109000, 0x00509000,
264 0x40101000, 0x40501000, 0x40109000, 0x40509000,
265 0x00101020, 0x00501020, 0x00109020, 0x00509020,
266 0x40101020, 0x40501020, 0x40109020, 0x40509020 },
267 /* table 6 */
268 { 0x00000000, 0x00000040, 0x04000000, 0x04000040,
269 0x00000800, 0x00000840, 0x04000800, 0x04000840,
270 0x00800000, 0x00800040, 0x04800000, 0x04800040,
271 0x00800800, 0x00800840, 0x04800800, 0x04800840,
272 0x10000000, 0x10000040, 0x14000000, 0x14000040,
273 0x10000800, 0x10000840, 0x14000800, 0x14000840,
274 0x10800000, 0x10800040, 0x14800000, 0x14800040,
275 0x10800800, 0x10800840, 0x14800800, 0x14800840,
276 0x00000080, 0x000000c0, 0x04000080, 0x040000c0,
277 0x00000880, 0x000008c0, 0x04000880, 0x040008c0,
278 0x00800080, 0x008000c0, 0x04800080, 0x048000c0,
279 0x00800880, 0x008008c0, 0x04800880, 0x048008c0,
280 0x10000080, 0x100000c0, 0x14000080, 0x140000c0,
281 0x10000880, 0x100008c0, 0x14000880, 0x140008c0,
282 0x10800080, 0x108000c0, 0x14800080, 0x148000c0,
283 0x10800880, 0x108008c0, 0x14800880, 0x148008c0 },
284 /* table 7 */
285 { 0x00000000, 0x00000010, 0x00000400, 0x00000410,
286 0x00000004, 0x00000014, 0x00000404, 0x00000414,
287 0x00004000, 0x00004010, 0x00004400, 0x00004410,
288 0x00004004, 0x00004014, 0x00004404, 0x00004414,
289 0x20000000, 0x20000010, 0x20000400, 0x20000410,
290 0x20000004, 0x20000014, 0x20000404, 0x20000414,
291 0x20004000, 0x20004010, 0x20004400, 0x20004410,
292 0x20004004, 0x20004014, 0x20004404, 0x20004414,
293 0x00200000, 0x00200010, 0x00200400, 0x00200410,
294 0x00200004, 0x00200014, 0x00200404, 0x00200414,
295 0x00204000, 0x00204010, 0x00204400, 0x00204410,
296 0x00204004, 0x00204014, 0x00204404, 0x00204414,
297 0x20200000, 0x20200010, 0x20200400, 0x20200410,
298 0x20200004, 0x20200014, 0x20200404, 0x20200414,
299 0x20204000, 0x20204010, 0x20204400, 0x20204410,
300 0x20204004, 0x20204014, 0x20204404, 0x20204414 }
301 };
302
303 /*
304 * The PC-1 Permutation
305 * If we number the bits of the 8 bytes of key input like this (in octal):
306 * 00 01 02 03 04 05 06 07
307 * 10 11 12 13 14 15 16 17
308 * 20 21 22 23 24 25 26 27
309 * 30 31 32 33 34 35 36 37
310 * 40 41 42 43 44 45 46 47
311 * 50 51 52 53 54 55 56 57
312 * 60 61 62 63 64 65 66 67
313 * 70 71 72 73 74 75 76 77
314 * then after the PC-1 permutation,
315 * C0 is
316 * 70 60 50 40 30 20 10 00
317 * 71 61 51 41 31 21 11 01
318 * 72 62 52 42 32 22 12 02
319 * 73 63 53 43
320 * D0 is
321 * 76 66 56 46 36 26 16 06
322 * 75 65 55 45 35 25 15 05
323 * 74 64 54 44 34 24 14 04
324 * 33 23 13 03
325 * and these parity bits have been discarded:
326 * 77 67 57 47 37 27 17 07
327 *
328 * We achieve this by flipping the input matrix about the diagonal from 70-07,
329 * getting left =
330 * 77 67 57 47 37 27 17 07 (these are the parity bits)
331 * 76 66 56 46 36 26 16 06
332 * 75 65 55 45 35 25 15 05
333 * 74 64 54 44 34 24 14 04
334 * right =
335 * 73 63 53 43 33 23 13 03
336 * 72 62 52 42 32 22 12 02
337 * 71 61 51 41 31 21 11 01
338 * 70 60 50 40 30 20 10 00
339 * then byte swap right, ala htonl() on a little endian machine.
340 * right =
341 * 70 60 50 40 30 20 10 00
342 * 71 67 57 47 37 27 11 07
343 * 72 62 52 42 32 22 12 02
344 * 73 63 53 43 33 23 13 03
345 * then
346 * c0 = right >> 4;
347 * d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
348 */
349
350 #define FLIP_RIGHT_DIAGONAL(word, temp) \
351 temp = (word ^ (word >> 18)) & 0x00003333; \
352 word ^= temp | (temp << 18); \
353 temp = (word ^ (word >> 9)) & 0x00550055; \
354 word ^= temp | (temp << 9);
355
356 #if defined(__GNUC__) && defined(NSS_X86_OR_X64)
357 #define BYTESWAP(word, temp) \
358 __asm("bswap %0" \
359 : "+r"(word));
360 #elif (_MSC_VER >= 1300) && defined(NSS_X86_OR_X64)
361 #include <stdlib.h>
362 #pragma intrinsic(_byteswap_ulong)
363 #define BYTESWAP(word, temp) \
364 word = _byteswap_ulong(word);
365 #elif defined(__GNUC__) && (defined(__thumb2__) || \
366 (!defined(__thumb__) && \
367 (defined(__ARM_ARCH_6__) || \
368 defined(__ARM_ARCH_6J__) || \
369 defined(__ARM_ARCH_6K__) || \
370 defined(__ARM_ARCH_6Z__) || \
371 defined(__ARM_ARCH_6ZK__) || \
372 defined(__ARM_ARCH_6T2__) || \
373 defined(__ARM_ARCH_7__) || \
374 defined(__ARM_ARCH_7A__) || \
375 defined(__ARM_ARCH_7R__))))
376 #define BYTESWAP(word, temp) \
377 __asm("rev %0, %0" \
378 : "+r"(word));
379 #else
380 #define BYTESWAP(word, temp) \
381 word = (word >> 16) | (word << 16); \
382 temp = 0x00ff00ff; \
383 word = ((word & temp) << 8) | ((word >> 8) & temp);
384 #endif
385
386 #define PC1(left, right, c0, d0, temp) \
387 right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
388 left ^= temp << 4; \
389 FLIP_RIGHT_DIAGONAL(left, temp); \
390 FLIP_RIGHT_DIAGONAL(right, temp); \
391 BYTESWAP(right, temp); \
392 c0 = right >> 4; \
393 d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
394
395 #define LEFT_SHIFT_1(reg) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)
396 #define LEFT_SHIFT_2(reg) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)
397
398 /*
399 * setup key schedules from key
400 */
401
402 void
DES_MakeSchedule(HALF * ks,const BYTE * key,DESDirection direction)403 DES_MakeSchedule(HALF *ks, const BYTE *key, DESDirection direction)
404 {
405 register HALF left, right;
406 register HALF c0, d0;
407 register HALF temp;
408 int delta;
409 unsigned int ls;
410
411 #if defined(HAVE_UNALIGNED_ACCESS)
412 left = HALFPTR(key)[0];
413 right = HALFPTR(key)[1];
414 #if defined(IS_LITTLE_ENDIAN)
415 BYTESWAP(left, temp);
416 BYTESWAP(right, temp);
417 #endif
418 #else
419 if (((ptrdiff_t)key & 0x03) == 0) {
420 left = HALFPTR(key)[0];
421 right = HALFPTR(key)[1];
422 #if defined(IS_LITTLE_ENDIAN)
423 BYTESWAP(left, temp);
424 BYTESWAP(right, temp);
425 #endif
426 } else {
427 left = ((HALF)key[0] << 24) | ((HALF)key[1] << 16) |
428 ((HALF)key[2] << 8) | key[3];
429 right = ((HALF)key[4] << 24) | ((HALF)key[5] << 16) |
430 ((HALF)key[6] << 8) | key[7];
431 }
432 #endif
433
434 PC1(left, right, c0, d0, temp);
435
436 if (direction == DES_ENCRYPT) {
437 delta = 2 * (int)sizeof(HALF);
438 } else {
439 ks += 30;
440 delta = (-2) * (int)sizeof(HALF);
441 }
442
443 for (ls = 0x8103; ls; ls >>= 1) {
444 if (ls & 1) {
445 c0 = LEFT_SHIFT_1(c0);
446 d0 = LEFT_SHIFT_1(d0);
447 } else {
448 c0 = LEFT_SHIFT_2(c0);
449 d0 = LEFT_SHIFT_2(d0);
450 }
451
452 #ifdef USE_INDEXING
453 #define PC2LOOKUP(b, c) PC2[b][c]
454
455 left = PC2LOOKUP(0, ((c0 >> 22) & 0x3F));
456 left |= PC2LOOKUP(1, ((c0 >> 13) & 0x3F));
457 left |= PC2LOOKUP(2, ((c0 >> 4) & 0x38) | (c0 & 0x7));
458 left |= PC2LOOKUP(3, ((c0 >> 18) & 0xC) | ((c0 >> 11) & 0x3) | (c0 & 0x30));
459
460 right = PC2LOOKUP(4, ((d0 >> 22) & 0x3F));
461 right |= PC2LOOKUP(5, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf));
462 right |= PC2LOOKUP(6, ((d0 >> 7) & 0x3F));
463 right |= PC2LOOKUP(7, ((d0 >> 1) & 0x3C) | (d0 & 0x3));
464 #else
465 #define PC2LOOKUP(b, c) *(HALF *)((BYTE *)&PC2[b][0] + (c))
466
467 left = PC2LOOKUP(0, ((c0 >> 20) & 0xFC));
468 left |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC));
469 left |= PC2LOOKUP(2, ((c0 >> 2) & 0xE0) | ((c0 << 2) & 0x1C));
470 left |= PC2LOOKUP(3, ((c0 >> 16) & 0x30) | ((c0 >> 9) & 0xC) | ((c0 << 2) & 0xC0));
471
472 right = PC2LOOKUP(4, ((d0 >> 20) & 0xFC));
473 right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C));
474 right |= PC2LOOKUP(6, ((d0 >> 5) & 0xFC));
475 right |= PC2LOOKUP(7, ((d0 << 1) & 0xF0) | ((d0 << 2) & 0x0C));
476 #endif
477 /* left contains key bits for S1 S3 S2 S4 */
478 /* right contains key bits for S6 S8 S5 S7 */
479 temp = (left << 16) /* S2 S4 XX XX */
480 | (right >> 16); /* XX XX S6 S8 */
481 ks[0] = temp;
482
483 temp = (left & 0xffff0000) /* S1 S3 XX XX */
484 | (right & 0x0000ffff); /* XX XX S5 S7 */
485 ks[1] = temp;
486
487 ks = (HALF *)((BYTE *)ks + delta);
488 }
489 }
490
491 /*
492 * The DES Initial Permutation
493 * if we number the bits of the 8 bytes of input like this (in octal):
494 * 00 01 02 03 04 05 06 07
495 * 10 11 12 13 14 15 16 17
496 * 20 21 22 23 24 25 26 27
497 * 30 31 32 33 34 35 36 37
498 * 40 41 42 43 44 45 46 47
499 * 50 51 52 53 54 55 56 57
500 * 60 61 62 63 64 65 66 67
501 * 70 71 72 73 74 75 76 77
502 * then after the initial permutation, they will be in this order.
503 * 71 61 51 41 31 21 11 01
504 * 73 63 53 43 33 23 13 03
505 * 75 65 55 45 35 25 15 05
506 * 77 67 57 47 37 27 17 07
507 * 70 60 50 40 30 20 10 00
508 * 72 62 52 42 32 22 12 02
509 * 74 64 54 44 34 24 14 04
510 * 76 66 56 46 36 26 16 06
511 *
512 * One way to do this is in two steps:
513 * 1. Flip this matrix about the diagonal from 70-07 as done for PC1.
514 * 2. Rearrange the bytes (rows in the matrix above) with the following code.
515 *
516 * #define swapHiLo(word, temp) \
517 * temp = (word ^ (word >> 24)) & 0x000000ff; \
518 * word ^= temp | (temp << 24);
519 *
520 * right ^= temp = ((left << 8) ^ right) & 0xff00ff00;
521 * left ^= temp >> 8;
522 * swapHiLo(left, temp);
523 * swapHiLo(right,temp);
524 *
525 * However, the two steps can be combined, so that the rows are rearranged
526 * while the matrix is being flipped, reducing the number of bit exchange
527 * operations from 8 ot 5.
528 *
529 * Initial Permutation */
530 #define IP(left, right, temp) \
531 right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
532 left ^= temp << 4; \
533 right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
534 left ^= temp << 16; \
535 right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
536 left ^= temp >> 2; \
537 right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
538 left ^= temp >> 8; \
539 right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
540 left ^= temp << 1;
541
542 /* The Final (Inverse Initial) permutation is done by reversing the
543 ** steps of the Initital Permutation
544 */
545
546 #define FP(left, right, temp) \
547 right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
548 left ^= temp << 1; \
549 right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
550 left ^= temp >> 8; \
551 right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
552 left ^= temp >> 2; \
553 right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
554 left ^= temp << 16; \
555 right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
556 left ^= temp << 4;
557
558 void NO_SANITIZE_ALIGNMENT
DES_Do1Block(HALF * ks,const BYTE * inbuf,BYTE * outbuf)559 DES_Do1Block(HALF *ks, const BYTE *inbuf, BYTE *outbuf)
560 {
561 register HALF left, right;
562 register HALF temp;
563
564 #if defined(HAVE_UNALIGNED_ACCESS)
565 left = HALFPTR(inbuf)[0];
566 right = HALFPTR(inbuf)[1];
567 #if defined(IS_LITTLE_ENDIAN)
568 BYTESWAP(left, temp);
569 BYTESWAP(right, temp);
570 #endif
571 #else
572 if (((ptrdiff_t)inbuf & 0x03) == 0) {
573 left = HALFPTR(inbuf)[0];
574 right = HALFPTR(inbuf)[1];
575 #if defined(IS_LITTLE_ENDIAN)
576 BYTESWAP(left, temp);
577 BYTESWAP(right, temp);
578 #endif
579 } else {
580 left = ((HALF)inbuf[0] << 24) | ((HALF)inbuf[1] << 16) |
581 ((HALF)inbuf[2] << 8) | inbuf[3];
582 right = ((HALF)inbuf[4] << 24) | ((HALF)inbuf[5] << 16) |
583 ((HALF)inbuf[6] << 8) | inbuf[7];
584 }
585 #endif
586
587 IP(left, right, temp);
588
589 /* shift the values left circularly 3 bits. */
590 left = (left << 3) | (left >> 29);
591 right = (right << 3) | (right >> 29);
592
593 #ifdef USE_INDEXING
594 #define KSLOOKUP(s, b) SP[s][((temp >> (b + 2)) & 0x3f)]
595 #else
596 #define KSLOOKUP(s, b) *(HALF *)((BYTE *)&SP[s][0] + ((temp >> b) & 0xFC))
597 #endif
598 #define ROUND(out, in, r) \
599 temp = in ^ ks[2 * r]; \
600 out ^= KSLOOKUP(1, 24); \
601 out ^= KSLOOKUP(3, 16); \
602 out ^= KSLOOKUP(5, 8); \
603 out ^= KSLOOKUP(7, 0); \
604 temp = ((in >> 4) | (in << 28)) ^ ks[2 * r + 1]; \
605 out ^= KSLOOKUP(0, 24); \
606 out ^= KSLOOKUP(2, 16); \
607 out ^= KSLOOKUP(4, 8); \
608 out ^= KSLOOKUP(6, 0);
609
610 /* Do the 16 Feistel rounds */
611 ROUND(left, right, 0)
612 ROUND(right, left, 1)
613 ROUND(left, right, 2)
614 ROUND(right, left, 3)
615 ROUND(left, right, 4)
616 ROUND(right, left, 5)
617 ROUND(left, right, 6)
618 ROUND(right, left, 7)
619 ROUND(left, right, 8)
620 ROUND(right, left, 9)
621 ROUND(left, right, 10)
622 ROUND(right, left, 11)
623 ROUND(left, right, 12)
624 ROUND(right, left, 13)
625 ROUND(left, right, 14)
626 ROUND(right, left, 15)
627
628 /* now shift circularly right 3 bits to undo the shifting done
629 ** above. switch left and right here.
630 */
631 temp = (left >> 3) | (left << 29);
632 left = (right >> 3) | (right << 29);
633 right = temp;
634
635 FP(left, right, temp);
636
637 #if defined(HAVE_UNALIGNED_ACCESS)
638 #if defined(IS_LITTLE_ENDIAN)
639 BYTESWAP(left, temp);
640 BYTESWAP(right, temp);
641 #endif
642 HALFPTR(outbuf)
643 [0] = left;
644 HALFPTR(outbuf)
645 [1] = right;
646 #else
647 if (((ptrdiff_t)outbuf & 0x03) == 0) {
648 #if defined(IS_LITTLE_ENDIAN)
649 BYTESWAP(left, temp);
650 BYTESWAP(right, temp);
651 #endif
652 HALFPTR(outbuf)
653 [0] = left;
654 HALFPTR(outbuf)
655 [1] = right;
656 } else {
657 outbuf[0] = (BYTE)(left >> 24);
658 outbuf[1] = (BYTE)(left >> 16);
659 outbuf[2] = (BYTE)(left >> 8);
660 outbuf[3] = (BYTE)(left);
661
662 outbuf[4] = (BYTE)(right >> 24);
663 outbuf[5] = (BYTE)(right >> 16);
664 outbuf[6] = (BYTE)(right >> 8);
665 outbuf[7] = (BYTE)(right);
666 }
667 #endif
668 }
669
670 /* Ackowledgements:
671 ** Two ideas used in this implementation were shown to me by Dennis Ferguson
672 ** in 1990. He credits them to Richard Outerbridge and Dan Hoey. They were:
673 ** 1. The method of computing the Initial and Final permutations.
674 ** 2. Circularly rotating the SP tables and the initial values of left and
675 ** right to reduce the number of shifts required during the 16 rounds.
676 */
677