Merge s2s branch
[prosody.git] / util-src / hashes.c
1 /* Prosody IM
2 -- Copyright (C) 2009-2010 Matthew Wild
3 -- Copyright (C) 2009-2010 Waqas Hussain
4 -- 
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8 */
9
10
11 /*
12 * hashes.c
13 * Lua library for sha1, sha256 and md5 hashes
14 */
15
16 #include <string.h>
17 #include <stdlib.h>
18 #include <inttypes.h>
19
20 #include "lua.h"
21 #include "lauxlib.h"
22 #include <openssl/sha.h>
23 #include <openssl/md5.h>
24
25 #define HMAC_IPAD 0x36363636
26 #define HMAC_OPAD 0x5c5c5c5c
27
28 const char *hex_tab = "0123456789abcdef";
29 void toHex(const unsigned char *in, int length, unsigned char *out) {
30         int i;
31         for (i = 0; i < length; i++) {
32                 out[i*2] = hex_tab[(in[i] >> 4) & 0xF];
33                 out[i*2+1] = hex_tab[(in[i]) & 0xF];
34         }
35 }
36
37 #define MAKE_HASH_FUNCTION(myFunc, func, size) \
38 static int myFunc(lua_State *L) { \
39         size_t len; \
40         const char *s = luaL_checklstring(L, 1, &len); \
41         int hex_out = lua_toboolean(L, 2); \
42         unsigned char hash[size], result[size*2]; \
43         func((const unsigned char*)s, len, hash);  \
44         if (hex_out) { \
45                 toHex(hash, size, result); \
46                 lua_pushlstring(L, (char*)result, size*2); \
47         } else { \
48                 lua_pushlstring(L, (char*)hash, size);\
49         } \
50         return 1; \
51 }
52
53 MAKE_HASH_FUNCTION(Lsha1, SHA1, SHA_DIGEST_LENGTH)
54 MAKE_HASH_FUNCTION(Lsha224, SHA224, SHA224_DIGEST_LENGTH)
55 MAKE_HASH_FUNCTION(Lsha256, SHA256, SHA256_DIGEST_LENGTH)
56 MAKE_HASH_FUNCTION(Lsha384, SHA384, SHA384_DIGEST_LENGTH)
57 MAKE_HASH_FUNCTION(Lsha512, SHA512, SHA512_DIGEST_LENGTH)
58 MAKE_HASH_FUNCTION(Lmd5, MD5, MD5_DIGEST_LENGTH)
59
60 struct hash_desc {
61         int (*Init)(void*);
62         int (*Update)(void*, const void *, size_t);
63         int (*Final)(unsigned char*, void*);
64         size_t digestLength;
65         void *ctx, *ctxo;
66 };
67
68 static void hmac(struct hash_desc *desc, const char *key, size_t key_len,
69     const char *msg, size_t msg_len, unsigned char *result)
70 {
71         union xory {
72                 unsigned char bytes[64];
73                 uint32_t quadbytes[16];
74         };
75
76         int i;
77         char hashedKey[64]; /* Maximum used digest length */
78         union xory k_ipad, k_opad;
79
80         if (key_len > 64) {
81                 desc->Init(desc->ctx);
82                 desc->Update(desc->ctx, key, key_len);
83                 desc->Final(desc->ctx, hashedKey);
84                 key = (const char*)hashedKey;
85                 key_len = desc->digestLength;
86         }
87
88         memcpy(k_ipad.bytes, key, key_len);
89         memset(k_ipad.bytes + key_len, 0, 64 - key_len);
90         memcpy(k_opad.bytes, k_ipad.bytes, 64);
91
92         for (i = 0; i < 16; i++) {
93                 k_ipad.quadbytes[i] ^= HMAC_IPAD;
94                 k_opad.quadbytes[i] ^= HMAC_OPAD;
95         }
96
97         desc->Init(desc->ctx);
98         desc->Update(desc->ctx, k_ipad.bytes, 64);
99         desc->Init(desc->ctxo);
100         desc->Update(desc->ctxo, k_opad.bytes, 64);
101         desc->Update(desc->ctx, msg, msg_len);
102         desc->Final(result, desc->ctx);
103         desc->Update(desc->ctxo, result, desc->digestLength);
104         desc->Final(result, desc->ctxo);
105 }
106
107 #define MAKE_HMAC_FUNCTION(myFunc, func, size, type) \
108 static int myFunc(lua_State *L) { \
109         type ctx, ctxo; \
110         unsigned char hash[size], result[2*size]; \
111         size_t key_len, msg_len; \
112         const char *key = luaL_checklstring(L, 1, &key_len); \
113         const char *msg = luaL_checklstring(L, 2, &msg_len); \
114         const int hex_out = lua_toboolean(L, 3); \
115         struct hash_desc desc; \
116         desc.Init = (int (*)(void*))func##_Init; \
117         desc.Update = (int (*)(void*, const void *, size_t))func##_Update; \
118         desc.Final = (int (*)(unsigned char*, void*))func##_Final; \
119         desc.digestLength = size; \
120         desc.ctx = &ctx; \
121         desc.ctxo = &ctxo; \
122         hmac(&desc, key, key_len, msg, msg_len, hash); \
123         if (hex_out) { \
124                 toHex(hash, size, result); \
125                 lua_pushlstring(L, (char*)result, size*2); \
126         } else { \
127                 lua_pushlstring(L, (char*)hash, size); \
128         } \
129         return 1; \
130 }
131
132 MAKE_HMAC_FUNCTION(Lhmac_sha1, SHA1, SHA_DIGEST_LENGTH, SHA_CTX)
133 MAKE_HMAC_FUNCTION(Lhmac_sha256, SHA256, SHA256_DIGEST_LENGTH, SHA256_CTX)
134 MAKE_HMAC_FUNCTION(Lhmac_sha512, SHA512, SHA512_DIGEST_LENGTH, SHA512_CTX)
135 MAKE_HMAC_FUNCTION(Lhmac_md5, MD5, MD5_DIGEST_LENGTH, MD5_CTX)
136
137 static int LscramHi(lua_State *L) {
138         union xory {
139                 unsigned char bytes[SHA_DIGEST_LENGTH];
140                 uint32_t quadbytes[SHA_DIGEST_LENGTH/4];
141         };
142         int i;
143         SHA_CTX ctx, ctxo;
144         unsigned char Ust[SHA_DIGEST_LENGTH];
145         union xory Und;
146         union xory res;
147         size_t str_len, salt_len;
148         struct hash_desc desc;
149         const char *str = luaL_checklstring(L, 1, &str_len);
150         const char *salt = luaL_checklstring(L, 2, &salt_len);
151         char *salt2;
152         const int iter = luaL_checkinteger(L, 3);
153
154         desc.Init = (int (*)(void*))SHA1_Init;
155         desc.Update = (int (*)(void*, const void *, size_t))SHA1_Update;
156         desc.Final = (int (*)(unsigned char*, void*))SHA1_Final;
157         desc.digestLength = SHA_DIGEST_LENGTH;
158         desc.ctx = &ctx;
159         desc.ctxo = &ctxo;
160
161         salt2 = malloc(salt_len + 4);
162         if (salt2 == NULL)
163                 luaL_error(L, "Out of memory in scramHi");
164         memcpy(salt2, salt, salt_len);
165         memcpy(salt2 + salt_len, "\0\0\0\1", 4);
166         hmac(&desc, str, str_len, salt2, salt_len + 4, Ust);
167         free(salt2);
168
169         memcpy(res.bytes, Ust, sizeof(res));
170         for (i = 1; i < iter; i++) {
171                 int j;
172                 hmac(&desc, str, str_len, (char*)Ust, sizeof(Ust), Und.bytes);
173                 for (j = 0; j < SHA_DIGEST_LENGTH/4; j++)
174                         res.quadbytes[j] ^= Und.quadbytes[j];
175                 memcpy(Ust, Und.bytes, sizeof(Ust));
176         }
177
178         lua_pushlstring(L, (char*)res.bytes, SHA_DIGEST_LENGTH);
179
180         return 1;
181 }
182
183 static const luaL_Reg Reg[] =
184 {
185         { "sha1",               Lsha1           },
186         { "sha224",             Lsha224         },
187         { "sha256",             Lsha256         },
188         { "sha384",             Lsha384         },
189         { "sha512",             Lsha512         },
190         { "md5",                Lmd5            },
191         { "hmac_sha1",          Lhmac_sha1      },
192         { "hmac_sha256",        Lhmac_sha256    },
193         { "hmac_sha512",        Lhmac_sha512    },
194         { "hmac_md5",           Lhmac_md5       },
195         { "scram_Hi_sha1",      LscramHi        },
196         { NULL,                 NULL            }
197 };
198
199 LUALIB_API int luaopen_util_hashes(lua_State *L)
200 {
201         luaL_register(L, "hashes", Reg);
202         lua_pushliteral(L, "version");                  /** version */
203         lua_pushliteral(L, "-3.14");
204         lua_settable(L,-3);
205         return 1;
206 }