diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/rng/rng.h')
-rw-r--r-- | comm/third_party/botan/src/lib/rng/rng.h | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/rng/rng.h b/comm/third_party/botan/src/lib/rng/rng.h new file mode 100644 index 0000000000..54a8ea8319 --- /dev/null +++ b/comm/third_party/botan/src/lib/rng/rng.h @@ -0,0 +1,297 @@ +/* +* Random Number Generator base classes +* (C) 1999-2009,2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H_ +#define BOTAN_RANDOM_NUMBER_GENERATOR_H_ + +#include <botan/secmem.h> +#include <botan/exceptn.h> +#include <botan/mutex.h> +#include <type_traits> +#include <chrono> +#include <string> + +namespace Botan { + +class Entropy_Sources; + +/** +* An interface to a cryptographic random number generator +*/ +class BOTAN_PUBLIC_API(2,0) RandomNumberGenerator + { + public: + virtual ~RandomNumberGenerator() = default; + + RandomNumberGenerator() = default; + + /* + * Never copy a RNG, create a new one + */ + RandomNumberGenerator(const RandomNumberGenerator& rng) = delete; + RandomNumberGenerator& operator=(const RandomNumberGenerator& rng) = delete; + + /** + * Randomize a byte array. + * @param output the byte array to hold the random output. + * @param length the length of the byte array output in bytes. + */ + virtual void randomize(uint8_t output[], size_t length) = 0; + + /** + * Returns false if it is known that this RNG object is not able to accept + * externally provided inputs (via add_entropy, randomize_with_input, etc). + * In this case, any such provided inputs are ignored. + * + * If this function returns true, then inputs may or may not be accepted. + */ + virtual bool accepts_input() const = 0; + + /** + * Incorporate some additional data into the RNG state. For + * example adding nonces or timestamps from a peer's protocol + * message can help hedge against VM state rollback attacks. + * A few RNG types do not accept any externally provided input, + * in which case this function is a no-op. + * + * @param input a byte array containg the entropy to be added + * @param length the length of the byte array in + */ + virtual void add_entropy(const uint8_t input[], size_t length) = 0; + + /** + * Incorporate some additional data into the RNG state. + */ + template<typename T> void add_entropy_T(const T& t) + { + static_assert(std::is_standard_layout<T>::value && std::is_trivial<T>::value, "add_entropy_T data must be POD"); + this->add_entropy(reinterpret_cast<const uint8_t*>(&t), sizeof(T)); + } + + /** + * Incorporate entropy into the RNG state then produce output. + * Some RNG types implement this using a single operation, default + * calls add_entropy + randomize in sequence. + * + * Use this to further bind the outputs to your current + * process/protocol state. For instance if generating a new key + * for use in a session, include a session ID or other such + * value. See NIST SP 800-90 A, B, C series for more ideas. + * + * @param output buffer to hold the random output + * @param output_len size of the output buffer in bytes + * @param input entropy buffer to incorporate + * @param input_len size of the input buffer in bytes + */ + virtual void randomize_with_input(uint8_t output[], size_t output_len, + const uint8_t input[], size_t input_len); + + /** + * This calls `randomize_with_input` using some timestamps as extra input. + * + * For a stateful RNG using non-random but potentially unique data the + * extra input can help protect against problems with fork, VM state + * rollback, or other cases where somehow an RNG state is duplicated. If + * both of the duplicated RNG states later incorporate a timestamp (and the + * timestamps don't themselves repeat), their outputs will diverge. + */ + virtual void randomize_with_ts_input(uint8_t output[], size_t output_len); + + /** + * @return the name of this RNG type + */ + virtual std::string name() const = 0; + + /** + * Clear all internally held values of this RNG + * @post is_seeded() == false + */ + virtual void clear() = 0; + + /** + * Check whether this RNG is seeded. + * @return true if this RNG was already seeded, false otherwise. + */ + virtual bool is_seeded() const = 0; + + /** + * Poll provided sources for up to poll_bits bits of entropy + * or until the timeout expires. Returns estimate of the number + * of bits collected. + */ + virtual size_t reseed(Entropy_Sources& srcs, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS, + std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT); + + /** + * Reseed by reading specified bits from the RNG + */ + virtual void reseed_from_rng(RandomNumberGenerator& rng, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS); + + // Some utility functions built on the interface above: + + /** + * Return a random vector + * @param bytes number of bytes in the result + * @return randomized vector of length bytes + */ + secure_vector<uint8_t> random_vec(size_t bytes) + { + secure_vector<uint8_t> output; + random_vec(output, bytes); + return output; + } + + template<typename Alloc> + void random_vec(std::vector<uint8_t, Alloc>& v, size_t bytes) + { + v.resize(bytes); + this->randomize(v.data(), v.size()); + } + + /** + * Return a random byte + * @return random byte + */ + uint8_t next_byte() + { + uint8_t b; + this->randomize(&b, 1); + return b; + } + + /** + * @return a random byte that is greater than zero + */ + uint8_t next_nonzero_byte() + { + uint8_t b = this->next_byte(); + while(b == 0) + b = this->next_byte(); + return b; + } + + /** + * Create a seeded and active RNG object for general application use + * Added in 1.8.0 + * Use AutoSeeded_RNG instead + */ + BOTAN_DEPRECATED("Use AutoSeeded_RNG") + static RandomNumberGenerator* make_rng(); + }; + +/** +* Convenience typedef +*/ +typedef RandomNumberGenerator RNG; + +/** +* Hardware_RNG exists to tag hardware RNG types (PKCS11_RNG, TPM_RNG, Processor_RNG) +*/ +class BOTAN_PUBLIC_API(2,0) Hardware_RNG : public RandomNumberGenerator + { + public: + virtual void clear() final override { /* no way to clear state of hardware RNG */ } + }; + +/** +* Null/stub RNG - fails if you try to use it for anything +* This is not generally useful except for in certain tests +*/ +class BOTAN_PUBLIC_API(2,0) Null_RNG final : public RandomNumberGenerator + { + public: + bool is_seeded() const override { return false; } + + bool accepts_input() const override { return false; } + + void clear() override {} + + void randomize(uint8_t[], size_t) override + { + throw PRNG_Unseeded("Null_RNG called"); + } + + void add_entropy(const uint8_t[], size_t) override {} + + std::string name() const override { return "Null_RNG"; } + }; + +#if defined(BOTAN_TARGET_OS_HAS_THREADS) +/** +* Wraps access to a RNG in a mutex +* Note that most of the time it's much better to use a RNG per thread +* otherwise the RNG will act as an unnecessary contention point +* +* Since 2.16.0 all Stateful_RNG instances have an internal lock, so +* this class is no longer needed. It will be removed in a future major +* release. +*/ +class BOTAN_PUBLIC_API(2,0) Serialized_RNG final : public RandomNumberGenerator + { + public: + void randomize(uint8_t out[], size_t len) override + { + lock_guard_type<mutex_type> lock(m_mutex); + m_rng->randomize(out, len); + } + + bool accepts_input() const override + { + lock_guard_type<mutex_type> lock(m_mutex); + return m_rng->accepts_input(); + } + + bool is_seeded() const override + { + lock_guard_type<mutex_type> lock(m_mutex); + return m_rng->is_seeded(); + } + + void clear() override + { + lock_guard_type<mutex_type> lock(m_mutex); + m_rng->clear(); + } + + std::string name() const override + { + lock_guard_type<mutex_type> lock(m_mutex); + return m_rng->name(); + } + + size_t reseed(Entropy_Sources& src, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS, + std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override + { + lock_guard_type<mutex_type> lock(m_mutex); + return m_rng->reseed(src, poll_bits, poll_timeout); + } + + void add_entropy(const uint8_t in[], size_t len) override + { + lock_guard_type<mutex_type> lock(m_mutex); + m_rng->add_entropy(in, len); + } + + BOTAN_DEPRECATED("Use Serialized_RNG(new AutoSeeded_RNG) instead") Serialized_RNG(); + + /* + * Since 2.16.0 this is no longer needed for any RNG type. This + * class will be removed in a future major release. + */ + explicit Serialized_RNG(RandomNumberGenerator* rng) : m_rng(rng) {} + private: + mutable mutex_type m_mutex; + std::unique_ptr<RandomNumberGenerator> m_rng; + }; +#endif + +} + +#endif |