Botan
1.11.15
|
#include <hmac_rng.h>
Public Member Functions | |
void | add_entropy (const byte[], size_t) |
void | clear () |
HMAC_RNG (MessageAuthenticationCode *extractor, MessageAuthenticationCode *prf) | |
bool | is_seeded () const |
std::string | name () const |
byte | next_byte () |
virtual secure_vector< byte > | random_vec (size_t bytes) |
void | randomize (byte buf[], size_t len) |
void | reseed (size_t poll_bits) |
Static Public Member Functions | |
static RandomNumberGenerator * | make_rng () |
HMAC_RNG - based on the design described in "On Extract-then-Expand Key Derivation Functions and an HMAC-based KDF" by Hugo Krawczyk (henceforce, 'E-t-E')
However it actually can be parameterized with any two MAC functions, not restricted to HMAC (this variation is also described in Krawczyk's paper), for instance one could use HMAC(SHA-512) as the extractor and CMAC(AES-256) as the PRF.
Definition at line 27 of file hmac_rng.h.
Botan::HMAC_RNG::HMAC_RNG | ( | MessageAuthenticationCode * | extractor, |
MessageAuthenticationCode * | prf | ||
) |
extractor | a MAC used for extracting the entropy |
prf | a MAC used as a PRF using HKDF construction |
Definition at line 42 of file hmac_rng.cpp.
References Botan::Buffered_Computation::process().
: m_extractor(extractor), m_prf(prf) { if(!m_prf->valid_keylength(m_extractor->output_length()) || !m_extractor->valid_keylength(m_prf->output_length())) throw Invalid_Argument("HMAC_RNG: Bad algo combination " + m_extractor->name() + " and " + m_prf->name()); // First PRF inputs are all zero, as specified in section 2 m_K.resize(m_prf->output_length()); /* Normally we want to feedback PRF outputs to the extractor function to ensure a single bad poll does not reduce entropy. Thus in reseed we'll want to invoke the PRF before we reset the PRF key, but until the first reseed the PRF is unkeyed. Rather than trying to keep track of this, just set the initial PRF key to constant zero. Since all PRF inputs in the first reseed are constants, this amounts to suffixing the seed in the first poll with a fixed constant string. The PRF key will not be used to generate outputs until after reseed sets m_seeded to true. */ secure_vector<byte> prf_key(m_extractor->output_length()); m_prf->set_key(prf_key); /* Use PRF("Botan HMAC_RNG XTS") as the intitial XTS key. This will be used during the first extraction sequence; XTS values after this one are generated using the PRF. If I understand the E-t-E paper correctly (specifically Section 4), using this fixed extractor key is safe to do. */ m_extractor->set_key(prf->process("Botan HMAC_RNG XTS")); }
void Botan::HMAC_RNG::add_entropy | ( | const byte | in[], |
size_t | length | ||
) | [virtual] |
Add entropy to this RNG.
in | a byte array containg the entropy to be added |
length | the length of the byte array in |
Implements Botan::RandomNumberGenerator.
Definition at line 186 of file hmac_rng.cpp.
References reseed().
{ m_extractor->update(input, length); reseed(BOTAN_RNG_RESEED_POLL_BITS); }
void Botan::HMAC_RNG::clear | ( | ) | [virtual] |
Clear all internally held values of this RNG.
Implements Botan::RandomNumberGenerator.
Definition at line 195 of file hmac_rng.cpp.
References Botan::zeroise().
{ m_collected_entropy_estimate = 0; m_extractor->clear(); m_prf->clear(); zeroise(m_K); m_counter = 0; }
bool Botan::HMAC_RNG::is_seeded | ( | ) | const [virtual] |
Check whether this RNG is seeded.
Implements Botan::RandomNumberGenerator.
Definition at line 178 of file hmac_rng.cpp.
Referenced by randomize().
{
return (m_collected_entropy_estimate >= 256);
}
RandomNumberGenerator * Botan::RandomNumberGenerator::make_rng | ( | ) | [static, inherited] |
Create a seeded and active RNG object for general application use Added in 1.8.0
Definition at line 14 of file rng.cpp.
{ std::unique_ptr<RandomNumberGenerator> rng( new HMAC_RNG(make_a<MessageAuthenticationCode>("HMAC(SHA-512)"), make_a<MessageAuthenticationCode>("HMAC(SHA-256)")) ); rng->reseed(256); return rng.release(); }
std::string Botan::HMAC_RNG::name | ( | ) | const [virtual] |
Return the name of this object
Implements Botan::RandomNumberGenerator.
Definition at line 207 of file hmac_rng.cpp.
Referenced by randomize().
{ return "HMAC_RNG(" + m_extractor->name() + "," + m_prf->name() + ")"; }
byte Botan::RandomNumberGenerator::next_byte | ( | ) | [inline, inherited] |
Return a random byte
Definition at line 53 of file rng.h.
Referenced by Botan::random_prime().
virtual secure_vector<byte> Botan::RandomNumberGenerator::random_vec | ( | size_t | bytes | ) | [inline, virtual, inherited] |
Return a random vector
bytes | number of bytes in the result |
Definition at line 42 of file rng.h.
Referenced by Botan::TLS::Client_Key_Exchange::Client_Key_Exchange(), Botan::Curve25519_PrivateKey::Curve25519_PrivateKey(), Botan::TLS::Session::encrypt(), Botan::KeyPair::encryption_consistency_check(), Botan::generate_bcrypt(), Botan::mceies_encrypt(), Botan::OctetString::OctetString(), Botan::pbes2_encrypt(), Botan::BigInt::randomize(), Botan::TLS::Session_Manager_SQL::Session_Manager_SQL(), and Botan::KeyPair::signature_consistency_check().
{ secure_vector<byte> output(bytes); randomize(&output[0], output.size()); return output; }
void Botan::HMAC_RNG::randomize | ( | byte | output[], |
size_t | length | ||
) | [virtual] |
Randomize a byte array.
output | the byte array to hold the random output. |
length | the length of the byte array output. |
Implements Botan::RandomNumberGenerator.
Definition at line 86 of file hmac_rng.cpp.
References Botan::copy_mem(), is_seeded(), name(), and reseed().
{ if(!is_seeded()) { reseed(256); if(!is_seeded()) throw PRNG_Unseeded(name()); } const size_t max_per_prf_iter = m_prf->output_length() / 2; m_output_since_reseed += length; if(m_output_since_reseed >= BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED) reseed(BOTAN_RNG_RESEED_POLL_BITS); /* HMAC KDF as described in E-t-E, using a CTXinfo of "rng" */ while(length) { hmac_prf(*m_prf, m_K, m_counter, "rng"); const size_t copied = std::min<size_t>(length, max_per_prf_iter); copy_mem(out, &m_K[0], copied); out += copied; length -= copied; } }
void Botan::HMAC_RNG::reseed | ( | size_t | bits_to_collect | ) | [virtual] |
Seed this RNG using the entropy sources it contains.
bits_to_collect | is the number of bits of entropy to attempt to gather from the entropy sources |
Implements Botan::RandomNumberGenerator.
Definition at line 120 of file hmac_rng.cpp.
References Botan::EntropySource::poll_available_sources(), and Botan::zeroise().
Referenced by add_entropy(), and randomize().
{ /* Using the terminology of E-t-E, XTR is the MAC function (normally HMAC) seeded with XTS (below) and we form SKM, the key material, by polling as many sources as we think needed to reach our polling goal. We then also include feedback of the current PRK so that a bad poll doesn't wipe us out. */ double bits_collected = 0; Entropy_Accumulator accum( [&](const byte in[], size_t in_len, double entropy_estimate) { m_extractor->update(in, in_len); bits_collected += entropy_estimate; return (bits_collected >= poll_bits); }); EntropySource::poll_available_sources(accum); /* * It is necessary to feed forward poll data. Otherwise, a good poll * (collecting a large amount of conditional entropy) followed by a * bad one (collecting little) would be unsafe. Do this by * generating new PRF outputs using the previous key and feeding * them into the extractor function. * * Cycle the RNG once (CTXinfo="rng"), then generate a new PRF * output using the CTXinfo "reseed". Provide these values as input * to the extractor function. */ hmac_prf(*m_prf, m_K, m_counter, "rng"); m_extractor->update(m_K); // K is the CTXinfo=rng PRF output hmac_prf(*m_prf, m_K, m_counter, "reseed"); m_extractor->update(m_K); // K is the CTXinfo=reseed PRF output /* Now derive the new PRK using everything that has been fed into the extractor, and set the PRF key to that */ m_prf->set_key(m_extractor->final()); // Now generate a new PRF output to use as the XTS extractor salt hmac_prf(*m_prf, m_K, m_counter, "xts"); m_extractor->set_key(m_K); // Reset state zeroise(m_K); m_counter = 0; m_collected_entropy_estimate = std::min<size_t>(m_collected_entropy_estimate + bits_collected, m_extractor->output_length() * 8); m_output_since_reseed = 0; }