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