📄 fnaaccumulator.cpp
字号:
/* Copyright 2001,2002,2003 NAH6 BV
* All Rights Reserved
*
* $Header: /var/lib/cvs/secphone/ui/rng/fortuna/fnaAccumulator.cpp,v 1.4 2003/11/21 16:12:58 itsme Exp $
*
*
* Design of the PRNG is literally taken from 'Practical Cryptography', by Niels Ferguson, and Bruce Schneier.
*
*/
#include "fnaAccumulator.h"
#include "debug.h"
//--------------------------------------------------------------------------
Accumulator::Accumulator()
{
Initialize();
}
Accumulator::~Accumulator()
{
// on shutdown updateseedfile.
// unfortunately most of the time we are just killed, and no shutdown
// takes place. for that reason, we can either always call updateseedfile
// after a call to RandomData, or always gather entropy from sources before
// returning the first random.
UpdateSeedFile();
}
void Accumulator::Initialize()
{
// well, these 'initialize' calls are not really nescesary,
// they are also called from each objects default constructor.
for (int i=1 ; i<Accumulator::NROFPOOLS ; ++i)
m_pools[i].Initialize();
m_generator.Initialize();
m_reseedcount= 0;
debug("Accumulator::initialize()\n");
}
bool Accumulator::AddRandomEvent(sourcenumber_t source, poolnumber_t pool, const ByteVector& data)
{
if (source<0 || source>=Accumulator::NROFSOURCES)
{
debug("Accumulator::AddRandomEvent: invalid source number\n");
return false;
}
if (pool<0 || pool>=Accumulator::NROFPOOLS)
{
debug("Accumulator::AddRandomEvent: invalid pool number\n");
return false;
}
if (data.size()<=0 || data.size()>32)
{
debug("Accumulator::AddRandomEvent: invalid data size\n");
return false;
}
if (m_pools[pool].WaitForMutex())
{
m_pools[pool].Add((BYTE)source);
m_pools[pool].Add((BYTE)data.size());
m_pools[pool].Add(data);
m_pools[pool].ReleaseMutex();
return true;
}
debug("Accumulator::AddRandomEvent: could not get pool mutex\n");
return false;
}
void Accumulator::DoReseed()
{
debug("Accumulator::DoReseed\n");
ByteVector seed=m_pools[0].Use();
++m_reseedcount;
for (int i=1 ; i<Accumulator::NROFPOOLS ; ++i)
{
if (m_reseedcount&(1<<(i-1)))
break;
ByteVector poolvalue= m_pools[i].Use();
seed.insert(seed.end(), poolvalue.begin(), poolvalue.end());
}
m_generator.Reseed(seed);
}
bool Accumulator::RandomData(int nBytesRequested, ByteVector& r)
{
debug("Accumulator::RandomData pool[0]=%d, time=%d\n",
m_pools[0].GetSize(), GetTickCount()-m_reseedtime);
if (m_pools[0].GetSize() >= Accumulator::MINIMUMPOOLSIZE
&& GetTickCount()-m_reseedtime > Accumulator::MINIMUMRESEEDINTERVAL)
{
DoReseed();
m_reseedtime= GetTickCount();
}
return m_generator.PseudoRandomData(nBytesRequested, r);
}
bool Accumulator::WriteSeedFile()
{
ByteVector random;
if (!RandomData(Accumulator::SEEDFILESIZE, random))
{
debug("Accumulator::WriteSeedFile: error getting random data\n");
return false;
}
HANDLE hFile= CreateFile(L"seedfile.fna", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
if (hFile==NULL || hFile==INVALID_HANDLE_VALUE)
{
error("Accumulator::WriteSeedFile: error opening seedfile\n");
return false;
}
bool bRes= true;
DWORD nWritten;
if (!WriteFile(hFile, vectorptr(random), random.size(), &nWritten, NULL))
{
error("Accumulator::WriteSeedFile: error opening seedfile\n");
bRes= false;
}
if (nWritten!=random.size())
{
debug("Accumulator::WriteSeedFile: error writing seedfile\n");
bRes= false;
}
if (!FlushFileBuffers(hFile))
{
error("Accumulator::WriteSeedFile: error flushing seedfile\n");
bRes= false;
}
if (!CloseHandle(hFile))
{
error("Accumulator::WriteSeedFile: error closing seedfile\n");
bRes= false;
}
return bRes;
}
// this function should be called regularly
bool Accumulator::UpdateSeedFile()
{
if (!m_mutexUpdateSeed.Get())
{
debug("Accumulator::UpdateSeedFile: error getting mutex\n");
return false;
}
// todo: do this safer:
// - delete seedfile.lck
// - rename seedfile.fna to seedfile.lck
// - read seedfile.lck
// - create seedfile.fna
// - delete seedfile.lck
HANDLE hFile= CreateFile(L"seedfile.fna", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
if (hFile==NULL || hFile==INVALID_HANDLE_VALUE)
{
error("Accumulator::UpdateSeedFile: error opening seedfile\n");
m_mutexUpdateSeed.Release();
return false;
}
ByteVector random(Accumulator::SEEDFILESIZE);
bool bRes= true;
DWORD nRead;
if (!ReadFile(hFile, vectorptr(random), random.size(), &nRead, NULL))
{
error("Accumulator::UpdateSeedFile: error reading seedfile\n");
bRes= false;
}
if (nRead!=random.size())
{
debug("Accumulator::UpdateSeedFile: error reading seedfile\n");
bRes= false;
}
// make sure file is erased
if (0!=SetFilePointer(hFile, 0, NULL, FILE_BEGIN))
{
error("Accumulator::UpdateSeedFile: error truncating seedfile\n");
bRes= false;
}
if (!SetEndOfFile(hFile))
{
error("Accumulator::UpdateSeedFile: error truncating seedfile\n");
bRes= false;
}
AddSystemTimeToRandom(random);
m_generator.Reseed(random);
// reusing 'random' variable to update seedfile
if (!RandomData(Accumulator::SEEDFILESIZE, random))
{
debug("Accumulator::UpdateSeedFile: error getting random\n");
bRes= false; // should never happen.
}
DWORD nWritten;
if (!WriteFile(hFile, vectorptr(random), random.size(), &nWritten, NULL))
{
error("Accumulator::UpdateSeedFile: error writing seedfile\n");
bRes= false;
}
if (nWritten!=random.size())
{
debug("Accumulator::UpdateSeedFile: error writing seedfile\n");
bRes= false;
}
if (!FlushFileBuffers(hFile))
{
error("Accumulator::UpdateSeedFile: error flushing seedfile\n");
bRes= false;
}
if (!CloseHandle(hFile))
{
error("Accumulator::UpdateSeedFile: error closing seedfile\n");
bRes= false;
}
m_properly_seeded= bRes;
m_mutexUpdateSeed.Release();
return bRes;
}
void Accumulator::AddSystemTimeToRandom(ByteVector& random)
{
SYSTEMTIME systime[1];
GetSystemTime(systime);
ByteVector bytes((BYTE*)&systime[0], (BYTE*)&systime[1]);
random.insert(random.end(), bytes.begin(), bytes.end());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -