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