1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.
3 * The ASF licenses this file to You under the Apache License, Version 2.0
4 * (the "License"); you may not use this file except in compliance with
5 * the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 * ---------------------------------------------------------------------------
16 * This work is derived from the famos luacrypto library:
17 *
18 * The LuaCrypto library is designed and implemented by Keith Howe. The
19 * implementation is not derived from licensed software.
20 *
21 * Copyright © 2006 Keith Howe.
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to
25 * deal in the Software without restriction, including without limitation the
26 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
27 * sell copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in all
31 * copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
38 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
39 * IN THE SOFTWARE.
40 * ---------------------------------------------------------------------------
41 */
42
43 /**
44 * @file
45 *
46 * @Author christian liesch <liesch@gmx.ch>
47 *
48 * Interface of the HTTP Test Tool lua crypto extention.
49 */
50
51
52 /************************************************************************
53 * Includes
54 ***********************************************************************/
55
56 #ifdef HAVE_CONFIG_H
57 #include <config.h>
58 #endif
59
60 #include <string.h>
61 #include <openssl/ssl.h>
62 #include <openssl/err.h>
63 #include <openssl/asn1.h>
64 #include <openssl/evp.h>
65 #include <openssl/hmac.h>
66 #include <openssl/rand.h>
67 #include <openssl/x509.h>
68 #include <openssl/dh.h>
69
70 #define LUA_COMPAT_MODULE
71 #include "lua.h"
72 #include "lauxlib.h"
73 #if ! defined (LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
74 #include "compat-5.1.h"
75 #endif
76
77 #include "lua_crypto.h"
78 #include "module.h"
79
80 /************************************************************************
81 * Definitions
82 ***********************************************************************/
83
84 #define LUACRYPTO_PREFIX "LuaCrypto: "
85 #define LUACRYPTO_CORE "crypto"
86 #define LUACRYPTO_EVP "crypto.evp"
87 #define LUACRYPTO_HMAC "crypto.hmac"
88 #define LUACRYPTO_RAND "crypto.rand"
89 #define LUACRYPTO_BASE64 "crypto.base64"
90 #define LUACRYPTO_X509 "crypto.x509"
91 #define LUACRYPTO_X509NAME "crypto.x509name"
92 #define LUACRYPTO_ASN1TIME "crypto.asn1time"
93 #define LUACRYPTO_DH "crypto.dh"
94
95
96 /************************************************************************
97 * Forward declaration
98 ***********************************************************************/
99
100 int luaopen_crypto(lua_State *L);
101
102
103 /************************************************************************
104 * Implementation
105 ***********************************************************************/
106
crypto_error(lua_State * L)107 static int crypto_error(lua_State *L) {
108 char buf[120];
109 unsigned long e = ERR_get_error();
110 ERR_load_crypto_strings();
111 lua_pushnil(L);
112 lua_pushstring(L, ERR_error_string(e, buf));
113 return 2;
114 }
115
116 /**
117 * EVP Object
118 */
evp_pget(lua_State * L,int i)119 static EVP_MD_CTX *evp_pget(lua_State *L, int i) {
120 if (luaL_checkudata(L, i, LUACRYPTO_EVP) == NULL) {
121 luaL_argerror(L, 1, "invalid object type");
122 }
123 return lua_touserdata(L, i);
124 }
125
evp_pnew(lua_State * L)126 static EVP_MD_CTX *evp_pnew(lua_State *L) {
127 EVP_MD_CTX *c = lua_newuserdata(L, sizeof(c));
128 luaL_getmetatable(L, LUACRYPTO_EVP);
129 lua_setmetatable(L, -2);
130 return c;
131 }
132
evp_fnew(lua_State * L)133 static int evp_fnew(lua_State *L) {
134 EVP_MD_CTX *c = NULL;
135 const char *s = luaL_checkstring(L, 1);
136 const EVP_MD *type = EVP_get_digestbyname(s);
137
138 if (type == NULL) {
139 luaL_argerror(L, 1, "invalid digest type");
140 return 0;
141 }
142
143 c = evp_pnew(L);
144 EVP_MD_CTX_init(c);
145 EVP_DigestInit_ex(c, type, NULL);
146
147 return 1;
148 }
149
evp_clone(lua_State * L)150 static int evp_clone(lua_State *L) {
151 EVP_MD_CTX *c = evp_pget(L, 1);
152 EVP_MD_CTX *d = evp_pnew(L);
153 EVP_MD_CTX_init(d);
154 EVP_MD_CTX_copy_ex(d, c);
155 return 1;
156 }
157
evp_reset(lua_State * L)158 static int evp_reset(lua_State *L) {
159 EVP_MD_CTX *c = evp_pget(L, 1);
160 const EVP_MD *t = EVP_MD_CTX_md(c);
161 EVP_MD_CTX_reset(c);
162 EVP_DigestInit_ex(c, t, NULL);
163 return 0;
164 }
165
evp_update(lua_State * L)166 static int evp_update(lua_State *L) {
167 EVP_MD_CTX *c = evp_pget(L, 1);
168 const char *s = luaL_checkstring(L, 2);
169
170 EVP_DigestUpdate(c, s, strlen(s));
171
172 lua_settop(L, 1);
173 return 1;
174 }
175
evp_digest(lua_State * L)176 static int evp_digest(lua_State *L) {
177 EVP_MD_CTX *c = evp_pget(L, 1);
178 EVP_MD_CTX *d = NULL;
179 unsigned char digest[EVP_MAX_MD_SIZE];
180 unsigned int written = 0;
181 unsigned int i;
182 char *hex;
183
184 if (lua_isstring(L, 2)) {
185 const char *s = luaL_checkstring(L, 2);
186 EVP_DigestUpdate(c, s, strlen(s));
187 }
188
189 d = EVP_MD_CTX_create();
190 EVP_MD_CTX_copy_ex(d, c);
191 EVP_DigestFinal_ex(d, digest, &written);
192 EVP_MD_CTX_destroy(d);
193
194 if (lua_toboolean(L, 3)) {
195 lua_pushlstring(L, (char *)digest, written);
196 }
197 else {
198 hex = calloc(sizeof(char), written*2 + 1);
199 for (i = 0; i < written; i++)
200 sprintf(hex + 2*i, "%02x", digest[i]);
201 lua_pushlstring(L, hex, written*2);
202 free(hex);
203 }
204
205 return 1;
206 }
207
evp_tostring(lua_State * L)208 static int evp_tostring(lua_State *L) {
209 EVP_MD_CTX *c = evp_pget(L, 1);
210 char s[64];
211 sprintf(s, "%s %p", LUACRYPTO_EVP, (void *)c);
212 lua_pushstring(L, s);
213 return 1;
214 }
215
evp_gc(lua_State * L)216 static int evp_gc(lua_State *L) {
217 EVP_MD_CTX *c = evp_pget(L, 1);
218 EVP_MD_CTX_free(c);
219 return 1;
220 }
221
evp_fdigest(lua_State * L)222 static int evp_fdigest(lua_State *L) {
223 EVP_MD_CTX *c = NULL;
224 const char *type_name = luaL_checkstring(L, 1);
225 const char *s = luaL_checkstring(L, 2);
226 const EVP_MD *type = EVP_get_digestbyname(type_name);
227 unsigned char digest[EVP_MAX_MD_SIZE];
228 unsigned int written = 0;
229 unsigned int i;
230 char *hex;
231
232 if (type == NULL) {
233 luaL_argerror(L, 1, "invalid digest type");
234 return 0;
235 }
236
237 c = EVP_MD_CTX_create();
238 EVP_DigestInit_ex(c, type, NULL);
239 EVP_DigestUpdate(c, s, strlen(s));
240 EVP_DigestFinal_ex(c, digest, &written);
241
242 if (lua_toboolean(L, 3)) {
243 lua_pushlstring(L, (char *)digest, written);
244 }
245 else {
246 hex = calloc(sizeof(char), written*2 + 1);
247 for (i = 0; i < written; i++) {
248 sprintf(hex + 2*i, "%02x", digest[i]);
249 }
250 lua_pushlstring(L, hex, written*2);
251 free(hex);
252 }
253
254 return 1;
255 }
256
257 /**
258 * HMAC Object
259 */
hmac_pget(lua_State * L,int i)260 static HMAC_CTX *hmac_pget(lua_State *L, int i) {
261 if (luaL_checkudata(L, i, LUACRYPTO_HMAC) == NULL) {
262 luaL_argerror(L, 1, "invalid object type");
263 }
264 return lua_touserdata(L, i);
265 }
266
hmac_pnew(lua_State * L)267 static HMAC_CTX *hmac_pnew(lua_State *L) {
268 HMAC_CTX *c = lua_newuserdata(L, sizeof(c));
269 luaL_getmetatable(L, LUACRYPTO_HMAC);
270 lua_setmetatable(L, -2);
271 return c;
272 }
273
hmac_fnew(lua_State * L)274 static int hmac_fnew(lua_State *L) {
275 HMAC_CTX *c = hmac_pnew(L);
276 const char *s = luaL_checkstring(L, 1);
277 const char *k = luaL_checkstring(L, 2);
278 const EVP_MD *type = EVP_get_digestbyname(s);
279
280 if (type == NULL) {
281 luaL_argerror(L, 1, "invalid digest type");
282 return 0;
283 }
284
285 c = HMAC_CTX_new();
286 HMAC_Init_ex(c, k, strlen(k), type, NULL);
287
288 return 1;
289 }
290
hmac_clone(lua_State * L)291 static int hmac_clone(lua_State *L) {
292 HMAC_CTX *c = hmac_pget(L, 1);
293 HMAC_CTX *d = hmac_pnew(L);
294 HMAC_CTX_copy(d, c);
295 return 1;
296 }
297
hmac_reset(lua_State * L)298 static int hmac_reset(lua_State *L) {
299 HMAC_CTX *c = hmac_pget(L, 1);
300 HMAC_Init_ex(c, NULL, 0, NULL, NULL);
301 return 0;
302 }
303
hmac_update(lua_State * L)304 static int hmac_update(lua_State *L) {
305 HMAC_CTX *c = hmac_pget(L, 1);
306 const char *s = luaL_checkstring(L, 2);
307
308 HMAC_Update(c, (unsigned char *)s, strlen(s));
309
310 lua_settop(L, 1);
311 return 1;
312 }
313
hmac_digest(lua_State * L)314 static int hmac_digest(lua_State *L) {
315 HMAC_CTX *c = hmac_pget(L, 1);
316 unsigned char digest[EVP_MAX_MD_SIZE];
317 unsigned int written = 0;
318 unsigned int i;
319 char *hex;
320
321 if (lua_isstring(L, 2))
322 {
323 const char *s = luaL_checkstring(L, 2);
324 HMAC_Update(c, (unsigned char *)s, strlen(s));
325 }
326
327 HMAC_Final(c, digest, &written);
328
329 if (lua_toboolean(L, 3)) {
330 lua_pushlstring(L, (char *)digest, written);
331 }
332 else {
333 hex = calloc(sizeof(char), written*2 + 1);
334 for (i = 0; i < written; i++) {
335 sprintf(hex + 2*i, "%02x", digest[i]);
336 }
337 lua_pushlstring(L, hex, written*2);
338 free(hex);
339 }
340
341 return 1;
342 }
343
hmac_tostring(lua_State * L)344 static int hmac_tostring(lua_State *L) {
345 HMAC_CTX *c = hmac_pget(L, 1);
346 char s[64];
347 sprintf(s, "%s %p", LUACRYPTO_HMAC, (void *)c);
348 lua_pushstring(L, s);
349 return 1;
350 }
351
hmac_gc(lua_State * L)352 static int hmac_gc(lua_State *L) {
353 HMAC_CTX *c = hmac_pget(L, 1);
354 HMAC_CTX_free(c);
355 return 1;
356 }
357
hmac_fdigest(lua_State * L)358 static int hmac_fdigest(lua_State *L) {
359 HMAC_CTX *c;
360 unsigned char digest[EVP_MAX_MD_SIZE];
361 unsigned int written = 0;
362 unsigned int i;
363 char *hex;
364 const char *t = luaL_checkstring(L, 1);
365 const char *s = luaL_checkstring(L, 2);
366 const char *k = luaL_checkstring(L, 3);
367 const EVP_MD *type = EVP_get_digestbyname(t);
368
369 if (type == NULL) {
370 luaL_argerror(L, 1, "invalid digest type");
371 return 0;
372 }
373
374 c = HMAC_CTX_new();
375 HMAC_Init_ex(c, k, strlen(k), type, NULL);
376 HMAC_Update(c, (unsigned char *)s, strlen(s));
377 HMAC_Final(c, digest, &written);
378 HMAC_CTX_free(c);
379
380 if (lua_toboolean(L, 4)) {
381 lua_pushlstring(L, (char *)digest, written);
382 }
383 else {
384 hex = calloc(sizeof(char), written*2 + 1);
385 for (i = 0; i < written; i++) {
386 sprintf(hex + 2*i, "%02x", digest[i]);
387 }
388 lua_pushlstring(L, hex, written*2);
389 free(hex);
390 }
391
392 return 1;
393 }
394
395 /**
396 * Random Object
397 */
rand_do_bytes(lua_State * L,int (* bytes)(unsigned char * buf,int len))398 static int rand_do_bytes(lua_State *L, int (*bytes)(unsigned char *buf, int len)) {
399 size_t count = luaL_checkint(L, 1);
400 unsigned char tmp[256], *buf = tmp;
401 if (count > sizeof tmp) {
402 buf = malloc(count);
403 }
404 if (!buf) {
405 return luaL_error(L, "out of memory");
406 }
407 else if (!bytes(buf, count)) {
408 return crypto_error(L);
409 }
410 lua_pushlstring(L, (char *)buf, count);
411 if (buf != tmp) {
412 free(buf);
413 }
414 return 1;
415 }
416
rand_bytes(lua_State * L)417 static int rand_bytes(lua_State *L) {
418 return rand_do_bytes(L, RAND_bytes);
419 }
420
rand_pseudo_bytes(lua_State * L)421 static int rand_pseudo_bytes(lua_State *L) {
422 return rand_do_bytes(L, RAND_pseudo_bytes);
423 }
424
rand_add(lua_State * L)425 static int rand_add(lua_State *L) {
426 size_t num;
427 const void *buf = luaL_checklstring(L, 1, &num);
428 double entropy = luaL_optnumber(L, 2, num);
429 RAND_add(buf, num, entropy);
430 return 0;
431 }
432
rand_status(lua_State * L)433 static int rand_status(lua_State *L) {
434 lua_pushboolean(L, RAND_status());
435 return 1;
436 }
437
438 enum { WRITE_FILE_COUNT = 1024 };
rand_load(lua_State * L)439 static int rand_load(lua_State *L) {
440 const char *name = luaL_optstring(L, 1, 0);
441 char tmp[256];
442 int n;
443 if (!name && !(name = RAND_file_name(tmp, sizeof tmp))) {
444 return crypto_error(L);
445 }
446 n = RAND_load_file(name, WRITE_FILE_COUNT);
447 if (n == 0) {
448 return crypto_error(L);
449 }
450 lua_pushnumber(L, n);
451 return 1;
452 }
453
rand_write(lua_State * L)454 static int rand_write(lua_State *L) {
455 const char *name = luaL_optstring(L, 1, 0);
456 char tmp[256];
457 int n;
458 if (!name && !(name = RAND_file_name(tmp, sizeof tmp))) {
459 return crypto_error(L);
460 }
461 n = RAND_write_file(name);
462 if (n == 0) {
463 return crypto_error(L);
464 }
465 lua_pushnumber(L, n);
466 return 1;
467 }
468
rand_cleanup(lua_State * L)469 static int rand_cleanup(lua_State *L) {
470 RAND_cleanup();
471 return 0;
472 }
473
474 /**
475 * Base64
476 */
b64_encode(lua_State * L)477 static int b64_encode(lua_State *L) {
478 if (lua_isstring(L, -1)) {
479 apr_pool_t *pool;
480 apr_size_t len;
481 apr_size_t b64len;
482 char *base64;
483
484 const char *buffer = lua_tolstring(L, -1, &len);
485
486 HT_POOL_CREATE(&pool);
487 b64len = apr_base64_encode_len(len);
488 base64 = apr_pcalloc(pool, b64len + 1);
489 apr_base64_encode(base64, buffer, len);
490
491 lua_pushstring(L, base64);
492 apr_pool_destroy(pool);
493 return 1;
494 }
495 else {
496 luaL_error(L, "Expect a string parameter");
497 return 1;
498 }
499 }
500
b64_decode(lua_State * L)501 static int b64_decode(lua_State *L) {
502 if (lua_isstring(L, -1)) {
503 apr_pool_t *pool;
504 apr_size_t len;
505 unsigned char *plain;
506
507 const char *buffer = lua_tolstring(L, -1, &len);
508
509 HT_POOL_CREATE(&pool);
510
511 len = apr_base64_decode_len(buffer);
512 plain = apr_pcalloc(pool, len);
513 apr_base64_decode_binary(plain, buffer);
514
515 lua_pushlstring(L, (char *)plain, len);
516 apr_pool_destroy(pool);
517 return 1;
518 }
519 else {
520 luaL_error(L, "Expect a string parameter");
521 return 1;
522 }
523 }
524
525 /**
526 * X509 Object
527 */
x509_pget(lua_State * L,int i)528 static X509 *x509_pget(lua_State *L, int i) {
529 if (luaL_checkudata(L, i, LUACRYPTO_X509) == NULL) {
530 luaL_argerror(L, 1, "invalid object type");
531 }
532 return lua_touserdata(L, i);
533 }
534
x509_fnew(lua_State * L)535 static int x509_fnew(lua_State *L) {
536 apr_size_t len;
537 const char *data = luaL_checklstring(L, 1, &len);
538 X509 *cert;
539 BIO *mem;
540
541 if (data == NULL) {
542 luaL_argerror(L, 1, "PEM cert to load");
543 return 0;
544 }
545
546 mem = BIO_new_mem_buf((void *)data, len);
547 cert = PEM_read_bio_X509(mem, NULL, NULL, NULL);
548
549 lua_pushlightuserdata(L, cert);
550 luaL_getmetatable(L, LUACRYPTO_X509);
551 lua_setmetatable(L, -2);
552
553 return 1;
554 }
555
x509_fload(lua_State * L)556 static int x509_fload(lua_State *L) {
557 const char *filename = luaL_checkstring(L, 1);
558 X509 *cert;
559 BIO *file;
560
561 if (filename == NULL) {
562 luaL_argerror(L, 1, "path to x509 pem formated cert missing");
563 return 0;
564 }
565
566 file = BIO_new_file(filename, "r");
567 cert = PEM_read_bio_X509(file, NULL, NULL, NULL);
568
569 lua_pushlightuserdata(L, cert);
570 luaL_getmetatable(L, LUACRYPTO_X509);
571 lua_setmetatable(L, -2);
572
573 return 1;
574 }
575
x509_clone(lua_State * L)576 static int x509_clone(lua_State *L) {
577 X509 *cert = x509_pget(L, 1);
578 X509 *copy = X509_dup(cert);
579
580 lua_pushlightuserdata(L, copy);
581 luaL_getmetatable(L, LUACRYPTO_X509);
582 lua_setmetatable(L, -2);
583 return 1;
584 }
585
x509_get_subject_name(lua_State * L)586 static int x509_get_subject_name(lua_State *L) {
587 X509 *cert = x509_pget(L, 1);
588 X509_NAME *name = X509_get_subject_name(cert);
589
590 lua_pushlightuserdata(L, name);
591 luaL_getmetatable(L, LUACRYPTO_X509NAME);
592 lua_setmetatable(L, -2);
593 return 1;
594 }
595
x509_get_issuer_name(lua_State * L)596 static int x509_get_issuer_name(lua_State *L) {
597 X509 *cert = x509_pget(L, 1);
598 X509_NAME *name = X509_get_issuer_name(cert);
599
600 lua_pushlightuserdata(L, name);
601 luaL_getmetatable(L, LUACRYPTO_X509NAME);
602 lua_setmetatable(L, -2);
603 return 1;
604 }
605
x509_get_not_before(lua_State * L)606 static int x509_get_not_before(lua_State *L) {
607 X509 *cert = x509_pget(L, 1);
608 ASN1_TIME *time = X509_get_notBefore(cert);
609
610 lua_pushlightuserdata(L, time);
611 luaL_getmetatable(L, LUACRYPTO_ASN1TIME);
612 lua_setmetatable(L, -2);
613 return 1;
614 }
615
x509_get_not_after(lua_State * L)616 static int x509_get_not_after(lua_State *L) {
617 X509 *cert = x509_pget(L, 1);
618 ASN1_TIME *time = X509_get_notAfter(cert);
619
620 lua_pushlightuserdata(L, time);
621 luaL_getmetatable(L, LUACRYPTO_ASN1TIME);
622 lua_setmetatable(L, -2);
623 return 1;
624 }
625
x509_tostring(lua_State * L)626 static int x509_tostring(lua_State *L) {
627 apr_pool_t *pool;
628 X509 *cert = x509_pget(L, 1);
629 char *s;
630 HT_POOL_CREATE(&pool);
631 s = apr_psprintf(pool, "X509 cert %p", (void *)cert);
632 lua_pushstring(L, s);
633 apr_pool_destroy(pool);
634 return 1;
635 }
636
x509_gc(lua_State * L)637 static int x509_gc(lua_State *L) {
638 X509 *c = x509_pget(L, 1);
639 X509_free(c);
640 return 1;
641 }
642
643 /**
644 * X509_NAME Object
645 */
x509_name_pget(lua_State * L,int i)646 static X509_NAME *x509_name_pget(lua_State *L, int i) {
647 if (luaL_checkudata(L, i, LUACRYPTO_X509NAME) == NULL) {
648 luaL_argerror(L, 1, "invalid object type");
649 }
650 return lua_touserdata(L, i);
651 }
652
x509_name_clone(lua_State * L)653 static int x509_name_clone(lua_State *L) {
654 X509_NAME *name = x509_name_pget(L, 1);
655 X509_NAME *copy = X509_NAME_dup(name);
656
657 lua_pushlightuserdata(L, copy);
658 luaL_getmetatable(L, LUACRYPTO_X509NAME);
659 lua_setmetatable(L, -2);
660 return 1;
661 }
662
x509_name_tostring(lua_State * L)663 static int x509_name_tostring(lua_State *L) {
664 char *s;
665 X509_NAME *name = x509_name_pget(L, 1);
666 s = X509_NAME_oneline(name, NULL, 0);
667 lua_pushstring(L, s);
668 OPENSSL_free(s);
669 return 1;
670 }
671
x509_name_toasn1(lua_State * L)672 static int x509_name_toasn1(lua_State *L) {
673 unsigned char *s = NULL;
674 apr_size_t len;
675 X509_NAME *name = x509_name_pget(L, 1);
676 len = i2d_X509_NAME(name, &s);
677 lua_pushlstring(L, (char *)s, len);
678 OPENSSL_free(s);
679 return 1;
680 }
681
x509_name_gc(lua_State * L)682 static int x509_name_gc(lua_State *L) {
683 X509_NAME *name = x509_name_pget(L, 1);
684 X509_NAME_free(name);
685 return 1;
686 }
687
688 /**
689 * ASN1_TIME Object
690 */
asn1_time_pget(lua_State * L,int i)691 static ASN1_TIME *asn1_time_pget(lua_State *L, int i) {
692 if (luaL_checkudata(L, i, LUACRYPTO_ASN1TIME) == NULL) {
693 luaL_argerror(L, 1, "invalid object type");
694 }
695 return lua_touserdata(L, i);
696 }
697
asn1_time_fnew(lua_State * L)698 static int asn1_time_fnew(lua_State *L) {
699 ASN1_TIME *asn1time = (ASN1_TIME *)ASN1_STRING_type_new(V_ASN1_UTCTIME);
700 time_t t = time(NULL);
701 ASN1_TIME_set(asn1time, t);
702 lua_pushlightuserdata(L, asn1time);
703 luaL_getmetatable(L, LUACRYPTO_ASN1TIME);
704 lua_setmetatable(L, -2);
705
706 return 1;
707 }
708
asn1_time_clone(lua_State * L)709 static int asn1_time_clone(lua_State *L) {
710 ASN1_TIME *time = asn1_time_pget(L, 1);
711 ASN1_TIME *copy = ASN1_STRING_dup((const ASN1_STRING *)time);
712
713 lua_pushlightuserdata(L, copy);
714 luaL_getmetatable(L, LUACRYPTO_ASN1TIME);
715 lua_setmetatable(L, -2);
716 return 1;
717 }
718
asn1_time_tostring(lua_State * L)719 static int asn1_time_tostring(lua_State *L) {
720 char s[1024];
721 BIO *mem;
722 ASN1_TIME *time = asn1_time_pget(L, 1);
723 mem = BIO_new_mem_buf((void *)s, 1024);
724 ASN1_TIME_print(mem, time);
725 lua_pushstring(L, s);
726 return 1;
727 }
728
asn1_time_toasn1(lua_State * L)729 static int asn1_time_toasn1(lua_State *L) {
730 unsigned char *s = NULL;
731 apr_size_t len;
732 ASN1_TIME *time = asn1_time_pget(L, 1);
733 len = i2d_ASN1_TIME(time, &s);
734 lua_pushlstring(L, (char *)s, len);
735 OPENSSL_free(s);
736 return 1;
737 }
738
asn1_time_gc(lua_State * L)739 static int asn1_time_gc(lua_State *L) {
740 ASN1_TIME *time = asn1_time_pget(L, 1);
741 ASN1_STRING_free((ASN1_STRING *)time);
742 return 1;
743 }
744
745 /**
746 * DH object
747 */
748
dh_cb(int p,int n,BN_GENCB * cb)749 static int dh_cb(int p, int n, BN_GENCB *cb) {
750 char c='*';
751
752 switch (p) {
753 case 0:
754 c='.';
755 break;
756 case 1:
757 c='+';
758 break;
759 case 2:
760 c='*';
761 break;
762 case 3:
763 c='\n';
764 break;
765 }
766 BIO_write(BN_GENCB_get_arg(cb),&c,1);
767 (void)BIO_flush(BN_GENCB_get_arg(cb));
768 return 1;
769 }
770
dh_pget(lua_State * L,int i)771 static DH *dh_pget(lua_State *L, int i) {
772 if (luaL_checkudata(L, i, LUACRYPTO_DH) == NULL) {
773 luaL_argerror(L, 1, "invalid object type");
774 }
775 return lua_touserdata(L, i);
776 }
777
dh_fnew(lua_State * L)778 static int dh_fnew(lua_State *L) {
779 int generator = luaL_checknumber(L, 1);
780 int num = luaL_checknumber(L, 2);
781 DH *dh = DH_new();
782 BIO *bio_err;
783 BN_GENCB *cb;
784 cb = BN_GENCB_new();
785 if (!cb) {
786 luaL_argerror(L, 1, "could not create BN_GENCB structure");
787 return 1;
788 }
789 if ((bio_err = BIO_new(BIO_s_file())) != NULL) {
790 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
791 }
792 BN_GENCB_set(cb, dh_cb, bio_err);
793 if (!DH_generate_parameters_ex(dh, num, generator, cb)) {
794 luaL_argerror(L, 1, "could not generate DH paramters");
795 BN_GENCB_free(cb);
796 return 1;
797 }
798 DH_generate_key(dh);
799 lua_pushlightuserdata(L, dh);
800 luaL_getmetatable(L, LUACRYPTO_DH);
801 lua_setmetatable(L, -2);
802 BN_GENCB_free(cb);
803
804 return 1;
805 }
806
dh_clone(lua_State * L)807 static int dh_clone(lua_State *L) {
808 DH *dh = dh_pget(L, 1);
809 DH *copy = DHparams_dup(dh);
810
811 lua_pushlightuserdata(L, copy);
812 luaL_getmetatable(L, LUACRYPTO_DH);
813 lua_setmetatable(L, -2);
814 return 1;
815 }
816
dh_tostring(lua_State * L)817 static int dh_tostring(lua_State *L) {
818 char *s;
819 apr_pool_t *pool;
820 DH *dh = dh_pget(L, 1);
821 HT_POOL_CREATE(&pool);
822 s = apr_psprintf(pool, "DH %p", (void *)dh);
823 lua_pushstring(L, s);
824 apr_pool_destroy(pool);
825 return 1;
826 }
827
828 #if !defined(LIBRESSL_VERSION_NUMBER)
dh_get_prime(lua_State * L)829 static int dh_get_prime(lua_State *L) {
830 apr_size_t len;
831 unsigned char *s;
832 apr_pool_t *pool;
833 DH *dh = dh_pget(L, 1);
834 HT_POOL_CREATE(&pool);
835 s = apr_pcalloc(pool, BN_num_bytes(DH_get0_p(dh)));
836 len = BN_bn2bin(DH_get0_p(dh), s);
837 lua_pushlstring(L, (char *)s, len);
838 apr_pool_destroy(pool);
839 return 1;
840 }
841 #endif
842
843 #if !defined(LIBRESSL_VERSION_NUMBER)
dh_get_priv_key(lua_State * L)844 static int dh_get_priv_key(lua_State *L) {
845 apr_size_t len;
846 unsigned char *s;
847 apr_pool_t *pool;
848 DH *dh = dh_pget(L, 1);
849 HT_POOL_CREATE(&pool);
850 s = apr_pcalloc(pool, BN_num_bytes(DH_get0_priv_key(dh)));
851 len = BN_bn2bin(DH_get0_priv_key(dh), s);
852 lua_pushlstring(L, (char *)s, len);
853 apr_pool_destroy(pool);
854 return 1;
855 }
856 #endif
857
858 #if !defined(LIBRESSL_VERSION_NUMBER)
dh_get_pub_key(lua_State * L)859 static int dh_get_pub_key(lua_State *L) {
860 apr_size_t len;
861 unsigned char *s;
862 apr_pool_t *pool;
863 DH *dh = dh_pget(L, 1);
864 HT_POOL_CREATE(&pool);
865 s = apr_pcalloc(pool, BN_num_bytes(DH_get0_pub_key(dh)));
866 len = BN_bn2bin(DH_get0_pub_key(dh), s);
867 lua_pushlstring(L, (char *)s, len);
868 apr_pool_destroy(pool);
869 return 1;
870 }
871 #endif
872
dh_gc(lua_State * L)873 static int dh_gc(lua_State *L) {
874 DH *dh = dh_pget(L, 1);
875 DH_free(dh);
876 return 1;
877 }
878
879 /**
880 * Create a metatable and leave it on top of the stack.
881 */
luacrypto_createmeta(lua_State * L,const char * name,const luaL_Reg * methods)882 int luacrypto_createmeta (lua_State *L, const char *name, const luaL_Reg *methods) {
883 if (!luaL_newmetatable (L, name)) {
884 return 0;
885 }
886
887 /* define methods */
888 luaL_openlib (L, NULL, methods, 0);
889
890 /* define metamethods */
891 lua_pushliteral (L, "__index");
892 lua_pushvalue (L, -2);
893 lua_settable (L, -3);
894
895 lua_pushliteral (L, "__metatable");
896 lua_pushliteral (L, LUACRYPTO_PREFIX"you're not allowed to get this metatable");
897 lua_settable (L, -3);
898
899 return 1;
900 }
901
902 /**
903 * Create metatables for each class of object.
904 */
create_metatables(lua_State * L)905 static void create_metatables (lua_State *L) {
906 struct luaL_Reg evp_functions[] = {
907 { "digest", evp_fdigest },
908 { "new", evp_fnew },
909 {NULL, NULL},
910 };
911
912 struct luaL_Reg evp_methods[] = {
913 { "__tostring", evp_tostring },
914 { "__gc", evp_gc },
915 { "clone", evp_clone },
916 { "digest", evp_digest },
917 { "reset", evp_reset },
918 { "tostring", evp_tostring },
919 { "update", evp_update },
920 {NULL, NULL},
921 };
922
923 struct luaL_Reg hmac_functions[] = {
924 { "digest", hmac_fdigest },
925 { "new", hmac_fnew },
926 { NULL, NULL }
927 };
928
929 struct luaL_Reg hmac_methods[] = {
930 { "__tostring", hmac_tostring },
931 { "__gc", hmac_gc },
932 { "clone", hmac_clone },
933 { "digest", hmac_digest },
934 { "reset", hmac_reset },
935 { "tostring", hmac_tostring },
936 { "update", hmac_update },
937 { NULL, NULL }
938 };
939 struct luaL_Reg rand_functions[] = {
940 { "bytes", rand_bytes },
941 { "pseudo_bytes", rand_pseudo_bytes },
942 { "add", rand_add },
943 { "seed", rand_add },
944 { "status", rand_status },
945 { "load", rand_load },
946 { "write", rand_write },
947 { "cleanup", rand_cleanup },
948 { NULL, NULL }
949 };
950 struct luaL_Reg b64_functions[] = {
951 { "encode", b64_encode },
952 { "decode", b64_decode },
953 {NULL, NULL},
954 };
955
956 struct luaL_Reg x509_functions[] = {
957 { "new", x509_fnew },
958 { "load", x509_fload },
959 {NULL, NULL},
960 };
961
962 struct luaL_Reg x509_methods[] = {
963 { "__tostring", x509_tostring },
964 { "__gc", x509_gc },
965 { "clone", x509_clone },
966 { "tostring", x509_tostring },
967 { "get_subject_name", x509_get_subject_name },
968 { "get_issuer_name", x509_get_issuer_name },
969 { "get_not_before", x509_get_not_before },
970 { "get_not_after", x509_get_not_after },
971 {NULL, NULL},
972 };
973
974 struct luaL_Reg x509_name_methods[] = {
975 { "__tostring", x509_name_tostring },
976 { "__gc", x509_name_gc },
977 { "clone", x509_name_clone },
978 { "tostring", x509_name_tostring },
979 { "toasn1", x509_name_toasn1 },
980 {NULL, NULL},
981 };
982
983 struct luaL_Reg asn1_time_functions[] = {
984 { "new", asn1_time_fnew },
985 {NULL, NULL},
986 };
987
988 struct luaL_Reg asn1_time_methods[] = {
989 { "__tostring", asn1_time_tostring },
990 { "__gc", asn1_time_gc },
991 { "clone", asn1_time_clone },
992 { "tostring", asn1_time_tostring },
993 { "toasn1", asn1_time_toasn1 },
994 {NULL, NULL},
995 };
996
997 struct luaL_Reg dh_functions[] = {
998 { "new", dh_fnew },
999 {NULL, NULL},
1000 };
1001
1002 struct luaL_Reg dh_methods[] = {
1003 { "__tostring", dh_tostring },
1004 { "__gc", dh_gc },
1005 { "clone", dh_clone },
1006 { "tostring", dh_tostring },
1007 #if !defined(LIBRESSL_VERSION_NUMBER)
1008 { "get_prime", dh_get_prime },
1009 { "get_priv_key", dh_get_priv_key },
1010 { "get_pub_key", dh_get_pub_key },
1011 #endif
1012 {NULL, NULL},
1013 };
1014
1015 luaL_openlib (L, LUACRYPTO_EVP, evp_functions, 0);
1016 luacrypto_createmeta(L, LUACRYPTO_EVP, evp_methods);
1017 luaL_openlib (L, LUACRYPTO_HMAC, hmac_functions, 0);
1018 luacrypto_createmeta(L, LUACRYPTO_HMAC, hmac_methods);
1019 luaL_openlib (L, LUACRYPTO_RAND, rand_functions, 0);
1020 luaL_openlib (L, LUACRYPTO_BASE64, b64_functions, 0);
1021 luaL_openlib (L, LUACRYPTO_X509, x509_functions, 0);
1022 luacrypto_createmeta(L, LUACRYPTO_X509, x509_methods);
1023 luacrypto_createmeta(L, LUACRYPTO_X509NAME, x509_name_methods);
1024 luaL_openlib (L, LUACRYPTO_ASN1TIME, asn1_time_functions, 0);
1025 luacrypto_createmeta(L, LUACRYPTO_ASN1TIME, asn1_time_methods);
1026 luaL_openlib (L, LUACRYPTO_DH, dh_functions, 0);
1027 luacrypto_createmeta(L, LUACRYPTO_DH, dh_methods);
1028 lua_pop (L, 3);
1029 }
1030
1031 /**
1032 * Creates the metatables for the objects and registers the
1033 * driver open method.
1034 * @param L IN Lua hook
1035 * @return 1
1036 */
luaopen_crypto(lua_State * L)1037 int luaopen_crypto(lua_State *L) {
1038 struct luaL_Reg core[] = {
1039 {NULL, NULL},
1040 };
1041 OpenSSL_add_all_digests();
1042 create_metatables (L);
1043 luaL_openlib (L, LUACRYPTO_CORE, core, 0);
1044 return 1;
1045 }
1046