1 /*
2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include "inner.h"
26
27 /*
28 * PC2left[x] tells where bit x goes when applying PC-2. 'x' is a bit
29 * position in the left rotated key word. Both position are in normal
30 * order (rightmost bit is 0).
31 */
32 static const unsigned char PC2left[] = {
33 16, 3, 7, 24, 20, 11, 24,
34 13, 2, 10, 24, 22, 5, 15,
35 23, 1, 9, 21, 12, 24, 6,
36 4, 14, 18, 8, 17, 0, 19
37 };
38
39 /*
40 * Similar to PC2left[x], for the right rotated key word.
41 */
42 static const unsigned char PC2right[] = {
43 8, 18, 24, 6, 22, 15, 3,
44 10, 12, 19, 5, 14, 11, 24,
45 4, 23, 16, 9, 24, 20, 2,
46 24, 7, 13, 0, 21, 17, 1
47 };
48
49 /*
50 * S-boxes and PC-1 merged.
51 */
52 static const uint32_t S1[] = {
53 0x00808200, 0x00000000, 0x00008000, 0x00808202,
54 0x00808002, 0x00008202, 0x00000002, 0x00008000,
55 0x00000200, 0x00808200, 0x00808202, 0x00000200,
56 0x00800202, 0x00808002, 0x00800000, 0x00000002,
57 0x00000202, 0x00800200, 0x00800200, 0x00008200,
58 0x00008200, 0x00808000, 0x00808000, 0x00800202,
59 0x00008002, 0x00800002, 0x00800002, 0x00008002,
60 0x00000000, 0x00000202, 0x00008202, 0x00800000,
61 0x00008000, 0x00808202, 0x00000002, 0x00808000,
62 0x00808200, 0x00800000, 0x00800000, 0x00000200,
63 0x00808002, 0x00008000, 0x00008200, 0x00800002,
64 0x00000200, 0x00000002, 0x00800202, 0x00008202,
65 0x00808202, 0x00008002, 0x00808000, 0x00800202,
66 0x00800002, 0x00000202, 0x00008202, 0x00808200,
67 0x00000202, 0x00800200, 0x00800200, 0x00000000,
68 0x00008002, 0x00008200, 0x00000000, 0x00808002
69 };
70
71 static const uint32_t S2[] = {
72 0x40084010, 0x40004000, 0x00004000, 0x00084010,
73 0x00080000, 0x00000010, 0x40080010, 0x40004010,
74 0x40000010, 0x40084010, 0x40084000, 0x40000000,
75 0x40004000, 0x00080000, 0x00000010, 0x40080010,
76 0x00084000, 0x00080010, 0x40004010, 0x00000000,
77 0x40000000, 0x00004000, 0x00084010, 0x40080000,
78 0x00080010, 0x40000010, 0x00000000, 0x00084000,
79 0x00004010, 0x40084000, 0x40080000, 0x00004010,
80 0x00000000, 0x00084010, 0x40080010, 0x00080000,
81 0x40004010, 0x40080000, 0x40084000, 0x00004000,
82 0x40080000, 0x40004000, 0x00000010, 0x40084010,
83 0x00084010, 0x00000010, 0x00004000, 0x40000000,
84 0x00004010, 0x40084000, 0x00080000, 0x40000010,
85 0x00080010, 0x40004010, 0x40000010, 0x00080010,
86 0x00084000, 0x00000000, 0x40004000, 0x00004010,
87 0x40000000, 0x40080010, 0x40084010, 0x00084000
88 };
89
90 static const uint32_t S3[] = {
91 0x00000104, 0x04010100, 0x00000000, 0x04010004,
92 0x04000100, 0x00000000, 0x00010104, 0x04000100,
93 0x00010004, 0x04000004, 0x04000004, 0x00010000,
94 0x04010104, 0x00010004, 0x04010000, 0x00000104,
95 0x04000000, 0x00000004, 0x04010100, 0x00000100,
96 0x00010100, 0x04010000, 0x04010004, 0x00010104,
97 0x04000104, 0x00010100, 0x00010000, 0x04000104,
98 0x00000004, 0x04010104, 0x00000100, 0x04000000,
99 0x04010100, 0x04000000, 0x00010004, 0x00000104,
100 0x00010000, 0x04010100, 0x04000100, 0x00000000,
101 0x00000100, 0x00010004, 0x04010104, 0x04000100,
102 0x04000004, 0x00000100, 0x00000000, 0x04010004,
103 0x04000104, 0x00010000, 0x04000000, 0x04010104,
104 0x00000004, 0x00010104, 0x00010100, 0x04000004,
105 0x04010000, 0x04000104, 0x00000104, 0x04010000,
106 0x00010104, 0x00000004, 0x04010004, 0x00010100
107 };
108
109 static const uint32_t S4[] = {
110 0x80401000, 0x80001040, 0x80001040, 0x00000040,
111 0x00401040, 0x80400040, 0x80400000, 0x80001000,
112 0x00000000, 0x00401000, 0x00401000, 0x80401040,
113 0x80000040, 0x00000000, 0x00400040, 0x80400000,
114 0x80000000, 0x00001000, 0x00400000, 0x80401000,
115 0x00000040, 0x00400000, 0x80001000, 0x00001040,
116 0x80400040, 0x80000000, 0x00001040, 0x00400040,
117 0x00001000, 0x00401040, 0x80401040, 0x80000040,
118 0x00400040, 0x80400000, 0x00401000, 0x80401040,
119 0x80000040, 0x00000000, 0x00000000, 0x00401000,
120 0x00001040, 0x00400040, 0x80400040, 0x80000000,
121 0x80401000, 0x80001040, 0x80001040, 0x00000040,
122 0x80401040, 0x80000040, 0x80000000, 0x00001000,
123 0x80400000, 0x80001000, 0x00401040, 0x80400040,
124 0x80001000, 0x00001040, 0x00400000, 0x80401000,
125 0x00000040, 0x00400000, 0x00001000, 0x00401040
126 };
127
128 static const uint32_t S5[] = {
129 0x00000080, 0x01040080, 0x01040000, 0x21000080,
130 0x00040000, 0x00000080, 0x20000000, 0x01040000,
131 0x20040080, 0x00040000, 0x01000080, 0x20040080,
132 0x21000080, 0x21040000, 0x00040080, 0x20000000,
133 0x01000000, 0x20040000, 0x20040000, 0x00000000,
134 0x20000080, 0x21040080, 0x21040080, 0x01000080,
135 0x21040000, 0x20000080, 0x00000000, 0x21000000,
136 0x01040080, 0x01000000, 0x21000000, 0x00040080,
137 0x00040000, 0x21000080, 0x00000080, 0x01000000,
138 0x20000000, 0x01040000, 0x21000080, 0x20040080,
139 0x01000080, 0x20000000, 0x21040000, 0x01040080,
140 0x20040080, 0x00000080, 0x01000000, 0x21040000,
141 0x21040080, 0x00040080, 0x21000000, 0x21040080,
142 0x01040000, 0x00000000, 0x20040000, 0x21000000,
143 0x00040080, 0x01000080, 0x20000080, 0x00040000,
144 0x00000000, 0x20040000, 0x01040080, 0x20000080
145 };
146
147 static const uint32_t S6[] = {
148 0x10000008, 0x10200000, 0x00002000, 0x10202008,
149 0x10200000, 0x00000008, 0x10202008, 0x00200000,
150 0x10002000, 0x00202008, 0x00200000, 0x10000008,
151 0x00200008, 0x10002000, 0x10000000, 0x00002008,
152 0x00000000, 0x00200008, 0x10002008, 0x00002000,
153 0x00202000, 0x10002008, 0x00000008, 0x10200008,
154 0x10200008, 0x00000000, 0x00202008, 0x10202000,
155 0x00002008, 0x00202000, 0x10202000, 0x10000000,
156 0x10002000, 0x00000008, 0x10200008, 0x00202000,
157 0x10202008, 0x00200000, 0x00002008, 0x10000008,
158 0x00200000, 0x10002000, 0x10000000, 0x00002008,
159 0x10000008, 0x10202008, 0x00202000, 0x10200000,
160 0x00202008, 0x10202000, 0x00000000, 0x10200008,
161 0x00000008, 0x00002000, 0x10200000, 0x00202008,
162 0x00002000, 0x00200008, 0x10002008, 0x00000000,
163 0x10202000, 0x10000000, 0x00200008, 0x10002008
164 };
165
166 static const uint32_t S7[] = {
167 0x00100000, 0x02100001, 0x02000401, 0x00000000,
168 0x00000400, 0x02000401, 0x00100401, 0x02100400,
169 0x02100401, 0x00100000, 0x00000000, 0x02000001,
170 0x00000001, 0x02000000, 0x02100001, 0x00000401,
171 0x02000400, 0x00100401, 0x00100001, 0x02000400,
172 0x02000001, 0x02100000, 0x02100400, 0x00100001,
173 0x02100000, 0x00000400, 0x00000401, 0x02100401,
174 0x00100400, 0x00000001, 0x02000000, 0x00100400,
175 0x02000000, 0x00100400, 0x00100000, 0x02000401,
176 0x02000401, 0x02100001, 0x02100001, 0x00000001,
177 0x00100001, 0x02000000, 0x02000400, 0x00100000,
178 0x02100400, 0x00000401, 0x00100401, 0x02100400,
179 0x00000401, 0x02000001, 0x02100401, 0x02100000,
180 0x00100400, 0x00000000, 0x00000001, 0x02100401,
181 0x00000000, 0x00100401, 0x02100000, 0x00000400,
182 0x02000001, 0x02000400, 0x00000400, 0x00100001
183 };
184
185 static const uint32_t S8[] = {
186 0x08000820, 0x00000800, 0x00020000, 0x08020820,
187 0x08000000, 0x08000820, 0x00000020, 0x08000000,
188 0x00020020, 0x08020000, 0x08020820, 0x00020800,
189 0x08020800, 0x00020820, 0x00000800, 0x00000020,
190 0x08020000, 0x08000020, 0x08000800, 0x00000820,
191 0x00020800, 0x00020020, 0x08020020, 0x08020800,
192 0x00000820, 0x00000000, 0x00000000, 0x08020020,
193 0x08000020, 0x08000800, 0x00020820, 0x00020000,
194 0x00020820, 0x00020000, 0x08020800, 0x00000800,
195 0x00000020, 0x08020020, 0x00000800, 0x00020820,
196 0x08000800, 0x00000020, 0x08000020, 0x08020000,
197 0x08020020, 0x08000000, 0x00020000, 0x08000820,
198 0x00000000, 0x08020820, 0x00020020, 0x08000020,
199 0x08020000, 0x08000800, 0x08000820, 0x00000000,
200 0x08020820, 0x00020800, 0x00020800, 0x00000820,
201 0x00000820, 0x00020020, 0x08000000, 0x08020800
202 };
203
204 static inline uint32_t
Fconf(uint32_t r0,uint32_t skl,uint32_t skr)205 Fconf(uint32_t r0, uint32_t skl, uint32_t skr)
206 {
207 uint32_t r1;
208
209 r1 = (r0 << 16) | (r0 >> 16);
210 return
211 S1[((r1 >> 11) ^ (skl >> 18)) & 0x3F]
212 | S2[((r0 >> 23) ^ (skl >> 12)) & 0x3F]
213 | S3[((r0 >> 19) ^ (skl >> 6)) & 0x3F]
214 | S4[((r0 >> 15) ^ (skl )) & 0x3F]
215 | S5[((r0 >> 11) ^ (skr >> 18)) & 0x3F]
216 | S6[((r0 >> 7) ^ (skr >> 12)) & 0x3F]
217 | S7[((r0 >> 3) ^ (skr >> 6)) & 0x3F]
218 | S8[((r1 >> 15) ^ (skr )) & 0x3F];
219 }
220
221 static void
process_block_unit(uint32_t * pl,uint32_t * pr,const uint32_t * skey)222 process_block_unit(uint32_t *pl, uint32_t *pr, const uint32_t *skey)
223 {
224 int i;
225 uint32_t l, r;
226
227 l = *pl;
228 r = *pr;
229 for (i = 0; i < 16; i ++) {
230 uint32_t t;
231
232 t = l ^ Fconf(r, skey[(i << 1) + 0], skey[(i << 1) + 1]);
233 l = r;
234 r = t;
235 }
236 *pl = r;
237 *pr = l;
238 }
239
240 /* see inner.h */
241 void
br_des_tab_process_block(unsigned num_rounds,const uint32_t * skey,void * block)242 br_des_tab_process_block(unsigned num_rounds, const uint32_t *skey, void *block)
243 {
244 unsigned char *buf;
245 uint32_t l, r;
246
247 buf = block;
248 l = br_dec32be(buf);
249 r = br_dec32be(buf + 4);
250 br_des_do_IP(&l, &r);
251 while (num_rounds -- > 0) {
252 process_block_unit(&l, &r, skey);
253 skey += 32;
254 }
255 br_des_do_invIP(&l, &r);
256 br_enc32be(buf, l);
257 br_enc32be(buf + 4, r);
258 }
259
260 static void
keysched_unit(uint32_t * skey,const void * key)261 keysched_unit(uint32_t *skey, const void *key)
262 {
263 int i;
264
265 br_des_keysched_unit(skey, key);
266
267 /*
268 * Apply PC-2 to get the 48-bit subkeys.
269 */
270 for (i = 0; i < 16; i ++) {
271 uint32_t xl, xr, ul, ur;
272 int j;
273
274 xl = skey[(i << 1) + 0];
275 xr = skey[(i << 1) + 1];
276 ul = 0;
277 ur = 0;
278 for (j = 0; j < 28; j ++) {
279 ul |= (xl & 1) << PC2left[j];
280 ur |= (xr & 1) << PC2right[j];
281 xl >>= 1;
282 xr >>= 1;
283 }
284 skey[(i << 1) + 0] = ul;
285 skey[(i << 1) + 1] = ur;
286 }
287 }
288
289 /* see inner.h */
290 unsigned
br_des_tab_keysched(uint32_t * skey,const void * key,size_t key_len)291 br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len)
292 {
293 switch (key_len) {
294 case 8:
295 keysched_unit(skey, key);
296 return 1;
297 case 16:
298 keysched_unit(skey, key);
299 keysched_unit(skey + 32, (const unsigned char *)key + 8);
300 br_des_rev_skey(skey + 32);
301 memcpy(skey + 64, skey, 32 * sizeof *skey);
302 return 3;
303 default:
304 keysched_unit(skey, key);
305 keysched_unit(skey + 32, (const unsigned char *)key + 8);
306 br_des_rev_skey(skey + 32);
307 keysched_unit(skey + 64, (const unsigned char *)key + 16);
308 return 3;
309 }
310 }
311