make compile
[heimdal.git] / lib / hcrypto / des.c
blob5826ef0e4d4b1b2b0bbb36e03884275ec91b5fd4
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.
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.
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.
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.
35 * The document that got me started for real was "Efficient
36 * Implementation of the Data Encryption Standard" by Dag Arne Osvik.
37 * I never got to the PC1 transformation was working, instead I used
38 * table-lookup was used for all key schedule setup. The document was
39 * very useful since it de-mystified other implementations for me.
41 * The core DES function (SBOX + P transformation) is from Richard
42 * Outerbridge public domain DES implementation. My sanity is saved
43 * thanks to his work. Thank you Richard.
46 #ifdef HAVE_CONFIG_H
47 #include <config.h>
48 RCSID("$Id$");
49 #endif
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <krb5-types.h>
55 #include <assert.h>
57 #include "des.h"
58 #include "ui.h"
60 static void desx(uint32_t [2], DES_key_schedule *, int);
61 static void IP(uint32_t [2]);
62 static void FP(uint32_t [2]);
64 #include "des-tables.h"
66 #define ROTATE_LEFT28(x,one) \
67 if (one) { \
68 x = ( ((x)<<(1)) & 0xffffffe) | ((x) >> 27); \
69 } else { \
70 x = ( ((x)<<(2)) & 0xffffffc) | ((x) >> 26); \
77 int
78 DES_set_odd_parity(DES_cblock *key)
80 int i;
81 for (i = 0; i < DES_CBLOCK_LEN; i++)
82 (*key)[i] = odd_parity[(*key)[i]];
83 return 0;
90 /* FIPS 74 */
91 static DES_cblock weak_keys[] = {
92 {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, /* weak keys */
93 {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
94 {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
95 {0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1},
96 {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE}, /* semi-weak keys */
97 {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
98 {0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},
99 {0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},
100 {0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},
101 {0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},
102 {0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},
103 {0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},
104 {0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},
105 {0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},
106 {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
107 {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}
111 DES_is_weak_key(DES_cblock *key)
113 int i;
115 for (i = 0; i < sizeof(weak_keys)/sizeof(weak_keys[0]); i++) {
116 if (memcmp(weak_keys[i], key, DES_CBLOCK_LEN) == 0)
117 return 1;
119 return 0;
128 DES_set_key(DES_cblock *key, DES_key_schedule *ks)
130 uint32_t t1, t2;
131 uint32_t c, d;
132 int shifts[16] = { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
133 uint32_t *k = &ks->ks[0];
134 int i;
136 t1 = (*key)[0] << 24 | (*key)[1] << 16 | (*key)[2] << 8 | (*key)[3];
137 t2 = (*key)[4] << 24 | (*key)[5] << 16 | (*key)[6] << 8 | (*key)[7];
139 c = (pc1_c_3[(t1 >> (5 )) & 0x7] << 3)
140 | (pc1_c_3[(t1 >> (5 + 8 )) & 0x7] << 2)
141 | (pc1_c_3[(t1 >> (5 + 8 + 8 )) & 0x7] << 1)
142 | (pc1_c_3[(t1 >> (5 + 8 + 8 + 8)) & 0x7] << 0)
143 | (pc1_c_4[(t2 >> (4 )) & 0xf] << 3)
144 | (pc1_c_4[(t2 >> (4 + 8 )) & 0xf] << 2)
145 | (pc1_c_4[(t2 >> (4 + 8 + 8 )) & 0xf] << 1)
146 | (pc1_c_4[(t2 >> (4 + 8 + 8 + 8)) & 0xf] << 0);
149 d = (pc1_d_3[(t2 >> (1 )) & 0x7] << 3)
150 | (pc1_d_3[(t2 >> (1 + 8 )) & 0x7] << 2)
151 | (pc1_d_3[(t2 >> (1 + 8 + 8 )) & 0x7] << 1)
152 | (pc1_d_3[(t2 >> (1 + 8 + 8 + 8)) & 0x7] << 0)
153 | (pc1_d_4[(t1 >> (1 )) & 0xf] << 3)
154 | (pc1_d_4[(t1 >> (1 + 8 )) & 0xf] << 2)
155 | (pc1_d_4[(t1 >> (1 + 8 + 8 )) & 0xf] << 1)
156 | (pc1_d_4[(t1 >> (1 + 8 + 8 + 8)) & 0xf] << 0);
158 for (i = 0; i < 16; i++) {
159 uint32_t kc, kd;
161 ROTATE_LEFT28(c, shifts[i]);
162 ROTATE_LEFT28(d, shifts[i]);
164 kc = pc2_c_1[(c >> 22) & 0x3f] |
165 pc2_c_2[((c >> 16) & 0x30) | ((c >> 15) & 0xf)] |
166 pc2_c_3[((c >> 9 ) & 0x3c) | ((c >> 8 ) & 0x3)] |
167 pc2_c_4[((c >> 2 ) & 0x20) | ((c >> 1) & 0x18) | (c & 0x7)];
168 kd = pc2_d_1[(d >> 22) & 0x3f] |
169 pc2_d_2[((d >> 15) & 0x30) | ((d >> 14) & 0xf)] |
170 pc2_d_3[ (d >> 7 ) & 0x3f] |
171 pc2_d_4[((d >> 1 ) & 0x3c) | ((d ) & 0x3)];
173 /* Change to byte order used by the S boxes */
174 *k = (kc & 0x00fc0000L) << 6;
175 *k |= (kc & 0x00000fc0L) << 10;
176 *k |= (kd & 0x00fc0000L) >> 10;
177 *k++ |= (kd & 0x00000fc0L) >> 6;
178 *k = (kc & 0x0003f000L) << 12;
179 *k |= (kc & 0x0000003fL) << 16;
180 *k |= (kd & 0x0003f000L) >> 4;
181 *k++ |= (kd & 0x0000003fL);
184 return 0;
192 DES_set_key_checked(DES_cblock *key, DES_key_schedule *ks)
194 if (DES_is_weak_key(key)) {
195 memset(ks, 0, sizeof(*ks));
196 return 1;
198 return DES_set_key(key, ks);
202 * Compatibility function for eay libdes
206 DES_key_sched(DES_cblock *key, DES_key_schedule *ks)
208 return DES_set_key(key, ks);
215 static void
216 load(const unsigned char *b, uint32_t v[2])
218 v[0] = b[0] << 24;
219 v[0] |= b[1] << 16;
220 v[0] |= b[2] << 8;
221 v[0] |= b[3] << 0;
222 v[1] = b[4] << 24;
223 v[1] |= b[5] << 16;
224 v[1] |= b[6] << 8;
225 v[1] |= b[7] << 0;
228 static void
229 store(const uint32_t v[2], unsigned char *b)
231 b[0] = (v[0] >> 24) & 0xff;
232 b[1] = (v[0] >> 16) & 0xff;
233 b[2] = (v[0] >> 8) & 0xff;
234 b[3] = (v[0] >> 0) & 0xff;
235 b[4] = (v[1] >> 24) & 0xff;
236 b[5] = (v[1] >> 16) & 0xff;
237 b[6] = (v[1] >> 8) & 0xff;
238 b[7] = (v[1] >> 0) & 0xff;
245 void
246 DES_encrypt(uint32_t u[2], DES_key_schedule *ks, int forward_encrypt)
248 IP(u);
249 desx(u, ks, forward_encrypt);
250 FP(u);
257 void
258 DES_ecb_encrypt(DES_cblock *input, DES_cblock *output,
259 DES_key_schedule *ks, int forward_encrypt)
261 uint32_t u[2];
262 load(*input, u);
263 DES_encrypt(u, ks, forward_encrypt);
264 store(u, *output);
271 void
272 DES_cbc_encrypt(const void *in, void *out, long length,
273 DES_key_schedule *ks, DES_cblock *iv, int forward_encrypt)
275 const unsigned char *input = in;
276 unsigned char *output = out;
277 uint32_t u[2];
278 uint32_t uiv[2];
280 load(*iv, uiv);
282 if (forward_encrypt) {
283 while (length >= DES_CBLOCK_LEN) {
284 load(input, u);
285 u[0] ^= uiv[0]; u[1] ^= uiv[1];
286 DES_encrypt(u, ks, 1);
287 uiv[0] = u[0]; uiv[1] = u[1];
288 store(u, output);
290 length -= DES_CBLOCK_LEN;
291 input += DES_CBLOCK_LEN;
292 output += DES_CBLOCK_LEN;
294 if (length) {
295 unsigned char tmp[DES_CBLOCK_LEN];
296 memcpy(tmp, input, length);
297 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
298 load(tmp, u);
299 u[0] ^= uiv[0]; u[1] ^= uiv[1];
300 DES_encrypt(u, ks, 1);
301 store(u, output);
303 } else {
304 uint32_t t[2];
305 while (length >= DES_CBLOCK_LEN) {
306 load(input, u);
307 t[0] = u[0]; t[1] = u[1];
308 DES_encrypt(u, ks, 0);
309 u[0] ^= uiv[0]; u[1] ^= uiv[1];
310 store(u, output);
311 uiv[0] = t[0]; uiv[1] = t[1];
313 length -= DES_CBLOCK_LEN;
314 input += DES_CBLOCK_LEN;
315 output += DES_CBLOCK_LEN;
317 if (length) {
318 unsigned char tmp[DES_CBLOCK_LEN];
319 memcpy(tmp, input, length);
320 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
321 load(tmp, u);
322 DES_encrypt(u, ks, 0);
323 u[0] ^= uiv[0]; u[1] ^= uiv[1];
324 store(u, output);
327 uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
334 void
335 DES_pcbc_encrypt(const void *in, void *out, long length,
336 DES_key_schedule *ks, DES_cblock *iv, int forward_encrypt)
338 const unsigned char *input = in;
339 unsigned char *output = out;
340 uint32_t u[2];
341 uint32_t uiv[2];
343 load(*iv, uiv);
345 if (forward_encrypt) {
346 uint32_t t[2];
347 while (length >= DES_CBLOCK_LEN) {
348 load(input, u);
349 t[0] = u[0]; t[1] = u[1];
350 u[0] ^= uiv[0]; u[1] ^= uiv[1];
351 DES_encrypt(u, ks, 1);
352 uiv[0] = u[0] ^ t[0]; uiv[1] = u[1] ^ t[1];
353 store(u, output);
355 length -= DES_CBLOCK_LEN;
356 input += DES_CBLOCK_LEN;
357 output += DES_CBLOCK_LEN;
359 if (length) {
360 unsigned char tmp[DES_CBLOCK_LEN];
361 memcpy(tmp, input, length);
362 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
363 load(tmp, u);
364 u[0] ^= uiv[0]; u[1] ^= uiv[1];
365 DES_encrypt(u, ks, 1);
366 store(u, output);
368 } else {
369 uint32_t t[2];
370 while (length >= DES_CBLOCK_LEN) {
371 load(input, u);
372 t[0] = u[0]; t[1] = u[1];
373 DES_encrypt(u, ks, 0);
374 u[0] ^= uiv[0]; u[1] ^= uiv[1];
375 store(u, output);
376 uiv[0] = t[0] ^ u[0]; uiv[1] = t[1] ^ u[1];
378 length -= DES_CBLOCK_LEN;
379 input += DES_CBLOCK_LEN;
380 output += DES_CBLOCK_LEN;
382 if (length) {
383 unsigned char tmp[DES_CBLOCK_LEN];
384 memcpy(tmp, input, length);
385 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
386 load(tmp, u);
387 DES_encrypt(u, ks, 0);
388 u[0] ^= uiv[0]; u[1] ^= uiv[1];
391 uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
398 static void
399 _des3_encrypt(uint32_t u[2], DES_key_schedule *ks1, DES_key_schedule *ks2,
400 DES_key_schedule *ks3, int forward_encrypt)
402 IP(u);
403 if (forward_encrypt) {
404 desx(u, ks1, 1); /* IP + FP cancel out each other */
405 desx(u, ks2, 0);
406 desx(u, ks3, 1);
407 } else {
408 desx(u, ks3, 0);
409 desx(u, ks2, 1);
410 desx(u, ks1, 0);
412 FP(u);
419 void
420 DES_ecb3_encrypt(DES_cblock *input,
421 DES_cblock *output,
422 DES_key_schedule *ks1,
423 DES_key_schedule *ks2,
424 DES_key_schedule *ks3,
425 int forward_encrypt)
427 uint32_t u[2];
428 load(*input, u);
429 _des3_encrypt(u, ks1, ks2, ks3, forward_encrypt);
430 store(u, *output);
431 return;
438 void
439 DES_ede3_cbc_encrypt(const void *in, void *out,
440 long length, DES_key_schedule *ks1,
441 DES_key_schedule *ks2, DES_key_schedule *ks3,
442 DES_cblock *iv, int forward_encrypt)
444 const unsigned char *input = in;
445 unsigned char *output = out;
446 uint32_t u[2];
447 uint32_t uiv[2];
449 load(*iv, uiv);
451 if (forward_encrypt) {
452 while (length >= DES_CBLOCK_LEN) {
453 load(input, u);
454 u[0] ^= uiv[0]; u[1] ^= uiv[1];
455 _des3_encrypt(u, ks1, ks2, ks3, 1);
456 uiv[0] = u[0]; uiv[1] = u[1];
457 store(u, output);
459 length -= DES_CBLOCK_LEN;
460 input += DES_CBLOCK_LEN;
461 output += DES_CBLOCK_LEN;
463 if (length) {
464 unsigned char tmp[DES_CBLOCK_LEN];
465 memcpy(tmp, input, length);
466 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
467 load(tmp, u);
468 u[0] ^= uiv[0]; u[1] ^= uiv[1];
469 _des3_encrypt(u, ks1, ks2, ks3, 1);
470 store(u, output);
472 } else {
473 uint32_t t[2];
474 while (length >= DES_CBLOCK_LEN) {
475 load(input, u);
476 t[0] = u[0]; t[1] = u[1];
477 _des3_encrypt(u, ks1, ks2, ks3, 0);
478 u[0] ^= uiv[0]; u[1] ^= uiv[1];
479 store(u, output);
480 uiv[0] = t[0]; uiv[1] = t[1];
482 length -= DES_CBLOCK_LEN;
483 input += DES_CBLOCK_LEN;
484 output += DES_CBLOCK_LEN;
486 if (length) {
487 unsigned char tmp[DES_CBLOCK_LEN];
488 memcpy(tmp, input, length);
489 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
490 load(tmp, u);
491 _des3_encrypt(u, ks1, ks2, ks3, 0);
492 u[0] ^= uiv[0]; u[1] ^= uiv[1];
493 store(u, output);
496 store(uiv, *iv);
497 uiv[0] = 0; u[0] = 0; uiv[1] = 0; u[1] = 0;
504 void
505 DES_cfb64_encrypt(const void *in, void *out,
506 long length, DES_key_schedule *ks, DES_cblock *iv,
507 int *num, int forward_encrypt)
509 const unsigned char *input = in;
510 unsigned char *output = out;
511 unsigned char tmp[DES_CBLOCK_LEN];
512 uint32_t uiv[2];
514 load(*iv, uiv);
516 assert(*num >= 0 && *num < DES_CBLOCK_LEN);
518 if (forward_encrypt) {
519 int i = *num;
521 while (length > 0) {
522 if (i == 0)
523 DES_encrypt(uiv, ks, 1);
524 store(uiv, tmp);
525 for (; i < DES_CBLOCK_LEN && i < length; i++) {
526 output[i] = tmp[i] ^ input[i];
528 if (i == DES_CBLOCK_LEN)
529 load(output, uiv);
530 output += i;
531 input += i;
532 length -= i;
533 if (i == DES_CBLOCK_LEN)
534 i = 0;
536 store(uiv, *iv);
537 *num = i;
538 } else {
539 int i = *num;
540 unsigned char c;
542 while (length > 0) {
543 if (i == 0) {
544 DES_encrypt(uiv, ks, 1);
545 store(uiv, tmp);
547 for (; i < DES_CBLOCK_LEN && i < length; i++) {
548 c = input[i];
549 output[i] = tmp[i] ^ input[i];
550 (*iv)[i] = c;
552 output += i;
553 input += i;
554 length -= i;
555 if (i == DES_CBLOCK_LEN) {
556 i = 0;
557 load(*iv, uiv);
560 store(uiv, *iv);
561 *num = i;
569 uint32_t
570 DES_cbc_cksum(const void *in, DES_cblock *output,
571 long length, DES_key_schedule *ks, DES_cblock *iv)
573 const unsigned char *input = in;
574 uint32_t uiv[2];
575 uint32_t u[2] = { 0, 0 };
577 load(*iv, uiv);
579 while (length >= DES_CBLOCK_LEN) {
580 load(input, u);
581 u[0] ^= uiv[0]; u[1] ^= uiv[1];
582 DES_encrypt(u, ks, 1);
583 uiv[0] = u[0]; uiv[1] = u[1];
585 length -= DES_CBLOCK_LEN;
586 input += DES_CBLOCK_LEN;
588 if (length) {
589 unsigned char tmp[DES_CBLOCK_LEN];
590 memcpy(tmp, input, length);
591 memset(tmp + length, 0, DES_CBLOCK_LEN - length);
592 load(tmp, u);
593 u[0] ^= uiv[0]; u[1] ^= uiv[1];
594 DES_encrypt(u, ks, 1);
596 if (output)
597 store(u, *output);
599 uiv[0] = 0; u[0] = 0; uiv[1] = 0;
600 return u[1];
607 static unsigned char
608 bitswap8(unsigned char b)
610 unsigned char r = 0;
611 int i;
612 for (i = 0; i < 8; i++) {
613 r = r << 1 | (b & 1);
614 b = b >> 1;
616 return r;
619 void
620 DES_string_to_key(const char *str, DES_cblock *key)
622 const unsigned char *s;
623 unsigned char *k;
624 DES_key_schedule ks;
625 size_t i, len;
627 memset(key, 0, sizeof(*key));
628 k = *key;
629 s = (const unsigned char *)str;
631 len = strlen(str);
632 for (i = 0; i < len; i++) {
633 if ((i % 16) < 8)
634 k[i % 8] ^= s[i] << 1;
635 else
636 k[7 - (i % 8)] ^= bitswap8(s[i]);
638 DES_set_odd_parity(key);
639 if (DES_is_weak_key(key))
640 k[7] ^= 0xF0;
641 DES_set_key(key, &ks);
642 DES_cbc_cksum(s, key, len, &ks, key);
643 memset(&ks, 0, sizeof(ks));
644 DES_set_odd_parity(key);
645 if (DES_is_weak_key(key))
646 k[7] ^= 0xF0;
654 DES_read_password(DES_cblock *key, char *prompt, int verify)
656 char buf[512];
657 int ret;
659 ret = UI_UTIL_read_pw_string(buf, sizeof(buf) - 1, prompt, verify);
660 if (ret == 0)
661 DES_string_to_key(buf, key);
662 return ret;
670 void
671 _DES_ipfp_test(void)
673 DES_cblock k = "\x01\x02\x04\x08\x10\x20\x40\x80", k2;
674 uint32_t u[2] = { 1, 0 };
675 IP(u);
676 FP(u);
677 IP(u);
678 FP(u);
679 if (u[0] != 1 || u[1] != 0)
680 abort();
682 load(k, u);
683 store(u, k2);
684 if (memcmp(k, k2, 8) != 0)
685 abort();
688 /* D3DES (V5.09) -
690 * A portable, public domain, version of the Data Encryption Standard.
692 * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
693 * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
694 * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
695 * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
696 * for humouring me on.
698 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
699 * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
702 static uint32_t SP1[64] = {
703 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
704 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
705 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
706 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
707 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
708 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
709 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
710 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
711 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
712 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
713 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
714 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
715 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
716 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
717 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
718 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
720 static uint32_t SP2[64] = {
721 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
722 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
723 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
724 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
725 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
726 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
727 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
728 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
729 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
730 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
731 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
732 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
733 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
734 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
735 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
736 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
738 static uint32_t SP3[64] = {
739 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
740 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
741 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
742 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
743 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
744 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
745 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
746 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
747 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
748 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
749 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
750 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
751 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
752 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
753 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
754 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
756 static uint32_t SP4[64] = {
757 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
758 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
759 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
760 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
761 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
762 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
763 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
764 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
765 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
766 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
767 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
768 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
769 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
770 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
771 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
772 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
774 static uint32_t SP5[64] = {
775 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
776 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
777 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
778 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
779 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
780 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
781 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
782 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
783 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
784 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
785 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
786 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
787 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
788 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
789 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
790 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
792 static uint32_t SP6[64] = {
793 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
794 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
795 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
796 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
797 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
798 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
799 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
800 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
801 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
802 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
803 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
804 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
805 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
806 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
807 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
808 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
810 static uint32_t SP7[64] = {
811 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
812 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
813 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
814 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
815 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
816 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
817 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
818 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
819 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
820 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
821 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
822 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
823 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
824 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
825 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
826 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
828 static uint32_t SP8[64] = {
829 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
830 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
831 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
832 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
833 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
834 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
835 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
836 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
837 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
838 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
839 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
840 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
841 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
842 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
843 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
844 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
846 static void
847 IP(uint32_t v[2])
849 uint32_t work;
851 work = ((v[0] >> 4) ^ v[1]) & 0x0f0f0f0fL;
852 v[1] ^= work;
853 v[0] ^= (work << 4);
854 work = ((v[0] >> 16) ^ v[1]) & 0x0000ffffL;
855 v[1] ^= work;
856 v[0] ^= (work << 16);
857 work = ((v[1] >> 2) ^ v[0]) & 0x33333333L;
858 v[0] ^= work;
859 v[1] ^= (work << 2);
860 work = ((v[1] >> 8) ^ v[0]) & 0x00ff00ffL;
861 v[0] ^= work;
862 v[1] ^= (work << 8);
863 v[1] = ((v[1] << 1) | ((v[1] >> 31) & 1L)) & 0xffffffffL;
864 work = (v[0] ^ v[1]) & 0xaaaaaaaaL;
865 v[0] ^= work;
866 v[1] ^= work;
867 v[0] = ((v[0] << 1) | ((v[0] >> 31) & 1L)) & 0xffffffffL;
870 static void
871 FP(uint32_t v[2])
873 uint32_t work;
875 v[0] = (v[0] << 31) | (v[0] >> 1);
876 work = (v[1] ^ v[0]) & 0xaaaaaaaaL;
877 v[1] ^= work;
878 v[0] ^= work;
879 v[1] = (v[1] << 31) | (v[1] >> 1);
880 work = ((v[1] >> 8) ^ v[0]) & 0x00ff00ffL;
881 v[0] ^= work;
882 v[1] ^= (work << 8);
883 work = ((v[1] >> 2) ^ v[0]) & 0x33333333L;
884 v[0] ^= work;
885 v[1] ^= (work << 2);
886 work = ((v[0] >> 16) ^ v[1]) & 0x0000ffffL;
887 v[1] ^= work;
888 v[0] ^= (work << 16);
889 work = ((v[0] >> 4) ^ v[1]) & 0x0f0f0f0fL;
890 v[1] ^= work;
891 v[0] ^= (work << 4);
894 static void
895 desx(uint32_t block[2], DES_key_schedule *ks, int forward_encrypt)
897 uint32_t *keys;
898 uint32_t fval, work, right, left;
899 int round;
901 left = block[0];
902 right = block[1];
904 if (forward_encrypt) {
905 keys = &ks->ks[0];
907 for( round = 0; round < 8; round++ ) {
908 work = (right << 28) | (right >> 4);
909 work ^= *keys++;
910 fval = SP7[ work & 0x3fL];
911 fval |= SP5[(work >> 8) & 0x3fL];
912 fval |= SP3[(work >> 16) & 0x3fL];
913 fval |= SP1[(work >> 24) & 0x3fL];
914 work = right ^ *keys++;
915 fval |= SP8[ work & 0x3fL];
916 fval |= SP6[(work >> 8) & 0x3fL];
917 fval |= SP4[(work >> 16) & 0x3fL];
918 fval |= SP2[(work >> 24) & 0x3fL];
919 left ^= fval;
920 work = (left << 28) | (left >> 4);
921 work ^= *keys++;
922 fval = SP7[ work & 0x3fL];
923 fval |= SP5[(work >> 8) & 0x3fL];
924 fval |= SP3[(work >> 16) & 0x3fL];
925 fval |= SP1[(work >> 24) & 0x3fL];
926 work = left ^ *keys++;
927 fval |= SP8[ work & 0x3fL];
928 fval |= SP6[(work >> 8) & 0x3fL];
929 fval |= SP4[(work >> 16) & 0x3fL];
930 fval |= SP2[(work >> 24) & 0x3fL];
931 right ^= fval;
933 } else {
934 keys = &ks->ks[30];
936 for( round = 0; round < 8; round++ ) {
937 work = (right << 28) | (right >> 4);
938 work ^= *keys++;
939 fval = SP7[ work & 0x3fL];
940 fval |= SP5[(work >> 8) & 0x3fL];
941 fval |= SP3[(work >> 16) & 0x3fL];
942 fval |= SP1[(work >> 24) & 0x3fL];
943 work = right ^ *keys++;
944 fval |= SP8[ work & 0x3fL];
945 fval |= SP6[(work >> 8) & 0x3fL];
946 fval |= SP4[(work >> 16) & 0x3fL];
947 fval |= SP2[(work >> 24) & 0x3fL];
948 left ^= fval;
949 work = (left << 28) | (left >> 4);
950 keys -= 4;
951 work ^= *keys++;
952 fval = SP7[ work & 0x3fL];
953 fval |= SP5[(work >> 8) & 0x3fL];
954 fval |= SP3[(work >> 16) & 0x3fL];
955 fval |= SP1[(work >> 24) & 0x3fL];
956 work = left ^ *keys++;
957 fval |= SP8[ work & 0x3fL];
958 fval |= SP6[(work >> 8) & 0x3fL];
959 fval |= SP4[(work >> 16) & 0x3fL];
960 fval |= SP2[(work >> 24) & 0x3fL];
961 right ^= fval;
962 keys -= 4;
965 block[0] = right;
966 block[1] = left;