summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config_host.mk.in1
-rw-r--r--configure.ac23
-rw-r--r--sal/CppunitTest_sal_rtl.mk4
-rw-r--r--sal/Library_sal.mk8
-rw-r--r--sal/qa/rtl/cipher/rtl_cipher.cxx61
-rw-r--r--sal/rtl/cipher.cxx164
6 files changed, 258 insertions, 3 deletions
diff --git a/config_host.mk.in b/config_host.mk.in
index b5eef155d524..38872e2330ae 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -115,6 +115,7 @@ export ENABLE_AVAHI=@ENABLE_AVAHI@
export ENABLE_BREAKPAD=@ENABLE_BREAKPAD@
export ENABLE_CAIRO_CANVAS=@ENABLE_CAIRO_CANVAS@
export ENABLE_CHART_TESTS=@ENABLE_CHART_TESTS@
+export ENABLE_CIPHER_OPENSSL_BACKEND=@ENABLE_CIPHER_OPENSSL_BACKEND@
export ENABLE_LIBCMIS=@ENABLE_LIBCMIS@
export ENABLE_COINMP=@ENABLE_COINMP@
export SYSTEM_COINMP=@SYSTEM_COINMP@
diff --git a/configure.ac b/configure.ac
index fbb74238379b..88dd8bfb3e1a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1480,6 +1480,11 @@ AC_ARG_ENABLE(openssl,
use only if you are hacking on it.]),
,enable_openssl=yes)
+libo_FUZZ_ARG_ENABLE(cipher-openssl-backend,
+ AS_HELP_STRING([--enable-cipher-openssl-backend],
+ [Enable using OpenSSL as the actual implementation of the rtl/cipher.h functionality.
+ Requires --enable-openssl.]))
+
AC_ARG_ENABLE(library-bin-tar,
AS_HELP_STRING([--enable-library-bin-tar],
[Enable the building and reused of tarball of binary build for some 'external' libraries.
@@ -9471,6 +9476,24 @@ fi
AC_SUBST([DISABLE_OPENSSL])
+if test "$enable_cipher_openssl_backend" = yes && test "$DISABLE_OPENSSL" = TRUE; then
+ if test "$libo_fuzzed_enable_cipher_openssl_backend" = yes; then
+ AC_MSG_NOTICE([Resetting --enable-cipher-openssl-backend=no])
+ enable_cipher_openssl_backend=no
+ else
+ AC_MSG_ERROR([--enable-cipher-openssl-backend needs OpenSSL, but --disable-openssl was given.])
+ fi
+fi
+AC_MSG_CHECKING([whether to enable the OpenSSL backend for rtl/cipher.h])
+ENABLE_CIPHER_OPENSSL_BACKEND=
+if test "$enable_cipher_openssl_backend" = yes; then
+ AC_MSG_RESULT([yes])
+ ENABLE_CIPHER_OPENSSL_BACKEND=TRUE
+else
+ AC_MSG_RESULT([no])
+fi
+AC_SUBST([ENABLE_CIPHER_OPENSSL_BACKEND])
+
dnl ===================================================================
dnl Check for building gnutls
dnl ===================================================================
diff --git a/sal/CppunitTest_sal_rtl.mk b/sal/CppunitTest_sal_rtl.mk
index 43533fc5ab1c..c2eaa72daa26 100644
--- a/sal/CppunitTest_sal_rtl.mk
+++ b/sal/CppunitTest_sal_rtl.mk
@@ -63,4 +63,8 @@ $(call gb_CppunitTest_get_target,sal_rtl) : \
$(eval $(call gb_CppunitTest_use_external,sal_rtl,boost_headers))
+ifeq ($(ENABLE_CIPHER_OPENSSL_BACKEND),TRUE)
+$(eval $(call gb_CppunitTest_add_defs,sal_rtl,-DLIBO_CIPHER_OPENSSL_BACKEND))
+endif
+
# vim: set noet sw=4 ts=4:
diff --git a/sal/Library_sal.mk b/sal/Library_sal.mk
index 9d5822e36256..868d9f8dd23d 100644
--- a/sal/Library_sal.mk
+++ b/sal/Library_sal.mk
@@ -254,4 +254,12 @@ $(eval $(call gb_Library_add_exception_objects,sal,\
endif # ifneq ($(OS),WNT)
+ifeq ($(ENABLE_CIPHER_OPENSSL_BACKEND),TRUE)
+$(eval $(call gb_Library_add_defs,sal,-DLIBO_CIPHER_OPENSSL_BACKEND))
+$(eval $(call gb_Library_use_externals,sal, \
+ openssl \
+ openssl_headers \
+))
+endif
+
# vim: set noet sw=4 ts=4:
diff --git a/sal/qa/rtl/cipher/rtl_cipher.cxx b/sal/qa/rtl/cipher/rtl_cipher.cxx
index e8877a92c5d5..57c22eb573ac 100644
--- a/sal/qa/rtl/cipher/rtl_cipher.cxx
+++ b/sal/qa/rtl/cipher/rtl_cipher.cxx
@@ -37,8 +37,12 @@ public:
void create_001()
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
rtl_cipher_destroy(aCipher);
+#endif
}
void create_002()
{
@@ -48,8 +52,12 @@ public:
void create_003()
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeCBC);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
rtl_cipher_destroy(aCipher);
+#endif
}
void create_004()
{
@@ -101,14 +109,22 @@ public:
void createBF_001()
{
rtlCipher aCipher = rtl_cipher_createBF(rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
rtl_cipher_destroy(aCipher);
+#endif
}
void createBF_002()
{
rtlCipher aCipher = rtl_cipher_createBF(rtl_Cipher_ModeCBC);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
rtl_cipher_destroy(aCipher);
+#endif
}
void createBF_003()
{
@@ -141,6 +157,12 @@ public:
void test_encode(sal_uInt8 _nKeyValue, sal_uInt8 _nArgValue, rtl::OString const& _sPlainTextStr)
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+ (void) _nKeyValue;
+ (void) _nArgValue;
+ (void) _sPlainTextStr;
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
sal_uInt32 nKeyLen = 16;
@@ -184,11 +206,18 @@ public:
delete [] pKeyBuffer;
rtl_cipher_destroy(aCipher);
+#endif
}
void test_encode_and_decode(sal_uInt8 _nKeyValue, sal_uInt8 _nArgValue, rtl::OString const& _sPlainTextStr)
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+ (void) _nKeyValue;
+ (void) _nArgValue;
+ (void) _sPlainTextStr;
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
sal_uInt32 nKeyLen = 16;
@@ -236,6 +265,7 @@ public:
delete [] pKeyBuffer;
rtl_cipher_destroy(aCipher);
+#endif
}
void decode_001()
@@ -286,8 +316,12 @@ public:
void destroy_001()
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeCBC);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
rtl_cipher_destroy(aCipher);
+#endif
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
@@ -305,10 +339,14 @@ public:
void destroyBF_001()
{
rtlCipher aCipher = rtl_cipher_createBF(rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
rtl_cipher_destroyBF(aCipher);
// more proforma
// should not GPF
+#endif
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
@@ -326,6 +364,12 @@ public:
void test_encode(sal_uInt8 _nKeyValue, sal_uInt8 _nArgValue, sal_uInt8 _nDataValue)
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+ (void) _nKeyValue;
+ (void) _nArgValue;
+ (void) _nDataValue;
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
sal_uInt32 nKeyLen = 16;
@@ -360,6 +404,7 @@ public:
delete [] pKeyBuffer;
rtl_cipher_destroy(aCipher);
+#endif
}
void encode_001()
@@ -407,6 +452,9 @@ public:
void init_001()
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
sal_uInt32 nKeyLen = 16;
@@ -424,11 +472,15 @@ public:
delete [] pKeyBuffer;
rtl_cipher_destroy(aCipher);
+#endif
}
void init_002()
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
sal_uInt32 nKeyLen = 16;
@@ -447,10 +499,14 @@ public:
delete [] pKeyBuffer;
rtl_cipher_destroy(aCipher);
+#endif
}
void init_003()
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
sal_uInt32 nKeyLen = 16;
@@ -469,10 +525,14 @@ public:
delete [] pKeyBuffer;
rtl_cipher_destroy(aCipher);
+#endif
}
void init_004()
{
rtlCipher aCipher = rtl_cipher_create(rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeECB);
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ CPPUNIT_ASSERT_EQUAL(rtlCipher(nullptr), aCipher);
+#else
CPPUNIT_ASSERT_MESSAGE("create failed.", aCipher != nullptr);
sal_uInt32 nKeyLen = 16;
@@ -492,6 +552,7 @@ public:
delete [] pKeyBuffer;
rtl_cipher_destroy(aCipher);
+#endif
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
diff --git a/sal/rtl/cipher.cxx b/sal/rtl/cipher.cxx
index bd913c38faf1..96cb896623e1 100644
--- a/sal/rtl/cipher.cxx
+++ b/sal/rtl/cipher.cxx
@@ -23,7 +23,15 @@
#include <rtl/alloc.h>
#include <rtl/cipher.h>
#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <limits>
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+#include <openssl/evp.h>
+#endif
+
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
#define RTL_CIPHER_NTOHL(c, l) \
((l) = (static_cast<sal_uInt32>(*((c)++))) << 24, \
(l) |= (static_cast<sal_uInt32>(*((c)++))) << 16, \
@@ -82,6 +90,7 @@
case 1: *(--(c)) = static_cast<sal_uInt8>(((xl) >> 24) & 0xff); \
} \
}
+#endif
typedef rtlCipherError(cipher_init_t) (
rtlCipher Cipher,
@@ -183,6 +192,7 @@ void SAL_CALL rtl_cipher_destroy(rtlCipher Cipher) SAL_THROW_EXTERN_C()
pImpl->m_delete(Cipher);
}
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
#define CIPHER_ROUNDS_BF 16
struct CipherKeyBF
@@ -190,9 +200,13 @@ struct CipherKeyBF
sal_uInt32 m_S[4][256];
sal_uInt32 m_P[CIPHER_ROUNDS_BF + 2];
};
+#endif
struct CipherContextBF
{
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ EVP_CIPHER_CTX * m_context;
+#else
CipherKeyBF m_key;
union
{
@@ -200,6 +214,7 @@ struct CipherContextBF
sal_uInt8 m_byte[8];
} m_iv;
sal_uInt32 m_offset;
+#endif
};
struct CipherBF_Impl
@@ -208,11 +223,13 @@ struct CipherBF_Impl
CipherContextBF m_context;
};
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
static rtlCipherError BF_init(
CipherContextBF *ctx,
rtlCipherMode eMode,
const sal_uInt8 *pKeyData, sal_Size nKeyLen,
const sal_uInt8 *pArgData, sal_Size nArgLen);
+#endif
static rtlCipherError BF_update(
CipherContextBF *ctx,
@@ -221,6 +238,7 @@ static rtlCipherError BF_update(
const sal_uInt8 *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen);
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
static void BF_updateECB(
CipherContextBF *ctx,
rtlCipherDirection direction,
@@ -609,7 +627,9 @@ static const CipherKeyBF BF_key =
0x9216D5D9L, 0x8979FB1BL
}
};
+#endif
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
static rtlCipherError BF_init(
CipherContextBF *ctx,
rtlCipherMode eMode,
@@ -676,6 +696,7 @@ static rtlCipherError BF_init(
return rtl_Cipher_E_None;
}
+#endif
static rtlCipherError BF_update(
CipherContextBF *ctx,
@@ -692,6 +713,31 @@ static rtlCipherError BF_update(
return rtl_Cipher_E_BufferSize;
/* Update. */
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ assert(eMode == rtl_Cipher_ModeStream);
+ (void) eDirection;
+ while (nDatLen > std::numeric_limits<int>::max()) {
+ int outl;
+ if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, std::numeric_limits<int>::max())
+ == 0)
+ {
+ return rtl_Cipher_E_Unknown;
+ }
+ assert(outl == std::numeric_limits<int>::max());
+ pData += std::numeric_limits<int>::max();
+ nDatLen -= std::numeric_limits<int>::max();
+ pBuffer += std::numeric_limits<int>::max();
+ }
+ int outl;
+ if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, static_cast<int>(nDatLen)) == 0)
+ {
+ return rtl_Cipher_E_Unknown;
+ }
+ assert(outl == static_cast<int>(nDatLen));
+ // A final call to EVP_CipherFinal_ex is intentionally missing; it wouldn't fit the rtl/cipher.h
+ // interface, and is hopefully not needed, as each individual Blowfish CFB update step doesn't
+ // hold back any data that would need to be finally flushed.
+#else
if (eMode == rtl_Cipher_ModeECB)
{
/* Block mode. */
@@ -727,9 +773,11 @@ static rtlCipherError BF_update(
pBuffer += 1;
}
}
+#endif
return rtl_Cipher_E_None;
}
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
static void BF_updateECB(
CipherContextBF *ctx,
rtlCipherDirection direction,
@@ -932,6 +980,7 @@ static sal_uInt32 BF(CipherKeyBF *key, sal_uInt32 x)
return y;
}
+#endif
/**
rtl_cipherBF (Blowfish) implementation.
@@ -944,6 +993,12 @@ rtlCipher SAL_CALL rtl_cipher_createBF(rtlCipherMode Mode) SAL_THROW_EXTERN_C()
if (Mode == rtl_Cipher_ModeInvalid)
return nullptr;
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ if (Mode != rtl_Cipher_ModeStream) {
+ // Cannot easily support ModeECB and ModeCBC, and they aren't used in the LO code at least:
+ return nullptr;
+ }
+#endif
pImpl = static_cast<CipherBF_Impl*>(rtl_allocateZeroMemory(sizeof (CipherBF_Impl)));
if (pImpl)
@@ -979,9 +1034,45 @@ rtlCipherError SAL_CALL rtl_cipher_initBF(
else
return rtl_Cipher_E_Direction;
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionBoth) {
+ // Cannot easily support DirectionBoth, and it isn't used in the LO code at least:
+ return rtl_Cipher_E_Direction;
+ }
+ if (nKeyLen > std::numeric_limits<int>::max()) {
+ return rtl_Cipher_E_BufferSize;
+ }
+ if (pImpl->m_context.m_context != nullptr) {
+ EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
+ }
+ pImpl->m_context.m_context = EVP_CIPHER_CTX_new();
+ if (pImpl->m_context.m_context == nullptr) {
+ return rtl_Cipher_E_Memory;
+ }
+ unsigned char iv[8];
+ auto const n = std::min(nArgLen, sal_Size(8));
+ std::memcpy(iv, pArgData, n);
+ std::memset(iv + n, 0, 8 - n);
+ if (EVP_CipherInit_ex(
+ pImpl->m_context.m_context, EVP_bf_cfb(), nullptr, nullptr, iv,
+ pImpl->m_cipher.m_direction == rtl_Cipher_DirectionDecode ? 0 : 1)
+ == 0)
+ {
+ return rtl_Cipher_E_Unknown;
+ }
+ if (EVP_CIPHER_CTX_set_key_length(pImpl->m_context.m_context, static_cast<int>(nKeyLen)) == 0) {
+ return rtl_Cipher_E_Unknown;
+ }
+ if (EVP_CipherInit_ex(pImpl->m_context.m_context, nullptr, nullptr, pKeyData, nullptr, -1) == 0)
+ {
+ return rtl_Cipher_E_Unknown;
+ }
+ return rtl_Cipher_E_None;
+#else
return BF_init(
&(pImpl->m_context), pImpl->m_cipher.m_mode,
pKeyData, nKeyLen, pArgData, nArgLen);
+#endif
}
rtlCipherError SAL_CALL rtl_cipher_encodeBF(
@@ -1038,18 +1129,31 @@ void SAL_CALL rtl_cipher_destroyBF(rtlCipher Cipher) SAL_THROW_EXTERN_C()
if (pImpl)
{
if (pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmBF)
+ {
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ if (pImpl->m_context.m_context != nullptr) {
+ EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
+ }
+#endif
rtl_freeZeroMemory(pImpl, sizeof(CipherBF_Impl));
+ }
else
rtl_freeMemory(pImpl);
}
}
+#if !defined LIBO_CIPHER_OPENSSL_BACKEND
#define CIPHER_CBLOCK_ARCFOUR 256
+#endif
struct ContextARCFOUR_Impl
{
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ EVP_CIPHER_CTX * m_context;
+#else
unsigned int m_S[CIPHER_CBLOCK_ARCFOUR];
unsigned int m_X, m_Y;
+#endif
};
struct CipherARCFOUR_Impl
@@ -1067,6 +1171,29 @@ static rtlCipherError rtl_cipherARCFOUR_init_Impl(
ContextARCFOUR_Impl *ctx,
const sal_uInt8 *pKeyData, sal_Size nKeyLen)
{
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ if (nKeyLen > std::numeric_limits<int>::max()) {
+ return rtl_Cipher_E_BufferSize;
+ }
+ if (ctx->m_context != nullptr) {
+ EVP_CIPHER_CTX_free(ctx->m_context);
+ }
+ ctx->m_context = EVP_CIPHER_CTX_new();
+ if (ctx->m_context == nullptr) {
+ return rtl_Cipher_E_Memory;
+ }
+ if (EVP_CipherInit_ex(ctx->m_context, EVP_rc4(), nullptr, nullptr, nullptr, 0) == 0) {
+ // RC4 en- and decryption is identical, so we can use 0=decrypt regardless of direction,
+ // and thus also support rtl_Cipher_DirectionBoth
+ return rtl_Cipher_E_Unknown;
+ }
+ if (EVP_CIPHER_CTX_set_key_length(ctx->m_context, static_cast<int>(nKeyLen)) == 0) {
+ return rtl_Cipher_E_Unknown;
+ }
+ if (EVP_CipherInit_ex(ctx->m_context, nullptr, nullptr, pKeyData, nullptr, -1) == 0) {
+ return rtl_Cipher_E_Unknown;
+ }
+#else
unsigned int K[CIPHER_CBLOCK_ARCFOUR];
unsigned int *L, *S;
unsigned int x, y;
@@ -1107,6 +1234,7 @@ static rtlCipherError rtl_cipherARCFOUR_init_Impl(
/* Initialize counters X and Y. */
ctx->m_X = 0;
ctx->m_Y = 0;
+#endif
return rtl_Cipher_E_None;
}
@@ -1116,9 +1244,6 @@ static rtlCipherError rtl_cipherARCFOUR_update_Impl(
const sal_uInt8 *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen)
{
- unsigned int *S;
- sal_Size k;
-
/* Check arguments. */
if (!pData || !pBuffer)
return rtl_Cipher_E_Argument;
@@ -1126,6 +1251,31 @@ static rtlCipherError rtl_cipherARCFOUR_update_Impl(
if (!((0 < nDatLen) && (nDatLen <= nBufLen)))
return rtl_Cipher_E_BufferSize;
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ while (nDatLen > std::numeric_limits<int>::max()) {
+ int outl;
+ if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, std::numeric_limits<int>::max())
+ == 0)
+ {
+ return rtl_Cipher_E_Unknown;
+ }
+ assert(outl == std::numeric_limits<int>::max());
+ pData += std::numeric_limits<int>::max();
+ nDatLen -= std::numeric_limits<int>::max();
+ pBuffer += std::numeric_limits<int>::max();
+ }
+ int outl;
+ if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, static_cast<int>(nDatLen)) == 0) {
+ return rtl_Cipher_E_Unknown;
+ }
+ assert(outl == static_cast<int>(nDatLen));
+ // A final call to EVP_CipherFinal_ex is intentionally missing; it wouldn't fit the rtl/cipher.h
+ // interface, and is hopefully not needed, as each individual RC4 update step doesn't hold back
+ // any data that would need to be finally flushed.
+#else
+ unsigned int *S;
+ sal_Size k;
+
/* Update. */
S = &(ctx->m_S[0]);
for (k = 0; k < nDatLen; k++)
@@ -1147,6 +1297,7 @@ static rtlCipherError rtl_cipherARCFOUR_update_Impl(
t = (S[x] + S[y]) % CIPHER_CBLOCK_ARCFOUR;
pBuffer[k] = pData[k] ^ static_cast<sal_uInt8>(S[t] & 0xff);
}
+#endif
return rtl_Cipher_E_None;
}
@@ -1249,7 +1400,14 @@ void SAL_CALL rtl_cipher_destroyARCFOUR(rtlCipher Cipher) SAL_THROW_EXTERN_C()
if (pImpl)
{
if (pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmARCFOUR)
+ {
+#if defined LIBO_CIPHER_OPENSSL_BACKEND
+ if (pImpl->m_context.m_context != nullptr) {
+ EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
+ }
+#endif
rtl_freeZeroMemory(pImpl, sizeof(CipherARCFOUR_Impl));
+ }
else
rtl_freeMemory(pImpl);
}