2 * Copyright (c) 2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
35 * @page page_des DES - Data Encryption Standard crypto interface
37 * See the library functions here: @ref hcrypto_des
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).
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.
46 * Read more the iteresting history of DES on Wikipedia
47 * http://www.wikipedia.org/wiki/Data_Encryption_Standard .
49 * @section des_impl DES implementation history
51 * There was no complete BSD licensed, fast, GPL compatible
52 * implementation of DES, so Love wrote the part that was missing,
53 * fast key schedule setup and adapted the interface to the orignal
56 * The document that got me started for real was "Efficient
57 * Implementation of the Data Encryption Standard" by Dag Arne Osvik.
58 * I never got to the PC1 transformation was working, instead I used
59 * table-lookup was used for all key schedule setup. The document was
60 * very useful since it de-mystified other implementations for me.
62 * The core DES function (SBOX + P transformation) is from Richard
63 * Outerbridge public domain DES implementation. My sanity is saved
64 * thanks to his work. Thank you Richard.
75 #include <krb5-types.h>
81 static void desx(uint32_t [2], DES_key_schedule
*, int);
82 static void IP(uint32_t [2]);
83 static void FP(uint32_t [2]);
85 #include "des-tables.h"
87 #define ROTATE_LEFT28(x,one) \
89 x = ( ((x)<<(1)) & 0xffffffe) | ((x) >> 27); \
91 x = ( ((x)<<(2)) & 0xffffffc) | ((x) >> 26); \
99 DES_set_odd_parity(DES_cblock
*key
)
102 for (i
= 0; i
< DES_CBLOCK_LEN
; i
++)
103 (*key
)[i
] = odd_parity
[(*key
)[i
]];
112 static DES_cblock weak_keys
[] = {
113 {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, /* weak keys */
114 {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
115 {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
116 {0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1},
117 {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE}, /* semi-weak keys */
118 {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
119 {0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},
120 {0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},
121 {0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},
122 {0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},
123 {0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},
124 {0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},
125 {0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},
126 {0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},
127 {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
128 {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}
132 DES_is_weak_key(DES_cblock
*key
)
136 for (i
= 0; i
< sizeof(weak_keys
)/sizeof(weak_keys
[0]); i
++) {
137 if (memcmp(weak_keys
[i
], key
, DES_CBLOCK_LEN
) == 0)
145 * Setup a des key schedule from a key. The key is no longer needed
146 * after this transaction and can cleared.
148 * @param key a key to initialize the key schedule with.
149 * @param ks a key schedule to initialize.
151 * @return 0 on success
152 * @ingroup hcrypto_des
156 DES_set_key(DES_cblock
*key
, DES_key_schedule
*ks
)
160 int shifts
[16] = { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
161 uint32_t *k
= &ks
->ks
[0];
164 t1
= (*key
)[0] << 24 | (*key
)[1] << 16 | (*key
)[2] << 8 | (*key
)[3];
165 t2
= (*key
)[4] << 24 | (*key
)[5] << 16 | (*key
)[6] << 8 | (*key
)[7];
167 c
= (pc1_c_3
[(t1
>> (5 )) & 0x7] << 3)
168 | (pc1_c_3
[(t1
>> (5 + 8 )) & 0x7] << 2)
169 | (pc1_c_3
[(t1
>> (5 + 8 + 8 )) & 0x7] << 1)
170 | (pc1_c_3
[(t1
>> (5 + 8 + 8 + 8)) & 0x7] << 0)
171 | (pc1_c_4
[(t2
>> (4 )) & 0xf] << 3)
172 | (pc1_c_4
[(t2
>> (4 + 8 )) & 0xf] << 2)
173 | (pc1_c_4
[(t2
>> (4 + 8 + 8 )) & 0xf] << 1)
174 | (pc1_c_4
[(t2
>> (4 + 8 + 8 + 8)) & 0xf] << 0);
177 d
= (pc1_d_3
[(t2
>> (1 )) & 0x7] << 3)
178 | (pc1_d_3
[(t2
>> (1 + 8 )) & 0x7] << 2)
179 | (pc1_d_3
[(t2
>> (1 + 8 + 8 )) & 0x7] << 1)
180 | (pc1_d_3
[(t2
>> (1 + 8 + 8 + 8)) & 0x7] << 0)
181 | (pc1_d_4
[(t1
>> (1 )) & 0xf] << 3)
182 | (pc1_d_4
[(t1
>> (1 + 8 )) & 0xf] << 2)
183 | (pc1_d_4
[(t1
>> (1 + 8 + 8 )) & 0xf] << 1)
184 | (pc1_d_4
[(t1
>> (1 + 8 + 8 + 8)) & 0xf] << 0);
186 for (i
= 0; i
< 16; i
++) {
189 ROTATE_LEFT28(c
, shifts
[i
]);
190 ROTATE_LEFT28(d
, shifts
[i
]);
192 kc
= pc2_c_1
[(c
>> 22) & 0x3f] |
193 pc2_c_2
[((c
>> 16) & 0x30) | ((c
>> 15) & 0xf)] |
194 pc2_c_3
[((c
>> 9 ) & 0x3c) | ((c
>> 8 ) & 0x3)] |
195 pc2_c_4
[((c
>> 2 ) & 0x20) | ((c
>> 1) & 0x18) | (c
& 0x7)];
196 kd
= pc2_d_1
[(d
>> 22) & 0x3f] |
197 pc2_d_2
[((d
>> 15) & 0x30) | ((d
>> 14) & 0xf)] |
198 pc2_d_3
[ (d
>> 7 ) & 0x3f] |
199 pc2_d_4
[((d
>> 1 ) & 0x3c) | ((d
) & 0x3)];
201 /* Change to byte order used by the S boxes */
202 *k
= (kc
& 0x00fc0000L
) << 6;
203 *k
|= (kc
& 0x00000fc0L
) << 10;
204 *k
|= (kd
& 0x00fc0000L
) >> 10;
205 *k
++ |= (kd
& 0x00000fc0L
) >> 6;
206 *k
= (kc
& 0x0003f000L
) << 12;
207 *k
|= (kc
& 0x0000003fL
) << 16;
208 *k
|= (kd
& 0x0003f000L
) >> 4;
209 *k
++ |= (kd
& 0x0000003fL
);
220 DES_set_key_checked(DES_cblock
*key
, DES_key_schedule
*ks
)
222 if (DES_is_weak_key(key
)) {
223 memset(ks
, 0, sizeof(*ks
));
226 return DES_set_key(key
, ks
);
230 * Compatibility function for eay libdes
234 DES_key_sched(DES_cblock
*key
, DES_key_schedule
*ks
)
236 return DES_set_key(key
, ks
);
244 load(const unsigned char *b
, uint32_t v
[2])
257 store(const uint32_t v
[2], unsigned char *b
)
259 b
[0] = (v
[0] >> 24) & 0xff;
260 b
[1] = (v
[0] >> 16) & 0xff;
261 b
[2] = (v
[0] >> 8) & 0xff;
262 b
[3] = (v
[0] >> 0) & 0xff;
263 b
[4] = (v
[1] >> 24) & 0xff;
264 b
[5] = (v
[1] >> 16) & 0xff;
265 b
[6] = (v
[1] >> 8) & 0xff;
266 b
[7] = (v
[1] >> 0) & 0xff;
270 * Encrypt/decrypt a block using DES. Also called ECB mode
272 * @param u data to encrypt
273 * @param ks key schedule to use
274 * @param encp if non zero, encrypt. if zero, decrypt.
276 * @ingroup hcrypto_des
280 DES_encrypt(uint32_t u
[2], DES_key_schedule
*ks
, int encp
)
288 * Encrypt/decrypt a block using DES.
290 * @param input data to encrypt
291 * @param output data to encrypt
292 * @param ks key schedule to use
293 * @param encp if non zero, encrypt. if zero, decrypt.
295 * @ingroup hcrypto_des
299 DES_ecb_encrypt(DES_cblock
*input
, DES_cblock
*output
,
300 DES_key_schedule
*ks
, int encp
)
304 DES_encrypt(u
, ks
, encp
);
309 * Encrypt/decrypt a block using DES in Chain Block Cipher mode (cbc).
311 * The IV must always be diffrent for diffrent input data blocks.
313 * @param in data to encrypt
314 * @param out data to encrypt
315 * @param length length of data
316 * @param ks key schedule to use
317 * @param iv initial vector to use
318 * @param encp if non zero, encrypt. if zero, decrypt.
320 * @ingroup hcrypto_des
324 DES_cbc_encrypt(const void *in
, void *out
, long length
,
325 DES_key_schedule
*ks
, DES_cblock
*iv
, int encp
)
327 const unsigned char *input
= in
;
328 unsigned char *output
= out
;
335 while (length
>= DES_CBLOCK_LEN
) {
337 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
338 DES_encrypt(u
, ks
, 1);
339 uiv
[0] = u
[0]; uiv
[1] = u
[1];
342 length
-= DES_CBLOCK_LEN
;
343 input
+= DES_CBLOCK_LEN
;
344 output
+= DES_CBLOCK_LEN
;
347 unsigned char tmp
[DES_CBLOCK_LEN
];
348 memcpy(tmp
, input
, length
);
349 memset(tmp
+ length
, 0, DES_CBLOCK_LEN
- length
);
351 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
352 DES_encrypt(u
, ks
, 1);
357 while (length
>= DES_CBLOCK_LEN
) {
359 t
[0] = u
[0]; t
[1] = u
[1];
360 DES_encrypt(u
, ks
, 0);
361 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
363 uiv
[0] = t
[0]; uiv
[1] = t
[1];
365 length
-= DES_CBLOCK_LEN
;
366 input
+= DES_CBLOCK_LEN
;
367 output
+= DES_CBLOCK_LEN
;
370 unsigned char tmp
[DES_CBLOCK_LEN
];
371 memcpy(tmp
, input
, length
);
372 memset(tmp
+ length
, 0, DES_CBLOCK_LEN
- length
);
374 DES_encrypt(u
, ks
, 0);
375 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
379 uiv
[0] = 0; u
[0] = 0; uiv
[1] = 0; u
[1] = 0;
383 * Encrypt/decrypt a block using DES in Propagating Cipher Block
384 * Chaining mode. This mode is only used for Kerberos 4, and it should
387 * The IV must always be diffrent for diffrent input data blocks.
389 * @param in data to encrypt
390 * @param out data to encrypt
391 * @param length length of data
392 * @param ks key schedule to use
393 * @param iv initial vector to use
394 * @param encp if non zero, encrypt. if zero, decrypt.
396 * @ingroup hcrypto_des
400 DES_pcbc_encrypt(const void *in
, void *out
, long length
,
401 DES_key_schedule
*ks
, DES_cblock
*iv
, int encp
)
403 const unsigned char *input
= in
;
404 unsigned char *output
= out
;
412 while (length
>= DES_CBLOCK_LEN
) {
414 t
[0] = u
[0]; t
[1] = u
[1];
415 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
416 DES_encrypt(u
, ks
, 1);
417 uiv
[0] = u
[0] ^ t
[0]; uiv
[1] = u
[1] ^ t
[1];
420 length
-= DES_CBLOCK_LEN
;
421 input
+= DES_CBLOCK_LEN
;
422 output
+= DES_CBLOCK_LEN
;
425 unsigned char tmp
[DES_CBLOCK_LEN
];
426 memcpy(tmp
, input
, length
);
427 memset(tmp
+ length
, 0, DES_CBLOCK_LEN
- length
);
429 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
430 DES_encrypt(u
, ks
, 1);
435 while (length
>= DES_CBLOCK_LEN
) {
437 t
[0] = u
[0]; t
[1] = u
[1];
438 DES_encrypt(u
, ks
, 0);
439 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
441 uiv
[0] = t
[0] ^ u
[0]; uiv
[1] = t
[1] ^ u
[1];
443 length
-= DES_CBLOCK_LEN
;
444 input
+= DES_CBLOCK_LEN
;
445 output
+= DES_CBLOCK_LEN
;
448 unsigned char tmp
[DES_CBLOCK_LEN
];
449 memcpy(tmp
, input
, length
);
450 memset(tmp
+ length
, 0, DES_CBLOCK_LEN
- length
);
452 DES_encrypt(u
, ks
, 0);
453 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
456 uiv
[0] = 0; u
[0] = 0; uiv
[1] = 0; u
[1] = 0;
464 _des3_encrypt(uint32_t u
[2], DES_key_schedule
*ks1
, DES_key_schedule
*ks2
,
465 DES_key_schedule
*ks3
, int encp
)
469 desx(u
, ks1
, 1); /* IP + FP cancel out each other */
481 * Encrypt/decrypt a block using triple DES using EDE mode,
482 * encrypt/decrypt/encrypt.
484 * @param input data to encrypt
485 * @param output data to encrypt
486 * @param ks1 key schedule to use
487 * @param ks2 key schedule to use
488 * @param ks3 key schedule to use
489 * @param encp if non zero, encrypt. if zero, decrypt.
491 * @ingroup hcrypto_des
495 DES_ecb3_encrypt(DES_cblock
*input
,
497 DES_key_schedule
*ks1
,
498 DES_key_schedule
*ks2
,
499 DES_key_schedule
*ks3
,
504 _des3_encrypt(u
, ks1
, ks2
, ks3
, encp
);
510 * Encrypt/decrypt using Triple DES in Chain Block Cipher mode (cbc).
512 * The IV must always be diffrent for diffrent input data blocks.
514 * @param in data to encrypt
515 * @param out data to encrypt
516 * @param length length of data
517 * @param ks1 key schedule to use
518 * @param ks2 key schedule to use
519 * @param ks3 key schedule to use
520 * @param iv initial vector to use
521 * @param encp if non zero, encrypt. if zero, decrypt.
523 * @ingroup hcrypto_des
527 DES_ede3_cbc_encrypt(const void *in
, void *out
,
528 long length
, DES_key_schedule
*ks1
,
529 DES_key_schedule
*ks2
, DES_key_schedule
*ks3
,
530 DES_cblock
*iv
, int encp
)
532 const unsigned char *input
= in
;
533 unsigned char *output
= out
;
540 while (length
>= DES_CBLOCK_LEN
) {
542 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
543 _des3_encrypt(u
, ks1
, ks2
, ks3
, 1);
544 uiv
[0] = u
[0]; uiv
[1] = u
[1];
547 length
-= DES_CBLOCK_LEN
;
548 input
+= DES_CBLOCK_LEN
;
549 output
+= DES_CBLOCK_LEN
;
552 unsigned char tmp
[DES_CBLOCK_LEN
];
553 memcpy(tmp
, input
, length
);
554 memset(tmp
+ length
, 0, DES_CBLOCK_LEN
- length
);
556 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
557 _des3_encrypt(u
, ks1
, ks2
, ks3
, 1);
562 while (length
>= DES_CBLOCK_LEN
) {
564 t
[0] = u
[0]; t
[1] = u
[1];
565 _des3_encrypt(u
, ks1
, ks2
, ks3
, 0);
566 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
568 uiv
[0] = t
[0]; uiv
[1] = t
[1];
570 length
-= DES_CBLOCK_LEN
;
571 input
+= DES_CBLOCK_LEN
;
572 output
+= DES_CBLOCK_LEN
;
575 unsigned char tmp
[DES_CBLOCK_LEN
];
576 memcpy(tmp
, input
, length
);
577 memset(tmp
+ length
, 0, DES_CBLOCK_LEN
- length
);
579 _des3_encrypt(u
, ks1
, ks2
, ks3
, 0);
580 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
585 uiv
[0] = 0; u
[0] = 0; uiv
[1] = 0; u
[1] = 0;
589 * Encrypt/decrypt using DES in cipher feedback mode with 64 bit
592 * The IV must always be diffrent for diffrent input data blocks.
594 * @param in data to encrypt
595 * @param out data to encrypt
596 * @param length length of data
597 * @param ks key schedule to use
598 * @param iv initial vector to use
599 * @param num offset into in cipher block encryption/decryption stop last time.
600 * @param encp if non zero, encrypt. if zero, decrypt.
602 * @ingroup hcrypto_des
606 DES_cfb64_encrypt(const void *in
, void *out
,
607 long length
, DES_key_schedule
*ks
, DES_cblock
*iv
,
610 const unsigned char *input
= in
;
611 unsigned char *output
= out
;
612 unsigned char tmp
[DES_CBLOCK_LEN
];
617 assert(*num
>= 0 && *num
< DES_CBLOCK_LEN
);
624 DES_encrypt(uiv
, ks
, 1);
626 for (; i
< DES_CBLOCK_LEN
&& i
< length
; i
++) {
627 output
[i
] = tmp
[i
] ^ input
[i
];
629 if (i
== DES_CBLOCK_LEN
)
634 if (i
== DES_CBLOCK_LEN
)
645 DES_encrypt(uiv
, ks
, 1);
648 for (; i
< DES_CBLOCK_LEN
&& i
< length
; i
++) {
650 output
[i
] = tmp
[i
] ^ input
[i
];
656 if (i
== DES_CBLOCK_LEN
) {
667 * Crete a checksum using DES in CBC encryption mode. This mode is
668 * only used for Kerberos 4, and it should stay that way.
670 * The IV must always be diffrent for diffrent input data blocks.
672 * @param in data to checksum
673 * @param output the checksum
674 * @param length length of data
675 * @param ks key schedule to use
676 * @param iv initial vector to use
678 * @ingroup hcrypto_des
682 DES_cbc_cksum(const void *in
, DES_cblock
*output
,
683 long length
, DES_key_schedule
*ks
, DES_cblock
*iv
)
685 const unsigned char *input
= in
;
687 uint32_t u
[2] = { 0, 0 };
691 while (length
>= DES_CBLOCK_LEN
) {
693 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
694 DES_encrypt(u
, ks
, 1);
695 uiv
[0] = u
[0]; uiv
[1] = u
[1];
697 length
-= DES_CBLOCK_LEN
;
698 input
+= DES_CBLOCK_LEN
;
701 unsigned char tmp
[DES_CBLOCK_LEN
];
702 memcpy(tmp
, input
, length
);
703 memset(tmp
+ length
, 0, DES_CBLOCK_LEN
- length
);
705 u
[0] ^= uiv
[0]; u
[1] ^= uiv
[1];
706 DES_encrypt(u
, ks
, 1);
711 uiv
[0] = 0; u
[0] = 0; uiv
[1] = 0;
720 bitswap8(unsigned char b
)
724 for (i
= 0; i
< 8; i
++) {
725 r
= r
<< 1 | (b
& 1);
732 * Convert a string to a DES key. Use something like
733 * PKCS5_PBKDF2_HMAC_SHA1() to create key from passwords.
735 * @param str The string to convert to a key
736 * @param key the resulting key
738 * @ingroup hcrypto_des
742 DES_string_to_key(const char *str
, DES_cblock
*key
)
744 const unsigned char *s
;
749 memset(key
, 0, sizeof(*key
));
751 s
= (const unsigned char *)str
;
754 for (i
= 0; i
< len
; i
++) {
756 k
[i
% 8] ^= s
[i
] << 1;
758 k
[7 - (i
% 8)] ^= bitswap8(s
[i
]);
760 DES_set_odd_parity(key
);
761 if (DES_is_weak_key(key
))
763 DES_set_key(key
, &ks
);
764 DES_cbc_cksum(s
, key
, len
, &ks
, key
);
765 memset(&ks
, 0, sizeof(ks
));
766 DES_set_odd_parity(key
);
767 if (DES_is_weak_key(key
))
772 * Read password from prompt and create a DES key.
774 * @param key key to convert to
775 * @param prompt prompt to display user
776 * @param verify prompt twice.
778 * @return 1 on success, non 1 on failure.
782 DES_read_password(DES_cblock
*key
, char *prompt
, int verify
)
787 ret
= UI_UTIL_read_pw_string(buf
, sizeof(buf
) - 1, prompt
, verify
);
789 DES_string_to_key(buf
, key
);
801 DES_cblock k
= "\x01\x02\x04\x08\x10\x20\x40\x80", k2
;
802 uint32_t u
[2] = { 1, 0 };
807 if (u
[0] != 1 || u
[1] != 0)
812 if (memcmp(k
, k2
, 8) != 0)
818 * A portable, public domain, version of the Data Encryption Standard.
820 * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
821 * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
822 * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
823 * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
824 * for humouring me on.
826 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
827 * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
830 static uint32_t SP1
[64] = {
831 0x01010400L
, 0x00000000L
, 0x00010000L
, 0x01010404L
,
832 0x01010004L
, 0x00010404L
, 0x00000004L
, 0x00010000L
,
833 0x00000400L
, 0x01010400L
, 0x01010404L
, 0x00000400L
,
834 0x01000404L
, 0x01010004L
, 0x01000000L
, 0x00000004L
,
835 0x00000404L
, 0x01000400L
, 0x01000400L
, 0x00010400L
,
836 0x00010400L
, 0x01010000L
, 0x01010000L
, 0x01000404L
,
837 0x00010004L
, 0x01000004L
, 0x01000004L
, 0x00010004L
,
838 0x00000000L
, 0x00000404L
, 0x00010404L
, 0x01000000L
,
839 0x00010000L
, 0x01010404L
, 0x00000004L
, 0x01010000L
,
840 0x01010400L
, 0x01000000L
, 0x01000000L
, 0x00000400L
,
841 0x01010004L
, 0x00010000L
, 0x00010400L
, 0x01000004L
,
842 0x00000400L
, 0x00000004L
, 0x01000404L
, 0x00010404L
,
843 0x01010404L
, 0x00010004L
, 0x01010000L
, 0x01000404L
,
844 0x01000004L
, 0x00000404L
, 0x00010404L
, 0x01010400L
,
845 0x00000404L
, 0x01000400L
, 0x01000400L
, 0x00000000L
,
846 0x00010004L
, 0x00010400L
, 0x00000000L
, 0x01010004L
};
848 static uint32_t SP2
[64] = {
849 0x80108020L
, 0x80008000L
, 0x00008000L
, 0x00108020L
,
850 0x00100000L
, 0x00000020L
, 0x80100020L
, 0x80008020L
,
851 0x80000020L
, 0x80108020L
, 0x80108000L
, 0x80000000L
,
852 0x80008000L
, 0x00100000L
, 0x00000020L
, 0x80100020L
,
853 0x00108000L
, 0x00100020L
, 0x80008020L
, 0x00000000L
,
854 0x80000000L
, 0x00008000L
, 0x00108020L
, 0x80100000L
,
855 0x00100020L
, 0x80000020L
, 0x00000000L
, 0x00108000L
,
856 0x00008020L
, 0x80108000L
, 0x80100000L
, 0x00008020L
,
857 0x00000000L
, 0x00108020L
, 0x80100020L
, 0x00100000L
,
858 0x80008020L
, 0x80100000L
, 0x80108000L
, 0x00008000L
,
859 0x80100000L
, 0x80008000L
, 0x00000020L
, 0x80108020L
,
860 0x00108020L
, 0x00000020L
, 0x00008000L
, 0x80000000L
,
861 0x00008020L
, 0x80108000L
, 0x00100000L
, 0x80000020L
,
862 0x00100020L
, 0x80008020L
, 0x80000020L
, 0x00100020L
,
863 0x00108000L
, 0x00000000L
, 0x80008000L
, 0x00008020L
,
864 0x80000000L
, 0x80100020L
, 0x80108020L
, 0x00108000L
};
866 static uint32_t SP3
[64] = {
867 0x00000208L
, 0x08020200L
, 0x00000000L
, 0x08020008L
,
868 0x08000200L
, 0x00000000L
, 0x00020208L
, 0x08000200L
,
869 0x00020008L
, 0x08000008L
, 0x08000008L
, 0x00020000L
,
870 0x08020208L
, 0x00020008L
, 0x08020000L
, 0x00000208L
,
871 0x08000000L
, 0x00000008L
, 0x08020200L
, 0x00000200L
,
872 0x00020200L
, 0x08020000L
, 0x08020008L
, 0x00020208L
,
873 0x08000208L
, 0x00020200L
, 0x00020000L
, 0x08000208L
,
874 0x00000008L
, 0x08020208L
, 0x00000200L
, 0x08000000L
,
875 0x08020200L
, 0x08000000L
, 0x00020008L
, 0x00000208L
,
876 0x00020000L
, 0x08020200L
, 0x08000200L
, 0x00000000L
,
877 0x00000200L
, 0x00020008L
, 0x08020208L
, 0x08000200L
,
878 0x08000008L
, 0x00000200L
, 0x00000000L
, 0x08020008L
,
879 0x08000208L
, 0x00020000L
, 0x08000000L
, 0x08020208L
,
880 0x00000008L
, 0x00020208L
, 0x00020200L
, 0x08000008L
,
881 0x08020000L
, 0x08000208L
, 0x00000208L
, 0x08020000L
,
882 0x00020208L
, 0x00000008L
, 0x08020008L
, 0x00020200L
};
884 static uint32_t SP4
[64] = {
885 0x00802001L
, 0x00002081L
, 0x00002081L
, 0x00000080L
,
886 0x00802080L
, 0x00800081L
, 0x00800001L
, 0x00002001L
,
887 0x00000000L
, 0x00802000L
, 0x00802000L
, 0x00802081L
,
888 0x00000081L
, 0x00000000L
, 0x00800080L
, 0x00800001L
,
889 0x00000001L
, 0x00002000L
, 0x00800000L
, 0x00802001L
,
890 0x00000080L
, 0x00800000L
, 0x00002001L
, 0x00002080L
,
891 0x00800081L
, 0x00000001L
, 0x00002080L
, 0x00800080L
,
892 0x00002000L
, 0x00802080L
, 0x00802081L
, 0x00000081L
,
893 0x00800080L
, 0x00800001L
, 0x00802000L
, 0x00802081L
,
894 0x00000081L
, 0x00000000L
, 0x00000000L
, 0x00802000L
,
895 0x00002080L
, 0x00800080L
, 0x00800081L
, 0x00000001L
,
896 0x00802001L
, 0x00002081L
, 0x00002081L
, 0x00000080L
,
897 0x00802081L
, 0x00000081L
, 0x00000001L
, 0x00002000L
,
898 0x00800001L
, 0x00002001L
, 0x00802080L
, 0x00800081L
,
899 0x00002001L
, 0x00002080L
, 0x00800000L
, 0x00802001L
,
900 0x00000080L
, 0x00800000L
, 0x00002000L
, 0x00802080L
};
902 static uint32_t SP5
[64] = {
903 0x00000100L
, 0x02080100L
, 0x02080000L
, 0x42000100L
,
904 0x00080000L
, 0x00000100L
, 0x40000000L
, 0x02080000L
,
905 0x40080100L
, 0x00080000L
, 0x02000100L
, 0x40080100L
,
906 0x42000100L
, 0x42080000L
, 0x00080100L
, 0x40000000L
,
907 0x02000000L
, 0x40080000L
, 0x40080000L
, 0x00000000L
,
908 0x40000100L
, 0x42080100L
, 0x42080100L
, 0x02000100L
,
909 0x42080000L
, 0x40000100L
, 0x00000000L
, 0x42000000L
,
910 0x02080100L
, 0x02000000L
, 0x42000000L
, 0x00080100L
,
911 0x00080000L
, 0x42000100L
, 0x00000100L
, 0x02000000L
,
912 0x40000000L
, 0x02080000L
, 0x42000100L
, 0x40080100L
,
913 0x02000100L
, 0x40000000L
, 0x42080000L
, 0x02080100L
,
914 0x40080100L
, 0x00000100L
, 0x02000000L
, 0x42080000L
,
915 0x42080100L
, 0x00080100L
, 0x42000000L
, 0x42080100L
,
916 0x02080000L
, 0x00000000L
, 0x40080000L
, 0x42000000L
,
917 0x00080100L
, 0x02000100L
, 0x40000100L
, 0x00080000L
,
918 0x00000000L
, 0x40080000L
, 0x02080100L
, 0x40000100L
};
920 static uint32_t SP6
[64] = {
921 0x20000010L
, 0x20400000L
, 0x00004000L
, 0x20404010L
,
922 0x20400000L
, 0x00000010L
, 0x20404010L
, 0x00400000L
,
923 0x20004000L
, 0x00404010L
, 0x00400000L
, 0x20000010L
,
924 0x00400010L
, 0x20004000L
, 0x20000000L
, 0x00004010L
,
925 0x00000000L
, 0x00400010L
, 0x20004010L
, 0x00004000L
,
926 0x00404000L
, 0x20004010L
, 0x00000010L
, 0x20400010L
,
927 0x20400010L
, 0x00000000L
, 0x00404010L
, 0x20404000L
,
928 0x00004010L
, 0x00404000L
, 0x20404000L
, 0x20000000L
,
929 0x20004000L
, 0x00000010L
, 0x20400010L
, 0x00404000L
,
930 0x20404010L
, 0x00400000L
, 0x00004010L
, 0x20000010L
,
931 0x00400000L
, 0x20004000L
, 0x20000000L
, 0x00004010L
,
932 0x20000010L
, 0x20404010L
, 0x00404000L
, 0x20400000L
,
933 0x00404010L
, 0x20404000L
, 0x00000000L
, 0x20400010L
,
934 0x00000010L
, 0x00004000L
, 0x20400000L
, 0x00404010L
,
935 0x00004000L
, 0x00400010L
, 0x20004010L
, 0x00000000L
,
936 0x20404000L
, 0x20000000L
, 0x00400010L
, 0x20004010L
};
938 static uint32_t SP7
[64] = {
939 0x00200000L
, 0x04200002L
, 0x04000802L
, 0x00000000L
,
940 0x00000800L
, 0x04000802L
, 0x00200802L
, 0x04200800L
,
941 0x04200802L
, 0x00200000L
, 0x00000000L
, 0x04000002L
,
942 0x00000002L
, 0x04000000L
, 0x04200002L
, 0x00000802L
,
943 0x04000800L
, 0x00200802L
, 0x00200002L
, 0x04000800L
,
944 0x04000002L
, 0x04200000L
, 0x04200800L
, 0x00200002L
,
945 0x04200000L
, 0x00000800L
, 0x00000802L
, 0x04200802L
,
946 0x00200800L
, 0x00000002L
, 0x04000000L
, 0x00200800L
,
947 0x04000000L
, 0x00200800L
, 0x00200000L
, 0x04000802L
,
948 0x04000802L
, 0x04200002L
, 0x04200002L
, 0x00000002L
,
949 0x00200002L
, 0x04000000L
, 0x04000800L
, 0x00200000L
,
950 0x04200800L
, 0x00000802L
, 0x00200802L
, 0x04200800L
,
951 0x00000802L
, 0x04000002L
, 0x04200802L
, 0x04200000L
,
952 0x00200800L
, 0x00000000L
, 0x00000002L
, 0x04200802L
,
953 0x00000000L
, 0x00200802L
, 0x04200000L
, 0x00000800L
,
954 0x04000002L
, 0x04000800L
, 0x00000800L
, 0x00200002L
};
956 static uint32_t SP8
[64] = {
957 0x10001040L
, 0x00001000L
, 0x00040000L
, 0x10041040L
,
958 0x10000000L
, 0x10001040L
, 0x00000040L
, 0x10000000L
,
959 0x00040040L
, 0x10040000L
, 0x10041040L
, 0x00041000L
,
960 0x10041000L
, 0x00041040L
, 0x00001000L
, 0x00000040L
,
961 0x10040000L
, 0x10000040L
, 0x10001000L
, 0x00001040L
,
962 0x00041000L
, 0x00040040L
, 0x10040040L
, 0x10041000L
,
963 0x00001040L
, 0x00000000L
, 0x00000000L
, 0x10040040L
,
964 0x10000040L
, 0x10001000L
, 0x00041040L
, 0x00040000L
,
965 0x00041040L
, 0x00040000L
, 0x10041000L
, 0x00001000L
,
966 0x00000040L
, 0x10040040L
, 0x00001000L
, 0x00041040L
,
967 0x10001000L
, 0x00000040L
, 0x10000040L
, 0x10040000L
,
968 0x10040040L
, 0x10000000L
, 0x00040000L
, 0x10001040L
,
969 0x00000000L
, 0x10041040L
, 0x00040040L
, 0x10000040L
,
970 0x10040000L
, 0x10001000L
, 0x10001040L
, 0x00000000L
,
971 0x10041040L
, 0x00041000L
, 0x00041000L
, 0x00001040L
,
972 0x00001040L
, 0x00040040L
, 0x10000000L
, 0x10041000L
};
979 work
= ((v
[0] >> 4) ^ v
[1]) & 0x0f0f0f0fL
;
982 work
= ((v
[0] >> 16) ^ v
[1]) & 0x0000ffffL
;
984 v
[0] ^= (work
<< 16);
985 work
= ((v
[1] >> 2) ^ v
[0]) & 0x33333333L
;
988 work
= ((v
[1] >> 8) ^ v
[0]) & 0x00ff00ffL
;
991 v
[1] = ((v
[1] << 1) | ((v
[1] >> 31) & 1L)) & 0xffffffffL
;
992 work
= (v
[0] ^ v
[1]) & 0xaaaaaaaaL
;
995 v
[0] = ((v
[0] << 1) | ((v
[0] >> 31) & 1L)) & 0xffffffffL
;
1003 v
[0] = (v
[0] << 31) | (v
[0] >> 1);
1004 work
= (v
[1] ^ v
[0]) & 0xaaaaaaaaL
;
1007 v
[1] = (v
[1] << 31) | (v
[1] >> 1);
1008 work
= ((v
[1] >> 8) ^ v
[0]) & 0x00ff00ffL
;
1010 v
[1] ^= (work
<< 8);
1011 work
= ((v
[1] >> 2) ^ v
[0]) & 0x33333333L
;
1013 v
[1] ^= (work
<< 2);
1014 work
= ((v
[0] >> 16) ^ v
[1]) & 0x0000ffffL
;
1016 v
[0] ^= (work
<< 16);
1017 work
= ((v
[0] >> 4) ^ v
[1]) & 0x0f0f0f0fL
;
1019 v
[0] ^= (work
<< 4);
1023 desx(uint32_t block
[2], DES_key_schedule
*ks
, int encp
)
1026 uint32_t fval
, work
, right
, left
;
1035 for( round
= 0; round
< 8; round
++ ) {
1036 work
= (right
<< 28) | (right
>> 4);
1038 fval
= SP7
[ work
& 0x3fL
];
1039 fval
|= SP5
[(work
>> 8) & 0x3fL
];
1040 fval
|= SP3
[(work
>> 16) & 0x3fL
];
1041 fval
|= SP1
[(work
>> 24) & 0x3fL
];
1042 work
= right
^ *keys
++;
1043 fval
|= SP8
[ work
& 0x3fL
];
1044 fval
|= SP6
[(work
>> 8) & 0x3fL
];
1045 fval
|= SP4
[(work
>> 16) & 0x3fL
];
1046 fval
|= SP2
[(work
>> 24) & 0x3fL
];
1048 work
= (left
<< 28) | (left
>> 4);
1050 fval
= SP7
[ work
& 0x3fL
];
1051 fval
|= SP5
[(work
>> 8) & 0x3fL
];
1052 fval
|= SP3
[(work
>> 16) & 0x3fL
];
1053 fval
|= SP1
[(work
>> 24) & 0x3fL
];
1054 work
= left
^ *keys
++;
1055 fval
|= SP8
[ work
& 0x3fL
];
1056 fval
|= SP6
[(work
>> 8) & 0x3fL
];
1057 fval
|= SP4
[(work
>> 16) & 0x3fL
];
1058 fval
|= SP2
[(work
>> 24) & 0x3fL
];
1064 for( round
= 0; round
< 8; round
++ ) {
1065 work
= (right
<< 28) | (right
>> 4);
1067 fval
= SP7
[ work
& 0x3fL
];
1068 fval
|= SP5
[(work
>> 8) & 0x3fL
];
1069 fval
|= SP3
[(work
>> 16) & 0x3fL
];
1070 fval
|= SP1
[(work
>> 24) & 0x3fL
];
1071 work
= right
^ *keys
++;
1072 fval
|= SP8
[ work
& 0x3fL
];
1073 fval
|= SP6
[(work
>> 8) & 0x3fL
];
1074 fval
|= SP4
[(work
>> 16) & 0x3fL
];
1075 fval
|= SP2
[(work
>> 24) & 0x3fL
];
1077 work
= (left
<< 28) | (left
>> 4);
1080 fval
= SP7
[ work
& 0x3fL
];
1081 fval
|= SP5
[(work
>> 8) & 0x3fL
];
1082 fval
|= SP3
[(work
>> 16) & 0x3fL
];
1083 fval
|= SP1
[(work
>> 24) & 0x3fL
];
1084 work
= left
^ *keys
++;
1085 fval
|= SP8
[ work
& 0x3fL
];
1086 fval
|= SP6
[(work
>> 8) & 0x3fL
];
1087 fval
|= SP4
[(work
>> 16) & 0x3fL
];
1088 fval
|= SP2
[(work
>> 24) & 0x3fL
];