https://github.com/randombit/botan/commit/e61a5f56fb404db3655909be4ce23c3a816cbb60

Port EVP_BlockCipher class to OpenSSL 1.1 API

Index: src/engine/openssl/ossl_bc.cpp
--- src/engine/openssl/ossl_bc.cpp.orig
+++ src/engine/openssl/ossl_bc.cpp
@@ -8,7 +8,7 @@
 #include <botan/internal/openssl_engine.h>
 #include <openssl/evp.h>
 
-#if OPENSSL_VERSION_NUMBER >= 0x10100000
+#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
   #error "OpenSSL 1.1 API not supported in Botan 1.10, upgrade to 2.x"
 #endif
 
@@ -44,7 +44,7 @@ class EVP_BlockCipher : public BlockCipher
       size_t block_sz;
       Key_Length_Specification cipher_key_spec;
       std::string cipher_name;
-      mutable EVP_CIPHER_CTX encrypt, decrypt;
+      mutable EVP_CIPHER_CTX *encrypt, *decrypt;
    };
 
 /*
@@ -59,14 +59,16 @@ EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* alg
    if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
       throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
 
-   EVP_CIPHER_CTX_init(&encrypt);
-   EVP_CIPHER_CTX_init(&decrypt);
+   encrypt = EVP_CIPHER_CTX_new();
+   decrypt = EVP_CIPHER_CTX_new();
+   if(encrypt == NULL || decrypt == NULL)
+      throw Internal_Error("EVP_CIPHER_CTX_new failed");
 
-   EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
-   EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+   EVP_EncryptInit_ex(encrypt, algo, 0, 0, 0);
+   EVP_DecryptInit_ex(decrypt, algo, 0, 0, 0);
 
-   EVP_CIPHER_CTX_set_padding(&encrypt, 0);
-   EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+   EVP_CIPHER_CTX_set_padding(encrypt, 0);
+   EVP_CIPHER_CTX_set_padding(decrypt, 0);
    }
 
 /*
@@ -83,14 +85,16 @@ EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* alg
    if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
       throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
 
-   EVP_CIPHER_CTX_init(&encrypt);
-   EVP_CIPHER_CTX_init(&decrypt);
+   encrypt = EVP_CIPHER_CTX_new();
+   decrypt = EVP_CIPHER_CTX_new();
+   if(encrypt == NULL || decrypt == NULL)
+      throw Internal_Error("EVP_CIPHER_CTX_new failed");
 
-   EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
-   EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+   EVP_EncryptInit_ex(encrypt, algo, 0, 0, 0);
+   EVP_DecryptInit_ex(decrypt, algo, 0, 0, 0);
 
-   EVP_CIPHER_CTX_set_padding(&encrypt, 0);
-   EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+   EVP_CIPHER_CTX_set_padding(encrypt, 0);
+   EVP_CIPHER_CTX_set_padding(decrypt, 0);
    }
 
 /*
@@ -98,8 +102,8 @@ EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* alg
 */
 EVP_BlockCipher::~EVP_BlockCipher()
    {
-   EVP_CIPHER_CTX_cleanup(&encrypt);
-   EVP_CIPHER_CTX_cleanup(&decrypt);
+   EVP_CIPHER_CTX_free(encrypt);
+   EVP_CIPHER_CTX_free(decrypt);
    }
 
 /*
@@ -109,7 +113,7 @@ void EVP_BlockCipher::encrypt_n(const byte in[], byte 
                                 size_t blocks) const
    {
    int out_len = 0;
-   EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * block_sz);
+   EVP_EncryptUpdate(encrypt, out, &out_len, in, blocks * block_sz);
    }
 
 /*
@@ -119,7 +123,7 @@ void EVP_BlockCipher::decrypt_n(const byte in[], byte 
                                 size_t blocks) const
    {
    int out_len = 0;
-   EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * block_sz);
+   EVP_DecryptUpdate(decrypt, out, &out_len, in, blocks * block_sz);
    }
 
 /*
@@ -134,19 +138,19 @@ void EVP_BlockCipher::key_schedule(const byte key[], s
       full_key += std::make_pair(key, 8);
       }
    else
-      if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 ||
-         EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0)
+      if(EVP_CIPHER_CTX_set_key_length(encrypt, length) == 0 ||
+         EVP_CIPHER_CTX_set_key_length(decrypt, length) == 0)
          throw Invalid_Argument("EVP_BlockCipher: Bad key length for " +
                                 cipher_name);
 
    if(cipher_name == "RC2")
       {
-      EVP_CIPHER_CTX_ctrl(&encrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
-      EVP_CIPHER_CTX_ctrl(&decrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
+      EVP_CIPHER_CTX_ctrl(encrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
+      EVP_CIPHER_CTX_ctrl(decrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
       }
 
-   EVP_EncryptInit_ex(&encrypt, 0, 0, full_key.begin(), 0);
-   EVP_DecryptInit_ex(&decrypt, 0, 0, full_key.begin(), 0);
+   EVP_EncryptInit_ex(encrypt, 0, 0, full_key.begin(), 0);
+   EVP_DecryptInit_ex(decrypt, 0, 0, full_key.begin(), 0);
    }
 
 /*
@@ -154,7 +158,7 @@ void EVP_BlockCipher::key_schedule(const byte key[], s
 */
 BlockCipher* EVP_BlockCipher::clone() const
    {
-   return new EVP_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt),
+   return new EVP_BlockCipher(EVP_CIPHER_CTX_cipher(encrypt),
                               cipher_name,
                               cipher_key_spec.minimum_keylength(),
                               cipher_key_spec.maximum_keylength(),
@@ -166,16 +170,14 @@ BlockCipher* EVP_BlockCipher::clone() const
 */
 void EVP_BlockCipher::clear()
    {
-   const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt);
+   const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(encrypt);
 
-   EVP_CIPHER_CTX_cleanup(&encrypt);
-   EVP_CIPHER_CTX_cleanup(&decrypt);
-   EVP_CIPHER_CTX_init(&encrypt);
-   EVP_CIPHER_CTX_init(&decrypt);
-   EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
-   EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
-   EVP_CIPHER_CTX_set_padding(&encrypt, 0);
-   EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+   EVP_CIPHER_CTX_cleanup(encrypt);
+   EVP_CIPHER_CTX_cleanup(decrypt);
+   EVP_EncryptInit_ex(encrypt, algo, 0, 0, 0);
+   EVP_DecryptInit_ex(decrypt, algo, 0, 0, 0);
+   EVP_CIPHER_CTX_set_padding(encrypt, 0);
+   EVP_CIPHER_CTX_set_padding(decrypt, 0);
    }
 
 }
