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