Browse Source

minimal change to implementation of bcrypt to not require static globals.

add some friendlier functions.
move the classic static data api into wrapper functions.
a few more changes to come...
OPENBSD_5_6
tedu 10 years ago
parent
commit
5ca97b2032
1 changed files with 88 additions and 39 deletions
  1. +88
    -39
      src/lib/libc/crypt/bcrypt.c

+ 88
- 39
src/lib/libc/crypt/bcrypt.c View File

@ -1,6 +1,7 @@
/* $OpenBSD: bcrypt.c,v 1.31 2014/03/22 23:02:03 tedu Exp $ */
/* $OpenBSD: bcrypt.c,v 1.32 2014/03/23 23:19:21 tedu Exp $ */
/*
* Copyright (c) 2014 Ted Unangst <tedu@openbsd.org>
* Copyright (c) 1997 Niels Provos <provos@umich.edu>
*
* Permission to use, copy, modify, and distribute this software for any
@ -47,37 +48,23 @@
#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
#define BCRYPT_MINLOGROUNDS 4 /* we have log2(rounds) in salt */
#define BCRYPT_SALTSPACE (7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1)
char *bcrypt_gensalt(u_int8_t);
static void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *);
static char encrypted[_PASSWORD_LEN];
static char gsalt[7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1];
static char error[] = ":";
static void
encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr)
{
salt[0] = '$';
salt[1] = BCRYPT_VERSION;
salt[2] = 'a';
salt[3] = '$';
snprintf(salt + 4, 4, "%2.2u$", logr);
encode_base64((u_int8_t *) salt + 7, csalt, clen);
}
/* Generates a salt for this version of crypt.
Since versions may change. Keeping this here
seems sensible.
/*
* Generates a salt for this version of crypt.
*/
char *
bcrypt_gensalt(u_int8_t log_rounds)
int
bcrypt_initsalt(int log_rounds, uint8_t *salt, size_t saltbuflen)
{
u_int8_t csalt[BCRYPT_MAXSALT];
uint8_t csalt[BCRYPT_MAXSALT];
if (saltbuflen < BCRYPT_SALTSPACE)
return -1;
arc4random_buf(csalt, sizeof(csalt));
@ -86,14 +73,18 @@ bcrypt_gensalt(u_int8_t log_rounds)
else if (log_rounds > 31)
log_rounds = 31;
encode_salt(gsalt, csalt, BCRYPT_MAXSALT, log_rounds);
return gsalt;
snprintf(salt, 4, "$2a$%2.2u$", log_rounds);
encode_base64((uint8_t *)salt + 7, csalt, sizeof(csalt));
return 0;
}
/* We handle $Vers$log2(NumRounds)$salt+passwd$
i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
char *
bcrypt(const char *key, const char *salt)
/*
* the core bcrypt function
*/
int
bcrypt_hashpass(const char *key, const char *salt, char *encrypted,
size_t encryptedlen)
{
blf_ctx state;
u_int32_t rounds, i, k;
@ -109,8 +100,7 @@ bcrypt(const char *key, const char *salt)
salt++;
if (*salt > BCRYPT_VERSION) {
/* How do I handle errors ? Return ':' */
return error;
return -1;
}
/* Check for minor versions */
@ -122,7 +112,7 @@ bcrypt(const char *key, const char *salt)
salt++;
break;
default:
return error;
return -1;
}
} else
minor = 0;
@ -132,15 +122,15 @@ bcrypt(const char *key, const char *salt)
if (salt[2] != '$')
/* Out of sync with passwd entry */
return error;
return -1;
memcpy(arounds, salt, sizeof(arounds));
if (arounds[sizeof(arounds) - 1] != '$')
return error;
return -1;
arounds[sizeof(arounds) - 1] = 0;
logr = strtonum(arounds, BCRYPT_MINLOGROUNDS, 31, NULL);
if (logr == 0)
return error;
return -1;
/* Computer power doesn't increase linearly, 2^x should be fine */
rounds = 1U << logr;
@ -148,7 +138,7 @@ bcrypt(const char *key, const char *salt)
salt += 3;
if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
return error;
return -1;
/* We dont want the base64 salt but the raw data */
decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
@ -211,9 +201,41 @@ bcrypt(const char *key, const char *salt)
memset(ciphertext, 0, sizeof(ciphertext));
memset(csalt, 0, sizeof(csalt));
memset(cdata, 0, sizeof(cdata));
return encrypted;
return 0;
}
/*
* user friendly functions
*/
int
bcrypt_newhash(const char *pass, int log_rounds, char *hash, size_t hashlen)
{
char salt[BCRYPT_SALTSPACE];
if (bcrypt_initsalt(log_rounds, salt, sizeof(salt)) != 0)
return -1;
if (bcrypt_hashpass(pass, salt, hash, hashlen) != 0)
return -1;
return 0;
}
int
bcrypt_checkpass(const char *pass, const char *goodhash)
{
char hash[_PASSWORD_LEN];
if (bcrypt_hashpass(pass, goodhash, hash, sizeof(hash)) != 0)
return -1;
if (strcmp(hash, goodhash) != 0)
return -1;
return 0;
}
/*
* internal utilities
*/
const static u_int8_t Base64Code[] =
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@ -298,3 +320,30 @@ encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
}
*bp = '\0';
}
/*
* classic interface
*/
char *
bcrypt_gensalt(u_int8_t log_rounds)
{
static char gsalt[7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1];
bcrypt_initsalt(log_rounds, gsalt, sizeof(gsalt));
return gsalt;
}
char *
bcrypt(const char *pass, const char *salt)
{
static char gencrypted[_PASSWORD_LEN];
static char gerror[] = ":";
/* How do I handle errors ? Return ':' */
if (bcrypt_hashpass(pass, salt, gencrypted, sizeof(gencrypted)) != 0)
return gerror;
return gencrypted;
}

Loading…
Cancel
Save