10cd13cbfSwyllys /*
20cd13cbfSwyllys  * CDDL HEADER START
30cd13cbfSwyllys  *
40cd13cbfSwyllys  * The contents of this file are subject to the terms of the
50cd13cbfSwyllys  * Common Development and Distribution License (the "License").
60cd13cbfSwyllys  * You may not use this file except in compliance with the License.
70cd13cbfSwyllys  *
80cd13cbfSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90cd13cbfSwyllys  * or http://www.opensolaris.org/os/licensing.
100cd13cbfSwyllys  * See the License for the specific language governing permissions
110cd13cbfSwyllys  * and limitations under the License.
120cd13cbfSwyllys  *
130cd13cbfSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
140cd13cbfSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150cd13cbfSwyllys  * If applicable, add the following below this CDDL HEADER, with the
160cd13cbfSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
170cd13cbfSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
180cd13cbfSwyllys  *
190cd13cbfSwyllys  * CDDL HEADER END
200cd13cbfSwyllys  */
210cd13cbfSwyllys /*
220cd13cbfSwyllys  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230cd13cbfSwyllys  * Use is subject to license terms.
240cd13cbfSwyllys  */
250cd13cbfSwyllys 
260cd13cbfSwyllys /*
270cd13cbfSwyllys  * Portions of this code from crypt_bsdmd5.so (bsdmd5.c) :
280cd13cbfSwyllys  * ----------------------------------------------------------------------------
290cd13cbfSwyllys  * "THE BEER-WARE LICENSE" (Revision 42):
300cd13cbfSwyllys  * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
310cd13cbfSwyllys  * can do whatever you want with this stuff. If we meet some day, and you think
320cd13cbfSwyllys  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
330cd13cbfSwyllys  * ----------------------------------------------------------------------------
340cd13cbfSwyllys  *
350cd13cbfSwyllys  * $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $
360cd13cbfSwyllys  *
370cd13cbfSwyllys  */
380cd13cbfSwyllys 
390cd13cbfSwyllys /*
400cd13cbfSwyllys  * Implements the specification from:
410cd13cbfSwyllys  *
420cd13cbfSwyllys  * From http://people.redhat.com/drepper/SHA-crypt.txt
430cd13cbfSwyllys  *
440cd13cbfSwyllys  * Portions of the code taken from inspired by or verified against the
450cd13cbfSwyllys  * source in the above document which is licensed as:
460cd13cbfSwyllys  *
470cd13cbfSwyllys  * "Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>."
480cd13cbfSwyllys  */
490cd13cbfSwyllys 
500cd13cbfSwyllys 
510cd13cbfSwyllys #include <sys/types.h>
520cd13cbfSwyllys #include <sys/stat.h>
530cd13cbfSwyllys #include <sys/sysmacros.h>
540cd13cbfSwyllys #include <fcntl.h>
550cd13cbfSwyllys #include <unistd.h>
560cd13cbfSwyllys #include <string.h>
570cd13cbfSwyllys #include <stdio.h>
580cd13cbfSwyllys #include <errno.h>
590cd13cbfSwyllys #include <stdlib.h>
600cd13cbfSwyllys #include <alloca.h>
610cd13cbfSwyllys 
620cd13cbfSwyllys #include <sha2.h>
630cd13cbfSwyllys #include <crypt.h>
640cd13cbfSwyllys 
650cd13cbfSwyllys #define	MAX_SALT_LEN	16
660cd13cbfSwyllys #define	ROUNDS_DEFAULT	5000
670cd13cbfSwyllys #define	ROUNDS_MIN	1000
680cd13cbfSwyllys #define	ROUNDS_MAX	999999999
690cd13cbfSwyllys 
700cd13cbfSwyllys #ifdef CRYPT_SHA256
710cd13cbfSwyllys 
720cd13cbfSwyllys #define	DIGEST_CTX	SHA256_CTX
730cd13cbfSwyllys #define	DIGESTInit	SHA256Init
740cd13cbfSwyllys #define	DIGESTUpdate	SHA256Update
750cd13cbfSwyllys #define	DIGESTFinal	SHA256Final
760cd13cbfSwyllys #define	DIGEST_LEN	SHA256_DIGEST_LENGTH
770cd13cbfSwyllys #define	MIXCHARS	32
780cd13cbfSwyllys static const char crypt_alg_magic[] = "$5$";
790cd13cbfSwyllys 
800cd13cbfSwyllys #elif CRYPT_SHA512
810cd13cbfSwyllys 
820cd13cbfSwyllys #define	DIGEST_CTX	SHA512_CTX
830cd13cbfSwyllys #define	DIGESTInit	SHA512Init
840cd13cbfSwyllys #define	DIGESTUpdate	SHA512Update
850cd13cbfSwyllys #define	DIGESTFinal	SHA512Final
860cd13cbfSwyllys #define	DIGEST_LEN	SHA512_DIGEST_LENGTH
870cd13cbfSwyllys #define	MIXCHARS	64
880cd13cbfSwyllys static const char crypt_alg_magic[] = "$6$";
890cd13cbfSwyllys 
900cd13cbfSwyllys #else
910cd13cbfSwyllys #error	"One of CRYPT_256 or CRYPT_512 must be defined"
920cd13cbfSwyllys #endif
930cd13cbfSwyllys 
940cd13cbfSwyllys static const int crypt_alg_magic_len = sizeof (crypt_alg_magic) - 1;
950cd13cbfSwyllys static const char rounds_prefix[] = "rounds=";
960cd13cbfSwyllys 
970cd13cbfSwyllys 
980cd13cbfSwyllys static uchar_t b64t[] =		/* 0 ... 63 => ascii - 64 */
990cd13cbfSwyllys 	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1000cd13cbfSwyllys 
1010cd13cbfSwyllys #define	b64_from_24bit(B2, B1, B0, N) \
1020cd13cbfSwyllys { \
1030cd13cbfSwyllys 	uint_t w = ((B2) << 16) | ((B1) << 8) | (B0); \
1040cd13cbfSwyllys 	int n = (N); \
1050cd13cbfSwyllys 	while (--n >= 0 && ctbufflen > 0) { \
1060cd13cbfSwyllys 		*p++ = b64t[w & 0x3f]; \
1070cd13cbfSwyllys 		w >>= 6; \
1080cd13cbfSwyllys 		ctbufflen--; \
1090cd13cbfSwyllys 	} \
1100cd13cbfSwyllys }
1110cd13cbfSwyllys 
1120cd13cbfSwyllys static void
1130cd13cbfSwyllys to64(char *s, uint64_t v, int n)
1140cd13cbfSwyllys {
1150cd13cbfSwyllys 	while (--n >= 0) {
1160cd13cbfSwyllys 		*s++ = b64t[v&0x3f];
1170cd13cbfSwyllys 		v >>= 6;
1180cd13cbfSwyllys 	}
1190cd13cbfSwyllys }
1200cd13cbfSwyllys 
1210cd13cbfSwyllys char *
1220cd13cbfSwyllys crypt_genhash_impl(char *ctbuffer,
1230cd13cbfSwyllys 	    size_t ctbufflen,
1240cd13cbfSwyllys 	    const char *plaintext,
1250cd13cbfSwyllys 	    const char *switchsalt,
1260cd13cbfSwyllys 	    const char **params)
1270cd13cbfSwyllys {
1280cd13cbfSwyllys 	int salt_len, plaintext_len, i;
1290cd13cbfSwyllys 	char *salt;
1300cd13cbfSwyllys 	uchar_t A[DIGEST_LEN];
1310cd13cbfSwyllys 	uchar_t B[DIGEST_LEN];
1320cd13cbfSwyllys 	uchar_t DP[DIGEST_LEN];
1330cd13cbfSwyllys 	uchar_t DS[DIGEST_LEN];
1340cd13cbfSwyllys 	DIGEST_CTX ctxA, ctxB, ctxC, ctxDP, ctxDS;
1350cd13cbfSwyllys 	int rounds = ROUNDS_DEFAULT;
1360cd13cbfSwyllys 	boolean_t custom_rounds = B_FALSE;
1370cd13cbfSwyllys 	char *p;
1380cd13cbfSwyllys 	char *P, *Pp;
1390cd13cbfSwyllys 	char *S, *Sp;
1400cd13cbfSwyllys 
1410cd13cbfSwyllys 	/* Refine the salt */
1420cd13cbfSwyllys 	salt = (char *)switchsalt;
1430cd13cbfSwyllys 
1440cd13cbfSwyllys 	/* skip our magic string */
1450cd13cbfSwyllys 	if (strncmp((char *)salt, crypt_alg_magic, crypt_alg_magic_len) == 0) {
1460cd13cbfSwyllys 		salt += crypt_alg_magic_len;
1470cd13cbfSwyllys 	}
1480cd13cbfSwyllys 
1490cd13cbfSwyllys 	if (strncmp(salt, rounds_prefix, sizeof (rounds_prefix) - 1) == 0) {
1500cd13cbfSwyllys 		char *num = salt + sizeof (rounds_prefix) - 1;
1510cd13cbfSwyllys 		char *endp;
1520cd13cbfSwyllys 		ulong_t srounds = strtoul(num, &endp, 10);
1530cd13cbfSwyllys 		if (*endp == '$') {
1540cd13cbfSwyllys 			salt = endp + 1;
1550cd13cbfSwyllys 			rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
1560cd13cbfSwyllys 			custom_rounds = B_TRUE;
1570cd13cbfSwyllys 		}
1580cd13cbfSwyllys 	}
1590cd13cbfSwyllys 
1600cd13cbfSwyllys 	salt_len = MIN(strcspn(salt, "$"), MAX_SALT_LEN);
1610cd13cbfSwyllys 	plaintext_len = strlen(plaintext);
1620cd13cbfSwyllys 
1630cd13cbfSwyllys 	/* 1. */
1640cd13cbfSwyllys 	DIGESTInit(&ctxA);
1650cd13cbfSwyllys 
1660cd13cbfSwyllys 	/* 2. The password first, since that is what is most unknown */
1670cd13cbfSwyllys 	DIGESTUpdate(&ctxA, plaintext, plaintext_len);
1680cd13cbfSwyllys 
1690cd13cbfSwyllys 	/* 3. Then the raw salt */
1700cd13cbfSwyllys 	DIGESTUpdate(&ctxA, salt, salt_len);
1710cd13cbfSwyllys 
1720cd13cbfSwyllys 	/* 4. - 8. */
1730cd13cbfSwyllys 	DIGESTInit(&ctxB);
1740cd13cbfSwyllys 	DIGESTUpdate(&ctxB, plaintext, plaintext_len);
1750cd13cbfSwyllys 	DIGESTUpdate(&ctxB, salt, salt_len);
1760cd13cbfSwyllys 	DIGESTUpdate(&ctxB, plaintext, plaintext_len);
1770cd13cbfSwyllys 	DIGESTFinal(B, &ctxB);
1780cd13cbfSwyllys 
1790cd13cbfSwyllys 	/* 9. - 10. */
1800cd13cbfSwyllys 	for (i = plaintext_len; i > MIXCHARS; i -= MIXCHARS)
1810cd13cbfSwyllys 		DIGESTUpdate(&ctxA, B, MIXCHARS);
1820cd13cbfSwyllys 	DIGESTUpdate(&ctxA, B, i);
1830cd13cbfSwyllys 
1840cd13cbfSwyllys 	/* 11. */
1850cd13cbfSwyllys 	for (i = plaintext_len; i > 0; i >>= 1) {
1860cd13cbfSwyllys 		if ((i & 1) != 0) {
1870cd13cbfSwyllys 			DIGESTUpdate(&ctxA, B, MIXCHARS);
1880cd13cbfSwyllys 		} else {
1890cd13cbfSwyllys 			DIGESTUpdate(&ctxA, plaintext, plaintext_len);
1900cd13cbfSwyllys 		}
1910cd13cbfSwyllys 	}
1920cd13cbfSwyllys 
1930cd13cbfSwyllys 	/* 12. */
1940cd13cbfSwyllys 	DIGESTFinal(A, &ctxA);
1950cd13cbfSwyllys 
1960cd13cbfSwyllys 	/* 13. - 15. */
1970cd13cbfSwyllys 	DIGESTInit(&ctxDP);
1980cd13cbfSwyllys 	for (i = 0; i < plaintext_len; i++)
1990cd13cbfSwyllys 		DIGESTUpdate(&ctxDP, plaintext, plaintext_len);
2000cd13cbfSwyllys 	DIGESTFinal(DP, &ctxDP);
2010cd13cbfSwyllys 
2020cd13cbfSwyllys 	/* 16. */
2030cd13cbfSwyllys 	Pp = P = alloca(plaintext_len);
2040cd13cbfSwyllys 	for (i = plaintext_len; i >= MIXCHARS; i -= MIXCHARS) {
2050cd13cbfSwyllys 		Pp = (char *)(memcpy(Pp, DP, MIXCHARS)) + MIXCHARS;
2060cd13cbfSwyllys 	}
2070cd13cbfSwyllys 	memcpy(Pp, DP, i);
2080cd13cbfSwyllys 
2090cd13cbfSwyllys 	/* 17. - 19. */
2100cd13cbfSwyllys 	DIGESTInit(&ctxDS);
2110cd13cbfSwyllys 	for (i = 0; i < 16 + (uint8_t)A[0]; i++)
2120cd13cbfSwyllys 		DIGESTUpdate(&ctxDS, salt, salt_len);
2130cd13cbfSwyllys 	DIGESTFinal(DS, &ctxDS);
2140cd13cbfSwyllys 
2150cd13cbfSwyllys 	/* 20. */
2160cd13cbfSwyllys 	Sp = S = alloca(salt_len);
2170cd13cbfSwyllys 	for (i = salt_len; i >= MIXCHARS; i -= MIXCHARS) {
2180cd13cbfSwyllys 		Sp = (char *)(memcpy(Sp, DS, MIXCHARS)) + MIXCHARS;
2190cd13cbfSwyllys 	}
2200cd13cbfSwyllys 	memcpy(Sp, DS, i);
2210cd13cbfSwyllys 
2220cd13cbfSwyllys 	/*  21. */
2230cd13cbfSwyllys 	for (i = 0; i < rounds; i++) {
2240cd13cbfSwyllys 		DIGESTInit(&ctxC);
2250cd13cbfSwyllys 
2260cd13cbfSwyllys 		if ((i & 1) != 0) {
2270cd13cbfSwyllys 			DIGESTUpdate(&ctxC, P, plaintext_len);
2280cd13cbfSwyllys 		} else {
2290cd13cbfSwyllys 			if (i == 0)
2300cd13cbfSwyllys 				DIGESTUpdate(&ctxC, A, MIXCHARS);
2310cd13cbfSwyllys 			else
2320cd13cbfSwyllys 				DIGESTUpdate(&ctxC, DP, MIXCHARS);
2330cd13cbfSwyllys 		}
2340cd13cbfSwyllys 
2350cd13cbfSwyllys 		if (i % 3 != 0) {
2360cd13cbfSwyllys 			DIGESTUpdate(&ctxC, S, salt_len);
2370cd13cbfSwyllys 		}
2380cd13cbfSwyllys 
2390cd13cbfSwyllys 		if (i % 7 != 0) {
2400cd13cbfSwyllys 			DIGESTUpdate(&ctxC, P, plaintext_len);
2410cd13cbfSwyllys 		}
2420cd13cbfSwyllys 
2430cd13cbfSwyllys 		if ((i & 1) != 0) {
2440cd13cbfSwyllys 			if (i == 0)
2450cd13cbfSwyllys 				DIGESTUpdate(&ctxC, A, MIXCHARS);
2460cd13cbfSwyllys 			else
2470cd13cbfSwyllys 				DIGESTUpdate(&ctxC, DP, MIXCHARS);
2480cd13cbfSwyllys 		} else {
2490cd13cbfSwyllys 			DIGESTUpdate(&ctxC, P, plaintext_len);
2500cd13cbfSwyllys 		}
2510cd13cbfSwyllys 		DIGESTFinal(DP, &ctxC);
2520cd13cbfSwyllys 	}
2530cd13cbfSwyllys 
2540cd13cbfSwyllys 	/* 22. Now make the output string */
2550cd13cbfSwyllys 	(void) strlcpy(ctbuffer, crypt_alg_magic, ctbufflen);
2560cd13cbfSwyllys 	if (custom_rounds) {
2570cd13cbfSwyllys 		(void) snprintf(ctbuffer, ctbufflen,
2580cd13cbfSwyllys 		    "%srounds=%zu$", ctbuffer, rounds);
2590cd13cbfSwyllys 	}
2600cd13cbfSwyllys 
261*20ed34ccSWyllys Ingersoll 	(void) strncat(ctbuffer, (const char *)salt, salt_len);
2620cd13cbfSwyllys 	(void) strlcat(ctbuffer, "$", ctbufflen);
2630cd13cbfSwyllys 	p = ctbuffer + strlen(ctbuffer);
2640cd13cbfSwyllys 	ctbufflen -= strlen(ctbuffer);
2650cd13cbfSwyllys 
2660cd13cbfSwyllys #ifdef CRYPT_SHA256
2670cd13cbfSwyllys 	b64_from_24bit(DP[ 0], DP[10], DP[20], 4);
2680cd13cbfSwyllys 	b64_from_24bit(DP[21], DP[ 1], DP[11], 4);
2690cd13cbfSwyllys 	b64_from_24bit(DP[12], DP[22], DP[ 2], 4);
2700cd13cbfSwyllys 	b64_from_24bit(DP[ 3], DP[13], DP[23], 4);
2710cd13cbfSwyllys 	b64_from_24bit(DP[24], DP[ 4], DP[14], 4);
2720cd13cbfSwyllys 	b64_from_24bit(DP[15], DP[25], DP[ 5], 4);
2730cd13cbfSwyllys 	b64_from_24bit(DP[ 6], DP[16], DP[26], 4);
2740cd13cbfSwyllys 	b64_from_24bit(DP[27], DP[ 7], DP[17], 4);
2750cd13cbfSwyllys 	b64_from_24bit(DP[18], DP[28], DP[ 8], 4);
2760cd13cbfSwyllys 	b64_from_24bit(DP[ 9], DP[19], DP[29], 4);
2770cd13cbfSwyllys 	b64_from_24bit(0, DP[31], DP[30], 3);
2780cd13cbfSwyllys #elif CRYPT_SHA512
2790cd13cbfSwyllys 	b64_from_24bit(DP[ 0], DP[21], DP[42], 4);
2800cd13cbfSwyllys 	b64_from_24bit(DP[22], DP[43], DP[ 1], 4);
2810cd13cbfSwyllys 	b64_from_24bit(DP[44], DP[ 2], DP[23], 4);
2820cd13cbfSwyllys 	b64_from_24bit(DP[ 3], DP[24], DP[45], 4);
2830cd13cbfSwyllys 	b64_from_24bit(DP[25], DP[46], DP[ 4], 4);
2840cd13cbfSwyllys 	b64_from_24bit(DP[47], DP[ 5], DP[26], 4);
2850cd13cbfSwyllys 	b64_from_24bit(DP[ 6], DP[27], DP[48], 4);
2860cd13cbfSwyllys 	b64_from_24bit(DP[28], DP[49], DP[ 7], 4);
2870cd13cbfSwyllys 	b64_from_24bit(DP[50], DP[ 8], DP[29], 4);
2880cd13cbfSwyllys 	b64_from_24bit(DP[ 9], DP[30], DP[51], 4);
2890cd13cbfSwyllys 	b64_from_24bit(DP[31], DP[52], DP[10], 4);
2900cd13cbfSwyllys 	b64_from_24bit(DP[53], DP[11], DP[32], 4);
2910cd13cbfSwyllys 	b64_from_24bit(DP[12], DP[33], DP[54], 4);
2920cd13cbfSwyllys 	b64_from_24bit(DP[34], DP[55], DP[13], 4);
2930cd13cbfSwyllys 	b64_from_24bit(DP[56], DP[14], DP[35], 4);
2940cd13cbfSwyllys 	b64_from_24bit(DP[15], DP[36], DP[57], 4);
2950cd13cbfSwyllys 	b64_from_24bit(DP[37], DP[58], DP[16], 4);
2960cd13cbfSwyllys 	b64_from_24bit(DP[59], DP[17], DP[38], 4);
2970cd13cbfSwyllys 	b64_from_24bit(DP[18], DP[39], DP[60], 4);
2980cd13cbfSwyllys 	b64_from_24bit(DP[40], DP[61], DP[19], 4);
2990cd13cbfSwyllys 	b64_from_24bit(DP[62], DP[20], DP[41], 4);
3000cd13cbfSwyllys 	b64_from_24bit(0, 0, DP[63], 2);
3010cd13cbfSwyllys #endif
3020cd13cbfSwyllys 	*p = '\0';
3030cd13cbfSwyllys 
3040cd13cbfSwyllys 	(void) memset(A, 0, sizeof (A));
3050cd13cbfSwyllys 	(void) memset(B, 0, sizeof (B));
3060cd13cbfSwyllys 	(void) memset(DP, 0, sizeof (DP));
3070cd13cbfSwyllys 	(void) memset(DS, 0, sizeof (DS));
3080cd13cbfSwyllys 
3090cd13cbfSwyllys 	return (ctbuffer);
3100cd13cbfSwyllys }
3110cd13cbfSwyllys 
3120cd13cbfSwyllys char *
3130cd13cbfSwyllys crypt_gensalt_impl(char *gsbuffer,
3140cd13cbfSwyllys 	    size_t gsbufflen,
3150cd13cbfSwyllys 	    const char *oldsalt,
3160cd13cbfSwyllys 	    const struct passwd *userinfo,
3170cd13cbfSwyllys 	    const char **params)
3180cd13cbfSwyllys {
3190cd13cbfSwyllys 	int fd;
3200cd13cbfSwyllys 	int err;
3210cd13cbfSwyllys 	ssize_t got;
3220cd13cbfSwyllys 	uint64_t rndval;
3230cd13cbfSwyllys 
3240cd13cbfSwyllys 	if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
3250cd13cbfSwyllys 		return (NULL);
3260cd13cbfSwyllys 	}
3270cd13cbfSwyllys 
3280cd13cbfSwyllys 	(void) strlcpy(gsbuffer, crypt_alg_magic, gsbufflen);
3290cd13cbfSwyllys 
3300cd13cbfSwyllys 	got = read(fd, &rndval, sizeof (rndval));
3310cd13cbfSwyllys 	if (got < sizeof (rndval)) {
3320cd13cbfSwyllys 		err = errno;
3330cd13cbfSwyllys 		(void) close(fd);
3340cd13cbfSwyllys 		errno = err;
3350cd13cbfSwyllys 		return (NULL);
3360cd13cbfSwyllys 	}
3370cd13cbfSwyllys 
3380cd13cbfSwyllys 	to64(&gsbuffer[strlen(crypt_alg_magic)], rndval, sizeof (rndval));
3390cd13cbfSwyllys 
3400cd13cbfSwyllys 	(void) close(fd);
3410cd13cbfSwyllys 
3420cd13cbfSwyllys 	return (gsbuffer);
3430cd13cbfSwyllys }
344