diff options
author | Florian Zeitz <florob@babelmonkeys.de> | 2013-04-28 02:28:42 +0200 |
---|---|---|
committer | Florian Zeitz <florob@babelmonkeys.de> | 2013-04-28 02:28:42 +0200 |
commit | a4390dda1d291b1ede374b28e7de5828ae71d204 (patch) | |
tree | 902b97c09c14427e90b5c8b1bf056d54f1650397 | |
parent | cb793c9eb157d3db69228fef171aa17e13af8e11 (diff) | |
download | prosody-a4390dda1d291b1ede374b28e7de5828ae71d204.tar.gz prosody-a4390dda1d291b1ede374b28e7de5828ae71d204.zip |
util.hashes, util.sasl.scram: Implement SCRAM-SHA1's Hi in C
-rw-r--r-- | util-src/hashes.c | 49 | ||||
-rw-r--r-- | util/sasl/scram.lua | 15 |
2 files changed, 51 insertions, 13 deletions
diff --git a/util-src/hashes.c b/util-src/hashes.c index 2a6625b3..8f7d7140 100644 --- a/util-src/hashes.c +++ b/util-src/hashes.c @@ -14,6 +14,8 @@ */ #include <string.h> +#include <stdlib.h> +#include <inttypes.h> #include "lua.h" #include "lauxlib.h" @@ -132,6 +134,52 @@ MAKE_HMAC_FUNCTION(Lhmac_sha256, SHA256, SHA256_DIGEST_LENGTH, SHA256_CTX) MAKE_HMAC_FUNCTION(Lhmac_sha512, SHA512, SHA512_DIGEST_LENGTH, SHA512_CTX) MAKE_HMAC_FUNCTION(Lhmac_md5, MD5, MD5_DIGEST_LENGTH, MD5_CTX) +static int LscramHi(lua_State *L) { + union xory { + unsigned char bytes[SHA_DIGEST_LENGTH]; + uint32_t quadbytes[SHA_DIGEST_LENGTH/4]; + }; + int i; + SHA_CTX ctx, ctxo; + unsigned char Ust[SHA_DIGEST_LENGTH]; + union xory Und; + union xory res; + size_t str_len, salt_len; + struct hash_desc desc; + const char *str = luaL_checklstring(L, 1, &str_len); + const char *salt = luaL_checklstring(L, 2, &salt_len); + char *salt2; + const int iter = luaL_checkinteger(L, 3); + + desc.Init = (int (*)(void*))SHA1_Init; + desc.Update = (int (*)(void*, const void *, size_t))SHA1_Update; + desc.Final = (int (*)(unsigned char*, void*))SHA1_Final; + desc.digestLength = SHA_DIGEST_LENGTH; + desc.ctx = &ctx; + desc.ctxo = &ctxo; + + salt2 = malloc(salt_len + 4); + if (salt2 == NULL) + luaL_error(L, "Out of memory in scramHi"); + memcpy(salt2, salt, salt_len); + memcpy(salt2 + salt_len, "\0\0\0\1", 4); + hmac(&desc, str, str_len, salt2, salt_len + 4, Ust); + free(salt2); + + memcpy(res.bytes, Ust, sizeof(res)); + for (i = 1; i < iter; i++) { + int j; + hmac(&desc, str, str_len, (char*)Ust, sizeof(Ust), Und.bytes); + for (j = 0; j < SHA_DIGEST_LENGTH/4; j++) + res.quadbytes[j] ^= Und.quadbytes[j]; + memcpy(Ust, Und.bytes, sizeof(Ust)); + } + + lua_pushlstring(L, (char*)res.bytes, SHA_DIGEST_LENGTH); + + return 1; +} + static const luaL_Reg Reg[] = { { "sha1", Lsha1 }, @@ -144,6 +192,7 @@ static const luaL_Reg Reg[] = { "hmac_sha256", Lhmac_sha256 }, { "hmac_sha512", Lhmac_sha512 }, { "hmac_md5", Lhmac_md5 }, + { "scram_Hi_sha1", LscramHi }, { NULL, NULL } }; diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 1ba12460..cf2f0ede 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -17,6 +17,7 @@ local string = string local base64 = require "util.encodings".base64; local hmac_sha1 = require "util.hashes".hmac_sha1; local sha1 = require "util.hashes".sha1; +local Hi = require "util.hashes".scram_Hi_sha1; local generate_uuid = require "util.uuid".generate; local saslprep = require "util.encodings".stringprep.saslprep; local nodeprep = require "util.encodings".stringprep.nodeprep; @@ -65,18 +66,6 @@ local function binaryXOR( a, b ) return t_concat(result); end --- hash algorithm independent Hi(PBKDF2) implementation -function Hi(hmac, str, salt, i) - local Ust = hmac(str, salt.."\0\0\0\1"); - local res = Ust; - for n=1,i-1 do - local Und = hmac(str, Ust) - res = binaryXOR(res, Und) - Ust = Und - end - return res -end - local function validate_username(username, _nodeprep) -- check for forbidden char sequences for eq in username:gmatch("=(.?.?)") do @@ -110,7 +99,7 @@ function getAuthenticationDatabaseSHA1(password, salt, iteration_count) if iteration_count < 4096 then log("warn", "Iteration count < 4096 which is the suggested minimum according to RFC 5802.") end - local salted_password = Hi(hmac_sha1, password, salt, iteration_count); + local salted_password = Hi(password, salt, iteration_count); local stored_key = sha1(hmac_sha1(salted_password, "Client Key")) local server_key = hmac_sha1(salted_password, "Server Key"); return true, stored_key, server_key |