aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-04-04 09:26:33 -0400
committerJack Lloyd <[email protected]>2017-04-04 09:26:33 -0400
commitd8d08447b7292759c2a9305c5ca592b9bfd97daf (patch)
treef5a11006565dc1ac67827c1cae2dbf621eaaef0e
parent6a7cb70c7bf740af222e727e9c6d49e9bf67c999 (diff)
parentd00cb108f6d3f5b7dee7b8426169f9e186235d54 (diff)
Merge GH #885 Change HMAC_DRBG::security_level to match NIST SP800-90A
-rw-r--r--src/lib/rng/hmac_drbg/hmac_drbg.cpp21
-rw-r--r--src/lib/rng/stateful_rng/stateful_rng.h5
-rw-r--r--src/tests/test_rng.cpp44
3 files changed, 57 insertions, 13 deletions
diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.cpp b/src/lib/rng/hmac_drbg/hmac_drbg.cpp
index e47d49628..4f19b5256 100644
--- a/src/lib/rng/hmac_drbg/hmac_drbg.cpp
+++ b/src/lib/rng/hmac_drbg/hmac_drbg.cpp
@@ -158,12 +158,27 @@ void HMAC_DRBG::update(const uint8_t input[], size_t input_len)
void HMAC_DRBG::add_entropy(const uint8_t input[], size_t input_len)
{
update(input, input_len);
+
+ if(8*input_len >= security_level())
+ {
+ m_reseed_counter = 1;
+ }
}
size_t HMAC_DRBG::security_level() const
{
- // sqrt of hash size
- return m_mac->output_length() * 8 / 2;
+ // security strength of the hash function
+ // for pre-image resistance (see NIST SP 800-57)
+ // SHA-160: 128 bits, SHA-224, SHA-512/224: 192 bits,
+ // SHA-256, SHA-512/256, SHA-384, SHA-512: >= 256 bits
+ // NIST SP 800-90A only supports up to 256 bits though
+ if(m_mac->output_length() < 32)
+ {
+ return (m_mac->output_length() - 4) * 8;
+ }
+ else
+ {
+ return 32 * 8;
+ }
}
-
}
diff --git a/src/lib/rng/stateful_rng/stateful_rng.h b/src/lib/rng/stateful_rng/stateful_rng.h
index 982747e01..ed51aac6a 100644
--- a/src/lib/rng/stateful_rng/stateful_rng.h
+++ b/src/lib/rng/stateful_rng/stateful_rng.h
@@ -121,14 +121,15 @@ class BOTAN_DLL Stateful_RNG : public RandomNumberGenerator
Entropy_Sources* m_entropy_sources = nullptr;
const size_t m_reseed_interval;
+ uint32_t m_last_pid = 0;
+ protected:
/*
- * Set to 1 after a sucessful seeding, then incremented. Reset
+ * Set to 1 after a successful seeding, then incremented. Reset
* to 0 by clear() or a fork. This logic is used even if
* automatic reseeding is disabled (via m_reseed_interval = 0)
*/
size_t m_reseed_counter = 0;
- uint32_t m_last_pid = 0;
};
}
diff --git a/src/tests/test_rng.cpp b/src/tests/test_rng.cpp
index c905b09e3..d057f0e55 100644
--- a/src/tests/test_rng.cpp
+++ b/src/tests/test_rng.cpp
@@ -144,16 +144,18 @@ class HMAC_DRBG_Unit_Tests : public Test
Request_Counting_RNG counting_rng;
Botan::HMAC_DRBG rng(std::move(mac), counting_rng, Botan::Entropy_Sources::global_sources(), 2);
Botan::secure_vector<uint8_t> seed_input(
- {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF});
+ {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,
+ 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF});
Botan::secure_vector<uint8_t> output_after_initialization(
- {0x26,0x06,0x95,0xF4,0xB8,0x96,0x0D,0x0B,0x27,0x4E,0xA2,0x9E,0x8D,0x2B,0x5A,0x35});
+ {0x48,0xD3,0xB4,0x5A,0xAB,0x65,0xEF,0x92,0xCC,0xFC,0xB9,0x42,0x7E,0xF2,0x0C,0x90,
+ 0x29,0x70,0x65,0xEC,0xC1,0xB8,0xA5,0x25,0xBF,0xE4,0xDC,0x6F,0xF3,0x6D,0x0E,0x38});
Botan::secure_vector<uint8_t> output_without_reseed(
{0xC4,0x90,0x04,0x5B,0x35,0x4F,0x50,0x09,0x68,0x45,0xF0,0x4B,0x11,0x03,0x58,0xF0});
result.test_eq("is_seeded",rng.is_seeded(),false);
rng.initialize_with(seed_input.data(), seed_input.size());
- Botan::secure_vector<uint8_t> out(16);
+ Botan::secure_vector<uint8_t> out(32);
rng.randomize(out.data(), out.size());
result.test_eq("underlying RNG calls", counting_rng.randomize_count(), size_t(0));
@@ -337,8 +339,8 @@ class HMAC_DRBG_Unit_Tests : public Test
// make sure the nonce has at least 1/2*security_strength bits
- // SHA-256 -> 128 bits security strength
- for( auto nonce_size : { 0, 4, 15, 16, 17, 32 } )
+ // SHA-256 -> 256 bits security strength
+ for( auto nonce_size : { 0, 4, 8, 16, 31, 32, 34 } )
{
if(!mac)
{
@@ -350,15 +352,15 @@ class HMAC_DRBG_Unit_Tests : public Test
std::vector<uint8_t> nonce(nonce_size);
rng.initialize_with(nonce.data(), nonce.size());
- if(nonce_size < 16)
+ if(nonce_size < 32)
{
result.test_eq("not seeded", rng.is_seeded(), false);
- result.test_throws("invalid nonce size", [&rng, &nonce] () { rng.random_vec(16); });
+ result.test_throws("invalid nonce size", [&rng, &nonce] () { rng.random_vec(32); });
}
else
{
result.test_eq("is seeded", rng.is_seeded(), true);
- rng.random_vec(16);
+ rng.random_vec(32);
}
}
@@ -487,6 +489,31 @@ class HMAC_DRBG_Unit_Tests : public Test
return result;
}
+ Test::Result test_security_level()
+ {
+ Test::Result result("HMAC_DRBG Security Level");
+
+ std::vector<std::string> approved_hash_fns { "SHA-160", "SHA-224", "SHA-256", "SHA-512/256", "SHA-384", "SHA-512" };
+ std::vector<uint32_t> security_strengths { 128, 192, 256, 256, 256, 256 };
+
+ for( size_t i = 0; i < approved_hash_fns.size(); ++i )
+ {
+ std::string hash_fn = approved_hash_fns[i];
+ std::string mac_name = "HMAC(" + hash_fn + ")";
+ auto mac = Botan::MessageAuthenticationCode::create(mac_name);
+ if(!mac)
+ {
+ result.note_missing(mac_name);
+ continue;
+ }
+
+ Botan::HMAC_DRBG rng(std::move(mac));
+ result.test_eq(hash_fn + " security level", rng.security_level(), security_strengths[i]);
+ }
+
+ return result;
+ }
+
Test::Result test_randomize_with_ts_input()
{
Test::Result result("HMAC_DRBG Randomize With Timestamp Input");
@@ -536,6 +563,7 @@ class HMAC_DRBG_Unit_Tests : public Test
results.push_back(test_prediction_resistance());
results.push_back(test_fork_safety());
results.push_back(test_randomize_with_ts_input());
+ results.push_back(test_security_level());
return results;
}
};