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