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

zhaozg / lua-openssl / 19224094960

10 Nov 2025 07:31AM UTC coverage: 93.551% (+0.001%) from 93.55%
19224094960

Pull #369

travis-ci

Copilot
Add security summary for error handling optimization work

- Created SECURITY_SUMMARY.md documenting all findings and fixes
- All security checks passed: AddressSanitizer (0 leaks), CodeQL (0 alerts)
- 3 memory leaks fixed in digest.c and hmac.c
- 188 tests passing (177 existing + 11 new)
- Comprehensive documentation added for contributors

Co-authored-by: zhaozg <542599+zhaozg@users.noreply.github.com>
Pull Request #369: Fix memory leaks in digest and HMAC error paths

0 of 2 new or added lines in 1 file covered. (0.0%)

2 existing lines in 1 file now uncovered.

10242 of 10948 relevant lines covered (93.55%)

2111.45 hits per line

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

94.25
/src/digest.c
1
/***
2
digest module perform digest operations base on OpenSSL EVP API.
3

4
@module digest
5
@usage
6
  digest = require('openssl').digest
7
*/
8
#include "openssl.h"
9
#include "private.h"
10
#if defined(LIBRESSL_VERSION_NUMBER)
11
#include <openssl/engine.h>
12
#endif
13

14
/***
15
list all support digest algs
16

17
@function list
18
@tparam[opt] boolean alias include alias names for digest alg, default true
19
@treturn[table] all methods
20
*/
21
static int openssl_digest_list(lua_State *L)
12✔
22
{
23
  int aliases = lua_isnone(L, 1) ? 1 : lua_toboolean(L, 1);
12✔
24
  lua_newtable(L);
12✔
25
  OBJ_NAME_do_all_sorted(
12✔
26
    OBJ_NAME_TYPE_MD_METH, aliases ? openssl_add_method_or_alias : openssl_add_method, L);
27
  return 1;
12✔
28
};
29

30
/***
31
get evp_digest object
32

33
@function get
34
@tparam string|integer|asn1_object alg name, nid or object identity
35
@treturn evp_digest digest object mapping EVP_MD in openssl
36

37
@see evp_digest
38
*/
39
static int openssl_digest_get(lua_State *L)
58✔
40
{
41
  const EVP_MD *md = get_digest(L, 1, NULL);
58✔
42

43
  PUSH_OBJECT((void *)md, "openssl.evp_digest");
58✔
44
  return 1;
58✔
45
}
46

47
/***
48
get evp_digest_ctx object
49

50
@function new
51
@tparam string|integer|asn1_object alg name, nid or object identity
52
@treturn evp_digest_ctx digest object mapping EVP_MD_CTX in openssl
53

54
@see evp_digest_ctx
55
*/
56
static int openssl_digest_new(lua_State *L)
510✔
57
{
58
  const EVP_MD *md = get_digest(L, 1, NULL);
510✔
59
  int           ret = 0;
106✔
60
  ENGINE       *e = lua_isnoneornil(L, 2) ? NULL : CHECK_OBJECT(2, ENGINE, "openssl.engine");
106✔
61
  EVP_MD_CTX   *ctx = EVP_MD_CTX_new();
102✔
62
  if (ctx) {
102✔
63
    lua_pushlightuserdata(L, e);
102✔
64
    lua_rawsetp(L, LUA_REGISTRYINDEX, ctx);
102✔
65
    ret = EVP_DigestInit_ex(ctx, md, e);
102✔
66
    if (ret == 1) {
102✔
67
      PUSH_OBJECT(ctx, "openssl.evp_digest_ctx");
102✔
68
    } else {
69
      EVP_MD_CTX_free(ctx);
×
70
      ret = openssl_pushresult(L, ret);
×
71
    }
72
  }
73
  return ret;
102✔
74
}
75

76
/***
77
quick method to generate digest result
78

79
@function digest
80
@tparam string|integer|asn1_object alg name, nid or object identity
81
@tparam string msg to compute digest
82
@tparam[opt] boolean raw binary result return if set true, or hex encoded string default
83
@treturn string digest result value
84
*/
85
static int openssl_digest(lua_State *L)
52✔
86
{
87
  const EVP_MD *md;
88
  ENGINE       *eng;
89
  size_t        inl;
90
  const char   *in;
91
  unsigned char buf[EVP_MAX_MD_SIZE];
92
  unsigned int  blen = sizeof(buf);
52✔
93
  int           raw, ret;
94

95
  md = get_digest(L, 1, NULL);
52✔
96
  in = luaL_checklstring(L, 2, &inl);
52✔
97
  raw = (lua_isnone(L, 3)) ? 0 : lua_toboolean(L, 3);
52✔
98
  eng = (lua_isnoneornil(L, 4) ? 0 : CHECK_OBJECT(4, ENGINE, "openssl.engine"));
52✔
99

100
  ret = EVP_Digest(in, inl, buf, &blen, md, eng);
52✔
101
  if (ret == 1) {
52✔
102
    if (raw)
52✔
103
      lua_pushlstring(L, (const char *)buf, blen);
44✔
104
    else {
105
      char hex[2 * EVP_MAX_MD_SIZE + 1];
106
      to_hex((const char *)buf, blen, hex);
8✔
107
      lua_pushstring(L, hex);
8✔
108
    }
109
  }
110
  return ret == 1 ? 1 : openssl_pushresult(L, ret);
52✔
111
};
112

113
/***
114
create digest object for sign
115

116
@function signInit
117
@tparam string|integer|asn1_object alg name, nid or object identity
118
@tparam[opt=nil] engine object
119
@treturn evp_digest_ctx
120
*/
121
static int openssl_signInit(lua_State *L)
26✔
122
{
123
  const EVP_MD *md = lua_isnil(L, 1) ? NULL : get_digest(L, 1, NULL);
26✔
124
  EVP_PKEY     *pkey = CHECK_OBJECT(2, EVP_PKEY, "openssl.evp_pkey");
26✔
125
  ENGINE       *e = lua_gettop(L) > 2 ? CHECK_OBJECT(3, ENGINE, "openssl.engine") : NULL;
22✔
126
  EVP_MD_CTX   *ctx = EVP_MD_CTX_new();
22✔
127
  int           ret = 0;
22✔
128

129
  if (ctx) {
22✔
130
    ret = EVP_DigestSignInit(ctx, NULL, md, e, pkey);
22✔
131
    if (ret == 1) {
22✔
132
      PUSH_OBJECT(ctx, "openssl.evp_digest_ctx");
22✔
133
    } else {
NEW
134
      EVP_MD_CTX_free(ctx);
×
UNCOV
135
      ret = openssl_pushresult(L, ret);
×
136
    }
137
  }
138
  return ret;
22✔
139
}
140

141
/***
142
create digest object for verify
143

144
@function verifyInit
145
@tparam string|integer|asn1_object alg name, nid or object identity
146
@tparam[opt=nil] engine object
147
@treturn evp_digest_ctx
148
*/
149
static int openssl_verifyInit(lua_State *L)
26✔
150
{
151
  const EVP_MD *md = lua_isnil(L, 1) ? NULL : get_digest(L, 1, NULL);
26✔
152
  EVP_PKEY     *pkey = CHECK_OBJECT(2, EVP_PKEY, "openssl.evp_pkey");
26✔
153
  ENGINE       *e = lua_gettop(L) > 2 ? CHECK_OBJECT(3, ENGINE, "openssl.engine") : NULL;
22✔
154
  EVP_PKEY_CTX *pctx = 0;
22✔
155
  EVP_MD_CTX   *ctx = EVP_MD_CTX_new();
22✔
156
  int           ret = 0;
22✔
157

158
  if (ctx) {
22✔
159
    ret = EVP_DigestVerifyInit(ctx, &pctx, md, e, pkey);
22✔
160
    if (ret) {
22✔
161
      PUSH_OBJECT(ctx, "openssl.evp_digest_ctx");
22✔
162
    } else {
NEW
163
      EVP_MD_CTX_free(ctx);
×
UNCOV
164
      ret = openssl_pushresult(L, ret);
×
165
    }
166
  }
167
  return ret;
22✔
168
}
169

170
/***
171
openssl.evp_digest object
172
@type evp_digest
173
*/
174

175
/***
176
compute msg digest result
177

178
@function digest
179
@tparam string msg data to digest
180
@tparam[opt] engine, eng
181
@treturn string result a binary hash value for msg
182
*/
183
static int openssl_digest_digest(lua_State *L)
10✔
184
{
185
  size_t      inl;
186
  EVP_MD     *md = CHECK_OBJECT(1, EVP_MD, "openssl.evp_digest");
10✔
187
  const char *in = luaL_checklstring(L, 2, &inl);
10✔
188
  ENGINE     *e = lua_isnoneornil(L, 3) ? NULL : CHECK_OBJECT(3, ENGINE, "openssl.engine");
6✔
189

190
  char         buf[EVP_MAX_MD_SIZE];
191
  unsigned int blen = EVP_MAX_MD_SIZE;
6✔
192

193
  int ret = EVP_Digest(in, inl, (unsigned char *)buf, &blen, md, e);
6✔
194
  if (ret == 1) {
6✔
195
    lua_pushlstring(L, buf, blen);
6✔
196
  } else
197
    ret = openssl_pushresult(L, ret);
×
198

199
  return ret;
6✔
200
}
201

202
/***
203
get infomation of evp_digest object
204

205
@function info
206
@treturn table info keys include nid,name size,block_size,pkey_type,flags
207
*/
208
static int openssl_digest_info(lua_State *L)
4✔
209
{
210
  EVP_MD *md = CHECK_OBJECT(1, EVP_MD, "openssl.evp_digest");
4✔
211
  lua_newtable(L);
4✔
212
  AUXILIAR_SET(L, -1, "nid", EVP_MD_nid(md), integer);
4✔
213
  AUXILIAR_SET(L, -1, "name", EVP_MD_name(md), string);
4✔
214
  AUXILIAR_SET(L, -1, "size", EVP_MD_size(md), integer);
4✔
215
  AUXILIAR_SET(L, -1, "block_size", EVP_MD_block_size(md), integer);
4✔
216

217
  AUXILIAR_SET(L, -1, "pkey_type", EVP_MD_pkey_type(md), integer);
4✔
218
  AUXILIAR_SET(L, -1, "flags", EVP_MD_type(md), integer);
4✔
219
  return 1;
4✔
220
}
221

222
/***
223
initialize digest context with message digest
224
@function init
225
@tparam evp_digest md message digest algorithm
226
@tparam[opt] engine, eng
227
@treturn evp_digest_ctx ctx
228
@see evp_digest_ctx
229
*/
230
static int openssl_evp_digest_init(lua_State *L)
4✔
231
{
232
  EVP_MD *md = CHECK_OBJECT(1, EVP_MD, "openssl.evp_digest");
4✔
233
  ENGINE *e = lua_isnoneornil(L, 2) ? NULL : CHECK_OBJECT(2, ENGINE, "openssl.engine");
4✔
234
  int     ret = 0;
4✔
235

236
  EVP_MD_CTX *ctx = EVP_MD_CTX_new();
4✔
237
  if (ctx) {
4✔
238
    ret = EVP_DigestInit_ex(ctx, md, e);
4✔
239
    if (ret == 1) {
4✔
240
      PUSH_OBJECT(ctx, "openssl.evp_digest_ctx");
4✔
241
    } else {
242
      EVP_MD_CTX_free(ctx);
×
243
      ret = openssl_pushresult(L, ret);
×
244
    }
245
  }
246
  return ret;
4✔
247
}
248

249
/***
250
create digest object for sign
251

252
@function signInit
253
@tparam[opt=nil] engine object
254
@treturn evp_digest_ctx
255
*/
256

257
/***
258
create digest object for verify
259

260
@function verifyInit
261
@tparam[opt=nil] engine object
262
@treturn evp_digest_ctx
263
*/
264

265
/***
266
openssl.evp_digest_ctx object
267
@type evp_digest_ctx
268
*/
269

270
/***
271
get infomation of evp_digest_ctx object
272

273
@function info
274
@treturn table info keys include size,block_size,digest
275
*/
276
static int openssl_digest_ctx_info(lua_State *L)
6✔
277
{
278
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
6✔
279
#if OPENSSL_VERSION_NUMBER < 0x30000000
280
  const EVP_MD *md = EVP_MD_CTX_md(ctx);
4✔
281
#else
282
  const EVP_MD *md = EVP_MD_CTX_get0_md(ctx);
2✔
283
#endif
284

285
  lua_newtable(L);
6✔
286
  AUXILIAR_SET(L, -1, "block_size", EVP_MD_CTX_block_size(ctx), integer);
6✔
287
  AUXILIAR_SET(L, -1, "size", EVP_MD_CTX_size(ctx), integer);
6✔
288
  AUXILIAR_SET(L, -1, "type", EVP_MD_CTX_type(ctx), integer);
6✔
289

290
  AUXILIAR_SETOBJECT(L, md, "openssl.evp_digest", -1, "digest");
6✔
291
  return 1;
6✔
292
}
293

294
/***
295
feed data to do digest
296

297
@function update
298
@tparam string msg data
299
@treturn boolean result true for success
300
*/
301
static int openssl_evp_digest_update(lua_State *L)
38✔
302
{
303
  size_t      inl;
304
  EVP_MD_CTX *c = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
38✔
305
  const char *in = luaL_checklstring(L, 2, &inl);
38✔
306

307
  int ret = EVP_DigestUpdate(c, in, inl);
38✔
308

309
  lua_pushboolean(L, ret);
38✔
310
  return 1;
38✔
311
}
312

313
/***
314
get result of digest
315

316
@function final
317
@tparam[opt] string last last part of data
318
@tparam[opt] boolean raw binary or hexadecimal result, default false for hexadecimal result
319
@treturn string val hash result
320
*/
321
static int openssl_evp_digest_final(lua_State *L)
38✔
322
{
323
  EVP_MD_CTX *c = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
38✔
324

325
  byte         out[EVP_MAX_MD_SIZE];
326
  unsigned int outl = sizeof(out);
38✔
327
  int          ret = 0, raw = 0;
38✔
328

329
  if (lua_isstring(L, 2)) {
38✔
330
    size_t      inl;
331
    const char *in = luaL_checklstring(L, 2, &inl);
16✔
332
    ret = EVP_DigestUpdate(c, in, inl);
16✔
333
    if (ret != 1) {
16✔
334
      ret = openssl_pushresult(L, ret);
×
335
      goto err;
×
336
    }
337

338
    raw = (lua_isnone(L, 3)) ? 0 : lua_toboolean(L, 3);
16✔
339
  } else if (lua_gettop(L) >= 3)
22✔
340
    raw = lua_toboolean(L, 3);
×
341
  else
342
    raw = (lua_isnone(L, 2)) ? 0 : lua_toboolean(L, 2);
22✔
343

344
  ret = EVP_DigestFinal_ex(c, (byte *)out, &outl);
38✔
345
  if (ret == 1) {
38✔
346
    if (raw) {
38✔
347
      lua_pushlstring(L, (const char *)out, outl);
18✔
348
    } else {
349
      char hex[2 * EVP_MAX_MD_SIZE + 1];
350
      to_hex((const char *)out, outl, hex);
20✔
351
      lua_pushstring(L, hex);
20✔
352
    }
353
  } else
354
    ret = openssl_pushresult(L, ret);
×
355

356
err:
38✔
357
  return ret;
38✔
358
}
359

360
static int openssl_digest_ctx_free(lua_State *L)
150✔
361
{
362
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
150✔
363
  lua_pushnil(L);
150✔
364
  lua_rawsetp(L, LUA_REGISTRYINDEX, ctx);
150✔
365
  EVP_MD_CTX_free(ctx);
150✔
366
  return 0;
150✔
367
}
368

369
/***
370
reset evp_diget_ctx to reuse
371

372
@function reset
373
@treturn boolean true on success, false on failure
374
*/
375
static int openssl_digest_ctx_reset(lua_State *L)
16✔
376
{
377
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
16✔
378
#if OPENSSL_VERSION_NUMBER < 0x30000000
379
  const EVP_MD *md = EVP_MD_CTX_md(ctx);
8✔
380
#else
381
  const EVP_MD *md = EVP_MD_CTX_get0_md(ctx);
8✔
382
#endif
383

384
  ENGINE *e = NULL;
16✔
385
  int     ret;
386

387
  lua_rawgetp(L, LUA_REGISTRYINDEX, ctx);
16✔
388
  e = (ENGINE *)lua_topointer(L, -1);
16✔
389
  ret = EVP_MD_CTX_reset(ctx);
16✔
390
  if (ret) {
16✔
391
    EVP_DigestInit_ex(ctx, md, e);
16✔
392
  }
393
  return openssl_pushresult(L, ret);
16✔
394
}
395

396
/***
397
retrieve md data
398

399
@function data
400
@tparam[opt] string md_data data to set (optional)
401
@treturn string|boolean if no parameter given, returns current md_data; if parameter given, returns boolean success status
402
*/
403
static int openssl_digest_ctx_data(lua_State *L)
6✔
404
{
405
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
6✔
406

407
#if OPENSSL_VERSION_NUMBER < 0x10100000L                                                           \
408
  || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050000fL)
409

410
  if (lua_isnone(L, 2)) {
2✔
411
    lua_pushlstring(L, ctx->md_data, ctx->digest->ctx_size);
1✔
412
  } else {
413
    size_t      l;
414
    const char *d = luaL_checklstring(L, 2, &l);
1✔
415
    luaL_argcheck(L, l == (size_t)ctx->digest->ctx_size, 2, "wrong data");
1✔
416
    memcpy(ctx->md_data, d, l);
1✔
417
    lua_pushboolean(L, 1);
1✔
418
  }
419
#else
420

421
#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER >= 0x30000000L
422
  /* without EVP_MD_meth_get_app_datasize
423
   * LibreSSL does not support this function
424
   * OpenSSL 3.0+ deprecated EVP_MD_meth_get_app_datasize in favor of provider-based architecture
425
   */
426
  (void)ctx;
427
  return 0;
2✔
428
#else
429

430
  const EVP_MD *md = EVP_MD_CTX_md(ctx);
2✔
431
  size_t ctx_size = (size_t)EVP_MD_meth_get_app_datasize(md);
2✔
432
  if (ctx_size == 0) return 0;
2✔
433

434
  if (lua_isnone(L, 2)) {
2✔
435
    lua_pushlstring(L, EVP_MD_CTX_md_data(ctx), ctx_size);
1✔
436
  } else {
437
    const char *d = luaL_checklstring(L, 2, &ctx_size);
1✔
438
    luaL_argcheck(L, ctx_size == (size_t)EVP_MD_meth_get_app_datasize(md), 2, "wrong data");
1✔
439
    memcpy(EVP_MD_CTX_md_data(ctx), d, ctx_size);
1✔
440
    lua_pushboolean(L, 1);
1✔
441
  }
442
#endif
443

444
#endif
445
  return 1;
4✔
446
}
447

448
/***
449
update digest context for signing operation
450
@function signUpdate
451
@tparam evp_digest_ctx ctx digest context
452
@tparam string data data to sign
453
@treturn boolean result
454
*/
455
static int openssl_signUpdate(lua_State *L)
32✔
456
{
457
  size_t      l;
458
  int         ret;
459
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
32✔
460
  const char *data = luaL_checklstring(L, 2, &l);
32✔
461
  ret = EVP_DigestSignUpdate(ctx, data, l);
32✔
462
  return openssl_pushresult(L, ret);
32✔
463
}
464

465
/***
466
feed data for verify with signature
467

468
@function verifyUpdate
469
@tparam string data to be verified
470
@treturn boolean result
471
*/
472
static int openssl_verifyUpdate(lua_State *L)
32✔
473
{
474
  size_t      l;
475
  int         ret;
476
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
32✔
477
  const char *data = luaL_checklstring(L, 2, &l);
32✔
478
  ret = EVP_DigestVerifyUpdate(ctx, data, l);
32✔
479
  return openssl_pushresult(L, ret);
32✔
480
}
481

482
/***
483
get result of sign
484

485
@function signFinal
486
@tparam evp_pkey private key to do sign
487
@treturn string singed result
488
*/
489
static int openssl_signFinal(lua_State *L)
16✔
490
{
491
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
16✔
492
  size_t      siglen = 0;
16✔
493
  int         ret = EVP_DigestSignFinal(ctx, NULL, &siglen);
16✔
494
  if (ret == 1) {
16✔
495
    unsigned char *sigbuf = OPENSSL_malloc(siglen);
16✔
496
    ret = EVP_DigestSignFinal(ctx, sigbuf, &siglen);
16✔
497
    if (ret == 1) {
16✔
498
      lua_pushlstring(L, (char *)sigbuf, siglen);
16✔
499
    }
500
    OPENSSL_free(sigbuf);
16✔
501
    EVP_MD_CTX_reset(ctx);
16✔
502
  }
503
  return ret == 1 ? 1 : openssl_pushresult(L, ret);
16✔
504
}
505

506
/***
507
get verify result
508

509
@function verifyFinal
510
@tparam string signature
511
@treturn boolean result, true for verify pass
512
*/
513
static int openssl_verifyFinal(lua_State *L)
16✔
514
{
515
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
16✔
516
  size_t      signature_len;
517
  const char *signature = luaL_checklstring(L, 2, &signature_len);
16✔
518
  int         ret = EVP_DigestVerifyFinal(ctx, (unsigned char *)signature, signature_len);
16✔
519

520
  EVP_MD_CTX_reset(ctx);
16✔
521
  return openssl_pushresult(L, ret);
16✔
522
}
523

524
static luaL_Reg digest_funs[] = {
525
  { "new",        openssl_evp_digest_init },
526
  { "info",       openssl_digest_info     },
527
  { "digest",     openssl_digest_digest   },
528

529
  { "signInit",   openssl_signInit        },
530
  { "verifyInit", openssl_verifyInit      },
531

532
  { "__tostring", auxiliar_tostring       },
533

534
  { NULL,         NULL                    }
535
};
536

537
#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)                     \
538
  || LIBRESSL_VERSION_NUMBER > 0x3050000fL
539
/***
540
get result of oneshot sign
541

542
@function sign
543
@tparam evp_digest_ctx ctx
544
@tparam string data to sign
545
@treturn[1] string singed result
546
@treturn[2] nil followd by error message
547
*/
548
static int openssl_oneshot_sign(lua_State *L)
6✔
549
{
550
  EVP_MD_CTX    *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
6✔
551
  size_t         tbslen;
552
  const uint8_t *tbs = (const uint8_t *)luaL_checklstring(L, 2, &tbslen);
6✔
553
  size_t         siglen = 0;
6✔
554

555
  int ret = EVP_DigestSign(ctx, NULL, &siglen, tbs, tbslen);
6✔
556
  if (ret == 1) {
6✔
557
    unsigned char *sigbuf = OPENSSL_malloc(siglen);
6✔
558
    ret = EVP_DigestSign(ctx, sigbuf, &siglen, tbs, tbslen);
6✔
559
    if (ret == 1) {
6✔
560
      lua_pushlstring(L, (const char *)sigbuf, siglen);
6✔
561
    }
562
    OPENSSL_free(sigbuf);
6✔
563
    EVP_MD_CTX_reset(ctx);
6✔
564
  }
565
  return ret == 1 ? 1 : openssl_pushresult(L, ret);
6✔
566
}
567

568
/***
569
get result of oneshot verify
570

571
@function verify
572
@tparam evp_digest_ctx ctx
573
@tparam string signature to verify
574
@tparam data to verify
575
@treturn[1] string singed result
576
@treturn[2] nil followd by error message
577
@tparam string signature
578
@treturn boolean result, true for verify pass
579
*/
580
static int openssl_oneshot_verify(lua_State *L)
6✔
581
{
582
  EVP_MD_CTX    *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
6✔
583
  size_t         siglen;
584
  const uint8_t *sig = (const uint8_t *)luaL_checklstring(L, 2, &siglen);
6✔
585
  size_t         tbslen;
586
  const uint8_t *tbs = (const uint8_t *)luaL_checklstring(L, 3, &tbslen);
6✔
587

588
  int ret = EVP_DigestVerify(ctx, sig, siglen, tbs, tbslen);
6✔
589
  EVP_MD_CTX_reset(ctx);
6✔
590

591
  if (ret < 0) return openssl_pushresult(L, ret);
6✔
592
  lua_pushboolean(L, ret);
6✔
593
  return ret;
6✔
594
}
595
#endif
596

597
static luaL_Reg digest_ctx_funs[] = {
598
  { "update",       openssl_evp_digest_update },
599
  { "final",        openssl_evp_digest_final  },
600
  { "info",         openssl_digest_ctx_info   },
601
  { "reset",        openssl_digest_ctx_reset  },
602
  { "close",        openssl_digest_ctx_free   },
603
  { "data",         openssl_digest_ctx_data   },
604

605
  { "signUpdate",   openssl_signUpdate        },
606
  { "signFinal",    openssl_signFinal         },
607
  { "verifyUpdate", openssl_verifyUpdate      },
608
  { "verifyFinal",  openssl_verifyFinal       },
609

610
#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)                     \
611
  || LIBRESSL_VERSION_NUMBER > 0x3050000fL
612
  { "sign",         openssl_oneshot_sign      },
613
  { "verify",       openssl_oneshot_verify    },
614
#endif
615

616
  { "__tostring",   auxiliar_tostring         },
617
  { "__gc",         openssl_digest_ctx_free   },
618
  { NULL,           NULL                      }
619
};
620

621
static const luaL_Reg R[] = {
622
  { "list",       openssl_digest_list },
623
  { "get",        openssl_digest_get  },
624
  { "new",        openssl_digest_new  },
625
  { "digest",     openssl_digest      },
626

627
  { "signInit",   openssl_signInit    },
628
  { "verifyInit", openssl_verifyInit  },
629

630
  { NULL,         NULL                }
631
};
632

633
int
634
luaopen_digest(lua_State *L)
43✔
635
{
636
  auxiliar_newclass(L, "openssl.evp_digest", digest_funs);
43✔
637
  auxiliar_newclass(L, "openssl.evp_digest_ctx", digest_ctx_funs);
43✔
638

639
  lua_newtable(L);
43✔
640
  luaL_setfuncs(L, R, 0);
43✔
641

642
  return 1;
43✔
643
}
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