Repository: randombit/botan
Pull request #3229 (2023-01-27 23:04:31)

More raw pointer cleanups
GH #2677

codecov-commenter: # [Codecov](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd) Report
Base: **88.13**% // Head: **88.15**% // Increases project coverage by **`+0.01%`** :tada:
> Coverage data is based on head [(`7d11114`)](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd) compared to base [(`00d6064`)](https://codecov.io/gh/randombit/botan/commit/00d6064906ec28298ca8a6d4d5eaf679810472c2?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd).
> Patch coverage: 86.00% of modified lines in pull request are covered.

:mega: This organization is not using Codecov’s [GitHub App Integration](https://github.com/apps/codecov). We recommend you install it so Codecov can continue to function properly for your repositories. [Learn more](https://about.codecov.io/blog/codecov-is-updating-its-github-integration/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd)

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #3229      +/-   ##
==========================================
+ Coverage   88.13%   88.15%   +0.01%     
==========================================
  Files         609      609              
  Lines       68212    68197      -15     
  Branches     6800     6798       -2     
==========================================
- Hits        60120    60118       -2     
+ Misses       5251     5247       -4     
+ Partials     2841     2832       -9     
```


| [Impacted Files](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd) | Coverage Δ | |
|---|---|---|
| [src/lib/pbkdf/pbkdf2/pbkdf2.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wYmtkZi9wYmtkZjIvcGJrZGYyLmNwcA==) | `78.04% <0.00%> (ø)` | |
| [src/lib/pk\_pad/emsa1/emsa1.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wa19wYWQvZW1zYTEvZW1zYTEuY3Bw) | `84.44% <0.00%> (ø)` | |
| [src/lib/pk\_pad/emsa\_pkcs1/emsa\_pkcs1.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wa19wYWQvZW1zYV9wa2NzMS9lbXNhX3BrY3MxLmNwcA==) | `77.41% <0.00%> (ø)` | |
| [src/lib/pbkdf/pgp\_s2k/pgp\_s2k.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wYmtkZi9wZ3BfczJrL3BncF9zMmsuY3Bw) | `85.71% <71.42%> (ø)` | |
| [src/cli/x509.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2NsaS94NTA5LmNwcA==) | `73.78% <100.00%> (+0.72%)` | :arrow_up: |
| [src/lib/passhash/passhash9/passhash9.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wYXNzaGFzaC9wYXNzaGFzaDkvcGFzc2hhc2g5LmNwcA==) | `90.74% <100.00%> (ø)` | |
| [src/lib/pbkdf/pbkdf.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wYmtkZi9wYmtkZi5jcHA=) | `33.33% <100.00%> (ø)` | |
| [src/lib/pbkdf/pwdhash.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wYmtkZi9wd2RoYXNoLmNwcA==) | `48.57% <100.00%> (ø)` | |
| [src/lib/pk\_pad/emsa\_pssr/pssr.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wa19wYWQvZW1zYV9wc3NyL3Bzc3IuY3Bw) | `81.60% <100.00%> (ø)` | |
| [src/lib/pubkey/dlies/dlies.cpp](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd#diff-c3JjL2xpYi9wdWJrZXkvZGxpZXMvZGxpZXMuY3Bw) | `83.14% <100.00%> (ø)` | |
| ... and [13 more](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/randombit/botan/pull/3229?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jack+Lloyd).

randombit: I've seen that a few times in the past and kept forgetting to chase it down or open up an issue. But it seems to be flaky and needs to be resolved. #3232 

Patch:
diff --git a/doc/migration_guide.rst b/doc/migration_guide.rst
index b51cebbf2..1056403ef 100644
--- a/doc/migration_guide.rst
+++ b/doc/migration_guide.rst
@@ -3,6 +3,10 @@ Botan 2.x to 3.x Migration
 
 This is a guide on migrating applications from Botan 2.x to 3.0.
 
+This guide attempts to be, but is not, complete. If you run into a problem while
+converting code that does not seem to be described here, please open an issue on
+Github.
+
 Headers
 --------
 
@@ -167,3 +171,15 @@ PKCS11_Request::subject_public_key and X509_Certificate::subject_public_key
 -----------------------------------------------------------------------------
 
 These functions now return a unique_ptr
+
+choose_sig_format removed
+---------------------------
+
+The freestanding functions choose_sig_format have been removed.
+Use X509_Object::choose_sig_format
+
+DLIES Constructors
+--------------------
+
+Previously the constructors to the DLIES classes took raw pointers,
+and retained ownership of them. They now consume std::unique_ptrs
diff --git a/src/cli/x509.cpp b/src/cli/x509.cpp
index 1f701fcc1..f70c5536c 100644
--- a/src/cli/x509.cpp
+++ b/src/cli/x509.cpp
@@ -124,11 +124,7 @@ class Sign_Cert final : public Command
             throw CLI_Error("Failed to load key from " + key_file);
             }
 
-         std::map<std::string, std::string> options;
-         if(emsa.empty() == false)
-            options["padding"] = emsa;
-
-         Botan::X509_CA ca(ca_cert, *key, options, hash, rng());
+         Botan::X509_CA ca(ca_cert, *key, hash, emsa, rng());
 
          Botan::PKCS10_Request req(get_arg("pkcs10_req"));
 
diff --git a/src/lib/compression/compression.h b/src/lib/compression/compression.h
index 4a8ec1675..d213d3ab7 100644
--- a/src/lib/compression/compression.h
+++ b/src/lib/compression/compression.h
@@ -131,11 +131,13 @@ class BOTAN_PUBLIC_API(2,0) Decompression_Algorithm
       virtual ~Decompression_Algorithm() = default;
    };
 
+BOTAN_DEPRECATED("Use Compression_Algorithm::create")
 inline Compression_Algorithm* make_compressor(const std::string& type)
    {
    return Compression_Algorithm::create(type).release();
    }
 
+BOTAN_DEPRECATED("Use Decompression_Algorithm::create")
 inline Decompression_Algorithm* make_decompressor(const std::string& type)
    {
    return Decompression_Algorithm::create(type).release();
diff --git a/src/lib/kdf/kdf.h b/src/lib/kdf/kdf.h
index 5eefd0336..f3f21e0b2 100644
--- a/src/lib/kdf/kdf.h
+++ b/src/lib/kdf/kdf.h
@@ -198,6 +198,7 @@ class BOTAN_PUBLIC_API(2,0) KDF
 *
 * Prefer KDF::create
 */
+BOTAN_DEPRECATED("Use KDF::create")
 inline KDF* get_kdf(const std::string& algo_spec)
    {
    auto kdf = KDF::create(algo_spec);
diff --git a/src/lib/passhash/passhash9/passhash9.cpp b/src/lib/passhash/passhash9/passhash9.cpp
index 3681b7e1d..de9570bf3 100644
--- a/src/lib/passhash/passhash9/passhash9.cpp
+++ b/src/lib/passhash/passhash9/passhash9.cpp
@@ -55,7 +55,7 @@ std::string generate_passhash9(const std::string& pass,
                              std::to_string(alg_id) +
                              " is not defined");
 
-   PKCS5_PBKDF2 kdf(prf.release()); // takes ownership of pointer
+   PKCS5_PBKDF2 kdf(std::move(prf));
 
    secure_vector<uint8_t> salt(SALT_BYTES);
    rng.randomize(salt.data(), salt.size());
@@ -117,7 +117,7 @@ bool check_passhash9(const std::string& pass, const std::string& hash)
    if(!pbkdf_prf)
       return false; // unknown algorithm, reject
 
-   PKCS5_PBKDF2 kdf(pbkdf_prf.release()); // takes ownership of pointer
+   PKCS5_PBKDF2 kdf(std::move(pbkdf_prf));
 
    secure_vector<uint8_t> cmp = kdf.derive_key(
       PASSHASH9_PBKDF_OUTPUT_LEN,
diff --git a/src/lib/pbkdf/pbkdf.cpp b/src/lib/pbkdf/pbkdf.cpp
index 5c668d6b8..f4f9ac512 100644
--- a/src/lib/pbkdf/pbkdf.cpp
+++ b/src/lib/pbkdf/pbkdf.cpp
@@ -32,10 +32,10 @@ std::unique_ptr<PBKDF> PBKDF::create(const std::string& algo_spec,
       if(provider.empty() || provider == "base")
          {
          if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
-            return std::make_unique<PKCS5_PBKDF2>(mac.release());
+            return std::make_unique<PKCS5_PBKDF2>(std::move(mac));
 
          if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
-            return std::make_unique<PKCS5_PBKDF2>(mac.release());
+            return std::make_unique<PKCS5_PBKDF2>(std::move(mac));
          }
 
       return nullptr;
@@ -46,7 +46,7 @@ std::unique_ptr<PBKDF> PBKDF::create(const std::string& algo_spec,
    if(req.algo_name() == "OpenPGP-S2K" && req.arg_count() == 1)
       {
       if(auto hash = HashFunction::create(req.arg(0)))
-         return std::make_unique<OpenPGP_S2K>(hash.release());
+         return std::make_unique<OpenPGP_S2K>(std::move(hash));
       }
 #endif
 
diff --git a/src/lib/pbkdf/pbkdf2/pbkdf2.cpp b/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
index f3982d006..8e2b56f65 100644
--- a/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
+++ b/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
@@ -176,7 +176,7 @@ std::string PKCS5_PBKDF2::name() const
 
 std::unique_ptr<PBKDF> PKCS5_PBKDF2::new_object() const
    {
-   return std::make_unique<PKCS5_PBKDF2>(m_mac->clone());
+   return std::make_unique<PKCS5_PBKDF2>(m_mac->new_object());
    }
 
 // PasswordHash interface
diff --git a/src/lib/pbkdf/pbkdf2/pbkdf2.h b/src/lib/pbkdf/pbkdf2/pbkdf2.h
index e1d3e6f0d..d56e53db7 100644
--- a/src/lib/pbkdf/pbkdf2/pbkdf2.h
+++ b/src/lib/pbkdf/pbkdf2/pbkdf2.h
@@ -64,7 +64,8 @@ class BOTAN_PUBLIC_API(2,8) PBKDF2 final : public PasswordHash
 class BOTAN_PUBLIC_API(2,8) PBKDF2_Family final : public PasswordHashFamily
    {
    public:
-      PBKDF2_Family(MessageAuthenticationCode* prf) : m_prf(prf) {}
+      PBKDF2_Family(std::unique_ptr<MessageAuthenticationCode> prf) :
+         m_prf(std::move(prf)) {}
 
       std::string name() const override;
 
@@ -107,7 +108,15 @@ class BOTAN_PUBLIC_API(2,0) PKCS5_PBKDF2 final : public PBKDF
       * Create a PKCS #5 instance using the specified message auth code
       * @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
+      */
+      explicit PKCS5_PBKDF2(std::unique_ptr<MessageAuthenticationCode> mac_fn) :
+         m_mac(std::move(mac_fn)) {}
    private:
       std::unique_ptr<MessageAuthenticationCode> m_mac;
    };
diff --git a/src/lib/pbkdf/pgp_s2k/pgp_s2k.cpp b/src/lib/pbkdf/pgp_s2k/pgp_s2k.cpp
index f4dff816b..ae0b476cb 100644
--- a/src/lib/pbkdf/pgp_s2k/pgp_s2k.cpp
+++ b/src/lib/pbkdf/pgp_s2k/pgp_s2k.cpp
@@ -81,7 +81,7 @@ size_t OpenPGP_S2K::pbkdf(uint8_t output_buf[], size_t output_len,
 
    if(iterations == 0)
       {
-      RFC4880_S2K_Family s2k_params(m_hash->clone());
+      RFC4880_S2K_Family s2k_params(m_hash->new_object());
       iterations = s2k_params.tune(output_len, msec, 0)->iterations();
       }
 
@@ -119,26 +119,26 @@ std::unique_ptr<PasswordHash> RFC4880_S2K_Family::tune(size_t output_len, std::c
    const double bytes_to_be_hashed = (hash_bytes_per_second * (desired_nsec / 1000000000.0)) / blocks_required;
    const size_t iterations = RFC4880_round_iterations(static_cast<size_t>(bytes_to_be_hashed));
 
-   return std::make_unique<RFC4880_S2K>(m_hash->clone(), iterations);
+   return std::make_unique<RFC4880_S2K>(m_hash->new_object(), iterations);
    }
 
 std::unique_ptr<PasswordHash> RFC4880_S2K_Family::from_params(size_t iter, size_t /*i2*/, size_t /*i3*/) const
    {
-   return std::make_unique<RFC4880_S2K>(m_hash->clone(), iter);
+   return std::make_unique<RFC4880_S2K>(m_hash->new_object(), iter);
    }
 
 std::unique_ptr<PasswordHash> RFC4880_S2K_Family::default_params() const
    {
-   return std::make_unique<RFC4880_S2K>(m_hash->clone(), 50331648);
+   return std::make_unique<RFC4880_S2K>(m_hash->new_object(), 50331648);
    }
 
 std::unique_ptr<PasswordHash> RFC4880_S2K_Family::from_iterations(size_t iter) const
    {
-   return std::make_unique<RFC4880_S2K>(m_hash->clone(), iter);
+   return std::make_unique<RFC4880_S2K>(m_hash->new_object(), iter);
    }
 
-RFC4880_S2K::RFC4880_S2K(HashFunction* hash, size_t iterations) :
-   m_hash(hash),
+RFC4880_S2K::RFC4880_S2K(std::unique_ptr<HashFunction> hash, size_t iterations) :
+   m_hash(std::move(hash)),
    m_iterations(iterations)
    {
    }
diff --git a/src/lib/pbkdf/pgp_s2k/pgp_s2k.h b/src/lib/pbkdf/pgp_s2k/pgp_s2k.h
index 2f8fadf41..73fb1f449 100644
--- a/src/lib/pbkdf/pgp_s2k/pgp_s2k.h
+++ b/src/lib/pbkdf/pgp_s2k/pgp_s2k.h
@@ -41,7 +41,7 @@ class BOTAN_PUBLIC_API(2,2) OpenPGP_S2K final : public PBKDF
       /**
       * @param hash the hash function to use
       */
-      explicit OpenPGP_S2K(HashFunction* hash) : m_hash(hash) {}
+      explicit OpenPGP_S2K(std::unique_ptr<HashFunction> hash) : m_hash(std::move(hash)) {}
 
       std::string name() const override
          {
@@ -50,7 +50,7 @@ class BOTAN_PUBLIC_API(2,2) OpenPGP_S2K final : public PBKDF
 
       std::unique_ptr<PBKDF> new_object() const override
          {
-         return std::make_unique<OpenPGP_S2K>(m_hash->clone());
+         return std::make_unique<OpenPGP_S2K>(m_hash->new_object());
          }
 
       size_t pbkdf(uint8_t output_buf[], size_t output_len,
@@ -94,7 +94,7 @@ class BOTAN_PUBLIC_API(2,8) RFC4880_S2K final : public PasswordHash
       * @param hash the hash function to use
       * @param iterations is rounded due to PGP formatting
       */
-      RFC4880_S2K(HashFunction* hash, size_t iterations);
+      RFC4880_S2K(std::unique_ptr<HashFunction> hash, size_t iterations);
 
       std::string to_string() const override;
 
@@ -112,7 +112,7 @@ class BOTAN_PUBLIC_API(2,8) RFC4880_S2K final : public PasswordHash
 class BOTAN_PUBLIC_API(2,8) RFC4880_S2K_Family final : public PasswordHashFamily
    {
    public:
-      RFC4880_S2K_Family(HashFunction* hash) : m_hash(hash) {}
+      RFC4880_S2K_Family(std::unique_ptr<HashFunction> hash) : m_hash(std::move(hash)) {}
 
       std::string name() const override;
 
diff --git a/src/lib/pbkdf/pwdhash.cpp b/src/lib/pbkdf/pwdhash.cpp
index a7911547e..948b21f66 100644
--- a/src/lib/pbkdf/pwdhash.cpp
+++ b/src/lib/pbkdf/pwdhash.cpp
@@ -57,10 +57,10 @@ std::unique_ptr<PasswordHashFamily> PasswordHashFamily::create(const std::string
       if(provider.empty() || provider == "base")
          {
          if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
-            return std::make_unique<PBKDF2_Family>(mac.release());
+            return std::make_unique<PBKDF2_Family>(std::move(mac));
 
          if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
-            return std::make_unique<PBKDF2_Family>(mac.release());
+            return std::make_unique<PBKDF2_Family>(std::move(mac));
          }
 
       return nullptr;
@@ -101,7 +101,7 @@ std::unique_ptr<PasswordHashFamily> PasswordHashFamily::create(const std::string
       {
       if(auto hash = HashFunction::create(req.arg(0)))
          {
-         return std::make_unique<RFC4880_S2K_Family>(hash.release());
+         return std::make_unique<RFC4880_S2K_Family>(std::move(hash));
          }
       }
 #endif
diff --git a/src/lib/pk_pad/emsa1/emsa1.cpp b/src/lib/pk_pad/emsa1/emsa1.cpp
index f3780883a..f8ec16870 100644
--- a/src/lib/pk_pad/emsa1/emsa1.cpp
+++ b/src/lib/pk_pad/emsa1/emsa1.cpp
@@ -101,8 +101,9 @@ AlgorithmIdentifier EMSA1::config_for_x509(const std::string& algo_name,
                                            const std::string& cert_hash_name) const
    {
    if(cert_hash_name != m_hash->name())
-      throw Invalid_Argument("Hash function from opts and hash_fn argument"
-         " need to be identical");
+      throw Invalid_Argument("EMSA1: Cert hash " + cert_hash_name +
+                             " incompatible with specified hash " + m_hash->name());
+
    // check that the signature algorithm and the padding scheme fit
    if(!sig_algo_and_pad_ok(algo_name, "EMSA1"))
       {
diff --git a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp
index ef9a36e0a..741339504 100644
--- a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp
+++ b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp
@@ -87,8 +87,9 @@ AlgorithmIdentifier EMSA_PKCS1v15::config_for_x509(const std::string& algo_name,
                                                    const std::string& cert_hash_name) const
    {
    if(cert_hash_name != m_hash->name())
-      throw Invalid_Argument("Hash function from opts and hash_fn argument"
-         " need to be identical");
+      throw Invalid_Argument("PKCS1v15: Cert hash " + cert_hash_name +
+                             " incompatible with specified hash " + m_hash->name());
+
    // check that the signature algorithm and the padding scheme fit
    if(!sig_algo_and_pad_ok(algo_name, "EMSA3"))
       {
diff --git a/src/lib/pk_pad/emsa_pssr/pssr.cpp b/src/lib/pk_pad/emsa_pssr/pssr.cpp
index 37233cb1c..4a9c2d36b 100644
--- a/src/lib/pk_pad/emsa_pssr/pssr.cpp
+++ b/src/lib/pk_pad/emsa_pssr/pssr.cpp
@@ -193,8 +193,8 @@ AlgorithmIdentifier PSSR::config_for_x509(const std::string& algo_name,
                                           const std::string& cert_hash_name) const
    {
    if(cert_hash_name != m_hash->name())
-      throw Invalid_Argument("Hash function from opts and hash_fn argument"
-         " need to be identical");
+      throw Invalid_Argument("PSSR: Cert hash " + cert_hash_name +
+                             " incompatible with specified hash " + m_hash->name());
    // check that the signature algorithm and the padding scheme fit
    if(!sig_algo_and_pad_ok(algo_name, "EMSA4"))
       {
diff --git a/src/lib/pubkey/dlies/dlies.cpp b/src/lib/pubkey/dlies/dlies.cpp
index 8113386a7..9b50ed677 100644
--- a/src/lib/pubkey/dlies/dlies.cpp
+++ b/src/lib/pubkey/dlies/dlies.cpp
@@ -13,32 +13,32 @@ namespace Botan {
 
 DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key,
                                  RandomNumberGenerator& rng,
-                                 KDF* kdf,
-                                 MessageAuthenticationCode* mac,
+                                 std::unique_ptr<KDF> kdf,
+                                 std::unique_ptr<MessageAuthenticationCode> mac,
                                  size_t mac_key_length) :
-   DLIES_Encryptor(own_priv_key, rng, kdf, nullptr, 0, mac, mac_key_length)
+   DLIES_Encryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length)
    {
    }
 
 DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key,
                                  RandomNumberGenerator& rng,
-                                 KDF* kdf,
-                                 Cipher_Mode* cipher,
+                                 std::unique_ptr<KDF> kdf,
+                                 std::unique_ptr<Cipher_Mode> cipher,
                                  size_t cipher_key_len,
-                                 MessageAuthenticationCode* mac,
+                                 std::unique_ptr<MessageAuthenticationCode> mac,
                                  size_t mac_key_length) :
    m_other_pub_key(),
    m_own_pub_key(own_priv_key.public_value()),
    m_ka(own_priv_key, rng, "Raw"),
-   m_kdf(kdf),
-   m_cipher(cipher),
+   m_kdf(std::move(kdf)),
+   m_cipher(std::move(cipher)),
    m_cipher_key_len(cipher_key_len),
-   m_mac(mac),
+   m_mac(std::move(mac)),
    m_mac_keylen(mac_key_length),
    m_iv()
    {
-   BOTAN_ASSERT_NONNULL(kdf);
-   BOTAN_ASSERT_NONNULL(mac);
+   BOTAN_ASSERT_NONNULL(m_kdf);
+   BOTAN_ASSERT_NONNULL(m_mac);
    }
 
 std::vector<uint8_t> DLIES_Encryptor::enc(const uint8_t in[], size_t length,
@@ -109,30 +109,30 @@ size_t DLIES_Encryptor::ciphertext_length(size_t ptext_len) const
 
 DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key,
                                  RandomNumberGenerator& rng,
-                                 KDF* kdf,
-                                 Cipher_Mode* cipher,
+                                 std::unique_ptr<KDF> kdf,
+                                 std::unique_ptr<Cipher_Mode> cipher,
                                  size_t cipher_key_len,
-                                 MessageAuthenticationCode* mac,
+                                 std::unique_ptr<MessageAuthenticationCode> mac,
                                  size_t mac_key_length) :
    m_pub_key_size(own_priv_key.public_value().size()),
    m_ka(own_priv_key, rng, "Raw"),
-   m_kdf(kdf),
-   m_cipher(cipher),
-   m_cipher_key_len(cipher_key_len),
-   m_mac(mac),
+   m_kdf(std::move(kdf)),
+   m_cipher(std::move(cipher)),
+   m_cipher_key_len(std::move(cipher_key_len)),
+   m_mac(std::move(mac)),
    m_mac_keylen(mac_key_length),
    m_iv()
    {
-   BOTAN_ASSERT_NONNULL(kdf);
-   BOTAN_ASSERT_NONNULL(mac);
+   BOTAN_ASSERT_NONNULL(m_kdf);
+   BOTAN_ASSERT_NONNULL(m_mac);
    }
 
 DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key,
                                  RandomNumberGenerator& rng,
-                                 KDF* kdf,
-                                 MessageAuthenticationCode* mac,
+                                 std::unique_ptr<KDF> kdf,
+                                 std::unique_ptr<MessageAuthenticationCode> mac,
                                  size_t mac_key_length) :
-   DLIES_Decryptor(own_priv_key, rng, kdf, nullptr, 0, mac, mac_key_length)
+   DLIES_Decryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length)
    {}
 
 size_t DLIES_Decryptor::plaintext_length(size_t ctext_len) const
diff --git a/src/lib/pubkey/dlies/dlies.h b/src/lib/pubkey/dlies/dlies.h
index 640a8655e..ffa53c2a8 100644
--- a/src/lib/pubkey/dlies/dlies.h
+++ b/src/lib/pubkey/dlies/dlies.h
@@ -36,8 +36,8 @@ class BOTAN_PUBLIC_API(2,0) DLIES_Encryptor final : public PK_Encryptor
       */
       DLIES_Encryptor(const DH_PrivateKey& own_priv_key,
                       RandomNumberGenerator& rng,
-                      KDF* kdf,
-                      MessageAuthenticationCode* mac,
+                      std::unique_ptr<KDF> kdf,
+                      std::unique_ptr<MessageAuthenticationCode> mac,
                       size_t mac_key_len = 20);
 
       /**
@@ -55,10 +55,10 @@ class BOTAN_PUBLIC_API(2,0) DLIES_Encryptor final : public PK_Encryptor
       */
       DLIES_Encryptor(const DH_PrivateKey& own_priv_key,
                       RandomNumberGenerator& rng,
-                      KDF* kdf,
-                      Cipher_Mode* cipher,
+                      std::unique_ptr<KDF> kdf,
+                      std::unique_ptr<Cipher_Mode> cipher,
                       size_t cipher_key_len,
-                      MessageAuthenticationCode* mac,
+                      std::unique_ptr<MessageAuthenticationCode> mac,
                       size_t mac_key_len = 20);
 
       // Set the other parties public key
@@ -111,8 +111,8 @@ class BOTAN_PUBLIC_API(2,0) DLIES_Decryptor final : public PK_Decryptor
       */
       DLIES_Decryptor(const DH_PrivateKey& own_priv_key,
                       RandomNumberGenerator& rng,
-                      KDF* kdf,
-                      MessageAuthenticationCode* mac,
+                      std::unique_ptr<KDF> kdf,
+                      std::unique_ptr<MessageAuthenticationCode> mac,
                       size_t mac_key_len = 20);
 
       /**
@@ -130,10 +130,10 @@ class BOTAN_PUBLIC_API(2,0) DLIES_Decryptor final : public PK_Decryptor
       */
       DLIES_Decryptor(const DH_PrivateKey& own_priv_key,
                       RandomNumberGenerator& rng,
-                      KDF* kdf,
-                      Cipher_Mode* cipher,
+                      std::unique_ptr<KDF> kdf,
+                      std::unique_ptr<Cipher_Mode> cipher,
                       size_t cipher_key_len,
-                      MessageAuthenticationCode* mac,
+                      std::unique_ptr<MessageAuthenticationCode> mac,
                       size_t mac_key_len = 20);
 
       /// Set the initialization vector for the data decryption method
diff --git a/src/lib/x509/x509_ca.cpp b/src/lib/x509/x509_ca.cpp
index d7bcb90f8..adb3ae37f 100644
--- a/src/lib/x509/x509_ca.cpp
+++ b/src/lib/x509/x509_ca.cpp
@@ -1,67 +1,35 @@
 /*
 * X.509 Certificate Authority
-* (C) 1999-2010 Jack Lloyd
+* (C) 1999-2010,2023 Jack Lloyd
 *
 * Botan is released under the Simplified BSD License (see license.txt)
 */
 
 #include <botan/x509_ca.h>
 #include <botan/x509_key.h>
-#include <botan/x509self.h>
+#include <botan/pkcs10.h>
 #include <botan/x509_ext.h>
-#include <botan/pkix_types.h>
 #include <botan/pubkey.h>
 #include <botan/der_enc.h>
 #include <botan/bigint.h>
-#include <botan/internal/parsing.h>
-#include <botan/oids.h>
-#include <botan/hash.h>
-#include <botan/internal/emsa.h>
-#include <botan/internal/scan_name.h>
-#include <algorithm>
-#include <iterator>
 
 namespace Botan {
 
 /*
 * Load the certificate and private key
 */
-X509_CA::X509_CA(const X509_Certificate& c,
+X509_CA::X509_CA(const X509_Certificate& cert,
                  const Private_Key& key,
                  const std::string& hash_fn,
+                 const std::string& padding_method,
                  RandomNumberGenerator& rng) :
-   m_ca_cert(c),
+   m_ca_cert(cert),
    m_hash_fn(hash_fn)
    {
    if(!m_ca_cert.is_CA_cert())
       throw Invalid_Argument("X509_CA: This certificate is not for a CA");
 
-   std::map<std::string,std::string> opts;
-   // constructor without additional options: use the padding used in the CA certificate
-   // sig_oid_str = <sig_alg>/<padding>, so padding with all its options will look
-   // like a cipher mode to the scanner
-   std::string sig_oid_str = OIDS::oid2str_or_throw(c.signature_algorithm().get_oid());
-   SCAN_Name scanner(sig_oid_str);
-   std::string pad = scanner.cipher_mode();
-   if(!pad.empty())
-      opts.insert({"padding",pad});
-
-   m_signer.reset(choose_sig_format(key, opts, rng, hash_fn, m_ca_sig_algo));
-   }
-
-/*
-* Load the certificate and private key, and additional options
-*/
-X509_CA::X509_CA(const X509_Certificate& ca_certificate,
-        const Private_Key& key,
-        const std::map<std::string,std::string>& opts,
-        const std::string& hash_fn,
-        RandomNumberGenerator& rng) : m_ca_cert(ca_certificate), m_hash_fn(hash_fn)
-   {
-   if(!m_ca_cert.is_CA_cert())
-      throw Invalid_Argument("X509_CA: This certificate is not for a CA");
-
-   m_signer.reset(choose_sig_format(key, opts, rng, hash_fn, m_ca_sig_algo));
+   m_signer = X509_Object::choose_sig_format(m_ca_sig_algo, key, rng, hash_fn, padding_method);
    }
 
 /*
@@ -306,28 +274,4 @@ X509_Certificate X509_CA::ca_certificate() const
    return m_ca_cert;
    }
 
-/*
-* Choose a signing format for the key
-*/
-
-PK_Signer* choose_sig_format(const Private_Key& key,
-                             RandomNumberGenerator& rng,
-                             const std::string& hash_fn,
-                             AlgorithmIdentifier& sig_algo)
-   {
-   return X509_Object::choose_sig_format(sig_algo, key, rng, hash_fn, "").release();
-   }
-
-PK_Signer* choose_sig_format(const Private_Key& key,
-                             const std::map<std::string,std::string>& opts,
-                             RandomNumberGenerator& rng,
-                             const std::string& hash_fn,
-                             AlgorithmIdentifier& sig_algo)
-   {
-   std::string padding;
-   if(opts.count("padding"))
-      padding = opts.at("padding");
-   return X509_Object::choose_sig_format(sig_algo, key, rng, hash_fn, padding).release();
-   }
-
 }
diff --git a/src/lib/x509/x509_ca.h b/src/lib/x509/x509_ca.h
index 5437cafd8..72a94c002 100644
--- a/src/lib/x509/x509_ca.h
+++ b/src/lib/x509/x509_ca.h
@@ -160,17 +160,36 @@ class BOTAN_PUBLIC_API(2,0) X509_CA final
                                         const Extensions& extensions);
 
       /**
-      * Create a new CA object.
+      * Create a new CA object with custom padding option
       * @param ca_certificate the certificate of the CA
       * @param key the private key of the CA
       * @param hash_fn name of a hash function to use for signing
+      * @param padding_method name of the signature padding method to use
       * @param rng the random generator to use
       */
       X509_CA(const X509_Certificate& ca_certificate,
               const Private_Key& key,
               const std::string& hash_fn,
+              const std::string& padding_method,
               RandomNumberGenerator& rng);
 
+      /**
+      * Create a new CA object.
+      * @param ca_certificate the certificate of the CA
+      * @param key the private key of the CA
+      * @param hash_fn name of a hash function to use for signing
+      * @param rng the random generator to use
+      */
+      X509_CA(const X509_Certificate& ca_certificate,
+              const Private_Key& key,
+              const std::string& hash_fn,
+              RandomNumberGenerator& rng) :
+         X509_CA(ca_certificate,
+                 key,
+                 hash_fn,
+                 "",
+                 rng) {}
+
       /**
       * Create a new CA object.
       * @param ca_certificate the certificate of the CA
@@ -179,11 +198,13 @@ class BOTAN_PUBLIC_API(2,0) X509_CA final
       * @param hash_fn name of a hash function to use for signing
       * @param rng the random generator to use
       */
+      BOTAN_DEPRECATED("Use version taking padding as an explicit arg")
       X509_CA(const X509_Certificate& ca_certificate,
               const Private_Key& key,
               const std::map<std::string,std::string>& opts,
               const std::string& hash_fn,
-              RandomNumberGenerator& rng);
+              RandomNumberGenerator& rng) :
+         X509_CA(ca_certificate, key, opts.at("padding"), hash_fn, rng) {}
 
       X509_CA(const X509_CA&) = delete;
       X509_CA& operator=(const X509_CA&) = delete;
@@ -206,44 +227,6 @@ class BOTAN_PUBLIC_API(2,0) X509_CA final
       std::unique_ptr<PK_Signer> m_signer;
    };
 
-/**
-* Choose the default signature format for a certain public key signature
-* scheme.
-* @param key will be the key to choose a padding scheme for
-* @param rng the random generator to use
-* @param hash_fn is the desired hash function
-* @param alg_id will be set to the chosen scheme
-* @return A PK_Signer object for generating signatures
-*/
-BOTAN_PUBLIC_API(2,0) PK_Signer* choose_sig_format(const Private_Key& key,
-                                       RandomNumberGenerator& rng,
-                                       const std::string& hash_fn,
-                                       AlgorithmIdentifier& alg_id);
-
-/**
-* @verbatim
-* Choose the default signature format for a certain public key signature
-* scheme.
-*
-* The only option recognized by opts at this moment is "padding"
-* Find an entry from src/build-data/oids.txt under [signature] of the form
-* <sig_algo>/<padding>[(<hash_algo>)] and add {"padding",<padding>}
-* to opts.
-* @endverbatim
-*
-* @param key will be the key to choose a padding scheme for
-* @param opts contains additional options for building the certificate
-* @param rng the random generator to use
-* @param hash_fn is the desired hash function
-* @param alg_id will be set to the chosen scheme
-* @return A PK_Signer object for generating signatures
-*/
-PK_Signer* choose_sig_format(const Private_Key& key,
-                             const std::map<std::string,std::string>& opts,
-                             RandomNumberGenerator& rng,
-                             const std::string& hash_fn,
-                             AlgorithmIdentifier& alg_id);
-
 }
 
 #endif
diff --git a/src/lib/x509/x509_obj.h b/src/lib/x509/x509_obj.h
index 45449ba40..6d9fa7cb6 100644
--- a/src/lib/x509/x509_obj.h
+++ b/src/lib/x509/x509_obj.h
@@ -107,6 +107,16 @@ class BOTAN_PUBLIC_API(2,0) X509_Object : public ASN1_Object
 
       virtual ~X509_Object() = default;
 
+      /**
+      * Choose the default signature format for a certain public key signature
+      * scheme.
+      * @param sig_algo will be set to the chosen algorithm
+      * @param key will be the key to choose a padding scheme for
+      * @param rng the random generator to use
+      * @param hash_fn is the desired hash function
+      * @param padding_algo specifies the padding method
+      * @return a PK_Signer object for generating signatures
+      */
       static std::unique_ptr<PK_Signer>
          choose_sig_format(AlgorithmIdentifier& sig_algo,
                            const Private_Key& key,
diff --git a/src/lib/x509/x509self.cpp b/src/lib/x509/x509self.cpp
index 1526c5b83..0f6ae459e 100644
--- a/src/lib/x509/x509self.cpp
+++ b/src/lib/x509/x509self.cpp
@@ -57,11 +57,8 @@ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
    X509_DN subject_dn;
    AlternativeName subject_alt;
 
-   // for now, only the padding option is used
-   std::map<std::string,std::string> sig_opts = { {"padding",opts.padding_scheme} };
-
    const std::vector<uint8_t> pub_key = X509::BER_encode(key);
-   std::unique_ptr<PK_Signer> signer(choose_sig_format(key, sig_opts, rng, hash_fn, sig_algo));
+   auto signer = X509_Object::choose_sig_format(sig_algo, key, rng, hash_fn, opts.padding_scheme);
    BOTAN_ASSERT_NOMSG(sig_algo.get_oid().has_value());
    load_info(opts, subject_dn, subject_alt);
 


Test patch:
diff --git a/src/tests/test_dlies.cpp b/src/tests/test_dlies.cpp
index 588be0d14..653436c35 100644
--- a/src/tests/test_dlies.cpp
+++ b/src/tests/test_dlies.cpp
@@ -81,10 +81,14 @@ class DLIES_KAT_Tests final : public Text_Based_Test
          Botan::DH_PrivateKey from(Test::rng(), domain, x1);
          Botan::DH_PrivateKey to(Test::rng(), domain, x2);
 
-         Botan::DLIES_Encryptor encryptor(from, Test::rng(), kdf->clone(), enc.release(), cipher_key_len, mac->clone(),
-                                          mac_key_len);
-         Botan::DLIES_Decryptor decryptor(to, Test::rng(), kdf.release(), dec.release(), cipher_key_len, mac.release(),
-                                          mac_key_len);
+         Botan::DLIES_Encryptor encryptor(from, Test::rng(),
+                                          kdf->new_object(),
+                                          std::move(enc), cipher_key_len,
+                                          mac->new_object(), mac_key_len);
+         Botan::DLIES_Decryptor decryptor(to, Test::rng(),
+                                          std::move(kdf),
+                                          std::move(dec), cipher_key_len,
+                                          std::move(mac), mac_key_len);
 
          if(!iv.empty())
             {
@@ -140,7 +144,7 @@ Test::Result test_xor()
             continue;
             }
 
-         Botan::DLIES_Encryptor encryptor(alice, Test::rng(), kdf->clone(), mac->clone(), mac_key_len);
+         Botan::DLIES_Encryptor encryptor(alice, Test::rng(), kdf->new_object(), mac->new_object(), mac_key_len);
 
          // negative test: other pub key not set
          Botan::secure_vector<uint8_t> plaintext = Test::rng().random_vec(32);
@@ -153,7 +157,7 @@ Test::Result test_xor()
          encryptor.set_other_key(bob.public_value());
          std::vector<uint8_t> ciphertext = encryptor.encrypt(plaintext, Test::rng());
 
-         Botan::DLIES_Decryptor decryptor(bob, Test::rng(), kdf->clone(), mac->clone(), mac_key_len);
+         Botan::DLIES_Decryptor decryptor(bob, Test::rng(), kdf->new_object(), mac->new_object(), mac_key_len);
 
          // negative test: ciphertext too short
          result.test_throws("ciphertext too short", [ &decryptor ]()
diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp
index fa344430d..63f13dfd0 100644
--- a/src/tests/unit_x509.cpp
+++ b/src/tests/unit_x509.cpp
@@ -726,14 +726,14 @@ Test::Result test_verify_gost2012_cert()
    // Create X509 CA object: will fail as the chosen hash functions differ
    try
       {
-      Botan::X509_CA ca_fail(ca_cert_exp, (*sk), {{"padding","EMSA4(SHA-256)"}},"SHA-512", Test::rng());
+      Botan::X509_CA ca_fail(ca_cert_exp, (*sk), "SHA-512", "EMSA4(SHA-256)", Test::rng());
       test_result.test_failure("Configured conflicting hash functions for CA");
       }
    catch(const Botan::Invalid_Argument& e)
       {
       test_result.test_eq("Configured conflicting hash functions for CA",
-            e.what(),
-            "Hash function from opts and hash_fn argument need to be identical");
+                          e.what(),
+                          "PSSR: Cert hash SHA-512 incompatible with specified hash SHA-256");
       }
 
    // Create X509 CA object: its signer will use the padding scheme from the CA certificate, i.e. EMSA3
@@ -742,12 +742,12 @@ Test::Result test_verify_gost2012_cert()
    test_result.test_eq("End certificate signature algorithm", Botan::OIDS::oid2str_or_throw(end_cert_emsa3.signature_algorithm().get_oid()), "RSA/EMSA3(SHA-512)");
 
    // Create X509 CA object: its signer will use the explicitly configured padding scheme, which is different from the CA certificate's scheme
-   Botan::X509_CA ca_diff(ca_cert_def, (*sk), {{"padding","EMSA-PSS"}}, "SHA-512", Test::rng());
+   Botan::X509_CA ca_diff(ca_cert_def, (*sk), "SHA-512", "EMSA-PSS", Test::rng());
    Botan::X509_Certificate end_cert_diff_emsa4 = ca_diff.sign_request(end_req, Test::rng(), not_before, not_after);
    test_result.test_eq("End certificate signature algorithm", Botan::OIDS::oid2str_or_throw(end_cert_diff_emsa4.signature_algorithm().get_oid()), "RSA/EMSA4");
 
    // Create X509 CA object: its signer will use the explicitly configured padding scheme, which is identical to the CA certificate's scheme
-   Botan::X509_CA ca_exp(ca_cert_exp, (*sk), {{"padding","EMSA4(SHA-512,MGF1,64)"}},"SHA-512", Test::rng());
+   Botan::X509_CA ca_exp(ca_cert_exp, (*sk), "SHA-512", "EMSA4(SHA-512,MGF1,64)", Test::rng());
    Botan::X509_Certificate end_cert_emsa4= ca_exp.sign_request(end_req, Test::rng(), not_before, not_after);
    test_result.test_eq("End certificate signature algorithm", Botan::OIDS::oid2str_or_throw(end_cert_emsa4.signature_algorithm().get_oid()), "RSA/EMSA4");
 
@@ -849,7 +849,7 @@ Test::Result test_x509_cert(const Botan::Private_Key& ca_key,
                                    Test::rng());
 
    /* Create the CA object */
-   Botan::X509_CA ca(ca_cert, ca_key, {{"padding",sig_padding}}, hash_fn, Test::rng());
+   Botan::X509_CA ca(ca_cert, ca_key, hash_fn, sig_padding, Test::rng());
 
    const BigInt user1_serial = 99;
 
@@ -1115,7 +1115,7 @@ Test::Result test_self_issued(const Botan::Private_Key& ca_key,
          ca_opts(sig_padding), ca_key, hash_fn, Test::rng());
 
    /* Create the CA object */
-   const Botan::X509_CA ca(ca_cert, ca_key, {{"padding",sig_padding}}, hash_fn, Test::rng());
+   const Botan::X509_CA ca(ca_cert, ca_key, hash_fn, sig_padding, Test::rng());
 
    std::unique_ptr<Botan::Private_Key> user_key(make_a_private_key(sig_algo));
 
@@ -1347,7 +1347,7 @@ Test::Result test_custom_dn_attr(const Botan::Private_Key& ca_key,
       Botan::X509::create_self_signed_cert(ca_opts(sig_padding), ca_key, hash_fn, Test::rng());
 
    /* Create the CA object */
-   Botan::X509_CA ca(ca_cert, ca_key, {{"padding",sig_padding}}, hash_fn, Test::rng());
+   Botan::X509_CA ca(ca_cert, ca_key, hash_fn, sig_padding, Test::rng());
 
    std::unique_ptr<Botan::Private_Key> user_key(make_a_private_key(sig_algo));
 
@@ -1416,7 +1416,7 @@ Test::Result test_x509_extensions(const Botan::Private_Key& ca_key,
       Botan::X509::create_self_signed_cert(ca_opts(sig_padding), ca_key, hash_fn, Test::rng());
 
    /* Create the CA object */
-   Botan::X509_CA ca(ca_cert, ca_key, {{"padding",sig_padding}}, hash_fn, Test::rng());
+   Botan::X509_CA ca(ca_cert, ca_key, hash_fn, sig_padding, Test::rng());
 
    std::unique_ptr<Botan::Private_Key> user_key(make_a_private_key(sig_algo));