2013-05-08 2103 views
9

here我知道BN_CTX是一个保存BIGNUM临时变量的结构。这些BIGNUM变量何时会输入BN_CTX的BN_POOL?如果我有BN_CTX *ctx;(无论是在我的函数的顶部声明,或通过作为参数)一bignum_ctx,当我应该做的OpenSSL BN_CTX用法

ctx = BN_CTX_new(); 
/* Do something */ 
BN_CTX_free(ctx); 

,而是当我应该做到以下几点?

BN_CTX_start(ctx); 
/* Do something */ 
BN_CTX_end(ctx); 

而且如果我有一个BIGNUM BIGNUM *bn;,在什么情况下我应该使用

BN_CTX_start(ctx); 
bn = BN_CTX_get(ctx); 
BN_CTX_end(ctx); 

,而不只是新的和免费的实例?

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

回答

15

这里我回答我自己的问题。我想这一直发生在所以。

OpenSSL中的BIGNUM是一个复杂的结构,它保存了一个任意大的数字,因此反复创建和释放BIGNUM实例会导致相当大的开销。 BIGNUM上下文或BN_CTX被创建并用于保存此开销。

结构

的BN_CTX结构包含两种结构:BN_POOLBN_STACKBN_POOL用一个链接列表保留一组临时的bignum,而BN_STACK管理这个栈帧。

上创建

一个BN_CTX例如ctxBN_CTX_new()创建。函数必须先调用BN_CTX_start()才能获得新的堆栈帧。通过调用BN_CTX_get(ctx),OpenSSL在ctxBN_POOL中查找未使用的bignum。如果没有任何可用的临时数字,OpenSSL将创建一个并链接到链接列表。这必须在通过ctx作为其他功能的参数之前完成。

当然有一种机制可以防止用户创建太多的临时牌。您可以在BN_POOL中创建的预定义数字的个数为16.一旦超出限制,可能的分段错误将发生在OpenSSL库中的随机位置。

在退出

功能后与BIGNUM实例从ctx了,并准备退出做,BN_CTX_end()被调用,以释放临时大数,这意味着这些大数成为“未使用”,可以是请求下一个BN_CTX_get()

最后,也许以后的BN_CTX_start()BN_CTX_end()几次,BN_CTX_end()被称为自由BN_STACK结构,明确免费大数在BN_POOL

示例代码

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); 
} 

而这里的功能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); 
} 

功能foo()创建一个新的BIGNUM上下文并把它作为参数传递给函数bar()。在第一次bar()调用BN_CTX_get()时,会创建一个临时的bignum并存储在BN_POOL中并返回。 BN_CTX_get()在随后的bar()中不会创建新的bignum,而是返回它首先创建的那个。这个临时性质将在foo()中被BN_CTX_free()最终清除。

结论

当性能是关注的,使用BN_CTX通过将其传递到

  1. 需要BIGNUM结构保存临时大数字功能,以节省BIGNUM创建的开销,以及
  2. 被顺序调用来执行某些bignum操作,或者
  3. 在循环中被重复调用。

请注意,存储在BN_CTX中的双子的数量存在限制。如果性能不是问题,那么使用

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

就好。

+1

什么是堆栈帧? – updogliu 2013-12-30 06:47:56

+0

由于一个BN_CTX对象'ctx'可以从函数传递给函数,栈帧是用来追踪这些函数调用深度的信息(它传递'ctx'作为参数)以及分配给内存的大小'ctx'。 – ChiaraHsieh 2013-12-30 07:06:46

+0

我想这是释放tmp变量函数的功能。如果有一个函数使用了两个tmp BIGNUM'bn1 = BN_CTX_get(ctx); bn2 = BN_CTX_get(ctx);'对我来说,释放'bn1'而不是'bn2'是没有办法的。它们只能在BN_CTX_end上一起发布。栈帧信息是要记住这个函数使用了两个tmps'bn1'和'bn2',我猜。 – updogliu 2013-12-30 15:48:02