1 /*-
2 * Copyright 2016 Vsevolod Stakhov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 /**
17 * @file lua_rsa.c
18 * This module exports routines to load rsa keys, check inline or external
19 * rsa signatures. It assumes sha256 based signatures.
20 */
21
22 #include "lua_common.h"
23 #include "unix-std.h"
24 #include <openssl/err.h>
25 #include <openssl/pem.h>
26 #include <openssl/sha.h>
27 #include <openssl/rsa.h>
28
29 LUA_FUNCTION_DEF (rsa_pubkey, load);
30 LUA_FUNCTION_DEF (rsa_pubkey, create);
31 LUA_FUNCTION_DEF (rsa_pubkey, gc);
32 LUA_FUNCTION_DEF (rsa_privkey, load_file);
33 LUA_FUNCTION_DEF (rsa_privkey, load_pem);
34 LUA_FUNCTION_DEF (rsa_privkey, load_raw);
35 LUA_FUNCTION_DEF (rsa_privkey, load_base64);
36 LUA_FUNCTION_DEF (rsa_privkey, create);
37 LUA_FUNCTION_DEF (rsa_privkey, gc);
38 LUA_FUNCTION_DEF (rsa_signature, create);
39 LUA_FUNCTION_DEF (rsa_signature, load);
40 LUA_FUNCTION_DEF (rsa_signature, save);
41 LUA_FUNCTION_DEF (rsa_signature, base64);
42 LUA_FUNCTION_DEF (rsa_signature, gc);
43 LUA_FUNCTION_DEF (rsa, verify_memory);
44 LUA_FUNCTION_DEF (rsa, sign_memory);
45
46 static const struct luaL_reg rsalib_f[] = {
47 LUA_INTERFACE_DEF (rsa, verify_memory),
48 LUA_INTERFACE_DEF (rsa, sign_memory),
49 {NULL, NULL}
50 };
51
52 static const struct luaL_reg rsapubkeylib_f[] = {
53 LUA_INTERFACE_DEF (rsa_pubkey, load),
54 LUA_INTERFACE_DEF (rsa_pubkey, create),
55 {NULL, NULL}
56 };
57
58 static const struct luaL_reg rsapubkeylib_m[] = {
59 {"__tostring", rspamd_lua_class_tostring},
60 {"__gc", lua_rsa_pubkey_gc},
61 {NULL, NULL}
62 };
63
64 static const struct luaL_reg rsaprivkeylib_f[] = {
65 LUA_INTERFACE_DEF (rsa_privkey, load_file),
66 LUA_INTERFACE_DEF (rsa_privkey, load_pem),
67 LUA_INTERFACE_DEF (rsa_privkey, load_raw),
68 LUA_INTERFACE_DEF (rsa_privkey, load_base64),
69 LUA_INTERFACE_DEF (rsa_privkey, create),
70 {NULL, NULL}
71 };
72
73 static const struct luaL_reg rsaprivkeylib_m[] = {
74 {"__tostring", rspamd_lua_class_tostring},
75 {"__gc", lua_rsa_privkey_gc},
76 {NULL, NULL}
77 };
78
79 static const struct luaL_reg rsasignlib_f[] = {
80 LUA_INTERFACE_DEF (rsa_signature, load),
81 LUA_INTERFACE_DEF (rsa_signature, create),
82 {NULL, NULL}
83 };
84
85 static const struct luaL_reg rsasignlib_m[] = {
86 LUA_INTERFACE_DEF (rsa_signature, save),
87 LUA_INTERFACE_DEF (rsa_signature, base64),
88 {"__tostring", rspamd_lua_class_tostring},
89 {"__gc", lua_rsa_signature_gc},
90 {NULL, NULL}
91 };
92
93 static RSA *
lua_check_rsa_pubkey(lua_State * L,int pos)94 lua_check_rsa_pubkey (lua_State * L, int pos)
95 {
96 void *ud = rspamd_lua_check_udata (L, pos, "rspamd{rsa_pubkey}");
97
98 luaL_argcheck (L, ud != NULL, 1, "'rsa_pubkey' expected");
99 return ud ? *((RSA **)ud) : NULL;
100 }
101
102 static RSA *
lua_check_rsa_privkey(lua_State * L,int pos)103 lua_check_rsa_privkey (lua_State * L, int pos)
104 {
105 void *ud = rspamd_lua_check_udata (L, pos, "rspamd{rsa_privkey}");
106
107 luaL_argcheck (L, ud != NULL, 1, "'rsa_privkey' expected");
108 return ud ? *((RSA **)ud) : NULL;
109 }
110
111 static rspamd_fstring_t *
lua_check_rsa_sign(lua_State * L,int pos)112 lua_check_rsa_sign (lua_State * L, int pos)
113 {
114 void *ud = rspamd_lua_check_udata (L, pos, "rspamd{rsa_signature}");
115
116 luaL_argcheck (L, ud != NULL, 1, "'rsa_signature' expected");
117 return ud ? *((rspamd_fstring_t **)ud) : NULL;
118 }
119
120 static gint
lua_rsa_pubkey_load(lua_State * L)121 lua_rsa_pubkey_load (lua_State *L)
122 {
123 RSA *rsa = NULL, **prsa;
124 const gchar *filename;
125 FILE *f;
126
127 filename = luaL_checkstring (L, 1);
128 if (filename != NULL) {
129 f = fopen (filename, "r");
130 if (f == NULL) {
131 msg_err ("cannot open pubkey from file: %s, %s",
132 filename,
133 strerror (errno));
134 lua_pushnil (L);
135 }
136 else {
137 if (!PEM_read_RSA_PUBKEY (f, &rsa, NULL, NULL)) {
138 msg_err ("cannot open pubkey from file: %s, %s", filename,
139 ERR_error_string (ERR_get_error (), NULL));
140 lua_pushnil (L);
141 }
142 else {
143 prsa = lua_newuserdata (L, sizeof (RSA *));
144 rspamd_lua_setclass (L, "rspamd{rsa_pubkey}", -1);
145 *prsa = rsa;
146 }
147 fclose (f);
148 }
149 }
150 else {
151 lua_pushnil (L);
152 }
153 return 1;
154 }
155
156 static gint
lua_rsa_pubkey_create(lua_State * L)157 lua_rsa_pubkey_create (lua_State *L)
158 {
159 RSA *rsa = NULL, **prsa;
160 const gchar *buf;
161 BIO *bp;
162
163 buf = luaL_checkstring (L, 1);
164 if (buf != NULL) {
165 bp = BIO_new_mem_buf ((void *)buf, -1);
166
167 if (!PEM_read_bio_RSA_PUBKEY (bp, &rsa, NULL, NULL)) {
168 msg_err ("cannot parse pubkey: %s",
169 ERR_error_string (ERR_get_error (), NULL));
170 lua_pushnil (L);
171 }
172 else {
173 prsa = lua_newuserdata (L, sizeof (RSA *));
174 rspamd_lua_setclass (L, "rspamd{rsa_pubkey}", -1);
175 *prsa = rsa;
176 }
177 BIO_free (bp);
178 }
179 else {
180 lua_pushnil (L);
181 }
182 return 1;
183 }
184
185 static gint
lua_rsa_pubkey_gc(lua_State * L)186 lua_rsa_pubkey_gc (lua_State *L)
187 {
188 RSA *rsa = lua_check_rsa_pubkey (L, 1);
189
190 if (rsa != NULL) {
191 RSA_free (rsa);
192 }
193
194 return 0;
195 }
196
197 static gint
lua_rsa_privkey_load_file(lua_State * L)198 lua_rsa_privkey_load_file (lua_State *L)
199 {
200 RSA *rsa = NULL, **prsa;
201 const gchar *filename;
202 FILE *f;
203
204 filename = luaL_checkstring (L, 1);
205 if (filename != NULL) {
206 f = fopen (filename, "r");
207 if (f == NULL) {
208 msg_err ("cannot open private key from file: %s, %s",
209 filename,
210 strerror (errno));
211 lua_pushnil (L);
212 }
213 else {
214 if (!PEM_read_RSAPrivateKey (f, &rsa, NULL, NULL)) {
215 msg_err ("cannot open private key from file: %s, %s", filename,
216 ERR_error_string (ERR_get_error (), NULL));
217 lua_pushnil (L);
218 }
219 else {
220 prsa = lua_newuserdata (L, sizeof (RSA *));
221 rspamd_lua_setclass (L, "rspamd{rsa_privkey}", -1);
222 *prsa = rsa;
223 }
224 fclose (f);
225 }
226 }
227 else {
228 lua_pushnil (L);
229 }
230 return 1;
231 }
232
233 static gint
lua_rsa_privkey_load_pem(lua_State * L)234 lua_rsa_privkey_load_pem (lua_State *L)
235 {
236 RSA *rsa = NULL, **prsa;
237 BIO *b;
238 struct rspamd_lua_text *t;
239 const gchar *data;
240 gsize len;
241
242 if (lua_isuserdata (L, 1)) {
243 t = lua_check_text (L, 1);
244
245 if (!t) {
246 return luaL_error (L, "invalid arguments");
247 }
248
249 data = t->start;
250 len = t->len;
251 }
252 else {
253 data = luaL_checklstring (L, 1, &len);
254 }
255
256 if (data != NULL) {
257 b = BIO_new_mem_buf (data, len);
258
259 if (!PEM_read_bio_RSAPrivateKey (b, &rsa, NULL, NULL)) {
260 msg_err ("cannot open private key from data, %s",
261 ERR_error_string (ERR_get_error (), NULL));
262 lua_pushnil (L);
263 }
264 else {
265 prsa = lua_newuserdata (L, sizeof (RSA *));
266 rspamd_lua_setclass (L, "rspamd{rsa_privkey}", -1);
267 *prsa = rsa;
268 }
269
270 BIO_free (b);
271 }
272 else {
273 return luaL_error (L, "invalid arguments");
274 }
275
276 return 1;
277 }
278
279 static gint
lua_rsa_privkey_load_raw(lua_State * L)280 lua_rsa_privkey_load_raw (lua_State *L)
281 {
282 RSA *rsa = NULL, **prsa;
283 BIO *b;
284 struct rspamd_lua_text *t;
285 const gchar *data;
286 gsize len;
287
288 if (lua_isuserdata (L, 1)) {
289 t = lua_check_text (L, 1);
290
291 if (!t) {
292 return luaL_error (L, "invalid arguments");
293 }
294
295 data = t->start;
296 len = t->len;
297 }
298 else {
299 data = luaL_checklstring (L, 1, &len);
300 }
301
302 if (data != NULL) {
303 b = BIO_new_mem_buf (data, len);
304 rsa = d2i_RSAPrivateKey_bio (b, NULL);
305
306 if (rsa == NULL) {
307 msg_err ("cannot open private key from data, %s",
308 ERR_error_string (ERR_get_error (), NULL));
309 lua_pushnil (L);
310 }
311 else {
312 prsa = lua_newuserdata (L, sizeof (RSA *));
313 rspamd_lua_setclass (L, "rspamd{rsa_privkey}", -1);
314 *prsa = rsa;
315 }
316
317 BIO_free (b);
318 }
319 else {
320 return luaL_error (L, "invalid arguments");
321 }
322
323 return 1;
324 }
325
326 static gint
lua_rsa_privkey_load_base64(lua_State * L)327 lua_rsa_privkey_load_base64 (lua_State *L)
328 {
329 RSA *rsa = NULL, **prsa;
330 BIO *b;
331 EVP_PKEY *evp = NULL;
332 struct rspamd_lua_text *t;
333 const gchar *data;
334 guchar *decoded;
335 gsize len, dec_len;
336
337 if (lua_isuserdata (L, 1)) {
338 t = lua_check_text (L, 1);
339
340 if (!t) {
341 return luaL_error (L, "invalid arguments");
342 }
343
344 data = t->start;
345 len = t->len;
346 }
347 else {
348 data = luaL_checklstring (L, 1, &len);
349 }
350
351 if (data != NULL) {
352 decoded = g_malloc (len);
353
354 if (!rspamd_cryptobox_base64_decode (data, len, decoded, &dec_len)) {
355 g_free (decoded);
356
357 return luaL_error (L, "invalid base64 encoding");
358 }
359
360 b = BIO_new_mem_buf (decoded, dec_len);
361
362 if (d2i_PrivateKey_bio (b, &evp) != NULL) {
363 rsa = EVP_PKEY_get1_RSA (evp);
364
365 if (rsa == NULL) {
366 msg_err ("cannot open RSA private key from data, %s",
367 ERR_error_string (ERR_get_error (), NULL));
368 lua_pushnil (L);
369 }
370 else {
371 prsa = lua_newuserdata (L, sizeof (RSA *));
372 rspamd_lua_setclass (L, "rspamd{rsa_privkey}", -1);
373 *prsa = rsa;
374 }
375
376 EVP_PKEY_free (evp);
377 }
378 else {
379 msg_err ("cannot open EVP private key from data, %s",
380 ERR_error_string (ERR_get_error (), NULL));
381 lua_pushnil (L);
382 }
383
384 BIO_free (b);
385 g_free (decoded);
386 }
387 else {
388 return luaL_error (L, "invalid arguments");
389 }
390
391 return 1;
392 }
393
394 static gint
lua_rsa_privkey_create(lua_State * L)395 lua_rsa_privkey_create (lua_State *L)
396 {
397 RSA *rsa = NULL, **prsa;
398 const gchar *buf;
399 BIO *bp;
400
401 buf = luaL_checkstring (L, 1);
402 if (buf != NULL) {
403 bp = BIO_new_mem_buf ((void *)buf, -1);
404
405 if (!PEM_read_bio_RSAPrivateKey (bp, &rsa, NULL, NULL)) {
406 msg_err ("cannot parse private key: %s",
407 ERR_error_string (ERR_get_error (), NULL));
408 lua_pushnil (L);
409 }
410 else {
411 prsa = lua_newuserdata (L, sizeof (RSA *));
412 rspamd_lua_setclass (L, "rspamd{rsa_privkey}", -1);
413 *prsa = rsa;
414 }
415 BIO_free (bp);
416 }
417 else {
418 lua_pushnil (L);
419 }
420 return 1;
421 }
422
423 static gint
lua_rsa_privkey_gc(lua_State * L)424 lua_rsa_privkey_gc (lua_State *L)
425 {
426 RSA *rsa = lua_check_rsa_privkey (L, 1);
427
428 if (rsa != NULL) {
429 RSA_free (rsa);
430 }
431
432 return 0;
433 }
434
435 static gint
lua_rsa_signature_load(lua_State * L)436 lua_rsa_signature_load (lua_State *L)
437 {
438 rspamd_fstring_t *sig, **psig;
439 const gchar *filename;
440 gpointer data;
441 int fd;
442 struct stat st;
443
444 filename = luaL_checkstring (L, 1);
445 if (filename != NULL) {
446 fd = open (filename, O_RDONLY);
447 if (fd == -1) {
448 msg_err ("cannot open signature file: %s, %s", filename,
449 strerror (errno));
450 lua_pushnil (L);
451 }
452 else {
453 if (fstat (fd, &st) == -1 ||
454 (data =
455 mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
456 == MAP_FAILED) {
457 msg_err ("cannot mmap file %s: %s", filename, strerror (errno));
458 lua_pushnil (L);
459 }
460 else {
461 sig = rspamd_fstring_new_init (data, st.st_size);
462 psig = lua_newuserdata (L, sizeof (rspamd_fstring_t *));
463 rspamd_lua_setclass (L, "rspamd{rsa_signature}", -1);
464 *psig = sig;
465 munmap (data, st.st_size);
466 }
467 close (fd);
468 }
469 }
470 else {
471 lua_pushnil (L);
472 }
473 return 1;
474 }
475
476 static gint
lua_rsa_signature_save(lua_State * L)477 lua_rsa_signature_save (lua_State *L)
478 {
479 rspamd_fstring_t *sig;
480 gint fd, flags;
481 const gchar *filename;
482 gboolean forced = FALSE, res = TRUE;
483
484 sig = lua_check_rsa_sign (L, 1);
485 filename = luaL_checkstring (L, 2);
486 if (lua_gettop (L) > 2) {
487 forced = lua_toboolean (L, 3);
488 }
489
490 if (sig != NULL && filename != NULL) {
491 flags = O_WRONLY | O_CREAT;
492 if (forced) {
493 flags |= O_TRUNC;
494 }
495 else {
496 flags |= O_EXCL;
497 }
498 fd = open (filename, flags, 00644);
499 if (fd == -1) {
500 msg_err ("cannot create a signature file: %s, %s",
501 filename,
502 strerror (errno));
503 lua_pushboolean (L, FALSE);
504 }
505 else {
506 while (write (fd, sig->str, sig->len) == -1) {
507 if (errno == EINTR) {
508 continue;
509 }
510 msg_err ("cannot write to a signature file: %s, %s",
511 filename,
512 strerror (errno));
513 res = FALSE;
514 break;
515 }
516 lua_pushboolean (L, res);
517 close (fd);
518 }
519 }
520 else {
521 lua_pushboolean (L, FALSE);
522 }
523
524 return 1;
525 }
526
527 static gint
lua_rsa_signature_create(lua_State * L)528 lua_rsa_signature_create (lua_State *L)
529 {
530 rspamd_fstring_t *sig, **psig;
531 const gchar *data;
532 gsize dlen;
533
534 data = luaL_checklstring (L, 1, &dlen);
535 if (data != NULL) {
536 sig = rspamd_fstring_new_init (data, dlen);
537 psig = lua_newuserdata (L, sizeof (rspamd_fstring_t *));
538 rspamd_lua_setclass (L, "rspamd{rsa_signature}", -1);
539 *psig = sig;
540 }
541
542 return 1;
543 }
544
545 static gint
lua_rsa_signature_gc(lua_State * L)546 lua_rsa_signature_gc (lua_State *L)
547 {
548 rspamd_fstring_t *sig = lua_check_rsa_sign (L, 1);
549
550 rspamd_fstring_free (sig);
551
552 return 0;
553 }
554
555 static gint
lua_rsa_signature_base64(lua_State * L)556 lua_rsa_signature_base64 (lua_State *L)
557 {
558 rspamd_fstring_t *sig = lua_check_rsa_sign (L, 1);
559 guint boundary = 0;
560 gchar *b64;
561 gsize outlen;
562 enum rspamd_newlines_type how = RSPAMD_TASK_NEWLINES_CRLF;
563
564 if (lua_isnumber (L, 2)) {
565 boundary = lua_tonumber (L, 2);
566 }
567
568 if (lua_isstring (L, 3)) {
569 const gchar *how_str = lua_tostring (L, 3);
570
571 if (strcmp (how_str, "cr") == 0) {
572 how = RSPAMD_TASK_NEWLINES_CR;
573 }
574 else if (strcmp (how_str, "lf") == 0) {
575 how = RSPAMD_TASK_NEWLINES_LF;
576 }
577 else {
578 how = RSPAMD_TASK_NEWLINES_CRLF;
579 }
580 }
581
582 b64 = rspamd_encode_base64_fold (sig->str, sig->len, boundary, &outlen, how);
583
584 if (b64) {
585 lua_pushlstring (L, b64, outlen);
586 g_free (b64);
587 }
588 else {
589 lua_pushnil (L);
590 }
591
592 return 1;
593 }
594
595 /**
596 * Check memory using specified rsa key and signature
597 *
598 * arguments:
599 * (rsa_pubkey, rsa_signature, string)
600 *
601 * returns:
602 * true - if string match rsa signature
603 * false - otherwise
604 */
605 static gint
lua_rsa_verify_memory(lua_State * L)606 lua_rsa_verify_memory (lua_State *L)
607 {
608 RSA *rsa;
609 rspamd_fstring_t *signature;
610 const gchar *data;
611 gsize sz;
612 gint ret;
613
614 rsa = lua_check_rsa_pubkey (L, 1);
615 signature = lua_check_rsa_sign (L, 2);
616 data = luaL_checklstring (L, 3, &sz);
617
618 if (rsa != NULL && signature != NULL && data != NULL) {
619 ret = RSA_verify (NID_sha256, data, sz,
620 signature->str, signature->len, rsa);
621
622 if (ret == 0) {
623 msg_info ("cannot check rsa signature for data: %s",
624 ERR_error_string (ERR_get_error (), NULL));
625 lua_pushboolean (L, FALSE);
626 }
627 else {
628 lua_pushboolean (L, TRUE);
629 }
630 }
631 else {
632 lua_pushnil (L);
633 }
634
635 return 1;
636 }
637
638 /**
639 * Sign memory using specified rsa key and signature
640 *
641 * arguments:
642 * (rsa_privkey, string)
643 *
644 * returns:
645 * rspamd_signature object
646 * nil - otherwise
647 */
648 static gint
lua_rsa_sign_memory(lua_State * L)649 lua_rsa_sign_memory (lua_State *L)
650 {
651 RSA *rsa;
652 rspamd_fstring_t *signature, **psig;
653 const gchar *data;
654 gsize sz;
655 gint ret;
656
657 rsa = lua_check_rsa_privkey (L, 1);
658 data = luaL_checklstring (L, 2, &sz);
659
660 if (rsa != NULL && data != NULL) {
661 signature = rspamd_fstring_sized_new (RSA_size (rsa));
662
663 guint siglen = signature->len;
664 ret = RSA_sign (NID_sha256, data, sz,
665 signature->str, &siglen, rsa);
666
667 if (ret != 1) {
668 rspamd_fstring_free (signature);
669
670 return luaL_error (L, "cannot sign: %s",
671 ERR_error_string (ERR_get_error (), NULL));
672 }
673 else {
674 signature->len = siglen;
675 psig = lua_newuserdata (L, sizeof (rspamd_fstring_t *));
676 rspamd_lua_setclass (L, "rspamd{rsa_signature}", -1);
677 *psig = signature;
678 }
679 }
680 else {
681 return luaL_error (L, "invalid arguments");
682 }
683
684 return 1;
685 }
686
687 static gint
lua_load_pubkey(lua_State * L)688 lua_load_pubkey (lua_State * L)
689 {
690 lua_newtable (L);
691 luaL_register (L, NULL, rsapubkeylib_f);
692
693 return 1;
694 }
695
696 static gint
lua_load_privkey(lua_State * L)697 lua_load_privkey (lua_State * L)
698 {
699 lua_newtable (L);
700 luaL_register (L, NULL, rsaprivkeylib_f);
701
702 return 1;
703 }
704
705 static gint
lua_load_signature(lua_State * L)706 lua_load_signature (lua_State * L)
707 {
708 lua_newtable (L);
709 luaL_register (L, NULL, rsasignlib_f);
710
711 return 1;
712 }
713
714 static gint
lua_load_rsa(lua_State * L)715 lua_load_rsa (lua_State * L)
716 {
717 lua_newtable (L);
718 luaL_register (L, NULL, rsalib_f);
719
720 return 1;
721 }
722
723 void
luaopen_rsa(lua_State * L)724 luaopen_rsa (lua_State * L)
725 {
726 rspamd_lua_new_class (L, "rspamd{rsa_pubkey}", rsapubkeylib_m);
727 lua_pop (L, 1);
728 rspamd_lua_add_preload (L, "rspamd_rsa_pubkey", lua_load_pubkey);
729
730 rspamd_lua_new_class (L, "rspamd{rsa_privkey}", rsaprivkeylib_m);
731 lua_pop (L, 1);
732 rspamd_lua_add_preload (L, "rspamd_rsa_privkey", lua_load_privkey);
733
734 rspamd_lua_new_class (L, "rspamd{rsa_signature}", rsasignlib_m);
735 lua_pop (L, 1);
736 rspamd_lua_add_preload (L, "rspamd_rsa_signature", lua_load_signature);
737
738 rspamd_lua_add_preload (L, "rspamd_rsa", lua_load_rsa);
739
740 lua_settop (L, 0);
741 }
742