Botan 3.11.0
Crypto and TLS for C&
des.cpp
Go to the documentation of this file.
1/*
2* DES
3* (C) 1999-2008,2018,2020,2026 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/des.h>
9
10#include <botan/compiler.h>
11#include <botan/internal/bit_ops.h>
12#include <botan/internal/loadstor.h>
13
14namespace Botan {
15
16namespace {
17
18template <typename T>
19concept BitsliceT = requires(T& a, const T& b) {
20 a ^= b;
21 a &= b;
22 a |= b;
23 ~a;
24};
25
26/*
27* The circuits for the DES sboxes used here were found by Roman Rusakov and
28* Solar Designer for use in JtR. The designers explicitly disclaimed all
29* copyright with regards to the circuits themselves ("Being mathematical
30* formulas, they are not copyrighted and are free for reuse by anyone.")
31*
32* John The Ripper also contains Sbox circuit descriptions making use of select
33* and ternlogd-style instruction sets which are significantly more compact than
34* these circuits. Sadly, very few CPUs support such instructions on GPRs.
35*/
36
37template <BitsliceT T>
38BOTAN_FORCE_INLINE void SBox1(T a1, T a2, T a3, T a4, T a5, T a6, T& out1, T& out2, T& out3, T& out4) {
39 const T x1 = a1 & ~a5;
40 const T x2 = a4 ^ x1;
41 const T x3 = a3 | a6;
42 const T x4 = a1 ^ a3;
43 const T x5 = x3 & x4;
44 const T x6 = a4 ^ x5;
45 const T x7 = x6 & ~x2;
46
47 const T x8 = a5 ^ a6;
48 const T x9 = a3 ^ x8;
49 const T x10 = x2 & ~x9;
50 const T x11 = a6 | x5;
51 const T x12 = x10 ^ x11;
52 const T x13 = x12 & ~x7;
53
54 const T x14 = a1 | a6;
55 const T x15 = x12 | x14;
56 const T x16 = a5 & ~x6;
57 const T x17 = x15 ^ x16;
58
59 const T x18 = a4 & ~x14;
60 const T x19 = x16 ^ x18;
61 const T x20 = x8 & ~x4;
62 const T x21 = x19 | x20;
63
64 const T x22 = a3 & ~x1;
65 const T x23 = x2 ^ x15;
66 const T x24 = x23 & ~x22;
67 const T x25 = ~x24;
68 const T x26 = x3 & x12;
69 const T x27 = x25 ^ x26;
70 const T x28 = x17 & ~a2;
71 const T x29 = x28 ^ x27;
72 out3 ^= x29;
73
74 const T x30 = x8 ^ x24;
75 const T x31 = x16 | x30;
76 const T x32 = x3 ^ x31;
77 const T x33 = a1 ^ x32;
78 const T x34 = x27 ^ x33;
79 const T x35 = x7 | a2;
80 const T x36 = x35 ^ x34;
81 out1 ^= x36;
82
83 const T x37 = x2 & ~x21;
84 const T x38 = x30 ^ x37;
85 const T x39 = x16 ^ x32;
86 const T x40 = x34 & ~x39;
87 const T x41 = x38 ^ x40;
88 const T x42 = a2 & ~x13;
89 const T x43 = x42 ^ x41;
90 out2 ^= x43;
91
92 const T x44 = x9 ^ x20;
93 const T x45 = x14 ^ x40;
94 const T x46 = x45 & ~x44;
95 const T x47 = x41 ^ x46;
96 const T x48 = x47 | a2;
97 const T x49 = x48 ^ x21;
98 out4 ^= x49;
99}
100
101template <BitsliceT T>
102BOTAN_FORCE_INLINE void SBox2(T a1, T a2, T a3, T a4, T a5, T a6, T& out1, T& out2, T& out3, T& out4) {
103 const T x1 = a2 ^ a5;
104
105 const T x2 = a1 & ~a6;
106 const T x3 = a5 & ~x2;
107 const T x4 = a2 | x3;
108
109 const T x5 = x1 & ~a6;
110 const T x6 = a1 & x1;
111 const T x7 = a5 ^ x6;
112 const T x8 = x7 & ~x5;
113
114 const T x9 = a3 & a6;
115 const T x10 = x3 ^ x5;
116 const T x11 = x4 & x10;
117 const T x12 = x11 & ~x9;
118
119 const T x13 = a3 & x11;
120 const T x14 = ~a1;
121 const T x15 = x13 ^ x14;
122 const T x16 = a6 ^ x1;
123 const T x17 = x16 & ~x9;
124 const T x18 = x15 ^ x17;
125 const T x19 = a4 & ~x12;
126 const T x20 = x19 ^ x18;
127 out2 ^= x20;
128
129 const T x21 = a2 & ~x17;
130 const T x22 = x7 ^ x21;
131 const T x23 = x15 & ~x22;
132 const T x24 = a3 ^ x16;
133 const T x25 = x23 ^ x24;
134 const T x26 = x4 & ~a4;
135 const T x27 = x26 ^ x25;
136 out1 ^= x27;
137
138 const T x28 = a2 & ~x9;
139 const T x29 = x24 | x28;
140 const T x30 = x4 ^ x18;
141 const T x31 = x9 | x30;
142 const T x32 = x29 ^ x31;
143
144 const T x33 = x11 ^ x18;
145 const T x34 = x25 ^ x33;
146 const T x35 = x31 & x34;
147 const T x36 = x1 & x29;
148 const T x37 = x35 ^ x36;
149 const T x38 = x37 | a4;
150 const T x39 = x38 ^ x32;
151 out3 ^= x39;
152
153 const T x40 = x37 & ~x22;
154 const T x41 = x16 | x30;
155 const T x42 = x40 ^ x41;
156 const T x43 = x8 | a4;
157 const T x44 = x43 ^ x42;
158 out4 ^= x44;
159}
160
161template <BitsliceT T>
162BOTAN_FORCE_INLINE void SBox3(T a1, T a2, T a3, T a4, T a5, T a6, T& out1, T& out2, T& out3, T& out4) {
163 const T x1 = a1 & ~a2;
164 const T x2 = a3 ^ a6;
165 const T x3 = x1 | x2;
166 const T x4 = a4 ^ a6;
167 const T x5 = x4 & ~a1;
168 const T x6 = x3 ^ x5;
169
170 const T x7 = a2 ^ x2;
171 const T x8 = x7 & ~a6;
172 const T x9 = x3 ^ x8;
173 const T x10 = x6 & ~x9;
174
175 const T x11 = a6 & x6;
176 const T x12 = a4 | x11;
177 const T x13 = a1 & x12;
178 const T x14 = x7 ^ x13;
179 const T x15 = x6 & ~a5;
180 const T x16 = x15 ^ x14;
181 out4 ^= x16;
182
183 const T x17 = x2 & x4;
184 const T x18 = a1 ^ a4;
185 const T x19 = x9 ^ x18;
186 const T x20 = a3 | x19;
187 const T x21 = x20 & ~x17;
188
189 const T x22 = x5 | x18;
190 const T x23 = x14 & ~x22;
191 const T x24 = a4 & a6;
192 const T x25 = x24 & ~a2;
193 const T x26 = x23 ^ x25;
194
195 const T x27 = x9 & x26;
196 const T x28 = x7 | x24;
197 const T x29 = x28 & ~x27;
198 const T x30 = a1 ^ x29;
199 const T x31 = x21 & a5;
200 const T x32 = x31 ^ x30;
201 out2 ^= x32;
202
203 const T x33 = x6 & ~a2;
204 const T x34 = x33 & ~a3;
205 const T x35 = ~x7;
206 const T x36 = x22 ^ x35;
207 const T x37 = x34 ^ x36;
208 const T x38 = a5 & ~x10;
209 const T x39 = x38 ^ x37;
210 out1 ^= x39;
211
212 const T x40 = x34 | x36;
213 const T x41 = x5 | x33;
214 const T x42 = x40 ^ x41;
215 const T x43 = a4 & ~x6;
216 const T x44 = x42 | x43;
217 const T x45 = a5 & ~x26;
218 const T x46 = x45 ^ x44;
219 out3 ^= x46;
220}
221
222template <BitsliceT T>
223BOTAN_FORCE_INLINE void SBox4(T a1, T a2, T a3, T a4, T a5, T a6, T& out1, T& out2, T& out3, T& out4) {
224 const T x1 = a1 ^ a3;
225 const T x2 = a3 ^ a5;
226 const T x3 = a2 | a4;
227 const T x4 = a5 ^ x3;
228 const T x5 = x2 & ~x4;
229 const T x6 = x2 & ~a2;
230 const T x7 = a4 ^ x6;
231 const T x8 = x1 | x7;
232 const T x9 = x8 & ~x5;
233 const T x10 = a2 ^ x9;
234
235 const T x11 = x7 & x10;
236 const T x12 = x2 & ~x11;
237 const T x13 = x1 ^ x10;
238 const T x14 = x13 & ~x12;
239 const T x15 = x5 ^ x14;
240
241 const T x16 = a2 ^ a4;
242 const T x17 = a5 | x6;
243 const T x18 = x13 ^ x17;
244 const T x19 = x18 & ~x16;
245 const T x20 = x9 ^ x19;
246 const T x21 = a6 & ~x15;
247 const T x22 = x21 ^ x20;
248 out1 ^= x22;
249
250 const T x23 = ~x20;
251 const T x24 = x15 & ~a6;
252 const T x25 = x24 ^ x23;
253 out2 ^= x25;
254
255 const T x26 = x15 ^ x23;
256 const T x27 = x26 & ~x16;
257 const T x28 = x11 | x27;
258 const T x29 = x18 ^ x28;
259 const T x30 = x10 | a6;
260 const T x31 = x30 ^ x29;
261 out3 ^= x31;
262
263 const T x32 = a6 & x10;
264 const T x33 = x32 ^ x29;
265 out4 ^= x33;
266}
267
268template <BitsliceT T>
269BOTAN_FORCE_INLINE void SBox5(T a1, T a2, T a3, T a4, T a5, T a6, T& out1, T& out2, T& out3, T& out4) {
270 const T x1 = a1 | a3;
271 const T x2 = x1 & ~a6;
272 const T x3 = a1 ^ x2;
273 const T x4 = a3 ^ x3;
274 const T x5 = a4 | x4;
275
276 const T x6 = x2 & ~a4;
277 const T x7 = a3 ^ x6;
278 const T x8 = a5 & x7;
279 const T x9 = a1 | x4;
280 const T x10 = x8 ^ x9;
281 const T x11 = a4 ^ x10;
282
283 const T x12 = a6 ^ x11;
284 const T x13 = x3 | x12;
285 const T x14 = a5 & x13;
286 const T x15 = x3 ^ x14;
287 const T x16 = a4 & x9;
288 const T x17 = x15 ^ x16;
289
290 const T x18 = x13 & ~a1;
291 const T x19 = x7 ^ x18;
292 const T x20 = a5 ^ x5;
293 const T x21 = x20 & ~x19;
294 const T x22 = ~x21;
295 const T x23 = x22 & ~a2;
296 const T x24 = x23 ^ x11;
297 out3 ^= x24;
298
299 const T x25 = x7 & ~x14;
300 const T x26 = x18 ^ x20;
301 const T x27 = x17 | x26;
302 const T x28 = x27 & ~x25;
303 const T x29 = x5 & ~x28;
304
305 const T x30 = x12 & x28;
306 const T x31 = x20 ^ x30;
307 const T x32 = x7 & x9;
308 const T x33 = x31 | x32;
309 const T x34 = x14 ^ x33;
310 const T x35 = x34 & a2;
311 const T x36 = x35 ^ x17;
312 out4 ^= x36;
313
314 const T x37 = x1 ^ x28;
315 const T x38 = a1 ^ x37;
316 const T x39 = a4 & x31;
317 const T x40 = x38 ^ x39;
318 const T x41 = x29 | a2;
319 const T x42 = x41 ^ x40;
320 out1 ^= x42;
321
322 const T x43 = x5 ^ x7;
323 const T x44 = x43 & ~x40;
324 const T x45 = x3 ^ x31;
325 const T x46 = x44 ^ x45;
326 const T x47 = x5 & a2;
327 const T x48 = x47 ^ x46;
328 out2 ^= x48;
329}
330
331template <BitsliceT T>
332BOTAN_FORCE_INLINE void SBox6(T a1, T a2, T a3, T a4, T a5, T a6, T& out1, T& out2, T& out3, T& out4) {
333 const T x1 = a2 ^ a5;
334
335 const T x2 = a2 | a6;
336 const T x3 = a1 & x2;
337 const T x4 = x1 ^ x3;
338 const T x5 = a6 ^ x4;
339 const T x6 = a5 & ~x5;
340
341 const T x7 = a1 & x5;
342 const T x8 = a2 ^ x7;
343 const T x9 = a1 ^ a3;
344 const T x10 = x8 | x9;
345 const T x11 = x4 ^ x10;
346
347 const T x12 = a3 & x11;
348 const T x13 = x12 & ~a6;
349 const T x14 = x6 | x8;
350 const T x15 = x13 ^ x14;
351 const T x16 = x15 & a4;
352 const T x17 = x16 ^ x11;
353 out4 ^= x17;
354
355 const T x18 = a2 ^ x10;
356 const T x19 = a6 & ~x18;
357 const T x20 = a3 ^ x19;
358 const T x21 = a5 & ~x12;
359 const T x22 = x20 | x21;
360
361 const T x23 = a2 | x9;
362 const T x24 = x15 ^ x23;
363 const T x25 = x3 | x22;
364 const T x26 = x24 ^ x25;
365
366 const T x27 = a1 | x11;
367 const T x28 = x14 & x27;
368 const T x29 = x20 ^ x28;
369 const T x30 = x29 & ~x13;
370 const T x31 = x6 | a4;
371 const T x32 = x31 ^ x30;
372 out3 ^= x32;
373
374 const T x33 = x4 ^ x29;
375 const T x34 = a5 & ~x33;
376 const T x35 = ~x23;
377 const T x36 = x18 ^ x35;
378 const T x37 = x34 ^ x36;
379 const T x38 = x37 & ~a4;
380 const T x39 = x38 ^ x26;
381 out2 ^= x39;
382
383 const T x40 = a6 ^ x7;
384 const T x41 = a1 ^ x20;
385 const T x42 = x40 & x41;
386 const T x43 = x12 ^ x36;
387 const T x44 = x42 ^ x43;
388 const T x45 = x22 & ~a4;
389 const T x46 = x45 ^ x44;
390 out1 ^= x46;
391}
392
393template <BitsliceT T>
394BOTAN_FORCE_INLINE void SBox7(T a1, T a2, T a3, T a4, T a5, T a6, T& out1, T& out2, T& out3, T& out4) {
395 const T x1 = a4 ^ a5;
396 const T x2 = a3 ^ x1;
397 const T x3 = a6 & x2;
398 const T x4 = a4 & x1;
399 const T x5 = a2 ^ x4;
400 const T x6 = x3 & x5;
401
402 const T x7 = a6 & x4;
403 const T x8 = a3 ^ x7;
404 const T x9 = x5 | x8;
405 const T x10 = a6 ^ x1;
406 const T x11 = x9 ^ x10;
407 const T x12 = a1 & ~x6;
408 const T x13 = x12 ^ x11;
409 out4 ^= x13;
410
411 const T x14 = a5 & ~x2;
412 const T x15 = x5 | x14;
413 const T x16 = x3 ^ x8;
414 const T x17 = x15 ^ x16;
415
416 const T x18 = x3 ^ x10;
417 const T x19 = a4 & ~x18;
418 const T x20 = x5 & ~x19;
419 const T x21 = a5 ^ x16;
420 const T x22 = x20 ^ x21;
421
422 const T x23 = x18 & ~x7;
423 const T x24 = x19 | x23;
424 const T x25 = a2 ^ x9;
425 const T x26 = x22 & x25;
426 const T x27 = x24 ^ x26;
427 const T x28 = x27 & a1;
428 const T x29 = x28 ^ x22;
429 out3 ^= x29;
430
431 const T x30 = x5 & ~a3;
432 const T x31 = x23 | x30;
433 const T x32 = x4 | x22;
434 const T x33 = x31 & x32;
435 const T x34 = x27 ^ x33;
436
437 const T x35 = x17 | x24;
438 const T x36 = x14 ^ x35;
439 const T x37 = a6 & x36;
440 const T x38 = x33 ^ x37;
441 const T x39 = x38 & ~a1;
442 const T x40 = x39 ^ x17;
443 out1 ^= x40;
444
445 const T x41 = ~x37;
446 const T x42 = a2 | x41;
447 const T x43 = x17 ^ x33;
448 const T x44 = x42 ^ x43;
449 const T x45 = x34 | a1;
450 const T x46 = x45 ^ x44;
451 out2 ^= x46;
452}
453
454template <BitsliceT T>
455BOTAN_FORCE_INLINE void SBox8(T a1, T a2, T a3, T a4, T a5, T a6, T& out1, T& out2, T& out3, T& out4) {
456 const T x1 = a3 & ~a2;
457 const T x2 = a5 & ~a3;
458 const T x3 = a4 ^ x2;
459 const T x4 = a1 & x3;
460 const T x5 = x4 & ~x1;
461
462 const T x6 = a2 & ~x3;
463 const T x7 = a1 | x6;
464 const T x8 = a2 & ~a3;
465 const T x9 = a5 ^ x8;
466 const T x10 = x7 & x9;
467 const T x11 = x4 | x10;
468
469 const T x12 = ~x3;
470 const T x13 = x10 ^ x12;
471 const T x14 = a3 & ~x7;
472 const T x15 = x13 ^ x14;
473 const T x16 = x1 ^ x15;
474 const T x17 = x5 | a6;
475 const T x18 = x17 ^ x16;
476 out2 ^= x18;
477
478 const T x19 = a1 ^ x16;
479 const T x20 = a5 & x19;
480 const T x21 = a2 ^ x15;
481 const T x22 = x20 ^ x21;
482 const T x23 = x6 ^ x22;
483
484 const T x24 = x11 ^ x22;
485 const T x25 = a2 | x24;
486 const T x26 = a5 ^ x19;
487 const T x27 = x25 ^ x26;
488 const T x28 = x11 & a6;
489 const T x29 = x28 ^ x27;
490 out3 ^= x29;
491
492 const T x30 = x9 ^ x23;
493 const T x31 = a4 | x21;
494 const T x32 = x30 ^ x31;
495 const T x33 = a1 ^ x32;
496 const T x34 = x33 & a6;
497 const T x35 = x34 ^ x23;
498 out4 ^= x35;
499
500 const T x36 = x30 & ~a4;
501 const T x37 = x27 & x36;
502 const T x38 = x5 ^ x32;
503 const T x39 = x37 ^ x38;
504 const T x40 = x39 | a6;
505 const T x41 = x40 ^ x23;
506 out1 ^= x41;
507}
508
509void des_transpose(uint64_t M[32]) {
510 for(size_t i = 0; i != 16; ++i) {
511 swap_bits<uint64_t>(M[i], M[i + 16], 0x0000FFFF0000FFFF, 16);
512 }
513
514 for(size_t i = 0; i != 32; i += 16) {
515 for(size_t j = 0; j != 8; ++j) {
516 swap_bits<uint64_t>(M[i + j], M[i + j + 8], 0x00FF00FF00FF00FF, 8);
517 }
518 }
519
520 for(size_t i = 0; i != 32; i += 8) {
521 for(size_t j = 0; j != 4; ++j) {
522 swap_bits<uint64_t>(M[i + j + 0], M[i + j + 4], 0x0F0F0F0F0F0F0F0F, 4);
523 }
524 }
525
526 for(size_t i = 0; i != 32; i += 4) {
527 for(size_t j = 0; j != 2; ++j) {
528 swap_bits<uint64_t>(M[i + j + 0], M[i + j + 2], 0x3333333333333333, 2);
529 }
530 }
531
532 for(size_t i = 0; i != 32; i += 2) {
533 swap_bits<uint64_t>(M[i], M[i + 1], 0x5555555555555555, 1);
534 }
535}
536
537void transpose_in(uint32_t B[64], const uint8_t in[], size_t n_blocks) {
538 uint64_t M[32] = {};
539
540 load_be<uint64_t>(M, in, n_blocks);
541
542 des_transpose(M);
543
544 // clang-format off
545 static constexpr uint8_t IP[64] = {
546 57, 49, 41, 33, 25, 17, 9, 1,
547 59, 51, 43, 35, 27, 19, 11, 3,
548 61, 53, 45, 37, 29, 21, 13, 5,
549 63, 55, 47, 39, 31, 23, 15, 7,
550 56, 48, 40, 32, 24, 16, 8, 0,
551 58, 50, 42, 34, 26, 18, 10, 2,
552 60, 52, 44, 36, 28, 20, 12, 4,
553 62, 54, 46, 38, 30, 22, 14, 6
554 };
555 // clang-format on
556
557 for(size_t i = 0; i < 64; ++i) {
558 const uint8_t src = IP[i];
559 if(src < 32) {
560 B[i] = static_cast<uint32_t>(M[31 - src] >> 32);
561 } else {
562 B[i] = static_cast<uint32_t>(M[63 - src]);
563 }
564 }
565}
566
567void transpose_out(uint8_t out[], const uint32_t B[64], size_t n_blocks) {
568 // clang-format off
569 static constexpr uint8_t FP[64] = {
570 39, 7, 47, 15, 55, 23, 63, 31,
571 38, 6, 46, 14, 54, 22, 62, 30,
572 37, 5, 45, 13, 53, 21, 61, 29,
573 36, 4, 44, 12, 52, 20, 60, 28,
574 35, 3, 43, 11, 51, 19, 59, 27,
575 34, 2, 42, 10, 50, 18, 58, 26,
576 33, 1, 41, 9, 49, 17, 57, 25,
577 32, 0, 40, 8, 48, 16, 56, 24
578 };
579 // clang-format on
580
581 uint64_t M[32];
582 for(size_t i = 0; i != 32; ++i) {
583 // XOR with 32 here absorbs the DES output swap into the FP
584 M[i] = (static_cast<uint64_t>(B[FP[31 - i] ^ 32]) << 32) | B[FP[63 - i] ^ 32];
585 }
586
587 des_transpose(M);
588
589 for(size_t i = 0; i != n_blocks; ++i) {
590 store_be(out + i * 8, M[i]);
591 }
592}
593
594/*
595* DES round - L ^= P(S(E(R) ^ K))
596*
597* Each S-box takes 6 bits from E(R) XORed with 6 round key bits,
598* and XORs 4 output bits into L at positions given by the P permutation.
599* The E expansion, key XOR, S-box evaluation, and P permutation are
600* all fused into the calls below.
601*/
602void des_round(uint32_t L[32], const uint32_t R[32], const uint32_t RK[48]) {
603 // clang-format off
604 SBox1(R[31] ^ RK[ 0], R[ 0] ^ RK[ 1], R[ 1] ^ RK[ 2],
605 R[ 2] ^ RK[ 3], R[ 3] ^ RK[ 4], R[ 4] ^ RK[ 5],
606 L[ 8], L[16], L[22], L[30]);
607
608 SBox2(R[ 3] ^ RK[ 6], R[ 4] ^ RK[ 7], R[ 5] ^ RK[ 8],
609 R[ 6] ^ RK[ 9], R[ 7] ^ RK[10], R[ 8] ^ RK[11],
610 L[12], L[27], L[ 1], L[17]);
611
612 SBox3(R[ 7] ^ RK[12], R[ 8] ^ RK[13], R[ 9] ^ RK[14],
613 R[10] ^ RK[15], R[11] ^ RK[16], R[12] ^ RK[17],
614 L[23], L[15], L[29], L[ 5]);
615
616 SBox4(R[11] ^ RK[18], R[12] ^ RK[19], R[13] ^ RK[20],
617 R[14] ^ RK[21], R[15] ^ RK[22], R[16] ^ RK[23],
618 L[25], L[19], L[ 9], L[ 0]);
619
620 SBox5(R[15] ^ RK[24], R[16] ^ RK[25], R[17] ^ RK[26],
621 R[18] ^ RK[27], R[19] ^ RK[28], R[20] ^ RK[29],
622 L[ 7], L[13], L[24], L[ 2]);
623
624 SBox6(R[19] ^ RK[30], R[20] ^ RK[31], R[21] ^ RK[32],
625 R[22] ^ RK[33], R[23] ^ RK[34], R[24] ^ RK[35],
626 L[ 3], L[28], L[10], L[18]);
627
628 SBox7(R[23] ^ RK[36], R[24] ^ RK[37], R[25] ^ RK[38],
629 R[26] ^ RK[39], R[27] ^ RK[40], R[28] ^ RK[41],
630 L[31], L[11], L[21], L[ 6]);
631
632 SBox8(R[27] ^ RK[42], R[28] ^ RK[43], R[29] ^ RK[44],
633 R[30] ^ RK[45], R[31] ^ RK[46], R[ 0] ^ RK[47],
634 L[ 4], L[26], L[14], L[20]);
635 // clang-format on
636}
637
638void des_encrypt(uint32_t L[32], uint32_t R[32], const uint32_t round_key[]) {
639 for(size_t round = 0; round < 16; round += 2) {
640 des_round(L, R, &round_key[round * 48]);
641 des_round(R, L, &round_key[(round + 1) * 48]);
642 }
643}
644
645void des_decrypt(uint32_t L[32], uint32_t R[32], const uint32_t round_key[]) {
646 for(size_t round = 16; round > 0; round -= 2) {
647 des_round(L, R, &round_key[(round - 1) * 48]);
648 des_round(R, L, &round_key[(round - 2) * 48]);
649 }
650}
651
652/*
653* The usual DES key schedule except that each round key is instead of 48 bits,
654* is 48 32-bit values which are either all-1 or all-0
655*/
656void des_key_schedule(uint32_t round_key[], const uint8_t key[8]) {
657 static const uint8_t ROT[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
658
659 uint32_t C = ((key[7] & 0x80) << 20) | ((key[6] & 0x80) << 19) | ((key[5] & 0x80) << 18) | ((key[4] & 0x80) << 17) |
660 ((key[3] & 0x80) << 16) | ((key[2] & 0x80) << 15) | ((key[1] & 0x80) << 14) | ((key[0] & 0x80) << 13) |
661 ((key[7] & 0x40) << 13) | ((key[6] & 0x40) << 12) | ((key[5] & 0x40) << 11) | ((key[4] & 0x40) << 10) |
662 ((key[3] & 0x40) << 9) | ((key[2] & 0x40) << 8) | ((key[1] & 0x40) << 7) | ((key[0] & 0x40) << 6) |
663 ((key[7] & 0x20) << 6) | ((key[6] & 0x20) << 5) | ((key[5] & 0x20) << 4) | ((key[4] & 0x20) << 3) |
664 ((key[3] & 0x20) << 2) | ((key[2] & 0x20) << 1) | ((key[1] & 0x20)) | ((key[0] & 0x20) >> 1) |
665 ((key[7] & 0x10) >> 1) | ((key[6] & 0x10) >> 2) | ((key[5] & 0x10) >> 3) | ((key[4] & 0x10) >> 4);
666 uint32_t D = ((key[7] & 0x02) << 26) | ((key[6] & 0x02) << 25) | ((key[5] & 0x02) << 24) | ((key[4] & 0x02) << 23) |
667 ((key[3] & 0x02) << 22) | ((key[2] & 0x02) << 21) | ((key[1] & 0x02) << 20) | ((key[0] & 0x02) << 19) |
668 ((key[7] & 0x04) << 17) | ((key[6] & 0x04) << 16) | ((key[5] & 0x04) << 15) | ((key[4] & 0x04) << 14) |
669 ((key[3] & 0x04) << 13) | ((key[2] & 0x04) << 12) | ((key[1] & 0x04) << 11) | ((key[0] & 0x04) << 10) |
670 ((key[7] & 0x08) << 8) | ((key[6] & 0x08) << 7) | ((key[5] & 0x08) << 6) | ((key[4] & 0x08) << 5) |
671 ((key[3] & 0x08) << 4) | ((key[2] & 0x08) << 3) | ((key[1] & 0x08) << 2) | ((key[0] & 0x08) << 1) |
672 ((key[3] & 0x10) >> 1) | ((key[2] & 0x10) >> 2) | ((key[1] & 0x10) >> 3) | ((key[0] & 0x10) >> 4);
673
674 static const uint8_t PC2_C[24] = {13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
675 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1};
676
677 static const uint8_t PC2_D[24] = {12, 23, 2, 8, 18, 26, 1, 11, 22, 16, 4, 19,
678 15, 20, 10, 27, 5, 24, 17, 13, 21, 7, 0, 3};
679
680 for(size_t i = 0; i != 16; ++i) {
681 C = ((C << ROT[i]) | (C >> (28 - ROT[i]))) & 0x0FFFFFFF;
682 D = ((D << ROT[i]) | (D >> (28 - ROT[i]))) & 0x0FFFFFFF;
683
684 uint32_t* rk = &round_key[i * 48];
685
686 for(size_t j = 0; j < 24; ++j) {
687 const uint32_t bit = (C >> (27 - PC2_C[j])) & 1;
688 rk[j] = static_cast<uint32_t>(0) - bit;
689 }
690
691 for(size_t j = 0; j < 24; ++j) {
692 const uint32_t bit = (D >> (27 - PC2_D[j])) & 1;
693 rk[24 + j] = static_cast<uint32_t>(0) - bit;
694 }
695 }
696}
697
698} // namespace
699
700/*
701* DES Encryption
702*/
703void DES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
705
706 uint32_t B[64];
707
708 while(blocks >= 32) {
709 transpose_in(B, in, 32);
710 des_encrypt(&B[0], &B[32], m_round_key.data());
711 transpose_out(out, B, 32);
712
713 in += 32 * BLOCK_SIZE;
714 out += 32 * BLOCK_SIZE;
715 blocks -= 32;
716 }
717
718 if(blocks > 0) {
719 transpose_in(B, in, blocks);
720 des_encrypt(&B[0], &B[32], m_round_key.data());
721 transpose_out(out, B, blocks);
722 }
723}
724
725/*
726* DES Decryption
727*/
728void DES::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
730
731 uint32_t B[64];
732
733 while(blocks >= 32) {
734 transpose_in(B, in, 32);
735 des_decrypt(&B[0], &B[32], m_round_key.data());
736 transpose_out(out, B, 32);
737
738 in += 32 * BLOCK_SIZE;
739 out += 32 * BLOCK_SIZE;
740 blocks -= 32;
741 }
742
743 if(blocks > 0) {
744 transpose_in(B, in, blocks);
745 des_decrypt(&B[0], &B[32], m_round_key.data());
746 transpose_out(out, B, blocks);
747 }
748}
749
751 return !m_round_key.empty();
752}
753
754/*
755* DES Key Schedule
756*/
757void DES::key_schedule(std::span<const uint8_t> key) {
758 m_round_key.resize(16 * 48);
759 des_key_schedule(m_round_key.data(), key.data());
760}
761
763 zap(m_round_key);
764}
765
766/*
767* TripleDES Encryption
768*/
769void TripleDES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
771
772 const uint32_t* k1 = m_round_key.data();
773 const uint32_t* k2 = k1 + 16 * 48;
774 const uint32_t* k3 = k2 + 16 * 48;
775
776 uint32_t B[64];
777
778 while(blocks >= 32) {
779 transpose_in(B, in, 32);
780 des_encrypt(&B[0], &B[32], k1);
781 des_decrypt(&B[32], &B[0], k2);
782 des_encrypt(&B[0], &B[32], k3);
783 transpose_out(out, B, 32);
784
785 in += 32 * BLOCK_SIZE;
786 out += 32 * BLOCK_SIZE;
787 blocks -= 32;
788 }
789
790 if(blocks > 0) {
791 transpose_in(B, in, blocks);
792 des_encrypt(&B[0], &B[32], k1);
793 des_decrypt(&B[32], &B[0], k2);
794 des_encrypt(&B[0], &B[32], k3);
795 transpose_out(out, B, blocks);
796 }
797}
798
799/*
800* TripleDES Decryption
801*/
802void TripleDES::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
804
805 const uint32_t* k1 = m_round_key.data();
806 const uint32_t* k2 = k1 + 16 * 48;
807 const uint32_t* k3 = k2 + 16 * 48;
808
809 uint32_t B[64];
810
811 while(blocks >= 32) {
812 transpose_in(B, in, 32);
813 des_decrypt(&B[0], &B[32], k3);
814 des_encrypt(&B[32], &B[0], k2);
815 des_decrypt(&B[0], &B[32], k1);
816 transpose_out(out, B, 32);
817
818 in += 32 * BLOCK_SIZE;
819 out += 32 * BLOCK_SIZE;
820 blocks -= 32;
821 }
822
823 if(blocks > 0) {
824 transpose_in(B, in, blocks);
825 des_decrypt(&B[0], &B[32], k3);
826 des_encrypt(&B[32], &B[0], k2);
827 des_decrypt(&B[0], &B[32], k1);
828 transpose_out(out, B, blocks);
829 }
830}
831
833 return !m_round_key.empty();
834}
835
836/*
837* TripleDES Key Schedule
838*/
839void TripleDES::key_schedule(std::span<const uint8_t> key) {
840 m_round_key.resize(3 * 16 * 48);
841 des_key_schedule(m_round_key.data(), key.first(8).data());
842 des_key_schedule(m_round_key.data() + 16 * 48, key.subspan(8, 8).data());
843
844 if(key.size() == 24) {
845 des_key_schedule(m_round_key.data() + 2 * 16 * 48, key.last(8).data());
846 } else {
847 copy_mem(m_round_key.data() + 2 * 16 * 48, m_round_key.data(), 16 * 48);
848 }
849}
850
852 zap(m_round_key);
853}
854
855} // namespace Botan
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition des.cpp:703
void clear() override
Definition des.cpp:762
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition des.cpp:728
bool has_keying_material() const override
Definition des.cpp:750
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition des.cpp:802
void clear() override
Definition des.cpp:851
bool has_keying_material() const override
Definition des.cpp:832
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition des.cpp:769
#define BOTAN_FORCE_INLINE
Definition compiler.h:87
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:133
BOTAN_FORCE_INLINE constexpr void swap_bits(T &x, T &y, T mask, size_t shift)
Definition bit_ops.h:202
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504