8388e0c
From e0c5d650ecf94b30b66584bdd9367dcacc0a6e94 Mon Sep 17 00:00:00 2001
8388e0c
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
8388e0c
Date: Thu, 20 Oct 2016 11:19:58 +0100
8388e0c
Subject: [PATCH] implement CryptoAPI RC4+SHA1 encryption scheme for xls import
8388e0c
8388e0c
there might be other variants out there in practice, but this
8388e0c
works for default encrypted xls of excel 2013
8388e0c
8388e0c
(cherry picked from commit 1473ce030314027c01c98f513407ed0897328585)
8388e0c
8388e0c
contains...
8388e0c
8388e0c
be more c++y
8388e0c
8388e0c
(cherry picked from commit fcf7f503b64b2cf7dbef019fb43dde033e3538e8)
8388e0c
8388e0c
hash len is 20 for xls cryptoapi configuration
8388e0c
8388e0c
(cherry picked from commit 491884350ce74f36044b3348bd66356ad1c234af)
8388e0c
8388e0c
clarify hash lengths a bit more
8388e0c
8388e0c
(cherry picked from commit 8db1b13e721683d0263925c8e0300dd86a022814)
8388e0c
8388e0c
hash len isn't going to change depending on who implements it
8388e0c
8388e0c
(cherry picked from commit fcc846e8f29839eaace7e1d28746abea8f4b598a)
8388e0c
8388e0c
move some useful header information to mscodec for reuse
8388e0c
8388e0c
(cherry picked from commit fc514cbf30be1613fdf4d4b7c12cbd55ca08b9b0)
8388e0c
8388e0c
rework things in light of now available documentation
8388e0c
8388e0c
(cherry picked from commit 3fabbd0a22219464545f933fc28c869a6fa89546)
8388e0c
8388e0c
split MSCodec_Std97 into a baseclass MSCodec97
8388e0c
8388e0c
(cherry picked from commit 06916c839b16866b47235306d2db50850df0ad7c)
8388e0c
8388e0c
6e06b8578959b8147043179db57e875b1d98d57d
8388e0c
66cea4b9efb82d29e6c052ac11a6f2eaca823ce0
8388e0c
ee585cba4acad74c11d083085153e2af96c8894f
8388e0c
c7adf3ed3c8279cc93a06975d6fb337210d1af87
8388e0c
f5f75e27191017a8c6a3929e2a70d21840f157c6
8388e0c
a3c41a048169c78684800def94e53fc9f3201e30
8388e0c
91c0e1d1d95fbd1c68966650e7ac7d23276bcbe3
8388e0c
8388e0c
Change-Id: I673b00e111a734bc626ba3d3f6ecf9692f1ce7db
8388e0c
---
8388e0c
 filter/source/msfilter/mscodec.cxx        | 206 +++++++++++++++++++---------
8388e0c
 include/filter/msfilter/mscodec.hxx       | 215 ++++++++++++++++++++++++------
8388e0c
 include/oox/crypto/CryptTools.hxx         |   3 -
8388e0c
 include/oox/crypto/Standard2007Engine.hxx |  76 ++---------
8388e0c
 oox/source/crypto/CryptTools.cxx          |  14 +-
8388e0c
 oox/source/crypto/DocumentDecryption.cxx  |  22 +--
8388e0c
 oox/source/crypto/Standard2007Engine.cxx  |  67 ++++------
8388e0c
 sc/source/filter/excel/xicontent.cxx      | 106 ++++++++++++---
8388e0c
 sc/source/filter/excel/xistream.cxx       |  70 ++++++----
8388e0c
 sc/source/filter/inc/xistream.hxx         |  67 ++++++++--
8388e0c
 sc/source/filter/inc/xlcontent.hxx        |   2 -
8388e0c
 11 files changed, 553 insertions(+), 295 deletions(-)
8388e0c
8388e0c
diff --git a/filter/source/msfilter/mscodec.cxx b/filter/source/msfilter/mscodec.cxx
8388e0c
index 87dbf70..ade583a 100644
8388e0c
--- a/filter/source/msfilter/mscodec.cxx
8388e0c
+++ b/filter/source/msfilter/mscodec.cxx
8388e0c
@@ -247,28 +247,37 @@ void MSCodec_Xor95::Skip( sal_Size nBytes )
8388e0c
     mnOffset = (mnOffset + nBytes) & 0x0F;
8388e0c
 }
8388e0c
 
8388e0c
+MSCodec97::MSCodec97(size_t nHashLen)
8388e0c
+    : m_nHashLen(nHashLen)
8388e0c
+    , m_hCipher(rtl_cipher_create(rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream))
8388e0c
+    , m_aDigestValue(nHashLen, 0)
8388e0c
+{
8388e0c
+    assert(m_hCipher != nullptr);
8388e0c
+    (void)memset (m_pDocId, 0, sizeof(m_pDocId));
8388e0c
+}
8388e0c
 
8388e0c
-
8388e0c
-MSCodec_Std97::MSCodec_Std97 ()
8388e0c
+MSCodec_Std97::MSCodec_Std97()
8388e0c
+    : MSCodec97(RTL_DIGEST_LENGTH_MD5)
8388e0c
 {
8388e0c
-    m_hCipher = rtl_cipher_create (
8388e0c
-        rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream);
8388e0c
-    OSL_ASSERT(m_hCipher != nullptr);
8388e0c
+    m_hDigest = rtl_digest_create(rtl_Digest_AlgorithmMD5);
8388e0c
+    assert(m_hDigest != nullptr);
8388e0c
+}
8388e0c
 
8388e0c
-    m_hDigest = rtl_digest_create (
8388e0c
-        rtl_Digest_AlgorithmMD5);
8388e0c
-    OSL_ASSERT(m_hDigest != nullptr);
8388e0c
+MSCodec_CryptoAPI::MSCodec_CryptoAPI()
8388e0c
+    : MSCodec97(RTL_DIGEST_LENGTH_SHA1)
8388e0c
+{
8388e0c
+}
8388e0c
 
8388e0c
-    (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue));
8388e0c
-    (void)memset (m_pDocId, 0, sizeof(m_pDocId));
8388e0c
+MSCodec97::~MSCodec97()
8388e0c
+{
8388e0c
+    (void)memset(m_aDigestValue.data(), 0, m_aDigestValue.size());
8388e0c
+    (void)memset(m_pDocId, 0, sizeof(m_pDocId));
8388e0c
+    rtl_cipher_destroy(m_hCipher);
8388e0c
 }
8388e0c
 
8388e0c
-MSCodec_Std97::~MSCodec_Std97 ()
8388e0c
+MSCodec_Std97::~MSCodec_Std97()
8388e0c
 {
8388e0c
-    (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue));
8388e0c
-    (void)memset (m_pDocId, 0, sizeof(m_pDocId));
8388e0c
-    rtl_digest_destroy (m_hDigest);
8388e0c
-    rtl_cipher_destroy (m_hCipher);
8388e0c
+    rtl_digest_destroy(m_hDigest);
8388e0c
 }
8388e0c
 
8388e0c
 #if DEBUG_MSO_ENCRYPTION_STD97
8388e0c
@@ -285,7 +294,7 @@ static inline void lcl_PrintDigest(const sal_uInt8* /*pDigest*/, const char* /*m
8388e0c
 }
8388e0c
 #endif
8388e0c
 
8388e0c
-bool MSCodec_Std97::InitCodec( const uno::Sequence< beans::NamedValue >& aData )
8388e0c
+bool MSCodec97::InitCodec( const uno::Sequence< beans::NamedValue >& aData )
8388e0c
 {
8388e0c
 #if DEBUG_MSO_ENCRYPTION_STD97
8388e0c
     fprintf(stdout, "MSCodec_Std97::InitCodec: --begin\n");fflush(stdout);
8388e0c
@@ -294,16 +303,17 @@ bool MSCodec_Std97::InitCodec( const uno::Sequence< beans::NamedValue >& aData )
8388e0c
 
8388e0c
     ::comphelper::SequenceAsHashMap aHashData( aData );
8388e0c
     uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault("STD97EncryptionKey", uno::Sequence< sal_Int8 >() );
8388e0c
-
8388e0c
-    if ( aKey.getLength() == RTL_DIGEST_LENGTH_MD5 )
8388e0c
+    const size_t nKeyLen = aKey.getLength();
8388e0c
+    if (nKeyLen == m_nHashLen)
8388e0c
     {
8388e0c
-        (void)memcpy( m_pDigestValue, aKey.getConstArray(), RTL_DIGEST_LENGTH_MD5 );
8388e0c
+        assert(m_aDigestValue.size() == m_nHashLen);
8388e0c
+        (void)memcpy(m_aDigestValue.data(), aKey.getConstArray(), m_nHashLen);
8388e0c
         uno::Sequence< sal_Int8 > aUniqueID = aHashData.getUnpackedValueOrDefault("STD97UniqueID", uno::Sequence< sal_Int8 >() );
8388e0c
         if ( aUniqueID.getLength() == 16 )
8388e0c
         {
8388e0c
             (void)memcpy( m_pDocId, aUniqueID.getConstArray(), 16 );
8388e0c
             bResult = true;
8388e0c
-            lcl_PrintDigest(m_pDigestValue, "digest value");
8388e0c
+            lcl_PrintDigest(m_aDigestValue.data(), "digest value");
8388e0c
             lcl_PrintDigest(m_pDocId, "DocId value");
8388e0c
         }
8388e0c
         else
8388e0c
@@ -315,10 +325,11 @@ bool MSCodec_Std97::InitCodec( const uno::Sequence< beans::NamedValue >& aData )
8388e0c
     return bResult;
8388e0c
 }
8388e0c
 
8388e0c
-uno::Sequence< beans::NamedValue > MSCodec_Std97::GetEncryptionData()
8388e0c
+uno::Sequence< beans::NamedValue > MSCodec97::GetEncryptionData()
8388e0c
 {
8388e0c
     ::comphelper::SequenceAsHashMap aHashData;
8388e0c
-    aHashData[ OUString( "STD97EncryptionKey" ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(m_pDigestValue), RTL_DIGEST_LENGTH_MD5 );
8388e0c
+    assert(m_aDigestValue.size() == m_nHashLen);
8388e0c
+    aHashData[ OUString( "STD97EncryptionKey" ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(m_aDigestValue.data()), m_nHashLen );
8388e0c
     aHashData[ OUString( "STD97UniqueID" ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(m_pDocId), 16 );
8388e0c
 
8388e0c
     return aHashData.getAsConstNamedValueList();
8388e0c
@@ -334,26 +345,51 @@ void MSCodec_Std97::InitKey (
8388e0c
     uno::Sequence< sal_Int8 > aKey = ::comphelper::DocPasswordHelper::GenerateStd97Key(pPassData, pDocId);
8388e0c
     // Fill raw digest of above updates into DigestValue.
8388e0c
 
8388e0c
-    if ( aKey.getLength() == sizeof(m_pDigestValue) )
8388e0c
-        (void)memcpy ( m_pDigestValue, aKey.getConstArray(), sizeof(m_pDigestValue) );
8388e0c
+    const size_t nKeyLen = aKey.getLength();
8388e0c
+    if (m_aDigestValue.size() == nKeyLen)
8388e0c
+        (void)memcpy(m_aDigestValue.data(), aKey.getConstArray(), m_aDigestValue.size());
8388e0c
     else
8388e0c
-        memset( m_pDigestValue, 0, sizeof(m_pDigestValue) );
8388e0c
+        memset(m_aDigestValue.data(), 0, m_aDigestValue.size());
8388e0c
+
8388e0c
+    lcl_PrintDigest(m_aDigestValue.data(), "digest value");
8388e0c
+
8388e0c
+    (void)memcpy (m_pDocId, pDocId, 16);
8388e0c
+
8388e0c
+    lcl_PrintDigest(m_pDocId, "DocId value");
8388e0c
+}
8388e0c
+
8388e0c
+void MSCodec_CryptoAPI::InitKey (
8388e0c
+    const sal_uInt16 pPassData[16],
8388e0c
+    const sal_uInt8  pDocId[16])
8388e0c
+{
8388e0c
+    sal_uInt32 saltSize = 16;
8388e0c
+
8388e0c
+    // Prepare initial data -> salt + password (in 16-bit chars)
8388e0c
+    std::vector<sal_uInt8> initialData(pDocId, pDocId + saltSize);
8388e0c
+
8388e0c
+    // Fill PassData into KeyData.
8388e0c
+    for (sal_Int32 nInd = 0; nInd < 16 && pPassData[nInd]; ++nInd)
8388e0c
+    {
8388e0c
+        initialData.push_back(sal::static_int_cast<sal_uInt8>((pPassData[nInd] >> 0) & 0xff));
8388e0c
+        initialData.push_back(sal::static_int_cast<sal_uInt8>((pPassData[nInd] >> 8) & 0xff));
8388e0c
+    }
8388e0c
+
8388e0c
+    // calculate SHA1 hash of initialData
8388e0c
+    rtl_digest_SHA1(initialData.data(), initialData.size(), m_aDigestValue.data(), m_aDigestValue.size());
8388e0c
 
8388e0c
-    lcl_PrintDigest(m_pDigestValue, "digest value");
8388e0c
+    lcl_PrintDigest(m_aDigestValue.data(), "digest value");
8388e0c
 
8388e0c
     (void)memcpy (m_pDocId, pDocId, 16);
8388e0c
 
8388e0c
     lcl_PrintDigest(m_pDocId, "DocId value");
8388e0c
 }
8388e0c
 
8388e0c
-bool MSCodec_Std97::VerifyKey (
8388e0c
-    const sal_uInt8 pSaltData[16],
8388e0c
-    const sal_uInt8 pSaltDigest[16])
8388e0c
+bool MSCodec97::VerifyKey(const sal_uInt8* pSaltData, const sal_uInt8* pSaltDigest)
8388e0c
 {
8388e0c
     // both the salt data and salt digest (hash) come from the document being imported.
8388e0c
 
8388e0c
 #if DEBUG_MSO_ENCRYPTION_STD97
8388e0c
-    fprintf(stdout, "MSCodec_Std97::VerifyKey: \n");
8388e0c
+    fprintf(stdout, "MSCodec97::VerifyKey: \n");
8388e0c
     lcl_PrintDigest(pSaltData, "salt data");
8388e0c
     lcl_PrintDigest(pSaltDigest, "salt hash");
8388e0c
 #endif
8388e0c
@@ -361,35 +397,42 @@ bool MSCodec_Std97::VerifyKey (
8388e0c
 
8388e0c
     if (InitCipher(0))
8388e0c
     {
8388e0c
-        sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5];
8388e0c
-        GetDigestFromSalt(pSaltData, pDigest);
8388e0c
+        std::vector<sal_uInt8> aDigest(m_nHashLen);
8388e0c
+        GetDigestFromSalt(pSaltData, aDigest.data());
8388e0c
 
8388e0c
-        sal_uInt8 pBuffer[16];
8388e0c
+        std::vector<sal_uInt8> aBuffer(m_nHashLen);
8388e0c
         // Decode original SaltDigest into Buffer.
8388e0c
-        rtl_cipher_decode (
8388e0c
-            m_hCipher, pSaltDigest, 16, pBuffer, sizeof(pBuffer));
8388e0c
+        rtl_cipher_decode(m_hCipher, pSaltDigest, m_nHashLen, aBuffer.data(), m_nHashLen);
8388e0c
 
8388e0c
         // Compare Buffer with computed Digest.
8388e0c
-        result = (memcmp (pBuffer, pDigest, sizeof(pDigest)) == 0);
8388e0c
+        result = (memcmp(aBuffer.data(), aDigest.data(), m_nHashLen) == 0);
8388e0c
 
8388e0c
         // Erase Buffer and Digest arrays.
8388e0c
-        rtl_secureZeroMemory (pBuffer, sizeof(pBuffer));
8388e0c
-        rtl_secureZeroMemory (pDigest, sizeof(pDigest));
8388e0c
+        rtl_secureZeroMemory(aBuffer.data(), m_nHashLen);
8388e0c
+        rtl_secureZeroMemory(aDigest.data(), m_nHashLen);
8388e0c
     }
8388e0c
 
8388e0c
     return result;
8388e0c
 }
8388e0c
 
8388e0c
-bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter)
8388e0c
+void MSCodec_CryptoAPI::GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest)
8388e0c
+{
8388e0c
+    std::vector<sal_uInt8> verifier(16);
8388e0c
+    rtl_cipher_decode(m_hCipher,
8388e0c
+        pSaltData, 16, verifier.data(), verifier.size());
8388e0c
+
8388e0c
+    rtl_digest_SHA1(verifier.data(), verifier.size(), pDigest, RTL_DIGEST_LENGTH_SHA1);
8388e0c
+}
8388e0c
+
8388e0c
+bool MSCodec_Std97::InitCipher(sal_uInt32 nCounter)
8388e0c
 {
8388e0c
-    rtlCipherError result;
8388e0c
     sal_uInt8      pKeyData[64]; // 512-bit message block
8388e0c
 
8388e0c
     // Initialize KeyData array.
8388e0c
     (void)memset (pKeyData, 0, sizeof(pKeyData));
8388e0c
 
8388e0c
     // Fill 40 bit of DigestValue into [0..4].
8388e0c
-    (void)memcpy (pKeyData, m_pDigestValue, 5);
8388e0c
+    (void)memcpy (pKeyData, m_aDigestValue.data(), 5);
8388e0c
 
8388e0c
     // Fill counter into [5..8].
8388e0c
     pKeyData[ 5] = sal_uInt8((nCounter >>  0) & 0xff);
8388e0c
@@ -407,7 +450,7 @@ bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter)
8388e0c
         m_hDigest, pKeyData, RTL_DIGEST_LENGTH_MD5);
8388e0c
 
8388e0c
     // Initialize Cipher with KeyData (for decoding).
8388e0c
-    result = rtl_cipher_init (
8388e0c
+    rtlCipherError result = rtl_cipher_init (
8388e0c
         m_hCipher, rtl_Cipher_DirectionBoth,
8388e0c
         pKeyData, RTL_DIGEST_LENGTH_MD5, nullptr, 0);
8388e0c
 
8388e0c
@@ -417,12 +460,30 @@ bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter)
8388e0c
     return (result == rtl_Cipher_E_None);
8388e0c
 }
8388e0c
 
8388e0c
-bool MSCodec_Std97::CreateSaltDigest( const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] )
8388e0c
+bool MSCodec_CryptoAPI::InitCipher(sal_uInt32 nCounter)
8388e0c
+{
8388e0c
+    // data = hash + iterator (4bytes)
8388e0c
+    std::vector<sal_uInt8> aKeyData(m_aDigestValue);
8388e0c
+    aKeyData.push_back(sal_uInt8((nCounter >>  0) & 0xff));
8388e0c
+    aKeyData.push_back(sal_uInt8((nCounter >>  8) & 0xff));
8388e0c
+    aKeyData.push_back(sal_uInt8((nCounter >> 16) & 0xff));
8388e0c
+    aKeyData.push_back(sal_uInt8((nCounter >> 24) & 0xff));
8388e0c
+
8388e0c
+    std::vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1);
8388e0c
+    rtl_digest_SHA1(aKeyData.data(), aKeyData.size(), hash.data(), RTL_DIGEST_LENGTH_SHA1);
8388e0c
+
8388e0c
+    rtlCipherError result =
8388e0c
+        rtl_cipher_init(m_hCipher, rtl_Cipher_DirectionDecode,
8388e0c
+                        hash.data(), ENCRYPT_KEY_SIZE_AES_128/8, nullptr, 0);
8388e0c
+
8388e0c
+    return (result == rtl_Cipher_E_None);
8388e0c
+}
8388e0c
+
8388e0c
+void MSCodec_Std97::CreateSaltDigest( const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] )
8388e0c
 {
8388e0c
 #if DEBUG_MSO_ENCRYPTION_STD97
8388e0c
     lcl_PrintDigest(nSaltData, "salt data");
8388e0c
 #endif
8388e0c
-    bool result = false;
8388e0c
 
8388e0c
     if (InitCipher(0))
8388e0c
     {
8388e0c
@@ -434,35 +495,29 @@ bool MSCodec_Std97::CreateSaltDigest( const sal_uInt8 nSaltData[16], sal_uInt8 n
8388e0c
 
8388e0c
         (void)memcpy(nSaltDigest, pDigest, 16);
8388e0c
     }
8388e0c
-
8388e0c
-    return result;
8388e0c
 }
8388e0c
 
8388e0c
-bool MSCodec_Std97::Encode (
8388e0c
-    const void *pData,   sal_Size nDatLen,
8388e0c
-    sal_uInt8  *pBuffer, sal_Size nBufLen)
8388e0c
+bool MSCodec97::Encode (
8388e0c
+    const void *pData,   std::size_t nDatLen,
8388e0c
+    sal_uInt8  *pBuffer, std::size_t nBufLen)
8388e0c
 {
8388e0c
-    rtlCipherError result;
8388e0c
-
8388e0c
-    result = rtl_cipher_encode (
8388e0c
+    rtlCipherError result = rtl_cipher_encode(
8388e0c
         m_hCipher, pData, nDatLen, pBuffer, nBufLen);
8388e0c
 
8388e0c
     return (result == rtl_Cipher_E_None);
8388e0c
 }
8388e0c
 
8388e0c
-bool MSCodec_Std97::Decode (
8388e0c
-    const void *pData,   sal_Size nDatLen,
8388e0c
-    sal_uInt8  *pBuffer, sal_Size nBufLen)
8388e0c
+bool MSCodec97::Decode (
8388e0c
+    const void *pData,   std::size_t nDatLen,
8388e0c
+    sal_uInt8  *pBuffer, std::size_t nBufLen)
8388e0c
 {
8388e0c
-    rtlCipherError result;
8388e0c
-
8388e0c
-    result = rtl_cipher_decode (
8388e0c
+    rtlCipherError result = rtl_cipher_decode(
8388e0c
         m_hCipher, pData, nDatLen, pBuffer, nBufLen);
8388e0c
 
8388e0c
     return (result == rtl_Cipher_E_None);
8388e0c
 }
8388e0c
 
8388e0c
-bool MSCodec_Std97::Skip( sal_Size nDatLen )
8388e0c
+bool MSCodec97::Skip(std::size_t nDatLen)
8388e0c
 {
8388e0c
     sal_uInt8 pnDummy[ 1024 ];
8388e0c
     sal_Size nDatLeft = nDatLen;
8388e0c
@@ -478,7 +533,7 @@ bool MSCodec_Std97::Skip( sal_Size nDatLen )
8388e0c
     return bResult;
8388e0c
 }
8388e0c
 
8388e0c
-void MSCodec_Std97::GetDigestFromSalt( const sal_uInt8 pSaltData[16], sal_uInt8 pDigest[16] )
8388e0c
+void MSCodec_Std97::GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest)
8388e0c
 {
8388e0c
     sal_uInt8 pBuffer[64];
8388e0c
     sal_uInt8 pDigestLocal[16];
8388e0c
@@ -537,12 +592,41 @@ void MSCodec_Std97::GetEncryptKey (
8388e0c
     }
8388e0c
 }
8388e0c
 
8388e0c
-void MSCodec_Std97::GetDocId( sal_uInt8 pDocId[16] )
8388e0c
+void MSCodec97::GetDocId( sal_uInt8 pDocId[16] )
8388e0c
 {
8388e0c
     if ( sizeof( m_pDocId ) == 16 )
8388e0c
         (void)memcpy( pDocId, m_pDocId, 16 );
8388e0c
 }
8388e0c
 
8388e0c
+EncryptionStandardHeader::EncryptionStandardHeader()
8388e0c
+{
8388e0c
+    flags        = 0;
8388e0c
+    sizeExtra    = 0;
8388e0c
+    algId        = 0;
8388e0c
+    algIdHash    = 0;
8388e0c
+    keyBits      = 0;
8388e0c
+    providedType = 0;
8388e0c
+    reserved1    = 0;
8388e0c
+    reserved2    = 0;
8388e0c
+}
8388e0c
+
8388e0c
+EncryptionVerifierAES::EncryptionVerifierAES()
8388e0c
+    : saltSize(SALT_LENGTH)
8388e0c
+    , encryptedVerifierHashSize(SHA1_HASH_LENGTH)
8388e0c
+{
8388e0c
+    memset(salt, 0, sizeof(salt));
8388e0c
+    memset(encryptedVerifier, 0, sizeof(encryptedVerifier));
8388e0c
+    memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash));
8388e0c
+}
8388e0c
+
8388e0c
+EncryptionVerifierRC4::EncryptionVerifierRC4()
8388e0c
+    : saltSize(SALT_LENGTH)
8388e0c
+    , encryptedVerifierHashSize(SHA1_HASH_LENGTH)
8388e0c
+{
8388e0c
+    memset(salt, 0, sizeof(salt));
8388e0c
+    memset(encryptedVerifier, 0, sizeof(encryptedVerifier));
8388e0c
+    memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash));
8388e0c
+}
8388e0c
 
8388e0c
 
8388e0c
 }
8388e0c
diff --git a/include/filter/msfilter/mscodec.hxx b/include/filter/msfilter/mscodec.hxx
8388e0c
index 4f5676b..4ab6c9b 100644
8388e0c
--- a/include/filter/msfilter/mscodec.hxx
8388e0c
+++ b/include/filter/msfilter/mscodec.hxx
8388e0c
@@ -26,6 +26,12 @@
8388e0c
 #include <rtl/cipher.h>
8388e0c
 #include <rtl/digest.h>
8388e0c
 #include <filter/msfilter/msfilterdllapi.h>
8388e0c
+#include <sal/types.h>
8388e0c
+#include <vector>
8388e0c
+
8388e0c
+namespace com { namespace sun { namespace star {
8388e0c
+    namespace beans { struct NamedValue; }
8388e0c
+} } }
8388e0c
 
8388e0c
 namespace msfilter {
8388e0c
 
8388e0c
@@ -172,20 +178,11 @@ public:
8388e0c
     virtual void                Decode( sal_uInt8* pnData, sal_Size nBytes ) override;
8388e0c
 };
8388e0c
 
8388e0c
-
8388e0c
-
8388e0c
-
8388e0c
-/** Encodes and decodes data from protected MSO 97+ documents.
8388e0c
-
8388e0c
-    This is a wrapper class around low level cryptographic functions from RTL.
8388e0c
-    Implementation is based on the wvDecrypt package by Caolan McNamara:
8388e0c
-    http://www.csn.ul.ie/~caolan/docs/wvDecrypt.html
8388e0c
- */
8388e0c
-class MSFILTER_DLLPUBLIC MSCodec_Std97
8388e0c
+class MSFILTER_DLLPUBLIC MSCodec97
8388e0c
 {
8388e0c
 public:
8388e0c
-    explicit            MSCodec_Std97();
8388e0c
-                        ~MSCodec_Std97();
8388e0c
+    MSCodec97(size_t nHashLen);
8388e0c
+    virtual ~MSCodec97();
8388e0c
 
8388e0c
     /** Initializes the algorithm with the encryption data.
8388e0c
 
8388e0c
@@ -193,7 +190,7 @@ public:
8388e0c
             The sequence contains the necessary data to initialize
8388e0c
             the codec.
8388e0c
      */
8388e0c
-    bool                InitCodec( const css::uno::Sequence< css::beans::NamedValue >& aData );
8388e0c
+    bool InitCodec(const css::uno::Sequence< css::beans::NamedValue >& aData);
8388e0c
 
8388e0c
     /** Retrieves the encryption data
8388e0c
 
8388e0c
@@ -203,7 +200,6 @@ public:
8388e0c
      */
8388e0c
     css::uno::Sequence< css::beans::NamedValue > GetEncryptionData();
8388e0c
 
8388e0c
-
8388e0c
     /** Initializes the algorithm with the specified password and document ID.
8388e0c
 
8388e0c
         @param pPassData
8388e0c
@@ -212,9 +208,9 @@ public:
8388e0c
         @param pDocId
8388e0c
             Unique document identifier read from or written to the file.
8388e0c
      */
8388e0c
-    void                InitKey(
8388e0c
-                            const sal_uInt16 pPassData[ 16 ],
8388e0c
-                            const sal_uInt8 pDocId[ 16 ] );
8388e0c
+    virtual void InitKey(const sal_uInt16 pPassData[16],
8388e0c
+                         const sal_uInt8 pDocId[16]) = 0;
8388e0c
+
8388e0c
 
8388e0c
     /** Verifies the validity of the password using the passed salt data.
8388e0c
 
8388e0c
@@ -230,9 +226,9 @@ public:
8388e0c
         @return
8388e0c
             true = Test was successful.
8388e0c
      */
8388e0c
-    bool                VerifyKey(
8388e0c
-                            const sal_uInt8 pSaltData[ 16 ],
8388e0c
-                            const sal_uInt8 pSaltDigest[ 16 ] );
8388e0c
+    bool VerifyKey(const sal_uInt8* pSaltData, const sal_uInt8* pSaltDigest);
8388e0c
+
8388e0c
+    virtual void GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest) = 0;
8388e0c
 
8388e0c
     /** Rekeys the codec using the specified counter.
8388e0c
 
8388e0c
@@ -249,11 +245,7 @@ public:
8388e0c
         @param nCounter
8388e0c
             Block counter used to rekey the cipher.
8388e0c
      */
8388e0c
-    bool                InitCipher( sal_uInt32 nCounter );
8388e0c
-
8388e0c
-    /** Creates an MD5 digest of salt digest. */
8388e0c
-    bool                CreateSaltDigest(
8388e0c
-                            const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] );
8388e0c
+    virtual bool                InitCipher(sal_uInt32 nCounter) = 0;
8388e0c
 
8388e0c
     /** Encodes a block of memory.
8388e0c
 
8388e0c
@@ -277,9 +269,8 @@ public:
8388e0c
         @return
8388e0c
             true = Encoding was successful (no error occurred).
8388e0c
     */
8388e0c
-    bool                Encode(
8388e0c
-                            const void* pData, sal_Size nDatLen,
8388e0c
-                            sal_uInt8* pBuffer, sal_Size nBufLen );
8388e0c
+    bool                Encode(const void* pData, std::size_t nDatLen,
8388e0c
+                               sal_uInt8* pBuffer, std::size_t nBufLen);
8388e0c
 
8388e0c
     /** Decodes a block of memory.
8388e0c
 
8388e0c
@@ -303,9 +294,8 @@ public:
8388e0c
         @return
8388e0c
             true = Decoding was successful (no error occurred).
8388e0c
     */
8388e0c
-    bool                Decode(
8388e0c
-                            const void* pData, sal_Size nDatLen,
8388e0c
-                            sal_uInt8* pBuffer, sal_Size nBufLen );
8388e0c
+    bool                Decode(const void* pData, std::size_t nDatLen,
8388e0c
+                               sal_uInt8* pBuffer, std::size_t nBufLen);
8388e0c
 
8388e0c
     /** Lets the cipher skip a specific amount of bytes.
8388e0c
 
8388e0c
@@ -319,7 +309,66 @@ public:
8388e0c
         @param nDatLen
8388e0c
             Number of bytes to be skipped (cipher "seeks" forward).
8388e0c
      */
8388e0c
-    bool                Skip( sal_Size nDatLen );
8388e0c
+    bool                Skip(std::size_t nDatLen);
8388e0c
+
8388e0c
+    /* allows to get the unique document id from the codec
8388e0c
+     */
8388e0c
+    void                GetDocId( sal_uInt8 pDocId[16] );
8388e0c
+
8388e0c
+private:
8388e0c
+                        MSCodec97(const MSCodec97&) = delete;
8388e0c
+    MSCodec97&          operator=(const MSCodec97&) = delete;
8388e0c
+
8388e0c
+protected:
8388e0c
+    size_t              m_nHashLen;
8388e0c
+    rtlCipher           m_hCipher;
8388e0c
+    sal_uInt8           m_pDocId[16];
8388e0c
+    std::vector<sal_uInt8> m_aDigestValue;
8388e0c
+};
8388e0c
+
8388e0c
+/** Encodes and decodes data from protected MSO 97+ documents.
8388e0c
+
8388e0c
+    This is a wrapper class around low level cryptographic functions from RTL.
8388e0c
+    Implementation is based on the wvDecrypt package by Caolan McNamara:
8388e0c
+    http://www.csn.ul.ie/~caolan/docs/wvDecrypt.html
8388e0c
+ */
8388e0c
+class MSFILTER_DLLPUBLIC MSCodec_Std97 :  public MSCodec97
8388e0c
+{
8388e0c
+public:
8388e0c
+    MSCodec_Std97();
8388e0c
+    virtual ~MSCodec_Std97() override;
8388e0c
+
8388e0c
+    /** Initializes the algorithm with the specified password and document ID.
8388e0c
+
8388e0c
+        @param pPassData
8388e0c
+            Wide character array containing the password. Must be zero
8388e0c
+            terminated, which results in a maximum length of 15 characters.
8388e0c
+        @param pDocId
8388e0c
+            Unique document identifier read from or written to the file.
8388e0c
+     */
8388e0c
+    virtual void InitKey(const sal_uInt16 pPassData[16],
8388e0c
+                         const sal_uInt8 pDocId[16]) override;
8388e0c
+
8388e0c
+    /** Rekeys the codec using the specified counter.
8388e0c
+
8388e0c
+        After reading a specific amount of data the cipher algorithm needs to
8388e0c
+        be rekeyed using a counter that counts the data blocks.
8388e0c
+
8388e0c
+        The block size is for example 512 Bytes for Word files and 1024 Bytes
8388e0c
+        for Excel files.
8388e0c
+
8388e0c
+        @precond
8388e0c
+            The codec must be initialized with InitKey() before this function
8388e0c
+            can be used.
8388e0c
+
8388e0c
+        @param nCounter
8388e0c
+            Block counter used to rekey the cipher.
8388e0c
+     */
8388e0c
+    virtual bool InitCipher(sal_uInt32 nCounter) override;
8388e0c
+
8388e0c
+    /** Creates an MD5 digest of salt digest. */
8388e0c
+    void               CreateSaltDigest(
8388e0c
+                            const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] );
8388e0c
 
8388e0c
     /** Gets salt data and salt digest.
8388e0c
 
8388e0c
@@ -339,22 +388,108 @@ public:
8388e0c
                             sal_uInt8 pSaltData[16],
8388e0c
                             sal_uInt8 pSaltDigest[16]);
8388e0c
 
8388e0c
-    /* allows to get the unique document id from the codec
8388e0c
-     */
8388e0c
-    void                GetDocId( sal_uInt8 pDocId[16] );
8388e0c
-
8388e0c
-    void                GetDigestFromSalt( const sal_uInt8 pSaltData[16], sal_uInt8 pDigest[16] );
8388e0c
+    virtual void        GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest) override;
8388e0c
 
8388e0c
 private:
8388e0c
                         MSCodec_Std97( const MSCodec_Std97& ) = delete;
8388e0c
     MSCodec_Std97&      operator=( const MSCodec_Std97& ) = delete;
8388e0c
 
8388e0c
-    rtlCipher           m_hCipher;
8388e0c
     rtlDigest           m_hDigest;
8388e0c
-    sal_uInt8           m_pDigestValue[ RTL_DIGEST_LENGTH_MD5 ];
8388e0c
-    sal_uInt8           m_pDocId[16];
8388e0c
 };
8388e0c
 
8388e0c
+class MSFILTER_DLLPUBLIC MSCodec_CryptoAPI :  public MSCodec97
8388e0c
+{
8388e0c
+public:
8388e0c
+    MSCodec_CryptoAPI();
8388e0c
+
8388e0c
+    virtual void InitKey(const sal_uInt16 pPassData[16],
8388e0c
+                         const sal_uInt8 pDocId[16]) override;
8388e0c
+    virtual bool InitCipher(sal_uInt32 nCounter) override;
8388e0c
+    virtual void GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest) override;
8388e0c
+};
8388e0c
+
8388e0c
+const sal_uInt32 ENCRYPTINFO_CRYPTOAPI      = 0x00000004;
8388e0c
+const sal_uInt32 ENCRYPTINFO_DOCPROPS       = 0x00000008;
8388e0c
+const sal_uInt32 ENCRYPTINFO_EXTERNAL       = 0x00000010;
8388e0c
+const sal_uInt32 ENCRYPTINFO_AES            = 0x00000020;
8388e0c
+
8388e0c
+const sal_uInt32 ENCRYPT_ALGO_AES128        = 0x0000660E;
8388e0c
+const sal_uInt32 ENCRYPT_ALGO_AES192        = 0x0000660F;
8388e0c
+const sal_uInt32 ENCRYPT_ALGO_AES256        = 0x00006610;
8388e0c
+const sal_uInt32 ENCRYPT_ALGO_RC4           = 0x00006801;
8388e0c
+
8388e0c
+const sal_uInt32 ENCRYPT_HASH_SHA1          = 0x00008004;
8388e0c
+
8388e0c
+const sal_uInt32 ENCRYPT_KEY_SIZE_AES_128   = 0x00000080;
8388e0c
+const sal_uInt32 ENCRYPT_KEY_SIZE_AES_192   = 0x000000C0;
8388e0c
+const sal_uInt32 ENCRYPT_KEY_SIZE_AES_256   = 0x00000100;
8388e0c
+
8388e0c
+const sal_uInt32 ENCRYPT_PROVIDER_TYPE_AES  = 0x00000018;
8388e0c
+const sal_uInt32 ENCRYPT_PROVIDER_TYPE_RC4  = 0x00000001;
8388e0c
+
8388e0c
+// version of encryption info used in MS Office 1997 (major = 1, minor = 1)
8388e0c
+const sal_uInt32 VERSION_INFO_1997_FORMAT       = 0x00010001;
8388e0c
+// version of encryption info used in MS Office 2007 (major = 3, minor = 2)
8388e0c
+const sal_uInt32 VERSION_INFO_2007_FORMAT       = 0x00020003;
8388e0c
+// version of encryption info used in MS Office 2007 SP2 and older (major = 4, minor = 2)
8388e0c
+const sal_uInt32 VERSION_INFO_2007_FORMAT_SP2   = 0x00020004;
8388e0c
+
8388e0c
+// version of encryption info - agile (major = 4, minor = 4)
8388e0c
+const sal_uInt32 VERSION_INFO_AGILE         = 0x00040004;
8388e0c
+
8388e0c
+const sal_uInt32 SALT_LENGTH                    = 16;
8388e0c
+const sal_uInt32 ENCRYPTED_VERIFIER_LENGTH      = 16;
8388e0c
+const sal_uInt32 SHA1_HASH_LENGTH = RTL_DIGEST_LENGTH_SHA1; // 20
8388e0c
+const sal_uInt32 SHA256_HASH_LENGTH = 32;
8388e0c
+const sal_uInt32 SHA512_HASH_LENGTH = 64;
8388e0c
+
8388e0c
+struct MSFILTER_DLLPUBLIC EncryptionStandardHeader
8388e0c
+{
8388e0c
+    sal_uInt32 flags;
8388e0c
+    sal_uInt32 sizeExtra;       // 0
8388e0c
+    sal_uInt32 algId;           // if flag AES && CRYPTOAPI this defaults to 128-bit AES
8388e0c
+    sal_uInt32 algIdHash;       // 0: determine by flags - defaults to SHA-1 if not external
8388e0c
+    sal_uInt32 keyBits;         // key size in bits: 0 (determine by flags), 128, 192, 256
8388e0c
+    sal_uInt32 providedType;    // AES or RC4
8388e0c
+    sal_uInt32 reserved1;       // 0
8388e0c
+    sal_uInt32 reserved2;       // 0
8388e0c
+
8388e0c
+    EncryptionStandardHeader();
8388e0c
+};
8388e0c
+
8388e0c
+struct MSFILTER_DLLPUBLIC EncryptionVerifierAES
8388e0c
+{
8388e0c
+    sal_uInt32 saltSize;                                                // must be 0x00000010
8388e0c
+    sal_uInt8  salt[SALT_LENGTH];                                       // random generated salt value
8388e0c
+    sal_uInt8  encryptedVerifier[ENCRYPTED_VERIFIER_LENGTH];            // randomly generated verifier value
8388e0c
+    sal_uInt32 encryptedVerifierHashSize;                               // actually written hash size - depends on algorithm
8388e0c
+    sal_uInt8  encryptedVerifierHash[SHA256_HASH_LENGTH];               // verifier value hash - itself also encrypted
8388e0c
+
8388e0c
+    EncryptionVerifierAES();
8388e0c
+};
8388e0c
+
8388e0c
+struct MSFILTER_DLLPUBLIC EncryptionVerifierRC4
8388e0c
+{
8388e0c
+    sal_uInt32 saltSize;                                                // must be 0x00000010
8388e0c
+    sal_uInt8  salt[SALT_LENGTH];                                       // random generated salt value
8388e0c
+    sal_uInt8  encryptedVerifier[ENCRYPTED_VERIFIER_LENGTH];            // randomly generated verifier value
8388e0c
+    sal_uInt32 encryptedVerifierHashSize;                               // actually written hash size - depends on algorithm
8388e0c
+    sal_uInt8  encryptedVerifierHash[SHA1_HASH_LENGTH];                 // verifier value hash - itself also encrypted
8388e0c
+
8388e0c
+    EncryptionVerifierRC4();
8388e0c
+};
8388e0c
+
8388e0c
+struct MSFILTER_DLLPUBLIC StandardEncryptionInfo
8388e0c
+{
8388e0c
+    EncryptionStandardHeader header;
8388e0c
+    EncryptionVerifierAES    verifier;
8388e0c
+};
8388e0c
+
8388e0c
+struct MSFILTER_DLLPUBLIC RC4EncryptionInfo
8388e0c
+{
8388e0c
+    EncryptionStandardHeader header;
8388e0c
+    EncryptionVerifierRC4 verifier;
8388e0c
+};
8388e0c
 
8388e0c
 
8388e0c
 } // namespace msfilter
8388e0c
diff --git a/include/oox/crypto/CryptTools.hxx b/include/oox/crypto/CryptTools.hxx
8388e0c
index 898c47d..dc91ad9 100644
8388e0c
--- a/include/oox/crypto/CryptTools.hxx
8388e0c
+++ b/include/oox/crypto/CryptTools.hxx
8388e0c
@@ -126,9 +126,6 @@ public:
8388e0c
         SHA512
8388e0c
     };
8388e0c
 
8388e0c
-    static const sal_uInt32 DIGEST_LENGTH_SHA1;
8388e0c
-    static const sal_uInt32 DIGEST_LENGTH_SHA512;
8388e0c
-
8388e0c
 private:
8388e0c
     DigestType meType;
8388e0c
 
8388e0c
diff --git a/include/oox/crypto/Standard2007Engine.hxx b/include/oox/crypto/Standard2007Engine.hxx
8388e0c
index 5e5a6fc..10cac82 100644
8388e0c
--- a/include/oox/crypto/Standard2007Engine.hxx
8388e0c
+++ b/include/oox/crypto/Standard2007Engine.hxx
8388e0c
@@ -13,75 +13,23 @@
8388e0c
 
8388e0c
 #include <oox/crypto/CryptTools.hxx>
8388e0c
 #include <oox/crypto/CryptoEngine.hxx>
8388e0c
+#include <filter/msfilter/mscodec.hxx>
8388e0c
+#include <oox/crypto/CryptoEngine.hxx>
8388e0c
+#include <rtl/digest.h>
8388e0c
+#include <rtl/ustring.hxx>
8388e0c
+#include <sal/types.h>
8388e0c
 
8388e0c
 namespace oox {
8388e0c
-namespace core {
8388e0c
-
8388e0c
-const sal_uInt32 ENCRYPTINFO_CRYPTOAPI      = 0x00000004;
8388e0c
-const sal_uInt32 ENCRYPTINFO_DOCPROPS       = 0x00000008;
8388e0c
-const sal_uInt32 ENCRYPTINFO_EXTERNAL       = 0x00000010;
8388e0c
-const sal_uInt32 ENCRYPTINFO_AES            = 0x00000020;
8388e0c
-
8388e0c
-const sal_uInt32 ENCRYPT_ALGO_AES128        = 0x0000660E;
8388e0c
-const sal_uInt32 ENCRYPT_ALGO_AES192        = 0x0000660F;
8388e0c
-const sal_uInt32 ENCRYPT_ALGO_AES256        = 0x00006610;
8388e0c
-const sal_uInt32 ENCRYPT_ALGO_RC4           = 0x00006801;
8388e0c
-
8388e0c
-const sal_uInt32 ENCRYPT_HASH_SHA1          = 0x00008004;
8388e0c
-
8388e0c
-const sal_uInt32 ENCRYPT_KEY_SIZE_AES_128   = 0x00000080;
8388e0c
-const sal_uInt32 ENCRYPT_KEY_SIZE_AES_192   = 0x000000C0;
8388e0c
-const sal_uInt32 ENCRYPT_KEY_SIZE_AES_256   = 0x00000100;
8388e0c
+    class BinaryXInputStream;
8388e0c
+    class BinaryXOutputStream;
8388e0c
+}
8388e0c
 
8388e0c
-const sal_uInt32 ENCRYPT_PROVIDER_TYPE_AES  = 0x00000018;
8388e0c
-const sal_uInt32 ENCRYPT_PROVIDER_TYPE_RC4  = 0x00000001;
8388e0c
-
8388e0c
-// version of encryption info used in MS Office 2007 (major = 3, minor = 2)
8388e0c
-const sal_uInt32 VERSION_INFO_2007_FORMAT       = 0x00020003;
8388e0c
-// version of encryption info used in MS Office 2007 SP2 and older (major = 4, minor = 2)
8388e0c
-const sal_uInt32 VERSION_INFO_2007_FORMAT_SP2   = 0x00020004;
8388e0c
-
8388e0c
-// version of encryption info - agile (major = 4, minor = 4)
8388e0c
-const sal_uInt32 VERSION_INFO_AGILE         = 0x00040004;
8388e0c
-
8388e0c
-const sal_uInt32 SALT_LENGTH                    = 16;
8388e0c
-const sal_uInt32 ENCRYPTED_VERIFIER_LENGTH      = 16;
8388e0c
-const sal_uInt32 ENCRYPTED_VERIFIER_HASH_LENGTH = 32;
8388e0c
-
8388e0c
-struct EncryptionStandardHeader
8388e0c
-{
8388e0c
-    sal_uInt32 flags;
8388e0c
-    sal_uInt32 sizeExtra;       // 0
8388e0c
-    sal_uInt32 algId;           // if flag AES && CRYPTOAPI this defaults to 128-bit AES
8388e0c
-    sal_uInt32 algIdHash;       // 0: determine by flags - defaults to SHA-1 if not external
8388e0c
-    sal_uInt32 keyBits;         // key size in bits: 0 (determine by flags), 128, 192, 256
8388e0c
-    sal_uInt32 providedType;    // AES or RC4
8388e0c
-    sal_uInt32 reserved1;       // 0
8388e0c
-    sal_uInt32 reserved2;       // 0
8388e0c
-
8388e0c
-    EncryptionStandardHeader();
8388e0c
-};
8388e0c
-
8388e0c
-struct EncryptionVerifierAES
8388e0c
-{
8388e0c
-    sal_uInt32 saltSize;                                                // must be 0x00000010
8388e0c
-    sal_uInt8  salt[SALT_LENGTH];                                       // random generated salt value
8388e0c
-    sal_uInt8  encryptedVerifier[ENCRYPTED_VERIFIER_LENGTH];            // randomly generated verifier value
8388e0c
-    sal_uInt32 encryptedVerifierHashSize;                               // actually written hash size - depends on algorithm
8388e0c
-    sal_uInt8  encryptedVerifierHash[ENCRYPTED_VERIFIER_HASH_LENGTH];   // verifier value hash - itself also encrypted
8388e0c
-
8388e0c
-    EncryptionVerifierAES();
8388e0c
-};
8388e0c
-
8388e0c
-struct StandardEncryptionInfo
8388e0c
-{
8388e0c
-    EncryptionStandardHeader header;
8388e0c
-    EncryptionVerifierAES    verifier;
8388e0c
-};
8388e0c
+namespace oox {
8388e0c
+namespace core {
8388e0c
 
8388e0c
 class Standard2007Engine : public CryptoEngine
8388e0c
 {
8388e0c
-    StandardEncryptionInfo mInfo;
8388e0c
+    msfilter::StandardEncryptionInfo mInfo;
8388e0c
 
8388e0c
     bool generateVerifier();
8388e0c
     bool calculateEncryptionKey(const OUString& rPassword);
8388e0c
@@ -90,7 +38,7 @@ public:
8388e0c
     Standard2007Engine();
8388e0c
     virtual ~Standard2007Engine();
8388e0c
 
8388e0c
-    StandardEncryptionInfo& getInfo() { return mInfo;}
8388e0c
+    msfilter::StandardEncryptionInfo& getInfo() { return mInfo;}
8388e0c
 
8388e0c
     virtual bool generateEncryptionKey(const OUString& rPassword) override;
8388e0c
 
8388e0c
diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx
8388e0c
index f21b0e1..9b1d50b 100644
8388e0c
--- a/oox/source/crypto/CryptTools.cxx
8388e0c
+++ b/oox/source/crypto/CryptTools.cxx
8388e0c
@@ -9,6 +9,7 @@
8388e0c
  */
8388e0c
 
8388e0c
 #include "oox/crypto/CryptTools.hxx"
8388e0c
+#include <filter/msfilter/mscodec.hxx>
8388e0c
 #include <com/sun/star/uno/RuntimeException.hpp>
8388e0c
 
8388e0c
 namespace oox {
8388e0c
@@ -196,15 +197,6 @@ sal_uInt32 Encrypt::update(vector<sal_uInt8>& output, vector<sal_uInt8>& input,
8388e0c
 
8388e0c
 // Digest
8388e0c
 
8388e0c
-#if USE_TLS_OPENSSL
8388e0c
-const sal_uInt32 Digest::DIGEST_LENGTH_SHA1 = SHA_DIGEST_LENGTH;
8388e0c
-const sal_uInt32 Digest::DIGEST_LENGTH_SHA512 = SHA512_DIGEST_LENGTH;
8388e0c
-#endif
8388e0c
-#if USE_TLS_NSS
8388e0c
-const sal_uInt32 Digest::DIGEST_LENGTH_SHA1 = SHA1_LENGTH;
8388e0c
-const sal_uInt32 Digest::DIGEST_LENGTH_SHA512 = SHA512_LENGTH;
8388e0c
-#endif
8388e0c
-
8388e0c
 namespace
8388e0c
 {
8388e0c
 
8388e0c
@@ -275,9 +267,9 @@ sal_uInt32 Digest::getLength()
8388e0c
     switch(meType)
8388e0c
     {
8388e0c
         case SHA1:
8388e0c
-            return DIGEST_LENGTH_SHA1;
8388e0c
+            return msfilter::SHA1_HASH_LENGTH;
8388e0c
         case SHA512:
8388e0c
-            return DIGEST_LENGTH_SHA512;
8388e0c
+            return msfilter::SHA512_HASH_LENGTH;
8388e0c
         default:
8388e0c
             break;
8388e0c
     }
8388e0c
diff --git a/oox/source/crypto/DocumentDecryption.cxx b/oox/source/crypto/DocumentDecryption.cxx
8388e0c
index 8dcf4ca..80054b3 100644
8388e0c
--- a/oox/source/crypto/DocumentDecryption.cxx
8388e0c
+++ b/oox/source/crypto/DocumentDecryption.cxx
8388e0c
@@ -235,7 +235,7 @@ bool DocumentDecryption::readAgileEncryptionInfo(Reference< XInputStream >& xInp
8388e0c
         info.cipherAlgorithm == "AES" &&
8388e0c
         info.cipherChaining  == "ChainingModeCBC" &&
8388e0c
         info.hashAlgorithm   == "SHA1" &&
8388e0c
-        info.hashSize        == 20)
8388e0c
+        info.hashSize        == msfilter::SHA1_HASH_LENGTH)
8388e0c
     {
8388e0c
         return true;
8388e0c
     }
8388e0c
@@ -245,7 +245,7 @@ bool DocumentDecryption::readAgileEncryptionInfo(Reference< XInputStream >& xInp
8388e0c
         info.cipherAlgorithm == "AES" &&
8388e0c
         info.cipherChaining  == "ChainingModeCBC" &&
8388e0c
         info.hashAlgorithm   == "SHA512" &&
8388e0c
-        info.hashSize        == 64 )
8388e0c
+        info.hashSize        == msfilter::SHA512_HASH_LENGTH)
8388e0c
     {
8388e0c
         return true;
8388e0c
     }
8388e0c
@@ -257,10 +257,10 @@ bool DocumentDecryption::readStandard2007EncryptionInfo(BinaryInputStream& rStre
8388e0c
 {
8388e0c
     Standard2007Engine* engine = new Standard2007Engine();
8388e0c
     mEngine.reset(engine);
8388e0c
-    StandardEncryptionInfo& info = engine->getInfo();
8388e0c
+    msfilter::StandardEncryptionInfo& info = engine->getInfo();
8388e0c
 
8388e0c
     info.header.flags = rStream.readuInt32();
8388e0c
-    if( getFlag( info.header.flags, ENCRYPTINFO_EXTERNAL ) )
8388e0c
+    if( getFlag( info.header.flags, msfilter::ENCRYPTINFO_EXTERNAL ) )
8388e0c
         return false;
8388e0c
 
8388e0c
     sal_uInt32 nHeaderSize = rStream.readuInt32();
8388e0c
@@ -291,18 +291,18 @@ bool DocumentDecryption::readStandard2007EncryptionInfo(BinaryInputStream& rStre
8388e0c
         return false;
8388e0c
 
8388e0c
     // check flags and algorithm IDs, required are AES128 and SHA-1
8388e0c
-    if( !getFlag( info.header.flags , ENCRYPTINFO_CRYPTOAPI ) )
8388e0c
+    if( !getFlag( info.header.flags, msfilter::ENCRYPTINFO_CRYPTOAPI ) )
8388e0c
         return false;
8388e0c
 
8388e0c
-    if( !getFlag( info.header.flags, ENCRYPTINFO_AES ) )
8388e0c
+    if( !getFlag( info.header.flags, msfilter::ENCRYPTINFO_AES ) )
8388e0c
         return false;
8388e0c
 
8388e0c
     // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set
8388e0c
-    if( info.header.algId != 0 && info.header.algId != ENCRYPT_ALGO_AES128 )
8388e0c
+    if( info.header.algId != 0 && info.header.algId != msfilter::ENCRYPT_ALGO_AES128 )
8388e0c
         return false;
8388e0c
 
8388e0c
     // hash algorithm ID 0 defaults to SHA-1 too
8388e0c
-    if( info.header.algIdHash != 0 && info.header.algIdHash != ENCRYPT_HASH_SHA1 )
8388e0c
+    if( info.header.algIdHash != 0 && info.header.algIdHash != msfilter::ENCRYPT_HASH_SHA1 )
8388e0c
         return false;
8388e0c
 
8388e0c
     if( info.verifier.encryptedVerifierHashSize != 20 )
8388e0c
@@ -326,12 +326,12 @@ bool DocumentDecryption::readEncryptionInfo()
8388e0c
 
8388e0c
     switch (aVersion)
8388e0c
     {
8388e0c
-        case VERSION_INFO_2007_FORMAT:
8388e0c
-        case VERSION_INFO_2007_FORMAT_SP2:
8388e0c
+        case msfilter::VERSION_INFO_2007_FORMAT:
8388e0c
+        case msfilter::VERSION_INFO_2007_FORMAT_SP2:
8388e0c
             mCryptoType = STANDARD_2007; // Set encryption info format
8388e0c
             bResult = readStandard2007EncryptionInfo( aBinaryInputStream );
8388e0c
             break;
8388e0c
-        case VERSION_INFO_AGILE:
8388e0c
+        case msfilter::VERSION_INFO_AGILE:
8388e0c
             mCryptoType = AGILE; // Set encryption info format
8388e0c
             aBinaryInputStream.skip(4);
8388e0c
             bResult = readAgileEncryptionInfo( xEncryptionInfo );
8388e0c
diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx
8388e0c
index 299d251..68df963 100644
8388e0c
--- a/oox/source/crypto/Standard2007Engine.cxx
8388e0c
+++ b/oox/source/crypto/Standard2007Engine.cxx
8388e0c
@@ -38,27 +38,6 @@ static const OUString lclCspName = "Microsoft Enhanced RSA and AES Cryptographic
8388e0c
 
8388e0c
 } // namespace
8388e0c
 
8388e0c
-EncryptionStandardHeader::EncryptionStandardHeader()
8388e0c
-{
8388e0c
-    flags        = 0;
8388e0c
-    sizeExtra    = 0;
8388e0c
-    algId        = 0;
8388e0c
-    algIdHash    = 0;
8388e0c
-    keyBits      = 0;
8388e0c
-    providedType = 0;
8388e0c
-    reserved1    = 0;
8388e0c
-    reserved2    = 0;
8388e0c
-}
8388e0c
-
8388e0c
-EncryptionVerifierAES::EncryptionVerifierAES() :
8388e0c
-    saltSize(SALT_LENGTH),
8388e0c
-    encryptedVerifierHashSize(Digest::DIGEST_LENGTH_SHA1)
8388e0c
-{
8388e0c
-    memset(salt, 0, sizeof(salt));
8388e0c
-    memset(encryptedVerifier, 0, sizeof(encryptedVerifier));
8388e0c
-    memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash));
8388e0c
-}
8388e0c
-
8388e0c
 Standard2007Engine::Standard2007Engine() :
8388e0c
     CryptoEngine()
8388e0c
 {}
8388e0c
@@ -72,23 +51,23 @@ bool Standard2007Engine::generateVerifier()
8388e0c
     if (mKey.size() != 16)
8388e0c
         return false;
8388e0c
 
8388e0c
-    vector<sal_uInt8> verifier(ENCRYPTED_VERIFIER_LENGTH);
8388e0c
-    vector<sal_uInt8> encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH);
8388e0c
+    vector<sal_uInt8> verifier(msfilter::ENCRYPTED_VERIFIER_LENGTH);
8388e0c
+    vector<sal_uInt8> encryptedVerifier(msfilter::ENCRYPTED_VERIFIER_LENGTH);
8388e0c
 
8388e0c
     lclRandomGenerateValues(&verifier[0], verifier.size());
8388e0c
 
8388e0c
     vector<sal_uInt8> iv;
8388e0c
     Encrypt aEncryptorVerifier(mKey, iv, Crypto::AES_128_ECB);
8388e0c
-    if (aEncryptorVerifier.update(encryptedVerifier, verifier) != ENCRYPTED_VERIFIER_LENGTH)
8388e0c
+    if (aEncryptorVerifier.update(encryptedVerifier, verifier) != msfilter::ENCRYPTED_VERIFIER_LENGTH)
8388e0c
         return false;
8388e0c
     std::copy(encryptedVerifier.begin(), encryptedVerifier.end(), mInfo.verifier.encryptedVerifier);
8388e0c
 
8388e0c
-    vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0);
8388e0c
-    mInfo.verifier.encryptedVerifierHashSize = RTL_DIGEST_LENGTH_SHA1;
8388e0c
+    vector<sal_uInt8> hash(msfilter::SHA1_HASH_LENGTH, 0);
8388e0c
+    mInfo.verifier.encryptedVerifierHashSize = msfilter::SHA1_HASH_LENGTH;
8388e0c
     Digest::sha1(hash, verifier);
8388e0c
-    hash.resize(ENCRYPTED_VERIFIER_HASH_LENGTH, 0);
8388e0c
+    hash.resize(msfilter::SHA256_HASH_LENGTH, 0);
8388e0c
 
8388e0c
-    vector<sal_uInt8> encryptedHash(ENCRYPTED_VERIFIER_HASH_LENGTH, 0);
8388e0c
+    vector<sal_uInt8> encryptedHash(msfilter::SHA256_HASH_LENGTH, 0);
8388e0c
 
8388e0c
     Encrypt aEncryptorHash(mKey, iv, Crypto::AES_128_ECB);
8388e0c
     aEncryptorHash.update(encryptedHash, hash, hash.size());
8388e0c
@@ -115,13 +94,13 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword)
8388e0c
         initialData.begin() + saltSize);
8388e0c
 
8388e0c
     // use "hash" vector for result of sha1 hashing
8388e0c
-    vector<sal_uInt8> hash(Digest::DIGEST_LENGTH_SHA1, 0);
8388e0c
+    vector<sal_uInt8> hash(msfilter::SHA1_HASH_LENGTH, 0);
8388e0c
 
8388e0c
     // calculate SHA1 hash of initialData
8388e0c
     Digest::sha1(hash, initialData);
8388e0c
 
8388e0c
     // data = iterator (4bytes) + hash
8388e0c
-    vector<sal_uInt8> data(Digest::DIGEST_LENGTH_SHA1 + 4, 0);
8388e0c
+    vector<sal_uInt8> data(msfilter::SHA1_HASH_LENGTH + 4, 0);
8388e0c
 
8388e0c
     for (sal_Int32 i = 0; i < 50000; ++i)
8388e0c
     {
8388e0c
@@ -130,7 +109,7 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword)
8388e0c
         Digest::sha1(hash, data);
8388e0c
     }
8388e0c
     std::copy(hash.begin(), hash.end(), data.begin() );
8388e0c
-    std::fill(data.begin() + Digest::DIGEST_LENGTH_SHA1, data.end(), 0 );
8388e0c
+    std::fill(data.begin() + msfilter::SHA1_HASH_LENGTH, data.end(), 0 );
8388e0c
 
8388e0c
     Digest::sha1(hash, data);
8388e0c
 
8388e0c
@@ -152,16 +131,16 @@ bool Standard2007Engine::generateEncryptionKey(const OUString& password)
8388e0c
 
8388e0c
     calculateEncryptionKey(password);
8388e0c
 
8388e0c
-    vector<sal_uInt8> encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH);
8388e0c
+    vector<sal_uInt8> encryptedVerifier(msfilter::ENCRYPTED_VERIFIER_LENGTH);
8388e0c
     std::copy(
8388e0c
         mInfo.verifier.encryptedVerifier,
8388e0c
-        mInfo.verifier.encryptedVerifier + ENCRYPTED_VERIFIER_LENGTH,
8388e0c
+        mInfo.verifier.encryptedVerifier + msfilter::ENCRYPTED_VERIFIER_LENGTH,
8388e0c
         encryptedVerifier.begin());
8388e0c
 
8388e0c
-    vector<sal_uInt8> encryptedHash(ENCRYPTED_VERIFIER_HASH_LENGTH);
8388e0c
+    vector<sal_uInt8> encryptedHash(msfilter::SHA256_HASH_LENGTH);
8388e0c
     std::copy(
8388e0c
         mInfo.verifier.encryptedVerifierHash,
8388e0c
-        mInfo.verifier.encryptedVerifierHash + ENCRYPTED_VERIFIER_HASH_LENGTH,
8388e0c
+        mInfo.verifier.encryptedVerifierHash + msfilter::SHA256_HASH_LENGTH,
8388e0c
         encryptedHash.begin());
8388e0c
 
8388e0c
     vector<sal_uInt8> verifier(encryptedVerifier.size(), 0);
8388e0c
@@ -170,7 +149,7 @@ bool Standard2007Engine::generateEncryptionKey(const OUString& password)
8388e0c
     vector<sal_uInt8> verifierHash(encryptedHash.size(), 0);
8388e0c
     Decrypt::aes128ecb(verifierHash, encryptedHash, mKey);
8388e0c
 
8388e0c
-    vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0);
8388e0c
+    vector<sal_uInt8> hash(msfilter::SHA1_HASH_LENGTH, 0);
8388e0c
     Digest::sha1(hash, verifier);
8388e0c
 
8388e0c
     return std::equal( hash.begin(), hash.end(), verifierHash.begin() );
8388e0c
@@ -200,11 +179,11 @@ bool Standard2007Engine::decrypt(
8388e0c
 
8388e0c
 bool Standard2007Engine::writeEncryptionInfo(const OUString& password, BinaryXOutputStream& rStream)
8388e0c
 {
8388e0c
-    mInfo.header.flags        = ENCRYPTINFO_AES | ENCRYPTINFO_CRYPTOAPI;
8388e0c
-    mInfo.header.algId        = ENCRYPT_ALGO_AES128;
8388e0c
-    mInfo.header.algIdHash    = ENCRYPT_HASH_SHA1;
8388e0c
-    mInfo.header.keyBits      = ENCRYPT_KEY_SIZE_AES_128;
8388e0c
-    mInfo.header.providedType = ENCRYPT_PROVIDER_TYPE_AES;
8388e0c
+    mInfo.header.flags        = msfilter::ENCRYPTINFO_AES | msfilter::ENCRYPTINFO_CRYPTOAPI;
8388e0c
+    mInfo.header.algId        = msfilter::ENCRYPT_ALGO_AES128;
8388e0c
+    mInfo.header.algIdHash    = msfilter::ENCRYPT_HASH_SHA1;
8388e0c
+    mInfo.header.keyBits      = msfilter::ENCRYPT_KEY_SIZE_AES_128;
8388e0c
+    mInfo.header.providedType = msfilter::ENCRYPT_PROVIDER_TYPE_AES;
8388e0c
 
8388e0c
     lclRandomGenerateValues(mInfo.verifier.salt, mInfo.verifier.saltSize);
8388e0c
     const sal_Int32 keyLength = mInfo.header.keyBits / 8;
8388e0c
@@ -218,11 +197,11 @@ bool Standard2007Engine::writeEncryptionInfo(const OUString& password, BinaryXOu
8388e0c
     if (!generateVerifier())
8388e0c
         return false;
8388e0c
 
8388e0c
-    rStream.WriteUInt32(VERSION_INFO_2007_FORMAT);
8388e0c
+    rStream.WriteUInt32(msfilter::VERSION_INFO_2007_FORMAT);
8388e0c
 
8388e0c
     sal_uInt32 cspNameSize = (lclCspName.getLength() * 2) + 2;
8388e0c
 
8388e0c
-    sal_uInt32 encryptionHeaderSize = static_cast<sal_uInt32>(sizeof(EncryptionStandardHeader));
8388e0c
+    sal_uInt32 encryptionHeaderSize = static_cast<sal_uInt32>(sizeof(msfilter::EncryptionStandardHeader));
8388e0c
 
8388e0c
     rStream.WriteUInt32( mInfo.header.flags );
8388e0c
     sal_uInt32 headerSize = encryptionHeaderSize + cspNameSize;
8388e0c
@@ -232,7 +211,7 @@ bool Standard2007Engine::writeEncryptionInfo(const OUString& password, BinaryXOu
8388e0c
     rStream.writeUnicodeArray(lclCspName);
8388e0c
     rStream.WriteUInt16(0);
8388e0c
 
8388e0c
-    sal_uInt32 encryptionVerifierSize = static_cast<sal_uInt32>(sizeof(EncryptionVerifierAES));
8388e0c
+    sal_uInt32 encryptionVerifierSize = static_cast<sal_uInt32>(sizeof(msfilter::EncryptionVerifierAES));
8388e0c
     rStream.writeMemory(&mInfo.verifier, encryptionVerifierSize);
8388e0c
 
8388e0c
     return true;
8388e0c
diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx
8388e0c
index 3e48f35..8c2622d 100644
8388e0c
--- a/sc/source/filter/excel/xicontent.cxx
8388e0c
+++ b/sc/source/filter/excel/xicontent.cxx
8388e0c
@@ -62,6 +62,7 @@
8388e0c
 #include <memory>
8388e0c
 #include <utility>
8388e0c
 #include <o3tl/make_unique.hxx>
8388e0c
+#include <oox/helper/helper.hxx>
8388e0c
 
8388e0c
 using ::com::sun::star::uno::Sequence;
8388e0c
 using ::std::unique_ptr;
8388e0c
@@ -1090,21 +1091,80 @@ XclImpDecrypterRef lclReadFilepass8_Standard( XclImpStream& rStrm )
8388e0c
     OSL_ENSURE( rStrm.GetRecLeft() == 48, "lclReadFilepass8 - wrong record size" );
8388e0c
     if( rStrm.GetRecLeft() == 48 )
8388e0c
     {
8388e0c
-        sal_uInt8 pnSalt[ 16 ];
8388e0c
-        sal_uInt8 pnVerifier[ 16 ];
8388e0c
-        sal_uInt8 pnVerifierHash[ 16 ];
8388e0c
-        rStrm.Read( pnSalt, 16 );
8388e0c
-        rStrm.Read( pnVerifier, 16 );
8388e0c
-        rStrm.Read( pnVerifierHash, 16 );
8388e0c
-        xDecr.reset( new XclImpBiff8Decrypter( pnSalt, pnVerifier, pnVerifierHash ) );
8388e0c
+        std::vector<sal_uInt8> aSalt(16);
8388e0c
+        std::vector<sal_uInt8> aVerifier(16);
8388e0c
+        std::vector<sal_uInt8> aVerifierHash(16);
8388e0c
+        rStrm.Read(aSalt.data(), 16);
8388e0c
+        rStrm.Read(aVerifier.data(), 16);
8388e0c
+        rStrm.Read(aVerifierHash.data(), 16);
8388e0c
+        xDecr.reset(new XclImpBiff8StdDecrypter(aSalt, aVerifier, aVerifierHash));
8388e0c
     }
8388e0c
     return xDecr;
8388e0c
 }
8388e0c
 
8388e0c
-XclImpDecrypterRef lclReadFilepass8_Strong( XclImpStream& /*rStrm*/ )
8388e0c
+XclImpDecrypterRef lclReadFilepass8_Strong(XclImpStream& rStream)
8388e0c
 {
8388e0c
-    // not supported
8388e0c
-    return XclImpDecrypterRef();
8388e0c
+    //Its possible there are other variants in existance but these
8388e0c
+    //are the defaults I get with Excel 2013
8388e0c
+    XclImpDecrypterRef xDecr;
8388e0c
+
8388e0c
+    msfilter::RC4EncryptionInfo info;
8388e0c
+
8388e0c
+    info.header.flags = rStream.ReaduInt32();
8388e0c
+    if (oox::getFlag( info.header.flags, msfilter::ENCRYPTINFO_EXTERNAL))
8388e0c
+        return xDecr;
8388e0c
+
8388e0c
+    sal_uInt32 nHeaderSize = rStream.ReaduInt32();
8388e0c
+    sal_uInt32 actualHeaderSize = sizeof(info.header);
8388e0c
+
8388e0c
+    if( (nHeaderSize < actualHeaderSize) )
8388e0c
+        return xDecr;
8388e0c
+
8388e0c
+    info.header.flags = rStream.ReaduInt32();
8388e0c
+    info.header.sizeExtra = rStream.ReaduInt32();
8388e0c
+    info.header.algId = rStream.ReaduInt32();
8388e0c
+    info.header.algIdHash = rStream.ReaduInt32();
8388e0c
+    info.header.keyBits = rStream.ReaduInt32();
8388e0c
+    info.header.providedType = rStream.ReaduInt32();
8388e0c
+    info.header.reserved1 = rStream.ReaduInt32();
8388e0c
+    info.header.reserved2 = rStream.ReaduInt32();
8388e0c
+
8388e0c
+    rStream.Ignore(nHeaderSize - actualHeaderSize);
8388e0c
+
8388e0c
+    info.verifier.saltSize = rStream.ReaduInt32();
8388e0c
+    if (info.verifier.saltSize != 16)
8388e0c
+        return xDecr;
8388e0c
+    rStream.Read(&info.verifier.salt, sizeof(info.verifier.salt));
8388e0c
+    rStream.Read(&info.verifier.encryptedVerifier, sizeof(info.verifier.encryptedVerifier));
8388e0c
+
8388e0c
+    info.verifier.encryptedVerifierHashSize = rStream.ReaduInt32();
8388e0c
+    if (info.verifier.encryptedVerifierHashSize != RTL_DIGEST_LENGTH_SHA1)
8388e0c
+        return xDecr;
8388e0c
+    rStream.Read(&info.verifier.encryptedVerifierHash, info.verifier.encryptedVerifierHashSize);
8388e0c
+
8388e0c
+    // check flags and algorithm IDs, required are AES128 and SHA-1
8388e0c
+    if (!oox::getFlag(info.header.flags, msfilter::ENCRYPTINFO_CRYPTOAPI))
8388e0c
+        return xDecr;
8388e0c
+
8388e0c
+    if (oox::getFlag(info.header.flags, msfilter::ENCRYPTINFO_AES))
8388e0c
+        return xDecr;
8388e0c
+
8388e0c
+    if (info.header.algId != msfilter::ENCRYPT_ALGO_RC4)
8388e0c
+        return xDecr;
8388e0c
+
8388e0c
+    // hash algorithm ID 0 defaults to SHA-1 too
8388e0c
+    if (info.header.algIdHash != 0 && info.header.algIdHash != msfilter::ENCRYPT_HASH_SHA1)
8388e0c
+        return xDecr;
8388e0c
+
8388e0c
+    xDecr.reset(new XclImpBiff8CryptoAPIDecrypter(
8388e0c
+        std::vector<sal_uInt8>(info.verifier.salt,
8388e0c
+            info.verifier.salt + SAL_N_ELEMENTS(info.verifier.salt)),
8388e0c
+        std::vector<sal_uInt8>(info.verifier.encryptedVerifier,
8388e0c
+            info.verifier.encryptedVerifier + SAL_N_ELEMENTS(info.verifier.encryptedVerifier)),
8388e0c
+        std::vector<sal_uInt8>(info.verifier.encryptedVerifierHash,
8388e0c
+            info.verifier.encryptedVerifierHash + SAL_N_ELEMENTS(info.verifier.encryptedVerifierHash))));
8388e0c
+
8388e0c
+    return xDecr;
8388e0c
 }
8388e0c
 
8388e0c
 XclImpDecrypterRef lclReadFilepass8( XclImpStream& rStrm )
8388e0c
@@ -1121,20 +1181,22 @@ XclImpDecrypterRef lclReadFilepass8( XclImpStream& rStrm )
8388e0c
 
8388e0c
         case EXC_FILEPASS_BIFF8:
8388e0c
         {
8388e0c
-            rStrm.Ignore( 2 );
8388e0c
-            sal_uInt16 nSubMode(0);
8388e0c
-            nSubMode = rStrm.ReaduInt16();
8388e0c
-            switch( nSubMode )
8388e0c
+            sal_uInt32 nVersion = rStrm.ReaduInt32();
8388e0c
+            if (nVersion == msfilter::VERSION_INFO_1997_FORMAT)
8388e0c
             {
8388e0c
-                case EXC_FILEPASS_BIFF8_STD:
8388e0c
-                    xDecr = lclReadFilepass8_Standard( rStrm );
8388e0c
-                break;
8388e0c
-                case EXC_FILEPASS_BIFF8_STRONG:
8388e0c
-                    xDecr = lclReadFilepass8_Strong( rStrm );
8388e0c
-                break;
8388e0c
-                default:
8388e0c
-                    OSL_FAIL( "lclReadFilepass8 - unknown BIFF8 encryption sub mode" );
8388e0c
+                //A Version structure where Version.vMajor MUST be 0x0001,
8388e0c
+                //and Version.vMinor MUST be 0x0001.
8388e0c
+                xDecr = lclReadFilepass8_Standard(rStrm);
8388e0c
             }
8388e0c
+            else if (nVersion == msfilter::VERSION_INFO_2007_FORMAT ||
8388e0c
+                     nVersion == msfilter::VERSION_INFO_2007_FORMAT_SP2)
8388e0c
+            {
8388e0c
+                //Version.vMajor MUST be 0x0002, 0x0003 or 0x0004 and
8388e0c
+                //Version.vMinor MUST be 0x0002.
8388e0c
+                xDecr = lclReadFilepass8_Strong(rStrm);
8388e0c
+            }
8388e0c
+            else
8388e0c
+                OSL_FAIL("lclReadFilepass8 - unknown BIFF8 encryption sub mode");
8388e0c
         }
8388e0c
         break;
8388e0c
 
8388e0c
diff --git a/sc/source/filter/excel/xistream.cxx b/sc/source/filter/excel/xistream.cxx
8388e0c
index a5eda2c..7bc231e 100644
8388e0c
--- a/sc/source/filter/excel/xistream.cxx
8388e0c
+++ b/sc/source/filter/excel/xistream.cxx
8388e0c
@@ -192,28 +192,50 @@ sal_uInt16 XclImpBiff5Decrypter::OnRead( SvStream& rStrm, sal_uInt8* pnData, sal
8388e0c
     return nRet;
8388e0c
 }
8388e0c
 
8388e0c
-XclImpBiff8Decrypter::XclImpBiff8Decrypter( sal_uInt8 pnSalt[ 16 ],
8388e0c
-        sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ) :
8388e0c
-    maSalt( pnSalt, pnSalt + 16 ),
8388e0c
-    maVerifier( pnVerifier, pnVerifier + 16 ),
8388e0c
-    maVerifierHash( pnVerifierHash, pnVerifierHash + 16 )
8388e0c
+XclImpBiff8Decrypter::XclImpBiff8Decrypter(const std::vector<sal_uInt8>& rSalt,
8388e0c
+                                           const std::vector<sal_uInt8>& rVerifier,
8388e0c
+                                           const std::vector<sal_uInt8>& rVerifierHash)
8388e0c
+    : maSalt(rSalt)
8388e0c
+    , maVerifier(rVerifier)
8388e0c
+    , maVerifierHash(rVerifierHash)
8388e0c
+    , mpCodec(nullptr)
8388e0c
 {
8388e0c
 }
8388e0c
 
8388e0c
-XclImpBiff8Decrypter::XclImpBiff8Decrypter( const XclImpBiff8Decrypter& rSrc ) :
8388e0c
-    XclImpDecrypter( rSrc ),
8388e0c
-    maEncryptionData( rSrc.maEncryptionData ),
8388e0c
-    maSalt( rSrc.maSalt ),
8388e0c
-    maVerifier( rSrc.maVerifier ),
8388e0c
-    maVerifierHash( rSrc.maVerifierHash )
8388e0c
+XclImpBiff8Decrypter::XclImpBiff8Decrypter(const XclImpBiff8Decrypter& rSrc)
8388e0c
+    : XclImpDecrypter(rSrc)
8388e0c
+    , maEncryptionData(rSrc.maEncryptionData)
8388e0c
+    , maSalt(rSrc.maSalt)
8388e0c
+    , maVerifier(rSrc.maVerifier)
8388e0c
+    , maVerifierHash(rSrc.maVerifierHash)
8388e0c
+    , mpCodec(nullptr)
8388e0c
 {
8388e0c
-    if( IsValid() )
8388e0c
-        maCodec.InitCodec( maEncryptionData );
8388e0c
 }
8388e0c
 
8388e0c
-XclImpBiff8Decrypter* XclImpBiff8Decrypter::OnClone() const
8388e0c
+XclImpBiff8StdDecrypter::XclImpBiff8StdDecrypter(const XclImpBiff8StdDecrypter& rSrc)
8388e0c
+    : XclImpBiff8Decrypter(rSrc)
8388e0c
 {
8388e0c
-    return new XclImpBiff8Decrypter( *this );
8388e0c
+    mpCodec = &maCodec;
8388e0c
+    if (IsValid())
8388e0c
+        maCodec.InitCodec(maEncryptionData);
8388e0c
+}
8388e0c
+
8388e0c
+XclImpBiff8StdDecrypter* XclImpBiff8StdDecrypter::OnClone() const
8388e0c
+{
8388e0c
+    return new XclImpBiff8StdDecrypter(*this);
8388e0c
+}
8388e0c
+
8388e0c
+XclImpBiff8CryptoAPIDecrypter::XclImpBiff8CryptoAPIDecrypter(const XclImpBiff8CryptoAPIDecrypter& rSrc)
8388e0c
+    : XclImpBiff8Decrypter(rSrc)
8388e0c
+{
8388e0c
+    mpCodec = &maCodec;
8388e0c
+    if (IsValid())
8388e0c
+        maCodec.InitCodec(maEncryptionData);
8388e0c
+}
8388e0c
+
8388e0c
+XclImpBiff8CryptoAPIDecrypter* XclImpBiff8CryptoAPIDecrypter::OnClone() const
8388e0c
+{
8388e0c
+    return new XclImpBiff8CryptoAPIDecrypter(*this);
8388e0c
 }
8388e0c
 
8388e0c
 uno::Sequence< beans::NamedValue > XclImpBiff8Decrypter::OnVerifyPassword( const OUString& rPassword )
8388e0c
@@ -232,9 +254,9 @@ uno::Sequence< beans::NamedValue > XclImpBiff8Decrypter::OnVerifyPassword( const
8388e0c
             *aIt = static_cast< sal_uInt16 >( *pcChar );
8388e0c
 
8388e0c
         // init codec
8388e0c
-        maCodec.InitKey( &aPassVect.front(), &maSalt.front() );
8388e0c
-        if ( maCodec.VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) )
8388e0c
-            maEncryptionData = maCodec.GetEncryptionData();
8388e0c
+        mpCodec->InitKey( &aPassVect.front(), &maSalt.front() );
8388e0c
+        if ( mpCodec->VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) )
8388e0c
+            maEncryptionData = mpCodec->GetEncryptionData();
8388e0c
     }
8388e0c
 
8388e0c
     return maEncryptionData;
8388e0c
@@ -247,9 +269,9 @@ bool XclImpBiff8Decrypter::OnVerifyEncryptionData( const uno::Sequence< beans::N
8388e0c
     if( rEncryptionData.getLength() )
8388e0c
     {
8388e0c
         // init codec
8388e0c
-        maCodec.InitCodec( rEncryptionData );
8388e0c
+        mpCodec->InitCodec( rEncryptionData );
8388e0c
 
8388e0c
-        if ( maCodec.VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) )
8388e0c
+        if ( mpCodec->VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) )
8388e0c
             maEncryptionData = rEncryptionData;
8388e0c
     }
8388e0c
 
8388e0c
@@ -269,13 +291,13 @@ void XclImpBiff8Decrypter::OnUpdate( sal_Size nOldStrmPos, sal_Size nNewStrmPos,
8388e0c
         /*  Rekey cipher, if block changed or if previous offset in same block. */
8388e0c
         if( (nNewBlock != nOldBlock) || (nNewOffset < nOldOffset) )
8388e0c
         {
8388e0c
-            maCodec.InitCipher( nNewBlock );
8388e0c
+            mpCodec->InitCipher( nNewBlock );
8388e0c
             nOldOffset = 0;     // reset nOldOffset for next if() statement
8388e0c
         }
8388e0c
 
8388e0c
         /*  Seek to correct offset. */
8388e0c
         if( nNewOffset > nOldOffset )
8388e0c
-            maCodec.Skip( nNewOffset - nOldOffset );
8388e0c
+            mpCodec->Skip( nNewOffset - nOldOffset );
8388e0c
     }
8388e0c
 }
8388e0c
 
8388e0c
@@ -293,9 +315,9 @@ sal_uInt16 XclImpBiff8Decrypter::OnRead( SvStream& rStrm, sal_uInt8* pnData, sal
8388e0c
         // read the block from stream
8388e0c
         nRet = nRet + static_cast< sal_uInt16 >( rStrm.Read( pnCurrData, nDecBytes ) );
8388e0c
         // decode the block inplace
8388e0c
-        maCodec.Decode( pnCurrData, nDecBytes, pnCurrData, nDecBytes );
8388e0c
+        mpCodec->Decode( pnCurrData, nDecBytes, pnCurrData, nDecBytes );
8388e0c
         if( GetOffset( rStrm.Tell() ) == 0 )
8388e0c
-            maCodec.InitCipher( GetBlock( rStrm.Tell() ) );
8388e0c
+            mpCodec->InitCipher( GetBlock( rStrm.Tell() ) );
8388e0c
 
8388e0c
         pnCurrData += nDecBytes;
8388e0c
         nBytesLeft = nBytesLeft - nDecBytes;
8388e0c
diff --git a/sc/source/filter/inc/xistream.hxx b/sc/source/filter/inc/xistream.hxx
8388e0c
index d5fc51a..56d32d7 100644
8388e0c
--- a/sc/source/filter/inc/xistream.hxx
8388e0c
+++ b/sc/source/filter/inc/xistream.hxx
8388e0c
@@ -119,16 +119,7 @@ private:
8388e0c
 /** Decrypts BIFF8 stream contents using the given document identifier. */
8388e0c
 class XclImpBiff8Decrypter : public XclImpDecrypter
8388e0c
 {
8388e0c
-public:
8388e0c
-    explicit            XclImpBiff8Decrypter( sal_uInt8 pnSalt[ 16 ],
8388e0c
-                            sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] );
8388e0c
-
8388e0c
 private:
8388e0c
-    /** Private copy c'tor for OnClone(). */
8388e0c
-    explicit            XclImpBiff8Decrypter( const XclImpBiff8Decrypter& rSrc );
8388e0c
-
8388e0c
-    /** Implementation of cloning this object. */
8388e0c
-    virtual XclImpBiff8Decrypter* OnClone() const override;
8388e0c
     /** Implements password verification and initialization of the decoder. */
8388e0c
     virtual css::uno::Sequence< css::beans::NamedValue >
8388e0c
         OnVerifyPassword( const OUString& rPassword ) override;
8388e0c
@@ -143,12 +134,62 @@ private:
8388e0c
     /** Returns the block offset corresponding to the passed stream position. */
8388e0c
     static sal_uInt16    GetOffset( sal_Size nStrmPos );
8388e0c
 
8388e0c
+protected:
8388e0c
+    explicit  XclImpBiff8Decrypter(const std::vector<sal_uInt8>& rSalt,
8388e0c
+                                   const std::vector<sal_uInt8>& rVerifier,
8388e0c
+                                   const std::vector<sal_uInt8>& rVerifierHash);
8388e0c
+
8388e0c
+    explicit  XclImpBiff8Decrypter(const XclImpBiff8Decrypter& rSrc);
8388e0c
+
8388e0c
+    css::uno::Sequence< css::beans::NamedValue > maEncryptionData;
8388e0c
+    std::vector< sal_uInt8 > maSalt;
8388e0c
+    std::vector< sal_uInt8 > maVerifier;
8388e0c
+    std::vector< sal_uInt8 > maVerifierHash;
8388e0c
+    msfilter::MSCodec97* mpCodec;       /// Crypto algorithm implementation.
8388e0c
+};
8388e0c
+
8388e0c
+class XclImpBiff8StdDecrypter : public XclImpBiff8Decrypter
8388e0c
+{
8388e0c
+public:
8388e0c
+    explicit XclImpBiff8StdDecrypter(const std::vector<sal_uInt8>& rSalt,
8388e0c
+                                     const std::vector<sal_uInt8>& rVerifier,
8388e0c
+                                     const std::vector<sal_uInt8>& rVerifierHash)
8388e0c
+        : XclImpBiff8Decrypter(rSalt, rVerifier, rVerifierHash)
8388e0c
+    {
8388e0c
+        mpCodec = &maCodec;
8388e0c
+    }
8388e0c
+
8388e0c
+private:
8388e0c
+    /** Private copy c'tor for OnClone(). */
8388e0c
+    explicit XclImpBiff8StdDecrypter(const XclImpBiff8StdDecrypter& rSrc);
8388e0c
+
8388e0c
+    /** Implementation of cloning this object. */
8388e0c
+    virtual XclImpBiff8StdDecrypter* OnClone() const override;
8388e0c
+
8388e0c
 private:
8388e0c
     ::msfilter::MSCodec_Std97 maCodec;       /// Crypto algorithm implementation.
8388e0c
-    css::uno::Sequence< css::beans::NamedValue > maEncryptionData;
8388e0c
-    ::std::vector< sal_uInt8 > maSalt;
8388e0c
-    ::std::vector< sal_uInt8 > maVerifier;
8388e0c
-    ::std::vector< sal_uInt8 > maVerifierHash;
8388e0c
+};
8388e0c
+
8388e0c
+class XclImpBiff8CryptoAPIDecrypter : public XclImpBiff8Decrypter
8388e0c
+{
8388e0c
+public:
8388e0c
+    explicit XclImpBiff8CryptoAPIDecrypter(const std::vector<sal_uInt8>& rSalt,
8388e0c
+                                           const std::vector<sal_uInt8>& rVerifier,
8388e0c
+                                           const std::vector<sal_uInt8>& rVerifierHash)
8388e0c
+        : XclImpBiff8Decrypter(rSalt, rVerifier, rVerifierHash)
8388e0c
+    {
8388e0c
+        mpCodec = &maCodec;
8388e0c
+    }
8388e0c
+
8388e0c
+private:
8388e0c
+    /** Private copy c'tor for OnClone(). */
8388e0c
+    explicit XclImpBiff8CryptoAPIDecrypter(const XclImpBiff8CryptoAPIDecrypter& rSrc);
8388e0c
+
8388e0c
+    /** Implementation of cloning this object. */
8388e0c
+    virtual XclImpBiff8CryptoAPIDecrypter* OnClone() const override;
8388e0c
+
8388e0c
+private:
8388e0c
+    ::msfilter::MSCodec_CryptoAPI maCodec;       /// Crypto algorithm implementation.
8388e0c
 };
8388e0c
 
8388e0c
 // Stream
8388e0c
diff --git a/sc/source/filter/inc/xlcontent.hxx b/sc/source/filter/inc/xlcontent.hxx
8388e0c
index 6bb7b0b..ec94750 100644
8388e0c
--- a/sc/source/filter/inc/xlcontent.hxx
8388e0c
+++ b/sc/source/filter/inc/xlcontent.hxx
8388e0c
@@ -39,8 +39,6 @@ const sal_uInt16 EXC_ID_FILEPASS            = 0x002F;
8388e0c
 
8388e0c
 const sal_uInt16 EXC_FILEPASS_BIFF5         = 0x0000;
8388e0c
 const sal_uInt16 EXC_FILEPASS_BIFF8         = 0x0001;
8388e0c
-const sal_uInt16 EXC_FILEPASS_BIFF8_STD     = 0x0001;
8388e0c
-const sal_uInt16 EXC_FILEPASS_BIFF8_STRONG  = 0x0002;
8388e0c
 
8388e0c
 // (0x00FC, 0x00FF) SST, EXTSST -----------------------------------------------
8388e0c
 
8388e0c
-- 
8388e0c
2.7.4
8388e0c