lua-bcrypt

Secure password hashing for Lua
Log | Files | Refs | README | LICENSE

bcrypt.c (8534B)


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