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.

Reply via email to