123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /*
- ---------------------------------------------------------------------------
- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
- All rights reserved.
- LICENSE TERMS
- The free distribution and use of this software in both source and binary
- form is allowed (with or without changes) provided that:
- 1. distributions of this source code include the above copyright
- notice, this list of conditions and the following disclaimer;
- 2. distributions in binary form include the above copyright
- notice, this list of conditions and the following disclaimer
- in the documentation and/or other associated materials;
- 3. the copyright holder's name is not used to endorse products
- built using this software without specific written permission.
- ALTERNATIVELY, provided that this notice is retained in full, this product
- may be distributed under the terms of the GNU General Public License (GPL),
- in which case the provisions of the GPL apply INSTEAD OF those given above.
- DISCLAIMER
- This software is provided 'as is' with no explicit or implied warranties
- in respect of its properties, including, but not limited to, correctness
- and/or fitness for purpose.
- ---------------------------------------------------------------------------
- Issue Date: 24/01/2003
- This file implements a random data pool based on the use of an external
- entropy function. It is based on the ideas advocated by Peter Gutmann in
- his work on pseudo random sequence generators. It is not a 'paranoid'
- random sequence generator and no attempt is made to protect the pool
- from prying eyes either by memory locking or by techniques to obscure
- its location in memory.
- */
- #include <memory.h>
- #include "prng.h"
- #if defined(__cplusplus)
- extern "C"
- {
- #endif
- /* mix a random data pool using the SHA1 compression function (as */
- /* suggested by Peter Gutmann in his paper on random pools) */
- static void prng_mix(unsigned char buf[])
- { unsigned int i, len;
- sha1_ctx ctx[1];
- /*lint -e{663} unusual array to pointer conversion */
- for(i = 0; i < PRNG_POOL_SIZE; i += SHA1_DIGEST_SIZE)
- {
- /* copy digest size pool block into SHA1 hash block */
- memcpy(ctx->hash, buf + (i ? i : PRNG_POOL_SIZE)
- - SHA1_DIGEST_SIZE, SHA1_DIGEST_SIZE);
- /* copy data from pool into the SHA1 data buffer */
- len = PRNG_POOL_SIZE - i;
- memcpy(ctx->wbuf, buf + i, (len > SHA1_BLOCK_SIZE ? SHA1_BLOCK_SIZE : len));
- if(len < SHA1_BLOCK_SIZE)
- memcpy(((char*)ctx->wbuf) + len, buf, SHA1_BLOCK_SIZE - len);
- /* compress using the SHA1 compression function */
- sha1_compile(ctx);
- /* put digest size block back into the random pool */
- memcpy(buf + i, ctx->hash, SHA1_DIGEST_SIZE);
- }
- }
- /* refresh the output buffer and update the random pool by adding */
- /* entropy and remixing */
- static void update_pool(prng_ctx ctx[1])
- { unsigned int i = 0;
- /* transfer random pool data to the output buffer */
- memcpy(ctx->obuf, ctx->rbuf, PRNG_POOL_SIZE);
- /* enter entropy data into the pool */
- while(i < PRNG_POOL_SIZE)
- i += ctx->entropy(ctx->rbuf + i, PRNG_POOL_SIZE - i);
- /* invert and xor the original pool data into the pool */
- for(i = 0; i < PRNG_POOL_SIZE; ++i)
- ctx->rbuf[i] ^= ~ctx->obuf[i];
- /* mix the pool and the output buffer */
- prng_mix(ctx->rbuf);
- prng_mix(ctx->obuf);
- }
- void prng_init(prng_entropy_fn fun, prng_ctx ctx[1])
- { int i;
- /* clear the buffers and the counter in the context */
- memset(ctx, 0, sizeof(prng_ctx));
- /* set the pointer to the entropy collection function */
- ctx->entropy = fun;
- /* initialise the random data pool */
- update_pool(ctx);
- /* mix the pool a minimum number of times */
- for(i = 0; i < PRNG_MIN_MIX; ++i)
- prng_mix(ctx->rbuf);
- /* update the pool to prime the pool output buffer */
- update_pool(ctx);
- }
- /* provide random bytes from the random data pool */
- void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1])
- { unsigned char *rp = data;
- unsigned int len, pos = ctx->pos;
- while(data_len)
- {
- /* transfer 'data_len' bytes (or the number of bytes remaining */
- /* the pool output buffer if less) into the output */
- len = (data_len < PRNG_POOL_SIZE - pos ? data_len : PRNG_POOL_SIZE - pos);
- memcpy(rp, ctx->obuf + pos, len);
- rp += len; /* update ouput buffer position pointer */
- pos += len; /* update pool output buffer pointer */
- data_len -= len; /* update the remaining data count */
- /* refresh the random pool if necessary */
- if(pos == PRNG_POOL_SIZE)
- {
- update_pool(ctx); pos = 0;
- }
- }
- ctx->pos = pos;
- }
- void prng_end(prng_ctx ctx[1])
- {
- /* ensure the data in the context is destroyed */
- memset(ctx, 0, sizeof(prng_ctx));
- }
- #if defined(__cplusplus)
- }
- #endif
|