/src/botan/src/lib/block/des/des.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * DES |
3 | | * (C) 1999-2008,2018 Jack Lloyd |
4 | | * |
5 | | * Based on a public domain implemenation 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/des.h> |
12 | | #include <botan/loadstor.h> |
13 | | #include <botan/rotate.h> |
14 | | |
15 | | namespace Botan { |
16 | | |
17 | | namespace { |
18 | | |
19 | | /* |
20 | | * DES Key Schedule |
21 | | */ |
22 | | void des_key_schedule(uint32_t round_key[32], const uint8_t key[8]) |
23 | 960 | { |
24 | 960 | static const uint8_t ROT[16] = { 1, 1, 2, 2, 2, 2, 2, 2, |
25 | 960 | 1, 2, 2, 2, 2, 2, 2, 1 }; |
26 | 960 | |
27 | 960 | uint32_t C = ((key[7] & 0x80) << 20) | ((key[6] & 0x80) << 19) | |
28 | 960 | ((key[5] & 0x80) << 18) | ((key[4] & 0x80) << 17) | |
29 | 960 | ((key[3] & 0x80) << 16) | ((key[2] & 0x80) << 15) | |
30 | 960 | ((key[1] & 0x80) << 14) | ((key[0] & 0x80) << 13) | |
31 | 960 | ((key[7] & 0x40) << 13) | ((key[6] & 0x40) << 12) | |
32 | 960 | ((key[5] & 0x40) << 11) | ((key[4] & 0x40) << 10) | |
33 | 960 | ((key[3] & 0x40) << 9) | ((key[2] & 0x40) << 8) | |
34 | 960 | ((key[1] & 0x40) << 7) | ((key[0] & 0x40) << 6) | |
35 | 960 | ((key[7] & 0x20) << 6) | ((key[6] & 0x20) << 5) | |
36 | 960 | ((key[5] & 0x20) << 4) | ((key[4] & 0x20) << 3) | |
37 | 960 | ((key[3] & 0x20) << 2) | ((key[2] & 0x20) << 1) | |
38 | 960 | ((key[1] & 0x20) ) | ((key[0] & 0x20) >> 1) | |
39 | 960 | ((key[7] & 0x10) >> 1) | ((key[6] & 0x10) >> 2) | |
40 | 960 | ((key[5] & 0x10) >> 3) | ((key[4] & 0x10) >> 4); |
41 | 960 | uint32_t D = ((key[7] & 0x02) << 26) | ((key[6] & 0x02) << 25) | |
42 | 960 | ((key[5] & 0x02) << 24) | ((key[4] & 0x02) << 23) | |
43 | 960 | ((key[3] & 0x02) << 22) | ((key[2] & 0x02) << 21) | |
44 | 960 | ((key[1] & 0x02) << 20) | ((key[0] & 0x02) << 19) | |
45 | 960 | ((key[7] & 0x04) << 17) | ((key[6] & 0x04) << 16) | |
46 | 960 | ((key[5] & 0x04) << 15) | ((key[4] & 0x04) << 14) | |
47 | 960 | ((key[3] & 0x04) << 13) | ((key[2] & 0x04) << 12) | |
48 | 960 | ((key[1] & 0x04) << 11) | ((key[0] & 0x04) << 10) | |
49 | 960 | ((key[7] & 0x08) << 8) | ((key[6] & 0x08) << 7) | |
50 | 960 | ((key[5] & 0x08) << 6) | ((key[4] & 0x08) << 5) | |
51 | 960 | ((key[3] & 0x08) << 4) | ((key[2] & 0x08) << 3) | |
52 | 960 | ((key[1] & 0x08) << 2) | ((key[0] & 0x08) << 1) | |
53 | 960 | ((key[3] & 0x10) >> 1) | ((key[2] & 0x10) >> 2) | |
54 | 960 | ((key[1] & 0x10) >> 3) | ((key[0] & 0x10) >> 4); |
55 | 960 | |
56 | 16.3k | for(size_t i = 0; i != 16; ++i) |
57 | 15.3k | { |
58 | 15.3k | C = ((C << ROT[i]) | (C >> (28-ROT[i]))) & 0x0FFFFFFF; |
59 | 15.3k | D = ((D << ROT[i]) | (D >> (28-ROT[i]))) & 0x0FFFFFFF; |
60 | 15.3k | round_key[2*i ] = ((C & 0x00000010) << 22) | ((C & 0x00000800) << 17) | |
61 | 15.3k | ((C & 0x00000020) << 16) | ((C & 0x00004004) << 15) | |
62 | 15.3k | ((C & 0x00000200) << 11) | ((C & 0x00020000) << 10) | |
63 | 15.3k | ((C & 0x01000000) >> 6) | ((C & 0x00100000) >> 4) | |
64 | 15.3k | ((C & 0x00010000) << 3) | ((C & 0x08000000) >> 2) | |
65 | 15.3k | ((C & 0x00800000) << 1) | ((D & 0x00000010) << 8) | |
66 | 15.3k | ((D & 0x00000002) << 7) | ((D & 0x00000001) << 2) | |
67 | 15.3k | ((D & 0x00000200) ) | ((D & 0x00008000) >> 2) | |
68 | 15.3k | ((D & 0x00000088) >> 3) | ((D & 0x00001000) >> 7) | |
69 | 15.3k | ((D & 0x00080000) >> 9) | ((D & 0x02020000) >> 14) | |
70 | 15.3k | ((D & 0x00400000) >> 21); |
71 | 15.3k | round_key[2*i+1] = ((C & 0x00000001) << 28) | ((C & 0x00000082) << 18) | |
72 | 15.3k | ((C & 0x00002000) << 14) | ((C & 0x00000100) << 10) | |
73 | 15.3k | ((C & 0x00001000) << 9) | ((C & 0x00040000) << 6) | |
74 | 15.3k | ((C & 0x02400000) << 4) | ((C & 0x00008000) << 2) | |
75 | 15.3k | ((C & 0x00200000) >> 1) | ((C & 0x04000000) >> 10) | |
76 | 15.3k | ((D & 0x00000020) << 6) | ((D & 0x00000100) ) | |
77 | 15.3k | ((D & 0x00000800) >> 1) | ((D & 0x00000040) >> 3) | |
78 | 15.3k | ((D & 0x00010000) >> 4) | ((D & 0x00000400) >> 5) | |
79 | 15.3k | ((D & 0x00004000) >> 10) | ((D & 0x04000000) >> 13) | |
80 | 15.3k | ((D & 0x00800000) >> 14) | ((D & 0x00100000) >> 18) | |
81 | 15.3k | ((D & 0x01000000) >> 24) | ((D & 0x08000000) >> 26); |
82 | 15.3k | } |
83 | 960 | } |
84 | | |
85 | | inline uint32_t spbox(uint32_t T0, uint32_t T1) |
86 | 914k | { |
87 | 914k | return DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^ |
88 | 914k | DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^ |
89 | 914k | DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^ |
90 | 914k | DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)]; |
91 | 914k | } |
92 | | |
93 | | /* |
94 | | * DES Encryption |
95 | | */ |
96 | | inline void des_encrypt(uint32_t& Lr, uint32_t& Rr, |
97 | | const uint32_t round_key[32]) |
98 | 2.07k | { |
99 | 2.07k | uint32_t L = Lr; |
100 | 2.07k | uint32_t R = Rr; |
101 | 18.6k | for(size_t i = 0; i != 16; i += 2) |
102 | 16.5k | { |
103 | 16.5k | L ^= spbox(rotr<4>(R) ^ round_key[2*i ], R ^ round_key[2*i+1]); |
104 | 16.5k | R ^= spbox(rotr<4>(L) ^ round_key[2*i+2], L ^ round_key[2*i+3]); |
105 | 16.5k | } |
106 | 2.07k | |
107 | 2.07k | Lr = L; |
108 | 2.07k | Rr = R; |
109 | 2.07k | } |
110 | | |
111 | | inline void des_encrypt_x2(uint32_t& L0r, uint32_t& R0r, |
112 | | uint32_t& L1r, uint32_t& R1r, |
113 | | const uint32_t round_key[32]) |
114 | 8.99k | { |
115 | 8.99k | uint32_t L0 = L0r; |
116 | 8.99k | uint32_t R0 = R0r; |
117 | 8.99k | uint32_t L1 = L1r; |
118 | 8.99k | uint32_t R1 = R1r; |
119 | 8.99k | |
120 | 80.9k | for(size_t i = 0; i != 16; i += 2) |
121 | 71.9k | { |
122 | 71.9k | L0 ^= spbox(rotr<4>(R0) ^ round_key[2*i ], R0 ^ round_key[2*i+1]); |
123 | 71.9k | L1 ^= spbox(rotr<4>(R1) ^ round_key[2*i ], R1 ^ round_key[2*i+1]); |
124 | 71.9k | |
125 | 71.9k | R0 ^= spbox(rotr<4>(L0) ^ round_key[2*i+2], L0 ^ round_key[2*i+3]); |
126 | 71.9k | R1 ^= spbox(rotr<4>(L1) ^ round_key[2*i+2], L1 ^ round_key[2*i+3]); |
127 | 71.9k | } |
128 | 8.99k | |
129 | 8.99k | L0r = L0; |
130 | 8.99k | R0r = R0; |
131 | 8.99k | L1r = L1; |
132 | 8.99k | R1r = R1; |
133 | 8.99k | } |
134 | | |
135 | | /* |
136 | | * DES Decryption |
137 | | */ |
138 | | inline void des_decrypt(uint32_t& Lr, uint32_t& Rr, |
139 | | const uint32_t round_key[32]) |
140 | 1.15k | { |
141 | 1.15k | uint32_t L = Lr; |
142 | 1.15k | uint32_t R = Rr; |
143 | 10.4k | for(size_t i = 16; i != 0; i -= 2) |
144 | 9.25k | { |
145 | 9.25k | L ^= spbox(rotr<4>(R) ^ round_key[2*i - 2], R ^ round_key[2*i - 1]); |
146 | 9.25k | R ^= spbox(rotr<4>(L) ^ round_key[2*i - 4], L ^ round_key[2*i - 3]); |
147 | 9.25k | } |
148 | 1.15k | Lr = L; |
149 | 1.15k | Rr = R; |
150 | 1.15k | } |
151 | | |
152 | | inline void des_decrypt_x2(uint32_t& L0r, uint32_t& R0r, |
153 | | uint32_t& L1r, uint32_t& R1r, |
154 | | const uint32_t round_key[32]) |
155 | 17.9k | { |
156 | 17.9k | uint32_t L0 = L0r; |
157 | 17.9k | uint32_t R0 = R0r; |
158 | 17.9k | uint32_t L1 = L1r; |
159 | 17.9k | uint32_t R1 = R1r; |
160 | 17.9k | |
161 | 161k | for(size_t i = 16; i != 0; i -= 2) |
162 | 143k | { |
163 | 143k | L0 ^= spbox(rotr<4>(R0) ^ round_key[2*i - 2], R0 ^ round_key[2*i - 1]); |
164 | 143k | L1 ^= spbox(rotr<4>(R1) ^ round_key[2*i - 2], R1 ^ round_key[2*i - 1]); |
165 | 143k | |
166 | 143k | R0 ^= spbox(rotr<4>(L0) ^ round_key[2*i - 4], L0 ^ round_key[2*i - 3]); |
167 | 143k | R1 ^= spbox(rotr<4>(L1) ^ round_key[2*i - 4], L1 ^ round_key[2*i - 3]); |
168 | 143k | } |
169 | 17.9k | |
170 | 17.9k | L0r = L0; |
171 | 17.9k | R0r = R0; |
172 | 17.9k | L1r = L1; |
173 | 17.9k | R1r = R1; |
174 | 17.9k | } |
175 | | |
176 | | inline void des_IP(uint32_t& L, uint32_t& R, const uint8_t block[]) |
177 | 19.0k | { |
178 | 19.0k | // IP sequence by Wei Dai, taken from public domain Crypto++ |
179 | 19.0k | L = load_be<uint32_t>(block, 0); |
180 | 19.0k | R = load_be<uint32_t>(block, 1); |
181 | 19.0k | |
182 | 19.0k | uint32_t T; |
183 | 19.0k | R = rotl<4>(R); |
184 | 19.0k | T = (L ^ R) & 0xF0F0F0F0; |
185 | 19.0k | L ^= T; |
186 | 19.0k | R = rotr<20>(R ^ T); |
187 | 19.0k | T = (L ^ R) & 0xFFFF0000; |
188 | 19.0k | L ^= T; |
189 | 19.0k | R = rotr<18>(R ^ T); |
190 | 19.0k | T = (L ^ R) & 0x33333333; |
191 | 19.0k | L ^= T; |
192 | 19.0k | R = rotr<6>(R ^ T); |
193 | 19.0k | T = (L ^ R) & 0x00FF00FF; |
194 | 19.0k | L ^= T; |
195 | 19.0k | R = rotl<9>(R ^ T); |
196 | 19.0k | T = (L ^ R) & 0xAAAAAAAA; |
197 | 19.0k | L = rotl<1>(L ^ T); |
198 | 19.0k | R ^= T; |
199 | 19.0k | } |
200 | | |
201 | | inline void des_FP(uint32_t L, uint32_t R, uint8_t out[]) |
202 | 19.0k | { |
203 | 19.0k | // FP sequence by Wei Dai, taken from public domain Crypto++ |
204 | 19.0k | uint32_t T; |
205 | 19.0k | |
206 | 19.0k | R = rotr<1>(R); |
207 | 19.0k | T = (L ^ R) & 0xAAAAAAAA; |
208 | 19.0k | R ^= T; |
209 | 19.0k | L = rotr<9>(L ^ T); |
210 | 19.0k | T = (L ^ R) & 0x00FF00FF; |
211 | 19.0k | R ^= T; |
212 | 19.0k | L = rotl<6>(L ^ T); |
213 | 19.0k | T = (L ^ R) & 0x33333333; |
214 | 19.0k | R ^= T; |
215 | 19.0k | L = rotl<18>(L ^ T); |
216 | 19.0k | T = (L ^ R) & 0xFFFF0000; |
217 | 19.0k | R ^= T; |
218 | 19.0k | L = rotl<20>(L ^ T); |
219 | 19.0k | T = (L ^ R) & 0xF0F0F0F0; |
220 | 19.0k | R ^= T; |
221 | 19.0k | L = rotr<4>(L ^ T); |
222 | 19.0k | |
223 | 19.0k | store_be(out, R, L); |
224 | 19.0k | } |
225 | | |
226 | | } |
227 | | |
228 | | /* |
229 | | * DES Encryption |
230 | | */ |
231 | | void DES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const |
232 | 0 | { |
233 | 0 | verify_key_set(m_round_key.empty() == false); |
234 | 0 |
|
235 | 0 | while(blocks >= 2) |
236 | 0 | { |
237 | 0 | uint32_t L0, R0; |
238 | 0 | uint32_t L1, R1; |
239 | 0 |
|
240 | 0 | des_IP(L0, R0, in); |
241 | 0 | des_IP(L1, R1, in + BLOCK_SIZE); |
242 | 0 |
|
243 | 0 | des_encrypt_x2(L0, R0, L1, R1, m_round_key.data()); |
244 | 0 |
|
245 | 0 | des_FP(L0, R0, out); |
246 | 0 | des_FP(L1, R1, out + BLOCK_SIZE); |
247 | 0 |
|
248 | 0 | in += 2*BLOCK_SIZE; |
249 | 0 | out += 2*BLOCK_SIZE; |
250 | 0 | blocks -= 2; |
251 | 0 | } |
252 | 0 |
|
253 | 0 | for(size_t i = 0; i < blocks; ++i) |
254 | 0 | { |
255 | 0 | uint32_t L, R; |
256 | 0 | des_IP(L, R, in + BLOCK_SIZE*i); |
257 | 0 | des_encrypt(L, R, m_round_key.data()); |
258 | 0 | des_FP(L, R, out + BLOCK_SIZE*i); |
259 | 0 | } |
260 | 0 | } |
261 | | |
262 | | /* |
263 | | * DES Decryption |
264 | | */ |
265 | | void DES::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const |
266 | 0 | { |
267 | 0 | verify_key_set(m_round_key.empty() == false); |
268 | 0 |
|
269 | 0 | while(blocks >= 2) |
270 | 0 | { |
271 | 0 | uint32_t L0, R0; |
272 | 0 | uint32_t L1, R1; |
273 | 0 |
|
274 | 0 | des_IP(L0, R0, in); |
275 | 0 | des_IP(L1, R1, in + BLOCK_SIZE); |
276 | 0 |
|
277 | 0 | des_decrypt_x2(L0, R0, L1, R1, m_round_key.data()); |
278 | 0 |
|
279 | 0 | des_FP(L0, R0, out); |
280 | 0 | des_FP(L1, R1, out + BLOCK_SIZE); |
281 | 0 |
|
282 | 0 | in += 2*BLOCK_SIZE; |
283 | 0 | out += 2*BLOCK_SIZE; |
284 | 0 | blocks -= 2; |
285 | 0 | } |
286 | 0 |
|
287 | 0 | for(size_t i = 0; i < blocks; ++i) |
288 | 0 | { |
289 | 0 | uint32_t L, R; |
290 | 0 | des_IP(L, R, in + BLOCK_SIZE*i); |
291 | 0 | des_decrypt(L, R, m_round_key.data()); |
292 | 0 | des_FP(L, R, out + BLOCK_SIZE*i); |
293 | 0 | } |
294 | 0 | } |
295 | | |
296 | | /* |
297 | | * DES Key Schedule |
298 | | */ |
299 | | void DES::key_schedule(const uint8_t key[], size_t) |
300 | 0 | { |
301 | 0 | m_round_key.resize(32); |
302 | 0 | des_key_schedule(m_round_key.data(), key); |
303 | 0 | } |
304 | | |
305 | | void DES::clear() |
306 | 0 | { |
307 | 0 | zap(m_round_key); |
308 | 0 | } |
309 | | |
310 | | /* |
311 | | * TripleDES Encryption |
312 | | */ |
313 | | void TripleDES::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const |
314 | 997 | { |
315 | 997 | verify_key_set(m_round_key.empty() == false); |
316 | 997 | |
317 | 997 | while(blocks >= 2) |
318 | 0 | { |
319 | 0 | uint32_t L0, R0; |
320 | 0 | uint32_t L1, R1; |
321 | 0 |
|
322 | 0 | des_IP(L0, R0, in); |
323 | 0 | des_IP(L1, R1, in + BLOCK_SIZE); |
324 | 0 |
|
325 | 0 | des_encrypt_x2(L0, R0, L1, R1, &m_round_key[0]); |
326 | 0 | des_decrypt_x2(R0, L0, R1, L1, &m_round_key[32]); |
327 | 0 | des_encrypt_x2(L0, R0, L1, R1, &m_round_key[64]); |
328 | 0 |
|
329 | 0 | des_FP(L0, R0, out); |
330 | 0 | des_FP(L1, R1, out + BLOCK_SIZE); |
331 | 0 |
|
332 | 0 | in += 2*BLOCK_SIZE; |
333 | 0 | out += 2*BLOCK_SIZE; |
334 | 0 | blocks -= 2; |
335 | 0 | } |
336 | 997 | |
337 | 1.99k | for(size_t i = 0; i != blocks; ++i) |
338 | 997 | { |
339 | 997 | uint32_t L, R; |
340 | 997 | des_IP(L, R, in + BLOCK_SIZE*i); |
341 | 997 | |
342 | 997 | des_encrypt(L, R, &m_round_key[0]); |
343 | 997 | des_decrypt(R, L, &m_round_key[32]); |
344 | 997 | des_encrypt(L, R, &m_round_key[64]); |
345 | 997 | |
346 | 997 | des_FP(L, R, out + BLOCK_SIZE*i); |
347 | 997 | } |
348 | 997 | } |
349 | | |
350 | | /* |
351 | | * TripleDES Decryption |
352 | | */ |
353 | | void TripleDES::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const |
354 | 4.56k | { |
355 | 4.56k | verify_key_set(m_round_key.empty() == false); |
356 | 4.56k | |
357 | 13.5k | while(blocks >= 2) |
358 | 8.99k | { |
359 | 8.99k | uint32_t L0, R0; |
360 | 8.99k | uint32_t L1, R1; |
361 | 8.99k | |
362 | 8.99k | des_IP(L0, R0, in); |
363 | 8.99k | des_IP(L1, R1, in + BLOCK_SIZE); |
364 | 8.99k | |
365 | 8.99k | des_decrypt_x2(L0, R0, L1, R1, &m_round_key[64]); |
366 | 8.99k | des_encrypt_x2(R0, L0, R1, L1, &m_round_key[32]); |
367 | 8.99k | des_decrypt_x2(L0, R0, L1, R1, &m_round_key[0]); |
368 | 8.99k | |
369 | 8.99k | des_FP(L0, R0, out); |
370 | 8.99k | des_FP(L1, R1, out + BLOCK_SIZE); |
371 | 8.99k | |
372 | 8.99k | in += 2*BLOCK_SIZE; |
373 | 8.99k | out += 2*BLOCK_SIZE; |
374 | 8.99k | blocks -= 2; |
375 | 8.99k | } |
376 | 4.56k | |
377 | 4.64k | for(size_t i = 0; i != blocks; ++i) |
378 | 80 | { |
379 | 80 | uint32_t L, R; |
380 | 80 | des_IP(L, R, in + BLOCK_SIZE*i); |
381 | 80 | |
382 | 80 | des_decrypt(L, R, &m_round_key[64]); |
383 | 80 | des_encrypt(R, L, &m_round_key[32]); |
384 | 80 | des_decrypt(L, R, &m_round_key[0]); |
385 | 80 | |
386 | 80 | des_FP(L, R, out + BLOCK_SIZE*i); |
387 | 80 | } |
388 | 4.56k | } |
389 | | |
390 | | /* |
391 | | * TripleDES Key Schedule |
392 | | */ |
393 | | void TripleDES::key_schedule(const uint8_t key[], size_t length) |
394 | 320 | { |
395 | 320 | m_round_key.resize(3*32); |
396 | 320 | des_key_schedule(&m_round_key[0], key); |
397 | 320 | des_key_schedule(&m_round_key[32], key + 8); |
398 | 320 | |
399 | 320 | if(length == 24) |
400 | 320 | des_key_schedule(&m_round_key[64], key + 16); |
401 | 0 | else |
402 | 0 | copy_mem(&m_round_key[64], &m_round_key[0], 32); |
403 | 320 | } |
404 | | |
405 | | void TripleDES::clear() |
406 | 0 | { |
407 | 0 | zap(m_round_key); |
408 | 0 | } |
409 | | |
410 | | } |