diff options
Diffstat (limited to 'src/libs/3rdparty/botan/src/lib/filters')
27 files changed, 3282 insertions, 0 deletions
diff --git a/src/libs/3rdparty/botan/src/lib/filters/aead_filt.h b/src/libs/3rdparty/botan/src/lib/filters/aead_filt.h new file mode 100644 index 00000000000..f569423a69a --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/aead_filt.h @@ -0,0 +1,40 @@ +/* +* Filter interface for AEAD Modes +* (C) 2013 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_AEAD_FILTER_H_ +#define BOTAN_AEAD_FILTER_H_ + +#include <botan/cipher_filter.h> +#include <botan/aead.h> + +namespace Botan { + +/** +* Filter interface for AEAD Modes +*/ +class AEAD_Filter final : public Cipher_Mode_Filter + { + public: + AEAD_Filter(AEAD_Mode* aead) : Cipher_Mode_Filter(aead) {} + + /** + * Set associated data that is not included in the ciphertext but + * that should be authenticated. Must be called after set_key + * and before end_msg. + * + * @param ad the associated data + * @param ad_len length of add in bytes + */ + void set_associated_data(const uint8_t ad[], size_t ad_len) + { + dynamic_cast<AEAD_Mode&>(get_transform()).set_associated_data(ad, ad_len); + } + }; + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/algo_filt.cpp b/src/libs/3rdparty/botan/src/lib/filters/algo_filt.cpp new file mode 100644 index 00000000000..c944b72e5be --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/algo_filt.cpp @@ -0,0 +1,96 @@ +/* +* Filters +* (C) 1999-2007,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/filters.h> +#include <algorithm> + +namespace Botan { + +#if defined(BOTAN_HAS_STREAM_CIPHER) + +StreamCipher_Filter::StreamCipher_Filter(StreamCipher* cipher) : + m_buffer(BOTAN_DEFAULT_BUFFER_SIZE), + m_cipher(cipher) + { + } + +StreamCipher_Filter::StreamCipher_Filter(StreamCipher* cipher, const SymmetricKey& key) : + StreamCipher_Filter(cipher) + { + m_cipher->set_key(key); + } + +StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) : + m_buffer(BOTAN_DEFAULT_BUFFER_SIZE), + m_cipher(StreamCipher::create_or_throw(sc_name)) + { + } + +StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name, const SymmetricKey& key) : + StreamCipher_Filter(sc_name) + { + m_cipher->set_key(key); + } + +void StreamCipher_Filter::write(const uint8_t input[], size_t length) + { + while(length) + { + size_t copied = std::min<size_t>(length, m_buffer.size()); + m_cipher->cipher(input, m_buffer.data(), copied); + send(m_buffer, copied); + input += copied; + length -= copied; + } + } + +#endif + +#if defined(BOTAN_HAS_HASH) + +Hash_Filter::Hash_Filter(const std::string& hash_name, size_t len) : + m_hash(HashFunction::create_or_throw(hash_name)), + m_out_len(len) + { + } + +void Hash_Filter::end_msg() + { + secure_vector<uint8_t> output = m_hash->final(); + if(m_out_len) + send(output, std::min<size_t>(m_out_len, output.size())); + else + send(output); + } +#endif + +#if defined(BOTAN_HAS_MAC) + +MAC_Filter::MAC_Filter(const std::string& mac_name, size_t len) : + m_mac(MessageAuthenticationCode::create_or_throw(mac_name)), + m_out_len(len) + { + } + +MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key, size_t len) : + MAC_Filter(mac_name, len) + { + m_mac->set_key(key); + } + +void MAC_Filter::end_msg() + { + secure_vector<uint8_t> output = m_mac->final(); + if(m_out_len) + send(output, std::min<size_t>(m_out_len, output.size())); + else + send(output); + } + +#endif + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/basefilt.cpp b/src/libs/3rdparty/botan/src/lib/filters/basefilt.cpp new file mode 100644 index 00000000000..89026f6005d --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/basefilt.cpp @@ -0,0 +1,70 @@ +/* +* Basic Filters +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/basefilt.h> +#include <botan/key_filt.h> + +namespace Botan { + +void Keyed_Filter::set_iv(const InitializationVector& iv) + { + if(iv.length() != 0) + throw Invalid_IV_Length(name(), iv.length()); + } + +/* +* Chain Constructor +*/ +Chain::Chain(Filter* f1, Filter* f2, Filter* f3, Filter* f4) + { + if(f1) { attach(f1); incr_owns(); } + if(f2) { attach(f2); incr_owns(); } + if(f3) { attach(f3); incr_owns(); } + if(f4) { attach(f4); incr_owns(); } + } + +/* +* Chain Constructor +*/ +Chain::Chain(Filter* filters[], size_t count) + { + for(size_t j = 0; j != count; ++j) + if(filters[j]) + { + attach(filters[j]); + incr_owns(); + } + } + +std::string Chain::name() const + { + return "Chain"; + } + +/* +* Fork Constructor +*/ +Fork::Fork(Filter* f1, Filter* f2, Filter* f3, Filter* f4) + { + Filter* filters[4] = { f1, f2, f3, f4 }; + set_next(filters, 4); + } + +/* +* Fork Constructor +*/ +Fork::Fork(Filter* filters[], size_t count) + { + set_next(filters, count); + } + +std::string Fork::name() const + { + return "Fork"; + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/basefilt.h b/src/libs/3rdparty/botan/src/lib/filters/basefilt.h new file mode 100644 index 00000000000..922d356693e --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/basefilt.h @@ -0,0 +1,124 @@ +/* +* Basic Filters +* (C) 1999-2007 Jack Lloyd +* (C) 2013 Joel Low +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_BASEFILT_H_ +#define BOTAN_BASEFILT_H_ + +#include <botan/filter.h> + +#if defined(BOTAN_TARGET_OS_HAS_THREADS) + #include <thread> +#endif + +namespace Botan { + +/** +* BitBucket is a filter which simply discards all inputs +*/ +class BOTAN_PUBLIC_API(2,0) BitBucket final : public Filter + { + public: + void write(const uint8_t[], size_t) override { /* discard */ } + + std::string name() const override { return "BitBucket"; } + }; + +/** +* This class represents Filter chains. A Filter chain is an ordered +* concatenation of Filters, the input to a Chain sequentially passes +* through all the Filters contained in the Chain. +*/ + +class BOTAN_PUBLIC_API(2,0) Chain final : public Fanout_Filter + { + public: + void write(const uint8_t input[], size_t length) override { send(input, length); } + + std::string name() const override; + + /** + * Construct a chain of up to four filters. The filters are set + * up in the same order as the arguments. + */ + Chain(Filter* = nullptr, Filter* = nullptr, + Filter* = nullptr, Filter* = nullptr); + + /** + * Construct a chain from range of filters + * @param filter_arr the list of filters + * @param length how many filters + */ + Chain(Filter* filter_arr[], size_t length); + }; + +/** +* This class represents a fork filter, whose purpose is to fork the +* flow of data. It causes an input message to result in n messages at +* the end of the filter, where n is the number of forks. +*/ +class BOTAN_PUBLIC_API(2,0) Fork : public Fanout_Filter + { + public: + void write(const uint8_t input[], size_t length) override { send(input, length); } + void set_port(size_t n) { Fanout_Filter::set_port(n); } + + std::string name() const override; + + /** + * Construct a Fork filter with up to four forks. + */ + Fork(Filter*, Filter*, Filter* = nullptr, Filter* = nullptr); + + /** + * Construct a Fork from range of filters + * @param filter_arr the list of filters + * @param length how many filters + */ + Fork(Filter* filter_arr[], size_t length); + }; + +#if defined(BOTAN_HAS_THREAD_UTILS) + +/** +* This class is a threaded version of the Fork filter. While this uses +* threads, the class itself is NOT thread-safe. This is meant as a drop- +* in replacement for Fork where performance gains are possible. +*/ +class BOTAN_PUBLIC_API(2,0) Threaded_Fork final : public Fork + { + public: + std::string name() const override; + + /** + * Construct a Threaded_Fork filter with up to four forks. + */ + Threaded_Fork(Filter*, Filter*, Filter* = nullptr, Filter* = nullptr); + + /** + * Construct a Threaded_Fork from range of filters + * @param filter_arr the list of filters + * @param length how many filters + */ + Threaded_Fork(Filter* filter_arr[], size_t length); + + ~Threaded_Fork(); + + private: + void set_next(Filter* f[], size_t n); + void send(const uint8_t in[], size_t length) override; + void thread_delegate_work(const uint8_t input[], size_t length); + void thread_entry(Filter* filter); + + std::vector<std::shared_ptr<std::thread>> m_threads; + std::unique_ptr<struct Threaded_Fork_Data> m_thread_data; + }; +#endif + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/buf_filt.cpp b/src/libs/3rdparty/botan/src/lib/filters/buf_filt.cpp new file mode 100644 index 00000000000..8acc6c74f9c --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/buf_filt.cpp @@ -0,0 +1,103 @@ +/* +* Buffered Filter +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/buf_filt.h> +#include <botan/mem_ops.h> +#include <botan/internal/rounding.h> +#include <botan/exceptn.h> + +namespace Botan { + +/* +* Buffered_Filter Constructor +*/ +Buffered_Filter::Buffered_Filter(size_t b, size_t f) : + m_main_block_mod(b), m_final_minimum(f) + { + if(m_main_block_mod == 0) + throw Invalid_Argument("m_main_block_mod == 0"); + + if(m_final_minimum > m_main_block_mod) + throw Invalid_Argument("m_final_minimum > m_main_block_mod"); + + m_buffer.resize(2 * m_main_block_mod); + m_buffer_pos = 0; + } + +/* +* Buffer input into blocks, trying to minimize copying +*/ +void Buffered_Filter::write(const uint8_t input[], size_t input_size) + { + if(!input_size) + return; + + if(m_buffer_pos + input_size >= m_main_block_mod + m_final_minimum) + { + size_t to_copy = std::min<size_t>(m_buffer.size() - m_buffer_pos, input_size); + + copy_mem(&m_buffer[m_buffer_pos], input, to_copy); + m_buffer_pos += to_copy; + + input += to_copy; + input_size -= to_copy; + + size_t total_to_consume = + round_down(std::min(m_buffer_pos, + m_buffer_pos + input_size - m_final_minimum), + m_main_block_mod); + + buffered_block(m_buffer.data(), total_to_consume); + + m_buffer_pos -= total_to_consume; + + copy_mem(m_buffer.data(), m_buffer.data() + total_to_consume, m_buffer_pos); + } + + if(input_size >= m_final_minimum) + { + size_t full_blocks = (input_size - m_final_minimum) / m_main_block_mod; + size_t to_copy = full_blocks * m_main_block_mod; + + if(to_copy) + { + buffered_block(input, to_copy); + + input += to_copy; + input_size -= to_copy; + } + } + + copy_mem(&m_buffer[m_buffer_pos], input, input_size); + m_buffer_pos += input_size; + } + +/* +* Finish/flush operation +*/ +void Buffered_Filter::end_msg() + { + if(m_buffer_pos < m_final_minimum) + throw Exception("Buffered filter end_msg without enough input"); + + size_t spare_blocks = (m_buffer_pos - m_final_minimum) / m_main_block_mod; + + if(spare_blocks) + { + size_t spare_bytes = m_main_block_mod * spare_blocks; + buffered_block(m_buffer.data(), spare_bytes); + buffered_final(&m_buffer[spare_bytes], m_buffer_pos - spare_bytes); + } + else + { + buffered_final(m_buffer.data(), m_buffer_pos); + } + + m_buffer_pos = 0; + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/buf_filt.h b/src/libs/3rdparty/botan/src/lib/filters/buf_filt.h new file mode 100644 index 00000000000..b4cd8e68095 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/buf_filt.h @@ -0,0 +1,93 @@ +/* +* Buffered Filter +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_BUFFERED_FILTER_H_ +#define BOTAN_BUFFERED_FILTER_H_ + +#include <botan/secmem.h> + +namespace Botan { + +/** +* Filter mixin that breaks input into blocks, useful for +* cipher modes +*/ +class BOTAN_PUBLIC_API(2,0) Buffered_Filter + { + public: + /** + * Write bytes into the buffered filter, which will them emit them + * in calls to buffered_block in the subclass + * @param in the input bytes + * @param length of in in bytes + */ + void write(const uint8_t in[], size_t length); + + template<typename Alloc> + void write(const std::vector<uint8_t, Alloc>& in, size_t length) + { + write(in.data(), length); + } + + /** + * Finish a message, emitting to buffered_block and buffered_final + * Will throw an exception if less than final_minimum bytes were + * written into the filter. + */ + void end_msg(); + + /** + * Initialize a Buffered_Filter + * @param block_size the function buffered_block will be called + * with inputs which are a multiple of this size + * @param final_minimum the function buffered_final will be called + * with at least this many bytes. + */ + Buffered_Filter(size_t block_size, size_t final_minimum); + + virtual ~Buffered_Filter() = default; + protected: + /** + * The block processor, implemented by subclasses + * @param input some input bytes + * @param length the size of input, guaranteed to be a multiple + * of block_size + */ + virtual void buffered_block(const uint8_t input[], size_t length) = 0; + + /** + * The final block, implemented by subclasses + * @param input some input bytes + * @param length the size of input, guaranteed to be at least + * final_minimum bytes + */ + virtual void buffered_final(const uint8_t input[], size_t length) = 0; + + /** + * @return block size of inputs + */ + size_t buffered_block_size() const { return m_main_block_mod; } + + /** + * @return current position in the buffer + */ + size_t current_position() const { return m_buffer_pos; } + + /** + * Reset the buffer position + */ + void buffer_reset() { m_buffer_pos = 0; } + private: + size_t m_main_block_mod, m_final_minimum; + + secure_vector<uint8_t> m_buffer; + size_t m_buffer_pos; + }; + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/cipher_filter.cpp b/src/libs/3rdparty/botan/src/lib/filters/cipher_filter.cpp new file mode 100644 index 00000000000..a3e7bd1c39b --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/cipher_filter.cpp @@ -0,0 +1,103 @@ +/* +* Filter interface for Cipher_Modes +* (C) 2013,2014,2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/cipher_filter.h> +#include <botan/internal/rounding.h> + +namespace Botan { + +namespace { + +size_t choose_update_size(size_t update_granularity) + { + const size_t target_size = 1024; + + if(update_granularity >= target_size) + return update_granularity; + + return round_up(target_size, update_granularity); + } + +} + +Cipher_Mode_Filter::Cipher_Mode_Filter(Cipher_Mode* mode) : + Buffered_Filter(choose_update_size(mode->update_granularity()), + mode->minimum_final_size()), + m_mode(mode), + m_nonce(mode->default_nonce_length()), + m_buffer(m_mode->update_granularity()) + { + } + +std::string Cipher_Mode_Filter::name() const + { + return m_mode->name(); + } + +void Cipher_Mode_Filter::set_iv(const InitializationVector& iv) + { + m_nonce = unlock(iv.bits_of()); + } + +void Cipher_Mode_Filter::set_key(const SymmetricKey& key) + { + m_mode->set_key(key); + } + +Key_Length_Specification Cipher_Mode_Filter::key_spec() const + { + return m_mode->key_spec(); + } + +bool Cipher_Mode_Filter::valid_iv_length(size_t length) const + { + return m_mode->valid_nonce_length(length); + } + +void Cipher_Mode_Filter::write(const uint8_t input[], size_t input_length) + { + Buffered_Filter::write(input, input_length); + } + +void Cipher_Mode_Filter::end_msg() + { + Buffered_Filter::end_msg(); + } + +void Cipher_Mode_Filter::start_msg() + { + if(m_nonce.empty() && !m_mode->valid_nonce_length(0)) + throw Invalid_State("Cipher " + m_mode->name() + " requires a fresh nonce for each message"); + + m_mode->start(m_nonce); + m_nonce.clear(); + } + +void Cipher_Mode_Filter::buffered_block(const uint8_t input[], size_t input_length) + { + while(input_length) + { + const size_t take = std::min(m_mode->update_granularity(), input_length); + + m_buffer.assign(input, input + take); + m_mode->update(m_buffer); + + send(m_buffer); + + input += take; + input_length -= take; + } + } + +void Cipher_Mode_Filter::buffered_final(const uint8_t input[], size_t input_length) + { + secure_vector<uint8_t> buf(input, input + input_length); + m_mode->finish(buf); + send(buf); + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/cipher_filter.h b/src/libs/3rdparty/botan/src/lib/filters/cipher_filter.h new file mode 100644 index 00000000000..750385d152f --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/cipher_filter.h @@ -0,0 +1,58 @@ +/* +* Filter interface for ciphers +* (C) 2013,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_TRANSFORM_FILTER_H_ +#define BOTAN_TRANSFORM_FILTER_H_ + +#include <botan/cipher_mode.h> +#include <botan/key_filt.h> +#include <botan/buf_filt.h> + +namespace Botan { + +/** +* Filter interface for cipher modes +*/ +class BOTAN_PUBLIC_API(2,0) Cipher_Mode_Filter final : public Keyed_Filter, + private Buffered_Filter + { + public: + explicit Cipher_Mode_Filter(Cipher_Mode* t); + + explicit Cipher_Mode_Filter(std::unique_ptr<Cipher_Mode> t) : + Cipher_Mode_Filter(t.release()) {} + + void set_iv(const InitializationVector& iv) override; + + void set_key(const SymmetricKey& key) override; + + Key_Length_Specification key_spec() const override; + + bool valid_iv_length(size_t length) const override; + + std::string name() const override; + + private: + void write(const uint8_t input[], size_t input_length) override; + void start_msg() override; + void end_msg() override; + + void buffered_block(const uint8_t input[], size_t input_length) override; + void buffered_final(const uint8_t input[], size_t input_length) override; + + std::unique_ptr<Cipher_Mode> m_mode; + std::vector<uint8_t> m_nonce; + secure_vector<uint8_t> m_buffer; + }; + +// deprecated aliases, will be removed before 2.0 +typedef Cipher_Mode_Filter Transform_Filter; +typedef Transform_Filter Transformation_Filter; + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/comp_filter.cpp b/src/libs/3rdparty/botan/src/lib/filters/comp_filter.cpp new file mode 100644 index 00000000000..2563a49077b --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/comp_filter.cpp @@ -0,0 +1,122 @@ +/* +* Filter interface for compression +* (C) 2014,2015,2016 Jack Lloyd +* (C) 2015 Matej Kenda +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/comp_filter.h> +#include <botan/exceptn.h> + +#if defined(BOTAN_HAS_COMPRESSION) + #include <botan/compression.h> +#endif + +namespace Botan { + +#if defined(BOTAN_HAS_COMPRESSION) + +Compression_Filter::Compression_Filter(const std::string& type, size_t level, size_t bs) : + m_comp(make_compressor(type)), + m_buffersize(std::max<size_t>(bs, 256)), + m_level(level) + { + if(!m_comp) + { + throw Invalid_Argument("Compression type '" + type + "' not found"); + } + } + +Compression_Filter::~Compression_Filter() { /* for unique_ptr */ } + +std::string Compression_Filter::name() const + { + return m_comp->name(); + } + +void Compression_Filter::start_msg() + { + m_comp->start(m_level); + } + +void Compression_Filter::write(const uint8_t input[], size_t input_length) + { + while(input_length) + { + const size_t take = std::min(m_buffersize, input_length); + BOTAN_ASSERT(take > 0, "Consumed something"); + + m_buffer.assign(input, input + take); + m_comp->update(m_buffer); + + send(m_buffer); + + input += take; + input_length -= take; + } + } + +void Compression_Filter::flush() + { + m_buffer.clear(); + m_comp->update(m_buffer, 0, true); + send(m_buffer); + } + +void Compression_Filter::end_msg() + { + m_buffer.clear(); + m_comp->finish(m_buffer); + send(m_buffer); + } + +Decompression_Filter::Decompression_Filter(const std::string& type, size_t bs) : + m_comp(make_decompressor(type)), + m_buffersize(std::max<size_t>(bs, 256)) + { + if(!m_comp) + { + throw Invalid_Argument("Compression type '" + type + "' not found"); + } + } + +Decompression_Filter::~Decompression_Filter() { /* for unique_ptr */ } + +std::string Decompression_Filter::name() const + { + return m_comp->name(); + } + +void Decompression_Filter::start_msg() + { + m_comp->start(); + } + +void Decompression_Filter::write(const uint8_t input[], size_t input_length) + { + while(input_length) + { + const size_t take = std::min(m_buffersize, input_length); + BOTAN_ASSERT(take > 0, "Consumed something"); + + m_buffer.assign(input, input + take); + m_comp->update(m_buffer); + + send(m_buffer); + + input += take; + input_length -= take; + } + } + +void Decompression_Filter::end_msg() + { + m_buffer.clear(); + m_comp->finish(m_buffer); + send(m_buffer); + } + +#endif + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/comp_filter.h b/src/libs/3rdparty/botan/src/lib/filters/comp_filter.h new file mode 100644 index 00000000000..d9cc00b6845 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/comp_filter.h @@ -0,0 +1,71 @@ +/* +* Filter interface for compression +* (C) 2014,2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_COMPRESSION_FILTER_H_ +#define BOTAN_COMPRESSION_FILTER_H_ + +#include <botan/filter.h> + +namespace Botan { + +#if defined(BOTAN_HAS_COMPRESSION) + +class Compression_Algorithm; +class Decompression_Algorithm; + +/** +* Filter interface for compression +*/ +class BOTAN_PUBLIC_API(2,0) Compression_Filter final : public Filter + { + public: + void start_msg() override; + void write(const uint8_t input[], size_t input_length) override; + void end_msg() override; + + void flush(); + + std::string name() const override; + + Compression_Filter(const std::string& type, + size_t compression_level, + size_t buffer_size = 4096); + + ~Compression_Filter(); + private: + std::unique_ptr<Compression_Algorithm> m_comp; + size_t m_buffersize, m_level; + secure_vector<uint8_t> m_buffer; + }; + +/** +* Filter interface for decompression +*/ +class BOTAN_PUBLIC_API(2,0) Decompression_Filter final : public Filter + { + public: + void start_msg() override; + void write(const uint8_t input[], size_t input_length) override; + void end_msg() override; + + std::string name() const override; + + Decompression_Filter(const std::string& type, + size_t buffer_size = 4096); + + ~Decompression_Filter(); + private: + std::unique_ptr<Decompression_Algorithm> m_comp; + std::size_t m_buffersize; + secure_vector<uint8_t> m_buffer; + }; + +#endif + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/data_snk.cpp b/src/libs/3rdparty/botan/src/lib/filters/data_snk.cpp new file mode 100644 index 00000000000..9f0ddff96d5 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/data_snk.cpp @@ -0,0 +1,75 @@ +/* +* DataSink +* (C) 1999-2007 Jack Lloyd +* 2005 Matthew Gregan +* 2017 Philippe Lieser +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/data_snk.h> +#include <botan/exceptn.h> +#include <ostream> + +#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) + #include <fstream> +#endif + +namespace Botan { + +/* +* Write to a stream +*/ +void DataSink_Stream::write(const uint8_t out[], size_t length) + { + m_sink.write(cast_uint8_ptr_to_char(out), length); + if(!m_sink.good()) + throw Stream_IO_Error("DataSink_Stream: Failure writing to " + + m_identifier); + } + +/* +* Flush the stream +*/ +void DataSink_Stream::end_msg() + { + m_sink.flush(); + } + +/* +* DataSink_Stream Constructor +*/ +DataSink_Stream::DataSink_Stream(std::ostream& out, + const std::string& name) : + m_identifier(name), + m_sink(out) + { + } + +#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) + +/* +* DataSink_Stream Constructor +*/ +DataSink_Stream::DataSink_Stream(const std::string& path, + bool use_binary) : + m_identifier(path), + m_sink_memory(new std::ofstream(path, use_binary ? std::ios::binary : std::ios::out)), + m_sink(*m_sink_memory) + { + if(!m_sink.good()) + { + throw Stream_IO_Error("DataSink_Stream: Failure opening " + path); + } + } +#endif + +/* +* DataSink_Stream Destructor +*/ +DataSink_Stream::~DataSink_Stream() + { + // for ~unique_ptr + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/data_snk.h b/src/libs/3rdparty/botan/src/lib/filters/data_snk.h new file mode 100644 index 00000000000..49484b1c1a6 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/data_snk.h @@ -0,0 +1,76 @@ +/* +* DataSink +* (C) 1999-2007 Jack Lloyd +* 2017 Philippe Lieser +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_DATA_SINK_H_ +#define BOTAN_DATA_SINK_H_ + +#include <botan/filter.h> +#include <memory> +#include <iosfwd> + +namespace Botan { + +/** +* This class represents abstract data sink objects. +*/ +class BOTAN_PUBLIC_API(2,0) DataSink : public Filter + { + public: + bool attachable() override { return false; } + DataSink() = default; + virtual ~DataSink() = default; + + DataSink& operator=(const DataSink&) = delete; + DataSink(const DataSink&) = delete; + }; + +/** +* This class represents a data sink which writes its output to a stream. +*/ +class BOTAN_PUBLIC_API(2,0) DataSink_Stream final : public DataSink + { + public: + /** + * Construct a DataSink_Stream from a stream. + * @param stream the stream to write to + * @param name identifier + */ + DataSink_Stream(std::ostream& stream, + const std::string& name = "<std::ostream>"); + +#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) + + /** + * Construct a DataSink_Stream from a filesystem path name. + * @param pathname the name of the file to open a stream to + * @param use_binary indicates whether to treat the file + * as a binary file or not + */ + DataSink_Stream(const std::string& pathname, + bool use_binary = false); +#endif + + std::string name() const override { return m_identifier; } + + void write(const uint8_t[], size_t) override; + + void end_msg() override; + + ~DataSink_Stream(); + + private: + const std::string m_identifier; + + // May be null, if m_sink was an external reference + std::unique_ptr<std::ostream> m_sink_memory; + std::ostream& m_sink; + }; + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/filter.cpp b/src/libs/3rdparty/botan/src/lib/filters/filter.cpp new file mode 100644 index 00000000000..6653fc78153 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/filter.cpp @@ -0,0 +1,129 @@ +/* +* Filter +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/filter.h> +#include <botan/exceptn.h> + +namespace Botan { + +/* +* Filter Constructor +*/ +Filter::Filter() + { + m_next.resize(1); + m_port_num = 0; + m_filter_owns = 0; + m_owned = false; + } + +/* +* Send data to all ports +*/ +void Filter::send(const uint8_t input[], size_t length) + { + if(!length) + return; + + bool nothing_attached = true; + for(size_t j = 0; j != total_ports(); ++j) + if(m_next[j]) + { + if(m_write_queue.size()) + m_next[j]->write(m_write_queue.data(), m_write_queue.size()); + m_next[j]->write(input, length); + nothing_attached = false; + } + + if(nothing_attached) + m_write_queue += std::make_pair(input, length); + else + m_write_queue.clear(); + } + +/* +* Start a new message +*/ +void Filter::new_msg() + { + start_msg(); + for(size_t j = 0; j != total_ports(); ++j) + if(m_next[j]) + m_next[j]->new_msg(); + } + +/* +* End the current message +*/ +void Filter::finish_msg() + { + end_msg(); + for(size_t j = 0; j != total_ports(); ++j) + if(m_next[j]) + m_next[j]->finish_msg(); + } + +/* +* Attach a filter to the current port +*/ +void Filter::attach(Filter* new_filter) + { + if(new_filter) + { + Filter* last = this; + while(last->get_next()) + last = last->get_next(); + last->m_next[last->current_port()] = new_filter; + } + } + +/* +* Set the active port on a filter +*/ +void Filter::set_port(size_t new_port) + { + if(new_port >= total_ports()) + throw Invalid_Argument("Filter: Invalid port number"); + m_port_num = new_port; + } + +/* +* Return the next Filter in the logical chain +*/ +Filter* Filter::get_next() const + { + if(m_port_num < m_next.size()) + return m_next[m_port_num]; + return nullptr; + } + +/* +* Set the next Filters +*/ +void Filter::set_next(Filter* filters[], size_t size) + { + m_next.clear(); + + m_port_num = 0; + m_filter_owns = 0; + + while(size && filters && (filters[size-1] == nullptr)) + --size; + + if(filters && size) + m_next.assign(filters, filters + size); + } + +/* +* Return the total number of ports +*/ +size_t Filter::total_ports() const + { + return m_next.size(); + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/filter.h b/src/libs/3rdparty/botan/src/lib/filters/filter.h new file mode 100644 index 00000000000..a0857c589e5 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/filter.h @@ -0,0 +1,183 @@ +/* +* Filter +* (C) 1999-2007 Jack Lloyd +* (C) 2013 Joel Low +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_FILTER_H_ +#define BOTAN_FILTER_H_ + +#include <botan/secmem.h> +#include <vector> +#include <string> + +namespace Botan { + +/** +* This class represents general abstract filter objects. +*/ +class BOTAN_PUBLIC_API(2,0) Filter + { + public: + /** + * @return descriptive name for this filter + */ + virtual std::string name() const = 0; + + /** + * Write a portion of a message to this filter. + * @param input the input as a byte array + * @param length the length of the byte array input + */ + virtual void write(const uint8_t input[], size_t length) = 0; + + /** + * Start a new message. Must be closed by end_msg() before another + * message can be started. + */ + virtual void start_msg() { /* default empty */ } + + /** + * Notify that the current message is finished; flush buffers and + * do end-of-message processing (if any). + */ + virtual void end_msg() { /* default empty */ } + + /** + * Check whether this filter is an attachable filter. + * @return true if this filter is attachable, false otherwise + */ + virtual bool attachable() { return true; } + + virtual ~Filter() = default; + protected: + /** + * @param in some input for the filter + * @param length the length of in + */ + virtual void send(const uint8_t in[], size_t length); + + /** + * @param in some input for the filter + */ + void send(uint8_t in) { send(&in, 1); } + + /** + * @param in some input for the filter + */ + void send(const secure_vector<uint8_t>& in) { send(in.data(), in.size()); } + + /** + * @param in some input for the filter + */ + void send(const std::vector<uint8_t>& in) { send(in.data(), in.size()); } + + /** + * @param in some input for the filter + * @param length the number of bytes of in to send + */ + void send(const secure_vector<uint8_t>& in, size_t length) + { + send(in.data(), length); + } + + /** + * @param in some input for the filter + * @param length the number of bytes of in to send + */ + void send(const std::vector<uint8_t>& in, size_t length) + { + send(in.data(), length); + } + + Filter(); + + Filter(const Filter&) = delete; + + Filter& operator=(const Filter&) = delete; + + private: + /** + * Start a new message in *this and all following filters. Only for + * internal use, not intended for use in client applications. + */ + void new_msg(); + + /** + * End a new message in *this and all following filters. Only for + * internal use, not intended for use in client applications. + */ + void finish_msg(); + + friend class Pipe; + friend class Fanout_Filter; + + size_t total_ports() const; + size_t current_port() const { return m_port_num; } + + /** + * Set the active port + * @param new_port the new value + */ + void set_port(size_t new_port); + + size_t owns() const { return m_filter_owns; } + + /** + * Attach another filter to this one + * @param f filter to attach + */ + void attach(Filter* f); + + /** + * @param filters the filters to set + * @param count number of items in filters + */ + void set_next(Filter* filters[], size_t count); + Filter* get_next() const; + + secure_vector<uint8_t> m_write_queue; + std::vector<Filter*> m_next; // not owned + size_t m_port_num, m_filter_owns; + + // true if filter belongs to a pipe --> prohibit filter sharing! + bool m_owned; + }; + +/** +* This is the abstract Fanout_Filter base class. +**/ +class BOTAN_PUBLIC_API(2,0) Fanout_Filter : public Filter + { + protected: + /** + * Increment the number of filters past us that we own + */ + void incr_owns() { ++m_filter_owns; } + + void set_port(size_t n) { Filter::set_port(n); } + + void set_next(Filter* f[], size_t n) { Filter::set_next(f, n); } + + void attach(Filter* f) { Filter::attach(f); } + + private: + friend class Threaded_Fork; + using Filter::m_write_queue; + using Filter::total_ports; + using Filter::m_next; + }; + +/** +* The type of checking to be performed by decoders: +* NONE - no checks, IGNORE_WS - perform checks, but ignore +* whitespaces, FULL_CHECK - perform checks, also complain +* about white spaces. +*/ +enum Decoder_Checking { NONE, IGNORE_WS, FULL_CHECK }; + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/filters.h b/src/libs/3rdparty/botan/src/lib/filters/filters.h new file mode 100644 index 00000000000..b4aee12078f --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/filters.h @@ -0,0 +1,227 @@ +/* +* Filters +* (C) 1999-2007,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_FILTERS_H_ +#define BOTAN_FILTERS_H_ + +#include <botan/basefilt.h> +#include <botan/key_filt.h> +#include <botan/data_snk.h> +#include <botan/pipe.h> + +#if defined(BOTAN_HAS_STREAM_CIPHER) + #include <botan/stream_cipher.h> +#endif + +#if defined(BOTAN_HAS_HASH) + #include <botan/hash.h> +#endif + +#if defined(BOTAN_HAS_MAC) + #include <botan/mac.h> +#endif + +#if defined(BOTAN_HAS_CODEC_FILTERS) + #include <botan/b64_filt.h> + #include <botan/hex_filt.h> +#endif + +namespace Botan { + +#if defined(BOTAN_HAS_STREAM_CIPHER) + +/** +* Stream Cipher Filter +*/ +class BOTAN_PUBLIC_API(2,0) StreamCipher_Filter final : public Keyed_Filter + { + public: + + std::string name() const override { return m_cipher->name(); } + + /** + * Write input data + * @param input data + * @param input_len length of input in bytes + */ + void write(const uint8_t input[], size_t input_len) override; + + bool valid_iv_length(size_t iv_len) const override + { return m_cipher->valid_iv_length(iv_len); } + + /** + * Set the initialization vector for this filter. + * @param iv the initialization vector to set + */ + void set_iv(const InitializationVector& iv) override + { + m_cipher->set_iv(iv.begin(), iv.length()); + } + + /** + * Set the key of this filter. + * @param key the key to set + */ + void set_key(const SymmetricKey& key) override { m_cipher->set_key(key); } + + Key_Length_Specification key_spec() const override { return m_cipher->key_spec(); } + + /** + * Construct a stream cipher filter. + * @param cipher a cipher object to use + */ + explicit StreamCipher_Filter(StreamCipher* cipher); + + /** + * Construct a stream cipher filter. + * @param cipher a cipher object to use + * @param key the key to use inside this filter + */ + StreamCipher_Filter(StreamCipher* cipher, const SymmetricKey& key); + + /** + * Construct a stream cipher filter. + * @param cipher the name of the desired cipher + */ + explicit StreamCipher_Filter(const std::string& cipher); + + /** + * Construct a stream cipher filter. + * @param cipher the name of the desired cipher + * @param key the key to use inside this filter + */ + StreamCipher_Filter(const std::string& cipher, const SymmetricKey& key); + private: + secure_vector<uint8_t> m_buffer; + std::unique_ptr<StreamCipher> m_cipher; + }; +#endif + +#if defined(BOTAN_HAS_HASH) + +/** +* Hash Filter. +*/ +class BOTAN_PUBLIC_API(2,0) Hash_Filter final : public Filter + { + public: + void write(const uint8_t input[], size_t len) override { m_hash->update(input, len); } + void end_msg() override; + + std::string name() const override { return m_hash->name(); } + + /** + * Construct a hash filter. + * @param hash the hash function to use + * @param len the output length of this filter. Leave the default + * value 0 if you want to use the full output of the hashfunction + * hash. Otherwise, specify a smaller value here so that the + * output of the hash algorithm will be cut off. + */ + Hash_Filter(HashFunction* hash, size_t len = 0) : + m_hash(hash), m_out_len(len) {} + + /** + * Construct a hash filter. + * @param request the name of the hash algorithm to use + * @param len the output length of this filter. Leave the default + * value 0 if you want to use the full output of the hashfunction + * hash. Otherwise, specify a smaller value here so that the + * output of the hash algorithm will be cut off. + */ + Hash_Filter(const std::string& request, size_t len = 0); + + private: + std::unique_ptr<HashFunction> m_hash; + const size_t m_out_len; + }; +#endif + +#if defined(BOTAN_HAS_MAC) + +/** +* MessageAuthenticationCode Filter. +*/ +class BOTAN_PUBLIC_API(2,0) MAC_Filter final : public Keyed_Filter + { + public: + void write(const uint8_t input[], size_t len) override { m_mac->update(input, len); } + void end_msg() override; + + std::string name() const override { return m_mac->name(); } + + /** + * Set the key of this filter. + * @param key the key to set + */ + void set_key(const SymmetricKey& key) override { m_mac->set_key(key); } + + Key_Length_Specification key_spec() const override { return m_mac->key_spec(); } + + /** + * Construct a MAC filter. The MAC key will be left empty. + * @param mac the MAC to use + * @param out_len the output length of this filter. Leave the default + * value 0 if you want to use the full output of the + * MAC. Otherwise, specify a smaller value here so that the + * output of the MAC will be cut off. + */ + MAC_Filter(MessageAuthenticationCode* mac, + size_t out_len = 0) : + m_mac(mac), + m_out_len(out_len) + { + } + + /** + * Construct a MAC filter. + * @param mac the MAC to use + * @param key the MAC key to use + * @param out_len the output length of this filter. Leave the default + * value 0 if you want to use the full output of the + * MAC. Otherwise, specify a smaller value here so that the + * output of the MAC will be cut off. + */ + MAC_Filter(MessageAuthenticationCode* mac, + const SymmetricKey& key, + size_t out_len = 0) : + m_mac(mac), + m_out_len(out_len) + { + m_mac->set_key(key); + } + + /** + * Construct a MAC filter. The MAC key will be left empty. + * @param mac the name of the MAC to use + * @param len the output length of this filter. Leave the default + * value 0 if you want to use the full output of the + * MAC. Otherwise, specify a smaller value here so that the + * output of the MAC will be cut off. + */ + MAC_Filter(const std::string& mac, size_t len = 0); + + /** + * Construct a MAC filter. + * @param mac the name of the MAC to use + * @param key the MAC key to use + * @param len the output length of this filter. Leave the default + * value 0 if you want to use the full output of the + * MAC. Otherwise, specify a smaller value here so that the + * output of the MAC will be cut off. + */ + MAC_Filter(const std::string& mac, const SymmetricKey& key, + size_t len = 0); + private: + std::unique_ptr<MessageAuthenticationCode> m_mac; + const size_t m_out_len; + }; +#endif + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/info.txt b/src/libs/3rdparty/botan/src/lib/filters/info.txt new file mode 100644 index 00000000000..cfc11435369 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/info.txt @@ -0,0 +1,24 @@ +<defines> +FILTERS -> 20160415 +</defines> + +<header:public> +basefilt.h +buf_filt.h +data_snk.h +comp_filter.h +filter.h +filters.h +key_filt.h +pipe.h +secqueue.h +cipher_filter.h +</header:public> + +<header:internal> +out_buf.h +</header:internal> + +<requires> +modes +</requires> diff --git a/src/libs/3rdparty/botan/src/lib/filters/key_filt.cpp b/src/libs/3rdparty/botan/src/lib/filters/key_filt.cpp new file mode 100644 index 00000000000..b87a8c87f33 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/key_filt.cpp @@ -0,0 +1,39 @@ +/* +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/key_filt.h> +#include <botan/cipher_filter.h> + +namespace Botan { + +Keyed_Filter* get_cipher(const std::string& algo_spec, + Cipher_Dir direction) + { + std::unique_ptr<Cipher_Mode> c(Cipher_Mode::create_or_throw(algo_spec, direction)); + return new Cipher_Mode_Filter(c.release()); + } + +Keyed_Filter* get_cipher(const std::string& algo_spec, + const SymmetricKey& key, + const InitializationVector& iv, + Cipher_Dir direction) + { + Keyed_Filter* cipher = get_cipher(algo_spec, key, direction); + if(iv.length()) + cipher->set_iv(iv); + return cipher; + } + +Keyed_Filter* get_cipher(const std::string& algo_spec, + const SymmetricKey& key, + Cipher_Dir direction) + { + Keyed_Filter* cipher = get_cipher(algo_spec, direction); + cipher->set_key(key); + return cipher; + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/key_filt.h b/src/libs/3rdparty/botan/src/lib/filters/key_filt.h new file mode 100644 index 00000000000..67b689f9984 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/key_filt.h @@ -0,0 +1,109 @@ +/* +* Keyed_Filter +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_KEYED_FILTER_H_ +#define BOTAN_KEYED_FILTER_H_ + +#include <botan/symkey.h> +#include <botan/filter.h> +#include <botan/cipher_mode.h> + +namespace Botan { + +/** +* This class represents keyed filters, i.e. filters that have to be +* fed with a key in order to function. +*/ +class BOTAN_PUBLIC_API(2,0) Keyed_Filter : public Filter + { + public: + /** + * Set the key of this filter + * @param key the key to use + */ + virtual void set_key(const SymmetricKey& key) = 0; + + /** + * Set the initialization vector of this filter. Note: you should + * call set_iv() only after you have called set_key() + * @param iv the initialization vector to use + */ + virtual void set_iv(const InitializationVector& iv); + + /** + * Check whether a key length is valid for this filter + * @param length the key length to be checked for validity + * @return true if the key length is valid, false otherwise + */ + bool valid_keylength(size_t length) const + { + return key_spec().valid_keylength(length); + } + + /** + * @return object describing limits on key size + */ + virtual Key_Length_Specification key_spec() const = 0; + + /** + * Check whether an IV length is valid for this filter + * @param length the IV length to be checked for validity + * @return true if the IV length is valid, false otherwise + */ + virtual bool valid_iv_length(size_t length) const + { return (length == 0); } + }; + + + +/* +* Get a cipher object +*/ + +/** +* Factory method for general symmetric cipher filters. +* @param algo_spec the name of the desired cipher +* @param key the key to be used for encryption/decryption performed by +* the filter +* @param iv the initialization vector to be used +* @param direction determines whether the filter will be an encrypting +* or decrypting filter +* @return pointer to newly allocated encryption or decryption filter +*/ +BOTAN_PUBLIC_API(2,0) Keyed_Filter* get_cipher(const std::string& algo_spec, + const SymmetricKey& key, + const InitializationVector& iv, + Cipher_Dir direction); + +/** +* Factory method for general symmetric cipher filters. +* @param algo_spec the name of the desired cipher +* @param key the key to be used for encryption/decryption performed by +* the filter +* @param direction determines whether the filter will be an encrypting +* or decrypting filter +* @return pointer to the encryption or decryption filter +*/ +BOTAN_PUBLIC_API(2,0) Keyed_Filter* get_cipher(const std::string& algo_spec, + const SymmetricKey& key, + Cipher_Dir direction); + +/** +* Factory method for general symmetric cipher filters. No key will be +* set in the filter. +* +* @param algo_spec the name of the desired cipher +* @param direction determines whether the filter will be an encrypting or +* decrypting filter +* @return pointer to the encryption or decryption filter +*/ +BOTAN_PUBLIC_API(2,0) Keyed_Filter* get_cipher(const std::string& algo_spec, + Cipher_Dir direction); + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/out_buf.cpp b/src/libs/3rdparty/botan/src/lib/filters/out_buf.cpp new file mode 100644 index 00000000000..645cc082365 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/out_buf.cpp @@ -0,0 +1,121 @@ +/* +* Pipe Output Buffer +* (C) 1999-2007,2011 Jack Lloyd +* 2012 Markus Wanner +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/internal/out_buf.h> +#include <botan/secqueue.h> + +namespace Botan { + +/* +* Read data from a message +*/ +size_t Output_Buffers::read(uint8_t output[], size_t length, + Pipe::message_id msg) + { + SecureQueue* q = get(msg); + if(q) + return q->read(output, length); + return 0; + } + +/* +* Peek at data in a message +*/ +size_t Output_Buffers::peek(uint8_t output[], size_t length, + size_t stream_offset, + Pipe::message_id msg) const + { + SecureQueue* q = get(msg); + if(q) + return q->peek(output, length, stream_offset); + return 0; + } + +/* +* Check available bytes in a message +*/ +size_t Output_Buffers::remaining(Pipe::message_id msg) const + { + SecureQueue* q = get(msg); + if(q) + return q->size(); + return 0; + } + +/* +* Return the total bytes of a message that have already been read. +*/ +size_t Output_Buffers::get_bytes_read(Pipe::message_id msg) const + { + SecureQueue* q = get(msg); + if (q) + return q->get_bytes_read(); + return 0; + } + +/* +* Add a new output queue +*/ +void Output_Buffers::add(SecureQueue* queue) + { + BOTAN_ASSERT(queue, "queue was provided"); + + BOTAN_ASSERT(m_buffers.size() < m_buffers.max_size(), + "Room was available in container"); + + m_buffers.push_back(std::unique_ptr<SecureQueue>(queue)); + } + +/* +* Retire old output queues +*/ +void Output_Buffers::retire() + { + for(size_t i = 0; i != m_buffers.size(); ++i) + if(m_buffers[i] && m_buffers[i]->size() == 0) + { + m_buffers[i].reset(); + } + + while(m_buffers.size() && !m_buffers[0]) + { + m_buffers.pop_front(); + m_offset = m_offset + Pipe::message_id(1); + } + } + +/* +* Get a particular output queue +*/ +SecureQueue* Output_Buffers::get(Pipe::message_id msg) const + { + if(msg < m_offset) + return nullptr; + + BOTAN_ASSERT(msg < message_count(), "Message number is in range"); + + return m_buffers[msg-m_offset].get(); + } + +/* +* Return the total number of messages +*/ +Pipe::message_id Output_Buffers::message_count() const + { + return (m_offset + m_buffers.size()); + } + +/* +* Output_Buffers Constructor +*/ +Output_Buffers::Output_Buffers() + { + m_offset = 0; + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/out_buf.h b/src/libs/3rdparty/botan/src/lib/filters/out_buf.h new file mode 100644 index 00000000000..d6efbdaf270 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/out_buf.h @@ -0,0 +1,44 @@ +/* +* Output Buffer +* (C) 1999-2007 Jack Lloyd +* 2012 Markus Wanner +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_OUTPUT_BUFFER_H_ +#define BOTAN_OUTPUT_BUFFER_H_ + +#include <botan/types.h> +#include <botan/pipe.h> +#include <deque> + +namespace Botan { + +/** +* Container of output buffers for Pipe +*/ +class Output_Buffers final + { + public: + size_t read(uint8_t[], size_t, Pipe::message_id); + size_t peek(uint8_t[], size_t, size_t, Pipe::message_id) const; + size_t get_bytes_read(Pipe::message_id) const; + size_t remaining(Pipe::message_id) const; + + void add(class SecureQueue*); + void retire(); + + Pipe::message_id message_count() const; + + Output_Buffers(); + private: + class SecureQueue* get(Pipe::message_id) const; + + std::deque<std::unique_ptr<SecureQueue>> m_buffers; + Pipe::message_id m_offset; + }; + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/pipe.cpp b/src/libs/3rdparty/botan/src/lib/filters/pipe.cpp new file mode 100644 index 00000000000..0bba81bf2d8 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/pipe.cpp @@ -0,0 +1,311 @@ +/* +* Pipe +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/pipe.h> +#include <botan/internal/out_buf.h> +#include <botan/secqueue.h> + +namespace Botan { + +namespace { + +/* +* A Filter that does nothing +*/ +class Null_Filter final : public Filter + { + public: + void write(const uint8_t input[], size_t length) override + { send(input, length); } + + std::string name() const override { return "Null"; } + }; + +} + +/* +* Pipe Constructor +*/ +Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4) : + Pipe({f1,f2,f3,f4}) + { + } + +/* +* Pipe Constructor +*/ +Pipe::Pipe(std::initializer_list<Filter*> args) + { + m_outputs.reset(new Output_Buffers); + m_pipe = nullptr; + m_default_read = 0; + m_inside_msg = false; + + for(auto i = args.begin(); i != args.end(); ++i) + do_append(*i); + } + +/* +* Pipe Destructor +*/ +Pipe::~Pipe() + { + destruct(m_pipe); + } + +/* +* Reset the Pipe +*/ +void Pipe::reset() + { + destruct(m_pipe); + m_pipe = nullptr; + m_inside_msg = false; + } + +/* +* Destroy the Pipe +*/ +void Pipe::destruct(Filter* to_kill) + { + if(!to_kill || dynamic_cast<SecureQueue*>(to_kill)) + return; + for(size_t j = 0; j != to_kill->total_ports(); ++j) + destruct(to_kill->m_next[j]); + delete to_kill; + } + +/* +* Test if the Pipe has any data in it +*/ +bool Pipe::end_of_data() const + { + return (remaining() == 0); + } + +/* +* Set the default read message +*/ +void Pipe::set_default_msg(message_id msg) + { + if(msg >= message_count()) + throw Invalid_Argument("Pipe::set_default_msg: msg number is too high"); + m_default_read = msg; + } + +/* +* Process a full message at once +*/ +void Pipe::process_msg(const uint8_t input[], size_t length) + { + start_msg(); + write(input, length); + end_msg(); + } + +/* +* Process a full message at once +*/ +void Pipe::process_msg(const secure_vector<uint8_t>& input) + { + process_msg(input.data(), input.size()); + } + +void Pipe::process_msg(const std::vector<uint8_t>& input) + { + process_msg(input.data(), input.size()); + } + +/* +* Process a full message at once +*/ +void Pipe::process_msg(const std::string& input) + { + process_msg(cast_char_ptr_to_uint8(input.data()), input.length()); + } + +/* +* Process a full message at once +*/ +void Pipe::process_msg(DataSource& input) + { + start_msg(); + write(input); + end_msg(); + } + +/* +* Start a new message +*/ +void Pipe::start_msg() + { + if(m_inside_msg) + throw Invalid_State("Pipe::start_msg: Message was already started"); + if(m_pipe == nullptr) + m_pipe = new Null_Filter; + find_endpoints(m_pipe); + m_pipe->new_msg(); + m_inside_msg = true; + } + +/* +* End the current message +*/ +void Pipe::end_msg() + { + if(!m_inside_msg) + throw Invalid_State("Pipe::end_msg: Message was already ended"); + m_pipe->finish_msg(); + clear_endpoints(m_pipe); + if(dynamic_cast<Null_Filter*>(m_pipe)) + { + delete m_pipe; + m_pipe = nullptr; + } + m_inside_msg = false; + + m_outputs->retire(); + } + +/* +* Find the endpoints of the Pipe +*/ +void Pipe::find_endpoints(Filter* f) + { + for(size_t j = 0; j != f->total_ports(); ++j) + if(f->m_next[j] && !dynamic_cast<SecureQueue*>(f->m_next[j])) + find_endpoints(f->m_next[j]); + else + { + SecureQueue* q = new SecureQueue; + f->m_next[j] = q; + m_outputs->add(q); + } + } + +/* +* Remove the SecureQueues attached to the Filter +*/ +void Pipe::clear_endpoints(Filter* f) + { + if(!f) return; + for(size_t j = 0; j != f->total_ports(); ++j) + { + if(f->m_next[j] && dynamic_cast<SecureQueue*>(f->m_next[j])) + f->m_next[j] = nullptr; + clear_endpoints(f->m_next[j]); + } + } + +void Pipe::append(Filter* filter) + { + do_append(filter); + } + +void Pipe::append_filter(Filter* filter) + { + if(m_outputs->message_count() != 0) + throw Invalid_State("Cannot call Pipe::append_filter after start_msg"); + + do_append(filter); + } + +void Pipe::prepend(Filter* filter) + { + do_prepend(filter); + } + +void Pipe::prepend_filter(Filter* filter) + { + if(m_outputs->message_count() != 0) + throw Invalid_State("Cannot call Pipe::prepend_filter after start_msg"); + + do_prepend(filter); + } + +/* +* Append a Filter to the Pipe +*/ +void Pipe::do_append(Filter* filter) + { + if(!filter) + return; + if(dynamic_cast<SecureQueue*>(filter)) + throw Invalid_Argument("Pipe::append: SecureQueue cannot be used"); + if(filter->m_owned) + throw Invalid_Argument("Filters cannot be shared among multiple Pipes"); + + if(m_inside_msg) + throw Invalid_State("Cannot append to a Pipe while it is processing"); + + filter->m_owned = true; + + if(!m_pipe) m_pipe = filter; + else m_pipe->attach(filter); + } + +/* +* Prepend a Filter to the Pipe +*/ +void Pipe::do_prepend(Filter* filter) + { + if(m_inside_msg) + throw Invalid_State("Cannot prepend to a Pipe while it is processing"); + if(!filter) + return; + if(dynamic_cast<SecureQueue*>(filter)) + throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used"); + if(filter->m_owned) + throw Invalid_Argument("Filters cannot be shared among multiple Pipes"); + + filter->m_owned = true; + + if(m_pipe) filter->attach(m_pipe); + m_pipe = filter; + } + +/* +* Pop a Filter off the Pipe +*/ +void Pipe::pop() + { + if(m_inside_msg) + throw Invalid_State("Cannot pop off a Pipe while it is processing"); + + if(!m_pipe) + return; + + if(m_pipe->total_ports() > 1) + throw Invalid_State("Cannot pop off a Filter with multiple ports"); + + size_t to_remove = m_pipe->owns() + 1; + + while(to_remove--) + { + std::unique_ptr<Filter> to_destroy(m_pipe); + m_pipe = m_pipe->m_next[0]; + } + } + +/* +* Return the number of messages in this Pipe +*/ +Pipe::message_id Pipe::message_count() const + { + return m_outputs->message_count(); + } + +/* +* Static Member Variables +*/ +const Pipe::message_id Pipe::LAST_MESSAGE = + static_cast<Pipe::message_id>(-2); + +const Pipe::message_id Pipe::DEFAULT_MESSAGE = + static_cast<Pipe::message_id>(-1); + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/pipe.h b/src/libs/3rdparty/botan/src/lib/filters/pipe.h new file mode 100644 index 00000000000..03b5160835f --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/pipe.h @@ -0,0 +1,379 @@ +/* +* Pipe +* (C) 1999-2007 Jack Lloyd +* 2012 Markus Wanner +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_PIPE_H_ +#define BOTAN_PIPE_H_ + +#include <botan/data_src.h> +#include <botan/exceptn.h> +#include <initializer_list> +#include <iosfwd> + +namespace Botan { + +class Filter; +class Output_Buffers; + +/** +* This class represents pipe objects. +* A set of filters can be placed into a pipe, and information flows +* through the pipe until it reaches the end, where the output is +* collected for retrieval. If you're familiar with the Unix shell +* environment, this design will sound quite familiar. +*/ +class BOTAN_PUBLIC_API(2,0) Pipe final : public DataSource + { + public: + /** + * An opaque type that identifies a message in this Pipe + */ + typedef size_t message_id; + + /** + * Exception if you use an invalid message as an argument to + * read, remaining, etc + */ + class BOTAN_PUBLIC_API(2,0) Invalid_Message_Number final : public Invalid_Argument + { + public: + /** + * @param where the error occurred + * @param msg the invalid message id that was used + */ + Invalid_Message_Number(const std::string& where, message_id msg) : + Invalid_Argument("Pipe::" + where + ": Invalid message number " + + std::to_string(msg)) + {} + }; + + /** + * A meta-id for whatever the last message is + */ + static const message_id LAST_MESSAGE; + + /** + * A meta-id for the default message (set with set_default_msg) + */ + static const message_id DEFAULT_MESSAGE; + + /** + * Write input to the pipe, i.e. to its first filter. + * @param in the byte array to write + * @param length the length of the byte array in + */ + void write(const uint8_t in[], size_t length); + + /** + * Write input to the pipe, i.e. to its first filter. + * @param in the secure_vector containing the data to write + */ + void write(const secure_vector<uint8_t>& in) + { write(in.data(), in.size()); } + + /** + * Write input to the pipe, i.e. to its first filter. + * @param in the std::vector containing the data to write + */ + void write(const std::vector<uint8_t>& in) + { write(in.data(), in.size()); } + + /** + * Write input to the pipe, i.e. to its first filter. + * @param in the string containing the data to write + */ + void write(const std::string& in); + + /** + * Write input to the pipe, i.e. to its first filter. + * @param in the DataSource to read the data from + */ + void write(DataSource& in); + + /** + * Write input to the pipe, i.e. to its first filter. + * @param in a single byte to be written + */ + void write(uint8_t in); + + /** + * Perform start_msg(), write() and end_msg() sequentially. + * @param in the byte array containing the data to write + * @param length the length of the byte array to write + */ + void process_msg(const uint8_t in[], size_t length); + + /** + * Perform start_msg(), write() and end_msg() sequentially. + * @param in the secure_vector containing the data to write + */ + void process_msg(const secure_vector<uint8_t>& in); + + /** + * Perform start_msg(), write() and end_msg() sequentially. + * @param in the secure_vector containing the data to write + */ + void process_msg(const std::vector<uint8_t>& in); + + /** + * Perform start_msg(), write() and end_msg() sequentially. + * @param in the string containing the data to write + */ + void process_msg(const std::string& in); + + /** + * Perform start_msg(), write() and end_msg() sequentially. + * @param in the DataSource providing the data to write + */ + void process_msg(DataSource& in); + + /** + * Find out how many bytes are ready to read. + * @param msg the number identifying the message + * for which the information is desired + * @return number of bytes that can still be read + */ + size_t remaining(message_id msg = DEFAULT_MESSAGE) const BOTAN_WARN_UNUSED_RESULT; + + /** + * Read the default message from the pipe. Moves the internal + * offset so that every call to read will return a new portion of + * the message. + * + * @param output the byte array to write the read bytes to + * @param length the length of the byte array output + * @return number of bytes actually read into output + */ + size_t read(uint8_t output[], size_t length) override BOTAN_WARN_UNUSED_RESULT; + + /** + * Read a specified message from the pipe. Moves the internal + * offset so that every call to read will return a new portion of + * the message. + * @param output the byte array to write the read bytes to + * @param length the length of the byte array output + * @param msg the number identifying the message to read from + * @return number of bytes actually read into output + */ + size_t read(uint8_t output[], size_t length, message_id msg) BOTAN_WARN_UNUSED_RESULT; + + /** + * Read a single byte from the pipe. Moves the internal offset so + * that every call to read will return a new portion of the + * message. + * + * @param output the byte to write the result to + * @param msg the message to read from + * @return number of bytes actually read into output + */ + size_t read(uint8_t& output, message_id msg = DEFAULT_MESSAGE) BOTAN_WARN_UNUSED_RESULT; + + /** + * Read the full contents of the pipe. + * @param msg the number identifying the message to read from + * @return secure_vector holding the contents of the pipe + */ + secure_vector<uint8_t> read_all(message_id msg = DEFAULT_MESSAGE) BOTAN_WARN_UNUSED_RESULT; + + /** + * Read the full contents of the pipe. + * @param msg the number identifying the message to read from + * @return string holding the contents of the pipe + */ + std::string read_all_as_string(message_id msg = DEFAULT_MESSAGE) BOTAN_WARN_UNUSED_RESULT; + + /** + * Read from the default message but do not modify the internal + * offset. Consecutive calls to peek() will return portions of + * the message starting at the same position. + * @param output the byte array to write the peeked message part to + * @param length the length of the byte array output + * @param offset the offset from the current position in message + * @return number of bytes actually peeked and written into output + */ + size_t peek(uint8_t output[], size_t length, size_t offset) const override BOTAN_WARN_UNUSED_RESULT; + + /** Read from the specified message but do not modify the + * internal offset. Consecutive calls to peek() will return + * portions of the message starting at the same position. + * @param output the byte array to write the peeked message part to + * @param length the length of the byte array output + * @param offset the offset from the current position in message + * @param msg the number identifying the message to peek from + * @return number of bytes actually peeked and written into output + */ + size_t peek(uint8_t output[], size_t length, + size_t offset, message_id msg) const BOTAN_WARN_UNUSED_RESULT; + + /** Read a single byte from the specified message but do not + * modify the internal offset. Consecutive calls to peek() will + * return portions of the message starting at the same position. + * @param output the byte to write the peeked message byte to + * @param offset the offset from the current position in message + * @param msg the number identifying the message to peek from + * @return number of bytes actually peeked and written into output + */ + size_t peek(uint8_t& output, size_t offset, + message_id msg = DEFAULT_MESSAGE) const BOTAN_WARN_UNUSED_RESULT; + + /** + * @return the number of bytes read from the default message. + */ + size_t get_bytes_read() const override; + + /** + * @return the number of bytes read from the specified message. + */ + size_t get_bytes_read(message_id msg) const; + + bool check_available(size_t n) override; + bool check_available_msg(size_t n, message_id msg); + + /** + * @return currently set default message + */ + size_t default_msg() const { return m_default_read; } + + /** + * Set the default message + * @param msg the number identifying the message which is going to + * be the new default message + */ + void set_default_msg(message_id msg); + + /** + * Get the number of messages the are in this pipe. + * @return number of messages the are in this pipe + */ + message_id message_count() const; + + /** + * Test whether this pipe has any data that can be read from. + * @return true if there is more data to read, false otherwise + */ + bool end_of_data() const override; + + /** + * Start a new message in the pipe. A potential other message in this pipe + * must be closed with end_msg() before this function may be called. + */ + void start_msg(); + + /** + * End the current message. + */ + void end_msg(); + + /** + * Insert a new filter at the front of the pipe + * Deprecated because runtime modification of Pipes is deprecated. + * You can instead use prepend_filter which only works before the first + * message is processed. + * @param filt the new filter to insert + */ + BOTAN_DEPRECATED("Runtime modification of Pipe deprecated") + void prepend(Filter* filt); + + /** + * Insert a new filter at the back of the pipe + * Deprecated because runtime modification of Pipes is deprecated. + * You can instead use append_filter which only works before the first + * message is processed. + * @param filt the new filter to insert + */ + BOTAN_DEPRECATED("Runtime modification of Pipe deprecated") + void append(Filter* filt); + + /** + * Remove the first filter at the front of the pipe. + */ + BOTAN_DEPRECATED("Runtime modification of Pipe deprecated") + void pop(); + + /** + * Reset this pipe to an empty pipe. + */ + BOTAN_DEPRECATED("Runtime modification of Pipe deprecated") + void reset(); + + /** + * Append a new filter onto the filter sequence. This may only be + * called immediately after initial construction, before _any_ + * calls to start_msg have been made. + * + * This function (unlike append) is not deprecated, as it allows + * only modification of the pipe at initialization (before use) + * rather than after messages have been processed. + */ + void append_filter(Filter* filt); + + /** + * Prepend a new filter onto the filter sequence. This may only be + * called immediately after initial construction, before _any_ + * calls to start_msg have been made. + * + * This function (unlike prepend) is not deprecated, as it allows + * only modification of the pipe at initialization (before use) + * rather than after messages have been processed. + */ + void prepend_filter(Filter* filt); + + /** + * Construct a Pipe of up to four filters. The filters are set up + * in the same order as the arguments. + */ + Pipe(Filter* = nullptr, Filter* = nullptr, + Filter* = nullptr, Filter* = nullptr); + + /** + * Construct a Pipe from a list of filters + * @param filters the set of filters to use + */ + explicit Pipe(std::initializer_list<Filter*> filters); + + Pipe(const Pipe&) = delete; + Pipe& operator=(const Pipe&) = delete; + + ~Pipe(); + private: + void destruct(Filter*); + void do_append(Filter* filt); + void do_prepend(Filter* filt); + void find_endpoints(Filter*); + void clear_endpoints(Filter*); + + message_id get_message_no(const std::string&, message_id) const; + + Filter* m_pipe; + std::unique_ptr<Output_Buffers> m_outputs; + message_id m_default_read; + bool m_inside_msg; + }; + +/** +* Stream output operator; dumps the results from pipe's default +* message to the output stream. +* @param out an output stream +* @param pipe the pipe +*/ +BOTAN_PUBLIC_API(2,0) std::ostream& operator<<(std::ostream& out, Pipe& pipe); + +/** +* Stream input operator; dumps the remaining bytes of input +* to the (assumed open) pipe message. +* @param in the input stream +* @param pipe the pipe +*/ +BOTAN_PUBLIC_API(2,0) std::istream& operator>>(std::istream& in, Pipe& pipe); + +} + +#if defined(BOTAN_HAS_PIPE_UNIXFD_IO) + #include <botan/fd_unix.h> +#endif + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/pipe_io.cpp b/src/libs/3rdparty/botan/src/lib/filters/pipe_io.cpp new file mode 100644 index 00000000000..a909cba7259 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/pipe_io.cpp @@ -0,0 +1,47 @@ +/* +* Pipe I/O +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/pipe.h> +#include <istream> +#include <ostream> + +namespace Botan { + +/* +* Write data from a pipe into an ostream +*/ +std::ostream& operator<<(std::ostream& stream, Pipe& pipe) + { + secure_vector<uint8_t> buffer(BOTAN_DEFAULT_BUFFER_SIZE); + while(stream.good() && pipe.remaining()) + { + const size_t got = pipe.read(buffer.data(), buffer.size()); + stream.write(cast_uint8_ptr_to_char(buffer.data()), got); + } + if(!stream.good()) + throw Stream_IO_Error("Pipe output operator (iostream) has failed"); + return stream; + } + +/* +* Read data from an istream into a pipe +*/ +std::istream& operator>>(std::istream& stream, Pipe& pipe) + { + secure_vector<uint8_t> buffer(BOTAN_DEFAULT_BUFFER_SIZE); + while(stream.good()) + { + stream.read(cast_uint8_ptr_to_char(buffer.data()), buffer.size()); + const size_t got = static_cast<size_t>(stream.gcount()); + pipe.write(buffer.data(), got); + } + if(stream.bad() || (stream.fail() && !stream.eof())) + throw Stream_IO_Error("Pipe input operator (iostream) has failed"); + return stream; + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/pipe_rw.cpp b/src/libs/3rdparty/botan/src/lib/filters/pipe_rw.cpp new file mode 100644 index 00000000000..dc7b973727d --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/pipe_rw.cpp @@ -0,0 +1,181 @@ +/* +* Pipe Reading/Writing +* (C) 1999-2007 Jack Lloyd +* 2012 Markus Wanner +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/pipe.h> +#include <botan/filter.h> +#include <botan/internal/out_buf.h> + +namespace Botan { + +/* +* Look up the canonical ID for a queue +*/ +Pipe::message_id Pipe::get_message_no(const std::string& func_name, + message_id msg) const + { + if(msg == DEFAULT_MESSAGE) + msg = default_msg(); + else if(msg == LAST_MESSAGE) + msg = message_count() - 1; + + if(msg >= message_count()) + throw Invalid_Message_Number(func_name, msg); + + return msg; + } + +/* +* Write into a Pipe +*/ +void Pipe::write(const uint8_t input[], size_t length) + { + if(!m_inside_msg) + throw Invalid_State("Cannot write to a Pipe while it is not processing"); + m_pipe->write(input, length); + } + +/* +* Write a string into a Pipe +*/ +void Pipe::write(const std::string& str) + { + write(cast_char_ptr_to_uint8(str.data()), str.size()); + } + +/* +* Write a single byte into a Pipe +*/ +void Pipe::write(uint8_t input) + { + write(&input, 1); + } + +/* +* Write the contents of a DataSource into a Pipe +*/ +void Pipe::write(DataSource& source) + { + secure_vector<uint8_t> buffer(BOTAN_DEFAULT_BUFFER_SIZE); + while(!source.end_of_data()) + { + size_t got = source.read(buffer.data(), buffer.size()); + write(buffer.data(), got); + } + } + +/* +* Read some data from the pipe +*/ +size_t Pipe::read(uint8_t output[], size_t length, message_id msg) + { + return m_outputs->read(output, length, get_message_no("read", msg)); + } + +/* +* Read some data from the pipe +*/ +size_t Pipe::read(uint8_t output[], size_t length) + { + return read(output, length, DEFAULT_MESSAGE); + } + +/* +* Read a single byte from the pipe +*/ +size_t Pipe::read(uint8_t& out, message_id msg) + { + return read(&out, 1, msg); + } + +/* +* Return all data in the pipe +*/ +secure_vector<uint8_t> Pipe::read_all(message_id msg) + { + msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg()); + secure_vector<uint8_t> buffer(remaining(msg)); + size_t got = read(buffer.data(), buffer.size(), msg); + buffer.resize(got); + return buffer; + } + +/* +* Return all data in the pipe as a string +*/ +std::string Pipe::read_all_as_string(message_id msg) + { + msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg()); + secure_vector<uint8_t> buffer(BOTAN_DEFAULT_BUFFER_SIZE); + std::string str; + str.reserve(remaining(msg)); + + while(true) + { + size_t got = read(buffer.data(), buffer.size(), msg); + if(got == 0) + break; + str.append(cast_uint8_ptr_to_char(buffer.data()), got); + } + + return str; + } + +/* +* Find out how many bytes are ready to read +*/ +size_t Pipe::remaining(message_id msg) const + { + return m_outputs->remaining(get_message_no("remaining", msg)); + } + +/* +* Peek at some data in the pipe +*/ +size_t Pipe::peek(uint8_t output[], size_t length, + size_t offset, message_id msg) const + { + return m_outputs->peek(output, length, offset, get_message_no("peek", msg)); + } + +/* +* Peek at some data in the pipe +*/ +size_t Pipe::peek(uint8_t output[], size_t length, size_t offset) const + { + return peek(output, length, offset, DEFAULT_MESSAGE); + } + +/* +* Peek at a byte in the pipe +*/ +size_t Pipe::peek(uint8_t& out, size_t offset, message_id msg) const + { + return peek(&out, 1, offset, msg); + } + +size_t Pipe::get_bytes_read() const + { + return m_outputs->get_bytes_read(default_msg()); + } + +size_t Pipe::get_bytes_read(message_id msg) const + { + return m_outputs->get_bytes_read(msg); + } + +bool Pipe::check_available(size_t n) + { + return (n <= remaining(default_msg())); + } + +bool Pipe::check_available_msg(size_t n, message_id msg) + { + return (n <= remaining(msg)); + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/secqueue.cpp b/src/libs/3rdparty/botan/src/lib/filters/secqueue.cpp new file mode 100644 index 00000000000..1c8d2814937 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/secqueue.cpp @@ -0,0 +1,232 @@ +/* +* SecureQueue +* (C) 1999-2007 Jack Lloyd +* 2012 Markus Wanner +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/secqueue.h> +#include <algorithm> + +namespace Botan { + +/** +* A node in a SecureQueue +*/ +class SecureQueueNode final + { + public: + SecureQueueNode() : m_buffer(BOTAN_DEFAULT_BUFFER_SIZE) + { m_next = nullptr; m_start = m_end = 0; } + + ~SecureQueueNode() { m_next = nullptr; m_start = m_end = 0; } + + size_t write(const uint8_t input[], size_t length) + { + size_t copied = std::min<size_t>(length, m_buffer.size() - m_end); + copy_mem(m_buffer.data() + m_end, input, copied); + m_end += copied; + return copied; + } + + size_t read(uint8_t output[], size_t length) + { + size_t copied = std::min(length, m_end - m_start); + copy_mem(output, m_buffer.data() + m_start, copied); + m_start += copied; + return copied; + } + + size_t peek(uint8_t output[], size_t length, size_t offset = 0) + { + const size_t left = m_end - m_start; + if(offset >= left) return 0; + size_t copied = std::min(length, left - offset); + copy_mem(output, m_buffer.data() + m_start + offset, copied); + return copied; + } + + size_t size() const { return (m_end - m_start); } + private: + friend class SecureQueue; + SecureQueueNode* m_next; + secure_vector<uint8_t> m_buffer; + size_t m_start, m_end; + }; + +/* +* Create a SecureQueue +*/ +SecureQueue::SecureQueue() + { + m_bytes_read = 0; + set_next(nullptr, 0); + m_head = m_tail = new SecureQueueNode; + } + +/* +* Copy a SecureQueue +*/ +SecureQueue::SecureQueue(const SecureQueue& input) : + Fanout_Filter(), DataSource() + { + m_bytes_read = 0; + set_next(nullptr, 0); + + m_head = m_tail = new SecureQueueNode; + SecureQueueNode* temp = input.m_head; + while(temp) + { + write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start); + temp = temp->m_next; + } + } + +/* +* Destroy this SecureQueue +*/ +void SecureQueue::destroy() + { + SecureQueueNode* temp = m_head; + while(temp) + { + SecureQueueNode* holder = temp->m_next; + delete temp; + temp = holder; + } + m_head = m_tail = nullptr; + } + +/* +* Copy a SecureQueue +*/ +SecureQueue& SecureQueue::operator=(const SecureQueue& input) + { + if(this == &input) + return *this; + + destroy(); + m_bytes_read = input.get_bytes_read(); + m_head = m_tail = new SecureQueueNode; + SecureQueueNode* temp = input.m_head; + while(temp) + { + write(&temp->m_buffer[temp->m_start], temp->m_end - temp->m_start); + temp = temp->m_next; + } + return (*this); + } + +/* +* Add some bytes to the queue +*/ +void SecureQueue::write(const uint8_t input[], size_t length) + { + if(!m_head) + m_head = m_tail = new SecureQueueNode; + while(length) + { + const size_t n = m_tail->write(input, length); + input += n; + length -= n; + if(length) + { + m_tail->m_next = new SecureQueueNode; + m_tail = m_tail->m_next; + } + } + } + +/* +* Read some bytes from the queue +*/ +size_t SecureQueue::read(uint8_t output[], size_t length) + { + size_t got = 0; + while(length && m_head) + { + const size_t n = m_head->read(output, length); + output += n; + got += n; + length -= n; + if(m_head->size() == 0) + { + SecureQueueNode* holder = m_head->m_next; + delete m_head; + m_head = holder; + } + } + m_bytes_read += got; + return got; + } + +/* +* Read data, but do not remove it from queue +*/ +size_t SecureQueue::peek(uint8_t output[], size_t length, size_t offset) const + { + SecureQueueNode* current = m_head; + + while(offset && current) + { + if(offset >= current->size()) + { + offset -= current->size(); + current = current->m_next; + } + else + break; + } + + size_t got = 0; + while(length && current) + { + const size_t n = current->peek(output, length, offset); + offset = 0; + output += n; + got += n; + length -= n; + current = current->m_next; + } + return got; + } + +/** +* Return how many bytes have been read so far. +*/ +size_t SecureQueue::get_bytes_read() const + { + return m_bytes_read; + } + +/* +* Return how many bytes the queue holds +*/ +size_t SecureQueue::size() const + { + SecureQueueNode* current = m_head; + size_t count = 0; + + while(current) + { + count += current->size(); + current = current->m_next; + } + return count; + } + +/* +* Test if the queue has any data in it +*/ +bool SecureQueue::end_of_data() const + { + return (size() == 0); + } + +bool SecureQueue::empty() const + { + return (size() == 0); + } + +} diff --git a/src/libs/3rdparty/botan/src/lib/filters/secqueue.h b/src/libs/3rdparty/botan/src/lib/filters/secqueue.h new file mode 100644 index 00000000000..00616f5cf5a --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/secqueue.h @@ -0,0 +1,72 @@ +/* +* SecureQueue +* (C) 1999-2007 Jack Lloyd +* 2012 Markus Wanner +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_SECURE_QUEUE_H_ +#define BOTAN_SECURE_QUEUE_H_ + +#include <botan/data_src.h> +#include <botan/filter.h> + +namespace Botan { + +/** +* A queue that knows how to zeroize itself +*/ +class BOTAN_PUBLIC_API(2,0) SecureQueue final : public Fanout_Filter, public DataSource + { + public: + std::string name() const override { return "Queue"; } + + void write(const uint8_t[], size_t) override; + + size_t read(uint8_t[], size_t) override; + size_t peek(uint8_t[], size_t, size_t = 0) const override; + size_t get_bytes_read() const override; + + bool end_of_data() const override; + + bool empty() const; + + bool check_available(size_t n) override { return n <= size(); } + + /** + * @return number of bytes available in the queue + */ + size_t size() const; + + bool attachable() override { return false; } + + /** + * SecureQueue assignment + * @param other the queue to copy + */ + SecureQueue& operator=(const SecureQueue& other); + + /** + * SecureQueue default constructor (creates empty queue) + */ + SecureQueue(); + + /** + * SecureQueue copy constructor + * @param other the queue to copy + */ + SecureQueue(const SecureQueue& other); + + ~SecureQueue() { destroy(); } + + private: + void destroy(); + size_t m_bytes_read; + class SecureQueueNode* m_head; + class SecureQueueNode* m_tail; + }; + +} + +#endif diff --git a/src/libs/3rdparty/botan/src/lib/filters/threaded_fork.cpp b/src/libs/3rdparty/botan/src/lib/filters/threaded_fork.cpp new file mode 100644 index 00000000000..35ea9410955 --- /dev/null +++ b/src/libs/3rdparty/botan/src/lib/filters/threaded_fork.cpp @@ -0,0 +1,153 @@ +/* +* Threaded Fork +* (C) 2013 Joel Low +* 2013 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/basefilt.h> + +#if defined(BOTAN_HAS_THREAD_UTILS) + +#include <botan/internal/semaphore.h> +#include <botan/internal/barrier.h> +#include <functional> + +namespace Botan { + +struct Threaded_Fork_Data + { + /* + * Semaphore for indicating that there is work to be done (or to + * quit) + */ + Semaphore m_input_ready_semaphore; + + /* + * Synchronises all threads to complete processing data in lock-step. + */ + Barrier m_input_complete_barrier; + + /* + * The work that needs to be done. This should be only when the threads + * are NOT running (i.e. before notifying the work condition, after + * the input_complete_barrier has reset.) + */ + const uint8_t* m_input = nullptr; + + /* + * The length of the work that needs to be done. + */ + size_t m_input_length = 0; + }; + +/* +* Threaded_Fork constructor +*/ +Threaded_Fork::Threaded_Fork(Filter* f1, Filter* f2, Filter* f3, Filter* f4) : + Fork(nullptr, static_cast<size_t>(0)), + m_thread_data(new Threaded_Fork_Data) + { + Filter* filters[4] = { f1, f2, f3, f4 }; + set_next(filters, 4); + } + +/* +* Threaded_Fork constructor +*/ +Threaded_Fork::Threaded_Fork(Filter* filters[], size_t count) : + Fork(nullptr, static_cast<size_t>(0)), + m_thread_data(new Threaded_Fork_Data) + { + set_next(filters, count); + } + +Threaded_Fork::~Threaded_Fork() + { + m_thread_data->m_input = nullptr; + m_thread_data->m_input_length = 0; + + m_thread_data->m_input_ready_semaphore.release(m_threads.size()); + + for(auto& thread : m_threads) + thread->join(); + } + +std::string Threaded_Fork::name() const + { + return "Threaded Fork"; + } + +void Threaded_Fork::set_next(Filter* f[], size_t n) + { + Fork::set_next(f, n); + n = m_next.size(); + + if(n < m_threads.size()) + m_threads.resize(n); + else + { + m_threads.reserve(n); + for(size_t i = m_threads.size(); i != n; ++i) + { + m_threads.push_back( + std::shared_ptr<std::thread>( + new std::thread( + std::bind(&Threaded_Fork::thread_entry, this, m_next[i])))); + } + } + } + +void Threaded_Fork::send(const uint8_t input[], size_t length) + { + if(m_write_queue.size()) + thread_delegate_work(m_write_queue.data(), m_write_queue.size()); + thread_delegate_work(input, length); + + bool nothing_attached = true; + for(size_t j = 0; j != total_ports(); ++j) + if(m_next[j]) + nothing_attached = false; + + if(nothing_attached) + m_write_queue += std::make_pair(input, length); + else + m_write_queue.clear(); + } + +void Threaded_Fork::thread_delegate_work(const uint8_t input[], size_t length) + { + //Set the data to do. + m_thread_data->m_input = input; + m_thread_data->m_input_length = length; + + //Let the workers start processing. + m_thread_data->m_input_complete_barrier.wait(total_ports() + 1); + m_thread_data->m_input_ready_semaphore.release(total_ports()); + + //Wait for all the filters to finish processing. + m_thread_data->m_input_complete_barrier.sync(); + + //Reset the thread data + m_thread_data->m_input = nullptr; + m_thread_data->m_input_length = 0; + } + +void Threaded_Fork::thread_entry(Filter* filter) + { + while(true) + { + m_thread_data->m_input_ready_semaphore.acquire(); + + if(!m_thread_data->m_input) + break; + + filter->write(m_thread_data->m_input, m_thread_data->m_input_length); + m_thread_data->m_input_complete_barrier.sync(); + } + } + +} + +#endif |