Repository: randombit/botan
Pull request #1992 (2019-06-03 09:31:22)

Allow overriding tls_verify_cert_chain callback for TLS::Stream
Implement `set_verify_callback` in both TLS::Stream and TLS::Context.

This allows users to have the stream override the `tls_verify_cert_chain` callback. If no custom callback is set the default callback will be used.

TLS::Context is now a class and the members are protected. TLS::Stream now stores the context as a reference rather than copying it, leaving the responsibility to manage the context's lifetime with the user.

codecov-io: # [Codecov](https://codecov.io/gh/randombit/botan/pull/1992?src=pr&el=h1) Report
> Merging [#1992](https://codecov.io/gh/randombit/botan/pull/1992?src=pr&el=desc) into [master](https://codecov.io/gh/randombit/botan/commit/df736f506c399b6ddde46579a3ebbbf6c907f2f3?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/randombit/botan/pull/1992/graphs/tree.svg?width=650&token=VR6iYmSPH8&height=150&src=pr)](https://codecov.io/gh/randombit/botan/pull/1992?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1992      +/-   ##
==========================================
+ Coverage   92.32%   92.32%   +<.01%     
==========================================
  Files         538      538              
  Lines       57944    57944              
  Branches     6152     6152              
==========================================
+ Hits        53494    53495       +1     
+ Misses       4450     4449       -1
```


| [Impacted Files](https://codecov.io/gh/randombit/botan/pull/1992?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/lib/pbkdf/bcrypt\_pbkdf/bcrypt\_pbkdf.cpp](https://codecov.io/gh/randombit/botan/pull/1992/diff?src=pr&el=tree#diff-c3JjL2xpYi9wYmtkZi9iY3J5cHRfcGJrZGYvYmNyeXB0X3Bia2RmLmNwcA==) | `91.66% <0%> (ø)` | :arrow_up: |
| [src/lib/pubkey/elgamal/elgamal.cpp](https://codecov.io/gh/randombit/botan/pull/1992/diff?src=pr&el=tree#diff-c3JjL2xpYi9wdWJrZXkvZWxnYW1hbC9lbGdhbWFsLmNwcA==) | `96.92% <0%> (+1.53%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/randombit/botan/pull/1992?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/randombit/botan/pull/1992?src=pr&el=footer). Last update [df736f5...6f612dd](https://codecov.io/gh/randombit/botan/pull/1992?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/configure.py b/configure.py
index b892389e3..6d12de3b1 100755
--- a/configure.py
+++ b/configure.py
@@ -1290,7 +1290,7 @@ class CompilerInfo(InfoObject): # pylint: disable=too-many-instance-attributes
                     raise UserError('No flags defined for sanitizer %s in %s' % (s, self.basename))
 
                 if s == 'default':
-                    abi_link.update([self.sanitizers[x] for x in default_san])
+                    abi_link.update([self.sanitizers[s] for s in default_san])
                 else:
                     abi_link.add(self.sanitizers[s])
 
@@ -2491,16 +2491,14 @@ class AmalgamationHeader(object):
         if name in self.included_already:
             return
 
+        if name == 'botan.h':
+            return
+
         self.included_already.add(name)
 
         if name not in self.file_contents:
             return
 
-        depr_marker = 'BOTAN_DEPRECATED_HEADER(%s)\n' % (name)
-        if depr_marker in self.file_contents[name]:
-            logging.debug("Ignoring deprecated header %s", name)
-            return
-
         for line in self.file_contents[name]:
             header = AmalgamationHelper.is_botan_include(line)
             if header:
@@ -2832,8 +2830,8 @@ def robust_makedirs(directory, max_retries=5):
         except OSError as e:
             if e.errno == errno.EEXIST:
                 raise
-
-        time.sleep(0.1)
+            else:
+                time.sleep(0.1)
 
     # Final attempt, pass any exceptions up to caller.
     os.makedirs(directory)
diff --git a/doc/api_ref/tls.rst b/doc/api_ref/tls.rst
index 74f8bf79a..f78d59e90 100644
--- a/doc/api_ref/tls.rst
+++ b/doc/api_ref/tls.rst
@@ -85,7 +85,7 @@ information about the connection.
      exception which will send a close message to the counterparty and
      reset the connection state.
 
- .. cpp::function:: void tls_verify_cert_chain(const std::vector<X509_Certificate>& cert_chain, \
+ .. cpp:function:: void tls_verify_cert_chain(const std::vector<X509_Certificate>& cert_chain, \
                    const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses, \
                    const std::vector<Certificate_Store*>& trusted_roots, \
                    Usage_Type usage, \
@@ -120,7 +120,7 @@ information about the connection.
      being authenticated using this certificate chain. It can be consulted
      for values such as allowable signature methods and key sizes.
 
- .. cpp::function:: std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
+ .. cpp:function:: std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
 
      Called by default `tls_verify_cert_chain` to set timeout for online OCSP requests
      on the certificate chain. Return 0 to disable OCSP. Current default is 0.
@@ -1618,6 +1618,7 @@ It offers the following interface:
 
    Construct a new TLS stream.
    The *context* parameter will be used to set up the underlying *native handle*, i.e. the :ref:`TLS::Client <tls_client>`, when :cpp:func:`handshake` is called.
+   Using code must ensure the context is kept alive for the lifetime of the stream.
    The further *args* will be forwarded to the *next layer*'s constructor.
 
    .. cpp:function:: template <typename... Args> \
@@ -1694,22 +1695,23 @@ It offers the following interface:
    The return type is an automatically deduced specialization of :cpp:class:`boost::asio::async_result`, depending on the *WriteHandler* type.
    *WriteHandler* should suffice the `requirements to a Boost.Asio write handler <https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/WriteHandler.html>`_.
 
-.. cpp:struct:: TLS::Context
+.. cpp:class:: TLS::Context
 
-   A helper struct to collect the initialization parameters for the Stream's underlying *native handle* (see :cpp:class:`TLS::Client`).
-   `TLS::Context` is defined as
+   A helper class to initialize and configure the Stream's underlying *native handle* (see :cpp:class:`TLS::Client`).
 
-   .. code-block:: cpp
+   .. cpp:function:: Context(Credentials_Manager&   credentialsManager, \
+                             RandomNumberGenerator& randomNumberGenerator, \
+                             Session_Manager&       sessionManager, \
+                             Policy&                policy, \
+                             Server_Information     serverInfo = Server_Information())
 
-      struct Context
-         {
-         Credentials_Manager*   credentialsManager;
-         RandomNumberGenerator* randomNumberGenerator;
-         Session_Manager*       sessionManager;
-         Policy*                policy;
-         Server_Information     serverInfo;
-         };
+   Constructor for TLS::Context.
 
+   .. cpp:function:: void set_verify_callback(Verify_Callback_T callback)
+
+   Set a user-defined callback function for certificate chain verification. This
+   will cause the stream to override the default implementation of the
+   :cpp:func:`tls_verify_cert_chain` callback.
 
 Stream Code Example
 ^^^^^^^^^^^^^^^^^^^^
@@ -1753,11 +1755,11 @@ Stream Code Example
                 boost::asio::ip::tcp::resolver::iterator endpoint_iterator,
                 http::request<http::string_body>         req)
             : request_(req)
-            , ctx_{&credentials_mgr_,
-                   &rng_,
-                   &session_mgr_,
-                   &policy_,
-                   Botan::TLS::Server_Information()}
+            , ctx_(credentials_mgr_,
+                   rng_,
+                   session_mgr_,
+                   policy_,
+                   Botan::TLS::Server_Information())
             , stream_(io_context, ctx_)
             {
             boost::asio::async_connect(stream_.lowest_layer(), endpoint_iterator,
diff --git a/doc/deprecated.rst b/doc/deprecated.rst
index 128a662bb..41f00d0d5 100644
--- a/doc/deprecated.rst
+++ b/doc/deprecated.rst
@@ -21,19 +21,7 @@ in the source.
 - Directly accessing the member variables of types calendar_point, ASN1_Attribute,
   AlgorithmIdentifier, and BER_Object
 
-- The following headers are currently public, but will be completely
-  removed in a future major release: ``botan.h``, ``init.h``,
-  ``lookup.h``, ``threefish.h``, ``sm2_enc.h``, ``datastor.h``,
-  ``basefilt.h``, ``hex_filt.h``, ``b64_filt.h``, ``comp_filter.h``,
-  ``key_filt.h``, ``buf_filt.h``, ``cipher_filter.h``
-
-- The following headers are currently public, but will be made
-  internal in a future major release, and no longer usable by
-  applications: ``rotate.h``, ``loadstor.h``, ``mul128.h``,
-  ``dyn_load.h``, ``atomic.h``, ``blinding.h``, ``gf2m_small_m.h``,
-  ``locking_allocator.h``, ``polyn_gf2m.h`,, ``parsing.h``,
-  ``rfc6979.h``, ``divide.h``, ``charset.h``, ``secqueue.h``,
-  ``buf_filt.h``, ``keypair.h``, ``http_util.h``, ``scan_name.h``
+- The headers ``botan.h``, ``init.h``, ``lookup.h``, ``threefish.h``, ``sm2_enc.h``
 
 - Using a default output length for "SHAKE-128" and "SHAKE-256". Instead,
   always specify the desired output length.
diff --git a/doc/dev_ref/mistakes.rst b/doc/dev_ref/mistakes.rst
index 03b2c7905..9f89e3059 100644
--- a/doc/dev_ref/mistakes.rst
+++ b/doc/dev_ref/mistakes.rst
@@ -27,13 +27,6 @@ the overall API and ABI surface.
 These interfaces are now deprecated, and perhaps will be able to be
 removed eventually.
 
-Header Directories
--------------------
-
-It would have been better to install all headers as ``X/header.h``
-where ``X`` is the base dir in the source, eg ``block/aes128.h``,
-``hash/md5.h``, ...
-
 Exceptions
 -----------
 
diff --git a/src/build-data/makefile.in b/src/build-data/makefile.in
index 9c1d102d4..52baec88f 100644
--- a/src/build-data/makefile.in
+++ b/src/build-data/makefile.in
@@ -1,6 +1,3 @@
-
-# This makefile was generated using '%{command_line}'
-
 # Paths to relevant programs
 
 CXX            = %{cxx}
diff --git a/src/build-data/version.txt b/src/build-data/version.txt
index ed6bafc01..2dc302a20 100644
--- a/src/build-data/version.txt
+++ b/src/build-data/version.txt
@@ -2,7 +2,7 @@
 release_major = 2
 release_minor = 11
 release_patch = 0
-release_so_abi_rev = 11
+release_so_abi_rev = 10
 
 # These are set by the distribution script
 release_vc_rev = None
diff --git a/src/lib/base/botan.h b/src/lib/base/botan.h
index a473e8fbf..26bfa75a7 100644
--- a/src/lib/base/botan.h
+++ b/src/lib/base/botan.h
@@ -16,6 +16,12 @@
 * This header file will be removed in Botan 3.x
 */
 
+#if defined(__GNUC__)
+  #warning "botan/botan.h is deprecated"
+#elif defined(_MSC_VER)
+  #pragma message ("botan/botan.h is deprecated")
+#endif
+
 #include <botan/lookup.h>
 #include <botan/version.h>
 #include <botan/parsing.h>
@@ -36,6 +42,4 @@
   #include <botan/pkcs8.h>
 #endif
 
-BOTAN_DEPRECATED_HEADER(botan.h)
-
 #endif
diff --git a/src/lib/base/init.h b/src/lib/base/init.h
index 668650846..ba014d8e1 100644
--- a/src/lib/base/init.h
+++ b/src/lib/base/init.h
@@ -13,8 +13,6 @@
 
 namespace Botan {
 
-BOTAN_DEPRECATED_HEADER(init.h)
-
 /*
 * Previously botan had state whose lifetime had to be explicitly
 * managed by the application. As of 1.11.14 this is no longer the
diff --git a/src/lib/base/lookup.h b/src/lib/base/lookup.h
index 4a14230db..1cfa7d3c9 100644
--- a/src/lib/base/lookup.h
+++ b/src/lib/base/lookup.h
@@ -32,8 +32,6 @@
 
 namespace Botan {
 
-BOTAN_DEPRECATED_HEADER(lookup.h)
-
 /*
 * As of 1.11.26 this header is deprecated. Instead use the calls T::create and
 * T::providers (as demonstrated in the implementation below).
diff --git a/src/lib/block/threefish_512/threefish.h b/src/lib/block/threefish_512/threefish.h
index f866a717f..6b21e9fdd 100644
--- a/src/lib/block/threefish_512/threefish.h
+++ b/src/lib/block/threefish_512/threefish.h
@@ -8,10 +8,6 @@
 #ifndef BOTAN_THREEFISH_H_
 #define BOTAN_THREEFISH_H_
 
-// This header is deprecated and will be removed in a future major release
-
 #include <botan/threefish_512.h>
 
-BOTAN_DEPRECATED_HEADER(threefish.h)
-
 #endif
diff --git a/src/lib/filters/aead_filt.h b/src/lib/filters/aead_filt.h
new file mode 100644
index 000000000..f569423a6
--- /dev/null
+++ b/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/lib/filters/b64_filt.h b/src/lib/filters/b64_filt.h
deleted file mode 100644
index af7bb7cf2..000000000
--- a/src/lib/filters/b64_filt.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-* Base64 Encoder/Decoder
-* (C) 1999-2010 Jack Lloyd
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#ifndef BOTAN_BASE64_FILTER_H_
-#define BOTAN_BASE64_FILTER_H_
-
-#include <botan/filters.h>
-BOTAN_DEPRECATED_HEADER(b64_filt.h)
-
-#endif
diff --git a/src/lib/filters/basefilt.cpp b/src/lib/filters/basefilt.cpp
index b34b70bd6..89026f600 100644
--- a/src/lib/filters/basefilt.cpp
+++ b/src/lib/filters/basefilt.cpp
@@ -1,13 +1,21 @@
 /*
+* Basic Filters
 * (C) 1999-2007 Jack Lloyd
 *
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
-#include <botan/filters.h>
+#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
 */
@@ -32,6 +40,11 @@ Chain::Chain(Filter* filters[], size_t count)
          }
    }
 
+std::string Chain::name() const
+   {
+   return "Chain";
+   }
+
 /*
 * Fork Constructor
 */
@@ -49,4 +62,9 @@ Fork::Fork(Filter* filters[], size_t count)
    set_next(filters, count);
    }
 
+std::string Fork::name() const
+   {
+   return "Fork";
+   }
+
 }
diff --git a/src/lib/filters/basefilt.h b/src/lib/filters/basefilt.h
index 422989b75..922d35669 100644
--- a/src/lib/filters/basefilt.h
+++ b/src/lib/filters/basefilt.h
@@ -9,10 +9,116 @@
 #ifndef BOTAN_BASEFILT_H_
 #define BOTAN_BASEFILT_H_
 
-// This header is deprecated and will be removed in a future major release
+#include <botan/filter.h>
 
-#include <botan/filters.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
 
-BOTAN_DEPRECATED_HEADER(basefilt.h)
+}
 
 #endif
diff --git a/src/lib/filters/buf_filt.cpp b/src/lib/filters/buf_filt.cpp
index 0e34a56dd..11ca9bbfe 100644
--- a/src/lib/filters/buf_filt.cpp
+++ b/src/lib/filters/buf_filt.cpp
@@ -5,7 +5,7 @@
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
-#include <botan/filters.h>
+#include <botan/buf_filt.h>
 #include <botan/mem_ops.h>
 #include <botan/internal/rounding.h>
 #include <botan/exceptn.h>
diff --git a/src/lib/filters/buf_filt.h b/src/lib/filters/buf_filt.h
index 1f9ed3eff..b4cd8e680 100644
--- a/src/lib/filters/buf_filt.h
+++ b/src/lib/filters/buf_filt.h
@@ -8,7 +8,86 @@
 #ifndef BOTAN_BUFFERED_FILTER_H_
 #define BOTAN_BUFFERED_FILTER_H_
 
-#include <botan/filters.h>
-BOTAN_DEPRECATED_HEADER(buf_filt.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/lib/filters/cipher_filter.cpp b/src/lib/filters/cipher_filter.cpp
index 720aeac6f..a3e7bd1c3 100644
--- a/src/lib/filters/cipher_filter.cpp
+++ b/src/lib/filters/cipher_filter.cpp
@@ -5,7 +5,7 @@
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
-#include <botan/filters.h>
+#include <botan/cipher_filter.h>
 #include <botan/internal/rounding.h>
 
 namespace Botan {
diff --git a/src/lib/filters/cipher_filter.h b/src/lib/filters/cipher_filter.h
index 84fc58b6e..750385d15 100644
--- a/src/lib/filters/cipher_filter.h
+++ b/src/lib/filters/cipher_filter.h
@@ -5,10 +5,54 @@
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
-#ifndef BOTAN_CIPHER_FILTER_H_
-#define BOTAN_CIPHER_FILTER_H_
+#ifndef BOTAN_TRANSFORM_FILTER_H_
+#define BOTAN_TRANSFORM_FILTER_H_
 
-#include <botan/filters.h>
-BOTAN_DEPRECATED_HEADER(cipher_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/lib/filters/b64_filt.cpp b/src/lib/filters/codec_filt/b64_filt.cpp
similarity index 99%
rename from src/lib/filters/b64_filt.cpp
rename to src/lib/filters/codec_filt/b64_filt.cpp
index 8cbba1a6e..0ce158fb4 100644
--- a/src/lib/filters/b64_filt.cpp
+++ b/src/lib/filters/codec_filt/b64_filt.cpp
@@ -5,7 +5,7 @@
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
-#include <botan/filters.h>
+#include <botan/b64_filt.h>
 #include <botan/base64.h>
 #include <botan/exceptn.h>
 #include <algorithm>
diff --git a/src/lib/filters/codec_filt/b64_filt.h b/src/lib/filters/codec_filt/b64_filt.h
new file mode 100644
index 000000000..9c9602b98
--- /dev/null
+++ b/src/lib/filters/codec_filt/b64_filt.h
@@ -0,0 +1,88 @@
+/*
+* Base64 Encoder/Decoder
+* (C) 1999-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_BASE64_FILTER_H_
+#define BOTAN_BASE64_FILTER_H_
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* This class represents a Base64 encoder.
+*/
+class BOTAN_PUBLIC_API(2,0) Base64_Encoder final : public Filter
+   {
+   public:
+      std::string name() const override { return "Base64_Encoder"; }
+
+      /**
+      * Input a part of a message to the encoder.
+      * @param input the message to input as a byte array
+      * @param length the length of the byte array input
+      */
+      void write(const uint8_t input[], size_t length) override;
+
+      /**
+      * Inform the Encoder that the current message shall be closed.
+      */
+      void end_msg() override;
+
+      /**
+      * Create a base64 encoder.
+      * @param breaks whether to use line breaks in the output
+      * @param length the length of the lines of the output
+      * @param t_n whether to use a trailing newline
+      */
+      Base64_Encoder(bool breaks = false, size_t length = 72,
+                     bool t_n = false);
+   private:
+      void encode_and_send(const uint8_t input[], size_t length,
+                           bool final_inputs = false);
+      void do_output(const uint8_t output[], size_t length);
+
+      const size_t m_line_length;
+      const bool m_trailing_newline;
+      std::vector<uint8_t> m_in, m_out;
+      size_t m_position, m_out_position;
+   };
+
+/**
+* This object represents a Base64 decoder.
+*/
+class BOTAN_PUBLIC_API(2,0) Base64_Decoder final : public Filter
+   {
+   public:
+      std::string name() const override { return "Base64_Decoder"; }
+
+      /**
+      * Input a part of a message to the decoder.
+      * @param input the message to input as a byte array
+      * @param length the length of the byte array input
+      */
+      void write(const uint8_t input[], size_t length) override;
+
+      /**
+      * Finish up the current message
+      */
+      void end_msg() override;
+
+      /**
+      * Create a base64 decoder.
+      * @param checking the type of checking that shall be performed by
+      * the decoder
+      */
+      explicit Base64_Decoder(Decoder_Checking checking = NONE);
+   private:
+      const Decoder_Checking m_checking;
+      std::vector<uint8_t> m_in, m_out;
+      size_t m_position;
+   };
+
+}
+
+#endif
diff --git a/src/lib/filters/hex_filt.cpp b/src/lib/filters/codec_filt/hex_filt.cpp
similarity index 99%
rename from src/lib/filters/hex_filt.cpp
rename to src/lib/filters/codec_filt/hex_filt.cpp
index 761c73ade..be1dbbc5c 100644
--- a/src/lib/filters/hex_filt.cpp
+++ b/src/lib/filters/codec_filt/hex_filt.cpp
@@ -5,7 +5,7 @@
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
-#include <botan/filters.h>
+#include <botan/hex_filt.h>
 #include <botan/hex.h>
 #include <botan/exceptn.h>
 #include <algorithm>
diff --git a/src/lib/filters/codec_filt/hex_filt.h b/src/lib/filters/codec_filt/hex_filt.h
new file mode 100644
index 000000000..4128d627a
--- /dev/null
+++ b/src/lib/filters/codec_filt/hex_filt.h
@@ -0,0 +1,81 @@
+/*
+* Hex Encoder/Decoder
+* (C) 1999-2010 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_HEX_FILTER_H_
+#define BOTAN_HEX_FILTER_H_
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* Converts arbitrary binary data to hex strings, optionally with
+* newlines inserted
+*/
+class BOTAN_PUBLIC_API(2,0) Hex_Encoder final : public Filter
+   {
+   public:
+      /**
+      * Whether to use uppercase or lowercase letters for the encoded string.
+      */
+      enum Case { Uppercase, Lowercase };
+
+      std::string name() const override { return "Hex_Encoder"; }
+
+      void write(const uint8_t in[], size_t length) override;
+      void end_msg() override;
+
+      /**
+      * Create a hex encoder.
+      * @param the_case the case to use in the encoded strings.
+      */
+      explicit Hex_Encoder(Case the_case);
+
+      /**
+      * Create a hex encoder.
+      * @param newlines should newlines be used
+      * @param line_length if newlines are used, how long are lines
+      * @param the_case the case to use in the encoded strings
+      */
+      Hex_Encoder(bool newlines = false,
+                  size_t line_length = 72,
+                  Case the_case = Uppercase);
+   private:
+      void encode_and_send(const uint8_t[], size_t);
+
+      const Case m_casing;
+      const size_t m_line_length;
+      std::vector<uint8_t> m_in, m_out;
+      size_t m_position, m_counter;
+   };
+
+/**
+* Converts hex strings to bytes
+*/
+class BOTAN_PUBLIC_API(2,0) Hex_Decoder final : public Filter
+   {
+   public:
+      std::string name() const override { return "Hex_Decoder"; }
+
+      void write(const uint8_t[], size_t) override;
+      void end_msg() override;
+
+      /**
+      * Construct a Hex Decoder using the specified
+      * character checking.
+      * @param checking the checking to use during decoding.
+      */
+      explicit Hex_Decoder(Decoder_Checking checking = NONE);
+   private:
+      const Decoder_Checking m_checking;
+      std::vector<uint8_t> m_in, m_out;
+      size_t m_position;
+   };
+
+}
+
+#endif
diff --git a/src/lib/filters/codec_filt/info.txt b/src/lib/filters/codec_filt/info.txt
index fd7b3fbd3..347c876a7 100644
--- a/src/lib/filters/codec_filt/info.txt
+++ b/src/lib/filters/codec_filt/info.txt
@@ -1,6 +1,8 @@
 <defines>
+CODEC_FILTERS -> 20131128
 </defines>
 
 <requires>
+base64
 filters
 </requires>
diff --git a/src/lib/filters/comp_filter.cpp b/src/lib/filters/comp_filter.cpp
index c2814460a..2563a4907 100644
--- a/src/lib/filters/comp_filter.cpp
+++ b/src/lib/filters/comp_filter.cpp
@@ -6,7 +6,7 @@
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
-#include <botan/filters.h>
+#include <botan/comp_filter.h>
 #include <botan/exceptn.h>
 
 #if defined(BOTAN_HAS_COMPRESSION)
diff --git a/src/lib/filters/comp_filter.h b/src/lib/filters/comp_filter.h
index 86b587ac3..d9cc00b68 100644
--- a/src/lib/filters/comp_filter.h
+++ b/src/lib/filters/comp_filter.h
@@ -8,8 +8,64 @@
 #ifndef BOTAN_COMPRESSION_FILTER_H_
 #define BOTAN_COMPRESSION_FILTER_H_
 
-BOTAN_DEPRECATED_HEADER(comp_filter.h)
+#include <botan/filter.h>
 
-#include <botan/filters.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/lib/filters/filters.h b/src/lib/filters/filters.h
index c19e1a749..b4aee1207 100644
--- a/src/lib/filters/filters.h
+++ b/src/lib/filters/filters.h
@@ -1,7 +1,6 @@
 /*
-* Common Filters
+* Filters
 * (C) 1999-2007,2015 Jack Lloyd
-* (C) 2013 Joel Low
 *
 * Botan is released under the Simplified BSD License (see license.txt)
 */
@@ -9,15 +8,10 @@
 #ifndef BOTAN_FILTERS_H_
 #define BOTAN_FILTERS_H_
 
-#include <botan/secmem.h>
+#include <botan/basefilt.h>
+#include <botan/key_filt.h>
 #include <botan/data_snk.h>
 #include <botan/pipe.h>
-#include <botan/symkey.h>
-#include <botan/cipher_mode.h>
-
-#if defined(BOTAN_TARGET_OS_HAS_THREADS)
-  #include <thread>
-#endif
 
 #if defined(BOTAN_HAS_STREAM_CIPHER)
    #include <botan/stream_cipher.h>
@@ -31,229 +25,12 @@
    #include <botan/mac.h>
 #endif
 
-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;
-   };
-
-/**
-* 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)
-         {
-         if(iv.length() != 0)
-            throw Invalid_IV_Length(name(), iv.length());
-         }
-
-      /**
-      * 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); }
-   };
-
-/**
-* 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 in a future major release
-typedef Cipher_Mode_Filter Transform_Filter;
-typedef Transform_Filter Transformation_Filter;
-
-/*
-* Get a cipher object
-*/
-
-/**
-* 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
-*/
-inline 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());
-   }
-
-/**
-* 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
-*/
-inline 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;
-   }
+#if defined(BOTAN_HAS_CODEC_FILTERS)
+  #include <botan/b64_filt.h>
+  #include <botan/hex_filt.h>
+#endif
 
-/**
-* 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
-*/
-inline 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;
-   }
+namespace Botan {
 
 #if defined(BOTAN_HAS_STREAM_CIPHER)
 
@@ -445,297 +222,6 @@ class BOTAN_PUBLIC_API(2,0) MAC_Filter final : public Keyed_Filter
    };
 #endif
 
-#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
-
-/**
-* This class represents a Base64 encoder.
-*/
-class BOTAN_PUBLIC_API(2,0) Base64_Encoder final : public Filter
-   {
-   public:
-      std::string name() const override { return "Base64_Encoder"; }
-
-      /**
-      * Input a part of a message to the encoder.
-      * @param input the message to input as a byte array
-      * @param length the length of the byte array input
-      */
-      void write(const uint8_t input[], size_t length) override;
-
-      /**
-      * Inform the Encoder that the current message shall be closed.
-      */
-      void end_msg() override;
-
-      /**
-      * Create a base64 encoder.
-      * @param breaks whether to use line breaks in the output
-      * @param length the length of the lines of the output
-      * @param t_n whether to use a trailing newline
-      */
-      Base64_Encoder(bool breaks = false, size_t length = 72,
-                     bool t_n = false);
-   private:
-      void encode_and_send(const uint8_t input[], size_t length,
-                           bool final_inputs = false);
-      void do_output(const uint8_t output[], size_t length);
-
-      const size_t m_line_length;
-      const bool m_trailing_newline;
-      std::vector<uint8_t> m_in, m_out;
-      size_t m_position, m_out_position;
-   };
-
-/**
-* This object represents a Base64 decoder.
-*/
-class BOTAN_PUBLIC_API(2,0) Base64_Decoder final : public Filter
-   {
-   public:
-      std::string name() const override { return "Base64_Decoder"; }
-
-      /**
-      * Input a part of a message to the decoder.
-      * @param input the message to input as a byte array
-      * @param length the length of the byte array input
-      */
-      void write(const uint8_t input[], size_t length) override;
-
-      /**
-      * Finish up the current message
-      */
-      void end_msg() override;
-
-      /**
-      * Create a base64 decoder.
-      * @param checking the type of checking that shall be performed by
-      * the decoder
-      */
-      explicit Base64_Decoder(Decoder_Checking checking = NONE);
-   private:
-      const Decoder_Checking m_checking;
-      std::vector<uint8_t> m_in, m_out;
-      size_t m_position;
-   };
-
-/**
-* Converts arbitrary binary data to hex strings, optionally with
-* newlines inserted
-*/
-class BOTAN_PUBLIC_API(2,0) Hex_Encoder final : public Filter
-   {
-   public:
-      /**
-      * Whether to use uppercase or lowercase letters for the encoded string.
-      */
-      enum Case { Uppercase, Lowercase };
-
-      std::string name() const override { return "Hex_Encoder"; }
-
-      void write(const uint8_t in[], size_t length) override;
-      void end_msg() override;
-
-      /**
-      * Create a hex encoder.
-      * @param the_case the case to use in the encoded strings.
-      */
-      explicit Hex_Encoder(Case the_case);
-
-      /**
-      * Create a hex encoder.
-      * @param newlines should newlines be used
-      * @param line_length if newlines are used, how long are lines
-      * @param the_case the case to use in the encoded strings
-      */
-      Hex_Encoder(bool newlines = false,
-                  size_t line_length = 72,
-                  Case the_case = Uppercase);
-   private:
-      void encode_and_send(const uint8_t[], size_t);
-
-      const Case m_casing;
-      const size_t m_line_length;
-      std::vector<uint8_t> m_in, m_out;
-      size_t m_position, m_counter;
-   };
-
-/**
-* Converts hex strings to bytes
-*/
-class BOTAN_PUBLIC_API(2,0) Hex_Decoder final : public Filter
-   {
-   public:
-      std::string name() const override { return "Hex_Decoder"; }
-
-      void write(const uint8_t[], size_t) override;
-      void end_msg() override;
-
-      /**
-      * Construct a Hex Decoder using the specified
-      * character checking.
-      * @param checking the checking to use during decoding.
-      */
-      explicit Hex_Decoder(Decoder_Checking checking = NONE);
-   private:
-      const Decoder_Checking m_checking;
-      std::vector<uint8_t> m_in, m_out;
-      size_t m_position;
-   };
-
-/**
-* 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 { return "Chain"; }
-
-      /**
-      * 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 { return "Fork"; }
-
-      /**
-      * 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/lib/filters/hex_filt.h b/src/lib/filters/hex_filt.h
deleted file mode 100644
index b529b5299..000000000
--- a/src/lib/filters/hex_filt.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-* Hex Encoder/Decoder
-* (C) 1999-2010 Jack Lloyd
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#ifndef BOTAN_HEX_FILTER_H_
-#define BOTAN_HEX_FILTER_H_
-
-#include <botan/filters.h>
-BOTAN_DEPRECATED_HEADER(hex_filt.h)
-
-#endif
diff --git a/src/lib/filters/info.txt b/src/lib/filters/info.txt
index 9fb8ef7ce..cfc114353 100644
--- a/src/lib/filters/info.txt
+++ b/src/lib/filters/info.txt
@@ -1,21 +1,18 @@
 <defines>
 FILTERS -> 20160415
-CODEC_FILTERS -> 20131128
 </defines>
 
 <header:public>
 basefilt.h
-comp_filter.h
-cipher_filter.h
 buf_filt.h
-key_filt.h
-
-secqueue.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>
@@ -24,5 +21,4 @@ out_buf.h
 
 <requires>
 modes
-base64
 </requires>
diff --git a/src/lib/filters/key_filt.cpp b/src/lib/filters/key_filt.cpp
new file mode 100644
index 000000000..b87a8c87f
--- /dev/null
+++ b/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/lib/filters/key_filt.h b/src/lib/filters/key_filt.h
index 3d85d886a..67b689f99 100644
--- a/src/lib/filters/key_filt.h
+++ b/src/lib/filters/key_filt.h
@@ -8,7 +8,102 @@
 #ifndef BOTAN_KEYED_FILTER_H_
 #define BOTAN_KEYED_FILTER_H_
 
+#include <botan/symkey.h>
 #include <botan/filter.h>
-BOTAN_DEPRECATED_HEADER(key_filt.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/lib/filters/threaded_fork.cpp b/src/lib/filters/threaded_fork.cpp
index 2d77f9fd1..35ea94109 100644
--- a/src/lib/filters/threaded_fork.cpp
+++ b/src/lib/filters/threaded_fork.cpp
@@ -6,7 +6,7 @@
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
-#include <botan/filters.h>
+#include <botan/basefilt.h>
 
 #if defined(BOTAN_HAS_THREAD_UTILS)
 
diff --git a/src/lib/math/bigint/bigint.h b/src/lib/math/bigint/bigint.h
index 80b23ca8c..e6b7bc4bb 100644
--- a/src/lib/math/bigint/bigint.h
+++ b/src/lib/math/bigint/bigint.h
@@ -905,7 +905,7 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
      * All elements of vec must have the same size, and output must be
      * pre-allocated with the same size.
      */
-     static void BOTAN_DEPRECATED("No longer in use") const_time_lookup(
+     static void const_time_lookup(
         secure_vector<word>& output,
         const std::vector<BigInt>& vec,
         size_t idx);
diff --git a/src/lib/prov/pkcs11/p11.h b/src/lib/prov/pkcs11/p11.h
index 46545b925..043b1795a 100644
--- a/src/lib/prov/pkcs11/p11.h
+++ b/src/lib/prov/pkcs11/p11.h
@@ -1817,16 +1817,11 @@ class BOTAN_PUBLIC_API(2,0) LowLevel
             }
 
          encrypted_data.resize(encrypted_size);
-         if (!C_Encrypt(session,
+         return C_Encrypt(session,
                           const_cast<Byte*>(plaintext_data.data()),
                           static_cast<Ulong>(plaintext_data.size()),
                           encrypted_data.data(),
-                          &encrypted_size, return_value))
-            {
-            return false;
-            }
-         encrypted_data.resize(encrypted_size);
-         return true;
+                          &encrypted_size, return_value);
          }
 
       /**
@@ -1955,16 +1950,11 @@ class BOTAN_PUBLIC_API(2,0) LowLevel
             }
 
          decrypted_data.resize(decrypted_size);
-         if(!C_Decrypt(session,
-                       const_cast<Byte*>(encrypted_data.data()),
-                       static_cast<Ulong>(encrypted_data.size()),
-                       decrypted_data.data(),
-                       &decrypted_size, return_value))
-            {
-            return false;
-            }
-         decrypted_data.resize(decrypted_size);
-         return true;
+         return C_Decrypt(session,
+                          const_cast<Byte*>(encrypted_data.data()),
+                          static_cast<Ulong>(encrypted_data.size()),
+                          decrypted_data.data(),
+                          &decrypted_size, return_value);
          }
 
       /**
@@ -2199,17 +2189,12 @@ class BOTAN_PUBLIC_API(2,0) LowLevel
             }
 
          signature.resize(signature_size);
-         if (!C_Sign(session,
+         return C_Sign(session,
                        const_cast<Byte*>(data.data()),
                        static_cast<Ulong>(data.size()),
                        signature.data(),
                        &signature_size,
-                       return_value))
-            {
-            return false;
-            }
-         signature.resize(signature_size);
-         return true;
+                       return_value);
          }
 
       /**
@@ -2305,12 +2290,7 @@ class BOTAN_PUBLIC_API(2,0) LowLevel
             }
 
          signature.resize(signature_size);
-         if (!C_SignFinal(session, signature.data(), &signature_size, return_value))
-            {
-            return false;
-            }
-         signature.resize(signature_size);
-         return true;
+         return C_SignFinal(session, signature.data(), &signature_size, return_value);
          }
 
       /**
diff --git a/src/lib/pubkey/sm2/sm2_enc.h b/src/lib/pubkey/sm2/sm2_enc.h
index ea8c43d9d..1384d3726 100644
--- a/src/lib/pubkey/sm2/sm2_enc.h
+++ b/src/lib/pubkey/sm2/sm2_enc.h
@@ -10,6 +10,4 @@
 
 #include <botan/sm2.h>
 
-BOTAN_DEPRECATED_HEADER(sm2_enc.h)
-
 #endif
diff --git a/src/lib/tls/asio/asio_context.h b/src/lib/tls/asio/asio_context.h
index 7de88ebce..e5e99e83a 100644
--- a/src/lib/tls/asio/asio_context.h
+++ b/src/lib/tls/asio/asio_context.h
@@ -14,8 +14,12 @@
 #include <boost/version.hpp>
 #if BOOST_VERSION >= 106600
 
+#include <functional>
+
 #include <botan/credentials_manager.h>
+#include <botan/ocsp.h>
 #include <botan/rng.h>
+#include <botan/tls_callbacks.h>
 #include <botan/tls_policy.h>
 #include <botan/tls_server_info.h>
 #include <botan/tls_session_manager.h>
@@ -23,13 +27,90 @@
 namespace Botan {
 namespace TLS {
 
-struct Context
+namespace detail {
+template <typename FunT>
+struct fn_signature_helper : public std::false_type {};
+
+template <typename R, typename D, typename... Args>
+struct fn_signature_helper<R(D::*)(Args...)>
+   {
+   using type = std::function<R(Args...)>;
+   };
+}  // namespace detail
+
+/**
+ * A helper class to initialize and configure Botan::TLS::Stream
+ */
+class Context
    {
-   Credentials_Manager*   credentialsManager;
-   RandomNumberGenerator* randomNumberGenerator;
-   Session_Manager*       sessionManager;
-   Policy*                policy;
-   Server_Information     serverInfo;
+   public:
+      // statically extract the function signature type from Callbacks::tls_verify_cert_chain
+      // and reuse it as an std::function<> for the verify callback signature
+      /**
+       * The signature of the callback function should correspond to the signature of
+       * Callbacks::tls_verify_cert_chain
+       */
+      using Verify_Callback =
+         detail::fn_signature_helper<decltype(&Callbacks::tls_verify_cert_chain)>::type;
+
+      Context(Credentials_Manager&   credentials_manager,
+              RandomNumberGenerator& rng,
+              Session_Manager&       session_manager,
+              Policy&                policy,
+              Server_Information     server_info = Server_Information()) :
+         m_credentials_manager(credentials_manager),
+         m_rng(rng),
+         m_session_manager(session_manager),
+         m_policy(policy),
+         m_server_info(server_info)
+         {}
+
+      virtual ~Context() = default;
+
+      Context(Context&&)                 = default;
+      Context(const Context&)            = delete;
+      Context& operator=(const Context&) = delete;
+      Context& operator=(Context&&)      = delete;
+
+      /**
+       * @brief Override the tls_verify_cert_chain callback
+       *
+       * This changes the verify_callback in the stream's TLS::Context, and hence the tls_verify_cert_chain callback
+       * used in the handshake.
+       * Using this function is equivalent to setting the callback via @see Botan::TLS::Stream::set_verify_callback
+       *
+       * @note This function should only be called before initiating the TLS handshake
+       */
+      void set_verify_callback(Verify_Callback callback)
+         {
+         m_verify_callback = std::move(callback);
+         }
+
+      bool has_verify_callback() const
+         {
+         return static_cast<bool>(m_verify_callback);
+         }
+
+      const Verify_Callback& get_verify_callback() const
+         {
+         return m_verify_callback;
+         }
+
+      void set_server_info(const Server_Information& server_info)
+         {
+         m_server_info = server_info;
+         }
+
+   protected:
+      template <class S, class C> friend class Stream;
+
+      Credentials_Manager&   m_credentials_manager;
+      RandomNumberGenerator& m_rng;
+      Session_Manager&       m_session_manager;
+      Policy&                m_policy;
+
+      Server_Information     m_server_info;
+      Verify_Callback        m_verify_callback;
    };
 
 }  // namespace TLS
diff --git a/src/lib/tls/asio/asio_stream.h b/src/lib/tls/asio/asio_stream.h
index 7cdd8d3dd..e8d9c2930 100644
--- a/src/lib/tls/asio/asio_stream.h
+++ b/src/lib/tls/asio/asio_stream.h
@@ -52,21 +52,38 @@ class Stream
       //! \name construction
       //! @{
 
+      /**
+       * @brief Construct a new Stream
+       *
+       * @param context The context parameter is used to set up the underlying native handle. Using code is
+       *                responsible for lifetime management of the context and must ensure that it is available for the
+       *                lifetime of the stream.
+       * @param args Arguments to be forwarded to the construction of the next layer.
+       */
       template <typename... Args>
       explicit Stream(Context& context, Args&& ... args)
          : m_context(context)
          , m_nextLayer(std::forward<Args>(args)...)
-         , m_core(m_receive_buffer, m_send_buffer)
+         , m_core(m_receive_buffer, m_send_buffer, m_context)
          , m_input_buffer_space(MAX_CIPHERTEXT_SIZE, '\0')
          , m_input_buffer(m_input_buffer_space.data(), m_input_buffer_space.size())
          {}
 
-      // overload for boost::asio::ssl::stream compatibility
+      /**
+       * @brief Construct a new Stream
+       *
+       * Convenience overload for boost::asio::ssl::stream compatibility.
+       *
+       * @param arg This argument is forwarded to the construction of the next layer.
+       * @param context The context parameter is used to set up the underlying native handle. Using code is
+       *                responsible for lifetime management of the context and must ensure that is available for the
+       *                lifetime of the stream.
+       */
       template <typename Arg>
       explicit Stream(Arg&& arg, Context& context)
          : m_context(context)
          , m_nextLayer(std::forward<Arg>(arg))
-         , m_core(m_receive_buffer, m_send_buffer)
+         , m_core(m_receive_buffer, m_send_buffer, m_context)
          , m_input_buffer_space(MAX_CIPHERTEXT_SIZE, '\0')
          , m_input_buffer(m_input_buffer_space.data(), m_input_buffer_space.size())
          {}
@@ -102,24 +119,29 @@ class Stream
       //! \name configuration and callback setters
       //! @{
 
-      //! @throws Not_Implemented
-      template<typename VerifyCallback>
-      void set_verify_callback(VerifyCallback callback)
+      /**
+       * @brief Override the tls_verify_cert_chain callback
+       *
+       * This changes the verify_callback in the stream's TLS::Context, and hence the tls_verify_cert_chain callback
+       * used in the handshake.
+       * Using this function is equivalent to setting the callback via @see Botan::TLS::Context::set_verify_callback
+       *
+       * @note This function should only be called before initiating the TLS handshake
+       */
+      void set_verify_callback(Context::Verify_Callback callback)
          {
-         BOTAN_UNUSED(callback);
-         throw Not_Implemented("set_verify_callback is not implemented");
+         m_context.set_verify_callback(std::move(callback));
          }
 
       /**
-       * Not Implemented.
-       * @param ec Will be set to `Botan::ErrorType::NotImplemented`
+       * @brief Compatibility overload of @ref set_verify_callback
+       *
+       * @param ec This parameter is unused.
        */
-      template<typename VerifyCallback>
-      void set_verify_callback(VerifyCallback callback,
-                               boost::system::error_code& ec)
+      void set_verify_callback(Context::Verify_Callback callback, boost::system::error_code& ec)
          {
-         BOTAN_UNUSED(callback);
-         ec = Botan::ErrorType::NotImplemented;
+         BOTAN_UNUSED(ec);
+         m_context.set_verify_callback(std::move(callback));
          }
 
       //! @throws Not_Implemented
@@ -133,8 +155,7 @@ class Stream
        * Not Implemented.
        * @param ec Will be set to `Botan::ErrorType::NotImplemented`
        */
-      void set_verify_depth(int depth,
-                            boost::system::error_code& ec)
+      void set_verify_depth(int depth, boost::system::error_code& ec)
          {
          BOTAN_UNUSED(depth);
          ec = Botan::ErrorType::NotImplemented;
@@ -153,8 +174,7 @@ class Stream
        * @param ec Will be set to `Botan::ErrorType::NotImplemented`
        */
       template <typename verify_mode>
-      void set_verify_mode(verify_mode v,
-                           boost::system::error_code& ec)
+      void set_verify_mode(verify_mode v, boost::system::error_code& ec)
          {
          BOTAN_UNUSED(v);
          ec = Botan::ErrorType::NotImplemented;
@@ -511,8 +531,8 @@ class Stream
       class StreamCore : public Botan::TLS::Callbacks
          {
          public:
-            StreamCore(boost::beast::flat_buffer& receive_buffer, boost::beast::flat_buffer& send_buffer)
-               : m_receive_buffer(receive_buffer), m_send_buffer(send_buffer) {}
+            StreamCore(boost::beast::flat_buffer& receive_buffer, boost::beast::flat_buffer& send_buffer, Context& context)
+               : m_receive_buffer(receive_buffer), m_send_buffer(send_buffer), m_tls_context(context) {}
 
             virtual ~StreamCore() = default;
 
@@ -546,8 +566,27 @@ class Stream
                return true;
                }
 
+            void tls_verify_cert_chain(
+               const std::vector<X509_Certificate>& cert_chain,
+               const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
+               const std::vector<Certificate_Store*>& trusted_roots,
+               Usage_Type usage,
+               const std::string& hostname,
+               const TLS::Policy& policy) override
+               {
+               if(m_tls_context.has_verify_callback())
+                  {
+                  m_tls_context.get_verify_callback()(cert_chain, ocsp_responses, trusted_roots, usage, hostname, policy);
+                  }
+               else
+                  {
+                  Callbacks::tls_verify_cert_chain(cert_chain, ocsp_responses, trusted_roots, usage, hostname, policy);
+                  }
+               }
+
             boost::beast::flat_buffer& m_receive_buffer;
             boost::beast::flat_buffer& m_send_buffer;
+            Context& m_tls_context;
          };
 
       const boost::asio::mutable_buffer& input_buffer() { return m_input_buffer; }
@@ -598,12 +637,13 @@ class Stream
          {
          if(side == CLIENT)
             {
-            m_native_handle = std::unique_ptr<Client>(new Client(m_core,
-                              *m_context.sessionManager,
-                              *m_context.credentialsManager,
-                              *m_context.policy,
-                              *m_context.randomNumberGenerator,
-                              m_context.serverInfo));
+            m_native_handle = std::unique_ptr<Client>(
+                                 new Client(m_core,
+                                            m_context.m_session_manager,
+                                            m_context.m_credentials_manager,
+                                            m_context.m_policy,
+                                            m_context.m_rng,
+                                            m_context.m_server_info));
             }
          else
             {
@@ -653,7 +693,7 @@ class Stream
             }
          }
 
-      Context                   m_context;
+      Context&                  m_context;
       StreamLayer               m_nextLayer;
 
       boost::beast::flat_buffer m_receive_buffer;
diff --git a/src/lib/utils/compiler.h b/src/lib/utils/compiler.h
index abb2a79f0..c515e0507 100644
--- a/src/lib/utils/compiler.h
+++ b/src/lib/utils/compiler.h
@@ -100,16 +100,13 @@
 
   #if defined(__clang__)
     #define BOTAN_DEPRECATED(msg) __attribute__ ((deprecated))
-    #define BOTAN_DEPRECATED_HEADER(hdr) _Pragma("message \"this header is deprecated\"")
 
   #elif defined(_MSC_VER)
     #define BOTAN_DEPRECATED(msg) __declspec(deprecated(msg))
-    #define BOTAN_DEPRECATED_HEADER(hdr) __pragma("message \"this header is deprecated\"")
 
   #elif defined(__GNUG__)
     /* msg supported since GCC 4.5, earliest we support is 4.8 */
     #define BOTAN_DEPRECATED(msg) __attribute__ ((deprecated(msg)))
-    #define BOTAN_DEPRECATED_HEADER(hdr) _Pragma("GCC warning \"this header is deprecated\"")
   #endif
 
 #endif
@@ -118,10 +115,6 @@
   #define BOTAN_DEPRECATED(msg)
 #endif
 
-#if !defined(BOTAN_DEPRECATED_HEADER)
-  #define BOTAN_DEPRECATED_HEADER(hdr)
-#endif
-
 /*
 * Define BOTAN_NORETURN
 */
diff --git a/src/python/botan2.py b/src/python/botan2.py
index 263bb8078..b0b2856ec 100755
--- a/src/python/botan2.py
+++ b/src/python/botan2.py
@@ -1248,8 +1248,7 @@ class X509Cert(object): # pylint: disable=invalid-name
             raise BotanException("No filename or buf given")
         if filename is not None and buf is not None:
             raise BotanException("Both filename and buf given")
-
-        if filename is not None:
+        elif filename is not None:
             self.__obj = c_void_p(0)
             _DLL.botan_x509_cert_load_file(byref(self.__obj), _ctype_str(filename))
         elif buf is not None:
@@ -1416,9 +1415,6 @@ class MPI(object):
         _DLL.botan_mp_cmp(byref(r), self.__obj, other.handle_())
         return r.value
 
-    def __hash__(self):
-        return hash(self.to_bytes())
-
     def __eq__(self, other):
         return self.cmp(other) == 0
 
diff --git a/src/scripts/build_docs.py b/src/scripts/build_docs.py
index b77319014..2c93b8e05 100755
--- a/src/scripts/build_docs.py
+++ b/src/scripts/build_docs.py
@@ -70,6 +70,7 @@ def copy_files(src_path, dest_dir):
         shutil.copy(src_path, dest_dir)
     else:
         for f in os.listdir(src_path):
+            print(f)
             src_file = os.path.join(src_path, f)
             file_mode = os.stat(src_file).st_mode
             if stat.S_ISREG(file_mode):
diff --git a/src/scripts/comba.py b/src/scripts/comba.py
index 711d1a950..b018b724c 100755
--- a/src/scripts/comba.py
+++ b/src/scripts/comba.py
@@ -80,11 +80,6 @@ def main(args = None):
     if args is None:
         args = sys.argv
 
-    if len(args) <= 1:
-        sizes = [4, 6, 8, 9, 16, 24]
-    else:
-        sizes = map(int, args[1:])
-
     print("""/*
 * Comba Multiplication and Squaring
 *
@@ -99,7 +94,7 @@ def main(args = None):
 namespace Botan {
 """ % (sys.argv[0], datetime.date.today().strftime("%Y-%m-%d")))
 
-    for n in sizes:
+    for n in [4,6,8,9,16,24]:
         print("/*\n* Comba %dx%d Squaring\n*/" % (n, n))
         print("void bigint_comba_sqr%d(word z[%d], const word x[%d])" % (n, 2*n, n))
         print("   {")
diff --git a/src/scripts/dist.py b/src/scripts/dist.py
index a43b2a468..ae894a74d 100755
--- a/src/scripts/dist.py
+++ b/src/scripts/dist.py
@@ -47,9 +47,9 @@ def check_subprocess_results(subproc, name):
         if stderr != '':
             logging.error(stderr)
         raise Exception('Running %s failed' % (name))
-
-    if stderr != '':
-        logging.warning(stderr)
+    else:
+        if stderr != '':
+            logging.warning(stderr)
 
     return raw_stdout
 
@@ -333,6 +333,7 @@ def main(args=None):
             (major, minor, patch) = [int(x) for x in target_version.split('.')]
 
             assert target_version == '%d.%d.%d' % (major, minor, patch)
+            target_version = target_version
         except ValueError as e:
             logging.error('Invalid version number %s' % (target_version))
 
diff --git a/src/scripts/ffi_decls.py b/src/scripts/ffi_decls.py
index b336e61f5..e4dbcefcc 100755
--- a/src/scripts/ffi_decls.py
+++ b/src/scripts/ffi_decls.py
@@ -8,7 +8,7 @@ Automatically generate declarations for the FFI layer
 Botan is released under the Simplified BSD License (see license.txt)
 """
 
-from pycparser import c_ast, parse_file
+from pycparser import c_parser, c_ast, parse_file
 
 ffi_header = 'src/lib/ffi/ffi.h'
 
diff --git a/src/scripts/monty.py b/src/scripts/monty.py
index d3e9b5cb3..e63442824 100755
--- a/src/scripts/monty.py
+++ b/src/scripts/monty.py
@@ -60,11 +60,6 @@ def main(args = None):
     if args is None:
         args = sys.argv
 
-    if len(args) <= 1:
-        sizes = [4, 6, 8, 16, 24, 32]
-    else:
-        sizes = map(int, args[1:])
-
     print("""/*
 * This file was automatically generated by %s on %s
 * All manual changes will be lost. Edit the script instead.
@@ -80,7 +75,7 @@ def main(args = None):
 namespace Botan {
 """ % (sys.argv[0], datetime.date.today().strftime("%Y-%m-%d")))
 
-    for n in sizes:
+    for n in [4, 6, 8, 16, 24, 32]:
         print("void bigint_monty_redc_%d(word z[], const word p[%d], word p_dash, word ws[])" % (n, n))
         print("   {")
 
diff --git a/src/scripts/run_tls_fuzzer.py b/src/scripts/run_tls_fuzzer.py
index b4ee91d24..4754480a6 100755
--- a/src/scripts/run_tls_fuzzer.py
+++ b/src/scripts/run_tls_fuzzer.py
@@ -92,7 +92,6 @@ def main(args = None):
                 else:
                     print("FAIL %s" % (script))
                 sys.stdout.flush()
-    return 0
 
 if __name__ == '__main__':
     sys.exit(main())
diff --git a/src/scripts/tls_suite_info.py b/src/scripts/tls_suite_info.py
index 0a894e0bc..e19c24186 100755
--- a/src/scripts/tls_suite_info.py
+++ b/src/scripts/tls_suite_info.py
@@ -118,6 +118,7 @@ def to_ciphersuite_info(code, name):
     if cipher_algo in ['AES', 'Camellia', 'ARIA']:
         cipher_algo += '-%d' % (cipher_keylen*8)
 
+    modestr = ''
     mode = ''
 
     if cipher[0] == 'CHACHA20' and cipher[1] == 'POLY1305':
@@ -135,9 +136,14 @@ def to_ciphersuite_info(code, name):
 
     if mode == 'CBC':
         return (name, code, sig_algo, kex_algo, cipher_algo, cipher_keylen, mac_algo, mac_keylen[mac_algo], mac_algo, 'CBC_MODE')
+
     elif mode == 'OCB':
         return (name, code, sig_algo, kex_algo, cipher_algo, cipher_keylen, "AEAD", 0, mac_algo, 'AEAD_XOR_12')
+
     else:
+        iv_bytes_from_hs = 4
+        iv_bytes_from_rec = 8
+
         return (name, code, sig_algo, kex_algo, cipher_algo, cipher_keylen, "AEAD", 0, mac_algo, 'AEAD_IMPLICIT_4')
 
 def open_input(args):
@@ -208,6 +214,7 @@ def main(args = None):
     ciphersuite_re = re.compile(' +0x([0-9a-fA-F][0-9a-fA-F]),0x([0-9a-fA-F][0-9a-fA-F]) + TLS_([A-Za-z_0-9]+) ')
 
     suites = {}
+    suite_codes = {}
 
     contents = ''
 
@@ -336,7 +343,5 @@ const std::vector<Ciphersuite>& Ciphersuite::all_known_ciphersuites()
         out.write(suite_info)
         out.close()
 
-    return 0
-
 if __name__ == '__main__':
     sys.exit(main())


Test patch:
diff --git a/src/scripts/test_cli.py b/src/scripts/test_cli.py
index 3c8376ba2..5c976adb0 100755
--- a/src/scripts/test_cli.py
+++ b/src/scripts/test_cli.py
@@ -1052,11 +1052,7 @@ def main(args=None):
 
         start = time.time()
         tmp_dir = tempfile.mkdtemp(prefix='botan_cli_')
-        try:
-            fn(tmp_dir)
-        except Exception as e: # pylint: disable=broad-except
-            logging.error("Test %s threw exception: %s", fn_name, e)
-
+        fn(tmp_dir)
         shutil.rmtree(tmp_dir)
         end = time.time()
         logging.debug("Ran %s in %.02f", fn_name, end-start)
diff --git a/src/tests/test_filters.cpp b/src/tests/test_filters.cpp
index e99329327..33649e56a 100644
--- a/src/tests/test_filters.cpp
+++ b/src/tests/test_filters.cpp
@@ -16,9 +16,15 @@
    #include <botan/pipe.h>
    #include <botan/filters.h>
    #include <botan/data_snk.h>
+   #include <botan/comp_filter.h>
    #include <botan/cipher_filter.h>
 #endif
 
+#if defined(BOTAN_HAS_CODEC_FILTERS)
+   #include <botan/hex_filt.h>
+   #include <botan/b64_filt.h>
+#endif
+
 #if defined(BOTAN_HAS_PIPE_UNIXFD_IO)
    #include <botan/fd_unix.h>
    #include <unistd.h>
diff --git a/src/tests/test_pkcs11_high_level.cpp b/src/tests/test_pkcs11_high_level.cpp
index 077e0240f..c9c34a28b 100644
--- a/src/tests/test_pkcs11_high_level.cpp
+++ b/src/tests/test_pkcs11_high_level.cpp
@@ -831,6 +831,9 @@ Test::Result test_rsa_encrypt_decrypt()
       Botan::PK_Decryptor_EME decryptor(keypair.second, Test::rng(), padding);
       auto decrypted = decryptor.decrypt(encrypted);
 
+      // some token / middlewares do not remove the padding bytes
+      decrypted.resize(plaintext.size());
+
       result.test_eq("RSA PKCS11 encrypt and decrypt: " + padding, decrypted, plaintext);
       };
 
diff --git a/src/tests/test_thread_utils.cpp b/src/tests/test_thread_utils.cpp
index f79877cf6..2374df860 100644
--- a/src/tests/test_thread_utils.cpp
+++ b/src/tests/test_thread_utils.cpp
@@ -25,39 +25,21 @@ Test::Result thread_pool()
    // Using lots of threads since here the works spend most of the time sleeping
    Botan::Thread_Pool pool(16);
 
-   auto sleep_or_throw = [](size_t x) -> size_t {
+   auto sleep_and_return = [](size_t x) -> size_t {
       std::this_thread::sleep_for(std::chrono::milliseconds((x*97)%127));
-
-      if(x % 2 == 0)
-         throw x;
       return x;
       };
 
    std::vector<std::future<size_t>> futures;
    for(size_t i = 0; i != 100; ++i)
       {
-      auto fut = pool.run(sleep_or_throw, i);
+      auto fut = pool.run(sleep_and_return, i);
       futures.push_back(std::move(fut));
       }
 
    for(size_t i = 0; i != futures.size(); ++i)
       {
-      if(i % 2 == 0)
-         {
-         try
-            {
-            futures[i].get();
-            result.test_failure("Expected future to throw");
-            }
-         catch(size_t x)
-            {
-            result.test_eq("Expected thrown value", x, i);
-            }
-         }
-      else
-         {
-         result.test_eq("Expected return value", futures[i].get(), i);
-         }
+      result.test_eq("Expected return value", futures[i].get(), i);
       }
 
    pool.shutdown();
diff --git a/src/tests/unit_asio_stream.cpp b/src/tests/unit_asio_stream.cpp
index ee80cdba4..5fd67cbd4 100644
--- a/src/tests/unit_asio_stream.cpp
+++ b/src/tests/unit_asio_stream.cpp
@@ -62,10 +62,6 @@ class MockChannel
       Botan::TLS::Callbacks& m_callbacks;
       std::size_t m_bytes_till_complete_record;  // number of bytes still to read before tls record is completed
       bool        m_active;
-
-      Botan::TLS::Session_Manager_Noop m_session_manager;
-      Botan::Null_RNG m_rng;
-      Botan::TLS::Default_Policy m_policy;
    };
 
 class ThrowingMockChannel : public MockChannel
@@ -130,6 +126,16 @@ class ThrowingAsioStream : public Botan::TLS::Stream<TestStream, ThrowingMockCha
  */
 class Asio_Stream_Tests final : public Test
    {
+      Botan::Credentials_Manager m_credentials_manager;
+      Botan::Null_RNG m_rng;
+      Botan::TLS::Session_Manager_Noop m_session_manager;
+      Botan::TLS::Default_Policy m_policy;
+
+      Botan::TLS::Context get_context()
+         {
+         return Botan::TLS::Context(m_credentials_manager, m_rng, m_session_manager, m_policy);
+         }
+
       // use memcmp to check if the data in a is a prefix of the data in b
       bool contains(const void* a, const void* b, const std::size_t size) { return memcmp(a, b, size) == 0; }
 
@@ -141,7 +147,7 @@ class Asio_Stream_Tests final : public Test
       void test_sync_handshake(std::vector<Test::Result>& results)
          {
          net::io_context ioc;
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, test_data());
 
          ssl.handshake(Botan::TLS::CLIENT);
@@ -158,7 +164,7 @@ class Asio_Stream_Tests final : public Test
          FailCount  fc{0, net::error::eof};
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, fc);
          ssl.next_layer().connect(remote);
 
@@ -179,7 +185,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          ThrowingAsioStream ssl(ctx, ioc, test_data());
          ssl.next_layer().connect(remote);
 
@@ -197,7 +203,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream      remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, test_data());
          ssl.next_layer().connect(remote);
 
@@ -227,7 +233,7 @@ class Asio_Stream_Tests final : public Test
          FailCount  fc{0, net::error::eof};
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, fc);
          ssl.next_layer().connect(remote);
 
@@ -253,7 +259,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream      remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          ThrowingAsioStream ssl(ctx, ioc, test_data());
          ssl.next_layer().connect(remote);
 
@@ -275,7 +281,7 @@ class Asio_Stream_Tests final : public Test
          {
          net::io_context ioc;
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, test_data());
 
          const std::size_t buf_size = 128;
@@ -296,7 +302,7 @@ class Asio_Stream_Tests final : public Test
          {
          net::io_context ioc;
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, test_data());
          error_code ec;
 
@@ -326,7 +332,7 @@ class Asio_Stream_Tests final : public Test
          FailCount  fc{0, net::error::eof};
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, fc);
          ssl.next_layer().connect(remote);
 
@@ -347,7 +353,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          ThrowingAsioStream ssl(ctx, ioc, test_data());
          ssl.next_layer().connect(remote);
 
@@ -367,7 +373,7 @@ class Asio_Stream_Tests final : public Test
          {
          net::io_context ioc;
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc);
 
          const std::size_t buf_size = 128;
@@ -390,7 +396,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream      remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, test_data());
          uint8_t    data[TEST_DATA_SIZE];
 
@@ -414,7 +420,7 @@ class Asio_Stream_Tests final : public Test
       void test_async_read_some_buffer_sequence(std::vector<Test::Result>& results)
          {
          net::io_context ioc;
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, test_data());
 
          std::vector<net::mutable_buffer> data;
@@ -446,7 +452,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          // fail right away
          FailCount  fc{0, net::error::eof};
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, fc);
          uint8_t    data[TEST_DATA_SIZE];
 
@@ -469,7 +475,7 @@ class Asio_Stream_Tests final : public Test
       void test_async_read_some_throw(std::vector<Test::Result>& results)
          {
          net::io_context ioc;
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          ThrowingAsioStream ssl(ctx, ioc, test_data());
          uint8_t    data[TEST_DATA_SIZE];
 
@@ -494,7 +500,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream      remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc);
          uint8_t    data[TEST_DATA_SIZE];
 
@@ -521,7 +527,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream      remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc);
          ssl.next_layer().connect(remote);
          error_code ec;
@@ -541,7 +547,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream      remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc);
          ssl.next_layer().connect(remote);
          error_code ec;
@@ -581,7 +587,7 @@ class Asio_Stream_Tests final : public Test
          FailCount  fc{0, net::error::eof};
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, fc);
          ssl.next_layer().connect(remote);
 
@@ -601,7 +607,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          ThrowingAsioStream ssl(ctx, ioc);
          ssl.next_layer().connect(remote);
          error_code ec;
@@ -620,7 +626,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream      remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc);
          ssl.next_layer().connect(remote);
 
@@ -644,7 +650,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream      remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc);
          ssl.next_layer().connect(remote);
 
@@ -687,7 +693,7 @@ class Asio_Stream_Tests final : public Test
          FailCount  fc{0, net::error::eof};
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          AsioStream ssl(ctx, ioc, fc);
          ssl.next_layer().connect(remote);
 
@@ -710,7 +716,7 @@ class Asio_Stream_Tests final : public Test
          net::io_context ioc;
          TestStream remote{ioc};
 
-         Botan::TLS::Context ctx;
+         auto ctx = get_context();
          ThrowingAsioStream ssl(ctx, ioc);
          ssl.next_layer().connect(remote);