engine/crypt/cryptRandPool.cc
2024-01-07 04:36:33 +00:00

103 lines
2.4 KiB
C++

//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "crypt/cryptRandPool.h"
#include "Core/bitStream.h"
#include "crypt/cryptSHA1.h"
namespace {
CryptRandomPool* sgRandPool = NULL;
} // namespace {}
void CryptRandomPool::init()
{
AssertFatal(sgRandPool == NULL, "RandPool already initialized");
sgRandPool = new CryptRandomPool;
}
void CryptRandomPool::destroy()
{
AssertFatal(sgRandPool != NULL, "RandPool not initialized");
delete sgRandPool;
sgRandPool = NULL;
}
CryptRandomPool::CryptRandomPool()
{
mPoolPos = 0;
mAvailableBytes = 0;
}
CryptRandomPool::~CryptRandomPool()
{
}
void CryptRandomPool::submitEntropy(U32 value, U32 entropicBits)
{
AssertFatal(sgRandPool != NULL, "No Random pool!");
for (U32 i = 0; i < entropicBits; i++) {
U8 bit = value & 0x1;
value >>= 1;
// Write this bit to the current pool pos
U32 byte = sgRandPool->mPoolPos / 8;
U32 mask = sgRandPool->mPoolPos % 8;
sgRandPool->mPool[byte] ^= bit << mask;
sgRandPool->mPoolPos = (sgRandPool->mPoolPos + 1) % (55 * 8);
}
}
void CryptRandomPool::extractRandomBytes(U8* pOutput, U32 bytesNeeded)
{
AssertFatal(sgRandPool != NULL, "No Random pool!");
U32 currOutput = 0;
while (sgRandPool->mAvailableBytes != 0 && bytesNeeded != 0) {
sgRandPool->mAvailableBytes--;
bytesNeeded--;
pOutput[currOutput++] = sgRandPool->mRandomBytes[sgRandPool->mAvailableBytes];
}
while (bytesNeeded != 0) {
sgRandPool->churnPool();
while (sgRandPool->mAvailableBytes != 0 && bytesNeeded != 0) {
sgRandPool->mAvailableBytes--;
bytesNeeded--;
pOutput[currOutput++] = sgRandPool->mRandomBytes[sgRandPool->mAvailableBytes];
}
}
}
void CryptRandomPool::churnPool()
{
SHA1Context hashCTX;
hashCTX.init();
hashCTX.hashBytes(mPool, 55);
hashCTX.finalize();
hashCTX.getHash(mRandomBytes);
mAvailableBytes = 20;
const U32* pChurn = (const U32*)mRandomBytes;
submitEntropy(pChurn[0], 32);
submitEntropy(pChurn[1], 32);
submitEntropy(pChurn[2], 32);
submitEntropy(pChurn[3], 32);
submitEntropy(pChurn[4], 32);
}