mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
3.8 KiB
182 lines
3.8 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: rng.c
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 8-15-95 RichardW Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "sslsspi.h"
|
|
|
|
#include "rc4.h"
|
|
|
|
|
|
#define RNG_BITS 64
|
|
#define RNG_BYTES_PER_BATCH 768
|
|
|
|
typedef struct _SourceBits {
|
|
ULONG Valid;
|
|
BYTE Bits[RNG_BITS];
|
|
} SourceBits, * PSourceBits;
|
|
|
|
typedef struct _RNG_State {
|
|
RTL_CRITICAL_SECTION csLock;
|
|
LONG Available;
|
|
RC4_KEYSTRUCT key;
|
|
} RNG_State;
|
|
|
|
|
|
|
|
#define SEED_ARRAY_SIZE 16
|
|
|
|
|
|
RNG_State SslRNG;
|
|
|
|
#define LockRNG(r) EnterCriticalSection( &r.csLock )
|
|
#define UnlockRNG(r) LeaveCriticalSection( &r.csLock )
|
|
|
|
|
|
#define ADD_BYTE(p, x) \
|
|
((PSourceBits) p)->Bits[ ((PSourceBits) p)->Valid++ ] = x; \
|
|
if (((PSourceBits) p)->Valid >= RNG_BITS ) \
|
|
{ \
|
|
goto SystemData_Exit; \
|
|
}
|
|
|
|
VOID
|
|
SslGetSystemData(
|
|
PSourceBits pBits
|
|
)
|
|
{
|
|
LARGE_INTEGER liPerf;
|
|
SYSTEMTIME SystemTime;
|
|
MEMORYSTATUS Mem;
|
|
DWORD i;
|
|
|
|
|
|
GetLocalTime(&SystemTime);
|
|
|
|
ADD_BYTE(pBits, LOBYTE( SystemTime.wMilliseconds ) );
|
|
|
|
ADD_BYTE(pBits, HIBYTE( SystemTime.wMilliseconds ) );
|
|
|
|
ADD_BYTE(pBits, LOBYTE( SystemTime.wSecond ) ^ LOBYTE( SystemTime.wMinute ) );
|
|
|
|
if (QueryPerformanceCounter(&liPerf))
|
|
{
|
|
ADD_BYTE(pBits, LOBYTE( LOWORD( liPerf.LowPart ) ) ^ LOBYTE( LOWORD( liPerf.HighPart ) ) );
|
|
ADD_BYTE(pBits, HIBYTE( LOWORD( liPerf.LowPart ) ) ^ LOBYTE( LOWORD( liPerf.HighPart ) ) );
|
|
ADD_BYTE(pBits, LOBYTE( HIWORD( liPerf.LowPart ) ) ^ LOBYTE( LOWORD( liPerf.HighPart ) ) );
|
|
ADD_BYTE(pBits, HIBYTE( HIWORD( liPerf.LowPart ) ) ^ LOBYTE( LOWORD( liPerf.HighPart ) ) );
|
|
}
|
|
|
|
GlobalMemoryStatus( &Mem );
|
|
|
|
ADD_BYTE(pBits, LOBYTE( HIWORD( Mem.dwAvailPhys ) ) );
|
|
ADD_BYTE(pBits, HIBYTE( HIWORD( Mem.dwAvailPhys ) ) );
|
|
ADD_BYTE(pBits, LOBYTE( HIWORD( Mem.dwAvailPageFile ) ) );
|
|
ADD_BYTE(pBits, HIBYTE( HIWORD( Mem.dwAvailPageFile ) ) );
|
|
ADD_BYTE(pBits, LOBYTE( HIWORD( Mem.dwAvailVirtual ) ) );
|
|
|
|
//
|
|
// TODO: Add other things, like cache manager, heap frag, etc.
|
|
//
|
|
|
|
SystemData_Exit:
|
|
|
|
for (i = 0 ; i < pBits->Valid ; i++ )
|
|
{
|
|
pBits->Bits[ i ] ^= pBits->Bits[ pBits->Valid - i ];
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
SslGenerateRandomBits(
|
|
PUCHAR pRandomData,
|
|
LONG cRandomData
|
|
)
|
|
{
|
|
LONG i;
|
|
DWORD Bytes;
|
|
SourceBits Bits;
|
|
|
|
ZeroMemory( pRandomData, cRandomData );
|
|
|
|
LockRNG( SslRNG );
|
|
|
|
if (cRandomData > SslRNG.Available)
|
|
{
|
|
Bytes = SslRNG.Available;
|
|
}
|
|
else
|
|
{
|
|
Bytes = cRandomData;
|
|
}
|
|
|
|
cRandomData -= Bytes;
|
|
|
|
if (Bytes)
|
|
{
|
|
rc4( &SslRNG.key, Bytes, pRandomData );
|
|
|
|
SslRNG.Available -= Bytes;
|
|
}
|
|
|
|
if (cRandomData)
|
|
{
|
|
pRandomData += Bytes;
|
|
|
|
Bits.Valid = 0;
|
|
|
|
SslGetSystemData( &Bits );
|
|
|
|
ZeroMemory( &SslRNG.key, sizeof( RC4_KEYSTRUCT ) );
|
|
|
|
rc4_key( &SslRNG.key, Bits.Valid, Bits.Bits );
|
|
|
|
rc4( &SslRNG.key, cRandomData, pRandomData );
|
|
|
|
SslRNG.Available = RNG_BYTES_PER_BATCH - cRandomData ;
|
|
|
|
if (SslRNG.Available < 0)
|
|
{
|
|
SslRNG.Available = 0;
|
|
}
|
|
|
|
}
|
|
|
|
UnlockRNG( SslRNG );
|
|
|
|
}
|
|
|
|
VOID
|
|
GenRandom(
|
|
PVOID ignored,
|
|
PUCHAR p,
|
|
ULONG c)
|
|
{
|
|
SslGenerateRandomBits(p, (LONG) c);
|
|
}
|
|
|
|
VOID
|
|
InitializeRNG(VOID)
|
|
{
|
|
InitializeCriticalSection( &SslRNG.csLock );
|
|
|
|
LockRNG( SslRNG );
|
|
|
|
SslRNG.Available = 0;
|
|
|
|
UnlockRNG( SslRNG );
|
|
|
|
}
|