Diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Check the comparisons that must not leak timing
constant_equals was only checked for its answers, on strings that
differ in one byte. Summing the plain differences instead of their
squares passed, which accepts any signature with the same byte sum, and
so did a plain == at the signature or the password check.
Diffstat (limited to 'tests/extensions')
| -rw-r--r-- | tests/extensions/test-auth.lua | 25 |
1 file changed, 25 insertions, 0 deletions
diff --git a/tests/extensions/test-auth.lua b/tests/extensions/test-auth.lua index 18017ff..6bd588d 100644 --- a/tests/extensions/test-auth.lua +++ b/tests/extensions/test-auth.lua @@ -231,6 +231,8 @@ h.check("and in linear time", os.clock() - started < 0.5) h.check("equal strings compare equal", constant_equals("abc", "abc")) h.check("differing strings do not", not constant_equals("abc", "abd")) +h.check("nor do strings whose byte differences cancel out", + not constant_equals("ab", "ba") and not constant_equals("ac", "bb")) h.check("differing lengths do not", not constant_equals("a", "ab")) h.check("non strings do not", not constant_equals(nil, "a")) @@ -468,6 +470,29 @@ h.equals("and grants a session that verifies", granted and validate_value("usern local expires = session_expiry(granted) h.check("which expires a week after the login", expires and expires >= before + 604800 and expires <= os.time() + 604800, tostring(expires)) + +-- A plain == at either comparison would leave every check above passing +-- while timing told a visitor how much of a guess was right. +local real_constant_equals = constant_equals +local compared = {} +constant_equals = function(a, b) + compared[#compared + 1] = { a, b } + return real_constant_equals(a, b) +end +local function was_compared(value) + for _, pair in ipairs(compared) do + if pair[1] == value or pair[2] == value then + return true + end + end + return false +end +visit("secret-repo", session) +h.check("a visit compares the signature in constant time", was_compared(session:match("[^|]+$"))) +compared = {} +login("Alice", password, way_back) +h.check("and a login the password's hash", was_compared(stored_hash)) +constant_equals = real_constant_equals h.equals("and logs nothing", h.error_log(), "") out = login("Alice", "wrong", way_back) |
