1 /*
2 * Copyright (c) 2014 Ted Unangst <tedu@openbsd.org>
3 * Copyright (c) 1997 Niels Provos <provos@umich.edu>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 /* This password hashing algorithm was designed by David Mazieres
18 * <dm@lcs.mit.edu> and works as follows:
19 *
20 * 1. state := InitState ()
21 * 2. state := ExpandKey (state, salt, password)
22 * 3. REPEAT rounds:
23 * state := ExpandKey (state, 0, password)
24 * state := ExpandKey (state, 0, salt)
25 * 4. ctext := "OrpheanBeholderScryDoubt"
26 * 5. REPEAT 64:
27 * ctext := Encrypt_ECB (state, ctext);
28 * 6. RETURN Concatenate (salt, ctext);
29 *
30 */
31
32 #include "config.h"
33
34 #include <sys/types.h>
35 #include "openbsd-blowfish.h"
36 #include <ctype.h>
37 #include <errno.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 /* This implementation is adaptable to current computing power.
43 * You can have up to 2^31 rounds which should be enough for some
44 * time to come.
45 */
46
47 #define BCRYPT_VERSION '2'
48 #define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */
49 #define BCRYPT_WORDS 6 /* Ciphertext words */
50 #define BCRYPT_MINLOGROUNDS 4 /* we have log2(rounds) in salt */
51
52 #define BCRYPT_SALTSPACE (7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1)
53 #define BCRYPT_HASHSPACE 61
54
55 static int encode_base64(char *, const u_int8_t *, size_t);
56 static int decode_base64(u_int8_t *, size_t, const char *);
57
58 /*
59 * the core bcrypt function
60 */
61 int
bcrypt_hashpass(const char * key,const char * salt,char * encrypted,size_t encryptedlen)62 bcrypt_hashpass(const char *key, const char *salt, char *encrypted,
63 size_t encryptedlen)
64 {
65 blf_ctx state;
66 u_int32_t rounds, i, k;
67 u_int16_t j;
68 size_t key_len;
69 u_int8_t salt_len, logr, minor;
70 u_int8_t ciphertext[4 * BCRYPT_WORDS] = "OrpheanBeholderScryDoubt";
71 u_int8_t csalt[BCRYPT_MAXSALT];
72 u_int32_t cdata[BCRYPT_WORDS];
73
74 if (encryptedlen < BCRYPT_HASHSPACE)
75 goto inval;
76
77 /* Check and discard "$" identifier */
78 if (salt[0] != '$')
79 goto inval;
80 salt += 1;
81
82 if (salt[0] != BCRYPT_VERSION)
83 goto inval;
84
85 /* Check for minor versions */
86 switch ((minor = salt[1])) {
87 case 'a':
88 key_len = (u_int8_t)(strlen(key) + 1);
89 break;
90 case 'b':
91 /* strlen() returns a size_t, but the function calls
92 * below result in implicit casts to a narrower integer
93 * type, so cap key_len at the actual maximum supported
94 * length here to avoid integer wraparound */
95 key_len = strlen(key);
96 if (key_len > 72)
97 key_len = 72;
98 key_len++; /* include the NUL */
99 break;
100 case 'y':
101 /* PHP-specific version; see:
102 * https://www.php.net/manual/en/function.password-hash.php
103 */
104 key_len = (u_int8_t)(strlen(key) + 1);
105 break;
106 default:
107 goto inval;
108 }
109 if (salt[2] != '$')
110 goto inval;
111 /* Discard version + "$" identifier */
112 salt += 3;
113
114 /* Check and parse num rounds */
115 if (!isdigit((unsigned char)salt[0]) ||
116 !isdigit((unsigned char)salt[1]) || salt[2] != '$')
117 goto inval;
118 logr = (salt[1] - '0') + ((salt[0] - '0') * 10);
119 if (logr < BCRYPT_MINLOGROUNDS || logr > 31)
120 goto inval;
121 /* Computer power doesn't increase linearly, 2^x should be fine */
122 rounds = 1U << logr;
123
124 /* Discard num rounds + "$" identifier */
125 salt += 3;
126
127 if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
128 goto inval;
129
130 /* We dont want the base64 salt but the raw data */
131 if (decode_base64(csalt, BCRYPT_MAXSALT, salt))
132 goto inval;
133 salt_len = BCRYPT_MAXSALT;
134
135 /* Setting up S-Boxes and Subkeys */
136 Blowfish_initstate(&state);
137 Blowfish_expandstate(&state, csalt, salt_len,
138 (u_int8_t *) key, key_len);
139 for (k = 0; k < rounds; k++) {
140 Blowfish_expand0state(&state, (u_int8_t *) key, key_len);
141 Blowfish_expand0state(&state, csalt, salt_len);
142 }
143
144 /* This can be precomputed later */
145 j = 0;
146 for (i = 0; i < BCRYPT_WORDS; i++)
147 cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_WORDS, &j);
148
149 /* Now do the encryption */
150 for (k = 0; k < 64; k++)
151 blf_enc(&state, cdata, BCRYPT_WORDS / 2);
152
153 for (i = 0; i < BCRYPT_WORDS; i++) {
154 ciphertext[4 * i + 3] = cdata[i] & 0xff;
155 cdata[i] = cdata[i] >> 8;
156 ciphertext[4 * i + 2] = cdata[i] & 0xff;
157 cdata[i] = cdata[i] >> 8;
158 ciphertext[4 * i + 1] = cdata[i] & 0xff;
159 cdata[i] = cdata[i] >> 8;
160 ciphertext[4 * i + 0] = cdata[i] & 0xff;
161 }
162
163
164 snprintf(encrypted, 8, "$2%c$%2.2u$", minor, logr);
165 encode_base64(encrypted + 7, csalt, BCRYPT_MAXSALT);
166 encode_base64(encrypted + 7 + 22, ciphertext, 4 * BCRYPT_WORDS - 1);
167 #if defined(HAVE_EXPLICIT_BZERO)
168 explicit_bzero(&state, sizeof(state));
169 explicit_bzero(ciphertext, sizeof(ciphertext));
170 explicit_bzero(csalt, sizeof(csalt));
171 explicit_bzero(cdata, sizeof(cdata));
172 #elif defined(HAVE_MEMSET_S)
173 (void) memset_s(&state, sizeof(state), '\0', sizeof(state));
174 (void) memset_s(ciphertext, sizeof(ciphertext), '\0', sizeof(ciphertext));
175 (void) memset_s(csalt, sizeof(csalt), '\0', sizeof(csalt));
176 (void) memset_s(cdata, sizeof(cdata), '\0', sizeof(cdata));
177 #else
178 memset(&state, '\0', sizeof(state));
179 memset(ciphertext, '\0', sizeof(ciphertext));
180 memset(csalt, '\0', sizeof(csalt));
181 memset(cdata, '\0', sizeof(cdata));
182 #endif
183 return 0;
184
185 inval:
186 errno = EINVAL;
187 return -1;
188 }
189
190 /*
191 * internal utilities
192 */
193 static const u_int8_t Base64Code[] =
194 "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
195
196 static const u_int8_t index_64[128] = {
197 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
198 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
199 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
200 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
201 255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
202 56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
203 255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
204 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
205 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
206 255, 255, 255, 255, 255, 255, 28, 29, 30,
207 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
208 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
209 51, 52, 53, 255, 255, 255, 255, 255
210 };
211 #define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
212
213 /*
214 * read buflen (after decoding) bytes of data from b64data
215 */
216 static int
decode_base64(u_int8_t * buffer,size_t len,const char * b64data)217 decode_base64(u_int8_t *buffer, size_t len, const char *b64data)
218 {
219 u_int8_t *bp = buffer;
220 const u_int8_t *p = (const unsigned char *) b64data;
221 u_int8_t c1, c2, c3, c4;
222
223 while (bp < buffer + len) {
224 c1 = CHAR64(*p);
225 /* Invalid data */
226 if (c1 == 255)
227 return -1;
228
229 c2 = CHAR64(*(p + 1));
230 if (c2 == 255)
231 return -1;
232
233 *bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
234 if (bp >= buffer + len)
235 break;
236
237 c3 = CHAR64(*(p + 2));
238 if (c3 == 255)
239 return -1;
240
241 *bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
242 if (bp >= buffer + len)
243 break;
244
245 c4 = CHAR64(*(p + 3));
246 if (c4 == 255)
247 return -1;
248 *bp++ = ((c3 & 0x03) << 6) | c4;
249
250 p += 4;
251 }
252 return 0;
253 }
254
255 /*
256 * Turn len bytes of data into base64 encoded data.
257 * This works without = padding.
258 */
259 int
encode_base64(char * b64buffer,const u_int8_t * data,size_t len)260 encode_base64(char *b64buffer, const u_int8_t *data, size_t len)
261 {
262 u_int8_t *bp = (unsigned char *) b64buffer;
263 const u_int8_t *p = data;
264 u_int8_t c1, c2;
265
266 while (p < data + len) {
267 c1 = *p++;
268 *bp++ = Base64Code[(c1 >> 2)];
269 c1 = (c1 & 0x03) << 4;
270 if (p >= data + len) {
271 *bp++ = Base64Code[c1];
272 break;
273 }
274 c2 = *p++;
275 c1 |= (c2 >> 4) & 0x0f;
276 *bp++ = Base64Code[c1];
277 c1 = (c2 & 0x0f) << 2;
278 if (p >= data + len) {
279 *bp++ = Base64Code[c1];
280 break;
281 }
282 c2 = *p++;
283 c1 |= (c2 >> 6) & 0x03;
284 *bp++ = Base64Code[c1];
285 *bp++ = Base64Code[c2 & 0x3f];
286 }
287 *bp = '\0';
288 return 0;
289 }
290