crypt-sha1.c revision 1.7 1 1.7 dholland /* $NetBSD: crypt-sha1.c,v 1.7 2013/08/10 18:42:29 dholland 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.1 sjg *
7 1.1 sjg * Redistribution and use in source and binary forms, with or without
8 1.1 sjg * modification, are permitted provided that the following conditions
9 1.1 sjg * are met:
10 1.1 sjg * 1. Redistributions of source code must retain the above copyright
11 1.1 sjg * 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.1 sjg * 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.1 sjg * from this software without specific prior written permission.
18 1.1 sjg *
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.1 sjg * 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.7 dholland __RCSID("$NetBSD: crypt-sha1.c,v 1.7 2013/08/10 18:42:29 dholland 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.1 sjg unsigned int
72 1.1 sjg __crypt_sha1_iterations (unsigned int hint)
73 1.1 sjg {
74 1.1 sjg static int once = 1;
75 1.1 sjg
76 1.1 sjg /*
77 1.1 sjg * We treat CRYPT_SHA1_ITERATIONS as a hint.
78 1.1 sjg * Make it harder for someone to pre-compute hashes for a
79 1.1 sjg * dictionary attack by not using the same iteration count for
80 1.1 sjg * every entry.
81 1.1 sjg */
82 1.1 sjg
83 1.1 sjg if (once) {
84 1.1 sjg int pid = getpid();
85 1.1 sjg
86 1.1 sjg srandom(time(NULL) ^ (pid * pid));
87 1.1 sjg once = 0;
88 1.1 sjg }
89 1.1 sjg if (hint == 0)
90 1.1 sjg hint = CRYPT_SHA1_ITERATIONS;
91 1.1 sjg return hint - (random() % (hint / 4));
92 1.1 sjg }
93 1.1 sjg
94 1.1 sjg /*
95 1.1 sjg * UNIX password using hmac_sha1
96 1.1 sjg * This is PBKDF1 from RFC 2898, but using hmac_sha1.
97 1.1 sjg *
98 1.1 sjg * The format of the encrypted password is:
99 1.1 sjg * $<tag>$<iterations>$<salt>$<digest>
100 1.1 sjg *
101 1.1 sjg * where:
102 1.1 sjg * <tag> is "sha1"
103 1.1 sjg * <iterations> is an unsigned int identifying how many rounds
104 1.1 sjg * have been applied to <digest>. The number
105 1.1 sjg * should vary slightly for each password to make
106 1.1 sjg * it harder to generate a dictionary of
107 1.1 sjg * pre-computed hashes. See crypt_sha1_iterations.
108 1.1 sjg * <salt> up to 64 bytes of random data, 8 bytes is
109 1.1 sjg * currently considered more than enough.
110 1.1 sjg * <digest> the hashed password.
111 1.1 sjg *
112 1.1 sjg * NOTE:
113 1.1 sjg * To be FIPS 140 compliant, the password which is used as a hmac key,
114 1.1 sjg * should be between 10 and 20 characters to provide at least 80bits
115 1.1 sjg * strength, and avoid the need to hash it before using as the
116 1.1 sjg * hmac key.
117 1.1 sjg */
118 1.1 sjg char *
119 1.1 sjg __crypt_sha1 (const char *pw, const char *salt)
120 1.1 sjg {
121 1.3 drochner static const char *magic = SHA1_MAGIC;
122 1.1 sjg static unsigned char hmac_buf[SHA1_SIZE];
123 1.1 sjg static char passwd[(2 * sizeof(SHA1_MAGIC)) +
124 1.1 sjg CRYPT_SHA1_SALT_LENGTH + SHA1_SIZE];
125 1.4 drochner const char *sp;
126 1.1 sjg char *ep;
127 1.1 sjg unsigned long ul;
128 1.1 sjg int sl;
129 1.1 sjg int pl;
130 1.1 sjg int dl;
131 1.1 sjg unsigned int iterations;
132 1.1 sjg unsigned int i;
133 1.7 dholland /* XXX silence -Wpointer-sign (would be nice to fix this some other way) */
134 1.7 dholland const unsigned char *pwu = (const unsigned char *)pw;
135 1.3 drochner
136 1.1 sjg /*
137 1.1 sjg * Salt format is
138 1.1 sjg * $<tag>$<iterations>$salt[$]
139 1.1 sjg * If it does not start with $ we use our default iterations.
140 1.1 sjg */
141 1.1 sjg
142 1.1 sjg /* If it starts with the magic string, then skip that */
143 1.4 drochner if (!strncmp(salt, magic, strlen(magic))) {
144 1.4 drochner salt += strlen(magic);
145 1.1 sjg /* and get the iteration count */
146 1.4 drochner iterations = strtoul(salt, &ep, 10);
147 1.1 sjg if (*ep != '$')
148 1.1 sjg return NULL; /* invalid input */
149 1.4 drochner salt = ep + 1; /* skip over the '$' */
150 1.1 sjg } else {
151 1.1 sjg iterations = __crypt_sha1_iterations(0);
152 1.1 sjg }
153 1.1 sjg
154 1.1 sjg /* It stops at the next '$', max CRYPT_SHA1_ITERATIONS chars */
155 1.4 drochner for (sp = salt; *sp && *sp != '$' && sp < (salt + CRYPT_SHA1_ITERATIONS); sp++)
156 1.1 sjg continue;
157 1.1 sjg
158 1.1 sjg /* Get the length of the actual salt */
159 1.4 drochner sl = sp - salt;
160 1.1 sjg pl = strlen(pw);
161 1.1 sjg
162 1.1 sjg /*
163 1.1 sjg * Now get to work...
164 1.1 sjg * Prime the pump with <salt><magic><iterations>
165 1.1 sjg */
166 1.1 sjg dl = snprintf(passwd, sizeof (passwd), "%.*s%s%u",
167 1.4 drochner sl, salt, magic, iterations);
168 1.1 sjg /*
169 1.1 sjg * Then hmac using <pw> as key, and repeat...
170 1.1 sjg */
171 1.7 dholland __hmac_sha1((unsigned char *)passwd, dl, pwu, pl, hmac_buf);
172 1.1 sjg for (i = 1; i < iterations; i++) {
173 1.7 dholland __hmac_sha1(hmac_buf, SHA1_SIZE, pwu, pl, hmac_buf);
174 1.1 sjg }
175 1.1 sjg /* Now output... */
176 1.1 sjg pl = snprintf(passwd, sizeof(passwd), "%s%u$%.*s$",
177 1.4 drochner magic, iterations, sl, salt);
178 1.1 sjg ep = passwd + pl;
179 1.1 sjg
180 1.1 sjg /* Every 3 bytes of hash gives 24 bits which is 4 base64 chars */
181 1.1 sjg for (i = 0; i < SHA1_SIZE - 3; i += 3) {
182 1.1 sjg ul = (hmac_buf[i+0] << 16) |
183 1.1 sjg (hmac_buf[i+1] << 8) |
184 1.1 sjg hmac_buf[i+2];
185 1.1 sjg __crypt_to64(ep, ul, 4); ep += 4;
186 1.1 sjg }
187 1.1 sjg /* Only 2 bytes left, so we pad with byte0 */
188 1.1 sjg ul = (hmac_buf[SHA1_SIZE - 2] << 16) |
189 1.1 sjg (hmac_buf[SHA1_SIZE - 1] << 8) |
190 1.1 sjg hmac_buf[0];
191 1.1 sjg __crypt_to64(ep, ul, 4); ep += 4;
192 1.1 sjg *ep = '\0';
193 1.1 sjg
194 1.1 sjg /* Don't leave anything around in vm they could use. */
195 1.6 riastrad __explicit_memset(hmac_buf, 0, sizeof hmac_buf);
196 1.1 sjg
197 1.1 sjg return passwd;
198 1.1 sjg }
199