kbrown / rpms / libreoffice

Forked from rpms/libreoffice 2 years ago
Clone

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

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