xref: /netbsd-src/lib/libcrypt/bcrypt.c (revision f9151ba9431bb13bf0df1b3f46076c89c8d4b5cd)
1*f9151ba9Snia /*	$NetBSD: bcrypt.c,v 1.22 2021/10/16 10:53:33 nia Exp $	*/
2c89c003eSitojun /*	$OpenBSD: bcrypt.c,v 1.16 2002/02/19 19:39:36 millert Exp $	*/
3c89c003eSitojun 
4c89c003eSitojun /*
5c89c003eSitojun  * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
6c89c003eSitojun  * All rights reserved.
7c89c003eSitojun  *
8c89c003eSitojun  * Redistribution and use in source and binary forms, with or without
9c89c003eSitojun  * modification, are permitted provided that the following conditions
10c89c003eSitojun  * are met:
11c89c003eSitojun  * 1. Redistributions of source code must retain the above copyright
12c89c003eSitojun  *    notice, this list of conditions and the following disclaimer.
13c89c003eSitojun  * 2. Redistributions in binary form must reproduce the above copyright
14c89c003eSitojun  *    notice, this list of conditions and the following disclaimer in the
15c89c003eSitojun  *    documentation and/or other materials provided with the distribution.
16c89c003eSitojun  * 3. All advertising materials mentioning features or use of this software
17c89c003eSitojun  *    must display the following acknowledgement:
18c89c003eSitojun  *      This product includes software developed by Niels Provos.
19c89c003eSitojun  * 4. The name of the author may not be used to endorse or promote products
20c89c003eSitojun  *    derived from this software without specific prior written permission.
21c89c003eSitojun  *
22c89c003eSitojun  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23c89c003eSitojun  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24c89c003eSitojun  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25c89c003eSitojun  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26c89c003eSitojun  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27c89c003eSitojun  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28c89c003eSitojun  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29c89c003eSitojun  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30c89c003eSitojun  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31c89c003eSitojun  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32c89c003eSitojun  */
33c89c003eSitojun 
34c89c003eSitojun /* This password hashing algorithm was designed by David Mazieres
35c89c003eSitojun  * <dm@lcs.mit.edu> and works as follows:
36c89c003eSitojun  *
37c89c003eSitojun  * 1. state := InitState ()
38c89c003eSitojun  * 2. state := ExpandKey (state, salt, password) 3.
39c89c003eSitojun  * REPEAT rounds:
40c89c003eSitojun  *	state := ExpandKey (state, 0, salt)
41c89c003eSitojun  *      state := ExpandKey(state, 0, password)
42c89c003eSitojun  * 4. ctext := "OrpheanBeholderScryDoubt"
43c89c003eSitojun  * 5. REPEAT 64:
44c89c003eSitojun  * 	ctext := Encrypt_ECB (state, ctext);
45c89c003eSitojun  * 6. RETURN Concatenate (salt, ctext);
46c89c003eSitojun  *
47c89c003eSitojun  */
48b91cb5beSjdolecek #include <sys/cdefs.h>
49*f9151ba9Snia __RCSID("$NetBSD: bcrypt.c,v 1.22 2021/10/16 10:53:33 nia Exp $");
50b91cb5beSjdolecek 
51c89c003eSitojun #include <stdio.h>
52c89c003eSitojun #include <stdlib.h>
53c89c003eSitojun #include <sys/types.h>
54c89c003eSitojun #include <string.h>
55c89c003eSitojun #include <pwd.h>
562c53ed14Schristos #include <errno.h>
57d205f30aSchristos #include <limits.h>
58c89c003eSitojun 
592c53ed14Schristos #include "crypt.h"
6090099f5fSthorpej #include "blowfish.c"
61c89c003eSitojun 
62c89c003eSitojun /* This implementation is adaptable to current computing power.
63c89c003eSitojun  * You can have up to 2^31 rounds which should be enough for some
64c89c003eSitojun  * time to come.
65c89c003eSitojun  */
66c89c003eSitojun 
67c89c003eSitojun #define BCRYPT_VERSION '2'
68c89c003eSitojun #define BCRYPT_MAXSALT 16	/* Precomputation is just so nice */
696fa22775Schristos #define BCRYPT_MAXSALTLEN 	(7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1)
70c89c003eSitojun #define BCRYPT_BLOCKS 6		/* Ciphertext blocks */
71c89c003eSitojun #define BCRYPT_MINROUNDS 16	/* we have log2(rounds) in salt */
72c89c003eSitojun 
73c89c003eSitojun static void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
746fa22775Schristos static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
75d205f30aSchristos static void decode_base64(u_int8_t *, u_int16_t, const u_int8_t *);
76c89c003eSitojun 
77*f9151ba9Snia crypt_private char *__bcrypt(const char *, const char *);	/* XXX */
78c89c003eSitojun 
79c89c003eSitojun static char    encrypted[_PASSWORD_LEN];
80c89c003eSitojun 
8165b9988bSdrochner static const u_int8_t Base64Code[] =
82c89c003eSitojun "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
83c89c003eSitojun 
847724b89cSchristos char *bcrypt_gensalt(u_int8_t);
857724b89cSchristos 
8665b9988bSdrochner static const u_int8_t index_64[128] =
87c89c003eSitojun {
88c89c003eSitojun 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
89c89c003eSitojun 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
90c89c003eSitojun 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
91c89c003eSitojun 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
92c89c003eSitojun 	255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
93c89c003eSitojun 	56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
94c89c003eSitojun 	255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
95c89c003eSitojun 	7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
96c89c003eSitojun 	17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
97c89c003eSitojun 	255, 255, 255, 255, 255, 255, 28, 29, 30,
98c89c003eSitojun 	31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
99c89c003eSitojun 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
100c89c003eSitojun 	51, 52, 53, 255, 255, 255, 255, 255
101c89c003eSitojun };
102c89c003eSitojun #define CHAR64(c)  ( (c) > 127 ? 255 : index_64[(c)])
103c89c003eSitojun 
104c89c003eSitojun static void
decode_base64(u_int8_t * buffer,u_int16_t len,const u_int8_t * data)105d205f30aSchristos decode_base64(u_int8_t *buffer, u_int16_t len, const u_int8_t *data)
106c89c003eSitojun {
107c89c003eSitojun 	u_int8_t *bp = buffer;
108d205f30aSchristos 	const u_int8_t *p = data;
109c89c003eSitojun 	u_int8_t c1, c2, c3, c4;
110c89c003eSitojun 	while (bp < buffer + len) {
111c89c003eSitojun 		c1 = CHAR64(*p);
112c89c003eSitojun 		c2 = CHAR64(*(p + 1));
113c89c003eSitojun 
114c89c003eSitojun 		/* Invalid data */
115c89c003eSitojun 		if (c1 == 255 || c2 == 255)
116c89c003eSitojun 			break;
117c89c003eSitojun 
118d205f30aSchristos 		*bp++ = ((u_int32_t)c1 << 2) | (((u_int32_t)c2 & 0x30) >> 4);
119c89c003eSitojun 		if (bp >= buffer + len)
120c89c003eSitojun 			break;
121c89c003eSitojun 
122c89c003eSitojun 		c3 = CHAR64(*(p + 2));
123c89c003eSitojun 		if (c3 == 255)
124c89c003eSitojun 			break;
125c89c003eSitojun 
126d205f30aSchristos 		*bp++ = (((u_int32_t)c2 & 0x0f) << 4) | (((uint32_t)c3 & 0x3c) >> 2);
127c89c003eSitojun 		if (bp >= buffer + len)
128c89c003eSitojun 			break;
129c89c003eSitojun 
130c89c003eSitojun 		c4 = CHAR64(*(p + 3));
131c89c003eSitojun 		if (c4 == 255)
132c89c003eSitojun 			break;
133c89c003eSitojun 		*bp++ = ((c3 & 0x03) << 6) | c4;
134c89c003eSitojun 
135c89c003eSitojun 		p += 4;
136c89c003eSitojun 	}
137c89c003eSitojun }
138c89c003eSitojun 
139c89c003eSitojun static void
encode_salt(char * salt,u_int8_t * csalt,u_int16_t clen,u_int8_t logr)140c89c003eSitojun encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr)
141c89c003eSitojun {
142c89c003eSitojun 	salt[0] = '$';
143c89c003eSitojun 	salt[1] = BCRYPT_VERSION;
144c89c003eSitojun 	salt[2] = 'a';
145c89c003eSitojun 	salt[3] = '$';
146c89c003eSitojun 
147c89c003eSitojun 	snprintf(salt + 4, 4, "%2.2u$", logr);
148c89c003eSitojun 
1496fa22775Schristos 	encode_base64((u_int8_t *) salt + 7, csalt, clen);
150c89c003eSitojun }
151c89c003eSitojun 
152*f9151ba9Snia crypt_private int
__gensalt_blowfish(char * salt,size_t saltlen,const char * option)1533131ddccSchristos __gensalt_blowfish(char *salt, size_t saltlen, const char *option)
154c89c003eSitojun {
1552c53ed14Schristos 	size_t i;
156c89c003eSitojun 	u_int32_t seed = 0;
1572c53ed14Schristos 	u_int8_t csalt[BCRYPT_MAXSALT];
158d205f30aSchristos 	unsigned long nrounds;
159d205f30aSchristos 	char *ep;
1602c53ed14Schristos 
1612c53ed14Schristos 	if (saltlen < BCRYPT_MAXSALTLEN) {
1622c53ed14Schristos 		errno = ENOSPC;
1632c53ed14Schristos 		return -1;
1642c53ed14Schristos 	}
165999ac788Smlelstv 	if (option == NULL) {
166999ac788Smlelstv 		errno = EINVAL;
167999ac788Smlelstv 		return -1;
168999ac788Smlelstv 	}
169d205f30aSchristos 	nrounds = strtoul(option, &ep, 0);
170d205f30aSchristos 	if (option == ep || *ep) {
171d205f30aSchristos 		errno = EINVAL;
172d205f30aSchristos 		return -1;
173d205f30aSchristos 	}
174d205f30aSchristos 	if (errno == ERANGE && nrounds == ULONG_MAX)
175d205f30aSchristos 		return -1;
1762c53ed14Schristos 
1772c53ed14Schristos 	if (nrounds < 4)
1782c53ed14Schristos 		nrounds = 4;
179ccdea5dfSdrochner 	else if (nrounds > 31)
180ccdea5dfSdrochner 		nrounds = 31;
181c89c003eSitojun 
182c89c003eSitojun 	for (i = 0; i < BCRYPT_MAXSALT; i++) {
183c89c003eSitojun 		if (i % 4 == 0)
184c89c003eSitojun 			seed = arc4random();
185c89c003eSitojun 		csalt[i] = seed & 0xff;
186c89c003eSitojun 		seed = seed >> 8;
187c89c003eSitojun 	}
188d205f30aSchristos 	encode_salt(salt, csalt, BCRYPT_MAXSALT, (u_int8_t)nrounds);
1892c53ed14Schristos 	return 0;
1902c53ed14Schristos }
191c89c003eSitojun 
1922c53ed14Schristos /* Generates a salt for this version of crypt.
1932c53ed14Schristos    Since versions may change. Keeping this here
1942c53ed14Schristos    seems sensible.
1952c53ed14Schristos    XXX: compat.
1962c53ed14Schristos  */
1972c53ed14Schristos char *
bcrypt_gensalt(u_int8_t log_rounds)1982c53ed14Schristos bcrypt_gensalt(u_int8_t log_rounds)
1992c53ed14Schristos {
2002c53ed14Schristos 	static char gsalt[BCRYPT_MAXSALTLEN];
2013131ddccSchristos 	char num[10];
2023131ddccSchristos 
2033131ddccSchristos 	(void)snprintf(num, sizeof(num), "%d", log_rounds);
2043131ddccSchristos 	if (__gensalt_blowfish(gsalt, sizeof(gsalt), num) == -1)
2052c53ed14Schristos 		return NULL;
206c89c003eSitojun 	return gsalt;
207c89c003eSitojun }
208c89c003eSitojun 
209c89c003eSitojun /* We handle $Vers$log2(NumRounds)$salt+passwd$
210c89c003eSitojun    i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
211c89c003eSitojun 
212*f9151ba9Snia crypt_private char   *
__bcrypt(const char * key,const char * salt)213f9113d00Smatt __bcrypt(const char *key, const char *salt)
214c89c003eSitojun {
215c89c003eSitojun 	blf_ctx state;
216c89c003eSitojun 	u_int32_t rounds, i, k;
217c89c003eSitojun 	u_int16_t j;
218c89c003eSitojun 	u_int8_t key_len, salt_len, logr, minor;
219c89c003eSitojun 	u_int8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt";
220c89c003eSitojun 	u_int8_t csalt[BCRYPT_MAXSALT];
221c89c003eSitojun 	u_int32_t cdata[BCRYPT_BLOCKS];
222ccdea5dfSdrochner 	int n;
2230d2c1e1bSchristos 	size_t len;
224c89c003eSitojun 
225c89c003eSitojun 	/* Discard "$" identifier */
226c89c003eSitojun 	salt++;
227c89c003eSitojun 
2280d2c1e1bSchristos 	if (*salt > BCRYPT_VERSION)
2290d2c1e1bSchristos 		return NULL;
230c89c003eSitojun 
231c89c003eSitojun 	/* Check for minor versions */
232c89c003eSitojun 	if (salt[1] != '$') {
233c89c003eSitojun 		switch (salt[1]) {
234c89c003eSitojun 		case 'a':
235c89c003eSitojun 			/* 'ab' should not yield the same as 'abab' */
236c89c003eSitojun 			minor = salt[1];
237c89c003eSitojun 			salt++;
238c89c003eSitojun 			break;
239c89c003eSitojun 		default:
2400d2c1e1bSchristos 			return NULL;
241c89c003eSitojun 		}
242c89c003eSitojun 	} else
243c89c003eSitojun 		 minor = 0;
244c89c003eSitojun 
245c89c003eSitojun 	/* Discard version + "$" identifier */
246c89c003eSitojun 	salt += 2;
247c89c003eSitojun 
248c89c003eSitojun 	if (salt[2] != '$')
249c89c003eSitojun 		/* Out of sync with passwd entry */
2500d2c1e1bSchristos 		return NULL;
251c89c003eSitojun 
252c89c003eSitojun 	/* Computer power doesn't increase linear, 2^x should be fine */
253ccdea5dfSdrochner 	n = atoi(salt);
254ccdea5dfSdrochner 	if (n > 31 || n < 0)
2550d2c1e1bSchristos 		return NULL;
256ccdea5dfSdrochner 	logr = (u_int8_t)n;
257ccdea5dfSdrochner 	if ((rounds = (u_int32_t) 1 << logr) < BCRYPT_MINROUNDS)
2580d2c1e1bSchristos 		return NULL;
259c89c003eSitojun 
260c89c003eSitojun 	/* Discard num rounds + "$" identifier */
261c89c003eSitojun 	salt += 3;
262c89c003eSitojun 
263c89c003eSitojun 	if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
2640d2c1e1bSchristos 		return NULL;
265c89c003eSitojun 
266c89c003eSitojun 	/* We dont want the base64 salt but the raw data */
267d205f30aSchristos 	decode_base64(csalt, BCRYPT_MAXSALT, (const u_int8_t *)salt);
268c89c003eSitojun 	salt_len = BCRYPT_MAXSALT;
2690d2c1e1bSchristos 	len = strlen(key);
2703b47f52cSchristos 	if (len > 72)
2713b47f52cSchristos 		key_len = 72;
2723b47f52cSchristos 	else
2733b47f52cSchristos 		key_len = (uint8_t)len;
2743b47f52cSchristos 	key_len += minor >= 'a' ? 1 : 0;
275c89c003eSitojun 
276c89c003eSitojun 	/* Setting up S-Boxes and Subkeys */
277c89c003eSitojun 	Blowfish_initstate(&state);
278c89c003eSitojun 	Blowfish_expandstate(&state, csalt, salt_len,
279d205f30aSchristos 	    (const u_int8_t *) key, key_len);
280c89c003eSitojun 	for (k = 0; k < rounds; k++) {
281d205f30aSchristos 		Blowfish_expand0state(&state, (const u_int8_t *) key, key_len);
282c89c003eSitojun 		Blowfish_expand0state(&state, csalt, salt_len);
283c89c003eSitojun 	}
284c89c003eSitojun 
285c89c003eSitojun 	/* This can be precomputed later */
286c89c003eSitojun 	j = 0;
287c89c003eSitojun 	for (i = 0; i < BCRYPT_BLOCKS; i++)
288c89c003eSitojun 		cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
289c89c003eSitojun 
290c89c003eSitojun 	/* Now do the encryption */
291c89c003eSitojun 	for (k = 0; k < 64; k++)
292c89c003eSitojun 		blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
293c89c003eSitojun 
294c89c003eSitojun 	for (i = 0; i < BCRYPT_BLOCKS; i++) {
295c89c003eSitojun 		ciphertext[4 * i + 3] = cdata[i] & 0xff;
296c89c003eSitojun 		cdata[i] = cdata[i] >> 8;
297c89c003eSitojun 		ciphertext[4 * i + 2] = cdata[i] & 0xff;
298c89c003eSitojun 		cdata[i] = cdata[i] >> 8;
299c89c003eSitojun 		ciphertext[4 * i + 1] = cdata[i] & 0xff;
300c89c003eSitojun 		cdata[i] = cdata[i] >> 8;
301c89c003eSitojun 		ciphertext[4 * i + 0] = cdata[i] & 0xff;
302c89c003eSitojun 	}
303c89c003eSitojun 
304c89c003eSitojun 
305c89c003eSitojun 	i = 0;
306c89c003eSitojun 	encrypted[i++] = '$';
307c89c003eSitojun 	encrypted[i++] = BCRYPT_VERSION;
308c89c003eSitojun 	if (minor)
309c89c003eSitojun 		encrypted[i++] = minor;
310c89c003eSitojun 	encrypted[i++] = '$';
311c89c003eSitojun 
312c89c003eSitojun 	snprintf(encrypted + i, 4, "%2.2u$", logr);
313c89c003eSitojun 
314c89c003eSitojun 	encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT);
315c89c003eSitojun 	encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext,
316c89c003eSitojun 	    4 * BCRYPT_BLOCKS - 1);
3171239c2bbSriastradh 	explicit_memset(&state, 0, sizeof(state));
318c89c003eSitojun 	return encrypted;
319c89c003eSitojun }
320c89c003eSitojun 
3216fa22775Schristos static void
encode_base64(u_int8_t * buffer,u_int8_t * data,u_int16_t len)322c89c003eSitojun encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
323c89c003eSitojun {
324c89c003eSitojun 	u_int8_t *bp = buffer;
325c89c003eSitojun 	u_int8_t *p = data;
326c89c003eSitojun 	u_int8_t c1, c2;
327c89c003eSitojun 	while (p < data + len) {
328c89c003eSitojun 		c1 = *p++;
329d205f30aSchristos 		*bp++ = Base64Code[((u_int32_t)c1 >> 2)];
330c89c003eSitojun 		c1 = (c1 & 0x03) << 4;
331c89c003eSitojun 		if (p >= data + len) {
332c89c003eSitojun 			*bp++ = Base64Code[c1];
333c89c003eSitojun 			break;
334c89c003eSitojun 		}
335c89c003eSitojun 		c2 = *p++;
336d205f30aSchristos 		c1 |= ((u_int32_t)c2 >> 4) & 0x0f;
337c89c003eSitojun 		*bp++ = Base64Code[c1];
338c89c003eSitojun 		c1 = (c2 & 0x0f) << 2;
339c89c003eSitojun 		if (p >= data + len) {
340c89c003eSitojun 			*bp++ = Base64Code[c1];
341c89c003eSitojun 			break;
342c89c003eSitojun 		}
343c89c003eSitojun 		c2 = *p++;
344d205f30aSchristos 		c1 |= ((u_int32_t)c2 >> 6) & 0x03;
345c89c003eSitojun 		*bp++ = Base64Code[c1];
346c89c003eSitojun 		*bp++ = Base64Code[c2 & 0x3f];
347c89c003eSitojun 	}
348c89c003eSitojun 	*bp = '\0';
349c89c003eSitojun }
350c89c003eSitojun #if 0
351c89c003eSitojun void
352c89c003eSitojun main()
353c89c003eSitojun {
354c89c003eSitojun 	char    blubber[73];
355c89c003eSitojun 	char    salt[100];
356c89c003eSitojun 	char   *p;
357c89c003eSitojun 	salt[0] = '$';
358c89c003eSitojun 	salt[1] = BCRYPT_VERSION;
359c89c003eSitojun 	salt[2] = '$';
360c89c003eSitojun 
361c89c003eSitojun 	snprintf(salt + 3, 4, "%2.2u$", 5);
362c89c003eSitojun 
363c89c003eSitojun 	printf("24 bytes of salt: ");
364c89c003eSitojun 	fgets(salt + 6, 94, stdin);
365c89c003eSitojun 	salt[99] = 0;
366c89c003eSitojun 	printf("72 bytes of password: ");
367c89c003eSitojun 	fpurge(stdin);
368c89c003eSitojun 	fgets(blubber, 73, stdin);
369c89c003eSitojun 	blubber[72] = 0;
370c89c003eSitojun 
371c89c003eSitojun 	p = crypt(blubber, salt);
372c89c003eSitojun 	printf("Passwd entry: %s\n\n", p);
373c89c003eSitojun 
374c89c003eSitojun 	p = bcrypt_gensalt(5);
375c89c003eSitojun 	printf("Generated salt: %s\n", p);
376c89c003eSitojun 	p = crypt(blubber, p);
377c89c003eSitojun 	printf("Passwd entry: %s\n", p);
378c89c003eSitojun }
379c89c003eSitojun #endif
380