xref: /titanic_53/usr/src/lib/libnsl/key/xcrypt.c (revision 61961e0f20c7637a3846bb39786bb9dffa91dfb9)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
22*61961e0fSrobinson 
237c478bd9Sstevel@tonic-gate /*
24*61961e0fSrobinson  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
257c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
297c478bd9Sstevel@tonic-gate /* All Rights Reserved */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
337c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * xcrypt.c: Hex encryption/decryption and utility routines
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <stdio.h>
437c478bd9Sstevel@tonic-gate #include <stdlib.h>
447c478bd9Sstevel@tonic-gate #include <sys/types.h>
457c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
467c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>   /* for KEYCHECKSUMSIZE */
477c478bd9Sstevel@tonic-gate #include <rpc/des_crypt.h>
487c478bd9Sstevel@tonic-gate #include <string.h>
497c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h>
507c478bd9Sstevel@tonic-gate #include <md5.h>
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #define	MD5HEXSIZE	32
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate extern int bin2hex(int len, unsigned char *binnum, char *hexnum);
557c478bd9Sstevel@tonic-gate extern int hex2bin(int len, char *hexnum, char *binnum);
567c478bd9Sstevel@tonic-gate static char hex[];	/* forward */
577c478bd9Sstevel@tonic-gate static char hexval();
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate int passwd2des(char *, char *);
607c478bd9Sstevel@tonic-gate static int weak_DES_key(des_block);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate  * For export control reasons, we want to limit the maximum size of
657c478bd9Sstevel@tonic-gate  * data that can be encrypted or decrypted.  We limit this to 1024
667c478bd9Sstevel@tonic-gate  * bits of key data, which amounts to 128 bytes.
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  * For the extended DH project, we have increased it to
697c478bd9Sstevel@tonic-gate  * 144 bytes (128key + 16checksum) to accomadate all the 128 bytes
707c478bd9Sstevel@tonic-gate  * being used by the new 1024bit keys plus 16 bytes MD5 checksum.
717c478bd9Sstevel@tonic-gate  * We discussed this with Sun's export control office and lawyers
727c478bd9Sstevel@tonic-gate  * and we have reason to believe this is ok for export.
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate #define	MAX_KEY_CRYPT_LEN	144
757c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /*
787c478bd9Sstevel@tonic-gate  * Encrypt a secret key given passwd
797c478bd9Sstevel@tonic-gate  * The secret key is passed and returned in hex notation.
807c478bd9Sstevel@tonic-gate  * Its length must be a multiple of 16 hex digits (64 bits).
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate int
837c478bd9Sstevel@tonic-gate xencrypt(secret, passwd)
847c478bd9Sstevel@tonic-gate 	char *secret;
857c478bd9Sstevel@tonic-gate 	char *passwd;
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
887c478bd9Sstevel@tonic-gate 	char key[8];
897c478bd9Sstevel@tonic-gate 	char ivec[8];
907c478bd9Sstevel@tonic-gate 	char *buf;
917c478bd9Sstevel@tonic-gate 	int err;
927c478bd9Sstevel@tonic-gate 	int len;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	len = (int)strlen(secret) / 2;
95*61961e0fSrobinson 	if (len > MAX_KEY_CRYPT_LEN)
967c478bd9Sstevel@tonic-gate 		return (0);
977c478bd9Sstevel@tonic-gate 	buf = malloc((unsigned)len);
987c478bd9Sstevel@tonic-gate 	(void) hex2bin(len, secret, buf);
997c478bd9Sstevel@tonic-gate 	(void) passwd2des(passwd, key);
1007c478bd9Sstevel@tonic-gate 	(void) memset(ivec, 0, 8);
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec);
1037c478bd9Sstevel@tonic-gate 	if (DES_FAILED(err)) {
1047c478bd9Sstevel@tonic-gate 		free(buf);
1057c478bd9Sstevel@tonic-gate 		return (0);
1067c478bd9Sstevel@tonic-gate 	}
1077c478bd9Sstevel@tonic-gate 	(void) bin2hex(len, (unsigned char *) buf, secret);
1087c478bd9Sstevel@tonic-gate 	free(buf);
1097c478bd9Sstevel@tonic-gate 	return (1);
1107c478bd9Sstevel@tonic-gate #if 0
1117c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
1127c478bd9Sstevel@tonic-gate 	return (0);
1137c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
1147c478bd9Sstevel@tonic-gate #endif
1157c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * Decrypt secret key using passwd
1207c478bd9Sstevel@tonic-gate  * The secret key is passed and returned in hex notation.
1217c478bd9Sstevel@tonic-gate  * Once again, the length is a multiple of 16 hex digits
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate int
1247c478bd9Sstevel@tonic-gate xdecrypt(secret, passwd)
1257c478bd9Sstevel@tonic-gate 	char *secret;
1267c478bd9Sstevel@tonic-gate 	char *passwd;
1277c478bd9Sstevel@tonic-gate {
1287c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
1297c478bd9Sstevel@tonic-gate 	char key[8];
1307c478bd9Sstevel@tonic-gate 	char ivec[8];
1317c478bd9Sstevel@tonic-gate 	char *buf;
1327c478bd9Sstevel@tonic-gate 	int err;
1337c478bd9Sstevel@tonic-gate 	int len;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	len = (int)strlen(secret) / 2;
136*61961e0fSrobinson 	if (len > MAX_KEY_CRYPT_LEN)
1377c478bd9Sstevel@tonic-gate 		return (0);
1387c478bd9Sstevel@tonic-gate 	buf = malloc((unsigned)len);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	(void) hex2bin(len, secret, buf);
1417c478bd9Sstevel@tonic-gate 	(void) passwd2des(passwd, key);
1427c478bd9Sstevel@tonic-gate 	(void) memset(ivec, 0, 8);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec);
1457c478bd9Sstevel@tonic-gate 	if (DES_FAILED(err)) {
1467c478bd9Sstevel@tonic-gate 		free(buf);
1477c478bd9Sstevel@tonic-gate 		return (0);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	(void) bin2hex(len, (unsigned char *) buf, secret);
1507c478bd9Sstevel@tonic-gate 	free(buf);
1517c478bd9Sstevel@tonic-gate 	return (1);
1527c478bd9Sstevel@tonic-gate #if 0
1537c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
1547c478bd9Sstevel@tonic-gate 	return (0);
1557c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
1567c478bd9Sstevel@tonic-gate #endif
1577c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate  * Turn password into DES key
1627c478bd9Sstevel@tonic-gate  */
1637c478bd9Sstevel@tonic-gate int
1647c478bd9Sstevel@tonic-gate passwd2des(pw, key)
1657c478bd9Sstevel@tonic-gate 	char *pw;
1667c478bd9Sstevel@tonic-gate 	char *key;
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	int i;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	(void) memset(key, 0, 8);
1717c478bd9Sstevel@tonic-gate 	for (i = 0; *pw; i = (i+1) % 8) {
1727c478bd9Sstevel@tonic-gate 		key[i] ^= *pw++ << 1;
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate 	des_setparity(key);
1757c478bd9Sstevel@tonic-gate 	return (1);
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate  * Hex to binary conversion
1817c478bd9Sstevel@tonic-gate  */
1827c478bd9Sstevel@tonic-gate int
1837c478bd9Sstevel@tonic-gate hex2bin(len, hexnum, binnum)
1847c478bd9Sstevel@tonic-gate 	int len;
1857c478bd9Sstevel@tonic-gate 	char *hexnum;
1867c478bd9Sstevel@tonic-gate 	char *binnum;
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 	int i;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
1917c478bd9Sstevel@tonic-gate 		*binnum++ = 16 * hexval(hexnum[2 * i]) +
1927c478bd9Sstevel@tonic-gate 					hexval(hexnum[2 * i + 1]);
1937c478bd9Sstevel@tonic-gate 	}
1947c478bd9Sstevel@tonic-gate 	return (1);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  * Binary to hex conversion
1997c478bd9Sstevel@tonic-gate  */
2007c478bd9Sstevel@tonic-gate int
2017c478bd9Sstevel@tonic-gate bin2hex(len, binnum, hexnum)
2027c478bd9Sstevel@tonic-gate 	int len;
2037c478bd9Sstevel@tonic-gate 	unsigned char *binnum;
2047c478bd9Sstevel@tonic-gate 	char *hexnum;
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	int i;
2077c478bd9Sstevel@tonic-gate 	unsigned val;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
2107c478bd9Sstevel@tonic-gate 		val = binnum[i];
2117c478bd9Sstevel@tonic-gate 		hexnum[i*2] = hex[val >> 4];
2127c478bd9Sstevel@tonic-gate 		hexnum[i*2+1] = hex[val & 0xf];
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 	hexnum[len*2] = 0;
2157c478bd9Sstevel@tonic-gate 	return (1);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate static char hex[16] = {
2197c478bd9Sstevel@tonic-gate 	'0', '1', '2', '3', '4', '5', '6', '7',
2207c478bd9Sstevel@tonic-gate 	'8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
2217c478bd9Sstevel@tonic-gate };
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate static char
2247c478bd9Sstevel@tonic-gate hexval(c)
2257c478bd9Sstevel@tonic-gate 	char c;
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate 	if (c >= '0' && c <= '9') {
2287c478bd9Sstevel@tonic-gate 		return (c - '0');
2297c478bd9Sstevel@tonic-gate 	} else if (c >= 'a' && c <= 'z') {
2307c478bd9Sstevel@tonic-gate 		return (c - 'a' + 10);
2317c478bd9Sstevel@tonic-gate 	} else if (c >= 'A' && c <= 'Z') {
2327c478bd9Sstevel@tonic-gate 		return (c - 'A' + 10);
2337c478bd9Sstevel@tonic-gate 	} else {
2347c478bd9Sstevel@tonic-gate 		return (-1);
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate  * Generic key length/algorithm version of xencrypt().
2407c478bd9Sstevel@tonic-gate  *
2417c478bd9Sstevel@tonic-gate  * Encrypt a secret key given passwd.
2427c478bd9Sstevel@tonic-gate  * The secret key is passed in hex notation.
2437c478bd9Sstevel@tonic-gate  * Arg encrypted_secret will be set to point to the encrypted
2447c478bd9Sstevel@tonic-gate  * secret key (NUL term, hex notation).
2457c478bd9Sstevel@tonic-gate  *
2467c478bd9Sstevel@tonic-gate  * Its length must be a multiple of 16 hex digits (64 bits).
2477c478bd9Sstevel@tonic-gate  *
2487c478bd9Sstevel@tonic-gate  * For 192-0 (AUTH_DES), then encrypt using the same method as xencrypt().
2497c478bd9Sstevel@tonic-gate  *
2507c478bd9Sstevel@tonic-gate  * If arg do_chksum is TRUE, append the checksum before the encrypt.
2517c478bd9Sstevel@tonic-gate  * For 192-0, the checksum is done the same as in xencrypt().  For
2527c478bd9Sstevel@tonic-gate  * bigger keys, MD5 is used.
2537c478bd9Sstevel@tonic-gate  *
2547c478bd9Sstevel@tonic-gate  * Arg netname can be NULL for 192-0.
2557c478bd9Sstevel@tonic-gate  */
2567c478bd9Sstevel@tonic-gate int
2577c478bd9Sstevel@tonic-gate xencrypt_g(
2587c478bd9Sstevel@tonic-gate 	char *secret,			/* in  */
2597c478bd9Sstevel@tonic-gate 	keylen_t keylen,		/* in  */
2607c478bd9Sstevel@tonic-gate 	algtype_t algtype,		/* in  */
2617c478bd9Sstevel@tonic-gate 	const char *passwd,		/* in  */
2627c478bd9Sstevel@tonic-gate 	const char netname[],  		/* in  */
2637c478bd9Sstevel@tonic-gate 	char **encrypted_secret,	/* out */
2647c478bd9Sstevel@tonic-gate 	bool_t do_chksum)		/* in  */
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
2677c478bd9Sstevel@tonic-gate 	des_block key;
2687c478bd9Sstevel@tonic-gate 	char ivec[8];
2697c478bd9Sstevel@tonic-gate 	char *binkeybuf;
2707c478bd9Sstevel@tonic-gate 	int err;
2717c478bd9Sstevel@tonic-gate 	const int classic_des = keylen == 192 && algtype == 0;
2727c478bd9Sstevel@tonic-gate 	const int hexkeybytes = BITS2NIBBLES(keylen);
2737c478bd9Sstevel@tonic-gate 	const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
2747c478bd9Sstevel@tonic-gate 	const int binkeybytes = do_chksum ? keylen/8 + keychecksumsize/2 :
2757c478bd9Sstevel@tonic-gate 		keylen/8;
2767c478bd9Sstevel@tonic-gate 	const int bufsize = do_chksum ? hexkeybytes + keychecksumsize + 1 :
2777c478bd9Sstevel@tonic-gate 		hexkeybytes + 1;
2787c478bd9Sstevel@tonic-gate 	char *hexkeybuf;
2797c478bd9Sstevel@tonic-gate 
280*61961e0fSrobinson 	if (!secret || !keylen || !passwd || !encrypted_secret)
2817c478bd9Sstevel@tonic-gate 		return (0);
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	if ((hexkeybuf = malloc(bufsize)) == 0)
2847c478bd9Sstevel@tonic-gate 		return (0);
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	(void) memcpy(hexkeybuf, secret, hexkeybytes);
2877c478bd9Sstevel@tonic-gate 	if (do_chksum)
2887c478bd9Sstevel@tonic-gate 		if (classic_des) {
2897c478bd9Sstevel@tonic-gate 			(void) memcpy(hexkeybuf + hexkeybytes, secret,
2907c478bd9Sstevel@tonic-gate 					keychecksumsize);
2917c478bd9Sstevel@tonic-gate 		} else {
2927c478bd9Sstevel@tonic-gate 			MD5_CTX md5_ctx;
2937c478bd9Sstevel@tonic-gate 			char md5hexbuf[MD5HEXSIZE + 1] = {0};
2947c478bd9Sstevel@tonic-gate 			uint8_t digest[MD5HEXSIZE/2];
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 			MD5Init(&md5_ctx);
2977c478bd9Sstevel@tonic-gate 			MD5Update(&md5_ctx, (unsigned char *)hexkeybuf,
2987c478bd9Sstevel@tonic-gate 					hexkeybytes);
2997c478bd9Sstevel@tonic-gate 			MD5Final(digest, &md5_ctx);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 			/* convert md5 binary digest to hex */
3027c478bd9Sstevel@tonic-gate 			(void) bin2hex(MD5HEXSIZE/2, digest, md5hexbuf);
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 			/* append the hex md5 string to the end of the key */
3057c478bd9Sstevel@tonic-gate 			(void) memcpy(hexkeybuf + hexkeybytes,
3067c478bd9Sstevel@tonic-gate 					(void *)md5hexbuf, MD5HEXSIZE);
3077c478bd9Sstevel@tonic-gate 		}
3087c478bd9Sstevel@tonic-gate 	hexkeybuf[bufsize - 1] = 0;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	if (binkeybytes > MAX_KEY_CRYPT_LEN) {
3117c478bd9Sstevel@tonic-gate 		free(hexkeybuf);
3127c478bd9Sstevel@tonic-gate 		return (0);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 	if ((binkeybuf = malloc((unsigned)binkeybytes)) == 0) {
3157c478bd9Sstevel@tonic-gate 		free(hexkeybuf);
3167c478bd9Sstevel@tonic-gate 		return (0);
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	(void) hex2bin(binkeybytes, hexkeybuf, binkeybuf);
3207c478bd9Sstevel@tonic-gate 	if (classic_des)
3217c478bd9Sstevel@tonic-gate 		(void) passwd2des((char *)passwd, key.c);
3227c478bd9Sstevel@tonic-gate 	else
3237c478bd9Sstevel@tonic-gate 		if (netname)
3247c478bd9Sstevel@tonic-gate 			(void) passwd2des_g(passwd, netname,
3257c478bd9Sstevel@tonic-gate 					(int)strlen(netname), &key, FALSE);
3267c478bd9Sstevel@tonic-gate 		else {
3277c478bd9Sstevel@tonic-gate 			free(hexkeybuf);
3287c478bd9Sstevel@tonic-gate 			return (0);
3297c478bd9Sstevel@tonic-gate 		}
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	(void) memset(ivec, 0, 8);
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	err = cbc_crypt(key.c, binkeybuf, binkeybytes, DES_ENCRYPT | DES_HW,
3347c478bd9Sstevel@tonic-gate 			ivec);
3357c478bd9Sstevel@tonic-gate 	if (DES_FAILED(err)) {
3367c478bd9Sstevel@tonic-gate 		free(hexkeybuf);
3377c478bd9Sstevel@tonic-gate 		free(binkeybuf);
3387c478bd9Sstevel@tonic-gate 		return (0);
3397c478bd9Sstevel@tonic-gate 	}
3407c478bd9Sstevel@tonic-gate 	(void) bin2hex(binkeybytes, (unsigned char *) binkeybuf, hexkeybuf);
3417c478bd9Sstevel@tonic-gate 	free(binkeybuf);
3427c478bd9Sstevel@tonic-gate 	*encrypted_secret = hexkeybuf;
3437c478bd9Sstevel@tonic-gate 	return (1);
3447c478bd9Sstevel@tonic-gate #if 0
3457c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
3467c478bd9Sstevel@tonic-gate 	return (0);
3477c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
3487c478bd9Sstevel@tonic-gate #endif
3497c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate /*
3537c478bd9Sstevel@tonic-gate  * Generic key len and alg type for version of xdecrypt.
3547c478bd9Sstevel@tonic-gate  *
3557c478bd9Sstevel@tonic-gate  * Decrypt secret key using passwd.  The decrypted secret key
3567c478bd9Sstevel@tonic-gate  * *overwrites* the supplied encrypted secret key.
3577c478bd9Sstevel@tonic-gate  * The secret key is passed and returned in hex notation.
3587c478bd9Sstevel@tonic-gate  * Once again, the length is a multiple of 16 hex digits.
3597c478bd9Sstevel@tonic-gate  *
3607c478bd9Sstevel@tonic-gate  * If 'do_chksum' is TRUE, the 'secret' buffer is assumed to contain
3617c478bd9Sstevel@tonic-gate  * a checksum calculated by a call to xencrypt_g().
3627c478bd9Sstevel@tonic-gate  *
3637c478bd9Sstevel@tonic-gate  * If keylen is 192 and algtype is 0, then decrypt the same way
3647c478bd9Sstevel@tonic-gate  * as xdecrypt().
3657c478bd9Sstevel@tonic-gate  *
3667c478bd9Sstevel@tonic-gate  * Arg netname can be NULL for 192-0.
3677c478bd9Sstevel@tonic-gate  */
3687c478bd9Sstevel@tonic-gate int
3697c478bd9Sstevel@tonic-gate xdecrypt_g(
3707c478bd9Sstevel@tonic-gate 	char *secret,		/* out  */
3717c478bd9Sstevel@tonic-gate 	int keylen,		/* in  */
3727c478bd9Sstevel@tonic-gate 	int algtype,		/* in  */
3737c478bd9Sstevel@tonic-gate 	const char *passwd,	/* in  */
3747c478bd9Sstevel@tonic-gate 	const char netname[],	/* in  */
3757c478bd9Sstevel@tonic-gate 	bool_t do_chksum)	/* in  */
3767c478bd9Sstevel@tonic-gate {
3777c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
3787c478bd9Sstevel@tonic-gate 	des_block key;
3797c478bd9Sstevel@tonic-gate 	char ivec[8];
3807c478bd9Sstevel@tonic-gate 	char *buf;
3817c478bd9Sstevel@tonic-gate 	int err;
3827c478bd9Sstevel@tonic-gate 	int len;
3837c478bd9Sstevel@tonic-gate 	const int classic_des = keylen == 192 && algtype == 0;
3847c478bd9Sstevel@tonic-gate 	const int hexkeybytes = BITS2NIBBLES(keylen);
3857c478bd9Sstevel@tonic-gate 	const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	len = (int)strlen(secret) / 2;
388*61961e0fSrobinson 	if (len > MAX_KEY_CRYPT_LEN)
3897c478bd9Sstevel@tonic-gate 		return (0);
3907c478bd9Sstevel@tonic-gate 	if ((buf = malloc((unsigned)len)) == 0)
3917c478bd9Sstevel@tonic-gate 		return (0);
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	(void) hex2bin(len, secret, buf);
3947c478bd9Sstevel@tonic-gate 	if (classic_des)
3957c478bd9Sstevel@tonic-gate 		(void) passwd2des((char *)passwd, key.c);
3967c478bd9Sstevel@tonic-gate 	else
3977c478bd9Sstevel@tonic-gate 		if (netname)
3987c478bd9Sstevel@tonic-gate 			(void) passwd2des_g(passwd, netname,
3997c478bd9Sstevel@tonic-gate 					(int)strlen(netname), &key, FALSE);
4007c478bd9Sstevel@tonic-gate 		else {
4017c478bd9Sstevel@tonic-gate 			free(buf);
4027c478bd9Sstevel@tonic-gate 			return (0);
4037c478bd9Sstevel@tonic-gate 		}
4047c478bd9Sstevel@tonic-gate 	(void) memset(ivec, 0, 8);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	err = cbc_crypt(key.c, buf, len, DES_DECRYPT | DES_HW, ivec);
4077c478bd9Sstevel@tonic-gate 	if (DES_FAILED(err)) {
4087c478bd9Sstevel@tonic-gate 		free(buf);
4097c478bd9Sstevel@tonic-gate 		return (0);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	(void) bin2hex(len, (unsigned char *) buf, secret);
4127c478bd9Sstevel@tonic-gate 	free(buf);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	if (do_chksum)
4157c478bd9Sstevel@tonic-gate 		if (classic_des) {
4167c478bd9Sstevel@tonic-gate 			if (memcmp(secret, &(secret[hexkeybytes]),
4177c478bd9Sstevel@tonic-gate 					keychecksumsize) != 0) {
4187c478bd9Sstevel@tonic-gate 				secret[0] = 0;
4197c478bd9Sstevel@tonic-gate 				return (0);
4207c478bd9Sstevel@tonic-gate 			}
4217c478bd9Sstevel@tonic-gate 		} else {
4227c478bd9Sstevel@tonic-gate 			MD5_CTX md5_ctx;
4237c478bd9Sstevel@tonic-gate 			char md5hexbuf[MD5HEXSIZE + 1] = {0};
4247c478bd9Sstevel@tonic-gate 			uint8_t digest[MD5HEXSIZE/2];
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 			MD5Init(&md5_ctx);
4277c478bd9Sstevel@tonic-gate 			MD5Update(&md5_ctx, (unsigned char *)secret,
4287c478bd9Sstevel@tonic-gate 					hexkeybytes);
4297c478bd9Sstevel@tonic-gate 			MD5Final(digest, &md5_ctx);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 			/* convert md5 binary digest to hex */
4327c478bd9Sstevel@tonic-gate 			(void) bin2hex(MD5HEXSIZE/2, digest, md5hexbuf);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 			/* does the digest match the appended one? */
4357c478bd9Sstevel@tonic-gate 			if (memcmp(&(secret[hexkeybytes]),
436*61961e0fSrobinson 					md5hexbuf, MD5HEXSIZE) != 0) {
4377c478bd9Sstevel@tonic-gate 				secret[0] = 0;
4387c478bd9Sstevel@tonic-gate 				return (0);
4397c478bd9Sstevel@tonic-gate 			}
4407c478bd9Sstevel@tonic-gate 		}
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	secret[hexkeybytes] = '\0';
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	return (1);
4457c478bd9Sstevel@tonic-gate #if 0
4467c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
4477c478bd9Sstevel@tonic-gate 	return (0);
4487c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */
4497c478bd9Sstevel@tonic-gate #endif
4507c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate /*
4557c478bd9Sstevel@tonic-gate  * Modified version of passwd2des(). passwd2des_g() uses the Kerberos
4567c478bd9Sstevel@tonic-gate  * RFC 1510 algorithm to generate a DES key from a user password
4577c478bd9Sstevel@tonic-gate  * and mix-in string. The mix-in is expected to be the netname.
4587c478bd9Sstevel@tonic-gate  * This function to be used only for extended Diffie-Hellman keys.
4597c478bd9Sstevel@tonic-gate  *
4607c478bd9Sstevel@tonic-gate  * If altarg is TRUE, reverse the concat of passwd and mix-in.
4617c478bd9Sstevel@tonic-gate  */
4627c478bd9Sstevel@tonic-gate int
4637c478bd9Sstevel@tonic-gate passwd2des_g(
4647c478bd9Sstevel@tonic-gate 	const char *pw,
4657c478bd9Sstevel@tonic-gate 	const char *mixin,
4667c478bd9Sstevel@tonic-gate 	int len,
4677c478bd9Sstevel@tonic-gate 	des_block *key, /* out */
4687c478bd9Sstevel@tonic-gate 	bool_t altalg)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	int  i, j, incr = 1;
4727c478bd9Sstevel@tonic-gate 	des_block ivec, tkey;
4737c478bd9Sstevel@tonic-gate 	char *text;
4747c478bd9Sstevel@tonic-gate 	int  plen, tlen;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	(void) memset(tkey.c, 0, 8);
4777c478bd9Sstevel@tonic-gate 	(void) memset(ivec.c, 0, 8);
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate /*
4817c478bd9Sstevel@tonic-gate  * Concatentate the password and the mix-in string, fan-fold and XOR them
4827c478bd9Sstevel@tonic-gate  * to the required eight byte initial DES key. Since passwords can be
4837c478bd9Sstevel@tonic-gate  * expected to use mostly seven bit ASCII, left shift the password one
4847c478bd9Sstevel@tonic-gate  * bit in order to preserve as much key space as possible.
4857c478bd9Sstevel@tonic-gate  */
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate #define	KEYLEN sizeof (tkey.c)
4887c478bd9Sstevel@tonic-gate 	plen = strlen(pw);
4897c478bd9Sstevel@tonic-gate 	tlen = ((plen + len + (KEYLEN-1))/KEYLEN)*KEYLEN;
490*61961e0fSrobinson 	if ((text = malloc(tlen)) == NULL) {
4917c478bd9Sstevel@tonic-gate 		return (0);
4927c478bd9Sstevel@tonic-gate 	}
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	(void) memset(text, 0, tlen);
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	if (!altalg) {
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate /*
4997c478bd9Sstevel@tonic-gate  * Concatenate the password and the mix-in string, fan-fold and XOR them
5007c478bd9Sstevel@tonic-gate  * to the required eight byte initial DES key. Since passwords can be
5017c478bd9Sstevel@tonic-gate  * expected to use mostly seven bit ASCII, left shift the password one
5027c478bd9Sstevel@tonic-gate  * bit in order to preserve as much key space as possible.
5037c478bd9Sstevel@tonic-gate  */
5047c478bd9Sstevel@tonic-gate 		(void) memcpy(text, pw, plen);
5057c478bd9Sstevel@tonic-gate 		(void) memcpy(&text[plen], mixin, len);
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 		for (i = 0, j = 0; pw[j]; j++) {
5087c478bd9Sstevel@tonic-gate 			tkey.c[i] ^= pw[j] << 1;
5097c478bd9Sstevel@tonic-gate 			i += incr;
5107c478bd9Sstevel@tonic-gate 			if (i == 8) {
5117c478bd9Sstevel@tonic-gate 				i = 7;
5127c478bd9Sstevel@tonic-gate 				incr = -incr;
5137c478bd9Sstevel@tonic-gate 			} else if (i == -1) {
5147c478bd9Sstevel@tonic-gate 				i = 0;
5157c478bd9Sstevel@tonic-gate 				incr = -incr;
5167c478bd9Sstevel@tonic-gate 			}
5177c478bd9Sstevel@tonic-gate 		}
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		for (j = 0; j < len; j++) {
5207c478bd9Sstevel@tonic-gate 			tkey.c[i] ^= mixin[j];
5217c478bd9Sstevel@tonic-gate 			i += incr;
5227c478bd9Sstevel@tonic-gate 			if (i == 8) {
5237c478bd9Sstevel@tonic-gate 				i = 7;
5247c478bd9Sstevel@tonic-gate 				incr = -incr;
5257c478bd9Sstevel@tonic-gate 			} else if (i == -1) {
5267c478bd9Sstevel@tonic-gate 				i = 0;
5277c478bd9Sstevel@tonic-gate 				incr = -incr;
5287c478bd9Sstevel@tonic-gate 			}
5297c478bd9Sstevel@tonic-gate 		}
5307c478bd9Sstevel@tonic-gate 	} else {  /* use alternative algorithm */
5317c478bd9Sstevel@tonic-gate 		(void) memcpy(text, mixin, len);
5327c478bd9Sstevel@tonic-gate 		(void) memcpy(&text[len], pw, plen);
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 		for (i = 0, j = 0; j < len; j++) {
5357c478bd9Sstevel@tonic-gate 			tkey.c[i] ^= mixin[j];
5367c478bd9Sstevel@tonic-gate 			i += incr;
5377c478bd9Sstevel@tonic-gate 			if (i == 8) {
5387c478bd9Sstevel@tonic-gate 				i = 7;
5397c478bd9Sstevel@tonic-gate 				incr = -incr;
5407c478bd9Sstevel@tonic-gate 			} else if (i == -1) {
5417c478bd9Sstevel@tonic-gate 				i = 0;
5427c478bd9Sstevel@tonic-gate 				incr = -incr;
5437c478bd9Sstevel@tonic-gate 			}
5447c478bd9Sstevel@tonic-gate 		}
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 		for (j = 0; pw[j]; j++) {
5477c478bd9Sstevel@tonic-gate 			tkey.c[i] ^= pw[j] << 1;
5487c478bd9Sstevel@tonic-gate 			i += incr;
5497c478bd9Sstevel@tonic-gate 			if (i == 8) {
5507c478bd9Sstevel@tonic-gate 				i = 7;
5517c478bd9Sstevel@tonic-gate 				incr = -incr;
5527c478bd9Sstevel@tonic-gate 			} else if (i == -1) {
5537c478bd9Sstevel@tonic-gate 				i = 0;
5547c478bd9Sstevel@tonic-gate 				incr = -incr;
5557c478bd9Sstevel@tonic-gate 			}
5567c478bd9Sstevel@tonic-gate 		}
5577c478bd9Sstevel@tonic-gate 	}
5587c478bd9Sstevel@tonic-gate 	des_setparity_g(&tkey);
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	/*
5617c478bd9Sstevel@tonic-gate 	 * Use the temporary key to produce a DES CBC checksum for the text
5627c478bd9Sstevel@tonic-gate 	 * string; cbc_crypt returns the checksum in the ivec.
5637c478bd9Sstevel@tonic-gate 	 */
5647c478bd9Sstevel@tonic-gate 	(void) cbc_crypt(tkey.c, text, tlen, DES_ENCRYPT|DES_HW, ivec.c);
5657c478bd9Sstevel@tonic-gate 	des_setparity_g(&ivec);
5667c478bd9Sstevel@tonic-gate 	free(text);
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	if (weak_DES_key(ivec)) {
5697c478bd9Sstevel@tonic-gate 		ivec.c[7] ^= 0xf0;
5707c478bd9Sstevel@tonic-gate 		/*
5717c478bd9Sstevel@tonic-gate 		 *  XORing with 0xf0 preserves parity, so no need to check
5727c478bd9Sstevel@tonic-gate 		 *  that again.
5737c478bd9Sstevel@tonic-gate 		 */
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	(void) memcpy((*key).c, ivec.c, sizeof (ivec.c));
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	return (1);
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate struct DESkey {
5837c478bd9Sstevel@tonic-gate 	uint32_t h1;
5847c478bd9Sstevel@tonic-gate 	uint32_t h2;
5857c478bd9Sstevel@tonic-gate };
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate /*
5887c478bd9Sstevel@tonic-gate  * Weak and semiweak keys from "Applied Cryptography", second edition,
5897c478bd9Sstevel@tonic-gate  * by Bruce Schneier, Wiley 1996.
5907c478bd9Sstevel@tonic-gate  */
5917c478bd9Sstevel@tonic-gate static struct DESkey weakDESkeys[] = {
5927c478bd9Sstevel@tonic-gate 	/* Weak keys */
5937c478bd9Sstevel@tonic-gate 	{0x01010101, 0x01010101},
5947c478bd9Sstevel@tonic-gate 	{0x1f1f1f1f, 0x1f1f1f1f},
5957c478bd9Sstevel@tonic-gate 	{0xe0e0e0e0, 0xe0e0e0e0},
5967c478bd9Sstevel@tonic-gate 	{0xfefefefe, 0xfefefefe},
5977c478bd9Sstevel@tonic-gate 	/* Semiweak keys */
5987c478bd9Sstevel@tonic-gate 	{0x01fe01fe, 0x01fe01fe},
5997c478bd9Sstevel@tonic-gate 	{0x1fe01fe0, 0x0ef10ef1},
6007c478bd9Sstevel@tonic-gate 	{0x01e001e0, 0x01f101f1},
6017c478bd9Sstevel@tonic-gate 	{0x1ffe1ffe, 0x0efe0efe},
6027c478bd9Sstevel@tonic-gate 	{0x011f011f, 0x010e010e},
6037c478bd9Sstevel@tonic-gate 	{0xe0fee0fe, 0xf1fef1fe},
6047c478bd9Sstevel@tonic-gate 	{0xfe01fe01, 0xfe01fe01},
6057c478bd9Sstevel@tonic-gate 	{0xe01fe01f, 0xf10ef10e},
6067c478bd9Sstevel@tonic-gate 	{0xe001e001, 0xf101f101},
6077c478bd9Sstevel@tonic-gate 	{0xfe1ffe1f, 0xfe0efe0e},
6087c478bd9Sstevel@tonic-gate 	{0x1f011f01, 0x0e010e01},
6097c478bd9Sstevel@tonic-gate 	{0xfee0fee0, 0xfef1fef1}
6107c478bd9Sstevel@tonic-gate };
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate static int
6137c478bd9Sstevel@tonic-gate weak_DES_key(des_block db)
6147c478bd9Sstevel@tonic-gate {
6157c478bd9Sstevel@tonic-gate 	int i;
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	for (i = 0; i < sizeof (weakDESkeys)/sizeof (struct DESkey); i++) {
6187c478bd9Sstevel@tonic-gate 		if (weakDESkeys[i].h1 == db.key.high &&
619*61961e0fSrobinson 			weakDESkeys[i].h2 == db.key.low)
6207c478bd9Sstevel@tonic-gate 			return (1);
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	return (0);
6247c478bd9Sstevel@tonic-gate }
625