Skip to content

This change makes bcrypt_nif thread safe #9

Closed
wants to merge 2 commits into from
View
23 c_src/bcrypt.c
@@ -63,14 +63,13 @@
#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
#define BCRYPT_MINROUNDS 16 /* we have log2(rounds) in salt */
-char *bcrypt(const char *, const char *);
+int bcrypt(char *, const char *, const char *);
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 error[] = ":";
+#define ERROR -1
const static u_int8_t Base64Code[] =
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@@ -143,8 +142,8 @@ encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr)
/* We handle $Vers$log2(NumRounds)$salt+passwd$
i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
-char *
-bcrypt(const char *key, const char *salt)
+int
+bcrypt(char * encrypted, const char *key, const char *salt)
{
blf_ctx state;
u_int32_t rounds, i, k;
@@ -160,7 +159,7 @@ bcrypt(const char *key, const char *salt)
if (*salt > BCRYPT_VERSION) {
/* How do I handle errors ? Return ':' */
- return error;
+ return ERROR;
}
/* Check for minor versions */
@@ -172,7 +171,7 @@ bcrypt(const char *key, const char *salt)
salt++;
break;
default:
- return error;
+ return ERROR;
}
} else
minor = 0;
@@ -182,21 +181,21 @@ bcrypt(const char *key, const char *salt)
if (salt[2] != '$')
/* Out of sync with passwd entry */
- return error;
+ return ERROR;
/* Computer power doesn't increase linear, 2^x should be fine */
n = atoi(salt);
if (n > 31 || n < 0)
- return error;
+ return ERROR;
logr = (u_int8_t)n;
if ((rounds = (u_int32_t) 1 << logr) < BCRYPT_MINROUNDS)
- return error;
+ return ERROR;
/* Discard num rounds + "$" identifier */
salt += 3;
if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
- return error;
+ return ERROR;
/* We dont want the base64 salt but the raw data */
decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
@@ -248,7 +247,7 @@ 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;
}
static void
View
11 c_src/bcrypt_nif.c
@@ -75,7 +75,7 @@ static ERL_NIF_TERM hashpw(task_t* task)
{
char password[1024] = { 0 };
char salt[1024] = { 0 };
- char *ret = NULL;
+ char encrypted[1024] = { 0 };
size_t password_sz = 1024;
if (password_sz > task->data.hash.password.size)
@@ -87,7 +87,7 @@ static ERL_NIF_TERM hashpw(task_t* task)
salt_sz = task->data.hash.salt.size;
(void)memcpy(&salt, task->data.hash.salt.data, salt_sz);
- if (NULL == (ret = bcrypt(password, salt)) || 0 == strcmp(ret, ":")) {
+ if (bcrypt(encrypted, password, salt)) {
return enif_make_tuple3(
task->env,
enif_make_atom(task->env, "error"),
@@ -99,7 +99,7 @@ static ERL_NIF_TERM hashpw(task_t* task)
task->env,
enif_make_atom(task->env, "ok"),
task->ref,
- enif_make_string(task->env, ret, ERL_NIF_LATIN1));
+ enif_make_string(task->env, encrypted, ERL_NIF_LATIN1));
}
void* async_worker(void* arg)
@@ -134,6 +134,7 @@ static ERL_NIF_TERM bcrypt_encode_salt(ErlNifEnv* env, int argc, const ERL_NIF_T
{
ErlNifBinary csalt, bin;
unsigned long log_rounds;
+ ERL_NIF_TERM ret;
if (!enif_inspect_binary(env, argv[0], &csalt) || 16 != csalt.size) {
return enif_make_badarg(env);
@@ -152,7 +153,9 @@ static ERL_NIF_TERM bcrypt_encode_salt(ErlNifEnv* env, int argc, const ERL_NIF_T
encode_salt((char *)bin.data, (u_int8_t*)csalt.data, csalt.size, log_rounds);
enif_release_binary(&csalt);
- return enif_make_string(env, (char *)bin.data, ERL_NIF_LATIN1);
+ ret = enif_make_string(env, (char *)bin.data, ERL_NIF_LATIN1);
+ enif_release_binary(&bin);
+ return ret;
}
static ERL_NIF_TERM bcrypt_hashpw(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
View
2 c_src/bcrypt_nif.h
@@ -5,7 +5,7 @@
typedef unsigned char byte;
-char *bcrypt(const char *, const char *);
+int bcrypt(char *, const char *, const char *);
void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
typedef struct {
Something went wrong with that request. Please try again.