bn_ctx.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <openssl/trace.h>
  10. #include "internal/cryptlib.h"
  11. #include "bn_local.h"
  12. /*-
  13. * TODO list
  14. *
  15. * 1. Check a bunch of "(words+1)" type hacks in various bignum functions and
  16. * check they can be safely removed.
  17. * - Check +1 and other ugliness in BN_from_montgomery()
  18. *
  19. * 2. Consider allowing a BN_new_ex() that, at least, lets you specify an
  20. * appropriate 'block' size that will be honoured by bn_expand_internal() to
  21. * prevent piddly little reallocations. OTOH, profiling bignum expansions in
  22. * BN_CTX doesn't show this to be a big issue.
  23. */
  24. /* How many bignums are in each "pool item"; */
  25. #define BN_CTX_POOL_SIZE 16
  26. /* The stack frame info is resizing, set a first-time expansion size; */
  27. #define BN_CTX_START_FRAMES 32
  28. /***********/
  29. /* BN_POOL */
  30. /***********/
  31. /* A bundle of bignums that can be linked with other bundles */
  32. typedef struct bignum_pool_item {
  33. /* The bignum values */
  34. BIGNUM vals[BN_CTX_POOL_SIZE];
  35. /* Linked-list admin */
  36. struct bignum_pool_item *prev, *next;
  37. } BN_POOL_ITEM;
  38. /* A linked-list of bignums grouped in bundles */
  39. typedef struct bignum_pool {
  40. /* Linked-list admin */
  41. BN_POOL_ITEM *head, *current, *tail;
  42. /* Stack depth and allocation size */
  43. unsigned used, size;
  44. } BN_POOL;
  45. static void BN_POOL_init(BN_POOL *);
  46. static void BN_POOL_finish(BN_POOL *);
  47. static BIGNUM *BN_POOL_get(BN_POOL *, int);
  48. static void BN_POOL_release(BN_POOL *, unsigned int);
  49. /************/
  50. /* BN_STACK */
  51. /************/
  52. /* A wrapper to manage the "stack frames" */
  53. typedef struct bignum_ctx_stack {
  54. /* Array of indexes into the bignum stack */
  55. unsigned int *indexes;
  56. /* Number of stack frames, and the size of the allocated array */
  57. unsigned int depth, size;
  58. } BN_STACK;
  59. static void BN_STACK_init(BN_STACK *);
  60. static void BN_STACK_finish(BN_STACK *);
  61. static int BN_STACK_push(BN_STACK *, unsigned int);
  62. static unsigned int BN_STACK_pop(BN_STACK *);
  63. /**********/
  64. /* BN_CTX */
  65. /**********/
  66. /* The opaque BN_CTX type */
  67. struct bignum_ctx {
  68. /* The bignum bundles */
  69. BN_POOL pool;
  70. /* The "stack frames", if you will */
  71. BN_STACK stack;
  72. /* The number of bignums currently assigned */
  73. unsigned int used;
  74. /* Depth of stack overflow */
  75. int err_stack;
  76. /* Block "gets" until an "end" (compatibility behaviour) */
  77. int too_many;
  78. /* Flags. */
  79. int flags;
  80. /* The library context */
  81. OPENSSL_CTX *libctx;
  82. };
  83. #ifndef FIPS_MODULE
  84. /* Debugging functionality */
  85. static void ctxdbg(BIO *channel, const char *text, BN_CTX *ctx)
  86. {
  87. unsigned int bnidx = 0, fpidx = 0;
  88. BN_POOL_ITEM *item = ctx->pool.head;
  89. BN_STACK *stack = &ctx->stack;
  90. BIO_printf(channel, "%s\n", text);
  91. BIO_printf(channel, " (%16p): ", (void*)ctx);
  92. while (bnidx < ctx->used) {
  93. BIO_printf(channel, "%03x ",
  94. item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax);
  95. if (!(bnidx % BN_CTX_POOL_SIZE))
  96. item = item->next;
  97. }
  98. BIO_printf(channel, "\n");
  99. bnidx = 0;
  100. BIO_printf(channel, " %16s : ", "");
  101. while (fpidx < stack->depth) {
  102. while (bnidx++ < stack->indexes[fpidx])
  103. BIO_printf(channel, " ");
  104. BIO_printf(channel, "^^^ ");
  105. bnidx++;
  106. fpidx++;
  107. }
  108. BIO_printf(channel, "\n");
  109. }
  110. # define CTXDBG(str, ctx) \
  111. OSSL_TRACE_BEGIN(BN_CTX) { \
  112. ctxdbg(trc_out, str, ctx); \
  113. } OSSL_TRACE_END(BN_CTX)
  114. #else
  115. /* TODO(3.0): Consider if we want to do this in FIPS mode */
  116. # define CTXDBG(str, ctx) do {} while(0)
  117. #endif /* FIPS_MODULE */
  118. BN_CTX *BN_CTX_new_ex(OPENSSL_CTX *ctx)
  119. {
  120. BN_CTX *ret;
  121. if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
  122. BNerr(BN_F_BN_CTX_NEW_EX, ERR_R_MALLOC_FAILURE);
  123. return NULL;
  124. }
  125. /* Initialise the structure */
  126. BN_POOL_init(&ret->pool);
  127. BN_STACK_init(&ret->stack);
  128. ret->libctx = ctx;
  129. return ret;
  130. }
  131. #ifndef FIPS_MODULE
  132. BN_CTX *BN_CTX_new(void)
  133. {
  134. return BN_CTX_new_ex(NULL);
  135. }
  136. #endif
  137. BN_CTX *BN_CTX_secure_new_ex(OPENSSL_CTX *ctx)
  138. {
  139. BN_CTX *ret = BN_CTX_new_ex(ctx);
  140. if (ret != NULL)
  141. ret->flags = BN_FLG_SECURE;
  142. return ret;
  143. }
  144. #ifndef FIPS_MODULE
  145. BN_CTX *BN_CTX_secure_new(void)
  146. {
  147. return BN_CTX_secure_new_ex(NULL);
  148. }
  149. #endif
  150. void BN_CTX_free(BN_CTX *ctx)
  151. {
  152. if (ctx == NULL)
  153. return;
  154. #ifndef FIPS_MODULE
  155. OSSL_TRACE_BEGIN(BN_CTX) {
  156. BN_POOL_ITEM *pool = ctx->pool.head;
  157. BIO_printf(trc_out,
  158. "BN_CTX_free(): stack-size=%d, pool-bignums=%d\n",
  159. ctx->stack.size, ctx->pool.size);
  160. BIO_printf(trc_out, " dmaxs: ");
  161. while (pool) {
  162. unsigned loop = 0;
  163. while (loop < BN_CTX_POOL_SIZE)
  164. BIO_printf(trc_out, "%02x ", pool->vals[loop++].dmax);
  165. pool = pool->next;
  166. }
  167. BIO_printf(trc_out, "\n");
  168. } OSSL_TRACE_END(BN_CTX);
  169. #endif
  170. BN_STACK_finish(&ctx->stack);
  171. BN_POOL_finish(&ctx->pool);
  172. OPENSSL_free(ctx);
  173. }
  174. void BN_CTX_start(BN_CTX *ctx)
  175. {
  176. CTXDBG("ENTER BN_CTX_start()", ctx);
  177. /* If we're already overflowing ... */
  178. if (ctx->err_stack || ctx->too_many)
  179. ctx->err_stack++;
  180. /* (Try to) get a new frame pointer */
  181. else if (!BN_STACK_push(&ctx->stack, ctx->used)) {
  182. BNerr(BN_F_BN_CTX_START, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
  183. ctx->err_stack++;
  184. }
  185. CTXDBG("LEAVE BN_CTX_start()", ctx);
  186. }
  187. void BN_CTX_end(BN_CTX *ctx)
  188. {
  189. if (ctx == NULL)
  190. return;
  191. CTXDBG("ENTER BN_CTX_end()", ctx);
  192. if (ctx->err_stack)
  193. ctx->err_stack--;
  194. else {
  195. unsigned int fp = BN_STACK_pop(&ctx->stack);
  196. /* Does this stack frame have anything to release? */
  197. if (fp < ctx->used)
  198. BN_POOL_release(&ctx->pool, ctx->used - fp);
  199. ctx->used = fp;
  200. /* Unjam "too_many" in case "get" had failed */
  201. ctx->too_many = 0;
  202. }
  203. CTXDBG("LEAVE BN_CTX_end()", ctx);
  204. }
  205. BIGNUM *BN_CTX_get(BN_CTX *ctx)
  206. {
  207. BIGNUM *ret;
  208. CTXDBG("ENTER BN_CTX_get()", ctx);
  209. if (ctx->err_stack || ctx->too_many)
  210. return NULL;
  211. if ((ret = BN_POOL_get(&ctx->pool, ctx->flags)) == NULL) {
  212. /*
  213. * Setting too_many prevents repeated "get" attempts from cluttering
  214. * the error stack.
  215. */
  216. ctx->too_many = 1;
  217. BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
  218. return NULL;
  219. }
  220. /* OK, make sure the returned bignum is "zero" */
  221. BN_zero(ret);
  222. /* clear BN_FLG_CONSTTIME if leaked from previous frames */
  223. ret->flags &= (~BN_FLG_CONSTTIME);
  224. ctx->used++;
  225. CTXDBG("LEAVE BN_CTX_get()", ctx);
  226. return ret;
  227. }
  228. OPENSSL_CTX *bn_get_lib_ctx(BN_CTX *ctx)
  229. {
  230. if (ctx == NULL)
  231. return NULL;
  232. return ctx->libctx;
  233. }
  234. /************/
  235. /* BN_STACK */
  236. /************/
  237. static void BN_STACK_init(BN_STACK *st)
  238. {
  239. st->indexes = NULL;
  240. st->depth = st->size = 0;
  241. }
  242. static void BN_STACK_finish(BN_STACK *st)
  243. {
  244. OPENSSL_free(st->indexes);
  245. st->indexes = NULL;
  246. }
  247. static int BN_STACK_push(BN_STACK *st, unsigned int idx)
  248. {
  249. if (st->depth == st->size) {
  250. /* Need to expand */
  251. unsigned int newsize =
  252. st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES;
  253. unsigned int *newitems;
  254. if ((newitems = OPENSSL_malloc(sizeof(*newitems) * newsize)) == NULL) {
  255. BNerr(BN_F_BN_STACK_PUSH, ERR_R_MALLOC_FAILURE);
  256. return 0;
  257. }
  258. if (st->depth)
  259. memcpy(newitems, st->indexes, sizeof(*newitems) * st->depth);
  260. OPENSSL_free(st->indexes);
  261. st->indexes = newitems;
  262. st->size = newsize;
  263. }
  264. st->indexes[(st->depth)++] = idx;
  265. return 1;
  266. }
  267. static unsigned int BN_STACK_pop(BN_STACK *st)
  268. {
  269. return st->indexes[--(st->depth)];
  270. }
  271. /***********/
  272. /* BN_POOL */
  273. /***********/
  274. static void BN_POOL_init(BN_POOL *p)
  275. {
  276. p->head = p->current = p->tail = NULL;
  277. p->used = p->size = 0;
  278. }
  279. static void BN_POOL_finish(BN_POOL *p)
  280. {
  281. unsigned int loop;
  282. BIGNUM *bn;
  283. while (p->head) {
  284. for (loop = 0, bn = p->head->vals; loop++ < BN_CTX_POOL_SIZE; bn++)
  285. if (bn->d)
  286. BN_clear_free(bn);
  287. p->current = p->head->next;
  288. OPENSSL_free(p->head);
  289. p->head = p->current;
  290. }
  291. }
  292. static BIGNUM *BN_POOL_get(BN_POOL *p, int flag)
  293. {
  294. BIGNUM *bn;
  295. unsigned int loop;
  296. /* Full; allocate a new pool item and link it in. */
  297. if (p->used == p->size) {
  298. BN_POOL_ITEM *item;
  299. if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) {
  300. BNerr(BN_F_BN_POOL_GET, ERR_R_MALLOC_FAILURE);
  301. return NULL;
  302. }
  303. for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) {
  304. bn_init(bn);
  305. if ((flag & BN_FLG_SECURE) != 0)
  306. BN_set_flags(bn, BN_FLG_SECURE);
  307. }
  308. item->prev = p->tail;
  309. item->next = NULL;
  310. if (p->head == NULL)
  311. p->head = p->current = p->tail = item;
  312. else {
  313. p->tail->next = item;
  314. p->tail = item;
  315. p->current = item;
  316. }
  317. p->size += BN_CTX_POOL_SIZE;
  318. p->used++;
  319. /* Return the first bignum from the new pool */
  320. return item->vals;
  321. }
  322. if (!p->used)
  323. p->current = p->head;
  324. else if ((p->used % BN_CTX_POOL_SIZE) == 0)
  325. p->current = p->current->next;
  326. return p->current->vals + ((p->used++) % BN_CTX_POOL_SIZE);
  327. }
  328. static void BN_POOL_release(BN_POOL *p, unsigned int num)
  329. {
  330. unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE;
  331. p->used -= num;
  332. while (num--) {
  333. bn_check_top(p->current->vals + offset);
  334. if (offset == 0) {
  335. offset = BN_CTX_POOL_SIZE - 1;
  336. p->current = p->current->prev;
  337. } else
  338. offset--;
  339. }
  340. }