xref: /freebsd/crypto/libecc/src/examples/hash/tdes.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
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