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;

Reply via email to