• 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

90.26
/src/cipher.c
1
/***
2
cipher module do encrypt or decrypt base on OpenSSL EVP API.
3

4
@module cipher
5
@usage
6
  cipher = require('openssl').cipher
7
@treturn various return value
8
*/
9
#include "openssl.h"
10
#include "private.h"
11

12
/***
13
list all support cipher algs
14

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

28
/***
29
get evp_cipher object
30

31
@function get
32
@tparam string|integer|asn1_object alg name, nid or object identity
33
@treturn evp_cipher cipher object mapping EVP_MD in openssl
34

35
@see evp_cipher
36
*/
37
static int openssl_cipher_get(lua_State *L)
113✔
38
{
39
  const EVP_CIPHER *cipher = get_cipher(L, 1, NULL);
113✔
40

41
  PUSH_OBJECT((void *)cipher, "openssl.evp_cipher");
113✔
42
  return 1;
113✔
43
}
44

45
static void
46
set_key_iv(const char *key,
372✔
47
           size_t      key_len,
48
           char       *evp_key,
49
           const char *iv,
50
           size_t      iv_len,
51
           char       *evp_iv)
52
{
53
  if (key) {
372✔
54
    key_len = EVP_MAX_KEY_LENGTH > key_len ? key_len : EVP_MAX_KEY_LENGTH;
302✔
55
    memcpy(evp_key, key, key_len);
302✔
56
  }
57
  if (iv_len > 0 && iv) {
372✔
58
    iv_len = EVP_MAX_IV_LENGTH > iv_len ? iv_len : EVP_MAX_IV_LENGTH;
278✔
59
    memcpy(evp_iv, iv, iv_len);
278✔
60
  }
61
}
372✔
62

63
/***
64
quick encrypt
65

66
@function encrypt
67
@tparam string|integer|asn1_object alg name, nid or object identity
68
@tparam string input data to encrypt
69
@tparam string key secret key
70
@tparam[opt] string iv
71
@tparam[opt] boolean pad true for padding default
72
@tparam[opt] engine engine custom crypto engine
73
@treturn string result encrypt data
74
*/
75
static int openssl_evp_encrypt(lua_State *L)
8✔
76
{
77
  const EVP_CIPHER *cipher = get_cipher(L, 1, NULL);
8✔
78
  size_t            input_len = 0;
8✔
79
  const char       *input = luaL_checklstring(L, 2, &input_len);
8✔
80
  size_t            key_len = 0;
8✔
81
  const char       *key = luaL_optlstring(L, 3, NULL, &key_len); /* can be NULL */
8✔
82
  size_t            iv_len = 0;
8✔
83
  const char       *iv = luaL_optlstring(L, 4, NULL, &iv_len); /* can be NULL */
8✔
84
  int               pad = lua_isnone(L, 5) ? 1 : lua_toboolean(L, 5);
8✔
85
  ENGINE           *e = lua_isnoneornil(L, 6) ? NULL : CHECK_OBJECT(6, ENGINE, "openssl.engine");
8✔
86

87
  EVP_CIPHER_CTX *c = EVP_CIPHER_CTX_new();
8✔
88

89
  int   output_len = 0;
8✔
90
  int   len = 0;
8✔
91
  char *buffer = NULL;
8✔
92
  char  evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
8✔
93
  char  evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
8✔
94
  int   ret = 0;
8✔
95

96
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
8✔
97

98
  ret = EVP_EncryptInit_ex(
8✔
99
    c, cipher, e, (const byte *)evp_key, iv_len > 0 ? (const byte *)evp_iv : NULL);
8✔
100
  if (ret == 1) {
8✔
101
    ret = EVP_CIPHER_CTX_set_padding(c, pad);
8✔
102
    if (ret == 1) {
8✔
103
      buffer = OPENSSL_malloc(input_len + EVP_CIPHER_CTX_block_size(c));
8✔
104
      if (buffer == NULL) {
8✔
105
        EVP_CIPHER_CTX_free(c);
×
106
        return luaL_error(L, "Memory allocation failed");
×
107
      }
108
      ret = EVP_EncryptUpdate(c, (byte *)buffer, &len, (const byte *)input, input_len);
8✔
109
      if (ret == 1) {
8✔
110
        output_len += len;
8✔
111
        ret = EVP_EncryptFinal_ex(c, (byte *)buffer + len, &len);
8✔
112
        if (ret == 1) {
8✔
113
          output_len += len;
8✔
114
          lua_pushlstring(L, buffer, output_len);
8✔
115
        }
116
      }
117
      OPENSSL_free(buffer);
8✔
118
    }
119
  }
120
  EVP_CIPHER_CTX_free(c);
8✔
121
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
8✔
122
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
8✔
123
  return (ret == 1) ? ret : openssl_pushresult(L, ret);
8✔
124
}
125

126
/***
127
quick decrypt
128

129
@function decrypt
130
@tparam string|integer|asn1_object alg name, nid or object identity
131
@tparam string input data to decrypt
132
@tparam string key secret key
133
@tparam[opt] string iv
134
@tparam[opt] boolean pad true for padding default
135
@tparam[opt] engine engine custom crypto engine
136
@treturn string result decrypt data
137
*/
138
static int openssl_evp_decrypt(lua_State *L)
8✔
139
{
140
  const EVP_CIPHER *cipher = get_cipher(L, 1, NULL);
8✔
141
  size_t            input_len = 0;
8✔
142
  const char       *input = luaL_checklstring(L, 2, &input_len);
8✔
143
  size_t            key_len = 0;
8✔
144
  const char       *key = luaL_optlstring(L, 3, NULL, &key_len); /* can be NULL */
8✔
145
  size_t            iv_len = 0;
8✔
146
  const char       *iv = luaL_optlstring(L, 4, NULL, &iv_len); /* can be NULL */
8✔
147
  int               pad = lua_isnone(L, 5) ? 1 : lua_toboolean(L, 5);
8✔
148
  ENGINE           *e = lua_isnoneornil(L, 6) ? NULL : CHECK_OBJECT(6, ENGINE, "openssl.engine");
8✔
149
  EVP_CIPHER_CTX   *c = EVP_CIPHER_CTX_new();
8✔
150

151
  int   output_len = 0;
8✔
152
  int   len = 0;
8✔
153
  char *buffer = NULL;
8✔
154
  char  evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
8✔
155
  char  evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
8✔
156
  int   ret;
157

158
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
8✔
159

160
  ret = EVP_DecryptInit_ex(
8✔
161
    c, cipher, e, key ? (const byte *)evp_key : NULL, iv_len > 0 ? (const byte *)evp_iv : NULL);
8✔
162
  if (ret == 1) {
8✔
163
    ret = EVP_CIPHER_CTX_set_padding(c, pad);
8✔
164
    if (ret == 1) {
8✔
165
      buffer = OPENSSL_malloc(input_len);
8✔
166
      if (buffer == NULL) {
8✔
167
        EVP_CIPHER_CTX_free(c);
×
168
        return luaL_error(L, "Memory allocation failed");
×
169
      }
170

171
      ret = EVP_DecryptUpdate(c, (byte *)buffer, &len, (const byte *)input, input_len);
8✔
172
      if (ret == 1) {
8✔
173
        output_len += len;
8✔
174
        len = input_len - len;
8✔
175
        ret = EVP_DecryptFinal_ex(c, (byte *)buffer + output_len, &len);
8✔
176
        if (ret == 1) {
8✔
177
          output_len += len;
8✔
178
          lua_pushlstring(L, buffer, output_len);
8✔
179
        }
180
      }
181
      OPENSSL_free(buffer);
8✔
182
    }
183
  }
184
  EVP_CIPHER_CTX_free(c);
8✔
185
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
8✔
186
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
8✔
187
  return (ret == 1) ? ret : openssl_pushresult(L, ret);
8✔
188
}
189

190
/***
191
quick encrypt or decrypt
192

193
@function cipher
194
@tparam string|integer|asn1_object alg name, nid or object identity
195
@tparam boolean encrypt true for encrypt,false for decrypt
196
@tparam string input data to encrypt or decrypt
197
@tparam string key secret key
198
@tparam[opt] string iv
199
@tparam[opt] boolean pad true for padding default
200
@tparam[opt] engine engine custom crypto engine
201
@treturn string result
202
*/
203
static int openssl_evp_cipher(lua_State *L)
8✔
204
{
205
  const EVP_CIPHER *cipher = get_cipher(L, 1, NULL);
8✔
206
  int               enc = lua_toboolean(L, 2);
8✔
207
  size_t            input_len = 0;
8✔
208
  const char       *input = luaL_checklstring(L, 3, &input_len);
8✔
209
  size_t            key_len = 0;
8✔
210
  const char       *key = luaL_checklstring(L, 4, &key_len);
8✔
211
  size_t            iv_len = 0;
8✔
212
  const char       *iv = luaL_optlstring(L, 5, NULL, &iv_len); /* can be NULL */
8✔
213

214
  int     pad = lua_isnone(L, 6) ? 1 : lua_toboolean(L, 6);
8✔
215
  ENGINE *e = lua_isnoneornil(L, 7) ? NULL : CHECK_OBJECT(7, ENGINE, "openssl.engine");
8✔
216

217
  EVP_CIPHER_CTX *c = EVP_CIPHER_CTX_new();
8✔
218

219
  int output_len = 0;
8✔
220
  int len = 0;
8✔
221

222
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
8✔
223
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
8✔
224

225
  int ret;
226

227
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
8✔
228

229
  ret = EVP_CipherInit_ex(
8✔
230
    c, cipher, e, (const byte *)evp_key, iv_len > 0 ? (const byte *)evp_iv : NULL, enc);
8✔
231
  if (ret == 1) {
8✔
232
    ret = EVP_CIPHER_CTX_set_padding(c, pad);
8✔
233
    if (ret == 1) {
8✔
234
      char *buffer;
235
      len = input_len + EVP_MAX_BLOCK_LENGTH;
8✔
236
      buffer = OPENSSL_malloc(len);
8✔
237
      ret = EVP_CipherUpdate(c, (byte *)buffer, &len, (const byte *)input, input_len);
8✔
238
      if (ret == 1) {
8✔
239
        output_len += len;
8✔
240
        len = input_len + EVP_MAX_BLOCK_LENGTH - len;
8✔
241
        ret = EVP_CipherFinal_ex(c, (byte *)buffer + output_len, &len);
8✔
242
        if (ret == 1) {
8✔
243
          output_len += len;
8✔
244
          lua_pushlstring(L, buffer, output_len);
8✔
245
        }
246
      }
247
      OPENSSL_free(buffer);
8✔
248
    }
249
  }
250
  EVP_CIPHER_CTX_free(c);
8✔
251
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
8✔
252
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
8✔
253
  return (ret == 1) ? ret : openssl_pushresult(L, ret);
8✔
254
}
255

256
typedef enum
257
{
258
  DO_CIPHER = 0,
259
  DO_ENCRYPT = 1,
260
  DO_DECRYPT = 2
261
} CIPHER_MODE;
262

263
/***
264
get evp_cipher_ctx object for encrypt or decrypt
265

266
@function new
267
@tparam string|integer|asn1_object alg name, nid or object identity
268
@tparam boolean encrypt true for encrypt,false for decrypt
269
@tparam[opt] string key secret key
270
@tparam[opt] string iv
271
@tparam[opt=true] boolean pad true for padding
272
@tparam[opt] engine engine custom crypto engine
273
@treturn evp_cipher_ctx cipher object mapping EVP_CIPHER_CTX in openssl
274

275
@see evp_cipher_ctx
276
*/
277

278
static int openssl_cipher_new(lua_State *L)
160✔
279
{
280
  const EVP_CIPHER *cipher = get_cipher(L, 1, NULL);
160✔
281
  int               enc = lua_toboolean(L, 2);
160✔
282
  size_t            key_len = 0;
160✔
283
  const char       *key = luaL_optlstring(L, 3, NULL, &key_len);
160✔
284
  size_t            iv_len = 0;
160✔
285
  const char       *iv = luaL_optlstring(L, 4, NULL, &iv_len);
160✔
286
  int               pad = lua_isnone(L, 5) ? 1 : lua_toboolean(L, 5);
160✔
287
  ENGINE           *e = lua_isnoneornil(L, 6) ? NULL : CHECK_OBJECT(6, ENGINE, "openssl.engine");
160✔
288
  EVP_CIPHER_CTX   *c = NULL;
160✔
289
  int               ret = 0;
160✔
290

291
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
160✔
292
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
160✔
293

294
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
160✔
295

296
  c = EVP_CIPHER_CTX_new();
160✔
297
  ret = EVP_CipherInit_ex(c,
160✔
298
                          cipher,
299
                          e,
300
                          key ? (const byte *)evp_key : NULL,
301
                          iv_len > 0 ? (const byte *)evp_iv : NULL,
160✔
302
                          enc);
303
  if (ret == 1) {
160✔
304
    EVP_CIPHER_CTX_set_padding(c, pad);
160✔
305
    PUSH_OBJECT(c, "openssl.evp_cipher_ctx");
160✔
306
    lua_pushinteger(L, DO_CIPHER);
160✔
307
    lua_rawsetp(L, LUA_REGISTRYINDEX, c);
160✔
308
    return 1;
160✔
309
  }
310
  EVP_CIPHER_CTX_free(c);
×
311
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
×
312
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
×
313
  return openssl_pushresult(L, ret);
×
314
}
315

316
/***
317
get evp_cipher_ctx object for encrypt
318

319
@function encrypt_new
320
@tparam string|integer|asn1_object alg name, nid or object identity
321
@tparam string key secret key
322
@tparam[opt] string iv
323
@tparam[opt] engine engine custom crypto engine
324
@tparam[opt=true] boolean pad true for padding
325
@treturn evp_cipher_ctx cipher object mapping EVP_CIPHER_CTX in openssl
326

327
@see evp_cipher_ctx
328
*/
329

330
static int openssl_cipher_encrypt_new(lua_State *L)
49✔
331
{
332
  const EVP_CIPHER *cipher = get_cipher(L, 1, NULL);
49✔
333
  int               ret;
334
  size_t            key_len = 0;
49✔
335
  const char       *key = luaL_optlstring(L, 2, NULL, &key_len); /* can be NULL */
49✔
336
  size_t            iv_len = 0;
49✔
337
  const char       *iv = luaL_optlstring(L, 3, NULL, &iv_len); /* can be NULL */
49✔
338
  ENGINE           *e = lua_isnoneornil(L, 4) ? NULL : CHECK_OBJECT(4, ENGINE, "openssl.engine");
49✔
339
  int               pad = lua_isnone(L, 5) ? 1 : lua_toboolean(L, 5);
49✔
340

341
  EVP_CIPHER_CTX *c = NULL;
49✔
342

343
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
49✔
344
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
49✔
345

346
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
49✔
347

348
  c = EVP_CIPHER_CTX_new();
49✔
349
  ret = EVP_EncryptInit_ex(
49✔
350
    c, cipher, e, key ? (const byte *)evp_key : NULL, iv_len > 0 ? (const byte *)evp_iv : NULL);
49✔
351
  if (ret == 1) {
49✔
352
    EVP_CIPHER_CTX_set_padding(c, pad);
49✔
353
    PUSH_OBJECT(c, "openssl.evp_cipher_ctx");
49✔
354
    lua_pushinteger(L, DO_ENCRYPT);
49✔
355
    lua_rawsetp(L, LUA_REGISTRYINDEX, c);
49✔
356
    return 1;
49✔
357
  }
358
  EVP_CIPHER_CTX_free(c);
×
359
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
×
360
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
×
361
  return openssl_pushresult(L, ret);
×
362
}
363

364
/***
365
get evp_cipher_ctx object for decrypt
366

367
@function decrypt_new
368
@tparam string|integer|asn1_object alg name, nid or object identity
369
@tparam string key secret key
370
@tparam[opt] string iv
371
@tparam[opt] engine engine custom crypto engine
372
@tparam[opt=true] boolean pad true for padding
373
@treturn evp_cipher_ctx cipher object mapping EVP_CIPHER_CTX in openssl
374

375
@see evp_cipher_ctx
376
*/
377

378
static int openssl_cipher_decrypt_new(lua_State *L)
49✔
379
{
380
  const EVP_CIPHER *cipher = get_cipher(L, 1, NULL);
49✔
381
  size_t            key_len = 0;
49✔
382
  const char       *key = luaL_optlstring(L, 2, NULL, &key_len); /* can be NULL */
49✔
383
  size_t            iv_len = 0;
49✔
384
  const char       *iv = luaL_optlstring(L, 3, NULL, &iv_len); /* can be NULL */
49✔
385
  ENGINE           *e = lua_isnoneornil(L, 4) ? NULL : CHECK_OBJECT(4, ENGINE, "openssl.engine");
49✔
386
  int               pad = lua_isnone(L, 5) ? 1 : lua_toboolean(L, 5);
49✔
387
  EVP_CIPHER_CTX   *c = NULL;
49✔
388

389
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
49✔
390
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
49✔
391
  int  ret;
392

393
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
49✔
394

395
  c = EVP_CIPHER_CTX_new();
49✔
396
  ret = EVP_DecryptInit_ex(
49✔
397
    c, cipher, e, key ? (const byte *)evp_key : NULL, iv_len > 0 ? (const byte *)evp_iv : NULL);
49✔
398
  if (ret == 1) {
49✔
399
    EVP_CIPHER_CTX_set_padding(c, pad);
49✔
400
    PUSH_OBJECT(c, "openssl.evp_cipher_ctx");
49✔
401
    lua_pushinteger(L, DO_DECRYPT);
49✔
402
    lua_rawsetp(L, LUA_REGISTRYINDEX, c);
49✔
403
    return 1;
49✔
404
  }
405
  EVP_CIPHER_CTX_free(c);
×
406
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
×
407
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
×
408
  return openssl_pushresult(L, ret);
×
409
}
410

411
/***
412
openssl.evp_cipher object
413
@type evp_cipher
414
*/
415
/***
416
get infomation of evp_cipher object
417

418
@function info
419
@treturn table info keys include name,block_size,key_length,iv_length,flags,mode
420
*/
421
static int openssl_cipher_info(lua_State *L)
109✔
422
{
423
  EVP_CIPHER *cipher = CHECK_OBJECT(1, EVP_CIPHER, "openssl.evp_cipher");
109✔
424
  lua_newtable(L);
109✔
425
  AUXILIAR_SET(L, -1, "name", EVP_CIPHER_name(cipher), string);
109✔
426
  AUXILIAR_SET(L, -1, "block_size", EVP_CIPHER_block_size(cipher), integer);
109✔
427
  AUXILIAR_SET(L, -1, "key_length", EVP_CIPHER_key_length(cipher), integer);
109✔
428
  AUXILIAR_SET(L, -1, "iv_length", EVP_CIPHER_iv_length(cipher), integer);
109✔
429
  AUXILIAR_SET(L, -1, "flags", EVP_CIPHER_flags(cipher), integer);
109✔
430
  AUXILIAR_SET(L, -1, "mode", EVP_CIPHER_mode(cipher), integer);
109✔
431
  return 1;
109✔
432
}
433

434
/***
435
derive key
436

437
@function BytesToKey
438
@tparam string data derive data
439
@tparam string[opt] string salt salt will get strong security
440
@tparam ev_digest|string md digest method used to diver key, default with 'sha1'
441
@treturn string key
442
@treturn string iv
443
*/
444
static int openssl_evp_BytesToKey(lua_State *L)
8✔
445
{
446
  EVP_CIPHER   *c = CHECK_OBJECT(1, EVP_CIPHER, "openssl.evp_cipher");
8✔
447
  size_t        lsalt, lk;
448
  const char   *k = luaL_checklstring(L, 2, &lk);
8✔
449
  const char   *salt = luaL_optlstring(L, 3, NULL, &lsalt);
8✔
450
  const EVP_MD *m = get_digest(L, 4, "sha256");
8✔
451
  char          key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
452
  int           ret;
453
  if (salt != NULL && lsalt < PKCS5_SALT_LEN) {
8✔
454
    lua_pushfstring(L, "salt must not shorter than %d", PKCS5_SALT_LEN);
×
455
    luaL_argerror(L, 3, lua_tostring(L, -1));
×
456
  }
457

458
  ret = EVP_BytesToKey(c,
8✔
459
                       m,
460
                       (unsigned char *)salt,
461
                       (unsigned char *)k,
462
                       lk,
463
                       1,
464
                       (unsigned char *)key,
465
                       (unsigned char *)iv);
466
  if (ret > 1) {
8✔
467
    lua_pushlstring(L, key, EVP_CIPHER_key_length(c));
8✔
468
    lua_pushlstring(L, iv, EVP_CIPHER_iv_length(c));
8✔
469
    return 2;
8✔
470
  }
471
  return openssl_pushresult(L, ret);
×
472
}
473

474
/***
475
get evp_cipher_ctx to encrypt or decrypt
476

477
@function new
478
@tparam boolean encrypt true for encrypt,false for decrypt
479
@tparam string key secret key
480
@tparam[opt] string iv
481
@tparam[opt] boolean pad true for padding default
482
@tparam[opt] engine engine custom crypto engine
483
@treturn evp_cipher_ctx evp_cipher_ctx object
484

485
@see evp_cipher_ctx
486
*/
487

488
/***
489
get evp_cipher_ctx to encrypt
490

491
@function encrypt_new
492
@tparam string key secret key
493
@tparam[opt] string iv
494
@tparam[opt] boolean pad true for padding default
495
@tparam[opt] engine engine custom crypto engine
496
@treturn evp_cipher_ctx evp_cipher_ctx object
497

498
@see evp_cipher_ctx
499
*/
500

501
/***
502
get evp_cipher_ctx to decrypt
503

504
@function decrypt_new
505
@tparam string key secret key
506
@tparam[opt] string iv
507
@tparam[opt] boolean pad true for padding default
508
@tparam[opt] engine engine custom crypto engine
509
@treturn evp_cipher_ctx evp_cipher_ctx object
510

511
@see evp_cipher_ctx
512
*/
513

514
/***
515
do encrypt or decrypt
516

517
@function cipher
518
@tparam boolean encrypt true for encrypt,false for decrypt
519
@tparam string input data to encrypt or decrypt
520
@tparam string key secret key
521
@tparam[opt] string iv
522
@tparam[opt] boolean pad true for padding default
523
@tparam[opt] engine engine custom crypto engine
524
@treturn string result
525
*/
526

527
/***
528
do encrypt
529

530
@function encrypt
531
@tparam string input data to encrypt
532
@tparam string key secret key
533
@tparam[opt] string iv
534
@tparam[opt] boolean pad true for padding default
535
@tparam[opt] engine engine custom crypto engine
536
@treturn string result
537
*/
538

539
/***
540
do decrypt
541

542
@function decrypt
543
@tparam string input data to decrypt
544
@tparam string key secret key
545
@tparam[opt] string iv
546
@tparam[opt] boolean pad true for padding default
547
@tparam[opt] engine engine custom crypto engine
548
@treturn string result
549
*/
550

551
/* evp_cipher_ctx method */
552
/***
553
openssl.evp_cipher_ctx object
554
@type evp_cipher_ctx
555
*/
556

557
/***
558
init encrypt/decrypt cipher ctx
559

560
@function init
561
@tparam string key secret key
562
@tparam[opt] string iv
563
@treturn boolean result and followd by error reason
564
*/
565

566
static int openssl_evp_cipher_init(lua_State *L)
90✔
567
{
568
  EVP_CIPHER_CTX *c = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
90✔
569
  int             ret;
570
  CIPHER_MODE     mode = 0;
90✔
571
  size_t          key_len = 0;
90✔
572
  const char     *key = luaL_checklstring(L, 2, &key_len);
90✔
573
  size_t          iv_len = 0;
90✔
574
  const char     *iv = luaL_optlstring(L, 3, NULL, &iv_len); /* can be NULL */
90✔
575

576
  lua_rawgetp(L, LUA_REGISTRYINDEX, c);
90✔
577
  mode = lua_tointeger(L, -1);
90✔
578
  lua_pop(L, 1);
90✔
579

580
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
90✔
581
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
90✔
582

583
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
90✔
584

585
  ret = 0;
90✔
586
  if (mode == DO_CIPHER) {
90✔
587
    int enc = lua_toboolean(L, 4);
12✔
588
    ret = EVP_CipherInit_ex(c,
12✔
589
                            NULL,
590
                            NULL,
591
                            key ? (const byte *)evp_key : NULL,
592
                            iv_len > 0 ? (const byte *)evp_iv : NULL,
12✔
593
                            enc);
594
  } else if (mode == DO_ENCRYPT)
78✔
595
    ret = EVP_EncryptInit_ex(
41✔
596
      c, NULL, NULL, key ? (const byte *)evp_key : NULL, iv_len > 0 ? (const byte *)evp_iv : NULL);
41✔
597
  else if (mode == DO_DECRYPT)
37✔
598
    ret = EVP_DecryptInit_ex(
37✔
599
      c, NULL, NULL, key ? (const byte *)evp_key : NULL, iv_len > 0 ? (const byte *)evp_iv : NULL);
37✔
600
  else
601
    luaL_error(L, "never go here");
×
602
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
90✔
603
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
90✔
604
  return openssl_pushresult(L, ret);
90✔
605
}
606

607
/***
608
feed data or set AAD to do cipher
609

610
@function update
611
@tparam string data message or AAD
612
@tparam[opt=false] boolean isAAD indicate to set AAD
613
@treturn string partial results, and "" when set AAD
614
*/
615
static int openssl_evp_cipher_update(lua_State *L)
282✔
616
{
617
  size_t      inl;
618
  const char *in;
619
  int         outl;
620
  char       *out;
621
  CIPHER_MODE mode;
622
  int         ret, isAAD = 0;
282✔
623

624
  EVP_CIPHER_CTX *c = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
282✔
625
  in = luaL_checklstring(L, 2, &inl);
282✔
626
  isAAD = lua_isnoneornil(L, 3) ? 0 : lua_toboolean(L, 3);
282✔
627
  outl = isAAD ? 0 : inl + EVP_MAX_BLOCK_LENGTH;
282✔
628
  out = isAAD ? 0 : OPENSSL_malloc(outl);
282✔
629

630
  lua_rawgetp(L, LUA_REGISTRYINDEX, c);
282✔
631
  mode = lua_tointeger(L, -1);
282✔
632
  lua_pop(L, 1);
282✔
633

634
  ret = 0;
282✔
635
  if (mode == DO_CIPHER)
282✔
636
    ret = EVP_CipherUpdate(c, (byte *)out, &outl, (const byte *)in, inl);
172✔
637
  else if (mode == DO_ENCRYPT)
110✔
638
    ret = EVP_EncryptUpdate(c, (byte *)out, &outl, (const byte *)in, inl);
57✔
639
  else if (mode == DO_DECRYPT)
53✔
640
    ret = EVP_DecryptUpdate(c, (byte *)out, &outl, (const byte *)in, inl);
53✔
641
  else
642
    luaL_error(L, "never go here");
×
643

644
  if (ret == 1) {
282✔
645
    if (isAAD)
282✔
646
      lua_pushliteral(L, "");
4✔
647
    else
648
      lua_pushlstring(L, out, outl);
278✔
649
  } else
650
    ret = openssl_pushresult(L, ret);
×
651

652
  OPENSSL_free(out);
282✔
653

654
  return ret;
282✔
655
}
656

657
/***
658
get result of cipher
659

660
@function final
661
@treturn string result last result
662
*/
663
static int openssl_evp_cipher_final(lua_State *L)
266✔
664
{
665
  EVP_CIPHER_CTX *c = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
266✔
666
  char            out[EVP_MAX_BLOCK_LENGTH];
667
  int             outl = sizeof(out);
266✔
668
  CIPHER_MODE     mode;
669
  int             ret = 0;
266✔
670

671
  lua_rawgetp(L, LUA_REGISTRYINDEX, c);
266✔
672
  mode = lua_tointeger(L, -1);
266✔
673

674
  if (mode == DO_CIPHER)
266✔
675
    ret = EVP_CipherFinal_ex(c, (byte *)out, &outl);
172✔
676
  else if (mode == DO_ENCRYPT)
94✔
677
    ret = EVP_EncryptFinal_ex(c, (byte *)out, &outl);
53✔
678
  else if (mode == DO_DECRYPT)
41✔
679
    ret = EVP_DecryptFinal_ex(c, (byte *)out, &outl);
41✔
680
  else
681
    luaL_error(L, "never go here");
×
682
  lua_pop(L, 1);
266✔
683

684
  if (ret == 1) {
266✔
685
    lua_pushlstring(L, out, outl);
262✔
686
    return 1;
262✔
687
  }
688
  return openssl_pushresult(L, ret);
4✔
689
}
690

691
/***
692
get infomation of evp_cipher_ctx object
693

694
@function info
695
@treturn table info keys include block_size,key_length,iv_length,flags,mode,nid,type, evp_cipher
696
*/
697
static int openssl_cipher_ctx_info(lua_State *L)
8✔
698
{
699
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
8✔
700
#if OPENSSL_VERSION_NUMBER > 0x30000000
701
  const EVP_CIPHER *cipher = EVP_CIPHER_CTX_get0_cipher(ctx);
4✔
702
#else
703
  const EVP_CIPHER *cipher = EVP_CIPHER_CTX_cipher(ctx);
4✔
704
#endif
705
  lua_newtable(L);
8✔
706
  AUXILIAR_SET(L, -1, "block_size", EVP_CIPHER_CTX_block_size(ctx), integer);
8✔
707
  AUXILIAR_SET(L, -1, "key_length", EVP_CIPHER_CTX_key_length(ctx), integer);
8✔
708
  AUXILIAR_SET(L, -1, "iv_length", EVP_CIPHER_CTX_iv_length(ctx), integer);
8✔
709
  AUXILIAR_SET(L, -1, "flags", EVP_CIPHER_flags(cipher), integer);
8✔
710
  AUXILIAR_SET(L, -1, "nid", EVP_CIPHER_CTX_nid(ctx), integer);
8✔
711
  AUXILIAR_SET(L, -1, "type", EVP_CIPHER_CTX_mode(ctx), integer);
8✔
712
  AUXILIAR_SET(L, -1, "mode", EVP_CIPHER_CTX_type(ctx), integer);
8✔
713

714
  AUXILIAR_SETOBJECT(L, cipher, "openssl.evp_cipher", -1, "cipher");
8✔
715
  return 1;
8✔
716
}
717

718
/***
719
set padding mode for cipher context
720
@function padding
721
@tparam boolean pad true to enable padding, false to disable
722
@treturn nil no return value
723
*/
724
static int openssl_cipher_ctx_padding(lua_State *L)
70✔
725
{
726
  int             pad;
727
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
70✔
728
  luaL_checkany(L, 2);
70✔
729

730
  pad = lua_toboolean(L, 2);
70✔
731
  EVP_CIPHER_CTX_set_padding(ctx, pad);
70✔
732
  return 0;
70✔
733
}
734

735
/***
736
control cipher context with various parameters
737
@function ctrl
738
@tparam number type control command type
739
@tparam number|string arg control argument
740
@treturn boolean|string result depends on control type
741
*/
742
static int openssl_cipher_ctx_ctrl(lua_State *L)
140✔
743
{
744
  int             ret = 0;
140✔
745
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
140✔
746
  int             type = luaL_checkint(L, 2);
140✔
747
  int             arg = 0;
140✔
748
  void           *ptr = NULL;
140✔
749

750
  switch (type) {
140✔
UNCOV
751
  case EVP_CTRL_INIT:
×
752
    ret = EVP_CIPHER_CTX_ctrl(ctx, type, 0, NULL);
×
753
    ret = openssl_pushresult(L, ret);
×
754
    break;
×
755
#if defined(EVP_CTRL_SET_KEY_LENGTH)
756
  /* NOTE: libressl 4.0.0 without EVP_CTRL_SET_KEY_LENGTH */
757
  case EVP_CTRL_SET_KEY_LENGTH:
70✔
758
#endif
759
  case EVP_CTRL_SET_RC2_KEY_BITS:
760
  case EVP_CTRL_SET_RC5_ROUNDS:
761
  case EVP_CTRL_GCM_SET_IVLEN:  // EVP_CTRL_CCM_SET_IVLEN
762
    arg = luaL_checkint(L, 3);
70✔
763
    ret = EVP_CIPHER_CTX_ctrl(ctx, type, arg, NULL);
70✔
764
    ret = openssl_pushresult(L, ret);
70✔
765
    break;
70✔
766
  case EVP_CTRL_GCM_SET_TAG:  // EVP_CTRL_CCM_SET_TAG
33✔
767
  {
768
    size_t sz = 0;
33✔
769
    luaL_argcheck(L, lua_isnumber(L, 3) || lua_isstring(L, 3), 3, "need integer or string");
33✔
770

771
    ptr = (void *)luaL_checklstring(L, 3, &sz);
33✔
772
    ret = EVP_CIPHER_CTX_ctrl(ctx, type, sz, ptr);
33✔
773

774
    ret = openssl_pushresult(L, ret);
33✔
775
    break;
33✔
776
  }
UNCOV
777
  case EVP_CTRL_GET_RC2_KEY_BITS:
×
778
  case EVP_CTRL_GET_RC5_ROUNDS:
UNCOV
779
    ret = EVP_CIPHER_CTX_ctrl(ctx, type, 0, &arg);
×
780
    if (ret == 1) {
×
781
      lua_pushinteger(L, arg);
×
782
      ret = 1;
×
783
    } else
UNCOV
784
      ret = openssl_pushresult(L, ret);
×
785
  case EVP_CTRL_GCM_GET_TAG:  // EVP_CTRL_CCM_GET_TAG
786
  {
787
    char buf[16];
788
    arg = luaL_checkint(L, 3);
37✔
789
    if (arg == 4 || arg == 6 || arg == 10 || arg == 12 || arg == 14 || arg == 16) {
37✔
790
      ret = EVP_CIPHER_CTX_ctrl(ctx, type, arg, buf);
37✔
791
      if (ret == 1) {
37✔
792
        lua_pushlstring(L, buf, arg);
37✔
793
        ret = 1;
37✔
794
      } else
UNCOV
795
        ret = openssl_pushresult(L, ret);
×
796
    } else
UNCOV
797
      luaL_argerror(L, 3, "invalid integer, must be 4, 6, 10, 12, 14 or 16");
×
798
    break;
37✔
799
  }
800
  /*
801
  EVP_CTRL_RAND_KEY
802
  EVP_CTRL_PBE_PRF_NID
803
  EVP_CTRL_COPY
804
  EVP_CTRL_GCM_SET_IV_FIXED
805
  EVP_CTRL_GCM_IV_GEN
806
  EVP_CTRL_CCM_SET_L
807
  EVP_CTRL_CCM_SET_MSGLEN
808
  EVP_CTRL_AEAD_TLS1_AAD
809
  EVP_CTRL_AEAD_SET_MAC_KEY
810
  EVP_CTRL_GCM_SET_IV_INV
811
  EVP_CTRL_TLS1_1_MULTIBLOCK_AAD
812
  EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT
813
  EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT
814
  EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE
815
  */
UNCOV
816
  default:
×
817
    luaL_error(L, "not support");
×
818
  }
819
  return ret;
140✔
820
}
821

822
/***
823
release cipher context resources
824
@function __gc
825
@treturn number 0
826
*/
827
static int openssl_cipher_ctx_free(lua_State *L)
286✔
828
{
829
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
286✔
830
  if (!ctx) return 0;
286✔
831
  lua_pushnil(L);
282✔
832
  lua_rawsetp(L, LUA_REGISTRYINDEX, ctx);
282✔
833
  EVP_CIPHER_CTX_free(ctx);
282✔
834
  FREE_OBJECT(1);
282✔
835
  return 0;
282✔
836
}
837

838
static luaL_Reg cipher_funs[] = {
839
  { "info",        openssl_cipher_info        },
840
  { "new",         openssl_cipher_new         },
841
  { "encrypt_new", openssl_cipher_encrypt_new },
842
  { "decrypt_new", openssl_cipher_decrypt_new },
843

844
  { "BytesToKey",  openssl_evp_BytesToKey     },
845

846
  { "encrypt",     openssl_evp_encrypt        },
847
  { "decrypt",     openssl_evp_decrypt        },
848
  { "cipher",      openssl_evp_cipher         },
849

850
  { "__tostring",  auxiliar_tostring          },
851

852
  { NULL,          NULL                       }
853
};
854

855
static luaL_Reg cipher_ctx_funs[] = {
856
  { "init",       openssl_evp_cipher_init    },
857
  { "update",     openssl_evp_cipher_update  },
858
  { "final",      openssl_evp_cipher_final   },
859
  { "info",       openssl_cipher_ctx_info    },
860
  { "close",      openssl_cipher_ctx_free    },
861
  { "ctrl",       openssl_cipher_ctx_ctrl    },
862
  { "padding",    openssl_cipher_ctx_padding },
863

864
  { "__gc",       openssl_cipher_ctx_free    },
865
  { "__tostring", auxiliar_tostring          },
866

867
  { NULL,         NULL                       }
868
};
869

870
static const luaL_Reg R[] = {
871
  { "list",        openssl_cipher_list        },
872
  { "get",         openssl_cipher_get         },
873
  { "encrypt",     openssl_evp_encrypt        },
874
  { "decrypt",     openssl_evp_decrypt        },
875
  { "cipher",      openssl_evp_cipher         },
876

877
  { "new",         openssl_cipher_new         },
878
  { "encrypt_new", openssl_cipher_encrypt_new },
879
  { "decrypt_new", openssl_cipher_decrypt_new },
880

881
  { NULL,          NULL                       }
882
};
883

884
static LuaL_Enumeration evp_ctrls_code[] = {
885
  { "EVP_CTRL_INIT",                          EVP_CTRL_INIT                          },
886
#if defined(EVP_CTRL_SET_KEY_LENGTH)
887
  { "EVP_CTRL_SET_KEY_LENGTH",                EVP_CTRL_SET_KEY_LENGTH                },
888
#endif
889
  { "EVP_CTRL_GET_RC2_KEY_BITS",              EVP_CTRL_GET_RC2_KEY_BITS              },
890
  { "EVP_CTRL_SET_RC2_KEY_BITS",              EVP_CTRL_SET_RC2_KEY_BITS              },
891
  { "EVP_CTRL_GET_RC5_ROUNDS",                EVP_CTRL_GET_RC5_ROUNDS                },
892
  { "EVP_CTRL_SET_RC5_ROUNDS",                EVP_CTRL_SET_RC5_ROUNDS                },
893
  { "EVP_CTRL_RAND_KEY",                      EVP_CTRL_RAND_KEY                      },
894
  { "EVP_CTRL_PBE_PRF_NID",                   EVP_CTRL_PBE_PRF_NID                   },
895
  { "EVP_CTRL_COPY",                          EVP_CTRL_COPY                          },
896
  { "EVP_CTRL_GCM_SET_IVLEN",                 EVP_CTRL_GCM_SET_IVLEN                 },
897
  { "EVP_CTRL_GCM_GET_TAG",                   EVP_CTRL_GCM_GET_TAG                   },
898
  { "EVP_CTRL_GCM_SET_TAG",                   EVP_CTRL_GCM_SET_TAG                   },
899
  { "EVP_CTRL_GCM_SET_IV_FIXED",              EVP_CTRL_GCM_SET_IV_FIXED              },
900
  { "EVP_CTRL_GCM_IV_GEN",                    EVP_CTRL_GCM_IV_GEN                    },
901
  { "EVP_CTRL_CCM_SET_IVLEN",                 EVP_CTRL_GCM_SET_IVLEN                 },
902
  { "EVP_CTRL_CCM_GET_TAG",                   EVP_CTRL_CCM_GET_TAG                   },
903
  { "EVP_CTRL_CCM_SET_TAG",                   EVP_CTRL_CCM_SET_TAG                   },
904
  { "EVP_CTRL_CCM_SET_L",                     EVP_CTRL_CCM_SET_L                     },
905
  { "EVP_CTRL_CCM_SET_MSGLEN",                EVP_CTRL_CCM_SET_MSGLEN                },
906
  { "EVP_CTRL_AEAD_TLS1_AAD",                 EVP_CTRL_AEAD_TLS1_AAD                 },
907
  { "EVP_CTRL_AEAD_SET_MAC_KEY",              EVP_CTRL_AEAD_SET_MAC_KEY              },
908
  { "EVP_CTRL_GCM_SET_IV_INV",                EVP_CTRL_GCM_SET_IV_INV                },
909

910
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
911
  { "EVP_CTRL_TLS1_1_MULTIBLOCK_AAD",         EVP_CTRL_TLS1_1_MULTIBLOCK_AAD         },
912
  { "EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT",     EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT     },
913
  { "EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT",     EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT     },
914
  { "EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE", EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE },
915
#endif
916

917
  { NULL,                                     -1                                     }
918
};
919

920
int
921
luaopen_cipher(lua_State *L)
43✔
922
{
923
  auxiliar_newclass(L, "openssl.evp_cipher", cipher_funs);
43✔
924
  auxiliar_newclass(L, "openssl.evp_cipher_ctx", cipher_ctx_funs);
43✔
925

926
  lua_newtable(L);
43✔
927
  luaL_setfuncs(L, R, 0);
43✔
928
  auxiliar_enumerate(L, -1, evp_ctrls_code);
43✔
929

930
  return 1;
43✔
931
}
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