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