suricata
util-lua-hashlib.c
Go to the documentation of this file.
1 /* Copyright (C) 2025 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * Hashing library for Lua.
22  *
23  * Usage:
24  *
25  * local hashing = require("suricata.hashing")
26  *
27  * -- One shot hash
28  * hash = hashing.sha256_digest("www.suricata.io")
29  *
30  * -- One shot hash to hex
31  * hash = hashing.sha256_hexdigest("www.suricata.io")
32  *
33  * -- Incremental hashing
34  * hasher = hashing.sha256()
35  * hasher:update("www.")
36  * hasher:update("suricata.io")
37  * hash = hasher:finalize()
38  *
39  * Support hashes: sha256, sha1, md5
40  */
41 
42 #include "util-lua-hashlib.h"
43 
44 #include "lauxlib.h"
45 #include "rust-bindings.h"
46 
47 #define SHA256_MT "suricata:hashlib:sha256"
48 #define SHA1_MT "suricata:hashlib:sha1"
49 #define MD5_MT "suricata:hashlib:md5"
50 
51 /**
52  * \brief Create a new SHA-256 hash instance.
53  */
54 static int LuaHashLibSha256New(lua_State *L)
55 {
56  struct SCSha256 **hasher = lua_newuserdata(L, sizeof(struct SCSha256 *));
57  if (hasher == NULL) {
58  return luaL_error(L, "failed to allocate userdata for sha256");
59  }
60  *hasher = SCSha256New();
61  luaL_getmetatable(L, SHA256_MT);
62  lua_setmetatable(L, -2);
63  return 1;
64 }
65 
66 /**
67  * \brief Add more data to an existing SHA-256 hash instance.
68  */
69 static int LuaHashLibSha256Update(lua_State *L)
70 {
71  struct SCSha256 **hasher = luaL_checkudata(L, 1, SHA256_MT);
72  if (hasher == NULL) {
73  return luaL_error(L, "null userdata");
74  }
75  size_t data_len;
76  const char *data = luaL_checklstring(L, 2, &data_len);
77  SCSha256Update(*hasher, (const uint8_t *)data, (uint32_t)data_len);
78  return 0;
79 }
80 
81 static int LuaHashLibSha256Finalize(lua_State *L)
82 {
83  struct SCSha256 **hasher = luaL_checkudata(L, 1, SHA256_MT);
84  if (hasher == NULL) {
85  return luaL_error(L, "null userdata");
86  }
87 
88  uint8_t hash[SC_SHA256_LEN];
89  SCSha256Finalize(*hasher, hash, sizeof(hash));
90  lua_pushlstring(L, (const char *)hash, sizeof(hash));
91 
92  // Finalize consumes the hasher, so set to NULL so its not free'd
93  // during garbage collection.
94  *hasher = NULL;
95 
96  return 1;
97 }
98 
99 static int LuaHashLibSha256FinalizeToHex(lua_State *L)
100 {
101  struct SCSha256 **hasher = luaL_checkudata(L, 1, SHA256_MT);
102  if (hasher == NULL) {
103  return luaL_error(L, "null userdata");
104  }
105 
106  char hash[SC_SHA256_HEX_LEN + 1];
107  if (!SCSha256FinalizeToHex(*hasher, hash, sizeof(hash))) {
108  *hasher = NULL;
109  return luaL_error(L, "sha256 hashing failed");
110  }
111 
112  lua_pushstring(L, (const char *)hash);
113 
114  // Finalize consumes the hasher, so set to NULL so its not free'd
115  // during garbage collection.
116  *hasher = NULL;
117 
118  return 1;
119 }
120 
121 static int LuaHashLibSha256Digest(lua_State *L)
122 {
123  size_t buf_len;
124  const char *input = luaL_checklstring(L, 1, &buf_len);
125 
126  uint8_t output[SC_SHA256_LEN];
127  if (!SCSha256HashBuffer((uint8_t *)input, (uint32_t)buf_len, output, SC_SHA256_LEN)) {
128  return luaL_error(L, "sha256 hashing failed");
129  }
130 
131  lua_pushlstring(L, (const char *)output, SC_SHA256_LEN);
132 
133  return 1;
134 }
135 
136 static int LuaHashLibSha256HexDigest(lua_State *L)
137 {
138  size_t buf_len;
139  const char *input = luaL_checklstring(L, 1, &buf_len);
140 
141  char output[SC_SHA256_HEX_LEN + 1];
142  if (!SCSha256HashBufferToHex((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
143  return luaL_error(L, "sha256 hashing failed");
144  }
145 
146  lua_pushstring(L, (const char *)output);
147  return 1;
148 }
149 
150 static int LuaHashLibSha256Gc(lua_State *L)
151 {
152  struct SCSha256 **hasher = luaL_checkudata(L, 1, SHA256_MT);
153  if (hasher && *hasher) {
154  SCSha256Free(*hasher);
155  }
156  return 0;
157 }
158 
159 static int LuaHashLibSha1New(lua_State *L)
160 {
161  struct SCSha1 **hasher = lua_newuserdata(L, sizeof(struct SCSha1 *));
162  if (hasher == NULL) {
163  return luaL_error(L, "failed to allocate userdata for sha1");
164  }
165  *hasher = SCSha1New();
166  luaL_getmetatable(L, SHA1_MT);
167  lua_setmetatable(L, -2);
168  return 1;
169 }
170 
171 static int LuaHashLibSha1Update(lua_State *L)
172 {
173  struct SCSha1 **hasher = luaL_checkudata(L, 1, SHA1_MT);
174  if (hasher == NULL) {
175  return luaL_error(L, "null userdata");
176  }
177 
178  size_t data_len;
179  const char *data = luaL_checklstring(L, 2, &data_len);
180  SCSha1Update(*hasher, (const uint8_t *)data, (uint32_t)data_len);
181  return 0;
182 }
183 
184 static int LuaHashLibSha1Finalize(lua_State *L)
185 {
186  struct SCSha1 **hasher = luaL_checkudata(L, 1, SHA1_MT);
187  if (hasher == NULL) {
188  return luaL_error(L, "null userdata");
189  }
190 
191  uint8_t hash[SC_SHA1_LEN];
192  SCSha1Finalize(*hasher, hash, sizeof(hash));
193  lua_pushlstring(L, (const char *)hash, sizeof(hash));
194 
195  // Finalize consumes the hasher, so set to NULL so its not free'd
196  // during garbage collection.
197  *hasher = NULL;
198 
199  return 1;
200 }
201 
202 static int LuaHashLibSha1FinalizeToHex(lua_State *L)
203 {
204  struct SCSha1 **hasher = luaL_checkudata(L, 1, SHA1_MT);
205  if (hasher == NULL) {
206  return luaL_error(L, "null userdata");
207  }
208 
209  char hash[SC_SHA1_HEX_LEN + 1];
210  if (!SCSha1FinalizeToHex(*hasher, hash, sizeof(hash))) {
211  *hasher = NULL;
212  return luaL_error(L, "sha1 hashing failed");
213  }
214 
215  lua_pushstring(L, (const char *)hash);
216 
217  // Finalize consumes the hasher, so set to NULL so its not free'd
218  // during garbage collection.
219  *hasher = NULL;
220 
221  return 1;
222 }
223 
224 static int LuaHashLibSha1Digest(lua_State *L)
225 {
226  size_t buf_len;
227  const char *input = luaL_checklstring(L, 1, &buf_len);
228 
229  uint8_t output[SC_SHA1_LEN];
230  if (!SCSha1HashBuffer((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
231  return luaL_error(L, "sha1 hashing failed");
232  }
233 
234  lua_pushlstring(L, (const char *)output, sizeof(output));
235  return 1;
236 }
237 
238 static int LuaHashLibSha1HexDigest(lua_State *L)
239 {
240  size_t buf_len;
241  const char *input = luaL_checklstring(L, 1, &buf_len);
242 
243  char output[SC_SHA1_HEX_LEN + 1];
244  if (!SCSha1HashBufferToHex((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
245  return luaL_error(L, "sha1 hashing failed");
246  }
247 
248  lua_pushstring(L, (const char *)output);
249  return 1;
250 }
251 
252 static int LuaHashLibSha1Gc(lua_State *L)
253 {
254  struct SCSha1 **hasher = luaL_checkudata(L, 1, SHA1_MT);
255  if (hasher && *hasher) {
256  SCSha1Free(*hasher);
257  }
258  return 0;
259 }
260 
261 static int LuaHashLibMd5New(lua_State *L)
262 {
263  struct SCMd5 **hasher = lua_newuserdata(L, sizeof(struct SCMd5 *));
264  if (hasher == NULL) {
265  return luaL_error(L, "failed to allocate userdata for sha1");
266  }
267  *hasher = SCMd5New();
268  luaL_getmetatable(L, MD5_MT);
269  lua_setmetatable(L, -2);
270  return 1;
271 }
272 
273 static int LuaHashLibMd5Update(lua_State *L)
274 {
275  struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
276  if (hasher == NULL) {
277  return luaL_error(L, "null userdata");
278  }
279 
280  size_t data_len;
281  const char *data = luaL_checklstring(L, 2, &data_len);
282  SCMd5Update(*hasher, (const uint8_t *)data, (uint32_t)data_len);
283  return 0;
284 }
285 
286 static int LuaHashLibMd5Finalize(lua_State *L)
287 {
288  struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
289  if (hasher == NULL) {
290  return luaL_error(L, "null userdata");
291  }
292 
293  uint8_t hash[SC_MD5_LEN];
294  SCMd5Finalize(*hasher, hash, sizeof(hash));
295  lua_pushlstring(L, (const char *)hash, sizeof(hash));
296 
297  // Finalize consumes the hasher, so set to NULL so its not free'd
298  // during garbage collection.
299  *hasher = NULL;
300 
301  return 1;
302 }
303 
304 static int LuaHashLibMd5FinalizeToHex(lua_State *L)
305 {
306  struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
307  if (hasher == NULL) {
308  return luaL_error(L, "null userdata");
309  }
310 
311  char hash[SC_MD5_HEX_LEN + 1];
312  if (!SCMd5FinalizeToHex(*hasher, hash, sizeof(hash))) {
313  *hasher = NULL;
314  return luaL_error(L, "md5 hashing failed");
315  }
316 
317  lua_pushstring(L, (const char *)hash);
318 
319  // Finalize consumes the hasher, so set to NULL so its not free'd
320  // during garbage collection.
321  *hasher = NULL;
322 
323  return 1;
324 }
325 
326 static int LuaHashLibMd5Digest(lua_State *L)
327 {
328  size_t buf_len;
329  const char *input = luaL_checklstring(L, 1, &buf_len);
330 
331  uint8_t output[SC_MD5_LEN];
332  if (!SCMd5HashBuffer((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
333  return luaL_error(L, "md5 hashing failed");
334  }
335 
336  lua_pushlstring(L, (const char *)output, sizeof(output));
337  return 1;
338 }
339 
340 static int LuaHashLibMd5HexDigest(lua_State *L)
341 {
342  size_t buf_len;
343  const char *input = luaL_checklstring(L, 1, &buf_len);
344 
345  char output[SC_MD5_HEX_LEN + 1];
346  if (!SCMd5HashBufferToHex((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
347  return luaL_error(L, "md5 hashing failed");
348  }
349 
350  lua_pushstring(L, (const char *)output);
351  return 1;
352 }
353 
354 static int LuaHashLibMd5Gc(lua_State *L)
355 {
356  struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
357  if (hasher && *hasher) {
358  SCMd5Free(*hasher);
359  }
360  return 0;
361 }
362 
363 static const struct luaL_Reg hashlib[] = {
364  // clang-format off
365  { "sha256_digest", LuaHashLibSha256Digest },
366  { "sha256_hexdigest", LuaHashLibSha256HexDigest },
367  { "sha256", LuaHashLibSha256New },
368  { "sha1_digest", LuaHashLibSha1Digest },
369  { "sha1_hexdigest", LuaHashLibSha1HexDigest },
370  { "sha1", LuaHashLibSha1New },
371  { "md5_digest", LuaHashLibMd5Digest },
372  { "md5_hexdigest", LuaHashLibMd5HexDigest },
373  { "md5", LuaHashLibMd5New },
374  { NULL, NULL },
375  // clang-format on
376 };
377 
378 static const struct luaL_Reg sha256_meta[] = {
379  // clang-format off
380  { "update", LuaHashLibSha256Update },
381  { "finalize", LuaHashLibSha256Finalize },
382  { "finalize_to_hex", LuaHashLibSha256FinalizeToHex },
383  { "__gc", LuaHashLibSha256Gc },
384  { NULL, NULL },
385  // clang-format on
386 };
387 
388 static const struct luaL_Reg sha1_meta[] = {
389  // clang-format off
390  { "update", LuaHashLibSha1Update },
391  { "finalize", LuaHashLibSha1Finalize },
392  { "finalize_to_hex", LuaHashLibSha1FinalizeToHex },
393  { "__gc", LuaHashLibSha1Gc },
394  { NULL, NULL },
395  // clang-format on
396 };
397 
398 static const struct luaL_Reg md5_meta[] = {
399  // clang-format off
400  { "update", LuaHashLibMd5Update },
401  { "finalize", LuaHashLibMd5Finalize },
402  { "finalize_to_hex", LuaHashLibMd5FinalizeToHex },
403  { "__gc", LuaHashLibMd5Gc },
404  { NULL, NULL },
405  // clang-format on
406 };
407 
409 {
410  luaL_newmetatable(L, SHA256_MT);
411  lua_pushvalue(L, -1);
412  lua_setfield(L, -2, "__index");
413  luaL_setfuncs(L, sha256_meta, 0);
414 
415  luaL_newmetatable(L, SHA1_MT);
416  lua_pushvalue(L, -1);
417  lua_setfield(L, -2, "__index");
418  luaL_setfuncs(L, sha1_meta, 0);
419 
420  luaL_newmetatable(L, MD5_MT);
421  lua_pushvalue(L, -1);
422  lua_setfield(L, -2, "__index");
423  luaL_setfuncs(L, md5_meta, 0);
424 
425  luaL_newlib(L, hashlib);
426 
427  return 1;
428 }
SCSha1
struct SCSha1 SCSha1
Definition: util-file.h:106
SC_SHA256_LEN
#define SC_SHA256_LEN
Definition: util-file.h:104
SC_SHA1_LEN
#define SC_SHA1_LEN
Definition: util-file.h:107
SCLuaLoadHashlib
int SCLuaLoadHashlib(lua_State *L)
Definition: util-lua-hashlib.c:408
util-lua-hashlib.h
SCSha256
struct SCSha256 SCSha256
Definition: util-file.h:103
lua_State
struct lua_State lua_State
Definition: suricata-common.h:523
MD5_MT
#define MD5_MT
Definition: util-lua-hashlib.c:49
SHA256_MT
#define SHA256_MT
Definition: util-lua-hashlib.c:47
SHA1_MT
#define SHA1_MT
Definition: util-lua-hashlib.c:48
SC_MD5_LEN
#define SC_MD5_LEN
Definition: util-file.h:110
SCMd5
struct SCMd5 SCMd5
Definition: util-file.h:109