diff --git a/.gitignore b/.gitignore index 411abce..3bbb645 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ Release TAGS tags *.so +tests/priv.pem +tests/pub.pem +tests/tmp.rnd + diff --git a/Makefile b/Makefile index 79ae8be..b6413a4 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,178 @@ -T= crypto -V= 0.2.0 -CONFIG= ./config +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 -include $(CONFIG) +# Default target executed when no arguments are given to make. +default_target: all -OBJS= src/l$T.o -SRCS= src/l$T.h src/l$T.c -TESTS=tests/*.lua +.PHONY : default_target -lib: $(LIBNAME) +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: -$(LIBNAME): $(OBJS) - export MACOSX_DEPLOYMENT_TARGET="10.3"; $(CC) $(CFLAGS) $(LIB_OPTION) -o $(LIBNAME) $(OBJS) $(OPENSSL_LIBS) -install: src/$(LIBNAME) - mkdir -p $(LUA_LIBDIR) - cp src/$(LIBNAME) $(LUA_LIBDIR) +#============================================================================= +# Special targets provided by cmake. +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/drew/code/luacrypto + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/drew/code/luacrypto + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/drew/code/luacrypto/CMakeFiles /home/drew/code/luacrypto/CMakeFiles/progress.marks + $(MAKE) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/drew/code/luacrypto/CMakeFiles 0 +.PHONY : all + +# The main clean target clean: - rm -f src/$(LIBNAME) $(OBJS) $(COMPAT_O) + $(MAKE) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named crypto + +# Build rule for target. +crypto: cmake_check_build_system + $(MAKE) -f CMakeFiles/Makefile2 crypto +.PHONY : crypto + +# fast build rule for target. +crypto/fast: + $(MAKE) -f CMakeFiles/crypto.dir/build.make CMakeFiles/crypto.dir/build +.PHONY : crypto/fast + +src/lcrypto.o: src/lcrypto.c.o + +.PHONY : src/lcrypto.o + +# target to build an object file +src/lcrypto.c.o: + $(MAKE) -f CMakeFiles/crypto.dir/build.make CMakeFiles/crypto.dir/src/lcrypto.c.o +.PHONY : src/lcrypto.c.o + +src/lcrypto.i: src/lcrypto.c.i + +.PHONY : src/lcrypto.i + +# target to preprocess a source file +src/lcrypto.c.i: + $(MAKE) -f CMakeFiles/crypto.dir/build.make CMakeFiles/crypto.dir/src/lcrypto.c.i +.PHONY : src/lcrypto.c.i + +src/lcrypto.s: src/lcrypto.c.s + +.PHONY : src/lcrypto.s + +# target to generate assembly for a file +src/lcrypto.c.s: + $(MAKE) -f CMakeFiles/crypto.dir/build.make CMakeFiles/crypto.dir/src/lcrypto.c.s +.PHONY : src/lcrypto.c.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... rebuild_cache" + @echo "... crypto" + @echo "... edit_cache" + @echo "... src/lcrypto.o" + @echo "... src/lcrypto.i" + @echo "... src/lcrypto.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. -tests: test -test: $(TESTS) lib - ./tests/run-tests +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system -.PHONY: test tests diff --git a/src/lcrypto.c b/src/lcrypto.c index 086a455..b57ce44 100644 --- a/src/lcrypto.c +++ b/src/lcrypto.c @@ -3,1569 +3,1613 @@ ** See Copyright Notice in license.html */ -#include +#include +#include #include #include #include +#include #include #include -#include -#include -#include #include #include +#include #ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifdef __GNUC__ -# define UNUSED __attribute__ ((unused)) +#define UNUSED __attribute__((unused)) #else -# define UNUSED +#define UNUSED #endif -#include #include +#include + #include "lcrypto.h" -LUACRYPTO_API int luaopen_crypto(lua_State *L); +LUACRYPTO_API int luaopen_crypto(lua_State* L); -static int crypto_error(lua_State *L) +static int crypto_error(lua_State* L) { - char buf[120]; - unsigned long e = ERR_get_error(); - ERR_load_crypto_strings(); - lua_pushnil(L); - lua_pushstring(L, ERR_error_string(e, buf)); - return 2; + char buf[120]; + unsigned long e = ERR_get_error(); + ERR_load_crypto_strings(); + lua_pushnil(L); + lua_pushstring(L, ERR_error_string(e, buf)); + return 2; } /*************** DIGEST API ***************/ +typedef struct digest_context { + EVP_MD_CTX* ctx; +} digest_context; -static EVP_MD_CTX *digest_pnew(lua_State *L) +static digest_context* digest_pnew(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)lua_newuserdata(L, sizeof(EVP_MD_CTX)); - luaL_getmetatable(L, LUACRYPTO_DIGESTNAME); - lua_setmetatable(L, -2); - return c; + digest_context* c = (digest_context*)lua_newuserdata(L, sizeof(digest_context)); + c->ctx = EVP_MD_CTX_new(); + + luaL_getmetatable(L, LUACRYPTO_DIGESTNAME); + lua_setmetatable(L, -2); + return c; } -static int digest_fnew(lua_State *L) +static int digest_fnew(lua_State* L) { - const char *s = luaL_checkstring(L, 1); - const EVP_MD *digest = EVP_get_digestbyname(s); - EVP_MD_CTX *c; + const char* s = luaL_checkstring(L, 1); + const EVP_MD* digest = EVP_get_digestbyname(s); + digest_context* c; - if (digest == NULL) - return luaL_argerror(L, 1, "invalid digest/cipher type"); + if (digest == NULL) + return luaL_argerror(L, 1, "invalid digest/cipher type"); - c = digest_pnew(L); - EVP_MD_CTX_init(c); - if (EVP_DigestInit_ex(c, digest, NULL) != 1) - return crypto_error(L); + c = digest_pnew(L); + if (EVP_DigestInit_ex(c->ctx, digest, NULL) != 1) + return crypto_error(L); - return 1; + return 1; } -static int digest_clone(lua_State *L) +static int digest_clone(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); - EVP_MD_CTX *d = digest_pnew(L); - EVP_MD_CTX_init(d); - if (!EVP_MD_CTX_copy_ex(d, c)) { - return crypto_error(L); - } - return 1; + digest_context* c = (digest_context*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); + digest_context* d = digest_pnew(L); + if (!EVP_MD_CTX_copy_ex(d->ctx, c->ctx)) { + return crypto_error(L); + } + return 1; } -static int digest_reset(lua_State *L) +static int digest_reset(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); - const EVP_MD *t = EVP_MD_CTX_md(c); - if (!EVP_MD_CTX_cleanup(c)) { - return crypto_error(L); - } - EVP_MD_CTX_init(c); - if (!EVP_DigestInit_ex(c, t, NULL)) { - return crypto_error(L); - } - return 0; + digest_context* c = (digest_context*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); + const EVP_MD* t = EVP_MD_CTX_md(c->ctx); + if (!EVP_MD_CTX_reset(c->ctx)) { + return crypto_error(L); + } + if (!EVP_DigestInit_ex(c->ctx, t, NULL)) { + return crypto_error(L); + } + return 0; } -static int digest_update(lua_State *L) +static int digest_update(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); - const char *s = luaL_checkstring(L, 2); + digest_context* c = (digest_context*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); + size_t sl; + const char* s = luaL_checklstring(L, 2, &sl); - if (!EVP_DigestUpdate(c, s, lua_rawlen(L, 2))) { - return crypto_error(L); - } + if (!EVP_DigestUpdate(c->ctx, s, sl)) { + return crypto_error(L); + } - lua_settop(L, 1); - return 1; + lua_settop(L, 1); + return 1; } -static int digest_final(lua_State *L) +static int digest_final(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); - EVP_MD_CTX *d = NULL; - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int written = 0; - unsigned int i; - char *hex; - - if (lua_isstring(L, 2)) { - const char *s = luaL_checkstring(L, 2); - if(!EVP_DigestUpdate(c, s, lua_rawlen(L, 2))) { - return crypto_error(L); + digest_context* c = (digest_context*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); + EVP_MD_CTX* d = NULL; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int written = 0; + unsigned int i; + char* hex; + size_t sl; + const char* s; + + if (lua_isstring(L, 2)) { + s = luaL_checklstring(L, 2, &sl); + if (!EVP_DigestUpdate(c->ctx, s, sl)) { + return crypto_error(L); + } } - } - d = EVP_MD_CTX_create(); - if (!EVP_MD_CTX_copy_ex(d, c)) { - return crypto_error(L); - } - if (!EVP_DigestFinal_ex(d, digest, &written)) { - return crypto_error(L); - } - EVP_MD_CTX_destroy(d); - - if (lua_toboolean(L, 3)) - lua_pushlstring(L, (char *)digest, written); - else { - hex = (char*)calloc(sizeof(char), written*2 + 1); - for (i = 0; i < written; i++) - sprintf(hex + 2*i, "%02x", digest[i]); - lua_pushlstring(L, hex, written*2); - free(hex); - } + d = EVP_MD_CTX_create(); + if (!EVP_MD_CTX_copy_ex(d, c->ctx)) { + return crypto_error(L); + } + if (!EVP_DigestFinal_ex(d, digest, &written)) { + return crypto_error(L); + } + EVP_MD_CTX_destroy(d); + + if (lua_toboolean(L, 3)) + lua_pushlstring(L, (char*)digest, written); + else { + hex = (char*)calloc(sizeof(char), written * 2 + 1); + for (i = 0; i < written; i++) + sprintf(hex + 2 * i, "%02x", digest[i]); + lua_pushlstring(L, hex, written * 2); + free(hex); + } - return 1; + return 1; } -static int digest_tostring(lua_State *L) +static int digest_tostring(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); - char s[64]; - sprintf(s, "%s %p", LUACRYPTO_DIGESTNAME, (void *)c); - lua_pushstring(L, s); - return 1; + digest_context* c = (digest_context*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); + char s[64]; + sprintf(s, "%s %p", LUACRYPTO_DIGESTNAME, (void*)c); + lua_pushstring(L, s); + return 1; } -static int digest_gc(lua_State *L) +static int digest_gc(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); - if (!EVP_MD_CTX_cleanup(c)) { - return crypto_error(L); - } - return 1; + digest_context* c = (digest_context*)luaL_checkudata(L, 1, LUACRYPTO_DIGESTNAME); + EVP_MD_CTX_free(c->ctx); + return 0; } -static int digest_fdigest(lua_State *L) +static int digest_fdigest(lua_State* L) { - const char *type_name = luaL_checkstring(L, 2); - const EVP_MD *type = EVP_get_digestbyname(type_name); - const char *s = luaL_checkstring(L, 3); - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int written = 0; - EVP_MD_CTX *c; + const char* type_name = luaL_checkstring(L, 2); + const EVP_MD* type = EVP_get_digestbyname(type_name); + size_t sl; + const char* s = luaL_checklstring(L, 3, &sl); + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int written = 0; + EVP_MD_CTX* c; - if (type == NULL) { - luaL_argerror(L, 1, "invalid digest type"); - return 0; - } + if (type == NULL) { + luaL_argerror(L, 1, "invalid digest type"); + return 0; + } - c = EVP_MD_CTX_create(); - if (!EVP_DigestInit_ex(c, type, NULL)) { - EVP_MD_CTX_destroy(c); - return crypto_error(L); - } - if (!EVP_DigestUpdate(c, s, lua_rawlen(L, 3))) { - EVP_MD_CTX_destroy(c); - return crypto_error(L); - } - if (!EVP_DigestFinal_ex(c, digest, &written)) { + c = EVP_MD_CTX_create(); + if (!EVP_DigestInit_ex(c, type, NULL)) { + EVP_MD_CTX_destroy(c); + return crypto_error(L); + } + if (!EVP_DigestUpdate(c, s, sl)) { + EVP_MD_CTX_destroy(c); + return crypto_error(L); + } + if (!EVP_DigestFinal_ex(c, digest, &written)) { + EVP_MD_CTX_destroy(c); + return crypto_error(L); + } EVP_MD_CTX_destroy(c); - return crypto_error(L); - } - EVP_MD_CTX_destroy(c); - if (lua_toboolean(L, 4)) - lua_pushlstring(L, (char *)digest, written); - else { - char *hex = (char*)calloc(sizeof(char), written*2 + 1); - unsigned int i; - for (i = 0; i < written; i++) - sprintf(hex + 2*i, "%02x", digest[i]); - lua_pushlstring(L, hex, written*2); - free(hex); - } + if (lua_toboolean(L, 4)) + lua_pushlstring(L, (char*)digest, written); + else { + char* hex = (char*)calloc(sizeof(char), written * 2 + 1); + unsigned int i; + for (i = 0; i < written; i++) + sprintf(hex + 2 * i, "%02x", digest[i]); + lua_pushlstring(L, hex, written * 2); + free(hex); + } - return 1; + return 1; } /*************** ENCRYPT API ***************/ +typedef struct cipher_context { + EVP_CIPHER_CTX* ctx; +} cipher_context; -static int parse_enc_params(lua_State *L, EVP_CIPHER** cipher, char** key, size_t *key_len, - char** iv, size_t* iv_len, int* pad, int* size_to_return, - int cipher_pos, int key_pos, int iv_pos, int pad_pos) +static int parse_enc_params(lua_State* L, EVP_CIPHER** cipher, char** key, size_t* key_len, + char** iv, size_t* iv_len, int* pad, int* size_to_return, + int cipher_pos, int key_pos, int iv_pos, int pad_pos) { - const char *s = luaL_checkstring(L, cipher_pos); - *cipher = (EVP_CIPHER*)EVP_get_cipherbyname(s); - *size_to_return = 0; + const char* s = luaL_checkstring(L, cipher_pos); + *cipher = (EVP_CIPHER*)EVP_get_cipherbyname(s); + *size_to_return = 0; - if (*cipher == NULL) { - return luaL_argerror(L, cipher_pos, "invalid encrypt cipher"); - } + if (*cipher == NULL) { + return luaL_argerror(L, cipher_pos, "invalid encrypt cipher"); + } - *key_len = 0; - *key = (char*)luaL_checklstring(L, key_pos, key_len); - if (*key_len > EVP_MAX_KEY_LENGTH) { - return luaL_argerror(L, key_pos, "invalid encrypt/decrypt key"); - } + *key_len = 0; + *key = (char*)luaL_checklstring(L, key_pos, key_len); + if (*key_len > EVP_MAX_KEY_LENGTH) { + return luaL_argerror(L, key_pos, "invalid encrypt/decrypt key"); + } - *iv_len = 0; - *iv = (char*)lua_tolstring(L, iv_pos, iv_len); /* can be NULL */ - if (*iv && (*iv_len > (size_t)EVP_CIPHER_iv_length(*cipher))) { - return luaL_argerror(L, iv_pos, "invalid iv length"); - } + *iv_len = 0; + *iv = (char*)lua_tolstring(L, iv_pos, iv_len); /* can be NULL */ + if (*iv && (*iv_len > (size_t)EVP_CIPHER_iv_length(*cipher))) { + return luaL_argerror(L, iv_pos, "invalid iv length"); + } - *pad = (lua_gettop(L) < pad_pos || lua_toboolean(L, pad_pos)); + *pad = (lua_gettop(L) < pad_pos || lua_toboolean(L, pad_pos)); - return 1; + return 1; } -static int parse_new_enc_params(lua_State *L, EVP_CIPHER** cipher, char** key, size_t *key_len, - char** iv, size_t* iv_len, int* pad, int* size_to_return) +static int parse_new_enc_params(lua_State* L, EVP_CIPHER** cipher, char** key, size_t* key_len, + char** iv, size_t* iv_len, int* pad, int* size_to_return) { - return parse_enc_params(L, cipher, key, key_len, iv, iv_len, pad, size_to_return, - 1, 2, 3, 4); + return parse_enc_params(L, cipher, key, key_len, iv, iv_len, pad, size_to_return, + 1, 2, 3, 4); } -static int parse_f_enc_params(lua_State *L, EVP_CIPHER** cipher, char** key, size_t *key_len, - char** iv, size_t* iv_len, int* pad, int* size_to_return) +static int parse_f_enc_params(lua_State* L, EVP_CIPHER** cipher, char** key, size_t* key_len, + char** iv, size_t* iv_len, int* pad, int* size_to_return) { - return parse_enc_params(L, cipher, key, key_len, iv, iv_len, pad, size_to_return, - 2, 4, 5, 6); + return parse_enc_params(L, cipher, key, key_len, iv, iv_len, pad, size_to_return, + 2, 4, 5, 6); } -#define TRY_CTX(fun) if (!fun) { *size_to_return = crypto_error(L); return 0; } +#define TRY_CTX(fun) \ + if (!fun) { \ + *size_to_return = crypto_error(L); \ + return 0; \ + } static int init_encryptor_decryptor(int (*init_fun)(EVP_CIPHER_CTX*, const EVP_CIPHER*, ENGINE*, const unsigned char*, const unsigned char*), - lua_State *L, EVP_CIPHER_CTX *c, const EVP_CIPHER* cipher, const char* key, size_t key_len, - const char* iv, size_t iv_len, int pad, int* size_to_return) + lua_State* L, EVP_CIPHER_CTX* c, const EVP_CIPHER* cipher, const char* key, size_t key_len, + const char* iv, size_t iv_len, int pad, int* size_to_return) { - unsigned char the_key[EVP_MAX_KEY_LENGTH] = {0}; - unsigned char the_iv[EVP_MAX_IV_LENGTH] = {0}; + unsigned char the_key[EVP_MAX_KEY_LENGTH] = { 0 }; + unsigned char the_iv[EVP_MAX_IV_LENGTH] = { 0 }; - EVP_CIPHER_CTX_init(c); - TRY_CTX(init_fun(c, cipher, NULL, NULL, NULL)) + TRY_CTX(init_fun(c, cipher, NULL, NULL, NULL)) - if (!pad) - TRY_CTX(EVP_CIPHER_CTX_set_padding(c, 0)) + if (!pad) + TRY_CTX(EVP_CIPHER_CTX_set_padding(c, 0)) - if (iv) - memcpy(the_iv, iv, iv_len); + if (iv) + memcpy(the_iv, iv, iv_len); - memcpy(the_key, key, key_len); - TRY_CTX(init_fun(c, NULL, NULL, the_key, the_iv)) + memcpy(the_key, key, key_len); + TRY_CTX(init_fun(c, NULL, NULL, the_key, the_iv)) - return 1; + return 1; } -static EVP_CIPHER_CTX *encrypt_pnew(lua_State *L) +static cipher_context* encrypt_pnew(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)lua_newuserdata(L, sizeof(EVP_CIPHER_CTX)); - luaL_getmetatable(L, LUACRYPTO_ENCRYPTNAME); - lua_setmetatable(L, -2); - return c; + cipher_context* c = (cipher_context*)lua_newuserdata(L, sizeof(cipher_context)); + c->ctx = EVP_CIPHER_CTX_new(); + + luaL_getmetatable(L, LUACRYPTO_ENCRYPTNAME); + lua_setmetatable(L, -2); + + return c; } -static int encrypt_fnew(lua_State *L) +static int encrypt_fnew(lua_State* L) { - const char *key = 0, *iv = 0; - const EVP_CIPHER *cipher = 0; + const char *key = 0, *iv = 0; + const EVP_CIPHER* cipher = 0; - size_t key_len = 0, iv_len = 0; - int pad = 1, size_to_return = 0; + size_t key_len = 0, iv_len = 0; + int pad = 1, size_to_return = 0; - EVP_CIPHER_CTX *c; + cipher_context* c; - if (!parse_new_enc_params(L, (EVP_CIPHER**)&cipher, (char**)&key, &key_len, - (char**)&iv, &iv_len, &pad, &size_to_return)) { - return size_to_return; - } + if (!parse_new_enc_params(L, (EVP_CIPHER**)&cipher, (char**)&key, &key_len, + (char**)&iv, &iv_len, &pad, &size_to_return)) { + return size_to_return; + } - c = encrypt_pnew(L); - if (!init_encryptor_decryptor(EVP_EncryptInit_ex, L, c, cipher, key, key_len, iv, iv_len, pad, &size_to_return)) { - return size_to_return; - } - return 1; + c = encrypt_pnew(L); + if (!init_encryptor_decryptor(EVP_EncryptInit_ex, L, c->ctx, cipher, key, key_len, iv, iv_len, pad, &size_to_return)) { + return size_to_return; + } + return 1; } -static int encrypt_update(lua_State *L) +static int encrypt_update(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)luaL_checkudata(L, 1, LUACRYPTO_ENCRYPTNAME); - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 2, &input_len); - int output_len = 0; - unsigned char *buffer = NULL; - - buffer = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(c)); - if (!EVP_EncryptUpdate(c, buffer, &output_len, input, (int)input_len)) { + cipher_context* c = (cipher_context*)luaL_checkudata(L, 1, LUACRYPTO_ENCRYPTNAME); + size_t input_len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 2, &input_len); + int output_len = 0; + unsigned char* buffer = NULL; + + buffer = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(c->ctx)); + if (!EVP_EncryptUpdate(c->ctx, buffer, &output_len, input, (int)input_len)) { + free(buffer); + return crypto_error(L); + } + lua_pushlstring(L, (char*)buffer, (size_t)output_len); free(buffer); - return crypto_error(L); - } - lua_pushlstring(L, (char*) buffer, (size_t)output_len); - free(buffer); - return 1; + return 1; } -static int encrypt_final(lua_State *L) +static int encrypt_final(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)luaL_checkudata(L, 1, LUACRYPTO_ENCRYPTNAME); - int output_len = 0; - unsigned char buffer[EVP_MAX_BLOCK_LENGTH]; + cipher_context* c = (cipher_context*)luaL_checkudata(L, 1, LUACRYPTO_ENCRYPTNAME); + int output_len = 0; + unsigned char buffer[EVP_MAX_BLOCK_LENGTH]; - if (!EVP_EncryptFinal_ex(c, buffer, &output_len)) { - return crypto_error(L); - } - lua_pushlstring(L, (char*) buffer, (size_t)output_len); - return 1; + if (!EVP_EncryptFinal_ex(c->ctx, buffer, &output_len)) { + return crypto_error(L); + } + lua_pushlstring(L, (char*)buffer, (size_t)output_len); + return 1; } -static int encrypt_tostring(lua_State *L) +static int encrypt_tostring(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)luaL_checkudata(L, 1, LUACRYPTO_ENCRYPTNAME); - char s[64]; - sprintf(s, "%s %p", LUACRYPTO_ENCRYPTNAME, (void *)c); - lua_pushstring(L, s); - return 1; + cipher_context* c = (cipher_context*)luaL_checkudata(L, 1, LUACRYPTO_ENCRYPTNAME); + char s[64]; + sprintf(s, "%s %p", LUACRYPTO_ENCRYPTNAME, (void*)c); + lua_pushstring(L, s); + return 1; } -static int encrypt_gc(lua_State *L) +static int encrypt_gc(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)luaL_checkudata(L, 1, LUACRYPTO_ENCRYPTNAME); - if (!EVP_CIPHER_CTX_cleanup(c)) { - return crypto_error(L); - } - return 1; + cipher_context* c = (cipher_context*)luaL_checkudata(L, 1, LUACRYPTO_ENCRYPTNAME); + EVP_CIPHER_CTX_free(c->ctx); + return 0; } -static int encrypt_fencrypt(lua_State *L) +static int encrypt_fencrypt(lua_State* L) { - /* parameter 1 is the 'crypto.encrypt' table */ - const EVP_CIPHER *type; + /* parameter 1 is the 'crypto.encrypt' table */ + const EVP_CIPHER* type; - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 3, &input_len); + size_t input_len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 3, &input_len); - size_t key_len = 0, iv_len = 0; - const char *key = NULL, *iv = NULL; - int pad = 0, size_to_return = 0; - EVP_CIPHER_CTX c; + size_t key_len = 0, iv_len = 0; + const char *key = NULL, *iv = NULL; + int pad = 0, size_to_return = 0; - int output_len = 0; - int len = 0; + int output_len = 0; + int len = 0; - unsigned char *buffer; + unsigned char* buffer; - if (!parse_f_enc_params(L, (EVP_CIPHER**)&type, (char**)&key, &key_len, (char**)&iv, &iv_len, &pad, &size_to_return)) { - return size_to_return; - } + EVP_CIPHER_CTX* c = EVP_CIPHER_CTX_new(); - if (!init_encryptor_decryptor(EVP_EncryptInit_ex, L, &c, type, key, key_len, iv, iv_len, pad, &size_to_return)) { - return size_to_return; - } + if (!parse_f_enc_params(L, (EVP_CIPHER**)&type, (char**)&key, &key_len, (char**)&iv, &iv_len, &pad, &size_to_return)) { + EVP_CIPHER_CTX_free(c); + return size_to_return; + } + if (!init_encryptor_decryptor(EVP_EncryptInit_ex, L, c, type, key, key_len, iv, iv_len, pad, &size_to_return)) { + EVP_CIPHER_CTX_free(c); + return size_to_return; + } - buffer = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(&c)); + buffer = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(c)); - if (!EVP_EncryptUpdate(&c, buffer, &len, input, (int)input_len)) { - EVP_CIPHER_CTX_cleanup(&c); - free(buffer); - return crypto_error(L); - } - output_len += len; - if (!EVP_EncryptFinal_ex(&c, &buffer[output_len], &len)) { - EVP_CIPHER_CTX_cleanup(&c); - free(buffer); - return crypto_error(L); - } - output_len += len; + if (!EVP_EncryptUpdate(c, buffer, &len, input, (int)input_len)) { + EVP_CIPHER_CTX_free(c); + free(buffer); + return crypto_error(L); + } + output_len += len; + if (!EVP_EncryptFinal_ex(c, &buffer[output_len], &len)) { + EVP_CIPHER_CTX_free(c); + free(buffer); + return crypto_error(L); + } + output_len += len; - lua_pushlstring(L, (char*) buffer, (size_t)output_len); - free(buffer); - EVP_CIPHER_CTX_cleanup(&c); - return 1; + lua_pushlstring(L, (char*)buffer, (size_t)output_len); + free(buffer); + EVP_CIPHER_CTX_free(c); + return 1; } /*************** DECRYPT API ***************/ -static EVP_CIPHER_CTX *decrypt_pnew(lua_State *L) +static cipher_context* decrypt_pnew(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)lua_newuserdata(L, sizeof(EVP_CIPHER_CTX)); - luaL_getmetatable(L, LUACRYPTO_DECRYPTNAME); - lua_setmetatable(L, -2); - return c; + cipher_context* c = (cipher_context*)lua_newuserdata(L, sizeof(cipher_context)); + c->ctx = EVP_CIPHER_CTX_new(); + + luaL_getmetatable(L, LUACRYPTO_DECRYPTNAME); + lua_setmetatable(L, -2); + + return c; } -static int decrypt_fnew(lua_State *L) +static int decrypt_fnew(lua_State* L) { - const char *key = 0, *iv = 0; - const EVP_CIPHER *cipher = 0; + const char *key = 0, *iv = 0; + const EVP_CIPHER* cipher = 0; - size_t key_len = 0, iv_len = 0; - int pad = 1, size_to_return = 0; - EVP_CIPHER_CTX *c; + size_t key_len = 0, iv_len = 0; + int pad = 1, size_to_return = 0; + cipher_context* c; - if (!parse_new_enc_params(L, (EVP_CIPHER**)&cipher, (char**)&key, &key_len, - (char**)&iv, &iv_len, &pad, &size_to_return)) { - return size_to_return; - } + if (!parse_new_enc_params(L, (EVP_CIPHER**)&cipher, (char**)&key, &key_len, + (char**)&iv, &iv_len, &pad, &size_to_return)) { + return size_to_return; + } - c = decrypt_pnew(L); - if (!init_encryptor_decryptor(EVP_DecryptInit_ex, L, c, cipher, key, key_len, iv, iv_len, pad, &size_to_return)) { - return size_to_return; - } - return 1; + c = decrypt_pnew(L); + if (!init_encryptor_decryptor(EVP_DecryptInit_ex, L, c->ctx, cipher, key, key_len, iv, iv_len, pad, &size_to_return)) { + return size_to_return; + } + return 1; } -static int decrypt_update(lua_State *L) +static int decrypt_update(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DECRYPTNAME); - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 2, &input_len); - int output_len = 0; - unsigned char *buffer = NULL; + cipher_context* c = (cipher_context*)luaL_checkudata(L, 1, LUACRYPTO_DECRYPTNAME); + size_t input_len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 2, &input_len); + int output_len = 0; + unsigned char* buffer = NULL; - buffer = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(c)); - if (!EVP_DecryptUpdate(c, buffer, &output_len, input, (int)input_len)) { - return crypto_error(L); - } - lua_pushlstring(L, (char*) buffer, (size_t)output_len); - free(buffer); + buffer = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(c->ctx)); + if (!EVP_DecryptUpdate(c->ctx, buffer, &output_len, input, (int)input_len)) { + return crypto_error(L); + } + lua_pushlstring(L, (char*)buffer, (size_t)output_len); + free(buffer); - return 1; + return 1; } -static int decrypt_final(lua_State *L) +static int decrypt_final(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DECRYPTNAME); - int output_len = 0; - unsigned char buffer[EVP_MAX_BLOCK_LENGTH]; + cipher_context* c = (cipher_context*)luaL_checkudata(L, 1, LUACRYPTO_DECRYPTNAME); + int output_len = 0; + unsigned char buffer[EVP_MAX_BLOCK_LENGTH]; - if (!EVP_DecryptFinal_ex(c, buffer, &output_len)) { - return crypto_error(L); - } - lua_pushlstring(L, (char*) buffer, (size_t)output_len); - return 1; + if (!EVP_DecryptFinal_ex(c->ctx, buffer, &output_len)) { + return crypto_error(L); + } + lua_pushlstring(L, (char*)buffer, (size_t)output_len); + return 1; } -static int decrypt_tostring(lua_State *L) +static int decrypt_tostring(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DECRYPTNAME); - char s[64]; - sprintf(s, "%s %p", LUACRYPTO_DECRYPTNAME, (void *)c); - lua_pushstring(L, s); - return 1; + cipher_context* c = (cipher_context*)luaL_checkudata(L, 1, LUACRYPTO_DECRYPTNAME); + char s[64]; + sprintf(s, "%s %p", LUACRYPTO_DECRYPTNAME, (void*)c); + lua_pushstring(L, s); + return 1; } -static int decrypt_gc(lua_State *L) +static int decrypt_gc(lua_State* L) { - EVP_CIPHER_CTX *c = (EVP_CIPHER_CTX*)luaL_checkudata(L, 1, LUACRYPTO_DECRYPTNAME); - if (!EVP_CIPHER_CTX_cleanup(c)) { - return crypto_error(L); - } - return 1; + cipher_context* c = (cipher_context*)luaL_checkudata(L, 1, LUACRYPTO_DECRYPTNAME); + EVP_CIPHER_CTX_free(c->ctx); + return 1; } -static int decrypt_fdecrypt(lua_State *L) +static int decrypt_fdecrypt(lua_State* L) { - /* parameter 1 is the 'crypto.decrypt' table */ - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 3, &input_len); + /* parameter 1 is the 'crypto.decrypt' table */ + size_t input_len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 3, &input_len); - const EVP_CIPHER *type; - size_t key_len = 0, iv_len = 0; - const char *key = NULL, *iv = NULL; - int pad = 0, size_to_return = 0; - EVP_CIPHER_CTX c; - unsigned char *buffer; - int output_len = 0; - int len = 0; + const EVP_CIPHER* type; + size_t key_len = 0, iv_len = 0; + const char *key = NULL, *iv = NULL; + int pad = 0, size_to_return = 0; + unsigned char* buffer; + int output_len = 0; + int len = 0; + EVP_CIPHER_CTX* c = EVP_CIPHER_CTX_new(); - if (!parse_f_enc_params(L, (EVP_CIPHER**)&type, (char**)&key, &key_len, (char**)&iv, &iv_len, &pad, &size_to_return)) { - return size_to_return; - } + if (!parse_f_enc_params(L, (EVP_CIPHER**)&type, (char**)&key, &key_len, (char**)&iv, &iv_len, &pad, &size_to_return)) { + EVP_CIPHER_CTX_free(c); + return size_to_return; + } - - if (!init_encryptor_decryptor(EVP_DecryptInit_ex, L, &c, type, key, key_len, iv, iv_len, pad, &size_to_return)) { - return size_to_return; - } + if (!init_encryptor_decryptor(EVP_DecryptInit_ex, L, c, type, key, key_len, iv, iv_len, pad, &size_to_return)) { + EVP_CIPHER_CTX_free(c); + return size_to_return; + } - buffer = (unsigned char *)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(&c)); - if (!EVP_DecryptUpdate(&c, buffer, &len, input, (int)input_len)) { - EVP_CIPHER_CTX_cleanup(&c); - free(buffer); - return crypto_error(L); - } - output_len += len; - if (!EVP_DecryptFinal_ex(&c, &buffer[len], &len)) { - EVP_CIPHER_CTX_cleanup(&c); - free(buffer); - return crypto_error(L); - } - output_len += len; + buffer = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(c)); + if (!EVP_DecryptUpdate(c, buffer, &len, input, (int)input_len)) { + EVP_CIPHER_CTX_free(c); + free(buffer); + return crypto_error(L); + } + output_len += len; + if (!EVP_DecryptFinal_ex(c, &buffer[len], &len)) { + EVP_CIPHER_CTX_free(c); + free(buffer); + return crypto_error(L); + } + output_len += len; - lua_pushlstring(L, (char*) buffer, (size_t)output_len); - free(buffer); - EVP_CIPHER_CTX_cleanup(&c); - return 1; + lua_pushlstring(L, (char*)buffer, (size_t)output_len); + free(buffer); + EVP_CIPHER_CTX_free(c); + return 1; } /*************** HMAC API ***************/ +typedef struct hmac_context { + HMAC_CTX* ctx; +} hmac_context; -static HMAC_CTX *hmac_pnew(lua_State *L) +static hmac_context* hmac_pnew(lua_State* L) { - HMAC_CTX *c = (HMAC_CTX*)lua_newuserdata(L, sizeof(HMAC_CTX)); - luaL_getmetatable(L, LUACRYPTO_HMACNAME); - lua_setmetatable(L, -2); - return c; + hmac_context* c = (hmac_context*)lua_newuserdata(L, sizeof(hmac_context)); + c->ctx = HMAC_CTX_new(); + + luaL_getmetatable(L, LUACRYPTO_HMACNAME); + lua_setmetatable(L, -2); + + return c; } -static int hmac_fnew(lua_State *L) +static int hmac_fnew(lua_State* L) { - HMAC_CTX *c = hmac_pnew(L); - const char *s = luaL_checkstring(L, 1); - const char *k = luaL_checkstring(L, 2); - const EVP_MD *type = EVP_get_digestbyname(s); + hmac_context* c = hmac_pnew(L); + + size_t k_len; + const char* s = luaL_checkstring(L, 1); + const char* k = luaL_checklstring(L, 2, &k_len); + const EVP_MD* type = EVP_get_digestbyname(s); - if (type == NULL) - return luaL_argerror(L, 1, "invalid digest type"); + if (type == NULL) + return luaL_argerror(L, 1, "invalid digest type"); - HMAC_CTX_init(c); - HMAC_Init_ex(c, k, (int)lua_rawlen(L, 2), type, NULL); + HMAC_Init_ex(c->ctx, k, k_len, type, NULL); - return 1; + return 1; } -static int hmac_clone(lua_State *L) +static int hmac_clone(lua_State* L) { - HMAC_CTX *c = (HMAC_CTX*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); - HMAC_CTX *d = hmac_pnew(L); - *d = *c; - return 1; + hmac_context* c = (hmac_context*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); + hmac_context* d = hmac_pnew(L); + if (!HMAC_CTX_copy(d->ctx, c->ctx)) { + return crypto_error(L); + } + return 1; } -static int hmac_reset(lua_State *L) +static int hmac_reset(lua_State* L) { - HMAC_CTX *c = (HMAC_CTX*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); - HMAC_Init_ex(c, NULL, 0, NULL, NULL); - return 0; + hmac_context* c = (hmac_context*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); + HMAC_Init_ex(c->ctx, NULL, 0, NULL, NULL); + return 0; } -static int hmac_update(lua_State *L) +static int hmac_update(lua_State* L) { - HMAC_CTX *c = (HMAC_CTX*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); - const char *s = luaL_checkstring(L, 2); + size_t s_len; + hmac_context* c = (hmac_context*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); + const char* s = luaL_checklstring(L, 2, &s_len); - HMAC_Update(c, (unsigned char *)s, lua_rawlen(L, 2)); + if(HMAC_Update(c->ctx, (const unsigned char*)s, s_len) != 1) { + return crypto_error(L); + } - lua_settop(L, 1); - return 1; + lua_settop(L, 1); + return 1; } -static int hmac_final(lua_State *L) +static int hmac_final(lua_State* L) { - HMAC_CTX *c = (HMAC_CTX*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int written = 0; - unsigned int i; - char *hex; + hmac_context* c = (hmac_context*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int written = 0; + unsigned int i; + char* hex; - if (lua_isstring(L, 2)) { - const char *s = luaL_checkstring(L, 2); - HMAC_Update(c, (unsigned char *)s, lua_rawlen(L, 2)); - } + if (lua_isstring(L, 2)) { + size_t s_len; + const char* s = luaL_checklstring(L, 2, &s_len); + HMAC_Update(c->ctx, (const unsigned char*)s, s_len); + } - HMAC_Final(c, digest, &written); + if(HMAC_Final(c->ctx, digest, &written) != 1) { + return crypto_error(L); + } - if (lua_toboolean(L, 3)) - lua_pushlstring(L, (char *)digest, written); - else { - hex = (char*)calloc(sizeof(char), written*2 + 1); - for (i = 0; i < written; i++) - sprintf(hex + 2*i, "%02x", digest[i]); - lua_pushlstring(L, hex, written*2); - free(hex); - } + if (lua_toboolean(L, 3)) + lua_pushlstring(L, (char*)digest, written); + else { + hex = (char*)calloc(sizeof(char), written * 2 + 1); + for (i = 0; i < written; i++) + sprintf(hex + 2 * i, "%02x", digest[i]); + lua_pushlstring(L, hex, written * 2); + free(hex); + } - return 1; + return 1; } -static int hmac_tostring(lua_State *L) +static int hmac_tostring(lua_State* L) { - HMAC_CTX *c = (HMAC_CTX*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); - char s[64]; - sprintf(s, "%s %p", LUACRYPTO_HMACNAME, (void *)c); - lua_pushstring(L, s); - return 1; + hmac_context* c = (hmac_context*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); + char s[64]; + sprintf(s, "%s %p", LUACRYPTO_HMACNAME, (void*)c); + lua_pushstring(L, s); + return 1; } -static int hmac_gc(lua_State *L) +static int hmac_gc(lua_State* L) { - HMAC_CTX *c = (HMAC_CTX*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); - HMAC_CTX_cleanup(c); - return 1; + hmac_context* c = (hmac_context*)luaL_checkudata(L, 1, LUACRYPTO_HMACNAME); + HMAC_CTX_free(c->ctx); + return 1; } -static int hmac_fdigest(lua_State *L) +static int hmac_fdigest(lua_State* L) { - const char *t = luaL_checkstring(L, 1); - const EVP_MD *type = EVP_get_digestbyname(t); - const char *s; - const char *k; - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int written = 0; - unsigned int i; - char *hex; - HMAC_CTX c; - - if (type == NULL) { - luaL_argerror(L, 1, "invalid digest type"); - return 0; - } - - s = luaL_checkstring(L, 2); - k = luaL_checkstring(L, 3); + const char* t = luaL_checkstring(L, 1); + const EVP_MD* type = EVP_get_digestbyname(t); + size_t s_len, k_len; + const char *s, *k; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int written = 0; + unsigned int i; + char* hex; + HMAC_CTX* c = HMAC_CTX_new(); - HMAC_CTX_init(&c); - HMAC_Init_ex(&c, k, (int)lua_rawlen(L, 3), type, NULL); - HMAC_Update(&c, (unsigned char *)s, lua_rawlen(L, 2)); - HMAC_Final(&c, digest, &written); - HMAC_CTX_cleanup(&c); + if (type == NULL) { + HMAC_CTX_free(c); + luaL_argerror(L, 1, "invalid digest type"); + return 0; + } - if (lua_toboolean(L, 4)) - lua_pushlstring(L, (char *)digest, written); - else { - hex = (char*)calloc(sizeof(char), written*2 + 1); - for (i = 0; i < written; i++) - sprintf(hex + 2*i, "%02x", digest[i]); - lua_pushlstring(L, hex, written*2); - free(hex); - } + s = luaL_checklstring(L, 2, &s_len); + k = luaL_checklstring(L, 3, &k_len); + + HMAC_Init_ex(c, k, (int)k_len, type, NULL); + HMAC_Update(c, (unsigned char*)s, s_len); + HMAC_Final(c, digest, &written); + HMAC_CTX_free(c); + + if (lua_toboolean(L, 4)) + lua_pushlstring(L, (char*)digest, written); + else { + hex = (char*)calloc(sizeof(char), written * 2 + 1); + for (i = 0; i < written; i++) + sprintf(hex + 2 * i, "%02x", digest[i]); + lua_pushlstring(L, hex, written * 2); + free(hex); + } - return 1; + return 1; } /*************** SIGN API ***************/ +typedef struct sign_context { + EVP_MD_CTX* ctx; +} sign_context; -static EVP_MD_CTX *sign_pnew(lua_State *L) +static sign_context* sign_pnew(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)lua_newuserdata(L, sizeof(EVP_MD_CTX)); - luaL_getmetatable(L, LUACRYPTO_SIGNNAME); - lua_setmetatable(L, -2); - return c; + sign_context* c = (sign_context*)lua_newuserdata(L, sizeof(sign_context)); + c->ctx = EVP_MD_CTX_new(); + + luaL_getmetatable(L, LUACRYPTO_SIGNNAME); + lua_setmetatable(L, -2); + return c; } -static int sign_fnew(lua_State *L) +static int sign_fnew(lua_State* L) { - const char *s = luaL_checkstring(L, 1); - const EVP_MD *md = EVP_get_digestbyname(s); - EVP_MD_CTX *c; + const char* s = luaL_checkstring(L, 1); + const EVP_MD* md = EVP_get_digestbyname(s); + sign_context* c; - if (md == NULL) - return luaL_argerror(L, 1, "invalid digest type"); + if (md == NULL) + return luaL_argerror(L, 1, "invalid digest type"); - c = sign_pnew(L); - EVP_MD_CTX_init(c); - if (EVP_SignInit_ex(c, md, NULL) != 1) - return crypto_error(L); + c = sign_pnew(L); + if (EVP_SignInit_ex(c->ctx, md, NULL) != 1) + return crypto_error(L); - return 1; + return 1; } -static int sign_update(lua_State *L) +static int sign_update(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_SIGNNAME); - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 2, &input_len); + sign_context* c = (sign_context*)luaL_checkudata(L, 1, LUACRYPTO_SIGNNAME); + size_t input_len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 2, &input_len); - EVP_SignUpdate(c, input, input_len); - return 0; + EVP_SignUpdate(c->ctx, input, input_len); + return 0; } -static int sign_final(lua_State *L) +static int sign_final(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_SIGNNAME); - unsigned int output_len = 0; - unsigned char *buffer; - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 2, LUACRYPTO_PKEYNAME); + sign_context* c = (sign_context*)luaL_checkudata(L, 1, LUACRYPTO_SIGNNAME); + unsigned int output_len = 0; + unsigned char* buffer; + EVP_PKEY** pkey = (EVP_PKEY**)luaL_checkudata(L, 2, LUACRYPTO_PKEYNAME); - buffer = (unsigned char*)malloc((size_t)EVP_PKEY_size(*pkey)); - if (!EVP_SignFinal(c, buffer, &output_len, *pkey)) { + buffer = (unsigned char*)malloc((size_t)EVP_PKEY_size(*pkey)); + if (!EVP_SignFinal(c->ctx, buffer, &output_len, *pkey)) { + free(buffer); + return crypto_error(L); + } + lua_pushlstring(L, (char*)buffer, output_len); free(buffer); - return crypto_error(L); - } - lua_pushlstring(L, (char*) buffer, output_len); - free(buffer); - return 1; + return 1; } -static int sign_tostring(lua_State *L) +static int sign_tostring(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_SIGNNAME); - char s[64]; - sprintf(s, "%s %p", LUACRYPTO_SIGNNAME, (void *)c); - lua_pushstring(L, s); - return 1; + sign_context* c = (sign_context*)luaL_checkudata(L, 1, LUACRYPTO_SIGNNAME); + char s[64]; + sprintf(s, "%s %p", LUACRYPTO_SIGNNAME, (void*)c); + lua_pushstring(L, s); + return 1; } -static int sign_gc(lua_State *L) +static int sign_gc(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_SIGNNAME); - EVP_MD_CTX_cleanup(c); - return 1; + sign_context* c = (sign_context*)luaL_checkudata(L, 1, LUACRYPTO_SIGNNAME); + EVP_MD_CTX_free(c->ctx); + return 1; } -static int sign_fsign(lua_State *L) +static int sign_fsign(lua_State* L) { - /* parameter 1 is the 'crypto.sign' table */ - const char *type_name = luaL_checkstring(L, 2); - const EVP_MD *type = EVP_get_digestbyname(type_name); + /* parameter 1 is the 'crypto.sign' table */ + const char* type_name = luaL_checkstring(L, 2); + const EVP_MD* type = EVP_get_digestbyname(type_name); + size_t input_len; + unsigned int output_len; + const unsigned char* input; + unsigned char* buffer; + EVP_PKEY** pkey; + EVP_MD_CTX* c; - if (type == NULL) { - luaL_argerror(L, 2, "invalid digest type"); - return 0; - } else { - EVP_MD_CTX c; - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 3, &input_len); - unsigned int output_len = 0; - unsigned char *buffer = NULL; - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 4, LUACRYPTO_PKEYNAME); + if (type == NULL) { + luaL_argerror(L, 2, "invalid digest type"); + return 0; + } + + input = (unsigned char*)luaL_checklstring(L, 3, &input_len); + pkey = (EVP_PKEY**)luaL_checkudata(L, 4, LUACRYPTO_PKEYNAME); - EVP_MD_CTX_init(&c); - EVP_SignInit_ex(&c, type, NULL); + c = EVP_MD_CTX_create(); + EVP_MD_CTX_init(c); + EVP_SignInit_ex(c, type, NULL); buffer = (unsigned char*)malloc((size_t)EVP_PKEY_size(*pkey)); - EVP_SignUpdate(&c, input, input_len); - if (!EVP_SignFinal(&c, buffer, &output_len, *pkey)) { - EVP_MD_CTX_cleanup(&c); - free(buffer); - return crypto_error(L); + EVP_SignUpdate(c, input, input_len); + if (!EVP_SignFinal(c, buffer, &output_len, *pkey)) { + EVP_MD_CTX_free(c); + free(buffer); + return crypto_error(L); } - EVP_MD_CTX_cleanup(&c); + EVP_MD_CTX_free(c); - lua_pushlstring(L, (char*) buffer, output_len); + lua_pushlstring(L, (char*)buffer, output_len); free(buffer); return 1; - } } /*************** VERIFY API ***************/ +typedef struct verify_context { + EVP_MD_CTX* ctx; +} verify_context; -static EVP_MD_CTX *verify_pnew(lua_State *L) +static verify_context* verify_pnew(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)lua_newuserdata(L, sizeof(EVP_MD_CTX)); - luaL_getmetatable(L, LUACRYPTO_VERIFYNAME); - lua_setmetatable(L, -2); - return c; + verify_context* c = (verify_context*)lua_newuserdata(L, sizeof(verify_context)); + c->ctx = EVP_MD_CTX_new(); + + luaL_getmetatable(L, LUACRYPTO_VERIFYNAME); + lua_setmetatable(L, -2); + return c; } -static int verify_fnew(lua_State *L) +static int verify_fnew(lua_State* L) { - const char *s = luaL_checkstring(L, 1); - const EVP_MD *md = EVP_get_digestbyname(s); - EVP_MD_CTX *c; + const char* s = luaL_checkstring(L, 1); + const EVP_MD* md = EVP_get_digestbyname(s); + verify_context* c; - if (md == NULL) - return luaL_argerror(L, 1, "invalid digest type"); + if (md == NULL) + return luaL_argerror(L, 1, "invalid digest type"); - c = verify_pnew(L); - EVP_MD_CTX_init(c); + c = verify_pnew(L); - if (EVP_VerifyInit_ex(c, md, NULL) != 1) - return crypto_error(L); + if (EVP_VerifyInit_ex(c->ctx, md, NULL) != 1) + return crypto_error(L); - return 1; + return 1; } -static int verify_update(lua_State *L) +static int verify_update(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_VERIFYNAME); - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 2, &input_len); + verify_context* c = (verify_context*)luaL_checkudata(L, 1, LUACRYPTO_VERIFYNAME); + size_t input_len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 2, &input_len); - EVP_VerifyUpdate(c, input, input_len); - return 0; + EVP_VerifyUpdate(c->ctx, input, input_len); + return 0; } -static int verify_final(lua_State *L) +static int verify_final(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_VERIFYNAME); - size_t sig_len = 0; - const unsigned char *sig = (unsigned char *) luaL_checklstring(L, 2, &sig_len); - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 3, LUACRYPTO_PKEYNAME); - int ret; + verify_context* c = (verify_context*)luaL_checkudata(L, 1, LUACRYPTO_VERIFYNAME); + size_t sig_len = 0; + const unsigned char* sig = (unsigned char*)luaL_checklstring(L, 2, &sig_len); + EVP_PKEY** pkey = (EVP_PKEY**)luaL_checkudata(L, 3, LUACRYPTO_PKEYNAME); + int ret; - ret = EVP_VerifyFinal(c, sig, sig_len, *pkey); - if (ret == -1) - return crypto_error(L); + ret = EVP_VerifyFinal(c->ctx, sig, sig_len, *pkey); + if (ret == -1) + return crypto_error(L); - lua_pushboolean(L, ret); - return 1; + lua_pushboolean(L, ret); + return 1; } -static int verify_tostring(lua_State *L) +static int verify_tostring(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_VERIFYNAME); - char s[64]; - sprintf(s, "%s %p", LUACRYPTO_VERIFYNAME, (void *)c); - lua_pushstring(L, s); - return 1; + verify_context* c = (verify_context*)luaL_checkudata(L, 1, LUACRYPTO_VERIFYNAME); + char s[64]; + sprintf(s, "%s %p", LUACRYPTO_VERIFYNAME, (void*)c); + lua_pushstring(L, s); + return 1; } -static int verify_gc(lua_State *L) +static int verify_gc(lua_State* L) { - EVP_MD_CTX *c = (EVP_MD_CTX*)luaL_checkudata(L, 1, LUACRYPTO_VERIFYNAME); - EVP_MD_CTX_cleanup(c); - return 1; + verify_context* c = (verify_context*)luaL_checkudata(L, 1, LUACRYPTO_VERIFYNAME); + EVP_MD_CTX_free(c->ctx); + return 1; } -static int verify_fverify(lua_State *L) +static int verify_fverify(lua_State* L) { - /* parameter 1 is the 'crypto.verify' table */ - const char *type_name = luaL_checkstring(L, 2); - const EVP_MD *type = EVP_get_digestbyname(type_name); + /* parameter 1 is the 'crypto.verify' table */ + const char* type_name = luaL_checkstring(L, 2); + const EVP_MD* type = EVP_get_digestbyname(type_name); - if (type == NULL) { - luaL_argerror(L, 1, "invalid digest type"); - return 0; - } else { - EVP_MD_CTX c; size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 3, &input_len); + const unsigned char* input; size_t sig_len = 0; - const unsigned char *sig = (unsigned char *) luaL_checklstring(L, 4, &sig_len); - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 5, LUACRYPTO_PKEYNAME); + const unsigned char* sig; int ret; + EVP_PKEY** pkey; + EVP_MD_CTX* c; + + if (type == NULL) { + luaL_argerror(L, 1, "invalid digest type"); + return 0; + } + + input = (unsigned char*)luaL_checklstring(L, 3, &input_len); + sig = (unsigned char*)luaL_checklstring(L, 4, &sig_len); + pkey = (EVP_PKEY**)luaL_checkudata(L, 5, LUACRYPTO_PKEYNAME); - EVP_MD_CTX_init(&c); - EVP_VerifyInit_ex(&c, type, NULL); - EVP_VerifyUpdate(&c, input, input_len); - ret = EVP_VerifyFinal(&c, sig, sig_len, *pkey); - EVP_MD_CTX_cleanup(&c); + c = EVP_MD_CTX_new(); + EVP_VerifyInit_ex(c, type, NULL); + EVP_VerifyUpdate(c, input, input_len); + ret = EVP_VerifyFinal(c, sig, sig_len, *pkey); + EVP_MD_CTX_free(c); if (ret == -1) - return crypto_error(L); + return crypto_error(L); lua_pushboolean(L, ret); return 1; - } } /*************** RAND API ***************/ -static int rand_do_bytes(lua_State *L, int (*bytes)(unsigned char *, int)) -{ - size_t count = (size_t)luaL_checkinteger(L, 1); - unsigned char tmp[256], *buf = tmp; - if (count > sizeof tmp) - buf = (unsigned char*)malloc(count); - if (!buf) - return luaL_error(L, "out of memory"); - else if (!bytes(buf, (int)count)) - return crypto_error(L); - lua_pushlstring(L, (char *)buf, count); - if (buf != tmp) - free(buf); - return 1; -} - -static int rand_bytes(lua_State *L) -{ - return rand_do_bytes(L, RAND_bytes); +static int rand_do_bytes(lua_State* L, int (*bytes)(unsigned char*, int)) +{ + size_t count = (size_t)luaL_checkinteger(L, 1); + unsigned char tmp[256], *buf = tmp; + if (count > sizeof tmp) + buf = (unsigned char*)malloc(count); + if (!buf) + return luaL_error(L, "out of memory"); + else if (!bytes(buf, (int)count)) + return crypto_error(L); + lua_pushlstring(L, (char*)buf, count); + if (buf != tmp) + free(buf); + return 1; } -static int rand_pseudo_bytes(lua_State *L) +static int rand_bytes(lua_State* L) { - return rand_do_bytes(L, RAND_pseudo_bytes); + return rand_do_bytes(L, RAND_bytes); } -static int rand_add(lua_State *L) +static int rand_add(lua_State* L) { - size_t num; - const void *buf = luaL_checklstring(L, 1, &num); - double entropy = luaL_optnumber(L, 2, num); - RAND_add(buf, (int)num, entropy); - return 0; + size_t num; + const void* buf = luaL_checklstring(L, 1, &num); + double entropy = luaL_optnumber(L, 2, num); + RAND_add(buf, (int)num, entropy); + return 0; } -static int rand_status(lua_State *L) +static int rand_status(lua_State* L) { - lua_pushboolean(L, RAND_status()); - return 1; + lua_pushboolean(L, RAND_status()); + return 1; } -enum { WRITE_FILE_COUNT = 1024 }; -static int rand_load(lua_State *L) -{ - const char *name = luaL_optstring(L, 1, 0); - char tmp[256]; - int n; - if (!name && !(name = RAND_file_name(tmp, sizeof tmp))) - return crypto_error(L); - n = RAND_load_file(name, WRITE_FILE_COUNT); - if (n == 0) - return crypto_error(L); - lua_pushnumber(L, n); - return 1; +enum { + WRITE_FILE_COUNT = 1024 +}; +static int rand_load(lua_State* L) +{ + const char* name = luaL_optstring(L, 1, 0); + char tmp[256]; + int n; + if (!name && !(name = RAND_file_name(tmp, sizeof tmp))) + return crypto_error(L); + n = RAND_load_file(name, WRITE_FILE_COUNT); + if (n == 0) + return crypto_error(L); + lua_pushnumber(L, n); + return 1; } -static int rand_write(lua_State *L) +static int rand_write(lua_State* L) { - const char *name = luaL_optstring(L, 1, 0); - char tmp[256]; - int n; - if (!name && !(name = RAND_file_name(tmp, sizeof tmp))) - return crypto_error(L); - n = RAND_write_file(name); - if (n == 0) - return crypto_error(L); - lua_pushnumber(L, n); - return 1; + const char* name = luaL_optstring(L, 1, 0); + char tmp[256]; + int n; + if (!name && !(name = RAND_file_name(tmp, sizeof tmp))) + return crypto_error(L); + n = RAND_write_file(name); + if (n == 0) + return crypto_error(L); + lua_pushnumber(L, n); + return 1; } -static int rand_cleanup(lua_State *L UNUSED ) +static int rand_cleanup(lua_State* L UNUSED) { - RAND_cleanup(); - return 0; + RAND_cleanup(); + return 0; } /*************** PKEY API ***************/ - -static EVP_PKEY **pkey_new(lua_State *L) -{ - EVP_PKEY **pkey = (EVP_PKEY **)lua_newuserdata(L, sizeof(EVP_PKEY*)); - luaL_getmetatable(L, LUACRYPTO_PKEYNAME); - lua_setmetatable(L, -2); - return pkey; -} - -static int pkey_generate(lua_State *L) -{ - const char *options[] = {"rsa", "dsa", NULL}; - int idx = luaL_checkoption(L, 1, NULL, options); - int key_len = luaL_checkinteger(L, 2); - EVP_PKEY **pkey = pkey_new(L); - if (idx==0) { - RSA *rsa = RSA_generate_key(key_len, RSA_F4, NULL, NULL); - if (!rsa) - return crypto_error(L); - - *pkey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(*pkey, rsa); - return 1; - } else { - DSA *dsa = DSA_generate_parameters(key_len, NULL, 0, NULL, NULL, NULL, NULL); - if (!DSA_generate_key(dsa)) - return crypto_error(L); - - *pkey = EVP_PKEY_new(); - EVP_PKEY_assign_DSA(*pkey, dsa); - return 1; - } +typedef struct pkey_context { + EVP_PKEY* pkey; +} pkey_context; + +static pkey_context* pkey_new(lua_State* L) +{ + pkey_context* c = (pkey_context*)lua_newuserdata(L, sizeof(pkey_context)); + c->pkey = NULL; + + luaL_getmetatable(L, LUACRYPTO_PKEYNAME); + lua_setmetatable(L, -2); + + return c; +} + +static int pkey_generate(lua_State* L) +{ + const char* options[] = { "rsa", "dsa", NULL }; + int idx = luaL_checkoption(L, 1, NULL, options); + int key_len = luaL_checkinteger(L, 2); + pkey_context* c = pkey_new(L); + if (idx == 0) { + RSA* rsa = RSA_new(); + BIGNUM* bne = BN_new(); + BN_set_word(bne, RSA_F4); + if (RSA_generate_key_ex(rsa, key_len, bne, NULL) != 1) { + RSA_free(rsa); + BN_free(bne); + return crypto_error(L); + } + BN_free(bne); + + c->pkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(c->pkey, rsa); + return 1; + } else { + DSA* dsa = DSA_new(); + if(DSA_generate_parameters_ex(dsa, key_len, NULL, 0, NULL, NULL, NULL) != 1) { + DSA_free(dsa); + return crypto_error(L); + } + + c->pkey = EVP_PKEY_new(); + EVP_PKEY_assign_DSA(c->pkey, dsa); + return 1; + } } -static int pkey_to_pem(lua_State *L) +static int pkey_to_pem(lua_State* L) { - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 1, LUACRYPTO_PKEYNAME); - int private = lua_isboolean(L, 2) && lua_toboolean(L, 2); - struct evp_pkey_st *pkey_st = *pkey; - int ret; - - BUF_MEM *buf; - BIO *mem = BIO_new(BIO_s_mem()); - - if (private && pkey_st->type == EVP_PKEY_DSA) - ret = PEM_write_bio_DSAPrivateKey(mem, pkey_st->pkey.dsa, NULL, NULL, 0, NULL, NULL); - else if (private && pkey_st->type == EVP_PKEY_RSA) - ret = PEM_write_bio_RSAPrivateKey(mem, pkey_st->pkey.rsa, NULL, NULL, 0, NULL, NULL); - else if (private) - ret = PEM_write_bio_PrivateKey(mem, *pkey, NULL, NULL, 0, NULL, NULL); - else - ret = PEM_write_bio_PUBKEY(mem, *pkey); + pkey_context* c = (pkey_context*)luaL_checkudata(L, 1, LUACRYPTO_PKEYNAME); + int private = lua_isboolean(L, 2) && lua_toboolean(L, 2); + int ret; - if (ret == 0) { - ret = crypto_error(L); - goto error; - } + BUF_MEM* buf; + BIO* mem = BIO_new(BIO_s_mem()); + int type = EVP_PKEY_base_id(c->pkey); + + if (private && type == EVP_PKEY_DSA) + ret = PEM_write_bio_DSAPrivateKey(mem, EVP_PKEY_get0_DSA(c->pkey), NULL, NULL, 0, NULL, NULL); + else if (private && type == EVP_PKEY_RSA) + ret = PEM_write_bio_RSAPrivateKey(mem, EVP_PKEY_get0_RSA(c->pkey), NULL, NULL, 0, NULL, NULL); + else if (private) + ret = PEM_write_bio_PrivateKey(mem, c->pkey, NULL, NULL, 0, NULL, NULL); + else + ret = PEM_write_bio_PUBKEY(mem, c->pkey); + + if (ret == 0) { + ret = crypto_error(L); + goto error; + } - BIO_get_mem_ptr(mem, &buf); - lua_pushlstring(L, buf->data, buf->length); - ret = 1; + BIO_get_mem_ptr(mem, &buf); + lua_pushlstring(L, buf->data, buf->length); + ret = 1; error: - BIO_free(mem); - return ret; + BIO_free(mem); + return ret; } -static int pkey_read(lua_State *L) +static int pkey_read(lua_State* L) { - const char *filename = luaL_checkstring(L, 1); - int readPrivate = lua_isboolean(L, 2) && lua_toboolean(L, 2); - FILE *fp = fopen(filename, "r"); - EVP_PKEY **pkey = pkey_new(L); + const char* filename = luaL_checkstring(L, 1); + int readPrivate = lua_isboolean(L, 2) && lua_toboolean(L, 2); + FILE* fp = fopen(filename, "r"); + pkey_context* c = pkey_new(L); - if (!fp) - luaL_error(L, "File not found: %s", filename); + if (!fp) + luaL_error(L, "File not found: %s", filename); - if (readPrivate) - *pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL); - else - *pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL); + if (readPrivate) + c->pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL); + else + c->pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL); - fclose(fp); + fclose(fp); - if (! *pkey) - return crypto_error(L); + if (!c->pkey) + return crypto_error(L); - return 1; + return 1; } -static int pkey_from_pem(lua_State *L) +static int pkey_from_pem(lua_State* L) { - const char *key = luaL_checkstring(L, 1); - int private = lua_isboolean(L, 2) && lua_toboolean(L, 2); - EVP_PKEY **pkey = pkey_new(L); - BIO *mem = BIO_new(BIO_s_mem()); - int ret; + const char* key = luaL_checkstring(L, 1); + int private = lua_isboolean(L, 2) && lua_toboolean(L, 2); + pkey_context* c = pkey_new(L); + BIO* mem = BIO_new(BIO_s_mem()); + int ret; - ret = BIO_puts(mem, key); - if (ret != (int)strlen(key)) { - goto error; - } + ret = BIO_puts(mem, key); + if (ret != (int)strlen(key)) { + goto error; + } - if(private) - *pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL); - else - *pkey = PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL); + if (private) + c->pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL); + else + c->pkey = PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL); - if (! *pkey) - goto error; + if (!c->pkey) + goto error; - return 1; + return 1; error: - BIO_free(mem); - return crypto_error(L); + BIO_free(mem); + return crypto_error(L); } -static int pkey_write(lua_State *L) +static int pkey_write(lua_State* L) { - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 1, LUACRYPTO_PKEYNAME); - const char *pubfn = lua_tostring(L, 2); - const char *privfn = lua_tostring(L, 3); - if (pubfn) { - FILE *fp = fopen(pubfn, "w"); - if (!fp) - luaL_error(L, "Unable to write to file: %s", pubfn); - if (!PEM_write_PUBKEY(fp, *pkey)) - return crypto_error(L); - fclose(fp); - } - if (privfn) { - FILE *fp = fopen(privfn, "w"); - if (!fp) - luaL_error(L, "Unable to write to file: %s", privfn); - if (!PEM_write_PrivateKey(fp, *pkey, NULL, NULL, 0, NULL, NULL)) - return crypto_error(L); - fclose(fp); - } - return 0; + pkey_context* c = (pkey_context*)luaL_checkudata(L, 1, LUACRYPTO_PKEYNAME); + const char* pubfn = lua_tostring(L, 2); + const char* privfn = lua_tostring(L, 3); + if (pubfn) { + FILE* fp = fopen(pubfn, "w"); + if (!fp) + luaL_error(L, "Unable to write to file: %s", pubfn); + if (!PEM_write_PUBKEY(fp, c->pkey)) + return crypto_error(L); + fclose(fp); + } + if (privfn) { + FILE* fp = fopen(privfn, "w"); + if (!fp) + luaL_error(L, "Unable to write to file: %s", privfn); + if (!PEM_write_PrivateKey(fp, c->pkey, NULL, NULL, 0, NULL, NULL)) + return crypto_error(L); + fclose(fp); + } + return 0; } -static int pkey_gc(lua_State *L) +static int pkey_gc(lua_State* L) { - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 1, LUACRYPTO_PKEYNAME); - EVP_PKEY_free(*pkey); - return 0; + pkey_context* c = (pkey_context*)luaL_checkudata(L, 1, LUACRYPTO_PKEYNAME); + if (c->pkey) { + EVP_PKEY_free(c->pkey); + } + return 0; } -static int pkey_tostring(lua_State *L) +static int pkey_tostring(lua_State* L) { - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 1, LUACRYPTO_PKEYNAME); - char buf[60]; - sprintf(buf, "%s %s %d %p", LUACRYPTO_PKEYNAME, (*pkey)->type == EVP_PKEY_DSA ? "DSA" : "RSA", EVP_PKEY_bits(*pkey), pkey); - lua_pushstring(L, buf); - return 1; + pkey_context* c = (pkey_context*)luaL_checkudata(L, 1, LUACRYPTO_PKEYNAME); + char buf[60]; + sprintf(buf, "%s %s %d %p", LUACRYPTO_PKEYNAME, EVP_PKEY_base_id(c->pkey) == EVP_PKEY_DSA ? "DSA" : "RSA", EVP_PKEY_bits(c->pkey), c); + lua_pushstring(L, buf); + return 1; } /*************** SEAL API ***************/ typedef struct seal_context { - EVP_CIPHER_CTX* ctx; - int eklen; - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char *ek; + EVP_CIPHER_CTX* ctx; + int eklen; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char* ek; } seal_context; -static seal_context *seal_pnew(lua_State* L) +static seal_context* seal_pnew(lua_State* L) { - seal_context *c = (seal_context*)lua_newuserdata(L, sizeof(seal_context)); - luaL_getmetatable(L, LUACRYPTO_SEALNAME); - lua_setmetatable(L, -2); + seal_context* c = (seal_context*)lua_newuserdata(L, sizeof(seal_context)); + luaL_getmetatable(L, LUACRYPTO_SEALNAME); + lua_setmetatable(L, -2); - memset(c, 0, sizeof(seal_context)); - c->ctx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); + memset(c, 0, sizeof(seal_context)); + c->ctx = EVP_CIPHER_CTX_new(); - return c; + return c; } static int seal_gc(lua_State* L) { - seal_context *c = (seal_context*)luaL_checkudata(L, 1, LUACRYPTO_SEALNAME); - EVP_CIPHER_CTX_cleanup(c->ctx); - free(c->ctx); - if (c->ek != NULL) { - free(c->ek); - } - return 0; + seal_context* c = (seal_context*)luaL_checkudata(L, 1, LUACRYPTO_SEALNAME); + EVP_CIPHER_CTX_free(c->ctx); + if (c->ek != NULL) { + free(c->ek); + } + return 0; } static int seal_tostring(lua_State* L) { - seal_context *c = (seal_context*)luaL_checkudata(L, 1, LUACRYPTO_SEALNAME); - char s[64]; - sprintf(s, "%s %p %s", LUACRYPTO_SEALNAME, (void *)c, EVP_CIPHER_name(c->ctx->cipher)); - lua_pushstring(L, s); - return 1; + seal_context* c = (seal_context*)luaL_checkudata(L, 1, LUACRYPTO_SEALNAME); + char s[64]; + sprintf(s, "%s %p %s", LUACRYPTO_SEALNAME, (void*)c, EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(c->ctx))); + lua_pushstring(L, s); + return 1; } static int seal_fnew(lua_State* L) { - const char *cipher_type = luaL_checkstring(L, 1); - const EVP_CIPHER *cipher = EVP_get_cipherbyname(cipher_type); - int npubk = 1; - EVP_PKEY **pkey; - seal_context *seal_ctx; + const char* cipher_type = luaL_checkstring(L, 1); + const EVP_CIPHER* cipher = EVP_get_cipherbyname(cipher_type); + int npubk = 1; + pkey_context* pkey_ctx; + seal_context* seal_ctx; - if (cipher == NULL) - return luaL_argerror(L, 1, "invalid encrypt cipher"); + if (cipher == NULL) + return luaL_argerror(L, 1, "invalid encrypt cipher"); - pkey = (EVP_PKEY **)luaL_checkudata(L, 2, LUACRYPTO_PKEYNAME); + pkey_ctx = (pkey_context*)luaL_checkudata(L, 2, LUACRYPTO_PKEYNAME); - seal_ctx = seal_pnew(L); - EVP_CIPHER_CTX_init(seal_ctx->ctx); + seal_ctx = seal_pnew(L); + EVP_CIPHER_CTX_init(seal_ctx->ctx); - seal_ctx->ek = (unsigned char*)malloc((size_t)EVP_PKEY_size(*pkey) * (size_t)npubk); + seal_ctx->ek = (unsigned char*)malloc((size_t)EVP_PKEY_size(pkey_ctx->pkey) * (size_t)npubk); - if (!EVP_SealInit(seal_ctx->ctx, cipher, &seal_ctx->ek, &seal_ctx->eklen, - seal_ctx->iv, pkey, npubk)) { - free(seal_ctx->ek); - seal_ctx->ek = NULL; - return crypto_error(L); - } + if (!EVP_SealInit(seal_ctx->ctx, cipher, &seal_ctx->ek, &seal_ctx->eklen, + seal_ctx->iv, &pkey_ctx->pkey, npubk)) { + free(seal_ctx->ek); + seal_ctx->ek = NULL; + return crypto_error(L); + } - return 1; + return 1; } static int seal_update(lua_State* L) { - seal_context *c = (seal_context*)luaL_checkudata(L, 1, LUACRYPTO_SEALNAME); - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 2, &input_len); - int output_len = 0; + seal_context* c = (seal_context*)luaL_checkudata(L, 1, LUACRYPTO_SEALNAME); + size_t input_len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 2, &input_len); + int output_len = 0; - unsigned char *temp = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(c->ctx)); - EVP_SealUpdate(c->ctx, temp, &output_len, input, (int)input_len); - lua_pushlstring(L, (char*) temp, (size_t)output_len); - free(temp); + unsigned char* temp = (unsigned char*)malloc(input_len + (size_t)EVP_CIPHER_CTX_block_size(c->ctx)); + EVP_SealUpdate(c->ctx, temp, &output_len, input, (int)input_len); + lua_pushlstring(L, (char*)temp, (size_t)output_len); + free(temp); - return 1; + return 1; } static int seal_final(lua_State* L) { - seal_context *c = (seal_context*)luaL_checkudata(L, 1, LUACRYPTO_SEALNAME); - int output_len = 0; - unsigned char buffer[EVP_MAX_BLOCK_LENGTH]; + seal_context* c = (seal_context*)luaL_checkudata(L, 1, LUACRYPTO_SEALNAME); + int output_len = 0; + unsigned char buffer[EVP_MAX_BLOCK_LENGTH]; - EVP_SealFinal(c->ctx, buffer, &output_len); - lua_pushlstring(L, (char*) buffer, (size_t)output_len); + EVP_SealFinal(c->ctx, buffer, &output_len); + lua_pushlstring(L, (char*)buffer, (size_t)output_len); - lua_pushlstring(L, (const char*)c->ek, (size_t)c->eklen); - lua_pushlstring(L, (const char*)c->iv, (size_t)EVP_CIPHER_iv_length(c->ctx->cipher)); + lua_pushlstring(L, (const char*)c->ek, (size_t)c->eklen); + lua_pushlstring(L, (const char*)c->iv, (size_t)EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(c->ctx))); - free(c->ek); - c->ek = NULL; + free(c->ek); + c->ek = NULL; - return 3; + return 3; } static int seal_fseal(lua_State* L) { - /* parameter 1 is the 'crypto.seal' table */ - const char *cipher_type = luaL_checkstring(L, 2); - const EVP_CIPHER *cipher = EVP_get_cipherbyname(cipher_type); - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, 4, LUACRYPTO_PKEYNAME); - int npubk = 1; - int eklen; - unsigned char iv[EVP_MAX_IV_LENGTH]; - const unsigned char* message; - int message_length; - unsigned char *ek; - int block_size; - EVP_CIPHER_CTX ctx; - luaL_Buffer buffer; - int output_length; - char *temp; - int sz; - - if (cipher == NULL) { - luaL_argerror(L, 1, "invalid encrypt cipher"); - return 0; - } - - message = (const unsigned char*)luaL_checkstring(L, 3); - message_length = (int)lua_rawlen(L, 3); + /* parameter 1 is the 'crypto.seal' table */ + const char* cipher_type = luaL_checkstring(L, 2); + const EVP_CIPHER* cipher = EVP_get_cipherbyname(cipher_type); + pkey_context* pkey_ctx = (pkey_context*)luaL_checkudata(L, 4, LUACRYPTO_PKEYNAME); + int npubk = 1; + int eklen; + unsigned char iv[EVP_MAX_IV_LENGTH]; + const unsigned char* message; + int message_length; + unsigned char* ek; + int block_size; + EVP_CIPHER_CTX* ctx; + luaL_Buffer buffer; + int output_length; + char* temp; + int sz; + if (cipher == NULL) { + luaL_argerror(L, 1, "invalid encrypt cipher"); + return 0; + } - ek = (unsigned char*)malloc((size_t)EVP_PKEY_size(*pkey) * (size_t)npubk); + message = (const unsigned char*)luaL_checkstring(L, 3); + message_length = (int)lua_rawlen(L, 3); - EVP_CIPHER_CTX_init(&ctx); + ek = (unsigned char*)malloc((size_t)EVP_PKEY_size(pkey_ctx->pkey) * (size_t)npubk); - if (!EVP_SealInit(&ctx, cipher, &ek, &eklen, iv, pkey, npubk)) { - free(ek); - EVP_CIPHER_CTX_cleanup(&ctx); - return crypto_error(L); - } + ctx = EVP_CIPHER_CTX_new(); + if (!EVP_SealInit(ctx, cipher, &ek, &eklen, iv, &pkey_ctx->pkey, npubk)) { + free(ek); + EVP_CIPHER_CTX_free(ctx); + return crypto_error(L); + } - luaL_buffinit(L, &buffer); + luaL_buffinit(L, &buffer); - block_size = EVP_CIPHER_block_size(cipher); + block_size = EVP_CIPHER_block_size(cipher); - while (message_length > 0) { - temp = luaL_prepbuffer(&buffer); - sz = MIN(LUAL_BUFFERSIZE - block_size - 1, message_length); + while (message_length > 0) { + temp = luaL_prepbuffer(&buffer); + sz = MIN(LUAL_BUFFERSIZE - block_size - 1, message_length); - if(!EVP_SealUpdate(&ctx, (unsigned char*)temp, &output_length, message, sz)) { - free(ek); - EVP_CIPHER_CTX_cleanup(&ctx); - return crypto_error(L); + if (!EVP_SealUpdate(ctx, (unsigned char*)temp, &output_length, message, sz)) { + free(ek); + EVP_CIPHER_CTX_free(ctx); + return crypto_error(L); + } + message += sz; + message_length -= sz; + luaL_addsize(&buffer, output_length); } - message += sz; - message_length -= sz; - luaL_addsize(&buffer, output_length); - } - temp = luaL_prepbuffer(&buffer); - if (!EVP_SealFinal(&ctx, (unsigned char*)temp, &output_length)) { - free(ek); - EVP_CIPHER_CTX_cleanup(&ctx); - return crypto_error(L); - } + temp = luaL_prepbuffer(&buffer); + if (!EVP_SealFinal(ctx, (unsigned char*)temp, &output_length)) { + free(ek); + EVP_CIPHER_CTX_free(ctx); + return crypto_error(L); + } - luaL_addsize(&buffer, output_length); + luaL_addsize(&buffer, output_length); - luaL_pushresult(&buffer); - lua_pushlstring(L, (const char*)ek, (size_t)eklen); - lua_pushlstring(L, (const char*)iv, (size_t)EVP_CIPHER_iv_length(cipher)); + luaL_pushresult(&buffer); + lua_pushlstring(L, (const char*)ek, (size_t)eklen); + lua_pushlstring(L, (const char*)iv, (size_t)EVP_CIPHER_iv_length(cipher)); - EVP_CIPHER_CTX_cleanup(&ctx); - free(ek); + EVP_CIPHER_CTX_free(ctx); + free(ek); - return 3; + return 3; } /*************** OPEN API ***************/ typedef struct open_context { - EVP_CIPHER_CTX* ctx; - EVP_CIPHER* cipher; - int pkey_ref; + EVP_CIPHER_CTX* ctx; + EVP_CIPHER* cipher; + int pkey_ref; } open_context; -static open_context *open_pnew(lua_State* L) +static open_context* open_pnew(lua_State* L) { - open_context *c = (open_context*)lua_newuserdata(L, sizeof(open_context)); - luaL_getmetatable(L, LUACRYPTO_OPENNAME); - lua_setmetatable(L, -2); + open_context* c = (open_context*)lua_newuserdata(L, sizeof(open_context)); + luaL_getmetatable(L, LUACRYPTO_OPENNAME); + lua_setmetatable(L, -2); - memset(c, 0, sizeof(open_context)); - c->ctx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); - c->pkey_ref = LUA_NOREF; + memset(c, 0, sizeof(open_context)); + c->ctx = EVP_CIPHER_CTX_new(); + c->pkey_ref = LUA_NOREF; - return c; + return c; } static int open_gc(lua_State* L) { - open_context *c = luaL_checkudata(L, 1, LUACRYPTO_OPENNAME); - EVP_CIPHER_CTX_cleanup(c->ctx); - free(c->ctx); - if (c->pkey_ref != LUA_NOREF) { - luaL_unref(L, LUA_REGISTRYINDEX, c->pkey_ref); - } - return 0; + open_context* c = luaL_checkudata(L, 1, LUACRYPTO_OPENNAME); + EVP_CIPHER_CTX_free(c->ctx); + + if (c->pkey_ref != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, c->pkey_ref); + } + return 0; } static int open_tostring(lua_State* L) { - open_context *c = (open_context*)luaL_checkudata(L, 1, LUACRYPTO_OPENNAME); - EVP_PKEY **pkey = (EVP_PKEY **)luaL_checkudata(L, -1, LUACRYPTO_PKEYNAME); - char s[64]; + open_context* c = (open_context*)luaL_checkudata(L, 1, LUACRYPTO_OPENNAME); + pkey_context* pkey_ctx = (pkey_context*)luaL_checkudata(L, -1, LUACRYPTO_PKEYNAME); + char s[64]; - lua_rawgeti(L, LUA_REGISTRYINDEX, c->pkey_ref); - sprintf(s, "%s %p %s %s %d %p", LUACRYPTO_OPENNAME, (void *)c, EVP_CIPHER_name(c->cipher), - (*pkey)->type == EVP_PKEY_DSA ? "DSA" : "RSA", EVP_PKEY_bits(*pkey), pkey); + lua_rawgeti(L, LUA_REGISTRYINDEX, c->pkey_ref); + sprintf(s, "%s %p %s %s %d %p", LUACRYPTO_OPENNAME, (void*)c, EVP_CIPHER_name(c->cipher), + EVP_PKEY_base_id(pkey_ctx->pkey) == EVP_PKEY_DSA ? "DSA" : "RSA", EVP_PKEY_bits(pkey_ctx->pkey), pkey_ctx->pkey); - lua_pop(L, 1); - lua_pushstring(L, s); - return 1; + lua_pop(L, 1); + lua_pushstring(L, s); + return 1; } static int open_fnew(lua_State* L) { - const char *type_name = luaL_checkstring(L, 1); - const EVP_CIPHER *cipher = EVP_get_cipherbyname(type_name); - const unsigned char* encrypted_key; - const unsigned char* iv; - EVP_PKEY **pkey; - open_context *open_ctx; + const char* type_name = luaL_checkstring(L, 1); + const EVP_CIPHER* cipher = EVP_get_cipherbyname(type_name); + size_t encrypted_key_len, iv_len; + const unsigned char *encrypted_key, *iv; + pkey_context* pkey_ctx = (pkey_context*)luaL_checkudata(L, 2, LUACRYPTO_PKEYNAME); + open_context* open_ctx; - if (cipher == NULL) - return luaL_argerror(L, 1, "invalid decrypt cipher"); + if (cipher == NULL) + return luaL_argerror(L, 1, "invalid decrypt cipher"); - pkey = (EVP_PKEY **)luaL_checkudata(L, 2, LUACRYPTO_PKEYNAME); + /* checks for the encrypted key */ + encrypted_key = (const unsigned char*)luaL_checklstring(L, 3, &encrypted_key_len); + /* checks for the initialization vector */ + iv = (const unsigned char*)luaL_checklstring(L, 4, &iv_len); - /* checks for the encrypted key */ - encrypted_key = (const unsigned char*)luaL_checkstring(L, 3); - /* checks for the initialization vector */ - iv = (const unsigned char*)luaL_checkstring(L, 4); + if ((size_t)EVP_CIPHER_iv_length(cipher) != iv_len) + return luaL_argerror(L, 4, "invalid iv length"); - if ((size_t)EVP_CIPHER_iv_length(cipher) != lua_rawlen(L, 4)) - return luaL_argerror(L, 4, "invalid iv length"); + open_ctx = open_pnew(L); + open_ctx->cipher = (EVP_CIPHER*)cipher; - open_ctx = open_pnew(L); - EVP_CIPHER_CTX_init(open_ctx->ctx); - open_ctx->cipher = (EVP_CIPHER*)cipher; + if (!EVP_OpenInit(open_ctx->ctx, open_ctx->cipher, encrypted_key, + (int)encrypted_key_len, iv, pkey_ctx->pkey)) + return crypto_error(L); - if (!EVP_OpenInit(open_ctx->ctx, open_ctx->cipher, encrypted_key, - (int)lua_rawlen(L, 3), iv, *pkey)) - return crypto_error(L); + lua_pushvalue(L, 2); + open_ctx->pkey_ref = luaL_ref(L, LUA_REGISTRYINDEX); - lua_pushvalue(L, 2); - open_ctx->pkey_ref = luaL_ref(L, LUA_REGISTRYINDEX); - - return 1; + return 1; } static int open_update(lua_State* L) { - open_context *c = (open_context*)luaL_checkudata(L, 1, LUACRYPTO_OPENNAME); - size_t input_len = 0; - const unsigned char *input = (unsigned char *) luaL_checklstring(L, 2, &input_len); - - luaL_Buffer buffer; - luaL_buffinit(L, &buffer); - - while (input_len > 0) { - int output_length; - unsigned char* temp = (unsigned char*)luaL_prepbuffer(&buffer); - size_t sz = MIN(LUAL_BUFFERSIZE - 1, input_len); - if(!EVP_OpenUpdate(c->ctx, temp, &output_length, input, (int)sz)) { - return crypto_error(L); + open_context* c = (open_context*)luaL_checkudata(L, 1, LUACRYPTO_OPENNAME); + size_t input_len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 2, &input_len); + + luaL_Buffer buffer; + luaL_buffinit(L, &buffer); + + while (input_len > 0) { + int output_length; + unsigned char* temp = (unsigned char*)luaL_prepbuffer(&buffer); + size_t sz = MIN(LUAL_BUFFERSIZE - 1, input_len); + if (!EVP_OpenUpdate(c->ctx, temp, &output_length, input, (int)sz)) { + return crypto_error(L); + } + + input += sz; + input_len -= sz; + luaL_addsize(&buffer, output_length); } - input += sz; - input_len -= sz; - luaL_addsize(&buffer, output_length); - } - - luaL_pushresult(&buffer); - return 1; + luaL_pushresult(&buffer); + return 1; } static int open_final(lua_State* L) { - open_context *c = (open_context*)luaL_checkudata(L, 1, LUACRYPTO_OPENNAME); - int output_len = 0; - unsigned char buffer[EVP_MAX_BLOCK_LENGTH]; + open_context* c = (open_context*)luaL_checkudata(L, 1, LUACRYPTO_OPENNAME); + int output_len = 0; + unsigned char buffer[EVP_MAX_BLOCK_LENGTH]; - EVP_OpenFinal(c->ctx, buffer, &output_len); - lua_pushlstring(L, (char*) buffer, (size_t)output_len); + EVP_OpenFinal(c->ctx, buffer, &output_len); + lua_pushlstring(L, (char*)buffer, (size_t)output_len); - return 1; + return 1; } static int open_fopen(lua_State* L) { - /* parameter 1 is the 'crypto.open' table */ - const char *type_name = luaL_checkstring(L, 2); - const EVP_CIPHER *cipher = EVP_get_cipherbyname(type_name); - unsigned char* data; - int data_length; - EVP_PKEY **pkey; - const unsigned char* encrypted_key; - const unsigned char* iv; - EVP_CIPHER_CTX ctx; - int eklen; - int output_length; - unsigned char* temp; - size_t sz; - luaL_Buffer buffer; - - if (cipher == NULL) { - luaL_argerror(L, 1, "invalid decrypt cipher"); - return 0; - } + /* parameter 1 is the 'crypto.open' table */ + const char* type_name = luaL_checkstring(L, 2); + const EVP_CIPHER* cipher = EVP_get_cipherbyname(type_name); + pkey_context* pkey_ctx = (pkey_context*)luaL_checkudata(L, 4, LUACRYPTO_PKEYNAME); + size_t data_len, encrypted_key_len, iv_len; + const unsigned char *data, *encrypted_key, *iv; + EVP_CIPHER_CTX* ctx; + int output_length; + unsigned char* temp; + size_t sz; + luaL_Buffer buffer; - data = (unsigned char*)luaL_checkstring(L, 3); - data_length = (int)lua_rawlen(L, 3); + if (cipher == NULL) { + luaL_argerror(L, 1, "invalid decrypt cipher"); + return 0; + } - pkey = (EVP_PKEY **)luaL_checkudata(L, 4, LUACRYPTO_PKEYNAME); + data = (const unsigned char*)luaL_checklstring(L, 3, &data_len); + encrypted_key = (const unsigned char*)luaL_checklstring(L, 5, &encrypted_key_len); + iv = (const unsigned char*)luaL_checklstring(L, 6, &iv_len); - encrypted_key = (const unsigned char*)luaL_checkstring(L, 5); - iv = (const unsigned char*)luaL_checkstring(L, 6); + if ((size_t)EVP_CIPHER_iv_length(cipher) != iv_len) { + luaL_argerror(L, 6, "invalid iv length"); + return 0; + } - if ((size_t)EVP_CIPHER_iv_length(cipher) != lua_rawlen(L, 6)) { - luaL_argerror(L, 6, "invalid iv length"); - return 0; - } + ctx = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_init(&ctx); + if (!EVP_OpenInit(ctx, cipher, encrypted_key, encrypted_key_len, iv, pkey_ctx->pkey)) { + EVP_CIPHER_CTX_free(ctx); + return crypto_error(L); + } - eklen = (int)lua_rawlen(L, 5); + luaL_buffinit(L, &buffer); - if (!EVP_OpenInit(&ctx, cipher, encrypted_key, eklen, iv, *pkey)) { - EVP_CIPHER_CTX_cleanup(&ctx); - return crypto_error(L); - } + while (data_len > 0) { + temp = (unsigned char*)luaL_prepbuffer(&buffer); + sz = MIN(LUAL_BUFFERSIZE - 1U, data_len); + if (!EVP_OpenUpdate(ctx, temp, &output_length, data, (int)sz)) { + EVP_CIPHER_CTX_free(ctx); + return crypto_error(L); + } - luaL_buffinit(L, &buffer); + data += sz; + data_len -= sz; + luaL_addsize(&buffer, output_length); + } - while (data_length > 0) { temp = (unsigned char*)luaL_prepbuffer(&buffer); - sz = MIN(LUAL_BUFFERSIZE - 1U, (size_t)data_length); - if(!EVP_OpenUpdate(&ctx, temp, &output_length, data, (int)sz)) { - EVP_CIPHER_CTX_cleanup(&ctx); - return crypto_error(L); + if (!EVP_OpenFinal(ctx, temp, &output_length)) { + EVP_CIPHER_CTX_free(ctx); + return crypto_error(L); } - - data += sz; - data_length -= (int)sz; luaL_addsize(&buffer, output_length); - } - temp = (unsigned char*)luaL_prepbuffer(&buffer); - if (!EVP_OpenFinal(&ctx, temp, &output_length)) { - EVP_CIPHER_CTX_cleanup(&ctx); - return crypto_error(L); - } - luaL_addsize(&buffer, output_length); - - luaL_pushresult(&buffer); - EVP_CIPHER_CTX_cleanup(&ctx); - return 1; + luaL_pushresult(&buffer); + EVP_CIPHER_CTX_free(ctx); + return 1; } /*************** CORE API ***************/ -static void list_callback(const OBJ_NAME *obj,void *arg) +static void list_callback(const OBJ_NAME* obj, void* arg) { - lua_State *L = (lua_State*) arg; - int idx = (int)lua_rawlen(L, -1); - lua_pushstring(L, obj->name); - lua_rawseti(L, -2, idx + 1); + lua_State* L = (lua_State*)arg; + int idx = (int)lua_rawlen(L, -1); + lua_pushstring(L, obj->name); + lua_rawseti(L, -2, idx + 1); } -static int luacrypto_list(lua_State *L) +static int luacrypto_list(lua_State* L) { - int options[] = {OBJ_NAME_TYPE_CIPHER_METH, OBJ_NAME_TYPE_MD_METH}; - const char * names[] = {"ciphers", "digests", NULL}; - int idx = luaL_checkoption (L, 1, NULL, names); - lua_createtable(L, 0, 0); - OBJ_NAME_do_all_sorted(options[idx], list_callback, L); - return 1; + int options[] = { OBJ_NAME_TYPE_CIPHER_METH, OBJ_NAME_TYPE_MD_METH }; + const char* names[] = { "ciphers", "digests", NULL }; + int idx = luaL_checkoption(L, 1, NULL, names); + lua_createtable(L, 0, 0); + OBJ_NAME_do_all_sorted(options[idx], list_callback, L); + return 1; } -static int luacrypto_hex(lua_State *L) +static int luacrypto_hex(lua_State* L) { - size_t i, len = 0; - const unsigned char * input = (unsigned char *) luaL_checklstring(L, 1, &len); - char * hex = (char*)calloc(sizeof(char), len*2 + 1); - for (i = 0; i < len; i++) { - sprintf(hex + 2*i, "%02x", input[i]); - } - lua_pushlstring(L, hex, len*2); - free(hex); - return 1; + size_t i, len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 1, &len); + char* hex = (char*)calloc(sizeof(char), len * 2 + 1); + for (i = 0; i < len; i++) { + sprintf(hex + 2 * i, "%02x", input[i]); + } + lua_pushlstring(L, hex, len * 2); + free(hex); + return 1; } -static int luacrypto_base64_encode(lua_State *L) -{ - BUF_MEM *buf; - size_t len = 0; - const unsigned char * input = (unsigned char *) luaL_checklstring(L, 1, &len); - BIO *b64 = BIO_new(BIO_f_base64()); - BIO *mem = BIO_new(BIO_s_mem()); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - mem = BIO_push(b64, mem); - BIO_write(mem, input, len); - BIO_flush(mem); - BIO_get_mem_ptr(mem, &buf); - lua_pushlstring(L, buf->data, buf->length); - BIO_free_all(mem); - return 1; +static int luacrypto_base64_encode(lua_State* L) +{ + BUF_MEM* buf; + size_t len = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 1, &len); + BIO* b64 = BIO_new(BIO_f_base64()); + BIO* mem = BIO_new(BIO_s_mem()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + mem = BIO_push(b64, mem); + BIO_write(mem, input, len); + BIO_flush(mem); + BIO_get_mem_ptr(mem, &buf); + lua_pushlstring(L, buf->data, buf->length); + BIO_free_all(mem); + return 1; } -static int luacrypto_base64_decode(lua_State *L) +static int luacrypto_base64_decode(lua_State* L) { - size_t len, out = 0; - const unsigned char * input = (unsigned char *) luaL_checklstring(L, 1, &len); - char *buffer = (char*)malloc(len); + size_t len, out = 0; + const unsigned char* input = (unsigned char*)luaL_checklstring(L, 1, &len); + char* buffer = (char*)malloc(len); - BIO *b64 = BIO_new(BIO_f_base64()); - BIO *mem = BIO_new_mem_buf((void*)input, len); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - mem = BIO_push(b64, mem); - out = BIO_read(mem, buffer, len); - lua_pushlstring(L, buffer, out); - free(buffer); - BIO_free_all(mem); - return 1; + BIO* b64 = BIO_new(BIO_f_base64()); + BIO* mem = BIO_new_mem_buf((void*)input, len); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + mem = BIO_push(b64, mem); + out = BIO_read(mem, buffer, len); + lua_pushlstring(L, buffer, out); + free(buffer); + BIO_free_all(mem); + return 1; } /*************** x509 API ***************/ -static X509 *x509__load_cert(BIO *cert) +static X509* x509__load_cert(BIO* cert) { - X509 *x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); + X509* x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); return x; } -static X509 *x509__x509_from_string(const char *pem) +static X509* x509__x509_from_string(const char* pem) { - BIO *mem = BIO_new(BIO_s_mem()); - X509 *cert; - int ret; + BIO* mem = BIO_new(BIO_s_mem()); + X509* cert; + int ret; - if (!mem) - return NULL; + if (!mem) + return NULL; - ret = BIO_puts(mem, pem); - if (ret != (int)strlen(pem)) - goto error; + ret = BIO_puts(mem, pem); + if (ret != (int)strlen(pem)) + goto error; - cert = x509__load_cert(mem); - if (cert == NULL) - goto error; + cert = x509__load_cert(mem); + if (cert == NULL) + goto error; - return cert; + return cert; error: BIO_free(mem); @@ -1573,362 +1617,360 @@ static X509 *x509__x509_from_string(const char *pem) } struct x509_cert { - X509 *cert; + X509* cert; }; -static struct x509_cert *x509_cert__get(lua_State *L) +static struct x509_cert* x509_cert__get(lua_State* L) { - return luaL_checkudata(L, 1, LUACRYPTO_X509_CERT_NAME); + return luaL_checkudata(L, 1, LUACRYPTO_X509_CERT_NAME); } -static int x509_cert_fnew(lua_State *L) +static int x509_cert_fnew(lua_State* L) { - struct x509_cert *x = lua_newuserdata(L, sizeof(struct x509_cert)); + struct x509_cert* x = lua_newuserdata(L, sizeof(struct x509_cert)); - x->cert = NULL; + x->cert = NULL; - luaL_getmetatable(L, LUACRYPTO_X509_CERT_NAME); - lua_setmetatable(L, -2); + luaL_getmetatable(L, LUACRYPTO_X509_CERT_NAME); + lua_setmetatable(L, -2); - return 1; + return 1; } -static int x509_cert_fx509_cert(lua_State *L) +static int x509_cert_fx509_cert(lua_State* L) { - return x509_cert_fnew(L); + return x509_cert_fnew(L); } -static int x509_cert_gc(lua_State *L) +static int x509_cert_gc(lua_State* L) { - struct x509_cert *c = x509_cert__get(L); - X509_free(c->cert); - return 0; + struct x509_cert* c = x509_cert__get(L); + X509_free(c->cert); + return 0; } -static int x509_cert_from_pem(lua_State *L) +static int x509_cert_from_pem(lua_State* L) { - struct x509_cert *x = x509_cert__get(L); - const char *pem = luaL_checkstring(L, 2); + struct x509_cert* x = x509_cert__get(L); + const char* pem = luaL_checkstring(L, 2); - if (x->cert != NULL) - X509_free(x->cert); + if (x->cert != NULL) + X509_free(x->cert); - x->cert = x509__x509_from_string(pem); - if (!x->cert) - return crypto_error(L); + x->cert = x509__x509_from_string(pem); + if (!x->cert) + return crypto_error(L); - return 1; + return 1; } -static int x509_cert_pubkey(lua_State *L) +static int x509_cert_pubkey(lua_State* L) { - struct x509_cert *x = x509_cert__get(L); - EVP_PKEY *pkey = X509_get_pubkey(x->cert); + struct x509_cert* x = x509_cert__get(L); + EVP_PKEY* pkey = X509_get_pubkey(x->cert); - if (!pkey) - return crypto_error(L); + if (!pkey) + return crypto_error(L); - EVP_PKEY **out_pkey = pkey_new(L); - *out_pkey = pkey; + pkey_context* pkey_ctx = pkey_new(L); + pkey_ctx->pkey = pkey; - return 1; + return 1; } struct x509_ca { - X509_STORE *store; - STACK_OF(X509) *stack; + X509_STORE* store; + STACK_OF(X509) * stack; }; -static int x509_ca_fnew(lua_State *L) +static int x509_ca_fnew(lua_State* L) { - struct x509_ca *x = lua_newuserdata(L, sizeof(struct x509_ca)); + struct x509_ca* x = lua_newuserdata(L, sizeof(struct x509_ca)); - x->store = X509_STORE_new(); - x->stack = sk_X509_new_null(); + x->store = X509_STORE_new(); + x->stack = sk_X509_new_null(); - luaL_getmetatable(L, LUACRYPTO_X509_CA_NAME); - lua_setmetatable(L, -2); + luaL_getmetatable(L, LUACRYPTO_X509_CA_NAME); + lua_setmetatable(L, -2); - return 1; + return 1; } -static int x509_ca_fx509_ca(lua_State *L) +static int x509_ca_fx509_ca(lua_State* L) { - return x509_ca_fnew(L); + return x509_ca_fnew(L); } -static struct x509_ca *x509_ca__get(lua_State *L) +static struct x509_ca* x509_ca__get(lua_State* L) { - return luaL_checkudata(L, 1, LUACRYPTO_X509_CA_NAME); + return luaL_checkudata(L, 1, LUACRYPTO_X509_CA_NAME); } -static int x509_ca_gc(lua_State *L) +static int x509_ca_gc(lua_State* L) { - struct x509_ca *c = x509_ca__get(L); - sk_X509_pop_free(c->stack, X509_free); - X509_STORE_free(c->store); - return 0; + struct x509_ca* c = x509_ca__get(L); + sk_X509_pop_free(c->stack, X509_free); + X509_STORE_free(c->store); + return 0; } /* verify a cert is signed by the ca */ -static int x509_ca__verify(struct x509_ca *x, X509 *cert) +static int x509_ca__verify(struct x509_ca* x, X509* cert) { - X509_STORE_CTX *csc; - int ret = -1; + X509_STORE_CTX* csc; + int ret = -1; - csc = X509_STORE_CTX_new(); - if (csc == NULL) - return ret; + csc = X509_STORE_CTX_new(); + if (csc == NULL) + return ret; - X509_STORE_set_flags(x->store, 0); - if(!X509_STORE_CTX_init(csc, x->store, cert, 0)) - goto out; + X509_STORE_set_flags(x->store, 0); + if (!X509_STORE_CTX_init(csc, x->store, cert, 0)) + goto out; - X509_STORE_CTX_trusted_stack(csc, x->stack); - ret = X509_verify_cert(csc); + X509_STORE_CTX_trusted_stack(csc, x->stack); + ret = X509_verify_cert(csc); out: - X509_STORE_CTX_free(csc); - return ret; + X509_STORE_CTX_free(csc); + return ret; } - /* verify a cert is signed by the ca */ -static int x509_ca_verify_pem(lua_State *L) +static int x509_ca_verify_pem(lua_State* L) { - struct x509_ca *x = x509_ca__get(L); - const char *pem = luaL_checkstring(L, 2); - X509 *cert; - int ret; + struct x509_ca* x = x509_ca__get(L); + const char* pem = luaL_checkstring(L, 2); + X509* cert; + int ret; - cert = x509__x509_from_string(pem); - if (!cert) - return crypto_error(L); + cert = x509__x509_from_string(pem); + if (!cert) + return crypto_error(L); - ret = x509_ca__verify(x, cert); - X509_free(cert); - if (ret < 0) - return crypto_error(L); + ret = x509_ca__verify(x, cert); + X509_free(cert); + if (ret < 0) + return crypto_error(L); - lua_pushboolean(L, ret); + lua_pushboolean(L, ret); - return 1; + return 1; } -static int x509_ca_add_pem(lua_State *L) +static int x509_ca_add_pem(lua_State* L) { - struct x509_ca *x = x509_ca__get(L); - const char *pem = luaL_checkstring(L, 2); - X509 *cert; + struct x509_ca* x = x509_ca__get(L); + const char* pem = luaL_checkstring(L, 2); + X509* cert; - cert = x509__x509_from_string(pem); - if (!cert) - return crypto_error(L); + cert = x509__x509_from_string(pem); + if (!cert) + return crypto_error(L); - sk_X509_push(x->stack, cert); + sk_X509_push(x->stack, cert); - lua_pushboolean(L, 1); + lua_pushboolean(L, 1); - return 1; + return 1; } /* ** Create a metatable and keep stack balance when leave */ -LUACRYPTO_API void luacrypto_createmeta (lua_State *L, const char *name, const luaL_Reg *methods) -{ - if (!luaL_newmetatable (L, name)) - return; - - /* define metamethods */ - lua_pushvalue (L, -1); // push metatable - lua_setfield(L, -2, "__index"); // metatable.__index = metatable - lua_pushliteral (L, LUACRYPTO_PREFIX"you're not allowed to get this metatable"); - lua_setfield(L, -2, "__metatable"); - luaL_setfuncs(L, methods, 0); //add methods to new metatable - lua_pop(L,1); // pop new metatable -} - - - -static void create_call_table(lua_State *L, const char *name, lua_CFunction creator, lua_CFunction starter) -{ - lua_createtable(L, 0, 1); - lua_pushcfunction(L, creator); - lua_setfield(L, -2, "new"); - /* create metatable for call */ - lua_createtable(L, 0, 1); - lua_pushcfunction(L, starter); - lua_setfield(L, -2, "__call"); - lua_setmetatable(L, -2); - lua_setfield(L, -2, name); -} - -#define EVP_METHODS(name) \ - struct luaL_Reg name##_methods[] = { \ - { "__tostring", name##_tostring }, \ - { "__gc", name##_gc }, \ - { "final", name##_final }, \ - { "tostring", name##_tostring }, \ - { "update", name##_update }, \ - {NULL, NULL}, \ - } +LUACRYPTO_API void luacrypto_createmeta(lua_State* L, const char* name, const luaL_Reg* methods) +{ + if (!luaL_newmetatable(L, name)) + return; + + /* define metamethods */ + lua_pushvalue(L, -1); // push metatable + lua_setfield(L, -2, "__index"); // metatable.__index = metatable + lua_pushliteral(L, LUACRYPTO_PREFIX "you're not allowed to get this metatable"); + lua_setfield(L, -2, "__metatable"); + luaL_setfuncs(L, methods, 0); //add methods to new metatable + lua_pop(L, 1); // pop new metatable +} + +static void create_call_table(lua_State* L, const char* name, lua_CFunction creator, lua_CFunction starter) +{ + lua_createtable(L, 0, 1); + lua_pushcfunction(L, creator); + lua_setfield(L, -2, "new"); + /* create metatable for call */ + lua_createtable(L, 0, 1); + lua_pushcfunction(L, starter); + lua_setfield(L, -2, "__call"); + lua_setmetatable(L, -2); + lua_setfield(L, -2, name); +} + +#define EVP_METHODS(name) \ + struct luaL_Reg name##_methods[] = { \ + { "__tostring", name##_tostring }, \ + { "__gc", name##_gc }, \ + { "final", name##_final }, \ + { "tostring", name##_tostring }, \ + { "update", name##_update }, \ + { NULL, NULL }, \ + } /* ** Create metatables for each class of object. */ -static void create_metatables (lua_State *L) -{ - struct luaL_Reg digest_methods[] = { - { "__tostring", digest_tostring }, - { "__gc", digest_gc }, - { "final", digest_final }, - { "tostring", digest_tostring }, - { "update", digest_update }, - { "reset", digest_reset }, - { "clone", digest_clone }, - {NULL, NULL} - }; - EVP_METHODS(encrypt); - EVP_METHODS(decrypt); - EVP_METHODS(sign); - EVP_METHODS(verify); - EVP_METHODS(seal); - EVP_METHODS(open); - struct luaL_Reg hmac_functions[] = { - { "digest", hmac_fdigest }, - { "new", hmac_fnew }, - { NULL, NULL } - }; - struct luaL_Reg hmac_methods[] = { - { "__tostring", hmac_tostring }, - { "__gc", hmac_gc }, - { "clone", hmac_clone }, - { "final", hmac_final }, - { "reset", hmac_reset }, - { "tostring", hmac_tostring }, - { "update", hmac_update }, - { NULL, NULL } - }; - struct luaL_Reg rand_functions[] = { - { "bytes", rand_bytes }, - { "pseudo_bytes", rand_pseudo_bytes }, - { "add", rand_add }, - { "seed", rand_add }, - { "status", rand_status }, - { "load", rand_load }, - { "write", rand_write }, - { "cleanup", rand_cleanup }, - { NULL, NULL } - }; - struct luaL_Reg pkey_functions[] = { - { "generate", pkey_generate }, - { "read", pkey_read }, - { "from_pem", pkey_from_pem }, - { NULL, NULL } - }; - struct luaL_Reg pkey_methods[] = { - { "__tostring", pkey_tostring }, - { "__gc", pkey_gc }, - { "write", pkey_write }, - { "to_pem", pkey_to_pem}, - { NULL, NULL } - }; - struct luaL_Reg x509_methods[] = { - { "__gc", x509_cert_gc }, - { "from_pem", x509_cert_from_pem}, - { "pubkey", x509_cert_pubkey}, - { NULL, NULL } - }; - struct luaL_Reg x509_ca_methods[] = { - { "__gc", x509_ca_gc }, - { "add_pem", x509_ca_add_pem }, - { "verify_pem", x509_ca_verify_pem }, - { NULL, NULL } - }; +static void create_metatables(lua_State* L) +{ + struct luaL_Reg digest_methods[] = { + { "__tostring", digest_tostring }, + { "__gc", digest_gc }, + { "final", digest_final }, + { "tostring", digest_tostring }, + { "update", digest_update }, + { "reset", digest_reset }, + { "clone", digest_clone }, + { NULL, NULL } + }; + EVP_METHODS(encrypt); + EVP_METHODS(decrypt); + EVP_METHODS(sign); + EVP_METHODS(verify); + EVP_METHODS(seal); + EVP_METHODS(open); + struct luaL_Reg hmac_functions[] = { + { "digest", hmac_fdigest }, + { "new", hmac_fnew }, + { NULL, NULL } + }; + struct luaL_Reg hmac_methods[] = { + { "__tostring", hmac_tostring }, + { "__gc", hmac_gc }, + { "clone", hmac_clone }, + { "final", hmac_final }, + { "reset", hmac_reset }, + { "tostring", hmac_tostring }, + { "update", hmac_update }, + { NULL, NULL } + }; + struct luaL_Reg rand_functions[] = { + { "bytes", rand_bytes }, + { "add", rand_add }, + { "seed", rand_add }, + { "status", rand_status }, + { "load", rand_load }, + { "write", rand_write }, + { "cleanup", rand_cleanup }, + { NULL, NULL } + }; + struct luaL_Reg pkey_functions[] = { + { "generate", pkey_generate }, + { "read", pkey_read }, + { "from_pem", pkey_from_pem }, + { NULL, NULL } + }; + struct luaL_Reg pkey_methods[] = { + { "__tostring", pkey_tostring }, + { "__gc", pkey_gc }, + { "write", pkey_write }, + { "to_pem", pkey_to_pem }, + { NULL, NULL } + }; + struct luaL_Reg x509_methods[] = { + { "__gc", x509_cert_gc }, + { "from_pem", x509_cert_from_pem }, + { "pubkey", x509_cert_pubkey }, + { NULL, NULL } + }; + struct luaL_Reg x509_ca_methods[] = { + { "__gc", x509_ca_gc }, + { "add_pem", x509_ca_add_pem }, + { "verify_pem", x509_ca_verify_pem }, + { NULL, NULL } + }; #define CALLTABLE(n) create_call_table(L, #n, n##_fnew, n##_f##n) - CALLTABLE(digest); - CALLTABLE(encrypt); - CALLTABLE(decrypt); - CALLTABLE(verify); - CALLTABLE(sign); - CALLTABLE(seal); - CALLTABLE(open); - CALLTABLE(x509_cert); - CALLTABLE(x509_ca); - - luacrypto_createmeta(L, LUACRYPTO_DIGESTNAME, digest_methods); - luacrypto_createmeta(L, LUACRYPTO_ENCRYPTNAME, encrypt_methods); - luacrypto_createmeta(L, LUACRYPTO_DECRYPTNAME, decrypt_methods); - luacrypto_createmeta(L, LUACRYPTO_HMACNAME, hmac_methods); - luacrypto_createmeta(L, LUACRYPTO_SIGNNAME, sign_methods); - luacrypto_createmeta(L, LUACRYPTO_VERIFYNAME, verify_methods); - luacrypto_createmeta(L, LUACRYPTO_PKEYNAME, pkey_methods); - luacrypto_createmeta(L, LUACRYPTO_SEALNAME, seal_methods); - luacrypto_createmeta(L, LUACRYPTO_OPENNAME, open_methods); - luacrypto_createmeta(L, LUACRYPTO_X509_CERT_NAME, x509_methods); - luacrypto_createmeta(L, LUACRYPTO_X509_CA_NAME, x509_ca_methods); - -#define NONCALLTABLE(n) luaL_newlib(L, n##_functions); lua_setfield(L, -2, #n) - NONCALLTABLE(rand); - NONCALLTABLE(hmac); - NONCALLTABLE(pkey); + CALLTABLE(digest); + CALLTABLE(encrypt); + CALLTABLE(decrypt); + CALLTABLE(verify); + CALLTABLE(sign); + CALLTABLE(seal); + CALLTABLE(open); + CALLTABLE(x509_cert); + CALLTABLE(x509_ca); + + luacrypto_createmeta(L, LUACRYPTO_DIGESTNAME, digest_methods); + luacrypto_createmeta(L, LUACRYPTO_ENCRYPTNAME, encrypt_methods); + luacrypto_createmeta(L, LUACRYPTO_DECRYPTNAME, decrypt_methods); + luacrypto_createmeta(L, LUACRYPTO_HMACNAME, hmac_methods); + luacrypto_createmeta(L, LUACRYPTO_SIGNNAME, sign_methods); + luacrypto_createmeta(L, LUACRYPTO_VERIFYNAME, verify_methods); + luacrypto_createmeta(L, LUACRYPTO_PKEYNAME, pkey_methods); + luacrypto_createmeta(L, LUACRYPTO_SEALNAME, seal_methods); + luacrypto_createmeta(L, LUACRYPTO_OPENNAME, open_methods); + luacrypto_createmeta(L, LUACRYPTO_X509_CERT_NAME, x509_methods); + luacrypto_createmeta(L, LUACRYPTO_X509_CA_NAME, x509_ca_methods); + +#define NONCALLTABLE(n) \ + luaL_newlib(L, n##_functions); \ + lua_setfield(L, -2, #n) + NONCALLTABLE(rand); + NONCALLTABLE(hmac); + NONCALLTABLE(pkey); } /* ** Define the metatable for the object on top of the stack */ -LUACRYPTO_API void luacrypto_setmeta (lua_State *L, const char *name) +LUACRYPTO_API void luacrypto_setmeta(lua_State* L, const char* name) { - luaL_getmetatable (L, name); - lua_setmetatable (L, -2); + luaL_getmetatable(L, name); + lua_setmetatable(L, -2); } /* ** Assumes the table is on top of the stack. */ -LUACRYPTO_API void luacrypto_set_info (lua_State *L) +LUACRYPTO_API void luacrypto_set_info(lua_State* L) { - lua_pushliteral (L, "_COPYRIGHT"); - lua_pushliteral (L, "Copyright (C) 2005-2006 Keith Howe"); - lua_settable (L, -3); - lua_pushliteral (L, "_DESCRIPTION"); - lua_pushliteral (L, "LuaCrypto is a Lua wrapper for OpenSSL"); - lua_settable (L, -3); - lua_pushliteral (L, "_VERSION"); - lua_pushliteral (L, "LuaCrypto 0.3.1"); - lua_settable (L, -3); + lua_pushliteral(L, "_COPYRIGHT"); + lua_pushliteral(L, "Copyright (C) 2005-2006 Keith Howe"); + lua_settable(L, -3); + lua_pushliteral(L, "_DESCRIPTION"); + lua_pushliteral(L, "LuaCrypto is a Lua wrapper for OpenSSL"); + lua_settable(L, -3); + lua_pushliteral(L, "_VERSION"); + lua_pushliteral(L, "LuaCrypto 0.4.0"); + lua_settable(L, -3); } /* ** Creates the metatables for the objects and registers the ** driver open method. */ -LUACRYPTO_API int luaopen_crypto(lua_State *L) -{ - struct luaL_Reg core_functions[] = { - { "list", luacrypto_list }, - { "hex", luacrypto_hex }, - { "base64", luacrypto_base64_encode}, - { "unbase64", luacrypto_base64_decode}, - { NULL, NULL } - }; - - luaL_newlib(L, core_functions); - create_metatables (L); - luacrypto_set_info (L); - luaL_checkversion(L); - return 1; +LUACRYPTO_API int luaopen_crypto(lua_State* L) +{ + struct luaL_Reg core_functions[] = { + { "list", luacrypto_list }, + { "hex", luacrypto_hex }, + { "base64", luacrypto_base64_encode }, + { "unbase64", luacrypto_base64_decode }, + { NULL, NULL } + }; + + luaL_newlib(L, core_functions); + create_metatables(L); + luacrypto_set_info(L); + luaL_checkversion(L); + return 1; } /* * OpenSSL_add_all_* is not thread safe, so init Openssl when dlopen */ -void __attribute__ ((constructor)) luacrypto_init(void){ - #ifndef OPENSSL_EXTERNAL_INITIALIZATION +void __attribute__((constructor)) luacrypto_init(void) +{ +#ifndef OPENSSL_EXTERNAL_INITIALIZATION OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); - #endif +#endif } - diff --git a/src/lcrypto.h b/src/lcrypto.h index 9cc47ea..e1903b8 100644 --- a/src/lcrypto.h +++ b/src/lcrypto.h @@ -7,7 +7,7 @@ #define _LUACRYPTO_ #ifndef LUACRYPTO_API -#define LUACRYPTO_API LUA_API +#define LUACRYPTO_API LUA_API #endif #define LUACRYPTO_PREFIX "LuaCrypto: " diff --git a/src/lcrypto_compat_110.h b/src/lcrypto_compat_110.h new file mode 100644 index 0000000..027fd5c --- /dev/null +++ b/src/lcrypto_compat_110.h @@ -0,0 +1,447 @@ +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#include +#include + +static void* OPENSSL_zalloc(size_t num) +{ + void* ret = OPENSSL_malloc(num); + + if (ret != NULL) + memset(ret, 0, num); + return ret; +} + +int RSA_set0_key(RSA* r, BIGNUM* n, BIGNUM* e, BIGNUM* d) +{ + /* If the fields n and e in r are NULL, the corresponding input + * parameters MUST be non-NULL for n and e. d may be + * left NULL (in case only the public key is used). + */ + if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) + return 0; + + if (n != NULL) { + BN_free(r->n); + r->n = n; + } + if (e != NULL) { + BN_free(r->e); + r->e = e; + } + if (d != NULL) { + BN_free(r->d); + r->d = d; + } + + return 1; +} + +int RSA_set0_factors(RSA* r, BIGNUM* p, BIGNUM* q) +{ + /* If the fields p and q in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL)) + return 0; + + if (p != NULL) { + BN_free(r->p); + r->p = p; + } + if (q != NULL) { + BN_free(r->q); + r->q = q; + } + + return 1; +} + +int RSA_set0_crt_params(RSA* r, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp) +{ + /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->dmp1 == NULL && dmp1 == NULL) || (r->dmq1 == NULL && dmq1 == NULL) || (r->iqmp == NULL && iqmp == NULL)) + return 0; + + if (dmp1 != NULL) { + BN_free(r->dmp1); + r->dmp1 = dmp1; + } + if (dmq1 != NULL) { + BN_free(r->dmq1); + r->dmq1 = dmq1; + } + if (iqmp != NULL) { + BN_free(r->iqmp); + r->iqmp = iqmp; + } + + return 1; +} + +void RSA_get0_key(const RSA* r, + const BIGNUM** n, const BIGNUM** e, const BIGNUM** d) +{ + if (n != NULL) + *n = r->n; + if (e != NULL) + *e = r->e; + if (d != NULL) + *d = r->d; +} + +void RSA_get0_factors(const RSA* r, const BIGNUM** p, const BIGNUM** q) +{ + if (p != NULL) + *p = r->p; + if (q != NULL) + *q = r->q; +} + +void RSA_get0_crt_params(const RSA* r, + const BIGNUM** dmp1, const BIGNUM** dmq1, + const BIGNUM** iqmp) +{ + if (dmp1 != NULL) + *dmp1 = r->dmp1; + if (dmq1 != NULL) + *dmq1 = r->dmq1; + if (iqmp != NULL) + *iqmp = r->iqmp; +} + +void DSA_get0_pqg(const DSA* d, + const BIGNUM** p, const BIGNUM** q, const BIGNUM** g) +{ + if (p != NULL) + *p = d->p; + if (q != NULL) + *q = d->q; + if (g != NULL) + *g = d->g; +} + +int DSA_set0_pqg(DSA* d, BIGNUM* p, BIGNUM* q, BIGNUM* g) +{ + /* If the fields p, q and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((d->p == NULL && p == NULL) || (d->q == NULL && q == NULL) || (d->g == NULL && g == NULL)) + return 0; + + if (p != NULL) { + BN_free(d->p); + d->p = p; + } + if (q != NULL) { + BN_free(d->q); + d->q = q; + } + if (g != NULL) { + BN_free(d->g); + d->g = g; + } + + return 1; +} + +void DSA_get0_key(const DSA* d, + const BIGNUM** pub_key, const BIGNUM** priv_key) +{ + if (pub_key != NULL) + *pub_key = d->pub_key; + if (priv_key != NULL) + *priv_key = d->priv_key; +} + +int DSA_set0_key(DSA* d, BIGNUM* pub_key, BIGNUM* priv_key) +{ + /* If the field pub_key in d is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (d->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) { + BN_free(d->pub_key); + d->pub_key = pub_key; + } + if (priv_key != NULL) { + BN_free(d->priv_key); + d->priv_key = priv_key; + } + + return 1; +} + +void DSA_SIG_get0(const DSA_SIG* sig, const BIGNUM** pr, const BIGNUM** ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int DSA_SIG_set0(DSA_SIG* sig, BIGNUM* r, BIGNUM* s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +void ECDSA_SIG_get0(const ECDSA_SIG* sig, const BIGNUM** pr, const BIGNUM** ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int ECDSA_SIG_set0(ECDSA_SIG* sig, BIGNUM* r, BIGNUM* s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +void DH_get0_pqg(const DH* dh, + const BIGNUM** p, const BIGNUM** q, const BIGNUM** g) +{ + if (p != NULL) + *p = dh->p; + if (q != NULL) + *q = dh->q; + if (g != NULL) + *g = dh->g; +} + +int DH_set0_pqg(DH* dh, BIGNUM* p, BIGNUM* q, BIGNUM* g) +{ + /* If the fields p and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. q may remain NULL. + */ + if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL)) + return 0; + + if (p != NULL) { + BN_free(dh->p); + dh->p = p; + } + if (q != NULL) { + BN_free(dh->q); + dh->q = q; + } + if (g != NULL) { + BN_free(dh->g); + dh->g = g; + } + + if (q != NULL) { + dh->length = BN_num_bits(q); + } + + return 1; +} + +void DH_get0_key(const DH* dh, const BIGNUM** pub_key, const BIGNUM** priv_key) +{ + if (pub_key != NULL) + *pub_key = dh->pub_key; + if (priv_key != NULL) + *priv_key = dh->priv_key; +} + +int DH_set0_key(DH* dh, BIGNUM* pub_key, BIGNUM* priv_key) +{ + /* If the field pub_key in dh is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (dh->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) { + BN_free(dh->pub_key); + dh->pub_key = pub_key; + } + if (priv_key != NULL) { + BN_free(dh->priv_key); + dh->priv_key = priv_key; + } + + return 1; +} + +int DH_set_length(DH* dh, long length) +{ + dh->length = length; + return 1; +} + +EVP_CIPHER_CTX* EVP_CIPHER_CTX_new() +{ + EVP_CIPHER_CTX* ctx = OPENSSL_malloc(sizeof(*ctx)); + if (ctx != NULL) { + if (!EVP_CIPHER_CTX_init(ctx)) { + OPENSSL_free(ctx); + return NULL; + } + } + return ctx; +} + +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX* ctx) +{ +} +const unsigned char* EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX* ctx) +{ + return ctx->iv; +} + +unsigned char* EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX* ctx) +{ + return ctx->iv; +} + +EVP_MD_CTX* EVP_MD_CTX_new(void) +{ + EVP_MD_CTX* ctx = OPENSSL_zalloc(sizeof(EVP_MD_CTX)); + if (ctx != NULL) { + if (!EVP_MD_CTX_init(ctx)) { + OPENSSL_free(ctx); + return NUll; + } + } + + return ctx; +} + +int EVP_MD_CTX_reset(EVP_MD_CTX* ctx) +{ + int ret = EVP_MD_CTX_cleanup(ctx); + if (!ret) { + return ret + } + EVP_MD_CTX_init(ctx); + return ret; +} + +void EVP_MD_CTX_free(EVP_MD_CTX* ctx) +{ + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +RSA_METHOD* RSA_meth_dup(const RSA_METHOD* meth) +{ + RSA_METHOD* ret; + + ret = OPENSSL_malloc(sizeof(RSA_METHOD)); + + if (ret != NULL) { + memcpy(ret, meth, sizeof(*meth)); + ret->name = OPENSSL_strdup(meth->name); + if (ret->name == NULL) { + OPENSSL_free(ret); + return NULL; + } + } + + return ret; +} + +int RSA_meth_set1_name(RSA_METHOD* meth, const char* name) +{ + char* tmpname; + + tmpname = OPENSSL_strdup(name); + if (tmpname == NULL) { + return 0; + } + + OPENSSL_free((char*)meth->name); + meth->name = tmpname; + + return 1; +} + +int RSA_meth_set_priv_enc(RSA_METHOD* meth, + int (*priv_enc)(int flen, const unsigned char* from, + unsigned char* to, RSA* rsa, + int padding)) +{ + meth->rsa_priv_enc = priv_enc; + return 1; +} + +int RSA_meth_set_priv_dec(RSA_METHOD* meth, + int (*priv_dec)(int flen, const unsigned char* from, + unsigned char* to, RSA* rsa, + int padding)) +{ + meth->rsa_priv_dec = priv_dec; + return 1; +} + +int RSA_meth_set_finish(RSA_METHOD* meth, int (*finish)(RSA* rsa)) +{ + meth->finish = finish; + return 1; +} + +void RSA_meth_free(RSA_METHOD* meth) +{ + if (meth != NULL) { + OPENSSL_free((char*)meth->name); + OPENSSL_free(meth); + } +} + +int RSA_bits(const RSA* r) +{ + return (BN_num_bits(r->n)); +} + +RSA* EVP_PKEY_get0_RSA(EVP_PKEY* pkey) +{ + if (pkey->type != EVP_PKEY_RSA) { + return NULL; + } + return pkey->pkey.rsa; +} + +HMAC_CTX* HMAC_CTX_new(void) +{ + HMAC_CTX* ctx = OPENSSL_malloc(sizeof(*ctx)); + if (ctx != NULL) { + if (!HMAC_CTX_reset(ctx)) { + HMAC_CTX_free(ctx); + return NULL; + } + } + return ctx; +} + +void HMAC_CTX_free(HMAC_CTX* ctx) +{ + if (ctx != NULL) { + hmac_ctx_cleanup(ctx); + EVP_MD_CTX_free(ctx->i_ctx); + EVP_MD_CTX_free(ctx->o_ctx); + EVP_MD_CTX_free(ctx->md_ctx); + OPENSSL_free(ctx); + } +} +#endif \ No newline at end of file diff --git a/tests/priv.pem b/tests/priv.pem deleted file mode 100644 index ac7c9ae..0000000 --- a/tests/priv.pem +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALRmX+J5s33Fq03h -YbL1BEh1srny+Rt28Zm1cSwNB9oBLd0X8iaSHxR1Pkho6Q9cvRBiCOvQilMEdMQO -VAygi9fHEVZk+K7f2p0xZAs6/BrMCER7miKUqjV41fNDBR6y40KCrrSJUTQjPCXl -9YXzjVDwT2woHUTYEw/HEHSAPb1TAgMBAAECgYAJ8rNK6+coAmSF8O3QTo6j6Emo -02tFRnPgRA8vnLBYJ0R+MrnZwqkQGb8Lgy2G+Vg7tQxE5MUb+tztitS7tYbAkZv5 -/0e+77NHVhRnzFJXRMzsERFPNasOcLw+0W6IAMstSTd0BJoFVfZGwaesiDQoDSuD -S4wm6bYDiNPU6lxCQQJBAOyeUfChzWEqqtfpf7Cw3sTflhomQQg3ldZbpGP0yxrn -imPDFVkAeFwSKLjEYXoRV3g9K5Q5H0wa2MGJTlDbdnECQQDDLTOKvdxK0gQamE4A -3ObNfDSvjsdpb6QKjr2KG2q74lq7Reuv9VwmrYz6TS4d6nXDMByo5dBpelKWgKaG -kfoDAkEApelJKUI64TPqwSRPzZPnUAI6nLFQDjPzk2+EsDXYKFBMIDGNCXAj9OMi -vJOuicoZHA1APlljUZjNfb8KM/X+cQJAVSvJfTcDBeeGAPELwRak5XDZMO82mA0u -4aiOj9END7Zkb6rAggWpU/uSNLwvbsCc6TN6nj3DZ/QITEMR6FGVbwJBAK+pUf3q -u/ITfIx4ZWIiVW0mgTslUG9Ta91X9+hZrF13dDJ+RNEL/K8K/XLqS87Hx8e3nGPT -gaOqoS00nccShis= ------END PRIVATE KEY----- diff --git a/tests/pub.pem b/tests/pub.pem deleted file mode 100644 index f7feea9..0000000 --- a/tests/pub.pem +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0Zl/iebN9xatN4WGy9QRIdbK5 -8vkbdvGZtXEsDQfaAS3dF/Imkh8UdT5IaOkPXL0QYgjr0IpTBHTEDlQMoIvXxxFW -ZPiu39qdMWQLOvwazAhEe5oilKo1eNXzQwUesuNCgq60iVE0Izwl5fWF841Q8E9s -KB1E2BMPxxB0gD29UwIDAQAB ------END PUBLIC KEY----- diff --git a/tests/rand.lua b/tests/rand.lua index b88f8e1..d20961b 100644 --- a/tests/rand.lua +++ b/tests/rand.lua @@ -35,13 +35,6 @@ end local N = 20 local S = 5 -print(string.format("generating %d sets of %d random bytes using pseudo_bytes()", S, N)) -for i = 1, S do - local data = assert(rand.pseudo_bytes(N)) - print(table.concat({string.byte(data, 1, N)}, ",")) -end -print("") - print(string.format("generating %d sets of %d random bytes using bytes()", S, N)) for i = 1, S do local data = assert(rand.bytes(N)) diff --git a/tests/test.lua b/tests/test.lua index fec1f65..2162364 100644 --- a/tests/test.lua +++ b/tests/test.lua @@ -33,7 +33,7 @@ for i, t in ipairs({"sha1", "md5", "sha1", "hmac"}) do assert(io.input(F)) report("all", d:final(io.read("*all")), F, t) - d:reset(d) + d:reset() assert(io.input(F)) while true do diff --git a/tests/tmp.rnd b/tests/tmp.rnd deleted file mode 100644 index 8c52c7a..0000000 Binary files a/tests/tmp.rnd and /dev/null differ