[random-manager] move entropy and rng related code into RandomManager (#3953)

This commit moves all the related code for managing entropy and crypto
and non-crypto random number generation into the `RandomManager`
class. This helps simplify the initialization process by having all
modules use a shared common init counter (`sInitCount`). This commit
also ensures that the shared instance of the non-crypto pseudo random
number generator is seeded only once.
This commit is contained in:
Abtin Keshavarzian
2019-07-03 10:54:17 -07:00
committed by Jonathan Hui
parent 0d75bbe3fa
commit be994b66cf
10 changed files with 253 additions and 447 deletions
-3
View File
@@ -133,14 +133,11 @@ LOCAL_SRC_FILES := \
src/core/coap/coap_message.cpp \
src/core/coap/coap_secure.cpp \
src/core/common/crc16.cpp \
src/core/common/entropy.cpp \
src/core/common/instance.cpp \
src/core/common/logging.cpp \
src/core/common/message.cpp \
src/core/common/notifier.cpp \
src/core/common/random_crypto.cpp \
src/core/common/random_manager.cpp \
src/core/common/random_noncrypto.cpp \
src/core/common/settings.cpp \
src/core/common/string.cpp \
src/core/common/tasklet.cpp \
-6
View File
@@ -137,14 +137,11 @@ SOURCES_COMMON = \
coap/coap_message.cpp \
coap/coap_secure.cpp \
common/crc16.cpp \
common/entropy.cpp \
common/instance.cpp \
common/logging.cpp \
common/message.cpp \
common/notifier.cpp \
common/random_crypto.cpp \
common/random_manager.cpp \
common/random_noncrypto.cpp \
common/settings.cpp \
common/string.cpp \
common/tasklet.cpp \
@@ -241,11 +238,9 @@ libopenthread_radio_a_SOURCES = \
api/logging_api.cpp \
api/random_noncrypto_api.cpp \
api/tasklet_api.cpp \
common/entropy.cpp \
common/instance.cpp \
common/logging.cpp \
common/random_manager.cpp \
common/random_noncrypto.cpp \
common/string.cpp \
common/tasklet.cpp \
common/timer.cpp \
@@ -302,7 +297,6 @@ HEADERS_COMMON = \
common/crc16.hpp \
common/debug.hpp \
common/encoding.hpp \
common/entropy.hpp \
common/extension.hpp \
common/instance.hpp \
common/locator.hpp \
+2 -4
View File
@@ -33,13 +33,11 @@
#include "openthread/entropy.h"
#include <mbedtls/entropy.h>
#include "common/entropy.hpp"
#include "common/random_manager.hpp"
using namespace ot;
mbedtls_entropy_context *otEntropyMbedTlsContextGet(void)
{
return Entropy::MbedTlsContextGet();
return RandomManager::GetMbedTlsEntropyContext();
}
-131
View File
@@ -1,131 +0,0 @@
/*
* Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file provides an implementation of entropy source.
*/
#include "entropy.hpp"
#include <openthread/platform/entropy.h>
#include <openthread/platform/toolchain.h>
#include "code_utils.hpp"
#include "debug.hpp"
#ifndef OPENTHREAD_RADIO
#include <mbedtls/entropy.h>
#include <mbedtls/entropy_poll.h>
#endif // OPENTHREAD_RADIO
namespace ot {
namespace Entropy {
static uint32_t sInitCnt = 0;
#ifndef OPENTHREAD_RADIO
static mbedtls_entropy_context sEntropy;
static int HandleMbedtlsEntropyPoll(void *aData, unsigned char *aOutput, size_t aInLen, size_t *aOutLen)
{
OT_UNUSED_VARIABLE(aData);
otError error;
int rval = 0;
error = otPlatEntropyGet(reinterpret_cast<uint8_t *>(aOutput), static_cast<uint16_t>(aInLen));
SuccessOrExit(error);
if (aOutLen != NULL)
{
*aOutLen = aInLen;
}
exit:
if (error != OT_ERROR_NONE)
{
rval = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
return rval;
}
#endif // OPENTHREAD_RADIO
void Init(void)
{
assert(sInitCnt < 0xffffffff);
#ifndef OPENTHREAD_RADIO
if (sInitCnt == 0)
{
mbedtls_entropy_init(&sEntropy);
mbedtls_entropy_add_source(&sEntropy, &HandleMbedtlsEntropyPoll, NULL, MBEDTLS_ENTROPY_MIN_HARDWARE,
MBEDTLS_ENTROPY_SOURCE_STRONG);
}
#endif // OPENTHREAD_RADIO
sInitCnt++;
}
void Deinit(void)
{
assert(sInitCnt > 0);
sInitCnt--;
#ifndef OPENTHREAD_RADIO
if (sInitCnt == 0)
{
mbedtls_entropy_free(&sEntropy);
}
#endif // OPENTHREAD_RADIO
}
#ifndef OPENTHREAD_RADIO
mbedtls_entropy_context *MbedTlsContextGet(void)
{
assert(sInitCnt > 0);
return &sEntropy;
}
#endif // OPENTHREAD_RADIO
otError GetUint32(uint32_t &aVal)
{
assert(sInitCnt > 0);
return otPlatEntropyGet(reinterpret_cast<uint8_t *>(&aVal), sizeof(aVal));
}
} // namespace Entropy
} // namespace ot
-88
View File
@@ -1,88 +0,0 @@
/*
* Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for OpenThread entropy generation.
*/
#ifndef ENTROPY_HPP_
#define ENTROPY_HPP_
#include "openthread-core-config.h"
#include <stdint.h>
#include <openthread/error.h>
#ifndef OPENTHREAD_RADIO
#include <mbedtls/entropy.h>
#endif // OPENTHREAD_RADIO
namespace ot {
namespace Entropy {
/**
* This function initializes entropy source.
*
*/
void Init(void);
/**
* This function deinitializes entropy source.
*
*/
void Deinit(void);
#ifndef OPENTHREAD_RADIO
/**
* This function returns initialized mbedtls_entropy_context.
*
* @returns A pointer to initialized mbedtls_entropy_context.
*/
mbedtls_entropy_context *MbedTlsContextGet(void);
#endif // OPENTHREAD_RADIO
/**
* This function generates and returns a 32 bit entropy.
*
* @param aVal[out] A generated 32 bit entropy value.
*
* @retval OT_ERROR_NONE Successfully generated 32 bit entropy.
*
*/
otError GetUint32(uint32_t &aVal);
} // namespace Entropy
} // namespace ot
#endif // ENTROPY_HPP_
+13 -29
View File
@@ -39,14 +39,9 @@
#include <openthread/error.h>
#include "common/debug.hpp"
#include "common/random_manager.hpp"
#include "utils/wrap_stdint.h"
#ifndef OPENTHREAD_RADIO
#include <mbedtls/ctr_drbg.h>
#endif // OPENTHREAD_RADIO
namespace ot {
namespace Random {
namespace NonCrypto {
@@ -57,7 +52,10 @@ namespace NonCrypto {
* @returns A random `uint32_t` value.
*
*/
uint32_t GetUint32(void);
inline uint32_t GetUint32(void)
{
return ot::RandomManager::NonCryptoGetUint32();
}
/**
* This function generates and returns a random byte.
@@ -159,32 +157,12 @@ inline uint32_t AddJitter(uint32_t aValue, uint16_t aJitter)
return aValue + GetUint32InRange(0, 2 * aJitter + 1) - aJitter;
}
/**
* This function seeds a software random generator.
*
* @param[in] aSeed Seed value.
*
*/
void Seed(uint32_t aSeed);
} // namespace NonCrypto
#ifndef OPENTHREAD_RADIO
namespace Crypto {
/**
* This function initializes cryptographic random number generator.
*
*/
void Init(void);
/**
* This function deinitializes cryptographic random number generator.
*
*/
void Deinit(void);
/**
* This function fills a given buffer with cryptographically secure random bytes.
*
@@ -194,7 +172,10 @@ void Deinit(void);
* @retval OT_ERROR_NONE Successfully filled buffer with random values.
*
*/
otError FillBuffer(uint8_t *aBuffer, uint16_t aSize);
inline otError FillBuffer(uint8_t *aBuffer, uint16_t aSize)
{
return RandomManager::CryptoFillBuffer(aBuffer, aSize);
}
/**
* This function returns initialized mbedtls_ctr_drbg_context.
@@ -202,7 +183,10 @@ otError FillBuffer(uint8_t *aBuffer, uint16_t aSize);
* @returns A pointer to initialized mbedtls_ctr_drbg_context.
*
*/
mbedtls_ctr_drbg_context *MbedTlsContextGet(void);
inline mbedtls_ctr_drbg_context *MbedTlsContextGet(void)
{
return RandomManager::GetMbedTlsCtrDrbgContext();
}
} // namespace Crypto
-96
View File
@@ -1,96 +0,0 @@
/*
* Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file provides an implementation of cryptographic random number generator.
*/
#include "random.hpp"
#include <stdint.h>
#include "entropy.hpp"
#include "crypto/mbedtls.hpp"
#include <mbedtls/entropy.h>
#include "debug.hpp"
namespace ot {
namespace Random {
namespace Crypto {
static uint32_t sInitCnt = 0;
static mbedtls_ctr_drbg_context sCtrDrbg;
void Init(void)
{
assert(sInitCnt < 0xffffffff);
if (sInitCnt == 0)
{
mbedtls_ctr_drbg_init(&sCtrDrbg);
mbedtls_ctr_drbg_seed(&sCtrDrbg, mbedtls_entropy_func, Entropy::MbedTlsContextGet(), NULL, 0);
}
sInitCnt++;
}
void Deinit(void)
{
assert(sInitCnt > 0);
sInitCnt--;
if (sInitCnt == 0)
{
mbedtls_ctr_drbg_free(&sCtrDrbg);
}
}
mbedtls_ctr_drbg_context *MbedTlsContextGet(void)
{
assert(sInitCnt > 0);
return &sCtrDrbg;
}
otError FillBuffer(uint8_t *aBuffer, uint16_t aSize)
{
int rval = 0;
assert(sInitCnt > 0);
rval = mbedtls_ctr_drbg_random(&sCtrDrbg, static_cast<unsigned char *>(aBuffer), static_cast<size_t>(aSize));
return ot::Crypto::MbedTls::MapError(rval);
}
} // namespace Crypto
} // namespace Random
} // namespace ot
+144 -12
View File
@@ -33,37 +33,169 @@
#include "random_manager.hpp"
#include <openthread/error.h>
#include <openthread/platform/entropy.h>
#include "debug.hpp"
#include "entropy.hpp"
#include "random.hpp"
#ifndef OPENTHREAD_RADIO
#include <mbedtls/entropy_poll.h>
#endif
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/random.hpp"
#include "crypto/mbedtls.hpp"
namespace ot {
uint16_t RandomManager::sInitCount = 0;
RandomManager::NonCryptoPrng RandomManager::sPrng;
#ifndef OPENTHREAD_RADIO
RandomManager::Entropy RandomManager::sEntropy;
RandomManager::CryptoCtrDrbg RandomManager::sCtrDrbg;
#endif
RandomManager::RandomManager(void)
{
uint32_t seed;
otError error;
Entropy::Init();
assert(sInitCount < 0xffff);
error = Entropy::GetUint32(seed);
assert(error == OT_ERROR_NONE);
Random::NonCrypto::Seed(seed);
VerifyOrExit(sInitCount == 0);
#ifndef OPENTHREAD_RADIO
Random::Crypto::Init();
sEntropy.Init();
#endif
error = otPlatEntropyGet(reinterpret_cast<uint8_t *>(&seed), sizeof(seed));
assert(error == OT_ERROR_NONE);
sPrng.Init(seed);
#ifndef OPENTHREAD_RADIO
sCtrDrbg.Init();
#endif
exit:
sInitCount++;
}
RandomManager::~RandomManager(void)
{
assert(sInitCount > 0);
sInitCount--;
VerifyOrExit(sInitCount == 0);
#ifndef OPENTHREAD_RADIO
Random::Crypto::Deinit();
sCtrDrbg.Deinit();
sEntropy.Deinit();
#endif
Entropy::Deinit();
exit:
return;
}
uint32_t RandomManager::NonCryptoGetUint32(void)
{
assert(sInitCount > 0);
return sPrng.GetNext();
}
//-------------------------------------------------------------------
// NonCryptoPrng
void RandomManager::NonCryptoPrng::Init(uint32_t aSeed)
{
// The PRNG has a cycle of length 1 for the below two initial
// seeds. For all other seed values the cycle is ~2^31 long.
if ((aSeed == 0) || (aSeed == 0x7fffffff))
{
aSeed = 0x1;
}
mState = aSeed;
}
uint32_t RandomManager::NonCryptoPrng::GetNext(void)
{
uint32_t mlcg, p, q;
uint64_t tmpstate;
tmpstate = (uint64_t)33614 * (uint64_t)mState;
q = tmpstate & 0xffffffff;
q = q >> 1;
p = tmpstate >> 32;
mlcg = p + q;
if (mlcg & 0x80000000)
{
mlcg &= 0x7fffffff;
mlcg++;
}
mState = mlcg;
return mlcg;
}
#ifndef OPENTHREAD_RADIO
//-------------------------------------------------------------------
// Entropy
void RandomManager::Entropy::Init(void)
{
mbedtls_entropy_init(&mEntropyContext);
mbedtls_entropy_add_source(&mEntropyContext, &RandomManager::Entropy::HandleMbedtlsEntropyPoll, NULL,
MBEDTLS_ENTROPY_MIN_HARDWARE, MBEDTLS_ENTROPY_SOURCE_STRONG);
}
void RandomManager::Entropy::Deinit(void)
{
mbedtls_entropy_free(&mEntropyContext);
}
int RandomManager::Entropy::HandleMbedtlsEntropyPoll(void * aData,
unsigned char *aOutput,
size_t aInLen,
size_t * aOutLen)
{
int rval = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
SuccessOrExit(otPlatEntropyGet(reinterpret_cast<uint8_t *>(aOutput), static_cast<uint16_t>(aInLen)));
rval = 0;
VerifyOrExit(aOutLen != NULL);
*aOutLen = aInLen;
exit:
OT_UNUSED_VARIABLE(aData);
return rval;
}
//-------------------------------------------------------------------
// CryptoCtrDrbg
void RandomManager::CryptoCtrDrbg::Init(void)
{
mbedtls_ctr_drbg_init(&mCtrDrbg);
mbedtls_ctr_drbg_seed(&mCtrDrbg, mbedtls_entropy_func, RandomManager::GetMbedTlsEntropyContext(), NULL, 0);
}
void RandomManager::CryptoCtrDrbg::Deinit(void)
{
mbedtls_ctr_drbg_free(&mCtrDrbg);
}
otError RandomManager::CryptoCtrDrbg::FillBuffer(uint8_t *aBuffer, uint16_t aSize)
{
return ot::Crypto::MbedTls::MapError(
mbedtls_ctr_drbg_random(&mCtrDrbg, static_cast<unsigned char *>(aBuffer), static_cast<size_t>(aSize)));
}
#endif // #ifndef OPENTHREAD_RADIO
} // namespace ot
+94
View File
@@ -34,6 +34,17 @@
#ifndef RANDOM_MANAGER_HPP_
#define RANDOM_MANAGER_HPP_
#include "openthread-core-config.h"
#include <openthread/error.h>
#ifndef OPENTHREAD_RADIO
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#endif
#include "utils/wrap_stdint.h"
namespace ot {
/**
@@ -54,6 +65,89 @@ public:
*
*/
~RandomManager(void);
/**
* This static method generates and returns a random value using a non-crypto Pseudo Random Number Generator.
*
* @returns A random `uint32_t` value.
*
*/
static uint32_t NonCryptoGetUint32(void);
#ifndef OPENTHREAD_RADIO
/**
* This static method returns the initialized mbedtls_entropy_context.
*
* @returns A pointer to initialized mbedtls_entropy_context.
*/
static mbedtls_entropy_context *GetMbedTlsEntropyContext(void) { return sEntropy.GetContext(); }
/**
* This static method fills a given buffer with cryptographically secure random bytes.
*
* @param[out] aBuffer A pointer to a buffer to fill with the random bytes.
* @param[in] aSize Size of buffer (number of bytes to fill).
*
* @retval OT_ERROR_NONE Successfully filled buffer with random values.
*
*/
static otError CryptoFillBuffer(uint8_t *aBuffer, uint16_t aSize) { return sCtrDrbg.FillBuffer(aBuffer, aSize); }
/**
* This static method returns the initialized mbedtls_ctr_drbg_context.
*
* @returns A pointer to the initialized mbedtls_ctr_drbg_context.
*
*/
static mbedtls_ctr_drbg_context *GetMbedTlsCtrDrbgContext(void) { return sCtrDrbg.GetContext(); }
#endif
private:
class NonCryptoPrng // A non-crypto Pseudo Random Number Generator (PRNG)
{
public:
void Init(uint32_t aSeed);
uint32_t GetNext(void);
private:
uint32_t mState;
};
#ifndef OPENTHREAD_RADIO
class Entropy
{
public:
void Init(void);
void Deinit(void);
mbedtls_entropy_context *GetContext(void) { return &mEntropyContext; }
private:
static int HandleMbedtlsEntropyPoll(void *aData, unsigned char *aOutput, size_t aInLen, size_t *aOutLen);
mbedtls_entropy_context mEntropyContext;
};
class CryptoCtrDrbg
{
public:
void Init(void);
void Deinit(void);
otError FillBuffer(uint8_t *aBuffer, uint16_t aSize);
mbedtls_ctr_drbg_context *GetContext(void) { return &mCtrDrbg; }
private:
mbedtls_ctr_drbg_context mCtrDrbg;
};
#endif
static uint16_t sInitCount;
static NonCryptoPrng sPrng;
#ifndef OPENTHREAD_RADIO
static Entropy sEntropy;
static CryptoCtrDrbg sCtrDrbg;
#endif
};
} // namespace ot
-78
View File
@@ -1,78 +0,0 @@
/*
* Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file provides an implementation of software random number generator.
*/
#include "random.hpp"
#include "debug.hpp"
#include "entropy.hpp"
namespace ot {
namespace Random {
namespace NonCrypto {
static uint32_t sState;
static bool sSeeded;
uint32_t GetUint32(void)
{
uint32_t mlcg, p, q;
uint64_t tmpstate;
assert(sSeeded);
tmpstate = (uint64_t)33614 * (uint64_t)sState;
q = tmpstate & 0xffffffff;
q = q >> 1;
p = tmpstate >> 32;
mlcg = p + q;
if (mlcg & 0x80000000)
{
mlcg &= 0x7fffffff;
mlcg++;
}
sState = mlcg;
return mlcg;
}
void Seed(uint32_t aSeed)
{
sSeeded = true;
sState = aSeed;
}
} // namespace NonCrypto
} // namespace Random
} // namespace ot