diff options
author | Jack Lloyd <[email protected]> | 2017-07-31 15:12:39 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-08-03 10:36:42 -0400 |
commit | 7edeec69f09fbed01881e93b0f45dbb038bfac73 (patch) | |
tree | 0ea798a7c1cc708b167d899eed73bedb927ec247 | |
parent | 62da578b1a166fa7885940457ad186cd0c948bab (diff) |
Add ChaCha_RNG
-rw-r--r-- | doc/manual/rng.rst | 13 | ||||
-rw-r--r-- | src/build-data/policy/bsi.txt | 3 | ||||
-rw-r--r-- | src/build-data/policy/nist.txt | 3 | ||||
-rw-r--r-- | src/cli/speed.cpp | 63 | ||||
-rw-r--r-- | src/lib/rng/chacha_rng/chacha_rng.cpp | 101 | ||||
-rw-r--r-- | src/lib/rng/chacha_rng/chacha_rng.h | 127 | ||||
-rw-r--r-- | src/lib/rng/chacha_rng/info.txt | 10 | ||||
-rw-r--r-- | src/tests/data/rng/chacha_rng.vec | 129 | ||||
-rw-r--r-- | src/tests/test_rng.cpp | 50 |
9 files changed, 451 insertions, 48 deletions
diff --git a/doc/manual/rng.rst b/doc/manual/rng.rst index 7d586e743..592f319fa 100644 --- a/doc/manual/rng.rst +++ b/doc/manual/rng.rst @@ -78,6 +78,19 @@ initial seed is generated either by the system PRNG (if available) or a default set of entropy sources. These are also used for periodic reseeding of the RNG state. +ChaCha_RNG +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is a very fast userspace PRNG based on ChaCha20 and HMAC(SHA-256). The key +for ChaCha is derived by hashing entropy inputs with HMAC. Then the ChaCha +keystream generator is run, first to generate the new HMAC key (used for any +future entropy additions), then the desired RNG outputs. + +This RNG composes two primitives thought to be secure (ChaCha and HMAC) in a +simple and well studied way (the extract-then-expand paradigm), but is still an +ad-hoc and non-standard construction. It is included because it is roughly 20x +faster then HMAC_DRBG, and certain applications need access to a very fast RNG. + TPM_RNG ^^^^^^^^^^^^^^^^^ diff --git a/src/build-data/policy/bsi.txt b/src/build-data/policy/bsi.txt index c4b9e4769..bc2e7d7f3 100644 --- a/src/build-data/policy/bsi.txt +++ b/src/build-data/policy/bsi.txt @@ -155,6 +155,9 @@ tiger whirlpool keccak +# rng +chacha_rng + # mac cbc_mac poly1305 diff --git a/src/build-data/policy/nist.txt b/src/build-data/policy/nist.txt index fe5183f15..4fafe7149 100644 --- a/src/build-data/policy/nist.txt +++ b/src/build-data/policy/nist.txt @@ -156,6 +156,9 @@ sm3 tiger whirlpool +# rng +chacha_rng + # mac cbc_mac poly1305 diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp index 7f25496e4..7705f89c1 100644 --- a/src/cli/speed.cpp +++ b/src/cli/speed.cpp @@ -44,14 +44,14 @@ #include <botan/hmac_drbg.h> #endif -#if defined(BOTAN_HAS_HMAC_RNG) - #include <botan/hmac_rng.h> -#endif - #if defined(BOTAN_HAS_RDRAND_RNG) #include <botan/rdrand_rng.h> #endif +#if defined(BOTAN_HAS_CHACHA_RNG) + #include <botan/chacha_rng.h> +#endif + #if defined(BOTAN_HAS_FPE_FE1) #include <botan/fpe_fe1.h> #endif @@ -119,9 +119,8 @@ #include <botan/sm2.h> #endif -#if defined(BOTAN_HAS_NEWHOPE) && defined(BOTAN_HAS_CHACHA) +#if defined(BOTAN_HAS_NEWHOPE) #include <botan/newhope.h> - #include <botan/chacha.h> #endif namespace Botan_CLI { @@ -793,7 +792,7 @@ class Speed final : public Command bench_xmss(provider, msec); } #endif -#if defined(BOTAN_HAS_NEWHOPE) && defined(BOTAN_HAS_CHACHA) +#if defined(BOTAN_HAS_NEWHOPE) && defined(BOTAN_HAS_CHACHA_RNG) else if(algo == "NEWHOPE") { bench_newhope(provider, msec); @@ -838,7 +837,7 @@ class Speed final : public Command { #if defined(BOTAN_HAS_AUTO_SEEDING_RNG) Botan::AutoSeeded_RNG auto_rng; - bench_rng(auto_rng, "AutoSeeded_RNG (periodic reseed)", msec, buf_sizes); + bench_rng(auto_rng, "AutoSeeded_RNG (with reseed)", msec, buf_sizes); #endif #if defined(BOTAN_HAS_SYSTEM_RNG) @@ -860,6 +859,13 @@ class Speed final : public Command bench_rng(hmac_drbg, hmac_drbg.name(), msec, buf_sizes); } #endif + +#if defined(BOTAN_HAS_CHACHA_RNG) + // Provide a dummy seed + Botan::ChaCha_RNG chacha_rng(Botan::secure_vector<uint8_t>(32)); + bench_rng(chacha_rng, "ChaCha_RNG", msec, buf_sizes); +#endif + } #if defined(BOTAN_HAS_SIMD_32) && defined(INCLUDE_SIMD_PERF) else if(algo == "simd") @@ -1965,7 +1971,7 @@ class Speed final : public Command #endif -#if defined(BOTAN_HAS_NEWHOPE) && defined(BOTAN_HAS_CHACHA) +#if defined(BOTAN_HAS_NEWHOPE) && defined(BOTAN_HAS_CHACHA_RNG) void bench_newhope(const std::string& /*provider*/, std::chrono::milliseconds msec) { @@ -1975,44 +1981,7 @@ class Speed final : public Command Timer shareda_timer(nm, "", "shareda"); Timer sharedb_timer(nm, "", "sharedb"); - class ChaCha20_RNG : public Botan::RandomNumberGenerator - { - public: - std::string name() const override - { - return "ChaCha20_RNG"; - } - void clear() override - { - /* ignored */ - } - - void randomize(uint8_t out[], size_t len) override - { - Botan::clear_mem(out, len); - m_chacha.cipher1(out, len); - } - - bool is_seeded() const override - { - return true; - } - - void add_entropy(const uint8_t[], size_t) override - { - /* ignored */ - } - - ChaCha20_RNG(const Botan::secure_vector<uint8_t>& seed) - { - m_chacha.set_key(seed); - } - - private: - Botan::ChaCha m_chacha; - }; - - ChaCha20_RNG nh_rng(rng().random_vec(32)); + Botan::ChaCha_RNG nh_rng; while(sharedb_timer.under(msec)) { diff --git a/src/lib/rng/chacha_rng/chacha_rng.cpp b/src/lib/rng/chacha_rng/chacha_rng.cpp new file mode 100644 index 000000000..86c71f9fe --- /dev/null +++ b/src/lib/rng/chacha_rng/chacha_rng.cpp @@ -0,0 +1,101 @@ +/* +* ChaCha_RNG +* (C) 2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/chacha_rng.h> + +namespace Botan { + +ChaCha_RNG::ChaCha_RNG() : Stateful_RNG() + { + m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); + m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); + clear(); + } + +ChaCha_RNG::ChaCha_RNG(const secure_vector<uint8_t>& seed) : Stateful_RNG() + { + m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); + m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); + clear(); + add_entropy(seed.data(), seed.size()); + } + +ChaCha_RNG::ChaCha_RNG(RandomNumberGenerator& underlying_rng, + size_t reseed_interval) : + Stateful_RNG(underlying_rng, reseed_interval) + { + m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); + m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); + clear(); + } + +ChaCha_RNG::ChaCha_RNG(RandomNumberGenerator& underlying_rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval) : + Stateful_RNG(underlying_rng, entropy_sources, reseed_interval) + { + m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); + m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); + clear(); + } + +ChaCha_RNG::ChaCha_RNG(Entropy_Sources& entropy_sources, + size_t reseed_interval) : + Stateful_RNG(entropy_sources, reseed_interval) + { + m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); + m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); + clear(); + } + +void ChaCha_RNG::clear() + { + Stateful_RNG::clear(); + + m_hmac->set_key(std::vector<uint8_t>(m_hmac->output_length(), 0x00)); + m_chacha->set_key(m_hmac->final()); + } + +void ChaCha_RNG::randomize(uint8_t output[], size_t output_len) + { + randomize_with_input(output, output_len, nullptr, 0); + } + +void ChaCha_RNG::randomize_with_input(uint8_t output[], size_t output_len, + const uint8_t input[], size_t input_len) + { + add_entropy(input, input_len); + reseed_check(); + + clear_mem(output, output_len); + m_chacha->cipher1(output, output_len); + } + +void ChaCha_RNG::add_entropy(const uint8_t input[], size_t input_len) + { + if(input_len > 0) + { + m_hmac->update(input, input_len); + m_chacha->set_key(m_hmac->final()); + + secure_vector<uint8_t> mac_key(m_hmac->output_length()); + m_chacha->cipher1(mac_key.data(), mac_key.size()); + m_hmac->set_key(mac_key); + + if(8*input_len >= security_level()) + { + m_reseed_counter = 1; + } + } + } + +size_t ChaCha_RNG::security_level() const + { + return 256; + } + +} diff --git a/src/lib/rng/chacha_rng/chacha_rng.h b/src/lib/rng/chacha_rng/chacha_rng.h new file mode 100644 index 000000000..b6a763f62 --- /dev/null +++ b/src/lib/rng/chacha_rng/chacha_rng.h @@ -0,0 +1,127 @@ +/* +* ChaCha_RNG +* (C) 2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_CHACHA_RNG_H__ +#define BOTAN_CHACHA_RNG_H__ + +#include <botan/stateful_rng.h> +#include <botan/stream_cipher.h> +#include <botan/mac.h> + +namespace Botan { + +class Entropy_Sources; + +/** +* ChaCha_RNG is a very fast but completely ad-hoc RNG created by +* creating a 256-bit random value and using it as a key for ChaCha20. +* +* The RNG maintains two 256-bit keys, one for HMAC_SHA256 (HK) and the +* other for ChaCha20 (CK). To compute a new key in response to +* reseeding request or add_entropy calls, ChaCha_RNG computes +* CK' = HMAC_SHA256(HK, input_material) +* Then a new HK' is computed by running ChaCha20 with the new key to +* output 32 bytes: +* HK' = ChaCha20(CK') +* +* Now output can be produced by continuing to produce output with ChaCha20 +* under CK' +* +* The first HK (before seeding occurs) is taken as the all zero value. +* +* @warning This RNG construction is probably fine but is non-standard. +* The primary reason to use it is in cases where the other RNGs are +* not fast enough. +*/ +class BOTAN_DLL ChaCha_RNG final : public Stateful_RNG + { + public: + /** + * Automatic reseeding is disabled completely, as it has no access to + * any source for seed material. + * + * If a fork is detected, the RNG will be unable to reseed itself + * in response. In this case, an exception will be thrown rather + * than generating duplicated output. + */ + ChaCha_RNG(); + + /** + * Provide an initial seed to the RNG, without providing an + * underlying RNG or entropy source. Automatic reseeding is + * disabled completely, as it has no access to any source for + * seed material. + * + * If a fork is detected, the RNG will be unable to reseed itself + * in response. In this case, an exception will be thrown rather + * than generating duplicated output. + * + * @param seed the seed material, should be at least 256 bits + */ + ChaCha_RNG(const secure_vector<uint8_t>& seed); + + /** + * Automatic reseeding from @p underlying_rng will take place after + * @p reseed_interval many requests or after a fork was detected. + * + * @param underlying_rng is a reference to some RNG which will be used + * to perform the periodic reseeding + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed + */ + ChaCha_RNG(RandomNumberGenerator& underlying_rng, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + /** + * Automatic reseeding from @p entropy_sources will take place after + * @p reseed_interval many requests or after a fork was detected. + * + * @param entropy_sources will be polled to perform reseeding periodically + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed. + */ + ChaCha_RNG(Entropy_Sources& entropy_sources, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + /** + * Automatic reseeding from @p underlying_rng and @p entropy_sources + * will take place after @p reseed_interval many requests or after + * a fork was detected. + * + * @param underlying_rng is a reference to some RNG which will be used + * to perform the periodic reseeding + * @param entropy_sources will be polled to perform reseeding periodically + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed. + */ + ChaCha_RNG(RandomNumberGenerator& underlying_rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + std::string name() const override { return "ChaCha_RNG"; } + + void clear() override; + + void randomize(uint8_t output[], size_t output_len) override; + + void randomize_with_input(uint8_t output[], size_t output_len, + const uint8_t input[], size_t input_len) override; + + void add_entropy(const uint8_t input[], size_t input_len) override; + + size_t security_level() const override; + + private: + void update(const uint8_t input[], size_t input_len); + + std::unique_ptr<MessageAuthenticationCode> m_hmac; + std::unique_ptr<StreamCipher> m_chacha; + }; + +} + +#endif diff --git a/src/lib/rng/chacha_rng/info.txt b/src/lib/rng/chacha_rng/info.txt new file mode 100644 index 000000000..3f51bf4d0 --- /dev/null +++ b/src/lib/rng/chacha_rng/info.txt @@ -0,0 +1,10 @@ +<defines> +CHACHA_RNG -> 20170728 +</defines> + +<requires> +hmac +sha2_32 +chacha +stateful_rng +</requires> diff --git a/src/tests/data/rng/chacha_rng.vec b/src/tests/data/rng/chacha_rng.vec new file mode 100644 index 000000000..efcab692a --- /dev/null +++ b/src/tests/data/rng/chacha_rng.vec @@ -0,0 +1,129 @@ +[ChaCha_RNG] + +# These vectors were generated by a simple implementation of the RNG +# written in Go + +EntropyInput = 0000000000000000000000000000000000000000000000000000000000000000 +EntropyInputReseed = 0000000000000000000000000000000000000000000000000000000000000000 +Out = a84e2a6af98d0a2601ffd05c994de713fa8da43b6f04b3c48c28b0b1b6c9c813726b1d536da5b8b359176c646a7156db35420d5ccd1cea945b246f25edf43b38 + +EntropyInput = 38002f1ebfac64151ec02c602921ace0769a15b6f6f922b30b2743006269f935 +EntropyInputReseed = 2ecc6e719637e6ff5006e3691bbac01a83a2e4f0e407800abcc7063cd6bb47dc +AdditionalInput1 = 37864bb3f4c5bf11cfb534b36444ea1c +AdditionalInput2 = 9dca561150a4d622d50269d2aad18661 +Out = ed4901a43569b58c216e32e74d8b14769e1b101f6dd5d524032253fda7d8b4757ce4e7d4fe4d9e3b6c3e937140f930ba9e311b38160d1332457ecd01fd2c67df + +EntropyInput = 44c52257803c224984f23ffa9417ebb186309634b0fd948a9fa069d233cdfd59 +EntropyInputReseed = 99aa36ca2148b390fd5bd4a6bde52d1a0502ee2633eeb1ea0dd1225dc623e6db +AdditionalInput1 = a34c8be4076e135b07150a28516a2c3a +AdditionalInput2 = 6c4d44cbed39c2bf09267232e5f989c6 +Out = 780f8a99d6719a656972df37000fc5ed0c514c29b1170ec55a2e8de76e0194879d80d4a3dace5bc31d7d011c8fc17e744df7c4741410704fe7708b5ea640b800 + +EntropyInput = bdceae46180d07f7a581c94b0d91d85b976ecd65091c9b17bbb6486b4a293351 +EntropyInputReseed = 15bc3cfbafe7442936bb780c98b3a12d42b90976d6c8c575e8b2612697dd4d59 +AdditionalInput1 = 3d99f5d6d3b4d9b98ff4688aeeb545ba +AdditionalInput2 = 058a43ed9d1852de48910d5ec0f2da64 +Out = 7b76eaae8b7ae31ac7fc4067a0b2b7e86eecfd951ce5e9e13a237a267a1db96bc247cfef9b233964508b302d0d325e5f620b9e7c08f6aa4bc0e5c5d69022220b + +EntropyInput = 0a4fb07966b36e583659edc71b61370f8d827b20d4de1bb0630b67d8d87b6d11 +EntropyInputReseed = 08bf1846a3c91d5a28f57344e9a5c3b11882659f4d20b2c13bc9e96a50c03c29 +AdditionalInput1 = 7e841fd11444f7ad7ee60953ff207b7e +AdditionalInput2 = 420a562bebb4872d51a8b0e342197894 +Out = 6437a0f47661b11f340796bb78b5016a61a8b2795fea0e1a669a1fb6a02b5e5225e83df280243d7d5f54727d56a55a275d9ed5939bc250919a396916cef8e0b5 + +EntropyInput = 0c04f83e4bdbd506738614e6b024060f511b8c9cfa5392d82e00447537191cc7 +EntropyInputReseed = b72ca03d42083f46cce8d6597185a9145fe15689edda6cda567363464c643358 +AdditionalInput1 = e4f77d67a03569338078b59a89dae593 +AdditionalInput2 = e3888f6f82a5b2ed3f12fe1e53c7386c +Out = e6b8b885a857e98e0def1126dfaaa654f34ec32d9c7417c81aaf8a9aa6213e4cbf8962147155146e6ee49e3130f0b5cc66e7699661f9150ed380b8fe1978575a + +EntropyInput = d3fbbc4611908fa8d880be5dccdad79409742a1161345a6ddf553278c58c4a6c +EntropyInputReseed = 34c397ce79b45c4605aad652f5e6fe90166dd8f2a0e4698bf39162e2d632489e +AdditionalInput1 = 2d51b98143561b70cdc15fcc5b56a222 +AdditionalInput2 = 39e427807e0d2fea0e9ef6a71d1b3ca3 +Out = 81cf95a0030f00aae715f2fd37d7691fe05ee435530abd8c43f89e113c2ad306c596451047b14127f950c42af5640ca18d24a898c0bd6172d708d3750c947e5b + +EntropyInput = fb8a522fb21b923879460acc2ea2de865f46faf2ac12c9579a9dc22f5d268a3e +EntropyInputReseed = 8747be06c76a504fe7c9d23cc2d6837dd519d54b123b7f5fa4dcbf3d2331da03 +AdditionalInput1 = 6856d58701a2beda014068818db45780 +AdditionalInput2 = 4642017cd6e61cf6764288af3c70c5ee +Out = 610ff2f79cf09c7ea66207957b77574a320c91a26719e431121cd4d93b472f2021b7461eac8fd6cf917e4da37a45e728b488f723ef393d15de51bbd1ca908c9a + +EntropyInput = 772e616eb2b876a5e3a4cb148dd88695d0419957b1767b004a5eaf4c4927f3b4 +EntropyInputReseed = ecc4a344d2c4256d81b382293f71cf12aab1330f1088cfa61fa9ec235f818900 +AdditionalInput1 = 2133d928ee950dce00f190c187f9c1dd +AdditionalInput2 = 49153c0dfbdecc902e24ba511ba3d22d +Out = 38372a6f65fcfddc510a99f2d51c43702f796fa4a1dab0b2f0a0cb82436d70efe10253ff6e38c8dea3c38ecc08d197b020d7ac57fc12c7150b65a783536e5014 + +EntropyInput = 946a5dd8c437c233efb44ea327eac846741ffb487ac9bcfc49468d69c26524d4 +EntropyInputReseed = 820b7f1cbe9730c378740eaf03cefa535fe9071cb3acac10bb7ec1bcef042346 +AdditionalInput1 = 2c2e72765402e28679caca88aea6a39e +AdditionalInput2 = 4a20e2ff0684cc93861240dfe9df2e38 +Out = 05e6bd717775eea8ba4871da85786df45183c2f1957d2e36a8a2230ab53778e94cde92edb86646be2d600a891a12715727037663b53bd38802b5e9408385cb8d + +EntropyInput = 4ebec81abc28a39f683eb9137065bec349c9616178993dbe987b70ce1015a134 +EntropyInputReseed = f2422607b9c266408eb74c8ad21ac3be7d3d6e2ef498cedd63e30ba933efdd9e +AdditionalInput1 = a822f49a68f5c98ab3afd1e7b27a9823 +AdditionalInput2 = d28a7dd06e69845c0dd8267621b5c867 +Out = 472aab0c6a53de0a4b7ce68720d7ef2766b7fe902633e09bb7cb4b056fbf6e2f251dd9486a0701fc9452f5dd2ffeb17eec04461361dfb5b0ae7ed919f0c177e8 + +EntropyInput = bac6fc3d796008ea765028652fbe516818d43f7935f63511842520441a3d9aac +EntropyInputReseed = 9834830402d7d087841e624b54f936d2cc554c3b77f12fefcaef492eed243d38 +AdditionalInput1 = c752b06e72d8f650e11ef9d556f613a4 +AdditionalInput2 = b84347008e613050c864d2596250f5d4 +Out = d9693147b1fcb434b68ca87bfd4b4791ac09dfc8a87448910157a1aa626f274b8aef568292a1c01982895c0310bd4597d2c5a6b1706116d7270866edc040d4d6 + +EntropyInput = a01393aa35eeb3522dba2dcbaca4c28f1de3fac2066ea00a37f34142e1993592 +EntropyInputReseed = d2aca9b92f4483900da6ae2be81d8bd2ac2a2000016db48e5894acba30ee3dd3 +AdditionalInput1 = 42025c459f59e5f9847efc6cc4da1db8 +AdditionalInput2 = 7ebf89dcf9b491230edb26da11985137 +Out = f91d97378ebd55c25f527c65da5138771245a38867ab105117cadf2291509e5ffbd3fdf36505e2fe78300106e5febbaa4b08b4d98ed693dbcbc496048aff6d68 + +EntropyInput = b2f2dd9263b1c1b4164c9f4ed4bea85c0397423c52efab1ebc84532df90b5f38 +EntropyInputReseed = 95e073c4a143b680f144782fddf621944b7fe1a9e15191256d6467596cc7847b +AdditionalInput1 = 53d2f2101fd5b09a602f07bf2a2b04a2 +AdditionalInput2 = d52f100278121939d70f460a21dc218f +Out = 92f3bf77ef6e6ca68bfda6581d791d059cc9d926df5356f032a96894bb9e3d37e82d40ac619bdce9f61532e878d5ef09e872b3cb9532c3d28792ea028f3a3a52 + +EntropyInput = ea3dfed2728c8818c62b2901b993bb64aa246f324f0bb003cad7d3ebcf8ad3e3 +EntropyInputReseed = fb55d34c9ca100c4b5ab810953fe382beb639f233299beef53f0ba8edf24302d +AdditionalInput1 = 465975974ca156cb55a127c393ae65ef +AdditionalInput2 = 8fbd33f59b305e9991ae1ef5373395ca +Out = 952770a8623fe7ffd9c3abbfcea3e1c43510e992e219aa0b087d3408112a521ecf3663c8cd60938b981c7568ad9000b07f895e7e197ab1d44f9a316c33e1d2dd + +EntropyInput = f38a98047fe48acfd2ee3da79263912cca4b9852e686bda3807045d3590eaaa2 +EntropyInputReseed = d87fd98d35218eaeec667e0c79f77a5b5f38daed8cbbdde4468b71204631a5b3 +AdditionalInput1 = b938b402dc3787d3330f0d961666ff4e +AdditionalInput2 = a05d6789ac19c823dae0f53bb29fd39b +Out = d7b5efc7f42d66d19e64c14eeb38d843b775bd7d836a12d8c2bef75623dfe3645cc0f2230b35c4ca708777681d062513847973d4547c8f3e5d41c7a60678995b + +EntropyInput = 11498ada4e77a9f6f9a185a42de81ec202a6246f6855d7eb9751185f338eafc0 +EntropyInputReseed = 772565fea0634216ee2a12ccc3ba87e334d14d9769ea0a2f4548154e1fc677c1 +AdditionalInput1 = 5c053b8a304fafac47faaa9eec3cd29d +AdditionalInput2 = 14b24bee4e3104c917c8572dd44a3b46 +Out = 4a8d639007c14d3a7c3be860e833fae793560cbb48a47780c26969d9e7979c9f9e684c5d0fe6851e1434d7ed53c53e96e148557067a49b0b97e64e6418c6185c + +EntropyInput = 2d00c48b41cee9286e34b8bf916f91de9dc2f1ec9c0c53b4c663eb3f05410f4e +EntropyInputReseed = b2703d38b570d83e8decc5981e057dc7dda6d88c5719df1bca7ef6bd54385a89 +AdditionalInput1 = ca8ffce1a2409694859347760c9cb9ff +AdditionalInput2 = 31d0e14249c8ae9b356158b43fef10b7 +Out = fbd40489e7245f230649db916311829f687d92d387e5b01826bc365692af0c7f249c0b04db81620dabc577794a1ae054ab24d0b2b8e64936e6c29ea134672ffb + +EntropyInput = 7fa36f65c91f4487bb7a765283746ef8e6d43d32f74121ee3c57c5e8e23b771d +EntropyInputReseed = c53787ac53e5eedbba4a813fd1c218d90a8f69f49c6fcc19d079e0570247e13d +AdditionalInput1 = 629657f04b2e4b2d86e3fbaff4698bfb +AdditionalInput2 = 190cd249e568096e962d8ff32b22c0de +Out = 91311f7f36c695aa13dd87f7c9a7209f062522e27cb04af88177e22b8e3728d88d395edd803c80f2d02cf95a25aceac7708f2c2d5b1490b2af65a26e54e85765 + +EntropyInput = 7295b42334884a41aed8fff9cc870020d71049219ee084a9cbc06bfe573b97f3 +EntropyInputReseed = ad5f770233adb60e19fbdd46e24ef65fc5098f7f91983f280b2810360d5d4a22 +AdditionalInput1 = b67d0c716aeda647c5aeb4aa4c1bebb4 +AdditionalInput2 = fb9350866c2b34eae90e3a1e9cbb51c3 +Out = 86b2265d200a34eb0be4f21c304c4ad1c4609d8ecc4b8a63da8c7fed3ead7fb93441a4050efb00b9b22d52ce59e409c06019198a9c3f32463eee24a01036cd74 + +EntropyInput = b8dcc441b4979af9b0c35e3cd065046632f83bc6de9ea575e1ec28b3d332abeb +EntropyInputReseed = 66f92647479dc296e4a1784a086eaf0c263eaa805d8584608b625d147c577944 +AdditionalInput1 = 9e663bfb63c5ca4395dad70ae5d7074a +AdditionalInput2 = 19b648af3efc4fe33781c90a1bd24d25 +Out = 918049db0049c744b75a403387c430f45c86c019f925c001481ec49069b2ef08e9657a8af26c80e227017b015679331a8708c4bd06bbea4774473e7460ba242b + diff --git a/src/tests/test_rng.cpp b/src/tests/test_rng.cpp index 76e0d28ea..470bddcdf 100644 --- a/src/tests/test_rng.cpp +++ b/src/tests/test_rng.cpp @@ -1,5 +1,5 @@ /* -* (C) 2014,2015 Jack Lloyd +* (C) 2014,2015,2017 Jack Lloyd * (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) @@ -16,6 +16,10 @@ #include <botan/auto_rng.h> #endif +#if defined(BOTAN_HAS_CHACHA_RNG) + #include <botan/chacha_rng.h> +#endif + #if defined(BOTAN_HAS_SYSTEM_RNG) #include <botan/system_rng.h> #endif @@ -62,6 +66,7 @@ class HMAC_DRBG_Tests : public Text_Based_Test Test::Result result("HMAC_DRBG(" + algo + ")"); auto mac = Botan::MessageAuthenticationCode::create("HMAC(" + algo + ")"); + if(!mac) { result.note_missing("HMAC(" + algo + ")"); @@ -603,6 +608,49 @@ BOTAN_REGISTER_TEST("hmac_drbg_unit", HMAC_DRBG_Unit_Tests); #endif + +#if defined(BOTAN_HAS_CHACHA_RNG) + +class ChaCha_RNG_Tests : public Text_Based_Test + { + public: + ChaCha_RNG_Tests() + : Text_Based_Test("rng/chacha_rng.vec", + "EntropyInput,EntropyInputReseed,Out", + "AdditionalInput1,AdditionalInput2") {} + + Test::Result run_one_test(const std::string& algo, const VarMap& vars) override + { + const std::vector<uint8_t> seed_input = get_req_bin(vars, "EntropyInput"); + const std::vector<uint8_t> reseed_input = get_req_bin(vars, "EntropyInputReseed"); + const std::vector<uint8_t> expected = get_req_bin(vars, "Out"); + + const std::vector<uint8_t> ad1 = get_opt_bin(vars, "AdditionalInput1"); + const std::vector<uint8_t> ad2 = get_opt_bin(vars, "AdditionalInput2"); + + Test::Result result("ChaCha_RNG"); + + Botan::ChaCha_RNG rng; + rng.initialize_with(seed_input.data(), seed_input.size()); + + // now reseed + rng.add_entropy(reseed_input.data(), reseed_input.size()); + + std::vector<uint8_t> out(expected.size()); + // first block is discarded + rng.randomize_with_input(out.data(), out.size(), ad1.data(), ad1.size()); + rng.randomize_with_input(out.data(), out.size(), ad2.data(), ad2.size()); + + result.test_eq("rng", out, expected); + return result; + } + + }; + +BOTAN_REGISTER_TEST("chacha_rng", ChaCha_RNG_Tests); + +#endif + #if defined(BOTAN_HAS_AUTO_RNG) class AutoSeeded_RNG_Tests : public Test |