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