Botan  1.11.15
src/lib/rng/hmac_drbg/hmac_drbg.cpp
Go to the documentation of this file.
00001 /*
00002 * HMAC_DRBG
00003 * (C) 2014 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/hmac_drbg.h>
00009 #include <algorithm>
00010 
00011 namespace Botan {
00012 
00013 HMAC_DRBG::HMAC_DRBG(MessageAuthenticationCode* mac,
00014                      RandomNumberGenerator* prng) :
00015    m_mac(mac),
00016    m_prng(prng),
00017    m_V(m_mac->output_length(), 0x01),
00018    m_reseed_counter(0)
00019    {
00020    m_mac->set_key(secure_vector<byte>(m_mac->output_length(), 0x00));
00021    }
00022 
00023 void HMAC_DRBG::randomize(byte out[], size_t length)
00024    {
00025    if(!is_seeded() || m_reseed_counter > BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED)
00026       reseed(m_mac->output_length() * 8);
00027 
00028    if(!is_seeded())
00029       throw PRNG_Unseeded(name());
00030 
00031    while(length)
00032       {
00033       const size_t to_copy = std::min(length, m_V.size());
00034       m_V = m_mac->process(m_V);
00035       copy_mem(&out[0], &m_V[0], to_copy);
00036 
00037       length -= to_copy;
00038       out += to_copy;
00039       }
00040 
00041    m_reseed_counter += length;
00042 
00043    update(nullptr, 0); // additional_data is always empty
00044    }
00045 
00046 /*
00047 * Reset V and the mac key with new values
00048 */
00049 void HMAC_DRBG::update(const byte input[], size_t input_len)
00050    {
00051    m_mac->update(m_V);
00052    m_mac->update(0x00);
00053    m_mac->update(input, input_len);
00054    m_mac->set_key(m_mac->final());
00055 
00056    m_V = m_mac->process(m_V);
00057 
00058    if(input_len)
00059       {
00060       m_mac->update(m_V);
00061       m_mac->update(0x01);
00062       m_mac->update(input, input_len);
00063       m_mac->set_key(m_mac->final());
00064 
00065       m_V = m_mac->process(m_V);
00066       }
00067    }
00068 
00069 void HMAC_DRBG::reseed(size_t poll_bits)
00070    {
00071    if(m_prng)
00072       {
00073       m_prng->reseed(poll_bits);
00074 
00075       if(m_prng->is_seeded())
00076          {
00077          secure_vector<byte> input = m_prng->random_vec(m_mac->output_length());
00078          update(&input[0], input.size());
00079          m_reseed_counter = 1;
00080          }
00081       }
00082    }
00083 
00084 void HMAC_DRBG::add_entropy(const byte input[], size_t length)
00085    {
00086    update(input, length);
00087    m_reseed_counter = 1;
00088    }
00089 
00090 bool HMAC_DRBG::is_seeded() const
00091    {
00092    return m_reseed_counter > 0;
00093    }
00094 
00095 void HMAC_DRBG::clear()
00096    {
00097    zeroise(m_V);
00098 
00099    m_mac->clear();
00100 
00101    if(m_prng)
00102       m_prng->clear();
00103    }
00104 
00105 std::string HMAC_DRBG::name() const
00106    {
00107    return "HMAC_DRBG(" + m_mac->name() + ")";
00108    }
00109 
00110 }