1 /*
2 * Copyright (C) 2021 - This file is part of libecc project
3 *
4 * Authors:
5 * Ryad BENADJILA <ryadbenadjila@gmail.com>
6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7 *
8 * This software is licensed under a dual BSD and GPL v2 license.
9 * See LICENSE file at the root folder of the project.
10 */
11
12 #include "tdes.h"
13
14 /* This is a very straightforward and basic implementation of DES and T-DES */
15
16 /* platform-independant 32-bit integer manipulation macros */
17 #ifndef GET_UINT32
18 #define GET_UINT32(n,b,i) \
19 do { \
20 (n) = ( (u32) (b)[(i) ] << 24 ) \
21 | ( (u32) (b)[(i) + 1] << 16 ) \
22 | ( (u32) (b)[(i) + 2] << 8 ) \
23 | ( (u32) (b)[(i) + 3] ); \
24 } while( 0 )
25 #endif
26
27 #ifndef PUT_UINT32
28 #define PUT_UINT32(n,b,i) \
29 do { \
30 (b)[(i) ] = (u8) ( (n) >> 24 ); \
31 (b)[(i) + 1] = (u8) ( (n) >> 16 ); \
32 (b)[(i) + 2] = (u8) ( (n) >> 8 ); \
33 (b)[(i) + 3] = (u8) ( (n) ); \
34 } while( 0 )
35 #endif
36
37 /* DES 8 S-Boxes */
38 static const u32 SB[8][64] = {
39 {
40 0x01010400, 0x00000000, 0x00010000, 0x01010404,
41 0x01010004, 0x00010404, 0x00000004, 0x00010000,
42 0x00000400, 0x01010400, 0x01010404, 0x00000400,
43 0x01000404, 0x01010004, 0x01000000, 0x00000004,
44 0x00000404, 0x01000400, 0x01000400, 0x00010400,
45 0x00010400, 0x01010000, 0x01010000, 0x01000404,
46 0x00010004, 0x01000004, 0x01000004, 0x00010004,
47 0x00000000, 0x00000404, 0x00010404, 0x01000000,
48 0x00010000, 0x01010404, 0x00000004, 0x01010000,
49 0x01010400, 0x01000000, 0x01000000, 0x00000400,
50 0x01010004, 0x00010000, 0x00010400, 0x01000004,
51 0x00000400, 0x00000004, 0x01000404, 0x00010404,
52 0x01010404, 0x00010004, 0x01010000, 0x01000404,
53 0x01000004, 0x00000404, 0x00010404, 0x01010400,
54 0x00000404, 0x01000400, 0x01000400, 0x00000000,
55 0x00010004, 0x00010400, 0x00000000, 0x01010004
56 },
57 {
58 0x80108020, 0x80008000, 0x00008000, 0x00108020,
59 0x00100000, 0x00000020, 0x80100020, 0x80008020,
60 0x80000020, 0x80108020, 0x80108000, 0x80000000,
61 0x80008000, 0x00100000, 0x00000020, 0x80100020,
62 0x00108000, 0x00100020, 0x80008020, 0x00000000,
63 0x80000000, 0x00008000, 0x00108020, 0x80100000,
64 0x00100020, 0x80000020, 0x00000000, 0x00108000,
65 0x00008020, 0x80108000, 0x80100000, 0x00008020,
66 0x00000000, 0x00108020, 0x80100020, 0x00100000,
67 0x80008020, 0x80100000, 0x80108000, 0x00008000,
68 0x80100000, 0x80008000, 0x00000020, 0x80108020,
69 0x00108020, 0x00000020, 0x00008000, 0x80000000,
70 0x00008020, 0x80108000, 0x00100000, 0x80000020,
71 0x00100020, 0x80008020, 0x80000020, 0x00100020,
72 0x00108000, 0x00000000, 0x80008000, 0x00008020,
73 0x80000000, 0x80100020, 0x80108020, 0x00108000
74 },
75 {
76 0x00000208, 0x08020200, 0x00000000, 0x08020008,
77 0x08000200, 0x00000000, 0x00020208, 0x08000200,
78 0x00020008, 0x08000008, 0x08000008, 0x00020000,
79 0x08020208, 0x00020008, 0x08020000, 0x00000208,
80 0x08000000, 0x00000008, 0x08020200, 0x00000200,
81 0x00020200, 0x08020000, 0x08020008, 0x00020208,
82 0x08000208, 0x00020200, 0x00020000, 0x08000208,
83 0x00000008, 0x08020208, 0x00000200, 0x08000000,
84 0x08020200, 0x08000000, 0x00020008, 0x00000208,
85 0x00020000, 0x08020200, 0x08000200, 0x00000000,
86 0x00000200, 0x00020008, 0x08020208, 0x08000200,
87 0x08000008, 0x00000200, 0x00000000, 0x08020008,
88 0x08000208, 0x00020000, 0x08000000, 0x08020208,
89 0x00000008, 0x00020208, 0x00020200, 0x08000008,
90 0x08020000, 0x08000208, 0x00000208, 0x08020000,
91 0x00020208, 0x00000008, 0x08020008, 0x00020200
92 },
93 {
94 0x00802001, 0x00002081, 0x00002081, 0x00000080,
95 0x00802080, 0x00800081, 0x00800001, 0x00002001,
96 0x00000000, 0x00802000, 0x00802000, 0x00802081,
97 0x00000081, 0x00000000, 0x00800080, 0x00800001,
98 0x00000001, 0x00002000, 0x00800000, 0x00802001,
99 0x00000080, 0x00800000, 0x00002001, 0x00002080,
100 0x00800081, 0x00000001, 0x00002080, 0x00800080,
101 0x00002000, 0x00802080, 0x00802081, 0x00000081,
102 0x00800080, 0x00800001, 0x00802000, 0x00802081,
103 0x00000081, 0x00000000, 0x00000000, 0x00802000,
104 0x00002080, 0x00800080, 0x00800081, 0x00000001,
105 0x00802001, 0x00002081, 0x00002081, 0x00000080,
106 0x00802081, 0x00000081, 0x00000001, 0x00002000,
107 0x00800001, 0x00002001, 0x00802080, 0x00800081,
108 0x00002001, 0x00002080, 0x00800000, 0x00802001,
109 0x00000080, 0x00800000, 0x00002000, 0x00802080
110 },
111 {
112 0x00000100, 0x02080100, 0x02080000, 0x42000100,
113 0x00080000, 0x00000100, 0x40000000, 0x02080000,
114 0x40080100, 0x00080000, 0x02000100, 0x40080100,
115 0x42000100, 0x42080000, 0x00080100, 0x40000000,
116 0x02000000, 0x40080000, 0x40080000, 0x00000000,
117 0x40000100, 0x42080100, 0x42080100, 0x02000100,
118 0x42080000, 0x40000100, 0x00000000, 0x42000000,
119 0x02080100, 0x02000000, 0x42000000, 0x00080100,
120 0x00080000, 0x42000100, 0x00000100, 0x02000000,
121 0x40000000, 0x02080000, 0x42000100, 0x40080100,
122 0x02000100, 0x40000000, 0x42080000, 0x02080100,
123 0x40080100, 0x00000100, 0x02000000, 0x42080000,
124 0x42080100, 0x00080100, 0x42000000, 0x42080100,
125 0x02080000, 0x00000000, 0x40080000, 0x42000000,
126 0x00080100, 0x02000100, 0x40000100, 0x00080000,
127 0x00000000, 0x40080000, 0x02080100, 0x40000100
128 },
129 {
130 0x20000010, 0x20400000, 0x00004000, 0x20404010,
131 0x20400000, 0x00000010, 0x20404010, 0x00400000,
132 0x20004000, 0x00404010, 0x00400000, 0x20000010,
133 0x00400010, 0x20004000, 0x20000000, 0x00004010,
134 0x00000000, 0x00400010, 0x20004010, 0x00004000,
135 0x00404000, 0x20004010, 0x00000010, 0x20400010,
136 0x20400010, 0x00000000, 0x00404010, 0x20404000,
137 0x00004010, 0x00404000, 0x20404000, 0x20000000,
138 0x20004000, 0x00000010, 0x20400010, 0x00404000,
139 0x20404010, 0x00400000, 0x00004010, 0x20000010,
140 0x00400000, 0x20004000, 0x20000000, 0x00004010,
141 0x20000010, 0x20404010, 0x00404000, 0x20400000,
142 0x00404010, 0x20404000, 0x00000000, 0x20400010,
143 0x00000010, 0x00004000, 0x20400000, 0x00404010,
144 0x00004000, 0x00400010, 0x20004010, 0x00000000,
145 0x20404000, 0x20000000, 0x00400010, 0x20004010
146 },
147 {
148 0x00200000, 0x04200002, 0x04000802, 0x00000000,
149 0x00000800, 0x04000802, 0x00200802, 0x04200800,
150 0x04200802, 0x00200000, 0x00000000, 0x04000002,
151 0x00000002, 0x04000000, 0x04200002, 0x00000802,
152 0x04000800, 0x00200802, 0x00200002, 0x04000800,
153 0x04000002, 0x04200000, 0x04200800, 0x00200002,
154 0x04200000, 0x00000800, 0x00000802, 0x04200802,
155 0x00200800, 0x00000002, 0x04000000, 0x00200800,
156 0x04000000, 0x00200800, 0x00200000, 0x04000802,
157 0x04000802, 0x04200002, 0x04200002, 0x00000002,
158 0x00200002, 0x04000000, 0x04000800, 0x00200000,
159 0x04200800, 0x00000802, 0x00200802, 0x04200800,
160 0x00000802, 0x04000002, 0x04200802, 0x04200000,
161 0x00200800, 0x00000000, 0x00000002, 0x04200802,
162 0x00000000, 0x00200802, 0x04200000, 0x00000800,
163 0x04000002, 0x04000800, 0x00000800, 0x00200002
164 },
165 {
166 0x10001040, 0x00001000, 0x00040000, 0x10041040,
167 0x10000000, 0x10001040, 0x00000040, 0x10000000,
168 0x00040040, 0x10040000, 0x10041040, 0x00041000,
169 0x10041000, 0x00041040, 0x00001000, 0x00000040,
170 0x10040000, 0x10000040, 0x10001000, 0x00001040,
171 0x00041000, 0x00040040, 0x10040040, 0x10041000,
172 0x00001040, 0x00000000, 0x00000000, 0x10040040,
173 0x10000040, 0x10001000, 0x00041040, 0x00040000,
174 0x00041040, 0x00040000, 0x10041000, 0x00001000,
175 0x00000040, 0x10040040, 0x00001000, 0x00041040,
176 0x10001000, 0x00000040, 0x10000040, 0x10040000,
177 0x10040040, 0x10000000, 0x00040000, 0x10001040,
178 0x00000000, 0x10041040, 0x00040040, 0x10000040,
179 0x10040000, 0x10001000, 0x10001040, 0x00000000,
180 0x10041040, 0x00041000, 0x00041000, 0x00001040,
181 0x00001040, 0x00040040, 0x10000000, 0x10041000
182 }
183 };
184
185 /* PC1: left and right halves bit-swap */
186
187 static const u32 LH[16] =
188 {
189 0x00000000, 0x00000001, 0x00000100, 0x00000101,
190 0x00010000, 0x00010001, 0x00010100, 0x00010101,
191 0x01000000, 0x01000001, 0x01000100, 0x01000101,
192 0x01010000, 0x01010001, 0x01010100, 0x01010101
193 };
194
195 static const u32 RH[16] =
196 {
197 0x00000000, 0x01000000, 0x00010000, 0x01010000,
198 0x00000100, 0x01000100, 0x00010100, 0x01010100,
199 0x00000001, 0x01000001, 0x00010001, 0x01010001,
200 0x00000101, 0x01000101, 0x00010101, 0x01010101,
201 };
202
203 /* DES Initial Permutation (IP) */
des_ip(u32 L[1],u32 R[1])204 static inline void des_ip(u32 L[1], u32 R[1])
205 {
206 u32 T;
207
208 T = ((L[0] >> 4) ^ R[0]) & 0x0F0F0F0F; R[0] ^= T; L[0] ^= (T << 4);
209 T = ((L[0] >> 16) ^ R[0]) & 0x0000FFFF; R[0] ^= T; L[0] ^= (T << 16);
210 T = ((R[0] >> 2) ^ L[0]) & 0x33333333; L[0] ^= T; R[0] ^= (T << 2);
211 T = ((R[0] >> 8) ^ L[0]) & 0x00FF00FF; L[0] ^= T; R[0] ^= (T << 8);
212 R[0] = ((R[0] << 1) | (R[0] >> 31)) & 0xFFFFFFFF;
213 T = (L[0] ^ R[0]) & 0xAAAAAAAA; R[0] ^= T; L[0] ^= T;
214 L[0] = ((L[0] << 1) | (L[0] >> 31)) & 0xFFFFFFFF;
215
216 return;
217 }
218
219 /* DES Final Permutation (FP) */
des_fp(u32 L[1],u32 R[1])220 static inline void des_fp(u32 L[1], u32 R[1])
221 {
222 u32 T;
223
224 L[0] = ((L[0] << 31) | (L[0] >> 1)) & 0xFFFFFFFF;
225 T = (L[0] ^ R[0]) & 0xAAAAAAAA; L[0] ^= T; R[0] ^= T;
226 R[0] = ((R[0] << 31) | (R[0] >> 1)) & 0xFFFFFFFF;
227 T = ((R[0] >> 8) ^ L[0]) & 0x00FF00FF; L[0] ^= T; R[0] ^= (T << 8);
228 T = ((R[0] >> 2) ^ L[0]) & 0x33333333; L[0] ^= T; R[0] ^= (T << 2);
229 T = ((L[0] >> 16) ^ R[0]) & 0x0000FFFF; R[0] ^= T; L[0] ^= (T << 16);
230 T = ((L[0] >> 4) ^ R[0]) & 0x0F0F0F0F; R[0] ^= T; L[0] ^= (T << 4);
231
232 return;
233 }
234
235 /* DES function: F(R, K) + L with inversion */
des_round(u32 L[1],u32 R[1],u64 K)236 static inline void des_round(u32 L[1], u32 R[1], u64 K)
237 {
238 u32 T;
239 u32 k1, k2;
240
241 k1 = (u32)K;
242 k2 = (u32)(K >> 32);
243
244 T = k1 ^ L[0];
245 R[0] ^= SB[7][ (T) & 0x3f] ^ SB[5][ (T >> 8) & 0x3f] ^ SB[3][ (T >> 16) & 0x3f] ^ SB[1][ (T >> 24) & 0x3f];
246 T = k2 ^ ((L[0] << 28) | (L[0] >> 4));
247 R[0] ^= SB[6][ (T) & 0x3f] ^ SB[4][ (T >> 8) & 0x3f] ^ SB[2][ (T >> 16) & 0x3f] ^ SB[0][ (T >> 24) & 0x3f];
248
249 return;
250 }
251
252 /* DES key schedule */
des_set_key(des_context * ctx,const u8 k[8],des_direction dir)253 ATTRIBUTE_WARN_UNUSED_RET int des_set_key(des_context *ctx, const u8 k[8], des_direction dir)
254 {
255 u32 i;
256 u32 C, D, T;
257 int ret;
258
259 if((ctx == NULL) || (k == NULL)){
260 ret = -1;
261 goto err;
262 }
263
264 ctx->dir = dir;
265
266 GET_UINT32(C, k, 0);
267 GET_UINT32(D, k, 4);
268
269 /* Permuted choice 1 */
270 T = ((D >> 4) ^ C) & 0x0F0F0F0F; C ^= T; D ^= (T << 4);
271 T = ((D ) ^ C) & 0x10101010; C ^= T; D ^= (T );
272
273 C = (LH[ (C ) & 0xF] << 3) | (LH[ (C >> 8) & 0xF ] << 2)
274 | (LH[ (C >> 16) & 0xF] << 1) | (LH[ (C >> 24) & 0xF ] )
275 | (LH[ (C >> 5) & 0xF] << 7) | (LH[ (C >> 13) & 0xF ] << 6)
276 | (LH[ (C >> 21) & 0xF] << 5) | (LH[ (C >> 29) & 0xF ] << 4);
277
278 D = (RH[ (D >> 1) & 0xF] << 3) | (RH[ (D >> 9) & 0xF ] << 2)
279 | (RH[ (D >> 17) & 0xF] << 1) | (RH[ (D >> 25) & 0xF ] )
280 | (RH[ (D >> 4) & 0xF] << 7) | (RH[ (D >> 12) & 0xF ] << 6)
281 | (RH[ (D >> 20) & 0xF] << 5) | (RH[ (D >> 28) & 0xF ] << 4);
282
283 C &= 0x0FFFFFFF;
284 D &= 0x0FFFFFFF;
285
286 /* Compute the subkeys */
287 for( i = 0; i < 16; i++ ){
288 u32 k1, k2;
289 if((i < 2) || (i == 8) || (i == 15)){
290 C = ((C << 1) | (C >> 27)) & 0x0FFFFFFF;
291 D = ((D << 1) | (D >> 27)) & 0x0FFFFFFF;
292 }
293 else{
294 C = ((C << 2) | (C >> 26)) & 0x0FFFFFFF;
295 D = ((D << 2) | (D >> 26)) & 0x0FFFFFFF;
296 }
297
298 k1 = ((C << 4) & 0x24000000) | ((C << 28) & 0x10000000)
299 | ((C << 14) & 0x08000000) | ((C << 18) & 0x02080000)
300 | ((C << 6) & 0x01000000) | ((C << 9) & 0x00200000)
301 | ((C >> 1) & 0x00100000) | ((C << 10) & 0x00040000)
302 | ((C << 2) & 0x00020000) | ((C >> 10) & 0x00010000)
303 | ((D >> 13) & 0x00002000) | ((D >> 4) & 0x00001000)
304 | ((D << 6) & 0x00000800) | ((D >> 1) & 0x00000400)
305 | ((D >> 14) & 0x00000200) | ((D ) & 0x00000100)
306 | ((D >> 5) & 0x00000020) | ((D >> 10) & 0x00000010)
307 | ((D >> 3) & 0x00000008) | ((D >> 18) & 0x00000004)
308 | ((D >> 26) & 0x00000002) | ((D >> 24) & 0x00000001);
309
310 k2 = ((C << 15) & 0x20000000) | ((C << 17) & 0x10000000)
311 | ((C << 10) & 0x08000000) | ((C << 22) & 0x04000000)
312 | ((C >> 2) & 0x02000000) | ((C << 1) & 0x01000000)
313 | ((C << 16) & 0x00200000) | ((C << 11) & 0x00100000)
314 | ((C << 3) & 0x00080000) | ((C >> 6) & 0x00040000)
315 | ((C << 15) & 0x00020000) | ((C >> 4) & 0x00010000)
316 | ((D >> 2) & 0x00002000) | ((D << 8) & 0x00001000)
317 | ((D >> 14) & 0x00000808) | ((D >> 9) & 0x00000400)
318 | ((D ) & 0x00000200) | ((D << 7) & 0x00000100)
319 | ((D >> 7) & 0x00000020) | ((D >> 3) & 0x00000011)
320 | ((D << 2) & 0x00000004) | ((D >> 21) & 0x00000002);
321
322 if(dir == DES_ENCRYPTION){
323 ctx->sk[i] = (((u64)k2) << 32) | (u64)k1;
324 }
325 else if(dir == DES_DECRYPTION){
326 ctx->sk[15-i] = (((u64)k2) << 32) | (u64)k1;
327 }
328 else{
329 ret = -1;
330 goto err;
331 }
332 }
333
334 ret = 0;
335
336 err:
337 return ret;
338 }
339
340 /* DES encryption core */
des_core(const des_context * ctx,const u8 input[8],u8 output[8])341 ATTRIBUTE_WARN_UNUSED_RET static inline int des_core(const des_context *ctx, const u8 input[8], u8 output[8])
342 {
343 u32 L, R;
344 u32 i;
345 int ret;
346
347 if((ctx == NULL) || (input == NULL) || (output == NULL)){
348 ret = -1;
349 goto err;
350 }
351
352 GET_UINT32(L, input, 0);
353 GET_UINT32(R, input, 4);
354
355 des_ip(&L, &R);
356
357 for(i = 0; i < 16; i++){
358 if((i % 2) == 0){
359 des_round(&R, &L, ctx->sk[i]);
360 }
361 else{
362 des_round(&L, &R, ctx->sk[i]);
363 }
364 }
365
366 des_fp(&R, &L);
367
368 PUT_UINT32(R, output, 0);
369 PUT_UINT32(L, output, 4);
370
371 ret = 0;
372 err:
373 return ret;
374 }
375
376 /* DES encryption/decryption */
des(const des_context * ctx,const u8 input[8],u8 output[8])377 ATTRIBUTE_WARN_UNUSED_RET int des(const des_context *ctx, const u8 input[8], u8 output[8])
378 {
379 return des_core(ctx, input, output);
380 }
381
382 /* TDES key schedules */
des3_set_keys(des3_context * ctx,const u8 k1[8],const u8 k2[8],const u8 k3[8],des_direction dir)383 ATTRIBUTE_WARN_UNUSED_RET int des3_set_keys(des3_context *ctx, const u8 k1[8], const u8 k2[8], const u8 k3[8], des_direction dir)
384 {
385 int ret;
386
387 if((ctx == NULL) || (k1 == NULL) || (k2 == NULL)){
388 ret = -1;
389 goto err;
390 }
391 ctx->dir = dir;
392 if(dir == DES_ENCRYPTION){
393 if(des_set_key(&(ctx->des[0]), k1, DES_ENCRYPTION)){
394 ret = -1;
395 goto err;
396 }
397 if(des_set_key(&(ctx->des[1]), k2, DES_DECRYPTION)){
398 ret = -1;
399 goto err;
400 }
401 if(k3 == NULL){
402 if(des_set_key(&(ctx->des[2]), k1, DES_ENCRYPTION)){
403 ret = -1;
404 goto err;
405 }
406 }
407 else{
408 if(des_set_key(&(ctx->des[2]), k3, DES_ENCRYPTION)){
409 ret = -1;
410 goto err;
411 }
412 }
413 }
414 else if(dir == DES_DECRYPTION){
415 if(des_set_key(&(ctx->des[0]), k1, DES_DECRYPTION)){
416 ret = -1;
417 goto err;
418 }
419 if(des_set_key(&(ctx->des[1]), k2, DES_ENCRYPTION)){
420 ret = -1;
421 goto err;
422 }
423 if(k3 == NULL){
424 if(des_set_key(&(ctx->des[2]), k1, DES_DECRYPTION)){
425 ret = -1;
426 goto err;
427 }
428 }
429 else{
430 if(des_set_key(&(ctx->des[2]), k3, DES_DECRYPTION)){
431 ret = -1;
432 goto err;
433 }
434 }
435 }
436 else{
437 ret = -1;
438 goto err;
439 }
440
441 ret = 0;
442 err:
443 return ret;
444 }
445
446 /* TDES encryption/decryption */
des3(const des3_context * ctx,const u8 input[8],u8 output[8])447 ATTRIBUTE_WARN_UNUSED_RET int des3(const des3_context *ctx, const u8 input[8], u8 output[8])
448 {
449 int ret;
450 u8 tmp[8];
451
452 if(ctx == NULL){
453 ret = -1;
454 goto err;
455 }
456 if(ctx->dir == DES_ENCRYPTION){
457 if(des_core(&(ctx->des[0]), input, output)){
458 ret = -1;
459 goto err;
460 }
461 if(des_core(&(ctx->des[1]), output, tmp)){
462 ret = -1;
463 goto err;
464 }
465 if(des_core(&(ctx->des[2]), tmp, output)){
466 ret = -1;
467 goto err;
468 }
469 }
470 else if(ctx->dir == DES_DECRYPTION){
471 if(des_core(&(ctx->des[2]), input, output)){
472 ret = -1;
473 goto err;
474 }
475 if(des_core(&(ctx->des[1]), output, tmp)){
476 ret = -1;
477 goto err;
478 }
479 if(des_core(&(ctx->des[0]), tmp, output)){
480 ret = -1;
481 goto err;
482 }
483 }
484 else{
485 ret = -1;
486 goto err;
487 }
488
489 ret = 0;
490 err:
491 return ret;
492 }
493