//
// entropy.c
//
//Functions for manipulating entropy pools.
//
//
//-UserX 2001/11/19

/**
Functions for handling \Ref{EntropyPool}s. <P>
@author UserX
@name entropy
*/
//@{

#include "crypt/sha1.h"
#include "crypt/entropy.h"
#include "base/dblock.h"
#include "base/mem.h"

/**
Creates and initializes an EntropyPool.
@return The pointer to the new EntropyPool.
*/
EntropyPool *entropyMake(void) {
	EntropyPool *ep;
	ep = memAlloc(sizeof(EntropyPool), "Entropy", NULL);
	ep->PoolSize = 0;
	SHA1Init(&ep->Sha1);
	return ep;
}

/**
Releases the memory used by an EntropyPool.
@param ep The pointer to the EntropyPool to be released.
*/
void entropyFree(EntropyPool *ep) {
	memFree(ep);
}

/**
Adds an integer to the EntropyPool.
@param ep The pointer to the EntropyPool to add the value to.
@param value The integer to add.
@param bits The number of bits worth of entropy there is in this.
*/
void entropyAddInt(EntropyPool *ep, int value, int bits) {
	int i;
	int b;
	if(ep == NULL) {
		return;
	}
	if (bits > sizeof(value) << 3) {
		bits = sizeof(value) << 3;
	}
	b = sizeof(value);
	for(i = 0; i < b; i++) {
		ep->tmp[i] = (uint8) (value >> (i * 8)); 
	}
	ep->PoolSize += bits;
	SHA1Update(&ep->Sha1, ep->tmp, b);
}

/**
Adds a buffer of bytes to an EntropyPool.
@param ep The pointer to the EntropyPool to add the value to.
@param buffer The pointer to the buffer.
@param length The number of bytes in the buffer.
@param bits The number of bits worth of entropy there is in this.
*/
void entropyAddBuffer(EntropyPool *ep, uint8 *buffer, int length, int bits) {
	if(ep == NULL) {
		return;
	}
	if(bits > length << 3) {
		bits = length << 3;
	}
	if(length == 0) {
		return;
	}
	ep->PoolSize += bits;
	SHA1Update(&ep->Sha1, buffer, length);
}


/**
Adds the entire contents of a DataBlock to an EntropyPool.
@param ep The pointer to the EntropyPool to add the value to.
@param db The DataBlock to use.
@param bits The number of bits worth of entropy there is in this.
*/
void entropyAddDBlock(EntropyPool *ep, DataBlock *db, int bits) {
	if(db == NULL) {
		return;
	}
	entropyAddBuffer(ep, db->data, db->size, bits);
}



/**
Finishes the hash and returns the digest in a supplied DataBlock. <P>
The hash is reinitialized to be ready for more entropy. 
The contents of <B>db</B> is erased. 
@param ep The pointer to the EntropyPool to use.
@param db The DataBlock to use.
@return The new pointer to <B>db</B>. 
*/
DataBlock *entropyGetDigest(EntropyPool *ep, DataBlock *db) {
	if(ep == NULL) {
		return db;
	}
	db = dblockResize(db, 20);
	db->size = 20;
	SHA1Final(db->data, &ep->Sha1);
	SHA1Init(&ep->Sha1);
	ep->PoolSize = 0;
	return db;
}

//@}
