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