osrng.h
Go to the documentation of this file.
// osrng.h - originally written and placed in the public domain by Wei Dai
/// \file osrng.h
/// \brief Classes for access to the operating system's random number generators
#ifndef CRYPTOPP_OSRNG_H
#define CRYPTOPP_OSRNG_H
#include "config.h"
#if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE)
#include "cryptlib.h"
#include "randpool.h"
#include "smartptr.h"
#include "fips140.h"
#include "hkdf.h"
#include "rng.h"
#include "aes.h"
#include "sha.h"
NAMESPACE_BEGIN(CryptoPP)
/// \brief Exception thrown when an operating system error is encountered
class CRYPTOPP_DLL OS_RNG_Err : public Exception
{
public:
/// \brief Constructs an OS_RNG_Err
/// \param operation the operation or API call when the error occurs
OS_RNG_Err(const std::string &operation);
};
#ifdef NONBLOCKING_RNG_AVAILABLE
#ifdef CRYPTOPP_WIN32_AVAILABLE
/// \brief Wrapper for Microsoft crypto service provider
/// \sa \def USE_MS_CRYPTOAPI, \def USE_MS_CNGAPI
class CRYPTOPP_DLL MicrosoftCryptoProvider
{
public:
/// \brief Construct a MicrosoftCryptoProvider
MicrosoftCryptoProvider();
~MicrosoftCryptoProvider();
// type HCRYPTPROV and BCRYPT_ALG_HANDLE, avoid #include <windows.h>
#if defined(USE_MS_CRYPTOAPI)
# if defined(__CYGWIN__) && defined(__x86_64__)
typedef unsigned long long ProviderHandle;
# elif defined(WIN64) || defined(_WIN64)
typedef unsigned __int64 ProviderHandle;
# else
typedef unsigned long ProviderHandle;
# endif
#elif defined(USE_MS_CNGAPI)
typedef void *PVOID;
typedef PVOID ProviderHandle;
#endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI
/// \brief Retrieves the provider handle
/// \return CryptoAPI provider handle
/// \details If USE_MS_CRYPTOAPI is in effect, then CryptAcquireContext()
/// acquires then handle and CryptReleaseContext() releases the handle
/// upon destruction. If USE_MS_CNGAPI is in effect, then
/// BCryptOpenAlgorithmProvider() acquires then handle and
/// BCryptCloseAlgorithmProvider() releases the handle upon destruction.
ProviderHandle GetProviderHandle() const {return m_hProvider;}
private:
ProviderHandle m_hProvider;
};
#if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CRYPTOAPI)
# pragma comment(lib, "advapi32.lib")
#endif
#if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CNGAPI)
# pragma comment(lib, "bcrypt.lib")
#endif
#endif // CRYPTOPP_WIN32_AVAILABLE
/// \brief Wrapper class for /dev/random and /dev/srandom
/// \details Encapsulates CryptoAPI's CryptGenRandom() or CryptoNG's BCryptGenRandom()
/// on Windows, or /dev/urandom on Unix and compatibles.
class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
{
public:
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "NonblockingRng"; }
~NonblockingRng();
/// \brief Construct a NonblockingRng
NonblockingRng();
/// \brief Generate random array of bytes
/// \param output the byte buffer
/// \param size the length of the buffer, in bytes
/// \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
void GenerateBlock(byte *output, size_t size);
protected:
#ifdef CRYPTOPP_WIN32_AVAILABLE
MicrosoftCryptoProvider m_Provider;
#else
int m_fd;
#endif
};
#endif
#if defined(BLOCKING_RNG_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
/// \brief Wrapper class for /dev/random and /dev/srandom
/// \details Encapsulates /dev/random on Linux, OS X and Unix; and /dev/srandom on the BSDs.
/// \note On Linux the /dev/random interface is effectively deprecated. According to the
/// Kernel Crypto developers, /dev/urandom or getrandom(2) should be used instead. Also
/// see <A HREF="https://lkml.org/lkml/2017/7/20/993">[RFC PATCH v12 3/4] Linux Random
/// Number Generator</A> on the kernel-crypto mailing list.
class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
{
public:
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "BlockingRng"; }
~BlockingRng();
/// \brief Construct a BlockingRng
BlockingRng();
/// \brief Generate random array of bytes
/// \param output the byte buffer
/// \param size the length of the buffer, in bytes
/// \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
void GenerateBlock(byte *output, size_t size);
protected:
int m_fd;
};
#endif
/// OS_GenerateRandomBlock
/// \brief Generate random array of bytes
/// \param blocking specifies whether a blocking or non-blocking generator should be used
/// \param output the byte buffer
/// \param size the length of the buffer, in bytes
/// \details OS_GenerateRandomBlock() uses the underlying operating system's
/// random number generator. On Windows, CryptGenRandom() is called using NonblockingRng.
/// \details On Unix and compatibles, /dev/urandom is called if blocking is false using
/// NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used
/// by way of BlockingRng, if available.
CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size);
/// \brief Automatically Seeded Randomness Pool
/// \details This class seeds itself using an operating system provided RNG.
/// AutoSeededRandomPool was suggested by Leonard Janke.
/// \details You should reseed the generator after a fork() to avoid multiple generators
/// with the same internal state.
class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
{
public:
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "AutoSeededRandomPool"; }
~AutoSeededRandomPool() {}
/// \brief Construct an AutoSeededRandomPool
/// \param blocking controls seeding with BlockingRng or NonblockingRng
/// \param seedSize the size of the seed, in bytes
/// \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
/// The parameter is ignored if only one of these is available.
explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
{Reseed(blocking, seedSize);}
/// \brief Reseed an AutoSeededRandomPool
/// \param blocking controls seeding with BlockingRng or NonblockingRng
/// \param seedSize the size of the seed, in bytes
void Reseed(bool blocking = false, unsigned int seedSize = 32);
};
/// \tparam BLOCK_CIPHER a block cipher
/// \brief Automatically Seeded X9.17 RNG
/// \details AutoSeededX917RNG is from ANSI X9.17 Appendix C, seeded using an OS provided RNG.
/// If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is
/// used, then its a X9.31 conforming generator.
/// \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER
/// can be any BlockTransformation derived class.
/// \details You should reseed the generator after a fork() to avoid multiple generators
/// with the same internal state.
/// \sa X917RNG, DefaultAutoSeededRNG
template <class BLOCK_CIPHER>
class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
{
public:
static std::string StaticAlgorithmName() {
return std::string("AutoSeededX917RNG(") + BLOCK_CIPHER::StaticAlgorithmName() + std::string(")");
}
~AutoSeededX917RNG() {}
/// \brief Construct an AutoSeededX917RNG
/// \param blocking controls seeding with BlockingRng or NonblockingRng
/// \param autoSeed controls auto seeding of the generator
/// \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
/// The parameter is ignored if only one of these is available.
/// \sa X917RNG
explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true)
{if (autoSeed) Reseed(blocking);}
/// \brief Reseed an AutoSeededX917RNG
/// \param blocking controls seeding with BlockingRng or NonblockingRng
/// \param input additional entropy to add to the generator
/// \param length the size of the additional entropy, in bytes
/// \details Internally, the generator uses SHA256 to extract the entropy from
/// from the seed and then stretch the material for the block cipher's key
/// and initialization vector.
void Reseed(bool blocking = false, const byte *input = NULLPTR, size_t length = 0);
/// \brief Deterministically reseed an AutoSeededX917RNG for testing
/// \param key the key to use for the deterministic reseeding
/// \param keylength the size of the key, in bytes
/// \param seed the seed to use for the deterministic reseeding
/// \param timeVector a time vector to use for deterministic reseeding
/// \details This is a testing interface for testing purposes, and should \a NOT
/// be used in production.
void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
bool CanIncorporateEntropy() const {return true;}
void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);}
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
{m_rng->GenerateIntoBufferedTransformation(target, channel, length);}
std::string AlgorithmProvider() const;
private:
member_ptr<RandomNumberGenerator> m_rng;
};
template <class BLOCK_CIPHER>
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
{
m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
}
template <class BLOCK_CIPHER>
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length)
{
enum {BlockSize=BLOCK_CIPHER::BLOCKSIZE};
enum {KeyLength=BLOCK_CIPHER::DEFAULT_KEYLENGTH};
enum {SeedSize=EnumToInt(BlockSize)+EnumToInt(KeyLength)};
SecByteBlock seed(SeedSize), temp(SeedSize);
const byte label[] = "X9.17 key generation";
const byte *key=NULLPTR;
do
{
OS_GenerateRandomBlock(blocking, temp, temp.size());
HKDF<SHA256> hkdf;
hkdf.DeriveKey(
seed, seed.size(), // derived secret
temp, temp.size(), // instance secret
input, length, // user secret
label, 20 // unique label
);
key = seed + BlockSize;
} // check that seed and key don't have same value
while (std::memcmp(key, seed, STDMIN((size_t)BlockSize, (size_t)KeyLength)) == 0);
Reseed(key, KeyLength, seed, NULLPTR);
}
template <class BLOCK_CIPHER>
std::string AutoSeededX917RNG<BLOCK_CIPHER>::AlgorithmProvider() const
{
// Hack for now... We need to instantiate one
typename BLOCK_CIPHER::Encryption bc;
return bc.AlgorithmProvider();
}
CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
/// \brief A typedef providing a default generator
/// \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG<AES> or AutoSeededRandomPool.
/// If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is
/// AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool.
/// \details You should reseed the generator after a fork() to avoid multiple generators
/// with the same internal state.
class DefaultAutoSeededRNG {}
#else
// AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
#else
typedef AutoSeededRandomPool DefaultAutoSeededRNG;
#endif
#endif // CRYPTOPP_DOXYGEN_PROCESSING
NAMESPACE_END
#endif
#endif
aes.h
Class file for the AES cipher (Rijndael)
AutoSeededRandomPool
Automatically Seeded Randomness Pool.
Definition osrng.h:159
AutoSeededRandomPool::Reseed
void Reseed(bool blocking=false, unsigned int seedSize=32)
Reseed an AutoSeededRandomPool.
AutoSeededRandomPool::AutoSeededRandomPool
AutoSeededRandomPool(bool blocking=false, unsigned int seedSize=32)
Construct an AutoSeededRandomPool.
Definition osrng.h:170
AutoSeededX917RNG
Automatically Seeded X9.17 RNG.
Definition osrng.h:191
AutoSeededX917RNG::CanIncorporateEntropy
bool CanIncorporateEntropy() const
Determines if a generator can accept additional entropy.
Definition osrng.h:226
AutoSeededX917RNG::Reseed
void Reseed(bool blocking=false, const byte *input=NULL, size_t length=0)
Reseed an AutoSeededX917RNG.
Definition osrng.h:244
AutoSeededX917RNG::IncorporateEntropy
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
Definition osrng.h:227
AutoSeededX917RNG::AlgorithmProvider
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
Definition osrng.h:274
AutoSeededX917RNG::GenerateIntoBufferedTransformation
void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
Generate random bytes into a BufferedTransformation.
Definition osrng.h:228
AutoSeededX917RNG::AutoSeededX917RNG
AutoSeededX917RNG(bool blocking=false, bool autoSeed=true)
Construct an AutoSeededX917RNG.
Definition osrng.h:205
BlockingRng
Wrapper class for /dev/random and /dev/srandom.
Definition osrng.h:120
BlockingRng::GenerateBlock
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
BlockingRng::BlockingRng
BlockingRng()
Construct a BlockingRng.
BufferedTransformation
Interface for buffered transformations.
Definition cryptlib.h:1657
DefaultAutoSeededRNG
A typedef providing a default generator.
Definition osrng.h:290
Exception
Base class for all exceptions thrown by the library.
Definition cryptlib.h:164
HKDF
Extract-and-Expand Key Derivation Function (HKDF)
Definition hkdf.h:26
HKDF::DeriveKey
size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const NameValuePairs &params) const
Derive a key from a seed.
Definition hkdf.h:101
MicrosoftCryptoProvider
Definition osrng.h:39
MicrosoftCryptoProvider::MicrosoftCryptoProvider
MicrosoftCryptoProvider()
Construct a MicrosoftCryptoProvider.
MicrosoftCryptoProvider::GetProviderHandle
ProviderHandle GetProviderHandle() const
Retrieves the provider handle.
Definition osrng.h:66
NonblockingRng
Wrapper class for /dev/random and /dev/srandom.
Definition osrng.h:86
NonblockingRng::NonblockingRng
NonblockingRng()
Construct a NonblockingRng.
NonblockingRng::GenerateBlock
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
NotCopyable
Ensures an object is not copyable.
Definition misc.h:241
OS_RNG_Err
Exception thrown when an operating system error is encountered.
Definition osrng.h:26
OS_RNG_Err::OS_RNG_Err
OS_RNG_Err(const std::string &operation)
Constructs an OS_RNG_Err.
RandomNumberGenerator
Interface for random number generators.
Definition cryptlib.h:1440
RandomNumberGenerator::GenerateIntoBufferedTransformation
virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
Generate random bytes into a BufferedTransformation.
RandomPool
Randomness Pool based on AES-256.
Definition randpool.h:44
SecBlock::size
size_type size() const
Provides the count of elements in the SecBlock.
Definition secblock.h:867
SecByteBlock
SecBlock<byte> typedef.
Definition secblock.h:1226
X917RNG
ANSI X9.17 RNG.
Definition rng.h:50
member_ptr
Pointer that overloads operator ->
Definition smartptr.h:38
config.h
Library configuration file.
CRYPTOPP_API
#define CRYPTOPP_API
Win32 calling convention.
Definition config_dll.h:119
CRYPTOPP_DLL_TEMPLATE_CLASS
#define CRYPTOPP_DLL_TEMPLATE_CLASS
Instantiate templates in a dynamic library.
Definition config_dll.h:72
lword
word64 lword
Large word type.
Definition config_int.h:168
cryptlib.h
Abstract base classes that provide a uniform interface to this library.
fips140.h
Classes and functions for the FIPS 140-2 validated library.
hkdf.h
Classes for HKDF from RFC 5869.
STDMIN
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition misc.h:657
EnumToInt
#define EnumToInt(v)
Integer value.
Definition misc.h:504
CryptoPP
Crypto++ library namespace.
OS_GenerateRandomBlock
CRYPTOPP_DLL void OS_GenerateRandomBlock(bool blocking, byte *output, size_t size)
OS_GenerateRandomBlock.
randpool.h
Class file for Randomness Pool.
rng.h
Miscellaneous classes for RNGs.
sha.h
Classes for SHA-1 and SHA-2 family of message digests.
smartptr.h
Classes for automatic resource management.