xref: /illumos-gate/usr/src/lib/libcrypt/common/des_crypt.c (revision 2bbdd445a21f9d61f4a0ca0faf05d5ceb2bd91f3)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma weak _des_crypt = des_crypt
31 #pragma weak _des_encrypt = des_encrypt
32 #pragma weak _des_setkey = des_setkey
33 
34 #include <sys/types.h>
35 #include <crypt.h>
36 #include "des_soft.h"
37 
38 #include <stdlib.h>
39 #include <thread.h>
40 #include <pthread.h>
41 #include <sys/types.h>
42 
43 /*
44  * This program implements the
45  * Proposed Federal Information Processing
46  *  Data Encryption Standard.
47  * See Federal Register, March 17, 1975 (40FR12134)
48  */
49 
50 /*
51  * Initial permutation,
52  */
53 static char IP[] = {
54 	58, 50, 42, 34, 26, 18, 10, 2,
55 	60, 52, 44, 36, 28, 20, 12, 4,
56 	62, 54, 46, 38, 30, 22, 14, 6,
57 	64, 56, 48, 40, 32, 24, 16, 8,
58 	57, 49, 41, 33, 25, 17, 9, 1,
59 	59, 51, 43, 35, 27, 19, 11, 3,
60 	61, 53, 45, 37, 29, 21, 13, 5,
61 	63, 55, 47, 39, 31, 23, 15, 7,
62 };
63 
64 /*
65  * Final permutation, FP = IP^(-1)
66  */
67 static char FP[] = {
68 	40, 8, 48, 16, 56, 24, 64, 32,
69 	39, 7, 47, 15, 55, 23, 63, 31,
70 	38, 6, 46, 14, 54, 22, 62, 30,
71 	37, 5, 45, 13, 53, 21, 61, 29,
72 	36, 4, 44, 12, 52, 20, 60, 28,
73 	35, 3, 43, 11, 51, 19, 59, 27,
74 	34, 2, 42, 10, 50, 18, 58, 26,
75 	33, 1, 41, 9, 49, 17, 57, 25,
76 };
77 
78 /*
79  * Permuted-choice 1 from the key bits
80  * to yield C and D.
81  * Note that bits 8, 16... are left out:
82  * They are intended for a parity check.
83  */
84 static char PC1_C[] = {
85 	57, 49, 41, 33, 25, 17, 9,
86 	1, 58, 50, 42, 34, 26, 18,
87 	10, 2, 59, 51, 43, 35, 27,
88 	19, 11, 3, 60, 52, 44, 36,
89 };
90 
91 static char PC1_D[] = {
92 	63, 55, 47, 39, 31, 23, 15,
93 	7, 62, 54, 46, 38, 30, 22,
94 	14, 6, 61, 53, 45, 37, 29,
95 	21, 13, 5, 28, 20, 12, 4,
96 };
97 
98 /*
99  * Sequence of shifts used for the key schedule.
100  */
101 static char shifts[] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, };
102 
103 /*
104  * Permuted-choice 2, to pick out the bits from
105  * the CD array that generate the key schedule.
106  */
107 static char PC2_C[] = {
108 	14, 17, 11, 24, 1, 5,
109 	3, 28, 15, 6, 21, 10,
110 	23, 19, 12, 4, 26, 8,
111 	16, 7, 27, 20, 13, 2,
112 };
113 
114 static char PC2_D[] = {
115 	41, 52, 31, 37, 47, 55,
116 	30, 40, 51, 45, 33, 48,
117 	44, 49, 39, 56, 34, 53,
118 	46, 42, 50, 36, 29, 32,
119 };
120 
121 /*
122  * The C and D arrays used to calculate the key schedule.
123  */
124 
125 static char C[28];
126 static char D[28];
127 /*
128  * The key schedule.
129  * Generated from the key.
130  */
131 static char KS[16][48];
132 
133 /*
134  * The E bit-selection table.
135  */
136 static char E[48];
137 static char e2[] = {
138 	32, 1, 2, 3, 4, 5,
139 	4, 5, 6, 7, 8, 9,
140 	8, 9, 10, 11, 12, 13,
141 	12, 13, 14, 15, 16, 17,
142 	16, 17, 18, 19, 20, 21,
143 	20, 21, 22, 23, 24, 25,
144 	24, 25, 26, 27, 28, 29,
145 	28, 29, 30, 31, 32, 1,
146 };
147 
148 /*
149  * Set up the key schedule from the key.
150  */
151 
152 static mutex_t lock = DEFAULTMUTEX;
153 
154 static void
155 des_setkey_nolock(const char *key)
156 {
157 	int i, j, k;
158 	char t;
159 
160 	/*
161 	 * First, generate C and D by permuting
162 	 * the key.  The low order bit of each
163 	 * 8-bit char is not used, so C and D are only 28
164 	 * bits apiece.
165 	 */
166 	for (i = 0; i < 28; i++) {
167 		C[i] = key[PC1_C[i]-1];
168 		D[i] = key[PC1_D[i]-1];
169 	}
170 	/*
171 	 * To generate Ki, rotate C and D according
172 	 * to schedule and pick up a permutation
173 	 * using PC2.
174 	 */
175 	for (i = 0; i < 16; i++) {
176 		/*
177 		 * rotate.
178 		 */
179 		for (k = 0; k < shifts[i]; k++) {
180 			t = C[0];
181 			for (j = 0; j < 28-1; j++)
182 				C[j] = C[j+1];
183 			C[27] = (char)t;
184 			t = D[0];
185 			for (j = 0; j < 28-1; j++)
186 				D[j] = D[j+1];
187 			D[27] = (char)t;
188 		}
189 		/*
190 		 * get Ki. Note C and D are concatenated.
191 		 */
192 		for (j = 0; j < 24; j++) {
193 			KS[i][j] = C[PC2_C[j]-1];
194 			KS[i][j+24] = D[PC2_D[j]-28-1];
195 		}
196 	}
197 
198 	for (i = 0; i < 48; i++)
199 		E[i] = e2[i];
200 }
201 
202 void
203 des_setkey(const char *key)
204 {
205 	(void) mutex_lock(&lock);
206 	des_setkey_nolock(key);
207 	(void) mutex_unlock(&lock);
208 }
209 
210 /*
211  * The 8 selection functions.
212  * For some reason, they give a 0-origin
213  * index, unlike everything else.
214  */
215 static char S[8][64] = {
216 	14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
217 	0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
218 	4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
219 	15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
220 
221 	15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
222 	3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
223 	0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
224 	13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
225 
226 	10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
227 	13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
228 	13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
229 	1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
230 
231 	7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
232 	13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
233 	10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
234 	3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
235 
236 	2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
237 	14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
238 	4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
239 	11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
240 
241 	12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
242 	10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
243 	9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
244 	4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
245 
246 	4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
247 	13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
248 	1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
249 	6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
250 
251 	13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
252 	1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
253 	7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
254 	2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
255 };
256 
257 /*
258  * P is a permutation on the selected combination
259  * of the current L and key.
260  */
261 static char P[] = {
262 	16, 7, 20, 21,
263 	29, 12, 28, 17,
264 	1, 15, 23, 26,
265 	5, 18, 31, 10,
266 	2, 8, 24, 14,
267 	32, 27, 3, 9,
268 	19, 13, 30, 6,
269 	22, 11, 4, 25,
270 };
271 
272 /*
273  * The current block, divided into 2 halves.
274  */
275 static char L[64];
276 static char tempL[32];
277 static char f[32];
278 
279 /*
280  * The combination of the key and the input, before selection.
281  */
282 static char preS[48];
283 
284 /*
285  * The payoff: encrypt a block.
286  */
287 
288 static void
289 des_encrypt_nolock(char *block, int edflag)
290 {
291 	if (edflag)
292 		(void) _des_decrypt1(block, L, IP, &L[32],
293 		    preS, E, KS, S, f, tempL, P, FP);
294 	else
295 		(void) des_encrypt1(block, L, IP, &L[32],
296 		    preS, E, KS, S, f, tempL, P, FP);
297 }
298 
299 void
300 des_encrypt(char *block, int edflag)
301 {
302 	(void) mutex_lock(&lock);
303 	des_encrypt_nolock(block, edflag);
304 	(void) mutex_unlock(&lock);
305 }
306 
307 
308 
309 #define	IOBUF_SIZE	16
310 
311 static char *
312 _get_iobuf(thread_key_t *keyp, unsigned size)
313 {
314 	char *iobuf;
315 
316 	if (thr_keycreate_once(keyp, free) != 0)
317 		return (NULL);
318 	iobuf = pthread_getspecific(*keyp);
319 	if (iobuf == NULL) {
320 		if (thr_setspecific(*keyp, (iobuf = malloc(size))) != 0) {
321 			if (iobuf)
322 				(void) free(iobuf);
323 			iobuf = NULL;
324 		}
325 	}
326 	return (iobuf);
327 }
328 
329 char *
330 des_crypt(const char *pw, const char *salt)
331 {
332 	int	i, j;
333 	char	c, temp;
334 	char block[66];
335 	static thread_key_t key = THR_ONCE_KEY;
336 	char *iobuf = _get_iobuf(&key, IOBUF_SIZE);
337 
338 	(void) mutex_lock(&lock);
339 	for (i = 0; i < 66; i++)
340 		block[i] = 0;
341 	for (i = 0; (c = *pw) && (i < 64); pw++) {
342 		for (j = 0; j < 7; j++, i++)
343 			block[i] = (c>>(6-j)) & 01;
344 		i++;
345 	}
346 
347 	des_setkey_nolock(block);
348 
349 	for (i = 0; i < 66; i++)
350 		block[i] = 0;
351 
352 	for (i = 0; i < 2; i++) {
353 		c = *salt++;
354 		iobuf[i] = (char)c;
355 		if (c > 'Z')
356 			c -= 6;
357 		if (c > '9')
358 			c -= 7;
359 		c -= '.';
360 		for (j = 0; j < 6; j++) {
361 			if ((c>>j) & 01) {
362 				temp = E[6*i+j];
363 				E[6*i+j] = E[6*i+j+24];
364 				E[6*i+j+24] = (char)temp;
365 			}
366 		}
367 	}
368 
369 	for (i = 0; i < 25; i++)
370 		(void) des_encrypt_nolock(block, 0);
371 
372 	for (i = 0; i < 11; i++) {
373 		c = 0;
374 		for (j = 0; j < 6; j++) {
375 			c <<= 1;
376 			c |= block[6*i+j];
377 		}
378 		c += '.';
379 		if (c > '9')
380 			c += 7;
381 		if (c > 'Z')
382 			c += 6;
383 		iobuf[i+2] = (char)c;
384 	}
385 	iobuf[i+2] = 0;
386 	if (iobuf[1] == 0)
387 		iobuf[1] = iobuf[0];
388 	(void) mutex_unlock(&lock);
389 	return (iobuf);
390 }
391