• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/util-lua-hashlib.c
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

UNCOV
47
#define SHA256_MT "suricata:hashlib:sha256"
×
UNCOV
48
#define SHA1_MT   "suricata:hashlib:sha1"
×
UNCOV
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)
UNCOV
55
{
×
UNCOV
56
    struct SCSha256 **hasher = lua_newuserdata(L, sizeof(struct SCSha256 *));
×
UNCOV
57
    if (hasher == NULL) {
×
58
        return luaL_error(L, "failed to allocate userdata for sha256");
×
59
    }
×
UNCOV
60
    *hasher = SCSha256New();
×
UNCOV
61
    luaL_getmetatable(L, SHA256_MT);
×
UNCOV
62
    lua_setmetatable(L, -2);
×
UNCOV
63
    return 1;
×
UNCOV
64
}
×
65

66
/**
67
 * \brief Add more data to an existing SHA-256 hash instance.
68
 */
69
static int LuaHashLibSha256Update(lua_State *L)
UNCOV
70
{
×
UNCOV
71
    struct SCSha256 **hasher = luaL_checkudata(L, 1, SHA256_MT);
×
UNCOV
72
    if (hasher == NULL) {
×
73
        return luaL_error(L, "null userdata");
×
74
    }
×
UNCOV
75
    size_t data_len;
×
UNCOV
76
    const char *data = luaL_checklstring(L, 2, &data_len);
×
UNCOV
77
    SCSha256Update(*hasher, (const uint8_t *)data, (uint32_t)data_len);
×
UNCOV
78
    return 0;
×
UNCOV
79
}
×
80

81
static int LuaHashLibSha256Finalize(lua_State *L)
UNCOV
82
{
×
UNCOV
83
    struct SCSha256 **hasher = luaL_checkudata(L, 1, SHA256_MT);
×
UNCOV
84
    if (hasher == NULL) {
×
85
        return luaL_error(L, "null userdata");
×
86
    }
×
87

UNCOV
88
    uint8_t hash[SC_SHA256_LEN];
×
UNCOV
89
    SCSha256Finalize(*hasher, hash, sizeof(hash));
×
UNCOV
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.
UNCOV
94
    *hasher = NULL;
×
95

UNCOV
96
    return 1;
×
UNCOV
97
}
×
98

99
static int LuaHashLibSha256FinalizeToHex(lua_State *L)
UNCOV
100
{
×
UNCOV
101
    struct SCSha256 **hasher = luaL_checkudata(L, 1, SHA256_MT);
×
UNCOV
102
    if (hasher == NULL) {
×
103
        return luaL_error(L, "null userdata");
×
104
    }
×
105

UNCOV
106
    char hash[SC_SHA256_HEX_LEN + 1];
×
UNCOV
107
    if (!SCSha256FinalizeToHex(*hasher, hash, sizeof(hash))) {
×
108
        *hasher = NULL;
×
109
        return luaL_error(L, "sha256 hashing failed");
×
110
    }
×
111

UNCOV
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.
UNCOV
116
    *hasher = NULL;
×
117

UNCOV
118
    return 1;
×
UNCOV
119
}
×
120

121
static int LuaHashLibSha256Digest(lua_State *L)
UNCOV
122
{
×
UNCOV
123
    size_t buf_len;
×
UNCOV
124
    const char *input = luaL_checklstring(L, 1, &buf_len);
×
125

UNCOV
126
    uint8_t output[SC_SHA256_LEN];
×
UNCOV
127
    if (!SCSha256HashBuffer((uint8_t *)input, (uint32_t)buf_len, output, SC_SHA256_LEN)) {
×
128
        return luaL_error(L, "sha256 hashing failed");
×
129
    }
×
130

UNCOV
131
    lua_pushlstring(L, (const char *)output, SC_SHA256_LEN);
×
132

UNCOV
133
    return 1;
×
UNCOV
134
}
×
135

136
static int LuaHashLibSha256HexDigest(lua_State *L)
UNCOV
137
{
×
UNCOV
138
    size_t buf_len;
×
UNCOV
139
    const char *input = luaL_checklstring(L, 1, &buf_len);
×
140

UNCOV
141
    char output[SC_SHA256_HEX_LEN + 1];
×
UNCOV
142
    if (!SCSha256HashBufferToHex((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
×
143
        return luaL_error(L, "sha256 hashing failed");
×
144
    }
×
145

UNCOV
146
    lua_pushstring(L, (const char *)output);
×
UNCOV
147
    return 1;
×
UNCOV
148
}
×
149

150
static int LuaHashLibSha256Gc(lua_State *L)
UNCOV
151
{
×
UNCOV
152
    struct SCSha256 **hasher = luaL_checkudata(L, 1, SHA256_MT);
×
UNCOV
153
    if (hasher && *hasher) {
×
154
        SCSha256Free(*hasher);
×
155
    }
×
UNCOV
156
    return 0;
×
UNCOV
157
}
×
158

159
static int LuaHashLibSha1New(lua_State *L)
UNCOV
160
{
×
UNCOV
161
    struct SCSha1 **hasher = lua_newuserdata(L, sizeof(struct SCSha1 *));
×
UNCOV
162
    if (hasher == NULL) {
×
163
        return luaL_error(L, "failed to allocate userdata for sha1");
×
164
    }
×
UNCOV
165
    *hasher = SCSha1New();
×
UNCOV
166
    luaL_getmetatable(L, SHA1_MT);
×
UNCOV
167
    lua_setmetatable(L, -2);
×
UNCOV
168
    return 1;
×
UNCOV
169
}
×
170

171
static int LuaHashLibSha1Update(lua_State *L)
UNCOV
172
{
×
UNCOV
173
    struct SCSha1 **hasher = luaL_checkudata(L, 1, SHA1_MT);
×
UNCOV
174
    if (hasher == NULL) {
×
175
        return luaL_error(L, "null userdata");
×
176
    }
×
177

UNCOV
178
    size_t data_len;
×
UNCOV
179
    const char *data = luaL_checklstring(L, 2, &data_len);
×
UNCOV
180
    SCSha1Update(*hasher, (const uint8_t *)data, (uint32_t)data_len);
×
UNCOV
181
    return 0;
×
UNCOV
182
}
×
183

184
static int LuaHashLibSha1Finalize(lua_State *L)
UNCOV
185
{
×
UNCOV
186
    struct SCSha1 **hasher = luaL_checkudata(L, 1, SHA1_MT);
×
UNCOV
187
    if (hasher == NULL) {
×
188
        return luaL_error(L, "null userdata");
×
189
    }
×
190

UNCOV
191
    uint8_t hash[SC_SHA1_LEN];
×
UNCOV
192
    SCSha1Finalize(*hasher, hash, sizeof(hash));
×
UNCOV
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.
UNCOV
197
    *hasher = NULL;
×
198

UNCOV
199
    return 1;
×
UNCOV
200
}
×
201

202
static int LuaHashLibSha1FinalizeToHex(lua_State *L)
UNCOV
203
{
×
UNCOV
204
    struct SCSha1 **hasher = luaL_checkudata(L, 1, SHA1_MT);
×
UNCOV
205
    if (hasher == NULL) {
×
206
        return luaL_error(L, "null userdata");
×
207
    }
×
208

UNCOV
209
    char hash[SC_SHA1_HEX_LEN + 1];
×
UNCOV
210
    if (!SCSha1FinalizeToHex(*hasher, hash, sizeof(hash))) {
×
211
        *hasher = NULL;
×
212
        return luaL_error(L, "sha1 hashing failed");
×
213
    }
×
214

UNCOV
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.
UNCOV
219
    *hasher = NULL;
×
220

UNCOV
221
    return 1;
×
UNCOV
222
}
×
223

224
static int LuaHashLibSha1Digest(lua_State *L)
UNCOV
225
{
×
UNCOV
226
    size_t buf_len;
×
UNCOV
227
    const char *input = luaL_checklstring(L, 1, &buf_len);
×
228

UNCOV
229
    uint8_t output[SC_SHA1_LEN];
×
UNCOV
230
    if (!SCSha1HashBuffer((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
×
231
        return luaL_error(L, "sha1 hashing failed");
×
232
    }
×
233

UNCOV
234
    lua_pushlstring(L, (const char *)output, sizeof(output));
×
UNCOV
235
    return 1;
×
UNCOV
236
}
×
237

238
static int LuaHashLibSha1HexDigest(lua_State *L)
UNCOV
239
{
×
UNCOV
240
    size_t buf_len;
×
UNCOV
241
    const char *input = luaL_checklstring(L, 1, &buf_len);
×
242

UNCOV
243
    char output[SC_SHA1_HEX_LEN + 1];
×
UNCOV
244
    if (!SCSha1HashBufferToHex((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
×
245
        return luaL_error(L, "sha1 hashing failed");
×
246
    }
×
247

UNCOV
248
    lua_pushstring(L, (const char *)output);
×
UNCOV
249
    return 1;
×
UNCOV
250
}
×
251

252
static int LuaHashLibSha1Gc(lua_State *L)
UNCOV
253
{
×
UNCOV
254
    struct SCSha1 **hasher = luaL_checkudata(L, 1, SHA1_MT);
×
UNCOV
255
    if (hasher && *hasher) {
×
256
        SCSha1Free(*hasher);
×
257
    }
×
UNCOV
258
    return 0;
×
UNCOV
259
}
×
260

261
static int LuaHashLibMd5New(lua_State *L)
UNCOV
262
{
×
UNCOV
263
    struct SCMd5 **hasher = lua_newuserdata(L, sizeof(struct SCMd5 *));
×
UNCOV
264
    if (hasher == NULL) {
×
265
        return luaL_error(L, "failed to allocate userdata for sha1");
×
266
    }
×
UNCOV
267
    *hasher = SCMd5New();
×
UNCOV
268
    luaL_getmetatable(L, MD5_MT);
×
UNCOV
269
    lua_setmetatable(L, -2);
×
UNCOV
270
    return 1;
×
UNCOV
271
}
×
272

273
static int LuaHashLibMd5Update(lua_State *L)
UNCOV
274
{
×
UNCOV
275
    struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
×
UNCOV
276
    if (hasher == NULL) {
×
277
        return luaL_error(L, "null userdata");
×
278
    }
×
279

UNCOV
280
    size_t data_len;
×
UNCOV
281
    const char *data = luaL_checklstring(L, 2, &data_len);
×
UNCOV
282
    SCMd5Update(*hasher, (const uint8_t *)data, (uint32_t)data_len);
×
UNCOV
283
    return 0;
×
UNCOV
284
}
×
285

286
static int LuaHashLibMd5Finalize(lua_State *L)
UNCOV
287
{
×
UNCOV
288
    struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
×
UNCOV
289
    if (hasher == NULL) {
×
290
        return luaL_error(L, "null userdata");
×
291
    }
×
292

UNCOV
293
    uint8_t hash[SC_MD5_LEN];
×
UNCOV
294
    SCMd5Finalize(*hasher, hash, sizeof(hash));
×
UNCOV
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.
UNCOV
299
    *hasher = NULL;
×
300

UNCOV
301
    return 1;
×
UNCOV
302
}
×
303

304
static int LuaHashLibMd5FinalizeToHex(lua_State *L)
UNCOV
305
{
×
UNCOV
306
    struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
×
UNCOV
307
    if (hasher == NULL) {
×
308
        return luaL_error(L, "null userdata");
×
309
    }
×
310

UNCOV
311
    char hash[SC_MD5_HEX_LEN + 1];
×
UNCOV
312
    if (!SCMd5FinalizeToHex(*hasher, hash, sizeof(hash))) {
×
313
        *hasher = NULL;
×
314
        return luaL_error(L, "md5 hashing failed");
×
315
    }
×
316

UNCOV
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.
UNCOV
321
    *hasher = NULL;
×
322

UNCOV
323
    return 1;
×
UNCOV
324
}
×
325

326
static int LuaHashLibMd5Digest(lua_State *L)
UNCOV
327
{
×
UNCOV
328
    size_t buf_len;
×
UNCOV
329
    const char *input = luaL_checklstring(L, 1, &buf_len);
×
330

UNCOV
331
    uint8_t output[SC_MD5_LEN];
×
UNCOV
332
    if (!SCMd5HashBuffer((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
×
333
        return luaL_error(L, "md5 hashing failed");
×
334
    }
×
335

UNCOV
336
    lua_pushlstring(L, (const char *)output, sizeof(output));
×
UNCOV
337
    return 1;
×
UNCOV
338
}
×
339

340
static int LuaHashLibMd5HexDigest(lua_State *L)
UNCOV
341
{
×
UNCOV
342
    size_t buf_len;
×
UNCOV
343
    const char *input = luaL_checklstring(L, 1, &buf_len);
×
344

UNCOV
345
    char output[SC_MD5_HEX_LEN + 1];
×
UNCOV
346
    if (!SCMd5HashBufferToHex((uint8_t *)input, (uint32_t)buf_len, output, sizeof(output))) {
×
347
        return luaL_error(L, "md5 hashing failed");
×
348
    }
×
349

UNCOV
350
    lua_pushstring(L, (const char *)output);
×
UNCOV
351
    return 1;
×
UNCOV
352
}
×
353

354
static int LuaHashLibMd5Gc(lua_State *L)
UNCOV
355
{
×
UNCOV
356
    struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
×
UNCOV
357
    if (hasher && *hasher) {
×
358
        SCMd5Free(*hasher);
×
359
    }
×
UNCOV
360
    return 0;
×
UNCOV
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

408
int SCLuaLoadHashlib(lua_State *L)
UNCOV
409
{
×
UNCOV
410
    luaL_newmetatable(L, SHA256_MT);
×
UNCOV
411
    lua_pushvalue(L, -1);
×
UNCOV
412
    lua_setfield(L, -2, "__index");
×
UNCOV
413
    luaL_setfuncs(L, sha256_meta, 0);
×
414

UNCOV
415
    luaL_newmetatable(L, SHA1_MT);
×
UNCOV
416
    lua_pushvalue(L, -1);
×
UNCOV
417
    lua_setfield(L, -2, "__index");
×
UNCOV
418
    luaL_setfuncs(L, sha1_meta, 0);
×
419

UNCOV
420
    luaL_newmetatable(L, MD5_MT);
×
UNCOV
421
    lua_pushvalue(L, -1);
×
UNCOV
422
    lua_setfield(L, -2, "__index");
×
UNCOV
423
    luaL_setfuncs(L, md5_meta, 0);
×
424

UNCOV
425
    luaL_newlib(L, hashlib);
×
426

UNCOV
427
    return 1;
×
UNCOV
428
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc