Coverage Report

Created: 2025-12-31 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/block/des/des.cpp
Line
Count
Source
1
/*
2
* DES
3
* (C) 1999-2008,2018,2020 Jack Lloyd
4
*
5
* Based on a public domain implementation by Phil Karn (who in turn
6
* credited Richard Outerbridge and Jim Gillogly)
7
*
8
* Botan is released under the Simplified BSD License (see license.txt)
9
*/
10
11
#include <botan/internal/des.h>
12
13
#include <botan/internal/loadstor.h>
14
#include <botan/internal/rotate.h>
15
#include <span>
16
17
namespace Botan {
18
19
namespace {
20
21
/*
22
* Constant time DES [with assumptions on the cache]
23
*
24
* Each SBOX lookup (in function spbox below) examines just a single 64 byte range of this table,
25
* converting it to the appropriate value using a multiplication and AND. Typically these tables
26
* are otherwise 256 bytes, and thus the lookups leak information about the data being processed.
27
* In contrast lookups within a single 64 byte cache line do not leak information [*] and we
28
* can use alignas to ensure that the table entries are cache line aligned.
29
*
30
* [*] Assuming that the cache lines are at least 64 bytes long, and that the machine does not
31
* suffer from cache bank conflicts. This is true for all Intel processors after Sandy Bridge,
32
* and many other modern processors.
33
*/
34
alignas(256) const uint8_t SPBOX_CATS[64 * 8] = {
35
   0x54, 0x00, 0x10, 0x55, 0x51, 0x15, 0x01, 0x10, 0x04, 0x54, 0x55, 0x04, 0x45, 0x51, 0x40, 0x01,
36
   0x05, 0x44, 0x44, 0x14, 0x14, 0x50, 0x50, 0x45, 0x11, 0x41, 0x41, 0x11, 0x00, 0x05, 0x15, 0x40,
37
   0x10, 0x55, 0x01, 0x50, 0x54, 0x40, 0x40, 0x04, 0x51, 0x10, 0x14, 0x41, 0x04, 0x01, 0x45, 0x15,
38
   0x55, 0x11, 0x50, 0x45, 0x41, 0x05, 0x15, 0x54, 0x05, 0x44, 0x44, 0x00, 0x11, 0x14, 0x00, 0x51,
39
40
   0x55, 0x44, 0x04, 0x15, 0x10, 0x01, 0x51, 0x45, 0x41, 0x55, 0x54, 0x40, 0x44, 0x10, 0x01, 0x51,
41
   0x14, 0x11, 0x45, 0x00, 0x40, 0x04, 0x15, 0x50, 0x11, 0x41, 0x00, 0x14, 0x05, 0x54, 0x50, 0x05,
42
   0x00, 0x15, 0x51, 0x10, 0x45, 0x50, 0x54, 0x04, 0x50, 0x44, 0x01, 0x55, 0x15, 0x01, 0x04, 0x40,
43
   0x05, 0x54, 0x10, 0x41, 0x11, 0x45, 0x41, 0x11, 0x14, 0x00, 0x44, 0x05, 0x40, 0x51, 0x55, 0x14,
44
45
   0x09, 0xA8, 0x00, 0xA1, 0x88, 0x00, 0x29, 0x88, 0x21, 0x81, 0x81, 0x20, 0xA9, 0x21, 0xA0, 0x09,
46
   0x80, 0x01, 0xA8, 0x08, 0x28, 0xA0, 0xA1, 0x29, 0x89, 0x28, 0x20, 0x89, 0x01, 0xA9, 0x08, 0x80,
47
   0xA8, 0x80, 0x21, 0x09, 0x20, 0xA8, 0x88, 0x00, 0x08, 0x21, 0xA9, 0x88, 0x81, 0x08, 0x00, 0xA1,
48
   0x89, 0x20, 0x80, 0xA9, 0x01, 0x29, 0x28, 0x81, 0xA0, 0x89, 0x09, 0xA0, 0x29, 0x01, 0xA1, 0x28,
49
50
   0x51, 0x15, 0x15, 0x04, 0x54, 0x45, 0x41, 0x11, 0x00, 0x50, 0x50, 0x55, 0x05, 0x00, 0x44, 0x41,
51
   0x01, 0x10, 0x40, 0x51, 0x04, 0x40, 0x11, 0x14, 0x45, 0x01, 0x14, 0x44, 0x10, 0x54, 0x55, 0x05,
52
   0x44, 0x41, 0x50, 0x55, 0x05, 0x00, 0x00, 0x50, 0x14, 0x44, 0x45, 0x01, 0x51, 0x15, 0x15, 0x04,
53
   0x55, 0x05, 0x01, 0x10, 0x41, 0x11, 0x54, 0x45, 0x11, 0x14, 0x40, 0x51, 0x04, 0x40, 0x10, 0x54,
54
55
   0x01, 0x29, 0x28, 0xA1, 0x08, 0x01, 0x80, 0x28, 0x89, 0x08, 0x21, 0x89, 0xA1, 0xA8, 0x09, 0x80,
56
   0x20, 0x88, 0x88, 0x00, 0x81, 0xA9, 0xA9, 0x21, 0xA8, 0x81, 0x00, 0xA0, 0x29, 0x20, 0xA0, 0x09,
57
   0x08, 0xA1, 0x01, 0x20, 0x80, 0x28, 0xA1, 0x89, 0x21, 0x80, 0xA8, 0x29, 0x89, 0x01, 0x20, 0xA8,
58
   0xA9, 0x09, 0xA0, 0xA9, 0x28, 0x00, 0x88, 0xA0, 0x09, 0x21, 0x81, 0x08, 0x00, 0x88, 0x29, 0x81,
59
60
   0x41, 0x50, 0x04, 0x55, 0x50, 0x01, 0x55, 0x10, 0x44, 0x15, 0x10, 0x41, 0x11, 0x44, 0x40, 0x05,
61
   0x00, 0x11, 0x45, 0x04, 0x14, 0x45, 0x01, 0x51, 0x51, 0x00, 0x15, 0x54, 0x05, 0x14, 0x54, 0x40,
62
   0x44, 0x01, 0x51, 0x14, 0x55, 0x10, 0x05, 0x41, 0x10, 0x44, 0x40, 0x05, 0x41, 0x55, 0x14, 0x50,
63
   0x15, 0x54, 0x00, 0x51, 0x01, 0x04, 0x50, 0x15, 0x04, 0x11, 0x45, 0x00, 0x54, 0x40, 0x11, 0x45,
64
65
   0x10, 0x51, 0x45, 0x00, 0x04, 0x45, 0x15, 0x54, 0x55, 0x10, 0x00, 0x41, 0x01, 0x40, 0x51, 0x05,
66
   0x44, 0x15, 0x11, 0x44, 0x41, 0x50, 0x54, 0x11, 0x50, 0x04, 0x05, 0x55, 0x14, 0x01, 0x40, 0x14,
67
   0x40, 0x14, 0x10, 0x45, 0x45, 0x51, 0x51, 0x01, 0x11, 0x40, 0x44, 0x10, 0x54, 0x05, 0x15, 0x54,
68
   0x05, 0x41, 0x55, 0x50, 0x14, 0x00, 0x01, 0x55, 0x00, 0x15, 0x50, 0x04, 0x41, 0x44, 0x04, 0x11,
69
70
   0x89, 0x08, 0x20, 0xA9, 0x80, 0x89, 0x01, 0x80, 0x21, 0xA0, 0xA9, 0x28, 0xA8, 0x29, 0x08, 0x01,
71
   0xA0, 0x81, 0x88, 0x09, 0x28, 0x21, 0xA1, 0xA8, 0x09, 0x00, 0x00, 0xA1, 0x81, 0x88, 0x29, 0x20,
72
   0x29, 0x20, 0xa8, 0x08, 0x01, 0xA1, 0x08, 0x29, 0x88, 0x01, 0x81, 0xA0, 0xA1, 0x80, 0x20, 0x89,
73
   0x00, 0xA9, 0x21, 0x81, 0xA0, 0x88, 0x89, 0x00, 0xA9, 0x28, 0x28, 0x09, 0x09, 0x21, 0x80, 0xA8,
74
};
75
76
const uint32_t SPBOX_CAT_0_MUL = 0x70041106;
77
const uint32_t SPBOX_CAT_1_MUL = 0x02012020;
78
const uint32_t SPBOX_CAT_2_MUL = 0x00901048;
79
const uint32_t SPBOX_CAT_3_MUL = 0x8e060221;
80
const uint32_t SPBOX_CAT_4_MUL = 0x00912140;
81
const uint32_t SPBOX_CAT_5_MUL = 0x80841018;
82
const uint32_t SPBOX_CAT_6_MUL = 0xe0120202;
83
const uint32_t SPBOX_CAT_7_MUL = 0x00212240;
84
85
const uint32_t SPBOX_CAT_0_MASK = 0x01010404;
86
const uint32_t SPBOX_CAT_1_MASK = 0x80108020;
87
const uint32_t SPBOX_CAT_2_MASK = 0x08020208;
88
const uint32_t SPBOX_CAT_3_MASK = 0x00802081;
89
const uint32_t SPBOX_CAT_4_MASK = 0x42080100;
90
const uint32_t SPBOX_CAT_5_MASK = 0x20404010;
91
const uint32_t SPBOX_CAT_6_MASK = 0x04200802;
92
const uint32_t SPBOX_CAT_7_MASK = 0x10041040;
93
94
/*
95
* DES Key Schedule
96
*/
97
0
void des_key_schedule(std::span<uint32_t, 32> round_key, const uint8_t key[8]) {
98
0
   static const uint8_t ROT[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
99
100
0
   uint32_t C = ((key[7] & 0x80) << 20) | ((key[6] & 0x80) << 19) | ((key[5] & 0x80) << 18) | ((key[4] & 0x80) << 17) |
101
0
                ((key[3] & 0x80) << 16) | ((key[2] & 0x80) << 15) | ((key[1] & 0x80) << 14) | ((key[0] & 0x80) << 13) |
102
0
                ((key[7] & 0x40) << 13) | ((key[6] & 0x40) << 12) | ((key[5] & 0x40) << 11) | ((key[4] & 0x40) << 10) |
103
0
                ((key[3] & 0x40) << 9) | ((key[2] & 0x40) << 8) | ((key[1] & 0x40) << 7) | ((key[0] & 0x40) << 6) |
104
0
                ((key[7] & 0x20) << 6) | ((key[6] & 0x20) << 5) | ((key[5] & 0x20) << 4) | ((key[4] & 0x20) << 3) |
105
0
                ((key[3] & 0x20) << 2) | ((key[2] & 0x20) << 1) | ((key[1] & 0x20)) | ((key[0] & 0x20) >> 1) |
106
0
                ((key[7] & 0x10) >> 1) | ((key[6] & 0x10) >> 2) | ((key[5] & 0x10) >> 3) | ((key[4] & 0x10) >> 4);
107
0
   uint32_t D = ((key[7] & 0x02) << 26) | ((key[6] & 0x02) << 25) | ((key[5] & 0x02) << 24) | ((key[4] & 0x02) << 23) |
108
0
                ((key[3] & 0x02) << 22) | ((key[2] & 0x02) << 21) | ((key[1] & 0x02) << 20) | ((key[0] & 0x02) << 19) |
109
0
                ((key[7] & 0x04) << 17) | ((key[6] & 0x04) << 16) | ((key[5] & 0x04) << 15) | ((key[4] & 0x04) << 14) |
110
0
                ((key[3] & 0x04) << 13) | ((key[2] & 0x04) << 12) | ((key[1] & 0x04) << 11) | ((key[0] & 0x04) << 10) |
111
0
                ((key[7] & 0x08) << 8) | ((key[6] & 0x08) << 7) | ((key[5] & 0x08) << 6) | ((key[4] & 0x08) << 5) |
112
0
                ((key[3] & 0x08) << 4) | ((key[2] & 0x08) << 3) | ((key[1] & 0x08) << 2) | ((key[0] & 0x08) << 1) |
113
0
                ((key[3] & 0x10) >> 1) | ((key[2] & 0x10) >> 2) | ((key[1] & 0x10) >> 3) | ((key[0] & 0x10) >> 4);
114
115
0
   for(size_t i = 0; i != 16; ++i) {
116
0
      C = ((C << ROT[i]) | (C >> (28 - ROT[i]))) & 0x0FFFFFFF;
117
0
      D = ((D << ROT[i]) | (D >> (28 - ROT[i]))) & 0x0FFFFFFF;
118
0
      round_key[2 * i] = ((C & 0x00000010) << 22) | ((C & 0x00000800) << 17) | ((C & 0x00000020) << 16) |
119
0
                         ((C & 0x00004004) << 15) | ((C & 0x00000200) << 11) | ((C & 0x00020000) << 10) |
120
0
                         ((C & 0x01000000) >> 6) | ((C & 0x00100000) >> 4) | ((C & 0x00010000) << 3) |
121
0
                         ((C & 0x08000000) >> 2) | ((C & 0x00800000) << 1) | ((D & 0x00000010) << 8) |
122
0
                         ((D & 0x00000002) << 7) | ((D & 0x00000001) << 2) | ((D & 0x00000200)) |
123
0
                         ((D & 0x00008000) >> 2) | ((D & 0x00000088) >> 3) | ((D & 0x00001000) >> 7) |
124
0
                         ((D & 0x00080000) >> 9) | ((D & 0x02020000) >> 14) | ((D & 0x00400000) >> 21);
125
0
      round_key[2 * i + 1] =
126
0
         ((C & 0x00000001) << 28) | ((C & 0x00000082) << 18) | ((C & 0x00002000) << 14) | ((C & 0x00000100) << 10) |
127
0
         ((C & 0x00001000) << 9) | ((C & 0x00040000) << 6) | ((C & 0x02400000) << 4) | ((C & 0x00008000) << 2) |
128
0
         ((C & 0x00200000) >> 1) | ((C & 0x04000000) >> 10) | ((D & 0x00000020) << 6) | ((D & 0x00000100)) |
129
0
         ((D & 0x00000800) >> 1) | ((D & 0x00000040) >> 3) | ((D & 0x00010000) >> 4) | ((D & 0x00000400) >> 5) |
130
0
         ((D & 0x00004000) >> 10) | ((D & 0x04000000) >> 13) | ((D & 0x00800000) >> 14) | ((D & 0x00100000) >> 18) |
131
0
         ((D & 0x01000000) >> 24) | ((D & 0x08000000) >> 26);
132
0
   }
133
0
}
134
135
0
inline uint32_t spbox(uint32_t T0, uint32_t T1) {
136
0
   return ((SPBOX_CATS[0 * 64 + ((T0 >> 24) & 0x3F)] * SPBOX_CAT_0_MUL) & SPBOX_CAT_0_MASK) ^
137
0
          ((SPBOX_CATS[1 * 64 + ((T1 >> 24) & 0x3F)] * SPBOX_CAT_1_MUL) & SPBOX_CAT_1_MASK) ^
138
0
          ((SPBOX_CATS[2 * 64 + ((T0 >> 16) & 0x3F)] * SPBOX_CAT_2_MUL) & SPBOX_CAT_2_MASK) ^
139
0
          ((SPBOX_CATS[3 * 64 + ((T1 >> 16) & 0x3F)] * SPBOX_CAT_3_MUL) & SPBOX_CAT_3_MASK) ^
140
0
          ((SPBOX_CATS[4 * 64 + ((T0 >> 8) & 0x3F)] * SPBOX_CAT_4_MUL) & SPBOX_CAT_4_MASK) ^
141
0
          ((SPBOX_CATS[5 * 64 + ((T1 >> 8) & 0x3F)] * SPBOX_CAT_5_MUL) & SPBOX_CAT_5_MASK) ^
142
0
          ((SPBOX_CATS[6 * 64 + ((T0 >> 0) & 0x3F)] * SPBOX_CAT_6_MUL) & SPBOX_CAT_6_MASK) ^
143
0
          ((SPBOX_CATS[7 * 64 + ((T1 >> 0) & 0x3F)] * SPBOX_CAT_7_MUL) & SPBOX_CAT_7_MASK);
144
0
}
145
146
/*
147
* DES Encryption
148
*/
149
0
inline void des_encrypt(uint32_t& Lr, uint32_t& Rr, std::span<const uint32_t, 32> round_key) {
150
0
   uint32_t L = Lr;
151
0
   uint32_t R = Rr;
152
0
   for(size_t i = 0; i != 16; i += 2) {
153
0
      L ^= spbox(rotr<4>(R) ^ round_key[2 * i], R ^ round_key[2 * i + 1]);
154
0
      R ^= spbox(rotr<4>(L) ^ round_key[2 * i + 2], L ^ round_key[2 * i + 3]);
155
0
   }
156
157
0
   Lr = L;
158
0
   Rr = R;
159
0
}
160
161
inline void des_encrypt_x2(
162
0
   uint32_t& L0r, uint32_t& R0r, uint32_t& L1r, uint32_t& R1r, std::span<const uint32_t, 32> round_key) {
163
0
   uint32_t L0 = L0r;
164
0
   uint32_t R0 = R0r;
165
0
   uint32_t L1 = L1r;
166
0
   uint32_t R1 = R1r;
167
168
0
   for(size_t i = 0; i != 16; i += 2) {
169
0
      L0 ^= spbox(rotr<4>(R0) ^ round_key[2 * i], R0 ^ round_key[2 * i + 1]);
170
0
      L1 ^= spbox(rotr<4>(R1) ^ round_key[2 * i], R1 ^ round_key[2 * i + 1]);
171
172
0
      R0 ^= spbox(rotr<4>(L0) ^ round_key[2 * i + 2], L0 ^ round_key[2 * i + 3]);
173
0
      R1 ^= spbox(rotr<4>(L1) ^ round_key[2 * i + 2], L1 ^ round_key[2 * i + 3]);
174
0
   }
175
176
0
   L0r = L0;
177
0
   R0r = R0;
178
0
   L1r = L1;
179
0
   R1r = R1;
180
0
}
181
182
/*
183
* DES Decryption
184
*/
185
0
inline void des_decrypt(uint32_t& Lr, uint32_t& Rr, std::span<const uint32_t, 32> round_key) {
186
0
   uint32_t L = Lr;
187
0
   uint32_t R = Rr;
188
0
   for(size_t i = 16; i != 0; i -= 2) {
189
0
      L ^= spbox(rotr<4>(R) ^ round_key[2 * i - 2], R ^ round_key[2 * i - 1]);
190
0
      R ^= spbox(rotr<4>(L) ^ round_key[2 * i - 4], L ^ round_key[2 * i - 3]);
191
0
   }
192
0
   Lr = L;
193
0
   Rr = R;
194
0
}
195
196
inline void des_decrypt_x2(
197
0
   uint32_t& L0r, uint32_t& R0r, uint32_t& L1r, uint32_t& R1r, std::span<const uint32_t, 32> round_key) {
198
0
   uint32_t L0 = L0r;
199
0
   uint32_t R0 = R0r;
200
0
   uint32_t L1 = L1r;
201
0
   uint32_t R1 = R1r;
202
203
0
   for(size_t i = 16; i != 0; i -= 2) {
204
0
      L0 ^= spbox(rotr<4>(R0) ^ round_key[2 * i - 2], R0 ^ round_key[2 * i - 1]);
205
0
      L1 ^= spbox(rotr<4>(R1) ^ round_key[2 * i - 2], R1 ^ round_key[2 * i - 1]);
206
207
0
      R0 ^= spbox(rotr<4>(L0) ^ round_key[2 * i - 4], L0 ^ round_key[2 * i - 3]);
208
0
      R1 ^= spbox(rotr<4>(L1) ^ round_key[2 * i - 4], L1 ^ round_key[2 * i - 3]);
209
0
   }
210
211
0
   L0r = L0;
212
0
   R0r = R0;
213
0
   L1r = L1;
214
0
   R1r = R1;
215
0
}
216
217
0
inline void des_IP(uint32_t& L, uint32_t& R) {
218
   // IP sequence by Wei Dai, taken from public domain Crypto++
219
0
   R = rotl<4>(R);
220
0
   uint32_t T = (L ^ R) & 0xF0F0F0F0;
221
0
   L ^= T;
222
0
   R = rotr<20>(R ^ T);
223
0
   T = (L ^ R) & 0xFFFF0000;
224
0
   L ^= T;
225
0
   R = rotr<18>(R ^ T);
226
0
   T = (L ^ R) & 0x33333333;
227
0
   L ^= T;
228
0
   R = rotr<6>(R ^ T);
229
0
   T = (L ^ R) & 0x00FF00FF;
230
0
   L ^= T;
231
0
   R = rotl<9>(R ^ T);
232
0
   T = (L ^ R) & 0xAAAAAAAA;
233
0
   L = rotl<1>(L ^ T);
234
0
   R ^= T;
235
0
}
236
237
0
inline void des_FP(uint32_t& L, uint32_t& R) {
238
   // FP sequence by Wei Dai, taken from public domain Crypto++
239
240
0
   R = rotr<1>(R);
241
0
   uint32_t T = (L ^ R) & 0xAAAAAAAA;
242
0
   R ^= T;
243
0
   L = rotr<9>(L ^ T);
244
0
   T = (L ^ R) & 0x00FF00FF;
245
0
   R ^= T;
246
0
   L = rotl<6>(L ^ T);
247
0
   T = (L ^ R) & 0x33333333;
248
0
   R ^= T;
249
0
   L = rotl<18>(L ^ T);
250
0
   T = (L ^ R) & 0xFFFF0000;
251
0
   R ^= T;
252
0
   L = rotl<20>(L ^ T);
253
0
   T = (L ^ R) & 0xF0F0F0F0;
254
0
   R ^= T;
255
0
   L = rotr<4>(L ^ T);
256
0
}
257
258
}  // namespace
259
260
/*
261
* DES Encryption
262
*/
263
0
void DES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
264
0
   assert_key_material_set();
265
266
0
   while(blocks >= 2) {
267
0
      uint32_t L0 = load_be<uint32_t>(in, 0);
268
0
      uint32_t R0 = load_be<uint32_t>(in, 1);
269
0
      uint32_t L1 = load_be<uint32_t>(in, 2);
270
0
      uint32_t R1 = load_be<uint32_t>(in, 3);
271
272
0
      des_IP(L0, R0);
273
0
      des_IP(L1, R1);
274
275
0
      des_encrypt_x2(L0, R0, L1, R1, std::span<const uint32_t, 32>{m_round_key});
276
277
0
      des_FP(L0, R0);
278
0
      des_FP(L1, R1);
279
280
0
      store_be(out, R0, L0, R1, L1);
281
282
0
      in += 2 * BLOCK_SIZE;
283
0
      out += 2 * BLOCK_SIZE;
284
0
      blocks -= 2;
285
0
   }
286
287
0
   while(blocks > 0) {
288
0
      uint32_t L0 = load_be<uint32_t>(in, 0);
289
0
      uint32_t R0 = load_be<uint32_t>(in, 1);
290
0
      des_IP(L0, R0);
291
0
      des_encrypt(L0, R0, std::span<const uint32_t, 32>{m_round_key});
292
0
      des_FP(L0, R0);
293
0
      store_be(out, R0, L0);
294
295
0
      in += BLOCK_SIZE;
296
0
      out += BLOCK_SIZE;
297
0
      blocks -= 1;
298
0
   }
299
0
}
300
301
/*
302
* DES Decryption
303
*/
304
0
void DES::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
305
0
   assert_key_material_set();
306
307
0
   const auto KS = std::span<const uint32_t, 32>{m_round_key};
308
309
0
   while(blocks >= 2) {
310
0
      uint32_t L0 = load_be<uint32_t>(in, 0);
311
0
      uint32_t R0 = load_be<uint32_t>(in, 1);
312
0
      uint32_t L1 = load_be<uint32_t>(in, 2);
313
0
      uint32_t R1 = load_be<uint32_t>(in, 3);
314
315
0
      des_IP(L0, R0);
316
0
      des_IP(L1, R1);
317
318
0
      des_decrypt_x2(L0, R0, L1, R1, KS);
319
320
0
      des_FP(L0, R0);
321
0
      des_FP(L1, R1);
322
323
0
      store_be(out, R0, L0, R1, L1);
324
325
0
      in += 2 * BLOCK_SIZE;
326
0
      out += 2 * BLOCK_SIZE;
327
0
      blocks -= 2;
328
0
   }
329
330
0
   while(blocks > 0) {
331
0
      uint32_t L0 = load_be<uint32_t>(in, 0);
332
0
      uint32_t R0 = load_be<uint32_t>(in, 1);
333
0
      des_IP(L0, R0);
334
0
      des_decrypt(L0, R0, KS);
335
0
      des_FP(L0, R0);
336
0
      store_be(out, R0, L0);
337
338
0
      in += BLOCK_SIZE;
339
0
      out += BLOCK_SIZE;
340
0
      blocks -= 1;
341
0
   }
342
0
}
343
344
0
bool DES::has_keying_material() const {
345
0
   return !m_round_key.empty();
346
0
}
347
348
/*
349
* DES Key Schedule
350
*/
351
0
void DES::key_schedule(std::span<const uint8_t> key) {
352
0
   m_round_key.resize(32);
353
0
   const auto KS = std::span<uint32_t, 32>{m_round_key};
354
0
   des_key_schedule(KS, key.data());
355
0
}
356
357
0
void DES::clear() {
358
0
   zap(m_round_key);
359
0
}
360
361
/*
362
* TripleDES Encryption
363
*/
364
0
void TripleDES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
365
0
   assert_key_material_set();
366
367
0
   const auto KS = std::span<const uint32_t, 3 * 32>{m_round_key};
368
0
   const auto K1 = KS.subspan<0, 32>();
369
0
   const auto K2 = KS.subspan<32, 32>();
370
0
   const auto K3 = KS.subspan<64, 32>();
371
372
0
   while(blocks >= 2) {
373
0
      uint32_t L0 = load_be<uint32_t>(in, 0);
374
0
      uint32_t R0 = load_be<uint32_t>(in, 1);
375
0
      uint32_t L1 = load_be<uint32_t>(in, 2);
376
0
      uint32_t R1 = load_be<uint32_t>(in, 3);
377
378
0
      des_IP(L0, R0);
379
0
      des_IP(L1, R1);
380
381
0
      des_encrypt_x2(L0, R0, L1, R1, K1);
382
0
      des_decrypt_x2(R0, L0, R1, L1, K2);
383
0
      des_encrypt_x2(L0, R0, L1, R1, K3);
384
385
0
      des_FP(L0, R0);
386
0
      des_FP(L1, R1);
387
388
0
      store_be(out, R0, L0, R1, L1);
389
390
0
      in += 2 * BLOCK_SIZE;
391
0
      out += 2 * BLOCK_SIZE;
392
0
      blocks -= 2;
393
0
   }
394
395
0
   while(blocks > 0) {
396
0
      uint32_t L0 = load_be<uint32_t>(in, 0);
397
0
      uint32_t R0 = load_be<uint32_t>(in, 1);
398
399
0
      des_IP(L0, R0);
400
0
      des_encrypt(L0, R0, K1);
401
0
      des_decrypt(R0, L0, K2);
402
0
      des_encrypt(L0, R0, K3);
403
0
      des_FP(L0, R0);
404
405
0
      store_be(out, R0, L0);
406
407
0
      in += BLOCK_SIZE;
408
0
      out += BLOCK_SIZE;
409
0
      blocks -= 1;
410
0
   }
411
0
}
412
413
/*
414
* TripleDES Decryption
415
*/
416
0
void TripleDES::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
417
0
   assert_key_material_set();
418
419
0
   const auto KS = std::span<const uint32_t, 3 * 32>{m_round_key};
420
0
   const auto K1 = KS.subspan<0, 32>();
421
0
   const auto K2 = KS.subspan<32, 32>();
422
0
   const auto K3 = KS.subspan<64, 32>();
423
424
0
   while(blocks >= 2) {
425
0
      uint32_t L0 = load_be<uint32_t>(in, 0);
426
0
      uint32_t R0 = load_be<uint32_t>(in, 1);
427
0
      uint32_t L1 = load_be<uint32_t>(in, 2);
428
0
      uint32_t R1 = load_be<uint32_t>(in, 3);
429
430
0
      des_IP(L0, R0);
431
0
      des_IP(L1, R1);
432
433
0
      des_decrypt_x2(L0, R0, L1, R1, K3);
434
0
      des_encrypt_x2(R0, L0, R1, L1, K2);
435
0
      des_decrypt_x2(L0, R0, L1, R1, K1);
436
437
0
      des_FP(L0, R0);
438
0
      des_FP(L1, R1);
439
440
0
      store_be(out, R0, L0, R1, L1);
441
442
0
      in += 2 * BLOCK_SIZE;
443
0
      out += 2 * BLOCK_SIZE;
444
0
      blocks -= 2;
445
0
   }
446
447
0
   while(blocks > 0) {
448
0
      uint32_t L0 = load_be<uint32_t>(in, 0);
449
0
      uint32_t R0 = load_be<uint32_t>(in, 1);
450
451
0
      des_IP(L0, R0);
452
0
      des_decrypt(L0, R0, K3);
453
0
      des_encrypt(R0, L0, K2);
454
0
      des_decrypt(L0, R0, K1);
455
0
      des_FP(L0, R0);
456
457
0
      store_be(out, R0, L0);
458
459
0
      in += BLOCK_SIZE;
460
0
      out += BLOCK_SIZE;
461
0
      blocks -= 1;
462
0
   }
463
0
}
464
465
0
bool TripleDES::has_keying_material() const {
466
0
   return !m_round_key.empty();
467
0
}
468
469
/*
470
* TripleDES Key Schedule
471
*/
472
0
void TripleDES::key_schedule(std::span<const uint8_t> key) {
473
0
   m_round_key.resize(3 * 32);
474
475
0
   auto KS = std::span<uint32_t, 3 * 32>{m_round_key};
476
0
   auto K1 = KS.subspan<0, 32>();
477
0
   auto K2 = KS.subspan<32, 32>();
478
0
   auto K3 = KS.subspan<64, 32>();
479
480
0
   des_key_schedule(K1, key.first(8).data());
481
0
   des_key_schedule(K2, key.subspan(8, 8).data());
482
483
0
   if(key.size() == 24) {
484
0
      des_key_schedule(K3, key.last(8).data());
485
0
   } else {
486
0
      copy_mem(&m_round_key[64], K1.data(), 32);
487
0
   }
488
0
}
489
490
0
void TripleDES::clear() {
491
0
   zap(m_round_key);
492
0
}
493
494
}  // namespace Botan