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 /* 22*0ca46ac5SWyllys Ingersoll * Copyright 2009 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 78*0ca46ac5SWyllys Ingersoll 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 88*0ca46ac5SWyllys Ingersoll 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 960cd13cbfSwyllys 970cd13cbfSwyllys static uchar_t b64t[] = /* 0 ... 63 => ascii - 64 */ 980cd13cbfSwyllys "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 990cd13cbfSwyllys 1000cd13cbfSwyllys #define b64_from_24bit(B2, B1, B0, N) \ 1010cd13cbfSwyllys { \ 1020cd13cbfSwyllys uint_t w = ((B2) << 16) | ((B1) << 8) | (B0); \ 1030cd13cbfSwyllys int n = (N); \ 1040cd13cbfSwyllys while (--n >= 0 && ctbufflen > 0) { \ 1050cd13cbfSwyllys *p++ = b64t[w & 0x3f]; \ 1060cd13cbfSwyllys w >>= 6; \ 1070cd13cbfSwyllys ctbufflen--; \ 1080cd13cbfSwyllys } \ 1090cd13cbfSwyllys } 1100cd13cbfSwyllys 1110cd13cbfSwyllys static void 1120cd13cbfSwyllys to64(char *s, uint64_t v, int n) 1130cd13cbfSwyllys { 1140cd13cbfSwyllys while (--n >= 0) { 1150cd13cbfSwyllys *s++ = b64t[v&0x3f]; 1160cd13cbfSwyllys v >>= 6; 1170cd13cbfSwyllys } 1180cd13cbfSwyllys } 1190cd13cbfSwyllys 120*0ca46ac5SWyllys Ingersoll #define ROUNDS "rounds=" 121*0ca46ac5SWyllys Ingersoll #define ROUNDSLEN (sizeof (ROUNDS) - 1) 122*0ca46ac5SWyllys Ingersoll 123*0ca46ac5SWyllys Ingersoll /* 124*0ca46ac5SWyllys Ingersoll * get the integer value after rounds= where ever it occurs in the string. 125*0ca46ac5SWyllys Ingersoll * if the last char after the int is a , or $ that is fine anything else is an 126*0ca46ac5SWyllys Ingersoll * error. 127*0ca46ac5SWyllys Ingersoll */ 128*0ca46ac5SWyllys Ingersoll static uint32_t 129*0ca46ac5SWyllys Ingersoll getrounds(const char *s) 130*0ca46ac5SWyllys Ingersoll { 131*0ca46ac5SWyllys Ingersoll char *r, *p, *e; 132*0ca46ac5SWyllys Ingersoll long val; 133*0ca46ac5SWyllys Ingersoll 134*0ca46ac5SWyllys Ingersoll if (s == NULL) 135*0ca46ac5SWyllys Ingersoll return (0); 136*0ca46ac5SWyllys Ingersoll 137*0ca46ac5SWyllys Ingersoll if ((r = strstr(s, ROUNDS)) == NULL) { 138*0ca46ac5SWyllys Ingersoll return (0); 139*0ca46ac5SWyllys Ingersoll } 140*0ca46ac5SWyllys Ingersoll 141*0ca46ac5SWyllys Ingersoll if (strncmp(r, ROUNDS, ROUNDSLEN) != 0) { 142*0ca46ac5SWyllys Ingersoll return (0); 143*0ca46ac5SWyllys Ingersoll } 144*0ca46ac5SWyllys Ingersoll 145*0ca46ac5SWyllys Ingersoll p = r + ROUNDSLEN; 146*0ca46ac5SWyllys Ingersoll errno = 0; 147*0ca46ac5SWyllys Ingersoll val = strtol(p, &e, 10); 148*0ca46ac5SWyllys Ingersoll /* 149*0ca46ac5SWyllys Ingersoll * An error occured or there is non-numeric stuff at the end 150*0ca46ac5SWyllys Ingersoll * which isn't one of the crypt(3c) special chars ',' or '$' 151*0ca46ac5SWyllys Ingersoll */ 152*0ca46ac5SWyllys Ingersoll if (errno != 0 || val < 0 || 153*0ca46ac5SWyllys Ingersoll !(*e == '\0' || *e == ',' || *e == '$')) { 154*0ca46ac5SWyllys Ingersoll return (0); 155*0ca46ac5SWyllys Ingersoll } 156*0ca46ac5SWyllys Ingersoll 157*0ca46ac5SWyllys Ingersoll return ((uint32_t)val); 158*0ca46ac5SWyllys Ingersoll } 159*0ca46ac5SWyllys Ingersoll 160*0ca46ac5SWyllys Ingersoll 1610cd13cbfSwyllys char * 1620cd13cbfSwyllys crypt_genhash_impl(char *ctbuffer, 1630cd13cbfSwyllys size_t ctbufflen, 1640cd13cbfSwyllys const char *plaintext, 1650cd13cbfSwyllys const char *switchsalt, 1660cd13cbfSwyllys const char **params) 1670cd13cbfSwyllys { 1680cd13cbfSwyllys int salt_len, plaintext_len, i; 1690cd13cbfSwyllys char *salt; 1700cd13cbfSwyllys uchar_t A[DIGEST_LEN]; 1710cd13cbfSwyllys uchar_t B[DIGEST_LEN]; 1720cd13cbfSwyllys uchar_t DP[DIGEST_LEN]; 1730cd13cbfSwyllys uchar_t DS[DIGEST_LEN]; 1740cd13cbfSwyllys DIGEST_CTX ctxA, ctxB, ctxC, ctxDP, ctxDS; 1750cd13cbfSwyllys int rounds = ROUNDS_DEFAULT; 176*0ca46ac5SWyllys Ingersoll int srounds = 0; 1770cd13cbfSwyllys boolean_t custom_rounds = B_FALSE; 1780cd13cbfSwyllys char *p; 1790cd13cbfSwyllys char *P, *Pp; 1800cd13cbfSwyllys char *S, *Sp; 1810cd13cbfSwyllys 1820cd13cbfSwyllys /* Refine the salt */ 1830cd13cbfSwyllys salt = (char *)switchsalt; 1840cd13cbfSwyllys 1850cd13cbfSwyllys /* skip our magic string */ 1860cd13cbfSwyllys if (strncmp((char *)salt, crypt_alg_magic, crypt_alg_magic_len) == 0) { 187*0ca46ac5SWyllys Ingersoll salt += crypt_alg_magic_len + 1; 1880cd13cbfSwyllys } 1890cd13cbfSwyllys 190*0ca46ac5SWyllys Ingersoll srounds = getrounds(salt); 191*0ca46ac5SWyllys Ingersoll if (srounds != 0) { 192*0ca46ac5SWyllys Ingersoll rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX)); 193*0ca46ac5SWyllys Ingersoll custom_rounds = B_TRUE; 194*0ca46ac5SWyllys Ingersoll p = strchr(salt, '$'); 195*0ca46ac5SWyllys Ingersoll if (p != NULL) 196*0ca46ac5SWyllys Ingersoll salt = p + 1; 1970cd13cbfSwyllys } 1980cd13cbfSwyllys 1990cd13cbfSwyllys salt_len = MIN(strcspn(salt, "$"), MAX_SALT_LEN); 2000cd13cbfSwyllys plaintext_len = strlen(plaintext); 2010cd13cbfSwyllys 2020cd13cbfSwyllys /* 1. */ 2030cd13cbfSwyllys DIGESTInit(&ctxA); 2040cd13cbfSwyllys 2050cd13cbfSwyllys /* 2. The password first, since that is what is most unknown */ 2060cd13cbfSwyllys DIGESTUpdate(&ctxA, plaintext, plaintext_len); 2070cd13cbfSwyllys 2080cd13cbfSwyllys /* 3. Then the raw salt */ 2090cd13cbfSwyllys DIGESTUpdate(&ctxA, salt, salt_len); 2100cd13cbfSwyllys 2110cd13cbfSwyllys /* 4. - 8. */ 2120cd13cbfSwyllys DIGESTInit(&ctxB); 2130cd13cbfSwyllys DIGESTUpdate(&ctxB, plaintext, plaintext_len); 2140cd13cbfSwyllys DIGESTUpdate(&ctxB, salt, salt_len); 2150cd13cbfSwyllys DIGESTUpdate(&ctxB, plaintext, plaintext_len); 2160cd13cbfSwyllys DIGESTFinal(B, &ctxB); 2170cd13cbfSwyllys 2180cd13cbfSwyllys /* 9. - 10. */ 2190cd13cbfSwyllys for (i = plaintext_len; i > MIXCHARS; i -= MIXCHARS) 2200cd13cbfSwyllys DIGESTUpdate(&ctxA, B, MIXCHARS); 2210cd13cbfSwyllys DIGESTUpdate(&ctxA, B, i); 2220cd13cbfSwyllys 2230cd13cbfSwyllys /* 11. */ 2240cd13cbfSwyllys for (i = plaintext_len; i > 0; i >>= 1) { 2250cd13cbfSwyllys if ((i & 1) != 0) { 2260cd13cbfSwyllys DIGESTUpdate(&ctxA, B, MIXCHARS); 2270cd13cbfSwyllys } else { 2280cd13cbfSwyllys DIGESTUpdate(&ctxA, plaintext, plaintext_len); 2290cd13cbfSwyllys } 2300cd13cbfSwyllys } 2310cd13cbfSwyllys 2320cd13cbfSwyllys /* 12. */ 2330cd13cbfSwyllys DIGESTFinal(A, &ctxA); 2340cd13cbfSwyllys 2350cd13cbfSwyllys /* 13. - 15. */ 2360cd13cbfSwyllys DIGESTInit(&ctxDP); 2370cd13cbfSwyllys for (i = 0; i < plaintext_len; i++) 2380cd13cbfSwyllys DIGESTUpdate(&ctxDP, plaintext, plaintext_len); 2390cd13cbfSwyllys DIGESTFinal(DP, &ctxDP); 2400cd13cbfSwyllys 2410cd13cbfSwyllys /* 16. */ 2420cd13cbfSwyllys Pp = P = alloca(plaintext_len); 2430cd13cbfSwyllys for (i = plaintext_len; i >= MIXCHARS; i -= MIXCHARS) { 2440cd13cbfSwyllys Pp = (char *)(memcpy(Pp, DP, MIXCHARS)) + MIXCHARS; 2450cd13cbfSwyllys } 2460cd13cbfSwyllys memcpy(Pp, DP, i); 2470cd13cbfSwyllys 2480cd13cbfSwyllys /* 17. - 19. */ 2490cd13cbfSwyllys DIGESTInit(&ctxDS); 2500cd13cbfSwyllys for (i = 0; i < 16 + (uint8_t)A[0]; i++) 2510cd13cbfSwyllys DIGESTUpdate(&ctxDS, salt, salt_len); 2520cd13cbfSwyllys DIGESTFinal(DS, &ctxDS); 2530cd13cbfSwyllys 2540cd13cbfSwyllys /* 20. */ 2550cd13cbfSwyllys Sp = S = alloca(salt_len); 2560cd13cbfSwyllys for (i = salt_len; i >= MIXCHARS; i -= MIXCHARS) { 2570cd13cbfSwyllys Sp = (char *)(memcpy(Sp, DS, MIXCHARS)) + MIXCHARS; 2580cd13cbfSwyllys } 2590cd13cbfSwyllys memcpy(Sp, DS, i); 2600cd13cbfSwyllys 2610cd13cbfSwyllys /* 21. */ 2620cd13cbfSwyllys for (i = 0; i < rounds; i++) { 2630cd13cbfSwyllys DIGESTInit(&ctxC); 2640cd13cbfSwyllys 2650cd13cbfSwyllys if ((i & 1) != 0) { 2660cd13cbfSwyllys DIGESTUpdate(&ctxC, P, plaintext_len); 2670cd13cbfSwyllys } else { 2680cd13cbfSwyllys if (i == 0) 2690cd13cbfSwyllys DIGESTUpdate(&ctxC, A, MIXCHARS); 2700cd13cbfSwyllys else 2710cd13cbfSwyllys DIGESTUpdate(&ctxC, DP, MIXCHARS); 2720cd13cbfSwyllys } 2730cd13cbfSwyllys 2740cd13cbfSwyllys if (i % 3 != 0) { 2750cd13cbfSwyllys DIGESTUpdate(&ctxC, S, salt_len); 2760cd13cbfSwyllys } 2770cd13cbfSwyllys 2780cd13cbfSwyllys if (i % 7 != 0) { 2790cd13cbfSwyllys DIGESTUpdate(&ctxC, P, plaintext_len); 2800cd13cbfSwyllys } 2810cd13cbfSwyllys 2820cd13cbfSwyllys if ((i & 1) != 0) { 2830cd13cbfSwyllys if (i == 0) 2840cd13cbfSwyllys DIGESTUpdate(&ctxC, A, MIXCHARS); 2850cd13cbfSwyllys else 2860cd13cbfSwyllys DIGESTUpdate(&ctxC, DP, MIXCHARS); 2870cd13cbfSwyllys } else { 2880cd13cbfSwyllys DIGESTUpdate(&ctxC, P, plaintext_len); 2890cd13cbfSwyllys } 2900cd13cbfSwyllys DIGESTFinal(DP, &ctxC); 2910cd13cbfSwyllys } 2920cd13cbfSwyllys 2930cd13cbfSwyllys /* 22. Now make the output string */ 2940cd13cbfSwyllys if (custom_rounds) { 2950cd13cbfSwyllys (void) snprintf(ctbuffer, ctbufflen, 296*0ca46ac5SWyllys Ingersoll "%s$rounds=%zu$", crypt_alg_magic, rounds); 297*0ca46ac5SWyllys Ingersoll } else { 298*0ca46ac5SWyllys Ingersoll (void) snprintf(ctbuffer, ctbufflen, 299*0ca46ac5SWyllys Ingersoll "%s$", crypt_alg_magic); 3000cd13cbfSwyllys } 30120ed34ccSWyllys Ingersoll (void) strncat(ctbuffer, (const char *)salt, salt_len); 3020cd13cbfSwyllys (void) strlcat(ctbuffer, "$", ctbufflen); 303*0ca46ac5SWyllys Ingersoll 3040cd13cbfSwyllys p = ctbuffer + strlen(ctbuffer); 3050cd13cbfSwyllys ctbufflen -= strlen(ctbuffer); 3060cd13cbfSwyllys 3070cd13cbfSwyllys #ifdef CRYPT_SHA256 3080cd13cbfSwyllys b64_from_24bit(DP[ 0], DP[10], DP[20], 4); 3090cd13cbfSwyllys b64_from_24bit(DP[21], DP[ 1], DP[11], 4); 3100cd13cbfSwyllys b64_from_24bit(DP[12], DP[22], DP[ 2], 4); 3110cd13cbfSwyllys b64_from_24bit(DP[ 3], DP[13], DP[23], 4); 3120cd13cbfSwyllys b64_from_24bit(DP[24], DP[ 4], DP[14], 4); 3130cd13cbfSwyllys b64_from_24bit(DP[15], DP[25], DP[ 5], 4); 3140cd13cbfSwyllys b64_from_24bit(DP[ 6], DP[16], DP[26], 4); 3150cd13cbfSwyllys b64_from_24bit(DP[27], DP[ 7], DP[17], 4); 3160cd13cbfSwyllys b64_from_24bit(DP[18], DP[28], DP[ 8], 4); 3170cd13cbfSwyllys b64_from_24bit(DP[ 9], DP[19], DP[29], 4); 3180cd13cbfSwyllys b64_from_24bit(0, DP[31], DP[30], 3); 3190cd13cbfSwyllys #elif CRYPT_SHA512 3200cd13cbfSwyllys b64_from_24bit(DP[ 0], DP[21], DP[42], 4); 3210cd13cbfSwyllys b64_from_24bit(DP[22], DP[43], DP[ 1], 4); 3220cd13cbfSwyllys b64_from_24bit(DP[44], DP[ 2], DP[23], 4); 3230cd13cbfSwyllys b64_from_24bit(DP[ 3], DP[24], DP[45], 4); 3240cd13cbfSwyllys b64_from_24bit(DP[25], DP[46], DP[ 4], 4); 3250cd13cbfSwyllys b64_from_24bit(DP[47], DP[ 5], DP[26], 4); 3260cd13cbfSwyllys b64_from_24bit(DP[ 6], DP[27], DP[48], 4); 3270cd13cbfSwyllys b64_from_24bit(DP[28], DP[49], DP[ 7], 4); 3280cd13cbfSwyllys b64_from_24bit(DP[50], DP[ 8], DP[29], 4); 3290cd13cbfSwyllys b64_from_24bit(DP[ 9], DP[30], DP[51], 4); 3300cd13cbfSwyllys b64_from_24bit(DP[31], DP[52], DP[10], 4); 3310cd13cbfSwyllys b64_from_24bit(DP[53], DP[11], DP[32], 4); 3320cd13cbfSwyllys b64_from_24bit(DP[12], DP[33], DP[54], 4); 3330cd13cbfSwyllys b64_from_24bit(DP[34], DP[55], DP[13], 4); 3340cd13cbfSwyllys b64_from_24bit(DP[56], DP[14], DP[35], 4); 3350cd13cbfSwyllys b64_from_24bit(DP[15], DP[36], DP[57], 4); 3360cd13cbfSwyllys b64_from_24bit(DP[37], DP[58], DP[16], 4); 3370cd13cbfSwyllys b64_from_24bit(DP[59], DP[17], DP[38], 4); 3380cd13cbfSwyllys b64_from_24bit(DP[18], DP[39], DP[60], 4); 3390cd13cbfSwyllys b64_from_24bit(DP[40], DP[61], DP[19], 4); 3400cd13cbfSwyllys b64_from_24bit(DP[62], DP[20], DP[41], 4); 3410cd13cbfSwyllys b64_from_24bit(0, 0, DP[63], 2); 3420cd13cbfSwyllys #endif 3430cd13cbfSwyllys *p = '\0'; 3440cd13cbfSwyllys 3450cd13cbfSwyllys (void) memset(A, 0, sizeof (A)); 3460cd13cbfSwyllys (void) memset(B, 0, sizeof (B)); 3470cd13cbfSwyllys (void) memset(DP, 0, sizeof (DP)); 3480cd13cbfSwyllys (void) memset(DS, 0, sizeof (DS)); 3490cd13cbfSwyllys 3500cd13cbfSwyllys return (ctbuffer); 3510cd13cbfSwyllys } 3520cd13cbfSwyllys 3530cd13cbfSwyllys char * 3540cd13cbfSwyllys crypt_gensalt_impl(char *gsbuffer, 3550cd13cbfSwyllys size_t gsbufflen, 3560cd13cbfSwyllys const char *oldsalt, 3570cd13cbfSwyllys const struct passwd *userinfo, 3580cd13cbfSwyllys const char **params) 3590cd13cbfSwyllys { 3600cd13cbfSwyllys int fd; 3610cd13cbfSwyllys int err; 3620cd13cbfSwyllys ssize_t got; 3630cd13cbfSwyllys uint64_t rndval; 364*0ca46ac5SWyllys Ingersoll uint32_t confrounds = 0; 365*0ca46ac5SWyllys Ingersoll uint32_t saltrounds; 366*0ca46ac5SWyllys Ingersoll char rndstr[sizeof (rndval) + 1]; 367*0ca46ac5SWyllys Ingersoll int i; 368*0ca46ac5SWyllys Ingersoll 369*0ca46ac5SWyllys Ingersoll for (i = 0; params != NULL && params[i] != NULL; i++) { 370*0ca46ac5SWyllys Ingersoll if (strncmp(params[i], ROUNDS, ROUNDSLEN) == 0) { 371*0ca46ac5SWyllys Ingersoll confrounds = getrounds(params[i]); 372*0ca46ac5SWyllys Ingersoll } else { 373*0ca46ac5SWyllys Ingersoll errno = EINVAL; 374*0ca46ac5SWyllys Ingersoll return (NULL); 375*0ca46ac5SWyllys Ingersoll } 376*0ca46ac5SWyllys Ingersoll } 377*0ca46ac5SWyllys Ingersoll 378*0ca46ac5SWyllys Ingersoll /* 379*0ca46ac5SWyllys Ingersoll * If the config file has a higher value for rounds= than what 380*0ca46ac5SWyllys Ingersoll * was in the old salt use that, otherwise keep what was in the 381*0ca46ac5SWyllys Ingersoll * old salt. 382*0ca46ac5SWyllys Ingersoll */ 383*0ca46ac5SWyllys Ingersoll saltrounds = getrounds(oldsalt); 384*0ca46ac5SWyllys Ingersoll if (confrounds > saltrounds) { 385*0ca46ac5SWyllys Ingersoll saltrounds = confrounds; 386*0ca46ac5SWyllys Ingersoll } 3870cd13cbfSwyllys 3880cd13cbfSwyllys if ((fd = open("/dev/urandom", O_RDONLY)) == -1) { 3890cd13cbfSwyllys return (NULL); 3900cd13cbfSwyllys } 3910cd13cbfSwyllys 3920cd13cbfSwyllys got = read(fd, &rndval, sizeof (rndval)); 3930cd13cbfSwyllys if (got < sizeof (rndval)) { 3940cd13cbfSwyllys err = errno; 3950cd13cbfSwyllys (void) close(fd); 3960cd13cbfSwyllys errno = err; 3970cd13cbfSwyllys return (NULL); 3980cd13cbfSwyllys } 399*0ca46ac5SWyllys Ingersoll (void) close(fd); 4000cd13cbfSwyllys 401*0ca46ac5SWyllys Ingersoll to64((char *)&rndstr, rndval, sizeof (rndval)); 402*0ca46ac5SWyllys Ingersoll rndstr[sizeof (rndstr) - 1] = 0; 403*0ca46ac5SWyllys Ingersoll 404*0ca46ac5SWyllys Ingersoll if (saltrounds > 0) { 405*0ca46ac5SWyllys Ingersoll if (snprintf(gsbuffer, gsbufflen, 406*0ca46ac5SWyllys Ingersoll "%s$rounds=%d$", 407*0ca46ac5SWyllys Ingersoll crypt_alg_magic, saltrounds) >= gsbufflen) 408*0ca46ac5SWyllys Ingersoll goto fail; 409*0ca46ac5SWyllys Ingersoll } else { 410*0ca46ac5SWyllys Ingersoll if (snprintf(gsbuffer, gsbufflen, 411*0ca46ac5SWyllys Ingersoll "%s$", crypt_alg_magic) >= gsbufflen) 412*0ca46ac5SWyllys Ingersoll goto fail; 413*0ca46ac5SWyllys Ingersoll } 414*0ca46ac5SWyllys Ingersoll if (strlcat(gsbuffer, rndstr, gsbufflen) >= gsbufflen) 415*0ca46ac5SWyllys Ingersoll goto fail; 416*0ca46ac5SWyllys Ingersoll if (strlcat(gsbuffer, "$", gsbufflen) >= gsbufflen) 417*0ca46ac5SWyllys Ingersoll goto fail; 4180cd13cbfSwyllys 419*0ca46ac5SWyllys Ingersoll return (gsbuffer); 4200cd13cbfSwyllys 421*0ca46ac5SWyllys Ingersoll fail: 422*0ca46ac5SWyllys Ingersoll (void) memset(gsbuffer, 0, gsbufflen); 4230cd13cbfSwyllys return (gsbuffer); 4240cd13cbfSwyllys } 425