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

zhaozg / lua-openssl / 17914554859

22 Sep 2025 12:00PM UTC coverage: 93.583%. Remained the same
17914554859

push

travis-ci

zhaozg
doc: LDoc documentation and doc check

Co-authored-by: zhaozg <542599+zhaozg@users.noreply.github.com>

1 of 1 new or added line in 1 file covered. (100.0%)

411 existing lines in 18 files now uncovered.

9640 of 10301 relevant lines covered (93.58%)

2556.19 hits per line

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

91.18
/src/engine.c
1
/*=========================================================================*\
2
* engine.c
3
* engine object for lua-openssl binding
4
*
5
* Author:  george zhao <zhaozg(at)gmail.com>
6
\*=========================================================================*/
7

8
/***
9
engine module for lua-openssl binding
10

11
OpenSSL engine support allows the use of alternative implementations
12
of cryptographic algorithms. Engines can provide hardware acceleration
13
or alternative software implementations of cryptographic operations.
14

15
@module engine
16
@usage
17
  engine = require('openssl').engine
18
*/
19

20
#include <openssl/engine.h>
21
#include <openssl/ssl.h>
22

23
#include "openssl.h"
24
#include "private.h"
25

26
#ifndef OPENSSL_NO_ENGINE
27
enum
28
{
29
  TYPE_RSA,
30
  TYPE_DSA,
31
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
32
  TYPE_ECDH,
33
  TYPE_ECDSA,
34
#else
35
  TYPE_EC,
36
#endif
37
  TYPE_DH,
38
  TYPE_RAND,
39
  TYPE_CIPHERS,
40
  TYPE_DIGESTS,
41
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
42
  TYPE_STORE,
43
#else
44
  TYPE_PKEY_METHODS,
45
  TYPE_PKEY_ASN1_METHODS,
46
#endif
47
  TYPE_COMPLETE
48
};
49

50
static const char *const list[] = { "RSA", /* 0 */
51
                                    "DSA",
52
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
53
                                    "ECDH", /* 2 */
54
                                    "ECDSA",
55
#else
56
                                    "EC",
57
#endif
58
                                    "DH", /* 4 */
59
                                    "RAND",     "ciphers", "digests", /* 8 */
60
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
61
                                    "STORE", /* 6 */
62
#else
63
                                    "PKEY",     "ASN1",
64
#endif
65
                                    "complete", /* 9 */
66

67
                                    NULL };
68

69
int
70
openssl_engine(lua_State *L)
56✔
71
{
72
  const ENGINE *eng = NULL;
56✔
73
  if (lua_isstring(L, 1)) {
56✔
74
    const char *id = luaL_checkstring(L, 1);
48✔
75
    eng = ENGINE_by_id(id);
48✔
76
  } else if (lua_isboolean(L, 1)) {
8✔
77
    int first = lua_toboolean(L, 1);
8✔
78
    if (first)
8✔
79
      eng = ENGINE_get_first();
4✔
80
    else
81
      eng = ENGINE_get_last();
4✔
82
  } else
83
    luaL_error(L,
×
84
               "#1 may be string or boolean\n"
85
               "\tstring for an engine id to load\n"
86
               "\ttrue for first engine, false or last engine\n"
87
               "\tbut we get %s:%s",
88
               lua_typename(L, lua_type(L, 1)),
89
               lua_tostring(L, 1));
90
  if (eng) {
56✔
91
    PUSH_OBJECT((void *)eng, "openssl.engine");
56✔
92
  } else
93
    lua_pushnil(L);
×
94
  return 1;
56✔
95
}
96

97
/***
98
get next engine in the list
99
@function next
100
@treturn engine|nil next engine object or nil if none
101
*/
102
static int
103
openssl_engine_next(lua_State *L)
10✔
104
{
105
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
10✔
106
  ENGINE_up_ref(eng);
10✔
107
  eng = ENGINE_get_next(eng);
10✔
108
  if (eng) {
10✔
109
    PUSH_OBJECT(eng, "openssl.engine");
6✔
110
  } else
111
    lua_pushnil(L);
4✔
112
  return 1;
10✔
113
}
114

115
/***
116
get previous engine in the internal list
117
@function prev
118
@treturn engine previous engine object or nil if none
119
*/
120
static int
121
openssl_engine_prev(lua_State *L)
10✔
122
{
123
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
10✔
124
  ENGINE_up_ref(eng);
10✔
125
  eng = ENGINE_get_prev(eng);
10✔
126
  if (eng) {
10✔
127
    PUSH_OBJECT(eng, "openssl.engine");
6✔
128
  } else
129
    lua_pushnil(L);
4✔
130
  return 1;
10✔
131
}
132

133
/***
134
add engine to the internal list for lookup by id or name
135
@function add
136
@treturn boolean true on success, false on failure
137
*/
138
static int
139
openssl_engine_add(lua_State *L)
4✔
140
{
141
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
4✔
142
  int     ret = ENGINE_add(eng);
4✔
143
  lua_pushboolean(L, ret);
4✔
144
  return 1;
4✔
145
}
146

147
/***
148
remove engine from the internal list
149
@function remove
150
@treturn boolean true on success, false on failure
151
*/
152
static int
153
openssl_engine_remove(lua_State *L)
4✔
154
{
155
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
4✔
156
  int     ret = ENGINE_remove(eng);
4✔
157
  lua_pushboolean(L, ret);
4✔
158
  return 1;
4✔
159
}
160

161
/***
162
register engine for specific algorithms
163
@function register
164
@tparam[opt=false] boolean unregister true to unregister, false to register
165
@tparam[opt] string algorithms algorithm types to register for (e.g., "ALL", "RSA", "DSA")
166
@treturn boolean true on success, false on failure
167
*/
168
static int
169
openssl_engine_register(lua_State *L)
80✔
170
{
171
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
80✔
172
  int     unregister = 0;
80✔
173
  int     first = 2;
80✔
174
  int     top = lua_gettop(L);
80✔
175
  if (lua_isboolean(L, 2)) {
80✔
176
    unregister = lua_toboolean(L, 2);
80✔
177
    first = 3;
80✔
178
  };
179
  while (first <= top) {
152✔
180
    int c = luaL_checkoption(L, first, "RSA", list);
80✔
181
    switch (c) {
80✔
182
    case TYPE_RSA:
8✔
183
      if (unregister)
8✔
184
        ENGINE_unregister_RSA(eng);
4✔
185
      else
186
        ENGINE_register_RSA(eng);
4✔
187
      break;
8✔
188
    case TYPE_DSA:
8✔
189
      if (unregister)
8✔
190
        ENGINE_unregister_DSA(eng);
4✔
191
      else
192
        ENGINE_register_DSA(eng);
4✔
193
      break;
8✔
194
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
195
    case TYPE_ECDH:
2✔
196
      if (unregister)
2✔
197
        ENGINE_unregister_ECDH(eng);
1✔
198
      else
199
        ENGINE_register_ECDH(eng);
1✔
200
      break;
2✔
201
    case TYPE_ECDSA:
2✔
202
      if (unregister)
2✔
203
        ENGINE_unregister_ECDSA(eng);
1✔
204
      else
205
        ENGINE_register_ECDSA(eng);
1✔
206
      break;
2✔
207
#else
208
    case TYPE_EC:
6✔
209
      if (unregister)
6✔
210
        ENGINE_unregister_EC(eng);
3✔
211
      else
212
        ENGINE_register_EC(eng);
3✔
213
      break;
6✔
214
#endif
215
    case TYPE_DH:
8✔
216
      if (unregister)
8✔
217
        ENGINE_unregister_DH(eng);
4✔
218
      else
219
        ENGINE_register_DH(eng);
4✔
220
      break;
8✔
221
    case TYPE_RAND:
8✔
222
      if (unregister)
8✔
223
        ENGINE_unregister_RAND(eng);
4✔
224
      else
225
        ENGINE_register_RAND(eng);
4✔
226
      break;
8✔
227
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
228
    case TYPE_STORE:
2✔
229
      if (unregister)
2✔
230
        ENGINE_unregister_STORE(eng);
1✔
231
      else
232
        ENGINE_register_STORE(eng);
1✔
233
      break;
2✔
234
#else
235
    case TYPE_PKEY_METHODS:
6✔
236
      if (unregister)
6✔
237
        ENGINE_unregister_pkey_meths(eng);
3✔
238
      else
239
        ENGINE_register_pkey_meths(eng);
3✔
240
      break;
6✔
241
    case TYPE_PKEY_ASN1_METHODS:
6✔
242
      if (unregister)
6✔
243
        ENGINE_unregister_pkey_asn1_meths(eng);
3✔
244
      else
245
        ENGINE_register_pkey_asn1_meths(eng);
3✔
246
      break;
6✔
247
#endif
248
    case TYPE_CIPHERS:
8✔
249
      if (unregister)
8✔
250
        ENGINE_unregister_ciphers(eng);
4✔
251
      else
252
        ENGINE_register_ciphers(eng);
4✔
253
      break;
8✔
254
    case TYPE_DIGESTS:
8✔
255
      if (unregister)
8✔
256
        ENGINE_unregister_digests(eng);
4✔
257
      else
258
        ENGINE_register_digests(eng);
4✔
259
      break;
8✔
260
    case TYPE_COMPLETE: {
8✔
261
      int ret = ENGINE_register_complete(eng);
8✔
262
      lua_pushboolean(L, ret);
8✔
263
      return 1;
8✔
264
    }
UNCOV
265
    default:
×
UNCOV
266
      luaL_error(L, "not support %d for %s", c, list[c]);
×
UNCOV
267
      break;
×
268
    }
269
    first++;
72✔
270
  }
271
  return 0;
72✔
272
};
273

274
/***
275
control engine operations and settings
276
@function ctrl
277
@tparam number|string cmd control command (number) or command string
278
@tparam[opt] any arg command argument (varies by command)
279
@treturn boolean|any result depends on command type
280
*/
281
static int
282
openssl_engine_ctrl(lua_State *L)
20✔
283
{
284
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
20✔
285
  int     ret = 0;
20✔
286
  if (lua_isnumber(L, 2)) {
20✔
287
    int cmd = luaL_checkint(L, 2);
8✔
288
    if (lua_isnone(L, 3)) {
8✔
289
      ret = ENGINE_cmd_is_executable(eng, cmd);
4✔
290
      lua_pushboolean(L, ret);
4✔
291
      return 1;
4✔
292
    } else {
293
      long  i = (long)luaL_checknumber(L, 3);
4✔
294
      void *p = lua_touserdata(L, 4);
4✔
295
      void *arg = lua_isnoneornil(L, 5) ? NULL : lua_touserdata(L, 5);
4✔
296
      ret = ENGINE_ctrl(eng, cmd, i, p, arg);
4✔
297
    }
298
  } else {
299
    const char *cmd = luaL_checkstring(L, 2);
12✔
300
    if (lua_type(L, 3) == LUA_TNUMBER) {
12✔
301
      long i = (long)luaL_checknumber(L, 3);
8✔
302
      if (lua_isstring(L, 4)) {
8✔
UNCOV
303
        const char *s = lua_tostring(L, 4);
×
UNCOV
304
        void       *arg = lua_isnoneornil(L, 5) ? NULL : lua_touserdata(L, 5);
×
UNCOV
305
        int         opt = luaL_optint(L, 6, 0);
×
UNCOV
306
        ret = ENGINE_ctrl_cmd(eng, cmd, i, (void *)s, arg, opt);
×
307
      } else {
308
        void *p = lua_touserdata(L, 4);
8✔
309
        void *arg = lua_isnoneornil(L, 5) ? NULL : lua_touserdata(L, 5);
8✔
310
        int   opt = luaL_optint(L, 6, 0);
8✔
311
        ret = ENGINE_ctrl_cmd(eng, cmd, i, p, arg, opt);
8✔
312
      }
313
    } else {
314
      const char *arg = luaL_optstring(L, 3, NULL);
4✔
315
      int         opt = luaL_optint(L, 4, 0);
4✔
316
      ret = ENGINE_ctrl_cmd_string(eng, cmd, arg, opt);
4✔
317
    }
318
  }
319
  return openssl_pushresult(L, ret);
16✔
320
}
321

322
static int
323
openssl_engine_gc(lua_State *L)
68✔
324
{
325
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
68✔
326
  ENGINE_free(eng);
68✔
327
  return 0;
68✔
328
}
329

330
/***
331
get or set engine identifier
332
@function id
333
@tparam[opt] string id new engine ID to set
334
@treturn string|boolean engine ID (if getting) or success status (if setting)
335
*/
336
static int
337
openssl_engine_id(lua_State *L)
12✔
338
{
339
  ENGINE     *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
12✔
340
  const char *id = NULL;
12✔
341
  if (lua_isstring(L, 2)) {
12✔
342
    int ret;
343
    id = luaL_checkstring(L, 2);
4✔
344
    ret = ENGINE_set_id(eng, id);
4✔
345
    lua_pushboolean(L, ret);
4✔
346
  } else
347
    lua_pushstring(L, ENGINE_get_id(eng));
8✔
348
  return 1;
12✔
349
}
350

351
/***
352
get or set engine name
353
@function name
354
@tparam[opt] string name new engine name to set
355
@treturn string|boolean engine name (if getting) or success status (if setting)
356
*/
357
static int
358
openssl_engine_name(lua_State *L)
8✔
359
{
360
  ENGINE     *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
8✔
361
  const char *id = NULL;
8✔
362
  if (lua_isstring(L, 2)) {
8✔
363
    int ret;
364
    id = luaL_checkstring(L, 2);
4✔
365
    ret = ENGINE_set_name(eng, id);
4✔
366
    lua_pushboolean(L, ret);
4✔
367
  } else
368
    lua_pushstring(L, ENGINE_get_name(eng));
4✔
369
  return 1;
8✔
370
}
371

372
/***
373
get or set engine flags
374
@function flags
375
@tparam[opt] number flags new engine flags to set
376
@treturn number|boolean engine flags (if getting) or success status (if setting)
377
*/
378
static int
379
openssl_engine_flags(lua_State *L)
8✔
380
{
381
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
8✔
382
  if (!lua_isnone(L, 2)) {
8✔
383
    int flags = luaL_checkint(L, 2);
4✔
384
    int ret = ENGINE_set_flags(eng, flags);
4✔
385
    lua_pushboolean(L, ret);
4✔
386
  } else
387
    lua_pushinteger(L, ENGINE_get_flags(eng));
4✔
388
  return 1;
8✔
389
}
390

391
/*
392
int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg);
393
void *ENGINE_get_ex_data(const ENGINE *e, int idx);
394
*/
395
/***
396
initialize an engine for use
397
@function init
398
@treturn boolean true on success, false on failure
399
*/
400
static int
401
openssl_engine_init(lua_State *L)
4✔
402
{
403
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
4✔
404
  int     ret = ENGINE_init(eng);
4✔
405
  lua_pushboolean(L, ret);
4✔
406
  return 1;
4✔
407
}
408

409
/***
410
release an initialized engine
411
@function finish
412
@treturn boolean true on success, false on failure
413
*/
414
static int
415
openssl_engine_finish(lua_State *L)
4✔
416
{
417
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
4✔
418
  int     ret = ENGINE_finish(eng);
4✔
419
  lua_pushboolean(L, ret);
4✔
420
  return 1;
4✔
421
}
422

423
/***
424
set engine as default for specified algorithm types
425
@function set_default
426
@tparam string ... algorithm types ("RSA", "DSA", "DH", "RAND", "ECDH", "ECDSA", "CIPHERS", "DIGESTS", "STORE", "complete")
427
@treturn boolean true on success, false on failure
428
*/
429
static int
430
openssl_engine_set_default(lua_State *L)
12✔
431
{
432
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
12✔
433
  int     ret = 0;
12✔
434
  int     first = 2;
12✔
435
  int     top = lua_gettop(L);
12✔
436

437
  while (first <= top) {
49✔
438
    int c = luaL_checkoption(L, first, "RSA", list);
37✔
439
    switch (c) {
37✔
440
    case TYPE_RSA:
8✔
441
      ret = ENGINE_set_default_RSA(eng);
8✔
442
      break;
8✔
443
    case TYPE_DSA:
4✔
444
      ret = ENGINE_set_default_DSA(eng);
4✔
445
      break;
4✔
446
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
447
    case TYPE_ECDH:
1✔
448
      ret = ENGINE_set_default_ECDH(eng);
1✔
449
      break;
1✔
450
    case TYPE_ECDSA:
2✔
451
      ret = ENGINE_set_default_ECDSA(eng);
2✔
452
      break;
2✔
453
#else
454
    case TYPE_EC:
6✔
455
      ret = ENGINE_set_default_EC(eng);
6✔
456
      break;
6✔
457
#endif
458
    case TYPE_DH:
4✔
459
      ret = ENGINE_set_default_DH(eng);
4✔
460
      break;
4✔
461
    case TYPE_RAND:
4✔
462
      ret = ENGINE_set_default_RAND(eng);
4✔
463
      break;
4✔
464
    case TYPE_CIPHERS:
4✔
465
      ret = ENGINE_set_default_ciphers(eng);
4✔
466
      break;
4✔
467
    case TYPE_DIGESTS:
4✔
468
      ret = ENGINE_set_default_digests(eng);
4✔
469
      break;
4✔
UNCOV
470
    default:
×
UNCOV
471
      luaL_error(L, "not support '%s' to set default", c, list[c]);
×
UNCOV
472
      break;
×
473
    }
474
    first++;
37✔
475
    if (ret != 1) break;
37✔
476
  }
477
  return openssl_pushresult(L, ret);
12✔
478
};
479

480
/***
481
set random number generator engine
482
@function set_rand_engine
483
@treturn boolean result true for success
484
*/
485
static int
486
openssl_engine_set_rand_engine(lua_State *L)
4✔
487
{
488
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
4✔
489
  int     ret = RAND_set_rand_engine(eng);
4✔
490
  return openssl_pushresult(L, ret);
4✔
491
}
492

493
/***
494
load private key from engine
495
@function load_private_key
496
@tparam string key_id key identifier
497
@treturn evp_pkey private key object or nil if failed
498
*/
499
static int
500
openssl_engine_load_private_key(lua_State *L)
4✔
501
{
502
  ENGINE     *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
4✔
503
  const char *key_id = luaL_checkstring(L, 2);
4✔
504
  EVP_PKEY   *pkey = ENGINE_load_private_key(eng, key_id, NULL, NULL);
4✔
505
  if (pkey != NULL) {
4✔
UNCOV
506
    PUSH_OBJECT(pkey, "openssl.evp_pkey");
×
UNCOV
507
    return 1;
×
508
  }
509
  return openssl_pushresult(L, 0);
4✔
510
}
511

512
/***
513
load public key from engine
514
@function load_public_key
515
@tparam string key_id key identifier
516
@treturn evp_pkey public key object or nil if failed
517
*/
518
static int
519
openssl_engine_load_public_key(lua_State *L)
4✔
520
{
521
  ENGINE     *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
4✔
522
  const char *key_id = luaL_checkstring(L, 2);
4✔
523
  EVP_PKEY   *pkey = ENGINE_load_public_key(eng, key_id, NULL, NULL);
4✔
524
  if (pkey != NULL) {
4✔
525
    PUSH_OBJECT(pkey, "openssl.evp_pkey");
×
526
    return 1;
×
527
  }
528
  return openssl_pushresult(L, 0);
4✔
529
}
530

531
/***
532
load SSL client certificate from engine
533
@function load_ssl_client_cert
534
@tparam ssl ssl SSL connection object
535
@treturn boolean result true for success
536
*/
537
static int
538
openssl_engine_load_ssl_client_cert(lua_State *L)
4✔
539
{
540
  ENGINE *eng = CHECK_OBJECT(1, ENGINE, "openssl.engine");
4✔
541
  SSL    *s = CHECK_OBJECT(2, SSL, "openssl.ssl");
4✔
542
  STACK_OF(X509_NAME) *ca_dn = SSL_get_client_CA_list(s);
4✔
543

544
  X509     *pcert = NULL;
4✔
545
  EVP_PKEY *pkey = NULL;
4✔
546
  STACK_OF(X509) *pothers = NULL;
4✔
547

548
  int ret = ENGINE_load_ssl_client_cert(eng, s, ca_dn, &pcert, &pkey, &pothers, NULL, NULL);
4✔
549
  if (ret == 1) {
4✔
UNCOV
550
    PUSH_OBJECT(pcert, "openssl.x509");
×
UNCOV
551
    if (pkey != NULL) {
×
UNCOV
552
      PUSH_OBJECT(pkey, "openssl.pkey");
×
UNCOV
553
      ret++;
×
554
    }
UNCOV
555
    if (pothers != NULL) {
×
UNCOV
556
      openssl_sk_x509_totable(L, pothers);
×
UNCOV
557
      ret++;
×
558
    }
UNCOV
559
    return ret;
×
560
  }
561
  return openssl_pushresult(L, 0);
4✔
562
}
563

564
static luaL_Reg eng_funcs[] = {
565
  { "next",                 openssl_engine_next                 },
566
  { "prev",                 openssl_engine_prev                 },
567
  { "add",                  openssl_engine_add                  },
568
  { "remove",               openssl_engine_remove               },
569
  { "register",             openssl_engine_register             },
570
  { "ctrl",                 openssl_engine_ctrl                 },
571
  { "id",                   openssl_engine_id                   },
572
  { "name",                 openssl_engine_name                 },
573
  { "flags",                openssl_engine_flags                },
574

575
  { "set_rand_engine",      openssl_engine_set_rand_engine      },
576
  { "load_private_key",     openssl_engine_load_private_key     },
577
  { "load_public_key",      openssl_engine_load_public_key      },
578
  { "load_ssl_client_cert", openssl_engine_load_ssl_client_cert },
579

580
  { "init",                 openssl_engine_init                 },
581
  { "finish",               openssl_engine_finish               },
582
  { "set_default",          openssl_engine_set_default          },
583

584
  { "__gc",                 openssl_engine_gc                   },
585
  { "__tostring",           auxiliar_tostring                   },
586

587
  { NULL,                   NULL                                },
588
};
589

590
int
591
openssl_register_engine(lua_State *L)
43✔
592
{
593
  auxiliar_newclass(L, "openssl.engine", eng_funcs);
43✔
594
  return 0;
43✔
595
}
596
#endif
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