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

jasonish / suricata / 22802647571

07 Mar 2026 04:23PM UTC coverage: 75.827% (-3.4%) from 79.233%
22802647571

push

github

jasonish
github-ci: add schema ordering check for yaml schema

253365 of 334137 relevant lines covered (75.83%)

3384729.69 hits per line

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

78.3
/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

47
#define SHA256_MT "suricata:hashlib:sha256"
68✔
48
#define SHA1_MT   "suricata:hashlib:sha1"
68✔
49
#define MD5_MT    "suricata:hashlib:md5"
68✔
50

51
/**
52
 * \brief Create a new SHA-256 hash instance.
53
 */
54
static int LuaHashLibSha256New(lua_State *L)
55
{
2✔
56
    struct SCSha256 **hasher = lua_newuserdata(L, sizeof(struct SCSha256 *));
2✔
57
    if (hasher == NULL) {
2✔
58
        return luaL_error(L, "failed to allocate userdata for sha256");
×
59
    }
×
60
    *hasher = SCSha256New();
2✔
61
    luaL_getmetatable(L, SHA256_MT);
2✔
62
    lua_setmetatable(L, -2);
2✔
63
    return 1;
2✔
64
}
2✔
65

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

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

88
    uint8_t hash[SC_SHA256_LEN];
1✔
89
    SCSha256Finalize(*hasher, hash, sizeof(hash));
1✔
90
    lua_pushlstring(L, (const char *)hash, sizeof(hash));
1✔
91

92
    // Finalize consumes the hasher, so set to NULL so its not free'd
93
    // during garbage collection.
94
    *hasher = NULL;
1✔
95

96
    return 1;
1✔
97
}
1✔
98

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

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

112
    lua_pushstring(L, (const char *)hash);
1✔
113

114
    // Finalize consumes the hasher, so set to NULL so its not free'd
115
    // during garbage collection.
116
    *hasher = NULL;
1✔
117

118
    return 1;
1✔
119
}
1✔
120

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

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

131
    lua_pushlstring(L, (const char *)output, SC_SHA256_LEN);
2✔
132

133
    return 1;
2✔
134
}
2✔
135

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

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

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

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

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

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

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

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

191
    uint8_t hash[SC_SHA1_LEN];
1✔
192
    SCSha1Finalize(*hasher, hash, sizeof(hash));
1✔
193
    lua_pushlstring(L, (const char *)hash, sizeof(hash));
1✔
194

195
    // Finalize consumes the hasher, so set to NULL so its not free'd
196
    // during garbage collection.
197
    *hasher = NULL;
1✔
198

199
    return 1;
1✔
200
}
1✔
201

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

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

215
    lua_pushstring(L, (const char *)hash);
1✔
216

217
    // Finalize consumes the hasher, so set to NULL so its not free'd
218
    // during garbage collection.
219
    *hasher = NULL;
1✔
220

221
    return 1;
1✔
222
}
1✔
223

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

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

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

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

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

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

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

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

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

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

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

293
    uint8_t hash[SC_MD5_LEN];
1✔
294
    SCMd5Finalize(*hasher, hash, sizeof(hash));
1✔
295
    lua_pushlstring(L, (const char *)hash, sizeof(hash));
1✔
296

297
    // Finalize consumes the hasher, so set to NULL so its not free'd
298
    // during garbage collection.
299
    *hasher = NULL;
1✔
300

301
    return 1;
1✔
302
}
1✔
303

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

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

317
    lua_pushstring(L, (const char *)hash);
1✔
318

319
    // Finalize consumes the hasher, so set to NULL so its not free'd
320
    // during garbage collection.
321
    *hasher = NULL;
1✔
322

323
    return 1;
1✔
324
}
1✔
325

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

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

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

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

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

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

354
static int LuaHashLibMd5Gc(lua_State *L)
355
{
2✔
356
    struct SCMd5 **hasher = luaL_checkudata(L, 1, MD5_MT);
2✔
357
    if (hasher && *hasher) {
2✔
358
        SCMd5Free(*hasher);
×
359
    }
×
360
    return 0;
2✔
361
}
2✔
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)
409
{
58✔
410
    luaL_newmetatable(L, SHA256_MT);
58✔
411
    lua_pushvalue(L, -1);
58✔
412
    lua_setfield(L, -2, "__index");
58✔
413
    luaL_setfuncs(L, sha256_meta, 0);
58✔
414

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

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

425
    luaL_newlib(L, hashlib);
58✔
426

427
    return 1;
58✔
428
}
58✔
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