/src/botan/src/lib/rng/chacha_rng/chacha_rng.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * ChaCha_RNG |
3 | | * (C) 2017 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #include <botan/chacha_rng.h> |
9 | | |
10 | | namespace Botan { |
11 | | |
12 | | ChaCha_RNG::ChaCha_RNG() : Stateful_RNG() |
13 | 0 | { |
14 | 0 | m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); |
15 | 0 | m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); |
16 | 0 | clear(); |
17 | 0 | } |
18 | | |
19 | | ChaCha_RNG::ChaCha_RNG(const secure_vector<uint8_t>& seed) : Stateful_RNG() |
20 | 7 | { |
21 | 7 | m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); |
22 | 7 | m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); |
23 | 7 | clear(); |
24 | 7 | add_entropy(seed.data(), seed.size()); |
25 | 7 | } |
26 | | |
27 | | ChaCha_RNG::ChaCha_RNG(RandomNumberGenerator& underlying_rng, |
28 | | size_t reseed_interval) : |
29 | | Stateful_RNG(underlying_rng, reseed_interval) |
30 | 0 | { |
31 | 0 | m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); |
32 | 0 | m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); |
33 | 0 | clear(); |
34 | 0 | } |
35 | | |
36 | | ChaCha_RNG::ChaCha_RNG(RandomNumberGenerator& underlying_rng, |
37 | | Entropy_Sources& entropy_sources, |
38 | | size_t reseed_interval) : |
39 | | Stateful_RNG(underlying_rng, entropy_sources, reseed_interval) |
40 | 0 | { |
41 | 0 | m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); |
42 | 0 | m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); |
43 | 0 | clear(); |
44 | 0 | } |
45 | | |
46 | | ChaCha_RNG::ChaCha_RNG(Entropy_Sources& entropy_sources, |
47 | | size_t reseed_interval) : |
48 | | Stateful_RNG(entropy_sources, reseed_interval) |
49 | 0 | { |
50 | 0 | m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); |
51 | 0 | m_chacha = StreamCipher::create_or_throw("ChaCha(20)"); |
52 | 0 | clear(); |
53 | 0 | } |
54 | | |
55 | | void ChaCha_RNG::clear() |
56 | 7 | { |
57 | 7 | Stateful_RNG::clear(); |
58 | 7 | |
59 | 7 | m_hmac->set_key(std::vector<uint8_t>(m_hmac->output_length(), 0x00)); |
60 | 7 | m_chacha->set_key(m_hmac->final()); |
61 | 7 | } |
62 | | |
63 | | void ChaCha_RNG::randomize(uint8_t output[], size_t output_len) |
64 | 541k | { |
65 | 541k | randomize_with_input(output, output_len, nullptr, 0); |
66 | 541k | } |
67 | | |
68 | | void ChaCha_RNG::randomize_with_input(uint8_t output[], size_t output_len, |
69 | | const uint8_t input[], size_t input_len) |
70 | 541k | { |
71 | 541k | reseed_check(); |
72 | 541k | |
73 | 541k | if(input_len > 0) |
74 | 0 | { |
75 | 0 | update(input, input_len); |
76 | 0 | } |
77 | 541k | |
78 | 541k | m_chacha->write_keystream(output, output_len); |
79 | 541k | } |
80 | | |
81 | | void ChaCha_RNG::update(const uint8_t input[], size_t input_len) |
82 | 7 | { |
83 | 7 | m_hmac->update(input, input_len); |
84 | 7 | m_chacha->set_key(m_hmac->final()); |
85 | 7 | |
86 | 7 | secure_vector<uint8_t> mac_key(m_hmac->output_length()); |
87 | 7 | m_chacha->write_keystream(mac_key.data(), mac_key.size()); |
88 | 7 | m_hmac->set_key(mac_key); |
89 | 7 | } |
90 | | |
91 | | void ChaCha_RNG::add_entropy(const uint8_t input[], size_t input_len) |
92 | 7 | { |
93 | 7 | update(input, input_len); |
94 | 7 | |
95 | 7 | if(8*input_len >= security_level()) |
96 | 7 | { |
97 | 7 | reset_reseed_counter(); |
98 | 7 | } |
99 | 7 | } |
100 | | |
101 | | size_t ChaCha_RNG::security_level() const |
102 | 7 | { |
103 | 7 | return 256; |
104 | 7 | } |
105 | | |
106 | | } |