Search code examples
c++memory-managementopenssldiffie-hellman

DH_free precise behavior


I'm using openssl, specifically the DH and BIGNUM libraries, to implement my own Diffie Hellman key exchange process, and I have some concerns about how it works.

The documentation I've been able to find, mostly here, hasn't been as accurate as I might have hoped. My question is about how DH_free works. Is it more or less a wrapper on free, or does openssl have its own internal functions that handle memory management? What happens when DH_free gets called on a null pointer?


Solution

  • My question is about how DH_free works. Is it more or less a wrapper on free, or does openssl have its own internal functions that handle memory management? What happens when DH_free gets called on a null pointer?

    When all else fails, go to the source.

    $ cd openssl-1.0.1h
    $ grep -R DH_free * | grep void
    crypto/dh/dh.h:void DH_free(DH *dh);
    crypto/dh/dh_lib.c:void DH_free(DH *r)
    doc/crypto/dh.pod: void DH_free(DH *dh);
    doc/crypto/DH_new.pod: void DH_free(DH *dh);
    

    The implementation is located in dh_lib.c. Below is the cleaned up version (some #defines were removed, and the source code was formatted):

    void DH_free(DH *r)
    {
        int i;
        if(r == NULL) return;
    
        i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH);
        if (i > 0) return;
    
        if (r->meth->finish)
            r->meth->finish(r);
    
    #ifndef OPENSSL_NO_ENGINE
        if (r->engine)
            ENGINE_finish(r->engine);
    #endif
    
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
    
        if (r->p != NULL) BN_clear_free(r->p);
        if (r->g != NULL) BN_clear_free(r->g);
        if (r->q != NULL) BN_clear_free(r->q);
        if (r->j != NULL) BN_clear_free(r->j);
        if (r->seed) OPENSSL_free(r->seed);
        if (r->counter != NULL) BN_clear_free(r->counter);
        if (r->pub_key != NULL) BN_clear_free(r->pub_key);
        if (r->priv_key != NULL) BN_clear_free(r->priv_key);
        OPENSSL_free(r);
    }