OpenSSL BN_CTX usage

Here I am answering my own question. I guess it happens all the time in SO.

BIGNUM in OpenSSL is a complicated structure that holds an arbitrarily big number, and hence creating and freeing BIGNUM instances repeatedly will result in a considerable overhead. BIGNUM context, or BN_CTX, is created and used to save this overhead.

Structure

The BN_CTX structure contains two structures: BN_POOL and BN_STACK. The BN_POOL keeps a bundle of temporary bignums with a linked-list, while the BN_STACK manages the stack frame.

On Create

BN_CTX instance ctx is created with BN_CTX_new(). A function must call BN_CTX_start() to get a new stack frame first. By calling BN_CTX_get(ctx), OpenSSL looks for an unused bignum in the BN_POOL of ctx. If there isn't any available temp bignum, OpenSSL will create one and link to the linked-list. This must be done before passing ctx as argument to other functions.

Of course there's a mechanism for preventing user creating too many temporary bignums. The predefined number of bignums you can create within a BN_POOL is 16. Once the limit is exceeded, probable segmentation fault will occur at random location in OpenSSL library.

On Exit

After the function is done with the BIGNUM instance it got from ctx and is ready to exit,BN_CTX_end() is called to release temporary bignums, meaning that these bignums become "unused" and can be requested by the next BN_CTX_get().

Finally, probably after several times of BN_CTX_start() and BN_CTX_end()BN_CTX_end() is called to free BN_STACK structure, and clear free bignums in BN_POOL.

Example Code

void foo(){
    BN_CTX* ctx;
    ctx = BN_CTX_new();

    /* Using BIGNUM context in a series of BIGNUM operations */
    bar(ctx);
    bar(ctx);
    bar(ctx);

    /* Using BIGNUM context in a function called in loops */
    while(/*condition*/){
        bar(ctx);
    }

    BN_CTX_free(ctx);
}

And here's the function bar( )

void bar(BN_CTX* ctx){
    BIGNUM *bn;
    BN_CTX_start(ctx);
    bn = BN_CTX_get(ctx);

    /* Do something with bn */

    BN_CTX_end(ctx);
}

The function foo() creates a new BIGNUM context and pass it as argument to function bar(). Upon the first time bar() calls BN_CTX_get(), a temporary bignum is created and stored in the BN_POOL and is returned. BN_CTX_get() in the subsequent bar() will not create new bignum but instead returns the one it created in the first place. This temporary bignum will finally be clear-freed by BN_CTX_free() in foo().

Conclusion

When performance is in concern, use BN_CTX to save the overhead of BIGNUM creation by passing it to functions that

  1. require BIGNUM structures to hold temporary big numbers, and
  2. are called sequentially to perform certain bignum operations, or
  3. are repeatedly called in loops.

Be aware that there is a limitation for the number of bignums stored in BN_CTX. If performance is not an issue, then using

bn = BN_new();
if (bn)
    BN_free(bn);

is just fine.

转载自:http://stackoverflow.com/questions/16437475/openssl-bn-ctx-usage/16578756#16578756

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值