xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hcrypto/des.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1 /*	$NetBSD: des.c,v 1.3 2023/06/19 21:41:43 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 /**
37  * @page page_des DES - Data Encryption Standard crypto interface
38  *
39  * See the library functions here: @ref hcrypto_des
40  *
41  * DES was created by IBM, modififed by NSA and then adopted by NBS
42  * (now NIST) and published ad FIPS PUB 46 (updated by FIPS 46-1).
43  *
44  * Since the 19th May 2005 DES was withdrawn by NIST and should no
45  * longer be used. See @ref page_evp for replacement encryption
46  * algorithms and interfaces.
47  *
48  * Read more the iteresting history of DES on Wikipedia
49  * http://www.wikipedia.org/wiki/Data_Encryption_Standard .
50  *
51  * @section des_keygen DES key generation
52  *
53  * To generate a DES key safely you have to use the code-snippet
54  * below. This is because the DES_random_key() can fail with an
55  * abort() in case of and failure to start the random generator.
56  *
57  * There is a replacement function DES_new_random_key(), however that
58  * function does not exists in OpenSSL.
59  *
60  * @code
61  * DES_cblock key;
62  * do {
63  *     if (RAND_rand(&key, sizeof(key)) != 1)
64  *          goto failure;
65  *     DES_set_odd_parity(key);
66  * } while (DES_is_weak_key(&key));
67  * @endcode
68  *
69  * @section des_impl DES implementation history
70  *
71  * There was no complete BSD licensed, fast, GPL compatible
72  * implementation of DES, so Love wrote the part that was missing,
73  * fast key schedule setup and adapted the interface to the orignal
74  * libdes.
75  *
76  * The document that got me started for real was "Efficient
77  * Implementation of the Data Encryption Standard" by Dag Arne Osvik.
78  * I never got to the PC1 transformation was working, instead I used
79  * table-lookup was used for all key schedule setup. The document was
80  * very useful since it de-mystified other implementations for me.
81  *
82  * The core DES function (SBOX + P transformation) is from Richard
83  * Outerbridge public domain DES implementation. My sanity is saved
84  * thanks to his work. Thank you Richard.
85  */
86 
87 #include <config.h>
88 #include <krb5/roken.h>
89 
90 #define HC_DEPRECATED
91 #include <krb5/krb5-types.h>
92 #include <assert.h>
93 
94 #include "des.h"
95 #include "ui.h"
96 
97 static void desx(uint32_t [2], DES_key_schedule *, int);
98 static void IP(uint32_t [2]);
99 static void FP(uint32_t [2]);
100 
101 #include "des-tables.h"
102 
103 #define ROTATE_LEFT28(x,one)				\
104     if (one) {						\
105 	x = ( ((x)<<(1)) & 0xffffffe) | ((x) >> 27);	\
106     } else {						\
107 	x = ( ((x)<<(2)) & 0xffffffc) | ((x) >> 26);	\
108     }
109 
110 /**
111  * Set the parity of the key block, used to generate a des key from a
112  * random key. See @ref des_keygen.
113  *
114  * @param key key to fixup the parity for.
115  * @ingroup hcrypto_des
116  */
117 
118 void
DES_set_odd_parity(DES_cblock * key)119 DES_set_odd_parity(DES_cblock *key)
120 {
121     unsigned int i;
122     for (i = 0; i < DES_CBLOCK_LEN; i++)
123 	(*key)[i] = odd_parity[(*key)[i]];
124 }
125 
126 /**
127  * Check if the key have correct parity.
128  *
129  * @param key key to check the parity.
130  * @return 1 on success, 0 on failure.
131  * @ingroup hcrypto_des
132  */
133 
134 int HC_DEPRECATED
DES_check_key_parity(DES_cblock * key)135 DES_check_key_parity(DES_cblock *key)
136 {
137     unsigned int i;
138 
139     for (i = 0; i <  DES_CBLOCK_LEN; i++)
140 	if ((*key)[i] != odd_parity[(*key)[i]])
141 	    return 0;
142     return 1;
143 }
144 
145 /*
146  *
147  */
148 
149 /* FIPS 74 */
150 static DES_cblock weak_keys[] = {
151     {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, /* weak keys */
152     {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
153     {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
154     {0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1},
155     {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE}, /* semi-weak keys */
156     {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
157     {0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},
158     {0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},
159     {0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},
160     {0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},
161     {0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},
162     {0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},
163     {0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},
164     {0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},
165     {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
166     {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}
167 };
168 
169 /**
170  * Checks if the key is any of the weaks keys that makes DES attacks
171  * trival.
172  *
173  * @param key key to check.
174  *
175  * @return 1 if the key is weak, 0 otherwise.
176  * @ingroup hcrypto_des
177  */
178 
179 int
DES_is_weak_key(DES_cblock * key)180 DES_is_weak_key(DES_cblock *key)
181 {
182     int weak = 0;
183     int i;
184 
185     for (i = 0; i < sizeof(weak_keys)/sizeof(weak_keys[0]); i++)
186 	weak ^= (ct_memcmp(weak_keys[i], key, DES_CBLOCK_LEN) == 0);
187 
188     return !!weak;
189 }
190 
191 /**
192  * Setup a des key schedule from a key. Deprecated function, use
193  * DES_set_key_unchecked() or DES_set_key_checked() instead.
194  *
195  * @param key a key to initialize the key schedule with.
196  * @param ks a key schedule to initialize.
197  *
198  * @return 0 on success
199  * @ingroup hcrypto_des
200  */
201 
202 int HC_DEPRECATED
DES_set_key(DES_cblock * key,DES_key_schedule * ks)203 DES_set_key(DES_cblock *key, DES_key_schedule *ks)
204 {
205     return DES_set_key_checked(key, ks);
206 }
207 
208 /**
209  * Setup a des key schedule from a key. The key is no longer needed
210  * after this transaction and can cleared.
211  *
212  * Does NOT check that the key is weak for or have wrong parity.
213  *
214  * @param key a key to initialize the key schedule with.
215  * @param ks a key schedule to initialize.
216  *
217  * @return 0 on success
218  * @ingroup hcrypto_des
219  */
220 
221 int
DES_set_key_unchecked(DES_cblock * key,DES_key_schedule * ks)222 DES_set_key_unchecked(DES_cblock *key, DES_key_schedule *ks)
223 {
224     uint32_t t1, t2;
225     uint32_t c, d;
226     int shifts[16] = { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
227     uint32_t *k = &ks->ks[0];
228     int i;
229 
230     t1 = (uint32_t)(*key)[0] << 24 | (*key)[1] << 16 | (*key)[2] << 8 | (*key)[3];
231     t2 = (uint32_t)(*key)[4] << 24 | (*key)[5] << 16 | (*key)[6] << 8 | (*key)[7];
232 
233     c =   (pc1_c_3[(t1 >> (5            )) & 0x7] << 3)
234 	| (pc1_c_3[(t1 >> (5 + 8        )) & 0x7] << 2)
235 	| (pc1_c_3[(t1 >> (5 + 8 + 8    )) & 0x7] << 1)
236 	| (pc1_c_3[(t1 >> (5 + 8 + 8 + 8)) & 0x7] << 0)
237 	| (pc1_c_4[(t2 >> (4            )) & 0xf] << 3)
238 	| (pc1_c_4[(t2 >> (4 + 8        )) & 0xf] << 2)
239 	| (pc1_c_4[(t2 >> (4 + 8 + 8    )) & 0xf] << 1)
240 	| (pc1_c_4[(t2 >> (4 + 8 + 8 + 8)) & 0xf] << 0);
241 
242 
243     d =   (pc1_d_3[(t2 >> (1            )) & 0x7] << 3)
244 	| (pc1_d_3[(t2 >> (1 + 8        )) & 0x7] << 2)
245 	| (pc1_d_3[(t2 >> (1 + 8 + 8    )) & 0x7] << 1)
246 	| (pc1_d_3[(t2 >> (1 + 8 + 8 + 8)) & 0x7] << 0)
247 	| (pc1_d_4[(t1 >> (1            )) & 0xf] << 3)
248 	| (pc1_d_4[(t1 >> (1 + 8        )) & 0xf] << 2)
249 	| (pc1_d_4[(t1 >> (1 + 8 + 8    )) & 0xf] << 1)
250 	| (pc1_d_4[(t1 >> (1 + 8 + 8 + 8)) & 0xf] << 0);
251 
252     for (i = 0; i < 16; i++) {
253 	uint32_t kc, kd;
254 
255 	ROTATE_LEFT28(c, shifts[i]);
256 	ROTATE_LEFT28(d, shifts[i]);
257 
258 	kc = pc2_c_1[(c >> 22) & 0x3f] |
259 	    pc2_c_2[((c >> 16) & 0x30) | ((c >> 15) & 0xf)] |
260 	    pc2_c_3[((c >> 9 ) & 0x3c) | ((c >> 8 ) & 0x3)] |
261 	    pc2_c_4[((c >> 2 ) & 0x20) | ((c >> 1) & 0x18) | (c & 0x7)];
262 	kd = pc2_d_1[(d >> 22) & 0x3f] |
263 	    pc2_d_2[((d >> 15) & 0x30) | ((d >> 14) & 0xf)] |
264 	    pc2_d_3[ (d >> 7 ) & 0x3f] |
265 	    pc2_d_4[((d >> 1 ) & 0x3c) | ((d      ) & 0x3)];
266 
267 	/* Change to byte order used by the S boxes */
268 	*k  =    (kc & 0x00fc0000L) << 6;
269 	*k |=    (kc & 0x00000fc0L) << 10;
270 	*k |=    (kd & 0x00fc0000L) >> 10;
271 	*k++  |= (kd & 0x00000fc0L) >> 6;
272 	*k  =    (kc & 0x0003f000L) << 12;
273 	*k |=    (kc & 0x0000003fL) << 16;
274 	*k |=    (kd & 0x0003f000L) >> 4;
275 	*k++  |= (kd & 0x0000003fL);
276     }
277 
278     return 0;
279 }
280 
281 /**
282  * Just like DES_set_key_unchecked() except checking that the key is
283  * not weak for or have correct parity.
284  *
285  * @param key a key to initialize the key schedule with.
286  * @param ks a key schedule to initialize.
287  *
288  * @return 0 on success, -1 on invalid parity, -2 on weak key.
289  * @ingroup hcrypto_des
290  */
291 
292 int
DES_set_key_checked(DES_cblock * key,DES_key_schedule * ks)293 DES_set_key_checked(DES_cblock *key, DES_key_schedule *ks)
294 {
295     if (!DES_check_key_parity(key)) {
296 	memset(ks, 0, sizeof(*ks));
297 	return -1;
298     }
299     if (DES_is_weak_key(key)) {
300 	memset(ks, 0, sizeof(*ks));
301 	return -2;
302     }
303     return DES_set_key_unchecked(key, ks);
304 }
305 
306 /**
307  * Compatibility function for eay libdes, works just like
308  * DES_set_key_checked().
309  *
310  * @param key a key to initialize the key schedule with.
311  * @param ks a key schedule to initialize.
312  *
313  * @return 0 on success, -1 on invalid parity, -2 on weak key.
314  * @ingroup hcrypto_des
315  */
316 
317 int
DES_key_sched(DES_cblock * key,DES_key_schedule * ks)318 DES_key_sched(DES_cblock *key, DES_key_schedule *ks)
319 {
320     return DES_set_key_checked(key, ks);
321 }
322 
323 /*
324  *
325  */
326 
327 static void
load(const unsigned char * b,uint32_t v[2])328 load(const unsigned char *b, uint32_t v[2])
329 {
330     v[0] =  (uint32_t)b[0] << 24U;
331     v[0] |= b[1] << 16U;
332     v[0] |= b[2] << 8U;
333     v[0] |= b[3] << 0U;
334     v[1] =  (uint32_t)b[4] << 24U;
335     v[1] |= b[5] << 16U;
336     v[1] |= b[6] << 8U;
337     v[1] |= b[7] << 0U;
338 }
339 
340 static void
store(const uint32_t v[2],unsigned char * b)341 store(const uint32_t v[2], unsigned char *b)
342 {
343     b[0] = (v[0] >> 24) & 0xffU;
344     b[1] = (v[0] >> 16) & 0xffU;
345     b[2] = (v[0] >>  8) & 0xffU;
346     b[3] = (v[0] >>  0) & 0xffU;
347     b[4] = (v[1] >> 24) & 0xffU;
348     b[5] = (v[1] >> 16) & 0xffU;
349     b[6] = (v[1] >>  8) & 0xffU;
350     b[7] = (v[1] >>  0) & 0xffU;
351 }
352 
353 /**
354  * Encrypt/decrypt a block using DES. Also called ECB mode
355  *
356  * @param u data to encrypt
357  * @param ks key schedule to use
358  * @param encp if non zero, encrypt. if zero, decrypt.
359  *
360  * @ingroup hcrypto_des
361  */
362 
363 void
DES_encrypt(uint32_t u[2],DES_key_schedule * ks,int encp)364 DES_encrypt(uint32_t u[2], DES_key_schedule *ks, int encp)
365 {
366     IP(u);
367     desx(u, ks, encp);
368     FP(u);
369 }
370 
371 /**
372  * Encrypt/decrypt a block using DES.
373  *
374  * @param input data to encrypt
375  * @param output data to encrypt
376  * @param ks key schedule to use
377  * @param encp if non zero, encrypt. if zero, decrypt.
378  *
379  * @ingroup hcrypto_des
380  */
381 
382 void
DES_ecb_encrypt(DES_cblock * input,DES_cblock * output,DES_key_schedule * ks,int encp)383 DES_ecb_encrypt(DES_cblock *input, DES_cblock *output,
384 		DES_key_schedule *ks, int encp)
385 {
386     uint32_t u[2];
387     load(*input, u);
388     DES_encrypt(u, ks, encp);
389     store(u, *output);
390 }
391 
392 /**
393  * Encrypt/decrypt a block using DES in Chain Block Cipher mode (cbc).
394  *
395  * The IV must always be diffrent for diffrent input data blocks.
396  *
397  * @param in data to encrypt
398  * @param out data to encrypt
399  * @param length length of data
400  * @param ks key schedule to use
401  * @param iv initial vector to use
402  * @param encp if non zero, encrypt. if zero, decrypt.
403  *
404  * @ingroup hcrypto_des
405  */
406 
407 void
DES_cbc_encrypt(const void * in,void * out,long length,DES_key_schedule * ks,DES_cblock * iv,int encp)408 DES_cbc_encrypt(const void *in, void *out, long length,
409 		DES_key_schedule *ks, DES_cblock *iv, int encp)
410 {
411     const unsigned char *input = in;
412     unsigned char *output = out;
413     uint32_t u[2];
414     uint32_t uiv[2];
415 
416     load(*iv, uiv);
417 
418     if (encp) {
419 	while (length >= DES_CBLOCK_LEN) {
420 	    load(input, u);
421 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
422 	    DES_encrypt(u, ks, 1);
423 	    uiv[0] = u[0]; uiv[1] = u[1];
424 	    store(u, output);
425 
426 	    length -= DES_CBLOCK_LEN;
427 	    input += DES_CBLOCK_LEN;
428 	    output += DES_CBLOCK_LEN;
429 	}
430 	if (length) {
431 	    unsigned char tmp[DES_CBLOCK_LEN];
432 	    memcpy(tmp, input, length);
433 	    memset(tmp + length, 0, DES_CBLOCK_LEN - length);
434 	    load(tmp, u);
435 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
436 	    DES_encrypt(u, ks, 1);
437 	    store(u, output);
438 	}
439     } else {
440 	uint32_t t[2];
441 	while (length >= DES_CBLOCK_LEN) {
442 	    load(input, u);
443 	    t[0] = u[0]; t[1] = u[1];
444 	    DES_encrypt(u, ks, 0);
445 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
446 	    store(u, output);
447 	    uiv[0] = t[0]; uiv[1] = t[1];
448 
449 	    length -= DES_CBLOCK_LEN;
450 	    input += DES_CBLOCK_LEN;
451 	    output += DES_CBLOCK_LEN;
452 	}
453 	if (length) {
454 	    unsigned char tmp[DES_CBLOCK_LEN];
455 	    memcpy(tmp, input, length);
456 	    memset(tmp + length, 0, DES_CBLOCK_LEN - length);
457 	    load(tmp, u);
458 	    DES_encrypt(u, ks, 0);
459 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
460 	    store(u, output);
461 	}
462     }
463     uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
464 }
465 
466 /**
467  * Encrypt/decrypt a block using DES in Propagating Cipher Block
468  * Chaining mode. This mode is only used for Kerberos 4, and it should
469  * stay that way.
470  *
471  * The IV must always be diffrent for diffrent input data blocks.
472  *
473  * @param in data to encrypt
474  * @param out data to encrypt
475  * @param length length of data
476  * @param ks key schedule to use
477  * @param iv initial vector to use
478  * @param encp if non zero, encrypt. if zero, decrypt.
479  *
480  * @ingroup hcrypto_des
481  */
482 
483 void
DES_pcbc_encrypt(const void * in,void * out,long length,DES_key_schedule * ks,DES_cblock * iv,int encp)484 DES_pcbc_encrypt(const void *in, void *out, long length,
485 		 DES_key_schedule *ks, DES_cblock *iv, int encp)
486 {
487     const unsigned char *input = in;
488     unsigned char *output = out;
489     uint32_t u[2];
490     uint32_t uiv[2];
491 
492     load(*iv, uiv);
493 
494     if (encp) {
495 	uint32_t t[2];
496 	while (length >= DES_CBLOCK_LEN) {
497 	    load(input, u);
498 	    t[0] = u[0]; t[1] = u[1];
499 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
500 	    DES_encrypt(u, ks, 1);
501 	    uiv[0] = u[0] ^ t[0]; uiv[1] = u[1] ^ t[1];
502 	    store(u, output);
503 
504 	    length -= DES_CBLOCK_LEN;
505 	    input += DES_CBLOCK_LEN;
506 	    output += DES_CBLOCK_LEN;
507 	}
508 	if (length) {
509 	    unsigned char tmp[DES_CBLOCK_LEN];
510 	    memcpy(tmp, input, length);
511 	    memset(tmp + length, 0, DES_CBLOCK_LEN - length);
512 	    load(tmp, u);
513 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
514 	    DES_encrypt(u, ks, 1);
515 	    store(u, output);
516 	}
517     } else {
518 	uint32_t t[2];
519 	while (length >= DES_CBLOCK_LEN) {
520 	    load(input, u);
521 	    t[0] = u[0]; t[1] = u[1];
522 	    DES_encrypt(u, ks, 0);
523 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
524 	    store(u, output);
525 	    uiv[0] = t[0] ^ u[0]; uiv[1] = t[1] ^ u[1];
526 
527 	    length -= DES_CBLOCK_LEN;
528 	    input += DES_CBLOCK_LEN;
529 	    output += DES_CBLOCK_LEN;
530 	}
531 	if (length) {
532 	    unsigned char tmp[DES_CBLOCK_LEN];
533 	    memcpy(tmp, input, length);
534 	    memset(tmp + length, 0, DES_CBLOCK_LEN - length);
535 	    load(tmp, u);
536 	    DES_encrypt(u, ks, 0);
537 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
538 	}
539     }
540     uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
541 }
542 
543 /*
544  *
545  */
546 
547 static void
_des3_encrypt(uint32_t u[2],DES_key_schedule * ks1,DES_key_schedule * ks2,DES_key_schedule * ks3,int encp)548 _des3_encrypt(uint32_t u[2], DES_key_schedule *ks1, DES_key_schedule *ks2,
549 	      DES_key_schedule *ks3, int encp)
550 {
551     IP(u);
552     if (encp) {
553 	desx(u, ks1, 1); /* IP + FP cancel out each other */
554 	desx(u, ks2, 0);
555 	desx(u, ks3, 1);
556     } else {
557 	desx(u, ks3, 0);
558 	desx(u, ks2, 1);
559 	desx(u, ks1, 0);
560     }
561     FP(u);
562 }
563 
564 /**
565  * Encrypt/decrypt a block using triple DES using EDE mode,
566  * encrypt/decrypt/encrypt.
567  *
568  * @param input data to encrypt
569  * @param output data to encrypt
570  * @param ks1 key schedule to use
571  * @param ks2 key schedule to use
572  * @param ks3 key schedule to use
573  * @param encp if non zero, encrypt. if zero, decrypt.
574  *
575  * @ingroup hcrypto_des
576  */
577 
578 void
DES_ecb3_encrypt(DES_cblock * input,DES_cblock * output,DES_key_schedule * ks1,DES_key_schedule * ks2,DES_key_schedule * ks3,int encp)579 DES_ecb3_encrypt(DES_cblock *input,
580 		 DES_cblock *output,
581 		 DES_key_schedule *ks1,
582 		 DES_key_schedule *ks2,
583 		 DES_key_schedule *ks3,
584 		 int encp)
585 {
586     uint32_t u[2];
587     load(*input, u);
588     _des3_encrypt(u, ks1, ks2, ks3, encp);
589     store(u, *output);
590     return;
591 }
592 
593 /**
594  * Encrypt/decrypt using Triple DES in Chain Block Cipher mode (cbc).
595  *
596  * The IV must always be diffrent for diffrent input data blocks.
597  *
598  * @param in data to encrypt
599  * @param out data to encrypt
600  * @param length length of data
601  * @param ks1 key schedule to use
602  * @param ks2 key schedule to use
603  * @param ks3 key schedule to use
604  * @param iv initial vector to use
605  * @param encp if non zero, encrypt. if zero, decrypt.
606  *
607  * @ingroup hcrypto_des
608  */
609 
610 void
DES_ede3_cbc_encrypt(const void * in,void * out,long length,DES_key_schedule * ks1,DES_key_schedule * ks2,DES_key_schedule * ks3,DES_cblock * iv,int encp)611 DES_ede3_cbc_encrypt(const void *in, void *out,
612 		     long length, DES_key_schedule *ks1,
613 		     DES_key_schedule *ks2, DES_key_schedule *ks3,
614 		     DES_cblock *iv, int encp)
615 {
616     const unsigned char *input = in;
617     unsigned char *output = out;
618     uint32_t u[2];
619     uint32_t uiv[2];
620 
621     load(*iv, uiv);
622 
623     if (encp) {
624 	while (length >= DES_CBLOCK_LEN) {
625 	    load(input, u);
626 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
627 	    _des3_encrypt(u, ks1, ks2, ks3, 1);
628 	    uiv[0] = u[0]; uiv[1] = u[1];
629 	    store(u, output);
630 
631 	    length -= DES_CBLOCK_LEN;
632 	    input += DES_CBLOCK_LEN;
633 	    output += DES_CBLOCK_LEN;
634 	}
635 	if (length) {
636 	    unsigned char tmp[DES_CBLOCK_LEN];
637 	    memcpy(tmp, input, length);
638 	    memset(tmp + length, 0, DES_CBLOCK_LEN - length);
639 	    load(tmp, u);
640 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
641 	    _des3_encrypt(u, ks1, ks2, ks3, 1);
642 	    store(u, output);
643 	}
644     } else {
645 	uint32_t t[2];
646 	while (length >= DES_CBLOCK_LEN) {
647 	    load(input, u);
648 	    t[0] = u[0]; t[1] = u[1];
649 	    _des3_encrypt(u, ks1, ks2, ks3, 0);
650 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
651 	    store(u, output);
652 	    uiv[0] = t[0]; uiv[1] = t[1];
653 
654 	    length -= DES_CBLOCK_LEN;
655 	    input += DES_CBLOCK_LEN;
656 	    output += DES_CBLOCK_LEN;
657 	}
658 	if (length) {
659 	    unsigned char tmp[DES_CBLOCK_LEN];
660 	    memcpy(tmp, input, length);
661 	    memset(tmp + length, 0, DES_CBLOCK_LEN - length);
662 	    load(tmp, u);
663 	    _des3_encrypt(u, ks1, ks2, ks3, 0);
664 	    u[0] ^= uiv[0]; u[1] ^= uiv[1];
665 	    store(u, output);
666 	}
667     }
668     store(uiv, *iv);
669     uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
670 }
671 
672 /**
673  * Encrypt/decrypt using DES in cipher feedback mode with 64 bit
674  * feedback.
675  *
676  * The IV must always be diffrent for diffrent input data blocks.
677  *
678  * @param in data to encrypt
679  * @param out data to encrypt
680  * @param length length of data
681  * @param ks key schedule to use
682  * @param iv initial vector to use
683  * @param num offset into in cipher block encryption/decryption stop last time.
684  * @param encp if non zero, encrypt. if zero, decrypt.
685  *
686  * @ingroup hcrypto_des
687  */
688 
689 void
DES_cfb64_encrypt(const void * in,void * out,long length,DES_key_schedule * ks,DES_cblock * iv,int * num,int encp)690 DES_cfb64_encrypt(const void *in, void *out,
691 		  long length, DES_key_schedule *ks, DES_cblock *iv,
692 		  int *num, int encp)
693 {
694     const unsigned char *input = in;
695     unsigned char *output = out;
696     unsigned char tmp[DES_CBLOCK_LEN];
697     uint32_t uiv[2];
698 
699     load(*iv, uiv);
700 
701     assert(*num >= 0 && *num < DES_CBLOCK_LEN);
702 
703     if (encp) {
704 	int i = *num;
705 
706 	while (length > 0) {
707 	    if (i == 0)
708 		DES_encrypt(uiv, ks, 1);
709 	    store(uiv, tmp);
710 	    for (; i < DES_CBLOCK_LEN && i < length; i++) {
711 		output[i] = tmp[i] ^ input[i];
712 	    }
713 	    if (i == DES_CBLOCK_LEN)
714 		load(output, uiv);
715 	    output += i;
716 	    input += i;
717 	    length -= i;
718 	    if (i == DES_CBLOCK_LEN)
719 		i = 0;
720 	}
721 	store(uiv, *iv);
722 	*num = i;
723     } else {
724 	int i = *num;
725 	unsigned char c;
726 
727 	while (length > 0) {
728 	    if (i == 0) {
729 		DES_encrypt(uiv, ks, 1);
730 		store(uiv, tmp);
731 	    }
732 	    for (; i < DES_CBLOCK_LEN && i < length; i++) {
733 		c = input[i];
734 		output[i] = tmp[i] ^ input[i];
735 		(*iv)[i] = c;
736 	    }
737 	    output += i;
738 	    input += i;
739 	    length -= i;
740 	    if (i == DES_CBLOCK_LEN) {
741 		i = 0;
742 		load(*iv, uiv);
743 	    }
744 	}
745 	store(uiv, *iv);
746 	*num = i;
747     }
748 }
749 
750 /**
751  * Crete a checksum using DES in CBC encryption mode. This mode is
752  * only used for Kerberos 4, and it should stay that way.
753  *
754  * The IV must always be diffrent for diffrent input data blocks.
755  *
756  * @param in data to checksum
757  * @param output the checksum
758  * @param length length of data
759  * @param ks key schedule to use
760  * @param iv initial vector to use
761  *
762  * @ingroup hcrypto_des
763  */
764 
765 uint32_t
DES_cbc_cksum(const void * in,DES_cblock * output,long length,DES_key_schedule * ks,DES_cblock * iv)766 DES_cbc_cksum(const void *in, DES_cblock *output,
767 	      long length, DES_key_schedule *ks, DES_cblock *iv)
768 {
769     const unsigned char *input = in;
770     uint32_t uiv[2];
771     uint32_t u[2] = { 0, 0 };
772 
773     load(*iv, uiv);
774 
775     while (length >= DES_CBLOCK_LEN) {
776 	load(input, u);
777 	u[0] ^= uiv[0]; u[1] ^= uiv[1];
778 	DES_encrypt(u, ks, 1);
779 	uiv[0] = u[0]; uiv[1] = u[1];
780 
781 	length -= DES_CBLOCK_LEN;
782 	input += DES_CBLOCK_LEN;
783     }
784     if (length) {
785 	unsigned char tmp[DES_CBLOCK_LEN];
786 	memcpy(tmp, input, length);
787 	memset(tmp + length, 0, DES_CBLOCK_LEN - length);
788 	load(tmp, u);
789 	u[0] ^= uiv[0]; u[1] ^= uiv[1];
790 	DES_encrypt(u, ks, 1);
791     }
792     if (output)
793 	store(u, *output);
794 
795     uiv[0] = 0; u[0] = 0; uiv[1] = 0;
796     return u[1];
797 }
798 
799 /*
800  *
801  */
802 
803 static unsigned char
bitswap8(unsigned char b)804 bitswap8(unsigned char b)
805 {
806     unsigned char r = 0;
807     int i;
808     for (i = 0; i < 8; i++) {
809 	r = r << 1 | (b & 1);
810 	b = b >> 1;
811     }
812     return r;
813 }
814 
815 /**
816  * Convert a string to a DES key. Use something like
817  * PKCS5_PBKDF2_HMAC_SHA1() to create key from passwords.
818  *
819  * @param str The string to convert to a key
820  * @param key the resulting key
821  *
822  * @ingroup hcrypto_des
823  */
824 
825 void
DES_string_to_key(const char * str,DES_cblock * key)826 DES_string_to_key(const char *str, DES_cblock *key)
827 {
828     const unsigned char *s;
829     unsigned char *k;
830     DES_key_schedule ks;
831     size_t i, len;
832 
833     memset(key, 0, sizeof(*key));
834     k = *key;
835     s = (const unsigned char *)str;
836 
837     len = strlen(str);
838     for (i = 0; i < len; i++) {
839 	if ((i % 16) < 8)
840 	    k[i % 8] ^= s[i] << 1;
841 	else
842 	    k[7 - (i % 8)] ^= bitswap8(s[i]);
843     }
844     DES_set_odd_parity(key);
845     if (DES_is_weak_key(key))
846 	k[7] ^= 0xF0;
847     DES_set_key(key, &ks);
848     DES_cbc_cksum(s, key, len, &ks, key);
849     memset(&ks, 0, sizeof(ks));
850     DES_set_odd_parity(key);
851     if (DES_is_weak_key(key))
852 	k[7] ^= 0xF0;
853 }
854 
855 /**
856  * Read password from prompt and create a DES key. Internal uses
857  * DES_string_to_key(). Really, go use a really string2key function
858  * like PKCS5_PBKDF2_HMAC_SHA1().
859  *
860  * @param key key to convert to
861  * @param prompt prompt to display user
862  * @param verify prompt twice.
863  *
864  * @return 1 on success, non 1 on failure.
865  */
866 
867 int
DES_read_password(DES_cblock * key,char * prompt,int verify)868 DES_read_password(DES_cblock *key, char *prompt, int verify)
869 {
870     char buf[512];
871     int ret;
872 
873     ret = UI_UTIL_read_pw_string(buf, sizeof(buf) - 1, prompt, verify);
874     if (ret == 1)
875 	DES_string_to_key(buf, key);
876     return ret;
877 }
878 
879 /*
880  *
881  */
882 
883 
884 void
_DES_ipfp_test(void)885 _DES_ipfp_test(void)
886 {
887     DES_cblock k = "\x01\x02\x04\x08\x10\x20\x40\x80", k2;
888     uint32_t u[2] = { 1, 0 };
889     IP(u);
890     FP(u);
891     IP(u);
892     FP(u);
893     if (u[0] != 1 || u[1] != 0)
894 	abort();
895 
896     load(k, u);
897     store(u, k2);
898     if (memcmp(k, k2, 8) != 0)
899 	abort();
900 }
901 
902 /* D3DES (V5.09) -
903  *
904  * A portable, public domain, version of the Data Encryption Standard.
905  *
906  * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
907  * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
908  * code;  Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
909  * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
910  * for humouring me on.
911  *
912  * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
913  * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
914  */
915 
916 static uint32_t SP1[64] = {
917     0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
918     0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
919     0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
920     0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
921     0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
922     0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
923     0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
924     0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
925     0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
926     0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
927     0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
928     0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
929     0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
930     0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
931     0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
932     0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
933 
934 static uint32_t SP2[64] = {
935     0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
936     0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
937     0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
938     0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
939     0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
940     0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
941     0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
942     0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
943     0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
944     0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
945     0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
946     0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
947     0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
948     0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
949     0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
950     0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
951 
952 static uint32_t SP3[64] = {
953     0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
954     0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
955     0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
956     0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
957     0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
958     0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
959     0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
960     0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
961     0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
962     0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
963     0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
964     0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
965     0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
966     0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
967     0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
968     0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
969 
970 static uint32_t SP4[64] = {
971     0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
972     0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
973     0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
974     0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
975     0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
976     0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
977     0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
978     0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
979     0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
980     0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
981     0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
982     0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
983     0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
984     0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
985     0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
986     0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
987 
988 static uint32_t SP5[64] = {
989     0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
990     0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
991     0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
992     0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
993     0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
994     0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
995     0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
996     0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
997     0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
998     0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
999     0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
1000     0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
1001     0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
1002     0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
1003     0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
1004     0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
1005 
1006 static uint32_t SP6[64] = {
1007     0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
1008     0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
1009     0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
1010     0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
1011     0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
1012     0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
1013     0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
1014     0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
1015     0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
1016     0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
1017     0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
1018     0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
1019     0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
1020     0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
1021     0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
1022     0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
1023 
1024 static uint32_t SP7[64] = {
1025     0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
1026     0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
1027     0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
1028     0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
1029     0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
1030     0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
1031     0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
1032     0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
1033     0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
1034     0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
1035     0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
1036     0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
1037     0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
1038     0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
1039     0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
1040     0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
1041 
1042 static uint32_t SP8[64] = {
1043     0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
1044     0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
1045     0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
1046     0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
1047     0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
1048     0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
1049     0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
1050     0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
1051     0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
1052     0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
1053     0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
1054     0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
1055     0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
1056     0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
1057     0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
1058     0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
1059 
1060 static void
IP(uint32_t v[2])1061 IP(uint32_t v[2])
1062 {
1063     uint32_t work;
1064 
1065     work = ((v[0] >> 4) ^ v[1]) & 0x0f0f0f0fL;
1066     v[1] ^= work;
1067     v[0] ^= (work << 4);
1068     work = ((v[0] >> 16) ^ v[1]) & 0x0000ffffL;
1069     v[1] ^= work;
1070     v[0] ^= (work << 16);
1071     work = ((v[1] >> 2) ^ v[0]) & 0x33333333L;
1072     v[0] ^= work;
1073     v[1] ^= (work << 2);
1074     work = ((v[1] >> 8) ^ v[0]) & 0x00ff00ffL;
1075     v[0] ^= work;
1076     v[1] ^= (work << 8);
1077     v[1] = ((v[1] << 1) | ((v[1] >> 31) & 1L)) & 0xffffffffL;
1078     work = (v[0] ^ v[1]) & 0xaaaaaaaaL;
1079     v[0] ^= work;
1080     v[1] ^= work;
1081     v[0] = ((v[0] << 1) | ((v[0] >> 31) & 1L)) & 0xffffffffL;
1082 }
1083 
1084 static void
FP(uint32_t v[2])1085 FP(uint32_t v[2])
1086 {
1087     uint32_t work;
1088 
1089     v[0] = (v[0] << 31) | (v[0] >> 1);
1090     work = (v[1] ^ v[0]) & 0xaaaaaaaaL;
1091     v[1] ^= work;
1092     v[0] ^= work;
1093     v[1] = (v[1] << 31) | (v[1] >> 1);
1094     work = ((v[1] >> 8) ^ v[0]) & 0x00ff00ffL;
1095     v[0] ^= work;
1096     v[1] ^= (work << 8);
1097     work = ((v[1] >> 2) ^ v[0]) & 0x33333333L;
1098     v[0] ^= work;
1099     v[1] ^= (work << 2);
1100     work = ((v[0] >> 16) ^ v[1]) & 0x0000ffffL;
1101     v[1] ^= work;
1102     v[0] ^= (work << 16);
1103     work = ((v[0] >> 4) ^ v[1]) & 0x0f0f0f0fL;
1104     v[1] ^= work;
1105     v[0] ^= (work << 4);
1106 }
1107 
1108 static void
desx(uint32_t block[2],DES_key_schedule * ks,int encp)1109 desx(uint32_t block[2], DES_key_schedule *ks, int encp)
1110 {
1111     uint32_t *keys;
1112     uint32_t fval, work, right, left;
1113     int round;
1114 
1115     left = block[0];
1116     right = block[1];
1117 
1118     if (encp) {
1119 	keys = &ks->ks[0];
1120 
1121 	for( round = 0; round < 8; round++ ) {
1122 	    work  = (right << 28) | (right >> 4);
1123 	    work ^= *keys++;
1124 	    fval  = SP7[ work     & 0x3fL];
1125 	    fval |= SP5[(work >>  8) & 0x3fL];
1126 	    fval |= SP3[(work >> 16) & 0x3fL];
1127 	    fval |= SP1[(work >> 24) & 0x3fL];
1128 	    work  = right ^ *keys++;
1129 	    fval |= SP8[ work     & 0x3fL];
1130 	    fval |= SP6[(work >>  8) & 0x3fL];
1131 	    fval |= SP4[(work >> 16) & 0x3fL];
1132 	    fval |= SP2[(work >> 24) & 0x3fL];
1133 	    left ^= fval;
1134 	    work  = (left << 28) | (left >> 4);
1135 	    work ^= *keys++;
1136 	    fval  = SP7[ work     & 0x3fL];
1137 	    fval |= SP5[(work >>  8) & 0x3fL];
1138 	    fval |= SP3[(work >> 16) & 0x3fL];
1139 	    fval |= SP1[(work >> 24) & 0x3fL];
1140 	    work  = left ^ *keys++;
1141 	    fval |= SP8[ work     & 0x3fL];
1142 	    fval |= SP6[(work >>  8) & 0x3fL];
1143 	    fval |= SP4[(work >> 16) & 0x3fL];
1144 	    fval |= SP2[(work >> 24) & 0x3fL];
1145 	    right ^= fval;
1146 	}
1147     } else {
1148 	keys = &ks->ks[30];
1149 
1150 	for( round = 0; round < 8; round++ ) {
1151 	    work  = (right << 28) | (right >> 4);
1152 	    work ^= *keys++;
1153 	    fval  = SP7[ work     & 0x3fL];
1154 	    fval |= SP5[(work >>  8) & 0x3fL];
1155 	    fval |= SP3[(work >> 16) & 0x3fL];
1156 	    fval |= SP1[(work >> 24) & 0x3fL];
1157 	    work  = right ^ *keys++;
1158 	    fval |= SP8[ work     & 0x3fL];
1159 	    fval |= SP6[(work >>  8) & 0x3fL];
1160 	    fval |= SP4[(work >> 16) & 0x3fL];
1161 	    fval |= SP2[(work >> 24) & 0x3fL];
1162 	    left ^= fval;
1163 	    work  = (left << 28) | (left >> 4);
1164 	    keys -= 4;
1165 	    work ^= *keys++;
1166 	    fval  = SP7[ work     & 0x3fL];
1167 	    fval |= SP5[(work >>  8) & 0x3fL];
1168 	    fval |= SP3[(work >> 16) & 0x3fL];
1169 	    fval |= SP1[(work >> 24) & 0x3fL];
1170 	    work  = left ^ *keys++;
1171 	    fval |= SP8[ work     & 0x3fL];
1172 	    fval |= SP6[(work >>  8) & 0x3fL];
1173 	    fval |= SP4[(work >> 16) & 0x3fL];
1174 	    fval |= SP2[(work >> 24) & 0x3fL];
1175 	    right ^= fval;
1176 	    keys -= 4;
1177 	}
1178     }
1179     block[0] = right;
1180     block[1] = left;
1181 }
1182