include/svl/cryptosign.hxx | 10 +- include/vcl/filter/pdfdocument.hxx | 8 + sfx2/qa/cppunit/data/unsigned.pdf |binary sfx2/qa/cppunit/view.cxx | 25 +++++ svl/source/crypto/cryptosign.cxx | 38 ++++++-- sw/source/core/edit/edfcol.cxx | 4 vcl/source/filter/ipdf/pdfdocument.cxx | 22 +++-- vcl/source/gdi/pdfwriter_impl.cxx | 4 xmlsecurity/inc/documentsignaturemanager.hxx | 6 + xmlsecurity/inc/pdfsignaturehelper.hxx | 8 + xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx | 5 - xmlsecurity/qa/unit/signing/signing.cxx | 55 +++++++++---- xmlsecurity/qa/xmlsec/xmlsec.cxx | 5 - xmlsecurity/source/component/documentdigitalsignatures.cxx | 6 - xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx | 7 + xmlsecurity/source/helper/documentsignaturemanager.cxx | 31 ++++--- xmlsecurity/source/helper/pdfsignaturehelper.cxx | 12 +- xmlsecurity/workben/pdfverify.cxx | 5 - 18 files changed, 180 insertions(+), 71 deletions(-)
New commits: commit 6cb4bbd680421dd6346407f344e82d804bf70324 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Nov 11 11:36:12 2024 +0100 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Mon Nov 11 14:08:40 2024 +0100 cool#9992 lok doc sign, hash extract: time for getCommandValues('Signature') The final goal of this API is to give time & hash information about the PDF signature, so once a 3rd-party produces the PKCS#7 signature, that can be added to the document and the actual PDF sign can be re-run with the same parameters. This commit continues the replacement of XCertificate with svl::crypto::SigningContext up to the point that the timestamp used in svl/ can be exposed on the LOK API. This is done by updating DocumentSignatureManager::add(), PDFSignatureHelper::SetX509Certificate(), vcl::filter::PDFDocument::Sign() and finally the svl::crypto::Signing ctor to work with the signing context instead of an XCertificate directly. Time reporting works now, so add a test for that. The digest part still needs doing. Change-Id: I83f1274cd420b67194b7caf12b1027e623d4f7fe Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176370 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/include/svl/cryptosign.hxx b/include/svl/cryptosign.hxx index a558690bbf48..a547036813c1 100644 --- a/include/svl/cryptosign.hxx +++ b/include/svl/cryptosign.hxx @@ -39,6 +39,7 @@ class SvStream; struct SignatureInformation; namespace svl::crypto { +class SigningContext; /// Converts a hex-encoded string into a byte array. SVL_DLLPUBLIC std::vector<unsigned char> DecodeHexString(std::string_view rHex); @@ -49,8 +50,8 @@ class SVL_DLLPUBLIC Signing { public: - Signing(css::uno::Reference<css::security::XCertificate> xCertificate) : - m_xCertificate(std::move(xCertificate)) + Signing(svl::crypto::SigningContext& rSigningContext) : + m_rSigningContext(rSigningContext) { } @@ -84,7 +85,7 @@ public: private: /// The certificate to use for signing. - const css::uno::Reference<css::security::XCertificate> m_xCertificate; + svl::crypto::SigningContext& m_rSigningContext; /// Data blocks (pointer-size pairs). std::vector<std::pair<const void*, sal_Int32>> m_dataBlocks; @@ -99,7 +100,8 @@ class SVL_DLLPUBLIC SigningContext public: /// If set, the certificate used for signing. css::uno::Reference<css::security::XCertificate> m_xCertificate; - /// If m_xCertificate is not set, the time that would be used. + /// If m_xCertificate is not set, the time that would be used, in milliseconds since the epoch + /// (1970-01-01 UTC). sal_Int64 m_nSignatureTime = 0; }; diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx index 0055ba50071c..c91b2d6cb608 100644 --- a/include/vcl/filter/pdfdocument.hxx +++ b/include/vcl/filter/pdfdocument.hxx @@ -35,6 +35,10 @@ namespace tools { class Rectangle; } +namespace svl::crypto +{ +class SigningContext; +} namespace vcl::filter { @@ -586,8 +590,8 @@ public: void SetSignatureLine(std::vector<sal_Int8>&& rSignatureLine); void SetSignaturePage(size_t nPage); /// Sign the read document with xCertificate in the edit buffer. - bool Sign(const css::uno::Reference<css::security::XCertificate>& xCertificate, - const OUString& rDescription, bool bAdES); + bool Sign(svl::crypto::SigningContext& rSigningContext, const OUString& rDescription, + bool bAdES); /// Serializes the contents of the edit buffer. bool Write(SvStream& rStream); /// Get a list of signatures embedded into this document. diff --git a/sfx2/qa/cppunit/data/unsigned.pdf b/sfx2/qa/cppunit/data/unsigned.pdf new file mode 100644 index 000000000000..64a29a593d16 Binary files /dev/null and b/sfx2/qa/cppunit/data/unsigned.pdf differ diff --git a/sfx2/qa/cppunit/view.cxx b/sfx2/qa/cppunit/view.cxx index 5a6a4be1f2d3..bd8100702be0 100644 --- a/sfx2/qa/cppunit/view.cxx +++ b/sfx2/qa/cppunit/view.cxx @@ -9,6 +9,8 @@ #include <test/unoapi_test.hxx> +#include <boost/property_tree/json_parser.hpp> + #include <com/sun/star/drawing/XDrawView.hpp> #include <com/sun/star/beans/XPropertySet.hpp> @@ -21,6 +23,7 @@ #include <sfx2/bindings.hxx> #include <sfx2/lokhelper.hxx> #include <sfx2/sfxbasemodel.hxx> +#include <tools/json_writer.hxx> using namespace com::sun::star; @@ -107,6 +110,28 @@ CPPUNIT_TEST_FIXTURE(Sfx2ViewTest, testLokHelperAddCertifices) // i.e. the signature status for an opened document was not updated when trusting a CA. CPPUNIT_ASSERT_EQUAL(SignatureState::OK, pObjectShell->GetDocumentSignatureState()); } + +CPPUNIT_TEST_FIXTURE(Sfx2ViewTest, testLokHelperCommandValuesSignature) +{ + // Given an unsigned PDF file: + loadFromFile(u"unsigned.pdf"); + + // When extracting hashes: + tools::JsonWriter aWriter; + SfxLokHelper::getCommandValues(aWriter, ".uno:Signature"); + OString aJson = aWriter.finishAndGetAsOString(); + + // Then make sure that we get a signature time: + CPPUNIT_ASSERT(SfxLokHelper::supportsCommand(u"Signature")); + std::stringstream aStream{ std::string(aJson) }; + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + // Non-zero timestamp: + auto it = aTree.find("signatureTime"); + CPPUNIT_ASSERT(it != aTree.not_found()); + auto nSignatureTime = it->second.get_value<sal_Int64>(); + CPPUNIT_ASSERT(nSignatureTime != 0); +} #endif CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/svl/source/crypto/cryptosign.cxx b/svl/source/crypto/cryptosign.cxx index 3fe6ae90ab34..eb95a4a9e0bf 100644 --- a/svl/source/crypto/cryptosign.cxx +++ b/svl/source/crypto/cryptosign.cxx @@ -950,22 +950,18 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer) return false; #else // Create the PKCS#7 object. - css::uno::Sequence<sal_Int8> aDerEncoded = m_xCertificate->getEncoded(); - if (!aDerEncoded.hasElements()) + css::uno::Sequence<sal_Int8> aDerEncoded; + if (m_rSigningContext.m_xCertificate.is()) { - SAL_WARN("svl.crypto", "Crypto::Signing: empty certificate"); - return false; + aDerEncoded = m_rSigningContext.m_xCertificate->getEncoded(); + if (!aDerEncoded.hasElements()) + { + SAL_WARN("svl.crypto", "Crypto::Signing: empty certificate"); + return false; + } } #if USE_CRYPTO_NSS - CERTCertificate *cert = CERT_DecodeCertFromPackage(reinterpret_cast<char *>(aDerEncoded.getArray()), aDerEncoded.getLength()); - - if (!cert) - { - SAL_WARN("svl.crypto", "CERT_DecodeCertFromPackage failed"); - return false; - } - std::vector<unsigned char> aHashResult; { comphelper::Hash aHash(comphelper::HashType::SHA256); @@ -980,6 +976,24 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer) digest.len = aHashResult.size(); PRTime now = PR_Now(); + + if (!m_rSigningContext.m_xCertificate.is()) + { + // The context unit is milliseconds, PR_Now() unit is microseconds. + m_rSigningContext.m_nSignatureTime = now / 1000; + // No certificate is provided: don't actually sign -- just update the context with the + // parameters for the signing and return. + return false; + } + + CERTCertificate *cert = CERT_DecodeCertFromPackage(reinterpret_cast<char *>(aDerEncoded.getArray()), aDerEncoded.getLength()); + + if (!cert) + { + SAL_WARN("svl.crypto", "CERT_DecodeCertFromPackage failed"); + return false; + } + NSSCMSSignedData *cms_sd(nullptr); NSSCMSSignerInfo *cms_signer(nullptr); NSSCMSMessage *cms_msg = CreateCMSMessage(nullptr, &cms_sd, &cms_signer, cert, &digest); diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 076f1fc3f7d0..d3d9d75063a4 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -1796,7 +1796,9 @@ void SwEditShell::SignParagraph() return; // 3. Sign it. - svl::crypto::Signing signing(xCertificate); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + svl::crypto::Signing signing(aSigningContext); signing.AddDataRange(utf8Text.getStr(), utf8Text.getLength()); OStringBuffer sigBuf; if (!signing.Sign(sigBuf)) diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx index f63853f86835..63c3424be3d1 100644 --- a/vcl/source/filter/ipdf/pdfdocument.cxx +++ b/vcl/source/filter/ipdf/pdfdocument.cxx @@ -855,8 +855,8 @@ void PDFDocument::WriteXRef(sal_uInt64 nXRefOffset, PDFReferenceElement const* p } } -bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificate, - const OUString& rDescription, bool bAdES) +bool PDFDocument::Sign(svl::crypto::SigningContext& rSigningContext, const OUString& rDescription, + bool bAdES) { m_aEditBuffer.Seek(STREAM_SEEK_TO_END); m_aEditBuffer.WriteOString(" "); @@ -922,11 +922,14 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat m_aEditBuffer.WriteOString(aByteRangeBuffer); // Create the PKCS#7 object. - css::uno::Sequence<sal_Int8> aDerEncoded = xCertificate->getEncoded(); - if (!aDerEncoded.hasElements()) + if (rSigningContext.m_xCertificate) { - SAL_WARN("vcl.filter", "PDFDocument::Sign: empty certificate"); - return false; + css::uno::Sequence<sal_Int8> aDerEncoded = rSigningContext.m_xCertificate->getEncoded(); + if (!aDerEncoded.hasElements()) + { + SAL_WARN("vcl.filter", "PDFDocument::Sign: empty certificate"); + return false; + } } m_aEditBuffer.Seek(0); @@ -940,12 +943,15 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat m_aEditBuffer.ReadBytes(aBuffer2.get(), nBufferSize2); OStringBuffer aCMSHexBuffer; - svl::crypto::Signing aSigning(xCertificate); + svl::crypto::Signing aSigning(rSigningContext); aSigning.AddDataRange(aBuffer1.get(), nBufferSize1); aSigning.AddDataRange(aBuffer2.get(), nBufferSize2); if (!aSigning.Sign(aCMSHexBuffer)) { - SAL_WARN("vcl.filter", "PDFDocument::Sign: PDFWriter::Sign() failed"); + if (rSigningContext.m_xCertificate.is()) + { + SAL_WARN("vcl.filter", "PDFDocument::Sign: PDFWriter::Sign() failed"); + } return false; } diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 48f6e19d1ce2..83d1c417e707 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -5776,7 +5776,9 @@ bool PDFWriterImpl::finalizeSignature() } OStringBuffer aCMSHexBuffer; - svl::crypto::Signing aSigning(m_aContext.SignCertificate); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = m_aContext.SignCertificate; + svl::crypto::Signing aSigning(aSigningContext); aSigning.AddDataRange(buffer1.get(), bytesRead1); aSigning.AddDataRange(buffer2.get(), bytesRead2); aSigning.SetSignTSA(m_aContext.SignTSA); diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx index a66d97e3c7dd..1ee3f8b97c9a 100644 --- a/xmlsecurity/inc/documentsignaturemanager.hxx +++ b/xmlsecurity/inc/documentsignaturemanager.hxx @@ -53,6 +53,10 @@ namespace uno class XComponentContext; } } +namespace svl::crypto +{ +class SigningContext; +} class PDFSignatureHelper; class Xmlsec; @@ -93,7 +97,7 @@ public: SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, bool bTempStream); /// Add a new signature, using xCert as a signing certificate, and rDescription as description. - bool add(const css::uno::Reference<css::security::XCertificate>& xCert, + bool add(svl::crypto::SigningContext& rSigningContext, const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant, const OUString& rSignatureLineId = OUString(), diff --git a/xmlsecurity/inc/pdfsignaturehelper.hxx b/xmlsecurity/inc/pdfsignaturehelper.hxx index ea24685d2ae4..a20598131db1 100644 --- a/xmlsecurity/inc/pdfsignaturehelper.hxx +++ b/xmlsecurity/inc/pdfsignaturehelper.hxx @@ -37,6 +37,10 @@ namespace xml::crypto class XSecurityEnvironment; } } +namespace svl::crypto +{ +class SigningContext; +} class SvStream; /// Handles signatures of a PDF file. @@ -44,7 +48,7 @@ class XMLSECURITY_DLLPUBLIC PDFSignatureHelper { SignatureInformations m_aSignatureInfos; - css::uno::Reference<css::security::XCertificate> m_xCertificate; + svl::crypto::SigningContext* m_pSigningContext = nullptr; OUString m_aDescription; public: @@ -59,7 +63,7 @@ public: /// Return the ID of the next created signature. sal_Int32 GetNewSecurityId() const; /// Certificate to be used next time signing is performed. - void SetX509Certificate(const css::uno::Reference<css::security::XCertificate>& xCertificate); + void SetX509Certificate(svl::crypto::SigningContext& rSigningContext); /// Comment / reason to be used next time signing is performed. void SetDescription(const OUString& rDescription); /// Append a new signature at the end of xInputStream. diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx index 46981b250a6f..238ab2f04b96 100644 --- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx +++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx @@ -29,6 +29,7 @@ #include <unotools/ucbstreamhelper.hxx> #include <vcl/filter/pdfdocument.hxx> #include <vcl/filter/PDFiumLibrary.hxx> +#include <svl/cryptosign.hxx> #include <documentsignaturemanager.hxx> #include <pdfsignaturehelper.hxx> @@ -148,7 +149,9 @@ bool PDFSigningTest::sign(const OUString& rInURL, const OUString& rOutURL, } else { - bool bSignResult = aDocument.Sign(cert, "test", /*bAdES=*/true); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = cert; + bool bSignResult = aDocument.Sign(aSigningContext, "test", /*bAdES=*/true); #ifdef _WIN32 if (!bSignResult) { diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx index cf33c8de030b..f2c6ddcfa714 100644 --- a/xmlsecurity/qa/unit/signing/signing.cxx +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -160,7 +160,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testDescription) return; OUString aDescription("SigningTest::testDescription"); sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, aDescription, nSecurityId, false); // Read back the signature and make sure that the description survives the roundtrip. aManager.read(/*bUseTempStream=*/true); @@ -191,7 +193,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testECDSA) if (!xCertificate.is()) return; sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, false); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, "", nSecurityId, false); // Read back the signature and make sure that it's valid. aManager.read(/*bUseTempStream=*/true); @@ -225,7 +229,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testECDSAOOXML) if (!xCertificate.is()) return; sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); // Read back the signature and make sure that it's valid. @@ -260,7 +266,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testECDSAPDF) if (!xCertificate.is()) return; sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/true); // Read back the signature and make sure that it's valid. @@ -302,7 +310,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLDescription) return; OUString aDescription("SigningTest::testDescription"); sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, aDescription, nSecurityId, false); // Read back the signature and make sure that the description survives the roundtrip. aManager.read(/*bUseTempStream=*/true); @@ -335,7 +345,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLAppend) if (!xCertificate.is()) return; sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, OUString(), nSecurityId, false); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, OUString(), nSecurityId, false); // Read back the signatures and make sure that we have the expected amount. aManager.read(/*bUseTempStream=*/true); @@ -859,7 +871,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESNotype) if (!xCertificate.is()) return; sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, /*bAdESCompliant=*/true); // Write to storage. @@ -914,7 +928,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testXAdES) if (!xCertificate.is()) return; sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, /*bAdESCompliant=*/true); // Write to storage. @@ -968,7 +984,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_ODT) if (!xCertificate.is()) return; sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, /*bAdESCompliant=*/true); // Read back the signature and make sure that it's valid. @@ -981,7 +999,7 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_ODT) rInformations[0].nStatus); } - aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + aManager.add(aSigningContext, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, /*bAdESCompliant=*/true); aManager.read(/*bUseTempStream=*/true); { @@ -992,7 +1010,7 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_ODT) rInformations[1].nStatus); } - aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + aManager.add(aSigningContext, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, /*bAdESCompliant=*/true); aManager.read(/*bUseTempStream=*/true); { @@ -1041,7 +1059,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_OOXML) return; sal_Int32 nSecurityId; - aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aManager.add(aSigningContext, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); aManager.read(/*bUseTempStream=*/true); { std::vector<SignatureInformation>& rInformations @@ -1051,7 +1071,7 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_OOXML) rInformations[0].nStatus); } - aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); + aManager.add(aSigningContext, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); aManager.read(/*bUseTempStream=*/true); { std::vector<SignatureInformation>& rInformations @@ -1061,7 +1081,7 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_OOXML) rInformations[1].nStatus); } - aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); + aManager.add(aSigningContext, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); aManager.read(/*bUseTempStream=*/true); { std::vector<SignatureInformation>& rInformations @@ -1185,11 +1205,14 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testImplicitScriptSign) OUString aDescription; sal_Int32 nSecurityId; bool bAdESCompliant = true; - aScriptManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, bAdESCompliant); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + aScriptManager.add(aSigningContext, mxSecurityContext, aDescription, nSecurityId, + bAdESCompliant); aScriptManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); aScriptManager.write(bAdESCompliant); aManager.setScriptingSignatureStream(xScriptingStream); - aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, bAdESCompliant); + aManager.add(aSigningContext, mxSecurityContext, aDescription, nSecurityId, bAdESCompliant); aManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); aManager.write(bAdESCompliant); diff --git a/xmlsecurity/qa/xmlsec/xmlsec.cxx b/xmlsecurity/qa/xmlsec/xmlsec.cxx index 9524b61ca5e8..9d985f552135 100644 --- a/xmlsecurity/qa/xmlsec/xmlsec.cxx +++ b/xmlsecurity/qa/xmlsec/xmlsec.cxx @@ -14,6 +14,7 @@ #include <comphelper/storagehelper.hxx> #include <sfx2/lokhelper.hxx> +#include <svl/cryptosign.hxx> #include <documentsignaturemanager.hxx> @@ -82,7 +83,9 @@ CPPUNIT_TEST_FIXTURE(Test, testInsertPrivateKey) // Get the certificate flags, the certificate chooser dialog does this: xSecurityEnvironment->getCertificateCharacters(xCertificate); sal_Int32 nSecurityId; - CPPUNIT_ASSERT(aManager.add(xCertificate, xSecurityContext, OUString(), nSecurityId, false)); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + CPPUNIT_ASSERT(aManager.add(aSigningContext, xSecurityContext, OUString(), nSecurityId, false)); // Then make sure that signing succeeds: aManager.read(/*bUseTempStream=*/true); diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx index 394cefe682ce..848a8f7623cd 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.cxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -331,7 +331,9 @@ sal_Bool DocumentDigitalSignatures::signSignatureLine( xSecurityContext = aSignatureManager.getSecurityContext(); sal_Int32 nSecurityId; - bool bSuccess = aSignatureManager.add(xCertificate, xSecurityContext, aComment, nSecurityId, + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + bool bSuccess = aSignatureManager.add(aSigningContext, xSecurityContext, aComment, nSecurityId, true, aSignatureLineId, xValidGraphic, xInvalidGraphic); if (!bSuccess) return false; @@ -923,7 +925,7 @@ bool DocumentDigitalSignatures::signWithCertificateImpl( sal_Int32 nSecurityId; - bool bSuccess = aSignatureManager.add(rSigningContext.m_xCertificate, xSecurityContext, "", nSecurityId, true); + bool bSuccess = aSignatureManager.add(rSigningContext, xSecurityContext, "", nSecurityId, true); if (!bSuccess) return false; diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx index fcfdfd04c0d5..1d613b5576d0 100644 --- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -68,6 +68,7 @@ #include <vcl/svapp.hxx> #include <unotools/configitem.hxx> #include <sfx2/viewsh.hxx> +#include <svl/cryptosign.hxx> #ifdef _WIN32 #include <o3tl/char16_t2wchar_t.hxx> @@ -550,9 +551,11 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void) { sal_Int32 nSecurityId; + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = aChooser->GetSelectedCertificates()[0]; if (moScriptSignatureManager) { - if (!moScriptSignatureManager->add(aChooser->GetSelectedCertificates()[0], + if (!moScriptSignatureManager->add(aSigningContext, aChooser->GetSelectedSecurityContext(), aChooser->GetDescription(), nSecurityId, m_bAdESCompliant)) @@ -566,7 +569,7 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void) maSignatureManager.setScriptingSignatureStream(moScriptSignatureManager->getSignatureStream()); } - if (!maSignatureManager.add(aChooser->GetSelectedCertificates()[0], aChooser->GetSelectedSecurityContext(), + if (!maSignatureManager.add(aSigningContext, aChooser->GetSelectedSecurityContext(), aChooser->GetDescription(), nSecurityId, m_bAdESCompliant)) return; mbSignaturesChanged = true; diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx index 9ed1cef7dcff..8a6060121c55 100644 --- a/xmlsecurity/source/helper/documentsignaturemanager.cxx +++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx @@ -42,6 +42,7 @@ #include <sal/log.hxx> #include <tools/datetime.hxx> #include <o3tl/string_view.hxx> +#include <svl/cryptosign.hxx> #include <certificate.hxx> #include <biginteger.hxx> @@ -326,20 +327,23 @@ SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int3 } bool DocumentSignatureManager::add( - const uno::Reference<security::XCertificate>& xCert, + svl::crypto::SigningContext& rSigningContext, const uno::Reference<xml::crypto::XXMLSecurityContext>& xSecurityContext, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant, const OUString& rSignatureLineId, const Reference<XGraphic>& xValidGraphic, const Reference<XGraphic>& xInvalidGraphic) { - if (!xCert.is()) + uno::Reference<security::XCertificate> xCert = rSigningContext.m_xCertificate; + uno::Reference<lang::XServiceInfo> xServiceInfo(xSecurityContext, uno::UNO_QUERY); + if (!xCert.is() + && xServiceInfo->getImplementationName() + == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl") { SAL_WARN("xmlsecurity.helper", "no certificate selected"); return false; } // GPG or X509 key? - uno::Reference<lang::XServiceInfo> xServiceInfo(xSecurityContext, uno::UNO_QUERY); if (xServiceInfo->getImplementationName() == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl") { @@ -373,28 +377,31 @@ bool DocumentSignatureManager::add( } else { - OUString aCertSerial = xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()); - if (aCertSerial.isEmpty()) - { - SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!"); - return false; - } - if (!mxStore.is()) { // Something not ZIP based, try PDF. nSecurityId = getPDFSignatureHelper().GetNewSecurityId(); - getPDFSignatureHelper().SetX509Certificate(xCert); + getPDFSignatureHelper().SetX509Certificate(rSigningContext); getPDFSignatureHelper().SetDescription(rDescription); uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY); if (!getPDFSignatureHelper().Sign(mxModel, xInputStream, bAdESCompliant)) { - SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed"); + if (rSigningContext.m_xCertificate.is()) + { + SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed"); + } return false; } return true; } + OUString aCertSerial = xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()); + if (aCertSerial.isEmpty()) + { + SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!"); + return false; + } + maSignatureHelper.StartMission(xSecurityContext); nSecurityId = maSignatureHelper.GetNewSecurityId(); diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx index 3c0084c8b4e2..c46313a9da9a 100644 --- a/xmlsecurity/source/helper/pdfsignaturehelper.cxx +++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx @@ -536,10 +536,9 @@ PDFSignatureHelper::GetDocumentSignatureInformations( sal_Int32 PDFSignatureHelper::GetNewSecurityId() const { return m_aSignatureInfos.size(); } -void PDFSignatureHelper::SetX509Certificate( - const uno::Reference<security::XCertificate>& xCertificate) +void PDFSignatureHelper::SetX509Certificate(svl::crypto::SigningContext& rSigningContext) { - m_xCertificate = xCertificate; + m_pSigningContext = &rSigningContext; } void PDFSignatureHelper::SetDescription(const OUString& rDescription) @@ -571,9 +570,12 @@ bool PDFSignatureHelper::Sign(const uno::Reference<frame::XModel>& xModel, aDocument.SetSignatureLine(std::move(aSignatureLineShape)); } - if (!aDocument.Sign(m_xCertificate, m_aDescription, bAdES)) + if (!m_pSigningContext || !aDocument.Sign(*m_pSigningContext, m_aDescription, bAdES)) { - SAL_WARN("xmlsecurity.helper", "failed to sign"); + if (m_pSigningContext && m_pSigningContext->m_xCertificate.is()) + { + SAL_WARN("xmlsecurity.helper", "failed to sign"); + } return false; } diff --git a/xmlsecurity/workben/pdfverify.cxx b/xmlsecurity/workben/pdfverify.cxx index 361e0ae4ae1e..df61168fa77c 100644 --- a/xmlsecurity/workben/pdfverify.cxx +++ b/xmlsecurity/workben/pdfverify.cxx @@ -26,6 +26,7 @@ #include <vcl/filter/pdfdocument.hxx> #include <comphelper/scopeguard.hxx> #include <svl/sigstruct.hxx> +#include <svl/cryptosign.hxx> #include <pdfsignaturehelper.hxx> @@ -183,7 +184,9 @@ int pdfVerify(int nArgc, char** pArgv) SAL_WARN("xmlsecurity.workben", "no signing certificates found"); return 1; } - if (!aDocument.Sign(aCertificates[0], "pdfverify", /*bAdES=*/true)) + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = aCertificates[0]; + if (!aDocument.Sign(aSigningContext, "pdfverify", /*bAdES=*/true)) { SAL_WARN("xmlsecurity.workben", "failed to sign"); return 1;