Botan
1.11.15
|
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 }