1
4
5# include "luametatex.h"
6# include "lmtoptional.h"
7
8
19
20typedef void * BIO;
21typedef void * EVP_PKEY;
22typedef void * X509;
23typedef void * X509_STORE;
24typedef void * pem_password_cb;
25typedef void * PKCS7;
26typedef void * OPENSSL_STACK;
27
28typedef struct openssllib_state_info {
29
30 int initialized;
31 int padding;
32
33 void (*OPENSSL_init_ssl) (
34 int,
35 void *
36 );
37
38 PKCS7 * (*PKCS7_sign) (
39 X509 *signcert,
40 EVP_PKEY *pkey,
41 X509 **certs,
42 BIO *data,
43 unsigned int flags
44 );
45
46 int (*PKCS7_final) (
47 PKCS7 *p7,
48 BIO *data,
49 int flags
50 );
51
52 int (*i2d_PKCS7) (
53 BIO *bp,
54 unsigned char **ppout
55 );
56
57 int (*i2d_PKCS7_DIGEST) (
58 BIO *bp,
59 unsigned char **ppout
60 );
61
62 int (*i2d_PKCS7_bio) (
63 BIO *bp,
64 PKCS7 *a
65 );
66
67 int (*SMIME_write_PKCS7) (
68 BIO *out,
69 PKCS7 *p7,
70 BIO *data,
71 int flags
72 );
73
74 void (*PKCS7_free) (
75 void *
76 );
77
78 void (*X509_free) (
79 void *
80 );
81
82 void (*EVP_PKEY_free) (
83 void *
84 );
85
86 void * (*BIO_new_file) (
87 const char *filename,
88 const char *mode
89 );
90
91 void * (*BIO_new_mem_buf) (
92 const char *data,
93 int size
94 );
95
96
97
98
99
100 long (*BIO_ctrl) (
101 BIO *bp,
102 int cmd,
103 long larg,
104 void *parg
105 );
106
107 void (*BIO_free) (
108 void *
109 );
110
111 X509 * (*PEM_read_bio_X509) (
112 BIO *bp,
113 X509 **x,
114 pem_password_cb *cb,
115 const char *u
116 );
117
118 EVP_PKEY * (*PEM_read_bio_PrivateKey) (
119 BIO *bp,
120 EVP_PKEY **x,
121 pem_password_cb *cb,
122 const char *u
123 );
124
125 int (*PKCS7_verify) (
126 PKCS7 *p7,
127 X509 *certs,
128 X509_STORE *store,
129 BIO *indata,
130 BIO *out,
131 int flags
132 );
133
134 int (*d2i_PKCS7) (
135 PKCS7 **a,
136 const char **ppin,
137 long length
138 );
139
140 int (*d2i_PKCS7_DIGEST) (
141 PKCS7 **a,
142 const char **ppin,
143 long length
144 );
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159} openssllib_state_info;
160
161# define BIO_CTRL_RESET 1
162# define BIO_CTRL_INFO 3
163
164# define PKCS7_DETACHED 0x0040
165# define PKCS7_BINARY 0x0080
166# define PKCS7_STREAM 0x1000
167
168# define PKCS7_NOINTERN 0x0010
169# define PKCS7_NOVERIFY 0x0020
170
171# define SSL_library_init() openssllib_state.OPENSSL_init_ssl(0, NULL)
172# define BIO_reset(b) openssllib_state.BIO_ctrl(b,BIO_CTRL_RESET,0,NULL)
173# define BIO_get_mem_data(b,pp) openssllib_state.BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)(pp))
174
175static openssllib_state_info openssllib_state = {
176
177 .initialized = 0,
178 .padding = 0,
179
180 .OPENSSL_init_ssl = NULL,
181 .PKCS7_sign = NULL,
182 .PKCS7_final = NULL,
183 .i2d_PKCS7 = NULL,
184 .i2d_PKCS7_bio = NULL,
185
186 .PKCS7_free = NULL,
187 .X509_free = NULL,
188 .EVP_PKEY_free = NULL,
189 .BIO_new_file = NULL,
190 .BIO_new_mem_buf = NULL,
191 .BIO_ctrl = NULL,
192 .BIO_free = NULL,
193 .PEM_read_bio_X509 = NULL,
194 .PEM_read_bio_PrivateKey = NULL,
195 .PKCS7_verify = NULL,
196 .d2i_PKCS7 = NULL,
197 .d2i_PKCS7_DIGEST = NULL,
198
199
200
201
202};
203
204static int openssllib_initialize(lua_State * L)
205{
206 if (! openssllib_state.initialized) {
207 const char *filename_c = lua_tostring(L, 1);
208 const char *filename_s = lua_tostring(L, 2);
209 if (filename_c && filename_s) {
210
211 lmt_library lib_c = lmt_library_load(filename_c);
212 lmt_library lib_s = lmt_library_load(filename_s);
213
214 openssllib_state.OPENSSL_init_ssl = lmt_library_find(lib_s, "OPENSSL_init_ssl");
215
216 openssllib_state.PKCS7_sign = lmt_library_find(lib_c, "PKCS7_sign");
217 openssllib_state.PKCS7_final = lmt_library_find(lib_c, "PKCS7_final");
218 openssllib_state.i2d_PKCS7 = lmt_library_find(lib_c, "i2d_PKCS7");
219 openssllib_state.i2d_PKCS7_bio = lmt_library_find(lib_c, "i2d_PKCS7_bio");
220
221 openssllib_state.PKCS7_free = lmt_library_find(lib_c, "PKCS7_free");
222
223 openssllib_state.X509_free = lmt_library_find(lib_c, "X509_free");
224 openssllib_state.EVP_PKEY_free = lmt_library_find(lib_c, "EVP_PKEY_free");
225 openssllib_state.BIO_new_file = lmt_library_find(lib_c, "BIO_new_file");
226 openssllib_state.BIO_new_mem_buf = lmt_library_find(lib_c, "BIO_new_mem_buf");
227 openssllib_state.BIO_ctrl = lmt_library_find(lib_c, "BIO_ctrl");
228 openssllib_state.BIO_free = lmt_library_find(lib_c, "BIO_free");
229 openssllib_state.PEM_read_bio_X509 = lmt_library_find(lib_c, "PEM_read_bio_X509");
230 openssllib_state.PEM_read_bio_PrivateKey = lmt_library_find(lib_c, "PEM_read_bio_PrivateKey");
231
232 openssllib_state.PKCS7_verify = lmt_library_find(lib_c, "PKCS7_verify");
233 openssllib_state.d2i_PKCS7 = lmt_library_find(lib_c, "d2i_PKCS7");
234 openssllib_state.d2i_PKCS7_DIGEST = lmt_library_find(lib_c, "d2i_PKCS7_DIGEST");
235
236
237
238
239
240 openssllib_state.initialized = lmt_library_okay(lib_s) && lmt_library_okay(lib_c);
241
242 openssllib_state.OPENSSL_init_ssl(0, NULL);
243 }
244 }
245 lua_pushboolean(L, openssllib_state.initialized);
246 return 1;
247}
248
249
252
253typedef enum messages {
254 m_all_is_okay,
255 m_invalid_certificate_file,
256 m_invalid_certificate,
257 m_invalid_private_key,
258 m_invalid_data_file,
259 m_invalid_signature,
260 m_unable_to_open_output_file,
261 m_unable_to_reset_file,
262 m_unable_to_save_signature,
263 m_incomplete_specification,
264 m_library_is_unitialized,
265} messages;
266
267
271
272static int openssllib_sign(lua_State * L)
273{
274 int message = m_all_is_okay;
275 if (openssllib_state.initialized) {
276 if (lua_type(L, 1) == LUA_TTABLE) {
277 const char *certfile = NULL;
278 const char *datafile = NULL;
279 const char *password = NULL;
280 const char *resultfile = NULL;
281 const char *data = NULL;
282 unsigned char *resultdata = NULL;
283 size_t datasize = 0;
284 size_t resultsize = 0;
285 if (lua_getfield(L, 1, "certfile") == LUA_TSTRING) { certfile = lua_tostring (L, -1); } lua_pop(L, 1);
286 if (lua_getfield(L, 1, "datafile") == LUA_TSTRING) { datafile = lua_tostring (L, -1); } lua_pop(L, 1);
287 if (lua_getfield(L, 1, "data") == LUA_TSTRING) { data = lua_tolstring(L, -1, &datasize); } lua_pop(L, 1);
288 if (lua_getfield(L, 1, "password") == LUA_TSTRING) { password = lua_tostring (L, -1); } lua_pop(L, 1);
289 if (lua_getfield(L, 1, "resultfile") == LUA_TSTRING) { resultfile = lua_tostring (L, -1); } lua_pop(L, 1);
290 if (certfile && password && (data || datafile)) {
291 int okay = 0;
292 BIO *input = NULL;
293 BIO *output = NULL;
294 BIO *certificate = NULL;
295 X509 *x509 = NULL;
296 EVP_PKEY *key = NULL;
297 PKCS7 *p7 = NULL;
298 int flags = PKCS7_DETACHED | PKCS7_STREAM | PKCS7_BINARY;
299 certificate = openssllib_state.BIO_new_file(certfile, "rb");
300 if (! certificate) {
301 message = m_invalid_certificate_file;
302 goto DONE;
303 }
304 x509 = openssllib_state.PEM_read_bio_X509(certificate, NULL, NULL, password);
305 if (! x509) {
306 message = m_invalid_certificate;
307 goto DONE;
308 }
309 if (BIO_reset(certificate) < 0) {
310 message = m_unable_to_reset_file;
311 goto DONE;
312 }
313 key = openssllib_state.PEM_read_bio_PrivateKey(certificate, NULL, NULL, password);
314 if (! key) {
315 message = m_invalid_private_key;
316 goto DONE;
317 }
318 if (datafile) {
319 input = openssllib_state.BIO_new_file(datafile, "rb");
320 } else {
321 input = openssllib_state.BIO_new_mem_buf(data, (int) datasize);
322 }
323 if (! input) {
324 message = m_invalid_data_file;
325 goto DONE;
326 }
327 p7 = openssllib_state.PKCS7_sign(x509, key, NULL, input, flags);
328 if (! p7) {
329 message = m_invalid_signature;
330 goto DONE;
331 }
332 openssllib_state.PKCS7_final(p7, input, flags);
333 if (resultfile) {
334 output = openssllib_state.BIO_new_file(resultfile, "wb");
335 if (! output) {
336 message = m_unable_to_open_output_file;
337 goto DONE;
338 }
339
340
341
342
343
344 if (! openssllib_state.i2d_PKCS7_bio(output, p7)) {
345 message = m_unable_to_save_signature;
346 goto DONE;
347 }
348 } else {
349 resultsize = openssllib_state.i2d_PKCS7(p7, &resultdata);
350 }
351 okay = 1;
352 DONE:
353 if (certificate) { openssllib_state.BIO_free(certificate); }
354 if (x509) { openssllib_state.X509_free(x509); }
355 if (p7) { openssllib_state.PKCS7_free(p7); }
356 if (key) { openssllib_state.EVP_PKEY_free(key); }
357 if (input) { openssllib_state.BIO_free(input); }
358 if (output) { openssllib_state.BIO_free(output); }
359 if (okay) {
360 if (resultdata && resultsize > 0) {
361 lua_pushboolean(L, 1);
362 lua_pushlstring(L, (const char *) resultdata, resultsize);
363 return 2;
364 } else {
365 return 1;
366 }
367 }
368 }
369 } else {
370 message = m_incomplete_specification;
371 }
372 } else {
373 message = m_library_is_unitialized;
374 }
375 lua_pushboolean(L, 0);
376 if (message) {
377 lua_pushinteger(L, message);
378 return 2;
379 } else {
380 return 1;
381 }
382}
383
384static int openssllib_verify(lua_State * L)
385{
386 int message = m_all_is_okay;
387 if (openssllib_state.initialized) {
388 const char *certfile = NULL;
389 const char *datafile = NULL;
390 const char *password = NULL;
391 const char *signature = NULL;
392 const char *data = NULL;
393 size_t signaturesize = 0;
394 size_t datasize = 0;
395 if (lua_getfield(L, 1, "certfile") == LUA_TSTRING) { certfile = lua_tostring (L, -1); } lua_pop(L, 1);
396 if (lua_getfield(L, 1, "datafile") == LUA_TSTRING) { datafile = lua_tostring (L, -1); } lua_pop(L, 1);
397 if (lua_getfield(L, 1, "data") == LUA_TSTRING) { data = lua_tolstring(L, -1, &datasize); } lua_pop(L, 1);
398 if (lua_getfield(L, 1, "signature") == LUA_TSTRING) { signature = lua_tolstring(L, -1, &signaturesize); } lua_pop(L, 1);
399 if (lua_getfield(L, 1, "password") == LUA_TSTRING) { password = lua_tostring (L, -1); } lua_pop(L, 1);
400 if (certfile && password && (data || datafile)) {
401 int okay = -1;
402 PKCS7 *p7 = NULL;
403 BIO *input = NULL;
404 BIO *certificate = NULL;
405 X509 *x509 = NULL;
406
407 int flags = PKCS7_NOVERIFY | PKCS7_BINARY;
408 certificate = openssllib_state.BIO_new_file(certfile, "rb");
409 if (! certificate) {
410 message = m_invalid_certificate_file;
411 goto DONE;
412 }
413 x509 = openssllib_state.PEM_read_bio_X509(certificate, NULL, NULL, password);
414 if (! x509) {
415 message = m_invalid_certificate;
416 goto DONE;
417 }
418
419
420
421
422
423
424 if (! openssllib_state.d2i_PKCS7(&p7, &signature, signaturesize)) {
425 message = m_invalid_signature;
426 goto DONE;
427 }
428 if (datafile) {
429 input = openssllib_state.BIO_new_file(datafile, "rb");
430 } else {
431 input = openssllib_state.BIO_new_mem_buf(data, datasize);
432 }
433 if (! input) {
434 message = m_invalid_data_file;
435 goto DONE;
436 }
437
438 okay = openssllib_state.PKCS7_verify(p7, NULL, NULL, input, NULL, flags);
439 DONE:
440 if (certificate) { openssllib_state.BIO_free(certificate); }
441 if (x509) { openssllib_state.X509_free(x509); }
442 if (p7) { openssllib_state.PKCS7_free(p7); }
443 if (input) { openssllib_state.BIO_free(input); }
444
445 if (okay > 0) {
446 lua_pushboolean(L, okay);
447 return 1;
448 } else {
449 message = m_invalid_signature;
450 }
451 }
452 }
453 lua_pushboolean(L, 0);
454 if (message) {
455 lua_pushinteger(L, message);
456 return 2;
457 } else {
458 return 1;
459 }
460 return 1;
461}
462
463static int openssllib_getversion(lua_State * L)
464{
465 if (openssllib_state.initialized) {
466
467 lua_pushinteger(L, 1);
468 } else {
469 lua_pushinteger(L, 0);
470 }
471 return 1;
472}
473
474static struct luaL_Reg openssllib_function_list[] = {
475 { "initialize", openssllib_initialize },
476 { "sign", openssllib_sign },
477 { "verify", openssllib_verify },
478 { "getversion", openssllib_getversion },
479 { NULL, NULL },
480};
481
482int luaopen_openssl(lua_State * L)
483{
484 lmt_library_register(L, "openssl", openssllib_function_list);
485 return 0;
486}
487 |