filter/source/msfilter/mscodec.cxx | 184 +++++++++++++++++++------- include/filter/msfilter/mscodec.hxx | 208 ++++++++++++++++++++++++------ include/oox/crypto/CryptTools.hxx | 3 include/oox/crypto/Standard2007Engine.hxx | 70 ---------- oox/source/crypto/CryptTools.cxx | 14 -- oox/source/crypto/DocumentDecryption.cxx | 22 +-- oox/source/crypto/Standard2007Engine.cxx | 67 +++------ sc/source/filter/excel/xicontent.cxx | 106 ++++++++++++--- sc/source/filter/excel/xistream.cxx | 70 ++++++---- sc/source/filter/inc/xistream.hxx | 67 +++++++-- sc/source/filter/inc/xlcontent.hxx | 2 11 files changed, 533 insertions(+), 280 deletions(-)
New commits: commit 1473ce030314027c01c98f513407ed0897328585 Author: Caolán McNamara <caol...@redhat.com> Date: Thu Oct 20 16:07:11 2016 +0100 implement CryptoAPI RC4+SHA1 encryption scheme for xls import there might be other variants out there in practice, but this works for default encrypted xls of excel 2013 Change-Id: I91c0e1d1d95fbd1c68966650e7ac7d23276bcbe3 diff --git a/filter/source/msfilter/mscodec.cxx b/filter/source/msfilter/mscodec.cxx index 20a1f4a..ffbbd09 100644 --- a/filter/source/msfilter/mscodec.cxx +++ b/filter/source/msfilter/mscodec.cxx @@ -245,30 +245,36 @@ void MSCodec_Xor95::Skip( std::size_t nBytes ) mnOffset = (mnOffset + nBytes) & 0x0F; } -MSCodec97::MSCodec97(rtlCipher hCipher) - : m_hCipher(hCipher) +MSCodec97::MSCodec97(size_t nHashLen) + : m_nHashLen(nHashLen) + , m_hCipher(rtl_cipher_create(rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream)) + , m_aDigestValue(nHashLen, 0) { + assert(m_hCipher != nullptr); + (void)memset (m_pDocId, 0, sizeof(m_pDocId)); } MSCodec_Std97::MSCodec_Std97() - : MSCodec97(rtl_cipher_create(rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream)) + : MSCodec97(RTL_DIGEST_LENGTH_MD5) { - assert(m_hCipher != nullptr); m_hDigest = rtl_digest_create(rtl_Digest_AlgorithmMD5); assert(m_hDigest != nullptr); - (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue)); - (void)memset (m_pDocId, 0, sizeof(m_pDocId)); +} + +MSCodec_CryptoAPI::MSCodec_CryptoAPI() + : MSCodec97(RTL_DIGEST_LENGTH_SHA1) +{ } MSCodec97::~MSCodec97() { + (void)memset(m_aDigestValue.data(), 0, m_aDigestValue.size()); + (void)memset(m_pDocId, 0, sizeof(m_pDocId)); rtl_cipher_destroy(m_hCipher); } MSCodec_Std97::~MSCodec_Std97() { - (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue)); - (void)memset (m_pDocId, 0, sizeof(m_pDocId)); rtl_digest_destroy(m_hDigest); } @@ -286,7 +292,7 @@ static inline void lcl_PrintDigest(const sal_uInt8* /*pDigest*/, const char* /*m } #endif -bool MSCodec_Std97::InitCodec( const uno::Sequence< beans::NamedValue >& aData ) +bool MSCodec97::InitCodec( const uno::Sequence< beans::NamedValue >& aData ) { #if DEBUG_MSO_ENCRYPTION_STD97 fprintf(stdout, "MSCodec_Std97::InitCodec: --begin\n");fflush(stdout); @@ -295,16 +301,17 @@ bool MSCodec_Std97::InitCodec( const uno::Sequence< beans::NamedValue >& aData ) ::comphelper::SequenceAsHashMap aHashData( aData ); uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault("STD97EncryptionKey", uno::Sequence< sal_Int8 >() ); - - if ( aKey.getLength() == RTL_DIGEST_LENGTH_MD5 ) + const size_t nKeyLen = aKey.getLength(); + if (nKeyLen == m_nHashLen) { - (void)memcpy( m_pDigestValue, aKey.getConstArray(), RTL_DIGEST_LENGTH_MD5 ); + assert(m_aDigestValue.size() == m_nHashLen); + (void)memcpy(m_aDigestValue.data(), aKey.getConstArray(), m_nHashLen); uno::Sequence< sal_Int8 > aUniqueID = aHashData.getUnpackedValueOrDefault("STD97UniqueID", uno::Sequence< sal_Int8 >() ); if ( aUniqueID.getLength() == 16 ) { (void)memcpy( m_pDocId, aUniqueID.getConstArray(), 16 ); bResult = true; - lcl_PrintDigest(m_pDigestValue, "digest value"); + lcl_PrintDigest(m_aDigestValue.data(), "digest value"); lcl_PrintDigest(m_pDocId, "DocId value"); } else @@ -316,10 +323,11 @@ bool MSCodec_Std97::InitCodec( const uno::Sequence< beans::NamedValue >& aData ) return bResult; } -uno::Sequence< beans::NamedValue > MSCodec_Std97::GetEncryptionData() +uno::Sequence< beans::NamedValue > MSCodec97::GetEncryptionData() { ::comphelper::SequenceAsHashMap aHashData; - aHashData[ OUString( "STD97EncryptionKey" ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(m_pDigestValue), RTL_DIGEST_LENGTH_MD5 ); + assert(m_aDigestValue.size() == m_nHashLen); + aHashData[ OUString( "STD97EncryptionKey" ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(m_aDigestValue.data()), m_nHashLen ); aHashData[ OUString( "STD97UniqueID" ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(m_pDocId), 16 ); return aHashData.getAsConstNamedValueList(); @@ -335,26 +343,51 @@ void MSCodec_Std97::InitKey ( uno::Sequence< sal_Int8 > aKey = ::comphelper::DocPasswordHelper::GenerateStd97Key(pPassData, pDocId); // Fill raw digest of above updates into DigestValue. - if ( aKey.getLength() == sizeof(m_pDigestValue) ) - (void)memcpy ( m_pDigestValue, aKey.getConstArray(), sizeof(m_pDigestValue) ); + const size_t nKeyLen = aKey.getLength(); + if (m_aDigestValue.size() == nKeyLen) + (void)memcpy(m_aDigestValue.data(), aKey.getConstArray(), m_aDigestValue.size()); else - memset( m_pDigestValue, 0, sizeof(m_pDigestValue) ); + memset(m_aDigestValue.data(), 0, m_aDigestValue.size()); + + lcl_PrintDigest(m_aDigestValue.data(), "digest value"); + + (void)memcpy (m_pDocId, pDocId, 16); + + lcl_PrintDigest(m_pDocId, "DocId value"); +} + +void MSCodec_CryptoAPI::InitKey ( + const sal_uInt16 pPassData[16], + const sal_uInt8 pDocId[16]) +{ + sal_uInt32 saltSize = 16; + + // Prepare initial data -> salt + password (in 16-bit chars) + std::vector<sal_uInt8> initialData(pDocId, pDocId + saltSize); + + // Fill PassData into KeyData. + for (sal_Int32 nInd = 0; nInd < 16 && pPassData[nInd]; ++nInd) + { + initialData.push_back(sal::static_int_cast<sal_uInt8>((pPassData[nInd] >> 0) & 0xff)); + initialData.push_back(sal::static_int_cast<sal_uInt8>((pPassData[nInd] >> 8) & 0xff)); + } + + // calculate SHA1 hash of initialData + rtl_digest_SHA1(initialData.data(), initialData.size(), m_aDigestValue.data(), m_aDigestValue.size()); - lcl_PrintDigest(m_pDigestValue, "digest value"); + lcl_PrintDigest(m_aDigestValue.data(), "digest value"); (void)memcpy (m_pDocId, pDocId, 16); lcl_PrintDigest(m_pDocId, "DocId value"); } -bool MSCodec_Std97::VerifyKey ( - const sal_uInt8 pSaltData[16], - const sal_uInt8 pSaltDigest[16]) +bool MSCodec97::VerifyKey(const sal_uInt8* pSaltData, const sal_uInt8* pSaltDigest) { // both the salt data and salt digest (hash) come from the document being imported. #if DEBUG_MSO_ENCRYPTION_STD97 - fprintf(stdout, "MSCodec_Std97::VerifyKey: \n"); + fprintf(stdout, "MSCodec97::VerifyKey: \n"); lcl_PrintDigest(pSaltData, "salt data"); lcl_PrintDigest(pSaltDigest, "salt hash"); #endif @@ -362,35 +395,42 @@ bool MSCodec_Std97::VerifyKey ( if (InitCipher(0)) { - sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5]; - GetDigestFromSalt(pSaltData, pDigest); + std::vector<sal_uInt8> aDigest(m_nHashLen); + GetDigestFromSalt(pSaltData, aDigest.data()); - sal_uInt8 pBuffer[16]; + std::vector<sal_uInt8> aBuffer(m_nHashLen); // Decode original SaltDigest into Buffer. - rtl_cipher_decode ( - m_hCipher, pSaltDigest, 16, pBuffer, sizeof(pBuffer)); + rtl_cipher_decode(m_hCipher, pSaltDigest, m_nHashLen, aBuffer.data(), m_nHashLen); // Compare Buffer with computed Digest. - result = (memcmp (pBuffer, pDigest, sizeof(pDigest)) == 0); + result = (memcmp(aBuffer.data(), aDigest.data(), m_nHashLen) == 0); // Erase Buffer and Digest arrays. - rtl_secureZeroMemory (pBuffer, sizeof(pBuffer)); - rtl_secureZeroMemory (pDigest, sizeof(pDigest)); + rtl_secureZeroMemory(aBuffer.data(), m_nHashLen); + rtl_secureZeroMemory(aDigest.data(), m_nHashLen); } return result; } -bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter) +void MSCodec_CryptoAPI::GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest) +{ + std::vector<sal_uInt8> verifier(16); + rtl_cipher_decode(m_hCipher, + pSaltData, 16, verifier.data(), verifier.size()); + + rtl_digest_SHA1(verifier.data(), verifier.size(), pDigest, RTL_DIGEST_LENGTH_SHA1); +} + +bool MSCodec_Std97::InitCipher(sal_uInt32 nCounter) { - rtlCipherError result; sal_uInt8 pKeyData[64]; // 512-bit message block // Initialize KeyData array. (void)memset (pKeyData, 0, sizeof(pKeyData)); // Fill 40 bit of DigestValue into [0..4]. - (void)memcpy (pKeyData, m_pDigestValue, 5); + (void)memcpy (pKeyData, m_aDigestValue.data(), 5); // Fill counter into [5..8]. pKeyData[ 5] = sal_uInt8((nCounter >> 0) & 0xff); @@ -408,7 +448,7 @@ bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter) m_hDigest, pKeyData, RTL_DIGEST_LENGTH_MD5); // Initialize Cipher with KeyData (for decoding). - result = rtl_cipher_init ( + rtlCipherError result = rtl_cipher_init ( m_hCipher, rtl_Cipher_DirectionBoth, pKeyData, RTL_DIGEST_LENGTH_MD5, nullptr, 0); @@ -418,6 +458,25 @@ bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter) return (result == rtl_Cipher_E_None); } +bool MSCodec_CryptoAPI::InitCipher(sal_uInt32 nCounter) +{ + // data = hash + iterator (4bytes) + std::vector<sal_uInt8> aKeyData(m_aDigestValue); + aKeyData.push_back(sal_uInt8((nCounter >> 0) & 0xff)); + aKeyData.push_back(sal_uInt8((nCounter >> 8) & 0xff)); + aKeyData.push_back(sal_uInt8((nCounter >> 16) & 0xff)); + aKeyData.push_back(sal_uInt8((nCounter >> 24) & 0xff)); + + std::vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1); + rtl_digest_SHA1(aKeyData.data(), aKeyData.size(), hash.data(), RTL_DIGEST_LENGTH_SHA1); + + rtlCipherError result = + rtl_cipher_init(m_hCipher, rtl_Cipher_DirectionDecode, + hash.data(), ENCRYPT_KEY_SIZE_AES_128/8, nullptr, 0); + + return (result == rtl_Cipher_E_None); +} + void MSCodec_Std97::CreateSaltDigest( const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] ) { #if DEBUG_MSO_ENCRYPTION_STD97 @@ -471,7 +530,7 @@ bool MSCodec97::Skip(std::size_t nDatLen) return bResult; } -void MSCodec_Std97::GetDigestFromSalt( const sal_uInt8 pSaltData[16], sal_uInt8 pDigest[16] ) +void MSCodec_Std97::GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest) { sal_uInt8 pBuffer[64]; sal_uInt8 pDigestLocal[16]; @@ -530,7 +589,7 @@ void MSCodec_Std97::GetEncryptKey ( } } -void MSCodec_Std97::GetDocId( sal_uInt8 pDocId[16] ) +void MSCodec97::GetDocId( sal_uInt8 pDocId[16] ) { if ( sizeof( m_pDocId ) == 16 ) (void)memcpy( pDocId, m_pDocId, 16 ); @@ -557,6 +616,15 @@ EncryptionVerifierAES::EncryptionVerifierAES() memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash)); } +EncryptionVerifierRC4::EncryptionVerifierRC4() + : saltSize(SALT_LENGTH) + , encryptedVerifierHashSize(SHA1_HASH_LENGTH) +{ + memset(salt, 0, sizeof(salt)); + memset(encryptedVerifier, 0, sizeof(encryptedVerifier)); + memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash)); +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/filter/msfilter/mscodec.hxx b/include/filter/msfilter/mscodec.hxx index afdf163..52846f8 100644 --- a/include/filter/msfilter/mscodec.hxx +++ b/include/filter/msfilter/mscodec.hxx @@ -25,6 +25,7 @@ #include <rtl/cipher.h> #include <rtl/digest.h> #include <sal/types.h> +#include <vector> namespace com { namespace sun { namespace star { namespace beans { struct NamedValue; } @@ -177,7 +178,7 @@ public: class MSFILTER_DLLPUBLIC MSCodec97 { public: - MSCodec97(rtlCipher m_hCipher); + MSCodec97(size_t nHashLen); virtual ~MSCodec97(); /** Initializes the algorithm with the encryption data. @@ -186,7 +187,7 @@ public: The sequence contains the necessary data to initialize the codec. */ - virtual bool InitCodec(const css::uno::Sequence< css::beans::NamedValue >& aData) = 0; + bool InitCodec(const css::uno::Sequence< css::beans::NamedValue >& aData); /** Retrieves the encryption data @@ -194,8 +195,37 @@ public: The sequence contains the necessary data to initialize the codec. */ - virtual css::uno::Sequence< css::beans::NamedValue > GetEncryptionData() = 0; + css::uno::Sequence< css::beans::NamedValue > GetEncryptionData(); + + /** Initializes the algorithm with the specified password and document ID. + + @param pPassData + Wide character array containing the password. Must be zero + terminated, which results in a maximum length of 15 characters. + @param pDocId + Unique document identifier read from or written to the file. + */ + virtual void InitKey(const sal_uInt16 pPassData[16], + const sal_uInt8 pDocId[16]) = 0; + + + /** Verifies the validity of the password using the passed salt data. + + @precond + The codec must be initialized with InitKey() before this function + can be used. + + @param pSaltData + Salt data block read from the file. + @param pSaltDigest + Salt digest read from the file. + + @return + true = Test was successful. + */ + bool VerifyKey(const sal_uInt8* pSaltData, const sal_uInt8* pSaltDigest); + virtual void GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest) = 0; /** Rekeys the codec using the specified counter. @@ -278,12 +308,19 @@ public: */ bool Skip(std::size_t nDatLen); + /* allows to get the unique document id from the codec + */ + void GetDocId( sal_uInt8 pDocId[16] ); + private: MSCodec97(const MSCodec97&) = delete; MSCodec97& operator=(const MSCodec97&) = delete; protected: + size_t m_nHashLen; rtlCipher m_hCipher; + sal_uInt8 m_pDocId[16]; + std::vector<sal_uInt8> m_aDigestValue; }; /** Encodes and decodes data from protected MSO 97+ documents. @@ -295,25 +332,8 @@ protected: class MSFILTER_DLLPUBLIC MSCodec_Std97 : public MSCodec97 { public: - explicit MSCodec_Std97(); - ~MSCodec_Std97(); - - /** Initializes the algorithm with the encryption data. - - @param aData - The sequence contains the necessary data to initialize - the codec. - */ - virtual bool InitCodec(const css::uno::Sequence< css::beans::NamedValue >& aData) override; - - /** Retrieves the encryption data - - @return - The sequence contains the necessary data to initialize - the codec. - */ - virtual css::uno::Sequence<css::beans::NamedValue> GetEncryptionData() override; - + MSCodec_Std97(); + virtual ~MSCodec_Std97() override; /** Initializes the algorithm with the specified password and document ID. @@ -323,27 +343,8 @@ public: @param pDocId Unique document identifier read from or written to the file. */ - void InitKey( - const sal_uInt16 pPassData[ 16 ], - const sal_uInt8 pDocId[ 16 ] ); - - /** Verifies the validity of the password using the passed salt data. - - @precond - The codec must be initialized with InitKey() before this function - can be used. - - @param pSaltData - Salt data block read from the file. - @param pSaltDigest - Salt digest read from the file. - - @return - true = Test was successful. - */ - bool VerifyKey( - const sal_uInt8 pSaltData[ 16 ], - const sal_uInt8 pSaltDigest[ 16 ] ); + virtual void InitKey(const sal_uInt16 pPassData[16], + const sal_uInt8 pDocId[16]) override; /** Rekeys the codec using the specified counter. @@ -384,19 +385,24 @@ public: sal_uInt8 pSaltData[16], sal_uInt8 pSaltDigest[16]); - /* allows to get the unique document id from the codec - */ - void GetDocId( sal_uInt8 pDocId[16] ); - - void GetDigestFromSalt( const sal_uInt8 pSaltData[16], sal_uInt8 pDigest[16] ); + virtual void GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest) override; private: MSCodec_Std97( const MSCodec_Std97& ) = delete; MSCodec_Std97& operator=( const MSCodec_Std97& ) = delete; rtlDigest m_hDigest; - sal_uInt8 m_pDigestValue[ RTL_DIGEST_LENGTH_MD5 ]; - sal_uInt8 m_pDocId[16]; +}; + +class MSFILTER_DLLPUBLIC MSCodec_CryptoAPI : public MSCodec97 +{ +public: + MSCodec_CryptoAPI(); + + virtual void InitKey(const sal_uInt16 pPassData[16], + const sal_uInt8 pDocId[16]) override; + virtual bool InitCipher(sal_uInt32 nCounter) override; + virtual void GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest) override; }; const sal_uInt32 ENCRYPTINFO_CRYPTOAPI = 0x00000004; @@ -459,12 +465,28 @@ struct MSFILTER_DLLPUBLIC EncryptionVerifierAES EncryptionVerifierAES(); }; +struct MSFILTER_DLLPUBLIC EncryptionVerifierRC4 +{ + sal_uInt32 saltSize; // must be 0x00000010 + sal_uInt8 salt[SALT_LENGTH]; // random generated salt value + sal_uInt8 encryptedVerifier[ENCRYPTED_VERIFIER_LENGTH]; // randomly generated verifier value + sal_uInt32 encryptedVerifierHashSize; // actually written hash size - depends on algorithm + sal_uInt8 encryptedVerifierHash[SHA1_HASH_LENGTH]; // verifier value hash - itself also encrypted + + EncryptionVerifierRC4(); +}; + struct MSFILTER_DLLPUBLIC StandardEncryptionInfo { EncryptionStandardHeader header; EncryptionVerifierAES verifier; }; +struct MSFILTER_DLLPUBLIC RC4EncryptionInfo +{ + EncryptionStandardHeader header; + EncryptionVerifierRC4 verifier; +}; } // namespace msfilter diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx index fdd43ae..c854d75 100644 --- a/sc/source/filter/excel/xicontent.cxx +++ b/sc/source/filter/excel/xicontent.cxx @@ -64,6 +64,7 @@ #include <memory> #include <utility> #include <o3tl/make_unique.hxx> +#include <oox/helper/helper.hxx> using ::com::sun::star::uno::Sequence; using ::std::unique_ptr; @@ -1110,21 +1111,80 @@ XclImpDecrypterRef lclReadFilepass8_Standard( XclImpStream& rStrm ) OSL_ENSURE( rStrm.GetRecLeft() == 48, "lclReadFilepass8 - wrong record size" ); if( rStrm.GetRecLeft() == 48 ) { - sal_uInt8 pnSalt[ 16 ]; - sal_uInt8 pnVerifier[ 16 ]; - sal_uInt8 pnVerifierHash[ 16 ]; - rStrm.Read( pnSalt, 16 ); - rStrm.Read( pnVerifier, 16 ); - rStrm.Read( pnVerifierHash, 16 ); - xDecr.reset( new XclImpBiff8Decrypter( pnSalt, pnVerifier, pnVerifierHash ) ); + std::vector<sal_uInt8> aSalt(16); + std::vector<sal_uInt8> aVerifier(16); + std::vector<sal_uInt8> aVerifierHash(16); + rStrm.Read(aSalt.data(), 16); + rStrm.Read(aVerifier.data(), 16); + rStrm.Read(aVerifierHash.data(), 16); + xDecr.reset(new XclImpBiff8StdDecrypter(aSalt, aVerifier, aVerifierHash)); } return xDecr; } -XclImpDecrypterRef lclReadFilepass8_Strong( XclImpStream& /*rStrm*/ ) +XclImpDecrypterRef lclReadFilepass8_Strong(XclImpStream& rStream) { - // not supported - return XclImpDecrypterRef(); + //Its possible there are other variants in existance but these + //are the defaults I get with Excel 2013 + XclImpDecrypterRef xDecr; + + msfilter::RC4EncryptionInfo info; + + info.header.flags = rStream.ReaduInt32(); + if (oox::getFlag( info.header.flags, msfilter::ENCRYPTINFO_EXTERNAL)) + return xDecr; + + sal_uInt32 nHeaderSize = rStream.ReaduInt32(); + sal_uInt32 actualHeaderSize = sizeof(info.header); + + if( (nHeaderSize < actualHeaderSize) ) + return xDecr; + + info.header.flags = rStream.ReaduInt32(); + info.header.sizeExtra = rStream.ReaduInt32(); + info.header.algId = rStream.ReaduInt32(); + info.header.algIdHash = rStream.ReaduInt32(); + info.header.keyBits = rStream.ReaduInt32(); + info.header.providedType = rStream.ReaduInt32(); + info.header.reserved1 = rStream.ReaduInt32(); + info.header.reserved2 = rStream.ReaduInt32(); + + rStream.Ignore(nHeaderSize - actualHeaderSize); + + info.verifier.saltSize = rStream.ReaduInt32(); + if (info.verifier.saltSize != 16) + return xDecr; + rStream.Read(&info.verifier.salt, sizeof(info.verifier.salt)); + rStream.Read(&info.verifier.encryptedVerifier, sizeof(info.verifier.encryptedVerifier)); + + info.verifier.encryptedVerifierHashSize = rStream.ReaduInt32(); + if (info.verifier.encryptedVerifierHashSize != RTL_DIGEST_LENGTH_SHA1) + return xDecr; + rStream.Read(&info.verifier.encryptedVerifierHash, info.verifier.encryptedVerifierHashSize); + + // check flags and algorithm IDs, required are AES128 and SHA-1 + if (!oox::getFlag(info.header.flags, msfilter::ENCRYPTINFO_CRYPTOAPI)) + return xDecr; + + if (oox::getFlag(info.header.flags, msfilter::ENCRYPTINFO_AES)) + return xDecr; + + if (info.header.algId != msfilter::ENCRYPT_ALGO_RC4) + return xDecr; + + // hash algorithm ID 0 defaults to SHA-1 too + if (info.header.algIdHash != 0 && info.header.algIdHash != msfilter::ENCRYPT_HASH_SHA1) + return xDecr; + + xDecr.reset(new XclImpBiff8CryptoAPIDecrypter( + std::vector<sal_uInt8>(info.verifier.salt, + info.verifier.salt + SAL_N_ELEMENTS(info.verifier.salt)), + std::vector<sal_uInt8>(info.verifier.encryptedVerifier, + info.verifier.encryptedVerifier + SAL_N_ELEMENTS(info.verifier.encryptedVerifier)), + std::vector<sal_uInt8>(info.verifier.encryptedVerifierHash, + info.verifier.encryptedVerifierHash + SAL_N_ELEMENTS(info.verifier.encryptedVerifierHash)))); + + return xDecr; } XclImpDecrypterRef lclReadFilepass8( XclImpStream& rStrm ) diff --git a/sc/source/filter/excel/xistream.cxx b/sc/source/filter/excel/xistream.cxx index 31cf3d5..4f28d9c 100644 --- a/sc/source/filter/excel/xistream.cxx +++ b/sc/source/filter/excel/xistream.cxx @@ -192,28 +192,50 @@ sal_uInt16 XclImpBiff5Decrypter::OnRead( SvStream& rStrm, sal_uInt8* pnData, sal return nRet; } -XclImpBiff8Decrypter::XclImpBiff8Decrypter( sal_uInt8 pnSalt[ 16 ], - sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ) : - maSalt( pnSalt, pnSalt + 16 ), - maVerifier( pnVerifier, pnVerifier + 16 ), - maVerifierHash( pnVerifierHash, pnVerifierHash + 16 ) +XclImpBiff8Decrypter::XclImpBiff8Decrypter(const std::vector<sal_uInt8>& rSalt, + const std::vector<sal_uInt8>& rVerifier, + const std::vector<sal_uInt8>& rVerifierHash) + : maSalt(rSalt) + , maVerifier(rVerifier) + , maVerifierHash(rVerifierHash) + , mpCodec(nullptr) { } -XclImpBiff8Decrypter::XclImpBiff8Decrypter( const XclImpBiff8Decrypter& rSrc ) : - XclImpDecrypter( rSrc ), - maEncryptionData( rSrc.maEncryptionData ), - maSalt( rSrc.maSalt ), - maVerifier( rSrc.maVerifier ), - maVerifierHash( rSrc.maVerifierHash ) +XclImpBiff8Decrypter::XclImpBiff8Decrypter(const XclImpBiff8Decrypter& rSrc) + : XclImpDecrypter(rSrc) + , maEncryptionData(rSrc.maEncryptionData) + , maSalt(rSrc.maSalt) + , maVerifier(rSrc.maVerifier) + , maVerifierHash(rSrc.maVerifierHash) + , mpCodec(nullptr) { - if( IsValid() ) - maCodec.InitCodec( maEncryptionData ); } -XclImpBiff8Decrypter* XclImpBiff8Decrypter::OnClone() const +XclImpBiff8StdDecrypter::XclImpBiff8StdDecrypter(const XclImpBiff8StdDecrypter& rSrc) + : XclImpBiff8Decrypter(rSrc) { - return new XclImpBiff8Decrypter( *this ); + mpCodec = &maCodec; + if (IsValid()) + maCodec.InitCodec(maEncryptionData); +} + +XclImpBiff8StdDecrypter* XclImpBiff8StdDecrypter::OnClone() const +{ + return new XclImpBiff8StdDecrypter(*this); +} + +XclImpBiff8CryptoAPIDecrypter::XclImpBiff8CryptoAPIDecrypter(const XclImpBiff8CryptoAPIDecrypter& rSrc) + : XclImpBiff8Decrypter(rSrc) +{ + mpCodec = &maCodec; + if (IsValid()) + maCodec.InitCodec(maEncryptionData); +} + +XclImpBiff8CryptoAPIDecrypter* XclImpBiff8CryptoAPIDecrypter::OnClone() const +{ + return new XclImpBiff8CryptoAPIDecrypter(*this); } uno::Sequence< beans::NamedValue > XclImpBiff8Decrypter::OnVerifyPassword( const OUString& rPassword ) @@ -232,9 +254,9 @@ uno::Sequence< beans::NamedValue > XclImpBiff8Decrypter::OnVerifyPassword( const *aIt = static_cast< sal_uInt16 >( *pcChar ); // init codec - maCodec.InitKey( &aPassVect.front(), &maSalt.front() ); - if ( maCodec.VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) ) - maEncryptionData = maCodec.GetEncryptionData(); + mpCodec->InitKey( &aPassVect.front(), &maSalt.front() ); + if ( mpCodec->VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) ) + maEncryptionData = mpCodec->GetEncryptionData(); } return maEncryptionData; @@ -247,9 +269,9 @@ bool XclImpBiff8Decrypter::OnVerifyEncryptionData( const uno::Sequence< beans::N if( rEncryptionData.getLength() ) { // init codec - maCodec.InitCodec( rEncryptionData ); + mpCodec->InitCodec( rEncryptionData ); - if ( maCodec.VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) ) + if ( mpCodec->VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) ) maEncryptionData = rEncryptionData; } @@ -269,13 +291,13 @@ void XclImpBiff8Decrypter::OnUpdate( std::size_t nOldStrmPos, std::size_t nNewSt /* Rekey cipher, if block changed or if previous offset in same block. */ if( (nNewBlock != nOldBlock) || (nNewOffset < nOldOffset) ) { - maCodec.InitCipher( nNewBlock ); + mpCodec->InitCipher( nNewBlock ); nOldOffset = 0; // reset nOldOffset for next if() statement } /* Seek to correct offset. */ if( nNewOffset > nOldOffset ) - maCodec.Skip( nNewOffset - nOldOffset ); + mpCodec->Skip( nNewOffset - nOldOffset ); } } @@ -293,9 +315,9 @@ sal_uInt16 XclImpBiff8Decrypter::OnRead( SvStream& rStrm, sal_uInt8* pnData, sal // read the block from stream nRet = nRet + static_cast<sal_uInt16>(rStrm.ReadBytes(pnCurrData, nDecBytes)); // decode the block inplace - maCodec.Decode( pnCurrData, nDecBytes, pnCurrData, nDecBytes ); + mpCodec->Decode( pnCurrData, nDecBytes, pnCurrData, nDecBytes ); if( GetOffset( rStrm.Tell() ) == 0 ) - maCodec.InitCipher( GetBlock( rStrm.Tell() ) ); + mpCodec->InitCipher( GetBlock( rStrm.Tell() ) ); pnCurrData += nDecBytes; nBytesLeft = nBytesLeft - nDecBytes; diff --git a/sc/source/filter/inc/xistream.hxx b/sc/source/filter/inc/xistream.hxx index 4e0e63b..3a53643 100644 --- a/sc/source/filter/inc/xistream.hxx +++ b/sc/source/filter/inc/xistream.hxx @@ -119,16 +119,7 @@ private: /** Decrypts BIFF8 stream contents using the given document identifier. */ class XclImpBiff8Decrypter : public XclImpDecrypter { -public: - explicit XclImpBiff8Decrypter( sal_uInt8 pnSalt[ 16 ], - sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ); - private: - /** Private copy c'tor for OnClone(). */ - explicit XclImpBiff8Decrypter( const XclImpBiff8Decrypter& rSrc ); - - /** Implementation of cloning this object. */ - virtual XclImpBiff8Decrypter* OnClone() const override; /** Implements password verification and initialization of the decoder. */ virtual css::uno::Sequence< css::beans::NamedValue > OnVerifyPassword( const OUString& rPassword ) override; @@ -143,12 +134,62 @@ private: /** Returns the block offset corresponding to the passed stream position. */ static sal_uInt16 GetOffset( std::size_t nStrmPos ); +protected: + explicit XclImpBiff8Decrypter(const std::vector<sal_uInt8>& rSalt, + const std::vector<sal_uInt8>& rVerifier, + const std::vector<sal_uInt8>& rVerifierHash); + + explicit XclImpBiff8Decrypter(const XclImpBiff8Decrypter& rSrc); + + css::uno::Sequence< css::beans::NamedValue > maEncryptionData; + std::vector< sal_uInt8 > maSalt; + std::vector< sal_uInt8 > maVerifier; + std::vector< sal_uInt8 > maVerifierHash; + msfilter::MSCodec97* mpCodec; /// Crypto algorithm implementation. +}; + +class XclImpBiff8StdDecrypter : public XclImpBiff8Decrypter +{ +public: + explicit XclImpBiff8StdDecrypter(const std::vector<sal_uInt8>& rSalt, + const std::vector<sal_uInt8>& rVerifier, + const std::vector<sal_uInt8>& rVerifierHash) + : XclImpBiff8Decrypter(rSalt, rVerifier, rVerifierHash) + { + mpCodec = &maCodec; + } + +private: + /** Private copy c'tor for OnClone(). */ + explicit XclImpBiff8StdDecrypter(const XclImpBiff8StdDecrypter& rSrc); + + /** Implementation of cloning this object. */ + virtual XclImpBiff8StdDecrypter* OnClone() const override; + private: ::msfilter::MSCodec_Std97 maCodec; /// Crypto algorithm implementation. - css::uno::Sequence< css::beans::NamedValue > maEncryptionData; - ::std::vector< sal_uInt8 > maSalt; - ::std::vector< sal_uInt8 > maVerifier; - ::std::vector< sal_uInt8 > maVerifierHash; +}; + +class XclImpBiff8CryptoAPIDecrypter : public XclImpBiff8Decrypter +{ +public: + explicit XclImpBiff8CryptoAPIDecrypter(const std::vector<sal_uInt8>& rSalt, + const std::vector<sal_uInt8>& rVerifier, + const std::vector<sal_uInt8>& rVerifierHash) + : XclImpBiff8Decrypter(rSalt, rVerifier, rVerifierHash) + { + mpCodec = &maCodec; + } + +private: + /** Private copy c'tor for OnClone(). */ + explicit XclImpBiff8CryptoAPIDecrypter(const XclImpBiff8CryptoAPIDecrypter& rSrc); + + /** Implementation of cloning this object. */ + virtual XclImpBiff8CryptoAPIDecrypter* OnClone() const override; + +private: + ::msfilter::MSCodec_CryptoAPI maCodec; /// Crypto algorithm implementation. }; // Stream commit 06916c839b16866b47235306d2db50850df0ad7c Author: Caolán McNamara <caol...@redhat.com> Date: Thu Oct 20 14:52:26 2016 +0100 split MSCodec_Std97 into a baseclass MSCodec97 Change-Id: Ia3c41a048169c78684800def94e53fc9f3201e30 diff --git a/filter/source/msfilter/mscodec.cxx b/filter/source/msfilter/mscodec.cxx index 9b9d243..20a1f4a 100644 --- a/filter/source/msfilter/mscodec.cxx +++ b/filter/source/msfilter/mscodec.cxx @@ -245,27 +245,31 @@ void MSCodec_Xor95::Skip( std::size_t nBytes ) mnOffset = (mnOffset + nBytes) & 0x0F; } - -MSCodec_Std97::MSCodec_Std97 () +MSCodec97::MSCodec97(rtlCipher hCipher) + : m_hCipher(hCipher) { - m_hCipher = rtl_cipher_create ( - rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream); - OSL_ASSERT(m_hCipher != nullptr); - - m_hDigest = rtl_digest_create ( - rtl_Digest_AlgorithmMD5); - OSL_ASSERT(m_hDigest != nullptr); +} +MSCodec_Std97::MSCodec_Std97() + : MSCodec97(rtl_cipher_create(rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream)) +{ + assert(m_hCipher != nullptr); + m_hDigest = rtl_digest_create(rtl_Digest_AlgorithmMD5); + assert(m_hDigest != nullptr); (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue)); (void)memset (m_pDocId, 0, sizeof(m_pDocId)); } -MSCodec_Std97::~MSCodec_Std97 () +MSCodec97::~MSCodec97() +{ + rtl_cipher_destroy(m_hCipher); +} + +MSCodec_Std97::~MSCodec_Std97() { (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue)); (void)memset (m_pDocId, 0, sizeof(m_pDocId)); - rtl_digest_destroy (m_hDigest); - rtl_cipher_destroy (m_hCipher); + rtl_digest_destroy(m_hDigest); } #if DEBUG_MSO_ENCRYPTION_STD97 @@ -431,7 +435,7 @@ void MSCodec_Std97::CreateSaltDigest( const sal_uInt8 nSaltData[16], sal_uInt8 n } } -bool MSCodec_Std97::Encode ( +bool MSCodec97::Encode ( const void *pData, std::size_t nDatLen, sal_uInt8 *pBuffer, std::size_t nBufLen) { @@ -441,7 +445,7 @@ bool MSCodec_Std97::Encode ( return (result == rtl_Cipher_E_None); } -bool MSCodec_Std97::Decode ( +bool MSCodec97::Decode ( const void *pData, std::size_t nDatLen, sal_uInt8 *pBuffer, std::size_t nBufLen) { @@ -451,7 +455,7 @@ bool MSCodec_Std97::Decode ( return (result == rtl_Cipher_E_None); } -bool MSCodec_Std97::Skip( std::size_t nDatLen ) +bool MSCodec97::Skip(std::size_t nDatLen) { sal_uInt8 pnDummy[ 1024 ]; std::size_t nDatLeft = nDatLen; diff --git a/include/filter/msfilter/mscodec.hxx b/include/filter/msfilter/mscodec.hxx index fa71a15..afdf163 100644 --- a/include/filter/msfilter/mscodec.hxx +++ b/include/filter/msfilter/mscodec.hxx @@ -174,18 +174,11 @@ public: virtual void Decode( sal_uInt8* pnData, std::size_t nBytes ) override; }; - -/** Encodes and decodes data from protected MSO 97+ documents. - - This is a wrapper class around low level cryptographic functions from RTL. - Implementation is based on the wvDecrypt package by Caolan McNamara: - http://www.csn.ul.ie/~caolan/docs/wvDecrypt.html - */ -class MSFILTER_DLLPUBLIC MSCodec_Std97 +class MSFILTER_DLLPUBLIC MSCodec97 { public: - explicit MSCodec_Std97(); - ~MSCodec_Std97(); + MSCodec97(rtlCipher m_hCipher); + virtual ~MSCodec97(); /** Initializes the algorithm with the encryption data. @@ -193,7 +186,7 @@ public: The sequence contains the necessary data to initialize the codec. */ - bool InitCodec( const css::uno::Sequence< css::beans::NamedValue >& aData ); + virtual bool InitCodec(const css::uno::Sequence< css::beans::NamedValue >& aData) = 0; /** Retrieves the encryption data @@ -201,38 +194,8 @@ public: The sequence contains the necessary data to initialize the codec. */ - css::uno::Sequence< css::beans::NamedValue > GetEncryptionData(); - - - /** Initializes the algorithm with the specified password and document ID. - - @param pPassData - Wide character array containing the password. Must be zero - terminated, which results in a maximum length of 15 characters. - @param pDocId - Unique document identifier read from or written to the file. - */ - void InitKey( - const sal_uInt16 pPassData[ 16 ], - const sal_uInt8 pDocId[ 16 ] ); - - /** Verifies the validity of the password using the passed salt data. - - @precond - The codec must be initialized with InitKey() before this function - can be used. - - @param pSaltData - Salt data block read from the file. - @param pSaltDigest - Salt digest read from the file. + virtual css::uno::Sequence< css::beans::NamedValue > GetEncryptionData() = 0; - @return - true = Test was successful. - */ - bool VerifyKey( - const sal_uInt8 pSaltData[ 16 ], - const sal_uInt8 pSaltDigest[ 16 ] ); /** Rekeys the codec using the specified counter. @@ -249,11 +212,7 @@ public: @param nCounter Block counter used to rekey the cipher. */ - bool InitCipher( sal_uInt32 nCounter ); - - /** Creates an MD5 digest of salt digest. */ - void CreateSaltDigest( - const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] ); + virtual bool InitCipher(sal_uInt32 nCounter) = 0; /** Encodes a block of memory. @@ -277,9 +236,8 @@ public: @return true = Encoding was successful (no error occurred). */ - bool Encode( - const void* pData, std::size_t nDatLen, - sal_uInt8* pBuffer, std::size_t nBufLen ); + bool Encode(const void* pData, std::size_t nDatLen, + sal_uInt8* pBuffer, std::size_t nBufLen); /** Decodes a block of memory. @@ -303,9 +261,8 @@ public: @return true = Decoding was successful (no error occurred). */ - bool Decode( - const void* pData, std::size_t nDatLen, - sal_uInt8* pBuffer, std::size_t nBufLen ); + bool Decode(const void* pData, std::size_t nDatLen, + sal_uInt8* pBuffer, std::size_t nBufLen); /** Lets the cipher skip a specific amount of bytes. @@ -319,7 +276,95 @@ public: @param nDatLen Number of bytes to be skipped (cipher "seeks" forward). */ - bool Skip( std::size_t nDatLen ); + bool Skip(std::size_t nDatLen); + +private: + MSCodec97(const MSCodec97&) = delete; + MSCodec97& operator=(const MSCodec97&) = delete; + +protected: + rtlCipher m_hCipher; +}; + +/** Encodes and decodes data from protected MSO 97+ documents. + + This is a wrapper class around low level cryptographic functions from RTL. + Implementation is based on the wvDecrypt package by Caolan McNamara: + http://www.csn.ul.ie/~caolan/docs/wvDecrypt.html + */ +class MSFILTER_DLLPUBLIC MSCodec_Std97 : public MSCodec97 +{ +public: + explicit MSCodec_Std97(); + ~MSCodec_Std97(); + + /** Initializes the algorithm with the encryption data. + + @param aData + The sequence contains the necessary data to initialize + the codec. + */ + virtual bool InitCodec(const css::uno::Sequence< css::beans::NamedValue >& aData) override; + + /** Retrieves the encryption data + + @return + The sequence contains the necessary data to initialize + the codec. + */ + virtual css::uno::Sequence<css::beans::NamedValue> GetEncryptionData() override; + + + /** Initializes the algorithm with the specified password and document ID. + + @param pPassData + Wide character array containing the password. Must be zero + terminated, which results in a maximum length of 15 characters. + @param pDocId + Unique document identifier read from or written to the file. + */ + void InitKey( + const sal_uInt16 pPassData[ 16 ], + const sal_uInt8 pDocId[ 16 ] ); + + /** Verifies the validity of the password using the passed salt data. + + @precond + The codec must be initialized with InitKey() before this function + can be used. + + @param pSaltData + Salt data block read from the file. + @param pSaltDigest + Salt digest read from the file. + + @return + true = Test was successful. + */ + bool VerifyKey( + const sal_uInt8 pSaltData[ 16 ], + const sal_uInt8 pSaltDigest[ 16 ] ); + + /** Rekeys the codec using the specified counter. + + After reading a specific amount of data the cipher algorithm needs to + be rekeyed using a counter that counts the data blocks. + + The block size is for example 512 Bytes for Word files and 1024 Bytes + for Excel files. + + @precond + The codec must be initialized with InitKey() before this function + can be used. + + @param nCounter + Block counter used to rekey the cipher. + */ + virtual bool InitCipher(sal_uInt32 nCounter) override; + + /** Creates an MD5 digest of salt digest. */ + void CreateSaltDigest( + const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] ); /** Gets salt data and salt digest. @@ -349,7 +394,6 @@ private: MSCodec_Std97( const MSCodec_Std97& ) = delete; MSCodec_Std97& operator=( const MSCodec_Std97& ) = delete; - rtlCipher m_hCipher; rtlDigest m_hDigest; sal_uInt8 m_pDigestValue[ RTL_DIGEST_LENGTH_MD5 ]; sal_uInt8 m_pDocId[16]; commit 3fabbd0a22219464545f933fc28c869a6fa89546 Author: Caolán McNamara <caol...@redhat.com> Date: Thu Oct 20 14:31:58 2016 +0100 rework things in light of now available documentation Change-Id: If5f75e27191017a8c6a3929e2a70d21840f157c6 diff --git a/include/filter/msfilter/mscodec.hxx b/include/filter/msfilter/mscodec.hxx index dd3acbc..fa71a15 100644 --- a/include/filter/msfilter/mscodec.hxx +++ b/include/filter/msfilter/mscodec.hxx @@ -374,6 +374,8 @@ const sal_uInt32 ENCRYPT_KEY_SIZE_AES_256 = 0x00000100; const sal_uInt32 ENCRYPT_PROVIDER_TYPE_AES = 0x00000018; const sal_uInt32 ENCRYPT_PROVIDER_TYPE_RC4 = 0x00000001; +// version of encryption info used in MS Office 1997 (major = 1, minor = 1) +const sal_uInt32 VERSION_INFO_1997_FORMAT = 0x00010001; // version of encryption info used in MS Office 2007 (major = 3, minor = 2) const sal_uInt32 VERSION_INFO_2007_FORMAT = 0x00020003; // version of encryption info used in MS Office 2007 SP2 and older (major = 4, minor = 2) diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx index 27e84eb..fdd43ae 100644 --- a/sc/source/filter/excel/xicontent.cxx +++ b/sc/source/filter/excel/xicontent.cxx @@ -1141,20 +1141,22 @@ XclImpDecrypterRef lclReadFilepass8( XclImpStream& rStrm ) case EXC_FILEPASS_BIFF8: { - rStrm.Ignore( 2 ); - sal_uInt16 nSubMode(0); - nSubMode = rStrm.ReaduInt16(); - switch( nSubMode ) + sal_uInt32 nVersion = rStrm.ReaduInt32(); + if (nVersion == msfilter::VERSION_INFO_1997_FORMAT) { - case EXC_FILEPASS_BIFF8_STD: - xDecr = lclReadFilepass8_Standard( rStrm ); - break; - case EXC_FILEPASS_BIFF8_STRONG: - xDecr = lclReadFilepass8_Strong( rStrm ); - break; - default: - OSL_FAIL( "lclReadFilepass8 - unknown BIFF8 encryption sub mode" ); + //A Version structure where Version.vMajor MUST be 0x0001, + //and Version.vMinor MUST be 0x0001. + xDecr = lclReadFilepass8_Standard(rStrm); + } + else if (nVersion == msfilter::VERSION_INFO_2007_FORMAT || + nVersion == msfilter::VERSION_INFO_2007_FORMAT_SP2) + { + //Version.vMajor MUST be 0x0002, 0x0003 or 0x0004 and + //Version.vMinor MUST be 0x0002. + xDecr = lclReadFilepass8_Strong(rStrm); } + else + OSL_FAIL("lclReadFilepass8 - unknown BIFF8 encryption sub mode"); } break; diff --git a/sc/source/filter/inc/xlcontent.hxx b/sc/source/filter/inc/xlcontent.hxx index 6bb7b0b..ec94750 100644 --- a/sc/source/filter/inc/xlcontent.hxx +++ b/sc/source/filter/inc/xlcontent.hxx @@ -39,8 +39,6 @@ const sal_uInt16 EXC_ID_FILEPASS = 0x002F; const sal_uInt16 EXC_FILEPASS_BIFF5 = 0x0000; const sal_uInt16 EXC_FILEPASS_BIFF8 = 0x0001; -const sal_uInt16 EXC_FILEPASS_BIFF8_STD = 0x0001; -const sal_uInt16 EXC_FILEPASS_BIFF8_STRONG = 0x0002; // (0x00FC, 0x00FF) SST, EXTSST ----------------------------------------------- commit fc514cbf30be1613fdf4d4b7c12cbd55ca08b9b0 Author: Caolán McNamara <caol...@redhat.com> Date: Thu Oct 20 14:25:13 2016 +0100 move some useful header information to mscodec for reuse Change-Id: Ic7adf3ed3c8279cc93a06975d6fb337210d1af87 diff --git a/filter/source/msfilter/mscodec.cxx b/filter/source/msfilter/mscodec.cxx index 141e361..9b9d243 100644 --- a/filter/source/msfilter/mscodec.cxx +++ b/filter/source/msfilter/mscodec.cxx @@ -532,6 +532,26 @@ void MSCodec_Std97::GetDocId( sal_uInt8 pDocId[16] ) (void)memcpy( pDocId, m_pDocId, 16 ); } +EncryptionStandardHeader::EncryptionStandardHeader() +{ + flags = 0; + sizeExtra = 0; + algId = 0; + algIdHash = 0; + keyBits = 0; + providedType = 0; + reserved1 = 0; + reserved2 = 0; +} + +EncryptionVerifierAES::EncryptionVerifierAES() + : saltSize(SALT_LENGTH) + , encryptedVerifierHashSize(SHA1_HASH_LENGTH) +{ + memset(salt, 0, sizeof(salt)); + memset(encryptedVerifier, 0, sizeof(encryptedVerifier)); + memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash)); +} } diff --git a/include/filter/msfilter/mscodec.hxx b/include/filter/msfilter/mscodec.hxx index 1b91df6..dd3acbc 100644 --- a/include/filter/msfilter/mscodec.hxx +++ b/include/filter/msfilter/mscodec.hxx @@ -355,6 +355,70 @@ private: sal_uInt8 m_pDocId[16]; }; +const sal_uInt32 ENCRYPTINFO_CRYPTOAPI = 0x00000004; +const sal_uInt32 ENCRYPTINFO_DOCPROPS = 0x00000008; +const sal_uInt32 ENCRYPTINFO_EXTERNAL = 0x00000010; +const sal_uInt32 ENCRYPTINFO_AES = 0x00000020; + +const sal_uInt32 ENCRYPT_ALGO_AES128 = 0x0000660E; +const sal_uInt32 ENCRYPT_ALGO_AES192 = 0x0000660F; +const sal_uInt32 ENCRYPT_ALGO_AES256 = 0x00006610; +const sal_uInt32 ENCRYPT_ALGO_RC4 = 0x00006801; + +const sal_uInt32 ENCRYPT_HASH_SHA1 = 0x00008004; + +const sal_uInt32 ENCRYPT_KEY_SIZE_AES_128 = 0x00000080; +const sal_uInt32 ENCRYPT_KEY_SIZE_AES_192 = 0x000000C0; +const sal_uInt32 ENCRYPT_KEY_SIZE_AES_256 = 0x00000100; + +const sal_uInt32 ENCRYPT_PROVIDER_TYPE_AES = 0x00000018; +const sal_uInt32 ENCRYPT_PROVIDER_TYPE_RC4 = 0x00000001; + +// version of encryption info used in MS Office 2007 (major = 3, minor = 2) +const sal_uInt32 VERSION_INFO_2007_FORMAT = 0x00020003; +// version of encryption info used in MS Office 2007 SP2 and older (major = 4, minor = 2) +const sal_uInt32 VERSION_INFO_2007_FORMAT_SP2 = 0x00020004; + +// version of encryption info - agile (major = 4, minor = 4) +const sal_uInt32 VERSION_INFO_AGILE = 0x00040004; + +const sal_uInt32 SALT_LENGTH = 16; +const sal_uInt32 ENCRYPTED_VERIFIER_LENGTH = 16; +const sal_uInt32 SHA1_HASH_LENGTH = RTL_DIGEST_LENGTH_SHA1; // 20 +const sal_uInt32 SHA256_HASH_LENGTH = 32; +const sal_uInt32 SHA512_HASH_LENGTH = 64; + +struct MSFILTER_DLLPUBLIC EncryptionStandardHeader +{ + sal_uInt32 flags; + sal_uInt32 sizeExtra; // 0 + sal_uInt32 algId; // if flag AES && CRYPTOAPI this defaults to 128-bit AES + sal_uInt32 algIdHash; // 0: determine by flags - defaults to SHA-1 if not external + sal_uInt32 keyBits; // key size in bits: 0 (determine by flags), 128, 192, 256 + sal_uInt32 providedType; // AES or RC4 + sal_uInt32 reserved1; // 0 + sal_uInt32 reserved2; // 0 + + EncryptionStandardHeader(); +}; + +struct MSFILTER_DLLPUBLIC EncryptionVerifierAES +{ + sal_uInt32 saltSize; // must be 0x00000010 + sal_uInt8 salt[SALT_LENGTH]; // random generated salt value + sal_uInt8 encryptedVerifier[ENCRYPTED_VERIFIER_LENGTH]; // randomly generated verifier value + sal_uInt32 encryptedVerifierHashSize; // actually written hash size - depends on algorithm + sal_uInt8 encryptedVerifierHash[SHA256_HASH_LENGTH]; // verifier value hash - itself also encrypted + + EncryptionVerifierAES(); +}; + +struct MSFILTER_DLLPUBLIC StandardEncryptionInfo +{ + EncryptionStandardHeader header; + EncryptionVerifierAES verifier; +}; + } // namespace msfilter diff --git a/include/oox/crypto/Standard2007Engine.hxx b/include/oox/crypto/Standard2007Engine.hxx index 1650b62..42998b4 100644 --- a/include/oox/crypto/Standard2007Engine.hxx +++ b/include/oox/crypto/Standard2007Engine.hxx @@ -11,6 +11,7 @@ #ifndef INCLUDED_OOX_CRYPTO_STANDARD2007ENGINE_HXX #define INCLUDED_OOX_CRYPTO_STANDARD2007ENGINE_HXX +#include <filter/msfilter/mscodec.hxx> #include <oox/crypto/CryptoEngine.hxx> #include <rtl/digest.h> #include <rtl/ustring.hxx> @@ -24,73 +25,9 @@ namespace oox { namespace oox { namespace core { -const sal_uInt32 ENCRYPTINFO_CRYPTOAPI = 0x00000004; -const sal_uInt32 ENCRYPTINFO_DOCPROPS = 0x00000008; -const sal_uInt32 ENCRYPTINFO_EXTERNAL = 0x00000010; -const sal_uInt32 ENCRYPTINFO_AES = 0x00000020; - -const sal_uInt32 ENCRYPT_ALGO_AES128 = 0x0000660E; -const sal_uInt32 ENCRYPT_ALGO_AES192 = 0x0000660F; -const sal_uInt32 ENCRYPT_ALGO_AES256 = 0x00006610; -const sal_uInt32 ENCRYPT_ALGO_RC4 = 0x00006801; - -const sal_uInt32 ENCRYPT_HASH_SHA1 = 0x00008004; - -const sal_uInt32 ENCRYPT_KEY_SIZE_AES_128 = 0x00000080; -const sal_uInt32 ENCRYPT_KEY_SIZE_AES_192 = 0x000000C0; -const sal_uInt32 ENCRYPT_KEY_SIZE_AES_256 = 0x00000100; - -const sal_uInt32 ENCRYPT_PROVIDER_TYPE_AES = 0x00000018; -const sal_uInt32 ENCRYPT_PROVIDER_TYPE_RC4 = 0x00000001; - -// version of encryption info used in MS Office 2007 (major = 3, minor = 2) -const sal_uInt32 VERSION_INFO_2007_FORMAT = 0x00020003; -// version of encryption info used in MS Office 2007 SP2 and older (major = 4, minor = 2) -const sal_uInt32 VERSION_INFO_2007_FORMAT_SP2 = 0x00020004; - -// version of encryption info - agile (major = 4, minor = 4) -const sal_uInt32 VERSION_INFO_AGILE = 0x00040004; - -const sal_uInt32 SALT_LENGTH = 16; -const sal_uInt32 ENCRYPTED_VERIFIER_LENGTH = 16; -const sal_uInt32 SHA1_HASH_LENGTH = RTL_DIGEST_LENGTH_SHA1; // 20 -const sal_uInt32 SHA256_HASH_LENGTH = 32; -const sal_uInt32 SHA512_HASH_LENGTH = 64; - -struct EncryptionStandardHeader -{ - sal_uInt32 flags; - sal_uInt32 sizeExtra; // 0 - sal_uInt32 algId; // if flag AES && CRYPTOAPI this defaults to 128-bit AES - sal_uInt32 algIdHash; // 0: determine by flags - defaults to SHA-1 if not external - sal_uInt32 keyBits; // key size in bits: 0 (determine by flags), 128, 192, 256 - sal_uInt32 providedType; // AES or RC4 - sal_uInt32 reserved1; // 0 - sal_uInt32 reserved2; // 0 - - EncryptionStandardHeader(); -}; - -struct EncryptionVerifierAES -{ - sal_uInt32 saltSize; // must be 0x00000010 - sal_uInt8 salt[SALT_LENGTH]; // random generated salt value - sal_uInt8 encryptedVerifier[ENCRYPTED_VERIFIER_LENGTH]; // randomly generated verifier value - sal_uInt32 encryptedVerifierHashSize; // actually written hash size - depends on algorithm - sal_uInt8 encryptedVerifierHash[SHA256_HASH_LENGTH]; // verifier value hash - itself also encrypted - - EncryptionVerifierAES(); -}; - -struct StandardEncryptionInfo -{ - EncryptionStandardHeader header; - EncryptionVerifierAES verifier; -}; - class Standard2007Engine : public CryptoEngine { - StandardEncryptionInfo mInfo; + msfilter::StandardEncryptionInfo mInfo; bool generateVerifier(); bool calculateEncryptionKey(const OUString& rPassword); @@ -99,7 +36,7 @@ public: Standard2007Engine(); virtual ~Standard2007Engine() override; - StandardEncryptionInfo& getInfo() { return mInfo;} + msfilter::StandardEncryptionInfo& getInfo() { return mInfo;} virtual bool generateEncryptionKey(const OUString& rPassword) override; diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx index d6dbc96..4bb3ec2 100644 --- a/oox/source/crypto/CryptTools.cxx +++ b/oox/source/crypto/CryptTools.cxx @@ -9,8 +9,8 @@ */ #include "oox/crypto/CryptTools.hxx" +#include <filter/msfilter/mscodec.hxx> #include <com/sun/star/uno/RuntimeException.hpp> -#include "oox/crypto/Standard2007Engine.hxx" namespace oox { namespace core { @@ -267,9 +267,9 @@ sal_uInt32 Digest::getLength() switch(meType) { case SHA1: - return oox::core::SHA1_HASH_LENGTH; + return msfilter::SHA1_HASH_LENGTH; case SHA512: - return oox::core::SHA512_HASH_LENGTH; + return msfilter::SHA512_HASH_LENGTH; default: break; } diff --git a/oox/source/crypto/DocumentDecryption.cxx b/oox/source/crypto/DocumentDecryption.cxx index c843ad1..3fcbc57 100644 --- a/oox/source/crypto/DocumentDecryption.cxx +++ b/oox/source/crypto/DocumentDecryption.cxx @@ -241,7 +241,7 @@ bool DocumentDecryption::readAgileEncryptionInfo(Reference< XInputStream >& xInp info.cipherAlgorithm == "AES" && info.cipherChaining == "ChainingModeCBC" && info.hashAlgorithm == "SHA1" && - info.hashSize == SHA1_HASH_LENGTH) + info.hashSize == msfilter::SHA1_HASH_LENGTH) { return true; } @@ -251,7 +251,7 @@ bool DocumentDecryption::readAgileEncryptionInfo(Reference< XInputStream >& xInp info.cipherAlgorithm == "AES" && info.cipherChaining == "ChainingModeCBC" && info.hashAlgorithm == "SHA512" && - info.hashSize == SHA512_HASH_LENGTH) + info.hashSize == msfilter::SHA512_HASH_LENGTH) { return true; } @@ -263,10 +263,10 @@ bool DocumentDecryption::readStandard2007EncryptionInfo(BinaryInputStream& rStre { Standard2007Engine* engine = new Standard2007Engine(); mEngine.reset(engine); - StandardEncryptionInfo& info = engine->getInfo(); + msfilter::StandardEncryptionInfo& info = engine->getInfo(); info.header.flags = rStream.readuInt32(); - if( getFlag( info.header.flags, ENCRYPTINFO_EXTERNAL ) ) + if( getFlag( info.header.flags, msfilter::ENCRYPTINFO_EXTERNAL ) ) return false; sal_uInt32 nHeaderSize = rStream.readuInt32(); @@ -297,18 +297,18 @@ bool DocumentDecryption::readStandard2007EncryptionInfo(BinaryInputStream& rStre return false; // check flags and algorithm IDs, required are AES128 and SHA-1 - if( !getFlag( info.header.flags , ENCRYPTINFO_CRYPTOAPI ) ) + if( !getFlag( info.header.flags, msfilter::ENCRYPTINFO_CRYPTOAPI ) ) return false; - if( !getFlag( info.header.flags, ENCRYPTINFO_AES ) ) + if( !getFlag( info.header.flags, msfilter::ENCRYPTINFO_AES ) ) return false; // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set - if( info.header.algId != 0 && info.header.algId != ENCRYPT_ALGO_AES128 ) + if( info.header.algId != 0 && info.header.algId != msfilter::ENCRYPT_ALGO_AES128 ) return false; // hash algorithm ID 0 defaults to SHA-1 too - if( info.header.algIdHash != 0 && info.header.algIdHash != ENCRYPT_HASH_SHA1 ) + if( info.header.algIdHash != 0 && info.header.algIdHash != msfilter::ENCRYPT_HASH_SHA1 ) return false; if( info.verifier.encryptedVerifierHashSize != 20 ) @@ -332,12 +332,12 @@ bool DocumentDecryption::readEncryptionInfo() switch (aVersion) { - case VERSION_INFO_2007_FORMAT: - case VERSION_INFO_2007_FORMAT_SP2: + case msfilter::VERSION_INFO_2007_FORMAT: + case msfilter::VERSION_INFO_2007_FORMAT_SP2: mCryptoType = STANDARD_2007; // Set encryption info format bResult = readStandard2007EncryptionInfo( aBinaryInputStream ); break; - case VERSION_INFO_AGILE: + case msfilter::VERSION_INFO_AGILE: mCryptoType = AGILE; // Set encryption info format aBinaryInputStream.skip(4); bResult = readAgileEncryptionInfo( xEncryptionInfo ); diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx index 87ef81b..ecf9d8c 100644 --- a/oox/source/crypto/Standard2007Engine.cxx +++ b/oox/source/crypto/Standard2007Engine.cxx @@ -42,27 +42,6 @@ static const OUString lclCspName = "Microsoft Enhanced RSA and AES Cryptographic } // namespace -EncryptionStandardHeader::EncryptionStandardHeader() -{ - flags = 0; - sizeExtra = 0; - algId = 0; - algIdHash = 0; - keyBits = 0; - providedType = 0; - reserved1 = 0; - reserved2 = 0; -} - -EncryptionVerifierAES::EncryptionVerifierAES() - : saltSize(SALT_LENGTH) - , encryptedVerifierHashSize(SHA1_HASH_LENGTH) -{ - memset(salt, 0, sizeof(salt)); - memset(encryptedVerifier, 0, sizeof(encryptedVerifier)); - memset(encryptedVerifierHash, 0, sizeof(encryptedVerifierHash)); -} - Standard2007Engine::Standard2007Engine() : CryptoEngine() {} @@ -76,23 +55,23 @@ bool Standard2007Engine::generateVerifier() if (mKey.size() != 16) return false; - vector<sal_uInt8> verifier(ENCRYPTED_VERIFIER_LENGTH); - vector<sal_uInt8> encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH); + vector<sal_uInt8> verifier(msfilter::ENCRYPTED_VERIFIER_LENGTH); + vector<sal_uInt8> encryptedVerifier(msfilter::ENCRYPTED_VERIFIER_LENGTH); lclRandomGenerateValues(&verifier[0], verifier.size()); vector<sal_uInt8> iv; Encrypt aEncryptorVerifier(mKey, iv, Crypto::AES_128_ECB); - if (aEncryptorVerifier.update(encryptedVerifier, verifier) != ENCRYPTED_VERIFIER_LENGTH) + if (aEncryptorVerifier.update(encryptedVerifier, verifier) != msfilter::ENCRYPTED_VERIFIER_LENGTH) return false; std::copy(encryptedVerifier.begin(), encryptedVerifier.end(), mInfo.verifier.encryptedVerifier); - vector<sal_uInt8> hash(SHA1_HASH_LENGTH, 0); - mInfo.verifier.encryptedVerifierHashSize = SHA1_HASH_LENGTH; + vector<sal_uInt8> hash(msfilter::SHA1_HASH_LENGTH, 0); + mInfo.verifier.encryptedVerifierHashSize = msfilter::SHA1_HASH_LENGTH; Digest::sha1(hash, verifier); - hash.resize(SHA256_HASH_LENGTH, 0); + hash.resize(msfilter::SHA256_HASH_LENGTH, 0); - vector<sal_uInt8> encryptedHash(SHA256_HASH_LENGTH, 0); + vector<sal_uInt8> encryptedHash(msfilter::SHA256_HASH_LENGTH, 0); Encrypt aEncryptorHash(mKey, iv, Crypto::AES_128_ECB); aEncryptorHash.update(encryptedHash, hash, hash.size()); @@ -119,13 +98,13 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword) initialData.begin() + saltSize); // use "hash" vector for result of sha1 hashing - vector<sal_uInt8> hash(SHA1_HASH_LENGTH, 0); + vector<sal_uInt8> hash(msfilter::SHA1_HASH_LENGTH, 0); // calculate SHA1 hash of initialData Digest::sha1(hash, initialData); // data = iterator (4bytes) + hash - vector<sal_uInt8> data(SHA1_HASH_LENGTH + 4, 0); + vector<sal_uInt8> data(msfilter::SHA1_HASH_LENGTH + 4, 0); for (sal_Int32 i = 0; i < 50000; ++i) { @@ -134,7 +113,7 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword) Digest::sha1(hash, data); } std::copy(hash.begin(), hash.end(), data.begin() ); - std::fill(data.begin() + SHA1_HASH_LENGTH, data.end(), 0 ); + std::fill(data.begin() + msfilter::SHA1_HASH_LENGTH, data.end(), 0 ); Digest::sha1(hash, data); @@ -156,16 +135,16 @@ bool Standard2007Engine::generateEncryptionKey(const OUString& password) calculateEncryptionKey(password); - vector<sal_uInt8> encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH); + vector<sal_uInt8> encryptedVerifier(msfilter::ENCRYPTED_VERIFIER_LENGTH); std::copy( mInfo.verifier.encryptedVerifier, - mInfo.verifier.encryptedVerifier + ENCRYPTED_VERIFIER_LENGTH, + mInfo.verifier.encryptedVerifier + msfilter::ENCRYPTED_VERIFIER_LENGTH, encryptedVerifier.begin()); - vector<sal_uInt8> encryptedHash(SHA256_HASH_LENGTH); + vector<sal_uInt8> encryptedHash(msfilter::SHA256_HASH_LENGTH); std::copy( mInfo.verifier.encryptedVerifierHash, - mInfo.verifier.encryptedVerifierHash + SHA256_HASH_LENGTH, + mInfo.verifier.encryptedVerifierHash + msfilter::SHA256_HASH_LENGTH, encryptedHash.begin()); vector<sal_uInt8> verifier(encryptedVerifier.size(), 0); @@ -174,7 +153,7 @@ bool Standard2007Engine::generateEncryptionKey(const OUString& password) vector<sal_uInt8> verifierHash(encryptedHash.size(), 0); Decrypt::aes128ecb(verifierHash, encryptedHash, mKey); - vector<sal_uInt8> hash(SHA1_HASH_LENGTH, 0); + vector<sal_uInt8> hash(msfilter::SHA1_HASH_LENGTH, 0); Digest::sha1(hash, verifier); return std::equal( hash.begin(), hash.end(), verifierHash.begin() ); @@ -204,11 +183,11 @@ bool Standard2007Engine::decrypt( void Standard2007Engine::writeEncryptionInfo(const OUString& password, BinaryXOutputStream& rStream) { - mInfo.header.flags = ENCRYPTINFO_AES | ENCRYPTINFO_CRYPTOAPI; - mInfo.header.algId = ENCRYPT_ALGO_AES128; - mInfo.header.algIdHash = ENCRYPT_HASH_SHA1; - mInfo.header.keyBits = ENCRYPT_KEY_SIZE_AES_128; - mInfo.header.providedType = ENCRYPT_PROVIDER_TYPE_AES; + mInfo.header.flags = msfilter::ENCRYPTINFO_AES | msfilter::ENCRYPTINFO_CRYPTOAPI; + mInfo.header.algId = msfilter::ENCRYPT_ALGO_AES128; + mInfo.header.algIdHash = msfilter::ENCRYPT_HASH_SHA1; + mInfo.header.keyBits = msfilter::ENCRYPT_KEY_SIZE_AES_128; + mInfo.header.providedType = msfilter::ENCRYPT_PROVIDER_TYPE_AES; lclRandomGenerateValues(mInfo.verifier.salt, mInfo.verifier.saltSize); const sal_Int32 keyLength = mInfo.header.keyBits / 8; @@ -222,11 +201,11 @@ void Standard2007Engine::writeEncryptionInfo(const OUString& password, BinaryXOu if (!generateVerifier()) return; - rStream.WriteUInt32(VERSION_INFO_2007_FORMAT); + rStream.WriteUInt32(msfilter::VERSION_INFO_2007_FORMAT); sal_uInt32 cspNameSize = (lclCspName.getLength() * 2) + 2; - sal_uInt32 encryptionHeaderSize = static_cast<sal_uInt32>(sizeof(EncryptionStandardHeader)); + sal_uInt32 encryptionHeaderSize = static_cast<sal_uInt32>(sizeof(msfilter::EncryptionStandardHeader)); rStream.WriteUInt32( mInfo.header.flags ); sal_uInt32 headerSize = encryptionHeaderSize + cspNameSize; @@ -236,7 +215,7 @@ void Standard2007Engine::writeEncryptionInfo(const OUString& password, BinaryXOu rStream.writeUnicodeArray(lclCspName); rStream.WriteUInt16(0); - sal_uInt32 encryptionVerifierSize = static_cast<sal_uInt32>(sizeof(EncryptionVerifierAES)); + sal_uInt32 encryptionVerifierSize = static_cast<sal_uInt32>(sizeof(msfilter::EncryptionVerifierAES)); rStream.writeMemory(&mInfo.verifier, encryptionVerifierSize); } commit fcc846e8f29839eaace7e1d28746abea8f4b598a Author: Caolán McNamara <caol...@redhat.com> Date: Thu Oct 20 14:13:19 2016 +0100 hash len isn't going to change depending on who implements it Change-Id: Iee585cba4acad74c11d083085153e2af96c8894f diff --git a/include/oox/crypto/CryptTools.hxx b/include/oox/crypto/CryptTools.hxx index d963be2..d4fdda2 100644 --- a/include/oox/crypto/CryptTools.hxx +++ b/include/oox/crypto/CryptTools.hxx @@ -123,9 +123,6 @@ public: SHA512 }; - static const sal_uInt32 DIGEST_LENGTH_SHA1; - static const sal_uInt32 DIGEST_LENGTH_SHA512; - private: DigestType meType; diff --git a/include/oox/crypto/Standard2007Engine.hxx b/include/oox/crypto/Standard2007Engine.hxx index 2ee4a55..1650b62 100644 --- a/include/oox/crypto/Standard2007Engine.hxx +++ b/include/oox/crypto/Standard2007Engine.hxx @@ -12,6 +12,7 @@ #define INCLUDED_OOX_CRYPTO_STANDARD2007ENGINE_HXX #include <oox/crypto/CryptoEngine.hxx> +#include <rtl/digest.h> #include <rtl/ustring.hxx> #include <sal/types.h> @@ -52,9 +53,9 @@ const sal_uInt32 VERSION_INFO_AGILE = 0x00040004; const sal_uInt32 SALT_LENGTH = 16; const sal_uInt32 ENCRYPTED_VERIFIER_LENGTH = 16; -const sal_uInt32 ENCRYPTED_SHA1_VERIFIER_HASH_LENGTH = 20; -const sal_uInt32 ENCRYPTED_SHA256_VERIFIER_HASH_LENGTH = 32; -const sal_uInt32 ENCRYPTED_SHA512_VERIFIER_HASH_LENGTH = 64; +const sal_uInt32 SHA1_HASH_LENGTH = RTL_DIGEST_LENGTH_SHA1; // 20 +const sal_uInt32 SHA256_HASH_LENGTH = 32; +const sal_uInt32 SHA512_HASH_LENGTH = 64; struct EncryptionStandardHeader { @@ -76,7 +77,7 @@ struct EncryptionVerifierAES sal_uInt8 salt[SALT_LENGTH]; // random generated salt value sal_uInt8 encryptedVerifier[ENCRYPTED_VERIFIER_LENGTH]; // randomly generated verifier value sal_uInt32 encryptedVerifierHashSize; // actually written hash size - depends on algorithm - sal_uInt8 encryptedVerifierHash[ENCRYPTED_SHA256_VERIFIER_HASH_LENGTH]; // verifier value hash - itself also encrypted + sal_uInt8 encryptedVerifierHash[SHA256_HASH_LENGTH]; // verifier value hash - itself also encrypted EncryptionVerifierAES(); }; diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx index 1204877..d6dbc96 100644 --- a/oox/source/crypto/CryptTools.cxx +++ b/oox/source/crypto/CryptTools.cxx @@ -10,6 +10,7 @@ #include "oox/crypto/CryptTools.hxx" #include <com/sun/star/uno/RuntimeException.hpp> +#include "oox/crypto/Standard2007Engine.hxx" namespace oox { namespace core { @@ -196,15 +197,6 @@ sal_uInt32 Encrypt::update(vector<sal_uInt8>& output, vector<sal_uInt8>& input, // Digest -#if USE_TLS_OPENSSL -const sal_uInt32 Digest::DIGEST_LENGTH_SHA1 = SHA_DIGEST_LENGTH; -const sal_uInt32 Digest::DIGEST_LENGTH_SHA512 = SHA512_DIGEST_LENGTH; -#endif -#if USE_TLS_NSS -const sal_uInt32 Digest::DIGEST_LENGTH_SHA1 = SHA1_LENGTH; -const sal_uInt32 Digest::DIGEST_LENGTH_SHA512 = SHA512_LENGTH; -#endif - namespace { @@ -275,9 +267,9 @@ sal_uInt32 Digest::getLength() switch(meType) { case SHA1: - return DIGEST_LENGTH_SHA1; + return oox::core::SHA1_HASH_LENGTH; case SHA512: - return DIGEST_LENGTH_SHA512; + return oox::core::SHA512_HASH_LENGTH; default: break; } diff --git a/oox/source/crypto/DocumentDecryption.cxx b/oox/source/crypto/DocumentDecryption.cxx index d60c6b3..c843ad1 100644 --- a/oox/source/crypto/DocumentDecryption.cxx +++ b/oox/source/crypto/DocumentDecryption.cxx @@ -241,7 +241,7 @@ bool DocumentDecryption::readAgileEncryptionInfo(Reference< XInputStream >& xInp info.cipherAlgorithm == "AES" && info.cipherChaining == "ChainingModeCBC" && info.hashAlgorithm == "SHA1" && - info.hashSize == ENCRYPTED_SHA1_VERIFIER_HASH_LENGTH) + info.hashSize == SHA1_HASH_LENGTH) { return true; } @@ -251,7 +251,7 @@ bool DocumentDecryption::readAgileEncryptionInfo(Reference< XInputStream >& xInp info.cipherAlgorithm == "AES" && info.cipherChaining == "ChainingModeCBC" && info.hashAlgorithm == "SHA512" && - info.hashSize == ENCRYPTED_SHA512_VERIFIER_HASH_LENGTH ) + info.hashSize == SHA512_HASH_LENGTH) { return true; } diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx index 2266e44..87ef81b 100644 --- a/oox/source/crypto/Standard2007Engine.cxx +++ b/oox/source/crypto/Standard2007Engine.cxx @@ -54,9 +54,9 @@ EncryptionStandardHeader::EncryptionStandardHeader() reserved2 = 0; } -EncryptionVerifierAES::EncryptionVerifierAES() : - saltSize(SALT_LENGTH), - encryptedVerifierHashSize(Digest::DIGEST_LENGTH_SHA1) +EncryptionVerifierAES::EncryptionVerifierAES() + : saltSize(SALT_LENGTH) + , encryptedVerifierHashSize(SHA1_HASH_LENGTH) { memset(salt, 0, sizeof(salt)); memset(encryptedVerifier, 0, sizeof(encryptedVerifier)); @@ -87,12 +87,12 @@ bool Standard2007Engine::generateVerifier() return false; std::copy(encryptedVerifier.begin(), encryptedVerifier.end(), mInfo.verifier.encryptedVerifier); - vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0); - mInfo.verifier.encryptedVerifierHashSize = RTL_DIGEST_LENGTH_SHA1; + vector<sal_uInt8> hash(SHA1_HASH_LENGTH, 0); + mInfo.verifier.encryptedVerifierHashSize = SHA1_HASH_LENGTH; Digest::sha1(hash, verifier); - hash.resize(ENCRYPTED_SHA256_VERIFIER_HASH_LENGTH, 0); + hash.resize(SHA256_HASH_LENGTH, 0); - vector<sal_uInt8> encryptedHash(ENCRYPTED_SHA256_VERIFIER_HASH_LENGTH, 0); + vector<sal_uInt8> encryptedHash(SHA256_HASH_LENGTH, 0); Encrypt aEncryptorHash(mKey, iv, Crypto::AES_128_ECB); aEncryptorHash.update(encryptedHash, hash, hash.size()); @@ -119,13 +119,13 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword) initialData.begin() + saltSize); // use "hash" vector for result of sha1 hashing - vector<sal_uInt8> hash(Digest::DIGEST_LENGTH_SHA1, 0); + vector<sal_uInt8> hash(SHA1_HASH_LENGTH, 0); // calculate SHA1 hash of initialData Digest::sha1(hash, initialData); // data = iterator (4bytes) + hash - vector<sal_uInt8> data(Digest::DIGEST_LENGTH_SHA1 + 4, 0); + vector<sal_uInt8> data(SHA1_HASH_LENGTH + 4, 0); for (sal_Int32 i = 0; i < 50000; ++i) { @@ -134,7 +134,7 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword) Digest::sha1(hash, data); } std::copy(hash.begin(), hash.end(), data.begin() ); - std::fill(data.begin() + Digest::DIGEST_LENGTH_SHA1, data.end(), 0 ); + std::fill(data.begin() + SHA1_HASH_LENGTH, data.end(), 0 ); Digest::sha1(hash, data); @@ -162,10 +162,10 @@ bool Standard2007Engine::generateEncryptionKey(const OUString& password) mInfo.verifier.encryptedVerifier + ENCRYPTED_VERIFIER_LENGTH, encryptedVerifier.begin()); - vector<sal_uInt8> encryptedHash(ENCRYPTED_SHA256_VERIFIER_HASH_LENGTH); + vector<sal_uInt8> encryptedHash(SHA256_HASH_LENGTH); std::copy( mInfo.verifier.encryptedVerifierHash, - mInfo.verifier.encryptedVerifierHash + ENCRYPTED_SHA256_VERIFIER_HASH_LENGTH, + mInfo.verifier.encryptedVerifierHash + SHA256_HASH_LENGTH, encryptedHash.begin()); vector<sal_uInt8> verifier(encryptedVerifier.size(), 0); @@ -174,7 +174,7 @@ bool Standard2007Engine::generateEncryptionKey(const OUString& password) vector<sal_uInt8> verifierHash(encryptedHash.size(), 0); Decrypt::aes128ecb(verifierHash, encryptedHash, mKey); - vector<sal_uInt8> hash(RTL_DIGEST_LENGTH_SHA1, 0); + vector<sal_uInt8> hash(SHA1_HASH_LENGTH, 0); Digest::sha1(hash, verifier); return std::equal( hash.begin(), hash.end(), verifierHash.begin() );
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits