From e5c1d346e29e5b1227ed30ee4d725a09eca0e532 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 5 Oct 2012 11:52:52 +0200 Subject: crypto: Make unloading of crypto safer Facts: crypto nif-lib registers callback functions that openssl uses for memory management and thread synchronization. The callback functions can only be set once, openssl does not allow changing the callback functions. Problem: If openssl is dynamicly linked to crypto, you might get s scenario where the crypto lib is unloaded while leaving openssl loaded with its old pointers to the unloaded crypto code intact. If crypto is then reloaded (by init:restart() for example), the crypto nif-lib might get relocated at a different address. crypto calls openssl which in turn calls the old invalid callback functions...kaboom. Solution: Break apart the callback functions into a separate dynamic lib that crypto loads with dlopen. When crypto is unloaded the callback lib is left in place to be reused if/when crypto is loaded again. --- lib/crypto/c_src/Makefile.in | 36 ++++-- lib/crypto/c_src/crypto.c | 219 +++++++++++++++---------------------- lib/crypto/c_src/crypto_callback.c | 163 +++++++++++++++++++++++++++ lib/crypto/c_src/crypto_callback.h | 42 +++++++ lib/crypto/src/crypto.erl | 6 +- 5 files changed, 324 insertions(+), 142 deletions(-) create mode 100644 lib/crypto/c_src/crypto_callback.c create mode 100644 lib/crypto/c_src/crypto_callback.h (limited to 'lib') diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in index ffd556ca1a..f7e2193cec 100644 --- a/lib/crypto/c_src/Makefile.in +++ b/lib/crypto/c_src/Makefile.in @@ -69,13 +69,16 @@ RELSYSDIR = $(RELEASE_PATH)/lib/crypto-$(VSN) # ---------------------------------------------------- # Misc Macros # ---------------------------------------------------- -OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o +CRYPTO_OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o +CALLBACK_OBJS = $(OBJDIR)/crypto_callback$(TYPEMARKER).o NIF_MAKEFILE = $(PRIVDIR)/Makefile ifeq ($(findstring win32,$(TARGET)), win32) NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).dll +CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).dll else NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).so +CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).so endif ifeq ($(HOST_OS),) @@ -97,32 +100,49 @@ endif _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) -debug opt valgrind: $(NIF_LIB) +debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB) $(OBJDIR)/%$(TYPEMARKER).o: %.c $(INSTALL_DIR) $(OBJDIR) $(CC) -c -o $@ $(ALL_CFLAGS) $< -$(LIBDIR)/crypto$(TYPEMARKER).so: $(OBJS) - $(INSTALL_DIR) $(LIBDIR) +$(LIBDIR)/crypto$(TYPEMARKER).so: $(CRYPTO_OBJS) + $(INSTALL_DIR) $(LIBDIR) $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CRYPTO_LINK_LIB) -$(LIBDIR)/crypto$(TYPEMARKER).dll: $(OBJS) +$(LIBDIR)/crypto$(TYPEMARKER).dll: $(CRYPTO_OBJS) + $(INSTALL_DIR) $(LIBDIR) + $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(CRYPTO_OBJS) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME) + +$(LIBDIR)/crypto_callback$(TYPEMARKER).so: $(CALLBACK_OBJS) $(INSTALL_DIR) $(LIBDIR) - $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(OBJS) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME) + $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +$(LIBDIR)/crypto_callback$(TYPEMARKER).dll: $(CALLBACK_OBJS) + $(INSTALL_DIR) $(LIBDIR) + $(LD) $(LDFLAGS) -o $@ $(CALLBACK_OBJS) + clean: ifeq ($(findstring win32,$(TARGET)), win32) rm -f $(LIBDIR)/crypto.dll rm -f $(LIBDIR)/crypto.debug.dll + rm -f $(LIBDIR)/crypto_callback.dll + rm -f $(LIBDIR)/crypto_callback.debug.dll else rm -f $(LIBDIR)/crypto.so rm -f $(LIBDIR)/crypto.debug.so rm -f $(LIBDIR)/crypto.valgrind.so + rm -f $(LIBDIR)/crypto_callback.so + rm -f $(LIBDIR)/crypto_callback.debug.so + rm -f $(LIBDIR)/crypto_callback.valgrind.so endif rm -f $(OBJDIR)/crypto.o rm -f $(OBJDIR)/crypto.debug.o rm -f $(OBJDIR)/crypto.valgrind.o + rm -f $(OBJDIR)/crypto_callback.o + rm -f $(OBJDIR)/crypto_callback.debug.o + rm -f $(OBJDIR)/crypto_callback.valgrind.o rm -f core *~ docs: @@ -136,8 +156,10 @@ release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj" $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" $(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj" - $(INSTALL_PROGRAM) $(OBJS) "$(RELSYSDIR)/priv/obj" + $(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj" + $(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib" + $(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib" release_docs_spec: diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 91ab244620..8bd0690a17 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -53,6 +53,8 @@ #include #include +#include "crypto_callback.h" + #if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA224) && defined(NID_sha224)\ && !defined(OPENSSL_NO_SHA256) /* disabled like this in my sha.h (?) */ # define HAVE_SHA224 @@ -125,7 +127,6 @@ /* NIF interface declarations */ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); -static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); static void unload(ErlNifEnv* env, void* priv_data); @@ -204,17 +205,6 @@ static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -/* openssl callbacks */ -#ifdef OPENSSL_THREADS -static void locking_function(int mode, int n, const char *file, int line); -static unsigned long id_function(void); -static struct CRYPTO_dynlock_value* dyn_create_function(const char *file, - int line); -static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value* ptr, - const char *file, int line); -static void dyn_destroy_function(struct CRYPTO_dynlock_value *ptr, - const char *file, int line); -#endif /* OPENSSL_THREADS */ /* helpers */ static void init_digest_types(ErlNifEnv* env); @@ -325,7 +315,7 @@ static ErlNifFunc nif_funcs[] = { {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt} }; -ERL_NIF_INIT(crypto,nif_funcs,load,reload,upgrade,unload) +ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload) #define MD5_CTX_LEN (sizeof(MD5_CTX)) @@ -347,7 +337,6 @@ ERL_NIF_INIT(crypto,nif_funcs,load,reload,upgrade,unload) #define HMAC_OPAD 0x5c -static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */ static ERL_NIF_TERM atom_true; static ERL_NIF_TERM atom_false; static ERL_NIF_TERM atom_sha; @@ -374,55 +363,97 @@ static ERL_NIF_TERM atom_none; static ERL_NIF_TERM atom_notsup; static ERL_NIF_TERM atom_digest; - -static int is_ok_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info) +static int change_basename(char* buf, int bufsz, const char* newfile) { - int i; - return enif_get_int(env,load_info,&i) && i == 101; -} -static void* crypto_alloc(size_t size) -{ - return enif_alloc(size); + char* p = strrchr(buf, '/'); + p = (p == NULL) ? buf : p + 1; + + if ((p - buf) + strlen(newfile) >= bufsz) { + /*fprintf(stderr, "CRYPTO: lib name too long\r\n");*/ + return 0; + } + strcpy(p, newfile); + return 1; } -static void* crypto_realloc(void* ptr, size_t size) + +static void error_handler(void* null, const char* errstr) { - return enif_realloc(ptr, size); -} -static void crypto_free(void* ptr) -{ - enif_free(ptr); + /*fprintf(stderr, "CRYPTO LOADING ERROR: '%s'\r\n", errstr);*/ } -static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) { ErlNifSysInfo sys_info; - CRYPTO_set_mem_functions(crypto_alloc, crypto_realloc, crypto_free); - - if (!is_ok_load_info(env, load_info)) { - return -1; + const char callback_lib[] = "crypto_callback"; + void* handle; + get_crypto_callbacks_t* funcp; + struct crypto_callbacks* ccb; + int nlocks = 0; + int tpl_arity; + const ERL_NIF_TERM* tpl_array; + int vernum; + char lib_buf[1000]; + + /* load_info: {201, "/full/path/of/this/library"} */ + if (!enif_get_tuple(env, load_info, &tpl_arity, &tpl_array) + || tpl_arity != 2 + || !enif_get_int(env, tpl_array[0], &vernum) + || vernum != 201 + || enif_get_string(env, tpl_array[1], lib_buf, sizeof(lib_buf), ERL_NIF_LATIN1) <= 0) { + + /*enif_fprintf(stderr, "CRYPTO: Invalid load_info '%T'\n", load_info);*/ + return 0; + } + if (library_refc > 0) { + return 1; } + if (!change_basename(lib_buf, sizeof(lib_buf), callback_lib)) { + return 0; + } + + if (!(handle = enif_dlopen(lib_buf, &error_handler, NULL))) { + return 0; + } + if (!(funcp = (get_crypto_callbacks_t*) enif_dlsym(handle, "get_crypto_callbacks", + &error_handler, NULL))) { + return 0; + } + #ifdef OPENSSL_THREADS enif_system_info(&sys_info, sizeof(sys_info)); - if (sys_info.scheduler_threads > 1) { - int i; - lock_vec = enif_alloc(CRYPTO_num_locks()*sizeof(*lock_vec)); - if (lock_vec==NULL) return -1; - memset(lock_vec,0,CRYPTO_num_locks()*sizeof(*lock_vec)); - - for (i=CRYPTO_num_locks()-1; i>=0; --i) { - lock_vec[i] = enif_rwlock_create("crypto_stat"); - if (lock_vec[i]==NULL) return -1; - } - CRYPTO_set_locking_callback(locking_function); - CRYPTO_set_id_callback(id_function); - CRYPTO_set_dynlock_create_callback(dyn_create_function); - CRYPTO_set_dynlock_lock_callback(dyn_lock_function); - CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); + nlocks = CRYPTO_num_locks(); } /* else no need for locks */ +#endif + + ccb = (*funcp)(nlocks); + + if (!ccb || ccb->sizeof_me != sizeof(*ccb)) { + /*fprintf(stderr, "Invalid 'crypto_callbacks'\r\n");*/ + return 0; + } + + CRYPTO_set_mem_functions(ccb->crypto_alloc, ccb->crypto_realloc, ccb->crypto_free); + +#ifdef OPENSSL_THREADS + if (nlocks > 0) { + CRYPTO_set_locking_callback(ccb->locking_function); + CRYPTO_set_id_callback(ccb->id_function); + CRYPTO_set_dynlock_create_callback(ccb->dyn_create_function); + CRYPTO_set_dynlock_lock_callback(ccb->dyn_lock_function); + CRYPTO_set_dynlock_destroy_callback(ccb->dyn_destroy_function); + } #endif /* OPENSSL_THREADS */ + return 1; +} + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + if (!init(env, load_info)) { + return -1; + } atom_true = enif_make_atom(env,"true"); atom_false = enif_make_atom(env,"false"); @@ -456,8 +487,12 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) return 0; } -static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) -{ +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, + ERL_NIF_TERM load_info) +{ + if (*old_priv_data != NULL) { + return -1; /* Don't know how to do that */ + } if (*priv_data != NULL) { return -1; /* Don't know how to do that */ } @@ -466,43 +501,16 @@ static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) when to (re)set the callbacks for allocation and locking. */ return -2; } - if (!is_ok_load_info(env, load_info)) { + if (!init(env, load_info)) { return -1; } - return 0; -} - -static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, - ERL_NIF_TERM load_info) -{ - int i; - if (*old_priv_data != NULL) { - return -1; /* Don't know how to do that */ - } - i = reload(env,priv_data,load_info); - if (i != 0) { - return i; - } library_refc++; return 0; } static void unload(ErlNifEnv* env, void* priv_data) { - if (--library_refc <= 0) { - CRYPTO_cleanup_all_ex_data(); - - if (lock_vec != NULL) { - int i; - for (i=CRYPTO_num_locks()-1; i>=0; --i) { - if (lock_vec[i] != NULL) { - enif_rwlock_destroy(lock_vec[i]); - } - } - enif_free(lock_vec); - } - } - /*else NIF library still used by other (new) module code */ + --library_refc; } static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -2338,59 +2346,6 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N -#ifdef OPENSSL_THREADS /* vvvvvvvvvvvvvvv OPENSSL_THREADS vvvvvvvvvvvvvvvv */ - -static INLINE void locking(int mode, ErlNifRWLock* lock) -{ - switch (mode) { - case CRYPTO_LOCK|CRYPTO_READ: - enif_rwlock_rlock(lock); - break; - case CRYPTO_LOCK|CRYPTO_WRITE: - enif_rwlock_rwlock(lock); - break; - case CRYPTO_UNLOCK|CRYPTO_READ: - enif_rwlock_runlock(lock); - break; - case CRYPTO_UNLOCK|CRYPTO_WRITE: - enif_rwlock_rwunlock(lock); - break; - default: - ASSERT(!"Invalid lock mode"); - } -} - -/* Callback from openssl for static locking - */ -static void locking_function(int mode, int n, const char *file, int line) -{ - ASSERT(n>=0 && n +#include + +#include "erl_nif.h" +#include "crypto_callback.h" + +#ifdef DEBUG + # define ASSERT(e) \ + ((void) ((e) ? 1 : (fprintf(stderr,"Assert '%s' failed at %s:%d\n",\ + #e, __FILE__, __LINE__), abort(), 0))) +#else + # define ASSERT(e) ((void) 1) +#endif + +#ifdef __GNUC__ + # define INLINE __inline__ +#elif defined(__WIN32__) + # define INLINE __forceinline +#else + # define INLINE +#endif + +#ifdef __WIN32__ +# define DLLEXPORT __declspec(dllexport) +#else +# define DLLEXPORT +#endif + +/* to be dlsym'ed */ +DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks); + + +static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */ + +static void* crypto_alloc(size_t size) +{ + return enif_alloc(size); +} +static void* crypto_realloc(void* ptr, size_t size) +{ + return enif_realloc(ptr, size); +} +static void crypto_free(void* ptr) +{ + enif_free(ptr); +} + + +#ifdef OPENSSL_THREADS /* vvvvvvvvvvvvvvv OPENSSL_THREADS vvvvvvvvvvvvvvvv */ + +#include + +static INLINE void locking(int mode, ErlNifRWLock* lock) +{ + switch (mode) { + case CRYPTO_LOCK|CRYPTO_READ: + enif_rwlock_rlock(lock); + break; + case CRYPTO_LOCK|CRYPTO_WRITE: + enif_rwlock_rwlock(lock); + break; + case CRYPTO_UNLOCK|CRYPTO_READ: + enif_rwlock_runlock(lock); + break; + case CRYPTO_UNLOCK|CRYPTO_WRITE: + enif_rwlock_rwunlock(lock); + break; + default: + ASSERT(!"Invalid lock mode"); + } +} + +static void locking_function(int mode, int n, const char *file, int line) +{ + ASSERT(n>=0 && n 0) { + int i; + lock_vec = enif_alloc(nlocks*sizeof(*lock_vec)); + if (lock_vec==NULL) return NULL; + memset(lock_vec, 0, nlocks*sizeof(*lock_vec)); + + for (i=nlocks-1; i>=0; --i) { + lock_vec[i] = enif_rwlock_create("crypto_stat"); + if (lock_vec[i]==NULL) return NULL; + } + } +#endif + is_initialized = 1; + } + return &the_struct; +} + +/* This is not really a NIF library, but we use ERL_NIF_INIT in order to + * get access to the erl_nif API (on Windows). + */ +ERL_NIF_INIT(dummy, (ErlNifFunc*)NULL , NULL, NULL, NULL, NULL) + diff --git a/lib/crypto/c_src/crypto_callback.h b/lib/crypto/c_src/crypto_callback.h new file mode 100644 index 0000000000..a0c828b502 --- /dev/null +++ b/lib/crypto/c_src/crypto_callback.h @@ -0,0 +1,42 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2012. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +struct crypto_callbacks +{ + size_t sizeof_me; + + void* (*crypto_alloc)(size_t size); + void* (*crypto_realloc)(void* ptr, size_t size); + void (*crypto_free)(void* ptr); + + /* openssl callbacks */ + #ifdef OPENSSL_THREADS + void (*locking_function)(int mode, int n, const char *file, int line); + unsigned long (*id_function)(void); + struct CRYPTO_dynlock_value* (*dyn_create_function)(const char *file, + int line); + void (*dyn_lock_function)(int mode, struct CRYPTO_dynlock_value* ptr, + const char *file, int line); + void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *ptr, + const char *file, int line); + #endif /* OPENSSL_THREADS */ +}; + +typedef struct crypto_callbacks* get_crypto_callbacks_t(int nlocks); + diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 0089e79a4f..21f507f153 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -114,7 +114,7 @@ -on_load(on_load/0). --define(CRYPTO_NIF_VSN,101). +-define(CRYPTO_NIF_VSN,201). on_load() -> LibBaseName = "crypto", @@ -140,7 +140,7 @@ on_load() -> end end, Lib = filename:join([PrivDir, "lib", LibName]), - Status = case erlang:load_nif(Lib, ?CRYPTO_NIF_VSN) of + Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,Lib}) of ok -> ok; {error, {load_failed, _}}=Error1 -> ArchLibDir = @@ -152,7 +152,7 @@ on_load() -> [] -> Error1; _ -> ArchLib = filename:join([ArchLibDir, LibName]), - erlang:load_nif(ArchLib, ?CRYPTO_NIF_VSN) + erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchLib}) end; Error1 -> Error1 end, -- cgit v1.2.3 From d969763b18582c8c879ab3dd9e3ce37502430972 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 16 Oct 2012 20:14:48 +0200 Subject: crypto: Enable runtime upgrade of crypto --- lib/crypto/c_src/crypto.c | 62 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 32 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 8bd0690a17..c98dacc3eb 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -405,9 +405,39 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) return 0; } if (library_refc > 0) { + /* Repeated loading of this library (module upgrade). + * Atoms and callbacks are already set, we are done. + */ return 1; } + atom_true = enif_make_atom(env,"true"); + atom_false = enif_make_atom(env,"false"); + atom_sha = enif_make_atom(env,"sha"); + atom_sha224 = enif_make_atom(env,"sha224"); + atom_sha256 = enif_make_atom(env,"sha256"); + atom_sha384 = enif_make_atom(env,"sha384"); + atom_sha512 = enif_make_atom(env,"sha512"); + atom_md5 = enif_make_atom(env,"md5"); + atom_ripemd160 = enif_make_atom(env,"ripemd160"); + atom_error = enif_make_atom(env,"error"); + atom_rsa_pkcs1_padding = enif_make_atom(env,"rsa_pkcs1_padding"); + atom_rsa_pkcs1_oaep_padding = enif_make_atom(env,"rsa_pkcs1_oaep_padding"); + atom_rsa_no_padding = enif_make_atom(env,"rsa_no_padding"); + atom_undefined = enif_make_atom(env,"undefined"); + atom_ok = enif_make_atom(env,"ok"); + atom_not_prime = enif_make_atom(env,"not_prime"); + atom_not_strong_prime = enif_make_atom(env,"not_strong_prime"); + atom_unable_to_check_generator = enif_make_atom(env,"unable_to_check_generator"); + atom_not_suitable_generator = enif_make_atom(env,"not_suitable_generator"); + atom_check_failed = enif_make_atom(env,"check_failed"); + atom_unknown = enif_make_atom(env,"unknown"); + atom_none = enif_make_atom(env,"none"); + atom_notsup = enif_make_atom(env,"notsup"); + atom_digest = enif_make_atom(env,"digest"); + + init_digest_types(env); + if (!change_basename(lib_buf, sizeof(lib_buf), callback_lib)) { return 0; } @@ -455,33 +485,6 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) return -1; } - atom_true = enif_make_atom(env,"true"); - atom_false = enif_make_atom(env,"false"); - atom_sha = enif_make_atom(env,"sha"); - atom_sha224 = enif_make_atom(env,"sha224"); - atom_sha256 = enif_make_atom(env,"sha256"); - atom_sha384 = enif_make_atom(env,"sha384"); - atom_sha512 = enif_make_atom(env,"sha512"); - atom_md5 = enif_make_atom(env,"md5"); - atom_ripemd160 = enif_make_atom(env,"ripemd160"); - atom_error = enif_make_atom(env,"error"); - atom_rsa_pkcs1_padding = enif_make_atom(env,"rsa_pkcs1_padding"); - atom_rsa_pkcs1_oaep_padding = enif_make_atom(env,"rsa_pkcs1_oaep_padding"); - atom_rsa_no_padding = enif_make_atom(env,"rsa_no_padding"); - atom_undefined = enif_make_atom(env,"undefined"); - atom_ok = enif_make_atom(env,"ok"); - atom_not_prime = enif_make_atom(env,"not_prime"); - atom_not_strong_prime = enif_make_atom(env,"not_strong_prime"); - atom_unable_to_check_generator = enif_make_atom(env,"unable_to_check_generator"); - atom_not_suitable_generator = enif_make_atom(env,"not_suitable_generator"); - atom_check_failed = enif_make_atom(env,"check_failed"); - atom_unknown = enif_make_atom(env,"unknown"); - atom_none = enif_make_atom(env,"none"); - atom_notsup = enif_make_atom(env,"notsup"); - atom_digest = enif_make_atom(env,"digest"); - - init_digest_types(env); - *priv_data = NULL; library_refc++; return 0; @@ -496,11 +499,6 @@ static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, if (*priv_data != NULL) { return -1; /* Don't know how to do that */ } - if (library_refc == 0) { - /* No support for real library upgrade. The tricky thing is to know - when to (re)set the callbacks for allocation and locking. */ - return -2; - } if (!init(env, load_info)) { return -1; } -- cgit v1.2.3 From 8d502f8f98a89678448d16a8a15e744d65603f01 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 22 Oct 2012 17:59:51 +0200 Subject: crypto: Add debug print macros --- lib/crypto/c_src/crypto.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index c98dacc3eb..ea0bb10cb7 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -363,13 +363,20 @@ static ERL_NIF_TERM atom_none; static ERL_NIF_TERM atom_notsup; static ERL_NIF_TERM atom_digest; +/* +#define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n") +#define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1) +*/ +#define PRINTF_ERR0(FMT) +#define PRINTF_ERR1(FMT,A1) + static int change_basename(char* buf, int bufsz, const char* newfile) { char* p = strrchr(buf, '/'); p = (p == NULL) ? buf : p + 1; if ((p - buf) + strlen(newfile) >= bufsz) { - /*fprintf(stderr, "CRYPTO: lib name too long\r\n");*/ + PRINTF_ERR0("CRYPTO: lib name too long"); return 0; } strcpy(p, newfile); @@ -378,7 +385,7 @@ static int change_basename(char* buf, int bufsz, const char* newfile) static void error_handler(void* null, const char* errstr) { - /*fprintf(stderr, "CRYPTO LOADING ERROR: '%s'\r\n", errstr);*/ + PRINTF_ERR1("CRYPTO LOADING ERROR: '%s'", errstr); } static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) @@ -401,7 +408,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) || vernum != 201 || enif_get_string(env, tpl_array[1], lib_buf, sizeof(lib_buf), ERL_NIF_LATIN1) <= 0) { - /*enif_fprintf(stderr, "CRYPTO: Invalid load_info '%T'\n", load_info);*/ + PRINTF_ERR1("CRYPTO: Invalid load_info '%T'", load_info); return 0; } if (library_refc > 0) { @@ -461,7 +468,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) ccb = (*funcp)(nlocks); if (!ccb || ccb->sizeof_me != sizeof(*ccb)) { - /*fprintf(stderr, "Invalid 'crypto_callbacks'\r\n");*/ + PRINTF_ERR0("Invalid 'crypto_callbacks'"); return 0; } -- cgit v1.2.3 From b7b4abaeac8e559a3a4f587d46dc0014332b517e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 22 Oct 2012 18:22:23 +0200 Subject: crypto: Link crypto_callback statically if static linking of openssl is used. --- lib/crypto/c_src/Makefile.in | 15 ++++++++++++--- lib/crypto/c_src/crypto.c | 30 ++++++++++++++++++------------ lib/crypto/c_src/crypto_callback.c | 2 ++ lib/crypto/c_src/crypto_callback.h | 4 ++++ 4 files changed, 36 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in index f7e2193cec..e19d6617f3 100644 --- a/lib/crypto/c_src/Makefile.in +++ b/lib/crypto/c_src/Makefile.in @@ -59,8 +59,6 @@ TYPE_FLAGS = $(CFLAGS) endif endif -ALL_CFLAGS = $(TYPE_FLAGS) $(INCLUDES) - # ---------------------------------------------------- # Release directory specification # ---------------------------------------------------- @@ -89,11 +87,18 @@ DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@ ifeq ($(DYNAMIC_CRYPTO_LIB),yes) SSL_DED_LD_RUNTIME_LIBRARY_PATH = @SSL_DED_LD_RUNTIME_LIBRARY_PATH@ CRYPTO_LINK_LIB=$(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -l$(SSL_CRYPTO_LIBNAME) +EXTRA_FLAGS = -DHAVE_DYNAMIC_CRYPTO_LIB else SSL_DED_LD_RUNTIME_LIBRARY_PATH= CRYPTO_LINK_LIB=$(SSL_LIBDIR)/lib$(SSL_CRYPTO_LIBNAME).a +EXTRA_FLAGS = +CRYPTO_OBJS := $(CRYPTO_OBJS) $(CALLBACK_OBJS) +CALLBACK_OBJS = +CALLBACK_LIB = endif +ALL_CFLAGS = $(TYPE_FLAGS) $(EXTRA_FLAGS) $(INCLUDES) + # ---------------------------------------------------- # Targets # ---------------------------------------------------- @@ -114,6 +119,7 @@ $(LIBDIR)/crypto$(TYPEMARKER).dll: $(CRYPTO_OBJS) $(INSTALL_DIR) $(LIBDIR) $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(CRYPTO_OBJS) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME) +ifeq ($(DYNAMIC_CRYPTO_LIB),yes) $(LIBDIR)/crypto_callback$(TYPEMARKER).so: $(CALLBACK_OBJS) $(INSTALL_DIR) $(LIBDIR) $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) @@ -121,6 +127,7 @@ $(LIBDIR)/crypto_callback$(TYPEMARKER).so: $(CALLBACK_OBJS) $(LIBDIR)/crypto_callback$(TYPEMARKER).dll: $(CALLBACK_OBJS) $(INSTALL_DIR) $(LIBDIR) $(LD) $(LDFLAGS) -o $@ $(CALLBACK_OBJS) +endif clean: @@ -157,9 +164,11 @@ release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" $(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj" - $(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib" +ifeq ($(DYNAMIC_CRYPTO_LIB),yes) + $(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj" $(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib" +endif release_docs_spec: diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index ea0bb10cb7..5dc088dcff 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -370,6 +370,7 @@ static ERL_NIF_TERM atom_digest; #define PRINTF_ERR0(FMT) #define PRINTF_ERR1(FMT,A1) +#ifdef HAVE_DYNAMIC_CRYPTO_LIB static int change_basename(char* buf, int bufsz, const char* newfile) { char* p = strrchr(buf, '/'); @@ -387,12 +388,11 @@ static void error_handler(void* null, const char* errstr) { PRINTF_ERR1("CRYPTO LOADING ERROR: '%s'", errstr); } +#endif /* HAVE_DYNAMIC_CRYPTO_LIB */ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) { ErlNifSysInfo sys_info; - const char callback_lib[] = "crypto_callback"; - void* handle; get_crypto_callbacks_t* funcp; struct crypto_callbacks* ccb; int nlocks = 0; @@ -445,17 +445,23 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) init_digest_types(env); - if (!change_basename(lib_buf, sizeof(lib_buf), callback_lib)) { - return 0; - } - - if (!(handle = enif_dlopen(lib_buf, &error_handler, NULL))) { - return 0; - } - if (!(funcp = (get_crypto_callbacks_t*) enif_dlsym(handle, "get_crypto_callbacks", - &error_handler, NULL))) { - return 0; +#ifdef HAVE_DYNAMIC_CRYPTO_LIB + { + void* handle; + if (!change_basename(lib_buf, sizeof(lib_buf), "crypto_callback")) { + return 0; + } + if (!(handle = enif_dlopen(lib_buf, &error_handler, NULL))) { + return 0; + } + if (!(funcp = (get_crypto_callbacks_t*) enif_dlsym(handle, "get_crypto_callbacks", + &error_handler, NULL))) { + return 0; + } } +#else /* !HAVE_DYNAMIC_CRYPTO_LIB */ + funcp = &get_crypto_callbacks; +#endif #ifdef OPENSSL_THREADS enif_system_info(&sys_info, sizeof(sys_info)); diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index 32e690a8d1..81106b4cc2 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -156,8 +156,10 @@ DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks) return &the_struct; } +#ifdef HAVE_DYNAMIC_CRYPTO_LIB /* This is not really a NIF library, but we use ERL_NIF_INIT in order to * get access to the erl_nif API (on Windows). */ ERL_NIF_INIT(dummy, (ErlNifFunc*)NULL , NULL, NULL, NULL, NULL) +#endif diff --git a/lib/crypto/c_src/crypto_callback.h b/lib/crypto/c_src/crypto_callback.h index a0c828b502..23ecba3e5d 100644 --- a/lib/crypto/c_src/crypto_callback.h +++ b/lib/crypto/c_src/crypto_callback.h @@ -40,3 +40,7 @@ struct crypto_callbacks typedef struct crypto_callbacks* get_crypto_callbacks_t(int nlocks); +#ifndef HAVE_DYNAMIC_CRYPTO_LIB +struct crypto_callbacks* get_crypto_callbacks(int nlocks); +#endif + -- cgit v1.2.3