mirror of https://github.com/acidanthera/audk.git
190 lines
4.7 KiB
C
190 lines
4.7 KiB
C
/** @file
|
|
BaseRng Library that uses the TimerLib to provide reasonably random numbers.
|
|
Do not use this on a production system.
|
|
|
|
Copyright (c) Microsoft Corporation.
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
|
|
|
#include <Base.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/TimerLib.h>
|
|
|
|
#define DEFAULT_DELAY_TIME_IN_MICROSECONDS 10
|
|
|
|
/**
|
|
Using the TimerLib GetPerformanceCounterProperties() we delay
|
|
for enough time for the PerformanceCounter to increment.
|
|
|
|
If the return value from GetPerformanceCounterProperties (TimerLib)
|
|
is zero, this function will return 10 and attempt to assert.
|
|
**/
|
|
STATIC
|
|
UINT32
|
|
CalculateMinimumDecentDelayInMicroseconds (
|
|
VOID
|
|
)
|
|
{
|
|
UINT64 CounterHz;
|
|
|
|
// Get the counter properties
|
|
CounterHz = GetPerformanceCounterProperties (NULL, NULL);
|
|
// Make sure we won't divide by zero
|
|
if (CounterHz == 0) {
|
|
ASSERT(CounterHz != 0); // Assert so the developer knows something is wrong
|
|
return DEFAULT_DELAY_TIME_IN_MICROSECONDS;
|
|
}
|
|
// Calculate the minimum delay based on 1.5 microseconds divided by the hertz.
|
|
// We calculate the length of a cycle (1/CounterHz) and multiply it by 1.5 microseconds
|
|
// This ensures that the performance counter has increased by at least one
|
|
return (UINT32)(MAX (DivU64x64Remainder (1500000,CounterHz, NULL), 1));
|
|
}
|
|
|
|
|
|
/**
|
|
Generates a 16-bit random number.
|
|
|
|
if Rand is NULL, then ASSERT().
|
|
|
|
@param[out] Rand Buffer pointer to store the 16-bit random value.
|
|
|
|
@retval TRUE Random number generated successfully.
|
|
@retval FALSE Failed to generate the random number.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
GetRandomNumber16 (
|
|
OUT UINT16 *Rand
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT8 *RandPtr;
|
|
UINT32 DelayInMicroSeconds;
|
|
|
|
ASSERT (Rand != NULL);
|
|
|
|
if (Rand == NULL) {
|
|
return FALSE;
|
|
}
|
|
DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
|
|
RandPtr = (UINT8*)Rand;
|
|
// Get 2 bytes of random ish data
|
|
for (Index = 0; Index < sizeof(UINT16); Index ++) {
|
|
*RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
|
|
// Delay to give the performance counter a chance to change
|
|
MicroSecondDelay (DelayInMicroSeconds);
|
|
RandPtr++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Generates a 32-bit random number.
|
|
|
|
if Rand is NULL, then ASSERT().
|
|
|
|
@param[out] Rand Buffer pointer to store the 32-bit random value.
|
|
|
|
@retval TRUE Random number generated successfully.
|
|
@retval FALSE Failed to generate the random number.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
GetRandomNumber32 (
|
|
OUT UINT32 *Rand
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT8 *RandPtr;
|
|
UINT32 DelayInMicroSeconds;
|
|
|
|
ASSERT (Rand != NULL);
|
|
|
|
if (NULL == Rand) {
|
|
return FALSE;
|
|
}
|
|
|
|
RandPtr = (UINT8 *) Rand;
|
|
DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
|
|
// Get 4 bytes of random ish data
|
|
for (Index = 0; Index < sizeof(UINT32); Index ++) {
|
|
*RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
|
|
// Delay to give the performance counter a chance to change
|
|
MicroSecondDelay (DelayInMicroSeconds);
|
|
RandPtr++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Generates a 64-bit random number.
|
|
|
|
if Rand is NULL, then ASSERT().
|
|
|
|
@param[out] Rand Buffer pointer to store the 64-bit random value.
|
|
|
|
@retval TRUE Random number generated successfully.
|
|
@retval FALSE Failed to generate the random number.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
GetRandomNumber64 (
|
|
OUT UINT64 *Rand
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT8 *RandPtr;
|
|
UINT32 DelayInMicroSeconds;
|
|
|
|
ASSERT (Rand != NULL);
|
|
|
|
if (NULL == Rand) {
|
|
return FALSE;
|
|
}
|
|
|
|
RandPtr = (UINT8 *)Rand;
|
|
DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
|
|
// Get 8 bytes of random ish data
|
|
for (Index = 0; Index < sizeof(UINT64); Index ++) {
|
|
*RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
|
|
// Delay to give the performance counter a chance to change
|
|
MicroSecondDelay (DelayInMicroSeconds);
|
|
RandPtr++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Generates a 128-bit random number.
|
|
|
|
if Rand is NULL, then ASSERT().
|
|
|
|
@param[out] Rand Buffer pointer to store the 128-bit random value.
|
|
|
|
@retval TRUE Random number generated successfully.
|
|
@retval FALSE Failed to generate the random number.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
GetRandomNumber128 (
|
|
OUT UINT64 *Rand
|
|
)
|
|
{
|
|
ASSERT (Rand != NULL);
|
|
// This should take around 80ms
|
|
|
|
// Read first 64 bits
|
|
if (!GetRandomNumber64 (Rand)) {
|
|
return FALSE;
|
|
}
|
|
|
|
// Read second 64 bits
|
|
return GetRandomNumber64 (++Rand);
|
|
}
|