xref: /dragonfly/lib/libcrypt/crypt-des.c (revision bc4d84b2)
10fe46dc6SMatthew Dillon /*
20fe46dc6SMatthew Dillon  * FreeSec: libcrypt for NetBSD
30fe46dc6SMatthew Dillon  *
40fe46dc6SMatthew Dillon  * Copyright (c) 1994 David Burren
50fe46dc6SMatthew Dillon  * All rights reserved.
60fe46dc6SMatthew Dillon  *
70fe46dc6SMatthew Dillon  * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet
80fe46dc6SMatthew Dillon  *	this file should now *only* export crypt(), in order to make
90fe46dc6SMatthew Dillon  *	binaries of libcrypt exportable from the USA
100fe46dc6SMatthew Dillon  *
110fe46dc6SMatthew Dillon  * Adapted for FreeBSD-4.0 by Mark R V Murray
120fe46dc6SMatthew Dillon  *	this file should now *only* export crypt_des(), in order to make
130fe46dc6SMatthew Dillon  *	a module that can be optionally included in libcrypt.
140fe46dc6SMatthew Dillon  *
150fe46dc6SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
160fe46dc6SMatthew Dillon  * modification, are permitted provided that the following conditions
170fe46dc6SMatthew Dillon  * are met:
180fe46dc6SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
190fe46dc6SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
200fe46dc6SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
210fe46dc6SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
220fe46dc6SMatthew Dillon  *    documentation and/or other materials provided with the distribution.
230fe46dc6SMatthew Dillon  * 3. Neither the name of the author nor the names of other contributors
240fe46dc6SMatthew Dillon  *    may be used to endorse or promote products derived from this software
250fe46dc6SMatthew Dillon  *    without specific prior written permission.
260fe46dc6SMatthew Dillon  *
270fe46dc6SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
280fe46dc6SMatthew Dillon  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
290fe46dc6SMatthew Dillon  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
300fe46dc6SMatthew Dillon  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
310fe46dc6SMatthew Dillon  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
320fe46dc6SMatthew Dillon  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
330fe46dc6SMatthew Dillon  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
340fe46dc6SMatthew Dillon  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
350fe46dc6SMatthew Dillon  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
360fe46dc6SMatthew Dillon  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
370fe46dc6SMatthew Dillon  * SUCH DAMAGE.
380fe46dc6SMatthew Dillon  *
390fe46dc6SMatthew Dillon  * $FreeBSD: src/secure/lib/libcrypt/crypt-des.c,v 1.12 1999/09/20 12:39:20 markm Exp $
400fe46dc6SMatthew Dillon  *
410fe46dc6SMatthew Dillon  * This is an original implementation of the DES and the crypt(3) interfaces
420fe46dc6SMatthew Dillon  * by David Burren <davidb@werj.com.au>.
430fe46dc6SMatthew Dillon  *
440fe46dc6SMatthew Dillon  * An excellent reference on the underlying algorithm (and related
450fe46dc6SMatthew Dillon  * algorithms) is:
460fe46dc6SMatthew Dillon  *
470fe46dc6SMatthew Dillon  *	B. Schneier, Applied Cryptography: protocols, algorithms,
480fe46dc6SMatthew Dillon  *	and source code in C, John Wiley & Sons, 1994.
490fe46dc6SMatthew Dillon  *
500fe46dc6SMatthew Dillon  * Note that in that book's description of DES the lookups for the initial,
510fe46dc6SMatthew Dillon  * pbox, and final permutations are inverted (this has been brought to the
520fe46dc6SMatthew Dillon  * attention of the author).  A list of errata for this book has been
530fe46dc6SMatthew Dillon  * posted to the sci.crypt newsgroup by the author and is available for FTP.
540fe46dc6SMatthew Dillon  *
550fe46dc6SMatthew Dillon  * ARCHITECTURE ASSUMPTIONS:
560fe46dc6SMatthew Dillon  *	It is assumed that the 8-byte arrays passed by reference can be
570fe46dc6SMatthew Dillon  *	addressed as arrays of u_int32_t's (ie. the CPU is not picky about
580fe46dc6SMatthew Dillon  *	alignment).
590fe46dc6SMatthew Dillon  */
600fe46dc6SMatthew Dillon #include <sys/types.h>
610fe46dc6SMatthew Dillon #include <sys/param.h>
620fe46dc6SMatthew Dillon #include <pwd.h>
630fe46dc6SMatthew Dillon #include <string.h>
640fe46dc6SMatthew Dillon #include "crypt.h"
65*bc4d84b2Szrj #include "local_xsi.h"
660fe46dc6SMatthew Dillon 
670fe46dc6SMatthew Dillon /* We can't always assume gcc */
680fe46dc6SMatthew Dillon #ifdef __GNUC__
690fe46dc6SMatthew Dillon #define INLINE inline
700fe46dc6SMatthew Dillon #endif
710fe46dc6SMatthew Dillon 
720fe46dc6SMatthew Dillon 
730fe46dc6SMatthew Dillon static u_char	IP[64] = {
740fe46dc6SMatthew Dillon 	58, 50, 42, 34, 26, 18, 10,  2, 60, 52, 44, 36, 28, 20, 12,  4,
750fe46dc6SMatthew Dillon 	62, 54, 46, 38, 30, 22, 14,  6, 64, 56, 48, 40, 32, 24, 16,  8,
760fe46dc6SMatthew Dillon 	57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11,  3,
770fe46dc6SMatthew Dillon 	61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15,  7
780fe46dc6SMatthew Dillon };
790fe46dc6SMatthew Dillon 
800fe46dc6SMatthew Dillon static u_char	inv_key_perm[64];
810fe46dc6SMatthew Dillon static u_char	u_key_perm[56];
820fe46dc6SMatthew Dillon static u_char	key_perm[56] = {
830fe46dc6SMatthew Dillon 	57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
840fe46dc6SMatthew Dillon 	10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
850fe46dc6SMatthew Dillon 	63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
860fe46dc6SMatthew Dillon 	14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
870fe46dc6SMatthew Dillon };
880fe46dc6SMatthew Dillon 
890fe46dc6SMatthew Dillon static u_char	key_shifts[16] = {
900fe46dc6SMatthew Dillon 	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
910fe46dc6SMatthew Dillon };
920fe46dc6SMatthew Dillon 
930fe46dc6SMatthew Dillon static u_char	inv_comp_perm[56];
940fe46dc6SMatthew Dillon static u_char	comp_perm[48] = {
950fe46dc6SMatthew Dillon 	14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
960fe46dc6SMatthew Dillon 	23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
970fe46dc6SMatthew Dillon 	41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
980fe46dc6SMatthew Dillon 	44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
990fe46dc6SMatthew Dillon };
1000fe46dc6SMatthew Dillon 
1010fe46dc6SMatthew Dillon /*
1020fe46dc6SMatthew Dillon  *	No E box is used, as it's replaced by some ANDs, shifts, and ORs.
1030fe46dc6SMatthew Dillon  */
1040fe46dc6SMatthew Dillon 
1050fe46dc6SMatthew Dillon static u_char	u_sbox[8][64];
1060fe46dc6SMatthew Dillon static u_char	sbox[8][64] = {
1070fe46dc6SMatthew Dillon 	{
1080fe46dc6SMatthew Dillon 		14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
1090fe46dc6SMatthew Dillon 		 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
1100fe46dc6SMatthew Dillon 		 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
1110fe46dc6SMatthew Dillon 		15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
1120fe46dc6SMatthew Dillon 	},
1130fe46dc6SMatthew Dillon 	{
1140fe46dc6SMatthew Dillon 		15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
1150fe46dc6SMatthew Dillon 		 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
1160fe46dc6SMatthew Dillon 		 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
1170fe46dc6SMatthew Dillon 		13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9
1180fe46dc6SMatthew Dillon 	},
1190fe46dc6SMatthew Dillon 	{
1200fe46dc6SMatthew Dillon 		10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
1210fe46dc6SMatthew Dillon 		13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
1220fe46dc6SMatthew Dillon 		13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
1230fe46dc6SMatthew Dillon 		 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12
1240fe46dc6SMatthew Dillon 	},
1250fe46dc6SMatthew Dillon 	{
1260fe46dc6SMatthew Dillon 		 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
1270fe46dc6SMatthew Dillon 		13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
1280fe46dc6SMatthew Dillon 		10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
1290fe46dc6SMatthew Dillon 		 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14
1300fe46dc6SMatthew Dillon 	},
1310fe46dc6SMatthew Dillon 	{
1320fe46dc6SMatthew Dillon 		 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
1330fe46dc6SMatthew Dillon 		14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
1340fe46dc6SMatthew Dillon 		 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
1350fe46dc6SMatthew Dillon 		11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3
1360fe46dc6SMatthew Dillon 	},
1370fe46dc6SMatthew Dillon 	{
1380fe46dc6SMatthew Dillon 		12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
1390fe46dc6SMatthew Dillon 		10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
1400fe46dc6SMatthew Dillon 		 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
1410fe46dc6SMatthew Dillon 		 4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13
1420fe46dc6SMatthew Dillon 	},
1430fe46dc6SMatthew Dillon 	{
1440fe46dc6SMatthew Dillon 		 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
1450fe46dc6SMatthew Dillon 		13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
1460fe46dc6SMatthew Dillon 		 1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
1470fe46dc6SMatthew Dillon 		 6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12
1480fe46dc6SMatthew Dillon 	},
1490fe46dc6SMatthew Dillon 	{
1500fe46dc6SMatthew Dillon 		13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
1510fe46dc6SMatthew Dillon 		 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
1520fe46dc6SMatthew Dillon 		 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
1530fe46dc6SMatthew Dillon 		 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
1540fe46dc6SMatthew Dillon 	}
1550fe46dc6SMatthew Dillon };
1560fe46dc6SMatthew Dillon 
1570fe46dc6SMatthew Dillon static u_char	un_pbox[32];
1580fe46dc6SMatthew Dillon static u_char	pbox[32] = {
1590fe46dc6SMatthew Dillon 	16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
1600fe46dc6SMatthew Dillon 	 2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
1610fe46dc6SMatthew Dillon };
1620fe46dc6SMatthew Dillon 
1630fe46dc6SMatthew Dillon static u_int32_t	bits32[32] =
1640fe46dc6SMatthew Dillon {
1650fe46dc6SMatthew Dillon 	0x80000000, 0x40000000, 0x20000000, 0x10000000,
1660fe46dc6SMatthew Dillon 	0x08000000, 0x04000000, 0x02000000, 0x01000000,
1670fe46dc6SMatthew Dillon 	0x00800000, 0x00400000, 0x00200000, 0x00100000,
1680fe46dc6SMatthew Dillon 	0x00080000, 0x00040000, 0x00020000, 0x00010000,
1690fe46dc6SMatthew Dillon 	0x00008000, 0x00004000, 0x00002000, 0x00001000,
1700fe46dc6SMatthew Dillon 	0x00000800, 0x00000400, 0x00000200, 0x00000100,
1710fe46dc6SMatthew Dillon 	0x00000080, 0x00000040, 0x00000020, 0x00000010,
1720fe46dc6SMatthew Dillon 	0x00000008, 0x00000004, 0x00000002, 0x00000001
1730fe46dc6SMatthew Dillon };
1740fe46dc6SMatthew Dillon 
1750fe46dc6SMatthew Dillon static u_char	bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
1760fe46dc6SMatthew Dillon 
1770fe46dc6SMatthew Dillon static u_int32_t	saltbits;
1780fe46dc6SMatthew Dillon static long		old_salt;
1790fe46dc6SMatthew Dillon static u_int32_t	*bits28, *bits24;
1800fe46dc6SMatthew Dillon static u_char		init_perm[64], final_perm[64];
1810fe46dc6SMatthew Dillon static u_int32_t	en_keysl[16], en_keysr[16];
1820fe46dc6SMatthew Dillon static u_int32_t	de_keysl[16], de_keysr[16];
1830fe46dc6SMatthew Dillon static int		des_initialised = 0;
1840fe46dc6SMatthew Dillon static u_char		m_sbox[4][4096];
1850fe46dc6SMatthew Dillon static u_int32_t	psbox[4][256];
1860fe46dc6SMatthew Dillon static u_int32_t	ip_maskl[8][256], ip_maskr[8][256];
1870fe46dc6SMatthew Dillon static u_int32_t	fp_maskl[8][256], fp_maskr[8][256];
1880fe46dc6SMatthew Dillon static u_int32_t	key_perm_maskl[8][128], key_perm_maskr[8][128];
1890fe46dc6SMatthew Dillon static u_int32_t	comp_maskl[8][128], comp_maskr[8][128];
1900fe46dc6SMatthew Dillon static u_int32_t	old_rawkey0, old_rawkey1;
1910fe46dc6SMatthew Dillon 
1920fe46dc6SMatthew Dillon static u_char	ascii64[] =
1930fe46dc6SMatthew Dillon 	 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1940fe46dc6SMatthew Dillon /*	  0000000000111111111122222222223333333333444444444455555555556666 */
1950fe46dc6SMatthew Dillon /*	  0123456789012345678901234567890123456789012345678901234567890123 */
1960fe46dc6SMatthew Dillon 
1970fe46dc6SMatthew Dillon static INLINE int
ascii_to_bin(char ch)1980fe46dc6SMatthew Dillon ascii_to_bin(char ch)
1990fe46dc6SMatthew Dillon {
2000fe46dc6SMatthew Dillon 	if (ch > 'z')
2010fe46dc6SMatthew Dillon 		return(0);
2020fe46dc6SMatthew Dillon 	if (ch >= 'a')
2030fe46dc6SMatthew Dillon 		return(ch - 'a' + 38);
2040fe46dc6SMatthew Dillon 	if (ch > 'Z')
2050fe46dc6SMatthew Dillon 		return(0);
2060fe46dc6SMatthew Dillon 	if (ch >= 'A')
2070fe46dc6SMatthew Dillon 		return(ch - 'A' + 12);
2080fe46dc6SMatthew Dillon 	if (ch > '9')
2090fe46dc6SMatthew Dillon 		return(0);
2100fe46dc6SMatthew Dillon 	if (ch >= '.')
2110fe46dc6SMatthew Dillon 		return(ch - '.');
2120fe46dc6SMatthew Dillon 	return(0);
2130fe46dc6SMatthew Dillon }
2140fe46dc6SMatthew Dillon 
2150fe46dc6SMatthew Dillon static void
des_init(void)2162ae2c6edSSascha Wildner des_init(void)
2170fe46dc6SMatthew Dillon {
2180fe46dc6SMatthew Dillon 	int	i, j, b, k, inbit, obit;
2190fe46dc6SMatthew Dillon 	u_int32_t	*p, *il, *ir, *fl, *fr;
2200fe46dc6SMatthew Dillon 
2210fe46dc6SMatthew Dillon 	old_rawkey0 = old_rawkey1 = 0L;
2220fe46dc6SMatthew Dillon 	saltbits = 0L;
2230fe46dc6SMatthew Dillon 	old_salt = 0L;
2240fe46dc6SMatthew Dillon 	bits24 = (bits28 = bits32 + 4) + 4;
2250fe46dc6SMatthew Dillon 
2260fe46dc6SMatthew Dillon 	/*
2270fe46dc6SMatthew Dillon 	 * Invert the S-boxes, reordering the input bits.
2280fe46dc6SMatthew Dillon 	 */
2290fe46dc6SMatthew Dillon 	for (i = 0; i < 8; i++)
2300fe46dc6SMatthew Dillon 		for (j = 0; j < 64; j++) {
2310fe46dc6SMatthew Dillon 			b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
2320fe46dc6SMatthew Dillon 			u_sbox[i][j] = sbox[i][b];
2330fe46dc6SMatthew Dillon 		}
2340fe46dc6SMatthew Dillon 
2350fe46dc6SMatthew Dillon 	/*
2360fe46dc6SMatthew Dillon 	 * Convert the inverted S-boxes into 4 arrays of 8 bits.
2370fe46dc6SMatthew Dillon 	 * Each will handle 12 bits of the S-box input.
2380fe46dc6SMatthew Dillon 	 */
2390fe46dc6SMatthew Dillon 	for (b = 0; b < 4; b++)
2400fe46dc6SMatthew Dillon 		for (i = 0; i < 64; i++)
2410fe46dc6SMatthew Dillon 			for (j = 0; j < 64; j++)
2420fe46dc6SMatthew Dillon 				m_sbox[b][(i << 6) | j] =
2430fe46dc6SMatthew Dillon 					(u_sbox[(b << 1)][i] << 4) |
2440fe46dc6SMatthew Dillon 					u_sbox[(b << 1) + 1][j];
2450fe46dc6SMatthew Dillon 
2460fe46dc6SMatthew Dillon 	/*
2470fe46dc6SMatthew Dillon 	 * Set up the initial & final permutations into a useful form, and
2480fe46dc6SMatthew Dillon 	 * initialise the inverted key permutation.
2490fe46dc6SMatthew Dillon 	 */
2500fe46dc6SMatthew Dillon 	for (i = 0; i < 64; i++) {
2510fe46dc6SMatthew Dillon 		init_perm[final_perm[i] = IP[i] - 1] = i;
2520fe46dc6SMatthew Dillon 		inv_key_perm[i] = 255;
2530fe46dc6SMatthew Dillon 	}
2540fe46dc6SMatthew Dillon 
2550fe46dc6SMatthew Dillon 	/*
2560fe46dc6SMatthew Dillon 	 * Invert the key permutation and initialise the inverted key
2570fe46dc6SMatthew Dillon 	 * compression permutation.
2580fe46dc6SMatthew Dillon 	 */
2590fe46dc6SMatthew Dillon 	for (i = 0; i < 56; i++) {
2600fe46dc6SMatthew Dillon 		u_key_perm[i] = key_perm[i] - 1;
2610fe46dc6SMatthew Dillon 		inv_key_perm[key_perm[i] - 1] = i;
2620fe46dc6SMatthew Dillon 		inv_comp_perm[i] = 255;
2630fe46dc6SMatthew Dillon 	}
2640fe46dc6SMatthew Dillon 
2650fe46dc6SMatthew Dillon 	/*
2660fe46dc6SMatthew Dillon 	 * Invert the key compression permutation.
2670fe46dc6SMatthew Dillon 	 */
2680fe46dc6SMatthew Dillon 	for (i = 0; i < 48; i++) {
2690fe46dc6SMatthew Dillon 		inv_comp_perm[comp_perm[i] - 1] = i;
2700fe46dc6SMatthew Dillon 	}
2710fe46dc6SMatthew Dillon 
2720fe46dc6SMatthew Dillon 	/*
2730fe46dc6SMatthew Dillon 	 * Set up the OR-mask arrays for the initial and final permutations,
2740fe46dc6SMatthew Dillon 	 * and for the key initial and compression permutations.
2750fe46dc6SMatthew Dillon 	 */
2760fe46dc6SMatthew Dillon 	for (k = 0; k < 8; k++) {
2770fe46dc6SMatthew Dillon 		for (i = 0; i < 256; i++) {
2780fe46dc6SMatthew Dillon 			*(il = &ip_maskl[k][i]) = 0L;
2790fe46dc6SMatthew Dillon 			*(ir = &ip_maskr[k][i]) = 0L;
2800fe46dc6SMatthew Dillon 			*(fl = &fp_maskl[k][i]) = 0L;
2810fe46dc6SMatthew Dillon 			*(fr = &fp_maskr[k][i]) = 0L;
2820fe46dc6SMatthew Dillon 			for (j = 0; j < 8; j++) {
2830fe46dc6SMatthew Dillon 				inbit = 8 * k + j;
2840fe46dc6SMatthew Dillon 				if (i & bits8[j]) {
2850fe46dc6SMatthew Dillon 					if ((obit = init_perm[inbit]) < 32)
2860fe46dc6SMatthew Dillon 						*il |= bits32[obit];
2870fe46dc6SMatthew Dillon 					else
2880fe46dc6SMatthew Dillon 						*ir |= bits32[obit-32];
2890fe46dc6SMatthew Dillon 					if ((obit = final_perm[inbit]) < 32)
2900fe46dc6SMatthew Dillon 						*fl |= bits32[obit];
2910fe46dc6SMatthew Dillon 					else
2920fe46dc6SMatthew Dillon 						*fr |= bits32[obit - 32];
2930fe46dc6SMatthew Dillon 				}
2940fe46dc6SMatthew Dillon 			}
2950fe46dc6SMatthew Dillon 		}
2960fe46dc6SMatthew Dillon 		for (i = 0; i < 128; i++) {
2970fe46dc6SMatthew Dillon 			*(il = &key_perm_maskl[k][i]) = 0L;
2980fe46dc6SMatthew Dillon 			*(ir = &key_perm_maskr[k][i]) = 0L;
2990fe46dc6SMatthew Dillon 			for (j = 0; j < 7; j++) {
3000fe46dc6SMatthew Dillon 				inbit = 8 * k + j;
3010fe46dc6SMatthew Dillon 				if (i & bits8[j + 1]) {
3020fe46dc6SMatthew Dillon 					if ((obit = inv_key_perm[inbit]) == 255)
3030fe46dc6SMatthew Dillon 						continue;
3040fe46dc6SMatthew Dillon 					if (obit < 28)
3050fe46dc6SMatthew Dillon 						*il |= bits28[obit];
3060fe46dc6SMatthew Dillon 					else
3070fe46dc6SMatthew Dillon 						*ir |= bits28[obit - 28];
3080fe46dc6SMatthew Dillon 				}
3090fe46dc6SMatthew Dillon 			}
3100fe46dc6SMatthew Dillon 			*(il = &comp_maskl[k][i]) = 0L;
3110fe46dc6SMatthew Dillon 			*(ir = &comp_maskr[k][i]) = 0L;
3120fe46dc6SMatthew Dillon 			for (j = 0; j < 7; j++) {
3130fe46dc6SMatthew Dillon 				inbit = 7 * k + j;
3140fe46dc6SMatthew Dillon 				if (i & bits8[j + 1]) {
3150fe46dc6SMatthew Dillon 					if ((obit=inv_comp_perm[inbit]) == 255)
3160fe46dc6SMatthew Dillon 						continue;
3170fe46dc6SMatthew Dillon 					if (obit < 24)
3180fe46dc6SMatthew Dillon 						*il |= bits24[obit];
3190fe46dc6SMatthew Dillon 					else
3200fe46dc6SMatthew Dillon 						*ir |= bits24[obit - 24];
3210fe46dc6SMatthew Dillon 				}
3220fe46dc6SMatthew Dillon 			}
3230fe46dc6SMatthew Dillon 		}
3240fe46dc6SMatthew Dillon 	}
3250fe46dc6SMatthew Dillon 
3260fe46dc6SMatthew Dillon 	/*
3270fe46dc6SMatthew Dillon 	 * Invert the P-box permutation, and convert into OR-masks for
3280fe46dc6SMatthew Dillon 	 * handling the output of the S-box arrays setup above.
3290fe46dc6SMatthew Dillon 	 */
3300fe46dc6SMatthew Dillon 	for (i = 0; i < 32; i++)
3310fe46dc6SMatthew Dillon 		un_pbox[pbox[i] - 1] = i;
3320fe46dc6SMatthew Dillon 
3330fe46dc6SMatthew Dillon 	for (b = 0; b < 4; b++)
3340fe46dc6SMatthew Dillon 		for (i = 0; i < 256; i++) {
3350fe46dc6SMatthew Dillon 			*(p = &psbox[b][i]) = 0L;
3360fe46dc6SMatthew Dillon 			for (j = 0; j < 8; j++) {
3370fe46dc6SMatthew Dillon 				if (i & bits8[j])
3380fe46dc6SMatthew Dillon 					*p |= bits32[un_pbox[8 * b + j]];
3390fe46dc6SMatthew Dillon 			}
3400fe46dc6SMatthew Dillon 		}
3410fe46dc6SMatthew Dillon 
3420fe46dc6SMatthew Dillon 	des_initialised = 1;
3430fe46dc6SMatthew Dillon }
3440fe46dc6SMatthew Dillon 
3450fe46dc6SMatthew Dillon static void
setup_salt(long salt)3460fe46dc6SMatthew Dillon setup_salt(long salt)
3470fe46dc6SMatthew Dillon {
3480fe46dc6SMatthew Dillon 	u_int32_t	obit, saltbit;
3490fe46dc6SMatthew Dillon 	int		i;
3500fe46dc6SMatthew Dillon 
3510fe46dc6SMatthew Dillon 	if (salt == old_salt)
3520fe46dc6SMatthew Dillon 		return;
3530fe46dc6SMatthew Dillon 	old_salt = salt;
3540fe46dc6SMatthew Dillon 
3550fe46dc6SMatthew Dillon 	saltbits = 0L;
3560fe46dc6SMatthew Dillon 	saltbit = 1;
3570fe46dc6SMatthew Dillon 	obit = 0x800000;
3580fe46dc6SMatthew Dillon 	for (i = 0; i < 24; i++) {
3590fe46dc6SMatthew Dillon 		if (salt & saltbit)
3600fe46dc6SMatthew Dillon 			saltbits |= obit;
3610fe46dc6SMatthew Dillon 		saltbit <<= 1;
3620fe46dc6SMatthew Dillon 		obit >>= 1;
3630fe46dc6SMatthew Dillon 	}
3640fe46dc6SMatthew Dillon }
3650fe46dc6SMatthew Dillon 
3660fe46dc6SMatthew Dillon static int
des_setkey(const char * key)3670fe46dc6SMatthew Dillon des_setkey(const char *key)
3680fe46dc6SMatthew Dillon {
3690fe46dc6SMatthew Dillon 	u_int32_t	k0, k1, rawkey0, rawkey1;
3700fe46dc6SMatthew Dillon 	int		shifts, round;
3710fe46dc6SMatthew Dillon 
3720fe46dc6SMatthew Dillon 	if (!des_initialised)
3730fe46dc6SMatthew Dillon 		des_init();
3740fe46dc6SMatthew Dillon 
3750fe46dc6SMatthew Dillon 	rawkey0 = ntohl(*(u_int32_t *) key);
3760fe46dc6SMatthew Dillon 	rawkey1 = ntohl(*(u_int32_t *) (key + 4));
3770fe46dc6SMatthew Dillon 
3780fe46dc6SMatthew Dillon 	if ((rawkey0 | rawkey1)
3790fe46dc6SMatthew Dillon 	    && rawkey0 == old_rawkey0
3800fe46dc6SMatthew Dillon 	    && rawkey1 == old_rawkey1) {
3810fe46dc6SMatthew Dillon 		/*
3820fe46dc6SMatthew Dillon 		 * Already setup for this key.
3830fe46dc6SMatthew Dillon 		 * This optimisation fails on a zero key (which is weak and
3840fe46dc6SMatthew Dillon 		 * has bad parity anyway) in order to simplify the starting
3850fe46dc6SMatthew Dillon 		 * conditions.
3860fe46dc6SMatthew Dillon 		 */
3870fe46dc6SMatthew Dillon 		return(0);
3880fe46dc6SMatthew Dillon 	}
3890fe46dc6SMatthew Dillon 	old_rawkey0 = rawkey0;
3900fe46dc6SMatthew Dillon 	old_rawkey1 = rawkey1;
3910fe46dc6SMatthew Dillon 
3920fe46dc6SMatthew Dillon 	/*
3930fe46dc6SMatthew Dillon 	 *	Do key permutation and split into two 28-bit subkeys.
3940fe46dc6SMatthew Dillon 	 */
3950fe46dc6SMatthew Dillon 	k0 = key_perm_maskl[0][rawkey0 >> 25]
3960fe46dc6SMatthew Dillon 	   | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
3970fe46dc6SMatthew Dillon 	   | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
3980fe46dc6SMatthew Dillon 	   | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
3990fe46dc6SMatthew Dillon 	   | key_perm_maskl[4][rawkey1 >> 25]
4000fe46dc6SMatthew Dillon 	   | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
4010fe46dc6SMatthew Dillon 	   | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
4020fe46dc6SMatthew Dillon 	   | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
4030fe46dc6SMatthew Dillon 	k1 = key_perm_maskr[0][rawkey0 >> 25]
4040fe46dc6SMatthew Dillon 	   | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
4050fe46dc6SMatthew Dillon 	   | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
4060fe46dc6SMatthew Dillon 	   | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
4070fe46dc6SMatthew Dillon 	   | key_perm_maskr[4][rawkey1 >> 25]
4080fe46dc6SMatthew Dillon 	   | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
4090fe46dc6SMatthew Dillon 	   | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
4100fe46dc6SMatthew Dillon 	   | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
4110fe46dc6SMatthew Dillon 	/*
4120fe46dc6SMatthew Dillon 	 *	Rotate subkeys and do compression permutation.
4130fe46dc6SMatthew Dillon 	 */
4140fe46dc6SMatthew Dillon 	shifts = 0;
4150fe46dc6SMatthew Dillon 	for (round = 0; round < 16; round++) {
4160fe46dc6SMatthew Dillon 		u_int32_t	t0, t1;
4170fe46dc6SMatthew Dillon 
4180fe46dc6SMatthew Dillon 		shifts += key_shifts[round];
4190fe46dc6SMatthew Dillon 
4200fe46dc6SMatthew Dillon 		t0 = (k0 << shifts) | (k0 >> (28 - shifts));
4210fe46dc6SMatthew Dillon 		t1 = (k1 << shifts) | (k1 >> (28 - shifts));
4220fe46dc6SMatthew Dillon 
4230fe46dc6SMatthew Dillon 		de_keysl[15 - round] =
4240fe46dc6SMatthew Dillon 		en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
4250fe46dc6SMatthew Dillon 				| comp_maskl[1][(t0 >> 14) & 0x7f]
4260fe46dc6SMatthew Dillon 				| comp_maskl[2][(t0 >> 7) & 0x7f]
4270fe46dc6SMatthew Dillon 				| comp_maskl[3][t0 & 0x7f]
4280fe46dc6SMatthew Dillon 				| comp_maskl[4][(t1 >> 21) & 0x7f]
4290fe46dc6SMatthew Dillon 				| comp_maskl[5][(t1 >> 14) & 0x7f]
4300fe46dc6SMatthew Dillon 				| comp_maskl[6][(t1 >> 7) & 0x7f]
4310fe46dc6SMatthew Dillon 				| comp_maskl[7][t1 & 0x7f];
4320fe46dc6SMatthew Dillon 
4330fe46dc6SMatthew Dillon 		de_keysr[15 - round] =
4340fe46dc6SMatthew Dillon 		en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
4350fe46dc6SMatthew Dillon 				| comp_maskr[1][(t0 >> 14) & 0x7f]
4360fe46dc6SMatthew Dillon 				| comp_maskr[2][(t0 >> 7) & 0x7f]
4370fe46dc6SMatthew Dillon 				| comp_maskr[3][t0 & 0x7f]
4380fe46dc6SMatthew Dillon 				| comp_maskr[4][(t1 >> 21) & 0x7f]
4390fe46dc6SMatthew Dillon 				| comp_maskr[5][(t1 >> 14) & 0x7f]
4400fe46dc6SMatthew Dillon 				| comp_maskr[6][(t1 >> 7) & 0x7f]
4410fe46dc6SMatthew Dillon 				| comp_maskr[7][t1 & 0x7f];
4420fe46dc6SMatthew Dillon 	}
4430fe46dc6SMatthew Dillon 	return(0);
4440fe46dc6SMatthew Dillon }
4450fe46dc6SMatthew Dillon 
4460fe46dc6SMatthew Dillon static int
do_des(u_int32_t l_in,u_int32_t r_in,u_int32_t * l_out,u_int32_t * r_out,int count)4470fe46dc6SMatthew Dillon do_des(	u_int32_t l_in, u_int32_t r_in, u_int32_t *l_out, u_int32_t *r_out, int count)
4480fe46dc6SMatthew Dillon {
4490fe46dc6SMatthew Dillon 	/*
4500fe46dc6SMatthew Dillon 	 *	l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
4510fe46dc6SMatthew Dillon 	 */
4520fe46dc6SMatthew Dillon 	u_int32_t	l, r, *kl, *kr, *kl1, *kr1;
4530fe46dc6SMatthew Dillon 	u_int32_t	f, r48l, r48r;
4540fe46dc6SMatthew Dillon 	int		round;
4550fe46dc6SMatthew Dillon 
4560fe46dc6SMatthew Dillon 	if (count == 0) {
4570fe46dc6SMatthew Dillon 		return(1);
4580fe46dc6SMatthew Dillon 	} else if (count > 0) {
4590fe46dc6SMatthew Dillon 		/*
4600fe46dc6SMatthew Dillon 		 * Encrypting
4610fe46dc6SMatthew Dillon 		 */
4620fe46dc6SMatthew Dillon 		kl1 = en_keysl;
4630fe46dc6SMatthew Dillon 		kr1 = en_keysr;
4640fe46dc6SMatthew Dillon 	} else {
4650fe46dc6SMatthew Dillon 		/*
4660fe46dc6SMatthew Dillon 		 * Decrypting
4670fe46dc6SMatthew Dillon 		 */
4680fe46dc6SMatthew Dillon 		count = -count;
4690fe46dc6SMatthew Dillon 		kl1 = de_keysl;
4700fe46dc6SMatthew Dillon 		kr1 = de_keysr;
4710fe46dc6SMatthew Dillon 	}
4720fe46dc6SMatthew Dillon 
4730fe46dc6SMatthew Dillon 	/*
4740fe46dc6SMatthew Dillon 	 *	Do initial permutation (IP).
4750fe46dc6SMatthew Dillon 	 */
4760fe46dc6SMatthew Dillon 	l = ip_maskl[0][l_in >> 24]
4770fe46dc6SMatthew Dillon 	  | ip_maskl[1][(l_in >> 16) & 0xff]
4780fe46dc6SMatthew Dillon 	  | ip_maskl[2][(l_in >> 8) & 0xff]
4790fe46dc6SMatthew Dillon 	  | ip_maskl[3][l_in & 0xff]
4800fe46dc6SMatthew Dillon 	  | ip_maskl[4][r_in >> 24]
4810fe46dc6SMatthew Dillon 	  | ip_maskl[5][(r_in >> 16) & 0xff]
4820fe46dc6SMatthew Dillon 	  | ip_maskl[6][(r_in >> 8) & 0xff]
4830fe46dc6SMatthew Dillon 	  | ip_maskl[7][r_in & 0xff];
4840fe46dc6SMatthew Dillon 	r = ip_maskr[0][l_in >> 24]
4850fe46dc6SMatthew Dillon 	  | ip_maskr[1][(l_in >> 16) & 0xff]
4860fe46dc6SMatthew Dillon 	  | ip_maskr[2][(l_in >> 8) & 0xff]
4870fe46dc6SMatthew Dillon 	  | ip_maskr[3][l_in & 0xff]
4880fe46dc6SMatthew Dillon 	  | ip_maskr[4][r_in >> 24]
4890fe46dc6SMatthew Dillon 	  | ip_maskr[5][(r_in >> 16) & 0xff]
4900fe46dc6SMatthew Dillon 	  | ip_maskr[6][(r_in >> 8) & 0xff]
4910fe46dc6SMatthew Dillon 	  | ip_maskr[7][r_in & 0xff];
4920fe46dc6SMatthew Dillon 
4930fe46dc6SMatthew Dillon 	while (count--) {
4940fe46dc6SMatthew Dillon 		/*
4950fe46dc6SMatthew Dillon 		 * Do each round.
4960fe46dc6SMatthew Dillon 		 */
4970fe46dc6SMatthew Dillon 		kl = kl1;
4980fe46dc6SMatthew Dillon 		kr = kr1;
4990fe46dc6SMatthew Dillon 		round = 16;
5000fe46dc6SMatthew Dillon 		while (round--) {
5010fe46dc6SMatthew Dillon 			/*
5020fe46dc6SMatthew Dillon 			 * Expand R to 48 bits (simulate the E-box).
5030fe46dc6SMatthew Dillon 			 */
5040fe46dc6SMatthew Dillon 			r48l	= ((r & 0x00000001) << 23)
5050fe46dc6SMatthew Dillon 				| ((r & 0xf8000000) >> 9)
5060fe46dc6SMatthew Dillon 				| ((r & 0x1f800000) >> 11)
5070fe46dc6SMatthew Dillon 				| ((r & 0x01f80000) >> 13)
5080fe46dc6SMatthew Dillon 				| ((r & 0x001f8000) >> 15);
5090fe46dc6SMatthew Dillon 
5100fe46dc6SMatthew Dillon 			r48r	= ((r & 0x0001f800) << 7)
5110fe46dc6SMatthew Dillon 				| ((r & 0x00001f80) << 5)
5120fe46dc6SMatthew Dillon 				| ((r & 0x000001f8) << 3)
5130fe46dc6SMatthew Dillon 				| ((r & 0x0000001f) << 1)
5140fe46dc6SMatthew Dillon 				| ((r & 0x80000000) >> 31);
5150fe46dc6SMatthew Dillon 			/*
5160fe46dc6SMatthew Dillon 			 * Do salting for crypt() and friends, and
5170fe46dc6SMatthew Dillon 			 * XOR with the permuted key.
5180fe46dc6SMatthew Dillon 			 */
5190fe46dc6SMatthew Dillon 			f = (r48l ^ r48r) & saltbits;
5200fe46dc6SMatthew Dillon 			r48l ^= f ^ *kl++;
5210fe46dc6SMatthew Dillon 			r48r ^= f ^ *kr++;
5220fe46dc6SMatthew Dillon 			/*
5230fe46dc6SMatthew Dillon 			 * Do sbox lookups (which shrink it back to 32 bits)
5240fe46dc6SMatthew Dillon 			 * and do the pbox permutation at the same time.
5250fe46dc6SMatthew Dillon 			 */
5260fe46dc6SMatthew Dillon 			f = psbox[0][m_sbox[0][r48l >> 12]]
5270fe46dc6SMatthew Dillon 			  | psbox[1][m_sbox[1][r48l & 0xfff]]
5280fe46dc6SMatthew Dillon 			  | psbox[2][m_sbox[2][r48r >> 12]]
5290fe46dc6SMatthew Dillon 			  | psbox[3][m_sbox[3][r48r & 0xfff]];
5300fe46dc6SMatthew Dillon 			/*
5310fe46dc6SMatthew Dillon 			 * Now that we've permuted things, complete f().
5320fe46dc6SMatthew Dillon 			 */
5330fe46dc6SMatthew Dillon 			f ^= l;
5340fe46dc6SMatthew Dillon 			l = r;
5350fe46dc6SMatthew Dillon 			r = f;
5360fe46dc6SMatthew Dillon 		}
5370fe46dc6SMatthew Dillon 		r = l;
5380fe46dc6SMatthew Dillon 		l = f;
5390fe46dc6SMatthew Dillon 	}
5400fe46dc6SMatthew Dillon 	/*
5410fe46dc6SMatthew Dillon 	 * Do final permutation (inverse of IP).
5420fe46dc6SMatthew Dillon 	 */
5430fe46dc6SMatthew Dillon 	*l_out	= fp_maskl[0][l >> 24]
5440fe46dc6SMatthew Dillon 		| fp_maskl[1][(l >> 16) & 0xff]
5450fe46dc6SMatthew Dillon 		| fp_maskl[2][(l >> 8) & 0xff]
5460fe46dc6SMatthew Dillon 		| fp_maskl[3][l & 0xff]
5470fe46dc6SMatthew Dillon 		| fp_maskl[4][r >> 24]
5480fe46dc6SMatthew Dillon 		| fp_maskl[5][(r >> 16) & 0xff]
5490fe46dc6SMatthew Dillon 		| fp_maskl[6][(r >> 8) & 0xff]
5500fe46dc6SMatthew Dillon 		| fp_maskl[7][r & 0xff];
5510fe46dc6SMatthew Dillon 	*r_out	= fp_maskr[0][l >> 24]
5520fe46dc6SMatthew Dillon 		| fp_maskr[1][(l >> 16) & 0xff]
5530fe46dc6SMatthew Dillon 		| fp_maskr[2][(l >> 8) & 0xff]
5540fe46dc6SMatthew Dillon 		| fp_maskr[3][l & 0xff]
5550fe46dc6SMatthew Dillon 		| fp_maskr[4][r >> 24]
5560fe46dc6SMatthew Dillon 		| fp_maskr[5][(r >> 16) & 0xff]
5570fe46dc6SMatthew Dillon 		| fp_maskr[6][(r >> 8) & 0xff]
5580fe46dc6SMatthew Dillon 		| fp_maskr[7][r & 0xff];
5590fe46dc6SMatthew Dillon 	return(0);
5600fe46dc6SMatthew Dillon }
5610fe46dc6SMatthew Dillon 
5620fe46dc6SMatthew Dillon static int
des_cipher(const char * in,char * out,long salt,int count)5630fe46dc6SMatthew Dillon des_cipher(const char *in, char *out, long salt, int count)
5640fe46dc6SMatthew Dillon {
5650fe46dc6SMatthew Dillon 	const uint32_t	*in32;
5660fe46dc6SMatthew Dillon 	uint32_t	l_out, r_out, rawl, rawr, *out32;
5670fe46dc6SMatthew Dillon 	int		retval;
5680fe46dc6SMatthew Dillon 
5690fe46dc6SMatthew Dillon 	if (!des_initialised)
5700fe46dc6SMatthew Dillon 		des_init();
5710fe46dc6SMatthew Dillon 
5720fe46dc6SMatthew Dillon 	setup_salt(salt);
5730fe46dc6SMatthew Dillon 
5740fe46dc6SMatthew Dillon 	in32 = (const uint32_t *)in;
5750fe46dc6SMatthew Dillon 	out32 = (uint32_t *)out;
5760fe46dc6SMatthew Dillon 
5770fe46dc6SMatthew Dillon 	rawl = ntohl(*in32++);
5780fe46dc6SMatthew Dillon 	rawr = ntohl(*in32);
5790fe46dc6SMatthew Dillon 
5800fe46dc6SMatthew Dillon 	retval = do_des(rawl, rawr, &l_out, &r_out, count);
5810fe46dc6SMatthew Dillon 
5820fe46dc6SMatthew Dillon 	*out32++ = htonl(l_out);
5830fe46dc6SMatthew Dillon 	*out32 = htonl(r_out);
5840fe46dc6SMatthew Dillon 	return(retval);
5850fe46dc6SMatthew Dillon }
5860fe46dc6SMatthew Dillon 
5870fe46dc6SMatthew Dillon char *
crypt_des(const char * key,const char * setting)5880fe46dc6SMatthew Dillon crypt_des(const char *key, const char *setting)
5890fe46dc6SMatthew Dillon {
5900fe46dc6SMatthew Dillon 	int		i;
5910fe46dc6SMatthew Dillon 	u_int32_t	count, salt, l, r0, r1, keybuf[2];
5920fe46dc6SMatthew Dillon 	u_char		*p, *q;
5930fe46dc6SMatthew Dillon 	static u_char	output[21];
5940fe46dc6SMatthew Dillon 
5950fe46dc6SMatthew Dillon 	if (!des_initialised)
5960fe46dc6SMatthew Dillon 		des_init();
5970fe46dc6SMatthew Dillon 
5980fe46dc6SMatthew Dillon 
5990fe46dc6SMatthew Dillon 	/*
6000fe46dc6SMatthew Dillon 	 * Copy the key, shifting each character up by one bit
6010fe46dc6SMatthew Dillon 	 * and padding with zeros.
6020fe46dc6SMatthew Dillon 	 */
6030fe46dc6SMatthew Dillon 	q = (u_char *) keybuf;
6040fe46dc6SMatthew Dillon 	while (q - (u_char *) keybuf - 8) {
6050fe46dc6SMatthew Dillon 		*q++ = *key << 1;
6060fe46dc6SMatthew Dillon 		if (*key != '\0')
6070fe46dc6SMatthew Dillon 			key++;
6080fe46dc6SMatthew Dillon 	}
6090fe46dc6SMatthew Dillon 	if (des_setkey((u_char *) keybuf))
6100fe46dc6SMatthew Dillon 		return(NULL);
6110fe46dc6SMatthew Dillon 
6120fe46dc6SMatthew Dillon 	if (*setting == _PASSWORD_EFMT1) {
6130fe46dc6SMatthew Dillon 		/*
6140fe46dc6SMatthew Dillon 		 * "new"-style:
6150fe46dc6SMatthew Dillon 		 *	setting - underscore, 4 bytes of count, 4 bytes of salt
6160fe46dc6SMatthew Dillon 		 *	key - unlimited characters
6170fe46dc6SMatthew Dillon 		 */
6180fe46dc6SMatthew Dillon 		for (i = 1, count = 0L; i < 5; i++)
6190fe46dc6SMatthew Dillon 			count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
6200fe46dc6SMatthew Dillon 
6210fe46dc6SMatthew Dillon 		for (i = 5, salt = 0L; i < 9; i++)
6220fe46dc6SMatthew Dillon 			salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
6230fe46dc6SMatthew Dillon 
6240fe46dc6SMatthew Dillon 		while (*key) {
6250fe46dc6SMatthew Dillon 			/*
6260fe46dc6SMatthew Dillon 			 * Encrypt the key with itself.
6270fe46dc6SMatthew Dillon 			 */
6280fe46dc6SMatthew Dillon 			if (des_cipher((u_char*)keybuf, (u_char*)keybuf, 0L, 1))
6290fe46dc6SMatthew Dillon 				return(NULL);
6300fe46dc6SMatthew Dillon 			/*
6310fe46dc6SMatthew Dillon 			 * And XOR with the next 8 characters of the key.
6320fe46dc6SMatthew Dillon 			 */
6330fe46dc6SMatthew Dillon 			q = (u_char *) keybuf;
6340fe46dc6SMatthew Dillon 			while (q - (u_char *) keybuf - 8 && *key)
6350fe46dc6SMatthew Dillon 				*q++ ^= *key++ << 1;
6360fe46dc6SMatthew Dillon 
6370fe46dc6SMatthew Dillon 			if (des_setkey((u_char *) keybuf))
6380fe46dc6SMatthew Dillon 				return(NULL);
6390fe46dc6SMatthew Dillon 		}
6400fe46dc6SMatthew Dillon 		strncpy(output, setting, 9);
6410fe46dc6SMatthew Dillon 
6420fe46dc6SMatthew Dillon 		/*
6430fe46dc6SMatthew Dillon 		 * Double check that we weren't given a short setting.
6440fe46dc6SMatthew Dillon 		 * If we were, the above code will probably have created
6450fe46dc6SMatthew Dillon 		 * weird values for count and salt, but we don't really care.
6460fe46dc6SMatthew Dillon 		 * Just make sure the output string doesn't have an extra
6470fe46dc6SMatthew Dillon 		 * NUL in it.
6480fe46dc6SMatthew Dillon 		 */
6490fe46dc6SMatthew Dillon 		output[9] = '\0';
6500fe46dc6SMatthew Dillon 		p = output + strlen(output);
6510fe46dc6SMatthew Dillon 	} else {
6520fe46dc6SMatthew Dillon 		/*
6530fe46dc6SMatthew Dillon 		 * "old"-style:
6540fe46dc6SMatthew Dillon 		 *	setting - 2 bytes of salt
6550fe46dc6SMatthew Dillon 		 *	key - up to 8 characters
6560fe46dc6SMatthew Dillon 		 */
6570fe46dc6SMatthew Dillon 		count = 25;
6580fe46dc6SMatthew Dillon 
6590fe46dc6SMatthew Dillon 		salt = (ascii_to_bin(setting[1]) << 6)
6600fe46dc6SMatthew Dillon 		     |  ascii_to_bin(setting[0]);
6610fe46dc6SMatthew Dillon 
6620fe46dc6SMatthew Dillon 		output[0] = setting[0];
6630fe46dc6SMatthew Dillon 		/*
6640fe46dc6SMatthew Dillon 		 * If the encrypted password that the salt was extracted from
6650fe46dc6SMatthew Dillon 		 * is only 1 character long, the salt will be corrupted.  We
6660fe46dc6SMatthew Dillon 		 * need to ensure that the output string doesn't have an extra
6670fe46dc6SMatthew Dillon 		 * NUL in it!
6680fe46dc6SMatthew Dillon 		 */
6690fe46dc6SMatthew Dillon 		output[1] = setting[1] ? setting[1] : output[0];
6700fe46dc6SMatthew Dillon 
6710fe46dc6SMatthew Dillon 		p = output + 2;
6720fe46dc6SMatthew Dillon 	}
6730fe46dc6SMatthew Dillon 	setup_salt(salt);
6740fe46dc6SMatthew Dillon 	/*
6750fe46dc6SMatthew Dillon 	 * Do it.
6760fe46dc6SMatthew Dillon 	 */
6770fe46dc6SMatthew Dillon 	if (do_des(0L, 0L, &r0, &r1, count))
6780fe46dc6SMatthew Dillon 		return(NULL);
6790fe46dc6SMatthew Dillon 	/*
6800fe46dc6SMatthew Dillon 	 * Now encode the result...
6810fe46dc6SMatthew Dillon 	 */
6820fe46dc6SMatthew Dillon 	l = (r0 >> 8);
6830fe46dc6SMatthew Dillon 	*p++ = ascii64[(l >> 18) & 0x3f];
6840fe46dc6SMatthew Dillon 	*p++ = ascii64[(l >> 12) & 0x3f];
6850fe46dc6SMatthew Dillon 	*p++ = ascii64[(l >> 6) & 0x3f];
6860fe46dc6SMatthew Dillon 	*p++ = ascii64[l & 0x3f];
6870fe46dc6SMatthew Dillon 
6880fe46dc6SMatthew Dillon 	l = (r0 << 16) | ((r1 >> 16) & 0xffff);
6890fe46dc6SMatthew Dillon 	*p++ = ascii64[(l >> 18) & 0x3f];
6900fe46dc6SMatthew Dillon 	*p++ = ascii64[(l >> 12) & 0x3f];
6910fe46dc6SMatthew Dillon 	*p++ = ascii64[(l >> 6) & 0x3f];
6920fe46dc6SMatthew Dillon 	*p++ = ascii64[l & 0x3f];
6930fe46dc6SMatthew Dillon 
6940fe46dc6SMatthew Dillon 	l = r1 << 2;
6950fe46dc6SMatthew Dillon 	*p++ = ascii64[(l >> 12) & 0x3f];
6960fe46dc6SMatthew Dillon 	*p++ = ascii64[(l >> 6) & 0x3f];
6970fe46dc6SMatthew Dillon 	*p++ = ascii64[l & 0x3f];
6980fe46dc6SMatthew Dillon 	*p = 0;
6990fe46dc6SMatthew Dillon 
7000fe46dc6SMatthew Dillon 	return(output);
7010fe46dc6SMatthew Dillon }
702*bc4d84b2Szrj 
703*bc4d84b2Szrj /*
704*bc4d84b2Szrj  * For crypt_xsi.c compatibility.
705*bc4d84b2Szrj  */
706*bc4d84b2Szrj 
707*bc4d84b2Szrj typedef union {
708*bc4d84b2Szrj 	unsigned char b[8];
709*bc4d84b2Szrj 	struct {
710*bc4d84b2Szrj 		int32_t	i0;
711*bc4d84b2Szrj 		int32_t	i1;
712*bc4d84b2Szrj 	} b32;
713*bc4d84b2Szrj } C_block;
714*bc4d84b2Szrj 
715*bc4d84b2Szrj int
__crypt_setkey(const char * key)716*bc4d84b2Szrj __crypt_setkey(const char *key)
717*bc4d84b2Szrj {
718*bc4d84b2Szrj 	int i, j, k;
719*bc4d84b2Szrj 	C_block keyblock;
720*bc4d84b2Szrj 
721*bc4d84b2Szrj 	for (i = 0; i < 8; i++) {
722*bc4d84b2Szrj 		k = 0;
723*bc4d84b2Szrj 		for (j = 0; j < 8; j++) {
724*bc4d84b2Szrj 			k <<= 1;
725*bc4d84b2Szrj 			k |= (unsigned char)*key++;
726*bc4d84b2Szrj 		}
727*bc4d84b2Szrj 		keyblock.b[i] = k;
728*bc4d84b2Szrj 	}
729*bc4d84b2Szrj 	return (des_setkey((char *)keyblock.b));
730*bc4d84b2Szrj }
731*bc4d84b2Szrj 
732*bc4d84b2Szrj int
__crypt_encrypt(char * block,int flag)733*bc4d84b2Szrj __crypt_encrypt(char *block, int flag)
734*bc4d84b2Szrj {
735*bc4d84b2Szrj 	int i, j, k;
736*bc4d84b2Szrj 	C_block cblock;
737*bc4d84b2Szrj 
738*bc4d84b2Szrj 	for (i = 0; i < 8; i++) {
739*bc4d84b2Szrj 		k = 0;
740*bc4d84b2Szrj 		for (j = 0; j < 8; j++) {
741*bc4d84b2Szrj 			k <<= 1;
742*bc4d84b2Szrj 			k |= (unsigned char)*block++;
743*bc4d84b2Szrj 		}
744*bc4d84b2Szrj 		cblock.b[i] = k;
745*bc4d84b2Szrj 	}
746*bc4d84b2Szrj 	if (des_cipher((char *)&cblock, (char *)&cblock, 0L, (flag ? -1: 1)))
747*bc4d84b2Szrj 		return (1);
748*bc4d84b2Szrj 	for (i = 7; i >= 0; i--) {
749*bc4d84b2Szrj 		k = cblock.b[i];
750*bc4d84b2Szrj 		for (j = 7; j >= 0; j--) {
751*bc4d84b2Szrj 			*--block = k&01;
752*bc4d84b2Szrj 			k >>= 1;
753*bc4d84b2Szrj 		}
754*bc4d84b2Szrj 	}
755*bc4d84b2Szrj 	return (0);
756*bc4d84b2Szrj }
757