Repository: randombit/botan
Pull request #4057 (2024-05-13 22:28:41)

Optimize XTS tweak computation
For AES-128 with AES-NI this almost doubles performance. The benefit for slower ciphers is less pronounced.


Patch:
diff --git a/.clang-format b/.clang-format
index 5b8c34b45..5c887c301 100644
--- a/.clang-format
+++ b/.clang-format
@@ -31,11 +31,7 @@ IncludeCategories:
     Priority:        1
     CaseSensitive:   false
 
-AttributeMacros: ['BOTAN_FUNC_ISA',
-                  'BOTAN_FUNC_ISA_INLINE',
-                  'BOTAN_FORCE_INLINE',
-                  'BOTAN_DEPRECATED',
-                  'BOTAN_DEPRECATED_API']
+AttributeMacros: ['BOTAN_FUNC_ISA', 'BOTAN_FUNC_ISA_INLINE', 'BOTAN_FORCE_INLINE']
 
 BinPackArguments: false
 BreakStringLiterals: false
diff --git a/doc/deprecated.rst b/doc/deprecated.rst
index 353d5bed8..498a20dc5 100644
--- a/doc/deprecated.rst
+++ b/doc/deprecated.rst
@@ -46,26 +46,13 @@ in a future major release:
   TLS PSKs for given identities and hosts. Instead, use the dedicated methods in
   ``Credentials_Manager`` and do not override the ``psk()`` method any longer.
 
-Elliptic Curve Deprecations
+Deprecated Functionality
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-A number of features relating to elliptic curves are deprecated.  As a typical
-user you would probably not notice these; their removal would not affect for
-example using ECDSA signatures or TLS, but only applications doing usual things
-such as custom elliptic curve parameters, or creating your own protocol using
-elliptic curve points.
+This section lists cryptographic functionality which will be removed
+in a future major release.
 
-- Support for explicit ECC curve parameters and ImplicitCA encoded parameters in
-  ``EC_Group`` and all users (including X.509 certificates and PKCS#8 private keys).
-
-- Currently it is possible to create an ``EC_Group`` with cofactor > 1. None of
-  the builtin groups have composite order, and in the future it will be
-  impossible to create composite order ``EC_Group``.
-
-- Currently it is possible to create an application specific ``EC_Group``
-  with parameters of effectively arbitrary size. In a future release
-  the maximum allowed bitlength of application provided groups will be
-  at most 521 bits.
+- Kyber 90s mode is deprecated and will be removed.
 
 - Elliptic curve points can be encoded in several different ways.  The
   most common are "compressed" and "uncompressed"; both are widely
@@ -75,68 +62,14 @@ elliptic curve points.
   format is quite obscure and seemingly rarely implemented. Support
   for this encoding will be removed in a future release.
 
-- Botan currently contains support for a number of relatively weak or little
-  used elliptic curves. These are deprecated. These include "secp160k1",
-  "secp160r1", "secp160r2", "secp192k1", "secp224k1", "brainpool160r1",
-  "brainpool192r1", "brainpool224r1", "brainpool320r1", "x962_p192v2",
-  "x962_p192v3", "x962_p239v1", "x962_p239v2", "x962_p239v3"
-
-Deprecated Modules
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-In a number of cases an entire module is deprecated. If the build is configured
-with ``--disable-deprecated`` then these will not be included. In a future major
-release the source for these modules will be entirely removed.
-
-Deprecated modules include
-
-- Kyber mode ``kyber_90s``: Kyber's "90s mode" is not in the NIST ML-KEM
-  standard, and seems to have been never implemented widely.
-
-- Dilithium mode ``dilithium_aes``: Similar situation to Kyber 90s mode.
-
-- Block cipher ``gost_28147``: This cipher was obsolete 20 years ago.
-
-- Block cipher ``noekeon``: An interesting design but not widely implemented.
-
-- Block cipher ``lion``: Similar situation to Noekeon
-
-- Hash function ``gost_3411``: Very weak and questionable hash function.
-
-- Hash function ``streebog``: Incredibly sketchy situation with the sbox
-
-- Hash function ``md4``: It's time to let go
-
-- Signature scheme ``gost_3410``
-
-- McEliece implementation ``mce``. Will be replaced by the proposal Classic
-  McEliece.
-
-- Stream cipher ``shake_cipher``. Note this deprecation affects only
-  using SHAKE as a ``StreamCipher`` not as a hash or XOF
-
-- `cryptobox`: A not unreasonable password based encryption utility
-  but neither modern (these days) nor widely implemented.
-
-- ``dlies``: DLIES is considered quite obsolete
-
-- ``tpm`` (TPM 1.2 only, rarely tested)
-
-Other Deprecated Functionality
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-This section lists other functionality which will be removed in a future major
-release, or where a backwards incompatible change is expected.
-
-- The ``PBKDF`` class is deprecated in favor of ``PasswordHash`` and
-  ``PasswordHashFamily``.
+- Currently it is possible to create an EC_Group with cofactor > 1.
+  None of the builtin groups have composite order, and in the future
+  it will be impossible to create composite order EC_Groups.
 
-- Implicit conversion of a private key into a public key. Currently
-  ``Private_Key`` derives from ``Public_Key`` (and likewise for each of the
-  algorithm specfic classes, eg ``RSA_PrivateKey`` derives from
-  ``RSA_PublicKey``). In a future release these derivations will not exist. To
-  correctly extract the public key from a private key, use the function
-  ``Private_Key::public_key()``
+- Currently it is possible to create an application specific EC_Group
+  with parameters of effectively arbitrary size. In a future release
+  the maximum allowed bitlength of application provided groups will be
+  at most 521 bits.
 
 - Prior to 2.8.0, SM2 algorithms were implemented as two distinct key
   types, one used for encryption and the other for signatures. In 2.8,
@@ -148,16 +81,36 @@ release, or where a backwards incompatible change is expected.
   required that the hash be named as "EMSA1(HASH_NAME)". This is no longer
   required. In a future major release, only "HASH_NAME" will be accepted.
 
-- The ``Buffered_Computation`` base class. In a future release the
-  class will be removed, and all of member functions instead declared
-  directly on ``MessageAuthenticationCode`` and ``HashFunction``. So
-  this only affects you if you are directly referencing
-  ``Botan::Buffered_Computation`` in some way.
+- Block cipher GOST 28147, Noekeon, Lion
+
+- Hash function GOST 34.11-94, Streebog, MD4
+
+- GOST 34.10 signature scheme
+
+- Stream cipher SHAKE (this does not affect SHAKE used as a HashFunction or XOF)
+
+- The utility functions in cryptobox.h
+
+- X9.42 KDF
+
+- The current McEliece implementation (in ``pubkey/mce``) will be
+  replaced by a more modern code-based KEM from the NIST
+  competition. (Probably the "Classic McEliece" submission.)
+
+- DLIES
 
 - GCM support for 64-bit tags
 
+- Weak or rarely used ECC builtin groups including "secp160k1", "secp160r1",
+  "secp160r2", "secp192k1", "secp224k1",
+  "brainpool160r1", "brainpool192r1", "brainpool224r1", "brainpool320r1",
+  "x962_p192v2", "x962_p192v3", "x962_p239v1", "x962_p239v2", "x962_p239v3".
+
 - All built in MODP groups < 2048 bits
 
+- Support for explicit ECC curve parameters and ImplicitCA encoded parameters in
+  EC_Group and all users (including X.509 certificates and PKCS#8 private keys).
+
 - All pre-created DSA groups
 
 - All support for loading, generating or using RSA keys with a public
@@ -166,9 +119,6 @@ release, or where a backwards incompatible change is expected.
 Deprecated Headers
 ^^^^^^^^^^^^^^^^^^^^^^
 
-These headers are currently publically available, but will be made
-internal to the library in the future.
-
   PBKDF headers: ``bcrypt_pbkdf.h``, ``pbkdf2.h``, ``pgp_s2k.h``, ``scrypt.h``,
   and ``argon2.h``: Use the ``PasswordHash`` interface instead.
 
@@ -183,3 +133,15 @@ internal to the library in the future.
   to implement other functionality.
   ``compiler.h``,
   ``uuid.h``,
+
+Other API deprecations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- The ``PBKDF`` class is deprecated in favor of ``PasswordHash`` and
+  ``PasswordHashFamily``.
+
+- The ``Buffered_Computation`` base class. In a future release the
+  class will be removed, and all of member functions instead declared
+  directly on ``MessageAuthenticationCode`` and ``HashFunction``. So
+  this only affects you if you are directly referencing
+  ``Botan::Buffered_Computation`` in some way.
diff --git a/doc/roadmap.rst b/doc/roadmap.rst
index e7b23d411..5cb0e8959 100644
--- a/doc/roadmap.rst
+++ b/doc/roadmap.rst
@@ -6,7 +6,7 @@ Near Term Plans
 ----------------------------------------
 
 Here is an outline for the development plans over the next 12-24 months,
-as of May 2024.
+as of February 2023.
 
 Botan 2
 ---------------
@@ -20,11 +20,11 @@ Botan 3
 The following future work is currently planned for Botan 3:
 
 * BSI Project 481 [https://github.com/randombit/botan/issues/3108]
-  will add several new post-quantum algorithms including LMS signatures
-  and Classic McEliece.
+  will add several new post-quantum algorithms including SPHINCS+
+  signatures, LMS signatures, FrodoKEM, and Classic McEliece.
 
 * New ECC based password authenticated key exchanges, to replace SRP.
-  The most likely candidate algorithms are CPace and OPAQUE.
+  The most likely candidate algorithms are CPace, OPAQUE, or SPAKE2+.
 
 * Adding an implementation of BLS12-381 elliptic curve pairing.
 
@@ -35,7 +35,7 @@ Botan 4
 
 At this time there is no immediate plan for a new major version. When it occurs,
 it will remove functionality currently marked as deprecated, and adopt a new C++
-version. This is unlikely to occur before 2027, at the earliest.
+version. This is unlikely to occur before 2026, at the earliest.
 
 One major change already planned for Botan 4 is that in this release, Public_Key
 will no longer derive from Private_Key. And similarly, specific private keys
diff --git a/doc/security.rst b/doc/security.rst
index d33fc767b..4f5b12952 100644
--- a/doc/security.rst
+++ b/doc/security.rst
@@ -41,7 +41,7 @@ https://keybase.io/jacklloyd and on most PGP keyservers.
 2022
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-* 2022-11-16 (CVE-2022-43705): Failure to correctly check OCSP responder embedded certificate
+* 2022-11-16: Failure to correctly check OCSP responder embedded certificate
 
   OCSP responses for some end entity are either signed by the issuing CA certificate of
   the PKI, or an OCSP responder certificate that the PKI authorized to sign responses in
@@ -60,7 +60,7 @@ https://keybase.io/jacklloyd and on most PGP keyservers.
   could exploit this to impersonate a legitimate TLS server using a compromised
   certificate of that host and get around the revocation check using OCSP stapling.
 
-  Introduced in 1.11.34, fixed in 2.19.3 and 3.0.0
+  Introduced in 1.11.34, fixed in 2.19.3
 
 2020
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/support.rst b/doc/support.rst
index dfa7ac970..87bccf9f4 100644
--- a/doc/support.rst
+++ b/doc/support.rst
@@ -66,7 +66,7 @@ Branch Support Status
 -------------------------
 
 Following table provides the support status for Botan branches, as of
-May 2024.
+July 2023.
 
 "Active development" refers to adding new features and optimizations. At the
 conclusion of the active development phase, only bugfixes are applied.
@@ -79,7 +79,7 @@ Branch         First Release  End of Active Development  End of Life
 Botan 1.8      2008-12-08     2010-08-31                 2016-02-13
 Botan 1.10     2011-06-20     2012-07-10                 2018-12-31
 Botan 2        2017-01-06     2020-11-05                 2024-12-31 or later
-Botan 3        2023-04-11     ?                          2027-12-31 or later
+Botan 3        2023-04-11     ?                          2026-12-31 or later
 ============== ============== ========================== ============
 
 Getting Help
diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt
index 0dee5441b..18371940b 100644
--- a/src/build-data/cc/gcc.txt
+++ b/src/build-data/cc/gcc.txt
@@ -10,10 +10,8 @@ lang_flags "-std=c++20 -D_REENTRANT"
 warning_flags "-Wall -Wextra -Wpedantic -Wstrict-aliasing -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wzero-as-null-pointer-constant -Wnon-virtual-dtor -Wold-style-cast -Wsuggest-override -Wshadow -Wextra-semi"
 
 # Boost headers have 0 as nullptr and non-virtual-dtor issues so we can't werror on them
-# -Wmaybe-uninitialized is buggy https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105937
-# -Wstringop-overread is buggy https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111499
-# -Wfree-nonheap-object is buggy https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115016
-werror_flags "-Werror -Wno-error=strict-overflow -Wno-error=zero-as-null-pointer-constant -Wno-error=non-virtual-dtor -Wno-error=maybe-uninitialized -Wno-error=stringop-overread -Wno-error=free-nonheap-object"
+# Have to disable maybe-uninitialized due to GCC bugs like https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105937
+werror_flags "-Werror -Wno-error=strict-overflow -Wno-error=zero-as-null-pointer-constant -Wno-error=non-virtual-dtor -Wno-error=maybe-uninitialized -Wno-error=stringop-overread"
 
 maintainer_warning_flags "-Wstrict-overflow=5"
 
diff --git a/src/cli/tls_http_server.cpp b/src/cli/tls_http_server.cpp
index cfbc17111..e5c57f22d 100644
--- a/src/cli/tls_http_server.cpp
+++ b/src/cli/tls_http_server.cpp
@@ -63,7 +63,19 @@ using tcp_stream = typename beast::tcp_stream::rebind_executor<
 
 class Logger final {
    private:
-      std::string timestamp() const { return Botan::OS::format_time(std::time(nullptr), "%c"); }
+      auto timestamp() const {
+         const auto t = std::time(nullptr);
+         struct tm tm;
+
+   #if defined(BOTAN_BUILD_COMPILER_IS_MSVC) || defined(BOTAN_TARGET_OS_IS_MINGW) || \
+      defined(BOTAN_TARGET_OS_IS_CYGWIN) || defined(BOTAN_TARGET_OS_IS_WINDOWS)
+         localtime_s(&tm, &t);
+   #else
+         localtime_r(&t, &tm);
+   #endif
+
+         return std::put_time(&tm, "%c");
+      }
 
    public:
       Logger(std::ostream& out, std::ostream& err) : m_out(out), m_err(err) {}
diff --git a/src/lib/asn1/asn1_obj.h b/src/lib/asn1/asn1_obj.h
index 8a5b70bd3..c3264cb4d 100644
--- a/src/lib/asn1/asn1_obj.h
+++ b/src/lib/asn1/asn1_obj.h
@@ -458,11 +458,13 @@ class BOTAN_PUBLIC_API(2, 0) AlgorithmIdentifier final : public ASN1_Object {
 
       const std::vector<uint8_t>& parameters() const { return m_parameters; }
 
-      BOTAN_DEPRECATED("Use AlgorithmIdentifier::oid") const OID& get_oid() const { return m_oid; }
+      BOTAN_DEPRECATED("Use AlgorithmIdentifier::oid")
 
-      BOTAN_DEPRECATED("Use AlgorithmIdentifier::parameters") const std::vector<uint8_t>& get_parameters() const {
-         return m_parameters;
-      }
+      const OID& get_oid() const { return m_oid; }
+
+      BOTAN_DEPRECATED("Use AlgorithmIdentifier::parameters")
+
+      const std::vector<uint8_t>& get_parameters() const { return m_parameters; }
 
       bool parameters_are_null() const;
 
diff --git a/src/lib/asn1/der_enc.h b/src/lib/asn1/der_enc.h
index 12424361e..e5288cc15 100644
--- a/src/lib/asn1/der_enc.h
+++ b/src/lib/asn1/der_enc.h
@@ -57,7 +57,8 @@ class BOTAN_PUBLIC_API(2, 0) DER_Encoder final {
       * contructor of DER_Encoder where the output will be placed. This
       * avoids several unecessary copies.
       */
-      BOTAN_DEPRECATED("Use DER_Encoder(vector) instead") std::vector<uint8_t> get_contents_unlocked();
+      BOTAN_DEPRECATED("Use DER_Encoder(vector) instead")
+      std::vector<uint8_t> get_contents_unlocked();
 
       DER_Encoder& start_cons(ASN1_Type type_tag, ASN1_Class class_tag);
 
diff --git a/src/lib/asn1/oids.h b/src/lib/asn1/oids.h
index 012b999aa..94fa12cbc 100644
--- a/src/lib/asn1/oids.h
+++ b/src/lib/asn1/oids.h
@@ -19,15 +19,23 @@ namespace Botan::OIDS {
 * @param oid the oid to register
 * @param name the name to be associated with the oid
 */
-BOTAN_DEPRECATED("Use OID::register_oid") inline void add_oid(const OID& oid, std::string_view name) {
+BOTAN_DEPRECATED("Use OID::register_oid")
+
+inline void add_oid(const OID& oid, std::string_view name) {
    OID::register_oid(oid, name);
 }
 
-BOTAN_DEPRECATED("Use OID::register_oid") BOTAN_UNSTABLE_API void add_oid2str(const OID& oid, std::string_view name);
+BOTAN_DEPRECATED("Use OID::register_oid")
+BOTAN_UNSTABLE_API
+void add_oid2str(const OID& oid, std::string_view name);
+
+BOTAN_DEPRECATED("Use OID::register_oid")
+BOTAN_UNSTABLE_API
+void add_str2oid(const OID& oid, std::string_view name);
 
-BOTAN_DEPRECATED("Use OID::register_oid") BOTAN_UNSTABLE_API void add_str2oid(const OID& oid, std::string_view name);
+BOTAN_DEPRECATED("Use OID::register_oid")
 
-BOTAN_DEPRECATED("Use OID::register_oid") inline void add_oidstr(const char* oidstr, const char* name) {
+inline void add_oidstr(const char* oidstr, const char* name) {
    OID::register_oid(OID(oidstr), name);
 }
 
@@ -36,7 +44,9 @@ BOTAN_DEPRECATED("Use OID::register_oid") inline void add_oidstr(const char* oid
 * @param oid the OID to look up
 * @return name associated with this OID, or an empty string
 */
-BOTAN_DEPRECATED("Use OID::human_name_or_empty") inline std::string oid2str_or_empty(const OID& oid) {
+BOTAN_DEPRECATED("Use OID::human_name_or_empty")
+
+inline std::string oid2str_or_empty(const OID& oid) {
    return oid.human_name_or_empty();
 }
 
@@ -46,11 +56,15 @@ BOTAN_DEPRECATED("Use OID::human_name_or_empty") inline std::string oid2str_or_e
 * @param name the name to resolve
 * @return OID associated with the specified name
 */
-BOTAN_DEPRECATED("Use OID::from_name") inline OID str2oid_or_empty(std::string_view name) {
+BOTAN_DEPRECATED("Use OID::from_name")
+
+inline OID str2oid_or_empty(std::string_view name) {
    return OID::from_name(name).value_or(OID());
 }
 
-BOTAN_DEPRECATED("Use OID::human_name_or_empty") inline std::string oid2str_or_throw(const OID& oid) {
+BOTAN_DEPRECATED("Use OID::human_name_or_empty")
+
+inline std::string oid2str_or_throw(const OID& oid) {
    std::string s = oid.human_name_or_empty();
    if(s.empty()) {
       throw Lookup_Error("No name associated with OID " + oid.to_string());
@@ -58,11 +72,15 @@ BOTAN_DEPRECATED("Use OID::human_name_or_empty") inline std::string oid2str_or_t
    return s;
 }
 
-BOTAN_DEPRECATED("Use OID::human_name_or_empty") inline std::string lookup(const OID& oid) {
+BOTAN_DEPRECATED("Use OID::human_name_or_empty")
+
+inline std::string lookup(const OID& oid) {
    return oid.human_name_or_empty();
 }
 
-BOTAN_DEPRECATED("Use OID::from_name") inline OID lookup(std::string_view name) {
+BOTAN_DEPRECATED("Use OID::from_name")
+
+inline OID lookup(std::string_view name) {
    return OID::from_name(name).value_or(OID());
 }
 
diff --git a/src/lib/base/symkey.h b/src/lib/base/symkey.h
index cf466a6dc..f5c5abba3 100644
--- a/src/lib/base/symkey.h
+++ b/src/lib/base/symkey.h
@@ -64,7 +64,8 @@ class BOTAN_PUBLIC_API(2, 0) OctetString final {
       * some very old or weird system which requires DES and also which do not
       * automatically ignore the parity bits.
       */
-      BOTAN_DEPRECATED("Why would you need to do this") void set_odd_parity();
+      BOTAN_DEPRECATED("Why would you need to do this")
+      void set_odd_parity();
 
       /**
       * Create a new OctetString
diff --git a/src/lib/block/gost_28147/info.txt b/src/lib/block/gost_28147/info.txt
index 38b3722b9..8c55a9b6e 100644
--- a/src/lib/block/gost_28147/info.txt
+++ b/src/lib/block/gost_28147/info.txt
@@ -4,5 +4,4 @@ GOST_28147_89 -> 20131128
 
 <module_info>
 name -> "GOST 28147-89"
-lifecycle -> "Deprecated"
 </module_info>
diff --git a/src/lib/block/lion/info.txt b/src/lib/block/lion/info.txt
index 6068545c5..1d5891bca 100644
--- a/src/lib/block/lion/info.txt
+++ b/src/lib/block/lion/info.txt
@@ -4,7 +4,6 @@ LION -> 20131128
 
 <module_info>
 name -> "Lion"
-lifecycle -> "Deprecated"
 </module_info>
 
 <requires>
diff --git a/src/lib/block/noekeon/info.txt b/src/lib/block/noekeon/info.txt
index 212e2f17f..2d5e03bda 100644
--- a/src/lib/block/noekeon/info.txt
+++ b/src/lib/block/noekeon/info.txt
@@ -4,5 +4,4 @@ NOEKEON -> 20131128
 
 <module_info>
 name -> "Noekeon"
-lifecycle -> "Deprecated"
 </module_info>
diff --git a/src/lib/filters/pipe.h b/src/lib/filters/pipe.h
index 1b2270d7a..738f7f5cc 100644
--- a/src/lib/filters/pipe.h
+++ b/src/lib/filters/pipe.h
@@ -266,7 +266,8 @@ class BOTAN_PUBLIC_API(2, 0) Pipe final : public DataSource {
       * message is processed.
       * @param filt the new filter to insert
       */
-      BOTAN_DEPRECATED("Runtime modification of Pipe deprecated") void prepend(Filter* filt);
+      BOTAN_DEPRECATED("Runtime modification of Pipe deprecated")
+      void prepend(Filter* filt);
 
       /**
       * Insert a new filter at the back of the pipe
@@ -275,17 +276,20 @@ class BOTAN_PUBLIC_API(2, 0) Pipe final : public DataSource {
       * message is processed.
       * @param filt the new filter to insert
       */
-      BOTAN_DEPRECATED("Runtime modification of Pipe deprecated") void append(Filter* filt);
+      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();
+      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();
+      BOTAN_DEPRECATED("Runtime modification of Pipe deprecated")
+      void reset();
 
       /**
       * Append a new filter onto the filter sequence. This may only be
diff --git a/src/lib/hash/md4/info.txt b/src/lib/hash/md4/info.txt
index dda5f008e..55a697b19 100644
--- a/src/lib/hash/md4/info.txt
+++ b/src/lib/hash/md4/info.txt
@@ -4,7 +4,6 @@ MD4 -> 20131128
 
 <module_info>
 name -> "MD4"
-lifecycle -> "Deprecated"
 </module_info>
 
 <requires>
diff --git a/src/lib/hash/streebog/info.txt b/src/lib/hash/streebog/info.txt
index 747de8b60..45640c544 100644
--- a/src/lib/hash/streebog/info.txt
+++ b/src/lib/hash/streebog/info.txt
@@ -4,5 +4,4 @@ STREEBOG -> 20170623
 
 <module_info>
 name -> "Streebog"
-lifecycle -> "Deprecated"
 </module_info>
diff --git a/src/lib/kdf/prf_x942/info.txt b/src/lib/kdf/prf_x942/info.txt
index c02d7d759..6bafcda17 100644
--- a/src/lib/kdf/prf_x942/info.txt
+++ b/src/lib/kdf/prf_x942/info.txt
@@ -4,7 +4,6 @@ X942_PRF -> 20131128
 
 <module_info>
 name -> "PRF X9.42"
-lifecycle -> "Deprecated"
 </module_info>
 
 <requires>
diff --git a/src/lib/math/numbertheory/reducer.h b/src/lib/math/numbertheory/reducer.h
index 7ea742b99..f42fbc845 100644
--- a/src/lib/math/numbertheory/reducer.h
+++ b/src/lib/math/numbertheory/reducer.h
@@ -10,8 +10,6 @@
 
 #include <botan/numthry.h>
 
-BOTAN_FUTURE_INTERNAL_HEADER(reducer.h)
-
 namespace Botan {
 
 /**
diff --git a/src/lib/misc/cryptobox/cryptobox.h b/src/lib/misc/cryptobox/cryptobox.h
index de25df2ed..a0a2c8e7d 100644
--- a/src/lib/misc/cryptobox/cryptobox.h
+++ b/src/lib/misc/cryptobox/cryptobox.h
@@ -30,8 +30,8 @@ namespace CryptoBox {
 * @param rng a ref to a random number generator, such as AutoSeeded_RNG
 */
 BOTAN_DEPRECATED("CryptoBox interface is deprecated")
-BOTAN_PUBLIC_API(2, 0) std::string
-   encrypt(const uint8_t input[], size_t input_len, std::string_view passphrase, RandomNumberGenerator& rng);
+BOTAN_PUBLIC_API(2, 0)
+std::string encrypt(const uint8_t input[], size_t input_len, std::string_view passphrase, RandomNumberGenerator& rng);
 
 /**
 * Decrypt a message encrypted with CryptoBox::encrypt
@@ -40,9 +40,8 @@ BOTAN_PUBLIC_API(2, 0) std::string
 * @param passphrase the passphrase used to encrypt the message
 */
 BOTAN_DEPRECATED("CryptoBox interface is deprecated")
-BOTAN_PUBLIC_API(2, 3) secure_vector<uint8_t> decrypt_bin(const uint8_t input[],
-                                                          size_t input_len,
-                                                          std::string_view passphrase);
+BOTAN_PUBLIC_API(2, 3)
+secure_vector<uint8_t> decrypt_bin(const uint8_t input[], size_t input_len, std::string_view passphrase);
 
 /**
 * Decrypt a message encrypted with CryptoBox::encrypt
@@ -50,7 +49,8 @@ BOTAN_PUBLIC_API(2, 3) secure_vector<uint8_t> decrypt_bin(const uint8_t input[],
 * @param passphrase the passphrase used to encrypt the message
 */
 BOTAN_DEPRECATED("CryptoBox interface is deprecated")
-BOTAN_PUBLIC_API(2, 3) secure_vector<uint8_t> decrypt_bin(std::string_view input, std::string_view passphrase);
+BOTAN_PUBLIC_API(2, 3)
+secure_vector<uint8_t> decrypt_bin(std::string_view input, std::string_view passphrase);
 
 /**
 * Decrypt a message encrypted with CryptoBox::encrypt
@@ -59,7 +59,8 @@ BOTAN_PUBLIC_API(2, 3) secure_vector<uint8_t> decrypt_bin(std::string_view input
 * @param passphrase the passphrase used to encrypt the message
 */
 BOTAN_DEPRECATED("CryptoBox interface is deprecated")
-BOTAN_PUBLIC_API(2, 0) std::string decrypt(const uint8_t input[], size_t input_len, std::string_view passphrase);
+BOTAN_PUBLIC_API(2, 0)
+std::string decrypt(const uint8_t input[], size_t input_len, std::string_view passphrase);
 
 /**
 * Decrypt a message encrypted with CryptoBox::encrypt
@@ -67,7 +68,8 @@ BOTAN_PUBLIC_API(2, 0) std::string decrypt(const uint8_t input[], size_t input_l
 * @param passphrase the passphrase used to encrypt the message
 */
 BOTAN_DEPRECATED("CryptoBox interface is deprecated")
-BOTAN_PUBLIC_API(2, 0) std::string decrypt(std::string_view input, std::string_view passphrase);
+BOTAN_PUBLIC_API(2, 0)
+std::string decrypt(std::string_view input, std::string_view passphrase);
 
 }  // namespace CryptoBox
 
diff --git a/src/lib/modes/aead/aead.h b/src/lib/modes/aead/aead.h
index 1f252f74a..6c0ebbed5 100644
--- a/src/lib/modes/aead/aead.h
+++ b/src/lib/modes/aead/aead.h
@@ -121,7 +121,9 @@ class BOTAN_PUBLIC_API(2, 0) AEAD_Mode : public Cipher_Mode {
       *
       * @param ad the associated data
       */
-      BOTAN_DEPRECATED("Use set_associated_data") void set_ad(std::span<const uint8_t> ad) { set_associated_data(ad); }
+      BOTAN_DEPRECATED("Please use set_associated_data")
+
+      void set_ad(std::span<const uint8_t> ad) { set_associated_data(ad); }
 
       /**
       * @return default AEAD nonce size (a commonly supported value among AEAD
@@ -137,7 +139,9 @@ class BOTAN_PUBLIC_API(2, 0) AEAD_Mode : public Cipher_Mode {
 * @param name AEAD name
 * @param direction Cipher_Dir::Encryption or Cipher_Dir::Decryption
 */
-BOTAN_DEPRECATED("Use AEAD_Mode::create") inline AEAD_Mode* get_aead(std::string_view name, Cipher_Dir direction) {
+BOTAN_DEPRECATED("Use AEAD_Mode::create")
+
+inline AEAD_Mode* get_aead(std::string_view name, Cipher_Dir direction) {
    return AEAD_Mode::create(name, direction, "").release();
 }
 
diff --git a/src/lib/modes/cipher_mode.h b/src/lib/modes/cipher_mode.h
index 5fe8f7ca1..3f88bb1d5 100644
--- a/src/lib/modes/cipher_mode.h
+++ b/src/lib/modes/cipher_mode.h
@@ -241,6 +241,7 @@ class BOTAN_PUBLIC_API(2, 0) Cipher_Mode : public SymmetricAlgorithm {
 * @param provider provider implementation to choose
 */
 BOTAN_DEPRECATED("Use Cipher_Mode::create")
+
 inline Cipher_Mode* get_cipher_mode(std::string_view algo_spec, Cipher_Dir direction, std::string_view provider = "") {
    return Cipher_Mode::create(algo_spec, direction, provider).release();
 }
diff --git a/src/lib/modes/xts/xts.cpp b/src/lib/modes/xts/xts.cpp
index 886b7c4a1..ce4c6e98c 100644
--- a/src/lib/modes/xts/xts.cpp
+++ b/src/lib/modes/xts/xts.cpp
@@ -100,9 +100,7 @@ void XTS_Mode::update_tweak(size_t which) {
 
    const size_t blocks_in_tweak = tweak_blocks();
 
-   for(size_t i = 1; i < blocks_in_tweak; ++i) {
-      poly_double_n_le(&m_tweak[i * BS], &m_tweak[(i - 1) * BS], BS);
-   }
+   xts_update_tweak_block(m_tweak.data(), BS, blocks_in_tweak);
 }
 
 size_t XTS_Encryption::output_length(size_t input_length) const {
diff --git a/src/lib/pbkdf/pbkdf.h b/src/lib/pbkdf/pbkdf.h
index 7d6db6b6a..f830a4857 100644
--- a/src/lib/pbkdf/pbkdf.h
+++ b/src/lib/pbkdf/pbkdf.h
@@ -37,7 +37,6 @@ class BOTAN_PUBLIC_API(2, 0) PBKDF {
       * @param provider provider implementation to choose
       * @return a null pointer if the algo/provider combination cannot be found
       */
-      BOTAN_DEPRECATED("Use PasswordHashFamily + PasswordHash")
       static std::unique_ptr<PBKDF> create(std::string_view algo_spec, std::string_view provider = "");
 
       /**
@@ -45,7 +44,6 @@ class BOTAN_PUBLIC_API(2, 0) PBKDF {
       * algo/provider combination cannot be found. If provider is
       * empty then best available is chosen.
       */
-      BOTAN_DEPRECATED("Use PasswordHashFamily + PasswordHash")
       static std::unique_ptr<PBKDF> create_or_throw(std::string_view algo_spec, std::string_view provider = "");
 
       /**
@@ -240,11 +238,14 @@ typedef PBKDF S2K;
 * @return pointer to newly allocated object of that type
 */
 BOTAN_DEPRECATED("Use PBKDF::create_or_throw")
+
 inline PBKDF* get_pbkdf(std::string_view algo_spec, std::string_view provider = "") {
    return PBKDF::create_or_throw(algo_spec, provider).release();
 }
 
-BOTAN_DEPRECATED("Use PBKDF::create_or_throw") inline PBKDF* get_s2k(std::string_view algo_spec) {
+BOTAN_DEPRECATED("Use PBKDF::create_or_throw")
+
+inline PBKDF* get_s2k(std::string_view algo_spec) {
    return PBKDF::create_or_throw(algo_spec).release();
 }
 
diff --git a/src/lib/pbkdf/pbkdf2/pbkdf2.h b/src/lib/pbkdf/pbkdf2/pbkdf2.h
index 9c5993533..a0f217499 100644
--- a/src/lib/pbkdf/pbkdf2/pbkdf2.h
+++ b/src/lib/pbkdf/pbkdf2/pbkdf2.h
@@ -116,13 +116,13 @@ class BOTAN_PUBLIC_API(2, 0) PKCS5_PBKDF2 final : public PBKDF {
       * @param mac_fn the MAC object to use as PRF
       */
       BOTAN_DEPRECATED("Use version taking unique_ptr")
+
       explicit PKCS5_PBKDF2(MessageAuthenticationCode* mac_fn) : m_mac(mac_fn) {}
 
       /**
       * Create a PKCS #5 instance using the specified message auth code
       * @param mac_fn the MAC object to use as PRF
       */
-      BOTAN_DEPRECATED("Use PasswordHashFamily + PasswordHash")
       explicit PKCS5_PBKDF2(std::unique_ptr<MessageAuthenticationCode> mac_fn) : m_mac(std::move(mac_fn)) {}
 
    private:
diff --git a/src/lib/pbkdf/scrypt/scrypt.h b/src/lib/pbkdf/scrypt/scrypt.h
index aa4fac152..2e8c3d074 100644
--- a/src/lib/pbkdf/scrypt/scrypt.h
+++ b/src/lib/pbkdf/scrypt/scrypt.h
@@ -83,6 +83,7 @@ class BOTAN_PUBLIC_API(2, 8) Scrypt_Family final : public PasswordHashFamily {
 * Scrypt uses approximately (p + N + 1) * 128 * r bytes of memory
 */
 BOTAN_DEPRECATED("Use PasswordHashFamily+PasswordHash")
+
 inline void scrypt(uint8_t output[],
                    size_t output_len,
                    const char* password,
@@ -115,6 +116,7 @@ inline void scrypt(uint8_t output[],
 * Scrypt uses approximately (p + N + 1) * 128 * r bytes of memory
 */
 BOTAN_DEPRECATED("Use PasswordHashFamily+PasswordHash")
+
 inline void scrypt(uint8_t output[],
                    size_t output_len,
                    std::string_view password,
diff --git a/src/lib/prov/tpm/info.txt b/src/lib/prov/tpm/info.txt
index 692e641a5..0218e2237 100644
--- a/src/lib/prov/tpm/info.txt
+++ b/src/lib/prov/tpm/info.txt
@@ -5,7 +5,6 @@ TPM -> 20151126
 <module_info>
 name -> "TPM"
 brief -> "Wrappers and Utilites to interact with TPMs"
-lifecycle -> "Deprecated"
 </module_info>
 
 load_on vendor
diff --git a/src/lib/prov/tpm/tpm.h b/src/lib/prov/tpm/tpm.h
index dfcdc4fc6..00088c9f0 100644
--- a/src/lib/prov/tpm/tpm.h
+++ b/src/lib/prov/tpm/tpm.h
@@ -16,8 +16,6 @@
 #include <botan/uuid.h>
 #include <functional>
 
-BOTAN_DEPRECATED_HEADER("tpm.h")
-
 //TODO remove this
 #include <tss/tspi.h>
 
@@ -48,7 +46,7 @@ class BOTAN_PUBLIC_API(2, 0) TPM_Context final {
       */
       typedef std::function<std::string(std::string)> pin_cb;
 
-      BOTAN_DEPRECATED("TPM support is deprecated see #3877") TPM_Context(pin_cb cb, const char* srk_password);
+      TPM_Context(pin_cb cb, const char* srk_password);
 
       ~TPM_Context();
 
diff --git a/src/lib/pubkey/dilithium/dilithium_aes/info.txt b/src/lib/pubkey/dilithium/dilithium_aes/info.txt
index 8720bb625..13920cb7a 100644
--- a/src/lib/pubkey/dilithium/dilithium_aes/info.txt
+++ b/src/lib/pubkey/dilithium/dilithium_aes/info.txt
@@ -4,7 +4,6 @@ DILITHIUM_AES -> 20221018
 
 <module_info>
 name -> "Dilithium (AES)"
-lifecycle -> "Deprecated"
 </module_info>
 
 <requires>
diff --git a/src/lib/pubkey/dlies/dlies.h b/src/lib/pubkey/dlies/dlies.h
index 840a69d05..4ed7f6542 100644
--- a/src/lib/pubkey/dlies/dlies.h
+++ b/src/lib/pubkey/dlies/dlies.h
@@ -15,8 +15,6 @@
 #include <botan/mac.h>
 #include <botan/pubkey.h>
 
-BOTAN_DEPRECATED_HEADER("dlies.h")
-
 namespace Botan {
 
 /**
diff --git a/src/lib/pubkey/dlies/info.txt b/src/lib/pubkey/dlies/info.txt
index 6797c3ffa..26742b31e 100644
--- a/src/lib/pubkey/dlies/info.txt
+++ b/src/lib/pubkey/dlies/info.txt
@@ -4,7 +4,6 @@ DLIES -> 20160713
 
 <module_info>
 name -> "DLIES"
-lifecycle -> "Deprecated"
 </module_info>
 
 <requires>
diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp
index d8db6bae7..0393cb2a8 100644
--- a/src/lib/pubkey/ec_group/ec_group.cpp
+++ b/src/lib/pubkey/ec_group/ec_group.cpp
@@ -399,10 +399,6 @@ EC_Group::EC_Group() = default;
 
 EC_Group::~EC_Group() = default;
 
-EC_Group::EC_Group(const EC_Group&) = default;
-
-EC_Group& EC_Group::operator=(const EC_Group&) = default;
-
 EC_Group::EC_Group(const OID& domain_oid) {
    this->m_data = ec_group_data().lookup(domain_oid);
    if(!this->m_data) {
diff --git a/src/lib/pubkey/ec_group/ec_group.h b/src/lib/pubkey/ec_group/ec_group.h
index 472690536..b5d71c622 100644
--- a/src/lib/pubkey/ec_group/ec_group.h
+++ b/src/lib/pubkey/ec_group/ec_group.h
@@ -102,10 +102,10 @@ class BOTAN_PUBLIC_API(2, 0) EC_Group final {
 
       ~EC_Group();
 
-      EC_Group(const EC_Group&);
+      EC_Group(const EC_Group&) = default;
       EC_Group(EC_Group&&) = default;
 
-      EC_Group& operator=(const EC_Group&);
+      EC_Group& operator=(const EC_Group&) = default;
       EC_Group& operator=(EC_Group&&) = default;
 
       /**
diff --git a/src/lib/pubkey/ed25519/ed25519.h b/src/lib/pubkey/ed25519/ed25519.h
index 2174baf8a..9e8929034 100644
--- a/src/lib/pubkey/ed25519/ed25519.h
+++ b/src/lib/pubkey/ed25519/ed25519.h
@@ -82,9 +82,9 @@ class BOTAN_PUBLIC_API(2, 2) Ed25519_PrivateKey final : public Ed25519_PublicKey
       */
       explicit Ed25519_PrivateKey(const secure_vector<uint8_t>& secret_key);
 
-      BOTAN_DEPRECATED("Use raw_private_key_bits") const secure_vector<uint8_t>& get_private_key() const {
-         return m_private;
-      }
+      BOTAN_DEPRECATED("Use raw_private_key_bits")
+
+      const secure_vector<uint8_t>& get_private_key() const { return m_private; }
 
       secure_vector<uint8_t> raw_private_key_bits() const override { return m_private; }
 
diff --git a/src/lib/pubkey/gost_3410/info.txt b/src/lib/pubkey/gost_3410/info.txt
index a82d0608b..60cfbba12 100644
--- a/src/lib/pubkey/gost_3410/info.txt
+++ b/src/lib/pubkey/gost_3410/info.txt
@@ -5,7 +5,6 @@ GOST_34_10_2012 -> 20190801
 
 <module_info>
 name -> "GOST 34.10-2001"
-lifecycle -> "Deprecated"
 </module_info>
 
 <requires>
diff --git a/src/lib/pubkey/kyber/kyber_round3/kyber_90s/info.txt b/src/lib/pubkey/kyber/kyber_round3/kyber_90s/info.txt
index 37106602a..ccad2eb5e 100644
--- a/src/lib/pubkey/kyber/kyber_round3/kyber_90s/info.txt
+++ b/src/lib/pubkey/kyber/kyber_round3/kyber_90s/info.txt
@@ -4,7 +4,6 @@ KYBER_90S -> 20220107
 
 <module_info>
 name -> "Kyber 90s"
-lifecycle -> "Deprecated"
 </module_info>
 
 <requires>
diff --git a/src/lib/pubkey/mce/info.txt b/src/lib/pubkey/mce/info.txt
index e79a5a0bb..9cf9ddf53 100644
--- a/src/lib/pubkey/mce/info.txt
+++ b/src/lib/pubkey/mce/info.txt
@@ -4,7 +4,6 @@ MCELIECE -> 20150922
 
 <module_info>
 name -> "McEliece"
-lifecycle -> "Deprecated"
 </module_info>
 
 <header:public>
diff --git a/src/lib/pubkey/mce/mceliece.h b/src/lib/pubkey/mce/mceliece.h
index 59fcd1aa2..5b7e9c0bd 100644
--- a/src/lib/pubkey/mce/mceliece.h
+++ b/src/lib/pubkey/mce/mceliece.h
@@ -14,8 +14,6 @@
 
 #include <botan/pk_keys.h>
 
-BOTAN_DEPRECATED_HEADER("mceliece.h")
-
 namespace Botan {
 
 typedef uint16_t gf2m;
diff --git a/src/lib/pubkey/pubkey.h b/src/lib/pubkey/pubkey.h
index d7b551a97..5f6d68022 100644
--- a/src/lib/pubkey/pubkey.h
+++ b/src/lib/pubkey/pubkey.h
@@ -599,6 +599,7 @@ class BOTAN_PUBLIC_API(2, 0) PK_KEM_Encryptor final {
       * @param provider the provider to use
       */
       BOTAN_DEPRECATED("Use constructor that does not take RNG")
+
       PK_KEM_Encryptor(const Public_Key& key,
                        RandomNumberGenerator& rng,
                        std::string_view kem_param = "",
@@ -694,6 +695,7 @@ class BOTAN_PUBLIC_API(2, 0) PK_KEM_Encryptor final {
                    std::span<const uint8_t> salt = {});
 
       BOTAN_DEPRECATED("use overload with salt as std::span<>")
+
       void encrypt(secure_vector<uint8_t>& out_encapsulated_key,
                    secure_vector<uint8_t>& out_shared_key,
                    size_t desired_shared_key_len,
@@ -704,6 +706,7 @@ class BOTAN_PUBLIC_API(2, 0) PK_KEM_Encryptor final {
       }
 
       BOTAN_DEPRECATED("use overload where rng comes after the out-paramters")
+
       void encrypt(secure_vector<uint8_t>& out_encapsulated_key,
                    secure_vector<uint8_t>& out_shared_key,
                    size_t desired_shared_key_len,
diff --git a/src/lib/pubkey/x25519/x25519.h b/src/lib/pubkey/x25519/x25519.h
index dcaa912b5..0f11dc0b2 100644
--- a/src/lib/pubkey/x25519/x25519.h
+++ b/src/lib/pubkey/x25519/x25519.h
@@ -81,7 +81,9 @@ class BOTAN_PUBLIC_API(2, 0) X25519_PrivateKey final : public X25519_PublicKey,
 
       secure_vector<uint8_t> raw_private_key_bits() const override { return m_private; }
 
-      BOTAN_DEPRECATED("Use raw_private_key_bits") const secure_vector<uint8_t>& get_x() const { return m_private; }
+      BOTAN_DEPRECATED("Use raw_private_key_bits")
+
+      const secure_vector<uint8_t>& get_x() const { return m_private; }
 
       secure_vector<uint8_t> private_key_bits() const override;
 
diff --git a/src/lib/pubkey/xmss/xmss.h b/src/lib/pubkey/xmss/xmss.h
index 3e598af13..36f98f1ba 100644
--- a/src/lib/pubkey/xmss/xmss.h
+++ b/src/lib/pubkey/xmss/xmss.h
@@ -221,12 +221,14 @@ class BOTAN_PUBLIC_API(2, 0) XMSS_PrivateKey final : public virtual XMSS_PublicK
        *
        * @return Index of the last unused leaf.
        **/
-      BOTAN_DEPRECATED("Use remaining_operations()") size_t unused_leaf_index() const;
+      BOTAN_DEPRECATED("Use remaining_operations()")
+      size_t unused_leaf_index() const;
 
       /**
        * Retrieves the number of remaining signatures for this private key.
        */
-      BOTAN_DEPRECATED("Use remaining_operations()") size_t remaining_signatures() const;
+      BOTAN_DEPRECATED("Use remaining_operations()")
+      size_t remaining_signatures() const;
 
       std::optional<uint64_t> remaining_operations() const override;
 
diff --git a/src/lib/stream/shake_cipher/info.txt b/src/lib/stream/shake_cipher/info.txt
index c57d48b8c..7bfeed590 100644
--- a/src/lib/stream/shake_cipher/info.txt
+++ b/src/lib/stream/shake_cipher/info.txt
@@ -5,7 +5,6 @@ SHAKE_CIPHER -> 20161018
 <module_info>
 name -> "SHAKE-based XOFs"
 brief -> "SHAKE-128 and SHAKE-256 XOF presented as stream ciphers"
-lifecycle -> "Deprecated"
 </module_info>
 
 <requires>
diff --git a/src/lib/tls/tls13/tls_cipher_state.cpp b/src/lib/tls/tls13/tls_cipher_state.cpp
index 340b4e890..8ab5d17d5 100644
--- a/src/lib/tls/tls13/tls_cipher_state.cpp
+++ b/src/lib/tls/tls13/tls_cipher_state.cpp
@@ -217,7 +217,6 @@ std::vector<uint8_t> current_nonce(const uint64_t seq_no, const secure_vector<ui
    //        client_write_iv or server_write_iv (depending on the role).
    std::vector<uint8_t> nonce(NONCE_LENGTH);
    store_be(seq_no, nonce.data() + (NONCE_LENGTH - sizeof(seq_no)));
-   BOTAN_ASSERT_EQUAL(iv.size(), NONCE_LENGTH, "Invalid TLS 1.3 nonce length");
    xor_buf(nonce, iv.data(), iv.size());
    return nonce;
 }
diff --git a/src/lib/tls/tls13/tls_extensions_key_share.cpp b/src/lib/tls/tls13/tls_extensions_key_share.cpp
index 9a21eb2f8..95598fba8 100644
--- a/src/lib/tls/tls13/tls_extensions_key_share.cpp
+++ b/src/lib/tls/tls13/tls_extensions_key_share.cpp
@@ -87,7 +87,7 @@ class Key_Share_Entry {
 
       std::vector<uint8_t> serialize() const {
          std::vector<uint8_t> result;
-         result.reserve(m_key_exchange.size() + 4);
+         result.reserve(m_key_exchange.size() + 2);
 
          const uint16_t named_curve_id = m_group.wire_code();
          result.push_back(get_byte<0>(named_curve_id));
diff --git a/src/lib/tls/tls13/tls_psk_identity_13.h b/src/lib/tls/tls13/tls_psk_identity_13.h
index c4fd74055..84bad1055 100644
--- a/src/lib/tls/tls13/tls_psk_identity_13.h
+++ b/src/lib/tls/tls13/tls_psk_identity_13.h
@@ -69,7 +69,8 @@ class BOTAN_PUBLIC_API(3, 1) PskIdentity {
  * re-name it to the more generic term "PskIdentity" to better reflect its dual
  * use case for resumption and externally provided PSKs.
  */
-BOTAN_DEPRECATED("Use PskIdentity") typedef PskIdentity Ticket;
+BOTAN_DEPRECATED("Use PskIdentity")
+typedef PskIdentity Ticket;
 
 }  // namespace Botan::TLS
 
diff --git a/src/lib/utils/loadstor.h b/src/lib/utils/loadstor.h
index 8340dd8ae..5e8ab5f7c 100644
--- a/src/lib/utils/loadstor.h
+++ b/src/lib/utils/loadstor.h
@@ -711,7 +711,7 @@ inline constexpr auto store_be(ParamTs&&... params) {
 namespace detail {
 
 template <Endianness endianness, unsigned_integralish T>
-size_t copy_out_any_word_aligned_portion(std::span<uint8_t>& out, std::span<const T>& in) {
+inline size_t copy_out_any_word_aligned_portion(std::span<uint8_t>& out, std::span<const T>& in) {
    const size_t full_words = out.size() / sizeof(T);
    const size_t full_word_bytes = full_words * sizeof(T);
    const size_t remaining_bytes = out.size() - full_word_bytes;
@@ -732,7 +732,7 @@ size_t copy_out_any_word_aligned_portion(std::span<uint8_t>& out, std::span<cons
  * byte order.
  */
 template <ranges::spanable_range InR>
-void copy_out_be(std::span<uint8_t> out, InR&& in) {
+inline void copy_out_be(std::span<uint8_t> out, InR&& in) {
    using T = std::ranges::range_value_t<InR>;
    std::span<const T> in_s{in};
    const auto remaining_bytes = detail::copy_out_any_word_aligned_portion<detail::Endianness::Big>(out, in_s);
@@ -748,7 +748,7 @@ void copy_out_be(std::span<uint8_t> out, InR&& in) {
  * byte order.
  */
 template <ranges::spanable_range InR>
-void copy_out_le(std::span<uint8_t> out, InR&& in) {
+inline void copy_out_le(std::span<uint8_t> out, InR&& in) {
    using T = std::ranges::range_value_t<InR>;
    std::span<const T> in_s{in};
    const auto remaining_bytes = detail::copy_out_any_word_aligned_portion<detail::Endianness::Little>(out, in_s);
diff --git a/src/lib/utils/mem_ops.h b/src/lib/utils/mem_ops.h
index fca6bbc87..9a4e8e7c5 100644
--- a/src/lib/utils/mem_ops.h
+++ b/src/lib/utils/mem_ops.h
@@ -263,7 +263,9 @@ inline constexpr To typecast_copy(const uint8_t src[]) noexcept {
 * @param n the number of Ts pointed to by ptr
 * @param val the value to set each byte to
 */
-BOTAN_DEPRECATED("This function is deprecated") inline constexpr void set_mem(uint8_t* ptr, size_t n, uint8_t val) {
+BOTAN_DEPRECATED("This function is deprecated")
+
+inline constexpr void set_mem(uint8_t* ptr, size_t n, uint8_t val) {
    if(n > 0) {
       std::memset(ptr, val, n);
    }
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp
index 45bea5daa..6b37e32f1 100644
--- a/src/lib/utils/os_utils.cpp
+++ b/src/lib/utils/os_utils.cpp
@@ -15,8 +15,6 @@
 #include <algorithm>
 #include <chrono>
 #include <cstdlib>
-#include <iomanip>
-#include <sstream>
 
 #if defined(BOTAN_TARGET_OS_HAS_EXPLICIT_BZERO)
    #include <string.h>
@@ -327,26 +325,6 @@ uint64_t OS::get_system_timestamp_ns() {
    return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
 }
 
-std::string OS::format_time(time_t time, const std::string& format) {
-   std::tm tm;
-
-#if defined(BOTAN_TARGET_OS_HAS_WIN32)
-   localtime_s(&tm, &time);
-#elif defined(BOTAN_TARGET_OS_HAS_POSIX1)
-   localtime_r(&time, &tm);
-#else
-   if(auto tmp = std::localtime(&time)) {
-      tm = *tmp;
-   } else {
-      throw Encoding_Error("Could not convert time_t to localtime");
-   }
-#endif
-
-   std::ostringstream oss;
-   oss << std::put_time(&tm, format.c_str());
-   return oss.str();
-}
-
 size_t OS::system_page_size() {
    const size_t default_page_size = 4096;
 
diff --git a/src/lib/utils/os_utils.h b/src/lib/utils/os_utils.h
index 465e7974f..cda39f10a 100644
--- a/src/lib/utils/os_utils.h
+++ b/src/lib/utils/os_utils.h
@@ -84,14 +84,6 @@ uint64_t BOTAN_TEST_API get_high_resolution_clock();
 */
 uint64_t BOTAN_TEST_API get_system_timestamp_ns();
 
-/**
-* Format a time
-*
-* Converts the time_t to a local time representation,
-* then invokes std::put_time with the specified format.
-*/
-std::string BOTAN_TEST_API format_time(time_t time, const std::string& format);
-
 /**
 * @return maximum amount of memory (in bytes) Botan could/should
 * hyptothetically allocate for the memory poool. Reads environment
diff --git a/src/lib/utils/poly_dbl/poly_dbl.cpp b/src/lib/utils/poly_dbl/poly_dbl.cpp
index e1d1a68e9..e7568c294 100644
--- a/src/lib/utils/poly_dbl/poly_dbl.cpp
+++ b/src/lib/utils/poly_dbl/poly_dbl.cpp
@@ -109,4 +109,28 @@ void poly_double_n_le(uint8_t out[], const uint8_t in[], size_t n) {
    }
 }
 
+void xts_update_tweak_block(uint8_t tweak[], size_t BS, size_t blocks_in_tweak) {
+   if(BS == 16) {
+      constexpr size_t LIMBS = 2;
+
+      uint64_t W[LIMBS];
+      load_le(W, &tweak[0], LIMBS);
+
+      const uint64_t POLY = static_cast<uint64_t>(MinWeightPolynomial::P128);
+
+      for(size_t i = 1; i < blocks_in_tweak; ++i) {
+         const uint64_t carry = POLY * (W[1] >> 63);
+         W[1] = (W[1] << 1) ^ (W[0] >> 63);
+         W[0] = (W[0] << 1) ^ carry;
+         copy_out_le(std::span(&tweak[i * BS], 2 * 8), W);
+      }
+   } else {
+      for(size_t i = 1; i < blocks_in_tweak; ++i) {
+         const uint8_t* prev = &tweak[(i - 1) * BS];
+         uint8_t* cur = &tweak[i * BS];
+         poly_double_n_le(cur, prev, BS);
+      }
+   }
+}
+
 }  // namespace Botan
diff --git a/src/lib/utils/poly_dbl/poly_dbl.h b/src/lib/utils/poly_dbl/poly_dbl.h
index e475b76aa..30bbee9ae 100644
--- a/src/lib/utils/poly_dbl/poly_dbl.h
+++ b/src/lib/utils/poly_dbl/poly_dbl.h
@@ -32,6 +32,11 @@ inline void poly_double_n(uint8_t buf[], size_t n) {
 */
 void BOTAN_TEST_API poly_double_n_le(uint8_t out[], const uint8_t in[], size_t n);
 
+/*
+* Tweak block update step for XTS
+*/
+void xts_update_tweak_block(uint8_t tweak[], size_t BS, size_t n);
+
 }  // namespace Botan
 
 #endif
diff --git a/src/lib/utils/uuid/uuid.h b/src/lib/utils/uuid/uuid.h
index b1fb0334f..ff57e8ed5 100644
--- a/src/lib/utils/uuid/uuid.h
+++ b/src/lib/utils/uuid/uuid.h
@@ -12,7 +12,7 @@
 #include <string>
 #include <vector>
 
-BOTAN_DEPRECATED_HEADER("uuid.h")
+//BOTAN_FUTURE_INTERNAL_HEADER(uuid.h)
 
 namespace Botan {
 
diff --git a/src/lib/x509/pkix_types.h b/src/lib/x509/pkix_types.h
index c1407f1fc..e2d1444f9 100644
--- a/src/lib/x509/pkix_types.h
+++ b/src/lib/x509/pkix_types.h
@@ -184,9 +184,11 @@ class BOTAN_PUBLIC_API(2, 0) AlternativeName final : public ASN1_Object {
       BOTAN_DEPRECATED("Use AlternativeName::add_other_name")
       void add_othername(const OID& oid, std::string_view value, ASN1_Type type);
 
-      BOTAN_DEPRECATED("Use AlternativeName::othernames") std::multimap<OID, ASN1_String> get_othernames() const;
+      BOTAN_DEPRECATED("Use AlternativeName::othernames")
+      std::multimap<OID, ASN1_String> get_othernames() const;
 
-      BOTAN_DEPRECATED("Use AlternativeName::directory_names") X509_DN dn() const;
+      BOTAN_DEPRECATED("Use AlternativeName::directory_names")
+      X509_DN dn() const;
 
       BOTAN_DEPRECATED("Use plain constructor plus add_{uri,dns,email,ip}")
       AlternativeName(std::string_view email_addr,
diff --git a/src/lib/x509/x509_crl.h b/src/lib/x509/x509_crl.h
index c0578365a..fb66cdf00 100644
--- a/src/lib/x509/x509_crl.h
+++ b/src/lib/x509/x509_crl.h
@@ -137,7 +137,8 @@ class BOTAN_PUBLIC_API(2, 0) X509_CRL final : public X509_Object {
       /**
       * Get the CRL's issuing distribution point
       */
-      BOTAN_DEPRECATED("Use issuing_distribution_points") std::string crl_issuing_distribution_point() const;
+      BOTAN_DEPRECATED("Use issuing_distribution_points")
+      std::string crl_issuing_distribution_point() const;
 
       /**
       * Get the CRL's issuing distribution points
diff --git a/src/lib/x509/x509cert.h b/src/lib/x509/x509cert.h
index 4b68579a8..05448b055 100644
--- a/src/lib/x509/x509cert.h
+++ b/src/lib/x509/x509cert.h
@@ -55,7 +55,8 @@ class BOTAN_PUBLIC_API(2, 0) X509_Certificate : public X509_Object {
       *
       * @return subject public key of this certificate
       */
-      BOTAN_DEPRECATED("Use subject_public_key") std::unique_ptr<Public_Key> load_subject_public_key() const;
+      BOTAN_DEPRECATED("Use subject_public_key")
+      std::unique_ptr<Public_Key> load_subject_public_key() const;
 
       /**
       * Get the public key associated with this certificate. This includes the
@@ -333,7 +334,8 @@ class BOTAN_PUBLIC_API(2, 0) X509_Certificate : public X509_Object {
       /**
       * Return the CRL distribution point, or empty if not set
       */
-      BOTAN_DEPRECATED("Use crl_distribution_points") std::string crl_distribution_point() const;
+      BOTAN_DEPRECATED("Use crl_distribution_points")
+      std::string crl_distribution_point() const;
 
       /**
       * Return the CRL distribution points, or empty if not set
diff --git a/src/lib/x509/x509path.cpp b/src/lib/x509/x509path.cpp
index a55d8e69a..9ea0f6fb1 100644
--- a/src/lib/x509/x509path.cpp
+++ b/src/lib/x509/x509path.cpp
@@ -48,68 +48,6 @@ CertificatePathStatusCodes PKIX::check_chain(const std::vector<X509_Certificate>
 
    CertificatePathStatusCodes cert_status(cert_path.size());
 
-   // Before anything else verify the entire chain of signatures
-   for(size_t i = 0; i != cert_path.size(); ++i) {
-      std::set<Certificate_Status_Code>& status = cert_status.at(i);
-
-      const bool at_self_signed_root = (i == cert_path.size() - 1);
-
-      const X509_Certificate& subject = cert_path[i];
-      const X509_Certificate& issuer = cert_path[at_self_signed_root ? (i) : (i + 1)];
-
-      // Check the signature algorithm is known
-      if(!subject.signature_algorithm().oid().registered_oid()) {
-         status.insert(Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN);
-      } else {
-         std::unique_ptr<Public_Key> issuer_key;
-         try {
-            issuer_key = issuer.subject_public_key();
-         } catch(...) {
-            status.insert(Certificate_Status_Code::CERT_PUBKEY_INVALID);
-         }
-
-         if(issuer_key) {
-            if(issuer_key->estimated_strength() < restrictions.minimum_key_strength()) {
-               status.insert(Certificate_Status_Code::SIGNATURE_METHOD_TOO_WEAK);
-            }
-
-            const auto sig_status = subject.verify_signature(*issuer_key);
-
-            if(sig_status.first != Certificate_Status_Code::VERIFIED) {
-               status.insert(sig_status.first);
-            } else {
-               // Signature is valid, check if hash used was acceptable
-               const std::string hash_used_for_signature = sig_status.second;
-               BOTAN_ASSERT_NOMSG(!hash_used_for_signature.empty());
-               const auto& trusted_hashes = restrictions.trusted_hashes();
-
-               // Ignore untrusted hashes on self-signed roots
-               if(!trusted_hashes.empty() && !at_self_signed_root) {
-                  if(!trusted_hashes.contains(hash_used_for_signature)) {
-                     status.insert(Certificate_Status_Code::UNTRUSTED_HASH);
-                  }
-               }
-            }
-         }
-      }
-   }
-
-   // If any of the signatures were invalid, return immediately; we know the
-   // chain is invalid and signature failure is always considered the most
-   // critical result. This does mean other problems in the certificate (eg
-   // expired) will not be reported, but we'd have to assume any such data is
-   // anyway arbitrary considering we couldn't verify the signature chain
-
-   for(size_t i = 0; i != cert_path.size(); ++i) {
-      for(auto status : cert_status.at(i)) {
-         // This ignores errors relating to the key or hash being weak since
-         // these are somewhat advisory
-         if(static_cast<uint32_t>(status) >= 5000) {
-            return cert_status;
-         }
-      }
-   }
-
    if(!hostname.empty() && !cert_path[0].matches_dns_name(hostname)) {
       cert_status[0].insert(Certificate_Status_Code::CERT_NAME_NOMATCH);
    }
@@ -145,7 +83,6 @@ CertificatePathStatusCodes PKIX::check_chain(const std::vector<X509_Certificate>
          status.insert(Certificate_Status_Code::CHAIN_LACKS_TRUST_ROOT);
       }
 
-      // This should never happen; it indicates a bug in path building
       if(subject.issuer_dn() != issuer.subject_dn()) {
          status.insert(Certificate_Status_Code::CHAIN_NAME_MISMATCH);
       }
@@ -190,6 +127,39 @@ CertificatePathStatusCodes PKIX::check_chain(const std::vector<X509_Certificate>
          status.insert(Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER);
       }
 
+      auto issuer_key = issuer.subject_public_key();
+
+      // Check the signature algorithm is known
+      if(!subject.signature_algorithm().oid().registered_oid()) {
+         status.insert(Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN);
+      } else {
+         // only perform the following checks if the signature algorithm is known
+         if(!issuer_key) {
+            status.insert(Certificate_Status_Code::CERT_PUBKEY_INVALID);
+         } else {
+            const auto sig_status = subject.verify_signature(*issuer_key);
+
+            if(sig_status.first == Certificate_Status_Code::VERIFIED) {
+               const std::string hash_used_for_signature = sig_status.second;
+               BOTAN_ASSERT_NOMSG(!hash_used_for_signature.empty());
+               const auto& trusted_hashes = restrictions.trusted_hashes();
+
+               // Ignore untrusted hashes on self-signed roots
+               if(!trusted_hashes.empty() && !at_self_signed_root) {
+                  if(!trusted_hashes.contains(hash_used_for_signature)) {
+                     status.insert(Certificate_Status_Code::UNTRUSTED_HASH);
+                  }
+               }
+            } else {
+               status.insert(sig_status.first);
+            }
+
+            if(issuer_key->estimated_strength() < restrictions.minimum_key_strength()) {
+               status.insert(Certificate_Status_Code::SIGNATURE_METHOD_TOO_WEAK);
+            }
+         }
+      }
+
       // Check cert extensions
 
       if(subject.x509_version() == 1) {


Test patch:
diff --git a/src/tests/runner/test_xml_reporter.cpp b/src/tests/runner/test_xml_reporter.cpp
index 8a69e4b57..9810b40e7 100644
--- a/src/tests/runner/test_xml_reporter.cpp
+++ b/src/tests/runner/test_xml_reporter.cpp
@@ -12,11 +12,11 @@
    #include <botan/build.h>
    #include <botan/version.h>
    #include <botan/internal/loadstor.h>
-   #include <botan/internal/os_utils.h>
 
    #include <iomanip>
    #include <numeric>
    #include <sstream>
+   #include <time.h>
 
 namespace Botan_Tests {
 
@@ -60,10 +60,24 @@ std::string full_compiler_name_string() {
    #endif
 }
 
+std::tm* localtime(const time_t* timer, std::tm* buffer) {
+   #if defined(BOTAN_BUILD_COMPILER_IS_MSVC) || defined(BOTAN_TARGET_OS_IS_MINGW) || \
+      defined(BOTAN_TARGET_OS_IS_CYGWIN) || defined(BOTAN_TARGET_OS_IS_WINDOWS)
+   localtime_s(buffer, timer);
+   #else
+   localtime_r(timer, buffer);
+   #endif
+   return buffer;
+}
+
 /// formats a given time point in ISO 8601 format (with time zone)
 std::string format(const std::chrono::system_clock::time_point& tp) {
    auto seconds_since_epoch = std::chrono::system_clock::to_time_t(tp);
-   return Botan::OS::format_time(seconds_since_epoch, "%FT%T%z");
+
+   std::ostringstream out;
+   std::tm buffer{};
+   out << std::put_time(localtime(&seconds_since_epoch, &buffer), "%FT%T%z");
+   return out.str();
 }
 
 std::string format(const std::chrono::nanoseconds& dur) {