xref: /illumos-gate/usr/src/lib/libnsl/key/xcrypt.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 
30 /*
31  * Portions of this source code were derived from Berkeley 4.3 BSD
32  * under license from the Regents of the University of California.
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 /*
38  * xcrypt.c: Hex encryption/decryption and utility routines
39  */
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <sys/types.h>
44 #include <rpc/trace.h>
45 #include <rpc/rpc.h>
46 #include <rpc/key_prot.h>   /* for KEYCHECKSUMSIZE */
47 #include <rpc/des_crypt.h>
48 #include <string.h>
49 #include <rpcsvc/nis_dhext.h>
50 #include <md5.h>
51 
52 #define	MD5HEXSIZE	32
53 
54 extern int bin2hex(int len, unsigned char *binnum, char *hexnum);
55 extern int hex2bin(int len, char *hexnum, char *binnum);
56 static char hex[];	/* forward */
57 static char hexval();
58 
59 int passwd2des(char *, char *);
60 static int weak_DES_key(des_block);
61 
62 /* EXPORT DELETE START */
63 /*
64  * For export control reasons, we want to limit the maximum size of
65  * data that can be encrypted or decrypted.  We limit this to 1024
66  * bits of key data, which amounts to 128 bytes.
67  *
68  * For the extended DH project, we have increased it to
69  * 144 bytes (128key + 16checksum) to accomadate all the 128 bytes
70  * being used by the new 1024bit keys plus 16 bytes MD5 checksum.
71  * We discussed this with Sun's export control office and lawyers
72  * and we have reason to believe this is ok for export.
73  */
74 #define	MAX_KEY_CRYPT_LEN	144
75 /* EXPORT DELETE END */
76 
77 /*
78  * Encrypt a secret key given passwd
79  * The secret key is passed and returned in hex notation.
80  * Its length must be a multiple of 16 hex digits (64 bits).
81  */
82 int
83 xencrypt(secret, passwd)
84 	char *secret;
85 	char *passwd;
86 {
87 /* EXPORT DELETE START */
88 	char key[8];
89 	char ivec[8];
90 	char *buf;
91 	int err;
92 	int len;
93 
94 	trace1(TR_xencrypt, 0);
95 	len = (int)strlen(secret) / 2;
96 	if (len > MAX_KEY_CRYPT_LEN) {
97 		trace1(TR_xencrypt, 1);
98 		return (0);
99 	}
100 	buf = malloc((unsigned)len);
101 	(void) hex2bin(len, secret, buf);
102 	(void) passwd2des(passwd, key);
103 	(void) memset(ivec, 0, 8);
104 
105 	err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec);
106 	if (DES_FAILED(err)) {
107 		free(buf);
108 		trace1(TR_xencrypt, 1);
109 		return (0);
110 	}
111 	(void) bin2hex(len, (unsigned char *) buf, secret);
112 	free(buf);
113 	trace1(TR_xencrypt, 1);
114 	return (1);
115 #if 0
116 /* EXPORT DELETE END */
117 	trace1(TR_xencrypt, 1);
118 	return (0);
119 /* EXPORT DELETE START */
120 #endif
121 /* EXPORT DELETE END */
122 }
123 
124 /*
125  * Decrypt secret key using passwd
126  * The secret key is passed and returned in hex notation.
127  * Once again, the length is a multiple of 16 hex digits
128  */
129 int
130 xdecrypt(secret, passwd)
131 	char *secret;
132 	char *passwd;
133 {
134 /* EXPORT DELETE START */
135 	char key[8];
136 	char ivec[8];
137 	char *buf;
138 	int err;
139 	int len;
140 
141 	trace1(TR_xdecrypt, 0);
142 	len = (int)strlen(secret) / 2;
143 	if (len > MAX_KEY_CRYPT_LEN) {
144 		trace1(TR_xdecrypt, 1);
145 		return (0);
146 	}
147 	buf = malloc((unsigned)len);
148 
149 	(void) hex2bin(len, secret, buf);
150 	(void) passwd2des(passwd, key);
151 	(void) memset(ivec, 0, 8);
152 
153 	err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec);
154 	if (DES_FAILED(err)) {
155 		free(buf);
156 		trace1(TR_xdecrypt, 1);
157 		return (0);
158 	}
159 	(void) bin2hex(len, (unsigned char *) buf, secret);
160 	free(buf);
161 	trace1(TR_xdecrypt, 1);
162 	return (1);
163 #if 0
164 /* EXPORT DELETE END */
165 	trace1(TR_xdecrypt, 1);
166 	return (0);
167 /* EXPORT DELETE START */
168 #endif
169 /* EXPORT DELETE END */
170 }
171 
172 /*
173  * Turn password into DES key
174  */
175 int
176 passwd2des(pw, key)
177 	char *pw;
178 	char *key;
179 {
180 	int i;
181 
182 	trace1(TR_passwd2des, 0);
183 	(void) memset(key, 0, 8);
184 	for (i = 0; *pw; i = (i+1) % 8) {
185 		key[i] ^= *pw++ << 1;
186 	}
187 	des_setparity(key);
188 	trace1(TR_passwd2des, 1);
189 	return (1);
190 }
191 
192 
193 /*
194  * Hex to binary conversion
195  */
196 int
197 hex2bin(len, hexnum, binnum)
198 	int len;
199 	char *hexnum;
200 	char *binnum;
201 {
202 	int i;
203 
204 	trace2(TR_hex2bin, 0, len);
205 	for (i = 0; i < len; i++) {
206 		*binnum++ = 16 * hexval(hexnum[2 * i]) +
207 					hexval(hexnum[2 * i + 1]);
208 	}
209 	trace1(TR_hex2bin, 1);
210 	return (1);
211 }
212 
213 /*
214  * Binary to hex conversion
215  */
216 int
217 bin2hex(len, binnum, hexnum)
218 	int len;
219 	unsigned char *binnum;
220 	char *hexnum;
221 {
222 	int i;
223 	unsigned val;
224 
225 	trace2(TR_bin2hex, 0, len);
226 	for (i = 0; i < len; i++) {
227 		val = binnum[i];
228 		hexnum[i*2] = hex[val >> 4];
229 		hexnum[i*2+1] = hex[val & 0xf];
230 	}
231 	hexnum[len*2] = 0;
232 	trace1(TR_bin2hex, 1);
233 	return (1);
234 }
235 
236 static char hex[16] = {
237 	'0', '1', '2', '3', '4', '5', '6', '7',
238 	'8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
239 };
240 
241 static char
242 hexval(c)
243 	char c;
244 {
245 	trace1(TR_hexval, 0);
246 	if (c >= '0' && c <= '9') {
247 		trace1(TR_hexval, 1);
248 		return (c - '0');
249 	} else if (c >= 'a' && c <= 'z') {
250 		trace1(TR_hexval, 1);
251 		return (c - 'a' + 10);
252 	} else if (c >= 'A' && c <= 'Z') {
253 		trace1(TR_hexval, 1);
254 		return (c - 'A' + 10);
255 	} else {
256 		trace1(TR_hexval, 1);
257 		return (-1);
258 	}
259 }
260 
261 /*
262  * Generic key length/algorithm version of xencrypt().
263  *
264  * Encrypt a secret key given passwd.
265  * The secret key is passed in hex notation.
266  * Arg encrypted_secret will be set to point to the encrypted
267  * secret key (NUL term, hex notation).
268  *
269  * Its length must be a multiple of 16 hex digits (64 bits).
270  *
271  * For 192-0 (AUTH_DES), then encrypt using the same method as xencrypt().
272  *
273  * If arg do_chksum is TRUE, append the checksum before the encrypt.
274  * For 192-0, the checksum is done the same as in xencrypt().  For
275  * bigger keys, MD5 is used.
276  *
277  * Arg netname can be NULL for 192-0.
278  */
279 int
280 xencrypt_g(
281 	char *secret,			/* in  */
282 	keylen_t keylen,		/* in  */
283 	algtype_t algtype,		/* in  */
284 	const char *passwd,		/* in  */
285 	const char netname[],  		/* in  */
286 	char **encrypted_secret,	/* out */
287 	bool_t do_chksum)		/* in  */
288 {
289 /* EXPORT DELETE START */
290 	des_block key;
291 	char ivec[8];
292 	char *binkeybuf;
293 	int err;
294 	const int classic_des = keylen == 192 && algtype == 0;
295 	const int hexkeybytes = BITS2NIBBLES(keylen);
296 	const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
297 	const int binkeybytes = do_chksum ? keylen/8 + keychecksumsize/2 :
298 		keylen/8;
299 	const int bufsize = do_chksum ? hexkeybytes + keychecksumsize + 1 :
300 		hexkeybytes + 1;
301 	char *hexkeybuf;
302 
303 	trace1(TR_xencrypt_g, 0);
304 
305 	if (!secret || !keylen || !passwd || !encrypted_secret) {
306 		trace1(TR_xencrypt_g, 1);
307 		return (0);
308 	}
309 
310 	if ((hexkeybuf = malloc(bufsize)) == 0)
311 		return (0);
312 
313 	(void) memcpy(hexkeybuf, secret, hexkeybytes);
314 	if (do_chksum)
315 		if (classic_des) {
316 			(void) memcpy(hexkeybuf + hexkeybytes, secret,
317 					keychecksumsize);
318 		} else {
319 			MD5_CTX md5_ctx;
320 			char md5hexbuf[MD5HEXSIZE + 1] = {0};
321 			uint8_t digest[MD5HEXSIZE/2];
322 
323 			MD5Init(&md5_ctx);
324 			MD5Update(&md5_ctx, (unsigned char *)hexkeybuf,
325 					hexkeybytes);
326 			MD5Final(digest, &md5_ctx);
327 
328 			/* convert md5 binary digest to hex */
329 			(void) bin2hex(MD5HEXSIZE/2, digest, md5hexbuf);
330 
331 			/* append the hex md5 string to the end of the key */
332 			(void) memcpy(hexkeybuf + hexkeybytes,
333 					(void *)md5hexbuf, MD5HEXSIZE);
334 		}
335 	hexkeybuf[bufsize - 1] = 0;
336 
337 	if (binkeybytes > MAX_KEY_CRYPT_LEN) {
338 		free(hexkeybuf);
339 		trace1(TR_xencrypt_g, 1);
340 		return (0);
341 	}
342 	if ((binkeybuf = malloc((unsigned)binkeybytes)) == 0) {
343 		free(hexkeybuf);
344 		return (0);
345 	}
346 
347 	(void) hex2bin(binkeybytes, hexkeybuf, binkeybuf);
348 	if (classic_des)
349 		(void) passwd2des((char *)passwd, key.c);
350 	else
351 		if (netname)
352 			(void) passwd2des_g(passwd, netname,
353 					(int)strlen(netname), &key, FALSE);
354 		else {
355 			free(hexkeybuf);
356 			return (0);
357 		}
358 
359 	(void) memset(ivec, 0, 8);
360 
361 	err = cbc_crypt(key.c, binkeybuf, binkeybytes, DES_ENCRYPT | DES_HW,
362 			ivec);
363 	if (DES_FAILED(err)) {
364 		free(hexkeybuf);
365 		free(binkeybuf);
366 		trace1(TR_xencrypt_g, 1);
367 		return (0);
368 	}
369 	(void) bin2hex(binkeybytes, (unsigned char *) binkeybuf, hexkeybuf);
370 	free(binkeybuf);
371 	*encrypted_secret = hexkeybuf;
372 	trace1(TR_xencrypt_g, 1);
373 	return (1);
374 #if 0
375 /* EXPORT DELETE END */
376 	trace1(TR_xencrypt_g, 1);
377 	return (0);
378 /* EXPORT DELETE START */
379 #endif
380 /* EXPORT DELETE END */
381 }
382 
383 /*
384  * Generic key len and alg type for version of xdecrypt.
385  *
386  * Decrypt secret key using passwd.  The decrypted secret key
387  * *overwrites* the supplied encrypted secret key.
388  * The secret key is passed and returned in hex notation.
389  * Once again, the length is a multiple of 16 hex digits.
390  *
391  * If 'do_chksum' is TRUE, the 'secret' buffer is assumed to contain
392  * a checksum calculated by a call to xencrypt_g().
393  *
394  * If keylen is 192 and algtype is 0, then decrypt the same way
395  * as xdecrypt().
396  *
397  * Arg netname can be NULL for 192-0.
398  */
399 int
400 xdecrypt_g(
401 	char *secret,		/* out  */
402 	int keylen,		/* in  */
403 	int algtype,		/* in  */
404 	const char *passwd,	/* in  */
405 	const char netname[],	/* in  */
406 	bool_t do_chksum)	/* in  */
407 {
408 /* EXPORT DELETE START */
409 	des_block key;
410 	char ivec[8];
411 	char *buf;
412 	int err;
413 	int len;
414 	const int classic_des = keylen == 192 && algtype == 0;
415 	const int hexkeybytes = BITS2NIBBLES(keylen);
416 	const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
417 
418 	trace1(TR_xdecrypt_g, 0);
419 	len = (int)strlen(secret) / 2;
420 	if (len > MAX_KEY_CRYPT_LEN) {
421 		trace1(TR_xdecrypt_g, 1);
422 		return (0);
423 	}
424 	if ((buf = malloc((unsigned)len)) == 0)
425 		return (0);
426 
427 	(void) hex2bin(len, secret, buf);
428 	if (classic_des)
429 		(void) passwd2des((char *)passwd, key.c);
430 	else
431 		if (netname)
432 			(void) passwd2des_g(passwd, netname,
433 					(int)strlen(netname), &key, FALSE);
434 		else {
435 			free(buf);
436 			trace1(TR_xdecrypt_g, 1);
437 			return (0);
438 		}
439 	(void) memset(ivec, 0, 8);
440 
441 	err = cbc_crypt(key.c, buf, len, DES_DECRYPT | DES_HW, ivec);
442 	if (DES_FAILED(err)) {
443 		free(buf);
444 		trace1(TR_xdecrypt_g, 1);
445 		return (0);
446 	}
447 	(void) bin2hex(len, (unsigned char *) buf, secret);
448 	free(buf);
449 
450 	if (do_chksum)
451 		if (classic_des) {
452 			if (memcmp(secret, &(secret[hexkeybytes]),
453 					keychecksumsize) != 0) {
454 				secret[0] = 0;
455 				trace1(TR_xdecrypt_g, 1);
456 				return (0);
457 			}
458 		} else {
459 			MD5_CTX md5_ctx;
460 			char md5hexbuf[MD5HEXSIZE + 1] = {0};
461 			uint8_t digest[MD5HEXSIZE/2];
462 
463 			MD5Init(&md5_ctx);
464 			MD5Update(&md5_ctx, (unsigned char *)secret,
465 					hexkeybytes);
466 			MD5Final(digest, &md5_ctx);
467 
468 			/* convert md5 binary digest to hex */
469 			(void) bin2hex(MD5HEXSIZE/2, digest, md5hexbuf);
470 
471 			/* does the digest match the appended one? */
472 			if (memcmp(&(secret[hexkeybytes]),
473 					(void *)md5hexbuf, MD5HEXSIZE) != 0) {
474 				secret[0] = 0;
475 				trace1(TR_xdecrypt_g, 1);
476 				return (0);
477 			}
478 		}
479 
480 	secret[hexkeybytes] = '\0';
481 
482 	trace1(TR_xdecrypt_g, 1);
483 	return (1);
484 #if 0
485 /* EXPORT DELETE END */
486 	trace1(TR_xdecrypt_g, 1);
487 	return (0);
488 /* EXPORT DELETE START */
489 #endif
490 /* EXPORT DELETE END */
491 }
492 
493 
494 /*
495  * Modified version of passwd2des(). passwd2des_g() uses the Kerberos
496  * RFC 1510 algorithm to generate a DES key from a user password
497  * and mix-in string. The mix-in is expected to be the netname.
498  * This function to be used only for extended Diffie-Hellman keys.
499  *
500  * If altarg is TRUE, reverse the concat of passwd and mix-in.
501  */
502 int
503 passwd2des_g(
504 	const char *pw,
505 	const char *mixin,
506 	int len,
507 	des_block *key, /* out */
508 	bool_t altalg)
509 {
510 
511 	int  i, j, incr = 1;
512 	des_block ivec, tkey;
513 	char *text;
514 	int  plen, tlen;
515 
516 	trace1(TR_passwd2des, 0);
517 	(void) memset(tkey.c, 0, 8);
518 	(void) memset(ivec.c, 0, 8);
519 
520 
521 /*
522  * Concatentate the password and the mix-in string, fan-fold and XOR them
523  * to the required eight byte initial DES key. Since passwords can be
524  * expected to use mostly seven bit ASCII, left shift the password one
525  * bit in order to preserve as much key space as possible.
526  */
527 
528 #define	KEYLEN sizeof (tkey.c)
529 	plen = strlen(pw);
530 	tlen = ((plen + len + (KEYLEN-1))/KEYLEN)*KEYLEN;
531 	if ((text = (char *)malloc(tlen)) == NULL) {
532 		return (0);
533 	}
534 
535 	(void) memset(text, 0, tlen);
536 
537 	if (! altalg) {
538 
539 /*
540  * Concatenate the password and the mix-in string, fan-fold and XOR them
541  * to the required eight byte initial DES key. Since passwords can be
542  * expected to use mostly seven bit ASCII, left shift the password one
543  * bit in order to preserve as much key space as possible.
544  */
545 		(void) memcpy(text, pw, plen);
546 		(void) memcpy(&text[plen], mixin, len);
547 
548 		for (i = 0, j = 0; pw[j]; j++) {
549 			tkey.c[i] ^= pw[j] << 1;
550 			i += incr;
551 			if (i == 8) {
552 				i = 7;
553 				incr = -incr;
554 			} else if (i == -1) {
555 				i = 0;
556 				incr = -incr;
557 			}
558 		}
559 
560 		for (j = 0; j < len; j++) {
561 			tkey.c[i] ^= mixin[j];
562 			i += incr;
563 			if (i == 8) {
564 				i = 7;
565 				incr = -incr;
566 			} else if (i == -1) {
567 				i = 0;
568 				incr = -incr;
569 			}
570 		}
571 	} else {  /* use alternative algorithm */
572 		(void) memcpy(text, mixin, len);
573 		(void) memcpy(&text[len], pw, plen);
574 
575 		for (i = 0, j = 0; j < len; j++) {
576 			tkey.c[i] ^= mixin[j];
577 			i += incr;
578 			if (i == 8) {
579 				i = 7;
580 				incr = -incr;
581 			} else if (i == -1) {
582 				i = 0;
583 				incr = -incr;
584 			}
585 		}
586 
587 		for (j = 0; pw[j]; j++) {
588 			tkey.c[i] ^= pw[j] << 1;
589 			i += incr;
590 			if (i == 8) {
591 				i = 7;
592 				incr = -incr;
593 			} else if (i == -1) {
594 				i = 0;
595 				incr = -incr;
596 			}
597 		}
598 	}
599 	des_setparity_g(&tkey);
600 
601 	/*
602 	 * Use the temporary key to produce a DES CBC checksum for the text
603 	 * string; cbc_crypt returns the checksum in the ivec.
604 	 */
605 	(void) cbc_crypt(tkey.c, text, tlen, DES_ENCRYPT|DES_HW, ivec.c);
606 	des_setparity_g(&ivec);
607 	free(text);
608 
609 	if (weak_DES_key(ivec)) {
610 		ivec.c[7] ^= 0xf0;
611 		/*
612 		 *  XORing with 0xf0 preserves parity, so no need to check
613 		 *  that again.
614 		 */
615 	}
616 
617 	(void) memcpy((*key).c, ivec.c, sizeof (ivec.c));
618 
619 	trace1(TR_passwd2des_g, 1);
620 	return (1);
621 
622 }
623 
624 struct DESkey {
625 	uint32_t h1;
626 	uint32_t h2;
627 };
628 
629 /*
630  * Weak and semiweak keys from "Applied Cryptography", second edition,
631  * by Bruce Schneier, Wiley 1996.
632  */
633 static struct DESkey weakDESkeys[] = {
634 	/* Weak keys */
635 	{0x01010101, 0x01010101},
636 	{0x1f1f1f1f, 0x1f1f1f1f},
637 	{0xe0e0e0e0, 0xe0e0e0e0},
638 	{0xfefefefe, 0xfefefefe},
639 	/* Semiweak keys */
640 	{0x01fe01fe, 0x01fe01fe},
641 	{0x1fe01fe0, 0x0ef10ef1},
642 	{0x01e001e0, 0x01f101f1},
643 	{0x1ffe1ffe, 0x0efe0efe},
644 	{0x011f011f, 0x010e010e},
645 	{0xe0fee0fe, 0xf1fef1fe},
646 	{0xfe01fe01, 0xfe01fe01},
647 	{0xe01fe01f, 0xf10ef10e},
648 	{0xe001e001, 0xf101f101},
649 	{0xfe1ffe1f, 0xfe0efe0e},
650 	{0x1f011f01, 0x0e010e01},
651 	{0xfee0fee0, 0xfef1fef1}
652 };
653 
654 static int
655 weak_DES_key(des_block db)
656 {
657 	int i;
658 
659 	trace1(TR_weak_DES_key, 0);
660 	for (i = 0; i < sizeof (weakDESkeys)/sizeof (struct DESkey); i++) {
661 		if (weakDESkeys[i].h1 == db.key.high &&
662 			weakDESkeys[i].h2 == db.key.low) {
663 			trace1(TR_weak_DES_key, 1);
664 			return (1);
665 		}
666 	}
667 
668 	trace1(TR_weak_DES_key, 1);
669 	return (0);
670 }
671