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