comphelper/CppunitTest_comphelper_test.mk | 1 comphelper/Library_comphelper.mk | 1 comphelper/qa/unit/CryptoTest.cxx | 100 ++++++++++++++ comphelper/source/crypto/Crypto.cxx | 213 +++++++++++++++++------------- include/comphelper/crypto/Crypto.hxx | 99 +++++++++++++ include/oox/crypto/AgileEngine.hxx | 11 - include/oox/crypto/CryptTools.hxx | 121 ----------------- oox/Library_oox.mk | 1 oox/qa/unit/CryptoTest.cxx | 60 -------- oox/source/crypto/AgileEngine.cxx | 50 +++---- oox/source/crypto/Standard2007Engine.cxx | 16 +- solenv/clang-format/excludelist | 2 vcl/source/gdi/pdfwriter_impl.cxx | 92 +++++++----- 13 files changed, 418 insertions(+), 349 deletions(-)
New commits: commit c8cba8ae30baef6feca3b0613366d28df4a5e568 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri Nov 1 12:48:10 2024 +0100 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Mon Nov 4 21:51:32 2024 +0100 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 <qui...@gmail.com> diff --git a/comphelper/CppunitTest_comphelper_test.mk b/comphelper/CppunitTest_comphelper_test.mk index 17de701aca26..3fe7c53f746e 100644 --- a/comphelper/CppunitTest_comphelper_test.mk +++ b/comphelper/CppunitTest_comphelper_test.mk @@ -20,6 +20,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,comphelper_test, \ comphelper/qa/unit/types_test \ comphelper/qa/unit/test_guards \ comphelper/qa/unit/test_traceevent \ + comphelper/qa/unit/CryptoTest \ )) $(eval $(call gb_CppunitTest_use_ure,comphelper_test)) diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk index 2ab1b1bfa5d7..159aaa65248d 100644 --- a/comphelper/Library_comphelper.mk +++ b/comphelper/Library_comphelper.mk @@ -75,6 +75,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/container/enumerablemap \ comphelper/source/container/enumhelper \ comphelper/source/container/namecontainer \ + comphelper/source/crypto/Crypto \ comphelper/source/eventattachermgr/eventattachermgr \ comphelper/source/misc/accessiblecomponenthelper \ comphelper/source/misc/accessibleeventnotifier \ diff --git a/comphelper/qa/unit/CryptoTest.cxx b/comphelper/qa/unit/CryptoTest.cxx new file mode 100644 index 000000000000..2b0dac47416f --- /dev/null +++ b/comphelper/qa/unit/CryptoTest.cxx @@ -0,0 +1,100 @@ +/* -*- 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 <sal/config.h> +#include <config_oox.h> +#include <comphelper/crypto/Crypto.hxx> +#include <comphelper/hash.hxx> + +#include <rtl/ustring.hxx> + +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +#if USE_TLS_NSS +#include <nss.h> +#endif + +class CryptoTest : public CppUnit::TestFixture +{ +public: + virtual void tearDown() + { +#if USE_TLS_NSS + NSS_Shutdown(); +#endif + } + + void testCryptoHash(); + void testRoundUp(); + + CPPUNIT_TEST_SUITE(CryptoTest); + CPPUNIT_TEST(testCryptoHash); + CPPUNIT_TEST(testRoundUp); + CPPUNIT_TEST_SUITE_END(); +}; + +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' }; + { + comphelper::CryptoHash aCryptoHash(aKey, comphelper::CryptoHashType::SHA1); + aCryptoHash.update(aContent); + std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL(std::string("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"), + comphelper::hashToString(aHash)); + } + + { + comphelper::CryptoHash aCryptoHash(aKey, comphelper::CryptoHashType::SHA256); + aCryptoHash.update(aContent); + std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL( + std::string("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8"), + comphelper::hashToString(aHash)); + } + + { + comphelper::CryptoHash aCryptoHash(aKey, comphelper::CryptoHashType::SHA384); + aCryptoHash.update(aContent); + std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL(std::string("d7f4727e2c0b39ae0f1e40cc96f60242d5b7801841cea6fc592c5d3e1" + "ae50700582a96cf35e1e554995fe4e03381c237"), + comphelper::hashToString(aHash)); + } + + { + comphelper::CryptoHash aCryptoHash(aKey, comphelper::CryptoHashType::SHA512); + aCryptoHash.update(aContent); + std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); + CPPUNIT_ASSERT_EQUAL( + std::string("b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549" + "f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3a"), + comphelper::hashToString(aHash)); + } +} + +void CryptoTest::testRoundUp() +{ + CPPUNIT_ASSERT_EQUAL(16, comphelper::roundUp(16, 16)); + CPPUNIT_ASSERT_EQUAL(32, comphelper::roundUp(32, 16)); + CPPUNIT_ASSERT_EQUAL(64, comphelper::roundUp(64, 16)); + + CPPUNIT_ASSERT_EQUAL(16, comphelper::roundUp(01, 16)); + CPPUNIT_ASSERT_EQUAL(32, comphelper::roundUp(17, 16)); + CPPUNIT_ASSERT_EQUAL(32, comphelper::roundUp(31, 16)); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(CryptoTest); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/crypto/CryptTools.cxx b/comphelper/source/crypto/Crypto.cxx similarity index 70% rename from oox/source/crypto/CryptTools.cxx rename to comphelper/source/crypto/Crypto.cxx index 32aefab57fac..a9f8b63a635d 100644 --- a/oox/source/crypto/CryptTools.cxx +++ b/comphelper/source/crypto/Crypto.cxx @@ -8,7 +8,7 @@ * */ -#include <oox/crypto/CryptTools.hxx> +#include <comphelper/crypto/Crypto.hxx> #include <com/sun/star/uno/RuntimeException.hpp> #include <sal/types.h> @@ -26,20 +26,20 @@ #include <pk11pub.h> #endif // USE_TLS_NSS -namespace oox::crypto { - +namespace comphelper +{ #if USE_TLS_OPENSSL #if (OPENSSL_VERSION_NUMBER < 0x10100000L) -static HMAC_CTX *HMAC_CTX_new(void) +static HMAC_CTX* HMAC_CTX_new(void) { - HMAC_CTX *pContext = new HMAC_CTX; - HMAC_CTX_init(pContext); - return pContext; + HMAC_CTX* pContext = new HMAC_CTX; + HMAC_CTX_init(pContext); + return pContext; } -static void HMAC_CTX_free(HMAC_CTX *pContext) +static void HMAC_CTX_free(HMAC_CTX* pContext) { HMAC_CTX_cleanup(pContext); delete pContext; @@ -48,17 +48,21 @@ static void HMAC_CTX_free(HMAC_CTX *pContext) namespace { - struct cipher_delete - { - void operator()(EVP_CIPHER_CTX* p) { EVP_CIPHER_CTX_free(p); } - }; +struct cipher_delete +{ + void operator()(EVP_CIPHER_CTX* p) { EVP_CIPHER_CTX_free(p); } +}; - struct hmac_delete +struct hmac_delete +{ + SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_free' is deprecated + void + operator()(HMAC_CTX* p) { -SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_free' is deprecated - void operator()(HMAC_CTX* p) { HMAC_CTX_free(p); } -SAL_WNODEPRECATED_DECLARATIONS_POP - }; + HMAC_CTX_free(p); + } + SAL_WNODEPRECATED_DECLARATIONS_POP +}; } struct CryptoImpl @@ -68,7 +72,8 @@ struct CryptoImpl CryptoImpl() = default; - void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType eType) + 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()); @@ -84,7 +89,8 @@ struct CryptoImpl EVP_CIPHER_CTX_set_padding(mpContext.get(), 0); } - void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType eType) + 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()); @@ -112,24 +118,28 @@ struct CryptoImpl 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 + 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; + aEvpMd = EVP_sha1(); + break; case CryptoHashType::SHA256: - aEvpMd = EVP_sha256(); break; + aEvpMd = EVP_sha256(); + break; case CryptoHashType::SHA384: - aEvpMd = EVP_sha384(); break; + aEvpMd = EVP_sha384(); + break; case CryptoHashType::SHA512: - aEvpMd = EVP_sha512(); break; + 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 + 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() @@ -140,7 +150,7 @@ SAL_WNODEPRECATED_DECLARATIONS_POP static const EVP_CIPHER* getCipher(Crypto::CryptoType type) { - switch(type) + switch (type) { case Crypto::CryptoType::AES_128_ECB: return EVP_aes_128_ecb(); @@ -163,10 +173,10 @@ struct CryptoImpl { PK11SlotInfo* mSlot; PK11Context* mContext; - SECItem* mSecParam; - PK11SymKey* mSymKey; + SECItem* mSecParam; + PK11SymKey* mSymKey; PK11Context* mWrapKeyContext; - PK11SymKey* mWrapKey; + PK11SymKey* mWrapKey; CryptoImpl() : mSlot(nullptr) @@ -184,7 +194,10 @@ struct CryptoImpl { 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)) + ")"); + throw css::uno::RuntimeException( + "NSS_NoDB_Init failed with " + + OUString(errorText, strlen(errorText), RTL_TEXTENCODING_UTF8) + " (" + + OUString::number(static_cast<int>(error)) + ")"); } } } @@ -227,7 +240,8 @@ struct CryptoImpl 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>()); + throw css::uno::RuntimeException(u"PK11_KeyGen SymKey failure"_ustr, + css::uno::Reference<css::uno::XInterface>()); /* * Encrypt authkey with wrapping key @@ -237,21 +251,26 @@ struct CryptoImpl * 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); + 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>()); + 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) + sizeof(wrapped_key_data), key->data, key->len) + != SECSuccess) { - throw css::uno::RuntimeException(u"PK11_CipherOp failure"_ustr, css::uno::Reference<css::uno::XInterface>()); + 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>()); + throw css::uno::RuntimeException(u"PK11_Finalize failure"_ustr, + css::uno::Reference<css::uno::XInterface>()); /* * Finally unwrap sym key @@ -261,28 +280,31 @@ struct CryptoImpl wrapped_key.len = wrapped_key_len; mSymKey = PK11_UnwrapSymKey(mWrapKey, wrap_mechanism, &tmp_sec_item, &wrapped_key, - mechanism, operation, key->len); + mechanism, operation, key->len); } return mSymKey; } - void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType type) + void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, + CryptoType type) { setupCryptoContext(key, iv, type, CKA_ENCRYPT); } - void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto::CryptoType type) + void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, + 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) + void setupCryptoContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, + CryptoType type, CK_ATTRIBUTE_TYPE operation) { CK_MECHANISM_TYPE mechanism = static_cast<CK_ULONG>(-1); SECItem ivItem; ivItem.type = siBuffer; - if(iv.empty()) + if (iv.empty()) ivItem.data = nullptr; else ivItem.data = iv.data(); @@ -290,13 +312,16 @@ struct CryptoImpl SECItem* pIvItem = nullptr; - switch(type) + switch (type) { - case Crypto::CryptoType::AES_128_ECB: + case CryptoType::AES_128_ECB: mechanism = CKM_AES_ECB; break; - case Crypto::CryptoType::AES_128_CBC: - case Crypto::CryptoType::AES_256_CBC: + case CryptoType::AES_128_CBC: + mechanism = CKM_AES_CBC; + pIvItem = &ivItem; + break; + case CryptoType::AES_256_CBC: mechanism = CKM_AES_CBC; pIvItem = &ivItem; break; @@ -307,16 +332,18 @@ struct CryptoImpl mSlot = PK11_GetBestSlot(mechanism, nullptr); if (!mSlot) - throw css::uno::RuntimeException(u"NSS Slot failure"_ustr, css::uno::Reference<css::uno::XInterface>()); + 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(); + 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>()); + 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); @@ -326,7 +353,7 @@ struct CryptoImpl { CK_MECHANISM_TYPE aMechanism = static_cast<CK_ULONG>(-1); - switch(eType) + switch (eType) { case CryptoHashType::SHA1: aMechanism = CKM_SHA_1_HMAC; @@ -345,15 +372,17 @@ struct CryptoImpl mSlot = PK11_GetBestSlot(aMechanism, nullptr); if (!mSlot) - throw css::uno::RuntimeException(u"NSS Slot failure"_ustr, css::uno::Reference<css::uno::XInterface>()); + 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(); + 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>()); + throw css::uno::RuntimeException(u"NSS SymKey failure"_ustr, + css::uno::Reference<css::uno::XInterface>()); SECItem param; param.data = nullptr; @@ -363,7 +392,8 @@ struct CryptoImpl }; #else struct CryptoImpl -{}; +{ +}; #endif Crypto::Crypto() @@ -371,9 +401,7 @@ Crypto::Crypto() { } -Crypto::~Crypto() -{ -} +Crypto::~Crypto() {} // DECRYPT @@ -388,12 +416,14 @@ Decrypt::Decrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto #endif } -sal_uInt32 Decrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, sal_uInt32 inputLength) +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; + sal_uInt32 actualInputLength + = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength; #else (void)output; (void)input; @@ -401,23 +431,26 @@ sal_uInt32 Decrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8 #endif #if USE_TLS_OPENSSL - (void)EVP_DecryptUpdate(mpImpl->mpContext.get(), output.data(), &outputLength, input.data(), actualInputLength); + (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); + (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 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); + Decrypt crypto(key, iv, CryptoType::AES_128_ECB); outputLength = crypto.update(output, input); return outputLength; } @@ -435,12 +468,14 @@ Encrypt::Encrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, Crypto #endif } -sal_uInt32 Encrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, sal_uInt32 inputLength) +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; + sal_uInt32 actualInputLength + = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength; #else (void)output; (void)input; @@ -448,11 +483,13 @@ sal_uInt32 Encrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8 #endif #if USE_TLS_OPENSSL - (void)EVP_EncryptUpdate(mpImpl->mpContext.get(), output.data(), &outputLength, input.data(), actualInputLength); + (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); + (void)PK11_CipherOp(mpImpl->mContext, output.data(), &outputLength, actualInputLength, + input.data(), actualInputLength); #endif // USE_TLS_NSS return static_cast<sal_uInt32>(outputLength); @@ -462,15 +499,18 @@ sal_uInt32 Encrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8 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; + case CryptoHashType::SHA1: + return 20; + case CryptoHashType::SHA256: + return 32; + case CryptoHashType::SHA384: + return 48; + case CryptoHashType::SHA512: + return 64; } return 0; } @@ -495,16 +535,18 @@ CryptoHash::CryptoHash(std::vector<sal_uInt8>& rKey, CryptoHashType eType) 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; + 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 + 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 @@ -515,19 +557,18 @@ SAL_WNODEPRECATED_DECLARATIONS_POP 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 + unsigned int nSizeWritten = 0; + 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 + unsigned int nSizeWritten = 0; PK11_DigestFinal(mpImpl->mContext, aHash.data(), &nSizeWritten, aHash.size()); #endif - (void)nSizeWritten; - return aHash; } -} // namespace oox::crypto +} // namespace comphelper /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/crypto/Crypto.hxx b/include/comphelper/crypto/Crypto.hxx new file mode 100644 index 000000000000..aba89642652a --- /dev/null +++ b/include/comphelper/crypto/Crypto.hxx @@ -0,0 +1,99 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <comphelper/comphelperdllapi.h> +#include <sal/types.h> + +#include <vector> +#include <memory> + +namespace comphelper +{ +/** Rounds up the input to the nearest multiple + * + * For example: + * input 1, multiple 16 = 16 + * input 16, multiple 16 = 16 + * input 17, multiple 16 = 32 + * input 31, multiple 16 = 32 + */ +template <typename T> T roundUp(T input, T multiple) +{ + if (input % multiple == 0) + return input; + return ((input / multiple) * multiple) + multiple; +} + +enum class CryptoHashType +{ + SHA1, + SHA256, + SHA384, + SHA512 +}; + +enum class CryptoType +{ + UNKNOWN, + AES_128_ECB, + AES_128_CBC, + AES_256_CBC, +}; + +struct CryptoImpl; + +class COMPHELPER_DLLPUBLIC Crypto +{ +protected: + std::unique_ptr<CryptoImpl> mpImpl; + +protected: + Crypto(); + +public: + virtual ~Crypto(); +}; + +class COMPHELPER_DLLPUBLIC Decrypt final : public Crypto +{ +public: + Decrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type); + + sal_uInt32 update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, + sal_uInt32 inputLength = 0); + + static sal_uInt32 aes128ecb(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, + std::vector<sal_uInt8>& key); +}; + +class COMPHELPER_DLLPUBLIC Encrypt final : public Crypto +{ +public: + Encrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type); + + sal_uInt32 update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, + sal_uInt32 inputLength = 0); +}; + +class COMPHELPER_DLLPUBLIC CryptoHash final : public Crypto +{ + sal_Int32 mnHashSize; + +public: + CryptoHash(std::vector<sal_uInt8>& rKey, CryptoHashType eType); + bool update(std::vector<sal_uInt8>& rInput, sal_uInt32 nInputLength = 0); + std::vector<sal_uInt8> finalize(); +}; + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/oox/crypto/AgileEngine.hxx b/include/oox/crypto/AgileEngine.hxx index 07ce3cb5eeb1..bccb30eaef3e 100644 --- a/include/oox/crypto/AgileEngine.hxx +++ b/include/oox/crypto/AgileEngine.hxx @@ -8,16 +8,15 @@ * */ -#ifndef INCLUDED_OOX_CRYPTO_AGILEENGINE_HXX -#define INCLUDED_OOX_CRYPTO_AGILEENGINE_HXX +#pragma once #include <vector> #include <oox/dllapi.h> -#include <oox/crypto/CryptTools.hxx> #include <oox/crypto/CryptoEngine.hxx> #include <rtl/ustring.hxx> #include <sal/types.h> +#include <comphelper/crypto/Crypto.hxx> namespace oox { class BinaryXInputStream; @@ -94,7 +93,7 @@ private: std::vector<sal_uInt8>& rInput, std::vector<sal_uInt8>& rOutput); - static Crypto::CryptoType cryptoType(const AgileEncryptionInfo& rInfo); + static comphelper::CryptoType cryptoType(const AgileEncryptionInfo& rInfo); public: AgileEngine(); @@ -141,8 +140,6 @@ public: bool setupEncryptionKey(OUString const & rPassword); }; -} // namespace oox::crypto - -#endif +} // namespace comphelper::crypto /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/oox/crypto/CryptTools.hxx b/include/oox/crypto/CryptTools.hxx deleted file mode 100644 index 10382b979380..000000000000 --- a/include/oox/crypto/CryptTools.hxx +++ /dev/null @@ -1,121 +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/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_OOX_CRYPTO_CRYPTTOOLS_HXX -#define INCLUDED_OOX_CRYPTO_CRYPTTOOLS_HXX - -#include <oox/dllapi.h> -#include <sal/types.h> - -#include <vector> -#include <memory> - -namespace oox::crypto { - -/** Rounds up the input to the nearest multiple - * - * For example: - * input 1, multiple 16 = 16 - * input 16, multiple 16 = 16 - * input 17, multiple 16 = 32 - * input 31, multiple 16 = 32 - */ -template<typename T> -T roundUp(T input, T multiple) -{ - if (input % multiple == 0) - return input; - return ((input / multiple) * multiple) + multiple; -} - -enum class CryptoHashType -{ - SHA1, - SHA256, - SHA384, - SHA512 -}; - -struct CryptoImpl; - -class OOX_DLLPUBLIC Crypto -{ -public: - enum CryptoType - { - UNKNOWN, - AES_128_ECB, - AES_128_CBC, - AES_256_CBC, - }; - -protected: - std::unique_ptr<CryptoImpl> mpImpl; - -protected: - Crypto(); - -public: - virtual ~Crypto(); -}; - -class Decrypt final : public Crypto -{ -public: - Decrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type); - - sal_uInt32 update( - std::vector<sal_uInt8>& output, - std::vector<sal_uInt8>& input, - sal_uInt32 inputLength = 0); - - - static sal_uInt32 aes128ecb( - std::vector<sal_uInt8>& output, - std::vector<sal_uInt8>& input, - std::vector<sal_uInt8>& key ); - -}; - -class Encrypt final : public Crypto -{ -public: - Encrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type); - - sal_uInt32 update( - std::vector<sal_uInt8>& output, - std::vector<sal_uInt8>& input, - sal_uInt32 inputLength = 0); -}; - -class OOX_DLLPUBLIC CryptoHash final : public Crypto -{ - sal_Int32 mnHashSize; -public: - CryptoHash(std::vector<sal_uInt8>& rKey, CryptoHashType eType); - bool update(std::vector<sal_uInt8>& rInput, sal_uInt32 nInputLength = 0); - std::vector<sal_uInt8> finalize(); -}; - - -} // namespace oox::crypto - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 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/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); } diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist index f5414f105fe0..e521a5ccb359 100644 --- a/solenv/clang-format/excludelist +++ b/solenv/clang-format/excludelist @@ -5316,7 +5316,6 @@ include/oox/core/relations.hxx include/oox/core/relationshandler.hxx include/oox/core/xmlfilterbase.hxx include/oox/crypto/AgileEngine.hxx -include/oox/crypto/CryptTools.hxx include/oox/crypto/CryptoEngine.hxx include/oox/crypto/DocumentDecryption.hxx include/oox/crypto/DocumentEncryption.hxx @@ -6961,7 +6960,6 @@ oox/source/core/relations.cxx oox/source/core/relationshandler.cxx oox/source/core/xmlfilterbase.cxx oox/source/crypto/AgileEngine.cxx -oox/source/crypto/CryptTools.cxx oox/source/crypto/DocumentEncryption.cxx oox/source/crypto/Standard2007Engine.cxx oox/source/docprop/docprophandler.cxx commit 6adbc3c7179fc3977a15867e505b4ea919caf765 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri Nov 1 00:24:14 2024 +0100 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Mon Nov 4 21:51:23 2024 +0100 pdf: Don't emit metadata for /Info, allow XMP for PDF >= 1.4 Metadata written to /Info dictionary is deprecated in PDF 2.0 with the exception of /CreateDate and /ModDate, so don't write it if we are writing to PDF 2.0. Instead of this allow to write the XMP metadata all the way back to PDF 1.4 (when it was added to the specs). Change-Id: I33e29d7d52e96d34e973032d7d8b42d876282dcb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176026 Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> Tested-by: Jenkins diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index fd9d3ee1ef30..632dbc7968a0 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -5854,51 +5854,63 @@ sal_Int32 PDFWriterImpl::emitInfoDict( ) if( updateObject( nObject ) ) { - OStringBuffer aLine( 1024 ); - aLine.append( nObject ); - aLine.append( " 0 obj " - "<<" ); - if( !m_aContext.DocumentInfo.Title.isEmpty() ) - { - aLine.append( "/Title" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Title, nObject, aLine ); - aLine.append( " " ); - } - if( !m_aContext.DocumentInfo.Author.isEmpty() ) - { - aLine.append( "/Author" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Author, nObject, aLine ); - aLine.append( " " ); - } - if( !m_aContext.DocumentInfo.Subject.isEmpty() ) - { - aLine.append( "/Subject" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Subject, nObject, aLine ); - aLine.append( " " ); - } - if( !m_aContext.DocumentInfo.Keywords.isEmpty() ) - { - aLine.append( "/Keywords" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Keywords, nObject, aLine ); - aLine.append( " " ); - } - if( !m_aContext.DocumentInfo.Creator.isEmpty() ) + OStringBuffer aLine(1024); + appendObjectID(nObject, aLine); + aLine.append("<<"); + + // These entries are deprecated in PDF 2.0 (in favor of XMP metadata) and shouldn't be written. + // Exception: CreationDate and ModDate (which we don't write) + if (m_aContext.Version < PDFWriter::PDFVersion::PDF_2_0) { - aLine.append( "/Creator" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Creator, nObject, aLine ); - aLine.append( " " ); + if (!m_aContext.DocumentInfo.Title.isEmpty()) + { + aLine.append("/Title" ); + appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Title, nObject, aLine ); + aLine.append(" " ); + } + if( !m_aContext.DocumentInfo.Author.isEmpty() ) + { + aLine.append( "/Author" ); + appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Author, nObject, aLine ); + aLine.append( " " ); + } + if( !m_aContext.DocumentInfo.Subject.isEmpty() ) + { + aLine.append( "/Subject" ); + appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Subject, nObject, aLine ); + aLine.append( " " ); + } + if( !m_aContext.DocumentInfo.Keywords.isEmpty() ) + { + aLine.append( "/Keywords" ); + appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Keywords, nObject, aLine ); + aLine.append( " " ); + } + if( !m_aContext.DocumentInfo.Creator.isEmpty() ) + { + aLine.append( "/Creator" ); + appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Creator, nObject, aLine ); + aLine.append( " " ); + } + if( !m_aContext.DocumentInfo.Producer.isEmpty() ) + { + aLine.append( "/Producer" ); + appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Producer, nObject, aLine ); + aLine.append( " " ); + } } - if( !m_aContext.DocumentInfo.Producer.isEmpty() ) + + // Allowed in PDF 2.0 { - aLine.append( "/Producer" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Producer, nObject, aLine ); + aLine.append("/CreationDate"); + appendLiteralStringEncrypt( m_aCreationDateString, nObject, aLine ); aLine.append( " " ); } - aLine.append( "/CreationDate" ); - appendLiteralStringEncrypt( m_aCreationDateString, nObject, aLine ); - aLine.append( ">> endobj " ); - if( ! writeBuffer( aLine ) ) + aLine.append(">> "); + aLine.append("endobj " ); + + if (!writeBuffer(aLine)) nObject = 0; } else @@ -6089,7 +6101,7 @@ static void lcl_assignMeta(const css::uno::Sequence<OUString>& rValues, std::vec // Since in PDF 1.4 sal_Int32 PDFWriterImpl::emitDocumentMetadata() { - if( !m_bIsPDF_A1 && !m_bIsPDF_A2 && !m_bIsPDF_A3 && !m_bIsPDF_A4 && !m_bIsPDF_UA) + if (m_aContext.Version < PDFWriter::PDFVersion::PDF_1_4) return 0; //get the object number for all the destinations