& copied into two pieces so that use of crypt() pulls in a crypt.o that contains only that one programmer interface -- this permits USA export of binaries that use crypt() for authentication purposes. morecrypt.c contains the other DES programmer interfaces commonly used.OPENBSD_2_0
@ -0,0 +1,8 @@ | |||
# $Id: Makefile.inc,v 1.1 1995/12/16 12:55:27 deraadt Exp $ | |||
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/crypt ${.CURDIR}/crypt | |||
SRCS+= crypt.c morecrypt.c | |||
MAN+= crypt.3 | |||
MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 |
@ -0,0 +1,237 @@ | |||
.\" FreeSec: libcrypt | |||
.\" | |||
.\" Copyright (c) 1994 David Burren | |||
.\" All rights reserved. | |||
.\" | |||
.\" Redistribution and use in source and binary forms, with or without | |||
.\" modification, are permitted provided that the following conditions | |||
.\" are met: | |||
.\" 1. Redistributions of source code must retain the above copyright | |||
.\" notice, this list of conditions and the following disclaimer. | |||
.\" 2. Redistributions in binary form must reproduce the above copyright | |||
.\" notice, this list of conditions and the following disclaimer in the | |||
.\" documentation and/or other materials provided with the distribution. | |||
.\" 4. Neither the name of the author nor the names of other contributors | |||
.\" may be used to endorse or promote products derived from this software | |||
.\" without specific prior written permission. | |||
.\" | |||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
.\" SUCH DAMAGE. | |||
.\" | |||
.\" $Id: crypt.3,v 1.1 1995/12/16 12:55:29 deraadt Exp $ | |||
.\" | |||
.\" Manual page, using -mandoc macros | |||
.\" | |||
.Dd March 9, 1994 | |||
.Dt CRYPT 3 | |||
.Os "FreeSec 1.0" | |||
.Sh NAME | |||
.Nm crypt , | |||
.Nm setkey , | |||
.Nm encrypt , | |||
.Nm des_setkey , | |||
.Nm des_cipher , | |||
.Nd DES encryption | |||
.Sh SYNOPSIS | |||
.Ft char | |||
.Fn *crypt "const char *key" "const char *setting" | |||
.Ft int | |||
.Fn setkey "char *key" | |||
.Ft int | |||
.Fn encrypt "char *block" "int flag" | |||
.Ft int | |||
.Fn des_setkey "const char *key" | |||
.Ft int | |||
.Fn des_cipher "const char *in" "char *out" "long salt" "int count" | |||
.Sh DESCRIPTION | |||
The | |||
.Fn crypt | |||
function performs password encryption, based on the | |||
.Tn NBS | |||
Data Encryption Standard (DES). | |||
Additional code has been added to deter key search attempts. | |||
The first argument to | |||
.Nm crypt | |||
is a | |||
.Dv null Ns -terminated | |||
string, typically a user's typed password. | |||
The second is in one of two forms: | |||
if it begins with an underscore (``_'') then an extended format is used | |||
in interpreting both the the key and the setting, as outlined below. | |||
.Ss Extended crypt: | |||
.Pp | |||
The | |||
.Ar key | |||
is divided into groups of 8 characters (the last group is null-padded) | |||
and the low-order 7 bits of each each character (56 bits per group) are | |||
used to form the DES key as follows: | |||
the first group of 56 bits becomes the initial DES key. | |||
For each additional group, the XOR of the encryption of the current DES | |||
key with itself and the group bits becomes the next DES key. | |||
.Pp | |||
The setting is a 9-character array consisting of an underscore followed | |||
by 4 bytes of iteration count and 4 bytes of salt. | |||
These are encoded as printable characters, 6 bits per character, | |||
least significant character first. | |||
The values 0 to 63 are encoded as ``./0-9A-Za-z''. | |||
This allows 24 bits for both | |||
.Fa count | |||
and | |||
.Fa salt . | |||
.Ss "Traditional" crypt: | |||
.Pp | |||
The first 8 bytes of the key are null-padded, and the low-order 7 bits of | |||
each character is used to form the 56-bit | |||
.Tn DES | |||
key. | |||
.Pp | |||
The setting is a 2-character array of the ASCII-encoded salt. | |||
Thus only 12 bits of | |||
.Fa salt | |||
are used. | |||
.Fa count | |||
is set to 25. | |||
.Ss Algorithm: | |||
.Pp | |||
The | |||
.Fa salt | |||
introduces disorder in the | |||
.Tn DES | |||
algorithm in one of 16777216 or 4096 possible ways | |||
(ie. with 24 or 12 bits: if bit | |||
.Em i | |||
of the | |||
.Ar salt | |||
is set, then bits | |||
.Em i | |||
and | |||
.Em i+24 | |||
are swapped in the | |||
.Tn DES | |||
E-box output). | |||
.Pp | |||
The DES key is used to encrypt a 64-bit constant using | |||
.Ar count | |||
iterations of | |||
.Tn DES . | |||
The value returned is a | |||
.Dv null Ns -terminated | |||
string, 20 or 13 bytes (plus null) in length, consisting of the | |||
.Ar setting | |||
followed by the encoded 64-bit encryption. | |||
.Pp | |||
The functions, | |||
.Fn encrypt , | |||
.Fn setkey , | |||
.Fn des_setkey | |||
and | |||
.Fn des_cipher | |||
provide access to the | |||
.Tn DES | |||
algorithm itself. | |||
.Fn setkey | |||
is passed a 64-byte array of binary values (numeric 0 or 1). | |||
A 56-bit key is extracted from this array by dividing the | |||
array into groups of 8, and ignoring the last bit in each group. | |||
That bit is reserved for a byte parity check by DES, but is ignored | |||
by these functions. | |||
.Pp | |||
The | |||
.Fa block | |||
argument to | |||
.Fn encrypt | |||
is also a 64-byte array of binary values. | |||
If the value of | |||
.Fa flag | |||
is 0, | |||
.Fa block | |||
is encrypted otherwise it is decrypted. | |||
The result is returned in the original array | |||
.Fa block | |||
after using the key specified by | |||
.Fn setkey | |||
to process it. | |||
.Pp | |||
The argument to | |||
.Fn des_setkey | |||
is a character array of length 8. | |||
The least significant bit (the parity bit) in each character is ignored, | |||
and the remaining bits are concatenated to form a 56-bit key. | |||
The function | |||
.Fn des_cipher | |||
encrypts (or decrypts if | |||
.Fa count | |||
is negative) the 64-bits stored in the 8 characters at | |||
.Fa in | |||
using | |||
.Xr abs 3 | |||
of | |||
.Fa count | |||
iterations of | |||
.Tn DES | |||
and stores the 64-bit result in the 8 characters at | |||
.Fa out | |||
(which may be the same as | |||
.Fa in | |||
). | |||
The | |||
.Fa salt | |||
specifies perturbations to the | |||
.Tn DES | |||
E-box output as described above. | |||
.Pp | |||
The function | |||
.Fn crypt | |||
returns a pointer to the encrypted value on success, and NULL on failure. | |||
The functions | |||
.Fn setkey , | |||
.Fn encrypt , | |||
.Fn des_setkey , | |||
and | |||
.Fn des_cipher | |||
return 0 on success and 1 on failure. | |||
.Pp | |||
The | |||
.Fn crypt , | |||
.Fn setkey | |||
and | |||
.Fn des_setkey | |||
functions all manipulate the same key space. | |||
.Sh SEE ALSO | |||
.Xr login 1 , | |||
.Xr passwd 1 , | |||
.Xr getpass 3 , | |||
.Xr passwd 5 | |||
.Sh BUGS | |||
The | |||
.Fn crypt | |||
function returns a pointer to static data, and subsequent calls to | |||
.Fn crypt | |||
will modify the same object. | |||
.Sh HISTORY | |||
A rotor-based | |||
.Fn crypt | |||
function appeared in | |||
.At v6 . | |||
The current style | |||
.Fn crypt | |||
first appeared in | |||
.At v7 . | |||
.Pp | |||
This library (FreeSec 1.0) was developed outside the United States of America | |||
as an unencumbered replacement for the U.S.-only libcrypt encryption | |||
library. | |||
Programs linked against the crypt() interface may be exported from the U.S.A. | |||
only if they use crypt() solely for authentication purposes and avoid use of | |||
the other programmer interfaces listed above. | |||
.Sh AUTHOR | |||
David Burren <davidb@werj.com.au> |
@ -0,0 +1,715 @@ | |||
/* $Id: crypt.c,v 1.1 1995/12/16 12:55:30 deraadt Exp $ */ | |||
/* | |||
* FreeSec: libcrypt | |||
* | |||
* Copyright (c) 1994 David Burren | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 4. Neither the name of the author nor the names of other contributors | |||
* may be used to endorse or promote products derived from this software | |||
* without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* | |||
* | |||
* This is an original implementation of the DES and the crypt(3) interfaces | |||
* by David Burren <davidb@werj.com.au>. | |||
* | |||
* An excellent reference on the underlying algorithm (and related | |||
* algorithms) is: | |||
* | |||
* B. Schneier, Applied Cryptography: protocols, algorithms, | |||
* and source code in C, John Wiley & Sons, 1994. | |||
* | |||
* Note that in that book's description of DES the lookups for the initial, | |||
* pbox, and final permutations are inverted (this has been brought to the | |||
* attention of the author). A list of errata for this book has been | |||
* posted to the sci.crypt newsgroup by the author and is available for FTP. | |||
* | |||
* ARCHITECTURE ASSUMPTIONS: | |||
* This code assumes that u_longs are 32 bits. It will probably not | |||
* operate on 64-bit machines without modifications. | |||
* It is assumed that the 8-byte arrays passed by reference can be | |||
* addressed as arrays of u_longs (ie. the CPU is not picky about | |||
* alignment). | |||
* | |||
* NOTE: | |||
* This file has a static version of des_setkey() so that crypt.o exports | |||
* only the crypt() interface. This is required to make binaries linked | |||
* against crypt.o exportable or re-exportable from the USA. | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/param.h> | |||
#include <pwd.h> | |||
#ifdef DEBUG | |||
# include <stdio.h> | |||
#endif | |||
static u_char IP[64] = { | |||
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, | |||
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, | |||
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, | |||
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 | |||
}; | |||
static u_char inv_key_perm[64]; | |||
static u_char u_key_perm[56]; | |||
static u_char key_perm[56] = { | |||
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, | |||
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, | |||
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, | |||
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 | |||
}; | |||
static u_char key_shifts[16] = { | |||
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 | |||
}; | |||
static u_char inv_comp_perm[56]; | |||
static u_char comp_perm[48] = { | |||
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, | |||
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, | |||
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, | |||
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 | |||
}; | |||
/* | |||
* No E box is used, as it's replaced by some ANDs, shifts, and ORs. | |||
*/ | |||
static u_char u_sbox[8][64]; | |||
static u_char sbox[8][64] = { | |||
{ | |||
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, | |||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, | |||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, | |||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 | |||
}, | |||
{ | |||
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, | |||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, | |||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, | |||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 | |||
}, | |||
{ | |||
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, | |||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, | |||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, | |||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 | |||
}, | |||
{ | |||
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, | |||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, | |||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, | |||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 | |||
}, | |||
{ | |||
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, | |||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, | |||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, | |||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 | |||
}, | |||
{ | |||
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, | |||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, | |||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, | |||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 | |||
}, | |||
{ | |||
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, | |||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, | |||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, | |||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 | |||
}, | |||
{ | |||
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, | |||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, | |||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, | |||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 | |||
} | |||
}; | |||
static u_char un_pbox[32]; | |||
static u_char pbox[32] = { | |||
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, | |||
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 | |||
}; | |||
static u_int32_t bits32[32] = | |||
{ | |||
0x80000000, 0x40000000, 0x20000000, 0x10000000, | |||
0x08000000, 0x04000000, 0x02000000, 0x01000000, | |||
0x00800000, 0x00400000, 0x00200000, 0x00100000, | |||
0x00080000, 0x00040000, 0x00020000, 0x00010000, | |||
0x00008000, 0x00004000, 0x00002000, 0x00001000, | |||
0x00000800, 0x00000400, 0x00000200, 0x00000100, | |||
0x00000080, 0x00000040, 0x00000020, 0x00000010, | |||
0x00000008, 0x00000004, 0x00000002, 0x00000001 | |||
}; | |||
static u_char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; | |||
static u_int32_t saltbits; | |||
static int32_t old_salt; | |||
static u_int32_t *bits28, *bits24; | |||
static u_char init_perm[64], final_perm[64]; | |||
static u_int32_t en_keysl[16], en_keysr[16]; | |||
static u_int32_t de_keysl[16], de_keysr[16]; | |||
static int des_initialised = 0; | |||
static u_char m_sbox[4][4096]; | |||
static u_int32_t psbox[4][256]; | |||
static u_int32_t ip_maskl[8][256], ip_maskr[8][256]; | |||
static u_int32_t fp_maskl[8][256], fp_maskr[8][256]; | |||
static u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128]; | |||
static u_int32_t comp_maskl[8][128], comp_maskr[8][128]; | |||
static u_int32_t old_rawkey0, old_rawkey1; | |||
static u_char ascii64[] = | |||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |||
/* 0000000000111111111122222222223333333333444444444455555555556666 */ | |||
/* 0123456789012345678901234567890123456789012345678901234567890123 */ | |||
static inline int | |||
ascii_to_bin(ch) | |||
char ch; | |||
{ | |||
if (ch > 'z') | |||
return(0); | |||
if (ch >= 'a') | |||
return(ch - 'a' + 38); | |||
if (ch > 'Z') | |||
return(0); | |||
if (ch >= 'A') | |||
return(ch - 'A' + 12); | |||
if (ch > '9') | |||
return(0); | |||
if (ch >= '.') | |||
return(ch - '.'); | |||
return(0); | |||
} | |||
static void | |||
des_init() | |||
{ | |||
int i, j, b, k, inbit, obit; | |||
u_int32_t *p, *il, *ir, *fl, *fr; | |||
old_rawkey0 = old_rawkey1 = 0; | |||
saltbits = 0; | |||
old_salt = 0; | |||
bits24 = (bits28 = bits32 + 4) + 4; | |||
/* | |||
* Invert the S-boxes, reordering the input bits. | |||
*/ | |||
for (i = 0; i < 8; i++) | |||
for (j = 0; j < 64; j++) { | |||
b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); | |||
u_sbox[i][j] = sbox[i][b]; | |||
} | |||
/* | |||
* Convert the inverted S-boxes into 4 arrays of 8 bits. | |||
* Each will handle 12 bits of the S-box input. | |||
*/ | |||
for (b = 0; b < 4; b++) | |||
for (i = 0; i < 64; i++) | |||
for (j = 0; j < 64; j++) | |||
m_sbox[b][(i << 6) | j] = | |||
(u_sbox[(b << 1)][i] << 4) | | |||
u_sbox[(b << 1) + 1][j]; | |||
/* | |||
* Set up the initial & final permutations into a useful form, and | |||
* initialise the inverted key permutation. | |||
*/ | |||
for (i = 0; i < 64; i++) { | |||
init_perm[final_perm[i] = IP[i] - 1] = i; | |||
inv_key_perm[i] = 255; | |||
} | |||
/* | |||
* Invert the key permutation and initialise the inverted key | |||
* compression permutation. | |||
*/ | |||
for (i = 0; i < 56; i++) { | |||
u_key_perm[i] = key_perm[i] - 1; | |||
inv_key_perm[key_perm[i] - 1] = i; | |||
inv_comp_perm[i] = 255; | |||
} | |||
/* | |||
* Invert the key compression permutation. | |||
*/ | |||
for (i = 0; i < 48; i++) { | |||
inv_comp_perm[comp_perm[i] - 1] = i; | |||
} | |||
/* | |||
* Set up the OR-mask arrays for the initial and final permutations, | |||
* and for the key initial and compression permutations. | |||
*/ | |||
for (k = 0; k < 8; k++) { | |||
for (i = 0; i < 256; i++) { | |||
*(il = &ip_maskl[k][i]) = 0; | |||
*(ir = &ip_maskr[k][i]) = 0; | |||
*(fl = &fp_maskl[k][i]) = 0; | |||
*(fr = &fp_maskr[k][i]) = 0; | |||
for (j = 0; j < 8; j++) { | |||
inbit = 8 * k + j; | |||
if (i & bits8[j]) { | |||
if ((obit = init_perm[inbit]) < 32) | |||
*il |= bits32[obit]; | |||
else | |||
*ir |= bits32[obit-32]; | |||
if ((obit = final_perm[inbit]) < 32) | |||
*fl |= bits32[obit]; | |||
else | |||
*fr |= bits32[obit - 32]; | |||
} | |||
} | |||
} | |||
for (i = 0; i < 128; i++) { | |||
*(il = &key_perm_maskl[k][i]) = 0; | |||
*(ir = &key_perm_maskr[k][i]) = 0; | |||
for (j = 0; j < 7; j++) { | |||
inbit = 8 * k + j; | |||
if (i & bits8[j + 1]) { | |||
if ((obit = inv_key_perm[inbit]) == 255) | |||
continue; | |||
if (obit < 28) | |||
*il |= bits28[obit]; | |||
else | |||
*ir |= bits28[obit - 28]; | |||
} | |||
} | |||
*(il = &comp_maskl[k][i]) = 0; | |||
*(ir = &comp_maskr[k][i]) = 0; | |||
for (j = 0; j < 7; j++) { | |||
inbit = 7 * k + j; | |||
if (i & bits8[j + 1]) { | |||
if ((obit=inv_comp_perm[inbit]) == 255) | |||
continue; | |||
if (obit < 24) | |||
*il |= bits24[obit]; | |||
else | |||
*ir |= bits24[obit - 24]; | |||
} | |||
} | |||
} | |||
} | |||
/* | |||
* Invert the P-box permutation, and convert into OR-masks for | |||
* handling the output of the S-box arrays setup above. | |||
*/ | |||
for (i = 0; i < 32; i++) | |||
un_pbox[pbox[i] - 1] = i; | |||
for (b = 0; b < 4; b++) | |||
for (i = 0; i < 256; i++) { | |||
*(p = &psbox[b][i]) = 0; | |||
for (j = 0; j < 8; j++) { | |||
if (i & bits8[j]) | |||
*p |= bits32[un_pbox[8 * b + j]]; | |||
} | |||
} | |||
des_initialised = 1; | |||
} | |||
static void | |||
setup_salt(salt) | |||
int32_t salt; | |||
{ | |||
u_int32_t obit, saltbit; | |||
int i; | |||
if (salt == old_salt) | |||
return; | |||
old_salt = salt; | |||
saltbits = 0; | |||
saltbit = 1; | |||
obit = 0x800000; | |||
for (i = 0; i < 24; i++) { | |||
if (salt & saltbit) | |||
saltbits |= obit; | |||
saltbit <<= 1; | |||
obit >>= 1; | |||
} | |||
} | |||
static int | |||
des_setkey(key) | |||
const char *key; | |||
{ | |||
u_int32_t k0, k1, rawkey0, rawkey1; | |||
int shifts, i, b, round; | |||
if (!des_initialised) | |||
des_init(); | |||
rawkey0 = ntohl(*(u_int32_t *) key); | |||
rawkey1 = ntohl(*(u_int32_t *) (key + 4)); | |||
if ((rawkey0 | rawkey1) | |||
&& rawkey0 == old_rawkey0 | |||
&& rawkey1 == old_rawkey1) { | |||
/* | |||
* Already setup for this key. | |||
* This optimisation fails on a zero key (which is weak and | |||
* has bad parity anyway) in order to simplify the starting | |||
* conditions. | |||
*/ | |||
return(0); | |||
} | |||
old_rawkey0 = rawkey0; | |||
old_rawkey1 = rawkey1; | |||
/* | |||
* Do key permutation and split into two 28-bit subkeys. | |||
*/ | |||
k0 = key_perm_maskl[0][rawkey0 >> 25] | |||
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] | |||
| key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] | |||
| key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] | |||
| key_perm_maskl[4][rawkey1 >> 25] | |||
| key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] | |||
| key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] | |||
| key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; | |||
k1 = key_perm_maskr[0][rawkey0 >> 25] | |||
| key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] | |||
| key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] | |||
| key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] | |||
| key_perm_maskr[4][rawkey1 >> 25] | |||
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] | |||
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] | |||
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; | |||
/* | |||
* Rotate subkeys and do compression permutation. | |||
*/ | |||
shifts = 0; | |||
for (round = 0; round < 16; round++) { | |||
u_int32_t t0, t1; | |||
int bit; | |||
shifts += key_shifts[round]; | |||
t0 = (k0 << shifts) | (k0 >> (28 - shifts)); | |||
t1 = (k1 << shifts) | (k1 >> (28 - shifts)); | |||
de_keysl[15 - round] = | |||
en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] | |||
| comp_maskl[1][(t0 >> 14) & 0x7f] | |||
| comp_maskl[2][(t0 >> 7) & 0x7f] | |||
| comp_maskl[3][t0 & 0x7f] | |||
| comp_maskl[4][(t1 >> 21) & 0x7f] | |||
| comp_maskl[5][(t1 >> 14) & 0x7f] | |||
| comp_maskl[6][(t1 >> 7) & 0x7f] | |||
| comp_maskl[7][t1 & 0x7f]; | |||
de_keysr[15 - round] = | |||
en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f] | |||
| comp_maskr[1][(t0 >> 14) & 0x7f] | |||
| comp_maskr[2][(t0 >> 7) & 0x7f] | |||
| comp_maskr[3][t0 & 0x7f] | |||
| comp_maskr[4][(t1 >> 21) & 0x7f] | |||
| comp_maskr[5][(t1 >> 14) & 0x7f] | |||
| comp_maskr[6][(t1 >> 7) & 0x7f] | |||
| comp_maskr[7][t1 & 0x7f]; | |||
} | |||
return(0); | |||
} | |||
static int | |||
do_des(l_in, r_in, l_out, r_out, count) | |||
u_int32_t l_in, r_in, *l_out, *r_out; | |||
int count; | |||
{ | |||
/* | |||
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. | |||
*/ | |||
u_int32_t mask, rawl, rawr, l, r, *kl, *kr, *kl1, *kr1; | |||
u_int32_t f, r48l, r48r; | |||
int i, j, b, round; | |||
if (count == 0) { | |||
return(1); | |||
} else if (count > 0) { | |||
/* | |||
* Encrypting | |||
*/ | |||
kl1 = en_keysl; | |||
kr1 = en_keysr; | |||
} else { | |||
/* | |||
* Decrypting | |||
*/ | |||
count = -count; | |||
kl1 = de_keysl; | |||
kr1 = de_keysr; | |||
} | |||
/* | |||
* Do initial permutation (IP). | |||
*/ | |||
l = ip_maskl[0][l_in >> 24] | |||
| ip_maskl[1][(l_in >> 16) & 0xff] | |||
| ip_maskl[2][(l_in >> 8) & 0xff] | |||
| ip_maskl[3][l_in & 0xff] | |||
| ip_maskl[4][r_in >> 24] | |||
| ip_maskl[5][(r_in >> 16) & 0xff] | |||
| ip_maskl[6][(r_in >> 8) & 0xff] | |||
| ip_maskl[7][r_in & 0xff]; | |||
r = ip_maskr[0][l_in >> 24] | |||
| ip_maskr[1][(l_in >> 16) & 0xff] | |||
| ip_maskr[2][(l_in >> 8) & 0xff] | |||
| ip_maskr[3][l_in & 0xff] | |||
| ip_maskr[4][r_in >> 24] | |||
| ip_maskr[5][(r_in >> 16) & 0xff] | |||
| ip_maskr[6][(r_in >> 8) & 0xff] | |||
| ip_maskr[7][r_in & 0xff]; | |||
while (count--) { | |||
/* | |||
* Do each round. | |||
*/ | |||
kl = kl1; | |||
kr = kr1; | |||
round = 16; | |||
while (round--) { | |||
/* | |||
* Expand R to 48 bits (simulate the E-box). | |||
*/ | |||
r48l = ((r & 0x00000001) << 23) | |||
| ((r & 0xf8000000) >> 9) | |||
| ((r & 0x1f800000) >> 11) | |||
| ((r & 0x01f80000) >> 13) | |||
| ((r & 0x001f8000) >> 15); | |||
r48r = ((r & 0x0001f800) << 7) | |||
| ((r & 0x00001f80) << 5) | |||
| ((r & 0x000001f8) << 3) | |||
| ((r & 0x0000001f) << 1) | |||
| ((r & 0x80000000) >> 31); | |||
/* | |||
* Do salting for crypt() and friends, and | |||
* XOR with the permuted key. | |||
*/ | |||
f = (r48l ^ r48r) & saltbits; | |||
r48l ^= f ^ *kl++; | |||
r48r ^= f ^ *kr++; | |||
/* | |||
* Do sbox lookups (which shrink it back to 32 bits) | |||
* and do the pbox permutation at the same time. | |||
*/ | |||
f = psbox[0][m_sbox[0][r48l >> 12]] | |||
| psbox[1][m_sbox[1][r48l & 0xfff]] | |||
| psbox[2][m_sbox[2][r48r >> 12]] | |||
| psbox[3][m_sbox[3][r48r & 0xfff]]; | |||
/* | |||
* Now that we've permuted things, complete f(). | |||
*/ | |||
f ^= l; | |||
l = r; | |||
r = f; | |||
} | |||
r = l; | |||
l = f; | |||
} | |||
/* | |||
* Do final permutation (inverse of IP). | |||
*/ | |||
*l_out = fp_maskl[0][l >> 24] | |||
| fp_maskl[1][(l >> 16) & 0xff] | |||
| fp_maskl[2][(l >> 8) & 0xff] | |||
| fp_maskl[3][l & 0xff] | |||
| fp_maskl[4][r >> 24] | |||
| fp_maskl[5][(r >> 16) & 0xff] | |||
| fp_maskl[6][(r >> 8) & 0xff] | |||
| fp_maskl[7][r & 0xff]; | |||
*r_out = fp_maskr[0][l >> 24] | |||
| fp_maskr[1][(l >> 16) & 0xff] | |||
| fp_maskr[2][(l >> 8) & 0xff] | |||
| fp_maskr[3][l & 0xff] | |||
| fp_maskr[4][r >> 24] | |||
| fp_maskr[5][(r >> 16) & 0xff] | |||
| fp_maskr[6][(r >> 8) & 0xff] | |||
| fp_maskr[7][r & 0xff]; | |||
return(0); | |||
} | |||
static int | |||
des_cipher(in, out, salt, count) | |||
const char *in; | |||
char *out; | |||
int32_t salt; | |||
int count; | |||
{ | |||
u_int32_t l_out, r_out, rawl, rawr; | |||
u_int32_t x[2]; | |||
int retval; | |||
if (!des_initialised) | |||
des_init(); | |||
setup_salt(salt); | |||
#if 0 | |||
rawl = ntohl(*((u_int32_t *) in)++); | |||
rawr = ntohl(*((u_int32_t *) in)); | |||
#else | |||
memcpy(x, in, sizeof x); | |||
rawl = ntohl(x[0]); | |||
rawr = ntohl(x[1]); | |||
#endif | |||
retval = do_des(rawl, rawr, &l_out, &r_out, count); | |||
#if 0 | |||
*((u_int32_t *) out)++ = htonl(l_out); | |||
*((u_int32_t *) out) = htonl(r_out); | |||
#else | |||
x[0] = htonl(l_out); | |||
x[1] = htonl(r_out); | |||
memcpy(out, x, sizeof x); | |||
#endif | |||
return(retval); | |||
} | |||
char * | |||
crypt(key, setting) | |||
char *key; | |||
char *setting; | |||
{ | |||
int i; | |||
u_int32_t count, salt, l, r0, r1, keybuf[2]; | |||
u_char *p, *q; | |||
static u_char output[21]; | |||
if (!des_initialised) | |||
des_init(); | |||
/* | |||
* Copy the key, shifting each character up by one bit | |||
* and padding with zeros. | |||
*/ | |||
q = (u_char *) keybuf; | |||
while (q - (u_char *) keybuf - 8) { | |||
if (*q++ = *key << 1) | |||
key++; | |||
} | |||
if (des_setkey((u_char *) keybuf)) | |||
return(NULL); | |||
if (*setting == _PASSWORD_EFMT1) { | |||
/* | |||
* "new"-style: | |||
* setting - underscore, 4 bytes of count, 4 bytes of salt | |||
* key - unlimited characters | |||
*/ | |||
for (i = 1, count = 0; i < 5; i++) | |||
count |= ascii_to_bin(setting[i]) << (i - 1) * 6; | |||
for (i = 5, salt = 0; i < 9; i++) | |||
salt |= ascii_to_bin(setting[i]) << (i - 5) * 6; | |||
while (*key) { | |||
/* | |||
* Encrypt the key with itself. | |||
*/ | |||
if (des_cipher((u_char*)keybuf, (u_char*)keybuf, 0, 1)) | |||
return(NULL); | |||
/* | |||
* And XOR with the next 8 characters of the key. | |||
*/ | |||
q = (u_char *) keybuf; | |||
while (q - (u_char *) keybuf - 8 && *key) | |||
*q++ ^= *key++ << 1; | |||
if (des_setkey((u_char *) keybuf)) | |||
return(NULL); | |||
} | |||
strncpy(output, setting, 9); | |||
/* | |||
* Double check that we weren't given a short setting. | |||
* If we were, the above code will probably have created | |||
* wierd values for count and salt, but we don't really care. | |||
* Just make sure the output string doesn't have an extra | |||
* NUL in it. | |||
*/ | |||
output[9] = '\0'; | |||
p = output + strlen(output); | |||
} else { | |||
/* | |||
* "old"-style: | |||
* setting - 2 bytes of salt | |||
* key - up to 8 characters | |||
*/ | |||
count = 25; | |||
salt = (ascii_to_bin(setting[1]) << 6) | |||
| ascii_to_bin(setting[0]); | |||
output[0] = setting[0]; | |||
/* | |||
* If the encrypted password that the salt was extracted from | |||
* is only 1 character long, the salt will be corrupted. We | |||
* need to ensure that the output string doesn't have an extra | |||
* NUL in it! | |||
*/ | |||
output[1] = setting[1] ? setting[1] : output[0]; | |||
p = output + 2; | |||
} | |||
setup_salt(salt); | |||
/* | |||
* Do it. | |||
*/ | |||
if (do_des(0, 0, &r0, &r1, count)) | |||
return(NULL); | |||
/* | |||
* Now encode the result... | |||
*/ | |||
l = (r0 >> 8); | |||
*p++ = ascii64[(l >> 18) & 0x3f]; | |||
*p++ = ascii64[(l >> 12) & 0x3f]; | |||
*p++ = ascii64[(l >> 6) & 0x3f]; | |||
*p++ = ascii64[l & 0x3f]; | |||
l = (r0 << 16) | ((r1 >> 16) & 0xffff); | |||
*p++ = ascii64[(l >> 18) & 0x3f]; | |||
*p++ = ascii64[(l >> 12) & 0x3f]; | |||
*p++ = ascii64[(l >> 6) & 0x3f]; | |||
*p++ = ascii64[l & 0x3f]; | |||
l = r1 << 2; | |||
*p++ = ascii64[(l >> 12) & 0x3f]; | |||
*p++ = ascii64[(l >> 6) & 0x3f]; | |||
*p++ = ascii64[l & 0x3f]; | |||
*p = 0; | |||
return(output); | |||
} |
@ -0,0 +1,338 @@ | |||
/* $Id: morecrypt.c,v 1.1 1995/12/16 12:55:31 deraadt Exp $ */ | |||
/* | |||
* FreeSec: libcrypt | |||
* | |||
* Copyright (c) 1994 David Burren | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 4. Neither the name of the author nor the names of other contributors | |||
* may be used to endorse or promote products derived from this software | |||
* without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* | |||
* | |||
* This is an original implementation of the DES and the crypt(3) interfaces | |||
* by David Burren <davidb@werj.com.au>. | |||
* | |||
* An excellent reference on the underlying algorithm (and related | |||
* algorithms) is: | |||
* | |||
* B. Schneier, Applied Cryptography: protocols, algorithms, | |||
* and source code in C, John Wiley & Sons, 1994. | |||
* | |||
* Note that in that book's description of DES the lookups for the initial, | |||
* pbox, and final permutations are inverted (this has been brought to the | |||
* attention of the author). A list of errata for this book has been | |||
* posted to the sci.crypt newsgroup by the author and is available for FTP. | |||
* | |||
* ARCHITECTURE ASSUMPTIONS: | |||
* This code assumes that u_longs are 32 bits. It will probably not | |||
* operate on 64-bit machines without modifications. | |||
* It is assumed that the 8-byte arrays passed by reference can be | |||
* addressed as arrays of u_longs (ie. the CPU is not picky about | |||
* alignment). | |||
* | |||
* NOTE: | |||
* This file must copy certain chunks of crypt.c for legal reasons. | |||
* crypt.c can only export the interface crypt(), to make binaries | |||
* exportable from the USA. Hence, to also have the other crypto interfaces | |||
* available we have to copy pieces... | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/param.h> | |||
#include <pwd.h> | |||
#ifdef DEBUG | |||
# include <stdio.h> | |||
#endif | |||
static u_char IP[64] = { | |||
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, | |||
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, | |||
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, | |||
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 | |||
}; | |||
static u_char inv_key_perm[64]; | |||
static u_char u_key_perm[56]; | |||
static u_char key_perm[56] = { | |||
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, | |||
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, | |||
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, | |||
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 | |||
}; | |||
static u_char key_shifts[16] = { | |||
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 | |||
}; | |||
static u_char inv_comp_perm[56]; | |||
static u_char comp_perm[48] = { | |||
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, | |||
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, | |||
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, | |||
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 | |||
}; | |||
/* | |||
* No E box is used, as it's replaced by some ANDs, shifts, and ORs. | |||
*/ | |||
static u_char u_sbox[8][64]; | |||
static u_char sbox[8][64] = { | |||
{ | |||
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, | |||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, | |||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, | |||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 | |||
}, | |||
{ | |||
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, | |||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, | |||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, | |||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 | |||
}, | |||
{ | |||
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, | |||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, | |||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, | |||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 | |||
}, | |||
{ | |||
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, | |||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, | |||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, | |||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 | |||
}, | |||
{ | |||
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, | |||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, | |||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, | |||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 | |||
}, | |||
{ | |||
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, | |||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, | |||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, | |||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 | |||
}, | |||
{ | |||
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, | |||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, | |||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, | |||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 | |||
}, | |||
{ | |||
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, | |||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, | |||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, | |||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 | |||
} | |||
}; | |||
static u_char un_pbox[32]; | |||
static u_char pbox[32] = { | |||
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, | |||
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 | |||
}; | |||
static u_int32_t bits32[32] = | |||
{ | |||
0x80000000, 0x40000000, 0x20000000, 0x10000000, | |||
0x08000000, 0x04000000, 0x02000000, 0x01000000, | |||
0x00800000, 0x00400000, 0x00200000, 0x00100000, | |||
0x00080000, 0x00040000, 0x00020000, 0x00010000, | |||
0x00008000, 0x00004000, 0x00002000, 0x00001000, | |||
0x00000800, 0x00000400, 0x00000200, 0x00000100, | |||
0x00000080, 0x00000040, 0x00000020, 0x00000010, | |||
0x00000008, 0x00000004, 0x00000002, 0x00000001 | |||
}; | |||
static u_char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; | |||
static u_int32_t saltbits; | |||
static int32_t old_salt; | |||
static u_int32_t *bits28, *bits24; | |||
static u_char init_perm[64], final_perm[64]; | |||
static u_int32_t en_keysl[16], en_keysr[16]; | |||
static u_int32_t de_keysl[16], de_keysr[16]; | |||
static int des_initialised = 0; | |||
static u_char m_sbox[4][4096]; | |||
static u_int32_t psbox[4][256]; | |||
static u_int32_t ip_maskl[8][256], ip_maskr[8][256]; | |||
static u_int32_t fp_maskl[8][256], fp_maskr[8][256]; | |||
static u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128]; | |||
static u_int32_t comp_maskl[8][128], comp_maskr[8][128]; | |||
static u_int32_t old_rawkey0, old_rawkey1; | |||
static u_char ascii64[] = | |||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |||
/* 0000000000111111111122222222223333333333444444444455555555556666 */ | |||
/* 0123456789012345678901234567890123456789012345678901234567890123 */ | |||
static inline int | |||
ascii_to_bin(ch) | |||
char ch; | |||
{ | |||
if (ch > 'z') | |||
return(0); | |||
if (ch >= 'a') | |||
return(ch - 'a' + 38); | |||
if (ch > 'Z') | |||
return(0); | |||
if (ch >= 'A') | |||
return(ch - 'A' + 12); | |||
if (ch > '9') | |||
return(0); | |||
if (ch >= '.') | |||
return(ch - '.'); | |||
return(0); | |||
} | |||
int | |||
des_setkey(key) | |||
const char *key; | |||
{ | |||
u_int32_t k0, k1, rawkey0, rawkey1; | |||
int shifts, i, b, round; | |||
if (!des_initialised) | |||
des_init(); | |||
rawkey0 = ntohl(*(u_int32_t *) key); | |||
rawkey1 = ntohl(*(u_int32_t *) (key + 4)); | |||
if ((rawkey0 | rawkey1) | |||
&& rawkey0 == old_rawkey0 | |||
&& rawkey1 == old_rawkey1) { | |||
/* | |||
* Already setup for this key. | |||
* This optimisation fails on a zero key (which is weak and | |||
* has bad parity anyway) in order to simplify the starting | |||
* conditions. | |||
*/ | |||
return(0); | |||
} | |||
old_rawkey0 = rawkey0; | |||
old_rawkey1 = rawkey1; | |||
/* | |||
* Do key permutation and split into two 28-bit subkeys. | |||
*/ | |||
k0 = key_perm_maskl[0][rawkey0 >> 25] | |||
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] | |||
| key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] | |||
| key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] | |||
| key_perm_maskl[4][rawkey1 >> 25] | |||
| key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] | |||
| key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] | |||
| key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; | |||
k1 = key_perm_maskr[0][rawkey0 >> 25] | |||
| key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] | |||
| key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] | |||
| key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] | |||
| key_perm_maskr[4][rawkey1 >> 25] | |||
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] | |||
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] | |||
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; | |||
/* | |||
* Rotate subkeys and do compression permutation. | |||
*/ | |||
shifts = 0; | |||
for (round = 0; round < 16; round++) { | |||
u_int32_t t0, t1; | |||
int bit; | |||
shifts += key_shifts[round]; | |||
t0 = (k0 << shifts) | (k0 >> (28 - shifts)); | |||
t1 = (k1 << shifts) | (k1 >> (28 - shifts)); | |||
de_keysl[15 - round] = | |||
en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] | |||
| comp_maskl[1][(t0 >> 14) & 0x7f] | |||
| comp_maskl[2][(t0 >> 7) & 0x7f] | |||
| comp_maskl[3][t0 & 0x7f] | |||
| comp_maskl[4][(t1 >> 21) & 0x7f] | |||
| comp_maskl[5][(t1 >> 14) & 0x7f] | |||
| comp_maskl[6][(t1 >> 7) & 0x7f] | |||
| comp_maskl[7][t1 & 0x7f]; | |||
de_keysr[15 - round] = | |||
en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f] | |||
| comp_maskr[1][(t0 >> 14) & 0x7f] | |||
| comp_maskr[2][(t0 >> 7) & 0x7f] | |||
| comp_maskr[3][t0 & 0x7f] | |||
| comp_maskr[4][(t1 >> 21) & 0x7f] | |||
| comp_maskr[5][(t1 >> 14) & 0x7f] | |||
| comp_maskr[6][(t1 >> 7) & 0x7f] | |||
| comp_maskr[7][t1 & 0x7f]; | |||
} | |||
return(0); | |||
} | |||
int | |||
setkey(key) | |||
char *key; | |||
{ | |||
int i, j; | |||
u_int32_t packed_keys[2]; | |||
u_char *p; | |||
p = (u_char *) packed_keys; | |||
for (i = 0; i < 8; i++) { | |||
p[i] = 0; | |||
for (j = 0; j < 8; j++) | |||
if (*key++ & 1) | |||
p[i] |= bits8[j]; | |||
} | |||
return(des_setkey(p)); | |||
} | |||
int | |||
encrypt(block, flag) | |||
char *block; | |||
int flag; | |||
{ | |||
u_int32_t io[2]; | |||
u_char *p; | |||
int i, j, retval; | |||
if (!des_initialised) | |||
des_init(); | |||
setup_salt(0L); | |||
p = block; | |||
for (i = 0; i < 2; i++) { | |||
io[i] = 0L; | |||
for (j = 0; j < 32; j++) | |||
if (*p++ & 1) | |||
io[i] |= bits32[j]; | |||
} | |||
retval = do_des(io[0], io[1], io, io + 1, flag ? -1 : 1); | |||
for (i = 0; i < 2; i++) | |||
for (j = 0; j < 32; j++) | |||
block[(i << 5) | j] = (io[i] & bits32[j]) ? 1 : 0; | |||
return(retval); | |||
} |