Skip to content
Snippets Groups Projects
Commit c4260b99 authored by Niels Möller's avatar Niels Möller
Browse files

* yarrow256.c: New file, implementing Yarrow.

Rev: src/nettle/yarrow.h:1.3
Rev: src/nettle/yarrow256.c:1.1
parent 9d103c65
No related branches found
No related tags found
No related merge requests found
...@@ -26,19 +26,22 @@ ...@@ -26,19 +26,22 @@
#ifndef NETTLE_YARROW_COMPAT_H_INCLUDED #ifndef NETTLE_YARROW_COMPAT_H_INCLUDED
#define NETTLE_YARROW_COMPAT_H_INCLUDED #define NETTLE_YARROW_COMPAT_H_INCLUDED
#include "sha1.h" #include "aes.h"
#include "des.h" #include "des.h"
#include "sha.h"
enum yarrow_pool_id { YARROW_FAST = 0, YARROW_SLOW = 1 }; enum yarrow_pool_id { YARROW_FAST = 0, YARROW_SLOW = 1 };
struct yarrow_source struct yarrow_source
{ {
uint32_t estimate; /* Indexed by yarrow_pool_id */
uint32_t estimate[2];
/* The pool next sample should go to. */ /* The pool next sample should go to. */
enum yarrow_pool_id next; enum yarrow_pool_id next;
}; };
/* Yarrow-160, based on SHA1 and DES3 */
struct yarrow160_ctx struct yarrow160_ctx
{ {
/* Indexed by yarrow_pool_id */ /* Indexed by yarrow_pool_id */
...@@ -67,5 +70,44 @@ yarrow160_random(struct yarrow160_ctx *ctx, unsigned length, uint8_t dst); ...@@ -67,5 +70,44 @@ yarrow160_random(struct yarrow160_ctx *ctx, unsigned length, uint8_t dst);
int int
yarrow160_seeded(struct yarrow160_ctx *ctx); yarrow160_seeded(struct yarrow160_ctx *ctx);
/* Yarrow-256, based on SHA-256 and AES-256 */
struct yarrow256_ctx
{
/* Indexed by yarrow_pool_id */
struct sha256_ctx pools[2];
int seeded;
/* The current key key and counter block */
struct aes_ctx key;
uint8_t counter[AES_BLOCK_SIZE];
uint8_t buffer[AES_BLOCK_SIZE];
unsigned index;
/* Number of block generated with the current key */
unsigned block_count;
/* The entropy sources */
unsigned nsources;
struct yarrow_source *sources;
};
void
yarrow256_init(struct yarrow256_ctx *ctx,
int nsources,
struct yarrow_source *sources);
void
yarrow256_update(struct yarrow256_ctx *ctx,
unsigned source, unsigned entropy,
unsigned length, const uint8_t *data);
void
yarrow256_random(struct yarrow256_ctx *ctx, unsigned length, uint8_t *dst);
int
yarrow256_seeded(struct yarrow256_ctx *ctx);
#endif /* NETTLE_YARROW_COMPAT_H_INCLUDED */ #endif /* NETTLE_YARROW_COMPAT_H_INCLUDED */
/* yarrow256.c
*
* The yarrow pseudo-randomness generator.
*/
/* nettle, low-level cryptographics library
*
* Copyright (C) 2001 Niels Mller
*
* The nettle library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The nettle library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "yarrow.h"
#include <assert.h>
#include <string.h>
/* Parameters */
/* An upper limit on the entropy (in bits) in one octet of sample
* data. */
#define YARROW_MULTIPLIER 4
/* Generator gate threshold */
#define YARROW_GATE_THRESHOLD 10
/* Entropy estimates sticks to this value, it is treated as infinity
* in calculations. It should fit comfortably in an uint32_t, to avoid
* overflows. */
#define YARROW_MAX_ENTROPY 0x100000
void
yarrow256_init(struct yarrow256_ctx *ctx,
int n,
struct yarrow_source *s)
{
sha256_init(&ctx->pools[0]);
sha256_init(&ctx->pools[1]);
ctx->seeded = 0;
ctx->nsources = n;
ctx->sources = s;
}
void
yarrow256_update(struct yarrow256_ctx *ctx,
unsigned source_index, unsigned entropy,
unsigned length, const uint8_t *data)
{
enum yarrow_pool_id current;
struct yarrow_source *source;
assert(source_index < ctx->nsources);
if (!length)
/* Nothing happens */
return;
source = &ctx->sources[source_index];
if (!ctx->seeded)
/* While seeding, use the slow pool */
current = YARROW_SLOW;
else
{
current = source->next;
source->next = !source->next;
}
sha256_update(&ctx->pools[current], length, data);
/* FIXME: Use different counters for fast and slow poll? Or a total
* for fast poll, and individual for slow poll? */
/* NOTE: We should be careful to avoid overflows in the estimates. */
if (source->estimate[current] < YARROW_MAX_ENTROPY)
{
if (entropy > YARROW_MAX_ENTROPY)
entropy = YARROW_MAX_ENTROPY;
if ( (length < (YARROW_MAX_ENTROPY / YARROW_MULTIPLIER))
&& (entropy > YARROW_MULTIPLIER * length) )
entropy = YARROW_MULTIPLIER * length;
/* FIXME: Calling a more sophisticated estimater should be done
* here. */
entropy += source->estimate[current];
if (entropy > YARROW_MAX_ENTROPY)
entropy = YARROW_MAX_ENTROPY;
source->estimate[current] = entropy;
}
/* Check for seed/reseed */
}
static void
yarrow_generate_block(struct yarrow256_ctx *ctx,
uint8_t *block)
{
unsigned i;
aes_encrypt(&ctx->key, AES_BLOCK_SIZE, block, ctx->counter);
/* Increment counter, treating it as a big-endian number.
*
* We could keep a representation of th counter as 4 32-bit values,
* and write entire words (in big-endian byteorder) into the counter
* block, whenever they change. */
for (i = AES_BLOCK_SIZE; i--; )
{
if (++ctx->counter[i])
break;
}
}
static void
yarrow_generate_block_with_gate(struct yarrow256_ctx *ctx,
uint8_t *block)
{
if (ctx->block_count < YARROW_GATE_THRESHOLD)
{
yarrow_generate_block(ctx, block);
ctx->block_count++;
}
else
{
uint8_t key[AES_MAX_KEY_SIZE];
unsigned i;
for (i = 0; i < sizeof(key); i+= AES_BLOCK_SIZE)
yarrow_generate_block(ctx, key + i);
aes_set_key(&ctx->key, sizeof(key), key);
yarrow_generate_block(ctx, block);
ctx->block_count = 1;
}
}
void
yarrow256_random(struct yarrow256_ctx *ctx, unsigned length, uint8_t *dst)
{
assert(ctx->seeded);
if (ctx->index < AES_BLOCK_SIZE)
{
unsigned left = AES_BLOCK_SIZE - ctx->index;
if (length <= left)
{
memcpy(dst, ctx->buffer + ctx->index, length);
ctx->index += length;
return;
}
memcpy(dst, ctx->buffer + ctx->index, left);
dst += left;
length -= left;
assert(length);
}
while (length > AES_BLOCK_SIZE)
{
yarrow_generate_block_with_gate(ctx, dst);
dst += AES_BLOCK_SIZE;
length -= AES_BLOCK_SIZE;
}
if (length)
{
assert(length < AES_BLOCK_SIZE);
yarrow_generate_block_with_gate(ctx, ctx->buffer);
memcpy(dst, ctx->buffer, length);
ctx->index = length;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment