mod_http: Use hostname from the correct context (thanks gryffus)
[prosody.git] / util-src / hashes.c
index 57f90781e767762b6142985b7b2123fba3e324eb..33041e83bdb8929f3673d860a408a3e89b22c064 100644 (file)
-/*\r
-* xxpath.c\r
-* An implementation of a subset of xpath for Lua 5.1\r
-* Waqas Hussain <waqas20@gmail.com>\r
-* 05 Oct 2008 15:28:15\r
-*/\r
-\r
-#include <string.h>\r
-\r
-#include "lua.h"\r
-#include "lauxlib.h"\r
-#include <openssl/sha.h>\r
-#include <openssl/md5.h>\r
-\r
-/*//typedef unsigned int uint32;\r
-#define uint32 unsigned int\r
-\r
-#define chrsz 8\r
-#define hexcase 0\r
-\r
-uint32 safe_add(uint32 x, uint32 y) {\r
-       uint32 lsw = (x & 0xFFFF) + (y & 0xFFFF);\r
-       uint32 msw = (x >> 16) + (y >> 16) + (lsw >> 16);\r
-       return (msw << 16) | (lsw & 0xFFFF);\r
-}\r
-\r
-uint32 S (uint32 X, uint32 n) { return ( X >> n ) | (X << (32 - n)); }\r
-uint32 R (uint32 X, uint32 n) { return ( X >> n ); }\r
-uint32 Ch(uint32 x, uint32 y, uint32 z) { return ((x & y) ^ ((~x) & z)); }\r
-uint32 Maj(uint32 x, uint32 y, uint32 z) { return ((x & y) ^ (x & z) ^ (y & z)); }\r
-uint32 Sigma0256(uint32 x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }\r
-uint32 Sigma1256(uint32 x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }\r
-uint32 Gamma0256(uint32 x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }\r
-uint32 Gamma1256(uint32 x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }\r
-\r
-static const uint32 K[64] = {0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2};\r
-\r
-void core_sha256 (char* m, uint32 l, uint32 m_length, uint32 out[8]) {\r
-\r
-       uint32 HASH[8] = {0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19};\r
-       uint32 W[64];\r
-       uint32 a, b, c, d, e, f, g, h, i, j;\r
-       uint32 T1, T2;\r
-       //uint32 i, j;\r
-       printf("core_sha256: start\n");\r
-\r
-       m[l >> 5] |= 0x80 << (24 - l % 32);\r
-       m[((l + 64 >> 9) << 4) + 15] = l;\r
-\r
-       printf("core_sha256: 1\n");\r
-       for ( i = 0; i<m_length; i+=16 ) {\r
-               a = HASH[0];\r
-               b = HASH[1];\r
-               c = HASH[2];\r
-               d = HASH[3];\r
-               e = HASH[4];\r
-               f = HASH[5];\r
-               g = HASH[6];\r
-               h = HASH[7];\r
-\r
-               for ( j = 0; j<64; j++) {\r
-                       if (j < 16) W[j] = m[j + i];\r
-                       else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);\r
-\r
-                       T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);\r
-                       T2 = safe_add(Sigma0256(a), Maj(a, b, c));\r
-\r
-                       h = g;\r
-                       g = f;\r
-                       f = e;\r
-                       e = safe_add(d, T1);\r
-                       d = c;\r
-                       c = b;\r
-                       b = a;\r
-                       a = safe_add(T1, T2);\r
-               }\r
-\r
-               HASH[0] = safe_add(a, HASH[0]);\r
-               HASH[1] = safe_add(b, HASH[1]);\r
-               HASH[2] = safe_add(c, HASH[2]);\r
-               HASH[3] = safe_add(d, HASH[3]);\r
-               HASH[4] = safe_add(e, HASH[4]);\r
-               HASH[5] = safe_add(f, HASH[5]);\r
-               HASH[6] = safe_add(g, HASH[6]);\r
-               HASH[7] = safe_add(h, HASH[7]);\r
-       }\r
-       printf("core_sha256: 2\n");\r
-\r
-       out[0] = HASH[0];\r
-       out[1] = HASH[1];\r
-       out[2] = HASH[2];\r
-       out[3] = HASH[3];\r
-       out[4] = HASH[4];\r
-       out[5] = HASH[5];\r
-       out[6] = HASH[6];\r
-       out[7] = HASH[7];\r
-\r
-       printf("core_sha256: end\n");\r
-}\r
-\r
-void binb2hex (const uint32 binarray[8], char str[65]) {\r
-       const char* hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";\r
-       uint32 pos = 0;\r
-       int i;\r
-       printf("binb2hex: start\n");\r
-       //var str = "";\r
-       for(i = 0; i < 8 * 4; i++) {\r
-               str[pos++] = hex_tab[(binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF];\r
-               str[pos++] = hex_tab[(binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF];\r
-       }\r
-       //return str;\r
-       str[64] = 0;\r
-       printf("binb2hex: end\n");\r
-}\r
-\r
-static void sha256(const char* s, uint32 s_length, char output[65]) {\r
-       uint32 hash[8];\r
-       char* copy;\r
-\r
-       printf("sha256: start\n");\r
-       \r
-       copy = (char*) malloc(s_length + 1);\r
-       strcpy(copy, s);\r
-       core_sha256(copy, s_length * chrsz, s_length, hash);\r
-       free(copy);\r
-\r
-       binb2hex(hash, output);\r
-\r
-       printf("sha256: end\n");\r
-\r
-\r
-\r
-    //s = Utf8Encode(s);\r
-    //return binb2hex(core_sha256(str2binb(s), s.length * chrsz));\r
-\r
-}\r
-*/\r
-\r
-//static int Lsha256(lua_State *L)             /** sha256(s) */\r
-/*{\r
-       size_t l;\r
-       const char *s = luaL_checklstring(L, 1, &l);\r
-       int len = strlen(s);\r
-       char hash[32];\r
-       char result[65];\r
-       \r
-       //sha256(s, len, hash);\r
-       SHA256(s, len, hash);\r
-       toHex(hash, 32, result);\r
-       \r
-       //printf("input: %s, length: %d, outlen: %d\n", s, len, strlen(result));\r
-\r
-       lua_pushstring(L, result);\r
-       return 1;\r
-}*/\r
-\r
-\r
-const char* hex_tab = "0123456789abcdef";\r
-void toHex(const char* in, int length, char* out) {\r
-       int i;\r
-       for (i = 0; i < length; i++) {\r
-               out[i*2] = hex_tab[(in[i] >> 4) & 0xF];\r
-               out[i*2+1] = hex_tab[(in[i]) & 0xF];\r
-       }\r
-       //out[i*2] = 0;\r
-}\r
-\r
-#define MAKE_HASH_FUNCTION(myFunc, func, size) \\r
-static int myFunc(lua_State *L) { \\r
-       size_t len; \\r
-       const char *s = luaL_checklstring(L, 1, &len); \\r
-       int hex_out = lua_toboolean(L, 2); \\r
-       char hash[size]; \\r
-       char result[size*2]; \\r
-       func(s, len, hash); \\r
-       if (hex_out) { \\r
-               toHex(hash, size, result); \\r
-               lua_pushlstring(L, result, size*2); \\r
-       } else { \\r
-               lua_pushlstring(L, hash, size);\\r
-       } \\r
-       return 1; \\r
-}\r
-\r
-MAKE_HASH_FUNCTION(Lsha1, SHA1, 20)\r
-MAKE_HASH_FUNCTION(Lsha256, SHA256, 32)\r
-MAKE_HASH_FUNCTION(Lmd5, MD5, 16)\r
-\r
-static const luaL_Reg Reg[] =\r
-{\r
-       { "sha1",       Lsha1   },\r
-       { "sha256",     Lsha256 },\r
-       { "md5",        Lmd5    },\r
-       { NULL,         NULL    }\r
-};\r
-\r
-LUALIB_API int luaopen_hashes(lua_State *L)\r
-{\r
-       luaL_register(L, "hashes", Reg);\r
-       lua_pushliteral(L, "version");                  /** version */\r
-       lua_pushliteral(L, "-3.14");\r
-       lua_settable(L,-3);\r
-       return 1;\r
-}\r
+/* Prosody IM
+-- Copyright (C) 2009-2010 Matthew Wild
+-- Copyright (C) 2009-2010 Waqas Hussain
+-- 
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
+--
+*/
+
+
+/*
+* hashes.c
+* Lua library for sha1, sha256 and md5 hashes
+*/
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+typedef unsigned __int32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#include "lua.h"
+#include "lauxlib.h"
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+
+#define HMAC_IPAD 0x36363636
+#define HMAC_OPAD 0x5c5c5c5c
+
+const char *hex_tab = "0123456789abcdef";
+void toHex(const unsigned char *in, int length, unsigned char *out) {
+       int i;
+       for (i = 0; i < length; i++) {
+               out[i*2] = hex_tab[(in[i] >> 4) & 0xF];
+               out[i*2+1] = hex_tab[(in[i]) & 0xF];
+       }
+}
+
+#define MAKE_HASH_FUNCTION(myFunc, func, size) \
+static int myFunc(lua_State *L) { \
+       size_t len; \
+       const char *s = luaL_checklstring(L, 1, &len); \
+       int hex_out = lua_toboolean(L, 2); \
+       unsigned char hash[size], result[size*2]; \
+       func((const unsigned char*)s, len, hash);  \
+       if (hex_out) { \
+               toHex(hash, size, result); \
+               lua_pushlstring(L, (char*)result, size*2); \
+       } else { \
+               lua_pushlstring(L, (char*)hash, size);\
+       } \
+       return 1; \
+}
+
+MAKE_HASH_FUNCTION(Lsha1, SHA1, SHA_DIGEST_LENGTH)
+MAKE_HASH_FUNCTION(Lsha224, SHA224, SHA224_DIGEST_LENGTH)
+MAKE_HASH_FUNCTION(Lsha256, SHA256, SHA256_DIGEST_LENGTH)
+MAKE_HASH_FUNCTION(Lsha384, SHA384, SHA384_DIGEST_LENGTH)
+MAKE_HASH_FUNCTION(Lsha512, SHA512, SHA512_DIGEST_LENGTH)
+MAKE_HASH_FUNCTION(Lmd5, MD5, MD5_DIGEST_LENGTH)
+
+struct hash_desc {
+       int (*Init)(void*);
+       int (*Update)(void*, const void *, size_t);
+       int (*Final)(unsigned char*, void*);
+       size_t digestLength;
+       void *ctx, *ctxo;
+};
+
+static void hmac(struct hash_desc *desc, const char *key, size_t key_len,
+    const char *msg, size_t msg_len, unsigned char *result)
+{
+       union xory {
+               unsigned char bytes[64];
+               uint32_t quadbytes[16];
+       };
+
+       int i;
+       unsigned char hashedKey[64]; /* Maximum used digest length */
+       union xory k_ipad, k_opad;
+
+       if (key_len > 64) {
+               desc->Init(desc->ctx);
+               desc->Update(desc->ctx, key, key_len);
+               desc->Final(hashedKey, desc->ctx);
+               key = (const char*)hashedKey;
+               key_len = desc->digestLength;
+       }
+
+       memcpy(k_ipad.bytes, key, key_len);
+       memset(k_ipad.bytes + key_len, 0, 64 - key_len);
+       memcpy(k_opad.bytes, k_ipad.bytes, 64);
+
+       for (i = 0; i < 16; i++) {
+               k_ipad.quadbytes[i] ^= HMAC_IPAD;
+               k_opad.quadbytes[i] ^= HMAC_OPAD;
+       }
+
+       desc->Init(desc->ctx);
+       desc->Update(desc->ctx, k_ipad.bytes, 64);
+       desc->Init(desc->ctxo);
+       desc->Update(desc->ctxo, k_opad.bytes, 64);
+       desc->Update(desc->ctx, msg, msg_len);
+       desc->Final(result, desc->ctx);
+       desc->Update(desc->ctxo, result, desc->digestLength);
+       desc->Final(result, desc->ctxo);
+}
+
+#define MAKE_HMAC_FUNCTION(myFunc, func, size, type) \
+static int myFunc(lua_State *L) { \
+       type ctx, ctxo; \
+       unsigned char hash[size], result[2*size]; \
+       size_t key_len, msg_len; \
+       const char *key = luaL_checklstring(L, 1, &key_len); \
+       const char *msg = luaL_checklstring(L, 2, &msg_len); \
+       const int hex_out = lua_toboolean(L, 3); \
+       struct hash_desc desc; \
+       desc.Init = (int (*)(void*))func##_Init; \
+       desc.Update = (int (*)(void*, const void *, size_t))func##_Update; \
+       desc.Final = (int (*)(unsigned char*, void*))func##_Final; \
+       desc.digestLength = size; \
+       desc.ctx = &ctx; \
+       desc.ctxo = &ctxo; \
+       hmac(&desc, key, key_len, msg, msg_len, hash); \
+       if (hex_out) { \
+               toHex(hash, size, result); \
+               lua_pushlstring(L, (char*)result, size*2); \
+       } else { \
+               lua_pushlstring(L, (char*)hash, size); \
+       } \
+       return 1; \
+}
+
+MAKE_HMAC_FUNCTION(Lhmac_sha1, SHA1, SHA_DIGEST_LENGTH, SHA_CTX)
+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           },
+       { "sha224",             Lsha224         },
+       { "sha256",             Lsha256         },
+       { "sha384",             Lsha384         },
+       { "sha512",             Lsha512         },
+       { "md5",                Lmd5            },
+       { "hmac_sha1",          Lhmac_sha1      },
+       { "hmac_sha256",        Lhmac_sha256    },
+       { "hmac_sha512",        Lhmac_sha512    },
+       { "hmac_md5",           Lhmac_md5       },
+       { "scram_Hi_sha1",      LscramHi        },
+       { NULL,                 NULL            }
+};
+
+LUALIB_API int luaopen_util_hashes(lua_State *L)
+{
+       luaL_register(L, "hashes", Reg);
+       lua_pushliteral(L, "version");                  /** version */
+       lua_pushliteral(L, "-3.14");
+       lua_settable(L,-3);
+       return 1;
+}