filter/source/pdf/impdialog.cxx                 |    3 
 filter/source/pdf/pdfexport.cxx                 |    3 
 include/vcl/pdf/PDFEncryptionInitialization.hxx |   31 ++++
 include/vcl/pdfwriter.hxx                       |   39 ++----
 vcl/Library_vcl.mk                              |    1 
 vcl/inc/pdf/IPDFEncryptor.hxx                   |   19 +--
 vcl/inc/pdf/PDFEncryptor.hxx                    |   30 +---
 vcl/inc/pdf/PDFEncryptorR6.hxx                  |   81 ++++++++++++
 vcl/inc/pdf/pdfwriter_impl.hxx                  |    3 
 vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx  |  117 ++++++++++++++++++
 vcl/source/gdi/pdfwriter.cxx                    |    3 
 vcl/source/gdi/pdfwriter_impl.cxx               |   20 +--
 vcl/source/gdi/pdfwriter_impl2.cxx              |    5 
 vcl/source/pdf/PDFEncryptionInitialization.cxx  |   32 +++++
 vcl/source/pdf/PDFEncryptor.cxx                 |   35 +----
 vcl/source/pdf/PDFEncryptorR6.cxx               |  150 +++++++++++++++++++++++-
 16 files changed, 476 insertions(+), 96 deletions(-)

New commits:
commit 2d286deb40ca980176aa22823b6e9557b2336429
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Wed Nov 20 18:33:40 2024 +0900
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Fri Feb 14 13:52:06 2025 +0100

    pdf: add /Perm encrypted access permission algorithm
    
    + add test
    
    Change-Id: Iba54dab6738c9707b37e434bab23ae286675436d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176882
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178756
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Tested-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/vcl/inc/pdf/PDFEncryptorR6.hxx b/vcl/inc/pdf/PDFEncryptorR6.hxx
index e6efdeb5768d..70f7a3422f3a 100644
--- a/vcl/inc/pdf/PDFEncryptorR6.hxx
+++ b/vcl/inc/pdf/PDFEncryptorR6.hxx
@@ -76,6 +76,31 @@ VCL_DLLPUBLIC std::vector<sal_uInt8> decryptKey(const 
sal_uInt8* pUserPass, size
                                                 std::vector<sal_uInt8>& U,
                                                 std::vector<sal_uInt8>& UE);
 
+/** Algorithm 13: Validating the permissions (Security handlers of revision 6)
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.4.12
+ */
+VCL_DLLPUBLIC std::vector<sal_uInt8> decryptPerms(std::vector<sal_uInt8>& 
rPermsEncrypted,
+                                                  std::vector<sal_uInt8>& 
rFileEncryptionKey);
+
+/** Algorithm 10 step f)
+ *
+ * Computing the encryption dictionary’s Perms (permissions) value (Security 
handlers of revision 6)
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.4.9
+ */
+VCL_DLLPUBLIC std::vector<sal_uInt8> encryptPerms(std::vector<sal_uInt8>& 
rPerms,
+                                                  std::vector<sal_uInt8>& 
rFileEncryptionKey);
+
+/** Algorithm 10 steps a) - e)
+ *
+ * Computing the encryption dictionary’s Perms (permissions) value (Security 
handlers of revision 6)
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.4.9
+ */
+VCL_DLLPUBLIC std::vector<sal_uInt8> createPerms(sal_Int32 nAccessPermissions,
+                                                 bool bEncryptMetadata);
+
 } // end vcl::pdf
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx 
b/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
index 6f1e868564e6..408735d12ca2 100644
--- a/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
+++ b/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
@@ -180,6 +180,70 @@ CPPUNIT_TEST_FIXTURE(PDFEncryptionTest, testGenerateOandOE)
     CPPUNIT_ASSERT_EQUAL(
         true, vcl::pdf::validateOwnerPassword(aOwnerPass.data(), 
aOwnerPass.size(), U, O));
 }
+
+CPPUNIT_TEST_FIXTURE(PDFEncryptionTest, testPermsEncryption)
+{
+    // Encrypts file permissions for /Perms entry
+
+    // We use a existing encrypted /Perm to validate the decryption and 
re-encryption
+    // algorithm works correctly.
+
+    const sal_uInt8 pUserPass[] = { 'T', 'e', 's', 't' };
+
+    // U and UE taken from an PDF that was encrypted with "Test" as password
+    std::vector<sal_uInt8> U = 
parseHex("7BD210807A0277FECC52C261C442F02E1AD62C1A23553348B8F8AF7320"
+                                        
"DC9978FAB7E65E1BF4CA76F4BE5E6D2AA8C7D5");
+    std::vector<sal_uInt8> UE
+        = 
parseHex("67022D91A6BDF3179F488DC9658E54B78A0AD05C6A9C419DCD17A6941C151197");
+
+    // We decrypt the key, which is needed to decrypt and encrypt the /Perms 
content
+    std::vector<sal_uInt8> aKey = vcl::pdf::decryptKey(pUserPass, 4, U, UE);
+
+    // Known encrypted /Perms content taken from the PDF
+    std::vector<sal_uInt8> aPermEncrypted = 
parseHex("6a2306c6e5e71a5bbd8404b07abec38f");
+
+    // Decrypt
+    std::vector<sal_uInt8> aPermsDecrpyted = 
vcl::pdf::decryptPerms(aPermEncrypted, aKey);
+
+    // Encrypt again
+    std::vector<sal_uInt8> aPermsReencrypted = 
vcl::pdf::encryptPerms(aPermsDecrpyted, aKey);
+
+    // Original encrypted /Perm content should be equal to decrypted and 
encrypted again
+    CPPUNIT_ASSERT_EQUAL(std::string("6a2306c6e5e71a5bbd8404b07abec38f"),
+                         comphelper::hashToString(aPermsReencrypted));
+
+    // Always should be a,b,d
+    CPPUNIT_ASSERT_EQUAL(sal_uInt8('a'), aPermsDecrpyted[9]);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt8('d'), aPermsDecrpyted[10]);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt8('b'), aPermsDecrpyted[11]);
+
+    // Metadata encrypted? - T or F
+    CPPUNIT_ASSERT_EQUAL(sal_uInt8('T'), aPermsDecrpyted[8]);
+
+    // Decrypting the access permissions
+    sal_Int32 aAccessPermissions
+        = sal_Int32(aPermsDecrpyted[0]) + sal_Int32(aPermsDecrpyted[1] << 8)
+          + sal_Int32(aPermsDecrpyted[2] << 16) + sal_Int32(aPermsDecrpyted[3] 
<< 24);
+
+    // Taken from the PDF (/P entry)
+    sal_Int32 nExpectedAccessPermisssions = -4;
+    CPPUNIT_ASSERT_EQUAL(nExpectedAccessPermisssions, aAccessPermissions);
+
+    // the whole decrypted /Perms content
+    CPPUNIT_ASSERT_EQUAL(std::string("fcffffffffffffff54616462bb609a8a"),
+                         comphelper::hashToString(aPermsDecrpyted));
+
+    // Check the creating /Perm content from access permissions works correctly
+    std::vector<sal_uInt8> aPermsCreated = 
vcl::pdf::createPerms(nExpectedAccessPermisssions, true);
+
+    // Last 12 bytes are random, so we shouldn't check those
+    std::vector<sal_uInt8> aPermsWithoutRandomBytes(aPermsCreated.begin(),
+                                                    aPermsCreated.begin() + 
12);
+
+    // Should match the decrypted content
+    CPPUNIT_ASSERT_EQUAL(std::string("fcffffffffffffff54616462"),
+                         comphelper::hashToString(aPermsWithoutRandomBytes));
+}
 } // end anonymous namespace
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/pdf/PDFEncryptorR6.cxx 
b/vcl/source/pdf/PDFEncryptorR6.cxx
index 9f0670f1fe1f..b3850a5929f8 100644
--- a/vcl/source/pdf/PDFEncryptorR6.cxx
+++ b/vcl/source/pdf/PDFEncryptorR6.cxx
@@ -129,6 +129,48 @@ std::vector<sal_uInt8> decryptKey(const sal_uInt8* pPass, 
size_t nLength, std::v
     return aFileEncryptionKey;
 }
 
+/** Algorithm 13: Validating the permissions */
+std::vector<sal_uInt8> decryptPerms(std::vector<sal_uInt8>& rPermsEncrypted,
+                                    std::vector<sal_uInt8>& rFileEncryptionKey)
+{
+    std::vector<sal_uInt8> aPermsDecrpyted(rPermsEncrypted.size());
+    std::vector<sal_uInt8> iv(IV_SIZE, 0);
+    comphelper::Decrypt aDecryptor(rFileEncryptionKey, iv, 
comphelper::CryptoType::AES_256_ECB);
+    aDecryptor.update(aPermsDecrpyted, rPermsEncrypted);
+    return aPermsDecrpyted;
+}
+
+/** Algorithm 10 step f) */
+std::vector<sal_uInt8> encryptPerms(std::vector<sal_uInt8>& rPerms,
+                                    std::vector<sal_uInt8>& rFileEncryptionKey)
+{
+    std::vector<sal_uInt8> aPermsEncrypted(rPerms.size());
+    std::vector<sal_uInt8> iv(IV_SIZE, 0);
+    comphelper::Encrypt aEncryptor(rFileEncryptionKey, iv, 
comphelper::CryptoType::AES_256_ECB);
+    aEncryptor.update(aPermsEncrypted, rPerms);
+    return aPermsEncrypted;
+}
+
+/** Algorithm 10 steps a) - e) */
+std::vector<sal_uInt8> createPerms(sal_Int32 nAccessPermissions, bool 
bEncryptMetadata)
+{
+    std::vector<sal_uInt8> aPermsCreated;
+    generateBytes(aPermsCreated, 16);
+    aPermsCreated[0] = sal_uInt8(nAccessPermissions);
+    aPermsCreated[1] = sal_uInt8(nAccessPermissions >> 8);
+    aPermsCreated[2] = sal_uInt8(nAccessPermissions >> 16);
+    aPermsCreated[3] = sal_uInt8(nAccessPermissions >> 24);
+    aPermsCreated[4] = sal_uInt8(0xff);
+    aPermsCreated[5] = sal_uInt8(0xff);
+    aPermsCreated[6] = sal_uInt8(0xff);
+    aPermsCreated[7] = sal_uInt8(0xff);
+    aPermsCreated[8] = bEncryptMetadata ? 'T' : 'F'; // Encrypt metadata
+    aPermsCreated[9] = 'a';
+    aPermsCreated[10] = 'd';
+    aPermsCreated[11] = 'b';
+    return aPermsCreated;
+}
+
 /** Algorithm 2.B: Computing a hash (revision 6 and later) */
 std::vector<sal_uInt8> computeHashR6(const sal_uInt8* pPassword, size_t 
nPasswordLength,
                                      std::vector<sal_uInt8> const& 
rValidationSalt,
commit 3ca27525c717be9e5967b1eaf8577f1f97b806f6
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Wed Nov 20 17:25:26 2024 +0900
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Fri Feb 14 13:50:44 2025 +0100

    pdf: generate U, UE and O, OE keys for R6 encryption
    
    Also test the algorithm against the known values from an example,
    to be sure we are calculating the values correctly. For this we
    need a couple of decryption algorithms, but those do mostly just
    the reverse of the encryption.
    
    Change-Id: I5499ed0b57671f44e48fe68961e07cde22be6b39
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176881
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178755
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/vcl/inc/pdf/PDFEncryptorR6.hxx b/vcl/inc/pdf/PDFEncryptorR6.hxx
index 7234e96f6af1..e6efdeb5768d 100644
--- a/vcl/inc/pdf/PDFEncryptorR6.hxx
+++ b/vcl/inc/pdf/PDFEncryptorR6.hxx
@@ -9,17 +9,73 @@
 
 #pragma once
 
+#include <rtl/ustring.hxx>
 #include <string_view>
 #include <vector>
 #include <vcl/dllapi.h>
 
 namespace vcl::pdf
 {
+/** Algorithm 2.B: Computing a hash (revision 6 and later)
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.3.4
+ */
 VCL_DLLPUBLIC std::vector<sal_uInt8>
 computeHashR6(const sal_uInt8* pPassword, size_t nPasswordLength,
               std::vector<sal_uInt8> const& rValidationSalt,
               std::vector<sal_uInt8> const& rUserKey = 
std::vector<sal_uInt8>());
 
+/** Algorithm 11: Authenticating the user password (Security handlers of 
revision 6)
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.4.10
+ */
+VCL_DLLPUBLIC bool validateUserPassword(const sal_uInt8* pUserPass, size_t 
nPasswordLength,
+                                        std::vector<sal_uInt8>& U);
+
+/** Algorithm 12: Authenticating the owner password (Security handlers of 
revision 6)
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.4.11
+ */
+VCL_DLLPUBLIC bool validateOwnerPassword(const sal_uInt8* pUserPass, size_t 
nPasswordLength,
+                                         std::vector<sal_uInt8>& U, 
std::vector<sal_uInt8>& O);
+
+/** Generates the encryption key - random data 32-byte */
+VCL_DLLPUBLIC std::vector<sal_uInt8> generateKey();
+
+/** Algorithm 8: U and UE
+ *
+ * Computing the encryption dictionary’s U (user password) and UE (user 
encryption) values
+ * (Security handlers of revision 6)
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.4.7
+ */
+VCL_DLLPUBLIC void generateUandUE(const sal_uInt8* pUserPass, size_t 
nPasswordLength,
+                                  std::vector<sal_uInt8>& rFileEncryptionKey,
+                                  std::vector<sal_uInt8>& U, 
std::vector<sal_uInt8>& UE);
+
+/** Algorithm 9: O and OE
+ *
+ * Computing the encryption dictionary’s O (owner password) and OE (owner 
encryption) values
+ * (Security handlers of revision 6)
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.4.8
+ */
+VCL_DLLPUBLIC void generateOandOE(const sal_uInt8* pUserPass, size_t 
nPasswordLength,
+                                  std::vector<sal_uInt8>& rFileEncryptionKey,
+                                  std::vector<sal_uInt8>& U, 
std::vector<sal_uInt8>& O,
+                                  std::vector<sal_uInt8>& OE);
+
+/** Algorithm 8 step b) in reverse
+ *
+ * Described in ISO 32000-2:2020(E) - 7.6.4.4.7
+ *
+ * - compute the hash with password and user key salt
+ * - decrypt with hash as key and zero IV
+ */
+VCL_DLLPUBLIC std::vector<sal_uInt8> decryptKey(const sal_uInt8* pUserPass, 
size_t nPasswordLength,
+                                                std::vector<sal_uInt8>& U,
+                                                std::vector<sal_uInt8>& UE);
+
 } // end vcl::pdf
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx 
b/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
index 4f2239bc01b8..6f1e868564e6 100644
--- a/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
+++ b/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
@@ -127,6 +127,59 @@ CPPUNIT_TEST_FIXTURE(PDFEncryptionTest, 
testComputeHashForR6)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(PDFEncryptionTest, testGenerateUandUE)
+{
+    // Checks we calculate U and UE correctly
+    const sal_uInt8 pUserPass[] = { 'T', 'e', 's', 't' };
+
+    std::vector<sal_uInt8> aInputKey = vcl::pdf::generateKey();
+
+    std::vector<sal_uInt8> U;
+    std::vector<sal_uInt8> UE;
+
+    // Generate the U and UE from the user password and encrypt the
+    // encryption key into UE
+    vcl::pdf::generateUandUE(pUserPass, 4, aInputKey, U, UE);
+
+    // Checks that the U validates the password (would fail if the U
+    // would be calculated wrongly).
+    CPPUNIT_ASSERT_EQUAL(true, vcl::pdf::validateUserPassword(pUserPass, 4, 
U));
+
+    // Decrypt the key - this would fail if U and UE would be calculated
+    // wrongly
+    auto aDecryptedKey = vcl::pdf::decryptKey(pUserPass, 4, U, UE);
+
+    // Decrypted key and input key need to match
+    CPPUNIT_ASSERT_EQUAL(comphelper::hashToString(aInputKey),
+                         comphelper::hashToString(aDecryptedKey));
+}
+
+CPPUNIT_TEST_FIXTURE(PDFEncryptionTest, testGenerateOandOE)
+{
+    // Checks we calculate O and OE correctly
+
+    const auto aUserPass = std::to_array<sal_uInt8>({ 'T', 'e', 's', 't' });
+    const auto aOwnerPass = std::to_array<sal_uInt8>({ 'T', 'e', 's', 't', '2' 
});
+
+    std::vector<sal_uInt8> aInputKey = vcl::pdf::generateKey();
+
+    std::vector<sal_uInt8> U;
+    std::vector<sal_uInt8> UE;
+    std::vector<sal_uInt8> O;
+    std::vector<sal_uInt8> OE;
+
+    // Generates U and UE - we need U in generateOandOE
+    vcl::pdf::generateUandUE(aUserPass.data(), aUserPass.size(), aInputKey, U, 
UE);
+    vcl::pdf::generateOandOE(aOwnerPass.data(), aOwnerPass.size(), aInputKey, 
U, O, OE);
+
+    // Checks the user password is valid
+    CPPUNIT_ASSERT_EQUAL(true,
+                         vcl::pdf::validateUserPassword(aUserPass.data(), 
aUserPass.size(), U));
+
+    // Checks the owner password is valid
+    CPPUNIT_ASSERT_EQUAL(
+        true, vcl::pdf::validateOwnerPassword(aOwnerPass.data(), 
aOwnerPass.size(), U, O));
+}
 } // end anonymous namespace
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/pdf/PDFEncryptorR6.cxx 
b/vcl/source/pdf/PDFEncryptorR6.cxx
index 64e668dca598..9f0670f1fe1f 100644
--- a/vcl/source/pdf/PDFEncryptorR6.cxx
+++ b/vcl/source/pdf/PDFEncryptorR6.cxx
@@ -18,6 +18,10 @@ namespace vcl::pdf
 {
 namespace
 {
+constexpr size_t IV_SIZE = 16;
+constexpr size_t KEY_SIZE = 32;
+constexpr size_t SALT_SIZE = 8;
+
 /** Calculates modulo 3 of the 128-bit integer, using the first 16 bytes of 
the vector */
 sal_Int32 calculateModulo3(std::vector<sal_uInt8> const& rInput)
 {
@@ -26,12 +30,106 @@ sal_Int32 calculateModulo3(std::vector<sal_uInt8> const& 
rInput)
         nSum += rInput[i];
     return nSum % 3;
 }
+
+void generateBytes(std::vector<sal_uInt8>& rBytes, size_t nSize)
+{
+    rBytes.resize(nSize);
+
+    for (size_t i = 0; i < rBytes.size(); ++i)
+        rBytes[i] = sal_uInt8(comphelper::rng::uniform_uint_distribution(0, 
0xFF));
 }
 
-/** Algorithm 2.B: Computing a hash (revision 6 and later)
- *
- * Described in ISO 32000-2:2020(E) - 7.6.4.3.4
- */
+} // end anonymous
+
+std::vector<sal_uInt8> generateKey()
+{
+    std::vector<sal_uInt8> aKey;
+    generateBytes(aKey, KEY_SIZE);
+    return aKey;
+}
+
+bool validateUserPassword(const sal_uInt8* pPass, size_t nLength, 
std::vector<sal_uInt8>& U)
+{
+    std::vector<sal_uInt8> aHash(U.begin(), U.begin() + KEY_SIZE);
+    std::vector<sal_uInt8> aValidationSalt(U.begin() + KEY_SIZE, U.begin() + 
KEY_SIZE + SALT_SIZE);
+    std::vector<sal_uInt8> aCalculatedHash
+        = vcl::pdf::computeHashR6(pPass, nLength, aValidationSalt);
+    return aHash == aCalculatedHash;
+}
+
+bool validateOwnerPassword(const sal_uInt8* pPass, size_t nLength, 
std::vector<sal_uInt8>& U,
+                           std::vector<sal_uInt8>& O)
+{
+    std::vector<sal_uInt8> aHash(O.begin(), O.begin() + KEY_SIZE);
+    std::vector<sal_uInt8> aValidationSalt(O.begin() + KEY_SIZE, O.begin() + 
KEY_SIZE + SALT_SIZE);
+    std::vector<sal_uInt8> aCalculatedHash
+        = vcl::pdf::computeHashR6(pPass, nLength, aValidationSalt, U);
+    return aHash == aCalculatedHash;
+}
+
+/** Algorithm 8 */
+void generateUandUE(const sal_uInt8* pPass, size_t nLength,
+                    std::vector<sal_uInt8>& rFileEncryptionKey, 
std::vector<sal_uInt8>& U,
+                    std::vector<sal_uInt8>& UE)
+{
+    std::vector<sal_uInt8> aValidationSalt;
+    generateBytes(aValidationSalt, SALT_SIZE);
+    std::vector<sal_uInt8> aKeySalt;
+    generateBytes(aKeySalt, SALT_SIZE);
+
+    U = vcl::pdf::computeHashR6(pPass, nLength, aValidationSalt);
+    U.insert(U.end(), aValidationSalt.begin(), aValidationSalt.end());
+    U.insert(U.end(), aKeySalt.begin(), aKeySalt.end());
+
+    std::vector<sal_uInt8> aKeyHash = vcl::pdf::computeHashR6(pPass, nLength, 
aKeySalt);
+    std::vector<sal_uInt8> iv(IV_SIZE, 0); // zero IV
+    UE = std::vector<sal_uInt8>(rFileEncryptionKey.size(), 0);
+    comphelper::Encrypt aEncrypt(aKeyHash, iv, 
comphelper::CryptoType::AES_256_CBC);
+    aEncrypt.update(UE, rFileEncryptionKey);
+}
+
+/** Algorithm 9 */
+void generateOandOE(const sal_uInt8* pPass, size_t nLength,
+                    std::vector<sal_uInt8>& rFileEncryptionKey, 
std::vector<sal_uInt8>& U,
+                    std::vector<sal_uInt8>& O, std::vector<sal_uInt8>& OE)
+{
+    std::vector<sal_uInt8> aValidationSalt;
+    generateBytes(aValidationSalt, SALT_SIZE);
+    std::vector<sal_uInt8> aKeySalt;
+    generateBytes(aKeySalt, SALT_SIZE);
+
+    O = vcl::pdf::computeHashR6(pPass, nLength, aValidationSalt, U);
+    O.insert(O.end(), aValidationSalt.begin(), aValidationSalt.end());
+    O.insert(O.end(), aKeySalt.begin(), aKeySalt.end());
+
+    std::vector<sal_uInt8> aKeyHash = vcl::pdf::computeHashR6(pPass, nLength, 
aKeySalt, U);
+    std::vector<sal_uInt8> iv(IV_SIZE, 0); // zero IV
+    OE = std::vector<sal_uInt8>(rFileEncryptionKey.size(), 0);
+    comphelper::Encrypt aEncrypt(aKeyHash, iv, 
comphelper::CryptoType::AES_256_CBC);
+    aEncrypt.update(OE, rFileEncryptionKey);
+}
+
+/** Algorithm 8 step b) */
+std::vector<sal_uInt8> decryptKey(const sal_uInt8* pPass, size_t nLength, 
std::vector<sal_uInt8>& U,
+                                  std::vector<sal_uInt8>& UE)
+{
+    std::vector<sal_uInt8> aKeySalt(U.begin() + KEY_SIZE + SALT_SIZE,
+                                    U.begin() + KEY_SIZE + SALT_SIZE + 
SALT_SIZE);
+
+    auto aKeyHash = vcl::pdf::computeHashR6(pPass, nLength, aKeySalt);
+
+    std::vector<sal_uInt8> aEncryptedKey(UE.begin(), UE.begin() + KEY_SIZE);
+    std::vector<sal_uInt8> iv(IV_SIZE, 0);
+
+    comphelper::Decrypt aDecryptCBC(aKeyHash, iv, 
comphelper::CryptoType::AES_256_CBC);
+    std::vector<sal_uInt8> aFileEncryptionKey(aEncryptedKey.size());
+    sal_uInt32 nDecrypted = aDecryptCBC.update(aFileEncryptionKey, 
aEncryptedKey);
+    if (nDecrypted == 0)
+        return std::vector<sal_uInt8>();
+    return aFileEncryptionKey;
+}
+
+/** Algorithm 2.B: Computing a hash (revision 6 and later) */
 std::vector<sal_uInt8> computeHashR6(const sal_uInt8* pPassword, size_t 
nPasswordLength,
                                      std::vector<sal_uInt8> const& 
rValidationSalt,
                                      std::vector<sal_uInt8> const& rUserKey)
@@ -47,7 +145,7 @@ std::vector<sal_uInt8> computeHashR6(const sal_uInt8* 
pPassword, size_t nPasswor
 
     std::vector<sal_uInt8> E;
 
-    sal_Int32 nRound = 1;
+    sal_Int32 nRound = 1; // round 0 is done already
     do
     {
         // Step a)
commit 53896e425579695c3a8f76fd77cc20802e0dea0b
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Wed Nov 20 17:04:48 2024 +0900
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Fri Feb 14 13:50:26 2025 +0100

    pdf: move common things to interface, prepare methods
    
    Move common flag, if the stream is encrypted from PDFEncryptor
    impl. to the IPDFEncryptor "interface".
    
    Change setupEncryption and encrypt methods to be closer to what
    will be needed in R6 implementation.
    
    Change-Id: I4dbd787c29e2a13ac900c6df360538b7e06af4ec
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176880
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178754
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Tested-by: Jenkins

diff --git a/vcl/inc/pdf/IPDFEncryptor.hxx b/vcl/inc/pdf/IPDFEncryptor.hxx
index bcd90dcef4bf..706eb82c71ed 100644
--- a/vcl/inc/pdf/IPDFEncryptor.hxx
+++ b/vcl/inc/pdf/IPDFEncryptor.hxx
@@ -39,6 +39,10 @@ namespace vcl::pdf
  */
 class IPDFEncryptor
 {
+private:
+    /* set to true if the following stream must be encrypted, used inside 
writeBuffer() */
+    bool m_bEncryptThisStream = false;
+
 public:
     virtual ~IPDFEncryptor() {}
 
@@ -73,17 +77,16 @@ public:
     virtual void setupKeysAndCheck(PDFEncryptionProperties& rProperties) = 0;
 
     /** Setup before we start encrypting - remembers the key */
-    virtual void setupEncryption(std::vector<sal_uInt8> const& rEncryptionKey, 
sal_Int32 nObject)
-        = 0;
-
-    virtual void enableStreamEncryption() = 0;
-    virtual void disableStreamEncryption() = 0;
-    virtual bool isStreamEncryptionEnabled() = 0;
+    virtual void setupEncryption(std::vector<sal_uInt8>& rEncryptionKey, 
sal_Int32 nObject) = 0;
 
     /** Encrypts the input and stores into the output */
-    virtual void encrypt(const void* pInput, sal_uInt64 nInputSize, sal_uInt8* 
pOutput,
-                         sal_uInt64 nOutputsSize)
+    virtual void encrypt(const void* pInput, sal_uInt64 nInputSize, 
std::vector<sal_uInt8>& rOutput,
+                         sal_uInt64 nOutputSize)
         = 0;
+
+    void enableStreamEncryption() { m_bEncryptThisStream = true; }
+    void disableStreamEncryption() { m_bEncryptThisStream = false; }
+    bool isStreamEncryptionEnabled() { return m_bEncryptThisStream; }
 };
 }
 
diff --git a/vcl/inc/pdf/PDFEncryptor.hxx b/vcl/inc/pdf/PDFEncryptor.hxx
index e4134605c194..9a65c5a0043b 100644
--- a/vcl/inc/pdf/PDFEncryptor.hxx
+++ b/vcl/inc/pdf/PDFEncryptor.hxx
@@ -15,11 +15,6 @@
 #include <vector>
 #include <pdf/IPDFEncryptor.hxx>
 
-namespace vcl
-{
-struct PDFEncryptionProperties;
-}
-
 namespace com::sun::star::uno
 {
 template <typename> class Reference;
@@ -41,9 +36,6 @@ private:
     sal_Int32 m_nKeyLength = 0; // key length, 16 or 5
     sal_Int32 m_nRC4KeyLength = 0; // key length, 16 or 10, to be input to the 
algorithm 3.1
 
-    /* set to true if the following stream must be encrypted, used inside 
writeBuffer() */
-    bool m_bEncryptThisStream = false;
-
     /* used to cipher the stream data and for password management */
     rtlCipher m_aCipher = nullptr;
 
@@ -67,14 +59,10 @@ public:
 
     void setupKeysAndCheck(PDFEncryptionProperties& rProperties) override;
 
-    void setupEncryption(std::vector<sal_uInt8> const& rEncryptionKey, 
sal_Int32 nObject) override;
-    void enableStreamEncryption() override;
-    void disableStreamEncryption() override;
-
-    bool isStreamEncryptionEnabled() override { return m_bEncryptThisStream; }
+    void setupEncryption(std::vector<sal_uInt8>& rEncryptionKey, sal_Int32 
nObject) override;
 
-    void encrypt(const void* pInput, sal_uInt64 nInputSize, sal_uInt8* pOutput,
-                 sal_uInt64 nOutputsSize) override;
+    void encrypt(const void* pInput, sal_uInt64 nInputSize, 
std::vector<sal_uInt8>& rOutput,
+                 sal_uInt64 nOutputSize) override;
 };
 }
 
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index 6ea3b49f156a..34e4a83a7a55 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -1618,7 +1618,7 @@ inline void 
PDFWriterImpl::appendUnicodeTextStringEncrypt( const OUString& rInSt
             *pCopy++ = static_cast<sal_uInt8>( aUnChar & 255 );
         }
         //encrypt in place
-        m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChars, 
m_vEncryptionBuffer.data(), nChars);
+        m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChars, 
m_vEncryptionBuffer, nChars);
         //now append, hexadecimal (appendHex), the encrypted result
         for(int i = 0; i < nChars; i++)
             appendHex( m_vEncryptionBuffer[i], rOutBuffer );
@@ -1638,7 +1638,7 @@ inline void PDFWriterImpl::appendLiteralStringEncrypt( 
std::string_view rInStrin
         m_vEncryptionBuffer.resize(nChars);
         //encrypt the string in a buffer, then append it
         enableStringEncryption(nInObjectNumber);
-        m_pPDFEncryptor->encrypt(rInString.data(), nChars, 
m_vEncryptionBuffer.data(), nChars);
+        m_pPDFEncryptor->encrypt(rInString.data(), nChars, 
m_vEncryptionBuffer, nChars);
         appendLiteralString( 
reinterpret_cast<char*>(m_vEncryptionBuffer.data()), nChars, rOutBuffer );
     }
     else
@@ -1749,7 +1749,7 @@ bool PDFWriterImpl::writeBufferBytes( const void* 
pBuffer, sal_uInt64 nBytes )
         if (bStreamEncryption)
         {
             m_vEncryptionBuffer.resize(nBytes);
-            m_pPDFEncryptor->encrypt(pBuffer, nBytes, 
m_vEncryptionBuffer.data(), nBytes);
+            m_pPDFEncryptor->encrypt(pBuffer, nBytes, m_vEncryptionBuffer, 
nBytes);
         }
 
         const void* pWriteBuffer = bStreamEncryption ? 
m_vEncryptionBuffer.data() : pBuffer;
@@ -9825,7 +9825,7 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& 
rObject, bool bMask )
                     m_vEncryptionBuffer[nChar++] = rColor.GetBlue();
                 }
                 //encrypt the colorspace lookup table
-                m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChar, 
m_vEncryptionBuffer.data(), nChar);
+                m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChar, 
m_vEncryptionBuffer, nChar);
                 //now queue the data for output
                 nChar = 0;
                 for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); 
i++ )
diff --git a/vcl/source/pdf/PDFEncryptor.cxx b/vcl/source/pdf/PDFEncryptor.cxx
index 63bb49c05425..a5425f014ae0 100644
--- a/vcl/source/pdf/PDFEncryptor.cxx
+++ b/vcl/source/pdf/PDFEncryptor.cxx
@@ -393,11 +393,7 @@ void 
PDFEncryptor::setupKeysAndCheck(vcl::PDFEncryptionProperties& rProperties)
     }
 }
 
-void PDFEncryptor::enableStreamEncryption() { m_bEncryptThisStream = true; }
-
-void PDFEncryptor::disableStreamEncryption() { m_bEncryptThisStream = false; }
-
-void PDFEncryptor::setupEncryption(std::vector<sal_uInt8> const& 
rEncryptionKey, sal_Int32 nObject)
+void PDFEncryptor::setupEncryption(std::vector<sal_uInt8>& rEncryptionKey, 
sal_Int32 nObject)
 {
     std::vector<sal_uInt8> aKey(rEncryptionKey.begin(), rEncryptionKey.begin() 
+ m_nKeyLength);
     std::vector<sal_uInt8> aObjectArray{
@@ -418,10 +414,10 @@ void PDFEncryptor::setupEncryption(std::vector<sal_uInt8> 
const& rEncryptionKey,
 }
 
 /* implement the encryption part of the PDF spec encryption algorithm 3.1 */
-void PDFEncryptor::encrypt(const void* pInput, sal_uInt64 nInputSize, 
sal_uInt8* pOutput,
-                           sal_uInt64 nOutputsSize)
+void PDFEncryptor::encrypt(const void* pInput, sal_uInt64 nInputSize,
+                           std::vector<sal_uInt8>& rOutput, sal_uInt64 
nOutputsSize)
 {
-    rtl_cipher_encodeARCFOUR(m_aCipher, pInput, sal_Size(nInputSize), pOutput,
+    rtl_cipher_encodeARCFOUR(m_aCipher, pInput, sal_Size(nInputSize), 
rOutput.data(),
                              sal_Size(nOutputsSize));
 }
 
commit 22ba67f0500a66a0e172b5911a30d5471a7ab3d7
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Mon Nov 11 22:53:26 2024 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Fri Feb 14 13:44:06 2025 +0100

    pdf: forward declare IPDFEncryptor
    
    To compile less when changing PDFEncryptor.
    
    Change-Id: I56e19e12494488fedb929998f8e6d0ff3bf8008c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176456
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177875
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx
index 3f09038068b8..4b7b72dce4fc 100644
--- a/vcl/inc/pdf/pdfwriter_impl.hxx
+++ b/vcl/inc/pdf/pdfwriter_impl.hxx
@@ -34,7 +34,6 @@
 #include <pdf/ResourceDict.hxx>
 #include <pdf/BitmapID.hxx>
 #include <pdf/Matrix3.hxx>
-#include <pdf/PDFEncryptor.hxx>
 
 #include <com/sun/star/lang/Locale.hpp>
 #include <com/sun/star/util/XURLTransformer.hpp>
@@ -684,6 +683,8 @@ struct PDFDocumentAttachedFile
     sal_Int32 mnObjectId;
 };
 
+class IPDFEncryptor;
+
 } // end pdf namespace
 
 class PDFWriterImpl final : public VirtualDevice, public PDFObjectContainer
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index 711783309aaf..6ea3b49f156a 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -96,6 +96,8 @@
 #include <pdf/objectcopier.hxx>
 #include <pdf/pdfwriter_impl.hxx>
 #include <pdf/PdfConfig.hxx>
+#include <pdf/IPDFEncryptor.hxx>
+#include <pdf/PDFEncryptor.hxx>
 #include <o3tl/sorted_vector.hxx>
 #include <frozen/bits/defines.h>
 #include <frozen/bits/elsa_std.h>
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx 
b/vcl/source/gdi/pdfwriter_impl2.cxx
index ec4adefa47c7..2f06a292c936 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -25,6 +25,7 @@
 #include <vcl/metaact.hxx>
 #include <vcl/BitmapReadAccess.hxx>
 #include <vcl/graph.hxx>
+#include <pdf/IPDFEncryptor.hxx>
 
 #include <unotools/streamwrap.hxx>
 
commit 8b9aacc39a56bbf7824fef3f885ee1dee1ca0e26
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Mon Nov 11 22:48:34 2024 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Fri Feb 14 13:43:53 2025 +0100

    pdf: cleanup and improve PDFEncryptionProperties
    
    Add clear method to clear the variables that we usually want to
    be cleared. Also rename Encrypt to canEncrypt - which is more
    clear what it means. Cleanup initializers.
    
    Change-Id: I96735eb6f73a699fb0759496fc8781bcff3854de
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176455
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177874
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Tested-by: Jenkins

diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx
index a863b17c1879..14c6265f3d88 100644
--- a/include/vcl/pdfwriter.hxx
+++ b/include/vcl/pdfwriter.hxx
@@ -77,15 +77,16 @@ class VCL_DLLPUBLIC PDFOutputStream
 struct PDFEncryptionProperties
 {
     //for both 40 and 128 bit security, see 3.5.2 PDF v 1.4 table 3.15, v 1.5 
and v 1.6 table 3.20.
-    bool CanPrintTheDocument;
-    bool CanModifyTheContent;
-    bool CanCopyOrExtract;
-    bool CanAddOrModify;
+    bool CanPrintTheDocument = false;
+    bool CanModifyTheContent = false;
+    bool CanCopyOrExtract = false;
+    bool CanAddOrModify = false;
+
     //for revision 3 (bit 128 security) only
-    bool CanFillInteractive;
-    bool CanExtractForAccessibility;
-    bool CanAssemble;
-    bool CanPrintFull;
+    bool CanFillInteractive = false;
+    bool CanExtractForAccessibility = true;
+    bool CanAssemble = false;
+    bool CanPrintFull = false;
 
     // encryption will only happen if EncryptionKey is not empty
     // EncryptionKey is actually a construct out of OValue, UValue and 
DocumentIdentifier
@@ -98,22 +99,16 @@ struct PDFEncryptionProperties
     std::vector<sal_uInt8> EncryptionKey;
     std::vector<sal_uInt8> DocumentIdentifier;
 
-    //permission default set for 128 bit, accessibility only
-    PDFEncryptionProperties() :
-        CanPrintTheDocument         ( false ),
-        CanModifyTheContent         ( false ),
-        CanCopyOrExtract            ( false ),
-        CanAddOrModify              ( false ),
-        CanFillInteractive          ( false ),
-        CanExtractForAccessibility  ( true ),
-        CanAssemble                 ( false ),
-        CanPrintFull                ( false )
-        {}
-
+    bool canEncrypt() const
+    {
+        return !OValue.empty() && !UValue.empty() && 
!DocumentIdentifier.empty();
+    }
 
-    bool Encrypt() const
+    void clear()
     {
-        return ! OValue.empty() && ! UValue.empty() && ! 
DocumentIdentifier.empty();
+        OValue.clear();
+        UValue.clear();
+        EncryptionKey.clear();
     }
 };
 
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index b86e84c03e79..711783309aaf 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -1461,7 +1461,7 @@ PDFWriterImpl::PDFWriterImpl( const 
PDFWriter::PDFWriterContext& rContext,
         m_pPDFEncryptor->prepareEncryption(xEncryptionMaterialHolder, 
m_aContext.Encryption);
     }
 
-    if (m_pPDFEncryptor && m_aContext.Encryption.Encrypt())
+    if (m_pPDFEncryptor && m_aContext.Encryption.canEncrypt())
     {
         m_pPDFEncryptor->setupKeysAndCheck(m_aContext.Encryption);
     }
@@ -1597,7 +1597,7 @@ append the string as unicode hex, encrypted if needed
 inline void PDFWriterImpl::appendUnicodeTextStringEncrypt( const OUString& 
rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer )
 {
     rOutBuffer.append( "<" );
-    if (m_aContext.Encryption.Encrypt())
+    if (m_aContext.Encryption.canEncrypt())
     {
         const sal_Unicode* pStr = rInString.getStr();
         sal_Int32 nLen = rInString.getLength();
@@ -1631,7 +1631,7 @@ inline void PDFWriterImpl::appendLiteralStringEncrypt( 
std::string_view rInStrin
     rOutBuffer.append( "(" );
     sal_Int32 nChars = rInString.size();
     //check for encryption, if ok, encrypt the string, then convert with 
appndLiteralString
-    if (m_aContext.Encryption.Encrypt())
+    if (m_aContext.Encryption.canEncrypt())
     {
         m_vEncryptionBuffer.resize(nChars);
         //encrypt the string in a buffer, then append it
@@ -6184,7 +6184,7 @@ bool PDFWriterImpl::emitTrailer()
 
     sal_Int32 nSecObject = 0;
 
-    if( m_aContext.Encryption.Encrypt() )
+    if (m_aContext.Encryption.canEncrypt())
     {
         nSecObject = emitEncrypt();
     }
@@ -9808,7 +9808,7 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& 
rObject, bool bMask )
             aLine.append( "[ /Indexed/DeviceRGB " );
             aLine.append( 
static_cast<sal_Int32>(pAccess->GetPaletteEntryCount()-1) );
             aLine.append( "
<" );
-            if( m_aContext.Encryption.Encrypt() )
+            if (m_aContext.Encryption.canEncrypt())
             {
                 enableStringEncryption(rObject.m_nObject);
                 //check encryption buffer size
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx 
b/vcl/source/gdi/pdfwriter_impl2.cxx
index 3efc67a32b61..ec4adefa47c7 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -1079,7 +1079,7 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& 
i_rMtf, vcl::PDFExtOutDevDa
 
 void PDFWriterImpl::checkAndEnableStreamEncryption(sal_Int32 nObject)
 {
-    if (!m_aContext.Encryption.Encrypt() || !m_pPDFEncryptor)
+    if (!m_aContext.Encryption.canEncrypt() || !m_pPDFEncryptor)
         return;
 
     m_pPDFEncryptor->enableStreamEncryption();
@@ -1094,7 +1094,7 @@ void PDFWriterImpl::disableStreamEncryption()
 
 void PDFWriterImpl::enableStringEncryption(sal_Int32 nObject)
 {
-    if (!m_aContext.Encryption.Encrypt() || !m_pPDFEncryptor)
+    if (!m_aContext.Encryption.canEncrypt() || !m_pPDFEncryptor)
         return;
 
     m_pPDFEncryptor->setupEncryption(m_aContext.Encryption.EncryptionKey, 
nObject);
diff --git a/vcl/source/pdf/PDFEncryptor.cxx b/vcl/source/pdf/PDFEncryptor.cxx
index 183e66e8e713..63bb49c05425 100644
--- a/vcl/source/pdf/PDFEncryptor.cxx
+++ b/vcl/source/pdf/PDFEncryptor.cxx
@@ -369,9 +369,7 @@ bool PDFEncryptor::prepareEncryption(
 
     if (!bSuccess)
     {
-        rProperties.OValue.clear();
-        rProperties.UValue.clear();
-        rProperties.EncryptionKey.clear();
+        rProperties.clear();
     }
     return bSuccess;
 }
@@ -386,8 +384,7 @@ void 
PDFEncryptor::setupKeysAndCheck(vcl::PDFEncryptionProperties& rProperties)
     {
         // the field lengths are invalid ? This was not setup by 
initEncryption.
         // do not encrypt after all
-        rProperties.OValue.clear();
-        rProperties.UValue.clear();
+        rProperties.clear();
         OSL_ENSURE(false, "encryption data failed sanity check, encryption 
disabled");
     }
     else // setup key lengths
commit dd1cff06e20e09784950327d744b68f75048b70a
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Mon Nov 11 19:14:49 2024 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Fri Feb 14 13:43:39 2025 +0100

    pdf: refactor and move encryption init. to a common function
    
    This is needed because we have to separate the init. for both
    encryption methods and we have to init both when the password is
    entered. Currently we only prepared this, to make this possible
    when we introduce the other encryption method.
    
    Change-Id: Id6556ddc6a6218164a93bb689f03d6ec6dbad8b9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176454
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177873
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx
index 482d523bed63..b62fb69158a7 100644
--- a/filter/source/pdf/impdialog.cxx
+++ b/filter/source/pdf/impdialog.cxx
@@ -23,6 +23,7 @@
 #include <vcl/errinf.hxx>
 #include <vcl/graphic/GraphicMetadata.hxx>
 #include <vcl/svapp.hxx>
+#include <vcl/pdf/PDFEncryptionInitialization.hxx>
 #include <vcl/weld.hxx>
 #include <sfx2/passwd.hxx>
 #include <comphelper/diagnose_ex.hxx>
@@ -1418,7 +1419,7 @@ IMPL_LINK_NOARG(ImpPDFTabSecurityPage, 
ClickmaPbSetPwdHdl, weld::Button&, void)
             mbHaveUserPassword = !aUserPW.isEmpty();
             mbHaveOwnerPassword = !aOwnerPW.isEmpty();
 
-            mxPreparedPasswords = vcl::PDFWriter::InitEncryption( aOwnerPW, 
aUserPW );
+            mxPreparedPasswords = vcl::pdf::initEncryption(aOwnerPW, aUserPW);
             if (!mxPreparedPasswords.is())
             {
                 OUString msg;
diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx
index 5956933154c6..cca7703c50c8 100644
--- a/filter/source/pdf/pdfexport.cxx
+++ b/filter/source/pdf/pdfexport.cxx
@@ -28,6 +28,7 @@
 #include <vcl/mapmod.hxx>
 #include <vcl/gdimtf.hxx>
 #include <vcl/graphic/GraphicMetadata.hxx>
+#include <vcl/pdf/PDFEncryptionInitialization.hxx>
 #include <rtl/ustring.hxx>
 #include <comphelper/propertyvalue.hxx>
 #include <comphelper/sequence.hxx>
@@ -931,7 +932,7 @@ bool PDFExport::Export( const OUString& rFile, const 
Sequence< PropertyValue >&
                 aContext.Encryption.CanCopyOrExtract                = 
bCanCopyOrExtract;
                 aContext.Encryption.CanExtractForAccessibility  = 
bCanExtractForAccessibility;
                 if( bEncrypt && ! xEnc.is() )
-                    xEnc = vcl::PDFWriter::InitEncryption( 
aPermissionPassword, aOpenPassword );
+                    xEnc = vcl::pdf::initEncryption(aPermissionPassword, 
aOpenPassword);
                 if( bEncrypt && !aPermissionPassword.isEmpty() && ! 
aPreparedPermissionPassword.hasElements() )
                     aPreparedPermissionPassword = 
comphelper::OStorageHelper::CreatePackageEncryptionData( aPermissionPassword );
             }
diff --git a/include/vcl/pdf/PDFEncryptionInitialization.hxx 
b/include/vcl/pdf/PDFEncryptionInitialization.hxx
new file mode 100644
index 000000000000..93b57476d7e4
--- /dev/null
+++ b/include/vcl/pdf/PDFEncryptionInitialization.hxx
@@ -0,0 +1,31 @@
+/* -*- 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 <rtl/ustring.hxx>
+#include <vcl/dllapi.h>
+
+namespace com::sun::star::beans
+{
+class XMaterialHolder;
+}
+namespace com::sun::star::uno
+{
+template <typename> class Reference;
+}
+
+namespace vcl::pdf
+{
+VCL_DLLPUBLIC css::uno::Reference<css::beans::XMaterialHolder>
+initEncryption(const OUString& i_rOwnerPassword, const OUString& 
i_rUserPassword);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 199792d2feba..f6a37a2c6228 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -511,6 +511,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/pdf/EncryptionHashTransporter \
     vcl/source/pdf/ExternalPDFStreams \
     vcl/source/pdf/PDFiumTools \
+    vcl/source/pdf/PDFEncryptionInitialization \
     vcl/source/pdf/PDFEncryptor \
     vcl/source/pdf/PDFEncryptorR6 \
     vcl/source/pdf/PdfConfig \
diff --git a/vcl/inc/pdf/PDFEncryptor.hxx b/vcl/inc/pdf/PDFEncryptor.hxx
index be4b99f9b7d6..e4134605c194 100644
--- a/vcl/inc/pdf/PDFEncryptor.hxx
+++ b/vcl/inc/pdf/PDFEncryptor.hxx
@@ -20,10 +20,6 @@ namespace vcl
 struct PDFEncryptionProperties;
 }
 
-namespace com::sun::star::beans
-{
-class XMaterialHolder;
-}
 namespace com::sun::star::uno
 {
 template <typename> class Reference;
@@ -31,6 +27,8 @@ template <typename> class Reference;
 
 namespace vcl::pdf
 {
+class EncryptionHashTransporter;
+
 class PDFEncryptor : public IPDFEncryptor
 {
 private:
@@ -60,10 +58,10 @@ public:
     sal_Int32 getKeyLength() override { return m_nKeyLength; }
     sal_Int32 getRC4KeyLength() { return m_nRC4KeyLength; }
 
-    static css::uno::Reference<css::beans::XMaterialHolder>
-    initEncryption(const OUString& i_rOwnerPassword, const OUString& 
i_rUserPassword);
+    static void initEncryption(EncryptionHashTransporter& 
rEncryptionHashTransporter,
+                               const OUString& i_rOwnerPassword, const 
OUString& i_rUserPassword);
 
-    virtual bool prepareEncryption(
+    bool prepareEncryption(
         const css::uno::Reference<css::beans::XMaterialHolder>& 
xEncryptionMaterialHolder,
         PDFEncryptionProperties& rProperties) override;
 
diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx
index ee762e2fca47..ca91054c53de 100644
--- a/vcl/source/gdi/pdfwriter.cxx
+++ b/vcl/source/gdi/pdfwriter.cxx
@@ -20,6 +20,7 @@
 #include <vcl/bitmapex.hxx>
 
 #include <pdf/pdfwriter_impl.hxx>
+#include <vcl/pdf/PDFEncryptionInitialization.hxx>
 
 using namespace vcl;
 
@@ -471,7 +472,7 @@ std::set< PDFWriter::ErrorCode > const & 
PDFWriter::GetErrors() const
 css::uno::Reference< css::beans::XMaterialHolder >
 PDFWriter::InitEncryption(const OUString& i_rOwnerPassword, const OUString& 
i_rUserPassword)
 {
-    return PDFEncryptor::initEncryption(i_rOwnerPassword, i_rUserPassword);
+    return vcl::pdf::initEncryption(i_rOwnerPassword, i_rUserPassword);
 }
 
 void PDFWriter::PlayMetafile( const GDIMetaFile& i_rMTF, const 
vcl::PDFWriter::PlayMetafileContext& i_rPlayContext, PDFExtOutDevData* i_pData )
diff --git a/vcl/source/pdf/PDFEncryptionInitialization.cxx 
b/vcl/source/pdf/PDFEncryptionInitialization.cxx
new file mode 100644
index 000000000000..df06968fc290
--- /dev/null
+++ b/vcl/source/pdf/PDFEncryptionInitialization.cxx
@@ -0,0 +1,32 @@
+/* -*- 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 <vcl/pdf/PDFEncryptionInitialization.hxx>
+#include <pdf/EncryptionHashTransporter.hxx>
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+#include <rtl/ref.hxx>
+#include <pdf/PDFEncryptor.hxx>
+#include <pdf/PDFEncryptorR6.hxx>
+
+using namespace css;
+
+namespace vcl::pdf
+{
+css::uno::Reference<css::beans::XMaterialHolder> initEncryption(const 
OUString& i_rOwnerPassword,
+                                                                const 
OUString& i_rUserPassword)
+{
+    rtl::Reference<EncryptionHashTransporter> pTransporter = new 
EncryptionHashTransporter;
+    PDFEncryptor::initEncryption(*pTransporter, i_rOwnerPassword, 
i_rUserPassword);
+    return pTransporter;
+}
+
+} // end vcl::pdf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/pdf/PDFEncryptor.cxx b/vcl/source/pdf/PDFEncryptor.cxx
index d97e671247de..183e66e8e713 100644
--- a/vcl/source/pdf/PDFEncryptor.cxx
+++ b/vcl/source/pdf/PDFEncryptor.cxx
@@ -327,32 +327,26 @@ PDFEncryptor::~PDFEncryptor() { 
rtl_cipher_destroyARCFOUR(m_aCipher); }
 1. init the document id, used both for building the document id and for 
building the encryption key(s)
 2. build the encryption key following algorithms described in the PDF 
specification
  */
-uno::Reference<beans::XMaterialHolder>
-PDFEncryptor::initEncryption(const OUString& i_rOwnerPassword, const OUString& 
i_rUserPassword)
+void PDFEncryptor::initEncryption(EncryptionHashTransporter& 
rEncryptionHashTransporter,
+                                  const OUString& i_rOwnerPassword, const 
OUString& i_rUserPassword)
 {
-    uno::Reference<beans::XMaterialHolder> xResult;
     if (!i_rOwnerPassword.isEmpty() || !i_rUserPassword.isEmpty())
     {
-        rtl::Reference<EncryptionHashTransporter> pTransporter = new 
EncryptionHashTransporter;
-        xResult = pTransporter;
-
         // get padded passwords
         sal_uInt8 aPadUPW[ENCRYPTED_PWD_SIZE], aPadOPW[ENCRYPTED_PWD_SIZE];
         padPassword(i_rOwnerPassword.isEmpty() ? i_rUserPassword : 
i_rOwnerPassword, aPadOPW);
         padPassword(i_rUserPassword, aPadUPW);
 
-        if (computeODictionaryValue(aPadOPW, aPadUPW, 
pTransporter->getOValue(), SECUR_128BIT_KEY))
+        if (computeODictionaryValue(aPadOPW, aPadUPW, 
rEncryptionHashTransporter.getOValue(),
+                                    SECUR_128BIT_KEY))
         {
-            pTransporter->getUDigest()->update(aPadUPW, ENCRYPTED_PWD_SIZE);
+            rEncryptionHashTransporter.getUDigest()->update(aPadUPW, 
ENCRYPTED_PWD_SIZE);
         }
-        else
-            xResult.clear();
 
         // trash temporary padded cleartext PWDs
         rtl_secureZeroMemory(aPadOPW, sizeof(aPadOPW));
         rtl_secureZeroMemory(aPadUPW, sizeof(aPadUPW));
     }
-    return xResult;
 }
 
 bool PDFEncryptor::prepareEncryption(

Reply via email to