[Libreoffice-commits] core.git: include/svl xmlsecurity/inc xmlsecurity/qa xmlsecurity/source

Miklos Vajna vmiklos at collabora.co.uk
Fri May 18 07:36:32 UTC 2018


 include/svl/sigstruct.hxx                                         |   16 ++
 xmlsecurity/inc/certificate.hxx                                   |   11 +
 xmlsecurity/inc/xmlsignaturehelper.hxx                            |    3 
 xmlsecurity/inc/xsecctl.hxx                                       |    9 +
 xmlsecurity/qa/unit/signing/data/cert8.db                         |binary
 xmlsecurity/qa/unit/signing/data/key3.db                          |binary
 xmlsecurity/qa/unit/signing/signing.cxx                           |   79 +++++++---
 xmlsecurity/source/gpg/CertificateImpl.cxx                        |    6 
 xmlsecurity/source/gpg/CertificateImpl.hxx                        |    2 
 xmlsecurity/source/helper/documentsignaturemanager.cxx            |    7 
 xmlsecurity/source/helper/xmlsignaturehelper.cxx                  |    6 
 xmlsecurity/source/helper/xsecctl.cxx                             |   29 +++
 xmlsecurity/source/helper/xsecparser.cxx                          |    7 
 xmlsecurity/source/helper/xsecsign.cxx                            |    5 
 xmlsecurity/source/helper/xsecverify.cxx                          |    8 +
 xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx |    6 
 xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx |    3 
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx         |   15 +
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx         |    3 
 19 files changed, 188 insertions(+), 27 deletions(-)

New commits:
commit fd1bc178b02e05cd12ec784ff87f5c97069bc5f5
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue May 15 22:16:42 2018 +0200

    tdf#109180 xmlsecurity nss: fix signing with ECDSA key
    
    Using an ECDSA key but writing RSA URIs would fail later in libxmlsec.
    
    Also fix up CppunitTest_xmlsecurity_signing (env vars were set too
    late), so that the new testcase actually fails without the fix.
    
    Change-Id: I9e584844d5cd046952b2f19130aeaa5a765bfc0a
    Reviewed-on: https://gerrit.libreoffice.org/54400
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/include/svl/sigstruct.hxx b/include/svl/sigstruct.hxx
index de5a03497dc4..414e0cd88a41 100644
--- a/include/svl/sigstruct.hxx
+++ b/include/svl/sigstruct.hxx
@@ -67,6 +67,19 @@ struct SignatureReferenceInformation
 
 typedef ::std::vector< SignatureReferenceInformation > SignatureReferenceInformations;
 
+namespace svl
+{
+namespace crypto
+{
+/// Specifies the algorithm used for signature generation and validation.
+enum class SignatureMethodAlgorithm
+{
+    RSA,
+    ECDSA
+};
+}
+}
+
 struct SignatureInformation
 {
     sal_Int32 nSecurityId;
@@ -123,6 +136,8 @@ struct SignatureInformation
     /// The certificate owner (aka subject).
     OUString ouSubject;
 
+    svl::crypto::SignatureMethodAlgorithm eAlgorithmID;
+
     SignatureInformation( sal_Int32 nId )
     {
         nSecurityId = nId;
@@ -130,6 +145,7 @@ struct SignatureInformation
         nDigestID = 0;
         bHasSigningCertificate = false;
         bPartialDocumentSignature = false;
+        eAlgorithmID = svl::crypto::SignatureMethodAlgorithm::RSA;
     }
 };
 
diff --git a/xmlsecurity/inc/certificate.hxx b/xmlsecurity/inc/certificate.hxx
index 0698e91f422f..61ad532fdd6b 100644
--- a/xmlsecurity/inc/certificate.hxx
+++ b/xmlsecurity/inc/certificate.hxx
@@ -14,6 +14,14 @@
 
 #include <com/sun/star/uno/Sequence.hxx>
 
+namespace svl
+{
+namespace crypto
+{
+enum class SignatureMethodAlgorithm;
+}
+}
+
 namespace xmlsecurity
 {
 
@@ -27,6 +35,9 @@ public:
     /// @throws css::uno::RuntimeException
     virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() = 0;
 
+    /// Same as getSubjectPublicKeyAlgorithm(), but returns an ID, not a string.
+    virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() = 0;
+
 protected:
     ~Certificate() noexcept = default;
 };
diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx
index 880293f68669..8e4bd48d8af8 100644
--- a/xmlsecurity/inc/xmlsignaturehelper.hxx
+++ b/xmlsecurity/inc/xmlsignaturehelper.hxx
@@ -119,7 +119,8 @@ public:
         certificate.
      */
     void SetX509Certificate(sal_Int32 nSecurityId, const OUString& ouX509IssuerName,
-        const OUString& ouX509SerialNumber, const OUString& ouX509Cert, const OUString& ouX509CertDigest);
+        const OUString& ouX509SerialNumber, const OUString& ouX509Cert, const OUString& ouX509CertDigest,
+        svl::crypto::SignatureMethodAlgorithm eAlgorithmID);
 
     void AddEncapsulatedX509Certificate(const OUString& ouEncapsulatedX509Certificate);
 
diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx
index cc3b11db80a7..c01284bea6e7 100644
--- a/xmlsecurity/inc/xsecctl.hxx
+++ b/xmlsecurity/inc/xsecctl.hxx
@@ -57,6 +57,9 @@
 #define ALGO_RSASHA1       "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
 #define ALGO_RSASHA256     "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
 #define ALGO_RSASHA512     "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
+#define ALGO_ECDSASHA1     "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"
+#define ALGO_ECDSASHA256   "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"
+#define ALGO_ECDSASHA512   "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"
 #define ALGO_XMLDSIGSHA1   "http://www.w3.org/2000/09/xmldsig#sha1"
 #define ALGO_XMLDSIGSHA256 "http://www.w3.org/2001/04/xmlenc#sha256"
 #define ALGO_XMLDSIGSHA512 "http://www.w3.org/2001/04/xmlenc#sha512"
@@ -66,6 +69,7 @@ class XSecParser;
 class XMLDocumentWrapper_XmlSecImpl;
 class SAXEventKeeperImpl;
 class XMLSignatureHelper;
+namespace svl { namespace crypto { enum class SignatureMethodAlgorithm; } }
 
 class InternalSignatureInformation
 {
@@ -251,6 +255,8 @@ private:
      * For signature verification
      */
     void addSignature();
+    /// Sets algorithm from <SignatureMethod Algorithm="...">.
+    void setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID);
     void switchGpgSignature();
     void addReference(
         const OUString& ouUri,
@@ -338,7 +344,8 @@ public:
         const OUString& ouX509IssuerName,
         const OUString& ouX509SerialNumber,
         const OUString& ouX509Cert,
-        const OUString& ouX509CertDigest);
+        const OUString& ouX509CertDigest,
+        svl::crypto::SignatureMethodAlgorithm eAlgorithmID);
 
     void addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate);
 
diff --git a/xmlsecurity/qa/unit/signing/data/cert8.db b/xmlsecurity/qa/unit/signing/data/cert8.db
index 8354fd309e3a..07afe1566989 100644
Binary files a/xmlsecurity/qa/unit/signing/data/cert8.db and b/xmlsecurity/qa/unit/signing/data/cert8.db differ
diff --git a/xmlsecurity/qa/unit/signing/data/key3.db b/xmlsecurity/qa/unit/signing/data/key3.db
index 8ab32c28d584..fac36c06870a 100644
Binary files a/xmlsecurity/qa/unit/signing/data/key3.db and b/xmlsecurity/qa/unit/signing/data/key3.db differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx
index 9d1f9240caef..31382925a092 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -41,6 +41,7 @@
 #include <documentsignaturehelper.hxx>
 #include <xmlsignaturehelper.hxx>
 #include <documentsignaturemanager.hxx>
+#include <certificate.hxx>
 
 using namespace com::sun::star;
 
@@ -64,6 +65,7 @@ public:
     void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override;
 
     void testDescription();
+    void testECDSA();
     /// Test a typical ODF where all streams are signed.
     void testODFGood();
     /// Test a typical broken ODF signature where one stream is corrupted.
@@ -113,6 +115,7 @@ public:
 #endif
     CPPUNIT_TEST_SUITE(SigningTest);
     CPPUNIT_TEST(testDescription);
+    CPPUNIT_TEST(testECDSA);
     CPPUNIT_TEST(testODFGood);
     CPPUNIT_TEST(testODFBroken);
     CPPUNIT_TEST(testODFNo);
@@ -147,7 +150,7 @@ public:
 private:
     void createDoc(const OUString& rURL);
     void createCalc(const OUString& rURL);
-    uno::Reference<security::XCertificate> getCertificate(DocumentSignatureManager& rSignatureManager);
+    uno::Reference<security::XCertificate> getCertificate(DocumentSignatureManager& rSignatureManager, svl::crypto::SignatureMethodAlgorithm eAlgo);
 };
 
 SigningTest::SigningTest()
@@ -158,11 +161,6 @@ void SigningTest::setUp()
 {
     test::BootstrapFixture::setUp();
 
-    mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
-    mxDesktop.set(frame::Desktop::create(mxComponentContext));
-    mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext);
-    mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
-
     OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
     OUString aTargetDir = m_directories.getURLFromWorkdir(
                               "/CppunitTest/xmlsecurity_signing.test.user/");
@@ -184,6 +182,12 @@ void SigningTest::setUp()
     osl_setEnvironment(mozCertVar.pData, aTargetPath.pData);
     OUString gpgHomeVar("GNUPGHOME");
     osl_setEnvironment(gpgHomeVar.pData, aTargetPath.pData);
+
+    // Initialize crypto after setting up the environment variables.
+    mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
+    mxDesktop.set(frame::Desktop::create(mxComponentContext));
+    mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext);
+    mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
 }
 
 void SigningTest::tearDown()
@@ -214,16 +218,19 @@ void SigningTest::createCalc(const OUString& rURL)
         mxComponent = loadFromDesktop(rURL, "com.sun.star.sheet.SpreadsheetDocument");
 }
 
-uno::Reference<security::XCertificate> SigningTest::getCertificate(DocumentSignatureManager& rSignatureManager)
+uno::Reference<security::XCertificate> SigningTest::getCertificate(DocumentSignatureManager& rSignatureManager, svl::crypto::SignatureMethodAlgorithm eAlgo)
 {
-    uno::Reference<security::XCertificate> xCertificate;
-
     uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment = rSignatureManager.getSecurityEnvironment();
     uno::Sequence<uno::Reference<security::XCertificate>> aCertificates = xSecurityEnvironment->getPersonalCertificates();
-    if (!aCertificates.hasElements())
-        return xCertificate;
 
-    return aCertificates[0];
+    for (const auto& xCertificate : aCertificates)
+    {
+        auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCertificate.get());
+        CPPUNIT_ASSERT(pCertificate);
+        if (pCertificate->getSignatureMethodAlgorithm() == eAlgo)
+            return xCertificate;
+    }
+    return uno::Reference<security::XCertificate>();
 }
 
 void SigningTest::testDescription()
@@ -246,7 +253,7 @@ void SigningTest::testDescription()
     aManager.maSignatureHelper.SetStorage(xStorage, "1.2");
 
     // Then add a signature document.
-    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager);
+    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
     if (!xCertificate.is())
         return;
     OUString aDescription("SigningTest::testDescription");
@@ -260,6 +267,42 @@ void SigningTest::testDescription()
     CPPUNIT_ASSERT_EQUAL(aDescription, rInformations[0].ouDescription);
 }
 
+void SigningTest::testECDSA()
+{
+    // Create an empty document and store it to a tempfile, finally load it as a storage.
+    createDoc("");
+
+    utl::TempFile aTempFile;
+    aTempFile.EnableKillingFile();
+    uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+    utl::MediaDescriptor aMediaDescriptor;
+    aMediaDescriptor["FilterName"] <<= OUString("writer8");
+    xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+    DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+    CPPUNIT_ASSERT(aManager.init());
+    uno::Reference <embed::XStorage> xStorage = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+    CPPUNIT_ASSERT(xStorage.is());
+    aManager.mxStore = xStorage;
+    aManager.maSignatureHelper.SetStorage(xStorage, "1.2");
+
+    // Then add a signature.
+    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA);
+    if (!xCertificate.is())
+        return;
+    OUString aDescription;
+    sal_Int32 nSecurityId;
+    aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false);
+
+    // Read back the signature and make sure that it's valid.
+    aManager.read(/*bUseTempStream=*/true);
+    std::vector<SignatureInformation>& rInformations = aManager.maCurrentSignatureInformations;
+    CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+    // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was
+    // broken.
+    CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, rInformations[0].nStatus);
+}
+
 void SigningTest::testOOXMLDescription()
 {
     // Create an empty document and store it to a tempfile, finally load it as a storage.
@@ -280,7 +323,7 @@ void SigningTest::testOOXMLDescription()
     aManager.maSignatureHelper.SetStorage(xStorage, "1.2");
 
     // Then add a document signature.
-    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager);
+    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
     if (!xCertificate.is())
         return;
     OUString aDescription("SigningTest::testDescription");
@@ -314,7 +357,7 @@ void SigningTest::testOOXMLAppend()
     CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
 
     // Then add a second document signature.
-    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager);
+    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
     if (!xCertificate.is())
         return;
     sal_Int32 nSecurityId;
@@ -346,7 +389,7 @@ void SigningTest::testOOXMLRemove()
     CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
 
     // Then remove the last added signature.
-    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager);
+    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
     if (!xCertificate.is())
         return;
     aManager.remove(0);
@@ -377,7 +420,7 @@ void SigningTest::testOOXMLRemoveAll()
     CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
 
     // Then remove the only signature in the document.
-    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager);
+    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
     if (!xCertificate.is())
         return;
     aManager.remove(0);
@@ -625,7 +668,7 @@ void SigningTest::testXAdES()
     aManager.maSignatureHelper.SetStorage(xStorage, "1.2");
 
     // Create a signature.
-    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager);
+    uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
     if (!xCertificate.is())
         return;
     sal_Int32 nSecurityId;
diff --git a/xmlsecurity/source/gpg/CertificateImpl.cxx b/xmlsecurity/source/gpg/CertificateImpl.cxx
index 81dafbe9e472..4a2934a9779c 100644
--- a/xmlsecurity/source/gpg/CertificateImpl.cxx
+++ b/xmlsecurity/source/gpg/CertificateImpl.cxx
@@ -17,6 +17,7 @@
 
 #include <com/sun/star/security/KeyUsage.hpp>
 #include <officecfg/Office/Common.hxx>
+#include <svl/sigstruct.hxx>
 
 #include <gpgme.h>
 #include <context.h>
@@ -171,6 +172,11 @@ Sequence<sal_Int8> CertificateImpl::getSHA256Thumbprint()
         keyId, strlen(keyId)+1);
 }
 
+svl::crypto::SignatureMethodAlgorithm CertificateImpl::getSignatureMethodAlgorithm()
+{
+    return svl::crypto::SignatureMethodAlgorithm::RSA;
+}
+
 Sequence< sal_Int8 > SAL_CALL CertificateImpl::getMD5Thumbprint()
 {
     // This is mapped to the shorter keyID for gpg
diff --git a/xmlsecurity/source/gpg/CertificateImpl.hxx b/xmlsecurity/source/gpg/CertificateImpl.hxx
index 91d0d1308bfc..e9839c31f013 100644
--- a/xmlsecurity/source/gpg/CertificateImpl.hxx
+++ b/xmlsecurity/source/gpg/CertificateImpl.hxx
@@ -88,6 +88,8 @@ public:
 
     /// @see xmlsecurity::Certificate::getSHA256Thumbprint().
     virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override;
+    /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm().
+    virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override;
     virtual css::security::CertificateKind SAL_CALL getCertificateKind() override;
 
     // Helper methods
diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx
index 8d6f2b3f6ed1..af93c2e90fb3 100644
--- a/xmlsecurity/source/helper/documentsignaturemanager.cxx
+++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx
@@ -338,18 +338,23 @@ bool DocumentSignatureManager::add(
         comphelper::Base64::encode(aStrBuffer, xCert->getEncoded());
 
         OUString aCertDigest;
+        svl::crypto::SignatureMethodAlgorithm eAlgorithmID
+            = svl::crypto::SignatureMethodAlgorithm::RSA;
         if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
         {
             OUStringBuffer aBuffer;
             comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint());
             aCertDigest = aBuffer.makeStringAndClear();
+
+            eAlgorithmID = pCertificate->getSignatureMethodAlgorithm();
         }
         else
             SAL_WARN("xmlsecurity.helper",
                      "XCertificate implementation without an xmlsecurity::Certificate one");
 
         maSignatureHelper.SetX509Certificate(nSecurityId, xCert->getIssuerName(), aCertSerial,
-                                             aStrBuffer.makeStringAndClear(), aCertDigest);
+                                             aStrBuffer.makeStringAndClear(), aCertDigest,
+                                             eAlgorithmID);
     }
 
     uno::Sequence<uno::Reference<security::XCertificate>> aCertPath
diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
index 9745fa19304b..1767b897c7ff 100644
--- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
@@ -109,14 +109,16 @@ void XMLSignatureHelper::SetX509Certificate(
         const OUString& ouX509IssuerName,
         const OUString& ouX509SerialNumber,
         const OUString& ouX509Cert,
-        const OUString& ouX509CertDigest)
+        const OUString& ouX509CertDigest,
+        svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
 {
     mpXSecController->setX509Certificate(
         nSecurityId,
         ouX509IssuerName,
         ouX509SerialNumber,
         ouX509Cert,
-        ouX509CertDigest);
+        ouX509CertDigest,
+        eAlgorithmID);
 }
 
 void XMLSignatureHelper::AddEncapsulatedX509Certificate(const OUString& ouEncapsulatedX509Certificate)
diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx
index 96d04436341f..c10e9f0d3c50 100644
--- a/xmlsecurity/source/helper/xsecctl.cxx
+++ b/xmlsecurity/source/helper/xsecctl.cxx
@@ -68,9 +68,32 @@ OUString getDigestURI(sal_Int32 nID)
             return OUString(ALGO_XMLDSIGSHA1);
     }
 }
-OUString getSignatureURI(sal_Int32 nID)
+OUString getSignatureURI(svl::crypto::SignatureMethodAlgorithm eAlgorithm, sal_Int32 nDigestID)
 {
-    switch( nID )
+    OUString aRet;
+
+    if (eAlgorithm == svl::crypto::SignatureMethodAlgorithm::ECDSA)
+    {
+        switch (nDigestID)
+        {
+            case cssxc::DigestID::SHA1:
+                aRet = ALGO_ECDSASHA1;
+                break;
+            case cssxc::DigestID::SHA256:
+                aRet = ALGO_ECDSASHA256;
+                break;
+            case cssxc::DigestID::SHA512:
+                aRet = ALGO_ECDSASHA512;
+                break;
+            default:
+                aRet = ALGO_ECDSASHA1;
+                break;
+        }
+    }
+    if (!aRet.isEmpty())
+        return aRet;
+
+    switch (nDigestID)
     {
         case cssxc::DigestID::SHA1:
             return OUString(ALGO_RSASHA1);
@@ -608,7 +631,7 @@ void XSecController::exportSignature(
             // SignatureMethod:Algorithm should be the corresponding one.
             pAttributeList->AddAttribute(
                 "Algorithm",
-                getSignatureURI(vReferenceInfors[0].nDigestID));
+                getSignatureURI(signatureInfo.eAlgorithmID, vReferenceInfors[0].nDigestID));
             xDocumentHandler->startElement( "SignatureMethod", cssu::Reference< cssxs::XAttributeList > (pAttributeList) );
             xDocumentHandler->endElement( "SignatureMethod" );
 
diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx
index 50c13dc95bee..2ec9c4082576 100644
--- a/xmlsecurity/source/helper/xsecparser.cxx
+++ b/xmlsecurity/source/helper/xsecparser.cxx
@@ -114,6 +114,13 @@ void SAL_CALL XSecParser::startElement(
                 m_pXSecController->setId( ouIdAttr );
             }
         }
+        else if (aName == "SignatureMethod")
+        {
+            OUString ouAlgorithm = xAttribs->getValueByName("Algorithm");
+            if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256
+                || ouAlgorithm == ALGO_ECDSASHA512)
+                m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA);
+        }
         else if ( aName == "Reference" )
         {
             OUString ouUri = xAttribs->getValueByName("URI");
diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx
index b5e50f3c8bf0..bd1873b4ddf7 100644
--- a/xmlsecurity/source/helper/xsecsign.cxx
+++ b/xmlsecurity/source/helper/xsecsign.cxx
@@ -19,6 +19,7 @@
 
 
 #include <xsecctl.hxx>
+#include <certificate.hxx>
 
 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
@@ -201,7 +202,8 @@ void XSecController::setX509Certificate(
     const OUString& ouX509IssuerName,
     const OUString& ouX509SerialNumber,
     const OUString& ouX509Cert,
-    const OUString& ouX509CertDigest)
+    const OUString& ouX509CertDigest,
+    svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
 {
     int index = findSignatureInfor( nSecurityId );
 
@@ -212,6 +214,7 @@ void XSecController::setX509Certificate(
         isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber;
         isi.signatureInfor.ouX509Certificate = ouX509Cert;
         isi.signatureInfor.ouCertDigest = ouX509CertDigest;
+        isi.signatureInfor.eAlgorithmID = eAlgorithmID;
         m_vInternalSignatureInformations.push_back( isi );
     }
     else
diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx
index 1cece7fb4b8b..5a23de6f2619 100644
--- a/xmlsecurity/source/helper/xsecverify.cxx
+++ b/xmlsecurity/source/helper/xsecverify.cxx
@@ -118,6 +118,14 @@ void XSecController::addSignature()
     m_vInternalSignatureInformations.push_back( isi );
 }
 
+void XSecController::setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
+{
+    if (m_vInternalSignatureInformations.empty())
+        return;
+
+    m_vInternalSignatureInformations.back().signatureInfor.eAlgorithmID = eAlgorithmID;
+}
+
 void XSecController::switchGpgSignature()
 {
 #if HAVE_FEATURE_GPGME
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
index 24773a0c8d9b..d213f21631f5 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
@@ -38,6 +38,7 @@
 #include <utility>
 #include <vector>
 #include <tools/time.hxx>
+#include <svl/sigstruct.hxx>
 
 using namespace com::sun::star;
 using namespace ::com::sun::star::uno ;
@@ -570,6 +571,11 @@ uno::Sequence<sal_Int8> X509Certificate_MSCryptImpl::getSHA256Thumbprint()
     return getThumbprint(m_pCertContext, CERT_SHA256_HASH_PROP_ID);
 }
 
+svl::crypto::SignatureMethodAlgorithm X509Certificate_MSCryptImpl::getSignatureMethodAlgorithm()
+{
+    return svl::crypto::SignatureMethodAlgorithm::RSA;
+}
+
 css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSHA1Thumbprint()
 {
     return getThumbprint(m_pCertContext, CERT_SHA1_HASH_PROP_ID);
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
index 4b7815dc1456..d19cd4611934 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
@@ -78,6 +78,9 @@ class X509Certificate_MSCryptImpl : public ::cppu::WeakImplHelper<
         /// @see xmlsecurity::Certificate::getSHA256Thumbprint().
         virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override;
 
+        /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm().
+        virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override;
+
         static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ;
         static X509Certificate_MSCryptImpl* getImplementation( const css::uno::Reference< css::uno::XInterface >& rObj ) ;
 
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
index f65bf09d97c3..0cf8c17d3303 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
@@ -36,6 +36,7 @@
 
 #include "sanextension_nssimpl.hxx"
 #include <tools/time.hxx>
+#include <svl/sigstruct.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno ;
@@ -441,6 +442,20 @@ OUString SAL_CALL X509Certificate_NssImpl::getSignatureAlgorithm()
     }
 }
 
+svl::crypto::SignatureMethodAlgorithm X509Certificate_NssImpl::getSignatureMethodAlgorithm()
+{
+    svl::crypto::SignatureMethodAlgorithm nRet = svl::crypto::SignatureMethodAlgorithm::RSA;
+
+    if (!m_pCert)
+        return nRet;
+
+    SECOidTag eTag = SECOID_GetAlgorithmTag(&m_pCert->subjectPublicKeyInfo.algorithm);
+    if (eTag == SEC_OID_ANSIX962_EC_PUBLIC_KEY)
+        nRet = svl::crypto::SignatureMethodAlgorithm::ECDSA;
+
+    return nRet;
+}
+
 css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSHA1Thumbprint()
 {
     return getThumbprint(m_pCert, SEC_OID_SHA1);
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
index 5c5794342c62..6e2b8a472068 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
@@ -85,6 +85,9 @@ class X509Certificate_NssImpl : public ::cppu::WeakImplHelper<
         /// @see xmlsecurity::Certificate::getSHA256Thumbprint().
         virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override;
 
+        /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm().
+        virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override;
+
         static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ;
 
         //Helper methods


More information about the Libreoffice-commits mailing list