Comparison

util-src/hashes.c @ 5537:15464633d8fb

util.hmac, util.hashes: Implement HMAC functions in C, and move to util.hashes
author Florian Zeitz <florob@babelmonkeys.de>
date Sat, 27 Apr 2013 17:01:31 +0200
parent 4829:0ebc636faa59
child 5538:62089c9c142d
comparison
equal deleted inserted replaced
5531:483f795f6f99 5537:15464633d8fb
18 #include "lua.h" 18 #include "lua.h"
19 #include "lauxlib.h" 19 #include "lauxlib.h"
20 #include <openssl/sha.h> 20 #include <openssl/sha.h>
21 #include <openssl/md5.h> 21 #include <openssl/md5.h>
22 22
23 const char* hex_tab = "0123456789abcdef"; 23 #define HMAC_IPAD 0x36363636
24 void toHex(const char* in, int length, char* out) { 24 #define HMAC_OPAD 0x5c5c5c5c
25
26 const char *hex_tab = "0123456789abcdef";
27 void toHex(const unsigned char *in, int length, unsigned char *out) {
25 int i; 28 int i;
26 for (i = 0; i < length; i++) { 29 for (i = 0; i < length; i++) {
27 out[i*2] = hex_tab[(in[i] >> 4) & 0xF]; 30 out[i*2] = hex_tab[(in[i] >> 4) & 0xF];
28 out[i*2+1] = hex_tab[(in[i]) & 0xF]; 31 out[i*2+1] = hex_tab[(in[i]) & 0xF];
29 } 32 }
32 #define MAKE_HASH_FUNCTION(myFunc, func, size) \ 35 #define MAKE_HASH_FUNCTION(myFunc, func, size) \
33 static int myFunc(lua_State *L) { \ 36 static int myFunc(lua_State *L) { \
34 size_t len; \ 37 size_t len; \
35 const char *s = luaL_checklstring(L, 1, &len); \ 38 const char *s = luaL_checklstring(L, 1, &len); \
36 int hex_out = lua_toboolean(L, 2); \ 39 int hex_out = lua_toboolean(L, 2); \
37 char hash[size]; \ 40 unsigned char hash[size], result[size*2]; \
38 char result[size*2]; \ 41 func((const unsigned char*)s, len, hash); \
39 func((const unsigned char*)s, len, (unsigned char*)hash); \
40 if (hex_out) { \ 42 if (hex_out) { \
41 toHex(hash, size, result); \ 43 toHex(hash, size, result); \
42 lua_pushlstring(L, result, size*2); \ 44 lua_pushlstring(L, (char*)result, size*2); \
43 } else { \ 45 } else { \
44 lua_pushlstring(L, hash, size);\ 46 lua_pushlstring(L, (char*)hash, size);\
45 } \ 47 } \
46 return 1; \ 48 return 1; \
47 } 49 }
48 50
49 MAKE_HASH_FUNCTION(Lsha1, SHA1, SHA_DIGEST_LENGTH) 51 MAKE_HASH_FUNCTION(Lsha1, SHA1, SHA_DIGEST_LENGTH)
51 MAKE_HASH_FUNCTION(Lsha256, SHA256, SHA256_DIGEST_LENGTH) 53 MAKE_HASH_FUNCTION(Lsha256, SHA256, SHA256_DIGEST_LENGTH)
52 MAKE_HASH_FUNCTION(Lsha384, SHA384, SHA384_DIGEST_LENGTH) 54 MAKE_HASH_FUNCTION(Lsha384, SHA384, SHA384_DIGEST_LENGTH)
53 MAKE_HASH_FUNCTION(Lsha512, SHA512, SHA512_DIGEST_LENGTH) 55 MAKE_HASH_FUNCTION(Lsha512, SHA512, SHA512_DIGEST_LENGTH)
54 MAKE_HASH_FUNCTION(Lmd5, MD5, MD5_DIGEST_LENGTH) 56 MAKE_HASH_FUNCTION(Lmd5, MD5, MD5_DIGEST_LENGTH)
55 57
58 struct hash_desc {
59 int (*Init)(void*);
60 int (*Update)(void*, const void *, size_t);
61 int (*Final)(unsigned char*, void*);
62 size_t digestLength;
63 void *ctx, *ctxo;
64 };
65
66 static void hmac(struct hash_desc *desc, const char *key, size_t key_len,
67 const char *msg, size_t msg_len, unsigned char *result)
68 {
69 union xory {
70 unsigned char bytes[64];
71 uint32_t quadbytes[16];
72 };
73
74 int i;
75 char hashedKey[64]; /* Maximum used digest length */
76 union xory k_ipad, k_opad;
77
78 if (key_len > 64) {
79 desc->Init(desc->ctx);
80 desc->Update(desc->ctx, key, key_len);
81 desc->Final(desc->ctx, hashedKey);
82 key = (const char*)hashedKey;
83 key_len = desc->digestLength;
84 }
85
86 memcpy(k_ipad.bytes, key, key_len);
87 memset(k_ipad.bytes + key_len, 0, 64 - key_len);
88 memcpy(k_opad.bytes, k_ipad.bytes, 64);
89
90 for (i = 0; i < 16; i++) {
91 k_ipad.quadbytes[i] ^= HMAC_IPAD;
92 k_opad.quadbytes[i] ^= HMAC_OPAD;
93 }
94
95 desc->Init(desc->ctx);
96 desc->Update(desc->ctx, k_ipad.bytes, 64);
97 desc->Init(desc->ctxo);
98 desc->Update(desc->ctxo, k_opad.bytes, 64);
99 desc->Update(desc->ctx, msg, msg_len);
100 desc->Final(result, desc->ctx);
101 desc->Update(desc->ctxo, result, desc->digestLength);
102 desc->Final(result, desc->ctxo);
103 }
104
105 #define MAKE_HMAC_FUNCTION(myFunc, func, size, type) \
106 static int myFunc(lua_State *L) { \
107 type ctx, ctxo; \
108 unsigned char hash[size], result[2*size]; \
109 size_t key_len, msg_len; \
110 const char *key = luaL_checklstring(L, 1, &key_len); \
111 const char *msg = luaL_checklstring(L, 2, &msg_len); \
112 const int hex_out = lua_toboolean(L, 3); \
113 struct hash_desc desc; \
114 desc.Init = (int (*)(void*))func##_Init; \
115 desc.Update = (int (*)(void*, const void *, size_t))func##_Update; \
116 desc.Final = (int (*)(unsigned char*, void*))func##_Final; \
117 desc.digestLength = size; \
118 desc.ctx = &ctx; \
119 desc.ctxo = &ctxo; \
120 hmac(&desc, key, key_len, msg, msg_len, hash); \
121 if (hex_out) { \
122 toHex(hash, size, result); \
123 lua_pushlstring(L, (char*)result, size*2); \
124 } else { \
125 lua_pushlstring(L, (char*)hash, size); \
126 } \
127 return 1; \
128 }
129
130 MAKE_HMAC_FUNCTION(Lhmac_sha1, SHA1, SHA_DIGEST_LENGTH, SHA_CTX)
131 MAKE_HMAC_FUNCTION(Lhmac_sha256, SHA256, SHA256_DIGEST_LENGTH, SHA256_CTX)
132 MAKE_HMAC_FUNCTION(Lhmac_sha512, SHA512, SHA512_DIGEST_LENGTH, SHA512_CTX)
133 MAKE_HMAC_FUNCTION(Lhmac_md5, MD5, MD5_DIGEST_LENGTH, MD5_CTX)
134
56 static const luaL_Reg Reg[] = 135 static const luaL_Reg Reg[] =
57 { 136 {
58 { "sha1", Lsha1 }, 137 { "sha1", Lsha1 },
59 { "sha224", Lsha224 }, 138 { "sha224", Lsha224 },
60 { "sha256", Lsha256 }, 139 { "sha256", Lsha256 },
61 { "sha384", Lsha384 }, 140 { "sha384", Lsha384 },
62 { "sha512", Lsha512 }, 141 { "sha512", Lsha512 },
63 { "md5", Lmd5 }, 142 { "md5", Lmd5 },
64 { NULL, NULL } 143 { "hmac_sha1", Lhmac_sha1 },
144 { "hmac_sha256", Lhmac_sha256 },
145 { "hmac_sha512", Lhmac_sha512 },
146 { "hmac_md5", Lhmac_md5 },
147 { NULL, NULL }
65 }; 148 };
66 149
67 LUALIB_API int luaopen_util_hashes(lua_State *L) 150 LUALIB_API int luaopen_util_hashes(lua_State *L)
68 { 151 {
69 luaL_register(L, "hashes", Reg); 152 luaL_register(L, "hashes", Reg);