xref: /freebsd/contrib/bearssl/src/symcipher/des_tab.c (revision ce6a89e27cd190313be39bb479880aeda4778436)
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
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
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
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
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
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