xref: /openbsd-src/lib/libcrypto/des/des_fcrypt.c (revision 48d3e433699451279531836f5a1bf8360c7a77be)
1*48d3e433Sjsing /* $OpenBSD: des_fcrypt.c,v 1.4 2024/08/31 16:22:18 jsing Exp $ */
2cc54cb09Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3cc54cb09Sjsing  * All rights reserved.
4cc54cb09Sjsing  *
5cc54cb09Sjsing  * This package is an SSL implementation written
6cc54cb09Sjsing  * by Eric Young (eay@cryptsoft.com).
7cc54cb09Sjsing  * The implementation was written so as to conform with Netscapes SSL.
8cc54cb09Sjsing  *
9cc54cb09Sjsing  * This library is free for commercial and non-commercial use as long as
10cc54cb09Sjsing  * the following conditions are aheared to.  The following conditions
11cc54cb09Sjsing  * apply to all code found in this distribution, be it the RC4, RSA,
12cc54cb09Sjsing  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13cc54cb09Sjsing  * included with this distribution is covered by the same copyright terms
14cc54cb09Sjsing  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15cc54cb09Sjsing  *
16cc54cb09Sjsing  * Copyright remains Eric Young's, and as such any Copyright notices in
17cc54cb09Sjsing  * the code are not to be removed.
18cc54cb09Sjsing  * If this package is used in a product, Eric Young should be given attribution
19cc54cb09Sjsing  * as the author of the parts of the library used.
20cc54cb09Sjsing  * This can be in the form of a textual message at program startup or
21cc54cb09Sjsing  * in documentation (online or textual) provided with the package.
22cc54cb09Sjsing  *
23cc54cb09Sjsing  * Redistribution and use in source and binary forms, with or without
24cc54cb09Sjsing  * modification, are permitted provided that the following conditions
25cc54cb09Sjsing  * are met:
26cc54cb09Sjsing  * 1. Redistributions of source code must retain the copyright
27cc54cb09Sjsing  *    notice, this list of conditions and the following disclaimer.
28cc54cb09Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
29cc54cb09Sjsing  *    notice, this list of conditions and the following disclaimer in the
30cc54cb09Sjsing  *    documentation and/or other materials provided with the distribution.
31cc54cb09Sjsing  * 3. All advertising materials mentioning features or use of this software
32cc54cb09Sjsing  *    must display the following acknowledgement:
33cc54cb09Sjsing  *    "This product includes cryptographic software written by
34cc54cb09Sjsing  *     Eric Young (eay@cryptsoft.com)"
35cc54cb09Sjsing  *    The word 'cryptographic' can be left out if the rouines from the library
36cc54cb09Sjsing  *    being used are not cryptographic related :-).
37cc54cb09Sjsing  * 4. If you include any Windows specific code (or a derivative thereof) from
38cc54cb09Sjsing  *    the apps directory (application code) you must include an acknowledgement:
39cc54cb09Sjsing  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40cc54cb09Sjsing  *
41cc54cb09Sjsing  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42cc54cb09Sjsing  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43cc54cb09Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44cc54cb09Sjsing  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45cc54cb09Sjsing  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46cc54cb09Sjsing  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47cc54cb09Sjsing  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48cc54cb09Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49cc54cb09Sjsing  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50cc54cb09Sjsing  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51cc54cb09Sjsing  * SUCH DAMAGE.
52cc54cb09Sjsing  *
53cc54cb09Sjsing  * The licence and distribution terms for any publically available version or
54cc54cb09Sjsing  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55cc54cb09Sjsing  * copied and put under another distribution licence
56cc54cb09Sjsing  * [including the GNU Public Licence.]
57cc54cb09Sjsing  */
58cc54cb09Sjsing 
59cc54cb09Sjsing #include <stdio.h>
60cc54cb09Sjsing 
61cc54cb09Sjsing /* This version of crypt has been developed from my MIT compatible
62cc54cb09Sjsing  * DES library.
63cc54cb09Sjsing  * Eric Young (eay@cryptsoft.com)
64cc54cb09Sjsing  */
65cc54cb09Sjsing 
66cc54cb09Sjsing /* Modification by Jens Kupferschmidt (Cu)
67cc54cb09Sjsing  * I have included directive PARA for shared memory computers.
68cc54cb09Sjsing  * I have included a directive LONGCRYPT to using this routine to cipher
69cc54cb09Sjsing  * passwords with more than 8 bytes like HP-UX 10.x it used. The MAXPLEN
70cc54cb09Sjsing  * definition is the maximum of length of password and can changed. I have
71cc54cb09Sjsing  * defined 24.
72cc54cb09Sjsing  */
73cc54cb09Sjsing 
74cc54cb09Sjsing #define DES_FCRYPT
75cc54cb09Sjsing #include "des_local.h"
76cc54cb09Sjsing #undef DES_FCRYPT
77cc54cb09Sjsing 
78cc54cb09Sjsing #undef PERM_OP
79cc54cb09Sjsing #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),			\
80cc54cb09Sjsing 	(b)^=(t),							\
81cc54cb09Sjsing 	(a)^=((t)<<(n)))
82cc54cb09Sjsing 
83cc54cb09Sjsing #undef HPERM_OP
84cc54cb09Sjsing #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),		\
85cc54cb09Sjsing 	(a)=(a)^(t)^(t>>(16-(n))))					\
86cc54cb09Sjsing 
87*48d3e433Sjsing static void
88cc54cb09Sjsing fcrypt_body(DES_LONG *out, DES_key_schedule *ks, DES_LONG Eswap0,
89cc54cb09Sjsing     DES_LONG Eswap1)
90cc54cb09Sjsing {
91cc54cb09Sjsing 	DES_LONG l, r, t, u;
92cc54cb09Sjsing 	DES_LONG *s;
93cc54cb09Sjsing 	int j;
94cc54cb09Sjsing 	DES_LONG E0, E1;
95cc54cb09Sjsing 
96cc54cb09Sjsing 	l = 0;
97cc54cb09Sjsing 	r = 0;
98cc54cb09Sjsing 
99cc54cb09Sjsing 	s = (DES_LONG *)ks;
100cc54cb09Sjsing 	E0 = Eswap0;
101cc54cb09Sjsing 	E1 = Eswap1;
102cc54cb09Sjsing 
103cc54cb09Sjsing 	for (j = 0; j < 25; j++) {
104cc54cb09Sjsing #ifndef DES_UNROLL
105cc54cb09Sjsing 		int i;
106cc54cb09Sjsing 
107cc54cb09Sjsing 		for (i = 0; i < 32; i += 4) {
108cc54cb09Sjsing 			D_ENCRYPT(l, r, i + 0); /*  1 */
109cc54cb09Sjsing 			D_ENCRYPT(r, l, i + 2); /*  2 */
110cc54cb09Sjsing 		}
111cc54cb09Sjsing #else
112cc54cb09Sjsing 		D_ENCRYPT(l, r, 0); /*  1 */
113cc54cb09Sjsing 		D_ENCRYPT(r, l, 2); /*  2 */
114cc54cb09Sjsing 		D_ENCRYPT(l, r, 4); /*  3 */
115cc54cb09Sjsing 		D_ENCRYPT(r, l, 6); /*  4 */
116cc54cb09Sjsing 		D_ENCRYPT(l, r, 8); /*  5 */
117cc54cb09Sjsing 		D_ENCRYPT(r, l, 10); /*  6 */
118cc54cb09Sjsing 		D_ENCRYPT(l, r, 12); /*  7 */
119cc54cb09Sjsing 		D_ENCRYPT(r, l, 14); /*  8 */
120cc54cb09Sjsing 		D_ENCRYPT(l, r, 16); /*  9 */
121cc54cb09Sjsing 		D_ENCRYPT(r, l, 18); /*  10 */
122cc54cb09Sjsing 		D_ENCRYPT(l, r, 20); /*  11 */
123cc54cb09Sjsing 		D_ENCRYPT(r, l, 22); /*  12 */
124cc54cb09Sjsing 		D_ENCRYPT(l, r, 24); /*  13 */
125cc54cb09Sjsing 		D_ENCRYPT(r, l, 26); /*  14 */
126cc54cb09Sjsing 		D_ENCRYPT(l, r, 28); /*  15 */
127cc54cb09Sjsing 		D_ENCRYPT(r, l, 30); /*  16 */
128cc54cb09Sjsing #endif
129cc54cb09Sjsing 
130cc54cb09Sjsing 		t = l;
131cc54cb09Sjsing 		l = r;
132cc54cb09Sjsing 		r = t;
133cc54cb09Sjsing 	}
134cc54cb09Sjsing 	l = ROTATE(l, 3) & 0xffffffffL;
135cc54cb09Sjsing 	r = ROTATE(r, 3) & 0xffffffffL;
136cc54cb09Sjsing 
137cc54cb09Sjsing 	PERM_OP(l, r, t, 1, 0x55555555L);
138cc54cb09Sjsing 	PERM_OP(r, l, t, 8, 0x00ff00ffL);
139cc54cb09Sjsing 	PERM_OP(l, r, t, 2, 0x33333333L);
140cc54cb09Sjsing 	PERM_OP(r, l, t, 16, 0x0000ffffL);
141cc54cb09Sjsing 	PERM_OP(l, r, t, 4, 0x0f0f0f0fL);
142cc54cb09Sjsing 
143cc54cb09Sjsing 	out[0] = r;
144cc54cb09Sjsing 	out[1] = l;
145cc54cb09Sjsing }
146cc54cb09Sjsing 
147cc54cb09Sjsing /* Added more values to handle illegal salt values the way normal
148cc54cb09Sjsing  * crypt() implementations do.  The patch was sent by
149cc54cb09Sjsing  * Bjorn Gronvall <bg@sics.se>
150cc54cb09Sjsing  */
151cc54cb09Sjsing static unsigned const char con_salt[128] = {
152cc54cb09Sjsing 	0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
153cc54cb09Sjsing 	0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1,
154cc54cb09Sjsing 	0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9,
155cc54cb09Sjsing 	0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1,
156cc54cb09Sjsing 	0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9,
157cc54cb09Sjsing 	0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01,
158cc54cb09Sjsing 	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
159cc54cb09Sjsing 	0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
160cc54cb09Sjsing 	0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
161cc54cb09Sjsing 	0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
162cc54cb09Sjsing 	0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,
163cc54cb09Sjsing 	0x23, 0x24, 0x25, 0x20, 0x21, 0x22, 0x23, 0x24,
164cc54cb09Sjsing 	0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
165cc54cb09Sjsing 	0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34,
166cc54cb09Sjsing 	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C,
167cc54cb09Sjsing 	0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,
168cc54cb09Sjsing };
169cc54cb09Sjsing 
170cc54cb09Sjsing static unsigned const char cov_2char[64] = {
171cc54cb09Sjsing 	0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
172cc54cb09Sjsing 	0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
173cc54cb09Sjsing 	0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
174cc54cb09Sjsing 	0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
175cc54cb09Sjsing 	0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
176cc54cb09Sjsing 	0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
177cc54cb09Sjsing 	0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
178cc54cb09Sjsing 	0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
179cc54cb09Sjsing };
180cc54cb09Sjsing 
181cc54cb09Sjsing char *
182cc54cb09Sjsing DES_crypt(const char *buf, const char *salt)
183cc54cb09Sjsing {
184cc54cb09Sjsing 	static char buff[14];
185cc54cb09Sjsing 
186cc54cb09Sjsing 	return (DES_fcrypt(buf, salt, buff));
187cc54cb09Sjsing }
188cc54cb09Sjsing LCRYPTO_ALIAS(DES_crypt);
189cc54cb09Sjsing 
190cc54cb09Sjsing char *
191cc54cb09Sjsing DES_fcrypt(const char *buf, const char *salt, char *ret)
192cc54cb09Sjsing {
193cc54cb09Sjsing 	unsigned int i, j, x, y;
194cc54cb09Sjsing 	DES_LONG Eswap0, Eswap1;
195cc54cb09Sjsing 	DES_LONG out[2], ll;
196cc54cb09Sjsing 	DES_cblock key;
197cc54cb09Sjsing 	DES_key_schedule ks;
198cc54cb09Sjsing 	unsigned char bb[9];
199cc54cb09Sjsing 	unsigned char *b = bb;
200cc54cb09Sjsing 	unsigned char c, u;
201cc54cb09Sjsing 
202cc54cb09Sjsing 	/* eay 25/08/92
203cc54cb09Sjsing 	 * If you call crypt("pwd","*") as often happens when you
204cc54cb09Sjsing 	 * have * as the pwd field in /etc/passwd, the function
205cc54cb09Sjsing 	 * returns *\0xxxxxxxxx
206cc54cb09Sjsing 	 * The \0 makes the string look like * so the pwd "*" would
207cc54cb09Sjsing 	 * crypt to "*".  This was found when replacing the crypt in
208cc54cb09Sjsing 	 * our shared libraries.  People found that the disabled
209cc54cb09Sjsing 	 * accounts effectively had no passwd :-(. */
210cc54cb09Sjsing 	x = ret[0] = ((salt[0] == '\0') ? 'A' : salt[0]);
211cc54cb09Sjsing 	Eswap0 = con_salt[x] << 2;
212cc54cb09Sjsing 	x = ret[1] = ((salt[1] == '\0') ? 'A' : salt[1]);
213cc54cb09Sjsing 	Eswap1 = con_salt[x] << 6;
214cc54cb09Sjsing /* EAY
215cc54cb09Sjsing r=strlen(buf);
216cc54cb09Sjsing r=(r+7)/8;
217cc54cb09Sjsing */
218cc54cb09Sjsing 	for (i = 0; i < 8; i++) {
219cc54cb09Sjsing 		c = *(buf++);
220cc54cb09Sjsing 		if (!c)
221cc54cb09Sjsing 			break;
222cc54cb09Sjsing 		key[i] = (c << 1);
223cc54cb09Sjsing 	}
224cc54cb09Sjsing 	for (; i < 8; i++)
225cc54cb09Sjsing 		key[i] = 0;
226cc54cb09Sjsing 
227cc54cb09Sjsing 	DES_set_key_unchecked(&key, &ks);
228cc54cb09Sjsing 	fcrypt_body(&(out[0]), &ks, Eswap0, Eswap1);
229cc54cb09Sjsing 
230cc54cb09Sjsing 	ll = out[0];
231cc54cb09Sjsing 	l2c(ll, b);
232cc54cb09Sjsing 	ll = out[1];
233cc54cb09Sjsing 	l2c(ll, b);
234cc54cb09Sjsing 	y = 0;
235cc54cb09Sjsing 	u = 0x80;
236cc54cb09Sjsing 	bb[8] = 0;
237cc54cb09Sjsing 	for (i = 2; i < 13; i++) {
238cc54cb09Sjsing 		c = 0;
239cc54cb09Sjsing 		for (j = 0; j < 6; j++) {
240cc54cb09Sjsing 			c <<= 1;
241cc54cb09Sjsing 			if (bb[y] & u)
242cc54cb09Sjsing 				c |= 1;
243cc54cb09Sjsing 			u >>= 1;
244cc54cb09Sjsing 			if (!u) {
245cc54cb09Sjsing 				y++;
246cc54cb09Sjsing 				u = 0x80;
247cc54cb09Sjsing 			}
248cc54cb09Sjsing 		}
249cc54cb09Sjsing 		ret[i] = cov_2char[c];
250cc54cb09Sjsing 	}
251cc54cb09Sjsing 	ret[13] = '\0';
252cc54cb09Sjsing 	return (ret);
253cc54cb09Sjsing }
254cc54cb09Sjsing LCRYPTO_ALIAS(DES_fcrypt);
255