Software /
code /
prosody
Comparison
util-src/crypto.c @ 12693:7c5afbdcbc77
util.crypto: New wrapper for some operations in OpenSSL's libcrypto
Specifically, ED25519 key generation/import/export, sign/verify operations,
and AES encrypt/decrypt.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 24 Jun 2022 16:56:16 +0100 |
child | 12697:916871447b2f |
comparison
equal
deleted
inserted
replaced
12692:b001b0f42512 | 12693:7c5afbdcbc77 |
---|---|
1 /* Prosody IM | |
2 -- Copyright (C) 2022 Matthew Wild | |
3 -- | |
4 -- This project is MIT/X11 licensed. Please see the | |
5 -- COPYING file in the source package for more information. | |
6 -- | |
7 */ | |
8 | |
9 /* | |
10 * crypto.c | |
11 * Lua library for cryptographic operations using OpenSSL | |
12 */ | |
13 | |
14 #include <string.h> | |
15 #include <stdlib.h> | |
16 | |
17 #ifdef _MSC_VER | |
18 typedef unsigned __int32 uint32_t; | |
19 #else | |
20 #include <inttypes.h> | |
21 #endif | |
22 | |
23 #include "lua.h" | |
24 #include "lauxlib.h" | |
25 #include <openssl/crypto.h> | |
26 #include <openssl/ecdsa.h> | |
27 #include <openssl/err.h> | |
28 #include <openssl/evp.h> | |
29 #include <openssl/obj_mac.h> | |
30 #include <openssl/pem.h> | |
31 | |
32 #if (LUA_VERSION_NUM == 501) | |
33 #define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) | |
34 #endif | |
35 | |
36 #include "managed_pointer.h" | |
37 | |
38 #define PKEY_MT_TAG "util.crypto key" | |
39 | |
40 static BIO* new_memory_BIO() { | |
41 return BIO_new(BIO_s_mem()); | |
42 } | |
43 | |
44 MANAGED_POINTER_ALLOCATOR(new_managed_EVP_MD_CTX, EVP_MD_CTX*, EVP_MD_CTX_new, EVP_MD_CTX_free) | |
45 MANAGED_POINTER_ALLOCATOR(new_managed_BIO_s_mem, BIO*, new_memory_BIO, BIO_free) | |
46 MANAGED_POINTER_ALLOCATOR(new_managed_EVP_CIPHER_CTX, EVP_CIPHER_CTX*, EVP_CIPHER_CTX_new, EVP_CIPHER_CTX_free) | |
47 | |
48 static EVP_PKEY* pkey_from_arg(lua_State *L, int idx, const int type, const int require_private) { | |
49 EVP_PKEY *pkey = *(EVP_PKEY**)luaL_checkudata(L, idx, PKEY_MT_TAG); | |
50 if(type || require_private) { | |
51 lua_getuservalue(L, idx); | |
52 if(type != 0) { | |
53 lua_getfield(L, -1, "type"); | |
54 if(lua_tointeger(L, -1) != type) { | |
55 luaL_argerror(L, idx, "unexpected key type"); | |
56 } | |
57 lua_pop(L, 1); | |
58 } | |
59 if(require_private != 0) { | |
60 lua_getfield(L, -1, "private"); | |
61 if(lua_toboolean(L, -1) != 1) { | |
62 luaL_argerror(L, idx, "private key expected, got public key only"); | |
63 } | |
64 lua_pop(L, 1); | |
65 } | |
66 lua_pop(L, 1); | |
67 } | |
68 return pkey; | |
69 } | |
70 | |
71 static int Lpkey_finalizer(lua_State *L) { | |
72 EVP_PKEY *pkey = pkey_from_arg(L, 1, 0, 0); | |
73 EVP_PKEY_free(pkey); | |
74 return 0; | |
75 } | |
76 | |
77 static int Lpkey_meth_get_type(lua_State *L) { | |
78 EVP_PKEY *pkey = pkey_from_arg(L, 1, 0, 0); | |
79 | |
80 int key_type = EVP_PKEY_id(pkey); | |
81 lua_pushstring(L, OBJ_nid2sn(key_type)); | |
82 return 1; | |
83 } | |
84 | |
85 static int base_evp_sign(lua_State *L, const int key_type, const EVP_MD *digest_type) { | |
86 EVP_PKEY *pkey = pkey_from_arg(L, 1, key_type, 1); | |
87 luaL_Buffer sigbuf; | |
88 | |
89 size_t msg_len; | |
90 const unsigned char* msg = (unsigned char*)lua_tolstring(L, 2, &msg_len); | |
91 | |
92 size_t sig_len; | |
93 unsigned char *sig = NULL; | |
94 EVP_MD_CTX *md_ctx = new_managed_EVP_MD_CTX(L); | |
95 | |
96 if(EVP_DigestSignInit(md_ctx, NULL, digest_type, NULL, pkey) != 1) { | |
97 lua_pushnil(L); | |
98 return 1; | |
99 } | |
100 if(EVP_DigestSign(md_ctx, NULL, &sig_len, msg, msg_len) != 1) { | |
101 lua_pushnil(L); | |
102 return 1; | |
103 } | |
104 | |
105 // COMPAT w/ Lua 5.1 | |
106 luaL_buffinit(L, &sigbuf); | |
107 sig = memset(luaL_prepbuffer(&sigbuf), 0, sig_len); | |
108 | |
109 if(EVP_DigestSign(md_ctx, sig, &sig_len, msg, msg_len) != 1) { | |
110 lua_pushnil(L); | |
111 } | |
112 else { | |
113 luaL_addsize(&sigbuf, sig_len); | |
114 luaL_pushresult(&sigbuf); | |
115 return 1; | |
116 } | |
117 | |
118 return 1; | |
119 } | |
120 | |
121 static int base_evp_verify(lua_State *L, const int key_type, const EVP_MD *digest_type) { | |
122 EVP_PKEY *pkey = pkey_from_arg(L, 1, key_type, 0); | |
123 | |
124 size_t msg_len; | |
125 const unsigned char *msg = (unsigned char*)luaL_checklstring(L, 2, &msg_len); | |
126 | |
127 size_t sig_len; | |
128 const unsigned char *sig = (unsigned char*)luaL_checklstring(L, 3, &sig_len); | |
129 | |
130 EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); | |
131 | |
132 if(EVP_DigestVerifyInit(md_ctx, NULL, digest_type, NULL, pkey) != 1) { | |
133 lua_pushnil(L); | |
134 goto cleanup; | |
135 } | |
136 int result = EVP_DigestVerify(md_ctx, sig, sig_len, msg, msg_len); | |
137 if(result == 0) { | |
138 lua_pushboolean(L, 0); | |
139 } else if(result != 1) { | |
140 lua_pushnil(L); | |
141 } | |
142 else { | |
143 lua_pushboolean(L, 1); | |
144 } | |
145 cleanup: | |
146 EVP_MD_CTX_free(md_ctx); | |
147 return 1; | |
148 } | |
149 | |
150 static int Lpkey_meth_public_pem(lua_State *L) { | |
151 char *data; | |
152 size_t bytes; | |
153 EVP_PKEY *pkey = pkey_from_arg(L, 1, 0, 0); | |
154 BIO *bio = new_managed_BIO_s_mem(L); | |
155 if(PEM_write_bio_PUBKEY(bio, pkey)) { | |
156 bytes = BIO_get_mem_data(bio, &data); | |
157 if (bytes > 0) { | |
158 lua_pushlstring(L, data, bytes); | |
159 } | |
160 else { | |
161 lua_pushnil(L); | |
162 } | |
163 } | |
164 else { | |
165 lua_pushnil(L); | |
166 } | |
167 return 1; | |
168 } | |
169 | |
170 static int Lpkey_meth_private_pem(lua_State *L) { | |
171 char *data; | |
172 size_t bytes; | |
173 EVP_PKEY *pkey = pkey_from_arg(L, 1, 0, 1); | |
174 BIO *bio = new_managed_BIO_s_mem(L); | |
175 | |
176 if(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) { | |
177 bytes = BIO_get_mem_data(bio, &data); | |
178 if (bytes > 0) { | |
179 lua_pushlstring(L, data, bytes); | |
180 } | |
181 else { | |
182 lua_pushnil(L); | |
183 } | |
184 } | |
185 else { | |
186 lua_pushnil(L); | |
187 } | |
188 return 1; | |
189 } | |
190 | |
191 /* ecdsa_sha256_sign(key, data) */ | |
192 static int Lecdsa_sha256_sign(lua_State *L) { | |
193 return base_evp_sign(L, NID_X9_62_id_ecPublicKey, EVP_sha256()); | |
194 } | |
195 | |
196 /* ecdsa_sha256_verify(key, data, sig) */ | |
197 static int Lecdsa_sha256_verify(lua_State *L) { | |
198 return base_evp_verify(L, NID_X9_62_id_ecPublicKey, EVP_sha256()); | |
199 } | |
200 | |
201 static int push_pkey(lua_State *L, EVP_PKEY *pkey, const int type, const int privkey) { | |
202 EVP_PKEY **ud = lua_newuserdata(L, sizeof(EVP_PKEY*)); | |
203 *ud = pkey; | |
204 luaL_newmetatable(L, PKEY_MT_TAG); | |
205 lua_setmetatable(L, -2); | |
206 | |
207 /* Set some info about the key and attach it as a user value */ | |
208 lua_newtable(L); | |
209 if(type != 0) { | |
210 lua_pushinteger(L, type); | |
211 lua_setfield(L, -2, "type"); | |
212 } | |
213 if(privkey != 0) { | |
214 lua_pushboolean(L, 1); | |
215 lua_setfield(L, -2, "private"); | |
216 } | |
217 lua_setuservalue(L, -2); | |
218 return 1; | |
219 } | |
220 | |
221 static int Lgenerate_ed25519_keypair(lua_State *L) { | |
222 EVP_PKEY *pkey = NULL; | |
223 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL); | |
224 | |
225 /* Generate key */ | |
226 EVP_PKEY_keygen_init(pctx); | |
227 EVP_PKEY_keygen(pctx, &pkey); | |
228 EVP_PKEY_CTX_free(pctx); | |
229 | |
230 push_pkey(L, pkey, NID_ED25519, 1); | |
231 return 1; | |
232 } | |
233 | |
234 static int Limport_private_pem(lua_State *L) { | |
235 EVP_PKEY *pkey = NULL; | |
236 | |
237 size_t privkey_bytes; | |
238 const char* privkey_data; | |
239 BIO *bio = new_managed_BIO_s_mem(L); | |
240 | |
241 privkey_data = luaL_checklstring(L, 1, &privkey_bytes); | |
242 BIO_write(bio, privkey_data, privkey_bytes); | |
243 pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); | |
244 if (pkey) { | |
245 push_pkey(L, pkey, EVP_PKEY_id(pkey), 1); | |
246 } | |
247 else { | |
248 lua_pushnil(L); | |
249 } | |
250 | |
251 return 1; | |
252 } | |
253 | |
254 static int Limport_public_pem(lua_State *L) { | |
255 EVP_PKEY *pkey = NULL; | |
256 | |
257 size_t pubkey_bytes; | |
258 const char* pubkey_data; | |
259 BIO *bio = new_managed_BIO_s_mem(L); | |
260 | |
261 pubkey_data = luaL_checklstring(L, 1, &pubkey_bytes); | |
262 BIO_write(bio, pubkey_data, pubkey_bytes); | |
263 pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); | |
264 if (pkey) { | |
265 push_pkey(L, pkey, EVP_PKEY_id(pkey), 0); | |
266 } | |
267 else { | |
268 lua_pushnil(L); | |
269 } | |
270 | |
271 return 1; | |
272 } | |
273 | |
274 static int Led25519_sign(lua_State *L) { | |
275 return base_evp_sign(L, NID_ED25519, NULL); | |
276 } | |
277 | |
278 static int Led25519_verify(lua_State *L) { | |
279 return base_evp_verify(L, NID_ED25519, NULL); | |
280 } | |
281 | |
282 /* gcm_encrypt(key, iv, plaintext) */ | |
283 static int Laes_gcm_encrypt(lua_State *L, const EVP_CIPHER *cipher, const unsigned char expected_key_len) { | |
284 EVP_CIPHER_CTX *ctx; | |
285 luaL_Buffer ciphertext_buffer; | |
286 | |
287 size_t key_len, iv_len, plaintext_len; | |
288 int ciphertext_len, final_len; | |
289 | |
290 const unsigned char *key = (unsigned char*)luaL_checklstring(L, 1, &key_len); | |
291 const unsigned char *iv = (unsigned char*)luaL_checklstring(L, 2, &iv_len); | |
292 const unsigned char *plaintext = (unsigned char*)luaL_checklstring(L, 3, &plaintext_len); | |
293 | |
294 if(key_len != expected_key_len) { | |
295 return luaL_error(L, "key must be %d bytes", expected_key_len); | |
296 } | |
297 luaL_argcheck(L, iv_len == 12, 2, "iv must be 12 bytes"); | |
298 if(lua_gettop(L) > 3) { | |
299 return luaL_error(L, "Expected 3 arguments, got %d", lua_gettop(L)); | |
300 } | |
301 | |
302 // Create and initialise the context | |
303 ctx = new_managed_EVP_CIPHER_CTX(L); | |
304 | |
305 // Initialise the encryption operation | |
306 if(1 != EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL)) { | |
307 return luaL_error(L, "Error while initializing encryption engine"); | |
308 } | |
309 | |
310 // Initialise key and IV | |
311 if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) { | |
312 return luaL_error(L, "Error while initializing key/iv"); | |
313 } | |
314 | |
315 luaL_buffinit(L, &ciphertext_buffer); | |
316 unsigned char *ciphertext = (unsigned char*)luaL_prepbuffsize(&ciphertext_buffer, plaintext_len+16); | |
317 | |
318 if(1 != EVP_EncryptUpdate(ctx, ciphertext, &ciphertext_len, plaintext, plaintext_len)) { | |
319 return luaL_error(L, "Error while encrypting data"); | |
320 } | |
321 | |
322 /* | |
323 * Finalise the encryption. Normally ciphertext bytes may be written at | |
324 * this stage, but this does not occur in GCM mode | |
325 */ | |
326 if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + ciphertext_len, &final_len)) { | |
327 return luaL_error(L, "Error while encrypting final data"); | |
328 } | |
329 if(final_len != 0) { | |
330 return luaL_error(L, "Non-zero final data"); | |
331 } | |
332 | |
333 /* Get the tag */ | |
334 if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, ciphertext + ciphertext_len)) { | |
335 return luaL_error(L, "Unable to read AEAD tag of encrypted data"); | |
336 } | |
337 | |
338 luaL_addsize(&ciphertext_buffer, ciphertext_len + 16); | |
339 luaL_pushresult(&ciphertext_buffer); | |
340 | |
341 return 1; | |
342 } | |
343 | |
344 static int Laes_128_gcm_encrypt(lua_State *L) { | |
345 return Laes_gcm_encrypt(L, EVP_aes_128_gcm(), 16); | |
346 } | |
347 | |
348 static int Laes_256_gcm_encrypt(lua_State *L) { | |
349 return Laes_gcm_encrypt(L, EVP_aes_256_gcm(), 32); | |
350 } | |
351 | |
352 /* gcm_decrypt(key, iv, ciphertext) */ | |
353 static int Laes_gcm_decrypt(lua_State *L, const EVP_CIPHER *cipher, const unsigned char expected_key_len) { | |
354 EVP_CIPHER_CTX *ctx; | |
355 luaL_Buffer plaintext_buffer; | |
356 | |
357 size_t key_len, iv_len, ciphertext_len; | |
358 int plaintext_len, final_len; | |
359 | |
360 const unsigned char *key = (unsigned char*)luaL_checklstring(L, 1, &key_len); | |
361 const unsigned char *iv = (unsigned char*)luaL_checklstring(L, 2, &iv_len); | |
362 const unsigned char *ciphertext = (unsigned char*)luaL_checklstring(L, 3, &ciphertext_len); | |
363 | |
364 if(key_len != expected_key_len) { | |
365 return luaL_error(L, "key must be %d bytes", expected_key_len); | |
366 } | |
367 luaL_argcheck(L, iv_len == 12, 2, "iv must be 12 bytes"); | |
368 luaL_argcheck(L, ciphertext_len > 16, 3, "ciphertext must be at least 16 bytes (including tag)"); | |
369 if(lua_gettop(L) > 3) { | |
370 return luaL_error(L, "Expected 3 arguments, got %d", lua_gettop(L)); | |
371 } | |
372 | |
373 /* Create and initialise the context */ | |
374 ctx = new_managed_EVP_CIPHER_CTX(L); | |
375 | |
376 /* Initialise the decryption operation. */ | |
377 if(!EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL)) { | |
378 return luaL_error(L, "Error while initializing decryption engine"); | |
379 } | |
380 | |
381 /* Initialise key and IV */ | |
382 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) { | |
383 return luaL_error(L, "Error while initializing key/iv"); | |
384 } | |
385 | |
386 luaL_buffinit(L, &plaintext_buffer); | |
387 unsigned char *plaintext = (unsigned char*)luaL_prepbuffsize(&plaintext_buffer, ciphertext_len); | |
388 | |
389 /* | |
390 * Provide the message to be decrypted, and obtain the plaintext output. | |
391 * EVP_DecryptUpdate can be called multiple times if necessary | |
392 */ | |
393 if(!EVP_DecryptUpdate(ctx, plaintext, &plaintext_len, ciphertext, ciphertext_len-16)) { | |
394 return luaL_error(L, "Error while decrypting data"); | |
395 } | |
396 | |
397 /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ | |
398 if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (unsigned char*)ciphertext + (ciphertext_len-16))) { | |
399 return luaL_error(L, "Error while processing authentication tag"); | |
400 } | |
401 | |
402 /* | |
403 * Finalise the decryption. A positive return value indicates success, | |
404 * anything else is a failure - the plaintext is not trustworthy. | |
405 */ | |
406 int ret = EVP_DecryptFinal_ex(ctx, plaintext + plaintext_len, &final_len); | |
407 | |
408 if(ret <= 0) { | |
409 /* Verify failed */ | |
410 lua_pushnil(L); | |
411 lua_pushliteral(L, "verify-failed"); | |
412 return 2; | |
413 } | |
414 | |
415 luaL_addsize(&plaintext_buffer, plaintext_len + final_len); | |
416 luaL_pushresult(&plaintext_buffer); | |
417 return 1; | |
418 } | |
419 | |
420 static int Laes_128_gcm_decrypt(lua_State *L) { | |
421 return Laes_gcm_decrypt(L, EVP_aes_128_gcm(), 16); | |
422 } | |
423 | |
424 static int Laes_256_gcm_decrypt(lua_State *L) { | |
425 return Laes_gcm_decrypt(L, EVP_aes_256_gcm(), 32); | |
426 } | |
427 | |
428 /* r, s = parse_ecdsa_sig(sig_der) */ | |
429 static int Lparse_ecdsa_signature(lua_State *L) { | |
430 ECDSA_SIG *sig; | |
431 size_t sig_der_len; | |
432 const unsigned char *sig_der = (unsigned char*)luaL_checklstring(L, 1, &sig_der_len); | |
433 const BIGNUM *r, *s; | |
434 luaL_Buffer rb, sb; | |
435 int rlen, slen; | |
436 | |
437 sig = d2i_ECDSA_SIG(NULL, &sig_der, sig_der_len); | |
438 | |
439 if(sig == NULL) { | |
440 lua_pushnil(L); | |
441 return 1; | |
442 } | |
443 | |
444 ECDSA_SIG_get0(sig, &r, &s); | |
445 | |
446 rlen = BN_num_bytes(r); | |
447 slen = BN_num_bytes(s); | |
448 | |
449 // COMPAT w/ Lua 5.1 | |
450 #if LUAL_BUFFERSIZE < 32 | |
451 #error Configured LUAL_BUFFERSIZE is too small for this operation | |
452 #endif | |
453 | |
454 luaL_buffinit(L, &rb); | |
455 BN_bn2bin(r, (unsigned char*)luaL_prepbuffer(&rb)); | |
456 luaL_addsize(&rb, rlen); | |
457 luaL_pushresult(&rb); | |
458 | |
459 luaL_buffinit(L, &sb); | |
460 BN_bn2bin(s, (unsigned char*)luaL_prepbuffer(&sb)); | |
461 luaL_addsize(&sb, slen); | |
462 luaL_pushresult(&sb); | |
463 | |
464 ECDSA_SIG_free(sig); | |
465 | |
466 return 2; | |
467 } | |
468 | |
469 /* sig_der = build_ecdsa_signature(r, s) */ | |
470 static int Lbuild_ecdsa_signature(lua_State *L) { | |
471 ECDSA_SIG *sig = ECDSA_SIG_new(); | |
472 BIGNUM *r, *s; | |
473 luaL_Buffer sigbuf; | |
474 | |
475 size_t rlen, slen; | |
476 const unsigned char *rbin, *sbin; | |
477 | |
478 rbin = (unsigned char*)luaL_checklstring(L, 1, &rlen); | |
479 sbin = (unsigned char*)luaL_checklstring(L, 2, &slen); | |
480 | |
481 r = BN_bin2bn(rbin, (int)rlen, NULL); | |
482 s = BN_bin2bn(sbin, (int)slen, NULL); | |
483 | |
484 ECDSA_SIG_set0(sig, r, s); | |
485 | |
486 luaL_buffinit(L, &sigbuf); | |
487 | |
488 // COMPAT w/ Lua 5.1 | |
489 #if LUAL_BUFFERSIZE < 128 | |
490 #error Configured LUAL_BUFFERSIZE is too small for this operation | |
491 #endif | |
492 | |
493 unsigned char *buffer = (unsigned char*)luaL_prepbuffer(&sigbuf); | |
494 int len = i2d_ECDSA_SIG(sig, &buffer); | |
495 luaL_addsize(&sigbuf, len); | |
496 luaL_pushresult(&sigbuf); | |
497 | |
498 ECDSA_SIG_free(sig); | |
499 | |
500 return 1; | |
501 } | |
502 | |
503 static const luaL_Reg Reg[] = { | |
504 { "ed25519_sign", Led25519_sign }, | |
505 { "ed25519_verify", Led25519_verify }, | |
506 { "aes_128_gcm_encrypt", Laes_128_gcm_encrypt }, | |
507 { "aes_128_gcm_decrypt", Laes_128_gcm_decrypt }, | |
508 { "aes_256_gcm_encrypt", Laes_256_gcm_encrypt }, | |
509 { "aes_256_gcm_decrypt", Laes_256_gcm_decrypt }, | |
510 { "ecdsa_sha256_sign", Lecdsa_sha256_sign }, | |
511 { "ecdsa_sha256_verify", Lecdsa_sha256_verify }, | |
512 { "generate_ed25519_keypair", Lgenerate_ed25519_keypair }, | |
513 { "import_private_pem", Limport_private_pem }, | |
514 { "import_public_pem", Limport_public_pem }, | |
515 { "parse_ecdsa_signature", Lparse_ecdsa_signature }, | |
516 { "build_ecdsa_signature", Lbuild_ecdsa_signature }, | |
517 { NULL, NULL } | |
518 }; | |
519 | |
520 static const luaL_Reg KeyMethods[] = { | |
521 { "private_pem", Lpkey_meth_private_pem }, | |
522 { "public_pem", Lpkey_meth_public_pem }, | |
523 { "get_type", Lpkey_meth_get_type }, | |
524 { NULL, NULL } | |
525 }; | |
526 | |
527 static const luaL_Reg KeyMetatable[] = { | |
528 { "__gc", Lpkey_finalizer }, | |
529 { NULL, NULL } | |
530 }; | |
531 | |
532 LUALIB_API int luaopen_util_crypto(lua_State *L) { | |
533 #if (LUA_VERSION_NUM > 501) | |
534 luaL_checkversion(L); | |
535 #endif | |
536 | |
537 /* Initialize pkey metatable */ | |
538 luaL_newmetatable(L, PKEY_MT_TAG); | |
539 luaL_setfuncs(L, KeyMetatable, 0); | |
540 lua_newtable(L); | |
541 luaL_setfuncs(L, KeyMethods, 0); | |
542 lua_setfield(L, -2, "__index"); | |
543 lua_pop(L, 1); | |
544 | |
545 /* Initialize lib table */ | |
546 lua_newtable(L); | |
547 luaL_setfuncs(L, Reg, 0); | |
548 lua_pushliteral(L, "-3.14"); | |
549 lua_setfield(L, -2, "version"); | |
550 #ifdef OPENSSL_VERSION | |
551 lua_pushstring(L, OpenSSL_version(OPENSSL_VERSION)); | |
552 lua_setfield(L, -2, "_LIBCRYPTO_VERSION"); | |
553 #endif | |
554 return 1; | |
555 } |