/*
  fortuna.c
  Fortuna cryptographic PRNG
  As seen in Ferguson and Schneier "Practical Cryptography"
  Greg Parker     gparker@cs.stanford.edu     2003-11-16
*/
/**********
 * Copyright (c) 2003-2004 Greg Parker.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY GREG PARKER ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **********/

#ifndef FORTUNA_LOCL_H
#define FORTUNA_LOCL_H

#include "includes.h"
#include "crypto/openssl/aes/aes.h"
#include "crypto/sha2/sha2.h"


#define KEY_BYTES   (AES_BLOCK_SIZE*2) // Two AES blocks; one SHA256 digest
#define CTR_BYTES   AES_BLOCK_SIZE
#define BLOCK_BYTES AES_BLOCK_SIZE


// accumulator

#define POOL_BYTES SHA256_DIGEST_LENGTH
#define POOL_COUNT 32
#define MIN_POOL_BYTES 64

typedef struct {
    SHA256_CTX hash;
    unsigned int bytesBeforeUseful;
} pool_t;

typedef struct {
    pool_t pools[POOL_COUNT];
} accumulator_t;

void accumulator_init(accumulator_t *a) FORTUNA_SEGMENT;
void accumulator_add_bytes(accumulator_t *a, uint8_t sourceID, uint8_t poolID, uint8_t *data, uint8_t len) FORTUNA_SEGMENT;
int accumulator_pool_is_useful(accumulator_t *a, uint8_t poolID) FORTUNA_SEGMENT;
void accumulator_extract_pool(accumulator_t *a, uint8_t poolID, uint8_t *outBytes) FORTUNA_SEGMENT;


// generator

typedef struct {
    AES_KEY aes_key;
    uint8_t key[KEY_BYTES];
    uint8_t ctr[CTR_BYTES];
} generator_t;

void generator_init(generator_t *g) FORTUNA_SEGMENT;
void generator_reseed(generator_t *g, uint8_t *data, unsigned int len) FORTUNA_SEGMENT;
void generator_emit_bytes(generator_t *g, uint8_t *outBytes, unsigned int byteCount) FORTUNA_SEGMENT;

#endif
