• 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

92.02
/src/ec.c
1
/***
2
ec module to create EC keys and do EC key processes.
3

4
@module ec
5
@usage
6
  ec = require('openssl').ec
7
*/
8
#include <openssl/engine.h>
9

10
#include "openssl.h"
11
#include "private.h"
12

13
#if !defined(OPENSSL_NO_EC)
14

15
static int openssl_push_group_asn1_flag(lua_State *L, int flag);
16
static int openssl_push_point_conversion_form(lua_State *L, point_conversion_form_t form);
17

18
/***
19
get or set affine coordinates of an elliptic curve point
20
@function affine_coordinates
21
@tparam ec_group group elliptic curve group
22
@tparam ec_point point elliptic curve point
23
@tparam[opt] bn x x coordinate (for setting)
24
@tparam[opt] bn y y coordinate (for setting)
25
@treturn bn x coordinate (when getting)
26
@treturn bn y coordinate (when getting)
27
*/
28
static int
29
openssl_ecpoint_affine_coordinates(lua_State *L)
32✔
30
{
31
  EC_GROUP *g = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
32✔
32
  EC_POINT *p = CHECK_OBJECT(2, EC_POINT, "openssl.ec_point");
32✔
33
  int       ret = 0;
32✔
34
  if (lua_gettop(L) == 2) {
32✔
35
    BIGNUM *x = BN_new();
8✔
36
    BIGNUM *y = BN_new();
8✔
37
    if (EC_POINT_get_affine_coordinates(g, p, x, y, NULL) == 1) {
8✔
38
      PUSH_BN(x);
8✔
39
      PUSH_BN(y);
8✔
40
      ret = 2;
8✔
41
    };
42
  } else {
43
    BIGNUM *x = CHECK_OBJECT(3, BIGNUM, "openssl.bn");
24✔
44
    BIGNUM *y = CHECK_OBJECT(4, BIGNUM, "openssl.bn");
24✔
45
    ret = EC_POINT_set_affine_coordinates(g, p, x, y, NULL);
24✔
46
    if (ret == 0) luaL_error(L, "EC_POINT_set_affine_coordinates fail");
24✔
47
    ret = 0;
24✔
48
  }
49
  return ret;
32✔
50
}
51

52
/***
53
create EC group and generator point from curve specification
54
@function group
55
@tparam string|table|number curve curve specification (name, parameters, or NID)
56
@treturn ec_group the elliptic curve group
57
@treturn ec_point the generator point
58
*/
59
static int
60
openssl_eckey_group(lua_State *L)
36✔
61
{
62
  const EC_GROUP *g = openssl_get_ec_group(L, 1, 2, 3);
36✔
63
  if (g) {
36✔
64
    const EC_POINT *p = EC_GROUP_get0_generator(g);
36✔
65
    p = EC_POINT_dup(p, g);
36✔
66
    PUSH_OBJECT(g, "openssl.ec_group");
36✔
67
    PUSH_OBJECT(p, "openssl.ec_point");
36✔
68
    return 2;
36✔
69
  }
UNCOV
70
  return 0;
×
71
};
72

73
/***
74
parse elliptic curve group to extract detailed parameters
75
@function parse
76
@treturn table containing curve parameters (generator, order, cofactor, etc.)
77
*/
78
static int
79
openssl_ec_group_parse(lua_State *L)
4✔
80
{
81
  const EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
4✔
82
  const EC_POINT *generator = EC_GROUP_get0_generator(group);
4✔
83
  BN_CTX         *ctx = BN_CTX_new();
4✔
84
  BIGNUM         *a, *b, *p, *order, *cofactor;
85

86
  lua_newtable(L);
4✔
87
  if (generator) {
4✔
88
    generator = EC_POINT_dup(generator, group);
4✔
89
    AUXILIAR_SETOBJECT(L, generator, "openssl.ec_point", -1, "generator");
4✔
90
  }
91

92
  order = BN_new();
4✔
93
  EC_GROUP_get_order(group, order, ctx);
4✔
94
  AUXILIAR_SETOBJECT(L, order, "openssl.bn", -1, "order");
4✔
95

96
  cofactor = BN_new();
4✔
97
  EC_GROUP_get_cofactor(group, cofactor, ctx);
4✔
98
  AUXILIAR_SETOBJECT(L, cofactor, "openssl.bn", -1, "cofactor");
4✔
99

100
  openssl_push_group_asn1_flag(L, EC_GROUP_get_asn1_flag(group));
4✔
101
  lua_setfield(L, -2, "asn1_flag");
4✔
102

103
  AUXILIAR_SET(L, -1, "degree", EC_GROUP_get_degree(group), integer);
4✔
104
  AUXILIAR_SET(L, -1, "curve_name", EC_GROUP_get_curve_name(group), integer);
4✔
105

106
  openssl_push_point_conversion_form(L, EC_GROUP_get_point_conversion_form(group));
4✔
107
  lua_setfield(L, -2, "conversion_form");
4✔
108

109
  AUXILIAR_SETLSTR(L, -1, "seed", EC_GROUP_get0_seed(group), EC_GROUP_get_seed_len(group));
4✔
110

111
  a = BN_new();
4✔
112
  b = BN_new();
4✔
113
  p = BN_new();
4✔
114
  EC_GROUP_get_curve(group, p, a, b, ctx);
4✔
115
  lua_newtable(L);
4✔
116
  {
117
    AUXILIAR_SETOBJECT(L, p, "openssl.bn", -1, "p");
4✔
118
    AUXILIAR_SETOBJECT(L, a, "openssl.bn", -1, "a");
4✔
119
    AUXILIAR_SETOBJECT(L, b, "openssl.bn", -1, "b");
4✔
120
  }
121
  lua_setfield(L, -2, "curve");
4✔
122
  BN_CTX_free(ctx);
4✔
123

124
  return 1;
4✔
125
}
126
static int
127
openssl_ec_group_free(lua_State *L)
100✔
128
{
129
  EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
100✔
130
  EC_GROUP_free(group);
100✔
131
  return 0;
100✔
132
}
133

134
static int
135
openssl_to_group_asn1_flag(lua_State *L, int i, const char *defval)
76✔
136
{
137
  const char *const flag[] = { "explicit", "named_curve", NULL };
76✔
138
  int               f = luaL_checkoption(L, i, defval, flag);
76✔
139
  int               form = 0;
76✔
140
  if (f == 0)
76✔
141
    form = 0;
60✔
142
  else if (f == 1)
16✔
143
    form = OPENSSL_EC_NAMED_CURVE;
16✔
144
  else
UNCOV
145
    luaL_argerror(L, i, "invalid paramater, only accept 'explicit' or 'named_curve'");
×
146
  return form;
76✔
147
}
148

149
static int
150
openssl_push_group_asn1_flag(lua_State *L, int flag)
52✔
151
{
152
  if (flag == 0)
52✔
153
    lua_pushstring(L, "explicit");
36✔
154
  else if (flag == 1)
16✔
155
    lua_pushstring(L, "named_curve");
16✔
156
  else
UNCOV
157
    lua_pushnil(L);
×
158
  return 1;
52✔
159
}
160

161
/***
162
get or set ASN1 flag for elliptic curve group
163
@function asn1_flag
164
@tparam ec_group group elliptic curve group
165
@tparam[opt] number|string flag ASN1 flag to set
166
@treturn string|number current ASN1 flag (string name and number value)
167
*/
168
static int
169
openssl_ec_group_asn1_flag(lua_State *L)
48✔
170
{
171
  EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
48✔
172
  int       asn1_flag;
173
  if (lua_isnone(L, 2)) {
48✔
174
    asn1_flag = EC_GROUP_get_asn1_flag(group);
24✔
175
    openssl_push_group_asn1_flag(L, asn1_flag);
24✔
176
    lua_pushinteger(L, asn1_flag);
24✔
177
    return 2;
24✔
178
  } else if (lua_isnumber(L, 2))
24✔
UNCOV
179
    asn1_flag = luaL_checkint(L, 2);
×
180
  else
181
    asn1_flag = openssl_to_group_asn1_flag(L, 2, NULL);
24✔
182
  EC_GROUP_set_asn1_flag(group, asn1_flag);
24✔
183
  lua_pushvalue(L, 1);
24✔
184
  return 1;
24✔
185
}
186

187
static point_conversion_form_t
188
openssl_to_point_conversion_form(lua_State *L, int i, const char *defval)
172✔
189
{
190
  const char             *options[] = { "compressed", "uncompressed", "hybrid", NULL };
172✔
191
  int                     f = luaL_checkoption(L, i, defval, options);
172✔
192
  point_conversion_form_t form = 0;
172✔
193
  if (f == 0)
172✔
194
    form = POINT_CONVERSION_COMPRESSED;
108✔
195
  else if (f == 1)
64✔
196
    form = POINT_CONVERSION_UNCOMPRESSED;
8✔
197
  else if (f == 2)
56✔
198
    form = POINT_CONVERSION_HYBRID;
56✔
199
  else
UNCOV
200
    luaL_argerror(L, i, "invalid paramater, only support 'compressed', 'uncompressed' or 'hybrid'");
×
201
  return form;
172✔
202
}
203

204
static int
205
openssl_push_point_conversion_form(lua_State *L, point_conversion_form_t form)
52✔
206
{
207
  if (form == POINT_CONVERSION_COMPRESSED)
52✔
208
    lua_pushstring(L, "compressed");
8✔
209
  else if (form == POINT_CONVERSION_UNCOMPRESSED)
44✔
210
    lua_pushstring(L, "uncompressed");
12✔
211
  else if (form == POINT_CONVERSION_HYBRID)
32✔
212
    lua_pushstring(L, "hybrid");
32✔
213
  else
UNCOV
214
    lua_pushnil(L);
×
215
  return 1;
52✔
216
}
217

218
/***
219
get or set point conversion form for elliptic curve group
220
@function point_conversion_form
221
@tparam ec_group group elliptic curve group
222
@tparam[opt] number|string form point conversion form to set
223
@treturn string|number current point conversion form (string name and number value)
224
*/
225
static int
226
openssl_ec_group_point_conversion_form(lua_State *L)
72✔
227
{
228
  EC_GROUP               *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
72✔
229
  point_conversion_form_t form;
230
  if (lua_isnone(L, 2)) {
72✔
231
    form = EC_GROUP_get_point_conversion_form(group);
24✔
232
    openssl_push_point_conversion_form(L, form);
24✔
233
    lua_pushinteger(L, form);
24✔
234
    return 2;
24✔
235
  } else if (lua_isnumber(L, 2))
48✔
236
    form = luaL_checkint(L, 2);
×
237
  else
238
    form = openssl_to_point_conversion_form(L, 2, NULL);
48✔
239
  EC_GROUP_set_point_conversion_form(group, form);
48✔
240
  lua_pushvalue(L, 1);
48✔
241
  return 1;
48✔
242
}
243

244
EC_GROUP *
245
openssl_get_ec_group(lua_State *L, int ec_name_idx, int param_enc_idx, int conv_form_idx)
92✔
246
{
247
  int       nid = NID_undef;
92✔
248
  EC_GROUP *g = NULL;
92✔
249
  if (lua_isnumber(L, ec_name_idx))
92✔
250
    nid = lua_tointeger(L, ec_name_idx);
28✔
251
  else if (lua_isstring(L, ec_name_idx)) {
64✔
252
    const char *name = luaL_checkstring(L, ec_name_idx);
56✔
253
    nid = OBJ_txt2nid(name);
56✔
254
  } else if (lua_isuserdata(L, ec_name_idx)) {
8✔
255
    if (auxiliar_getclassudata(L, "openssl.evp_pkey", ec_name_idx)) {
8✔
256
      EVP_PKEY *pkey = CHECK_OBJECT(1, EVP_PKEY, "openssl.evp_pkey");
4✔
257
      EC_KEY   *ec_key = EVP_PKEY_get1_EC_KEY(pkey);
4✔
258
      if (ec_key) {
4✔
259
        g = (EC_GROUP *)EC_KEY_get0_group(ec_key);
4✔
260
        EC_KEY_free(ec_key);
4✔
261
      }
262
    } else if (auxiliar_getclassudata(L, "openssl.ec_key", ec_name_idx)) {
4✔
263
      EC_KEY *ec_key = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
4✔
264
      g = (EC_GROUP *)EC_KEY_get0_group(ec_key);
4✔
265
    }
266
    if (g) g = EC_GROUP_dup(g);
8✔
267
  }
268

269
  if (g == NULL && nid != NID_undef) g = EC_GROUP_new_by_curve_name(nid);
92✔
270

271
  if (g) {
92✔
272
    if (param_enc_idx) {
92✔
273
      int form = 0;
92✔
274
      int type = lua_type(L, param_enc_idx);
92✔
275
      if (type == LUA_TSTRING) {
92✔
276
        form = openssl_to_point_conversion_form(L, param_enc_idx, NULL);
28✔
277
        EC_GROUP_set_point_conversion_form(g, form);
28✔
278
      } else if (type == LUA_TNUMBER) {
64✔
279
        form = luaL_checkint(L, param_enc_idx);
16✔
280
        EC_GROUP_set_point_conversion_form(g, form);
16✔
281
      } else if (lua_isnoneornil(L, param_enc_idx)) {
48✔
282
        EC_GROUP_set_point_conversion_form(g, POINT_CONVERSION_UNCOMPRESSED);
48✔
283
      } else
UNCOV
284
        luaL_argerror(L, param_enc_idx, "not accept type of point_conversion_form");
×
285
    } else
UNCOV
286
      EC_GROUP_set_point_conversion_form(g, POINT_CONVERSION_UNCOMPRESSED);
×
287

288
    if (conv_form_idx) {
92✔
289
      int asn1_flag = 0;
92✔
290
      int type = lua_type(L, conv_form_idx);
92✔
291
      if (type == LUA_TSTRING) {
92✔
292
        asn1_flag = openssl_to_group_asn1_flag(L, conv_form_idx, NULL);
28✔
293
        EC_GROUP_set_asn1_flag(g, asn1_flag);
28✔
294
      } else if (type == LUA_TNUMBER) {
64✔
295
        asn1_flag = luaL_checkint(L, conv_form_idx);
16✔
296
        EC_GROUP_set_asn1_flag(g, asn1_flag);
16✔
297
      } else if (lua_isnoneornil(L, conv_form_idx)) {
48✔
298
        EC_GROUP_set_asn1_flag(g, OPENSSL_EC_NAMED_CURVE);
48✔
299
      } else
UNCOV
300
        luaL_argerror(L, conv_form_idx, "not accept type of asn1 flag");
×
301
    } else
UNCOV
302
      EC_GROUP_set_asn1_flag(g, OPENSSL_EC_NAMED_CURVE);
×
303
  }
304

305
  return g;
92✔
306
}
307

308
/***
309
create new elliptic curve point for group
310
@function point_new
311
@tparam ec_group group elliptic curve group
312
@treturn ec_point new elliptic curve point
313
*/
314
static int
315
openssl_ec_group_point_new(lua_State *L)
24✔
316
{
317
  EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
24✔
318
  EC_POINT *point = EC_POINT_new(group);
24✔
319
  PUSH_OBJECT(point, "openssl.ec_point");
24✔
320
  return 1;
24✔
321
}
322

323
/***
324
duplicate an EC point
325
@function point_dup
326
@tparam ec_group group the EC group
327
@tparam ec_point point the EC point to duplicate
328
@treturn ec_point new EC point that is a copy of the input point
329
*/
330
static int
331
openssl_ec_point_dup(lua_State *L)
24✔
332
{
333
  const EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
24✔
334
  const EC_POINT *point = CHECK_OBJECT(2, EC_POINT, "openssl.ec_point");
24✔
335

336
  EC_POINT *new = EC_POINT_dup(point, group);
24✔
337
  PUSH_OBJECT(new, "openssl.ec_point");
24✔
338
  return 1;
24✔
339
}
340

341
/***
342
compare two EC points for equality
343
@function point_equal
344
@tparam ec_group group the EC group
345
@tparam ec_point a first EC point to compare
346
@tparam ec_point b second EC point to compare
347
@treturn boolean true if points are equal, false otherwise
348
*/
349
static int
350
openssl_ec_point_equal(lua_State *L)
192✔
351
{
352
  const EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
192✔
353
  const EC_POINT *a = CHECK_OBJECT(2, EC_POINT, "openssl.ec_point");
192✔
354
  const EC_POINT *b = CHECK_OBJECT(3, EC_POINT, "openssl.ec_point");
192✔
355

356
  int ret = EC_POINT_cmp(group, a, b, NULL) == 0;
192✔
357
  lua_pushboolean(L, ret);
192✔
358
  return 1;
192✔
359
}
360

361
/***
362
convert octet string to EC point
363
@function oct2point
364
@tparam ec_group group the EC group
365
@tparam string oct octet string representation
366
@treturn ec_point|nil the resulting EC point or nil on failure
367
*/
368
static int
369
openssl_ec_point_oct2point(lua_State *L)
48✔
370
{
371
  const EC_GROUP      *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
48✔
372
  size_t               size = 0;
48✔
373
  const unsigned char *oct = (const unsigned char *)luaL_checklstring(L, 2, &size);
48✔
374
  EC_POINT            *point = EC_POINT_new(group);
48✔
375

376
  int ret = EC_POINT_oct2point(group, point, oct, size, NULL);
48✔
377
  if (ret == 1)
48✔
378
    PUSH_OBJECT(point, "openssl.ec_point");
48✔
379
  else
UNCOV
380
    ret = openssl_pushresult(L, ret);
×
381
  return ret;
48✔
382
}
383

384
/***
385
convert EC point to octet string
386
@function point2oct
387
@tparam ec_group group the EC group
388
@tparam[opt] string form point conversion form ("compressed", "uncompressed", or "hybrid")
389
@treturn string octet string representation of the point
390
*/
391
static int
392
openssl_ec_point_point2oct(lua_State *L)
72✔
393
{
394
  const EC_GROUP         *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
72✔
395
  const EC_POINT         *point = CHECK_OBJECT(2, EC_POINT, "openssl.ec_point");
72✔
396
  point_conversion_form_t form = lua_isnone(L, 3)
72✔
397
                                   ? EC_GROUP_get_point_conversion_form(group)
48✔
398
                                   : openssl_to_point_conversion_form(L, 3, "uncompressed");
72✔
399
  size_t                  size = EC_POINT_point2oct(group, point, form, NULL, 0, NULL);
72✔
400
  if (size > 0) {
72✔
401
    unsigned char *oct = (unsigned char *)OPENSSL_malloc(size);
72✔
402
    size = EC_POINT_point2oct(group, point, form, oct, size, NULL);
72✔
403
    if (size > 0)
72✔
404
      lua_pushlstring(L, (const char *)oct, size);
72✔
405
    else
UNCOV
406
      lua_pushnil(L);
×
407
    OPENSSL_free(oct);
72✔
408
    return 1;
72✔
409
  }
UNCOV
410
  return 0;
×
411
}
412

413
/***
414
convert bignum to EC point
415
@function bn2point
416
@tparam ec_group group the EC group
417
@tparam bn the bignum to convert to point
418
@treturn ec_point|nil the resulting EC point or nil on failure
419
*/
420
static int
421
openssl_ec_point_bn2point(lua_State *L)
48✔
422
{
423
  const EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
48✔
424
  BIGNUM         *bn = CHECK_OBJECT(2, BIGNUM, "openssl.bn");
48✔
425
  EC_POINT       *pnt = EC_POINT_bn2point(group, bn, NULL, NULL);
48✔
426
  if (pnt)
48✔
427
    PUSH_OBJECT(pnt, "openssl.ec_point");
48✔
428
  else
UNCOV
429
    lua_pushnil(L);
×
430
  return 1;
48✔
431
}
432

433
/***
434
convert EC point to bignum
435
@function point2bn
436
@tparam ec_group group the EC group
437
@tparam[opt] string form point conversion form ("compressed", "uncompressed", or "hybrid")
438
@treturn bn|nil the resulting bignum representation or nil on failure
439
*/
440
static int
441
openssl_ec_point_point2bn(lua_State *L)
48✔
442
{
443
  const EC_GROUP         *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
48✔
444
  const EC_POINT         *point = CHECK_OBJECT(2, EC_POINT, "openssl.ec_point");
48✔
445
  point_conversion_form_t form = lua_isnone(L, 3)
48✔
446
                                   ? EC_GROUP_get_point_conversion_form(group)
24✔
447
                                   : openssl_to_point_conversion_form(L, 3, "uncompressed");
48✔
448
  BIGNUM                 *bn = EC_POINT_point2bn(group, point, form, NULL, NULL);
48✔
449
  if (bn)
48✔
450
    PUSH_OBJECT(bn, "openssl.bn");
48✔
451
  else
UNCOV
452
    lua_pushnil(L);
×
453
  return 1;
48✔
454
}
455

456
/***
457
convert hexadecimal string to EC point
458
@function hex2point
459
@tparam ec_group group the EC group
460
@tparam string hex hexadecimal string representation
461
@treturn ec_point|nil the resulting EC point or nil on failure
462
*/
463
static int
464
openssl_ec_point_hex2point(lua_State *L)
48✔
465
{
466
  const EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
48✔
467
  const char     *hex = luaL_checkstring(L, 2);
48✔
468

469
  EC_POINT *pnt = EC_POINT_hex2point(group, hex, NULL, NULL);
48✔
470
  if (pnt)
48✔
471
    PUSH_OBJECT(pnt, "openssl.ec_point");
48✔
472
  else
UNCOV
473
    lua_pushnil(L);
×
474
  return 1;
48✔
475
}
476

477
/***
478
convert EC point to hexadecimal string
479
@function point2hex
480
@tparam ec_group group the EC group
481
@tparam[opt] string form point conversion form ("compressed", "uncompressed", or "hybrid")
482
@treturn string|nil hexadecimal string representation or nil on failure
483
*/
484
static int
485
openssl_ec_point_point2hex(lua_State *L)
48✔
486
{
487
  const EC_GROUP         *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
48✔
488
  const EC_POINT         *point = CHECK_OBJECT(2, EC_POINT, "openssl.ec_point");
48✔
489
  point_conversion_form_t form = lua_isnone(L, 3)
48✔
490
                                   ? EC_GROUP_get_point_conversion_form(group)
24✔
491
                                   : openssl_to_point_conversion_form(L, 3, "uncompressed");
48✔
492
  char                   *hex = EC_POINT_point2hex(group, point, form, NULL);
48✔
493
  if (hex) {
48✔
494
    lua_pushstring(L, hex);
48✔
495
    OPENSSL_free(hex);
48✔
496
  } else
UNCOV
497
    lua_pushnil(L);
×
498
  return 1;
48✔
499
}
500

501
/***
502
generate EC key pair from group
503
@function generate_key
504
@treturn ec_key generated EC key object or nil if failed
505
*/
506
static int
507
openssl_ec_group_generate_key(lua_State *L)
28✔
508
{
509
  const EC_GROUP *group = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
28✔
510

511
  EC_KEY *ec = EC_KEY_new();
28✔
512
  if (ec) {
28✔
513
    int ret;
514
    EC_KEY_set_group(ec, group);
28✔
515
    ret = EC_KEY_generate_key(ec);
28✔
516
    if (ret == 1) {
28✔
517
      PUSH_OBJECT(ec, "openssl.ec_key");
28✔
518
      return 1;
28✔
519
    }
UNCOV
520
    EC_KEY_free(ec);
×
UNCOV
521
    return openssl_pushresult(L, ret);
×
522
  }
UNCOV
523
  return 0;
×
524
}
525

526
/***
527
check if two EC groups are equal
528
@function equal
529
@tparam ec_group other EC group to compare with
530
@treturn boolean true if groups are equal, false otherwise
531
*/
532
static int
533
openssl_ec_group_equal(lua_State *L)
24✔
534
{
535
  const EC_GROUP *a = CHECK_OBJECT(1, EC_GROUP, "openssl.ec_group");
24✔
536
  const EC_GROUP *b = CHECK_OBJECT(2, EC_GROUP, "openssl.ec_group");
24✔
537
  lua_pushboolean(L, EC_GROUP_cmp(a, b, NULL) == 0);
24✔
538
  return 1;
24✔
539
}
540

541
static luaL_Reg ec_group_funs[] = {
542
  { "__tostring",            auxiliar_tostring                      },
543
  { "__gc",                  openssl_ec_group_free                  },
544
  { "__eq",                  openssl_ec_group_equal                 },
545
  { "equal",                 openssl_ec_group_equal                 },
546

547
  { "affine_coordinates",    openssl_ecpoint_affine_coordinates     },
548
  { "parse",                 openssl_ec_group_parse                 },
549
  { "asn1_flag",             openssl_ec_group_asn1_flag             },
550

551
  { "point_conversion_form", openssl_ec_group_point_conversion_form },
552
  { "point_new",             openssl_ec_group_point_new             },
553
  { "point_dup",             openssl_ec_point_dup                   },
554
  { "point_equal",           openssl_ec_point_equal                 },
555
  { "point2oct",             openssl_ec_point_point2oct             },
556
  { "oct2point",             openssl_ec_point_oct2point             },
557
  { "point2bn",              openssl_ec_point_point2bn              },
558
  { "bn2point",              openssl_ec_point_bn2point              },
559
  { "point2hex",             openssl_ec_point_point2hex             },
560
  { "hex2point",             openssl_ec_point_hex2point             },
561

562
  { "generate_key",          openssl_ec_group_generate_key          },
563

564
  { NULL,                    NULL                                   }
565
};
566

567
static int
568
openssl_ecdsa_do_sign(lua_State *L)
72✔
569
{
570
  EC_KEY     *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
72✔
571
  size_t      l;
572
  const char *sdata = luaL_checklstring(L, 2, &l);
72✔
573
  ECDSA_SIG  *sig = ECDSA_do_sign((const unsigned char *)sdata, l, ec);
72✔
574
  int         der = lua_isnone(L, 3) ? 1 : lua_toboolean(L, 3);
72✔
575
  int         ret = 0;
72✔
576

577
  if (der) {
72✔
578
    unsigned char *p = NULL;
48✔
579
    l = i2d_ECDSA_SIG(sig, &p);
48✔
580
    if (l > 0) {
48✔
581
      lua_pushlstring(L, (const char *)p, l);
48✔
582
      OPENSSL_free(p);
48✔
583
      ret = 1;
48✔
584
    }
585
  } else {
586
    const BIGNUM *r = NULL, *s = NULL;
24✔
587
    ECDSA_SIG_get0(sig, &r, &s);
24✔
588

589
    r = BN_dup(r);
24✔
590
    s = BN_dup(s);
24✔
591

592
    PUSH_OBJECT(r, "openssl.bn");
24✔
593
    PUSH_OBJECT(s, "openssl.bn");
24✔
594
    ret = 2;
24✔
595
  }
596
  ECDSA_SIG_free(sig);
72✔
597
  return ret;
72✔
598
}
599

600
static int
601
openssl_ecdsa_do_verify(lua_State *L)
72✔
602
{
603
  size_t      l, sigl;
604
  int         ret;
605
  EC_KEY     *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
72✔
606
  const char *dgst = luaL_checklstring(L, 2, &l);
72✔
607
  int         top = lua_gettop(L);
72✔
608
  if (top == 3) {
72✔
609
    const char *s = luaL_checklstring(L, 3, &sigl);
48✔
610
    ECDSA_SIG  *sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&s, sigl);
48✔
611
    ret = ECDSA_do_verify((const unsigned char *)dgst, l, sig, ec);
48✔
612
    ECDSA_SIG_free(sig);
48✔
613
  } else {
614
    BIGNUM    *r = BN_get(L, 3);
24✔
615
    BIGNUM    *s = BN_get(L, 4);
24✔
616
    ECDSA_SIG *sig = ECDSA_SIG_new();
24✔
617
    ECDSA_SIG_set0(sig, r, s);
24✔
618
    ret = ECDSA_do_verify((const unsigned char *)dgst, l, sig, ec);
24✔
619
    ECDSA_SIG_free(sig);
24✔
620
  }
621
  if (ret == -1) return openssl_pushresult(L, ret);
72✔
622
  lua_pushboolean(L, ret);
72✔
623
  return 1;
72✔
624
}
625

626
/***
627
do EC sign
628

629
@function sign
630
@tparam ec_key eckey
631
@tparam string digest result of digest to be signed
632
@tparam evp_md|string|nid md digest alg identity, default is sm3
633
@treturn string signature
634
*/
635
static int openssl_ecdsa_sign(lua_State *L)
28✔
636
{
637
  int                  ret;
638
  EC_KEY              *eckey = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
28✔
639
  size_t               dgstlen = 0;
28✔
640
  const unsigned char *dgst = (const unsigned char *)luaL_checklstring(L, 2, &dgstlen);
28✔
641
  const EVP_MD        *md = get_digest(L, 3, NULL);
28✔
642
  unsigned int         siglen = ECDSA_size(eckey);
28✔
643
  unsigned char       *sig = OPENSSL_malloc(siglen);
28✔
644

645
  luaL_argcheck(L, dgstlen == EVP_MD_size(md), 4, "invalid digest");
28✔
646
  ret = ECDSA_sign(EVP_MD_type(md), dgst, dgstlen, sig, &siglen, eckey);
28✔
647
  if (ret == 1) {
28✔
648
    lua_pushlstring(L, (const char *)sig, siglen);
28✔
649
  } else
UNCOV
650
    ret = openssl_pushresult(L, ret);
×
651
  OPENSSL_free(sig);
28✔
652
  return ret;
28✔
653
}
654

655
/***
656
do EC verify, input msg is digest result
657

658
@function verify
659
@tparam ec_key eckey
660
@tparam string digest result of digest to be signed
661
@tparam string signature
662
@tparam evp_md|string|nid md digest alg identity
663
@treturn boolean true for verified, false for invalid signature
664
@return nil for error, and followed by error message
665
*/
666
static int openssl_ecdsa_verify(lua_State *L)
40✔
667
{
668
  int                  ret;
669
  EC_KEY              *eckey = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
40✔
670
  size_t               dgstlen = 0;
40✔
671
  const unsigned char *dgst = (const unsigned char *)luaL_checklstring(L, 2, &dgstlen);
40✔
672
  size_t               siglen = 0;
40✔
673
  const unsigned char *sig = (const unsigned char *)luaL_checklstring(L, 3, &siglen);
40✔
674
  const EVP_MD        *md = get_digest(L, 4, NULL);
40✔
675
  int                  type = EVP_MD_type(md);
40✔
676

677
  luaL_argcheck(L, dgstlen == EVP_MD_size(md), 4, "invalid digest");
40✔
678
  ret = ECDSA_verify(type, dgst, (int)dgstlen, sig, (int)siglen, eckey);
32✔
679
  if (ret == -1) return openssl_pushresult(L, ret);
32✔
680
  lua_pushboolean(L, ret);
28✔
681
  return 1;
28✔
682
}
683

684
/* ec_point */
685
/***
686
copy EC point
687
@function copy
688
@tparam ec_point from source EC point to copy from
689
@treturn boolean true on success, false on failure
690
*/
691
static int
692
openssl_ec_point_copy(lua_State *L)
24✔
693
{
694
  EC_POINT *self = CHECK_OBJECT(1, EC_POINT, "openssl.ec_point");
24✔
695
  EC_POINT *from = CHECK_OBJECT(2, EC_POINT, "openssl.ec_point");
24✔
696
  int       ret = EC_POINT_copy(self, from);
24✔
697
  return openssl_pushresult(L, ret);
24✔
698
}
699

700
static int
701
openssl_ec_point_free(lua_State *L)
272✔
702
{
703
  EC_POINT *p = CHECK_OBJECT(1, EC_POINT, "openssl.ec_point");
272✔
704
  EC_POINT_free(p);
272✔
705
  return 0;
272✔
706
}
707

708
static int
709
openssl_ec_key_free(lua_State *L)
96✔
710
{
711
  EC_KEY *p = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
96✔
712
  EC_KEY_free(p);
96✔
713
  return 0;
96✔
714
}
715

716
/***
717
parse EC key components and parameters
718
@function parse
719
@tparam[opt=false] boolean basic true for basic information only
720
@treturn table EC key information including encoding flags, conversion form, group, and key components
721
*/
722
static int
723
openssl_ec_key_parse(lua_State *L)
52✔
724
{
725
  EC_KEY         *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
52✔
726
  int             basic = luaL_opt(L, lua_toboolean, 2, 0);
52✔
727
  const EC_POINT *point = EC_KEY_get0_public_key(ec);
52✔
728
  const EC_GROUP *group = EC_KEY_get0_group(ec);
52✔
729
  const BIGNUM   *priv = EC_KEY_get0_private_key(ec);
52✔
730
  lua_newtable(L);
52✔
731

732
  AUXILIAR_SET(L, -1, "enc_flag", EC_KEY_get_enc_flags(ec), integer);
52✔
733
  AUXILIAR_SET(L, -1, "conv_form", EC_KEY_get_conv_form(ec), integer);
52✔
734
  AUXILIAR_SET(L, -1, "curve_name", EC_GROUP_get_curve_name(group), integer);
52✔
735

736
  if (basic) {
52✔
737
    BIGNUM *x = BN_new();
12✔
738
    BIGNUM *y = BN_new();
12✔
739

740
    if (priv != NULL) {
12✔
741
      priv = BN_dup(priv);
8✔
742
      AUXILIAR_SETOBJECT(L, priv, "openssl.bn", -1, "d");
8✔
743
    }
744

745
    if (point && EC_POINT_get_affine_coordinates(group, point, x, y, NULL) == 1) {
12✔
746
      AUXILIAR_SETOBJECT(L, x, "openssl.bn", -1, "x");
12✔
747
      AUXILIAR_SETOBJECT(L, y, "openssl.bn", -1, "y");
12✔
748
    };
749
  } else {
750
    point = EC_POINT_dup(point, group);
40✔
751
    AUXILIAR_SETOBJECT(L, point, "openssl.ec_point", -1, "pub_key");
40✔
752
    group = EC_GROUP_dup(group);
40✔
753
    AUXILIAR_SETOBJECT(L, group, "openssl.ec_group", -1, "group");
40✔
754

755
    OPENSSL_PKEY_GET_BN(priv, priv_key);
40✔
756
  }
757
  return 1;
52✔
758
};
759

760
#ifndef OPENSSL_NO_ECDH
761
static const int KDF1_SHA1_len = 20;
762
static void *
UNCOV
763
KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
×
764
{
765
#ifndef OPENSSL_NO_SHA
UNCOV
766
  if (*outlen < SHA_DIGEST_LENGTH)
×
UNCOV
767
    return NULL;
×
768
  else
UNCOV
769
    *outlen = SHA_DIGEST_LENGTH;
×
UNCOV
770
  return SHA1(in, inlen, out);
×
771
#else
772
  return NULL;
773
#endif /* OPENSSL_NO_SHA */
774
}
775
#endif /* OPENSSL_NO_ECDH */
776

777
#define MAX_ECDH_SIZE 256
778

779
/***
780
compute ECDH shared key
781
@function compute_key
782
@tparam ec_key peer peer EC key for key exchange
783
@tparam[opt] function kdf key derivation function
784
@treturn string shared secret or nil if failed
785
*/
786
static int
787
openssl_ecdh_compute_key(lua_State *L)
16✔
788
{
789
  EC_KEY *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
16✔
790
  EC_KEY *peer = CHECK_OBJECT(2, EC_KEY, "openssl.ec_key");
16✔
791

792
  int           field_size, outlen, secret_size_a;
793
  unsigned char secret_a[MAX_ECDH_SIZE];
794
  void *(*kdf)(const void *in, size_t inlen, void *out, size_t *xoutlen);
795
  field_size = EC_GROUP_get_degree(EC_KEY_get0_group(ec));
16✔
796
  if (field_size <= 24 * 8) {
16✔
UNCOV
797
    outlen = KDF1_SHA1_len;
×
UNCOV
798
    kdf = KDF1_SHA1;
×
799
  } else {
800
    outlen = (field_size + 7) / 8;
16✔
801
    kdf = NULL;
16✔
802
  }
803
  secret_size_a = ECDH_compute_key(secret_a, outlen, EC_KEY_get0_public_key(peer), ec, kdf);
16✔
804
  lua_pushlstring(L, (const char *)secret_a, secret_size_a);
16✔
805
  return 1;
16✔
806
}
807

808
/***
809
set ECDSA signing method for EC key
810
@function set_method
811
@tparam engine engine engine providing the ECDSA method
812
@treturn boolean result true for success
813
*/
814
static int
815
openssl_ecdsa_set_method(lua_State *L)
24✔
816
{
817
#ifndef OPENSSL_NO_ENGINE
818
  EC_KEY *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
24✔
819
  ENGINE *e = CHECK_OBJECT(2, ENGINE, "openssl.engine");
24✔
820
#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L
821
  const ECDSA_METHOD *m = ENGINE_get_ECDSA(e);
6✔
822
  if (m) {
6✔
823
    int r = ECDSA_set_method(ec, m);
6✔
824
    return openssl_pushresult(L, r);
6✔
825
  }
826
#else
827
  const EC_KEY_METHOD *m = ENGINE_get_EC(e);
18✔
828
  if (m) {
18✔
829
    int r = EC_KEY_set_method(ec, m);
18✔
830
    return openssl_pushresult(L, r);
18✔
831
  }
832
#endif
833
#endif
UNCOV
834
  return 0;
×
835
}
836

837
/***
838
check if EC key is valid
839
@function check
840
@treturn boolean true if key is valid, false otherwise
841
*/
842
static int
843
openssl_ec_key_check_key(lua_State *L)
24✔
844
{
845
  EC_KEY *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
24✔
846
  lua_pushboolean(L, EC_KEY_check_key(ec));
24✔
847
  return 1;
24✔
848
}
849

850
/***
851
export EC key to DER format
852
@function export
853
@treturn string DER encoded EC private key
854
*/
855
static int
856
openssl_ec_key_export(lua_State *L)
48✔
857
{
858
  EC_KEY        *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
48✔
859
  unsigned char *der = NULL;
48✔
860
  int            len = i2d_ECPrivateKey(ec, &der);
48✔
861
  if (len > 0)
48✔
862
    lua_pushlstring(L, (const char *)der, len);
48✔
863
  else
UNCOV
864
    lua_pushnil(L);
×
865
  if (der) OPENSSL_free(der);
48✔
866
  return 1;
48✔
867
}
868

869
/***
870
get or set EC group for EC key
871
@function group
872
@tparam[opt] ec_group group optional EC group to set
873
@treturn ec_group current EC group when called without parameters
874
@treturn boolean true when setting group successfully
875
*/
876
static int
877
openssl_ec_key_group(lua_State *L)
24✔
878
{
879
  EC_KEY *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
24✔
880
  if (!lua_isnone(L, 2)) {
24✔
UNCOV
881
    EC_GROUP *g = CHECK_OBJECT(2, EC_GROUP, "openssl.ec_group");
×
UNCOV
882
    int       ret = EC_KEY_set_group(ec, g);
×
UNCOV
883
    return openssl_pushresult(L, ret);
×
884
  } else {
885
    const EC_GROUP *g = EC_KEY_get0_group(ec);
24✔
886
    g = EC_GROUP_dup(g);
24✔
887
    PUSH_OBJECT(g, "openssl.ec_group");
24✔
888
    return 1;
24✔
889
  }
890
}
891

892
/***
893
read EC key from DER encoded data
894
@function read
895
@tparam string der DER encoded EC private key data
896
@treturn ec_key|nil parsed EC key or nil on failure
897
*/
898
static int
899
openssl_ec_key_read(lua_State *L)
24✔
900
{
901
  size_t               len = 0;
24✔
902
  const unsigned char *der = (const unsigned char *)luaL_checklstring(L, 1, &len);
24✔
903

904
  EC_KEY *ec = d2i_ECPrivateKey(NULL, &der, len);
24✔
905
  if (ec)
24✔
906
    PUSH_OBJECT(ec, "openssl.ec_key");
24✔
907
  else
UNCOV
908
    lua_pushnil(L);
×
909
  return 1;
24✔
910
}
911

912
/***
913
get or set point conversion form for EC key
914
@function conv_form
915
@tparam[opt] string|number form point conversion form to set
916
@treturn[1] string point conversion form name if getting
917
@treturn[1] number point conversion form value if getting
918
@treturn[2] boolean result true for success if setting
919
*/
920
static int
921
openssl_ec_key_conv_form(lua_State *L)
48✔
922
{
923
  EC_KEY                 *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
48✔
924
  point_conversion_form_t cform;
925
  if (lua_isnone(L, 2)) {
48✔
926
    cform = EC_KEY_get_conv_form(ec);
24✔
927
    openssl_push_point_conversion_form(L, cform);
24✔
928
    lua_pushinteger(L, cform);
24✔
929
    return 2;
24✔
930
  } else if (lua_isnumber(L, 2))
24✔
UNCOV
931
    cform = lua_tointeger(L, 2);
×
932
  else
933
    cform = openssl_to_point_conversion_form(L, 2, NULL);
24✔
934
  EC_KEY_set_conv_form(ec, cform);
24✔
935
  lua_pushvalue(L, 1);
24✔
936
  return 1;
24✔
937
}
938

939
/***
940
get or set encoding flags for EC key
941
@function enc_flags
942
@tparam[opt] string|number flags encoding flags to set
943
@treturn[1] string encoding flags name if getting
944
@treturn[1] number encoding flags value if getting
945
@treturn[2] boolean result true for success if setting
946
*/
947
static int
948
openssl_ec_key_enc_flags(lua_State *L)
48✔
949
{
950
  EC_KEY      *ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
48✔
951
  unsigned int flags;
952
  if (lua_isnone(L, 2)) {
48✔
953
    flags = EC_KEY_get_enc_flags(ec);
24✔
954
    openssl_push_group_asn1_flag(L, flags);
24✔
955
    lua_pushinteger(L, flags);
24✔
956
    return 2;
24✔
957
  } else if (lua_isnumber(L, 2))
24✔
UNCOV
958
    flags = luaL_checkint(L, 2);
×
959
  else
960
    flags = openssl_to_group_asn1_flag(L, 2, NULL);
24✔
961
  EC_KEY_set_enc_flags(ec, flags);
24✔
962
  lua_pushvalue(L, 1);
24✔
963
  return 1;
24✔
964
}
965

966
#ifdef EC_EXT
967
EC_EXT_DEFINE
968
#endif
969

970
static luaL_Reg ec_key_funs[] = {
971
  { "check",       openssl_ec_key_check_key },
972
  { "export",      openssl_ec_key_export    },
973
  { "parse",       openssl_ec_key_parse     },
974
  { "group",       openssl_ec_key_group     },
975
  { "do_sign",     openssl_ecdsa_do_sign    },
976
  { "do_verify",   openssl_ecdsa_do_verify  },
977
  { "sign",        openssl_ecdsa_sign       },
978
  { "verify",      openssl_ecdsa_verify     },
979
  { "compute_key", openssl_ecdh_compute_key },
980
  { "set_method",  openssl_ecdsa_set_method },
981
  { "conv_form",   openssl_ec_key_conv_form },
982
  { "enc_flags",   openssl_ec_key_enc_flags },
983

984
#ifdef EC_EXT
985
  EC_EXT
986
#endif
987

988
  { "__gc",        openssl_ec_key_free      },
989
  { "__tostring",  auxiliar_tostring        },
990

991
  { NULL,          NULL                     }
992
};
993

994
static luaL_Reg ec_point_funs[] = {
995
  { "__tostring", auxiliar_tostring     },
996
  { "__gc",       openssl_ec_point_free },
997
  { "copy",       openssl_ec_point_copy },
998

999
  { NULL,         NULL                  }
1000
};
1001

1002
/***
1003
list all available elliptic curve names
1004
@function list
1005
@treturn table array of curve names and descriptions
1006
*/
1007
static int openssl_ec_list_curve_name(lua_State *L)
4✔
1008
{
1009
  size_t            i = 0;
4✔
1010
  size_t            crv_len = EC_get_builtin_curves(NULL, 0);
4✔
1011
  EC_builtin_curve *curves = OPENSSL_malloc((int)(sizeof(EC_builtin_curve) * crv_len));
4✔
1012

1013
  if (curves == NULL) return 0;
4✔
1014

1015
  if (!EC_get_builtin_curves(curves, crv_len)) {
4✔
UNCOV
1016
    OPENSSL_free(curves);
×
UNCOV
1017
    return 0;
×
1018
  }
1019

1020
  lua_newtable(L);
4✔
1021
  for (i = 0; i < crv_len; i++) {
331✔
1022
    const char *comment;
1023
    const char *sname;
1024
    comment = curves[i].comment;
327✔
1025
    sname = OBJ_nid2sn(curves[i].nid);
327✔
1026
    if (comment == NULL) comment = "CURVE DESCRIPTION NOT AVAILABLE";
327✔
1027
    if (sname == NULL) sname = "";
327✔
1028

1029
    AUXILIAR_SET(L, -1, sname, comment, string);
327✔
1030
  }
1031

1032
  OPENSSL_free(curves);
4✔
1033
  return 1;
4✔
1034
};
1035

1036
static luaL_Reg R[] = {
1037
  { "read",      openssl_ec_key_read        },
1038
  { "list",      openssl_ec_list_curve_name },
1039
  { "group",     openssl_eckey_group        },
1040

1041
  { "do_sign",   openssl_ecdsa_do_sign      },
1042
  { "do_verify", openssl_ecdsa_do_verify    },
1043
  { "sign",      openssl_ecdsa_sign         },
1044
  { "verify",    openssl_ecdsa_verify       },
1045

1046
  { NULL,        NULL                       }
1047
};
1048

1049
int
1050
luaopen_ec(lua_State *L)
43✔
1051
{
1052
  auxiliar_newclass(L, "openssl.ec_point", ec_point_funs);
43✔
1053
  auxiliar_newclass(L, "openssl.ec_group", ec_group_funs);
43✔
1054
  auxiliar_newclass(L, "openssl.ec_key", ec_key_funs);
43✔
1055

1056
  lua_newtable(L);
43✔
1057
  luaL_setfuncs(L, R, 0);
43✔
1058

1059
  return 1;
43✔
1060
}
1061

1062
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc