1*6532Swyllys /* 2*6532Swyllys * CDDL HEADER START 3*6532Swyllys * 4*6532Swyllys * The contents of this file are subject to the terms of the 5*6532Swyllys * Common Development and Distribution License (the "License"). 6*6532Swyllys * You may not use this file except in compliance with the License. 7*6532Swyllys * 8*6532Swyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6532Swyllys * or http://www.opensolaris.org/os/licensing. 10*6532Swyllys * See the License for the specific language governing permissions 11*6532Swyllys * and limitations under the License. 12*6532Swyllys * 13*6532Swyllys * When distributing Covered Code, include this CDDL HEADER in each 14*6532Swyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6532Swyllys * If applicable, add the following below this CDDL HEADER, with the 16*6532Swyllys * fields enclosed by brackets "[]" replaced with your own identifying 17*6532Swyllys * information: Portions Copyright [yyyy] [name of copyright owner] 18*6532Swyllys * 19*6532Swyllys * CDDL HEADER END 20*6532Swyllys */ 21*6532Swyllys /* 22*6532Swyllys * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*6532Swyllys * Use is subject to license terms. 24*6532Swyllys */ 25*6532Swyllys 26*6532Swyllys #pragma ident "%Z%%M% %I% %E% SMI" 27*6532Swyllys 28*6532Swyllys /* 29*6532Swyllys * Portions of this code from crypt_bsdmd5.so (bsdmd5.c) : 30*6532Swyllys * ---------------------------------------------------------------------------- 31*6532Swyllys * "THE BEER-WARE LICENSE" (Revision 42): 32*6532Swyllys * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 33*6532Swyllys * can do whatever you want with this stuff. If we meet some day, and you think 34*6532Swyllys * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 35*6532Swyllys * ---------------------------------------------------------------------------- 36*6532Swyllys * 37*6532Swyllys * $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $ 38*6532Swyllys * 39*6532Swyllys */ 40*6532Swyllys 41*6532Swyllys /* 42*6532Swyllys * Implements the specification from: 43*6532Swyllys * 44*6532Swyllys * From http://people.redhat.com/drepper/SHA-crypt.txt 45*6532Swyllys * 46*6532Swyllys * Portions of the code taken from inspired by or verified against the 47*6532Swyllys * source in the above document which is licensed as: 48*6532Swyllys * 49*6532Swyllys * "Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>." 50*6532Swyllys */ 51*6532Swyllys 52*6532Swyllys 53*6532Swyllys #include <sys/types.h> 54*6532Swyllys #include <sys/stat.h> 55*6532Swyllys #include <sys/sysmacros.h> 56*6532Swyllys #include <fcntl.h> 57*6532Swyllys #include <unistd.h> 58*6532Swyllys #include <string.h> 59*6532Swyllys #include <stdio.h> 60*6532Swyllys #include <errno.h> 61*6532Swyllys #include <stdlib.h> 62*6532Swyllys #include <alloca.h> 63*6532Swyllys 64*6532Swyllys #include <sha2.h> 65*6532Swyllys #include <crypt.h> 66*6532Swyllys 67*6532Swyllys #define MAX_SALT_LEN 16 68*6532Swyllys #define ROUNDS_DEFAULT 5000 69*6532Swyllys #define ROUNDS_MIN 1000 70*6532Swyllys #define ROUNDS_MAX 999999999 71*6532Swyllys 72*6532Swyllys #ifdef CRYPT_SHA256 73*6532Swyllys 74*6532Swyllys #define DIGEST_CTX SHA256_CTX 75*6532Swyllys #define DIGESTInit SHA256Init 76*6532Swyllys #define DIGESTUpdate SHA256Update 77*6532Swyllys #define DIGESTFinal SHA256Final 78*6532Swyllys #define DIGEST_LEN SHA256_DIGEST_LENGTH 79*6532Swyllys #define MIXCHARS 32 80*6532Swyllys static const char crypt_alg_magic[] = "$5$"; 81*6532Swyllys 82*6532Swyllys #elif CRYPT_SHA512 83*6532Swyllys 84*6532Swyllys #define DIGEST_CTX SHA512_CTX 85*6532Swyllys #define DIGESTInit SHA512Init 86*6532Swyllys #define DIGESTUpdate SHA512Update 87*6532Swyllys #define DIGESTFinal SHA512Final 88*6532Swyllys #define DIGEST_LEN SHA512_DIGEST_LENGTH 89*6532Swyllys #define MIXCHARS 64 90*6532Swyllys static const char crypt_alg_magic[] = "$6$"; 91*6532Swyllys 92*6532Swyllys #else 93*6532Swyllys #error "One of CRYPT_256 or CRYPT_512 must be defined" 94*6532Swyllys #endif 95*6532Swyllys 96*6532Swyllys static const int crypt_alg_magic_len = sizeof (crypt_alg_magic) - 1; 97*6532Swyllys static const char rounds_prefix[] = "rounds="; 98*6532Swyllys 99*6532Swyllys 100*6532Swyllys static uchar_t b64t[] = /* 0 ... 63 => ascii - 64 */ 101*6532Swyllys "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 102*6532Swyllys 103*6532Swyllys #define b64_from_24bit(B2, B1, B0, N) \ 104*6532Swyllys { \ 105*6532Swyllys uint_t w = ((B2) << 16) | ((B1) << 8) | (B0); \ 106*6532Swyllys int n = (N); \ 107*6532Swyllys while (--n >= 0 && ctbufflen > 0) { \ 108*6532Swyllys *p++ = b64t[w & 0x3f]; \ 109*6532Swyllys w >>= 6; \ 110*6532Swyllys ctbufflen--; \ 111*6532Swyllys } \ 112*6532Swyllys } 113*6532Swyllys 114*6532Swyllys static void 115*6532Swyllys to64(char *s, uint64_t v, int n) 116*6532Swyllys { 117*6532Swyllys while (--n >= 0) { 118*6532Swyllys *s++ = b64t[v&0x3f]; 119*6532Swyllys v >>= 6; 120*6532Swyllys } 121*6532Swyllys } 122*6532Swyllys 123*6532Swyllys char * 124*6532Swyllys crypt_genhash_impl(char *ctbuffer, 125*6532Swyllys size_t ctbufflen, 126*6532Swyllys const char *plaintext, 127*6532Swyllys const char *switchsalt, 128*6532Swyllys const char **params) 129*6532Swyllys { 130*6532Swyllys int salt_len, plaintext_len, i; 131*6532Swyllys char *salt; 132*6532Swyllys uchar_t A[DIGEST_LEN]; 133*6532Swyllys uchar_t B[DIGEST_LEN]; 134*6532Swyllys uchar_t DP[DIGEST_LEN]; 135*6532Swyllys uchar_t DS[DIGEST_LEN]; 136*6532Swyllys DIGEST_CTX ctxA, ctxB, ctxC, ctxDP, ctxDS; 137*6532Swyllys int rounds = ROUNDS_DEFAULT; 138*6532Swyllys boolean_t custom_rounds = B_FALSE; 139*6532Swyllys char *p; 140*6532Swyllys char *P, *Pp; 141*6532Swyllys char *S, *Sp; 142*6532Swyllys 143*6532Swyllys /* Refine the salt */ 144*6532Swyllys salt = (char *)switchsalt; 145*6532Swyllys 146*6532Swyllys /* skip our magic string */ 147*6532Swyllys if (strncmp((char *)salt, crypt_alg_magic, crypt_alg_magic_len) == 0) { 148*6532Swyllys salt += crypt_alg_magic_len; 149*6532Swyllys } 150*6532Swyllys 151*6532Swyllys if (strncmp(salt, rounds_prefix, sizeof (rounds_prefix) - 1) == 0) { 152*6532Swyllys char *num = salt + sizeof (rounds_prefix) - 1; 153*6532Swyllys char *endp; 154*6532Swyllys ulong_t srounds = strtoul(num, &endp, 10); 155*6532Swyllys if (*endp == '$') { 156*6532Swyllys salt = endp + 1; 157*6532Swyllys rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX)); 158*6532Swyllys custom_rounds = B_TRUE; 159*6532Swyllys } 160*6532Swyllys } 161*6532Swyllys 162*6532Swyllys salt_len = MIN(strcspn(salt, "$"), MAX_SALT_LEN); 163*6532Swyllys plaintext_len = strlen(plaintext); 164*6532Swyllys 165*6532Swyllys /* 1. */ 166*6532Swyllys DIGESTInit(&ctxA); 167*6532Swyllys 168*6532Swyllys /* 2. The password first, since that is what is most unknown */ 169*6532Swyllys DIGESTUpdate(&ctxA, plaintext, plaintext_len); 170*6532Swyllys 171*6532Swyllys /* 3. Then the raw salt */ 172*6532Swyllys DIGESTUpdate(&ctxA, salt, salt_len); 173*6532Swyllys 174*6532Swyllys /* 4. - 8. */ 175*6532Swyllys DIGESTInit(&ctxB); 176*6532Swyllys DIGESTUpdate(&ctxB, plaintext, plaintext_len); 177*6532Swyllys DIGESTUpdate(&ctxB, salt, salt_len); 178*6532Swyllys DIGESTUpdate(&ctxB, plaintext, plaintext_len); 179*6532Swyllys DIGESTFinal(B, &ctxB); 180*6532Swyllys 181*6532Swyllys /* 9. - 10. */ 182*6532Swyllys for (i = plaintext_len; i > MIXCHARS; i -= MIXCHARS) 183*6532Swyllys DIGESTUpdate(&ctxA, B, MIXCHARS); 184*6532Swyllys DIGESTUpdate(&ctxA, B, i); 185*6532Swyllys 186*6532Swyllys /* 11. */ 187*6532Swyllys for (i = plaintext_len; i > 0; i >>= 1) { 188*6532Swyllys if ((i & 1) != 0) { 189*6532Swyllys DIGESTUpdate(&ctxA, B, MIXCHARS); 190*6532Swyllys } else { 191*6532Swyllys DIGESTUpdate(&ctxA, plaintext, plaintext_len); 192*6532Swyllys } 193*6532Swyllys } 194*6532Swyllys 195*6532Swyllys /* 12. */ 196*6532Swyllys DIGESTFinal(A, &ctxA); 197*6532Swyllys 198*6532Swyllys /* 13. - 15. */ 199*6532Swyllys DIGESTInit(&ctxDP); 200*6532Swyllys for (i = 0; i < plaintext_len; i++) 201*6532Swyllys DIGESTUpdate(&ctxDP, plaintext, plaintext_len); 202*6532Swyllys DIGESTFinal(DP, &ctxDP); 203*6532Swyllys 204*6532Swyllys /* 16. */ 205*6532Swyllys Pp = P = alloca(plaintext_len); 206*6532Swyllys for (i = plaintext_len; i >= MIXCHARS; i -= MIXCHARS) { 207*6532Swyllys Pp = (char *)(memcpy(Pp, DP, MIXCHARS)) + MIXCHARS; 208*6532Swyllys } 209*6532Swyllys memcpy(Pp, DP, i); 210*6532Swyllys 211*6532Swyllys /* 17. - 19. */ 212*6532Swyllys DIGESTInit(&ctxDS); 213*6532Swyllys for (i = 0; i < 16 + (uint8_t)A[0]; i++) 214*6532Swyllys DIGESTUpdate(&ctxDS, salt, salt_len); 215*6532Swyllys DIGESTFinal(DS, &ctxDS); 216*6532Swyllys 217*6532Swyllys /* 20. */ 218*6532Swyllys Sp = S = alloca(salt_len); 219*6532Swyllys for (i = salt_len; i >= MIXCHARS; i -= MIXCHARS) { 220*6532Swyllys Sp = (char *)(memcpy(Sp, DS, MIXCHARS)) + MIXCHARS; 221*6532Swyllys } 222*6532Swyllys memcpy(Sp, DS, i); 223*6532Swyllys 224*6532Swyllys /* 21. */ 225*6532Swyllys for (i = 0; i < rounds; i++) { 226*6532Swyllys DIGESTInit(&ctxC); 227*6532Swyllys 228*6532Swyllys if ((i & 1) != 0) { 229*6532Swyllys DIGESTUpdate(&ctxC, P, plaintext_len); 230*6532Swyllys } else { 231*6532Swyllys if (i == 0) 232*6532Swyllys DIGESTUpdate(&ctxC, A, MIXCHARS); 233*6532Swyllys else 234*6532Swyllys DIGESTUpdate(&ctxC, DP, MIXCHARS); 235*6532Swyllys } 236*6532Swyllys 237*6532Swyllys if (i % 3 != 0) { 238*6532Swyllys DIGESTUpdate(&ctxC, S, salt_len); 239*6532Swyllys } 240*6532Swyllys 241*6532Swyllys if (i % 7 != 0) { 242*6532Swyllys DIGESTUpdate(&ctxC, P, plaintext_len); 243*6532Swyllys } 244*6532Swyllys 245*6532Swyllys if ((i & 1) != 0) { 246*6532Swyllys if (i == 0) 247*6532Swyllys DIGESTUpdate(&ctxC, A, MIXCHARS); 248*6532Swyllys else 249*6532Swyllys DIGESTUpdate(&ctxC, DP, MIXCHARS); 250*6532Swyllys } else { 251*6532Swyllys DIGESTUpdate(&ctxC, P, plaintext_len); 252*6532Swyllys } 253*6532Swyllys DIGESTFinal(DP, &ctxC); 254*6532Swyllys } 255*6532Swyllys 256*6532Swyllys /* 22. Now make the output string */ 257*6532Swyllys (void) strlcpy(ctbuffer, crypt_alg_magic, ctbufflen); 258*6532Swyllys if (custom_rounds) { 259*6532Swyllys (void) snprintf(ctbuffer, ctbufflen, 260*6532Swyllys "%srounds=%zu$", ctbuffer, rounds); 261*6532Swyllys } 262*6532Swyllys 263*6532Swyllys (void) strncat(ctbuffer, (const char *)salt, MAX_SALT_LEN); 264*6532Swyllys (void) strlcat(ctbuffer, "$", ctbufflen); 265*6532Swyllys p = ctbuffer + strlen(ctbuffer); 266*6532Swyllys ctbufflen -= strlen(ctbuffer); 267*6532Swyllys 268*6532Swyllys #ifdef CRYPT_SHA256 269*6532Swyllys b64_from_24bit(DP[ 0], DP[10], DP[20], 4); 270*6532Swyllys b64_from_24bit(DP[21], DP[ 1], DP[11], 4); 271*6532Swyllys b64_from_24bit(DP[12], DP[22], DP[ 2], 4); 272*6532Swyllys b64_from_24bit(DP[ 3], DP[13], DP[23], 4); 273*6532Swyllys b64_from_24bit(DP[24], DP[ 4], DP[14], 4); 274*6532Swyllys b64_from_24bit(DP[15], DP[25], DP[ 5], 4); 275*6532Swyllys b64_from_24bit(DP[ 6], DP[16], DP[26], 4); 276*6532Swyllys b64_from_24bit(DP[27], DP[ 7], DP[17], 4); 277*6532Swyllys b64_from_24bit(DP[18], DP[28], DP[ 8], 4); 278*6532Swyllys b64_from_24bit(DP[ 9], DP[19], DP[29], 4); 279*6532Swyllys b64_from_24bit(0, DP[31], DP[30], 3); 280*6532Swyllys #elif CRYPT_SHA512 281*6532Swyllys b64_from_24bit(DP[ 0], DP[21], DP[42], 4); 282*6532Swyllys b64_from_24bit(DP[22], DP[43], DP[ 1], 4); 283*6532Swyllys b64_from_24bit(DP[44], DP[ 2], DP[23], 4); 284*6532Swyllys b64_from_24bit(DP[ 3], DP[24], DP[45], 4); 285*6532Swyllys b64_from_24bit(DP[25], DP[46], DP[ 4], 4); 286*6532Swyllys b64_from_24bit(DP[47], DP[ 5], DP[26], 4); 287*6532Swyllys b64_from_24bit(DP[ 6], DP[27], DP[48], 4); 288*6532Swyllys b64_from_24bit(DP[28], DP[49], DP[ 7], 4); 289*6532Swyllys b64_from_24bit(DP[50], DP[ 8], DP[29], 4); 290*6532Swyllys b64_from_24bit(DP[ 9], DP[30], DP[51], 4); 291*6532Swyllys b64_from_24bit(DP[31], DP[52], DP[10], 4); 292*6532Swyllys b64_from_24bit(DP[53], DP[11], DP[32], 4); 293*6532Swyllys b64_from_24bit(DP[12], DP[33], DP[54], 4); 294*6532Swyllys b64_from_24bit(DP[34], DP[55], DP[13], 4); 295*6532Swyllys b64_from_24bit(DP[56], DP[14], DP[35], 4); 296*6532Swyllys b64_from_24bit(DP[15], DP[36], DP[57], 4); 297*6532Swyllys b64_from_24bit(DP[37], DP[58], DP[16], 4); 298*6532Swyllys b64_from_24bit(DP[59], DP[17], DP[38], 4); 299*6532Swyllys b64_from_24bit(DP[18], DP[39], DP[60], 4); 300*6532Swyllys b64_from_24bit(DP[40], DP[61], DP[19], 4); 301*6532Swyllys b64_from_24bit(DP[62], DP[20], DP[41], 4); 302*6532Swyllys b64_from_24bit(0, 0, DP[63], 2); 303*6532Swyllys #endif 304*6532Swyllys *p = '\0'; 305*6532Swyllys 306*6532Swyllys (void) memset(A, 0, sizeof (A)); 307*6532Swyllys (void) memset(B, 0, sizeof (B)); 308*6532Swyllys (void) memset(DP, 0, sizeof (DP)); 309*6532Swyllys (void) memset(DS, 0, sizeof (DS)); 310*6532Swyllys 311*6532Swyllys return (ctbuffer); 312*6532Swyllys } 313*6532Swyllys 314*6532Swyllys char * 315*6532Swyllys crypt_gensalt_impl(char *gsbuffer, 316*6532Swyllys size_t gsbufflen, 317*6532Swyllys const char *oldsalt, 318*6532Swyllys const struct passwd *userinfo, 319*6532Swyllys const char **params) 320*6532Swyllys { 321*6532Swyllys int fd; 322*6532Swyllys int err; 323*6532Swyllys ssize_t got; 324*6532Swyllys uint64_t rndval; 325*6532Swyllys 326*6532Swyllys if ((fd = open("/dev/urandom", O_RDONLY)) == -1) { 327*6532Swyllys return (NULL); 328*6532Swyllys } 329*6532Swyllys 330*6532Swyllys (void) strlcpy(gsbuffer, crypt_alg_magic, gsbufflen); 331*6532Swyllys 332*6532Swyllys got = read(fd, &rndval, sizeof (rndval)); 333*6532Swyllys if (got < sizeof (rndval)) { 334*6532Swyllys err = errno; 335*6532Swyllys (void) close(fd); 336*6532Swyllys errno = err; 337*6532Swyllys return (NULL); 338*6532Swyllys } 339*6532Swyllys 340*6532Swyllys to64(&gsbuffer[strlen(crypt_alg_magic)], rndval, sizeof (rndval)); 341*6532Swyllys 342*6532Swyllys (void) close(fd); 343*6532Swyllys 344*6532Swyllys return (gsbuffer); 345*6532Swyllys } 346