Blame SOURCES/0005-rhbz-1618703-Allow-to-use-OpenSSL-as-backend-for-rtl.patch

55db36
From cb0fdfa1d2d98880839dda8114b0af7c4254bc86 Mon Sep 17 00:00:00 2001
55db36
From: Stephan Bergmann <sbergman@redhat.com>
55db36
Date: Wed, 22 Aug 2018 09:49:25 +0200
55db36
Subject: [PATCH 5/5] rhbz#1618703: Allow to use OpenSSL as backend for
55db36
 rtl/cipher.h
55db36
MIME-Version: 1.0
55db36
Content-Type: text/plain; charset=UTF-8
55db36
Content-Transfer-Encoding: 8bit
55db36
55db36
...with new configuration option --enable-cipher-openssl-backend
55db36
55db36
rtl/cipher.h (which is part of the stable URE interface) offers functionality to
55db36
en-/decrypt data with Blowfish in ECB, CBC, and streaming CFB mode, and with RC4
55db36
(aka ARCFOUR; which is a stream cipher).  LO itself only uses Blowfish CFB and
55db36
RC4, so only those are wired to OpenSSL for now, for simplicity.  Using Blowfish
55db36
ECB and CBC, or Blowfish CFB in DirectionBoth mode would cause failures for now
55db36
(cf. sal/qa/rtl/cipher/rtl_cipher.cxx); the assumption is that no external code
55db36
actually makes use of this functionality.
55db36
55db36
Using NSS instead of OpenSSL could be an alternative, but there appears to be no
55db36
support in NSS for Blowfish in streaming CFB mode, only CKM_BLOWFISH_CBC for
55db36
CBC mode.
55db36
55db36
Reviewed-on: https://gerrit.libreoffice.org/59428
55db36
Tested-by: Jenkins
55db36
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
55db36
(cherry picked from commit 4bc16aeb73c1201f187742e0fefe35521fae77ac)
55db36
Reviewed-on: https://gerrit.libreoffice.org/59575
55db36
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
55db36
Tested-by: Caolán McNamara <caolanm@redhat.com>
55db36
55db36
(cherry picked from commit 062ac27d7052bcdf0bdd5db978e041d4c614fd6b)
55db36
Conflicts:
55db36
	sal/rtl/cipher.cxx
55db36
55db36
Change-Id: I0bc042961539ed46844c96cb1c808209578528a0
55db36
---
55db36
 config_host.mk.in                |   1 +
55db36
 configure.ac                     |  23 +++++
55db36
 sal/CppunitTest_sal_rtl.mk       |   4 +
55db36
 sal/Library_sal.mk               |   8 ++
55db36
 sal/qa/rtl/cipher/rtl_cipher.cxx |  61 +++++++++++
55db36
 sal/rtl/cipher.cxx               | 167 ++++++++++++++++++++++++++++++-
55db36
 6 files changed, 260 insertions(+), 4 deletions(-)
55db36
55db36
diff --git a/config_host.mk.in b/config_host.mk.in
55db36
index 8cbbc5fee1d5..e683a5ac883c 100644
55db36
--- a/config_host.mk.in
55db36
+++ b/config_host.mk.in
55db36
@@ -109,6 +109,7 @@ export ENABLE_AVAHI=@ENABLE_AVAHI@
55db36
 export ENABLE_BREAKPAD=@ENABLE_BREAKPAD@
55db36
 export ENABLE_CAIRO_CANVAS=@ENABLE_CAIRO_CANVAS@
55db36
 export ENABLE_CHART_TESTS=@ENABLE_CHART_TESTS@
55db36
+export ENABLE_CIPHER_OPENSSL_BACKEND=@ENABLE_CIPHER_OPENSSL_BACKEND@
55db36
 export ENABLE_LIBCMIS=@ENABLE_LIBCMIS@
55db36
 export ENABLE_COINMP=@ENABLE_COINMP@
55db36
 export SYSTEM_COINMP=@SYSTEM_COINMP@
55db36
diff --git a/configure.ac b/configure.ac
55db36
index 938d20571242..70890733a2a8 100644
55db36
--- a/configure.ac
55db36
+++ b/configure.ac
55db36
@@ -1392,6 +1392,11 @@ AC_ARG_ENABLE(openssl,
55db36
          use only if you are hacking on it.]),
55db36
 ,enable_openssl=yes)
55db36
 
55db36
+libo_FUZZ_ARG_ENABLE(cipher-openssl-backend,
55db36
+    AS_HELP_STRING([--enable-cipher-openssl-backend],
55db36
+        [Enable using OpenSSL as the actual implementation of the rtl/cipher.h functionality.
55db36
+         Requires --enable-openssl.]))
55db36
+
55db36
 AC_ARG_ENABLE(library-bin-tar,
55db36
     AS_HELP_STRING([--enable-library-bin-tar],
55db36
         [Enable the building and reused of tarball of binary build for some 'external' libraries.
55db36
@@ -9240,6 +9245,24 @@ fi
55db36
 
55db36
 AC_SUBST([DISABLE_OPENSSL])
55db36
 
55db36
+if test "$enable_cipher_openssl_backend" = yes && test "$DISABLE_OPENSSL" = TRUE; then
55db36
+    if test "$libo_fuzzed_enable_cipher_openssl_backend" = yes; then
55db36
+        AC_MSG_NOTICE([Resetting --enable-cipher-openssl-backend=no])
55db36
+        enable_cipher_openssl_backend=no
55db36
+    else
55db36
+        AC_MSG_ERROR([--enable-cipher-openssl-backend needs OpenSSL, but --disable-openssl was given.])
55db36
+    fi
55db36
+fi
55db36
+AC_MSG_CHECKING([whether to enable the OpenSSL backend for rtl/cipher.h])
55db36
+ENABLE_CIPHER_OPENSSL_BACKEND=
55db36
+if test "$enable_cipher_openssl_backend" = yes; then
55db36
+    AC_MSG_RESULT([yes])
55db36
+    ENABLE_CIPHER_OPENSSL_BACKEND=TRUE
55db36
+else
55db36
+    AC_MSG_RESULT([no])
55db36
+fi
55db36
+AC_SUBST([ENABLE_CIPHER_OPENSSL_BACKEND])
55db36
+
55db36
 dnl ===================================================================
55db36
 dnl Check for building gnutls
55db36
 dnl ===================================================================
55db36
diff --git a/sal/CppunitTest_sal_rtl.mk b/sal/CppunitTest_sal_rtl.mk
55db36
index 43533fc5ab1c..c2eaa72daa26 100644
55db36
--- a/sal/CppunitTest_sal_rtl.mk
55db36
+++ b/sal/CppunitTest_sal_rtl.mk
55db36
@@ -63,4 +63,8 @@ $(call gb_CppunitTest_get_target,sal_rtl) : \
55db36
 
55db36
 $(eval $(call gb_CppunitTest_use_external,sal_rtl,boost_headers))
55db36
 
55db36
+ifeq ($(ENABLE_CIPHER_OPENSSL_BACKEND),TRUE)
55db36
+$(eval $(call gb_CppunitTest_add_defs,sal_rtl,-DLIBO_CIPHER_OPENSSL_BACKEND))
55db36
+endif
55db36
+
55db36
 # vim: set noet sw=4 ts=4:
55db36
diff --git a/sal/Library_sal.mk b/sal/Library_sal.mk
55db36
index 17d89ae79e4a..bce0437a19bf 100644
55db36
--- a/sal/Library_sal.mk
55db36
+++ b/sal/Library_sal.mk
55db36
@@ -255,4 +255,12 @@ $(eval $(call gb_Library_add_exception_objects,sal,\
55db36
 
55db36
 endif # ifneq ($(OS),WNT)
55db36
 
55db36
+ifeq ($(ENABLE_CIPHER_OPENSSL_BACKEND),TRUE)
55db36
+$(eval $(call gb_Library_add_defs,sal,-DLIBO_CIPHER_OPENSSL_BACKEND))
55db36
+$(eval $(call gb_Library_use_externals,sal, \
55db36
+    openssl \
55db36
+    openssl_headers \
55db36
+))
55db36
+endif
55db36
+
55db36
 # vim: set noet sw=4 ts=4:
55db36
diff --git a/sal/qa/rtl/cipher/rtl_cipher.cxx b/sal/qa/rtl/cipher/rtl_cipher.cxx
55db36
index e8877a92c5d5..57c22eb573ac 100644
55db36
--- a/sal/qa/rtl/cipher/rtl_cipher.cxx
55db36
+++ b/sal/qa/rtl/cipher/rtl_cipher.cxx
55db36
@@ -37,8 +37,12 @@ public:
55db36
     void create_001()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
     void create_002()
55db36
         {
55db36
@@ -48,8 +52,12 @@ public:
55db36
     void create_003()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeCBC);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
     void create_004()
55db36
         {
55db36
@@ -101,14 +109,22 @@ public:
55db36
     void createBF_001()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_createBF(rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
     void createBF_002()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_createBF(rtl_Cipher_ModeCBC);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
     void createBF_003()
55db36
         {
55db36
@@ -141,6 +157,12 @@ public:
55db36
     void test_encode(sal_uInt8 _nKeyValue, sal_uInt8 _nArgValue, rtl::OString const& _sPlainTextStr)
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+            (void) _nKeyValue;
55db36
+            (void) _nArgValue;
55db36
+            (void) _sPlainTextStr;
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
 
55db36
             sal_uInt32     nKeyLen = 16;
55db36
@@ -184,11 +206,18 @@ public:
55db36
             delete [] pKeyBuffer;
55db36
 
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
 
55db36
     void test_encode_and_decode(sal_uInt8 _nKeyValue, sal_uInt8 _nArgValue, rtl::OString const& _sPlainTextStr)
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+            (void) _nKeyValue;
55db36
+            (void) _nArgValue;
55db36
+            (void) _sPlainTextStr;
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
 
55db36
             sal_uInt32     nKeyLen = 16;
55db36
@@ -236,6 +265,7 @@ public:
55db36
             delete [] pKeyBuffer;
55db36
 
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
 
55db36
     void decode_001()
55db36
@@ -286,8 +316,12 @@ public:
55db36
     void destroy_001()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeCBC);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
     // Change the following lines only, if you add, remove or rename
55db36
     // member functions of the current class,
55db36
@@ -305,10 +339,14 @@ public:
55db36
     void destroyBF_001()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_createBF(rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
             rtl_cipher_destroyBF(aCipher);
55db36
             // more proforma
55db36
             // should not GPF
55db36
+#endif
55db36
         }
55db36
     // Change the following lines only, if you add, remove or rename
55db36
     // member functions of the current class,
55db36
@@ -326,6 +364,12 @@ public:
55db36
     void test_encode(sal_uInt8 _nKeyValue, sal_uInt8 _nArgValue, sal_uInt8 _nDataValue)
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+            (void) _nKeyValue;
55db36
+            (void) _nArgValue;
55db36
+            (void) _nDataValue;
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
 
55db36
             sal_uInt32     nKeyLen = 16;
55db36
@@ -360,6 +404,7 @@ public:
55db36
             delete [] pKeyBuffer;
55db36
 
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
 
55db36
     void encode_001()
55db36
@@ -407,6 +452,9 @@ public:
55db36
     void init_001()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
 
55db36
             sal_uInt32     nKeyLen = 16;
55db36
@@ -424,11 +472,15 @@ public:
55db36
             delete [] pKeyBuffer;
55db36
 
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
 
55db36
     void init_002()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
 
55db36
             sal_uInt32     nKeyLen = 16;
55db36
@@ -447,10 +499,14 @@ public:
55db36
             delete [] pKeyBuffer;
55db36
 
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
     void init_003()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
 
55db36
             sal_uInt32     nKeyLen = 16;
55db36
@@ -469,10 +525,14 @@ public:
55db36
             delete [] pKeyBuffer;
55db36
 
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
     void init_004()
55db36
         {
55db36
             rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
55db36
+#else
55db36
             CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
55db36
 
55db36
             sal_uInt32     nKeyLen = 16;
55db36
@@ -492,6 +552,7 @@ public:
55db36
             delete [] pKeyBuffer;
55db36
 
55db36
             rtl_cipher_destroy(aCipher);
55db36
+#endif
55db36
         }
55db36
     // Change the following lines only, if you add, remove or rename
55db36
     // member functions of the current class,
55db36
diff --git a/sal/rtl/cipher.cxx b/sal/rtl/cipher.cxx
55db36
index 80e096f5a3a1..9dd649848eff 100644
55db36
--- a/sal/rtl/cipher.cxx
55db36
+++ b/sal/rtl/cipher.cxx
55db36
@@ -22,7 +22,16 @@
55db36
 #include <sal/types.h>
55db36
 #include <rtl/alloc.h>
55db36
 #include <rtl/cipher.h>
55db36
+#include <algorithm>
55db36
+#include <cassert>
55db36
+#include <cstring>
55db36
+#include <limits>
55db36
 
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+#include <openssl/evp.h>
55db36
+#endif
55db36
+
55db36
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
 #define RTL_CIPHER_NTOHL(c, l) \
55db36
     ((l)  = ((sal_uInt32)(*((c)++))) << 24, \
55db36
      (l) |= ((sal_uInt32)(*((c)++))) << 16, \
55db36
@@ -81,6 +90,7 @@
55db36
         case 1: *(--(c)) = (sal_uInt8)(((xl) >> 24) & 0xff); \
55db36
     } \
55db36
 }
55db36
+#endif
55db36
 
55db36
 typedef rtlCipherError(SAL_CALL cipher_init_t) (
55db36
     rtlCipher          Cipher,
55db36
@@ -182,6 +192,7 @@ void SAL_CALL rtl_cipher_destroy(rtlCipher Cipher) SAL_THROW_EXTERN_C()
55db36
         pImpl->m_delete(Cipher);
55db36
 }
55db36
 
55db36
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
 #define CIPHER_ROUNDS_BF 16
55db36
 
55db36
 struct CipherKeyBF
55db36
@@ -189,9 +200,13 @@ struct CipherKeyBF
55db36
     sal_uInt32 m_S[4][256];
55db36
     sal_uInt32 m_P[CIPHER_ROUNDS_BF + 2];
55db36
 };
55db36
+#endif
55db36
 
55db36
 struct CipherContextBF
55db36
 {
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+    EVP_CIPHER_CTX * m_context;
55db36
+#else
55db36
     CipherKeyBF    m_key;
55db36
     union
55db36
     {
55db36
@@ -199,6 +214,7 @@ struct CipherContextBF
55db36
         sal_uInt8  m_byte[8];
55db36
     } m_iv;
55db36
     sal_uInt32     m_offset;
55db36
+#endif
55db36
 };
55db36
 
55db36
 struct CipherBF_Impl
55db36
@@ -207,11 +223,13 @@ struct CipherBF_Impl
55db36
     CipherContextBF m_context;
55db36
 };
55db36
 
55db36
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
 static rtlCipherError BF_init(
55db36
     CipherContextBF *ctx,
55db36
     rtlCipherMode    eMode,
55db36
     const sal_uInt8 *pKeyData, sal_Size nKeyLen,
55db36
     const sal_uInt8 *pArgData, sal_Size nArgLen);
55db36
+#endif
55db36
 
55db36
 static rtlCipherError BF_update(
55db36
     CipherContextBF    *ctx,
55db36
@@ -220,6 +238,7 @@ static rtlCipherError BF_update(
55db36
     const sal_uInt8    *pData,   sal_Size nDatLen,
55db36
     sal_uInt8          *pBuffer, sal_Size nBufLen);
55db36
 
55db36
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
 static void BF_updateECB(
55db36
     CipherContextBF    *ctx,
55db36
     rtlCipherDirection  direction,
55db36
@@ -608,7 +627,9 @@ static const CipherKeyBF BF_key =
55db36
         0x9216D5D9L, 0x8979FB1BL
55db36
     }
55db36
 };
55db36
+#endif
55db36
 
55db36
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
 static rtlCipherError BF_init(
55db36
     CipherContextBF *ctx,
55db36
     rtlCipherMode    eMode,
55db36
@@ -675,6 +696,7 @@ static rtlCipherError BF_init(
55db36
 
55db36
     return rtl_Cipher_E_None;
55db36
 }
55db36
+#endif
55db36
 
55db36
 static rtlCipherError BF_update(
55db36
     CipherContextBF    *ctx,
55db36
@@ -691,6 +713,31 @@ static rtlCipherError BF_update(
55db36
         return rtl_Cipher_E_BufferSize;
55db36
 
55db36
     /* Update. */
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+    assert(eMode == rtl_Cipher_ModeStream);
55db36
+    (void) eDirection;
55db36
+    while (nDatLen > std::numeric_limits<int>::max()) {
55db36
+        int outl;
55db36
+        if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, std::numeric_limits<int>::max())
55db36
+            == 0)
55db36
+        {
55db36
+            return rtl_Cipher_E_Unknown;
55db36
+        }
55db36
+        assert(outl == std::numeric_limits<int>::max());
55db36
+        pData += std::numeric_limits<int>::max();
55db36
+        nDatLen -= std::numeric_limits<int>::max();
55db36
+        pBuffer += std::numeric_limits<int>::max();
55db36
+    }
55db36
+    int outl;
55db36
+    if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, static_cast<int>(nDatLen)) == 0)
55db36
+    {
55db36
+        return rtl_Cipher_E_Unknown;
55db36
+    }
55db36
+    assert(outl == static_cast<int>(nDatLen));
55db36
+    // A final call to EVP_CipherFinal_ex is intentionally missing; it wouldn't fit the rtl/cipher.h
55db36
+    // interface, and is hopefully not needed, as each individual Blowfish CFB update step doesn't
55db36
+    // hold back any data that would need to be finally flushed.
55db36
+#else
55db36
     if (eMode == rtl_Cipher_ModeECB)
55db36
     {
55db36
         /* Block mode. */
55db36
@@ -726,9 +773,11 @@ static rtlCipherError BF_update(
55db36
             pBuffer += 1;
55db36
         }
55db36
     }
55db36
+#endif
55db36
     return rtl_Cipher_E_None;
55db36
 }
55db36
 
55db36
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
 static void BF_updateECB(
55db36
     CipherContextBF    *ctx,
55db36
     rtlCipherDirection  direction,
55db36
@@ -931,6 +980,7 @@ static sal_uInt32 BF(CipherKeyBF *key, sal_uInt32 x)
55db36
 
55db36
     return y;
55db36
 }
55db36
+#endif
55db36
 
55db36
 /**
55db36
     rtl_cipherBF (Blowfish) implementation.
55db36
@@ -943,6 +993,12 @@ rtlCipher SAL_CALL rtl_cipher_createBF(rtlCipherMode Mode) SAL_THROW_EXTERN_C()
55db36
 
55db36
     if (Mode == rtl_Cipher_ModeInvalid)
55db36
         return nullptr;
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+    if (Mode != rtl_Cipher_ModeStream) {
55db36
+        // Cannot easily support ModeECB and ModeCBC, and they aren't used in the LO code at least:
55db36
+        return nullptr;
55db36
+    }
55db36
+#endif
55db36
 
55db36
     pImpl = static_cast<CipherBF_Impl*>(rtl_allocateZeroMemory(sizeof (CipherBF_Impl)));
55db36
     if (pImpl)
55db36
@@ -978,9 +1034,45 @@ rtlCipherError SAL_CALL rtl_cipher_initBF(
55db36
     else
55db36
         return rtl_Cipher_E_Direction;
55db36
 
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+    if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionBoth) {
55db36
+        // Cannot easily support DirectionBoth, and it isn't used in the LO code at least:
55db36
+        return rtl_Cipher_E_Direction;
55db36
+    }
55db36
+    if (nKeyLen > std::numeric_limits<int>::max()) {
55db36
+        return rtl_Cipher_E_BufferSize;
55db36
+    }
55db36
+    if (pImpl->m_context.m_context != nullptr) {
55db36
+        EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
55db36
+    }
55db36
+    pImpl->m_context.m_context = EVP_CIPHER_CTX_new();
55db36
+    if (pImpl->m_context.m_context == nullptr) {
55db36
+        return rtl_Cipher_E_Memory;
55db36
+    }
55db36
+    unsigned char iv[8];
55db36
+    auto const n = std::min(nArgLen, sal_Size(8));
55db36
+    std::memcpy(iv, pArgData, n);
55db36
+    std::memset(iv + n, 0, 8 - n);
55db36
+    if (EVP_CipherInit_ex(
55db36
+            pImpl->m_context.m_context, EVP_bf_cfb(), nullptr, nullptr, iv,
55db36
+            pImpl->m_cipher.m_direction == rtl_Cipher_DirectionDecode ? 0 : 1)
55db36
+        == 0)
55db36
+    {
55db36
+        return rtl_Cipher_E_Unknown;
55db36
+    }
55db36
+    if (EVP_CIPHER_CTX_set_key_length(pImpl->m_context.m_context, static_cast<int>(nKeyLen)) == 0) {
55db36
+        return rtl_Cipher_E_Unknown;
55db36
+    }
55db36
+    if (EVP_CipherInit_ex(pImpl->m_context.m_context, nullptr, nullptr, pKeyData, nullptr, -1) == 0)
55db36
+    {
55db36
+        return rtl_Cipher_E_Unknown;
55db36
+    }
55db36
+    return rtl_Cipher_E_None;
55db36
+#else
55db36
     return BF_init(
55db36
         &(pImpl->m_context), pImpl->m_cipher.m_mode,
55db36
         pKeyData, nKeyLen, pArgData, nArgLen);
55db36
+#endif
55db36
 }
55db36
 
55db36
 rtlCipherError SAL_CALL rtl_cipher_encodeBF(
55db36
@@ -1037,18 +1129,31 @@ void SAL_CALL rtl_cipher_destroyBF(rtlCipher Cipher) SAL_THROW_EXTERN_C()
55db36
     if (pImpl)
55db36
     {
55db36
         if (pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmBF)
55db36
+        {
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            if (pImpl->m_context.m_context != nullptr) {
55db36
+                EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
55db36
+            }
55db36
+#endif
55db36
             rtl_freeZeroMemory(pImpl, sizeof(CipherBF_Impl));
55db36
+        }
55db36
         else
55db36
             rtl_freeMemory(pImpl);
55db36
     }
55db36
 }
55db36
 
55db36
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
 #define CIPHER_CBLOCK_ARCFOUR 256
55db36
+#endif
55db36
 
55db36
 struct ContextARCFOUR_Impl
55db36
 {
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+    EVP_CIPHER_CTX * m_context;
55db36
+#else
55db36
     unsigned int m_S[CIPHER_CBLOCK_ARCFOUR];
55db36
     unsigned int m_X, m_Y;
55db36
+#endif
55db36
 };
55db36
 
55db36
 struct CipherARCFOUR_Impl
55db36
@@ -1066,6 +1171,29 @@ static rtlCipherError rtl_cipherARCFOUR_init_Impl(
55db36
     ContextARCFOUR_Impl *ctx,
55db36
     const sal_uInt8     *pKeyData, sal_Size nKeyLen)
55db36
 {
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+    if (nKeyLen > std::numeric_limits<int>::max()) {
55db36
+        return rtl_Cipher_E_BufferSize;
55db36
+    }
55db36
+    if (ctx->m_context != nullptr) {
55db36
+        EVP_CIPHER_CTX_free(ctx->m_context);
55db36
+    }
55db36
+    ctx->m_context = EVP_CIPHER_CTX_new();
55db36
+    if (ctx->m_context == nullptr) {
55db36
+        return rtl_Cipher_E_Memory;
55db36
+    }
55db36
+    if (EVP_CipherInit_ex(ctx->m_context, EVP_rc4(), nullptr, nullptr, nullptr, 0) == 0) {
55db36
+            // RC4 en- and decryption is identical, so we can use 0=decrypt regardless of direction,
55db36
+            // and thus also support rtl_Cipher_DirectionBoth
55db36
+        return rtl_Cipher_E_Unknown;
55db36
+    }
55db36
+    if (EVP_CIPHER_CTX_set_key_length(ctx->m_context, static_cast<int>(nKeyLen)) == 0) {
55db36
+        return rtl_Cipher_E_Unknown;
55db36
+    }
55db36
+    if (EVP_CipherInit_ex(ctx->m_context, nullptr, nullptr, pKeyData, nullptr, -1) == 0) {
55db36
+        return rtl_Cipher_E_Unknown;
55db36
+    }
55db36
+#else
55db36
     unsigned int  K[CIPHER_CBLOCK_ARCFOUR];
55db36
     unsigned int *L, *S;
55db36
     unsigned int  x, y, t;
55db36
@@ -1106,6 +1234,7 @@ static rtlCipherError rtl_cipherARCFOUR_init_Impl(
55db36
     /* Initialize counters X and Y. */
55db36
     ctx->m_X = 0;
55db36
     ctx->m_Y = 0;
55db36
+#endif
55db36
 
55db36
     return rtl_Cipher_E_None;
55db36
 }
55db36
@@ -1115,10 +1244,6 @@ static rtlCipherError rtl_cipherARCFOUR_update_Impl(
55db36
     const sal_uInt8     *pData,   sal_Size nDatLen,
55db36
     sal_uInt8           *pBuffer, sal_Size nBufLen)
55db36
 {
55db36
-    unsigned int *S;
55db36
-    unsigned int t;
55db36
-    sal_Size k;
55db36
-
55db36
     /* Check arguments. */
55db36
     if (!pData || !pBuffer)
55db36
         return rtl_Cipher_E_Argument;
55db36
@@ -1126,6 +1251,32 @@ static rtlCipherError rtl_cipherARCFOUR_update_Impl(
55db36
     if (!((0 < nDatLen) && (nDatLen <= nBufLen)))
55db36
         return rtl_Cipher_E_BufferSize;
55db36
 
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+    while (nDatLen > std::numeric_limits<int>::max()) {
55db36
+        int outl;
55db36
+        if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, std::numeric_limits<int>::max())
55db36
+            == 0)
55db36
+        {
55db36
+            return rtl_Cipher_E_Unknown;
55db36
+        }
55db36
+        assert(outl == std::numeric_limits<int>::max());
55db36
+        pData += std::numeric_limits<int>::max();
55db36
+        nDatLen -= std::numeric_limits<int>::max();
55db36
+        pBuffer += std::numeric_limits<int>::max();
55db36
+    }
55db36
+    int outl;
55db36
+    if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, static_cast<int>(nDatLen)) == 0) {
55db36
+        return rtl_Cipher_E_Unknown;
55db36
+    }
55db36
+    assert(outl == static_cast<int>(nDatLen));
55db36
+    // A final call to EVP_CipherFinal_ex is intentionally missing; it wouldn't fit the rtl/cipher.h
55db36
+    // interface, and is hopefully not needed, as each individual RC4 update step doesn't hold back
55db36
+    // any data that would need to be finally flushed.
55db36
+#else
55db36
+    unsigned int *S;
55db36
+    unsigned int t;
55db36
+    sal_Size k;
55db36
+
55db36
     /* Update. */
55db36
     S = &(ctx->m_S[0]);
55db36
     for (k = 0; k < nDatLen; k++)
55db36
@@ -1147,6 +1298,7 @@ static rtlCipherError rtl_cipherARCFOUR_update_Impl(
55db36
         t = (S[x] + S[y]) % CIPHER_CBLOCK_ARCFOUR;
55db36
         pBuffer[k] = pData[k] ^ ((sal_uInt8)(S[t] & 0xff));
55db36
     }
55db36
+#endif
55db36
 
55db36
     return rtl_Cipher_E_None;
55db36
 }
55db36
@@ -1249,7 +1401,14 @@ void SAL_CALL rtl_cipher_destroyARCFOUR(rtlCipher Cipher) SAL_THROW_EXTERN_C()
55db36
     if (pImpl)
55db36
     {
55db36
         if (pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmARCFOUR)
55db36
+        {
55db36
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
55db36
+            if (pImpl->m_context.m_context != nullptr) {
55db36
+                EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
55db36
+            }
55db36
+#endif
55db36
             rtl_freeZeroMemory(pImpl, sizeof(CipherARCFOUR_Impl));
55db36
+        }
55db36
         else
55db36
             rtl_freeMemory(pImpl);
55db36
     }
55db36
-- 
55db36
2.17.1
55db36