xref: /freebsd/secure/lib/libcrypt/crypt-blowfish.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
143e30386SXin LI /*	$OpenBSD: bcrypt.c,v 1.29 2014/02/24 19:45:43 tedu Exp $	*/
243e30386SXin LI 
35c129616SMark Murray /*
45c129616SMark Murray  * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
55c129616SMark Murray  * All rights reserved.
65c129616SMark Murray  *
75c129616SMark Murray  * Redistribution and use in source and binary forms, with or without
85c129616SMark Murray  * modification, are permitted provided that the following conditions
95c129616SMark Murray  * are met:
105c129616SMark Murray  * 1. Redistributions of source code must retain the above copyright
115c129616SMark Murray  *    notice, this list of conditions and the following disclaimer.
125c129616SMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
135c129616SMark Murray  *    notice, this list of conditions and the following disclaimer in the
145c129616SMark Murray  *    documentation and/or other materials provided with the distribution.
155c129616SMark Murray  * 3. All advertising materials mentioning features or use of this software
165c129616SMark Murray  *    must display the following acknowledgement:
175c129616SMark Murray  *      This product includes software developed by Niels Provos.
185c129616SMark Murray  * 4. The name of the author may not be used to endorse or promote products
195c129616SMark Murray  *    derived from this software without specific prior written permission.
205c129616SMark Murray  *
215c129616SMark Murray  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
225c129616SMark Murray  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
235c129616SMark Murray  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
245c129616SMark Murray  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
255c129616SMark Murray  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
265c129616SMark Murray  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
275c129616SMark Murray  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
285c129616SMark Murray  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
295c129616SMark Murray  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
305c129616SMark Murray  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
315c129616SMark Murray  */
325c129616SMark Murray 
3368344a95SPeter Wemm #include <sys/cdefs.h>
345c129616SMark Murray /* This password hashing algorithm was designed by David Mazieres
355c129616SMark Murray  * <dm@lcs.mit.edu> and works as follows:
365c129616SMark Murray  *
375c129616SMark Murray  * 1. state := InitState ()
3843e30386SXin LI  * 2. state := ExpandKey (state, salt, password)
3943e30386SXin LI  * 3. REPEAT rounds:
405c129616SMark Murray  *      state := ExpandKey (state, 0, password)
4143e30386SXin LI  *	state := ExpandKey (state, 0, salt)
425c129616SMark Murray  * 4. ctext := "OrpheanBeholderScryDoubt"
435c129616SMark Murray  * 5. REPEAT 64:
445c129616SMark Murray  * 	ctext := Encrypt_ECB (state, ctext);
455c129616SMark Murray  * 6. RETURN Concatenate (salt, ctext);
465c129616SMark Murray  *
475c129616SMark Murray  */
485c129616SMark Murray 
495c129616SMark Murray /*
505c129616SMark Murray  * FreeBSD implementation by Paul Herman <pherman@frenchfries.net>
5143e30386SXin LI  * and updated by Xin Li <delphij@FreeBSD.org>
525c129616SMark Murray  */
535c129616SMark Murray 
545c129616SMark Murray #include <stdio.h>
555c129616SMark Murray #include <stdlib.h>
565c129616SMark Murray #include <sys/types.h>
575c129616SMark Murray #include <string.h>
585c129616SMark Murray #include <pwd.h>
595c129616SMark Murray #include "blowfish.h"
60f2ac424aSMark Murray #include "crypt.h"
615c129616SMark Murray 
625c129616SMark Murray /* This implementation is adaptable to current computing power.
635c129616SMark Murray  * You can have up to 2^31 rounds which should be enough for some
645c129616SMark Murray  * time to come.
655c129616SMark Murray  */
665c129616SMark Murray 
675c129616SMark Murray #define BCRYPT_VERSION '2'
685c129616SMark Murray #define BCRYPT_MAXSALT 16	/* Precomputation is just so nice */
695c129616SMark Murray #define BCRYPT_BLOCKS 6		/* Ciphertext blocks */
7043e30386SXin LI #define BCRYPT_MINLOGROUNDS 4	/* we have log2(rounds) in salt */
7143e30386SXin LI 
725c129616SMark Murray 
73f2ac424aSMark Murray static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
74f2ac424aSMark Murray static void decode_base64(u_int8_t *, u_int16_t, const u_int8_t *);
755c129616SMark Murray 
7643e30386SXin LI const static u_int8_t Base64Code[] =
775c129616SMark Murray "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
785c129616SMark Murray 
7943e30386SXin LI const static u_int8_t index_64[128] = {
805c129616SMark Murray 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
815c129616SMark Murray 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
825c129616SMark Murray 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
835c129616SMark Murray 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
845c129616SMark Murray 	255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
855c129616SMark Murray 	56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
865c129616SMark Murray 	255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
875c129616SMark Murray 	7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
885c129616SMark Murray 	17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
895c129616SMark Murray 	255, 255, 255, 255, 255, 255, 28, 29, 30,
905c129616SMark Murray 	31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
915c129616SMark Murray 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
925c129616SMark Murray 	51, 52, 53, 255, 255, 255, 255, 255
935c129616SMark Murray };
945c129616SMark Murray #define CHAR64(c)  ( (c) > 127 ? 255 : index_64[(c)])
955c129616SMark Murray 
965c129616SMark Murray static void
decode_base64(u_int8_t * buffer,u_int16_t len,const u_int8_t * data)97f2ac424aSMark Murray decode_base64(u_int8_t *buffer, u_int16_t len, const u_int8_t *data)
985c129616SMark Murray {
995c129616SMark Murray 	u_int8_t *bp = buffer;
100f2ac424aSMark Murray 	const u_int8_t *p = data;
1015c129616SMark Murray 	u_int8_t c1, c2, c3, c4;
1025c129616SMark Murray 	while (bp < buffer + len) {
1035c129616SMark Murray 		c1 = CHAR64(*p);
1045c129616SMark Murray 		c2 = CHAR64(*(p + 1));
1055c129616SMark Murray 
1065c129616SMark Murray 		/* Invalid data */
1075c129616SMark Murray 		if (c1 == 255 || c2 == 255)
1085c129616SMark Murray 			break;
1095c129616SMark Murray 
11043e30386SXin LI 		*bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
1115c129616SMark Murray 		if (bp >= buffer + len)
1125c129616SMark Murray 			break;
1135c129616SMark Murray 
1145c129616SMark Murray 		c3 = CHAR64(*(p + 2));
1155c129616SMark Murray 		if (c3 == 255)
1165c129616SMark Murray 			break;
1175c129616SMark Murray 
1185c129616SMark Murray 		*bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
1195c129616SMark Murray 		if (bp >= buffer + len)
1205c129616SMark Murray 			break;
1215c129616SMark Murray 
1225c129616SMark Murray 		c4 = CHAR64(*(p + 3));
1235c129616SMark Murray 		if (c4 == 255)
1245c129616SMark Murray 			break;
1255c129616SMark Murray 		*bp++ = ((c3 & 0x03) << 6) | c4;
1265c129616SMark Murray 
1275c129616SMark Murray 		p += 4;
1285c129616SMark Murray 	}
1295c129616SMark Murray }
1305c129616SMark Murray 
1315c129616SMark Murray /* We handle $Vers$log2(NumRounds)$salt+passwd$
1325c129616SMark Murray    i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
1335c129616SMark Murray 
134*5f521d7bSEd Schouten int
crypt_blowfish(const char * key,const char * salt,char * buffer)135*5f521d7bSEd Schouten crypt_blowfish(const char *key, const char *salt, char *buffer)
1365c129616SMark Murray {
1375c129616SMark Murray 	blf_ctx state;
1385c129616SMark Murray 	u_int32_t rounds, i, k;
1395c129616SMark Murray 	u_int16_t j;
14043e30386SXin LI 	size_t key_len;
14143e30386SXin LI 	u_int8_t salt_len, logr, minr;
1425c129616SMark Murray 	u_int8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt";
1435c129616SMark Murray 	u_int8_t csalt[BCRYPT_MAXSALT];
1445c129616SMark Murray 	u_int32_t cdata[BCRYPT_BLOCKS];
14543e30386SXin LI 	char arounds[3];
1465c129616SMark Murray 
1475c129616SMark Murray 	/* Defaults */
148185e05eeSXin LI 	minr = 'b';
14943e30386SXin LI 	logr = BCRYPT_MINLOGROUNDS;
15043e30386SXin LI 	rounds = 1U << logr;
1515c129616SMark Murray 
15243e30386SXin LI 	if (*salt == '$') {
1535c129616SMark Murray 		/* Discard "$" identifier */
1545c129616SMark Murray 		salt++;
1555c129616SMark Murray 
156*5f521d7bSEd Schouten 		if (*salt > BCRYPT_VERSION)
157*5f521d7bSEd Schouten 			return (-1);
1585c129616SMark Murray 
1595c129616SMark Murray 		/* Check for minor versions */
1605c129616SMark Murray 		if (salt[1] != '$') {
1615c129616SMark Murray 			 switch (salt[1]) {
16243e30386SXin LI 			 case 'a':	/* 'ab' should not yield the same as 'abab' */
16343e30386SXin LI 			 case 'b':	/* cap input length at 72 bytes */
164a3b20e50SAllan Jude 			 case 'y':	/* same as 'b', for compatibility
165a3b20e50SAllan Jude 					 * with openwall crypt_blowfish
166a3b20e50SAllan Jude 					 */
16743e30386SXin LI 				 minr = salt[1];
1685c129616SMark Murray 				 salt++;
1695c129616SMark Murray 				 break;
1705c129616SMark Murray 			 default:
171*5f521d7bSEd Schouten 				 return (-1);
1725c129616SMark Murray 			 }
1735c129616SMark Murray 		} else
174f2ac424aSMark Murray 			 minr = 0;
1755c129616SMark Murray 
1765c129616SMark Murray 		/* Discard version + "$" identifier */
1775c129616SMark Murray 		salt += 2;
1785c129616SMark Murray 
1795c129616SMark Murray 		if (salt[2] != '$')
1805c129616SMark Murray 			/* Out of sync with passwd entry */
181*5f521d7bSEd Schouten 			return (-1);
1825c129616SMark Murray 
18343e30386SXin LI 		memcpy(arounds, salt, sizeof(arounds));
18443e30386SXin LI 		if (arounds[sizeof(arounds) - 1] != '$')
185*5f521d7bSEd Schouten 			return (-1);
18643e30386SXin LI 		arounds[sizeof(arounds) - 1] = 0;
18743e30386SXin LI 		logr = strtonum(arounds, BCRYPT_MINLOGROUNDS, 31, NULL);
18843e30386SXin LI 		if (logr == 0)
189*5f521d7bSEd Schouten 			return (-1);
19043e30386SXin LI 		/* Computer power doesn't increase linearly, 2^x should be fine */
19143e30386SXin LI 		rounds = 1U << logr;
1925c129616SMark Murray 
1935c129616SMark Murray 		/* Discard num rounds + "$" identifier */
1945c129616SMark Murray 		salt += 3;
1955c129616SMark Murray 	}
1965c129616SMark Murray 
19743e30386SXin LI 	if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
198*5f521d7bSEd Schouten 		return (-1);
1995c129616SMark Murray 
2005c129616SMark Murray 	/* We dont want the base64 salt but the raw data */
201c8fa8e25SMark Murray 	decode_base64(csalt, BCRYPT_MAXSALT, (const u_int8_t *) salt);
2025c129616SMark Murray 	salt_len = BCRYPT_MAXSALT;
20343e30386SXin LI 	if (minr <= 'a')
204f2ac424aSMark Murray 		key_len = (u_int8_t)(strlen(key) + (minr >= 'a' ? 1 : 0));
20543e30386SXin LI 	else {
20643e30386SXin LI 		/* strlen() returns a size_t, but the function calls
20743e30386SXin LI 		 * below result in implicit casts to a narrower integer
20843e30386SXin LI 		 * type, so cap key_len at the actual maximum supported
20943e30386SXin LI 		 * length here to avoid integer wraparound */
21043e30386SXin LI 		key_len = strlen(key);
21143e30386SXin LI 		if (key_len > 72)
21243e30386SXin LI 			key_len = 72;
21343e30386SXin LI 		key_len++; /* include the NUL */
21443e30386SXin LI 	}
2155c129616SMark Murray 
2165c129616SMark Murray 	/* Setting up S-Boxes and Subkeys */
2175c129616SMark Murray 	Blowfish_initstate(&state);
2185c129616SMark Murray 	Blowfish_expandstate(&state, csalt, salt_len,
219f2ac424aSMark Murray 	    (const u_int8_t *) key, key_len);
2205c129616SMark Murray 	for (k = 0; k < rounds; k++) {
221f2ac424aSMark Murray 		Blowfish_expand0state(&state, (const u_int8_t *) key, key_len);
2225c129616SMark Murray 		Blowfish_expand0state(&state, csalt, salt_len);
2235c129616SMark Murray 	}
2245c129616SMark Murray 
2255c129616SMark Murray 	/* This can be precomputed later */
2265c129616SMark Murray 	j = 0;
2275c129616SMark Murray 	for (i = 0; i < BCRYPT_BLOCKS; i++)
2285c129616SMark Murray 		cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
2295c129616SMark Murray 
2305c129616SMark Murray 	/* Now do the encryption */
2315c129616SMark Murray 	for (k = 0; k < 64; k++)
2325c129616SMark Murray 		blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
2335c129616SMark Murray 
2345c129616SMark Murray 	for (i = 0; i < BCRYPT_BLOCKS; i++) {
2355c129616SMark Murray 		ciphertext[4 * i + 3] = cdata[i] & 0xff;
2365c129616SMark Murray 		cdata[i] = cdata[i] >> 8;
2375c129616SMark Murray 		ciphertext[4 * i + 2] = cdata[i] & 0xff;
2385c129616SMark Murray 		cdata[i] = cdata[i] >> 8;
2395c129616SMark Murray 		ciphertext[4 * i + 1] = cdata[i] & 0xff;
2405c129616SMark Murray 		cdata[i] = cdata[i] >> 8;
2415c129616SMark Murray 		ciphertext[4 * i + 0] = cdata[i] & 0xff;
2425c129616SMark Murray 	}
2435c129616SMark Murray 
2445c129616SMark Murray 
245*5f521d7bSEd Schouten 	*buffer++ = '$';
246*5f521d7bSEd Schouten 	*buffer++ = BCRYPT_VERSION;
247f2ac424aSMark Murray 	if (minr)
248*5f521d7bSEd Schouten 		*buffer++ = minr;
249*5f521d7bSEd Schouten 	*buffer++ = '$';
2505c129616SMark Murray 
251*5f521d7bSEd Schouten 	snprintf(buffer, 4, "%2.2u$", logr);
252*5f521d7bSEd Schouten 	buffer += 3;
2535c129616SMark Murray 
254*5f521d7bSEd Schouten 	encode_base64((u_int8_t *)buffer, csalt, BCRYPT_MAXSALT);
255*5f521d7bSEd Schouten 	buffer += strlen(buffer);
256*5f521d7bSEd Schouten 	encode_base64((u_int8_t *)buffer, ciphertext, 4 * BCRYPT_BLOCKS - 1);
25743e30386SXin LI 	memset(&state, 0, sizeof(state));
25843e30386SXin LI 	memset(ciphertext, 0, sizeof(ciphertext));
25943e30386SXin LI 	memset(csalt, 0, sizeof(csalt));
26043e30386SXin LI 	memset(cdata, 0, sizeof(cdata));
261*5f521d7bSEd Schouten 	return (0);
2625c129616SMark Murray }
2635c129616SMark Murray 
2645c129616SMark Murray static void
encode_base64(u_int8_t * buffer,u_int8_t * data,u_int16_t len)2655c129616SMark Murray encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
2665c129616SMark Murray {
2675c129616SMark Murray 	u_int8_t *bp = buffer;
2685c129616SMark Murray 	u_int8_t *p = data;
2695c129616SMark Murray 	u_int8_t c1, c2;
2705c129616SMark Murray 	while (p < data + len) {
2715c129616SMark Murray 		c1 = *p++;
2725c129616SMark Murray 		*bp++ = Base64Code[(c1 >> 2)];
2735c129616SMark Murray 		c1 = (c1 & 0x03) << 4;
2745c129616SMark Murray 		if (p >= data + len) {
2755c129616SMark Murray 			*bp++ = Base64Code[c1];
2765c129616SMark Murray 			break;
2775c129616SMark Murray 		}
2785c129616SMark Murray 		c2 = *p++;
2795c129616SMark Murray 		c1 |= (c2 >> 4) & 0x0f;
2805c129616SMark Murray 		*bp++ = Base64Code[c1];
2815c129616SMark Murray 		c1 = (c2 & 0x0f) << 2;
2825c129616SMark Murray 		if (p >= data + len) {
2835c129616SMark Murray 			*bp++ = Base64Code[c1];
2845c129616SMark Murray 			break;
2855c129616SMark Murray 		}
2865c129616SMark Murray 		c2 = *p++;
2875c129616SMark Murray 		c1 |= (c2 >> 6) & 0x03;
2885c129616SMark Murray 		*bp++ = Base64Code[c1];
2895c129616SMark Murray 		*bp++ = Base64Code[c2 & 0x3f];
2905c129616SMark Murray 	}
2915c129616SMark Murray 	*bp = '\0';
2925c129616SMark Murray }
2935c129616SMark Murray #if 0
2945c129616SMark Murray void
2955c129616SMark Murray main()
2965c129616SMark Murray {
2975c129616SMark Murray 	char    blubber[73];
2985c129616SMark Murray 	char    salt[100];
2995c129616SMark Murray 	char   *p;
3005c129616SMark Murray 	salt[0] = '$';
3015c129616SMark Murray 	salt[1] = BCRYPT_VERSION;
3025c129616SMark Murray 	salt[2] = '$';
3035c129616SMark Murray 
3045c129616SMark Murray 	snprintf(salt + 3, 4, "%2.2u$", 5);
3055c129616SMark Murray 
3065c129616SMark Murray 	printf("24 bytes of salt: ");
30743e30386SXin LI 	fgets(salt + 6, sizeof(salt) - 6, stdin);
3085c129616SMark Murray 	salt[99] = 0;
3095c129616SMark Murray 	printf("72 bytes of password: ");
3105c129616SMark Murray 	fpurge(stdin);
31143e30386SXin LI 	fgets(blubber, sizeof(blubber), stdin);
3125c129616SMark Murray 	blubber[72] = 0;
3135c129616SMark Murray 
3145c129616SMark Murray 	p = crypt(blubber, salt);
3155c129616SMark Murray 	printf("Passwd entry: %s\n\n", p);
3165c129616SMark Murray 
3175c129616SMark Murray 	p = bcrypt_gensalt(5);
3185c129616SMark Murray 	printf("Generated salt: %s\n", p);
3195c129616SMark Murray 	p = crypt(blubber, p);
3205c129616SMark Murray 	printf("Passwd entry: %s\n", p);
3215c129616SMark Murray }
3225c129616SMark Murray #endif
323