First pass at experimental NIF
diff --git a/lib/bcrypt/c_src/bcrypt_erlang.c b/lib/bcrypt/c_src/bcrypt_erlang.c
deleted file mode 100644
index cfd1729..0000000
--- a/lib/bcrypt/c_src/bcrypt_erlang.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2008 Hunter Morris <huntermorris@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <erl_interface.h>
-#include <ei.h>
-#include <unistd.h>
-
-#include "erl_blf.h"
-
-#define dec_int16(s) ((((unsigned char*)(s))[0] << 8) | \
- (((unsigned char*)(s))[1]))
-
-#define enc_int16(i, s) {((unsigned char*)(s))[0] = ((i) >> 8) & 0xff; \
- ((unsigned char*)(s))[1] = (i) & 0xff;}
-
-#define BUFSIZE (1 << 16)
-#define CMD_SALT 0
-#define CMD_HASHPW 1
-
-typedef unsigned char byte;
-
-char *bcrypt(const char *, const char *);
-void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
-
-/* These methods came from the Erlang port command tutorial:
- * http://www.erlang.org/doc/tutorial/c_port.html#4.2
- */
-static int
-read_buf(int fd, byte *buf, int len)
-{
- int i, got = 0;
- do {
- if ((i = read(fd, buf+got, len-got)) <= 0) {
- if (i == 0) return got;
- if (errno != EINTR)
- return got;
- i = 0;
- }
- got += i;
- } while (got < len);
- return (len);
-}
-
-static int
-read_cmd(byte *buf)
-{
- int len;
- if (read_buf(0, buf, 2) != 2)
- return 0;
- len = dec_int16(buf);
- if (read_buf(0, buf, len) != len)
- return 0;
- return 1;
-}
-
-static int
-write_buf(int fd, byte *buf, int len)
-{
- int i, done = 0;
- do {
- if ((i = write(fd, buf+done, len-done)) < 0) {
- if (errno != EINTR)
- return (i);
- i = 0;
- }
- done += i;
- } while (done < len);
- return (len);
-}
-
-static int
-write_cmd(byte *buf, int len)
-{
- byte hd[2];
- enc_int16(len, hd);
- if (write_buf(1, hd, 2) != 2)
- return 0;
- if (write_buf(1, buf, len) != len)
- return 0;
- return 1;
-}
-
-static int
-process_reply(ETERM *pid, int cmd, const char *res)
-{
- ETERM *result;
- int len, retval;
- byte *buf;
- result = erl_format("{~i, ~w, ~s}", cmd, pid, res);
- len = erl_term_len(result);
- buf = erl_malloc(len);
- erl_encode(result, buf);
- retval = write_cmd(buf, len);
- erl_free_term(result);
- erl_free(buf);
- return retval;
-}
-
-static int
-process_encode_salt(ETERM *pid, ETERM *data)
-{
- int retval = 0;
- ETERM *pattern, *cslt, *lr;
- byte *csalt = NULL;
- long log_rounds = -1;
- int csaltlen = -1;
- char ret[64];
- pattern = erl_format("{Csalt, LogRounds}");
- if (erl_match(pattern, data)) {
- cslt = erl_var_content(pattern, "Csalt");
- csaltlen = ERL_BIN_SIZE(cslt);
- csalt = ERL_BIN_PTR(cslt);
- lr = erl_var_content(pattern, "LogRounds");
- log_rounds = ERL_INT_UVALUE(lr);
- if (16 != csaltlen) {
- retval = process_reply(pid, CMD_SALT, "Invalid salt length");
- } else if (log_rounds < 4 || log_rounds > 31) {
- retval = process_reply(pid, CMD_SALT, "Invalid number of rounds");
- } else {
- encode_salt(ret, (u_int8_t*)csalt, csaltlen, log_rounds);
- retval = process_reply(pid, CMD_SALT, ret);
- }
- erl_free_term(cslt);
- erl_free_term(lr);
- };
- erl_free_term(pattern);
- return retval;
-}
-
-static int
-process_hashpw(ETERM *pid, ETERM *data)
-{
- int retval = 0;
- ETERM *pattern, *pwd, *slt;
- char *password, *salt;
- char *ret = NULL;
- pattern = erl_format("{Pass, Salt}");
- if (erl_match(pattern, data)) {
- pwd = erl_var_content(pattern, "Pass");
- password = erl_iolist_to_string(pwd);
- slt = erl_var_content(pattern, "Salt");
- salt = erl_iolist_to_string(slt);
- if (NULL == (ret = bcrypt(password, salt)) ||
- 0 == strcmp(ret, ":")) {
- retval = process_reply(pid, CMD_HASHPW, "Invalid salt");
- } else {
- retval = process_reply(pid, CMD_HASHPW, ret);
- }
- erl_free_term(pwd);
- erl_free_term(slt);
- erl_free(password);
- erl_free(salt);
- };
- erl_free_term(pattern);
- return retval;
-}
-
-static int
-process_command(unsigned char *buf)
-{
- int retval = 0;
- ETERM *pattern, *tuple, *cmd, *port, *data;
- pattern = erl_format("{Cmd, Port, Data}");
- tuple = erl_decode(buf);
- if (erl_match(pattern, tuple)) {
- cmd = erl_var_content(pattern, "Cmd");
- port = erl_var_content(pattern, "Port");
- data = erl_var_content(pattern, "Data");
- switch (ERL_INT_VALUE(cmd)) {
- case CMD_SALT:
- retval = process_encode_salt(port, data);
- break;
- case CMD_HASHPW:
- retval = process_hashpw(port, data);
- break;
- };
- erl_free_term(cmd);
- erl_free_term(port);
- erl_free_term(data);
- }
- erl_free_term(pattern);
- erl_free_term(tuple);
- return retval;
-}
-
-static void
-loop(void)
-{
- byte buf[BUFSIZE];
- int retval = 0;
- do {
- if (read_cmd(buf) > 0)
- retval = process_command(buf);
- else
- retval = 0;
- } while (retval);
-}
-
-int
-main(int argc, char *argv[])
-{
- erl_init(NULL, 0);
- loop();
- return 0;
-}
diff --git a/lib/bcrypt/c_src/bcrypt_nif.c b/lib/bcrypt/c_src/bcrypt_nif.c
new file mode 100644
index 0000000..7e41afc
--- /dev/null
+++ b/lib/bcrypt/c_src/bcrypt_nif.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2009 Hunter Morris <huntermorris@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "erl_nif.h"
+#include "erl_blf.h"
+
+typedef unsigned char byte;
+
+char *bcrypt(const char *, const char *);
+void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
+
+static ERL_NIF_TERM
+encode_salt(ErlNifEnv* env, ERL_NIF_TERM csalt_term, ERL_NIF_TERM log_rounds_term)
+{
+ ErlNifBinary csalt, bin;
+ unsigned long log_rounds;
+
+ if (!enif_inspect_binary(env, csalt_term, &csalt) || 16 != csalt.size) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_get_ulong(env, log_rounds_term, &log_rounds)) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_alloc_binary(env, 64, &bin)) {
+ return enif_make_badarg(env);
+ }
+
+ if (!encode_salt(bin.data, (u_int8_t*)csalt.data, csalt.size, log_rounds)) {
+ return enif_make_badarg(env);
+ }
+
+ return enif_make_binary(env, bin);
+}
+
+static ERL_NIF_TERM
+hashpw(ErlNifEnv* env, ERL_NIF_TERM pass_term, ERL_NIF_TERM salt_term)
+{
+ ErlNifBinary pass, salt, bin;
+ char *ret = NULL;
+
+ if (!enif_inspect_binary(env, pass_term, &pass)) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_inspect_binary(env, salt_term, &salt)) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_alloc_binary(env, 60, &bin)) {
+ return enif_make_badarg(env);
+ }
+
+ if (NULL == (ret = bcrypt(pass.data, salt.data)) || 0 == strcmp(ret, ":")) {
+ return enif_make_badarg(env);
+ }
+
+ return enif_make_string(env, ret);
+}
+
+static ErlNifFunc bcrypt_nif_funcs[] =
+{
+ {"encode_salt", 2, encode_salt},
+ {"hashpw", 2, hashpw}
+};
+
+ERL_NIF_INIT(bcrypt_nif, bcrypt_nif_funcs, NULL, NULL, NULL, NULL)
diff --git a/lib/bcrypt/c_src/erl_blf.h b/lib/bcrypt/c_src/erl_blf.h
index 74e6fc3..d64535f 100644
--- a/lib/bcrypt/c_src/erl_blf.h
+++ b/lib/bcrypt/c_src/erl_blf.h
@@ -57,8 +57,8 @@
/* Blowfish context */
typedef struct BlowfishContext {
- u_int32_t S[4][256]; /* S-Boxes */
- u_int32_t P[BLF_N + 2]; /* Subkeys */
+ u_int32_t S[4][256]; /* S-Boxes */
+ u_int32_t P[BLF_N + 2]; /* Subkeys */
} blf_ctx;
/* Raw access to customized Blowfish