X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fbn%2Fbn_ctx.c;h=f48055b268b9761ced40a9e8e274df64ef5adcc6;hp=8b079e237f1b569995ff630898a2e725fea6a04f;hb=9e051bac139ce07f846d88b90f3ec514c39ea416;hpb=9b141126d4b6f0636bc047e81b846c193ae26611 diff --git a/crypto/bn/bn_ctx.c b/crypto/bn/bn_ctx.c index 8b079e237f..f48055b268 100644 --- a/crypto/bn/bn_ctx.c +++ b/crypto/bn/bn_ctx.c @@ -54,17 +54,55 @@ * */ +#if !defined(BN_CTX_DEBUG) && !defined(BN_DEBUG) +#ifndef NDEBUG +#define NDEBUG +#endif +#endif + #include #include + #include "cryptlib.h" -#include +#include "bn_lcl.h" + +/* BN_CTX structure details */ +#define BN_CTX_NUM 32 +#define BN_CTX_NUM_POS 12 +struct bignum_ctx + { + int tos; + BIGNUM bn[BN_CTX_NUM]; + int flags; + int depth; + int pos[BN_CTX_NUM_POS]; + int too_many; + }; +#ifndef OPENSSL_NO_DEPRECATED +void BN_CTX_init(BN_CTX *ctx) +#else +static void BN_CTX_init(BN_CTX *ctx) +#endif + { +#if 0 /* explicit version */ + int i; + ctx->tos = 0; + ctx->flags = 0; + ctx->depth = 0; + ctx->too_many = 0; + for (i = 0; i < BN_CTX_NUM; i++) + BN_init(&(ctx->bn[i])); +#else + memset(ctx, 0, sizeof *ctx); +#endif + } BN_CTX *BN_CTX_new(void) { BN_CTX *ret; - ret=(BN_CTX *)Malloc(sizeof(BN_CTX)); + ret=(BN_CTX *)OPENSSL_malloc(sizeof(BN_CTX)); if (ret == NULL) { BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE); @@ -76,16 +114,6 @@ BN_CTX *BN_CTX_new(void) return(ret); } -void BN_CTX_init(BN_CTX *ctx) - { - int i; - ctx->tos = 0; - ctx->flags = 0; - ctx->depth = 0; - for (i = 0; i < BN_CTX_NUM; i++) - BN_init(&(ctx->bn[i])); - } - void BN_CTX_free(BN_CTX *ctx) { int i; @@ -93,31 +121,64 @@ void BN_CTX_free(BN_CTX *ctx) if (ctx == NULL) return; assert(ctx->depth == 0); - for (i=0; i < BN_CTX_NUM; i++) - BN_clear_free(&(ctx->bn[i])); + for (i=0; i < BN_CTX_NUM; i++) { + bn_check_top(&(ctx->bn[i])); + if (ctx->bn[i].d) + BN_clear_free(&(ctx->bn[i])); + } if (ctx->flags & BN_FLG_MALLOCED) - Free(ctx); + OPENSSL_free(ctx); } void BN_CTX_start(BN_CTX *ctx) { - ctx->pos[ctx->depth++] = ctx->tos; + if (ctx->depth < BN_CTX_NUM_POS) + ctx->pos[ctx->depth] = ctx->tos; + ctx->depth++; } + BIGNUM *BN_CTX_get(BN_CTX *ctx) { - if (ctx->tos >= BN_CTX_NUM) + BIGNUM *ret; + /* Note: If BN_CTX_get is ever changed to allocate BIGNUMs dynamically, + * make sure that if BN_CTX_get fails once it will return NULL again + * until BN_CTX_end is called. (This is so that callers have to check + * only the last return value.) + */ + if (ctx->depth > BN_CTX_NUM_POS || ctx->tos >= BN_CTX_NUM) { - BNerr(BN_F_BN_CTX_GET,BN_R_TOO_MANY_TEMPORARY_VARIABLES); + if (!ctx->too_many) + { + BNerr(BN_F_BN_CTX_GET,BN_R_TOO_MANY_TEMPORARY_VARIABLES); + /* disable error code until BN_CTX_end is called: */ + ctx->too_many = 1; + } return NULL; } - return (&(ctx->bn[ctx->tos++])); + ret = ctx->bn + (ctx->tos++); + /* always return a 'zeroed' bignum */ + BN_zero(ret); + return ret; } void BN_CTX_end(BN_CTX *ctx) { if (ctx == NULL) return; assert(ctx->depth > 0); + if (ctx->depth == 0) + /* should never happen, but we can tolerate it if not in + * debug mode (could be a 'goto err' in the calling function + * before BN_CTX_start was reached) */ + BN_CTX_start(ctx); + + ctx->too_many = 0; ctx->depth--; - ctx->tos = ctx->pos[ctx->depth]; + if (ctx->depth < BN_CTX_NUM_POS) +#ifndef BN_DEBUG + ctx->tos = ctx->pos[ctx->depth]; +#else + while(ctx->tos > ctx->pos[ctx->depth]) + bn_check_top(&ctx->bn[--(ctx->tos)]); +#endif }