Repository: randombit/botan
Pull request #2703 (2021-04-07 14:43:52)

Avoid raw pointers in cipher mode code


Patch:
diff --git a/src/lib/modes/aead/aead.cpp b/src/lib/modes/aead/aead.cpp
index 57950f83d..772b88ccd 100644
--- a/src/lib/modes/aead/aead.cpp
+++ b/src/lib/modes/aead/aead.cpp
@@ -117,9 +117,9 @@ std::unique_ptr<AEAD_Mode> AEAD_Mode::create(const std::string& algo,
       size_t tag_len = req.arg_as_integer(1, 16);
       size_t L_len = req.arg_as_integer(2, 3);
       if(dir == ENCRYPTION)
-         return std::make_unique<CCM_Encryption>(bc.release(), tag_len, L_len);
+         return std::make_unique<CCM_Encryption>(std::move(bc), tag_len, L_len);
       else
-         return std::make_unique<CCM_Decryption>(bc.release(), tag_len, L_len);
+         return std::make_unique<CCM_Decryption>(std::move(bc), tag_len, L_len);
       }
 #endif
 
@@ -128,9 +128,9 @@ std::unique_ptr<AEAD_Mode> AEAD_Mode::create(const std::string& algo,
       {
       size_t tag_len = req.arg_as_integer(1, 16);
       if(dir == ENCRYPTION)
-         return std::make_unique<GCM_Encryption>(bc.release(), tag_len);
+         return std::make_unique<GCM_Encryption>(std::move(bc), tag_len);
       else
-         return std::make_unique<GCM_Decryption>(bc.release(), tag_len);
+         return std::make_unique<GCM_Decryption>(std::move(bc), tag_len);
       }
 #endif
 
@@ -139,9 +139,9 @@ std::unique_ptr<AEAD_Mode> AEAD_Mode::create(const std::string& algo,
       {
       size_t tag_len = req.arg_as_integer(1, 16);
       if(dir == ENCRYPTION)
-         return std::make_unique<OCB_Encryption>(bc.release(), tag_len);
+         return std::make_unique<OCB_Encryption>(std::move(bc), tag_len);
       else
-         return std::make_unique<OCB_Decryption>(bc.release(), tag_len);
+         return std::make_unique<OCB_Decryption>(std::move(bc), tag_len);
       }
 #endif
 
@@ -150,9 +150,9 @@ std::unique_ptr<AEAD_Mode> AEAD_Mode::create(const std::string& algo,
       {
       size_t tag_len = req.arg_as_integer(1, bc->block_size());
       if(dir == ENCRYPTION)
-         return std::make_unique<EAX_Encryption>(bc.release(), tag_len);
+         return std::make_unique<EAX_Encryption>(std::move(bc), tag_len);
       else
-         return std::make_unique<EAX_Decryption>(bc.release(), tag_len);
+         return std::make_unique<EAX_Decryption>(std::move(bc), tag_len);
       }
 #endif
 
@@ -160,9 +160,9 @@ std::unique_ptr<AEAD_Mode> AEAD_Mode::create(const std::string& algo,
    if(req.algo_name() == "SIV")
       {
       if(dir == ENCRYPTION)
-         return std::make_unique<SIV_Encryption>(bc.release());
+         return std::make_unique<SIV_Encryption>(std::move(bc));
       else
-         return std::make_unique<SIV_Decryption>(bc.release());
+         return std::make_unique<SIV_Decryption>(std::move(bc));
       }
 #endif
 
diff --git a/src/lib/modes/aead/ccm/ccm.cpp b/src/lib/modes/aead/ccm/ccm.cpp
index fdc45a623..50f7118e7 100644
--- a/src/lib/modes/aead/ccm/ccm.cpp
+++ b/src/lib/modes/aead/ccm/ccm.cpp
@@ -17,10 +17,10 @@ static const size_t CCM_BS = 16;
 /*
 * CCM_Mode Constructor
 */
-CCM_Mode::CCM_Mode(BlockCipher* cipher, size_t tag_size, size_t L) :
+CCM_Mode::CCM_Mode(std::unique_ptr<BlockCipher> cipher, size_t tag_size, size_t L) :
    m_tag_size(tag_size),
    m_L(L),
-   m_cipher(cipher)
+   m_cipher(std::move(cipher))
    {
    if(m_cipher->block_size() != CCM_BS)
       throw Invalid_Argument(m_cipher->name() + " cannot be used with CCM mode");
diff --git a/src/lib/modes/aead/ccm/ccm.h b/src/lib/modes/aead/ccm/ccm.h
index 58ee101fd..a98d19632 100644
--- a/src/lib/modes/aead/ccm/ccm.h
+++ b/src/lib/modes/aead/ccm/ccm.h
@@ -44,7 +44,7 @@ class CCM_Mode : public AEAD_Mode
       size_t tag_size() const override { return m_tag_size; }
 
    protected:
-      CCM_Mode(BlockCipher* cipher, size_t tag_size, size_t L);
+      CCM_Mode(std::unique_ptr<BlockCipher> cipher, size_t tag_size, size_t L);
 
       size_t L() const { return m_L; }
 
@@ -85,8 +85,8 @@ class CCM_Encryption final : public CCM_Mode
       * @param L length of L parameter. The total message length
       *           must be less than 2**L bytes, and the nonce is 15-L bytes.
       */
-      CCM_Encryption(BlockCipher* cipher, size_t tag_size = 16, size_t L = 3) :
-         CCM_Mode(cipher, tag_size, L) {}
+      CCM_Encryption(std::unique_ptr<BlockCipher> cipher, size_t tag_size = 16, size_t L = 3) :
+         CCM_Mode(std::move(cipher), tag_size, L) {}
 
       void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
 
@@ -109,8 +109,8 @@ class CCM_Decryption final : public CCM_Mode
       * @param L length of L parameter. The total message length
       *           must be less than 2**L bytes, and the nonce is 15-L bytes.
       */
-      CCM_Decryption(BlockCipher* cipher, size_t tag_size = 16, size_t L = 3) :
-         CCM_Mode(cipher, tag_size, L) {}
+      CCM_Decryption(std::unique_ptr<BlockCipher> cipher, size_t tag_size = 16, size_t L = 3) :
+         CCM_Mode(std::move(cipher), tag_size, L) {}
 
       void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
 
diff --git a/src/lib/modes/aead/eax/eax.cpp b/src/lib/modes/aead/eax/eax.cpp
index 94b938a18..fc1e82b25 100644
--- a/src/lib/modes/aead/eax/eax.cpp
+++ b/src/lib/modes/aead/eax/eax.cpp
@@ -35,9 +35,9 @@ secure_vector<uint8_t> eax_prf(uint8_t tag, size_t block_size,
 /*
 * EAX_Mode Constructor
 */
-EAX_Mode::EAX_Mode(BlockCipher* cipher, size_t tag_size) :
+EAX_Mode::EAX_Mode(std::unique_ptr<BlockCipher> cipher, size_t tag_size) :
    m_tag_size(tag_size),
-   m_cipher(cipher),
+   m_cipher(std::move(cipher)),
    m_ctr(new CTR_BE(m_cipher->new_object())),
    m_cmac(new CMAC(m_cipher->new_object()))
    {
diff --git a/src/lib/modes/aead/eax/eax.h b/src/lib/modes/aead/eax/eax.h
index f4c055948..be888a900 100644
--- a/src/lib/modes/aead/eax/eax.h
+++ b/src/lib/modes/aead/eax/eax.h
@@ -44,7 +44,7 @@ class EAX_Mode : public AEAD_Mode
       * @param cipher the cipher to use
       * @param tag_size is how big the auth tag will be
       */
-      EAX_Mode(BlockCipher* cipher, size_t tag_size);
+      EAX_Mode(std::unique_ptr<BlockCipher> cipher, size_t tag_size);
 
       size_t block_size() const { return m_cipher->block_size(); }
 
@@ -73,8 +73,8 @@ class EAX_Encryption final : public EAX_Mode
       * @param cipher a 128-bit block cipher
       * @param tag_size is how big the auth tag will be
       */
-      EAX_Encryption(BlockCipher* cipher, size_t tag_size = 0) :
-         EAX_Mode(cipher, tag_size) {}
+      EAX_Encryption(std::unique_ptr<BlockCipher> cipher, size_t tag_size = 0) :
+         EAX_Mode(std::move(cipher), tag_size) {}
 
       size_t output_length(size_t input_length) const override
          { return input_length + tag_size(); }
@@ -96,8 +96,8 @@ class EAX_Decryption final : public EAX_Mode
       * @param cipher a 128-bit block cipher
       * @param tag_size is how big the auth tag will be
       */
-      EAX_Decryption(BlockCipher* cipher, size_t tag_size = 0) :
-         EAX_Mode(cipher, tag_size) {}
+      EAX_Decryption(std::unique_ptr<BlockCipher> cipher, size_t tag_size = 0) :
+         EAX_Mode(std::move(cipher), tag_size) {}
 
       size_t output_length(size_t input_length) const override
          {
diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp
index aa736f776..5b58fcc98 100644
--- a/src/lib/modes/aead/gcm/gcm.cpp
+++ b/src/lib/modes/aead/gcm/gcm.cpp
@@ -16,15 +16,16 @@ namespace Botan {
 /*
 * GCM_Mode Constructor
 */
-GCM_Mode::GCM_Mode(BlockCipher* cipher, size_t tag_size) :
+GCM_Mode::GCM_Mode(std::unique_ptr<BlockCipher> cipher, size_t tag_size) :
    m_tag_size(tag_size),
-   m_cipher_name(cipher->name()),
-   m_ctr(new CTR_BE(std::unique_ptr<BlockCipher>(cipher), 4)),
-   m_ghash(new GHASH)
+   m_cipher_name(cipher->name())
    {
    if(cipher->block_size() != GCM_BS)
       throw Invalid_Argument("Invalid block cipher for GCM");
 
+   m_ctr = std::make_unique<CTR_BE>(std::move(cipher), 4);
+   m_ghash = std::make_unique<GHASH>();
+
    /* We allow any of the values 128, 120, 112, 104, or 96 bits as a tag size */
    /* 64 bit tag is still supported but deprecated and will be removed in the future */
    if(m_tag_size != 8 && (m_tag_size < 12 || m_tag_size > 16))
diff --git a/src/lib/modes/aead/gcm/gcm.h b/src/lib/modes/aead/gcm/gcm.h
index ba67b2e47..6a4a0c8b6 100644
--- a/src/lib/modes/aead/gcm/gcm.h
+++ b/src/lib/modes/aead/gcm/gcm.h
@@ -42,7 +42,7 @@ class GCM_Mode : public AEAD_Mode
 
       std::string provider() const override;
    protected:
-      GCM_Mode(BlockCipher* cipher, size_t tag_size);
+      GCM_Mode(std::unique_ptr<BlockCipher> cipher, size_t tag_size);
 
       ~GCM_Mode();
 
@@ -71,8 +71,8 @@ class GCM_Encryption final : public GCM_Mode
       * @param cipher the 128 bit block cipher to use
       * @param tag_size is how big the auth tag will be
       */
-      GCM_Encryption(BlockCipher* cipher, size_t tag_size = 16) :
-         GCM_Mode(cipher, tag_size) {}
+      GCM_Encryption(std::unique_ptr<BlockCipher> cipher, size_t tag_size = 16) :
+         GCM_Mode(std::move(cipher), tag_size) {}
 
       size_t output_length(size_t input_length) const override
          { return input_length + tag_size(); }
@@ -94,8 +94,8 @@ class GCM_Decryption final : public GCM_Mode
       * @param cipher the 128 bit block cipher to use
       * @param tag_size is how big the auth tag will be
       */
-      GCM_Decryption(BlockCipher* cipher, size_t tag_size = 16) :
-         GCM_Mode(cipher, tag_size) {}
+      GCM_Decryption(std::unique_ptr<BlockCipher> cipher, size_t tag_size = 16) :
+         GCM_Mode(std::move(cipher), tag_size) {}
 
       size_t output_length(size_t input_length) const override
          {
diff --git a/src/lib/modes/aead/ocb/ocb.cpp b/src/lib/modes/aead/ocb/ocb.cpp
index aa0eada3e..030c6fd29 100644
--- a/src/lib/modes/aead/ocb/ocb.cpp
+++ b/src/lib/modes/aead/ocb/ocb.cpp
@@ -158,8 +158,8 @@ secure_vector<uint8_t> ocb_hash(const L_computer& L,
 
 }
 
-OCB_Mode::OCB_Mode(BlockCipher* cipher, size_t tag_size) :
-   m_cipher(cipher),
+OCB_Mode::OCB_Mode(std::unique_ptr<BlockCipher> cipher, size_t tag_size) :
+   m_cipher(std::move(cipher)),
    m_checksum(m_cipher->parallel_bytes()),
    m_ad_hash(m_cipher->block_size()),
    m_tag_size(tag_size),
diff --git a/src/lib/modes/aead/ocb/ocb.h b/src/lib/modes/aead/ocb/ocb.h
index b94d4e022..f4e3fdeb9 100644
--- a/src/lib/modes/aead/ocb/ocb.h
+++ b/src/lib/modes/aead/ocb/ocb.h
@@ -53,7 +53,7 @@ class BOTAN_TEST_API OCB_Mode : public AEAD_Mode
       * @param cipher the block cipher to use
       * @param tag_size is how big the auth tag will be
       */
-      OCB_Mode(BlockCipher* cipher, size_t tag_size);
+      OCB_Mode(std::unique_ptr<BlockCipher> cipher, size_t tag_size);
 
       size_t block_size() const { return m_block_size; }
       size_t par_blocks() const { return m_par_blocks; }
@@ -90,8 +90,8 @@ class BOTAN_TEST_API OCB_Encryption final : public OCB_Mode
       * @param cipher the block cipher to use
       * @param tag_size is how big the auth tag will be
       */
-      OCB_Encryption(BlockCipher* cipher, size_t tag_size = 16) :
-         OCB_Mode(cipher, tag_size) {}
+      OCB_Encryption(std::unique_ptr<BlockCipher> cipher, size_t tag_size = 16) :
+         OCB_Mode(std::move(cipher), tag_size) {}
 
       size_t output_length(size_t input_length) const override
          { return input_length + tag_size(); }
@@ -112,8 +112,8 @@ class BOTAN_TEST_API OCB_Decryption final : public OCB_Mode
       * @param cipher the block cipher to use
       * @param tag_size is how big the auth tag will be
       */
-      OCB_Decryption(BlockCipher* cipher, size_t tag_size = 16) :
-         OCB_Mode(cipher, tag_size) {}
+      OCB_Decryption(std::unique_ptr<BlockCipher> cipher, size_t tag_size = 16) :
+         OCB_Mode(std::move(cipher), tag_size) {}
 
       size_t output_length(size_t input_length) const override
          {
diff --git a/src/lib/modes/aead/siv/siv.cpp b/src/lib/modes/aead/siv/siv.cpp
index 59ae3e991..daa097039 100644
--- a/src/lib/modes/aead/siv/siv.cpp
+++ b/src/lib/modes/aead/siv/siv.cpp
@@ -14,13 +14,12 @@
 
 namespace Botan {
 
-SIV_Mode::SIV_Mode(BlockCipher* cipher) :
+SIV_Mode::SIV_Mode(std::unique_ptr<BlockCipher> cipher) :
    m_name(cipher->name() + "/SIV"),
+   m_bs(cipher->block_size()),
    m_ctr(new CTR_BE(cipher->new_object(), 8)),
-   m_mac(new CMAC(cipher->new_object())),
-   m_bs(cipher->block_size())
+   m_mac(new CMAC(std::move(cipher)))
    {
-   delete cipher; // fixme
    // Not really true but only 128 bit allowed at the moment
    if(m_bs != 16)
       throw Invalid_Argument("SIV requires a 128 bit block cipher");
diff --git a/src/lib/modes/aead/siv/siv.h b/src/lib/modes/aead/siv/siv.h
index 0315272a9..9f3b9ace3 100644
--- a/src/lib/modes/aead/siv/siv.h
+++ b/src/lib/modes/aead/siv/siv.h
@@ -57,7 +57,7 @@ class BOTAN_TEST_API SIV_Mode : public AEAD_Mode
       ~SIV_Mode();
 
    protected:
-      explicit SIV_Mode(BlockCipher* cipher);
+      explicit SIV_Mode(std::unique_ptr<BlockCipher> cipher);
 
       size_t block_size() const { return m_bs; }
 
@@ -74,11 +74,12 @@ class BOTAN_TEST_API SIV_Mode : public AEAD_Mode
       void key_schedule(const uint8_t key[], size_t length) override;
 
       const std::string m_name;
+      const size_t m_bs;
+
       std::unique_ptr<StreamCipher> m_ctr;
       std::unique_ptr<MessageAuthenticationCode> m_mac;
       secure_vector<uint8_t> m_nonce, m_msg_buf;
       std::vector<secure_vector<uint8_t>> m_ad_macs;
-      const size_t m_bs;
    };
 
 /**
@@ -90,7 +91,8 @@ class BOTAN_TEST_API SIV_Encryption final : public SIV_Mode
       /**
       * @param cipher a block cipher
       */
-      explicit SIV_Encryption(BlockCipher* cipher) : SIV_Mode(cipher) {}
+      explicit SIV_Encryption(std::unique_ptr<BlockCipher> cipher) :
+         SIV_Mode(std::move(cipher)) {}
 
       void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
 
@@ -109,7 +111,8 @@ class BOTAN_TEST_API SIV_Decryption final : public SIV_Mode
       /**
       * @param cipher a 128-bit block cipher
       */
-      explicit SIV_Decryption(BlockCipher* cipher) : SIV_Mode(cipher) {}
+      explicit SIV_Decryption(std::unique_ptr<BlockCipher> cipher) :
+         SIV_Mode(std::move(cipher)) {}
 
       void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
 
diff --git a/src/lib/modes/cbc/cbc.cpp b/src/lib/modes/cbc/cbc.cpp
index 105f2bbf7..d4f44739e 100644
--- a/src/lib/modes/cbc/cbc.cpp
+++ b/src/lib/modes/cbc/cbc.cpp
@@ -13,10 +13,11 @@
 
 namespace Botan {
 
-CBC_Mode::CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
-   m_cipher(cipher),
-   m_padding(padding),
-   m_block_size(cipher->block_size())
+CBC_Mode::CBC_Mode(std::unique_ptr<BlockCipher> cipher,
+                   std::unique_ptr<BlockCipherModePaddingMethod> padding) :
+   m_cipher(std::move(cipher)),
+   m_padding(std::move(padding)),
+   m_block_size(m_cipher->block_size())
    {
    if(m_padding && !m_padding->valid_blocksize(m_block_size))
       throw Invalid_Argument("Padding " + m_padding->name() +
diff --git a/src/lib/modes/cbc/cbc.h b/src/lib/modes/cbc/cbc.h
index c74e8f23b..6ebd3b5bd 100644
--- a/src/lib/modes/cbc/cbc.h
+++ b/src/lib/modes/cbc/cbc.h
@@ -36,7 +36,8 @@ class CBC_Mode : public Cipher_Mode
       void reset() override;
 
    protected:
-      CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding);
+      CBC_Mode(std::unique_ptr<BlockCipher> cipher,
+               std::unique_ptr<BlockCipherModePaddingMethod> padding);
 
       const BlockCipher& cipher() const { return *m_cipher; }
 
@@ -73,8 +74,9 @@ class CBC_Encryption : public CBC_Mode
       * @param cipher block cipher to use
       * @param padding padding method to use
       */
-      CBC_Encryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
-         CBC_Mode(cipher, padding) {}
+      CBC_Encryption(std::unique_ptr<BlockCipher> cipher,
+                     std::unique_ptr<BlockCipherModePaddingMethod> padding) :
+         CBC_Mode(std::move(cipher), std::move(padding)) {}
 
       size_t process(uint8_t buf[], size_t size) override;
 
@@ -94,7 +96,9 @@ class CTS_Encryption final : public CBC_Encryption
       /**
       * @param cipher block cipher to use
       */
-      explicit CTS_Encryption(BlockCipher* cipher) : CBC_Encryption(cipher, nullptr) {}
+      explicit CTS_Encryption(std::unique_ptr<BlockCipher> cipher) :
+         CBC_Encryption(std::move(cipher), nullptr)
+         {}
 
       size_t output_length(size_t input_length) const override;
 
@@ -115,8 +119,11 @@ class CBC_Decryption : public CBC_Mode
       * @param cipher block cipher to use
       * @param padding padding method to use
       */
-      CBC_Decryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
-         CBC_Mode(cipher, padding), m_tempbuf(update_granularity()) {}
+      CBC_Decryption(std::unique_ptr<BlockCipher> cipher,
+                     std::unique_ptr<BlockCipherModePaddingMethod> padding) :
+         CBC_Mode(std::move(cipher), std::move(padding)),
+         m_tempbuf(update_granularity())
+         {}
 
       size_t process(uint8_t buf[], size_t size) override;
 
@@ -141,7 +148,9 @@ class CTS_Decryption final : public CBC_Decryption
       /**
       * @param cipher block cipher to use
       */
-      explicit CTS_Decryption(BlockCipher* cipher) : CBC_Decryption(cipher, nullptr) {}
+      explicit CTS_Decryption(std::unique_ptr<BlockCipher> cipher) :
+         CBC_Decryption(std::move(cipher), nullptr)
+         {}
 
       void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
 
diff --git a/src/lib/modes/cfb/cfb.cpp b/src/lib/modes/cfb/cfb.cpp
index c8766f1c2..98630a412 100644
--- a/src/lib/modes/cfb/cfb.cpp
+++ b/src/lib/modes/cfb/cfb.cpp
@@ -10,12 +10,12 @@
 
 namespace Botan {
 
-CFB_Mode::CFB_Mode(BlockCipher* cipher, size_t feedback_bits) :
-   m_cipher(cipher),
+CFB_Mode::CFB_Mode(std::unique_ptr<BlockCipher> cipher, size_t feedback_bits) :
+   m_cipher(std::move(cipher)),
    m_block_size(m_cipher->block_size()),
    m_feedback_bytes(feedback_bits ? feedback_bits / 8 : m_block_size)
    {
-   if(feedback_bits % 8 || feedback() > cipher->block_size())
+   if(feedback_bits % 8 || feedback() > m_block_size)
       throw Invalid_Argument(name() + ": feedback bits " +
                                   std::to_string(feedback_bits) + " not supported");
    }
diff --git a/src/lib/modes/cfb/cfb.h b/src/lib/modes/cfb/cfb.h
index ae10e318f..190243477 100644
--- a/src/lib/modes/cfb/cfb.h
+++ b/src/lib/modes/cfb/cfb.h
@@ -38,7 +38,7 @@ class CFB_Mode : public Cipher_Mode
 
       void reset() override final;
    protected:
-      CFB_Mode(BlockCipher* cipher, size_t feedback_bits);
+      CFB_Mode(std::unique_ptr<BlockCipher> cipher, size_t feedback_bits);
 
       void shift_register();
 
@@ -71,8 +71,8 @@ class CFB_Encryption final : public CFB_Mode
       * @param feedback_bits number of bits fed back into the shift register,
       * must be a multiple of 8
       */
-      CFB_Encryption(BlockCipher* cipher, size_t feedback_bits) :
-         CFB_Mode(cipher, feedback_bits) {}
+      CFB_Encryption(std::unique_ptr<BlockCipher> cipher, size_t feedback_bits) :
+         CFB_Mode(std::move(cipher), feedback_bits) {}
 
       size_t process(uint8_t buf[], size_t size) override;
 
@@ -91,8 +91,8 @@ class CFB_Decryption final : public CFB_Mode
       * @param feedback_bits number of bits fed back into the shift register,
       * must be a multiple of 8
       */
-      CFB_Decryption(BlockCipher* cipher, size_t feedback_bits) :
-         CFB_Mode(cipher, feedback_bits) {}
+      CFB_Decryption(std::unique_ptr<BlockCipher> cipher, size_t feedback_bits) :
+         CFB_Mode(std::move(cipher), feedback_bits) {}
 
       size_t process(uint8_t buf[], size_t size) override;
 
diff --git a/src/lib/modes/cipher_mode.cpp b/src/lib/modes/cipher_mode.cpp
index ee41ff1ad..a1d80a586 100644
--- a/src/lib/modes/cipher_mode.cpp
+++ b/src/lib/modes/cipher_mode.cpp
@@ -84,14 +84,14 @@ std::unique_ptr<Cipher_Mode> Cipher_Mode::create(const std::string& algo,
 #if defined(BOTAN_HAS_STREAM_CIPHER)
    if(auto sc = StreamCipher::create(algo))
       {
-      return std::make_unique<Stream_Cipher_Mode>(sc.release());
+      return std::make_unique<Stream_Cipher_Mode>(std::move(sc));
       }
 #endif
 
 #if defined(BOTAN_HAS_AEAD_MODES)
    if(auto aead = AEAD_Mode::create(algo, direction))
       {
-      return std::unique_ptr<Cipher_Mode>(aead.release());
+      return aead;
       }
 #endif
 
@@ -141,9 +141,9 @@ std::unique_ptr<Cipher_Mode> Cipher_Mode::create(const std::string& algo,
       if(padding == "CTS")
          {
          if(direction == ENCRYPTION)
-            return std::make_unique<CTS_Encryption>(bc.release());
+            return std::make_unique<CTS_Encryption>(std::move(bc));
          else
-            return std::make_unique<CTS_Decryption>(bc.release());
+            return std::make_unique<CTS_Decryption>(std::move(bc));
          }
       else
          {
@@ -152,9 +152,9 @@ std::unique_ptr<Cipher_Mode> Cipher_Mode::create(const std::string& algo,
          if(pad)
             {
             if(direction == ENCRYPTION)
-               return std::make_unique<CBC_Encryption>(bc.release(), pad.release());
+               return std::make_unique<CBC_Encryption>(std::move(bc), std::move(pad));
             else
-               return std::make_unique<CBC_Decryption>(bc.release(), pad.release());
+               return std::make_unique<CBC_Decryption>(std::move(bc), std::move(pad));
             }
          }
       }
@@ -164,9 +164,9 @@ std::unique_ptr<Cipher_Mode> Cipher_Mode::create(const std::string& algo,
    if(spec.algo_name() == "XTS")
       {
       if(direction == ENCRYPTION)
-         return std::make_unique<XTS_Encryption>(bc.release());
+         return std::make_unique<XTS_Encryption>(std::move(bc));
       else
-         return std::make_unique<XTS_Decryption>(bc.release());
+         return std::make_unique<XTS_Decryption>(std::move(bc));
       }
 #endif
 
@@ -175,9 +175,9 @@ std::unique_ptr<Cipher_Mode> Cipher_Mode::create(const std::string& algo,
       {
       const size_t feedback_bits = spec.arg_as_integer(1, 8*bc->block_size());
       if(direction == ENCRYPTION)
-         return std::make_unique<CFB_Encryption>(bc.release(), feedback_bits);
+         return std::make_unique<CFB_Encryption>(std::move(bc), feedback_bits);
       else
-         return std::make_unique<CFB_Decryption>(bc.release(), feedback_bits);
+         return std::make_unique<CFB_Decryption>(std::move(bc), feedback_bits);
       }
 #endif
 
diff --git a/src/lib/modes/stream_mode.h b/src/lib/modes/stream_mode.h
index 4d06e1e32..a7c34be8c 100644
--- a/src/lib/modes/stream_mode.h
+++ b/src/lib/modes/stream_mode.h
@@ -24,7 +24,8 @@ class Stream_Cipher_Mode final : public Cipher_Mode
       /**
       * @param cipher underyling stream cipher
       */
-      explicit Stream_Cipher_Mode(StreamCipher* cipher) : m_cipher(cipher) {}
+      explicit Stream_Cipher_Mode(std::unique_ptr<StreamCipher> cipher) :
+         m_cipher(std::move(cipher)) {}
 
       size_t process(uint8_t buf[], size_t sz) override
          {
diff --git a/src/lib/modes/xts/xts.cpp b/src/lib/modes/xts/xts.cpp
index 725807188..f8f36d522 100644
--- a/src/lib/modes/xts/xts.cpp
+++ b/src/lib/modes/xts/xts.cpp
@@ -11,8 +11,8 @@
 
 namespace Botan {
 
-XTS_Mode::XTS_Mode(BlockCipher* cipher) :
-   m_cipher(cipher),
+XTS_Mode::XTS_Mode(std::unique_ptr<BlockCipher> cipher) :
+   m_cipher(std::move(cipher)),
    m_cipher_block_size(m_cipher->block_size()),
    m_cipher_parallelism(m_cipher->parallel_bytes())
    {
@@ -21,7 +21,7 @@ XTS_Mode::XTS_Mode(BlockCipher* cipher) :
       throw Invalid_Argument("Cannot use " + cipher->name() + " with XTS");
       }
 
-   m_tweak_cipher.reset(m_cipher->clone());
+   m_tweak_cipher = m_cipher->new_object();
    }
 
 void XTS_Mode::clear()
diff --git a/src/lib/modes/xts/xts.h b/src/lib/modes/xts/xts.h
index cd268e067..bcba08020 100644
--- a/src/lib/modes/xts/xts.h
+++ b/src/lib/modes/xts/xts.h
@@ -37,7 +37,7 @@ class XTS_Mode : public Cipher_Mode
       void reset() override;
 
    protected:
-      explicit XTS_Mode(BlockCipher* cipher);
+      explicit XTS_Mode(std::unique_ptr<BlockCipher> cipher);
 
       const uint8_t* tweak() const { return m_tweak.data(); }
 
@@ -69,7 +69,8 @@ class XTS_Encryption final : public XTS_Mode
       /**
       * @param cipher underlying block cipher
       */
-      explicit XTS_Encryption(BlockCipher* cipher) : XTS_Mode(cipher) {}
+      explicit XTS_Encryption(std::unique_ptr<BlockCipher> cipher) :
+         XTS_Mode(std::move(cipher)) {}
 
       size_t process(uint8_t buf[], size_t size) override;
 
@@ -87,7 +88,8 @@ class XTS_Decryption final : public XTS_Mode
       /**
       * @param cipher underlying block cipher
       */
-      explicit XTS_Decryption(BlockCipher* cipher) : XTS_Mode(cipher) {}
+      explicit XTS_Decryption(std::unique_ptr<BlockCipher> cipher) :
+         XTS_Mode(std::move(cipher)) {}
 
       size_t process(uint8_t buf[], size_t size) override;
 
diff --git a/src/lib/prov/commoncrypto/commoncrypto.h b/src/lib/prov/commoncrypto/commoncrypto.h
index 31fa110fc..5e17adc0a 100644
--- a/src/lib/prov/commoncrypto/commoncrypto.h
+++ b/src/lib/prov/commoncrypto/commoncrypto.h
@@ -45,7 +45,7 @@ class BOTAN_PUBLIC_API(2, 0) CommonCrypto_Error final : public Exception
 
 /* Cipher Modes */
 
-Cipher_Mode*
+std::unique_ptr<Cipher_Mode>
 make_commoncrypto_cipher_mode(const std::string& name, Cipher_Dir direction);
 
 /* Block Ciphers */
diff --git a/src/lib/prov/commoncrypto/commoncrypto_mode.cpp b/src/lib/prov/commoncrypto/commoncrypto_mode.cpp
index 82d4bd552..7e9ab7b31 100644
--- a/src/lib/prov/commoncrypto/commoncrypto_mode.cpp
+++ b/src/lib/prov/commoncrypto/commoncrypto_mode.cpp
@@ -230,14 +230,14 @@ void CommonCrypto_Cipher_Mode::key_schedule(const uint8_t key[], size_t length)
    }
 }
 
-Cipher_Mode*
+std::unique_ptr<Cipher_Mode>
 make_commoncrypto_cipher_mode(const std::string& name, Cipher_Dir direction)
    {
 
    try
       {
       CommonCryptor_Opts opts = commoncrypto_opts_from_algo(name);
-      return new CommonCrypto_Cipher_Mode(name, direction, opts);
+      return std::make_unique<CommonCrypto_Cipher_Mode>(name, direction, opts);
       }
    catch(CommonCrypto_Error& e)
       {
diff --git a/src/lib/prov/openssl/openssl.h b/src/lib/prov/openssl/openssl.h
index 17bbf650d..20cd44159 100644
--- a/src/lib/prov/openssl/openssl.h
+++ b/src/lib/prov/openssl/openssl.h
@@ -52,7 +52,7 @@ make_openssl_block_cipher(const std::string& name);
 
 /* Cipher Modes */
 
-Cipher_Mode*
+std::unique_ptr<Cipher_Mode>
 make_openssl_cipher_mode(const std::string& name, Cipher_Dir direction);
 
 /* Hash */
diff --git a/src/lib/prov/openssl/openssl_mode.cpp b/src/lib/prov/openssl/openssl_mode.cpp
index bdb2f0ca7..eed6670aa 100644
--- a/src/lib/prov/openssl/openssl_mode.cpp
+++ b/src/lib/prov/openssl/openssl_mode.cpp
@@ -211,11 +211,11 @@ void OpenSSL_Cipher_Mode::key_schedule(const uint8_t key[], size_t length)
 
 }
 
-Cipher_Mode*
+std::unique_ptr<Cipher_Mode>
 make_openssl_cipher_mode(const std::string& name, Cipher_Dir direction)
    {
 #define MAKE_OPENSSL_MODE(evp_fn) \
-   new OpenSSL_Cipher_Mode(name, (evp_fn)(), direction)
+   std::make_unique<OpenSSL_Cipher_Mode>(name, (evp_fn)(), direction)
 
 #if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_MODE_CBC) && !defined(OPENSSL_NO_AES)
    if(name == "AES-128/CBC/NoPadding")
diff --git a/src/lib/pubkey/xmss/xmss_hash.cpp b/src/lib/pubkey/xmss/xmss_hash.cpp
index cd714873c..8e4de06fd 100644
--- a/src/lib/pubkey/xmss/xmss_hash.cpp
+++ b/src/lib/pubkey/xmss/xmss_hash.cpp
@@ -29,7 +29,7 @@ XMSS_Hash::XMSS_Hash(const std::string& h_func_name) :
    BOTAN_ASSERT(m_output_length > 0, "Hash output length of zero is invalid.");
 
    m_zero_padding.resize(m_output_length - 1);
-   m_msg_hash.reset(m_hash->clone());
+   m_msg_hash = m_hash->new_object();
    }
 
 void
diff --git a/src/lib/tls/tls_cbc/tls_cbc.cpp b/src/lib/tls/tls_cbc/tls_cbc.cpp
index d2270e3b0..70a181c7c 100644
--- a/src/lib/tls/tls_cbc/tls_cbc.cpp
+++ b/src/lib/tls/tls_cbc/tls_cbc.cpp
@@ -46,10 +46,11 @@ TLS_CBC_HMAC_AEAD_Mode::TLS_CBC_HMAC_AEAD_Mode(Cipher_Dir dir,
 
    m_mac = std::move(mac);
 
+   auto null_padding = std::make_unique<Null_Padding>();
    if(dir == ENCRYPTION)
-      m_cbc.reset(new CBC_Encryption(cipher.release(), new Null_Padding));
+      m_cbc.reset(new CBC_Encryption(std::move(cipher), std::move(null_padding)));
    else
-      m_cbc.reset(new CBC_Decryption(cipher.release(), new Null_Padding));
+      m_cbc.reset(new CBC_Decryption(std::move(cipher), std::move(null_padding)));
    }
 
 void TLS_CBC_HMAC_AEAD_Mode::clear()


Test patch:
diff --git a/src/tests/test_ocb.cpp b/src/tests/test_ocb.cpp
index dbb9cbadc..21e6e330d 100644
--- a/src/tests/test_ocb.cpp
+++ b/src/tests/test_ocb.cpp
@@ -130,14 +130,16 @@ class OCB_Wide_KAT_Tests final : public Text_Based_Test
          const size_t bs = key.size();
          Botan::secure_vector<uint8_t> buf(input.begin(), input.end());
 
-         Botan::OCB_Encryption enc(new OCB_Wide_Test_Block_Cipher(bs), std::min<size_t>(bs, 32));
+         Botan::OCB_Encryption enc(std::make_unique<OCB_Wide_Test_Block_Cipher>(bs),
+                                   std::min<size_t>(bs, 32));
          enc.set_key(key);
          enc.set_ad(ad);
          enc.start(nonce);
          enc.finish(buf);
          result.test_eq("Ciphertext matches", buf, expected);
 
-         Botan::OCB_Decryption dec(new OCB_Wide_Test_Block_Cipher(bs), std::min<size_t>(bs, 32));
+         Botan::OCB_Decryption dec(std::make_unique<OCB_Wide_Test_Block_Cipher>(bs),
+                                   std::min<size_t>(bs, 32));
          dec.set_key(key);
          dec.set_ad(ad);
          dec.start(nonce);
@@ -189,7 +191,7 @@ class OCB_Wide_Long_KAT_Tests final : public Text_Based_Test
             cipher.reset(new OCB_Wide_Test_Block_Cipher(bs));
             }
 
-         Botan::OCB_Encryption enc(cipher.release(), std::min<size_t>(bs, 32));
+         Botan::OCB_Encryption enc(std::move(cipher), std::min<size_t>(bs, 32));
 
          /*
          Y, string of length min(B, 256) bits
@@ -286,8 +288,8 @@ class OCB_Long_KAT_Tests final : public Text_Based_Test
 
          std::unique_ptr<Botan::BlockCipher> aes(Botan::BlockCipher::create_or_throw(algo));
 
-         Botan::OCB_Encryption enc(aes->clone(), taglen / 8);
-         Botan::OCB_Decryption dec(aes->clone(), taglen / 8);
+         Botan::OCB_Encryption enc(aes->new_object(), taglen / 8);
+         Botan::OCB_Decryption dec(std::move(aes), taglen / 8);
 
          std::vector<uint8_t> key(keylen / 8);
          key[keylen / 8 - 1] = static_cast<uint8_t>(taglen);