crypt-sha1.c revision 1.1
1/* 2 * Copyright (c) 2004, Juniper Networks, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31#if !defined(lint) 32__RCSID("$Id: crypt-sha1.c,v 1.1 2004/07/02 00:05:23 sjg Exp $"); 33#endif /* not lint */ 34 35#include <stdlib.h> 36#include <unistd.h> 37#include <stdio.h> 38#include <string.h> 39#include <time.h> 40 41#include <err.h> 42#include "crypt.h" 43 44/* 45 * The default iterations - should take >0s on a fast CPU 46 * but not be insane for a slow CPU. 47 */ 48#ifndef CRYPT_SHA1_ITERATIONS 49# define CRYPT_SHA1_ITERATIONS 24680 50#endif 51/* 52 * Support a reasonably? long salt. 53 */ 54#ifndef CRYPT_SHA1_SALT_LENGTH 55# define CRYPT_SHA1_SALT_LENGTH 64 56#endif 57 58extern void hmac_sha1(unsigned char *text, size_t text_len, 59 unsigned char *key, size_t key_len, 60 unsigned char *digest); 61 62/* 63 * This may be called from crypt_sha1 or gensalt. 64 * 65 * The value returned will be slightly less than <hint> which defaults 66 * to 24680. The goals are that the number of iterations should take 67 * non-zero amount of time on a fast cpu while not taking insanely 68 * long on a slow cpu. The current default will take about 5 seconds 69 * on a 100MHz sparc, and about 0.04 seconds on a 3GHz i386. 70 * The number is varied to frustrate those attempting to generate a 71 * dictionary of pre-computed hashes. 72 */ 73unsigned int 74__crypt_sha1_iterations (unsigned int hint) 75{ 76 static int once = 1; 77 78 /* 79 * We treat CRYPT_SHA1_ITERATIONS as a hint. 80 * Make it harder for someone to pre-compute hashes for a 81 * dictionary attack by not using the same iteration count for 82 * every entry. 83 */ 84 85 if (once) { 86 int pid = getpid(); 87 88 srandom(time(NULL) ^ (pid * pid)); 89 once = 0; 90 } 91 if (hint == 0) 92 hint = CRYPT_SHA1_ITERATIONS; 93 return hint - (random() % (hint / 4)); 94} 95 96/* 97 * UNIX password using hmac_sha1 98 * This is PBKDF1 from RFC 2898, but using hmac_sha1. 99 * 100 * The format of the encrypted password is: 101 * $<tag>$<iterations>$<salt>$<digest> 102 * 103 * where: 104 * <tag> is "sha1" 105 * <iterations> is an unsigned int identifying how many rounds 106 * have been applied to <digest>. The number 107 * should vary slightly for each password to make 108 * it harder to generate a dictionary of 109 * pre-computed hashes. See crypt_sha1_iterations. 110 * <salt> up to 64 bytes of random data, 8 bytes is 111 * currently considered more than enough. 112 * <digest> the hashed password. 113 * 114 * NOTE: 115 * To be FIPS 140 compliant, the password which is used as a hmac key, 116 * should be between 10 and 20 characters to provide at least 80bits 117 * strength, and avoid the need to hash it before using as the 118 * hmac key. 119 */ 120char * 121__crypt_sha1 (const char *pw, const char *salt) 122{ 123 static char *magic = SHA1_MAGIC; 124 static unsigned char hmac_buf[SHA1_SIZE]; 125 static char passwd[(2 * sizeof(SHA1_MAGIC)) + 126 CRYPT_SHA1_SALT_LENGTH + SHA1_SIZE]; 127 char *sp; 128 char *ep; 129 unsigned long ul; 130 int sl; 131 int pl; 132 int dl; 133 unsigned int iterations; 134 unsigned int i; 135 136 /* 137 * Salt format is 138 * $<tag>$<iterations>$salt[$] 139 * If it does not start with $ we use our default iterations. 140 */ 141 sp = UNCONST(salt); 142 143 /* If it starts with the magic string, then skip that */ 144 if (!strncmp(sp, magic, strlen(magic))) { 145 sp += strlen(magic); 146 /* and get the iteration count */ 147 iterations = strtoul(sp, &ep, 10); 148 if (*ep != '$') 149 return NULL; /* invalid input */ 150 sp = ep + 1; /* skip over the '$' */ 151 } else { 152 iterations = __crypt_sha1_iterations(0); 153 } 154 155 /* It stops at the next '$', max CRYPT_SHA1_ITERATIONS chars */ 156 for (ep = sp; *ep && *ep != '$' && ep < (sp + CRYPT_SHA1_ITERATIONS); ep++) 157 continue; 158 159 /* Get the length of the actual salt */ 160 sl = ep - sp; 161 pl = strlen(pw); 162 163 /* 164 * Now get to work... 165 * Prime the pump with <salt><magic><iterations> 166 */ 167 dl = snprintf(passwd, sizeof (passwd), "%.*s%s%u", 168 sl, sp, magic, iterations); 169 /* 170 * Then hmac using <pw> as key, and repeat... 171 */ 172 ep = UNCONST(pw); /* keep gcc happy */ 173 hmac_sha1(passwd, dl, ep, pl, hmac_buf); 174 for (i = 1; i < iterations; i++) { 175 hmac_sha1(hmac_buf, SHA1_SIZE, ep, pl, hmac_buf); 176 } 177 /* Now output... */ 178 pl = snprintf(passwd, sizeof(passwd), "%s%u$%.*s$", 179 magic, iterations, sl, sp); 180 ep = passwd + pl; 181 182 /* Every 3 bytes of hash gives 24 bits which is 4 base64 chars */ 183 for (i = 0; i < SHA1_SIZE - 3; i += 3) { 184 ul = (hmac_buf[i+0] << 16) | 185 (hmac_buf[i+1] << 8) | 186 hmac_buf[i+2]; 187 __crypt_to64(ep, ul, 4); ep += 4; 188 } 189 /* Only 2 bytes left, so we pad with byte0 */ 190 ul = (hmac_buf[SHA1_SIZE - 2] << 16) | 191 (hmac_buf[SHA1_SIZE - 1] << 8) | 192 hmac_buf[0]; 193 __crypt_to64(ep, ul, 4); ep += 4; 194 *ep = '\0'; 195 196 /* Don't leave anything around in vm they could use. */ 197 memset(hmac_buf, 0, sizeof hmac_buf); 198 199 return passwd; 200} 201