xref: /onnv-gate/usr/src/common/openssl/crypto/bn/bn_ctx.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* crypto/bn/bn_ctx.c */
20Sstevel@tonic-gate /* Written by Ulf Moeller for the OpenSSL project. */
30Sstevel@tonic-gate /* ====================================================================
4*2139Sjp161948  * Copyright (c) 1998-2004 The OpenSSL Project.  All rights reserved.
50Sstevel@tonic-gate  *
60Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
70Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
80Sstevel@tonic-gate  * are met:
90Sstevel@tonic-gate  *
100Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
110Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
140Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
150Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
160Sstevel@tonic-gate  *    distribution.
170Sstevel@tonic-gate  *
180Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
190Sstevel@tonic-gate  *    software must display the following acknowledgment:
200Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
210Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
240Sstevel@tonic-gate  *    endorse or promote products derived from this software without
250Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
260Sstevel@tonic-gate  *    openssl-core@openssl.org.
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
290Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
300Sstevel@tonic-gate  *    permission of the OpenSSL Project.
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
330Sstevel@tonic-gate  *    acknowledgment:
340Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
350Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
360Sstevel@tonic-gate  *
370Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
380Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
390Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
400Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
410Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
420Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
430Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
440Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
450Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
460Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
470Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
480Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
490Sstevel@tonic-gate  * ====================================================================
500Sstevel@tonic-gate  *
510Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
520Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
530Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
540Sstevel@tonic-gate  *
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate 
57*2139Sjp161948 #if !defined(BN_CTX_DEBUG) && !defined(BN_DEBUG)
58*2139Sjp161948 #ifndef NDEBUG
59*2139Sjp161948 #define NDEBUG
60*2139Sjp161948 #endif
610Sstevel@tonic-gate #endif
620Sstevel@tonic-gate 
630Sstevel@tonic-gate #include <stdio.h>
640Sstevel@tonic-gate #include <assert.h>
650Sstevel@tonic-gate 
660Sstevel@tonic-gate #include "cryptlib.h"
670Sstevel@tonic-gate #include "bn_lcl.h"
680Sstevel@tonic-gate 
69*2139Sjp161948 /* TODO list
70*2139Sjp161948  *
71*2139Sjp161948  * 1. Check a bunch of "(words+1)" type hacks in various bignum functions and
72*2139Sjp161948  * check they can be safely removed.
73*2139Sjp161948  *  - Check +1 and other ugliness in BN_from_montgomery()
74*2139Sjp161948  *
75*2139Sjp161948  * 2. Consider allowing a BN_new_ex() that, at least, lets you specify an
76*2139Sjp161948  * appropriate 'block' size that will be honoured by bn_expand_internal() to
77*2139Sjp161948  * prevent piddly little reallocations. OTOH, profiling bignum expansions in
78*2139Sjp161948  * BN_CTX doesn't show this to be a big issue.
79*2139Sjp161948  */
80*2139Sjp161948 
81*2139Sjp161948 /* How many bignums are in each "pool item"; */
82*2139Sjp161948 #define BN_CTX_POOL_SIZE	16
83*2139Sjp161948 /* The stack frame info is resizing, set a first-time expansion size; */
84*2139Sjp161948 #define BN_CTX_START_FRAMES	32
85*2139Sjp161948 
86*2139Sjp161948 /***********/
87*2139Sjp161948 /* BN_POOL */
88*2139Sjp161948 /***********/
89*2139Sjp161948 
90*2139Sjp161948 /* A bundle of bignums that can be linked with other bundles */
91*2139Sjp161948 typedef struct bignum_pool_item
92*2139Sjp161948 	{
93*2139Sjp161948 	/* The bignum values */
94*2139Sjp161948 	BIGNUM vals[BN_CTX_POOL_SIZE];
95*2139Sjp161948 	/* Linked-list admin */
96*2139Sjp161948 	struct bignum_pool_item *prev, *next;
97*2139Sjp161948 	} BN_POOL_ITEM;
98*2139Sjp161948 /* A linked-list of bignums grouped in bundles */
99*2139Sjp161948 typedef struct bignum_pool
100*2139Sjp161948 	{
101*2139Sjp161948 	/* Linked-list admin */
102*2139Sjp161948 	BN_POOL_ITEM *head, *current, *tail;
103*2139Sjp161948 	/* Stack depth and allocation size */
104*2139Sjp161948 	unsigned used, size;
105*2139Sjp161948 	} BN_POOL;
106*2139Sjp161948 static void		BN_POOL_init(BN_POOL *);
107*2139Sjp161948 static void		BN_POOL_finish(BN_POOL *);
108*2139Sjp161948 #ifndef OPENSSL_NO_DEPRECATED
109*2139Sjp161948 static void		BN_POOL_reset(BN_POOL *);
110*2139Sjp161948 #endif
111*2139Sjp161948 static BIGNUM *		BN_POOL_get(BN_POOL *);
112*2139Sjp161948 static void		BN_POOL_release(BN_POOL *, unsigned int);
113*2139Sjp161948 
114*2139Sjp161948 /************/
115*2139Sjp161948 /* BN_STACK */
116*2139Sjp161948 /************/
117*2139Sjp161948 
118*2139Sjp161948 /* A wrapper to manage the "stack frames" */
119*2139Sjp161948 typedef struct bignum_ctx_stack
120*2139Sjp161948 	{
121*2139Sjp161948 	/* Array of indexes into the bignum stack */
122*2139Sjp161948 	unsigned int *indexes;
123*2139Sjp161948 	/* Number of stack frames, and the size of the allocated array */
124*2139Sjp161948 	unsigned int depth, size;
125*2139Sjp161948 	} BN_STACK;
126*2139Sjp161948 static void		BN_STACK_init(BN_STACK *);
127*2139Sjp161948 static void		BN_STACK_finish(BN_STACK *);
128*2139Sjp161948 #ifndef OPENSSL_NO_DEPRECATED
129*2139Sjp161948 static void		BN_STACK_reset(BN_STACK *);
130*2139Sjp161948 #endif
131*2139Sjp161948 static int		BN_STACK_push(BN_STACK *, unsigned int);
132*2139Sjp161948 static unsigned int	BN_STACK_pop(BN_STACK *);
133*2139Sjp161948 
134*2139Sjp161948 /**********/
135*2139Sjp161948 /* BN_CTX */
136*2139Sjp161948 /**********/
137*2139Sjp161948 
138*2139Sjp161948 /* The opaque BN_CTX type */
139*2139Sjp161948 struct bignum_ctx
140*2139Sjp161948 	{
141*2139Sjp161948 	/* The bignum bundles */
142*2139Sjp161948 	BN_POOL pool;
143*2139Sjp161948 	/* The "stack frames", if you will */
144*2139Sjp161948 	BN_STACK stack;
145*2139Sjp161948 	/* The number of bignums currently assigned */
146*2139Sjp161948 	unsigned int used;
147*2139Sjp161948 	/* Depth of stack overflow */
148*2139Sjp161948 	int err_stack;
149*2139Sjp161948 	/* Block "gets" until an "end" (compatibility behaviour) */
150*2139Sjp161948 	int too_many;
151*2139Sjp161948 	};
152*2139Sjp161948 
153*2139Sjp161948 /* Enable this to find BN_CTX bugs */
154*2139Sjp161948 #ifdef BN_CTX_DEBUG
155*2139Sjp161948 static const char *ctxdbg_cur = NULL;
ctxdbg(BN_CTX * ctx)156*2139Sjp161948 static void ctxdbg(BN_CTX *ctx)
157*2139Sjp161948 	{
158*2139Sjp161948 	unsigned int bnidx = 0, fpidx = 0;
159*2139Sjp161948 	BN_POOL_ITEM *item = ctx->pool.head;
160*2139Sjp161948 	BN_STACK *stack = &ctx->stack;
161*2139Sjp161948 	fprintf(stderr,"(%08x): ", (unsigned int)ctx);
162*2139Sjp161948 	while(bnidx < ctx->used)
163*2139Sjp161948 		{
164*2139Sjp161948 		fprintf(stderr,"%02x ", item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax);
165*2139Sjp161948 		if(!(bnidx % BN_CTX_POOL_SIZE))
166*2139Sjp161948 			item = item->next;
167*2139Sjp161948 		}
168*2139Sjp161948 	fprintf(stderr,"\n");
169*2139Sjp161948 	bnidx = 0;
170*2139Sjp161948 	fprintf(stderr,"          : ");
171*2139Sjp161948 	while(fpidx < stack->depth)
172*2139Sjp161948 		{
173*2139Sjp161948 		while(bnidx++ < stack->indexes[fpidx])
174*2139Sjp161948 			fprintf(stderr,"   ");
175*2139Sjp161948 		fprintf(stderr,"^^ ");
176*2139Sjp161948 		bnidx++;
177*2139Sjp161948 		fpidx++;
178*2139Sjp161948 		}
179*2139Sjp161948 	fprintf(stderr,"\n");
180*2139Sjp161948 	}
181*2139Sjp161948 #define CTXDBG_ENTRY(str, ctx)	do { \
182*2139Sjp161948 				ctxdbg_cur = (str); \
183*2139Sjp161948 				fprintf(stderr,"Starting %s\n", ctxdbg_cur); \
184*2139Sjp161948 				ctxdbg(ctx); \
185*2139Sjp161948 				} while(0)
186*2139Sjp161948 #define CTXDBG_EXIT(ctx)	do { \
187*2139Sjp161948 				fprintf(stderr,"Ending %s\n", ctxdbg_cur); \
188*2139Sjp161948 				ctxdbg(ctx); \
189*2139Sjp161948 				} while(0)
190*2139Sjp161948 #define CTXDBG_RET(ctx,ret)
191*2139Sjp161948 #else
192*2139Sjp161948 #define CTXDBG_ENTRY(str, ctx)
193*2139Sjp161948 #define CTXDBG_EXIT(ctx)
194*2139Sjp161948 #define CTXDBG_RET(ctx,ret)
195*2139Sjp161948 #endif
196*2139Sjp161948 
197*2139Sjp161948 /* This function is an evil legacy and should not be used. This implementation
198*2139Sjp161948  * is WYSIWYG, though I've done my best. */
199*2139Sjp161948 #ifndef OPENSSL_NO_DEPRECATED
BN_CTX_init(BN_CTX * ctx)200*2139Sjp161948 void BN_CTX_init(BN_CTX *ctx)
201*2139Sjp161948 	{
202*2139Sjp161948 	/* Assume the caller obtained the context via BN_CTX_new() and so is
203*2139Sjp161948 	 * trying to reset it for use. Nothing else makes sense, least of all
204*2139Sjp161948 	 * binary compatibility from a time when they could declare a static
205*2139Sjp161948 	 * variable. */
206*2139Sjp161948 	BN_POOL_reset(&ctx->pool);
207*2139Sjp161948 	BN_STACK_reset(&ctx->stack);
208*2139Sjp161948 	ctx->used = 0;
209*2139Sjp161948 	ctx->err_stack = 0;
210*2139Sjp161948 	ctx->too_many = 0;
211*2139Sjp161948 	}
212*2139Sjp161948 #endif
2130Sstevel@tonic-gate 
BN_CTX_new(void)2140Sstevel@tonic-gate BN_CTX *BN_CTX_new(void)
2150Sstevel@tonic-gate 	{
216*2139Sjp161948 	BN_CTX *ret = OPENSSL_malloc(sizeof(BN_CTX));
217*2139Sjp161948 	if(!ret)
2180Sstevel@tonic-gate 		{
2190Sstevel@tonic-gate 		BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE);
220*2139Sjp161948 		return NULL;
2210Sstevel@tonic-gate 		}
222*2139Sjp161948 	/* Initialise the structure */
223*2139Sjp161948 	BN_POOL_init(&ret->pool);
224*2139Sjp161948 	BN_STACK_init(&ret->stack);
225*2139Sjp161948 	ret->used = 0;
226*2139Sjp161948 	ret->err_stack = 0;
227*2139Sjp161948 	ret->too_many = 0;
228*2139Sjp161948 	return ret;
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 
BN_CTX_free(BN_CTX * ctx)2310Sstevel@tonic-gate void BN_CTX_free(BN_CTX *ctx)
2320Sstevel@tonic-gate 	{
233*2139Sjp161948 	if (ctx == NULL)
234*2139Sjp161948 		return;
235*2139Sjp161948 #ifdef BN_CTX_DEBUG
236*2139Sjp161948 	{
237*2139Sjp161948 	BN_POOL_ITEM *pool = ctx->pool.head;
238*2139Sjp161948 	fprintf(stderr,"BN_CTX_free, stack-size=%d, pool-bignums=%d\n",
239*2139Sjp161948 		ctx->stack.size, ctx->pool.size);
240*2139Sjp161948 	fprintf(stderr,"dmaxs: ");
241*2139Sjp161948 	while(pool) {
242*2139Sjp161948 		unsigned loop = 0;
243*2139Sjp161948 		while(loop < BN_CTX_POOL_SIZE)
244*2139Sjp161948 			fprintf(stderr,"%02x ", pool->vals[loop++].dmax);
245*2139Sjp161948 		pool = pool->next;
246*2139Sjp161948 	}
247*2139Sjp161948 	fprintf(stderr,"\n");
248*2139Sjp161948 	}
249*2139Sjp161948 #endif
250*2139Sjp161948 	BN_STACK_finish(&ctx->stack);
251*2139Sjp161948 	BN_POOL_finish(&ctx->pool);
252*2139Sjp161948 	OPENSSL_free(ctx);
2530Sstevel@tonic-gate 	}
2540Sstevel@tonic-gate 
BN_CTX_start(BN_CTX * ctx)2550Sstevel@tonic-gate void BN_CTX_start(BN_CTX *ctx)
2560Sstevel@tonic-gate 	{
257*2139Sjp161948 	CTXDBG_ENTRY("BN_CTX_start", ctx);
258*2139Sjp161948 	/* If we're already overflowing ... */
259*2139Sjp161948 	if(ctx->err_stack || ctx->too_many)
260*2139Sjp161948 		ctx->err_stack++;
261*2139Sjp161948 	/* (Try to) get a new frame pointer */
262*2139Sjp161948 	else if(!BN_STACK_push(&ctx->stack, ctx->used))
2630Sstevel@tonic-gate 		{
264*2139Sjp161948 		BNerr(BN_F_BN_CTX_START,BN_R_TOO_MANY_TEMPORARY_VARIABLES);
265*2139Sjp161948 		ctx->err_stack++;
2660Sstevel@tonic-gate 		}
267*2139Sjp161948 	CTXDBG_EXIT(ctx);
2680Sstevel@tonic-gate 	}
2690Sstevel@tonic-gate 
BN_CTX_end(BN_CTX * ctx)2700Sstevel@tonic-gate void BN_CTX_end(BN_CTX *ctx)
2710Sstevel@tonic-gate 	{
272*2139Sjp161948 	CTXDBG_ENTRY("BN_CTX_end", ctx);
273*2139Sjp161948 	if(ctx->err_stack)
274*2139Sjp161948 		ctx->err_stack--;
275*2139Sjp161948 	else
276*2139Sjp161948 		{
277*2139Sjp161948 		unsigned int fp = BN_STACK_pop(&ctx->stack);
278*2139Sjp161948 		/* Does this stack frame have anything to release? */
279*2139Sjp161948 		if(fp < ctx->used)
280*2139Sjp161948 			BN_POOL_release(&ctx->pool, ctx->used - fp);
281*2139Sjp161948 		ctx->used = fp;
282*2139Sjp161948 		/* Unjam "too_many" in case "get" had failed */
283*2139Sjp161948 		ctx->too_many = 0;
284*2139Sjp161948 		}
285*2139Sjp161948 	CTXDBG_EXIT(ctx);
286*2139Sjp161948 	}
287*2139Sjp161948 
BN_CTX_get(BN_CTX * ctx)288*2139Sjp161948 BIGNUM *BN_CTX_get(BN_CTX *ctx)
289*2139Sjp161948 	{
290*2139Sjp161948 	BIGNUM *ret;
291*2139Sjp161948 	CTXDBG_ENTRY("BN_CTX_get", ctx);
292*2139Sjp161948 	if(ctx->err_stack || ctx->too_many) return NULL;
293*2139Sjp161948 	if((ret = BN_POOL_get(&ctx->pool)) == NULL)
294*2139Sjp161948 		{
295*2139Sjp161948 		/* Setting too_many prevents repeated "get" attempts from
296*2139Sjp161948 		 * cluttering the error stack. */
297*2139Sjp161948 		ctx->too_many = 1;
298*2139Sjp161948 		BNerr(BN_F_BN_CTX_GET,BN_R_TOO_MANY_TEMPORARY_VARIABLES);
299*2139Sjp161948 		return NULL;
300*2139Sjp161948 		}
301*2139Sjp161948 	/* OK, make sure the returned bignum is "zero" */
302*2139Sjp161948 	BN_zero(ret);
303*2139Sjp161948 	ctx->used++;
304*2139Sjp161948 	CTXDBG_RET(ctx, ret);
305*2139Sjp161948 	return ret;
306*2139Sjp161948 	}
307*2139Sjp161948 
308*2139Sjp161948 /************/
309*2139Sjp161948 /* BN_STACK */
310*2139Sjp161948 /************/
311*2139Sjp161948 
BN_STACK_init(BN_STACK * st)312*2139Sjp161948 static void BN_STACK_init(BN_STACK *st)
313*2139Sjp161948 	{
314*2139Sjp161948 	st->indexes = NULL;
315*2139Sjp161948 	st->depth = st->size = 0;
316*2139Sjp161948 	}
317*2139Sjp161948 
BN_STACK_finish(BN_STACK * st)318*2139Sjp161948 static void BN_STACK_finish(BN_STACK *st)
319*2139Sjp161948 	{
320*2139Sjp161948 	if(st->size) OPENSSL_free(st->indexes);
321*2139Sjp161948 	}
322*2139Sjp161948 
323*2139Sjp161948 #ifndef OPENSSL_NO_DEPRECATED
BN_STACK_reset(BN_STACK * st)324*2139Sjp161948 static void BN_STACK_reset(BN_STACK *st)
325*2139Sjp161948 	{
326*2139Sjp161948 	st->depth = 0;
327*2139Sjp161948 	}
328*2139Sjp161948 #endif
329*2139Sjp161948 
BN_STACK_push(BN_STACK * st,unsigned int idx)330*2139Sjp161948 static int BN_STACK_push(BN_STACK *st, unsigned int idx)
331*2139Sjp161948 	{
332*2139Sjp161948 	if(st->depth == st->size)
333*2139Sjp161948 		/* Need to expand */
334*2139Sjp161948 		{
335*2139Sjp161948 		unsigned int newsize = (st->size ?
336*2139Sjp161948 				(st->size * 3 / 2) : BN_CTX_START_FRAMES);
337*2139Sjp161948 		unsigned int *newitems = OPENSSL_malloc(newsize *
338*2139Sjp161948 						sizeof(unsigned int));
339*2139Sjp161948 		if(!newitems) return 0;
340*2139Sjp161948 		if(st->depth)
341*2139Sjp161948 			memcpy(newitems, st->indexes, st->depth *
342*2139Sjp161948 						sizeof(unsigned int));
343*2139Sjp161948 		if(st->size) OPENSSL_free(st->indexes);
344*2139Sjp161948 		st->indexes = newitems;
345*2139Sjp161948 		st->size = newsize;
346*2139Sjp161948 		}
347*2139Sjp161948 	st->indexes[(st->depth)++] = idx;
348*2139Sjp161948 	return 1;
349*2139Sjp161948 	}
350*2139Sjp161948 
BN_STACK_pop(BN_STACK * st)351*2139Sjp161948 static unsigned int BN_STACK_pop(BN_STACK *st)
352*2139Sjp161948 	{
353*2139Sjp161948 	return st->indexes[--(st->depth)];
354*2139Sjp161948 	}
355*2139Sjp161948 
356*2139Sjp161948 /***********/
357*2139Sjp161948 /* BN_POOL */
358*2139Sjp161948 /***********/
3590Sstevel@tonic-gate 
BN_POOL_init(BN_POOL * p)360*2139Sjp161948 static void BN_POOL_init(BN_POOL *p)
361*2139Sjp161948 	{
362*2139Sjp161948 	p->head = p->current = p->tail = NULL;
363*2139Sjp161948 	p->used = p->size = 0;
364*2139Sjp161948 	}
365*2139Sjp161948 
BN_POOL_finish(BN_POOL * p)366*2139Sjp161948 static void BN_POOL_finish(BN_POOL *p)
367*2139Sjp161948 	{
368*2139Sjp161948 	while(p->head)
369*2139Sjp161948 		{
370*2139Sjp161948 		unsigned int loop = 0;
371*2139Sjp161948 		BIGNUM *bn = p->head->vals;
372*2139Sjp161948 		while(loop++ < BN_CTX_POOL_SIZE)
373*2139Sjp161948 			{
374*2139Sjp161948 			if(bn->d) BN_clear_free(bn);
375*2139Sjp161948 			bn++;
376*2139Sjp161948 			}
377*2139Sjp161948 		p->current = p->head->next;
378*2139Sjp161948 		OPENSSL_free(p->head);
379*2139Sjp161948 		p->head = p->current;
380*2139Sjp161948 		}
381*2139Sjp161948 	}
382*2139Sjp161948 
383*2139Sjp161948 #ifndef OPENSSL_NO_DEPRECATED
BN_POOL_reset(BN_POOL * p)384*2139Sjp161948 static void BN_POOL_reset(BN_POOL *p)
385*2139Sjp161948 	{
386*2139Sjp161948 	BN_POOL_ITEM *item = p->head;
387*2139Sjp161948 	while(item)
388*2139Sjp161948 		{
389*2139Sjp161948 		unsigned int loop = 0;
390*2139Sjp161948 		BIGNUM *bn = item->vals;
391*2139Sjp161948 		while(loop++ < BN_CTX_POOL_SIZE)
392*2139Sjp161948 			{
393*2139Sjp161948 			if(bn->d) BN_clear(bn);
394*2139Sjp161948 			bn++;
395*2139Sjp161948 			}
396*2139Sjp161948 		item = item->next;
397*2139Sjp161948 		}
398*2139Sjp161948 	p->current = p->head;
399*2139Sjp161948 	p->used = 0;
4000Sstevel@tonic-gate 	}
401*2139Sjp161948 #endif
402*2139Sjp161948 
BN_POOL_get(BN_POOL * p)403*2139Sjp161948 static BIGNUM *BN_POOL_get(BN_POOL *p)
404*2139Sjp161948 	{
405*2139Sjp161948 	if(p->used == p->size)
406*2139Sjp161948 		{
407*2139Sjp161948 		BIGNUM *bn;
408*2139Sjp161948 		unsigned int loop = 0;
409*2139Sjp161948 		BN_POOL_ITEM *item = OPENSSL_malloc(sizeof(BN_POOL_ITEM));
410*2139Sjp161948 		if(!item) return NULL;
411*2139Sjp161948 		/* Initialise the structure */
412*2139Sjp161948 		bn = item->vals;
413*2139Sjp161948 		while(loop++ < BN_CTX_POOL_SIZE)
414*2139Sjp161948 			BN_init(bn++);
415*2139Sjp161948 		item->prev = p->tail;
416*2139Sjp161948 		item->next = NULL;
417*2139Sjp161948 		/* Link it in */
418*2139Sjp161948 		if(!p->head)
419*2139Sjp161948 			p->head = p->current = p->tail = item;
420*2139Sjp161948 		else
421*2139Sjp161948 			{
422*2139Sjp161948 			p->tail->next = item;
423*2139Sjp161948 			p->tail = item;
424*2139Sjp161948 			p->current = item;
425*2139Sjp161948 			}
426*2139Sjp161948 		p->size += BN_CTX_POOL_SIZE;
427*2139Sjp161948 		p->used++;
428*2139Sjp161948 		/* Return the first bignum from the new pool */
429*2139Sjp161948 		return item->vals;
430*2139Sjp161948 		}
431*2139Sjp161948 	if(!p->used)
432*2139Sjp161948 		p->current = p->head;
433*2139Sjp161948 	else if((p->used % BN_CTX_POOL_SIZE) == 0)
434*2139Sjp161948 		p->current = p->current->next;
435*2139Sjp161948 	return p->current->vals + ((p->used++) % BN_CTX_POOL_SIZE);
436*2139Sjp161948 	}
437*2139Sjp161948 
BN_POOL_release(BN_POOL * p,unsigned int num)438*2139Sjp161948 static void BN_POOL_release(BN_POOL *p, unsigned int num)
439*2139Sjp161948 	{
440*2139Sjp161948 	unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE;
441*2139Sjp161948 	p->used -= num;
442*2139Sjp161948 	while(num--)
443*2139Sjp161948 		{
444*2139Sjp161948 		bn_check_top(p->current->vals + offset);
445*2139Sjp161948 		if(!offset)
446*2139Sjp161948 			{
447*2139Sjp161948 			offset = BN_CTX_POOL_SIZE - 1;
448*2139Sjp161948 			p->current = p->current->prev;
449*2139Sjp161948 			}
450*2139Sjp161948 		else
451*2139Sjp161948 			offset--;
452*2139Sjp161948 		}
453*2139Sjp161948 	}
454*2139Sjp161948 
455