Coverage Report

Created: 2025-04-11 06:34

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