diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2024-11-01 12:48:10 +0100 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2024-11-04 21:51:32 +0100 |
commit | c8cba8ae30baef6feca3b0613366d28df4a5e568 (patch) | |
tree | 6c70cba4f20b6c62062ad316fe0f04b745e7d59b /oox | |
parent | 6adbc3c7179fc3977a15867e505b4ea919caf765 (diff) |
move CryptTools from oox to comphelper so we can reuse it
Also move the relevant tests and clean-up the names a bit to make
it mroe consistent.
Change-Id: I929ef9c13b954fd6a506471231d1bc41e4ef9980
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176027
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'oox')
-rw-r--r-- | oox/Library_oox.mk | 1 | ||||
-rw-r--r-- | oox/qa/unit/CryptoTest.cxx | 60 | ||||
-rw-r--r-- | oox/source/crypto/AgileEngine.cxx | 50 | ||||
-rw-r--r-- | oox/source/crypto/CryptTools.cxx | 533 | ||||
-rw-r--r-- | oox/source/crypto/Standard2007Engine.cxx | 16 |
5 files changed, 34 insertions, 626 deletions
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk index 7330fcc8995d..df8e484f7303 100644 --- a/oox/Library_oox.mk +++ b/oox/Library_oox.mk @@ -139,7 +139,6 @@ $(eval $(call gb_Library_add_exception_objects,oox,\ oox/source/core/relationshandler \ oox/source/core/xmlfilterbase \ oox/source/crypto/AgileEngine \ - oox/source/crypto/CryptTools \ oox/source/crypto/DocumentEncryption \ oox/source/crypto/DocumentDecryption \ oox/source/crypto/Standard2007Engine \ diff --git a/oox/qa/unit/CryptoTest.cxx b/oox/qa/unit/CryptoTest.cxx index 60938962fa72..88e71173a00d 100644 --- a/oox/qa/unit/CryptoTest.cxx +++ b/oox/qa/unit/CryptoTest.cxx @@ -31,8 +31,7 @@ class CryptoTest : public CppUnit::TestFixture { public: virtual ~CryptoTest() override; - void testCryptoHash(); - void testRoundUp(); + void testStandard2007(); void testAgileEncryptionVerifier(); void testAgileEncryptionInfoWritingAndParsing(); @@ -40,8 +39,6 @@ public: void testAgileEncryptingAndDecrypting(); CPPUNIT_TEST_SUITE(CryptoTest); - CPPUNIT_TEST(testCryptoHash); - CPPUNIT_TEST(testRoundUp); CPPUNIT_TEST(testStandard2007); CPPUNIT_TEST(testAgileEncryptionVerifier); CPPUNIT_TEST(testAgileEncryptionInfoWritingAndParsing); @@ -71,61 +68,6 @@ CryptoTest::~CryptoTest() #endif } -void CryptoTest::testCryptoHash() -{ - // Check examples from Wikipedia (https://en.wikipedia.org/wiki/HMAC) - OString aContentString("The quick brown fox jumps over the lazy dog"_ostr); - std::vector<sal_uInt8> aContent(aContentString.getStr(), - aContentString.getStr() + aContentString.getLength()); - std::vector<sal_uInt8> aKey = { 'k', 'e', 'y' }; - { - oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA1); - aCryptoHash.update(aContent); - std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); - CPPUNIT_ASSERT_EQUAL(std::string("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"), - toString(aHash)); - } - - { - oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA256); - aCryptoHash.update(aContent); - std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); - CPPUNIT_ASSERT_EQUAL( - std::string("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8"), - toString(aHash)); - } - - { - oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA384); - aCryptoHash.update(aContent); - std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); - CPPUNIT_ASSERT_EQUAL(std::string("d7f4727e2c0b39ae0f1e40cc96f60242d5b7801841cea6fc592c5d3e1" - "ae50700582a96cf35e1e554995fe4e03381c237"), - toString(aHash)); - } - - { - oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA512); - aCryptoHash.update(aContent); - std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); - CPPUNIT_ASSERT_EQUAL( - std::string("b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549" - "f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a"), - toString(aHash)); - } -} - -void CryptoTest::testRoundUp() -{ - CPPUNIT_ASSERT_EQUAL(16, oox::crypto::roundUp(16, 16)); - CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(32, 16)); - CPPUNIT_ASSERT_EQUAL(64, oox::crypto::roundUp(64, 16)); - - CPPUNIT_ASSERT_EQUAL(16, oox::crypto::roundUp(01, 16)); - CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(17, 16)); - CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(31, 16)); -} - void CryptoTest::testStandard2007() { oox::crypto::Standard2007Engine aEngine; diff --git a/oox/source/crypto/AgileEngine.cxx b/oox/source/crypto/AgileEngine.cxx index 1f164aa6ab42..6b552620f24d 100644 --- a/oox/source/crypto/AgileEngine.cxx +++ b/oox/source/crypto/AgileEngine.cxx @@ -218,14 +218,14 @@ bool hashCalc(std::vector<sal_uInt8>& output, return false; } -CryptoHashType cryptoHashTypeFromString(std::u16string_view sAlgorithm) +comphelper::CryptoHashType cryptoHashTypeFromString(std::u16string_view sAlgorithm) { if (sAlgorithm == u"SHA512") - return CryptoHashType::SHA512; + return comphelper::CryptoHashType::SHA512; else if (sAlgorithm == u"SHA384") - return CryptoHashType::SHA384; + return comphelper::CryptoHashType::SHA384; else - return CryptoHashType::SHA1; + return comphelper::CryptoHashType::SHA1; } } // namespace @@ -234,13 +234,13 @@ AgileEngine::AgileEngine() : meEncryptionPreset(AgileEncryptionPreset::AES_256_SHA512) {} -Crypto::CryptoType AgileEngine::cryptoType(const AgileEncryptionInfo& rInfo) +comphelper::CryptoType AgileEngine::cryptoType(const AgileEncryptionInfo& rInfo) { if (rInfo.keyBits == 128 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC") - return Crypto::AES_128_CBC; + return comphelper::CryptoType::AES_128_CBC; else if (rInfo.keyBits == 256 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC") - return Crypto::AES_256_CBC; - return Crypto::UNKNOWN; + return comphelper::CryptoType::AES_256_CBC; + return comphelper::CryptoType::UNKNOWN; } static std::vector<sal_uInt8> calculateIV(comphelper::HashType eType, @@ -252,7 +252,7 @@ static std::vector<sal_uInt8> calculateIV(comphelper::HashType eType, aHasher.update(rSalt.data(), rSalt.size()); aHasher.update(rBlock.data(), rBlock.size()); std::vector<sal_uInt8> aIV = aHasher.finalize(); - aIV.resize(roundUp(sal_Int32(aIV.size()), nCipherBlockSize), 0x36); + aIV.resize(comphelper::roundUp(sal_Int32(aIV.size()), nCipherBlockSize), 0x36); return aIV; } @@ -274,7 +274,7 @@ void AgileEngine::calculateBlock( std::copy(hash.begin(), hash.begin() + keySize, key.begin()); - Decrypt aDecryptor(key, mInfo.saltValue, cryptoType(mInfo)); + comphelper::Decrypt aDecryptor(key, mInfo.saltValue, cryptoType(mInfo)); aDecryptor.update(rOutput, rInput); } @@ -296,7 +296,7 @@ void AgileEngine::encryptBlock( std::copy(hash.begin(), hash.begin() + keySize, key.begin()); - Encrypt aEncryptor(key, mInfo.saltValue, cryptoType(mInfo)); + comphelper::Encrypt aEncryptor(key, mInfo.saltValue, cryptoType(mInfo)); aEncryptor.update(rOutput, rInput); } @@ -338,7 +338,7 @@ bool AgileEngine::decryptAndCheckVerifierHash(OUString const & rPassword) std::vector<sal_uInt8>& encryptedHashInput = mInfo.encryptedVerifierHashInput; // SALT - needs to be a multiple of block size (?) - sal_uInt32 nSaltSize = roundUp(mInfo.saltSize, mInfo.blockSize); + sal_uInt32 nSaltSize = comphelper::roundUp(mInfo.saltSize, mInfo.blockSize); if (nSaltSize < encryptedHashInput.size()) return false; std::vector<sal_uInt8> hashInput(nSaltSize, 0); @@ -400,7 +400,7 @@ bool AgileEngine::decryptHmacKey() std::vector<sal_uInt8> iv = calculateIV(eType, mInfo.keyDataSalt, constBlockHmac1, mInfo.blockSize); // Decrypt without key, calculated iv - Decrypt aDecrypt(mKey, iv, cryptoType(mInfo)); + comphelper::Decrypt aDecrypt(mKey, iv, cryptoType(mInfo)); aDecrypt.update(mInfo.hmacKey, mInfo.hmacEncryptedKey); mInfo.hmacKey.resize(mInfo.hashSize, 0); @@ -427,7 +427,7 @@ bool AgileEngine::decryptHmacValue() std::vector<sal_uInt8> iv = calculateIV(eType, mInfo.keyDataSalt, constBlockHmac2, mInfo.blockSize); // Decrypt without key, calculated iv - Decrypt aDecrypt(mKey, iv, cryptoType(mInfo)); + comphelper::Decrypt aDecrypt(mKey, iv, cryptoType(mInfo)); aDecrypt.update(mInfo.hmacHash, mInfo.hmacEncryptedValue); mInfo.hmacHash.resize(mInfo.hashSize, 0); @@ -446,7 +446,7 @@ bool AgileEngine::checkDataIntegrity() bool AgileEngine::decrypt(BinaryXInputStream& aInputStream, BinaryXOutputStream& aOutputStream) { - CryptoHash aCryptoHash(mInfo.hmacKey, cryptoHashTypeFromString(mInfo.hashAlgorithm)); + comphelper::CryptoHash aCryptoHash(mInfo.hmacKey, cryptoHashTypeFromString(mInfo.hashAlgorithm)); sal_uInt32 totalSize = aInputStream.readuInt32(); // Document unencrypted size - 4 bytes // account for size in HMAC @@ -492,7 +492,7 @@ bool AgileEngine::decrypt(BinaryXInputStream& aInputStream, // Only if hash > keySize std::copy(hash.begin(), hash.begin() + keySize, iv.begin()); - Decrypt aDecryptor(mKey, iv, AgileEngine::cryptoType(mInfo)); + comphelper::Decrypt aDecryptor(mKey, iv, cryptoType(mInfo)); outputLength = aDecryptor.update(outputBuffer, inputBuffer, inputLength); sal_uInt32 writeLength = std::min(outputLength, remaining); @@ -593,7 +593,7 @@ bool AgileEngine::generateAndEncryptVerifierHash(OUString const & rPassword) return false; // HASH - needs to be modified to be multiple of block size - sal_Int32 nVerifierHash = roundUp(mInfo.hashSize, mInfo.blockSize); + sal_Int32 nVerifierHash = comphelper::roundUp(mInfo.hashSize, mInfo.blockSize); std::vector<sal_uInt8> unencryptedVerifierHashValue; if (!hashCalc(unencryptedVerifierHashValue, unencryptedVerifierHashInput, mInfo.hashAlgorithm)) return false; @@ -619,7 +619,7 @@ bool AgileEngine::encryptHmacKey() return false; // Encrypted salt must be multiple of block size - sal_Int32 nEncryptedSaltSize = oox::crypto::roundUp(mInfo.hashSize, mInfo.blockSize); + sal_Int32 nEncryptedSaltSize = comphelper::roundUp(mInfo.hashSize, mInfo.blockSize); // We need to extend hmacSalt to multiple of block size, padding with 0x36 std::vector<sal_uInt8> extendedSalt(mInfo.hmacKey); @@ -643,7 +643,7 @@ bool AgileEngine::encryptHmacKey() std::vector<sal_uInt8> iv = calculateIV(eType, mInfo.keyDataSalt, constBlockHmac1, mInfo.blockSize); // Encrypt without key, calculated iv - Encrypt aEncryptor(mKey, iv, cryptoType(mInfo)); + comphelper::Encrypt aEncryptor(mKey, iv, cryptoType(mInfo)); aEncryptor.update(mInfo.hmacEncryptedKey, extendedSalt); return true; @@ -651,7 +651,7 @@ bool AgileEngine::encryptHmacKey() bool AgileEngine::encryptHmacValue() { - sal_Int32 nEncryptedValueSize = roundUp(mInfo.hashSize, mInfo.blockSize); + sal_Int32 nEncryptedValueSize = comphelper::roundUp(mInfo.hashSize, mInfo.blockSize); mInfo.hmacEncryptedValue.clear(); mInfo.hmacEncryptedValue.resize(nEncryptedValueSize, 0); @@ -672,7 +672,7 @@ bool AgileEngine::encryptHmacValue() std::vector<sal_uInt8> iv = calculateIV(eType, mInfo.keyDataSalt, constBlockHmac2, mInfo.blockSize); // Encrypt without key, calculated iv - Encrypt aEncryptor(mKey, iv, cryptoType(mInfo)); + comphelper::Encrypt aEncryptor(mKey, iv, cryptoType(mInfo)); aEncryptor.update(mInfo.hmacEncryptedValue, extendedHash); return true; @@ -726,7 +726,7 @@ void AgileEngine::setupEncryptionParameters(AgileEncryptionParameters const & rA mInfo.keyDataSalt.resize(mInfo.saltSize); mInfo.saltValue.resize(mInfo.saltSize); mInfo.encryptedVerifierHashInput.resize(mInfo.saltSize); - mInfo.encryptedVerifierHashValue.resize(roundUp(mInfo.hashSize, mInfo.blockSize), 0); + mInfo.encryptedVerifierHashValue.resize(comphelper::roundUp(mInfo.hashSize, mInfo.blockSize), 0); } bool AgileEngine::setupEncryptionKey(OUString const & rPassword) @@ -803,7 +803,7 @@ void AgileEngine::encrypt(const css::uno::Reference<css::io::XInputStream> & rx css::uno::Reference<css::io::XOutputStream> & rxOutputStream, sal_uInt32 nSize) { - CryptoHash aCryptoHash(mInfo.hmacKey, cryptoHashTypeFromString(mInfo.hashAlgorithm)); + comphelper::CryptoHash aCryptoHash(mInfo.hmacKey, cryptoHashTypeFromString(mInfo.hashAlgorithm)); BinaryXOutputStream aBinaryOutputStream(rxOutputStream, false); BinaryXInputStream aBinaryInputStream(rxInputStream, false); @@ -839,7 +839,7 @@ void AgileEngine::encrypt(const css::uno::Reference<css::io::XInputStream> & rx while ((inputLength = aBinaryInputStream.readMemory(inputBuffer.data(), inputBuffer.size())) > 0) { sal_uInt32 correctedInputLength = inputLength % mInfo.blockSize == 0 ? - inputLength : oox::crypto::roundUp(inputLength, sal_uInt32(mInfo.blockSize)); + inputLength : comphelper::roundUp(inputLength, sal_uInt32(mInfo.blockSize)); // Update Key auto p = saltWithBlockKey.begin() + saltSize; @@ -853,7 +853,7 @@ void AgileEngine::encrypt(const css::uno::Reference<css::io::XInputStream> & rx // Only if hash > keySize std::copy(hash.begin(), hash.begin() + keySize, iv.begin()); - Encrypt aEncryptor(mKey, iv, AgileEngine::cryptoType(mInfo)); + comphelper::Encrypt aEncryptor(mKey, iv, AgileEngine::cryptoType(mInfo)); outputLength = aEncryptor.update(outputBuffer, inputBuffer, correctedInputLength); aBinaryOutputStream.writeMemory(outputBuffer.data(), outputLength); aCryptoHash.update(outputBuffer, outputLength); diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx deleted file mode 100644 index 32aefab57fac..000000000000 --- a/oox/source/crypto/CryptTools.cxx +++ /dev/null @@ -1,533 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - */ - -#include <oox/crypto/CryptTools.hxx> -#include <com/sun/star/uno/RuntimeException.hpp> -#include <sal/types.h> - -#include <config_oox.h> - -#if USE_TLS_OPENSSL -#include <openssl/evp.h> -#include <openssl/sha.h> -#include <openssl/hmac.h> -#endif // USE_TLS_OPENSSL - -#if USE_TLS_NSS -#include <nss.h> -#include <nspr.h> -#include <pk11pub.h> -#endif // USE_TLS_NSS - -namespace oox::crypto { - -#if USE_TLS_OPENSSL - -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) - -static HMAC_CTX *HMAC_CTX_new(void) -{ - HMAC_CTX *pContext = new HMAC_CTX; - HMAC_CTX_init(pContext); - return pContext; -} - -static void HMAC_CTX_free(HMAC_CTX *pContext) -{ - HMAC_CTX_cleanup(pContext); - delete pContext; -} -#endif - -namespace -{ - struct cipher_delete - { - void operator()(EVP_CIPHER_CTX* p) { EVP_CIPHER_CTX_free(p); } - }; - - struct hmac_delete - { -SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_free' is deprecated - void operator()(HMAC_CTX* p) { HMAC_CTX_free(p); } -SAL_WNODEPRECATED_DECLARATIONS_POP - }; -} - -struct CryptoImpl -{ - std::unique_ptr<EVP_CIPHER_CTX, cipher_delete> mpContext; - std::unique_ptr<HMAC_CTX, hmac_delete> mpHmacContext; - - CryptoImpl() = default; - - void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType eType) - { - mpContext.reset(EVP_CIPHER_CTX_new()); - EVP_CIPHER_CTX_init(mpContext.get()); - - const EVP_CIPHER* cipher = getCipher(eType); - if (cipher == nullptr) - return; - - if (iv.empty()) - EVP_EncryptInit_ex(mpContext.get(), cipher, nullptr, key.data(), nullptr); - else - EVP_EncryptInit_ex(mpContext.get(), cipher, nullptr, key.data(), iv.data()); - EVP_CIPHER_CTX_set_padding(mpContext.get(), 0); - } - - void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType eType) - { - mpContext.reset(EVP_CIPHER_CTX_new()); - EVP_CIPHER_CTX_init(mpContext.get()); - - const EVP_CIPHER* pCipher = getCipher(eType); - if (pCipher == nullptr) - return; - - const size_t nMinKeySize = EVP_CIPHER_key_length(pCipher); - if (key.size() < nMinKeySize) - key.resize(nMinKeySize, 0); - - if (iv.empty()) - EVP_DecryptInit_ex(mpContext.get(), pCipher, nullptr, key.data(), nullptr); - else - { - const size_t nMinIVSize = EVP_CIPHER_iv_length(pCipher); - if (iv.size() < nMinIVSize) - iv.resize(nMinIVSize, 0); - - EVP_DecryptInit_ex(mpContext.get(), pCipher, nullptr, key.data(), iv.data()); - } - EVP_CIPHER_CTX_set_padding(mpContext.get(), 0); - } - - void setupCryptoHashContext(std::vector<sal_uInt8>& rKey, CryptoHashType eType) - { -SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_new' is deprecated - mpHmacContext.reset(HMAC_CTX_new()); -SAL_WNODEPRECATED_DECLARATIONS_POP - const EVP_MD* aEvpMd = nullptr; - switch (eType) - { - case CryptoHashType::SHA1: - aEvpMd = EVP_sha1(); break; - case CryptoHashType::SHA256: - aEvpMd = EVP_sha256(); break; - case CryptoHashType::SHA384: - aEvpMd = EVP_sha384(); break; - case CryptoHashType::SHA512: - aEvpMd = EVP_sha512(); break; - } -SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Init_ex' is deprecated - HMAC_Init_ex(mpHmacContext.get(), rKey.data(), rKey.size(), aEvpMd, nullptr); -SAL_WNODEPRECATED_DECLARATIONS_POP - } - - ~CryptoImpl() - { - if (mpContext) - EVP_CIPHER_CTX_cleanup(mpContext.get()); - } - - static const EVP_CIPHER* getCipher(Crypto::CryptoType type) - { - switch(type) - { - case Crypto::CryptoType::AES_128_ECB: - return EVP_aes_128_ecb(); - case Crypto::CryptoType::AES_128_CBC: - return EVP_aes_128_cbc(); - case Crypto::CryptoType::AES_256_CBC: - return EVP_aes_256_cbc(); - default: - break; - } - return nullptr; - } -}; - -#elif USE_TLS_NSS - -#define MAX_WRAPPED_KEY_LEN 128 - -struct CryptoImpl -{ - PK11SlotInfo* mSlot; - PK11Context* mContext; - SECItem* mSecParam; - PK11SymKey* mSymKey; - PK11Context* mWrapKeyContext; - PK11SymKey* mWrapKey; - - CryptoImpl() - : mSlot(nullptr) - , mContext(nullptr) - , mSecParam(nullptr) - , mSymKey(nullptr) - , mWrapKeyContext(nullptr) - , mWrapKey(nullptr) - { - // Initialize NSS, database functions are not needed - if (!NSS_IsInitialized()) - { - auto const e = NSS_NoDB_Init(nullptr); - if (e != SECSuccess) - { - PRErrorCode error = PR_GetError(); - const char* errorText = PR_ErrorToName(error); - throw css::uno::RuntimeException("NSS_NoDB_Init failed with " + OUString(errorText, strlen(errorText), RTL_TEXTENCODING_UTF8) + " (" + OUString::number(static_cast<int>(error)) + ")"); - } - } - } - - ~CryptoImpl() - { - if (mContext) - PK11_DestroyContext(mContext, PR_TRUE); - if (mSecParam) - SECITEM_FreeItem(mSecParam, PR_TRUE); - if (mSymKey) - PK11_FreeSymKey(mSymKey); - if (mWrapKeyContext) - PK11_DestroyContext(mWrapKeyContext, PR_TRUE); - if (mWrapKey) - PK11_FreeSymKey(mWrapKey); - if (mSlot) - PK11_FreeSlot(mSlot); - } - - PK11SymKey* ImportSymKey(CK_MECHANISM_TYPE mechanism, CK_ATTRIBUTE_TYPE operation, SECItem* key) - { - mSymKey = PK11_ImportSymKey(mSlot, mechanism, PK11_OriginUnwrap, operation, key, nullptr); - if (!mSymKey) //rhbz#1614419 maybe failed due to FIPS, use rhbz#1461450 style workaround - { - /* - * Without FIPS it would be possible to just use - * mSymKey = PK11_ImportSymKey( mSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr ); - * with FIPS NSS Level 2 certification has to be "workarounded" (so it becomes Level 1) by using - * following method: - * 1. Generate wrap key - * 2. Encrypt authkey with wrap key - * 3. Unwrap encrypted authkey using wrap key - */ - - /* - * Generate wrapping key - */ - CK_MECHANISM_TYPE wrap_mechanism = PK11_GetBestWrapMechanism(mSlot); - int wrap_key_len = PK11_GetBestKeyLength(mSlot, wrap_mechanism); - mWrapKey = PK11_KeyGen(mSlot, wrap_mechanism, nullptr, wrap_key_len, nullptr); - if (!mWrapKey) - throw css::uno::RuntimeException(u"PK11_KeyGen SymKey failure"_ustr, css::uno::Reference<css::uno::XInterface>()); - - /* - * Encrypt authkey with wrapping key - */ - - /* - * Initialization of IV is not needed because PK11_GetBestWrapMechanism should return ECB mode - */ - SECItem tmp_sec_item = {}; - mWrapKeyContext = PK11_CreateContextBySymKey(wrap_mechanism, CKA_ENCRYPT, mWrapKey, &tmp_sec_item); - if (!mWrapKeyContext) - throw css::uno::RuntimeException(u"PK11_CreateContextBySymKey failure"_ustr, css::uno::Reference<css::uno::XInterface>()); - - unsigned char wrapped_key_data[MAX_WRAPPED_KEY_LEN]; - int wrapped_key_len = sizeof(wrapped_key_data); - - if (PK11_CipherOp(mWrapKeyContext, wrapped_key_data, &wrapped_key_len, - sizeof(wrapped_key_data), key->data, key->len) != SECSuccess) - { - throw css::uno::RuntimeException(u"PK11_CipherOp failure"_ustr, css::uno::Reference<css::uno::XInterface>()); - } - - if (PK11_Finalize(mWrapKeyContext) != SECSuccess) - throw css::uno::RuntimeException(u"PK11_Finalize failure"_ustr, css::uno::Reference<css::uno::XInterface>()); - - /* - * Finally unwrap sym key - */ - SECItem wrapped_key = {}; - wrapped_key.data = wrapped_key_data; - wrapped_key.len = wrapped_key_len; - - mSymKey = PK11_UnwrapSymKey(mWrapKey, wrap_mechanism, &tmp_sec_item, &wrapped_key, - mechanism, operation, key->len); - } - return mSymKey; - } - - void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType type) - { - setupCryptoContext(key, iv, type, CKA_ENCRYPT); - } - - void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType type) - { - setupCryptoContext(key, iv, type, CKA_DECRYPT); - } - - void setupCryptoContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType type, CK_ATTRIBUTE_TYPE operation) - { - CK_MECHANISM_TYPE mechanism = static_cast<CK_ULONG>(-1); - - SECItem ivItem; - ivItem.type = siBuffer; - if(iv.empty()) - ivItem.data = nullptr; - else - ivItem.data = iv.data(); - ivItem.len = iv.size(); - - SECItem* pIvItem = nullptr; - - switch(type) - { - case Crypto::CryptoType::AES_128_ECB: - mechanism = CKM_AES_ECB; - break; - case Crypto::CryptoType::AES_128_CBC: - case Crypto::CryptoType::AES_256_CBC: - mechanism = CKM_AES_CBC; - pIvItem = &ivItem; - break; - default: - break; - } - - mSlot = PK11_GetBestSlot(mechanism, nullptr); - - if (!mSlot) - throw css::uno::RuntimeException(u"NSS Slot failure"_ustr, css::uno::Reference<css::uno::XInterface>()); - - SECItem keyItem; - keyItem.type = siBuffer; - keyItem.data = key.data(); - keyItem.len = key.size(); - - mSymKey = ImportSymKey(mechanism, CKA_ENCRYPT, &keyItem); - if (!mSymKey) - throw css::uno::RuntimeException(u"NSS SymKey failure"_ustr, css::uno::Reference<css::uno::XInterface>()); - - mSecParam = PK11_ParamFromIV(mechanism, pIvItem); - mContext = PK11_CreateContextBySymKey(mechanism, operation, mSymKey, mSecParam); - } - - void setupCryptoHashContext(std::vector<sal_uInt8>& rKey, CryptoHashType eType) - { - CK_MECHANISM_TYPE aMechanism = static_cast<CK_ULONG>(-1); - - switch(eType) - { - case CryptoHashType::SHA1: - aMechanism = CKM_SHA_1_HMAC; - break; - case CryptoHashType::SHA256: - aMechanism = CKM_SHA256_HMAC; - break; - case CryptoHashType::SHA384: - aMechanism = CKM_SHA384_HMAC; - break; - case CryptoHashType::SHA512: - aMechanism = CKM_SHA512_HMAC; - break; - } - - mSlot = PK11_GetBestSlot(aMechanism, nullptr); - - if (!mSlot) - throw css::uno::RuntimeException(u"NSS Slot failure"_ustr, css::uno::Reference<css::uno::XInterface>()); - - SECItem aKeyItem; - aKeyItem.data = rKey.data(); - aKeyItem.len = rKey.size(); - - mSymKey = ImportSymKey(aMechanism, CKA_SIGN, &aKeyItem); - if (!mSymKey) - throw css::uno::RuntimeException(u"NSS SymKey failure"_ustr, css::uno::Reference<css::uno::XInterface>()); - - SECItem param; - param.data = nullptr; - param.len = 0; - mContext = PK11_CreateContextBySymKey(aMechanism, CKA_SIGN, mSymKey, ¶m); - } -}; -#else -struct CryptoImpl -{}; -#endif - -Crypto::Crypto() - : mpImpl(std::make_unique<CryptoImpl>()) -{ -} - -Crypto::~Crypto() -{ -} - -// DECRYPT - -Decrypt::Decrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type) -{ -#if USE_TLS_OPENSSL + USE_TLS_NSS == 0 - (void)key; - (void)iv; - (void)type; -#else - mpImpl->setupDecryptContext(key, iv, type); -#endif -} - -sal_uInt32 Decrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, sal_uInt32 inputLength) -{ - int outputLength = 0; - -#if USE_TLS_OPENSSL + USE_TLS_NSS > 0 - sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength; -#else - (void)output; - (void)input; - (void)inputLength; -#endif - -#if USE_TLS_OPENSSL - (void)EVP_DecryptUpdate(mpImpl->mpContext.get(), output.data(), &outputLength, input.data(), actualInputLength); -#endif // USE_TLS_OPENSSL - -#if USE_TLS_NSS - if (!mpImpl->mContext) - return 0; - (void)PK11_CipherOp(mpImpl->mContext, output.data(), &outputLength, actualInputLength, input.data(), actualInputLength); -#endif // USE_TLS_NSS - - return static_cast<sal_uInt32>(outputLength); -} - -sal_uInt32 Decrypt::aes128ecb(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, std::vector<sal_uInt8>& key) -{ - sal_uInt32 outputLength = 0; - std::vector<sal_uInt8> iv; - Decrypt crypto(key, iv, Crypto::AES_128_ECB); - outputLength = crypto.update(output, input); - return outputLength; -} - -// ENCRYPT - -Encrypt::Encrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type) -{ -#if USE_TLS_OPENSSL + USE_TLS_NSS == 0 - (void)key; - (void)iv; - (void)type; -#else - mpImpl->setupEncryptContext(key, iv, type); -#endif -} - -sal_uInt32 Encrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, sal_uInt32 inputLength) -{ - int outputLength = 0; - -#if USE_TLS_OPENSSL + USE_TLS_NSS > 0 - sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength; -#else - (void)output; - (void)input; - (void)inputLength; -#endif - -#if USE_TLS_OPENSSL - (void)EVP_EncryptUpdate(mpImpl->mpContext.get(), output.data(), &outputLength, input.data(), actualInputLength); -#endif // USE_TLS_OPENSSL - -#if USE_TLS_NSS - (void)PK11_CipherOp(mpImpl->mContext, output.data(), &outputLength, actualInputLength, input.data(), actualInputLength); -#endif // USE_TLS_NSS - - return static_cast<sal_uInt32>(outputLength); -} - -// CryptoHash - HMAC - -namespace -{ - -sal_Int32 getSizeForHashType(CryptoHashType eType) -{ - switch (eType) - { - case CryptoHashType::SHA1: return 20; - case CryptoHashType::SHA256: return 32; - case CryptoHashType::SHA384: return 48; - case CryptoHashType::SHA512: return 64; - } - return 0; -} - -} // end anonymous namespace - -CryptoHash::CryptoHash(std::vector<sal_uInt8>& rKey, CryptoHashType eType) - : mnHashSize(getSizeForHashType(eType)) -{ -#if USE_TLS_OPENSSL + USE_TLS_NSS > 0 - mpImpl->setupCryptoHashContext(rKey, eType); - -#if USE_TLS_NSS - PK11_DigestBegin(mpImpl->mContext); -#endif - -#else - (void)rKey; -#endif -} - -bool CryptoHash::update(std::vector<sal_uInt8>& rInput, sal_uInt32 nInputLength) -{ -#if USE_TLS_OPENSSL + USE_TLS_NSS > 0 - sal_uInt32 nActualInputLength = (nInputLength == 0 || nInputLength > rInput.size()) ? rInput.size() : nInputLength; -#else - (void)rInput; - (void)nInputLength; -#endif - -#if USE_TLS_OPENSSL -SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Update' is deprecated - return HMAC_Update(mpImpl->mpHmacContext.get(), rInput.data(), nActualInputLength) != 0; -SAL_WNODEPRECATED_DECLARATIONS_POP -#elif USE_TLS_NSS - return PK11_DigestOp(mpImpl->mContext, rInput.data(), nActualInputLength) == SECSuccess; -#else - return false; // ??? -#endif -} - -std::vector<sal_uInt8> CryptoHash::finalize() -{ - std::vector<sal_uInt8> aHash(mnHashSize, 0); - unsigned int nSizeWritten; -#if USE_TLS_OPENSSL -SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Final' is deprecated - (void) HMAC_Final(mpImpl->mpHmacContext.get(), aHash.data(), &nSizeWritten); -SAL_WNODEPRECATED_DECLARATIONS_POP -#elif USE_TLS_NSS - PK11_DigestFinal(mpImpl->mContext, aHash.data(), &nSizeWritten, aHash.size()); -#endif - (void)nSizeWritten; - - return aHash; -} - -} // namespace oox::crypto - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx index 792c6c27cc7a..a9fb8d3c2339 100644 --- a/oox/source/crypto/Standard2007Engine.cxx +++ b/oox/source/crypto/Standard2007Engine.cxx @@ -10,11 +10,11 @@ #include <oox/crypto/Standard2007Engine.hxx> -#include <oox/crypto/CryptTools.hxx> #include <oox/helper/binaryinputstream.hxx> #include <oox/helper/binaryoutputstream.hxx> #include <rtl/random.h> +#include <comphelper/crypto/Crypto.hxx> #include <comphelper/hash.hxx> namespace oox::crypto { @@ -50,7 +50,7 @@ bool Standard2007Engine::generateVerifier() lclRandomGenerateValues(verifier.data(), verifier.size()); std::vector<sal_uInt8> iv; - Encrypt aEncryptorVerifier(mKey, iv, Crypto::AES_128_ECB); + comphelper::Encrypt aEncryptorVerifier(mKey, iv, comphelper::CryptoType::AES_128_ECB); if (aEncryptorVerifier.update(encryptedVerifier, verifier) != msfilter::ENCRYPTED_VERIFIER_LENGTH) return false; std::copy(encryptedVerifier.begin(), encryptedVerifier.end(), mInfo.verifier.encryptedVerifier); @@ -61,7 +61,7 @@ bool Standard2007Engine::generateVerifier() std::vector<sal_uInt8> encryptedHash(comphelper::SHA256_HASH_LENGTH, 0); - Encrypt aEncryptorHash(mKey, iv, Crypto::AES_128_ECB); + comphelper::Encrypt aEncryptorHash(mKey, iv, comphelper::CryptoType::AES_128_ECB); aEncryptorHash.update(encryptedHash, hash, hash.size()); std::copy(encryptedHash.begin(), encryptedHash.end(), mInfo.verifier.encryptedVerifierHash); @@ -148,10 +148,10 @@ bool Standard2007Engine::generateEncryptionKey(const OUString& password) encryptedHash.begin()); std::vector<sal_uInt8> verifier(encryptedVerifier.size(), 0); - Decrypt::aes128ecb(verifier, encryptedVerifier, mKey); + comphelper::Decrypt::aes128ecb(verifier, encryptedVerifier, mKey); std::vector<sal_uInt8> verifierHash(encryptedHash.size(), 0); - Decrypt::aes128ecb(verifierHash, encryptedHash, mKey); + comphelper::Decrypt::aes128ecb(verifierHash, encryptedHash, mKey); std::vector<sal_uInt8> hash = comphelper::Hash::calculateHash(verifier.data(), verifier.size(), comphelper::HashType::SHA1); @@ -165,7 +165,7 @@ bool Standard2007Engine::decrypt(BinaryXInputStream& aInputStream, aInputStream.skip(4); // Reserved 4 Bytes std::vector<sal_uInt8> iv; - Decrypt aDecryptor(mKey, iv, Crypto::AES_128_ECB); + comphelper::Decrypt aDecryptor(mKey, iv, comphelper::CryptoType::AES_128_ECB); std::vector<sal_uInt8> inputBuffer (4096); std::vector<sal_uInt8> outputBuffer(4096); sal_uInt32 inputLength; @@ -261,13 +261,13 @@ void Standard2007Engine::encrypt(const css::uno::Reference<css::io::XInputStream sal_uInt32 outputLength; std::vector<sal_uInt8> iv; - Encrypt aEncryptor(mKey, iv, Crypto::AES_128_ECB); + comphelper::Encrypt aEncryptor(mKey, iv, comphelper::CryptoType::AES_128_ECB); while ((inputLength = aBinaryInputStream.readMemory(inputBuffer.data(), inputBuffer.size())) > 0) { // increase size to multiple of 16 (size of mKey) if necessary inputLength = inputLength % AES128Size == 0 ? - inputLength : roundUp(inputLength, AES128Size); + inputLength : comphelper::roundUp(inputLength, AES128Size); outputLength = aEncryptor.update(outputBuffer, inputBuffer, inputLength); aBinaryOutputStream.writeMemory(outputBuffer.data(), outputLength); } |