diff options
author | Jack Lloyd <[email protected]> | 2016-08-29 15:35:29 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-08-30 07:39:25 -0400 |
commit | 5739c41504f8193b71e3b0ff6fbe9a508f3ece6a (patch) | |
tree | d588cf58066000779d2017fd61fa88d61cd2d129 /src/tests/test_newhope.cpp | |
parent | a09d2df0885137ea6d7af181e3bcc823412850d8 (diff) |
Add NEWHOPE KEM scheme
Provides conjectured 200-bit security against a quantum attacker.
Based on the public domain reference implementation at
https://github.com/tpoeppelmann/newhope and bit-for-bit
compatible with that version.
Test vectors generated by the reference testvector.c
Diffstat (limited to 'src/tests/test_newhope.cpp')
-rw-r--r-- | src/tests/test_newhope.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/tests/test_newhope.cpp b/src/tests/test_newhope.cpp new file mode 100644 index 000000000..cfa8d9caa --- /dev/null +++ b/src/tests/test_newhope.cpp @@ -0,0 +1,127 @@ +/* +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "tests.h" +#include <botan/newhope.h> +#include <botan/chacha.h> +#include <botan/rng.h> + +namespace Botan_Tests { + +class NEWHOPE_RNG : public Botan::RandomNumberGenerator + { + public: + std::string name() const override { return "NEWHOPE_RNG"; } + void clear() override { /* ignored */ } + + void randomize(byte out[], size_t len) override + { + if(m_first.size() == len) + { + if(len != 32) + throw Test_Error("NEWHOPE_RNG called in unexpected way, bad test?"); + + Botan::copy_mem(out, m_first.data(), m_first.size()); + return; + } + + /* + * This slavishly emulates the behavior of the reference + * implementations RNG, in order to ensure that from the same + * random seed we compute the exact same result. + */ + Botan::clear_mem(out, len); + m_chacha.cipher1(out, len); + + m_calls += 1; + + byte nonce[8] = { 0 }; + + if(m_calls < 3) + { + nonce[0] = m_calls; + } + else + { + nonce[7] = m_calls; + } + + m_chacha.set_iv(nonce, 8); + } + + bool is_seeded() const override { return true; } + + void add_entropy(const byte[], size_t) override { /* ignored */ } + + NEWHOPE_RNG(const std::vector<uint8_t>& seed) + { + if(seed.size() != 64 && seed.size() != 32) + { + throw Test_Error("Invalid NEWHOPE RNG seed"); + } + + if(seed.size() == 64) + { + m_first.assign(seed.begin(), seed.begin() + 32); + m_chacha.set_key(seed.data() + 32, 32); + } + else + { + m_chacha.set_key(seed.data(), 32); + } + } + + private: + Botan::ChaCha m_chacha; + std::vector<uint8_t> m_first; + byte m_calls = 0; + }; + +class NEWHOPE_Tests : public Text_Based_Test + { + public: + NEWHOPE_Tests() : Text_Based_Test("pubkey/newhope.vec", {"DRBG_SeedA", "H_OutputA", "DRBG_SeedB", "H_OutputB", "SharedKey"}) {} + + Test::Result run_one_test(const std::string&, const VarMap& vars) override + { + Test::Result result("NEWHOPE"); + + const std::vector<uint8_t> h_output_a = get_req_bin(vars, "H_OutputA"); + const std::vector<uint8_t> h_output_b = get_req_bin(vars, "H_OutputB"); + const std::vector<uint8_t> shared_key = get_req_bin(vars, "SharedKey"); + + NEWHOPE_RNG drbg_a(get_req_bin(vars, "DRBG_SeedA")); + NEWHOPE_RNG drbg_b(get_req_bin(vars, "DRBG_SeedB")); + + std::vector<uint8_t> send_a(NEWHOPE_SENDABYTES); + Botan::newhope_poly a_sk; + Botan::newhope_keygen(send_a.data(), &a_sk, drbg_a); + + std::vector<uint8_t> h_send_a(32); + Botan::newhope_hash(h_send_a.data(), send_a.data(), send_a.size()); + + result.test_eq("Hash Output A", h_send_a, h_output_a); + + std::vector<uint8_t> sharedkey_b(32); + std::vector<uint8_t> send_b(NEWHOPE_SENDBBYTES); + Botan::newhope_sharedb(sharedkey_b.data(), send_b.data(), send_a.data(), drbg_b); + result.test_eq("Key B", sharedkey_b, shared_key); + + std::vector<uint8_t> h_send_b(32); + Botan::newhope_hash(h_send_b.data(), send_b.data(), send_b.size()); + result.test_eq("Hash Output B", h_send_b, h_output_b); + + std::vector<uint8_t> sharedkey_a(32); + newhope_shareda(sharedkey_a.data(), &a_sk, send_b.data()); + result.test_eq("Key A", sharedkey_a, shared_key); + + return result; + } + }; + +BOTAN_REGISTER_TEST("newhope", NEWHOPE_Tests); + +} |