I fixed the problem. I'm listing it here in case someone else runs into this:
In the loadEngine() I call ENGINE_set_default(). I have to the opposite when unloading my engine. Unfortunately, I could not find any "ENGINE_unset_default()" or "ENGINE_unregister_all()" so I had to explicitly unregister my method pointers. So my new unloadEngine looks like the following: void unloadEngine(ENGINE *e) { ENGINE_unregister_pkey_asn1_meths(e); ENGINE_unregister_pkey_meths(e); ENGINE_unregister_RSA(e); ENGINE_remove(e); /* Release the functional reference from ENGINE_init() */ ENGINE_finish(e); /* Release the structural reference from ENGINE_by_id() */ ENGINE_free(e); } On 10-08-13 09:23 AM, Jeff Saremi wrote: > I'm trying to use my custom engine however I cannot get it to clean up > nicely. > For the initialization i used the sample in openssl ENGINE(3) documentation. > > Here's how it goes: > > ENGINE *loadEngine() > { > ENGINE *e; > e = ENGINE_by_id(MY_ENGINE_ID); > if(!e) > ENGINE_load_my(); > e = ENGINE_by_id(MY_ENGINE_ID); /* try again */ > if(!e) > /* the engine isn't available */ > return NULL; > if(!ENGINE_init(e)) { > /* the engine couldn't initialise, release 'e' */ > ENGINE_free(e); > return NULL; > } > ENGINE_set_default(e, ENGINE_METHOD_ALL); > return e; > } > void unloadEngine(ENGINE *e) > { > /* Release the functional reference from ENGINE_init() */ > ENGINE_finish(e); > /* Release the structural reference from ENGINE_by_id() */ > ENGINE_free(e); > /* ENGINE_cleanup(); my engine_finish method does not get > called unless I include this line */ > } > void testKeyGen() > { > /* some openssl initialization code such as loading ciphers, > algorithms, existing engines, establishing dynamic locks and so on */ > > ENGINE *e = loadEngine(); > ASSERT(e, "could not create the engine\n"); > EVP_PKEY *pkey = NULL; > genPKey(e, &pkey); /* some calls to EVP_PKEY_CTX_new_id, > EVP_PKEY_keygen and so on */ > ASSERT(pkey, "could not generate PKEY\n"); > > /* so far so good */ > if(pkey) > EVP_PKEY_free(pkey); > > unloadEngine(e); > /* at the end of this I have unfreed memory (the dynamic lock I > created in my engine because my_finish was not called */ > } > > And here's my engine initialization and deinit routines. I stepped > through the code in ENGINE_finish() and realized that the following line > (to_return = e->finish(e); ) does not get executed because apparently > the ref count is not zero: > > ********* file openssl/crypto/engine/eng_init.c ************** > int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers) > { > if((e->funct_ref == 0) && e->finish) > { > if(unlock_for_handlers) > CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); > to_return = e->finish(e); > if(unlock_for_handlers) > CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); > if(!to_return) > return 0; > ... > } > > ********* continuation of my code -- my engine init routines ********* > > static int my_init(ENGINE *e) > { > ERR_load_MY_strings(); > my_lock_id = CRYPTO_get_new_dynlockid(); > ... > return 1; > } > static int my_finish(ENGINE *e) > { > ERR_unload_MY_strings(); > CRYPTO_destroy_dynlockid(my_lock_id); > return 1; > } > static int bind_helper(ENGINE *e) > { > ... > if (!ENGINE_set_id(e, MY_ENGINE_ID) > || !ENGINE_set_name(e, MY_ENGINE_NAME) > || !ENGINE_set_destroy_function(e, my_destroy) > || !ENGINE_set_init_function(e, my_init) > || !ENGINE_set_finish_function(e, my_finish) > ... > return 0; > return 1; > } > static ENGINE *engine_my(void) > { > ENGINE *ret = ENGINE_new(); > if (!ret) > return NULL; > if (!bind_helper(ret)) > { > ENGINE_free(ret); > return NULL; > } > return ret; > } > void ENGINE_load_my(void) > { > ENGINE *toadd = engine_my(); > if (!toadd) > return; > ENGINE_add(toadd); > ENGINE_free(toadd); > ERR_clear_error(); > } > > > > > > This email contains Morega Systems Inc. Privileged and Confidential > information. This email contains Morega Systems Inc. Privileged and Confidential information.