Botan  1.11.15
Public Member Functions | Static Public Member Functions
Botan::HMAC_RNG Class Reference

#include <hmac_rng.h>

Inheritance diagram for Botan::HMAC_RNG:
Botan::RandomNumberGenerator

List of all members.

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< byterandom_vec (size_t bytes)
void randomize (byte buf[], size_t len)
void reseed (size_t poll_bits)

Static Public Member Functions

static RandomNumberGeneratormake_rng ()

Detailed Description

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.


Constructor & Destructor Documentation

Parameters:
extractora MAC used for extracting the entropy
prfa 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"));
   }

Member Function Documentation

void Botan::HMAC_RNG::add_entropy ( const byte  in[],
size_t  length 
) [virtual]

Add entropy to this RNG.

Parameters:
ina byte array containg the entropy to be added
lengththe 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.

Returns:
true if this RNG was already seeded, false otherwise.

Implements Botan::RandomNumberGenerator.

Definition at line 178 of file hmac_rng.cpp.

Referenced by randomize().

   {
   return (m_collected_entropy_estimate >= 256);
   }

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() + ")";
   }

Return a random byte

Returns:
random byte

Definition at line 53 of file rng.h.

Referenced by Botan::random_prime().

         {
         byte out;
         this->randomize(&out, 1);
         return out;
         }
virtual secure_vector<byte> Botan::RandomNumberGenerator::random_vec ( size_t  bytes) [inline, virtual, inherited]
void Botan::HMAC_RNG::randomize ( byte  output[],
size_t  length 
) [virtual]

Randomize a byte array.

Parameters:
outputthe byte array to hold the random output.
lengththe 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.

Parameters:
bits_to_collectis 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;
   }

The documentation for this class was generated from the following files: