UNPKG

8.04 kBtext/x-cView Raw
1/* $OpenBSD: bcrypt.c,v 1.31 2014/03/22 23:02:03 tedu Exp $ */
2
3/*
4 * Copyright (c) 1997 Niels Provos <provos@umich.edu>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/* This password hashing algorithm was designed by David Mazieres
20 * <dm@lcs.mit.edu> and works as follows:
21 *
22 * 1. state := InitState ()
23 * 2. state := ExpandKey (state, salt, password)
24 * 3. REPEAT rounds:
25 * state := ExpandKey (state, 0, password)
26 * state := ExpandKey (state, 0, salt)
27 * 4. ctext := "OrpheanBeholderScryDoubt"
28 * 5. REPEAT 64:
29 * ctext := Encrypt_ECB (state, ctext);
30 * 6. RETURN Concatenate (salt, ctext);
31 *
32 */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <sys/types.h>
37#include <string.h>
38
39#include "node_blf.h"
40
41#ifdef _WIN32
42#define snprintf _snprintf
43#endif
44
45//#if !defined(__APPLE__) && !defined(__MACH__)
46//#include "bsd/stdlib.h"
47//#endif
48
49/* This implementation is adaptable to current computing power.
50 * You can have up to 2^31 rounds which should be enough for some
51 * time to come.
52 */
53
54static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
55static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *);
56
57const static char* error = ":";
58
59const static u_int8_t Base64Code[] =
60"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
61
62const static u_int8_t index_64[128] = {
63 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
64 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
65 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
66 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
67 255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
68 56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
69 255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
70 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
71 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
72 255, 255, 255, 255, 255, 255, 28, 29, 30,
73 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
74 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
75 51, 52, 53, 255, 255, 255, 255, 255
76};
77#define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
78
79static void
80decode_base64(u_int8_t *buffer, u_int16_t len, u_int8_t *data)
81{
82 u_int8_t *bp = buffer;
83 u_int8_t *p = data;
84 u_int8_t c1, c2, c3, c4;
85 while (bp < buffer + len) {
86 c1 = CHAR64(*p);
87 c2 = CHAR64(*(p + 1));
88
89 /* Invalid data */
90 if (c1 == 255 || c2 == 255)
91 break;
92
93 *bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
94 if (bp >= buffer + len)
95 break;
96
97 c3 = CHAR64(*(p + 2));
98 if (c3 == 255)
99 break;
100
101 *bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
102 if (bp >= buffer + len)
103 break;
104
105 c4 = CHAR64(*(p + 3));
106 if (c4 == 255)
107 break;
108 *bp++ = ((c3 & 0x03) << 6) | c4;
109
110 p += 4;
111 }
112}
113
114void
115encode_salt(char *salt, u_int8_t *csalt, char minor, u_int16_t clen, u_int8_t logr)
116{
117 salt[0] = '$';
118 salt[1] = BCRYPT_VERSION;
119 salt[2] = minor;
120 salt[3] = '$';
121
122 // Max rounds are 31
123 snprintf(salt + 4, 4, "%2.2u$", logr & 0x001F);
124
125 encode_base64((u_int8_t *) salt + 7, csalt, clen);
126}
127
128
129/* Generates a salt for this version of crypt.
130 Since versions may change. Keeping this here
131 seems sensible.
132 from: http://mail-index.netbsd.org/tech-crypto/2002/05/24/msg000204.html
133*/
134void
135bcrypt_gensalt(char minor, u_int8_t log_rounds, u_int8_t *seed, char *gsalt)
136{
137 if (log_rounds < 4)
138 log_rounds = 4;
139 else if (log_rounds > 31)
140 log_rounds = 31;
141
142 encode_salt(gsalt, seed, minor, BCRYPT_MAXSALT, log_rounds);
143}
144
145/* We handle $Vers$log2(NumRounds)$salt+passwd$
146 i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
147
148void
149bcrypt(const char *key, size_t key_len, const char *salt, char *encrypted)
150{
151 blf_ctx state;
152 u_int32_t rounds, i, k;
153 u_int16_t j;
154 u_int8_t salt_len, logr, minor;
155 u_int8_t ciphertext[4 * BCRYPT_BLOCKS+1] = "OrpheanBeholderScryDoubt";
156 u_int8_t csalt[BCRYPT_MAXSALT];
157 u_int32_t cdata[BCRYPT_BLOCKS];
158 int n;
159
160 /* Discard "$" identifier */
161 salt++;
162
163 if (*salt > BCRYPT_VERSION) {
164 /* How do I handle errors ? Return ':' */
165 strcpy(encrypted, error);
166 return;
167 }
168
169 /* Check for minor versions */
170 if (salt[1] != '$') {
171 switch (salt[1]) {
172 case 'a': /* 'ab' should not yield the same as 'abab' */
173 case 'b': /* cap input length at 72 bytes */
174 minor = salt[1];
175 salt++;
176 break;
177 default:
178 strcpy(encrypted, error);
179 return;
180 }
181 } else
182 minor = 0;
183
184 /* Discard version + "$" identifier */
185 salt += 2;
186
187 if (salt[2] != '$') {
188 /* Out of sync with passwd entry */
189 strcpy(encrypted, error);
190 return;
191 }
192
193 /* Computer power doesn't increase linear, 2^x should be fine */
194 n = atoi(salt);
195 if (n > 31 || n < 0) {
196 strcpy(encrypted, error);
197 return;
198 }
199 logr = (u_int8_t)n;
200 if ((rounds = (u_int32_t) 1 << logr) < BCRYPT_MINROUNDS) {
201 strcpy(encrypted, error);
202 return;
203 }
204
205 /* Discard num rounds + "$" identifier */
206 salt += 3;
207
208 if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT) {
209 strcpy(encrypted, error);
210 return;
211 }
212
213 /* We dont want the base64 salt but the raw data */
214 decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
215 salt_len = BCRYPT_MAXSALT;
216 if (minor <= 'a')
217 key_len = (u_int8_t)(key_len + (minor >= 'a' ? 1 : 0));
218 else
219 {
220 /* cap key_len at the actual maximum supported
221 * length here to avoid integer wraparound */
222 if (key_len > 72)
223 key_len = 72;
224 key_len++; /* include the NUL */
225 }
226
227
228 /* Setting up S-Boxes and Subkeys */
229 Blowfish_initstate(&state);
230 Blowfish_expandstate(&state, csalt, salt_len,
231 (u_int8_t *) key, key_len);
232 for (k = 0; k < rounds; k++) {
233 Blowfish_expand0state(&state, (u_int8_t *) key, key_len);
234 Blowfish_expand0state(&state, csalt, salt_len);
235 }
236
237 /* This can be precomputed later */
238 j = 0;
239 for (i = 0; i < BCRYPT_BLOCKS; i++)
240 cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
241
242 /* Now do the encryption */
243 for (k = 0; k < 64; k++)
244 blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
245
246 for (i = 0; i < BCRYPT_BLOCKS; i++) {
247 ciphertext[4 * i + 3] = cdata[i] & 0xff;
248 cdata[i] = cdata[i] >> 8;
249 ciphertext[4 * i + 2] = cdata[i] & 0xff;
250 cdata[i] = cdata[i] >> 8;
251 ciphertext[4 * i + 1] = cdata[i] & 0xff;
252 cdata[i] = cdata[i] >> 8;
253 ciphertext[4 * i + 0] = cdata[i] & 0xff;
254 }
255
256 i = 0;
257 encrypted[i++] = '$';
258 encrypted[i++] = BCRYPT_VERSION;
259 if (minor)
260 encrypted[i++] = minor;
261 encrypted[i++] = '$';
262
263 snprintf(encrypted + i, 4, "%2.2u$", logr & 0x001F);
264
265 encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT);
266 encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext,
267 4 * BCRYPT_BLOCKS - 1);
268 memset(&state, 0, sizeof(state));
269 memset(ciphertext, 0, sizeof(ciphertext));
270 memset(csalt, 0, sizeof(csalt));
271 memset(cdata, 0, sizeof(cdata));
272}
273
274u_int32_t bcrypt_get_rounds(const char * hash)
275{
276 /* skip past the leading "$" */
277 if (!hash || *(hash++) != '$') return 0;
278
279 /* skip past version */
280 if (0 == (*hash++)) return 0;
281 if (*hash && *hash != '$') hash++;
282 if (*hash++ != '$') return 0;
283
284 return atoi(hash);
285}
286
287static void
288encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
289{
290 u_int8_t *bp = buffer;
291 u_int8_t *p = data;
292 u_int8_t c1, c2;
293 while (p < data + len) {
294 c1 = *p++;
295 *bp++ = Base64Code[(c1 >> 2)];
296 c1 = (c1 & 0x03) << 4;
297 if (p >= data + len) {
298 *bp++ = Base64Code[c1];
299 break;
300 }
301 c2 = *p++;
302 c1 |= (c2 >> 4) & 0x0f;
303 *bp++ = Base64Code[c1];
304 c1 = (c2 & 0x0f) << 2;
305 if (p >= data + len) {
306 *bp++ = Base64Code[c1];
307 break;
308 }
309 c2 = *p++;
310 c1 |= (c2 >> 6) & 0x03;
311 *bp++ = Base64Code[c1];
312 *bp++ = Base64Code[c2 & 0x3f];
313 }
314 *bp = '\0';
315}