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

zhaozg / lua-openssl / 14016924506

23 Mar 2025 07:55AM UTC coverage: 93.18% (+0.3%) from 92.866%
14016924506

push

travis-ci

zhaozg
style: .clang-format

3374 of 3453 new or added lines in 34 files covered. (97.71%)

148 existing lines in 23 files now uncovered.

9291 of 9971 relevant lines covered (93.18%)

1907.56 hits per line

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

90.24
/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(
12✔
23
    OBJ_NAME_TYPE_CIPHER_METH, alias ? openssl_add_method_or_alias : openssl_add_method, L);
24
  return 1;
12✔
25
}
26

27
/***
28
get evp_cipher object
29

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

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

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

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

62
/***
63
quick encrypt
64

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

86
  EVP_CIPHER_CTX *c = EVP_CIPHER_CTX_new();
6✔
87

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

95
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
6✔
96

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

125
/***
126
quick decrypt
127

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

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

157
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
6✔
158

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

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

189
/***
190
quick encrypt or decrypt
191

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

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

216
  EVP_CIPHER_CTX *c = EVP_CIPHER_CTX_new();
6✔
217

218
  int output_len = 0;
6✔
219
  int len = 0;
6✔
220

221
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
6✔
222
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
6✔
223

224
  int ret;
225

226
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
6✔
227

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

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

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

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

274
@see evp_cipher_ctx
275
*/
276

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

290
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
120✔
291
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
120✔
292

293
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
120✔
294

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

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

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

326
@see evp_cipher_ctx
327
*/
328

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

340
  EVP_CIPHER_CTX *c = NULL;
36✔
341

342
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
36✔
343
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
36✔
344

345
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
36✔
346

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

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

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

374
@see evp_cipher_ctx
375
*/
376

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

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

392
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
36✔
393

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

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

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

433
/***
434
derive key
435

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

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

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

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

484
@see evp_cipher_ctx
485
*/
486

487
/***
488
get evp_cipher_ctx to encrypt
489

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

497
@see evp_cipher_ctx
498
*/
499

500
/***
501
get evp_cipher_ctx to decrypt
502

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

510
@see evp_cipher_ctx
511
*/
512

513
/***
514
do encrypt or decrypt
515

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

526
/***
527
do encrypt
528

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

538
/***
539
do decrypt
540

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

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

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

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

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

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

579
  char evp_key[EVP_MAX_KEY_LENGTH] = { 0 };
66✔
580
  char evp_iv[EVP_MAX_IV_LENGTH] = { 0 };
66✔
581

582
  set_key_iv(key, key_len, evp_key, iv, iv_len, evp_iv);
66✔
583

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

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

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

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

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

633
  ret = 0;
210✔
634
  if (mode == DO_CIPHER)
210✔
635
    ret = EVP_CipherUpdate(c, (byte *)out, &outl, (const byte *)in, inl);
129✔
636
  else if (mode == DO_ENCRYPT)
81✔
637
    ret = EVP_EncryptUpdate(c, (byte *)out, &outl, (const byte *)in, inl);
42✔
638
  else if (mode == DO_DECRYPT)
39✔
639
    ret = EVP_DecryptUpdate(c, (byte *)out, &outl, (const byte *)in, inl);
39✔
640
  else
641
    luaL_error(L, "never go here");
×
642

643
  if (ret == 1) {
210✔
644
    if (isAAD)
210✔
645
      lua_pushliteral(L, "");
3✔
646
    else
647
      lua_pushlstring(L, out, outl);
207✔
648
  } else
UNCOV
649
    ret = openssl_pushresult(L, ret);
×
650

651
  OPENSSL_free(out);
210✔
652

653
  return ret;
210✔
654
}
655

656
/***
657
get result of cipher
658

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

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

673
  if (mode == DO_CIPHER)
198✔
674
    ret = EVP_CipherFinal_ex(c, (byte *)out, &outl);
129✔
675
  else if (mode == DO_ENCRYPT)
69✔
676
    ret = EVP_EncryptFinal_ex(c, (byte *)out, &outl);
39✔
677
  else if (mode == DO_DECRYPT)
30✔
678
    ret = EVP_DecryptFinal_ex(c, (byte *)out, &outl);
30✔
679
  else
680
    luaL_error(L, "never go here");
×
681
  lua_pop(L, 1);
198✔
682

683
  if (ret == 1) {
198✔
684
    lua_pushlstring(L, out, outl);
195✔
685
    return 1;
195✔
686
  }
687
  return openssl_pushresult(L, ret);
3✔
688
}
689

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

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

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

717
static LUA_FUNCTION(openssl_cipher_ctx_padding)
51✔
718
{
719
  int             pad;
720
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
51✔
721
  luaL_checkany(L, 2);
51✔
722

723
  pad = lua_toboolean(L, 2);
51✔
724
  EVP_CIPHER_CTX_set_padding(ctx, pad);
51✔
725
  return 0;
51✔
726
}
727

728
static LUA_FUNCTION(openssl_cipher_ctx_ctrl)
102✔
729
{
730
  int             ret = 0;
102✔
731
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
102✔
732
  int             type = luaL_checkint(L, 2);
102✔
733
  int             arg = 0;
102✔
734
  void           *ptr = NULL;
102✔
735

736
  switch (type) {
102✔
UNCOV
737
  case EVP_CTRL_INIT:
×
738
    ret = EVP_CIPHER_CTX_ctrl(ctx, type, 0, NULL);
×
739
    ret = openssl_pushresult(L, ret);
×
740
    break;
×
741
#if defined(EVP_CTRL_SET_KEY_LENGTH)
742
  /* NOTE: libressl 4.0.0 without EVP_CTRL_SET_KEY_LENGTH */
743
  case EVP_CTRL_SET_KEY_LENGTH:
51✔
744
#endif
745
  case EVP_CTRL_SET_RC2_KEY_BITS:
746
  case EVP_CTRL_SET_RC5_ROUNDS:
747
  case EVP_CTRL_GCM_SET_IVLEN:  // EVP_CTRL_CCM_SET_IVLEN
748
    arg = luaL_checkint(L, 3);
51✔
749
    ret = EVP_CIPHER_CTX_ctrl(ctx, type, arg, NULL);
51✔
750
    ret = openssl_pushresult(L, ret);
51✔
751
    break;
51✔
752
  case EVP_CTRL_GCM_SET_TAG:  // EVP_CTRL_CCM_SET_TAG
24✔
753
  {
754
    size_t sz = 0;
24✔
755
    luaL_argcheck(L, lua_isnumber(L, 3) || lua_isstring(L, 3), 3, "need integer or string");
24✔
756

757
    ptr = (void *)luaL_checklstring(L, 3, &sz);
24✔
758
    ret = EVP_CIPHER_CTX_ctrl(ctx, type, sz, ptr);
24✔
759

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

808
static LUA_FUNCTION(openssl_cipher_ctx_free)
213✔
809
{
810
  EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx");
213✔
811
  if (!ctx) return 0;
213✔
812
  lua_pushnil(L);
210✔
813
  lua_rawsetp(L, LUA_REGISTRYINDEX, ctx);
210✔
814
  EVP_CIPHER_CTX_free(ctx);
210✔
815
  FREE_OBJECT(1);
210✔
816
  return 0;
210✔
817
}
818

819
static luaL_Reg cipher_funs[] = {
820
  { "info",        openssl_cipher_info        },
821
  { "new",         openssl_cipher_new         },
822
  { "encrypt_new", openssl_cipher_encrypt_new },
823
  { "decrypt_new", openssl_cipher_decrypt_new },
824

825
  { "BytesToKey",  openssl_evp_BytesToKey     },
826

827
  { "encrypt",     openssl_evp_encrypt        },
828
  { "decrypt",     openssl_evp_decrypt        },
829
  { "cipher",      openssl_evp_cipher         },
830

831
  { "__tostring",  auxiliar_tostring          },
832

833
  { NULL,          NULL                       }
834
};
835

836
static luaL_Reg cipher_ctx_funs[] = {
837
  { "init",       openssl_evp_cipher_init    },
838
  { "update",     openssl_evp_cipher_update  },
839
  { "final",      openssl_evp_cipher_final   },
840
  { "info",       openssl_cipher_ctx_info    },
841
  { "close",      openssl_cipher_ctx_free    },
842
  { "ctrl",       openssl_cipher_ctx_ctrl    },
843
  { "padding",    openssl_cipher_ctx_padding },
844

845
  { "__gc",       openssl_cipher_ctx_free    },
846
  { "__tostring", auxiliar_tostring          },
847

848
  { NULL,         NULL                       }
849
};
850

851
static const luaL_Reg R[] = {
852
  { "list",        openssl_cipher_list        },
853
  { "get",         openssl_cipher_get         },
854
  { "encrypt",     openssl_evp_encrypt        },
855
  { "decrypt",     openssl_evp_decrypt        },
856
  { "cipher",      openssl_evp_cipher         },
857

858
  { "new",         openssl_cipher_new         },
859
  { "encrypt_new", openssl_cipher_encrypt_new },
860
  { "decrypt_new", openssl_cipher_decrypt_new },
861

862
  { NULL,          NULL                       }
863
};
864

865
static LuaL_Enumeration evp_ctrls_code[] = {
866
  { "EVP_CTRL_INIT",                          EVP_CTRL_INIT                          },
867
#if defined(EVP_CTRL_SET_KEY_LENGTH)
868
  { "EVP_CTRL_SET_KEY_LENGTH",                EVP_CTRL_SET_KEY_LENGTH                },
869
#endif
870
  { "EVP_CTRL_GET_RC2_KEY_BITS",              EVP_CTRL_GET_RC2_KEY_BITS              },
871
  { "EVP_CTRL_SET_RC2_KEY_BITS",              EVP_CTRL_SET_RC2_KEY_BITS              },
872
  { "EVP_CTRL_GET_RC5_ROUNDS",                EVP_CTRL_GET_RC5_ROUNDS                },
873
  { "EVP_CTRL_SET_RC5_ROUNDS",                EVP_CTRL_SET_RC5_ROUNDS                },
874
  { "EVP_CTRL_RAND_KEY",                      EVP_CTRL_RAND_KEY                      },
875
  { "EVP_CTRL_PBE_PRF_NID",                   EVP_CTRL_PBE_PRF_NID                   },
876
  { "EVP_CTRL_COPY",                          EVP_CTRL_COPY                          },
877
  { "EVP_CTRL_GCM_SET_IVLEN",                 EVP_CTRL_GCM_SET_IVLEN                 },
878
  { "EVP_CTRL_GCM_GET_TAG",                   EVP_CTRL_GCM_GET_TAG                   },
879
  { "EVP_CTRL_GCM_SET_TAG",                   EVP_CTRL_GCM_SET_TAG                   },
880
  { "EVP_CTRL_GCM_SET_IV_FIXED",              EVP_CTRL_GCM_SET_IV_FIXED              },
881
  { "EVP_CTRL_GCM_IV_GEN",                    EVP_CTRL_GCM_IV_GEN                    },
882
  { "EVP_CTRL_CCM_SET_IVLEN",                 EVP_CTRL_GCM_SET_IVLEN                 },
883
  { "EVP_CTRL_CCM_GET_TAG",                   EVP_CTRL_CCM_GET_TAG                   },
884
  { "EVP_CTRL_CCM_SET_TAG",                   EVP_CTRL_CCM_SET_TAG                   },
885
  { "EVP_CTRL_CCM_SET_L",                     EVP_CTRL_CCM_SET_L                     },
886
  { "EVP_CTRL_CCM_SET_MSGLEN",                EVP_CTRL_CCM_SET_MSGLEN                },
887
  { "EVP_CTRL_AEAD_TLS1_AAD",                 EVP_CTRL_AEAD_TLS1_AAD                 },
888
  { "EVP_CTRL_AEAD_SET_MAC_KEY",              EVP_CTRL_AEAD_SET_MAC_KEY              },
889
  { "EVP_CTRL_GCM_SET_IV_INV",                EVP_CTRL_GCM_SET_IV_INV                },
890

891
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
892
  { "EVP_CTRL_TLS1_1_MULTIBLOCK_AAD",         EVP_CTRL_TLS1_1_MULTIBLOCK_AAD         },
893
  { "EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT",     EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT     },
894
  { "EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT",     EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT     },
895
  { "EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE", EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE },
896
#endif
897

898
  { NULL,                                     -1                                     }
899
};
900

901
int
902
luaopen_cipher(lua_State *L)
27✔
903
{
904
  auxiliar_newclass(L, "openssl.evp_cipher", cipher_funs);
27✔
905
  auxiliar_newclass(L, "openssl.evp_cipher_ctx", cipher_ctx_funs);
27✔
906

907
  lua_newtable(L);
27✔
908
  luaL_setfuncs(L, R, 0);
27✔
909
  auxiliar_enumerate(L, -1, evp_ctrls_code);
27✔
910

911
  return 1;
27✔
912
}
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