16532Swyllys /*
26532Swyllys * CDDL HEADER START
36532Swyllys *
46532Swyllys * The contents of this file are subject to the terms of the
56532Swyllys * Common Development and Distribution License (the "License").
66532Swyllys * You may not use this file except in compliance with the License.
76532Swyllys *
86532Swyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96532Swyllys * or http://www.opensolaris.org/os/licensing.
106532Swyllys * See the License for the specific language governing permissions
116532Swyllys * and limitations under the License.
126532Swyllys *
136532Swyllys * When distributing Covered Code, include this CDDL HEADER in each
146532Swyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156532Swyllys * If applicable, add the following below this CDDL HEADER, with the
166532Swyllys * fields enclosed by brackets "[]" replaced with your own identifying
176532Swyllys * information: Portions Copyright [yyyy] [name of copyright owner]
186532Swyllys *
196532Swyllys * CDDL HEADER END
206532Swyllys */
216532Swyllys /*
229557SWyllys.Ingersoll@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
236532Swyllys * Use is subject to license terms.
246532Swyllys */
256532Swyllys
266532Swyllys /*
276532Swyllys * Portions of this code from crypt_bsdmd5.so (bsdmd5.c) :
286532Swyllys * ----------------------------------------------------------------------------
296532Swyllys * "THE BEER-WARE LICENSE" (Revision 42):
306532Swyllys * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
316532Swyllys * can do whatever you want with this stuff. If we meet some day, and you think
326532Swyllys * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
336532Swyllys * ----------------------------------------------------------------------------
346532Swyllys *
356532Swyllys * $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $
366532Swyllys *
376532Swyllys */
386532Swyllys
396532Swyllys /*
406532Swyllys * Implements the specification from:
416532Swyllys *
426532Swyllys * From http://people.redhat.com/drepper/SHA-crypt.txt
436532Swyllys *
446532Swyllys * Portions of the code taken from inspired by or verified against the
456532Swyllys * source in the above document which is licensed as:
466532Swyllys *
476532Swyllys * "Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>."
486532Swyllys */
496532Swyllys
506532Swyllys
516532Swyllys #include <sys/types.h>
526532Swyllys #include <sys/stat.h>
536532Swyllys #include <sys/sysmacros.h>
546532Swyllys #include <fcntl.h>
556532Swyllys #include <unistd.h>
566532Swyllys #include <string.h>
576532Swyllys #include <stdio.h>
586532Swyllys #include <errno.h>
596532Swyllys #include <stdlib.h>
606532Swyllys #include <alloca.h>
616532Swyllys
626532Swyllys #include <sha2.h>
636532Swyllys #include <crypt.h>
646532Swyllys
656532Swyllys #define MAX_SALT_LEN 16
666532Swyllys #define ROUNDS_DEFAULT 5000
676532Swyllys #define ROUNDS_MIN 1000
686532Swyllys #define ROUNDS_MAX 999999999
696532Swyllys
706532Swyllys #ifdef CRYPT_SHA256
716532Swyllys
726532Swyllys #define DIGEST_CTX SHA256_CTX
736532Swyllys #define DIGESTInit SHA256Init
746532Swyllys #define DIGESTUpdate SHA256Update
756532Swyllys #define DIGESTFinal SHA256Final
766532Swyllys #define DIGEST_LEN SHA256_DIGEST_LENGTH
776532Swyllys #define MIXCHARS 32
789557SWyllys.Ingersoll@Sun.COM static const char crypt_alg_magic[] = "$5";
796532Swyllys
806532Swyllys #elif CRYPT_SHA512
816532Swyllys
826532Swyllys #define DIGEST_CTX SHA512_CTX
836532Swyllys #define DIGESTInit SHA512Init
846532Swyllys #define DIGESTUpdate SHA512Update
856532Swyllys #define DIGESTFinal SHA512Final
866532Swyllys #define DIGEST_LEN SHA512_DIGEST_LENGTH
876532Swyllys #define MIXCHARS 64
889557SWyllys.Ingersoll@Sun.COM static const char crypt_alg_magic[] = "$6";
896532Swyllys
906532Swyllys #else
916532Swyllys #error "One of CRYPT_256 or CRYPT_512 must be defined"
926532Swyllys #endif
936532Swyllys
946532Swyllys static const int crypt_alg_magic_len = sizeof (crypt_alg_magic) - 1;
956532Swyllys
966532Swyllys
976532Swyllys static uchar_t b64t[] = /* 0 ... 63 => ascii - 64 */
986532Swyllys "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
996532Swyllys
1006532Swyllys #define b64_from_24bit(B2, B1, B0, N) \
1016532Swyllys { \
1026532Swyllys uint_t w = ((B2) << 16) | ((B1) << 8) | (B0); \
1036532Swyllys int n = (N); \
1046532Swyllys while (--n >= 0 && ctbufflen > 0) { \
1056532Swyllys *p++ = b64t[w & 0x3f]; \
1066532Swyllys w >>= 6; \
1076532Swyllys ctbufflen--; \
1086532Swyllys } \
1096532Swyllys }
1106532Swyllys
1116532Swyllys static void
to64(char * s,uint64_t v,int n)1126532Swyllys to64(char *s, uint64_t v, int n)
1136532Swyllys {
1146532Swyllys while (--n >= 0) {
115*10935Sopensolaris@drydog.com *s++ = b64t[v & 0x3f];
1166532Swyllys v >>= 6;
1176532Swyllys }
1186532Swyllys }
1196532Swyllys
1209557SWyllys.Ingersoll@Sun.COM #define ROUNDS "rounds="
1219557SWyllys.Ingersoll@Sun.COM #define ROUNDSLEN (sizeof (ROUNDS) - 1)
1229557SWyllys.Ingersoll@Sun.COM
1239557SWyllys.Ingersoll@Sun.COM /*
1249557SWyllys.Ingersoll@Sun.COM * get the integer value after rounds= where ever it occurs in the string.
1259557SWyllys.Ingersoll@Sun.COM * if the last char after the int is a , or $ that is fine anything else is an
1269557SWyllys.Ingersoll@Sun.COM * error.
1279557SWyllys.Ingersoll@Sun.COM */
1289557SWyllys.Ingersoll@Sun.COM static uint32_t
getrounds(const char * s)1299557SWyllys.Ingersoll@Sun.COM getrounds(const char *s)
1309557SWyllys.Ingersoll@Sun.COM {
1319557SWyllys.Ingersoll@Sun.COM char *r, *p, *e;
1329557SWyllys.Ingersoll@Sun.COM long val;
1339557SWyllys.Ingersoll@Sun.COM
1349557SWyllys.Ingersoll@Sun.COM if (s == NULL)
1359557SWyllys.Ingersoll@Sun.COM return (0);
1369557SWyllys.Ingersoll@Sun.COM
1379557SWyllys.Ingersoll@Sun.COM if ((r = strstr(s, ROUNDS)) == NULL) {
1389557SWyllys.Ingersoll@Sun.COM return (0);
1399557SWyllys.Ingersoll@Sun.COM }
1409557SWyllys.Ingersoll@Sun.COM
1419557SWyllys.Ingersoll@Sun.COM if (strncmp(r, ROUNDS, ROUNDSLEN) != 0) {
1429557SWyllys.Ingersoll@Sun.COM return (0);
1439557SWyllys.Ingersoll@Sun.COM }
1449557SWyllys.Ingersoll@Sun.COM
1459557SWyllys.Ingersoll@Sun.COM p = r + ROUNDSLEN;
1469557SWyllys.Ingersoll@Sun.COM errno = 0;
1479557SWyllys.Ingersoll@Sun.COM val = strtol(p, &e, 10);
1489557SWyllys.Ingersoll@Sun.COM /*
149*10935Sopensolaris@drydog.com * An error occurred or there is non-numeric stuff at the end
1509557SWyllys.Ingersoll@Sun.COM * which isn't one of the crypt(3c) special chars ',' or '$'
1519557SWyllys.Ingersoll@Sun.COM */
1529557SWyllys.Ingersoll@Sun.COM if (errno != 0 || val < 0 ||
1539557SWyllys.Ingersoll@Sun.COM !(*e == '\0' || *e == ',' || *e == '$')) {
1549557SWyllys.Ingersoll@Sun.COM return (0);
1559557SWyllys.Ingersoll@Sun.COM }
1569557SWyllys.Ingersoll@Sun.COM
1579557SWyllys.Ingersoll@Sun.COM return ((uint32_t)val);
1589557SWyllys.Ingersoll@Sun.COM }
1599557SWyllys.Ingersoll@Sun.COM
1609557SWyllys.Ingersoll@Sun.COM
161*10935Sopensolaris@drydog.com /* ARGSUSED4 */
1626532Swyllys char *
crypt_genhash_impl(char * ctbuffer,size_t ctbufflen,const char * plaintext,const char * switchsalt,const char ** params)1636532Swyllys crypt_genhash_impl(char *ctbuffer,
1646532Swyllys size_t ctbufflen,
1656532Swyllys const char *plaintext,
1666532Swyllys const char *switchsalt,
1676532Swyllys const char **params)
1686532Swyllys {
1696532Swyllys int salt_len, plaintext_len, i;
1706532Swyllys char *salt;
1716532Swyllys uchar_t A[DIGEST_LEN];
1726532Swyllys uchar_t B[DIGEST_LEN];
1736532Swyllys uchar_t DP[DIGEST_LEN];
1746532Swyllys uchar_t DS[DIGEST_LEN];
1756532Swyllys DIGEST_CTX ctxA, ctxB, ctxC, ctxDP, ctxDS;
1766532Swyllys int rounds = ROUNDS_DEFAULT;
1779557SWyllys.Ingersoll@Sun.COM int srounds = 0;
1786532Swyllys boolean_t custom_rounds = B_FALSE;
1796532Swyllys char *p;
1806532Swyllys char *P, *Pp;
1816532Swyllys char *S, *Sp;
1826532Swyllys
1836532Swyllys /* Refine the salt */
1846532Swyllys salt = (char *)switchsalt;
1856532Swyllys
1866532Swyllys /* skip our magic string */
1876532Swyllys if (strncmp((char *)salt, crypt_alg_magic, crypt_alg_magic_len) == 0) {
1889557SWyllys.Ingersoll@Sun.COM salt += crypt_alg_magic_len + 1;
1896532Swyllys }
1906532Swyllys
1919557SWyllys.Ingersoll@Sun.COM srounds = getrounds(salt);
1929557SWyllys.Ingersoll@Sun.COM if (srounds != 0) {
1939557SWyllys.Ingersoll@Sun.COM rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
1949557SWyllys.Ingersoll@Sun.COM custom_rounds = B_TRUE;
1959557SWyllys.Ingersoll@Sun.COM p = strchr(salt, '$');
1969557SWyllys.Ingersoll@Sun.COM if (p != NULL)
1979557SWyllys.Ingersoll@Sun.COM salt = p + 1;
1986532Swyllys }
1996532Swyllys
2006532Swyllys salt_len = MIN(strcspn(salt, "$"), MAX_SALT_LEN);
2016532Swyllys plaintext_len = strlen(plaintext);
2026532Swyllys
2036532Swyllys /* 1. */
2046532Swyllys DIGESTInit(&ctxA);
2056532Swyllys
2066532Swyllys /* 2. The password first, since that is what is most unknown */
2076532Swyllys DIGESTUpdate(&ctxA, plaintext, plaintext_len);
2086532Swyllys
2096532Swyllys /* 3. Then the raw salt */
2106532Swyllys DIGESTUpdate(&ctxA, salt, salt_len);
2116532Swyllys
2126532Swyllys /* 4. - 8. */
2136532Swyllys DIGESTInit(&ctxB);
2146532Swyllys DIGESTUpdate(&ctxB, plaintext, plaintext_len);
2156532Swyllys DIGESTUpdate(&ctxB, salt, salt_len);
2166532Swyllys DIGESTUpdate(&ctxB, plaintext, plaintext_len);
2176532Swyllys DIGESTFinal(B, &ctxB);
2186532Swyllys
2196532Swyllys /* 9. - 10. */
2206532Swyllys for (i = plaintext_len; i > MIXCHARS; i -= MIXCHARS)
2216532Swyllys DIGESTUpdate(&ctxA, B, MIXCHARS);
2226532Swyllys DIGESTUpdate(&ctxA, B, i);
2236532Swyllys
2246532Swyllys /* 11. */
2256532Swyllys for (i = plaintext_len; i > 0; i >>= 1) {
2266532Swyllys if ((i & 1) != 0) {
2276532Swyllys DIGESTUpdate(&ctxA, B, MIXCHARS);
2286532Swyllys } else {
2296532Swyllys DIGESTUpdate(&ctxA, plaintext, plaintext_len);
2306532Swyllys }
2316532Swyllys }
2326532Swyllys
2336532Swyllys /* 12. */
2346532Swyllys DIGESTFinal(A, &ctxA);
2356532Swyllys
2366532Swyllys /* 13. - 15. */
2376532Swyllys DIGESTInit(&ctxDP);
2386532Swyllys for (i = 0; i < plaintext_len; i++)
2396532Swyllys DIGESTUpdate(&ctxDP, plaintext, plaintext_len);
2406532Swyllys DIGESTFinal(DP, &ctxDP);
2416532Swyllys
2426532Swyllys /* 16. */
2436532Swyllys Pp = P = alloca(plaintext_len);
2446532Swyllys for (i = plaintext_len; i >= MIXCHARS; i -= MIXCHARS) {
2456532Swyllys Pp = (char *)(memcpy(Pp, DP, MIXCHARS)) + MIXCHARS;
2466532Swyllys }
247*10935Sopensolaris@drydog.com (void) memcpy(Pp, DP, i);
2486532Swyllys
2496532Swyllys /* 17. - 19. */
2506532Swyllys DIGESTInit(&ctxDS);
2516532Swyllys for (i = 0; i < 16 + (uint8_t)A[0]; i++)
2526532Swyllys DIGESTUpdate(&ctxDS, salt, salt_len);
2536532Swyllys DIGESTFinal(DS, &ctxDS);
2546532Swyllys
2556532Swyllys /* 20. */
2566532Swyllys Sp = S = alloca(salt_len);
2576532Swyllys for (i = salt_len; i >= MIXCHARS; i -= MIXCHARS) {
2586532Swyllys Sp = (char *)(memcpy(Sp, DS, MIXCHARS)) + MIXCHARS;
2596532Swyllys }
260*10935Sopensolaris@drydog.com (void) memcpy(Sp, DS, i);
2616532Swyllys
2626532Swyllys /* 21. */
2636532Swyllys for (i = 0; i < rounds; i++) {
2646532Swyllys DIGESTInit(&ctxC);
2656532Swyllys
2666532Swyllys if ((i & 1) != 0) {
2676532Swyllys DIGESTUpdate(&ctxC, P, plaintext_len);
2686532Swyllys } else {
2696532Swyllys if (i == 0)
2706532Swyllys DIGESTUpdate(&ctxC, A, MIXCHARS);
2716532Swyllys else
2726532Swyllys DIGESTUpdate(&ctxC, DP, MIXCHARS);
2736532Swyllys }
2746532Swyllys
2756532Swyllys if (i % 3 != 0) {
2766532Swyllys DIGESTUpdate(&ctxC, S, salt_len);
2776532Swyllys }
2786532Swyllys
2796532Swyllys if (i % 7 != 0) {
2806532Swyllys DIGESTUpdate(&ctxC, P, plaintext_len);
2816532Swyllys }
2826532Swyllys
2836532Swyllys if ((i & 1) != 0) {
2846532Swyllys if (i == 0)
2856532Swyllys DIGESTUpdate(&ctxC, A, MIXCHARS);
2866532Swyllys else
2876532Swyllys DIGESTUpdate(&ctxC, DP, MIXCHARS);
2886532Swyllys } else {
2896532Swyllys DIGESTUpdate(&ctxC, P, plaintext_len);
2906532Swyllys }
2916532Swyllys DIGESTFinal(DP, &ctxC);
2926532Swyllys }
2936532Swyllys
2946532Swyllys /* 22. Now make the output string */
2956532Swyllys if (custom_rounds) {
2966532Swyllys (void) snprintf(ctbuffer, ctbufflen,
2979557SWyllys.Ingersoll@Sun.COM "%s$rounds=%zu$", crypt_alg_magic, rounds);
2989557SWyllys.Ingersoll@Sun.COM } else {
2999557SWyllys.Ingersoll@Sun.COM (void) snprintf(ctbuffer, ctbufflen,
3009557SWyllys.Ingersoll@Sun.COM "%s$", crypt_alg_magic);
3016532Swyllys }
3027314SWyllys.Ingersoll@Sun.COM (void) strncat(ctbuffer, (const char *)salt, salt_len);
3036532Swyllys (void) strlcat(ctbuffer, "$", ctbufflen);
3049557SWyllys.Ingersoll@Sun.COM
3056532Swyllys p = ctbuffer + strlen(ctbuffer);
3066532Swyllys ctbufflen -= strlen(ctbuffer);
3076532Swyllys
3086532Swyllys #ifdef CRYPT_SHA256
3096532Swyllys b64_from_24bit(DP[ 0], DP[10], DP[20], 4);
3106532Swyllys b64_from_24bit(DP[21], DP[ 1], DP[11], 4);
3116532Swyllys b64_from_24bit(DP[12], DP[22], DP[ 2], 4);
3126532Swyllys b64_from_24bit(DP[ 3], DP[13], DP[23], 4);
3136532Swyllys b64_from_24bit(DP[24], DP[ 4], DP[14], 4);
3146532Swyllys b64_from_24bit(DP[15], DP[25], DP[ 5], 4);
3156532Swyllys b64_from_24bit(DP[ 6], DP[16], DP[26], 4);
3166532Swyllys b64_from_24bit(DP[27], DP[ 7], DP[17], 4);
3176532Swyllys b64_from_24bit(DP[18], DP[28], DP[ 8], 4);
3186532Swyllys b64_from_24bit(DP[ 9], DP[19], DP[29], 4);
3196532Swyllys b64_from_24bit(0, DP[31], DP[30], 3);
3206532Swyllys #elif CRYPT_SHA512
3216532Swyllys b64_from_24bit(DP[ 0], DP[21], DP[42], 4);
3226532Swyllys b64_from_24bit(DP[22], DP[43], DP[ 1], 4);
3236532Swyllys b64_from_24bit(DP[44], DP[ 2], DP[23], 4);
3246532Swyllys b64_from_24bit(DP[ 3], DP[24], DP[45], 4);
3256532Swyllys b64_from_24bit(DP[25], DP[46], DP[ 4], 4);
3266532Swyllys b64_from_24bit(DP[47], DP[ 5], DP[26], 4);
3276532Swyllys b64_from_24bit(DP[ 6], DP[27], DP[48], 4);
3286532Swyllys b64_from_24bit(DP[28], DP[49], DP[ 7], 4);
3296532Swyllys b64_from_24bit(DP[50], DP[ 8], DP[29], 4);
3306532Swyllys b64_from_24bit(DP[ 9], DP[30], DP[51], 4);
3316532Swyllys b64_from_24bit(DP[31], DP[52], DP[10], 4);
3326532Swyllys b64_from_24bit(DP[53], DP[11], DP[32], 4);
3336532Swyllys b64_from_24bit(DP[12], DP[33], DP[54], 4);
3346532Swyllys b64_from_24bit(DP[34], DP[55], DP[13], 4);
3356532Swyllys b64_from_24bit(DP[56], DP[14], DP[35], 4);
3366532Swyllys b64_from_24bit(DP[15], DP[36], DP[57], 4);
3376532Swyllys b64_from_24bit(DP[37], DP[58], DP[16], 4);
3386532Swyllys b64_from_24bit(DP[59], DP[17], DP[38], 4);
3396532Swyllys b64_from_24bit(DP[18], DP[39], DP[60], 4);
3406532Swyllys b64_from_24bit(DP[40], DP[61], DP[19], 4);
3416532Swyllys b64_from_24bit(DP[62], DP[20], DP[41], 4);
3426532Swyllys b64_from_24bit(0, 0, DP[63], 2);
3436532Swyllys #endif
3446532Swyllys *p = '\0';
3456532Swyllys
3466532Swyllys (void) memset(A, 0, sizeof (A));
3476532Swyllys (void) memset(B, 0, sizeof (B));
3486532Swyllys (void) memset(DP, 0, sizeof (DP));
3496532Swyllys (void) memset(DS, 0, sizeof (DS));
3506532Swyllys
3516532Swyllys return (ctbuffer);
3526532Swyllys }
3536532Swyllys
354*10935Sopensolaris@drydog.com
355*10935Sopensolaris@drydog.com /* ARGSUSED3 */
3566532Swyllys char *
crypt_gensalt_impl(char * gsbuffer,size_t gsbufflen,const char * oldsalt,const struct passwd * userinfo,const char ** params)3576532Swyllys crypt_gensalt_impl(char *gsbuffer,
3586532Swyllys size_t gsbufflen,
3596532Swyllys const char *oldsalt,
3606532Swyllys const struct passwd *userinfo,
3616532Swyllys const char **params)
3626532Swyllys {
3636532Swyllys int fd;
3646532Swyllys int err;
3656532Swyllys ssize_t got;
3666532Swyllys uint64_t rndval;
3679557SWyllys.Ingersoll@Sun.COM uint32_t confrounds = 0;
3689557SWyllys.Ingersoll@Sun.COM uint32_t saltrounds;
3699557SWyllys.Ingersoll@Sun.COM char rndstr[sizeof (rndval) + 1];
3709557SWyllys.Ingersoll@Sun.COM int i;
3719557SWyllys.Ingersoll@Sun.COM
3729557SWyllys.Ingersoll@Sun.COM for (i = 0; params != NULL && params[i] != NULL; i++) {
3739557SWyllys.Ingersoll@Sun.COM if (strncmp(params[i], ROUNDS, ROUNDSLEN) == 0) {
3749557SWyllys.Ingersoll@Sun.COM confrounds = getrounds(params[i]);
3759557SWyllys.Ingersoll@Sun.COM } else {
3769557SWyllys.Ingersoll@Sun.COM errno = EINVAL;
3779557SWyllys.Ingersoll@Sun.COM return (NULL);
3789557SWyllys.Ingersoll@Sun.COM }
3799557SWyllys.Ingersoll@Sun.COM }
3809557SWyllys.Ingersoll@Sun.COM
3819557SWyllys.Ingersoll@Sun.COM /*
3829557SWyllys.Ingersoll@Sun.COM * If the config file has a higher value for rounds= than what
3839557SWyllys.Ingersoll@Sun.COM * was in the old salt use that, otherwise keep what was in the
3849557SWyllys.Ingersoll@Sun.COM * old salt.
3859557SWyllys.Ingersoll@Sun.COM */
3869557SWyllys.Ingersoll@Sun.COM saltrounds = getrounds(oldsalt);
3879557SWyllys.Ingersoll@Sun.COM if (confrounds > saltrounds) {
3889557SWyllys.Ingersoll@Sun.COM saltrounds = confrounds;
3899557SWyllys.Ingersoll@Sun.COM }
3906532Swyllys
3916532Swyllys if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
3926532Swyllys return (NULL);
3936532Swyllys }
3946532Swyllys
3956532Swyllys got = read(fd, &rndval, sizeof (rndval));
3966532Swyllys if (got < sizeof (rndval)) {
3976532Swyllys err = errno;
3986532Swyllys (void) close(fd);
3996532Swyllys errno = err;
4006532Swyllys return (NULL);
4016532Swyllys }
4026532Swyllys (void) close(fd);
4036532Swyllys
4049557SWyllys.Ingersoll@Sun.COM to64((char *)&rndstr, rndval, sizeof (rndval));
4059557SWyllys.Ingersoll@Sun.COM rndstr[sizeof (rndstr) - 1] = 0;
4069557SWyllys.Ingersoll@Sun.COM
4079557SWyllys.Ingersoll@Sun.COM if (saltrounds > 0) {
4089557SWyllys.Ingersoll@Sun.COM if (snprintf(gsbuffer, gsbufflen,
4099557SWyllys.Ingersoll@Sun.COM "%s$rounds=%d$",
4109557SWyllys.Ingersoll@Sun.COM crypt_alg_magic, saltrounds) >= gsbufflen)
4119557SWyllys.Ingersoll@Sun.COM goto fail;
4129557SWyllys.Ingersoll@Sun.COM } else {
4139557SWyllys.Ingersoll@Sun.COM if (snprintf(gsbuffer, gsbufflen,
4149557SWyllys.Ingersoll@Sun.COM "%s$", crypt_alg_magic) >= gsbufflen)
4159557SWyllys.Ingersoll@Sun.COM goto fail;
4169557SWyllys.Ingersoll@Sun.COM }
4179557SWyllys.Ingersoll@Sun.COM if (strlcat(gsbuffer, rndstr, gsbufflen) >= gsbufflen)
4189557SWyllys.Ingersoll@Sun.COM goto fail;
4199557SWyllys.Ingersoll@Sun.COM if (strlcat(gsbuffer, "$", gsbufflen) >= gsbufflen)
4209557SWyllys.Ingersoll@Sun.COM goto fail;
4219557SWyllys.Ingersoll@Sun.COM
4229557SWyllys.Ingersoll@Sun.COM return (gsbuffer);
4239557SWyllys.Ingersoll@Sun.COM
4249557SWyllys.Ingersoll@Sun.COM fail:
4259557SWyllys.Ingersoll@Sun.COM (void) memset(gsbuffer, 0, gsbufflen);
4266532Swyllys return (gsbuffer);
4276532Swyllys }
428