xref: /freebsd/secure/lib/libcrypt/crypt-des.c (revision c8813424c9d126a6a743269f6e092d4fd8b39e0a)
1c4f09032SGeoff Rehmet /*
2c4f09032SGeoff Rehmet  * FreeSec: libcrypt for NetBSD
3c4f09032SGeoff Rehmet  *
4c4f09032SGeoff Rehmet  * Copyright (c) 1994 David Burren
5c4f09032SGeoff Rehmet  * All rights reserved.
6c4f09032SGeoff Rehmet  *
7712ca8b4SGeoff Rehmet  * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet
8e1e54354SMark Murray  *	this file should now *only* export crypt(), in order to make
9712ca8b4SGeoff Rehmet  *	binaries of libcrypt exportable from the USA
10712ca8b4SGeoff Rehmet  *
11e1e54354SMark Murray  * Adapted for FreeBSD-4.0 by Mark R V Murray
12e1e54354SMark Murray  *	this file should now *only* export crypt_des(), in order to make
13e1e54354SMark Murray  *	a module that can be optionally included in libcrypt.
14e1e54354SMark Murray  *
15c4f09032SGeoff Rehmet  * Redistribution and use in source and binary forms, with or without
16c4f09032SGeoff Rehmet  * modification, are permitted provided that the following conditions
17c4f09032SGeoff Rehmet  * are met:
18c4f09032SGeoff Rehmet  * 1. Redistributions of source code must retain the above copyright
19c4f09032SGeoff Rehmet  *    notice, this list of conditions and the following disclaimer.
20c4f09032SGeoff Rehmet  * 2. Redistributions in binary form must reproduce the above copyright
21c4f09032SGeoff Rehmet  *    notice, this list of conditions and the following disclaimer in the
22c4f09032SGeoff Rehmet  *    documentation and/or other materials provided with the distribution.
23e1e54354SMark Murray  * 3. Neither the name of the author nor the names of other contributors
24c4f09032SGeoff Rehmet  *    may be used to endorse or promote products derived from this software
25c4f09032SGeoff Rehmet  *    without specific prior written permission.
26c4f09032SGeoff Rehmet  *
27c4f09032SGeoff Rehmet  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28c4f09032SGeoff Rehmet  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29c4f09032SGeoff Rehmet  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30c4f09032SGeoff Rehmet  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31c4f09032SGeoff Rehmet  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32c4f09032SGeoff Rehmet  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33c4f09032SGeoff Rehmet  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34c4f09032SGeoff Rehmet  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35c4f09032SGeoff Rehmet  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36c4f09032SGeoff Rehmet  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37c4f09032SGeoff Rehmet  * SUCH DAMAGE.
38c4f09032SGeoff Rehmet  *
39c4f09032SGeoff Rehmet  * This is an original implementation of the DES and the crypt(3) interfaces
40c4f09032SGeoff Rehmet  * by David Burren <davidb@werj.com.au>.
41c4f09032SGeoff Rehmet  *
42c4f09032SGeoff Rehmet  * An excellent reference on the underlying algorithm (and related
43c4f09032SGeoff Rehmet  * algorithms) is:
44c4f09032SGeoff Rehmet  *
45c4f09032SGeoff Rehmet  *	B. Schneier, Applied Cryptography: protocols, algorithms,
46c4f09032SGeoff Rehmet  *	and source code in C, John Wiley & Sons, 1994.
47c4f09032SGeoff Rehmet  *
48c4f09032SGeoff Rehmet  * Note that in that book's description of DES the lookups for the initial,
49c4f09032SGeoff Rehmet  * pbox, and final permutations are inverted (this has been brought to the
50c4f09032SGeoff Rehmet  * attention of the author).  A list of errata for this book has been
51c4f09032SGeoff Rehmet  * posted to the sci.crypt newsgroup by the author and is available for FTP.
52c4f09032SGeoff Rehmet  *
53c4f09032SGeoff Rehmet  * ARCHITECTURE ASSUMPTIONS:
54c4f09032SGeoff Rehmet  *	It is assumed that the 8-byte arrays passed by reference can be
55e1e54354SMark Murray  *	addressed as arrays of u_int32_t's (ie. the CPU is not picky about
56c4f09032SGeoff Rehmet  *	alignment).
57c4f09032SGeoff Rehmet  */
5868344a95SPeter Wemm 
59c4f09032SGeoff Rehmet #include <sys/types.h>
60c4f09032SGeoff Rehmet #include <sys/param.h>
61fd8e4ebcSMike Barcroft #include <arpa/inet.h>
62c4f09032SGeoff Rehmet #include <pwd.h>
6396e718feSMark Murray #include <string.h>
64e1e54354SMark Murray #include "crypt.h"
65c4f09032SGeoff Rehmet 
66712ca8b4SGeoff Rehmet /* We can't always assume gcc */
67f2ac424aSMark Murray #if	defined(__GNUC__) && !defined(lint)
68712ca8b4SGeoff Rehmet #define INLINE inline
69f2ac424aSMark Murray #else
70f2ac424aSMark Murray #define INLINE
71712ca8b4SGeoff Rehmet #endif
72712ca8b4SGeoff Rehmet 
73c4f09032SGeoff Rehmet 
74*7d681ad7SEdward Tomasz Napierala static const u_char	IP[64] = {
75c4f09032SGeoff Rehmet 	58, 50, 42, 34, 26, 18, 10,  2, 60, 52, 44, 36, 28, 20, 12,  4,
76c4f09032SGeoff Rehmet 	62, 54, 46, 38, 30, 22, 14,  6, 64, 56, 48, 40, 32, 24, 16,  8,
77c4f09032SGeoff Rehmet 	57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11,  3,
78c4f09032SGeoff Rehmet 	61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15,  7
79c4f09032SGeoff Rehmet };
80c4f09032SGeoff Rehmet 
81*7d681ad7SEdward Tomasz Napierala static __thread u_char	inv_key_perm[64];
82*7d681ad7SEdward Tomasz Napierala static const u_char	key_perm[56] = {
83c4f09032SGeoff Rehmet 	57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
84c4f09032SGeoff Rehmet 	10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
85c4f09032SGeoff Rehmet 	63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
86c4f09032SGeoff Rehmet 	14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
87c4f09032SGeoff Rehmet };
88c4f09032SGeoff Rehmet 
89*7d681ad7SEdward Tomasz Napierala static const u_char	key_shifts[16] = {
90c4f09032SGeoff Rehmet 	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
91c4f09032SGeoff Rehmet };
92c4f09032SGeoff Rehmet 
93*7d681ad7SEdward Tomasz Napierala static __thread u_char	inv_comp_perm[56];
94*7d681ad7SEdward Tomasz Napierala static const u_char	comp_perm[48] = {
95c4f09032SGeoff Rehmet 	14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
96c4f09032SGeoff Rehmet 	23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
97c4f09032SGeoff Rehmet 	41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
98c4f09032SGeoff Rehmet 	44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
99c4f09032SGeoff Rehmet };
100c4f09032SGeoff Rehmet 
101c4f09032SGeoff Rehmet /*
102c4f09032SGeoff Rehmet  *	No E box is used, as it's replaced by some ANDs, shifts, and ORs.
103c4f09032SGeoff Rehmet  */
104c4f09032SGeoff Rehmet 
105*7d681ad7SEdward Tomasz Napierala static __thread u_char	u_sbox[8][64];
106*7d681ad7SEdward Tomasz Napierala static const u_char	sbox[8][64] = {
107c4f09032SGeoff Rehmet 	{
108c4f09032SGeoff Rehmet 		14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
109c4f09032SGeoff Rehmet 		 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
110c4f09032SGeoff Rehmet 		 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
111c4f09032SGeoff Rehmet 		15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
112c4f09032SGeoff Rehmet 	},
113c4f09032SGeoff Rehmet 	{
114c4f09032SGeoff Rehmet 		15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
115c4f09032SGeoff Rehmet 		 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
116c4f09032SGeoff Rehmet 		 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
117c4f09032SGeoff Rehmet 		13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9
118c4f09032SGeoff Rehmet 	},
119c4f09032SGeoff Rehmet 	{
120c4f09032SGeoff Rehmet 		10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
121c4f09032SGeoff Rehmet 		13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
122c4f09032SGeoff Rehmet 		13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
123c4f09032SGeoff Rehmet 		 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12
124c4f09032SGeoff Rehmet 	},
125c4f09032SGeoff Rehmet 	{
126c4f09032SGeoff Rehmet 		 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
127c4f09032SGeoff Rehmet 		13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
128c4f09032SGeoff Rehmet 		10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
129c4f09032SGeoff Rehmet 		 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14
130c4f09032SGeoff Rehmet 	},
131c4f09032SGeoff Rehmet 	{
132c4f09032SGeoff Rehmet 		 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
133c4f09032SGeoff Rehmet 		14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
134c4f09032SGeoff Rehmet 		 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
135c4f09032SGeoff Rehmet 		11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3
136c4f09032SGeoff Rehmet 	},
137c4f09032SGeoff Rehmet 	{
138c4f09032SGeoff Rehmet 		12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
139c4f09032SGeoff Rehmet 		10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
140c4f09032SGeoff Rehmet 		 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
141c4f09032SGeoff Rehmet 		 4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13
142c4f09032SGeoff Rehmet 	},
143c4f09032SGeoff Rehmet 	{
144c4f09032SGeoff Rehmet 		 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
145c4f09032SGeoff Rehmet 		13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
146c4f09032SGeoff Rehmet 		 1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
147c4f09032SGeoff Rehmet 		 6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12
148c4f09032SGeoff Rehmet 	},
149c4f09032SGeoff Rehmet 	{
150c4f09032SGeoff Rehmet 		13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
151c4f09032SGeoff Rehmet 		 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
152c4f09032SGeoff Rehmet 		 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
153c4f09032SGeoff Rehmet 		 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
154c4f09032SGeoff Rehmet 	}
155c4f09032SGeoff Rehmet };
156c4f09032SGeoff Rehmet 
157*7d681ad7SEdward Tomasz Napierala static __thread u_char	un_pbox[32];
158*7d681ad7SEdward Tomasz Napierala static const u_char	pbox[32] = {
159c4f09032SGeoff Rehmet 	16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
160c4f09032SGeoff Rehmet 	 2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
161c4f09032SGeoff Rehmet };
162c4f09032SGeoff Rehmet 
163*7d681ad7SEdward Tomasz Napierala static const u_int32_t	bits32[32] =
164c4f09032SGeoff Rehmet {
165c4f09032SGeoff Rehmet 	0x80000000, 0x40000000, 0x20000000, 0x10000000,
166c4f09032SGeoff Rehmet 	0x08000000, 0x04000000, 0x02000000, 0x01000000,
167c4f09032SGeoff Rehmet 	0x00800000, 0x00400000, 0x00200000, 0x00100000,
168c4f09032SGeoff Rehmet 	0x00080000, 0x00040000, 0x00020000, 0x00010000,
169c4f09032SGeoff Rehmet 	0x00008000, 0x00004000, 0x00002000, 0x00001000,
170c4f09032SGeoff Rehmet 	0x00000800, 0x00000400, 0x00000200, 0x00000100,
171c4f09032SGeoff Rehmet 	0x00000080, 0x00000040, 0x00000020, 0x00000010,
172c4f09032SGeoff Rehmet 	0x00000008, 0x00000004, 0x00000002, 0x00000001
173c4f09032SGeoff Rehmet };
174c4f09032SGeoff Rehmet 
175*7d681ad7SEdward Tomasz Napierala static const u_char	bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
176c4f09032SGeoff Rehmet 
177*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	saltbits;
178*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	old_salt;
179*7d681ad7SEdward Tomasz Napierala static __thread const u_int32_t	*bits28, *bits24;
180*7d681ad7SEdward Tomasz Napierala static __thread u_char		init_perm[64], final_perm[64];
181*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	en_keysl[16], en_keysr[16];
182*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	de_keysl[16], de_keysr[16];
183*7d681ad7SEdward Tomasz Napierala static __thread int		des_initialised = 0;
184*7d681ad7SEdward Tomasz Napierala static __thread u_char		m_sbox[4][4096];
185*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	psbox[4][256];
186*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	ip_maskl[8][256], ip_maskr[8][256];
187*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	fp_maskl[8][256], fp_maskr[8][256];
188*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	key_perm_maskl[8][128], key_perm_maskr[8][128];
189*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	comp_maskl[8][128], comp_maskr[8][128];
190*7d681ad7SEdward Tomasz Napierala static __thread u_int32_t	old_rawkey0, old_rawkey1;
191c4f09032SGeoff Rehmet 
192*7d681ad7SEdward Tomasz Napierala static const u_char	ascii64[] =
193c4f09032SGeoff Rehmet 	 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
194c4f09032SGeoff Rehmet /*	  0000000000111111111122222222223333333333444444444455555555556666 */
195c4f09032SGeoff Rehmet /*	  0123456789012345678901234567890123456789012345678901234567890123 */
196c4f09032SGeoff Rehmet 
197712ca8b4SGeoff Rehmet static INLINE int
ascii_to_bin(char ch)198c4f09032SGeoff Rehmet ascii_to_bin(char ch)
199c4f09032SGeoff Rehmet {
200c4f09032SGeoff Rehmet 	if (ch > 'z')
201c4f09032SGeoff Rehmet 		return(0);
202c4f09032SGeoff Rehmet 	if (ch >= 'a')
203c4f09032SGeoff Rehmet 		return(ch - 'a' + 38);
204c4f09032SGeoff Rehmet 	if (ch > 'Z')
205c4f09032SGeoff Rehmet 		return(0);
206c4f09032SGeoff Rehmet 	if (ch >= 'A')
207c4f09032SGeoff Rehmet 		return(ch - 'A' + 12);
208c4f09032SGeoff Rehmet 	if (ch > '9')
209c4f09032SGeoff Rehmet 		return(0);
210c4f09032SGeoff Rehmet 	if (ch >= '.')
211c4f09032SGeoff Rehmet 		return(ch - '.');
212c4f09032SGeoff Rehmet 	return(0);
213c4f09032SGeoff Rehmet }
214c4f09032SGeoff Rehmet 
215c4f09032SGeoff Rehmet static void
des_init(void)216f2ac424aSMark Murray des_init(void)
217c4f09032SGeoff Rehmet {
218c4f09032SGeoff Rehmet 	int	i, j, b, k, inbit, obit;
219e1e54354SMark Murray 	u_int32_t	*p, *il, *ir, *fl, *fr;
220c4f09032SGeoff Rehmet 
221c4f09032SGeoff Rehmet 	old_rawkey0 = old_rawkey1 = 0L;
222c4f09032SGeoff Rehmet 	saltbits = 0L;
223c4f09032SGeoff Rehmet 	old_salt = 0L;
224c4f09032SGeoff Rehmet 	bits24 = (bits28 = bits32 + 4) + 4;
225c4f09032SGeoff Rehmet 
226c4f09032SGeoff Rehmet 	/*
227c4f09032SGeoff Rehmet 	 * Invert the S-boxes, reordering the input bits.
228c4f09032SGeoff Rehmet 	 */
229c4f09032SGeoff Rehmet 	for (i = 0; i < 8; i++)
230c4f09032SGeoff Rehmet 		for (j = 0; j < 64; j++) {
231c4f09032SGeoff Rehmet 			b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
232c4f09032SGeoff Rehmet 			u_sbox[i][j] = sbox[i][b];
233c4f09032SGeoff Rehmet 		}
234c4f09032SGeoff Rehmet 
235c4f09032SGeoff Rehmet 	/*
236c4f09032SGeoff Rehmet 	 * Convert the inverted S-boxes into 4 arrays of 8 bits.
237c4f09032SGeoff Rehmet 	 * Each will handle 12 bits of the S-box input.
238c4f09032SGeoff Rehmet 	 */
239c4f09032SGeoff Rehmet 	for (b = 0; b < 4; b++)
240c4f09032SGeoff Rehmet 		for (i = 0; i < 64; i++)
241c4f09032SGeoff Rehmet 			for (j = 0; j < 64; j++)
242c4f09032SGeoff Rehmet 				m_sbox[b][(i << 6) | j] =
243f2ac424aSMark Murray 					(u_char)((u_sbox[(b << 1)][i] << 4) |
244f2ac424aSMark Murray 					u_sbox[(b << 1) + 1][j]);
245c4f09032SGeoff Rehmet 
246c4f09032SGeoff Rehmet 	/*
247c4f09032SGeoff Rehmet 	 * Set up the initial & final permutations into a useful form, and
248c4f09032SGeoff Rehmet 	 * initialise the inverted key permutation.
249c4f09032SGeoff Rehmet 	 */
250c4f09032SGeoff Rehmet 	for (i = 0; i < 64; i++) {
251f2ac424aSMark Murray 		init_perm[final_perm[i] = IP[i] - 1] = (u_char)i;
252c4f09032SGeoff Rehmet 		inv_key_perm[i] = 255;
253c4f09032SGeoff Rehmet 	}
254c4f09032SGeoff Rehmet 
255c4f09032SGeoff Rehmet 	/*
256c4f09032SGeoff Rehmet 	 * Invert the key permutation and initialise the inverted key
257c4f09032SGeoff Rehmet 	 * compression permutation.
258c4f09032SGeoff Rehmet 	 */
259c4f09032SGeoff Rehmet 	for (i = 0; i < 56; i++) {
260f2ac424aSMark Murray 		inv_key_perm[key_perm[i] - 1] = (u_char)i;
261c4f09032SGeoff Rehmet 		inv_comp_perm[i] = 255;
262c4f09032SGeoff Rehmet 	}
263c4f09032SGeoff Rehmet 
264c4f09032SGeoff Rehmet 	/*
265c4f09032SGeoff Rehmet 	 * Invert the key compression permutation.
266c4f09032SGeoff Rehmet 	 */
267c4f09032SGeoff Rehmet 	for (i = 0; i < 48; i++) {
268f2ac424aSMark Murray 		inv_comp_perm[comp_perm[i] - 1] = (u_char)i;
269c4f09032SGeoff Rehmet 	}
270c4f09032SGeoff Rehmet 
271c4f09032SGeoff Rehmet 	/*
272c4f09032SGeoff Rehmet 	 * Set up the OR-mask arrays for the initial and final permutations,
273c4f09032SGeoff Rehmet 	 * and for the key initial and compression permutations.
274c4f09032SGeoff Rehmet 	 */
275c4f09032SGeoff Rehmet 	for (k = 0; k < 8; k++) {
276c4f09032SGeoff Rehmet 		for (i = 0; i < 256; i++) {
277c4f09032SGeoff Rehmet 			*(il = &ip_maskl[k][i]) = 0L;
278c4f09032SGeoff Rehmet 			*(ir = &ip_maskr[k][i]) = 0L;
279c4f09032SGeoff Rehmet 			*(fl = &fp_maskl[k][i]) = 0L;
280c4f09032SGeoff Rehmet 			*(fr = &fp_maskr[k][i]) = 0L;
281c4f09032SGeoff Rehmet 			for (j = 0; j < 8; j++) {
282c4f09032SGeoff Rehmet 				inbit = 8 * k + j;
283c4f09032SGeoff Rehmet 				if (i & bits8[j]) {
284c4f09032SGeoff Rehmet 					if ((obit = init_perm[inbit]) < 32)
285c4f09032SGeoff Rehmet 						*il |= bits32[obit];
286c4f09032SGeoff Rehmet 					else
287c4f09032SGeoff Rehmet 						*ir |= bits32[obit-32];
288c4f09032SGeoff Rehmet 					if ((obit = final_perm[inbit]) < 32)
289c4f09032SGeoff Rehmet 						*fl |= bits32[obit];
290c4f09032SGeoff Rehmet 					else
291c4f09032SGeoff Rehmet 						*fr |= bits32[obit - 32];
292c4f09032SGeoff Rehmet 				}
293c4f09032SGeoff Rehmet 			}
294c4f09032SGeoff Rehmet 		}
295c4f09032SGeoff Rehmet 		for (i = 0; i < 128; i++) {
296c4f09032SGeoff Rehmet 			*(il = &key_perm_maskl[k][i]) = 0L;
297c4f09032SGeoff Rehmet 			*(ir = &key_perm_maskr[k][i]) = 0L;
298c4f09032SGeoff Rehmet 			for (j = 0; j < 7; j++) {
299c4f09032SGeoff Rehmet 				inbit = 8 * k + j;
300c4f09032SGeoff Rehmet 				if (i & bits8[j + 1]) {
301c4f09032SGeoff Rehmet 					if ((obit = inv_key_perm[inbit]) == 255)
302c4f09032SGeoff Rehmet 						continue;
303c4f09032SGeoff Rehmet 					if (obit < 28)
304c4f09032SGeoff Rehmet 						*il |= bits28[obit];
305c4f09032SGeoff Rehmet 					else
306c4f09032SGeoff Rehmet 						*ir |= bits28[obit - 28];
307c4f09032SGeoff Rehmet 				}
308c4f09032SGeoff Rehmet 			}
309c4f09032SGeoff Rehmet 			*(il = &comp_maskl[k][i]) = 0L;
310c4f09032SGeoff Rehmet 			*(ir = &comp_maskr[k][i]) = 0L;
311c4f09032SGeoff Rehmet 			for (j = 0; j < 7; j++) {
312c4f09032SGeoff Rehmet 				inbit = 7 * k + j;
313c4f09032SGeoff Rehmet 				if (i & bits8[j + 1]) {
314c4f09032SGeoff Rehmet 					if ((obit=inv_comp_perm[inbit]) == 255)
315c4f09032SGeoff Rehmet 						continue;
316c4f09032SGeoff Rehmet 					if (obit < 24)
317c4f09032SGeoff Rehmet 						*il |= bits24[obit];
318c4f09032SGeoff Rehmet 					else
319c4f09032SGeoff Rehmet 						*ir |= bits24[obit - 24];
320c4f09032SGeoff Rehmet 				}
321c4f09032SGeoff Rehmet 			}
322c4f09032SGeoff Rehmet 		}
323c4f09032SGeoff Rehmet 	}
324c4f09032SGeoff Rehmet 
325c4f09032SGeoff Rehmet 	/*
326c4f09032SGeoff Rehmet 	 * Invert the P-box permutation, and convert into OR-masks for
327c4f09032SGeoff Rehmet 	 * handling the output of the S-box arrays setup above.
328c4f09032SGeoff Rehmet 	 */
329c4f09032SGeoff Rehmet 	for (i = 0; i < 32; i++)
330f2ac424aSMark Murray 		un_pbox[pbox[i] - 1] = (u_char)i;
331c4f09032SGeoff Rehmet 
332c4f09032SGeoff Rehmet 	for (b = 0; b < 4; b++)
333c4f09032SGeoff Rehmet 		for (i = 0; i < 256; i++) {
334c4f09032SGeoff Rehmet 			*(p = &psbox[b][i]) = 0L;
335c4f09032SGeoff Rehmet 			for (j = 0; j < 8; j++) {
336c4f09032SGeoff Rehmet 				if (i & bits8[j])
337c4f09032SGeoff Rehmet 					*p |= bits32[un_pbox[8 * b + j]];
338c4f09032SGeoff Rehmet 			}
339c4f09032SGeoff Rehmet 		}
340c4f09032SGeoff Rehmet 
341c4f09032SGeoff Rehmet 	des_initialised = 1;
342c4f09032SGeoff Rehmet }
343c4f09032SGeoff Rehmet 
344c4f09032SGeoff Rehmet static void
setup_salt(u_int32_t salt)345f2ac424aSMark Murray setup_salt(u_int32_t salt)
346c4f09032SGeoff Rehmet {
347e1e54354SMark Murray 	u_int32_t	obit, saltbit;
348c4f09032SGeoff Rehmet 	int		i;
349c4f09032SGeoff Rehmet 
350c4f09032SGeoff Rehmet 	if (salt == old_salt)
351c4f09032SGeoff Rehmet 		return;
352c4f09032SGeoff Rehmet 	old_salt = salt;
353c4f09032SGeoff Rehmet 
354c4f09032SGeoff Rehmet 	saltbits = 0L;
355c4f09032SGeoff Rehmet 	saltbit = 1;
356c4f09032SGeoff Rehmet 	obit = 0x800000;
357c4f09032SGeoff Rehmet 	for (i = 0; i < 24; i++) {
358c4f09032SGeoff Rehmet 		if (salt & saltbit)
359c4f09032SGeoff Rehmet 			saltbits |= obit;
360c4f09032SGeoff Rehmet 		saltbit <<= 1;
361c4f09032SGeoff Rehmet 		obit >>= 1;
362c4f09032SGeoff Rehmet 	}
363c4f09032SGeoff Rehmet }
364c4f09032SGeoff Rehmet 
365bf8f9d53SPaul Traina static int
des_setkey(const char * key)366c4f09032SGeoff Rehmet des_setkey(const char *key)
367c4f09032SGeoff Rehmet {
368e1e54354SMark Murray 	u_int32_t	k0, k1, rawkey0, rawkey1;
36996e718feSMark Murray 	int		shifts, round;
370c4f09032SGeoff Rehmet 
371c4f09032SGeoff Rehmet 	if (!des_initialised)
372c4f09032SGeoff Rehmet 		des_init();
373c4f09032SGeoff Rehmet 
374f2ac424aSMark Murray 	rawkey0 = ntohl(*(const u_int32_t *) key);
375f2ac424aSMark Murray 	rawkey1 = ntohl(*(const u_int32_t *) (key + 4));
376c4f09032SGeoff Rehmet 
377c4f09032SGeoff Rehmet 	if ((rawkey0 | rawkey1)
378c4f09032SGeoff Rehmet 	    && rawkey0 == old_rawkey0
379c4f09032SGeoff Rehmet 	    && rawkey1 == old_rawkey1) {
380c4f09032SGeoff Rehmet 		/*
381c4f09032SGeoff Rehmet 		 * Already setup for this key.
382c4f09032SGeoff Rehmet 		 * This optimisation fails on a zero key (which is weak and
383c4f09032SGeoff Rehmet 		 * has bad parity anyway) in order to simplify the starting
384c4f09032SGeoff Rehmet 		 * conditions.
385c4f09032SGeoff Rehmet 		 */
386c4f09032SGeoff Rehmet 		return(0);
387c4f09032SGeoff Rehmet 	}
388c4f09032SGeoff Rehmet 	old_rawkey0 = rawkey0;
389c4f09032SGeoff Rehmet 	old_rawkey1 = rawkey1;
390c4f09032SGeoff Rehmet 
391c4f09032SGeoff Rehmet 	/*
392c4f09032SGeoff Rehmet 	 *	Do key permutation and split into two 28-bit subkeys.
393c4f09032SGeoff Rehmet 	 */
394c4f09032SGeoff Rehmet 	k0 = key_perm_maskl[0][rawkey0 >> 25]
395c4f09032SGeoff Rehmet 	   | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
396c4f09032SGeoff Rehmet 	   | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
397c4f09032SGeoff Rehmet 	   | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
398c4f09032SGeoff Rehmet 	   | key_perm_maskl[4][rawkey1 >> 25]
399c4f09032SGeoff Rehmet 	   | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
400c4f09032SGeoff Rehmet 	   | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
401c4f09032SGeoff Rehmet 	   | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
402c4f09032SGeoff Rehmet 	k1 = key_perm_maskr[0][rawkey0 >> 25]
403c4f09032SGeoff Rehmet 	   | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
404c4f09032SGeoff Rehmet 	   | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
405c4f09032SGeoff Rehmet 	   | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
406c4f09032SGeoff Rehmet 	   | key_perm_maskr[4][rawkey1 >> 25]
407c4f09032SGeoff Rehmet 	   | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
408c4f09032SGeoff Rehmet 	   | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
409c4f09032SGeoff Rehmet 	   | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
410c4f09032SGeoff Rehmet 	/*
411c4f09032SGeoff Rehmet 	 *	Rotate subkeys and do compression permutation.
412c4f09032SGeoff Rehmet 	 */
413c4f09032SGeoff Rehmet 	shifts = 0;
414c4f09032SGeoff Rehmet 	for (round = 0; round < 16; round++) {
415e1e54354SMark Murray 		u_int32_t	t0, t1;
416c4f09032SGeoff Rehmet 
417c4f09032SGeoff Rehmet 		shifts += key_shifts[round];
418c4f09032SGeoff Rehmet 
419c4f09032SGeoff Rehmet 		t0 = (k0 << shifts) | (k0 >> (28 - shifts));
420c4f09032SGeoff Rehmet 		t1 = (k1 << shifts) | (k1 >> (28 - shifts));
421c4f09032SGeoff Rehmet 
422c4f09032SGeoff Rehmet 		de_keysl[15 - round] =
423c4f09032SGeoff Rehmet 		en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
424c4f09032SGeoff Rehmet 				| comp_maskl[1][(t0 >> 14) & 0x7f]
425c4f09032SGeoff Rehmet 				| comp_maskl[2][(t0 >> 7) & 0x7f]
426c4f09032SGeoff Rehmet 				| comp_maskl[3][t0 & 0x7f]
427c4f09032SGeoff Rehmet 				| comp_maskl[4][(t1 >> 21) & 0x7f]
428c4f09032SGeoff Rehmet 				| comp_maskl[5][(t1 >> 14) & 0x7f]
429c4f09032SGeoff Rehmet 				| comp_maskl[6][(t1 >> 7) & 0x7f]
430c4f09032SGeoff Rehmet 				| comp_maskl[7][t1 & 0x7f];
431c4f09032SGeoff Rehmet 
432c4f09032SGeoff Rehmet 		de_keysr[15 - round] =
433c4f09032SGeoff Rehmet 		en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
434c4f09032SGeoff Rehmet 				| comp_maskr[1][(t0 >> 14) & 0x7f]
435c4f09032SGeoff Rehmet 				| comp_maskr[2][(t0 >> 7) & 0x7f]
436c4f09032SGeoff Rehmet 				| comp_maskr[3][t0 & 0x7f]
437c4f09032SGeoff Rehmet 				| comp_maskr[4][(t1 >> 21) & 0x7f]
438c4f09032SGeoff Rehmet 				| comp_maskr[5][(t1 >> 14) & 0x7f]
439c4f09032SGeoff Rehmet 				| comp_maskr[6][(t1 >> 7) & 0x7f]
440c4f09032SGeoff Rehmet 				| comp_maskr[7][t1 & 0x7f];
441c4f09032SGeoff Rehmet 	}
442c4f09032SGeoff Rehmet 	return(0);
443c4f09032SGeoff Rehmet }
444c4f09032SGeoff Rehmet 
445c4f09032SGeoff Rehmet 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)446e1e54354SMark Murray do_des(	u_int32_t l_in, u_int32_t r_in, u_int32_t *l_out, u_int32_t *r_out, int count)
447c4f09032SGeoff Rehmet {
448c4f09032SGeoff Rehmet 	/*
449c4f09032SGeoff Rehmet 	 *	l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
450c4f09032SGeoff Rehmet 	 */
451e1e54354SMark Murray 	u_int32_t	l, r, *kl, *kr, *kl1, *kr1;
452e1e54354SMark Murray 	u_int32_t	f, r48l, r48r;
45396e718feSMark Murray 	int		round;
454c4f09032SGeoff Rehmet 
455c4f09032SGeoff Rehmet 	if (count == 0) {
456c4f09032SGeoff Rehmet 		return(1);
457c4f09032SGeoff Rehmet 	} else if (count > 0) {
458c4f09032SGeoff Rehmet 		/*
459c4f09032SGeoff Rehmet 		 * Encrypting
460c4f09032SGeoff Rehmet 		 */
461c4f09032SGeoff Rehmet 		kl1 = en_keysl;
462c4f09032SGeoff Rehmet 		kr1 = en_keysr;
463c4f09032SGeoff Rehmet 	} else {
464c4f09032SGeoff Rehmet 		/*
465c4f09032SGeoff Rehmet 		 * Decrypting
466c4f09032SGeoff Rehmet 		 */
467c4f09032SGeoff Rehmet 		count = -count;
468c4f09032SGeoff Rehmet 		kl1 = de_keysl;
469c4f09032SGeoff Rehmet 		kr1 = de_keysr;
470c4f09032SGeoff Rehmet 	}
471c4f09032SGeoff Rehmet 
472c4f09032SGeoff Rehmet 	/*
473c4f09032SGeoff Rehmet 	 *	Do initial permutation (IP).
474c4f09032SGeoff Rehmet 	 */
475c4f09032SGeoff Rehmet 	l = ip_maskl[0][l_in >> 24]
476c4f09032SGeoff Rehmet 	  | ip_maskl[1][(l_in >> 16) & 0xff]
477c4f09032SGeoff Rehmet 	  | ip_maskl[2][(l_in >> 8) & 0xff]
478c4f09032SGeoff Rehmet 	  | ip_maskl[3][l_in & 0xff]
479c4f09032SGeoff Rehmet 	  | ip_maskl[4][r_in >> 24]
480c4f09032SGeoff Rehmet 	  | ip_maskl[5][(r_in >> 16) & 0xff]
481c4f09032SGeoff Rehmet 	  | ip_maskl[6][(r_in >> 8) & 0xff]
482c4f09032SGeoff Rehmet 	  | ip_maskl[7][r_in & 0xff];
483c4f09032SGeoff Rehmet 	r = ip_maskr[0][l_in >> 24]
484c4f09032SGeoff Rehmet 	  | ip_maskr[1][(l_in >> 16) & 0xff]
485c4f09032SGeoff Rehmet 	  | ip_maskr[2][(l_in >> 8) & 0xff]
486c4f09032SGeoff Rehmet 	  | ip_maskr[3][l_in & 0xff]
487c4f09032SGeoff Rehmet 	  | ip_maskr[4][r_in >> 24]
488c4f09032SGeoff Rehmet 	  | ip_maskr[5][(r_in >> 16) & 0xff]
489c4f09032SGeoff Rehmet 	  | ip_maskr[6][(r_in >> 8) & 0xff]
490c4f09032SGeoff Rehmet 	  | ip_maskr[7][r_in & 0xff];
491c4f09032SGeoff Rehmet 
492c4f09032SGeoff Rehmet 	while (count--) {
493c4f09032SGeoff Rehmet 		/*
494c4f09032SGeoff Rehmet 		 * Do each round.
495c4f09032SGeoff Rehmet 		 */
496c4f09032SGeoff Rehmet 		kl = kl1;
497c4f09032SGeoff Rehmet 		kr = kr1;
498c4f09032SGeoff Rehmet 		round = 16;
499c4f09032SGeoff Rehmet 		while (round--) {
500c4f09032SGeoff Rehmet 			/*
501c4f09032SGeoff Rehmet 			 * Expand R to 48 bits (simulate the E-box).
502c4f09032SGeoff Rehmet 			 */
503c4f09032SGeoff Rehmet 			r48l	= ((r & 0x00000001) << 23)
504c4f09032SGeoff Rehmet 				| ((r & 0xf8000000) >> 9)
505c4f09032SGeoff Rehmet 				| ((r & 0x1f800000) >> 11)
506c4f09032SGeoff Rehmet 				| ((r & 0x01f80000) >> 13)
507c4f09032SGeoff Rehmet 				| ((r & 0x001f8000) >> 15);
508c4f09032SGeoff Rehmet 
509c4f09032SGeoff Rehmet 			r48r	= ((r & 0x0001f800) << 7)
510c4f09032SGeoff Rehmet 				| ((r & 0x00001f80) << 5)
511c4f09032SGeoff Rehmet 				| ((r & 0x000001f8) << 3)
512c4f09032SGeoff Rehmet 				| ((r & 0x0000001f) << 1)
513c4f09032SGeoff Rehmet 				| ((r & 0x80000000) >> 31);
514c4f09032SGeoff Rehmet 			/*
515c4f09032SGeoff Rehmet 			 * Do salting for crypt() and friends, and
516c4f09032SGeoff Rehmet 			 * XOR with the permuted key.
517c4f09032SGeoff Rehmet 			 */
518c4f09032SGeoff Rehmet 			f = (r48l ^ r48r) & saltbits;
519c4f09032SGeoff Rehmet 			r48l ^= f ^ *kl++;
520c4f09032SGeoff Rehmet 			r48r ^= f ^ *kr++;
521c4f09032SGeoff Rehmet 			/*
522c4f09032SGeoff Rehmet 			 * Do sbox lookups (which shrink it back to 32 bits)
523c4f09032SGeoff Rehmet 			 * and do the pbox permutation at the same time.
524c4f09032SGeoff Rehmet 			 */
525c4f09032SGeoff Rehmet 			f = psbox[0][m_sbox[0][r48l >> 12]]
526c4f09032SGeoff Rehmet 			  | psbox[1][m_sbox[1][r48l & 0xfff]]
527c4f09032SGeoff Rehmet 			  | psbox[2][m_sbox[2][r48r >> 12]]
528c4f09032SGeoff Rehmet 			  | psbox[3][m_sbox[3][r48r & 0xfff]];
529c4f09032SGeoff Rehmet 			/*
530c4f09032SGeoff Rehmet 			 * Now that we've permuted things, complete f().
531c4f09032SGeoff Rehmet 			 */
532c4f09032SGeoff Rehmet 			f ^= l;
533c4f09032SGeoff Rehmet 			l = r;
534c4f09032SGeoff Rehmet 			r = f;
535c4f09032SGeoff Rehmet 		}
536c4f09032SGeoff Rehmet 		r = l;
537c4f09032SGeoff Rehmet 		l = f;
538c4f09032SGeoff Rehmet 	}
539c4f09032SGeoff Rehmet 	/*
540c4f09032SGeoff Rehmet 	 * Do final permutation (inverse of IP).
541c4f09032SGeoff Rehmet 	 */
542c4f09032SGeoff Rehmet 	*l_out	= fp_maskl[0][l >> 24]
543c4f09032SGeoff Rehmet 		| fp_maskl[1][(l >> 16) & 0xff]
544c4f09032SGeoff Rehmet 		| fp_maskl[2][(l >> 8) & 0xff]
545c4f09032SGeoff Rehmet 		| fp_maskl[3][l & 0xff]
546c4f09032SGeoff Rehmet 		| fp_maskl[4][r >> 24]
547c4f09032SGeoff Rehmet 		| fp_maskl[5][(r >> 16) & 0xff]
548c4f09032SGeoff Rehmet 		| fp_maskl[6][(r >> 8) & 0xff]
549c4f09032SGeoff Rehmet 		| fp_maskl[7][r & 0xff];
550c4f09032SGeoff Rehmet 	*r_out	= fp_maskr[0][l >> 24]
551c4f09032SGeoff Rehmet 		| fp_maskr[1][(l >> 16) & 0xff]
552c4f09032SGeoff Rehmet 		| fp_maskr[2][(l >> 8) & 0xff]
553c4f09032SGeoff Rehmet 		| fp_maskr[3][l & 0xff]
554c4f09032SGeoff Rehmet 		| fp_maskr[4][r >> 24]
555c4f09032SGeoff Rehmet 		| fp_maskr[5][(r >> 16) & 0xff]
556c4f09032SGeoff Rehmet 		| fp_maskr[6][(r >> 8) & 0xff]
557c4f09032SGeoff Rehmet 		| fp_maskr[7][r & 0xff];
558c4f09032SGeoff Rehmet 	return(0);
559c4f09032SGeoff Rehmet }
560c4f09032SGeoff Rehmet 
561bf8f9d53SPaul Traina static int
des_cipher(const char * in,char * out,u_long salt,int count)562f2ac424aSMark Murray des_cipher(const char *in, char *out, u_long salt, int count)
563c4f09032SGeoff Rehmet {
564e1e54354SMark Murray 	u_int32_t	l_out, r_out, rawl, rawr;
565c4f09032SGeoff Rehmet 	int		retval;
566f2ac424aSMark Murray 	union {
567f2ac424aSMark Murray 		u_int32_t	*ui32;
568f2ac424aSMark Murray 		const char	*c;
569f2ac424aSMark Murray 	} trans;
570c4f09032SGeoff Rehmet 
571c4f09032SGeoff Rehmet 	if (!des_initialised)
572c4f09032SGeoff Rehmet 		des_init();
573c4f09032SGeoff Rehmet 
574c4f09032SGeoff Rehmet 	setup_salt(salt);
575c4f09032SGeoff Rehmet 
576f2ac424aSMark Murray 	trans.c = in;
577f2ac424aSMark Murray 	rawl = ntohl(*trans.ui32++);
578f2ac424aSMark Murray 	rawr = ntohl(*trans.ui32);
579c4f09032SGeoff Rehmet 
580c4f09032SGeoff Rehmet 	retval = do_des(rawl, rawr, &l_out, &r_out, count);
581c4f09032SGeoff Rehmet 
582f2ac424aSMark Murray 	trans.c = out;
583f2ac424aSMark Murray 	*trans.ui32++ = htonl(l_out);
584f2ac424aSMark Murray 	*trans.ui32 = htonl(r_out);
585c4f09032SGeoff Rehmet 	return(retval);
586c4f09032SGeoff Rehmet }
587c4f09032SGeoff Rehmet 
5885f521d7bSEd Schouten int
crypt_des(const char * key,const char * setting,char * buffer)5895f521d7bSEd Schouten crypt_des(const char *key, const char *setting, char *buffer)
590c4f09032SGeoff Rehmet {
591c4f09032SGeoff Rehmet 	int		i;
592e1e54354SMark Murray 	u_int32_t	count, salt, l, r0, r1, keybuf[2];
5935f521d7bSEd Schouten 	u_char		*q;
594c4f09032SGeoff Rehmet 
595c4f09032SGeoff Rehmet 	if (!des_initialised)
596c4f09032SGeoff Rehmet 		des_init();
597c4f09032SGeoff Rehmet 
598c4f09032SGeoff Rehmet 	/*
599c4f09032SGeoff Rehmet 	 * Copy the key, shifting each character up by one bit
600c4f09032SGeoff Rehmet 	 * and padding with zeros.
601c4f09032SGeoff Rehmet 	 */
602c4f09032SGeoff Rehmet 	q = (u_char *)keybuf;
603c4f09032SGeoff Rehmet 	while (q - (u_char *)keybuf - 8) {
604f2ac424aSMark Murray 		*q++ = *key << 1;
605071183efSBjoern A. Zeeb 		if (*key != '\0')
606c4f09032SGeoff Rehmet 			key++;
607c4f09032SGeoff Rehmet 	}
608f2ac424aSMark Murray 	if (des_setkey((char *)keybuf))
6095f521d7bSEd Schouten 		return (-1);
610c4f09032SGeoff Rehmet 
611c4f09032SGeoff Rehmet 	if (*setting == _PASSWORD_EFMT1) {
612c4f09032SGeoff Rehmet 		/*
613c4f09032SGeoff Rehmet 		 * "new"-style:
614c4f09032SGeoff Rehmet 		 *	setting - underscore, 4 bytes of count, 4 bytes of salt
615c4f09032SGeoff Rehmet 		 *	key - unlimited characters
616c4f09032SGeoff Rehmet 		 */
617c4f09032SGeoff Rehmet 		for (i = 1, count = 0L; i < 5; i++)
618f2ac424aSMark Murray 			count |= ascii_to_bin(setting[i]) << ((i - 1) * 6);
619c4f09032SGeoff Rehmet 
620c4f09032SGeoff Rehmet 		for (i = 5, salt = 0L; i < 9; i++)
621f2ac424aSMark Murray 			salt |= ascii_to_bin(setting[i]) << ((i - 5) * 6);
622c4f09032SGeoff Rehmet 
623c4f09032SGeoff Rehmet 		while (*key) {
624c4f09032SGeoff Rehmet 			/*
625c4f09032SGeoff Rehmet 			 * Encrypt the key with itself.
626c4f09032SGeoff Rehmet 			 */
627f2ac424aSMark Murray 			if (des_cipher((char *)keybuf, (char *)keybuf, 0L, 1))
6285f521d7bSEd Schouten 				return (-1);
629c4f09032SGeoff Rehmet 			/*
630c4f09032SGeoff Rehmet 			 * And XOR with the next 8 characters of the key.
631c4f09032SGeoff Rehmet 			 */
632c4f09032SGeoff Rehmet 			q = (u_char *)keybuf;
633c4f09032SGeoff Rehmet 			while (q - (u_char *)keybuf - 8 && *key)
634c4f09032SGeoff Rehmet 				*q++ ^= *key++ << 1;
635c4f09032SGeoff Rehmet 
636f2ac424aSMark Murray 			if (des_setkey((char *)keybuf))
6375f521d7bSEd Schouten 				return (-1);
638c4f09032SGeoff Rehmet 		}
6395f521d7bSEd Schouten 		buffer = stpncpy(buffer, setting, 9);
640c4f09032SGeoff Rehmet 	} else {
641c4f09032SGeoff Rehmet 		/*
642c4f09032SGeoff Rehmet 		 * "old"-style:
643c4f09032SGeoff Rehmet 		 *	setting - 2 bytes of salt
644c4f09032SGeoff Rehmet 		 *	key - up to 8 characters
645c4f09032SGeoff Rehmet 		 */
646c4f09032SGeoff Rehmet 		count = 25;
647c4f09032SGeoff Rehmet 
648c4f09032SGeoff Rehmet 		salt = (ascii_to_bin(setting[1]) << 6)
649c4f09032SGeoff Rehmet 		     |  ascii_to_bin(setting[0]);
650c4f09032SGeoff Rehmet 
6515f521d7bSEd Schouten 		*buffer++ = setting[0];
65249de4157SGeoff Rehmet 		/*
65349de4157SGeoff Rehmet 		 * If the encrypted password that the salt was extracted from
65449de4157SGeoff Rehmet 		 * is only 1 character long, the salt will be corrupted.  We
65549de4157SGeoff Rehmet 		 * need to ensure that the output string doesn't have an extra
65649de4157SGeoff Rehmet 		 * NUL in it!
65749de4157SGeoff Rehmet 		 */
6585f521d7bSEd Schouten 		*buffer++ = setting[1] ? setting[1] : setting[0];
659c4f09032SGeoff Rehmet 	}
660c4f09032SGeoff Rehmet 	setup_salt(salt);
661c4f09032SGeoff Rehmet 	/*
662c4f09032SGeoff Rehmet 	 * Do it.
663c4f09032SGeoff Rehmet 	 */
664f2ac424aSMark Murray 	if (do_des(0L, 0L, &r0, &r1, (int)count))
6655f521d7bSEd Schouten 		return (-1);
666c4f09032SGeoff Rehmet 	/*
667c4f09032SGeoff Rehmet 	 * Now encode the result...
668c4f09032SGeoff Rehmet 	 */
669c4f09032SGeoff Rehmet 	l = (r0 >> 8);
6705f521d7bSEd Schouten 	*buffer++ = ascii64[(l >> 18) & 0x3f];
6715f521d7bSEd Schouten 	*buffer++ = ascii64[(l >> 12) & 0x3f];
6725f521d7bSEd Schouten 	*buffer++ = ascii64[(l >> 6) & 0x3f];
6735f521d7bSEd Schouten 	*buffer++ = ascii64[l & 0x3f];
674c4f09032SGeoff Rehmet 
675c4f09032SGeoff Rehmet 	l = (r0 << 16) | ((r1 >> 16) & 0xffff);
6765f521d7bSEd Schouten 	*buffer++ = ascii64[(l >> 18) & 0x3f];
6775f521d7bSEd Schouten 	*buffer++ = ascii64[(l >> 12) & 0x3f];
6785f521d7bSEd Schouten 	*buffer++ = ascii64[(l >> 6) & 0x3f];
6795f521d7bSEd Schouten 	*buffer++ = ascii64[l & 0x3f];
680c4f09032SGeoff Rehmet 
681c4f09032SGeoff Rehmet 	l = r1 << 2;
6825f521d7bSEd Schouten 	*buffer++ = ascii64[(l >> 12) & 0x3f];
6835f521d7bSEd Schouten 	*buffer++ = ascii64[(l >> 6) & 0x3f];
6845f521d7bSEd Schouten 	*buffer++ = ascii64[l & 0x3f];
6855f521d7bSEd Schouten 	*buffer = '\0';
686c4f09032SGeoff Rehmet 
6875f521d7bSEd Schouten 	return (0);
688c4f09032SGeoff Rehmet }
689