Search code examples
c++pointersopensslallocation

BN_CTX_free() vs BN_CTX_end() EXC_BAD_ACCESS exception


From the OpenSSL docs, BN_CTX_end() must be called before BN_CTX_free(), however in the example below, I get a bad access exception when I run the program in the order specified by the docs (note the docs say in most cases, yet I'm unsure how to check if I should call BN_CTX_end() before BN_CTX_free())

BIGNUM* util::math::find_seed_num(std::vector<int> lst, int lst_int, int index) {
    //python: reduce((lambda x, y: x * y), lst[0:index]) % lst_int

    BN_CTX* ctx;
    ctx = BN_CTX_new();

    cout << "\nsize of lst " << lst.size() << "\n";
    BIGNUM *sum = BN_new();
    BIGNUM *tmp = BN_new();

    sum = BN_CTX_get(ctx);
    BN_set_word(sum, lst[0]);

    cout << "\n index: " << index << "\n";

    for (int a = 1; a < index; a = a + 1) {
        BN_set_word(tmp, lst[a]);
        cout << "temp = " << BN_bn2dec(tmp) << "\n";
        BN_mul(sum, sum, tmp, ctx);
        cout << "sum = " << BN_bn2dec(sum) << "\n";
    }

    BIGNUM *result = BN_new();
    BIGNUM *modulo = BN_new();

    BN_set_word(modulo, lst_int);

    BN_nnmod(result, sum, modulo, ctx);

    cout << "\nsum: " << BN_bn2dec(result) << "\n";

    BN_free(sum);
    BN_free(result);
    BN_free(modulo);
    BN_free(tmp);
    BN_CTX_end(ctx); //Running this produces the exception
    BN_CTX_free(ctx); //Running this w/out the above line leads to no exception thrown

    return result;
}

I'm new to C++, thus my worry is that the context isn't being deallocated properly if BN_CTX_end(); isn't called.


Solution

  • I am no expert of OpenSSL, but the documentation says

    A function must call BN_CTX_start() first. Then, BN_CTX_get() may be called repeatedly to obtain temporary BIGNUMs. All BN_CTX_get() calls must be made before calling any other functions that use the ctx as an argument.

    Finally, BN_CTX_end() must be called

    So try adding a BN_CTX_start at the beginning after BN_CTX_new (see https://www.openssl.org/docs/man1.0.2/man3/BN_CTX_start.html)

    Secondly, from the doc:

    When BN_CTX_end() is called, the BIGNUM pointers obtained from BN_CTX_get() become invalid.

    So you might want to try to avoid freeing sum because it will (at least as far as I know) be freed once you call BN_CTX_end()

    Lastly (minor issue):

    BIGNUM *sum = BN_new();
    ....
    sum = BN_CTX_get(ctx);
    

    First you allocate a BIGNUM, then you overwrite the pointer with another pointer to another memory location. You therefore lose the pointer, creating a memory leak, consider using either BN_new() (in that case you must free) or BN_CTX_get

    I tried to compile with MSVC 2019 and calling BN_CTX_start() already fixed the issue for me.