doap: Add XEP-0288
[prosody.git] / util-src / hashes.c
blob4c48b26f32733ed1f2743362a5892332aa66428a
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 */
11 * hashes.c
12 * Lua library for sha1, sha256 and md5 hashes
15 #include <string.h>
16 #include <stdlib.h>
18 #ifdef _MSC_VER
19 typedef unsigned __int32 uint32_t;
20 #else
21 #include <inttypes.h>
22 #endif
24 #include "lua.h"
25 #include "lauxlib.h"
26 #include <openssl/sha.h>
27 #include <openssl/md5.h>
28 #include <openssl/hmac.h>
29 #include <openssl/evp.h>
31 #if (LUA_VERSION_NUM == 501)
32 #define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R)
33 #endif
35 #define HMAC_IPAD 0x36363636
36 #define HMAC_OPAD 0x5c5c5c5c
38 const char *hex_tab = "0123456789abcdef";
39 void toHex(const unsigned char *in, int length, unsigned char *out) {
40 int i;
42 for(i = 0; i < length; i++) {
43 out[i * 2] = hex_tab[(in[i] >> 4) & 0xF];
44 out[i * 2 + 1] = hex_tab[(in[i]) & 0xF];
48 #define MAKE_HASH_FUNCTION(myFunc, func, size) \
49 static int myFunc(lua_State *L) { \
50 size_t len; \
51 const char *s = luaL_checklstring(L, 1, &len); \
52 int hex_out = lua_toboolean(L, 2); \
53 unsigned char hash[size], result[size*2]; \
54 func((const unsigned char*)s, len, hash); \
55 if (hex_out) { \
56 toHex(hash, size, result); \
57 lua_pushlstring(L, (char*)result, size*2); \
58 } else { \
59 lua_pushlstring(L, (char*)hash, size);\
60 } \
61 return 1; \
64 MAKE_HASH_FUNCTION(Lsha1, SHA1, SHA_DIGEST_LENGTH)
65 MAKE_HASH_FUNCTION(Lsha224, SHA224, SHA224_DIGEST_LENGTH)
66 MAKE_HASH_FUNCTION(Lsha256, SHA256, SHA256_DIGEST_LENGTH)
67 MAKE_HASH_FUNCTION(Lsha384, SHA384, SHA384_DIGEST_LENGTH)
68 MAKE_HASH_FUNCTION(Lsha512, SHA512, SHA512_DIGEST_LENGTH)
69 MAKE_HASH_FUNCTION(Lmd5, MD5, MD5_DIGEST_LENGTH)
71 struct hash_desc {
72 int (*Init)(void *);
73 int (*Update)(void *, const void *, size_t);
74 int (*Final)(unsigned char *, void *);
75 size_t digestLength;
76 void *ctx, *ctxo;
79 #define MAKE_HMAC_FUNCTION(myFunc, evp, size, type) \
80 static int myFunc(lua_State *L) { \
81 unsigned char hash[size], result[2*size]; \
82 size_t key_len, msg_len; \
83 unsigned int out_len; \
84 const char *key = luaL_checklstring(L, 1, &key_len); \
85 const char *msg = luaL_checklstring(L, 2, &msg_len); \
86 const int hex_out = lua_toboolean(L, 3); \
87 HMAC(evp(), key, key_len, (const unsigned char*)msg, msg_len, (unsigned char*)hash, &out_len); \
88 if (hex_out) { \
89 toHex(hash, out_len, result); \
90 lua_pushlstring(L, (char*)result, out_len*2); \
91 } else { \
92 lua_pushlstring(L, (char*)hash, out_len); \
93 } \
94 return 1; \
97 MAKE_HMAC_FUNCTION(Lhmac_sha1, EVP_sha1, SHA_DIGEST_LENGTH, SHA_CTX)
98 MAKE_HMAC_FUNCTION(Lhmac_sha256, EVP_sha256, SHA256_DIGEST_LENGTH, SHA256_CTX)
99 MAKE_HMAC_FUNCTION(Lhmac_sha512, EVP_sha512, SHA512_DIGEST_LENGTH, SHA512_CTX)
100 MAKE_HMAC_FUNCTION(Lhmac_md5, EVP_md5, MD5_DIGEST_LENGTH, MD5_CTX)
102 static int Lpbkdf2_sha1(lua_State *L) {
103 unsigned char out[SHA_DIGEST_LENGTH];
105 size_t pass_len, salt_len;
106 const char *pass = luaL_checklstring(L, 1, &pass_len);
107 const unsigned char *salt = (unsigned char *)luaL_checklstring(L, 2, &salt_len);
108 const int iter = luaL_checkinteger(L, 3);
110 if(PKCS5_PBKDF2_HMAC(pass, pass_len, salt, salt_len, iter, EVP_sha1(), SHA_DIGEST_LENGTH, out) == 0) {
111 return luaL_error(L, "PKCS5_PBKDF2_HMAC() failed");
114 lua_pushlstring(L, (char *)out, SHA_DIGEST_LENGTH);
116 return 1;
120 static int Lpbkdf2_sha256(lua_State *L) {
121 unsigned char out[SHA256_DIGEST_LENGTH];
123 size_t pass_len, salt_len;
124 const char *pass = luaL_checklstring(L, 1, &pass_len);
125 const unsigned char *salt = (unsigned char *)luaL_checklstring(L, 2, &salt_len);
126 const int iter = luaL_checkinteger(L, 3);
128 if(PKCS5_PBKDF2_HMAC(pass, pass_len, salt, salt_len, iter, EVP_sha256(), SHA256_DIGEST_LENGTH, out) == 0) {
129 return luaL_error(L, "PKCS5_PBKDF2_HMAC() failed");
132 lua_pushlstring(L, (char *)out, SHA_DIGEST_LENGTH);
133 return 1;
136 static const luaL_Reg Reg[] = {
137 { "sha1", Lsha1 },
138 { "sha224", Lsha224 },
139 { "sha256", Lsha256 },
140 { "sha384", Lsha384 },
141 { "sha512", Lsha512 },
142 { "md5", Lmd5 },
143 { "hmac_sha1", Lhmac_sha1 },
144 { "hmac_sha256", Lhmac_sha256 },
145 { "hmac_sha512", Lhmac_sha512 },
146 { "hmac_md5", Lhmac_md5 },
147 { "scram_Hi_sha1", Lpbkdf2_sha1 }, /* COMPAT */
148 { "pbkdf2_hmac_sha1", Lpbkdf2_sha1 },
149 { "pbkdf2_hmac_sha256", Lpbkdf2_sha256 },
150 { NULL, NULL }
153 LUALIB_API int luaopen_util_hashes(lua_State *L) {
154 #if (LUA_VERSION_NUM > 501)
155 luaL_checkversion(L);
156 #endif
157 lua_newtable(L);
158 luaL_setfuncs(L, Reg, 0);
159 lua_pushliteral(L, "-3.14");
160 lua_setfield(L, -2, "version");
161 return 1;