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