Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(argon2) ensure we are JIT compiled #11

Merged
merged 3 commits into from
Jan 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ install:
- luarocks make

script:
- make lint && busted -v --coverage -o gtest --repeat 3 spec
- make lint
- busted --exclude-tags=JIT -v --coverage -o gtest --repeat 3 spec
- if [ "$LUA" = "luajit 2.1" ]; then busted -v -o gtest --tags JIT; fi

after_success:
- luacov-coveralls -i ./src/argon2.lua
Expand Down
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
## [Unreleased][unrelease]

## [3.0.1] - 2017/01/18

### Added

- Ensure `hash_encoded()` and `verify()` are JIT compiled in LuaJIT 2.1.
[#11](https://github.com/thibaultcha/lua-argon2-ffi/pull/11)

## [3.0.0] - 2016/12/08

**Note**: This module's version was bumped to `3.0.0` to reflect the
interoperability of its API with the lua-argon2 implementation. In the future,
lua-argon2 and lua-argon2-ffi will continue sharing the same version number
lua-argon2 and lua-argon2-ffi will continue sharing the same major version number
for similar versions.

### Changed
Expand Down
44 changes: 44 additions & 0 deletions spec/argon2_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ describe("hash_encoded()", function()
argon2.hash_encoded("", "", {parallelism = ""})
end, "bad argument #3 to 'hash_encoded' (expected parallelism to be a number, got string)")

assert.has_error(function()
argon2.hash_encoded("", "", {hash_len = ""})
end, "bad argument #3 to 'hash_encoded' (expected hash_len to be a number, got string)")

--[[
assert.has_error(function()
argon2.hash_encoded("", "", {}, "")
Expand Down Expand Up @@ -233,6 +237,46 @@ describe("verify()", function()
end)
end)

describe("#JIT", function()

local function read_trace(outfile)
local f = assert(io.open(outfile, "r"))
local t = f:read("*a")
f:close()
return t
end

it("hash_encoded() JITs", function()
local v = require "jit.v"
local outfile = os.tmpname()
v.on(outfile)

for _ = 1, 100 do
argon2.hash_encoded("password", "somesalt")
end

local trace = read_trace(outfile)
assert.matches("argon2_spec%.lua:%d+ loop", trace)
assert.not_matches("NYI", trace)
end)

it("verify() JITs", function()
local v = require "jit.v"
local outfile = os.tmpname()
v.on(outfile)

local hash = assert(argon2.hash_encoded("password", "somesalt"))

for _ = 1, 100 do
argon2.verify(hash, "password")
end

local trace = read_trace(outfile)
assert.matches("argon2_spec%.lua:%d+ loop", trace)
assert.not_matches("NYI", trace)
end)
end)

--[[
pending("module settings", function()

Expand Down
95 changes: 52 additions & 43 deletions src/argon2.lua
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
-- vim:set st=4 sw=4 et:
-- vim:set st=4 sw=4 sts=4 et:
local ffi = require "ffi"


local ffi_new = ffi.new
local ffi_str = ffi.string
local find = string.find
local error = error
local pairs = pairs
local type = type


local empty_t = {}


ffi.cdef [[
typedef enum Argon2_type {
Argon2_d = 0,
Expand Down Expand Up @@ -73,15 +75,6 @@ do
end


local OPTIONS = {
t_cost = 3,
m_cost = 4096,
parallelism = 1,
hash_len = 32,
variant = argon2_i,
}


local _M = {
_VERSION = "3.0.0",
_AUTHOR = "Thibault Charbonnier",
Expand All @@ -106,57 +99,73 @@ function _M.hash_encoded(pwd, salt, opts)
.. type(salt) .. ")", 2)
end

if opts and type(opts) ~= "table" then
if not opts then
opts = empty_t
end

if type(opts) ~= "table" then
return error("bad argument #3 to 'hash_encoded' (expected to be a "
.. "table)", 2)
end

if opts == nil then
opts = OPTIONS

else
for k, v in pairs(OPTIONS) do
local o = opts[k]
local t_cost = opts.t_cost or 3
local m_cost = opts.m_cost or 4096
local parallelism = opts.parallelism or 1
local hash_len = opts.hash_len or 32
local variant = opts.variant or argon2_i

if type(variant) ~= "cdata" then
return error("bad argument #3 to 'hash_encoded' (expected " ..
"variant to be an argon2_type, got " ..
type(opts.variant) .. ")", 2)
end

if o == nil then
opts[k] = v
if type(t_cost) ~= "number" then
return error("bad argument #3 to 'hash_encoded' (expected " ..
"t_cost to be a number, got " ..
type(t_cost) .. ")", 2)
end

elseif k == "variant" then
if type(o) ~= "cdata" then
return error("bad argument #3 to 'hash_encoded' (expected "
.. k .. " to be an argon2_type, got "
.. type(o) .. ")", 2)
end
if type(m_cost) ~= "number" then
return error("bad argument #3 to 'hash_encoded' (expected " ..
"m_cost to be a number, got " ..
type(m_cost) .. ")", 2)
end

if type(parallelism) ~= "number" then
return error("bad argument #3 to 'hash_encoded' (expected " ..
"parallelism to be a number, got " ..
type(parallelism) .. ")", 2)
end

elseif type(o) ~= "number" then
return error("bad argument #3 to 'hash_encoded' (expected "
.. k .. " to be a number, got "
.. type(o) .. ")", 2)
end
end
if type(hash_len) ~= "number" then
return error("bad argument #3 to 'hash_encoded' (expected " ..
"hash_len to be a number, got " ..
type(hash_len) .. ")", 2)
end

local buf_len = lib.argon2_encodedlen(opts.t_cost, opts.m_cost,
opts.parallelism, #salt,
opts.hash_len, opts.variant)
local buf_len = lib.argon2_encodedlen(t_cost, m_cost,
parallelism, #salt,
hash_len, variant)

local buf = ffi_new("char[?]", buf_len)
local ret_code

if opts.variant == argon2_d then
ret_code = lib.argon2d_hash_encoded(opts.t_cost, opts.m_cost,
opts.parallelism, pwd, #pwd, salt,
#salt, opts.hash_len, buf, buf_len)
ret_code = lib.argon2d_hash_encoded(t_cost, m_cost,
parallelism, pwd, #pwd, salt,
#salt, hash_len, buf, buf_len)

elseif opts.variant == argon2_id then
ret_code = lib.argon2id_hash_encoded(opts.t_cost, opts.m_cost,
opts.parallelism, pwd, #pwd, salt,
#salt, opts.hash_len, buf, buf_len)
ret_code = lib.argon2id_hash_encoded(t_cost, m_cost,
parallelism, pwd, #pwd, salt,
#salt, hash_len, buf, buf_len)

else
ret_code = lib.argon2i_hash_encoded(opts.t_cost, opts.m_cost,
opts.parallelism, pwd, #pwd, salt,
#salt, opts.hash_len, buf, buf_len)
ret_code = lib.argon2i_hash_encoded(t_cost, m_cost,
parallelism, pwd, #pwd, salt,
#salt, hash_len, buf, buf_len)
end

if ret_code ~= ARGON2_OK then
Expand Down