vcl/inc/pdf/PDFEncryptor.hxx | 46 +++++++++++++++++++++++++++---------- vcl/inc/pdf/pdfwriter_impl.hxx | 2 - vcl/source/gdi/pdfwriter_impl.cxx | 30 +++++++++++++----------- vcl/source/gdi/pdfwriter_impl2.cxx | 14 +++++------ 4 files changed, 59 insertions(+), 33 deletions(-)
New commits: commit d60d4bd4b58a52fa70cb3364213f4ba69a04dcaf Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri Nov 8 11:50:14 2024 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Nov 29 09:30:14 2024 +0100 pdf: Introduce a IPDFEncryptor and use it in PDFWriterImpl The idea of IPDFEncryptor is to be the interface to encrypt the stream/string in the same way, irregardless which PDF encryption version/revision we are using. Change-Id: Ie7835384f1be5a44c53985b01c8187323400aa0e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176448 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/vcl/inc/pdf/PDFEncryptor.hxx b/vcl/inc/pdf/PDFEncryptor.hxx index 5b9f50492742..f6182be7f93c 100644 --- a/vcl/inc/pdf/PDFEncryptor.hxx +++ b/vcl/inc/pdf/PDFEncryptor.hxx @@ -33,7 +33,29 @@ namespace vcl::pdf { class EncryptionHashTransporter; -class PDFEncryptor +class IPDFEncryptor +{ +public: + virtual ~IPDFEncryptor() {} + virtual sal_Int32 getAccessPermissions() = 0; + virtual sal_Int32 getKeyLength() = 0; + virtual bool prepareEncryption( + const css::uno::Reference<css::beans::XMaterialHolder>& xEncryptionMaterialHolder, + PDFEncryptionProperties& rProperties) + = 0; + virtual void setupKeysAndCheck(PDFEncryptionProperties& rProperties) = 0; + + 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 encrypt(const void* pInput, sal_uInt64 nInputSize, sal_uInt8* pOutput, + sal_uInt64 nOutputsSize) + = 0; +}; + +class PDFEncryptor : public IPDFEncryptor { private: /* the numerical value of the access permissions, according to PDF spec, must be signed */ @@ -50,30 +72,30 @@ private: public: PDFEncryptor(); - ~PDFEncryptor(); + virtual ~PDFEncryptor(); /* used to cipher the stream data and for password management */ rtlCipher m_aCipher = nullptr; - sal_Int32 getAccessPermissions() { return m_nAccessPermissions; } - sal_Int32 getKeyLength() { return m_nKeyLength; } + sal_Int32 getAccessPermissions() override { return m_nAccessPermissions; } + 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); - virtual bool prepareEncryption( + bool prepareEncryption( const css::uno::Reference<css::beans::XMaterialHolder>& xEncryptionMaterialHolder, - PDFEncryptionProperties& rProperties); - void setupKeysAndCheck(PDFEncryptionProperties& rProperties); + PDFEncryptionProperties& rProperties) override; + void setupKeysAndCheck(PDFEncryptionProperties& rProperties) override; - void setupEncryption(std::vector<sal_uInt8> const& rEncryptionKey, sal_Int32 nObject); - void enableStreamEncryption(); - void disableStreamEncryption(); + void setupEncryption(std::vector<sal_uInt8> const& rEncryptionKey, sal_Int32 nObject) override; + void enableStreamEncryption() override; + void disableStreamEncryption() override; - bool isStreamEncryptionEnabled() { return m_bEncryptThisStream; } + bool isStreamEncryptionEnabled() override { return m_bEncryptThisStream; } void encrypt(const void* pInput, sal_uInt64 nInputSize, sal_uInt8* pOutput, - sal_uInt64 nOutputsSize); + sal_uInt64 nOutputsSize) override; }; } diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx index 5756bebf0082..fe0052915a23 100644 --- a/vcl/inc/pdf/pdfwriter_impl.hxx +++ b/vcl/inc/pdf/pdfwriter_impl.hxx @@ -800,7 +800,7 @@ private: ExternalPDFStreams m_aExternalPDFStreams; - PDFEncryptor m_aPDFEncryptor; + std::unique_ptr<IPDFEncryptor> m_pPDFEncryptor; /* output redirection; e.g. to accumulate content streams for XObjects diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 893471b3a34b..e80af24f1679 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -1454,11 +1454,14 @@ PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, setupDocInfo(); if (xEncryptionMaterialHolder.is()) - m_aPDFEncryptor.prepareEncryption(xEncryptionMaterialHolder, m_aContext.Encryption); + { + m_pPDFEncryptor.reset(new PDFEncryptor); + m_pPDFEncryptor->prepareEncryption(xEncryptionMaterialHolder, m_aContext.Encryption); + } if (m_aContext.Encryption.Encrypt()) { - m_aPDFEncryptor.setupKeysAndCheck(m_aContext.Encryption); + m_pPDFEncryptor->setupKeysAndCheck(m_aContext.Encryption); } // write header @@ -1592,7 +1595,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.Encrypt()) { const sal_Unicode* pStr = rInString.getStr(); sal_Int32 nLen = rInString.getLength(); @@ -1611,7 +1614,7 @@ inline void PDFWriterImpl::appendUnicodeTextStringEncrypt( const OUString& rInSt *pCopy++ = static_cast<sal_uInt8>( aUnChar & 255 ); } //encrypt in place - rtl_cipher_encodeARCFOUR( m_aPDFEncryptor.m_aCipher, m_vEncryptionBuffer.data(), nChars, m_vEncryptionBuffer.data(), nChars); + m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChars, m_vEncryptionBuffer.data(), nChars); //now append, hexadecimal (appendHex), the encrypted result for(int i = 0; i < nChars; i++) appendHex( m_vEncryptionBuffer[i], rOutBuffer ); @@ -1626,12 +1629,12 @@ 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.Encrypt()) { m_vEncryptionBuffer.resize(nChars); //encrypt the string in a buffer, then append it - enableStringEncryption( nInObjectNumber ); - rtl_cipher_encodeARCFOUR(m_aPDFEncryptor.m_aCipher, rInString.data(), nChars, m_vEncryptionBuffer.data(), nChars); + enableStringEncryption(nInObjectNumber); + m_pPDFEncryptor->encrypt(rInString.data(), nChars, m_vEncryptionBuffer.data(), nChars); appendLiteralString( reinterpret_cast<char*>(m_vEncryptionBuffer.data()), nChars, rOutBuffer ); } else @@ -1739,16 +1742,17 @@ bool PDFWriterImpl::writeBufferBytes( const void* pBuffer, sal_uInt64 nBytes ) else { bool buffOK = true; - if (m_aPDFEncryptor.isStreamEncryptionEnabled()) + bool bStreamEncryption = m_pPDFEncryptor && m_pPDFEncryptor->isStreamEncryptionEnabled(); + if (bStreamEncryption) { m_vEncryptionBuffer.resize(nBytes); if (buffOK) { - m_aPDFEncryptor.encrypt(pBuffer, nBytes, m_vEncryptionBuffer.data(), nBytes); + m_pPDFEncryptor->encrypt(pBuffer, nBytes, m_vEncryptionBuffer.data(), nBytes); } } - const void* pWriteBuffer = (m_aPDFEncryptor.isStreamEncryptionEnabled() && buffOK) ? m_vEncryptionBuffer.data() : pBuffer; + const void* pWriteBuffer = (bStreamEncryption && buffOK) ? m_vEncryptionBuffer.data() : pBuffer; m_DocDigest.update(static_cast<unsigned char const*>(pWriteBuffer), static_cast<sal_uInt32>(nBytes)); if (m_aFile.write(pWriteBuffer, nBytes, nWritten) != osl::File::E_None) @@ -6099,7 +6103,7 @@ sal_Int32 PDFWriterImpl::emitEncrypt() // emit the owner password, must not be encrypted aWriter.writeString("/O", reinterpret_cast<char*>(m_aContext.Encryption.OValue.data()), sal_Int32(m_aContext.Encryption.OValue.size())); aWriter.writeString("/U", reinterpret_cast<char*>(m_aContext.Encryption.UValue.data()), sal_Int32(m_aContext.Encryption.UValue.size())); - aWriter.write("/P", m_aPDFEncryptor.getAccessPermissions()); + aWriter.write("/P", m_pPDFEncryptor->getAccessPermissions()); aWriter.endDict(); aWriter.endObject(); @@ -9667,7 +9671,7 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& rObject, bool bMask ) aLine.append( " <" ); if( m_aContext.Encryption.Encrypt() ) { - enableStringEncryption( rObject.m_nObject ); + enableStringEncryption(rObject.m_nObject); //check encryption buffer size m_vEncryptionBuffer.resize(pAccess->GetPaletteEntryCount()*3); int nChar = 0; @@ -9680,7 +9684,7 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& rObject, bool bMask ) m_vEncryptionBuffer[nChar++] = rColor.GetBlue(); } //encrypt the colorspace lookup table - rtl_cipher_encodeARCFOUR(m_aPDFEncryptor.m_aCipher, m_vEncryptionBuffer.data(), nChar, m_vEncryptionBuffer.data(), nChar); + m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChar, m_vEncryptionBuffer.data(), nChar); //now queue the data for output nChar = 0; for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); i++ ) diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx index 547c0fb36896..2f67295b9a7f 100644 --- a/vcl/source/gdi/pdfwriter_impl2.cxx +++ b/vcl/source/gdi/pdfwriter_impl2.cxx @@ -1080,25 +1080,25 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa void PDFWriterImpl::checkAndEnableStreamEncryption(sal_Int32 nObject) { - if (!m_aContext.Encryption.Encrypt()) + if (!m_aContext.Encryption.Encrypt() || !m_pPDFEncryptor) return; - m_aPDFEncryptor.enableStreamEncryption(); - m_aPDFEncryptor.setupEncryption(m_aContext.Encryption.EncryptionKey, nObject); + m_pPDFEncryptor->enableStreamEncryption(); + m_pPDFEncryptor->setupEncryption(m_aContext.Encryption.EncryptionKey, nObject); } void PDFWriterImpl::disableStreamEncryption() { - m_aPDFEncryptor.disableStreamEncryption(); - + if (m_pPDFEncryptor) + m_pPDFEncryptor->disableStreamEncryption(); } void PDFWriterImpl::enableStringEncryption(sal_Int32 nObject) { - if (!m_aContext.Encryption.Encrypt()) + if (!m_aContext.Encryption.Encrypt() || !m_pPDFEncryptor) return; - m_aPDFEncryptor.setupEncryption(m_aContext.Encryption.EncryptionKey, nObject); + m_pPDFEncryptor->setupEncryption(m_aContext.Encryption.EncryptionKey, nObject); } const tools::Long unsetRun[256] =