2013-05-08 2 views
9

De here Je comprends que BN_CTX est une structure qui contient des variables temporaires BIGNUM. Quand ces variables BIGNUM entreront-elles dans BN_POOL de BN_CTX? Si j'ai un bignum_ctx BN_CTX *ctx; (soit déclaré en haut de ma fonction, ou passée en argument), quand dois-je faireUtilisation d'OpenSSL BN_CTX

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

et quand dois-je faire ce qui suit à la place?

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

Et si j'ai un bignum BIGNUM *bn;, dans quelles circonstances dois-je utiliser

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

au lieu de l'instance tout nouveau et libre?

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

Répondre

15

Ici, je réponds à ma propre question. Je suppose que cela arrive tout le temps dans SO. BIGNUM dans OpenSSL est une structure compliquée qui contient un nombre arbitrairement grand, et donc créer et libérer des instances BIGNUM de manière répétée entraînera un surcoût considérable. Le contexte BIGNUM, ou BN_CTX, est créé et utilisé pour enregistrer cette surcharge.

Structure

La structure BN_CTX contient deux structures: BN_POOL et BN_STACK. Le BN_POOL conserve un ensemble de bignums temporaires avec une liste liée, tandis que le BN_STACK gère le cadre de pile.

sur Créer

Un exemple BN_CTXctx est créé avec BN_CTX_new(). Une fonction doit appeler BN_CTX_start() pour obtenir une nouvelle trame de pile en premier. En appelant BN_CTX_get(ctx), OpenSSL cherche un bignum inutilisé dans le BN_POOL de ctx. S'il n'y a pas de temp bignum disponible, OpenSSL en crée un et le lie à la liste liée. Cela doit être fait avant de passer ctx comme argument à d'autres fonctions.

Bien sûr, il existe un mécanisme pour empêcher l'utilisateur de créer trop de bignums temporaires. Le nombre prédéfini de bignums que vous pouvez créer dans un BN_POOL est 16. Une fois la limite dépassée, une erreur de segmentation probable se produira au hasard dans la bibliothèque OpenSSL.

Sur la sortie

Une fois la fonction se fait avec l'instance BIGNUM il a obtenu de ctx et est prêt à sortir, BN_CTX_end() est appelé à libérer bignums temporaires, ce qui signifie que ces bignums deviennent « inutilisées » et peuvent être demandé par le prochain BN_CTX_get().

Enfin, probablement après plusieurs reprises de BN_CTX_start() et BN_CTX_end(), BN_CTX_end() est appelé à libérer la structure BN_STACK et bignums libres claires dans BN_POOL.

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

Et voici la fonction 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); 
} 

La fonction foo() crée un nouveau contexte de BIGNUM et passer comme argument pour fonctionner bar(). Lors de la première fois bar() appelle BN_CTX_get(), un bignum temporaire est créé et stocké dans le BN_POOL et est retourné. BN_CTX_get() dans le prochain bar() ne créera pas de nouveau bignum mais à la place renvoie celui qu'il a créé en premier lieu. Ce bignum temporaire sera finalement libéré par BN_CTX_free() en foo().

Conclusion

Quand la performance est dans le souci, utilisez BN_CTX pour sauver la tête de la création BIGNUM en le faisant passer à des fonctions qui

  1. supposera des structures Bignum pour tenir des numéros temporaires grands et
  2. sont appelés séquentiellement pour effectuer certaines opérations bignum, ou
  3. sont appelés à plusieurs reprises dans des boucles. Sachez qu'il y a une limitation pour le nombre de bignums stockés dans BN_CTX

Si les performances ne sont pas un problème, l'utilisation de

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

est très bien.

+1

À quoi sert le cadre de la pile? – updogliu

+0

Puisqu'un objet BN_CTX 'ctx' peut passer des fonctions aux fonctions, le cadre de la pile est un tas d'information utilisé pour suivre la profondeur de ces appels de fonction (qui passent' ctx' comme argument), et la taille de la mémoire allouée à 'ctx'. – ChiaraHsieh

+0

Je suppose que c'est pour libérer des variables tmp fonction par fonction. S'il y a une fonction utilise deux tmp BIGNUMs 'bn1 = BN_CTX_get (ctx); bn2 = BN_CTX_get (ctx); 'Il n'y a aucun moyen (pour moi) de libérer 'bn1' mais pas' bn2'. Ils ne peuvent être sortis ensemble que sur BN_CTX_end. L'information de cadre de pile est de se rappeler que cette fonction utilise deux tmps 'bn1' et' bn2', je devine. – updogliu