From fc514cbf30be1613fdf4d4b7c12cbd55ca08b9b0 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Thu, 20 Oct 2016 14:25:13 +0100 Subject: move some useful header information to mscodec for reuse Change-Id: Ic7adf3ed3c8279cc93a06975d6fb337210d1af87 --- filter/source/msfilter/mscodec.cxx | 20 +++++++++ include/filter/msfilter/mscodec.hxx | 64 ++++++++++++++++++++++++++++ include/oox/crypto/Standard2007Engine.hxx | 69 ++----------------------------- oox/source/crypto/CryptTools.cxx | 6 +-- oox/source/crypto/DocumentDecryption.cxx | 22 +++++----- oox/source/crypto/Standard2007Engine.cxx | 67 +++++++++++------------------- 6 files changed, 124 insertions(+), 124 deletions(-) diff --git a/filter/source/msfilter/mscodec.cxx b/filter/source/msfilter/mscodec.cxx index 141e36137c2e..9b9d243106c0 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 1b91df68b33d..dd3acbc1a6bf 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 1650b622e9f5..42998b492760 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 #include #include #include @@ -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 d6dbc96dc989..4bb3ec2f2d28 100644 --- a/oox/source/crypto/CryptTools.cxx +++ b/oox/source/crypto/CryptTools.cxx @@ -9,8 +9,8 @@ */ #include "oox/crypto/CryptTools.hxx" +#include #include -#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 c843ad116d13..3fcbc571d3f1 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 87ef81b56e9b..ecf9d8c5dfe8 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 verifier(ENCRYPTED_VERIFIER_LENGTH); - vector encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH); + vector verifier(msfilter::ENCRYPTED_VERIFIER_LENGTH); + vector encryptedVerifier(msfilter::ENCRYPTED_VERIFIER_LENGTH); lclRandomGenerateValues(&verifier[0], verifier.size()); vector 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 hash(SHA1_HASH_LENGTH, 0); - mInfo.verifier.encryptedVerifierHashSize = SHA1_HASH_LENGTH; + vector 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 encryptedHash(SHA256_HASH_LENGTH, 0); + vector 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 hash(SHA1_HASH_LENGTH, 0); + vector hash(msfilter::SHA1_HASH_LENGTH, 0); // calculate SHA1 hash of initialData Digest::sha1(hash, initialData); // data = iterator (4bytes) + hash - vector data(SHA1_HASH_LENGTH + 4, 0); + vector 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 encryptedVerifier(ENCRYPTED_VERIFIER_LENGTH); + vector 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 encryptedHash(SHA256_HASH_LENGTH); + vector 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 verifier(encryptedVerifier.size(), 0); @@ -174,7 +153,7 @@ bool Standard2007Engine::generateEncryptionKey(const OUString& password) vector verifierHash(encryptedHash.size(), 0); Decrypt::aes128ecb(verifierHash, encryptedHash, mKey); - vector hash(SHA1_HASH_LENGTH, 0); + vector 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(sizeof(EncryptionStandardHeader)); + sal_uInt32 encryptionHeaderSize = static_cast(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(sizeof(EncryptionVerifierAES)); + sal_uInt32 encryptionVerifierSize = static_cast(sizeof(msfilter::EncryptionVerifierAES)); rStream.writeMemory(&mInfo.verifier, encryptionVerifierSize); } -- cgit