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

zhaozg / lua-openssl / 14009379566

22 Mar 2025 02:16PM UTC coverage: 92.866% (-0.2%) from 93.095%
14009379566

push

travis-ci

zhaozg
update version

9399 of 10121 relevant lines covered (92.87%)

2144.86 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
*/
8
#include "openssl.h"
9
#include "private.h"
10

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

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

26
/***
27
get evp_cipher object
28

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

33
@see evp_cipher
34
*/
35
static LUA_FUNCTION(openssl_cipher_get)
84✔
36
{
37
  const EVP_CIPHER* cipher = get_cipher(L, 1, NULL);
84✔
38

39
  PUSH_OBJECT((void*)cipher, "openssl.evp_cipher");
84✔
40
  return 1;
84✔
41
}
42

43
static void set_key_iv(const char *key, size_t key_len, char *evp_key,
276✔
44
                       const char *iv, size_t iv_len, char *evp_iv) {
45
  if (key) {
276✔
46
    key_len = EVP_MAX_KEY_LENGTH > key_len ? key_len : EVP_MAX_KEY_LENGTH;
225✔
47
    memcpy(evp_key, key, key_len);
225✔
48
  }
49
  if (iv_len > 0 && iv) {
276✔
50
    iv_len = EVP_MAX_IV_LENGTH > iv_len ? iv_len : EVP_MAX_IV_LENGTH;
207✔
51
    memcpy(evp_iv, iv, iv_len);
207✔
52
  }
53
}
276✔
54

55
/***
56
quick encrypt
57

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

79
  EVP_CIPHER_CTX *c = EVP_CIPHER_CTX_new();
6✔
80

81
  int output_len = 0;
6✔
82
  int len = 0;
6✔
83
  char *buffer = NULL;
6✔
84
  char evp_key[EVP_MAX_KEY_LENGTH] = {0};
6✔
85
  char evp_iv[EVP_MAX_IV_LENGTH] = {0};
6✔
86
  int ret = 0;
6✔
87

88
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
6✔
89

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

123
/***
124
quick decrypt
125

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

148
  int output_len = 0;
6✔
149
  int len = 0;
6✔
150
  char *buffer = NULL;
6✔
151
  char evp_key[EVP_MAX_KEY_LENGTH] = {0};
6✔
152
  char evp_iv[EVP_MAX_IV_LENGTH] = {0};
6✔
153
  int ret;
154

155
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
6✔
156

157
  ret = EVP_DecryptInit_ex(c, cipher, e,
6✔
158
                           key ? (const byte*)evp_key : NULL,
159
                           iv_len > 0 ? (const byte*)evp_iv : NULL);
6✔
160
  if (ret == 1)
6✔
161
  {
162
    ret = EVP_CIPHER_CTX_set_padding(c, pad);
6✔
163
    if (ret == 1)
6✔
164
    {
165
      buffer = OPENSSL_malloc(input_len);
6✔
166
      if (buffer == NULL) {
6✔
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);
6✔
172
      if (ret == 1)
6✔
173
      {
174
        output_len += len;
6✔
175
        len = input_len - len;
6✔
176
        ret = EVP_DecryptFinal_ex(c, (byte*)buffer + output_len, &len);
6✔
177
        if (ret == 1)
6✔
178
        {
179
          output_len += len;
6✔
180
          lua_pushlstring(L, buffer, output_len);
6✔
181
        }
182
      }
183
      OPENSSL_free(buffer);
6✔
184
    }
185
  }
186
  EVP_CIPHER_CTX_free(c);
6✔
187
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
6✔
188
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
6✔
189
  return (ret == 1) ? ret : openssl_pushresult(L, ret);
6✔
190
}
191

192
/***
193
quick encrypt or decrypt
194

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

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

219
  EVP_CIPHER_CTX *c = EVP_CIPHER_CTX_new();
6✔
220

221
  int output_len = 0;
6✔
222
  int len = 0;
6✔
223

224
  char evp_key[EVP_MAX_KEY_LENGTH] = {0};
6✔
225
  char evp_iv[EVP_MAX_IV_LENGTH] = {0};
6✔
226

227
  int ret;
228

229
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
6✔
230

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

264
typedef enum
265
{
266
  DO_CIPHER = 0,
267
  DO_ENCRYPT = 1,
268
  DO_DECRYPT = 2
269
} CIPHER_MODE;
270

271
/***
272
get evp_cipher_ctx object for encrypt or decrypt
273

274
@function new
275
@tparam string|integer|asn1_object alg name, nid or object identity
276
@tparam boolean encrypt true for encrypt,false for decrypt
277
@tparam[opt] string key secret key
278
@tparam[opt] string iv
279
@tparam[opt=true] boolean pad true for padding
280
@tparam[opt] engine engine custom crypto engine
281
@treturn evp_cipher_ctx cipher object mapping EVP_CIPHER_CTX in openssl
282

283
@see evp_cipher_ctx
284
*/
285

286
static LUA_FUNCTION(openssl_cipher_new)
120✔
287
{
288
  const EVP_CIPHER* cipher = get_cipher(L, 1, NULL);
120✔
289
  int enc = lua_toboolean(L, 2);
120✔
290
  size_t key_len = 0;
120✔
291
  const char *key = luaL_optlstring(L, 3, NULL, &key_len);
120✔
292
  size_t iv_len = 0;
120✔
293
  const char *iv = luaL_optlstring(L, 4, NULL, &iv_len);
120✔
294
  int pad = lua_isnone(L, 5) ? 1 : lua_toboolean(L, 5);
120✔
295
  ENGINE *e = lua_isnoneornil(L, 6) ? NULL : CHECK_OBJECT(6, ENGINE, "openssl.engine");
120✔
296
  EVP_CIPHER_CTX *c = NULL;
120✔
297
  int ret = 0;
120✔
298

299
  char evp_key[EVP_MAX_KEY_LENGTH] = {0};
120✔
300
  char evp_iv[EVP_MAX_IV_LENGTH] = {0};
120✔
301

302
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
120✔
303

304
  c = EVP_CIPHER_CTX_new();
120✔
305
  ret = EVP_CipherInit_ex(c, cipher, e,
120✔
306
                          key ? (const byte*)evp_key : NULL,
307
                          iv_len > 0 ? (const byte*)evp_iv : NULL,
120✔
308
                          enc);
309
  if (ret==1)
120✔
310
  {
311
    EVP_CIPHER_CTX_set_padding(c, pad);
120✔
312
    PUSH_OBJECT(c, "openssl.evp_cipher_ctx");
120✔
313
    lua_pushinteger(L, DO_CIPHER);
120✔
314
    lua_rawsetp(L, LUA_REGISTRYINDEX, c);
120✔
315
    return 1;
120✔
316
  }
317
  EVP_CIPHER_CTX_free(c);
×
318
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
×
319
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
×
320
  return openssl_pushresult(L, ret);
×
321
}
322

323
/***
324
get evp_cipher_ctx object for encrypt
325

326
@function encrypt_new
327
@tparam string|integer|asn1_object alg name, nid or object identity
328
@tparam string key secret key
329
@tparam[opt] string iv
330
@tparam[opt] engine engine custom crypto engine
331
@tparam[opt=true] boolean pad true for padding
332
@treturn evp_cipher_ctx cipher object mapping EVP_CIPHER_CTX in openssl
333

334
@see evp_cipher_ctx
335
*/
336

337
static LUA_FUNCTION(openssl_cipher_encrypt_new)
36✔
338
{
339
  const EVP_CIPHER* cipher  = get_cipher(L, 1, NULL);
36✔
340
  int ret;
341
  size_t key_len = 0;
36✔
342
  const char *key = luaL_optlstring(L, 2, NULL, &key_len); /* can be NULL */
36✔
343
  size_t iv_len = 0;
36✔
344
  const char *iv = luaL_optlstring(L, 3, NULL, &iv_len); /* can be NULL */
36✔
345
  ENGINE *e = lua_isnoneornil(L, 4) ? NULL : CHECK_OBJECT(4, ENGINE, "openssl.engine");
36✔
346
  int pad = lua_isnone(L, 5) ? 1 : lua_toboolean(L, 5);
36✔
347

348
  EVP_CIPHER_CTX *c = NULL;
36✔
349

350
  char evp_key[EVP_MAX_KEY_LENGTH] = {0};
36✔
351
  char evp_iv[EVP_MAX_IV_LENGTH] = {0};
36✔
352

353
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
36✔
354

355
  c = EVP_CIPHER_CTX_new();
36✔
356
  ret = EVP_EncryptInit_ex(c, cipher, e,
36✔
357
                           key ? (const byte*)evp_key : NULL,
358
                           iv_len > 0 ? (const byte*)evp_iv : NULL);
36✔
359
  if (ret==1)
36✔
360
  {
361
    EVP_CIPHER_CTX_set_padding(c, pad);
36✔
362
    PUSH_OBJECT(c, "openssl.evp_cipher_ctx");
36✔
363
    lua_pushinteger(L, DO_ENCRYPT);
36✔
364
    lua_rawsetp(L, LUA_REGISTRYINDEX, c);
36✔
365
    return 1;
36✔
366
  }
367
  EVP_CIPHER_CTX_free(c);
×
368
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
×
369
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
×
370
  return openssl_pushresult(L, ret);
×
371
}
372

373
/***
374
get evp_cipher_ctx object for decrypt
375

376
@function decrypt_new
377
@tparam string|integer|asn1_object alg name, nid or object identity
378
@tparam string key secret key
379
@tparam[opt] string iv
380
@tparam[opt] engine engine custom crypto engine
381
@tparam[opt=true] boolean pad true for padding
382
@treturn evp_cipher_ctx cipher object mapping EVP_CIPHER_CTX in openssl
383

384
@see evp_cipher_ctx
385
*/
386

387
static LUA_FUNCTION(openssl_cipher_decrypt_new)
36✔
388
{
389
  const EVP_CIPHER* cipher = get_cipher(L, 1, NULL);
36✔
390
  size_t key_len = 0;
36✔
391
  const char *key = luaL_optlstring(L, 2, NULL, &key_len); /* can be NULL */
36✔
392
  size_t iv_len = 0;
36✔
393
  const char *iv = luaL_optlstring(L, 3, NULL, &iv_len); /* can be NULL */
36✔
394
  ENGINE *e = lua_isnoneornil(L, 4) ? NULL : CHECK_OBJECT(4, ENGINE, "openssl.engine");
36✔
395
  int pad = lua_isnone(L, 5) ? 1 : lua_toboolean(L, 5);
36✔
396
  EVP_CIPHER_CTX *c = NULL;
36✔
397

398
  char evp_key[EVP_MAX_KEY_LENGTH] = {0};
36✔
399
  char evp_iv[EVP_MAX_IV_LENGTH] = {0};
36✔
400
  int ret;
401

402
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
36✔
403

404
  c = EVP_CIPHER_CTX_new();
36✔
405
  ret = EVP_DecryptInit_ex(c, cipher, e,
36✔
406
                           key ? (const byte*)evp_key : NULL,
407
                           iv_len > 0 ? (const byte*)evp_iv : NULL);
36✔
408
  if (ret == 1)
36✔
409
  {
410
    EVP_CIPHER_CTX_set_padding(c, pad);
36✔
411
    PUSH_OBJECT(c, "openssl.evp_cipher_ctx");
36✔
412
    lua_pushinteger(L, DO_DECRYPT);
36✔
413
    lua_rawsetp(L, LUA_REGISTRYINDEX, c);
36✔
414
    return 1;
36✔
415
  }
416
  EVP_CIPHER_CTX_free(c);
×
417
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
×
418
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
×
419
  return openssl_pushresult(L, ret);
×
420
}
421

422
/***
423
openssl.evp_cipher object
424
@type evp_cipher
425
*/
426
/***
427
get infomation of evp_cipher object
428

429
@function info
430
@treturn table info keys include name,block_size,key_length,iv_length,flags,mode
431
*/
432
static LUA_FUNCTION(openssl_cipher_info)
81✔
433
{
434
  EVP_CIPHER *cipher = CHECK_OBJECT(1, EVP_CIPHER, "openssl.evp_cipher");
81✔
435
  lua_newtable(L);
81✔
436
  AUXILIAR_SET(L, -1, "name", EVP_CIPHER_name(cipher), string);
81✔
437
  AUXILIAR_SET(L, -1, "block_size", EVP_CIPHER_block_size(cipher), integer);
81✔
438
  AUXILIAR_SET(L, -1, "key_length", EVP_CIPHER_key_length(cipher), integer);
81✔
439
  AUXILIAR_SET(L, -1, "iv_length", EVP_CIPHER_iv_length(cipher), integer);
81✔
440
  AUXILIAR_SET(L, -1, "flags", EVP_CIPHER_flags(cipher), integer);
81✔
441
  AUXILIAR_SET(L, -1, "mode", EVP_CIPHER_mode(cipher), integer);
81✔
442
  return 1;
81✔
443
}
444

445
/***
446
derive key
447

448
@function BytesToKey
449
@tparam string data derive data
450
@tparam string[opt] string salt salt will get strong security
451
@tparam ev_digest|string md digest method used to diver key, default with 'sha1'
452
@treturn string key
453
@treturn string iv
454
*/
455
static LUA_FUNCTION(openssl_evp_BytesToKey)
6✔
456
{
457
  EVP_CIPHER* c = CHECK_OBJECT(1, EVP_CIPHER, "openssl.evp_cipher");
6✔
458
  size_t lsalt, lk;
459
  const char* k = luaL_checklstring(L, 2, &lk);
6✔
460
  const char* salt = luaL_optlstring(L, 3, NULL, &lsalt);
6✔
461
  const EVP_MD* m = get_digest(L, 4, "sha256");
6✔
462
  char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
463
  int ret;
464
  if (salt != NULL && lsalt < PKCS5_SALT_LEN)
6✔
465
  {
466
    lua_pushfstring(L, "salt must not shorter than %d", PKCS5_SALT_LEN);
×
467
    luaL_argerror(L, 3, lua_tostring(L, -1));
×
468
  }
469

470
  ret = EVP_BytesToKey(c, m, (unsigned char*)salt, (unsigned char*)k, lk, 1, (unsigned char*)key, (unsigned char*)iv);
6✔
471
  if (ret > 1)
6✔
472
  {
473
    lua_pushlstring(L, key, EVP_CIPHER_key_length(c));
6✔
474
    lua_pushlstring(L, iv, EVP_CIPHER_iv_length(c));
6✔
475
    return 2;
6✔
476
  }
477
  return openssl_pushresult(L, ret);
×
478
}
479

480
/***
481
get evp_cipher_ctx to encrypt or decrypt
482

483
@function new
484
@tparam boolean encrypt true for encrypt,false for decrypt
485
@tparam string key secret key
486
@tparam[opt] string iv
487
@tparam[opt] boolean pad true for padding default
488
@tparam[opt] engine engine custom crypto engine
489
@treturn evp_cipher_ctx evp_cipher_ctx object
490

491
@see evp_cipher_ctx
492
*/
493

494
/***
495
get evp_cipher_ctx to encrypt
496

497
@function encrypt_new
498
@tparam string key secret key
499
@tparam[opt] string iv
500
@tparam[opt] boolean pad true for padding default
501
@tparam[opt] engine engine custom crypto engine
502
@treturn evp_cipher_ctx evp_cipher_ctx object
503

504
@see evp_cipher_ctx
505
*/
506

507
/***
508
get evp_cipher_ctx to decrypt
509

510
@function decrypt_new
511
@tparam string key secret key
512
@tparam[opt] string iv
513
@tparam[opt] boolean pad true for padding default
514
@tparam[opt] engine engine custom crypto engine
515
@treturn evp_cipher_ctx evp_cipher_ctx object
516

517
@see evp_cipher_ctx
518
*/
519

520
/***
521
do encrypt or decrypt
522

523
@function cipher
524
@tparam boolean encrypt true for encrypt,false for decrypt
525
@tparam string input data to encrypt or decrypt
526
@tparam string key secret key
527
@tparam[opt] string iv
528
@tparam[opt] boolean pad true for padding default
529
@tparam[opt] engine engine custom crypto engine
530
@treturn string result
531
*/
532

533
/***
534
do encrypt
535

536
@function encrypt
537
@tparam string input data to encrypt
538
@tparam string key secret key
539
@tparam[opt] string iv
540
@tparam[opt] boolean pad true for padding default
541
@tparam[opt] engine engine custom crypto engine
542
@treturn string result
543
*/
544

545
/***
546
do decrypt
547

548
@function decrypt
549
@tparam string input data to decrypt
550
@tparam string key secret key
551
@tparam[opt] string iv
552
@tparam[opt] boolean pad true for padding default
553
@tparam[opt] engine engine custom crypto engine
554
@treturn string result
555
*/
556

557
/* evp_cipher_ctx method */
558
/***
559
openssl.evp_cipher_ctx object
560
@type evp_cipher_ctx
561
*/
562

563
/***
564
init encrypt/decrypt cipher ctx
565

566
@function init
567
@tparam string key secret key
568
@tparam[opt] string iv
569
@treturn boolean result and followd by error reason
570
*/
571

572
static LUA_FUNCTION(openssl_evp_cipher_init)
66✔
573
{
574
  EVP_CIPHER_CTX* c = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
66✔
575
  int ret;
576
  CIPHER_MODE mode = 0;
66✔
577
  size_t key_len = 0;
66✔
578
  const char *key = luaL_checklstring(L, 2, &key_len);
66✔
579
  size_t iv_len = 0;
66✔
580
  const char *iv = luaL_optlstring(L, 3, NULL, &iv_len); /* can be NULL */
66✔
581

582
  lua_rawgetp(L, LUA_REGISTRYINDEX, c);
66✔
583
  mode = lua_tointeger(L, -1);
66✔
584
  lua_pop(L, 1);
66✔
585

586
  char evp_key[EVP_MAX_KEY_LENGTH] = {0};
66✔
587
  char evp_iv[EVP_MAX_IV_LENGTH] = {0};
66✔
588

589
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
66✔
590

591
  ret = 0;
66✔
592
  if (mode == DO_CIPHER) {
66✔
593
    int enc = lua_toboolean(L, 4);
9✔
594
    ret = EVP_CipherInit_ex(c, NULL, NULL,
9✔
595
                            key ? (const byte*)evp_key : NULL,
596
                            iv_len > 0 ? (const byte*)evp_iv : NULL, enc);
9✔
597
  }
598
  else if (mode == DO_ENCRYPT)
57✔
599
    ret = EVP_EncryptInit_ex(c, NULL, NULL,
30✔
600
                             key ? (const byte*)evp_key : NULL,
601
                             iv_len > 0 ? (const byte*)evp_iv : NULL);
30✔
602
  else if (mode == DO_DECRYPT)
27✔
603
    ret = EVP_DecryptInit_ex(c, NULL, NULL,
27✔
604
                             key ? (const byte*)evp_key : NULL,
605
                             iv_len > 0 ? (const byte*)evp_iv : NULL);
27✔
606
  else
607
    luaL_error(L, "never go here");
×
608
  OPENSSL_cleanse(evp_key, sizeof(evp_key));
66✔
609
  OPENSSL_cleanse(evp_iv, sizeof(evp_iv));
66✔
610
  return openssl_pushresult(L, ret);
66✔
611
}
612

613
/***
614
feed data or set AAD to do cipher
615

616
@function update
617
@tparam string data message or AAD
618
@tparam[opt=false] boolean isAAD indicate to set AAD
619
@treturn string partial results, and "" when set AAD
620
*/
621
static LUA_FUNCTION(openssl_evp_cipher_update)
210✔
622
{
623
  size_t inl;
624
  const char *in;
625
  int outl;
626
  char *out;
627
  CIPHER_MODE mode;
628
  int ret, isAAD = 0;
210✔
629

630
  EVP_CIPHER_CTX* c = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
210✔
631
  in = luaL_checklstring(L, 2, &inl);
210✔
632
  isAAD = lua_isnoneornil(L, 3) ? 0 : lua_toboolean(L, 3);
210✔
633
  outl = isAAD ? 0 : inl + EVP_MAX_BLOCK_LENGTH;
210✔
634
  out = isAAD ? 0 : OPENSSL_malloc(outl);
210✔
635

636
  lua_rawgetp(L, LUA_REGISTRYINDEX, c);
210✔
637
  mode = lua_tointeger(L, -1);
210✔
638
  lua_pop(L, 1);
210✔
639

640
  ret = 0;
210✔
641
  if (mode == DO_CIPHER)
210✔
642
    ret = EVP_CipherUpdate(c, (byte*)out, &outl, (const byte*)in, inl);
129✔
643
  else if (mode == DO_ENCRYPT)
81✔
644
    ret = EVP_EncryptUpdate(c, (byte*)out, &outl, (const byte*)in, inl);
42✔
645
  else if (mode == DO_DECRYPT)
39✔
646
    ret = EVP_DecryptUpdate(c, (byte*)out, &outl, (const byte*)in, inl);
39✔
647
  else
648
    luaL_error(L, "never go here");
×
649

650
  if (ret == 1) {
210✔
651
    if (isAAD)
210✔
652
      lua_pushliteral(L, "");
3✔
653
    else
654
      lua_pushlstring(L, out, outl);
207✔
655
  }
656
  else
657
    ret = openssl_pushresult(L, ret);
×
658

659
  OPENSSL_free(out);
210✔
660

661
  return ret;
210✔
662
}
663

664
/***
665
get result of cipher
666

667
@function final
668
@treturn string result last result
669
*/
670
static LUA_FUNCTION(openssl_evp_cipher_final)
198✔
671
{
672
  EVP_CIPHER_CTX* c = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
198✔
673
  char out[EVP_MAX_BLOCK_LENGTH];
674
  int outl = sizeof(out);
198✔
675
  CIPHER_MODE mode;
676
  int ret = 0;
198✔
677

678
  lua_rawgetp(L, LUA_REGISTRYINDEX, c);
198✔
679
  mode = lua_tointeger(L, -1);
198✔
680

681
  if (mode == DO_CIPHER)
198✔
682
    ret = EVP_CipherFinal_ex(c, (byte*)out, &outl);
129✔
683
  else if (mode == DO_ENCRYPT)
69✔
684
    ret = EVP_EncryptFinal_ex(c, (byte*)out, &outl);
39✔
685
  else if (mode == DO_DECRYPT)
30✔
686
    ret = EVP_DecryptFinal_ex(c, (byte*)out, &outl);
30✔
687
  else
688
    luaL_error(L, "never go here");
×
689
  lua_pop(L, 1);
198✔
690

691
  if (ret == 1)
198✔
692
  {
693
    lua_pushlstring(L, out, outl);
195✔
694
    return 1;
195✔
695
  }
696
  return openssl_pushresult(L, ret);
3✔
697
}
698

699
/***
700
get infomation of evp_cipher_ctx object
701

702
@function info
703
@treturn table info keys include block_size,key_length,iv_length,flags,mode,nid,type, evp_cipher
704
*/
705
static LUA_FUNCTION(openssl_cipher_ctx_info)
6✔
706
{
707
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
6✔
708
#if OPENSSL_VERSION_NUMBER > 0x30000000
709
  const EVP_CIPHER *cipher = EVP_CIPHER_CTX_get0_cipher(ctx);
710
#else
711
  const EVP_CIPHER *cipher = EVP_CIPHER_CTX_cipher(ctx);
6✔
712
#endif
713
  lua_newtable(L);
6✔
714
  AUXILIAR_SET(L, -1, "block_size", EVP_CIPHER_CTX_block_size(ctx), integer);
6✔
715
  AUXILIAR_SET(L, -1, "key_length", EVP_CIPHER_CTX_key_length(ctx), integer);
6✔
716
  AUXILIAR_SET(L, -1, "iv_length", EVP_CIPHER_CTX_iv_length(ctx), integer);
6✔
717
  AUXILIAR_SET(L, -1, "flags", EVP_CIPHER_flags(cipher), integer);
6✔
718
  AUXILIAR_SET(L, -1, "nid", EVP_CIPHER_CTX_nid(ctx), integer);
6✔
719
  AUXILIAR_SET(L, -1, "type", EVP_CIPHER_CTX_mode(ctx), integer);
6✔
720
  AUXILIAR_SET(L, -1, "mode", EVP_CIPHER_CTX_type(ctx), integer);
6✔
721

722
  AUXILIAR_SETOBJECT(L, cipher, "openssl.evp_cipher", -1, "cipher");
6✔
723
  return 1;
6✔
724
}
725

726
static LUA_FUNCTION(openssl_cipher_ctx_padding)
51✔
727
{
728
  int pad;
729
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
51✔
730
  luaL_checkany(L, 2);
51✔
731

732
  pad = lua_toboolean(L, 2);
51✔
733
  EVP_CIPHER_CTX_set_padding(ctx, pad);
51✔
734
  return 0;
51✔
735
}
736

737
static LUA_FUNCTION(openssl_cipher_ctx_ctrl)
102✔
738
{
739
  int ret = 0;
102✔
740
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
102✔
741
  int type = luaL_checkint(L, 2);
102✔
742
  int arg = 0;
102✔
743
  void *ptr = NULL;
102✔
744

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

767
    ptr = (void*)luaL_checklstring(L, 3, &sz);
24✔
768
    ret = EVP_CIPHER_CTX_ctrl(ctx, type, sz, ptr);
24✔
769

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

823
static LUA_FUNCTION(openssl_cipher_ctx_free)
213✔
824
{
825
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
213✔
826
  if(!ctx)
213✔
827
    return 0;
3✔
828
  lua_pushnil(L);
210✔
829
  lua_rawsetp(L, LUA_REGISTRYINDEX, ctx);
210✔
830
  EVP_CIPHER_CTX_free(ctx);
210✔
831
  FREE_OBJECT(1);
210✔
832
  return 0;
210✔
833
}
834

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

842
  {"BytesToKey",  openssl_evp_BytesToKey},
843

844
  {"encrypt",     openssl_evp_encrypt },
845
  {"decrypt",     openssl_evp_decrypt },
846
  {"cipher",      openssl_evp_cipher },
847

848
  {"__tostring",  auxiliar_tostring},
849

850
  {NULL, NULL}
851
};
852

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

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

866
  {NULL, NULL}
867
};
868

869
static const luaL_Reg R[] =
870
{
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
{
886
  {"EVP_CTRL_INIT",                           EVP_CTRL_INIT},
887
#if defined(EVP_CTRL_SET_KEY_LENGTH)
888
  {"EVP_CTRL_SET_KEY_LENGTH",                 EVP_CTRL_SET_KEY_LENGTH},
889
#endif
890
  {"EVP_CTRL_GET_RC2_KEY_BITS",               EVP_CTRL_GET_RC2_KEY_BITS},
891
  {"EVP_CTRL_SET_RC2_KEY_BITS",               EVP_CTRL_SET_RC2_KEY_BITS},
892
  {"EVP_CTRL_GET_RC5_ROUNDS",                 EVP_CTRL_GET_RC5_ROUNDS},
893
  {"EVP_CTRL_SET_RC5_ROUNDS",                 EVP_CTRL_SET_RC5_ROUNDS},
894
  {"EVP_CTRL_RAND_KEY",                       EVP_CTRL_RAND_KEY},
895
  {"EVP_CTRL_PBE_PRF_NID",                    EVP_CTRL_PBE_PRF_NID},
896
  {"EVP_CTRL_COPY",                           EVP_CTRL_COPY},
897
  {"EVP_CTRL_GCM_SET_IVLEN",                  EVP_CTRL_GCM_SET_IVLEN},
898
  {"EVP_CTRL_GCM_GET_TAG",                    EVP_CTRL_GCM_GET_TAG},
899
  {"EVP_CTRL_GCM_SET_TAG",                    EVP_CTRL_GCM_SET_TAG},
900
  {"EVP_CTRL_GCM_SET_IV_FIXED",               EVP_CTRL_GCM_SET_IV_FIXED},
901
  {"EVP_CTRL_GCM_IV_GEN",                     EVP_CTRL_GCM_IV_GEN},
902
  {"EVP_CTRL_CCM_SET_IVLEN",                  EVP_CTRL_GCM_SET_IVLEN},
903
  {"EVP_CTRL_CCM_GET_TAG",                    EVP_CTRL_CCM_GET_TAG},
904
  {"EVP_CTRL_CCM_SET_TAG",                    EVP_CTRL_CCM_SET_TAG},
905
  {"EVP_CTRL_CCM_SET_L",                      EVP_CTRL_CCM_SET_L},
906
  {"EVP_CTRL_CCM_SET_MSGLEN",                 EVP_CTRL_CCM_SET_MSGLEN},
907
  {"EVP_CTRL_AEAD_TLS1_AAD",                  EVP_CTRL_AEAD_TLS1_AAD},
908
  {"EVP_CTRL_AEAD_SET_MAC_KEY",               EVP_CTRL_AEAD_SET_MAC_KEY},
909
  {"EVP_CTRL_GCM_SET_IV_INV",                 EVP_CTRL_GCM_SET_IV_INV},
910

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

918
  {NULL,                    -1}
919
};
920

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

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

930
  return 1;
27✔
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