summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--openssl.c595
1 files changed, 587 insertions, 8 deletions
diff --git a/openssl.c b/openssl.c
index 3cbedec..949176a 100644
--- a/openssl.c
+++ b/openssl.c
@@ -26,9 +26,12 @@
26#ifndef L_OPENSSL_H 26#ifndef L_OPENSSL_H
27#define L_OPENSSH_H 27#define L_OPENSSH_H
28 28
29#include <limits.h> /* INT_MAX INT_MIN */
29#include <string.h> /* memset(3) */ 30#include <string.h> /* memset(3) */
31#include <math.h> /* fabs(3) floor(3) round(3) isfinite(3) */
30 32
31#include <openssl/err.h> 33#include <openssl/err.h>
34#include <openssl/bn.h>
32#include <openssl/x509.h> 35#include <openssl/x509.h>
33#include <openssl/x509v3.h> 36#include <openssl/x509v3.h>
34 37
@@ -37,8 +40,13 @@
37#include <lauxlib.h> 40#include <lauxlib.h>
38 41
39 42
40#define X509_NAME_CLASS "X.509 Name" 43#define X509_NAME_CLASS "OpenSSL X.509 Name"
41#define X509_CERT_CLASS "X.509 Cert" 44#define X509_CERT_CLASS "OpenSSL X.509 Cert"
45#define BIGNUM_CLASS "OpenSSL BN"
46
47
48#define countof(a) (sizeof (a) / sizeof *(a))
49#define endof(a) (&(a)[countof(a)])
42 50
43 51
44static void *prepudata(lua_State *L, const char *tname, size_t size) { 52static void *prepudata(lua_State *L, const char *tname, size_t size) {
@@ -50,7 +58,7 @@ static void *prepudata(lua_State *L, const char *tname, size_t size) {
50 58
51static void *prepsimple(lua_State *L, const char *tname) { 59static void *prepsimple(lua_State *L, const char *tname) {
52 void **p = prepudata(L, tname, sizeof (void *)); 60 void **p = prepudata(L, tname, sizeof (void *));
53 return *p; 61 return p;
54} /* presimple() */ 62} /* presimple() */
55 63
56 64
@@ -60,9 +68,18 @@ static void *checksimple(lua_State *L, int index, const char *tname) {
60} /* checksimple() */ 68} /* checksimple() */
61 69
62 70
63static int throwssl(lua_State *L, const char *func) { 71static int throwssl(lua_State *L, const char *fun) {
64 /* FIXME */ 72 unsigned long code;
65 return luaL_error(L, "%s: SSL error (%lu)", func, ERR_get_error()); 73 const char *file;
74 int line;
75 char txt[256];
76
77 code = ERR_get_error_line(&file, &line);
78 ERR_clear_error();
79
80 ERR_error_string_n(code, txt, sizeof txt);
81
82 return luaL_error(L, "%s: %s:%d:%s", fun, file, line, txt);
66} /* throwssl() */ 83} /* throwssl() */
67 84
68 85
@@ -93,6 +110,372 @@ static void addclass(lua_State *L, const char *name, const luaL_Reg *methods, co
93 110
94 111
95/* 112/*
113 * BIGNUM - openssl.bignum
114 *
115 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
116
117static BIGNUM *bn_push(lua_State *L) {
118 BIGNUM **ud = prepsimple(L, BIGNUM_CLASS);
119
120 if (!(*ud = BN_new()))
121 throwssl(L, "bignum.new");
122
123 return *ud;
124} /* bn_push() */
125
126
127static int bn_new(lua_State *L) {
128 bn_push(L);
129
130 return 1;
131} /* bn_new() */
132
133
134static int bn_interpose(lua_State *L) {
135 return interpose(L, BIGNUM_CLASS);
136} /* bn_interpose() */
137
138
139/* return integral part */
140static inline double intof(double f) {
141 return (isfinite(f))? floor(fabs(f)) : 0.0;
142} /* intof() */
143
144
145/* convert integral to BN_ULONG. returns success or failure. */
146static _Bool int2ul(BN_ULONG *ul, double f) {
147 int exp;
148
149 frexp(f, &exp);
150
151 if (exp > (int)sizeof *ul * 8)
152 return 0;
153
154 *ul = (BN_ULONG)f;
155
156 return 1;
157} /* int2ul() */
158
159
160/* convert integral BIGNUM. returns success or failure. */
161static _Bool int2bn(BIGNUM **bn, double q) {
162 unsigned char nib[32], bin[32], *p;
163 size_t i, n;
164 double r;
165
166 p = nib;
167
168 while (q >= 1.0 && p < endof(nib)) {
169 r = fmod(q, 256.0);
170 *p++ = r;
171 q = round((q - r) / 256.0);
172 }
173
174 n = p - nib;
175
176 for (i = 0; i < n; i++) {
177 bin[i] = *--p;
178 }
179
180 if (!(*bn = BN_bin2bn(bin, n, *bn)))
181 return 0;
182
183 return 1;
184} /* int2bn() */
185
186
187/* convert double to BIGNUM. returns success or failure. */
188static _Bool f2bn(BIGNUM **bn, double f) {
189 double i = intof(f);
190 BN_ULONG lu;
191
192 if (int2ul(&lu, i)) {
193 if (!*bn && !(*bn = BN_new()))
194 return 0;
195
196 if (!BN_set_word(*bn, lu))
197 return 0;
198 } else if (!int2bn(bn, i))
199 return 0;
200
201 BN_set_negative(*bn, signbit(f));
202
203 return 1;
204} /* f2bn() */
205
206
207static BIGNUM *checkbig(lua_State *L, int index, _Bool *lvalue) {
208 BIGNUM **bn;
209 const char *dec;
210 size_t len;
211
212 index = lua_absindex(L, index);
213
214 switch (lua_type(L, index)) {
215 case LUA_TSTRING:
216 *lvalue = 0;
217
218 dec = lua_tolstring(L, index, &len);
219
220 luaL_argcheck(L, len > 0 && *dec, index, "invalid big number string");
221
222 bn = prepsimple(L, BIGNUM_CLASS);
223
224 if (!BN_dec2bn(bn, dec))
225 throwssl(L, "bignum");
226
227 lua_replace(L, index);
228
229 return *bn;
230 case LUA_TNUMBER:
231 *lvalue = 0;
232
233 bn = prepsimple(L, BIGNUM_CLASS);
234
235 if (!f2bn(bn, lua_tonumber(L, index)))
236 throwssl(L, "bignum");
237
238 lua_replace(L, index);
239
240 return *bn;
241 default:
242 *lvalue = 1;
243
244 return checksimple(L, index, BIGNUM_CLASS);
245 } /* switch() */
246} /* checkbig() */
247
248
249static void bn_prepops(lua_State *L, BIGNUM **r, BIGNUM **a, BIGNUM **b, _Bool commute) {
250 _Bool lvalue = 1;
251
252 lua_settop(L, 2); /* a, b */
253
254 *a = checkbig(L, 1, &lvalue);
255
256 if (!lvalue && commute)
257 lua_pushvalue(L, 1);
258
259 *b = checkbig(L, 2, &lvalue);
260
261 if (!lvalue && commute && lua_gettop(L) < 3)
262 lua_pushvalue(L, 2);
263
264 if (lua_gettop(L) < 3)
265 bn_push(L);
266
267 *r = *(BIGNUM **)lua_touserdata(L, 3);
268} /* bn_prepops() */
269
270
271static int ctx__gc(lua_State *L) {
272 BN_CTX **ctx = lua_touserdata(L, 1);
273
274 BN_CTX_free(*ctx);
275 *ctx = NULL;
276
277 return 0;
278} /* ctx__gc() */
279
280static BN_CTX *getctx(lua_State *L) {
281 BN_CTX **ctx;
282
283 lua_pushcfunction(L, &ctx__gc);
284 lua_gettable(L, LUA_REGISTRYINDEX);
285
286 if (lua_isnil(L, -1)) {
287 lua_pop(L, 1);
288
289 ctx = lua_newuserdata(L, sizeof *ctx);
290 *ctx = NULL;
291
292 lua_newtable(L);
293 lua_pushcfunction(L, &ctx__gc);
294 lua_setfield(L, -2, "__gc");
295 lua_setmetatable(L, -2);
296
297 if (!(*ctx = BN_CTX_new()))
298 throwssl(L, "bignum");
299
300 lua_pushcfunction(L, &ctx__gc);
301 lua_pushvalue(L, -2);
302 lua_settable(L, LUA_REGISTRYINDEX);
303
304 }
305
306 ctx = lua_touserdata(L, -1);
307 lua_pop(L, 1);
308
309 return *ctx;
310} /* getctx() */
311
312
313static int bn__add(lua_State *L) {
314 BIGNUM *r, *a, *b;
315
316 bn_prepops(L, &r, &a, &b, 1);
317
318 if (!BN_add(r, a, b))
319 return throwssl(L, "bignum:__add");
320
321 return 1;
322} /* bn__add() */
323
324
325static int bn__sub(lua_State *L) {
326 BIGNUM *r, *a, *b;
327
328 bn_prepops(L, &r, &a, &b, 0);
329
330 if (!BN_sub(r, a, b))
331 return throwssl(L, "bignum:__sub");
332
333 return 1;
334} /* bn__sub() */
335
336
337static int bn__mul(lua_State *L) {
338 BIGNUM *r, *a, *b;
339
340 bn_prepops(L, &r, &a, &b, 1);
341
342 if (!BN_mul(r, a, b, getctx(L)))
343 return throwssl(L, "bignum:__mul");
344
345 return 1;
346} /* bn__mul() */
347
348
349static int bn__div(lua_State *L) {
350 BIGNUM *r, *a, *b;
351 BN_CTX *ctx;
352
353 bn_prepops(L, &r, &a, &b, 0);
354
355 if (!BN_div(r, NULL, a, b, getctx(L)))
356 return throwssl(L, "bignum:__div");
357
358 return 1;
359} /* bn__div() */
360
361
362static int bn__mod(lua_State *L) {
363 BIGNUM *r, *a, *b;
364 BN_CTX *ctx;
365
366 bn_prepops(L, &r, &a, &b, 0);
367
368 if (!BN_mod(r, a, b, getctx(L)))
369 return throwssl(L, "bignum:__mod");
370
371 return 1;
372} /* bn__mod() */
373
374
375static int bn__pow(lua_State *L) {
376 BIGNUM *r, *a, *b;
377 BN_CTX *ctx;
378
379 bn_prepops(L, &r, &a, &b, 0);
380
381 if (!BN_exp(r, a, b, getctx(L)))
382 return throwssl(L, "bignum:__pow");
383
384 return 1;
385} /* bn__pow() */
386
387
388static int bn__eq(lua_State *L) {
389 BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS);
390 BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS);
391
392 lua_pushboolean(L, 0 == BN_cmp(a, b));
393
394 return 1;
395} /* bn__eq() */
396
397
398static int bn__lt(lua_State *L) {
399 BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS);
400 BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS);
401 int cmp = BN_cmp(a, b);
402
403 lua_pushboolean(L, cmp == -1);
404
405 return 1;
406} /* bn__lt() */
407
408
409static int bn__le(lua_State *L) {
410 BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS);
411 BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS);
412 int cmp = BN_cmp(a, b);
413
414 lua_pushboolean(L, cmp <= 0);
415
416 return 1;
417} /* bn__le() */
418
419
420static int bn__gc(lua_State *L) {
421 BIGNUM **ud = luaL_checkudata(L, 1, BIGNUM_CLASS);
422
423 BN_free(*ud);
424 *ud = NULL;
425
426 return 0;
427} /* bn__gc() */
428
429
430static int bn__tostring(lua_State *L) {
431 BIGNUM *bn = checksimple(L, 1, X509_NAME_CLASS);
432 char *txt;
433
434 if (!(txt = BN_bn2dec(bn)))
435 throwssl(L, "bignum:__tostring");
436
437 lua_pushstring(L, txt);
438
439 return 1;
440} /* bn__tostring() */
441
442
443static const luaL_Reg bn_methods[] = {
444 { NULL, NULL },
445};
446
447static const luaL_Reg bn_metatable[] = {
448 { "__add", &bn__add },
449 { "__sub", &bn__sub },
450 { "__mul", &bn__mul },
451 { "__div", &bn__div },
452 { "__mod", &bn__mod },
453 { "__pow", &bn__pow },
454 { "__eq", &bn__eq },
455 { "__lt", &bn__lt },
456 { "__le", &bn__le },
457 { "__gc", &bn__gc },
458 { "__tostring", &bn__tostring },
459 { NULL, NULL },
460};
461
462
463static const luaL_Reg bn_globals[] = {
464 { "new", &bn_new },
465 { "interpose", &bn_interpose },
466 { NULL, NULL },
467};
468
469int luaopen__openssl_bignum_open(lua_State *L) {
470 addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable);
471
472 luaL_newlib(L, bn_globals);
473
474 return 1;
475} /* luaopen__openssl_bignum_open() */
476
477
478/*
96 * X509_NAME - openssl.x509.name 479 * X509_NAME - openssl.x509.name
97 * 480 *
98 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 481 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -152,14 +535,28 @@ static int xn__gc(lua_State *L) {
152} /* xn__gc() */ 535} /* xn__gc() */
153 536
154 537
538static int xn__tostring(lua_State *L) {
539 X509_NAME *name = checksimple(L, 1, X509_NAME_CLASS);
540 char txt[1024] = { 0 };
541
542 /* FIXME: oneline is deprecated */
543 X509_NAME_oneline(name, txt, sizeof txt);
544
545 lua_pushstring(L, txt);
546
547 return 1;
548} /* xn__tostring() */
549
550
155static const luaL_Reg xn_methods[] = { 551static const luaL_Reg xn_methods[] = {
156 { "add", &xn_add }, 552 { "add", &xn_add },
157 { NULL, NULL }, 553 { NULL, NULL },
158}; 554};
159 555
160static const luaL_Reg xn_metatable[] = { 556static const luaL_Reg xn_metatable[] = {
161 { "__gc", &xn__gc }, 557 { "__gc", &xn__gc },
162 { NULL, NULL }, 558 { "__tostring", &xn__tostring },
559 { NULL, NULL },
163}; 560};
164 561
165 562
@@ -178,5 +575,187 @@ int luaopen__openssl_x509_name_open(lua_State *L) {
178} /* luaopen__openssl_x509_name_open() */ 575} /* luaopen__openssl_x509_name_open() */
179 576
180 577
578/*
579 * X509_NAME - openssl.x509.name
580 *
581 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
582
583static int xc_new(lua_State *L) {
584 X509 **ud = prepsimple(L, X509_CERT_CLASS);
585
586 if (!(*ud = X509_new()))
587 return throwssl(L, "x509.cert.new");
588
589 X509_gmtime_adj(X509_get_notBefore(*ud), 0);
590 X509_gmtime_adj(X509_get_notAfter(*ud), 0);
591
592 return 1;
593} /* xc_new() */
594
595
596static int xc_interpose(lua_State *L) {
597 return interpose(L, X509_CERT_CLASS);
598} /* xc_interpose() */
599
600
601static int xc_getVersion(lua_State *L) {
602 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
603
604 lua_pushinteger(L, X509_get_version(crt) + 1);
605
606 return 1;
607} /* xc_getVersion() */
608
609
610static int xc_setVersion(lua_State *L) {
611 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
612 int version = luaL_checkint(L, 2);
613
614 if (!X509_set_version(crt, version - 1))
615 return luaL_error(L, "x509.cert:setVersion: %d: invalid version", version);
616
617 lua_pushboolean(L, 1);
618
619 return 1;
620} /* xc_setVersion() */
621
622
623static int xc_getSerialNumber(lua_State *L) {
624 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
625 BIGNUM *srl = bn_push(L);
626 ASN1_INTEGER *num;
627
628 if ((num = X509_get_serialNumber(crt))) {
629 if (!ASN1_INTEGER_to_BN(num, srl))
630 return throwssl(L, "x509.cert.getSerialNumber");
631 }
632
633 return 1;
634} /* xc_getSerialNumber() */
635
636
637static int xc_setSerialNumber(lua_State *L) {
638 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
639 ASN1_INTEGER *srl = NULL;
640 int ok;
641
642 luaL_checkany(L, 2);
643
644 if (lua_isstring(L, 2)) {
645 BIGNUM *num = NULL;
646
647 if (!BN_dec2bn(&num, lua_tostring(L, 2)))
648 goto error;
649
650 if (!(srl = ASN1_INTEGER_new()) || !(BN_to_ASN1_INTEGER(num, srl)))
651 goto error;
652
653 ok = X509_set_serialNumber(crt, srl);
654 ASN1_INTEGER_free(srl);
655
656 if (!ok)
657 goto error;
658 } else {
659 BIGNUM *num = checksimple(L, 2, BIGNUM_CLASS);
660
661 if (!(srl = ASN1_INTEGER_new()) || !(BN_to_ASN1_INTEGER(num, srl)))
662 goto error;
663
664 ok = X509_set_serialNumber(crt, srl);
665 ASN1_INTEGER_free(srl);
666
667 if (!ok)
668 goto error;
669 }
670
671 lua_pushboolean(L, 1);
672
673 return 1;
674error:
675 return throwssl(L, "x509.cert.setSerialNumber");
676} /* xc_setSerialNumber() */
677
678
679#if 0
680static int xc_digest(lua_State *L) {
681 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
682 const char *type = luaL_optstring(L, 2, "sha1");
683 const EVP_MD *dgst;
684 unsigned char md[EVP_MAX_MD_SIZE];
685 unsigned int len;
686
687 if (!(dgst = EVP_getdigestbyname(type)))
688 return luaL_error(L, "x509.cert:digest: %s: invalid digest type", type);
689
690 X509_digest(crt, dgst, md, &len);
691
692 lua_pushlstring(L, md, len);
693
694 return 1;
695} /* xc_digest() */
696#endif
697
698static int xc_lifetime(lua_State *L) {
699 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
700 return 0;
701} /* xc_lifetime() */
702
703
704static int xc_issuer(lua_State *L) {
705 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
706 X509_NAME *name;
707
708 lua_settop(L, 2);
709
710 if ((name = X509_get_issuer_name(crt)))
711 xn_dup(L, name);
712
713 if (!lua_isnil(L, 2))
714 X509_set_issuer_name(crt, checksimple(L, 2, X509_NAME_CLASS));
715
716 return !!name;
717} /* xc_issuer() */
718
719
720static int xc__gc(lua_State *L) {
721 X509 **ud = luaL_checkudata(L, 1, X509_CERT_CLASS);
722
723 X509_free(*ud);
724 *ud = NULL;
725
726 return 0;
727} /* xc__gc() */
728
729
730static const luaL_Reg xc_methods[] = {
731 { "getVersion", &xc_getVersion },
732 { "setVersion", &xc_setVersion },
733 { NULL, NULL },
734};
735
736static const luaL_Reg xc_metatable[] = {
737 { "__gc", &xc__gc },
738 { NULL, NULL },
739};
740
741
742static const luaL_Reg xc_globals[] = {
743 { "new", &xc_new },
744 { "interpose", &xc_interpose },
745 { NULL, NULL },
746};
747
748int luaopen__openssl_x509_cert_open(lua_State *L) {
749 addclass(L, X509_CERT_CLASS, xc_methods, xc_metatable);
750
751 luaL_newlib(L, xc_globals);
752
753 return 1;
754} /* luaopen__openssl_x509_cert_open() */
755
756
757
758
759
181 760
182#endif /* L_OPENSSL_H */ 761#endif /* L_OPENSSL_H */