Coverage Report

Created: 2025-06-24 06:49

/src/nss/lib/freebl/des.c
Line
Count
Source
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
528k
    temp = (word ^ (word >> 18)) & 0x00003333; \
352
528k
    word ^= temp | (temp << 18);               \
353
528k
    temp = (word ^ (word >> 9)) & 0x00550055;  \
354
528k
    word ^= temp | (temp << 9);
355
356
#if defined(__GNUC__) && defined(NSS_X86_OR_X64)
357
#define BYTESWAP(word, temp) \
358
5.83M
    __asm("bswap  %0"        \
359
5.83M
          : "+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
264k
    right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
388
264k
    left ^= temp << 4;                                  \
389
264k
    FLIP_RIGHT_DIAGONAL(left, temp);                    \
390
264k
    FLIP_RIGHT_DIAGONAL(right, temp);                   \
391
264k
    BYTESWAP(right, temp);                              \
392
264k
    c0 = right >> 4;                                    \
393
264k
    d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
394
395
2.11M
#define LEFT_SHIFT_1(reg) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)
396
6.34M
#define LEFT_SHIFT_2(reg) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)
397
398
/*
399
 *   setup key schedules from key
400
 */
401
402
void
403
DES_MakeSchedule(HALF *ks, const BYTE *key, DESDirection direction)
404
264k
{
405
264k
    register HALF left, right;
406
264k
    register HALF c0, d0;
407
264k
    register HALF temp;
408
264k
    int delta;
409
264k
    unsigned int ls;
410
411
264k
#if defined(HAVE_UNALIGNED_ACCESS)
412
264k
    left = HALFPTR(key)[0];
413
264k
    right = HALFPTR(key)[1];
414
264k
#if defined(IS_LITTLE_ENDIAN)
415
264k
    BYTESWAP(left, temp);
416
264k
    BYTESWAP(right, temp);
417
264k
#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
264k
    PC1(left, right, c0, d0, temp);
435
436
264k
    if (direction == DES_ENCRYPT) {
437
157k
        delta = 2 * (int)sizeof(HALF);
438
157k
    } else {
439
107k
        ks += 30;
440
107k
        delta = (-2) * (int)sizeof(HALF);
441
107k
    }
442
443
4.49M
    for (ls = 0x8103; ls; ls >>= 1) {
444
4.22M
        if (ls & 1) {
445
1.05M
            c0 = LEFT_SHIFT_1(c0);
446
1.05M
            d0 = LEFT_SHIFT_1(d0);
447
3.17M
        } else {
448
3.17M
            c0 = LEFT_SHIFT_2(c0);
449
3.17M
            d0 = LEFT_SHIFT_2(d0);
450
3.17M
        }
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
33.8M
#define PC2LOOKUP(b, c) *(HALF *)((BYTE *)&PC2[b][0] + (c))
466
467
4.22M
        left = PC2LOOKUP(0, ((c0 >> 20) & 0xFC));
468
4.22M
        left |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC));
469
4.22M
        left |= PC2LOOKUP(2, ((c0 >> 2) & 0xE0) | ((c0 << 2) & 0x1C));
470
4.22M
        left |= PC2LOOKUP(3, ((c0 >> 16) & 0x30) | ((c0 >> 9) & 0xC) | ((c0 << 2) & 0xC0));
471
472
4.22M
        right = PC2LOOKUP(4, ((d0 >> 20) & 0xFC));
473
4.22M
        right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C));
474
4.22M
        right |= PC2LOOKUP(6, ((d0 >> 5) & 0xFC));
475
4.22M
        right |= PC2LOOKUP(7, ((d0 << 1) & 0xF0) | ((d0 << 2) & 0x0C));
476
4.22M
#endif
477
        /* left  contains key bits for S1 S3 S2 S4 */
478
        /* right contains key bits for S6 S8 S5 S7 */
479
4.22M
        temp = (left << 16)     /* S2 S4 XX XX */
480
4.22M
               | (right >> 16); /* XX XX S6 S8 */
481
4.22M
        ks[0] = temp;
482
483
4.22M
        temp = (left & 0xffff0000)     /* S1 S3 XX XX */
484
4.22M
               | (right & 0x0000ffff); /* XX XX S5 S7 */
485
4.22M
        ks[1] = temp;
486
487
4.22M
        ks = (HALF *)((BYTE *)ks + delta);
488
4.22M
    }
489
264k
}
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
1.26M
    right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f;  \
532
1.26M
    left ^= temp << 4;                                   \
533
1.26M
    right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
534
1.26M
    left ^= temp << 16;                                  \
535
1.26M
    right ^= temp = ((left << 2) ^ right) & 0xcccccccc;  \
536
1.26M
    left ^= temp >> 2;                                   \
537
1.26M
    right ^= temp = ((left << 8) ^ right) & 0xff00ff00;  \
538
1.26M
    left ^= temp >> 8;                                   \
539
1.26M
    right ^= temp = ((left >> 1) ^ right) & 0x55555555;  \
540
1.26M
    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
1.26M
    right ^= temp = ((left >> 1) ^ right) & 0x55555555;  \
548
1.26M
    left ^= temp << 1;                                   \
549
1.26M
    right ^= temp = ((left << 8) ^ right) & 0xff00ff00;  \
550
1.26M
    left ^= temp >> 8;                                   \
551
1.26M
    right ^= temp = ((left << 2) ^ right) & 0xcccccccc;  \
552
1.26M
    left ^= temp >> 2;                                   \
553
1.26M
    right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
554
1.26M
    left ^= temp << 16;                                  \
555
1.26M
    right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f;  \
556
1.26M
    left ^= temp << 4;
557
558
void NO_SANITIZE_ALIGNMENT
559
DES_Do1Block(HALF *ks, const BYTE *inbuf, BYTE *outbuf)
560
1.26M
{
561
1.26M
    register HALF left, right;
562
1.26M
    register HALF temp;
563
564
1.26M
#if defined(HAVE_UNALIGNED_ACCESS)
565
1.26M
    left = HALFPTR(inbuf)[0];
566
1.26M
    right = HALFPTR(inbuf)[1];
567
1.26M
#if defined(IS_LITTLE_ENDIAN)
568
1.26M
    BYTESWAP(left, temp);
569
1.26M
    BYTESWAP(right, temp);
570
1.26M
#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
1.26M
    IP(left, right, temp);
588
589
    /* shift the values left circularly 3 bits. */
590
1.26M
    left = (left << 3) | (left >> 29);
591
1.26M
    right = (right << 3) | (right >> 29);
592
593
#ifdef USE_INDEXING
594
#define KSLOOKUP(s, b) SP[s][((temp >> (b + 2)) & 0x3f)]
595
#else
596
161M
#define KSLOOKUP(s, b) *(HALF *)((BYTE *)&SP[s][0] + ((temp >> b) & 0xFC))
597
1.26M
#endif
598
1.26M
#define ROUND(out, in, r)                            \
599
20.1M
    temp = in ^ ks[2 * r];                           \
600
20.1M
    out ^= KSLOOKUP(1, 24);                          \
601
20.1M
    out ^= KSLOOKUP(3, 16);                          \
602
20.1M
    out ^= KSLOOKUP(5, 8);                           \
603
20.1M
    out ^= KSLOOKUP(7, 0);                           \
604
20.1M
    temp = ((in >> 4) | (in << 28)) ^ ks[2 * r + 1]; \
605
20.1M
    out ^= KSLOOKUP(0, 24);                          \
606
20.1M
    out ^= KSLOOKUP(2, 16);                          \
607
20.1M
    out ^= KSLOOKUP(4, 8);                           \
608
20.1M
    out ^= KSLOOKUP(6, 0);
609
610
    /* Do the 16 Feistel rounds */
611
1.26M
    ROUND(left, right, 0)
612
1.26M
    ROUND(right, left, 1)
613
1.26M
    ROUND(left, right, 2)
614
1.26M
    ROUND(right, left, 3)
615
1.26M
    ROUND(left, right, 4)
616
1.26M
    ROUND(right, left, 5)
617
1.26M
    ROUND(left, right, 6)
618
1.26M
    ROUND(right, left, 7)
619
1.26M
    ROUND(left, right, 8)
620
1.26M
    ROUND(right, left, 9)
621
1.26M
    ROUND(left, right, 10)
622
1.26M
    ROUND(right, left, 11)
623
1.26M
    ROUND(left, right, 12)
624
1.26M
    ROUND(right, left, 13)
625
1.26M
    ROUND(left, right, 14)
626
1.26M
    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
1.26M
    temp = (left >> 3) | (left << 29);
632
1.26M
    left = (right >> 3) | (right << 29);
633
1.26M
    right = temp;
634
635
1.26M
    FP(left, right, temp);
636
637
1.26M
#if defined(HAVE_UNALIGNED_ACCESS)
638
1.26M
#if defined(IS_LITTLE_ENDIAN)
639
1.26M
    BYTESWAP(left, temp);
640
1.26M
    BYTESWAP(right, temp);
641
1.26M
#endif
642
1.26M
    HALFPTR(outbuf)
643
1.26M
    [0] = left;
644
1.26M
    HALFPTR(outbuf)
645
1.26M
    [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
1.26M
}
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
*/