Makefile.in                                                                    
   |    2 
 RepositoryExternal.mk                                                          
   |   26 
 dev/null                                                                       
   |binary
 external/coinmp/UnpackedTarball_coinmp.mk                                      
   |    2 
 external/coinmp/configure-exit.patch                                           
   |   33 
 external/coinmp/register.patch                                                 
   |  369 ++++++++++
 solenv/gbuild/platform/com_GCC_defs.mk                                         
   |    4 
 xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk                              
   |    8 
 xmlsecurity/CppunitTest_xmlsecurity_signing.mk                                 
   |    9 
 xmlsecurity/inc/biginteger.hxx                                                 
   |   11 
 xmlsecurity/inc/xmlsec-wrapper.h                                               
   |    4 
 xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx                                  
   |   37 -
 
xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt
 |binary
 xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt     
   |binary
 xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt    
   |binary
 
xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt
 |binary
 
xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt
  |binary
 xmlsecurity/qa/unit/signing/data/cert9.db                                      
   |binary
 xmlsecurity/qa/unit/signing/data/key4.db                                       
   |binary
 xmlsecurity/qa/unit/signing/data/pkcs11.txt                                    
   |    5 
 xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt         
   |binary
 xmlsecurity/qa/unit/signing/data/test.p7b                                      
   |  249 ++++++
 xmlsecurity/qa/unit/signing/signing.cxx                                        
   |  174 ++++
 xmlsecurity/source/component/documentdigitalsignatures.cxx                     
   |   13 
 xmlsecurity/source/helper/xmlsignaturehelper.cxx                               
   |    6 
 xmlsecurity/source/helper/xsecverify.cxx                                       
   |    6 
 xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx          
   |   63 +
 xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx              
   |   92 ++
 xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx                 
   |    4 
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx                      
   |   95 ++
 xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx                         
   |    4 
 31 files changed, 1180 insertions(+), 36 deletions(-)

New commits:
commit 59e239eb6210e10b75b097810c02f90ab7e0715b
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Mar 3 14:22:37 2022 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 20:46:38 2022 +0200

    compare authors using Thumbprint
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130929
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit 65442205b5b274ad309308162f150f8d41648f72)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130866
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit a7aaa78acea4c1d51283c2fce54ff9f5339026f8)
    
    Change-Id: I338f58eb07cbf0a3d13a7dafdaddac09252a8546
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131368
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 2c8c221b88f2e2bb5b29a6c1bcce1ea75e98136a)

diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx 
b/xmlsecurity/source/component/documentdigitalsignatures.cxx
index 928b1d67aed8..385f5121d14c 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -647,8 +647,17 @@ sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
     for ( ; pAuthors != pAuthorsEnd; ++pAuthors )
     {
         SvtSecurityOptions::Certificate aAuthor = *pAuthors;
-        if (xmlsecurity::EqualDistinguishedNames(aAuthor[0], 
xAuthor->getIssuerName(), xmlsecurity::NOCOMPAT)
-            && (aAuthor[1] == sSerialNum))
+        if (!xmlsecurity::EqualDistinguishedNames(aAuthor[0], 
xAuthor->getIssuerName(), xmlsecurity::NOCOMPAT))
+            continue;
+        if (aAuthor[1] != sSerialNum)
+            continue;
+
+        DocumentSignatureManager aSignatureManager(mxCtx, {});
+        if (!aSignatureManager.init())
+            return false;
+        uno::Reference<css::security::XCertificate> xCert =
+            
aSignatureManager.getSecurityEnvironment()->createCertificateFromAscii(aAuthor[2]);
+        if (xCert->getSHA1Thumbprint() == xAuthor->getSHA1Thumbprint())
         {
             bFound = true;
             break;
commit d8173087b2c987cd6a077ccfe893d3a5044461d0
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Mon Dec 20 17:05:44 2021 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 20:43:53 2022 +0200

    only use X509Data
    
    Change-Id: I52e6588f5fac04bb26d77c1f3af470db73e41f72
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127193
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit be446d81e07b5499152efeca6ca23034e51ea5ff)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127178
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>
    (cherry picked from commit b0404f80577de9ff69e58390c6f6ef949fdb0139)
    (cherry picked from commit 0268fd5a52c11f5701b10c9f9a92681c56254f17)

diff --git a/xmlsecurity/inc/xmlsec-wrapper.h b/xmlsecurity/inc/xmlsec-wrapper.h
index c060c8bf23b8..2d06dcfdd549 100644
--- a/xmlsecurity/inc/xmlsec-wrapper.h
+++ b/xmlsecurity/inc/xmlsec-wrapper.h
@@ -43,6 +43,10 @@
 #include <xmlsec/nss/app.h>
 #include <xmlsec/nss/crypto.h>
 #include <xmlsec/nss/pkikeys.h>
+#include <xmlsec/nss/x509.h>
+#endif
+#ifdef XMLSEC_CRYPTO_MSCRYPTO
+#include <xmlsec/mscng/x509.h>
 #endif
 
 #endif
diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx 
b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
index 6b16efd46752..a3a04b5c1241 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
@@ -229,6 +229,10 @@ SAL_CALL XMLSignature_MSCryptImpl::validate(
     // We do certificate verification ourselves.
     pDsigCtx->keyInfoReadCtx.flags |= 
XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
 
+    // limit possible key data to valid X509 certificates only, no KeyValues
+    if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST 
xmlSecMSCngKeyDataX509GetKlass()) < 0)
+        throw RuntimeException("failed to limit allowed key data");
+
     //Verify signature
     //The documentation says that the signature is only valid if the return 
value is 0 (that is, not < 0)
     //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not 
make any assumptions, if
diff --git a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx 
b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx
index e50daa47e868..c4e21d791c2d 100644
--- a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx
@@ -244,6 +244,10 @@ SAL_CALL XMLSignature_NssImpl::validate(
         // We do certificate verification ourselves.
         pDsigCtx->keyInfoReadCtx.flags |= 
XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
 
+        // limit possible key data to valid X509 certificates only, no 
KeyValues
+        if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), 
BAD_CAST xmlSecNssKeyDataX509GetKlass()) < 0)
+            throw RuntimeException("failed to limit allowed key data");
+
         //Verify signature
         int rs = xmlSecDSigCtxVerify( pDsigCtx.get() , pNode );
 
commit a55ef494199f02bea728c83f37ab3a02690d6b17
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Oct 27 15:28:11 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 20:39:55 2022 +0200

    xmlsecurity: some Distinguished Names are less equal than others
    
    It turns out that the 2 backends NSS and MS CryptoAPI generate different
    string representations of the same Distinguished Name in at least one
    corner case, when a value contains a quote " U+0022.
    
    The CryptoAPI function to generate the strings is:
    CertNameToStr(..., CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, ...)
    
    This is documented on MSDN:
    
https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR
    
    NSS appears to implement RFC 1485, at least that's what the internal
    function is named after, or perhaps one of its several successor RFCs
    (not clear currently if there's a relevant difference).
    
    This is now causing trouble if a certificate with such a DN is used in a
    signature, created on WNT but then verified on another platform, because
    commit 5af5ea893bcb8a8eb472ac11133da10e5a604e66
    introduced consistency checks that compare the DNs that occur as strings
    in META-INF/documentsignatures.xml:
    
    xmlsecurity/source/helper/xmlsignaturehelper.cxx:672: X509Data cannot be 
parsed
    
    The reason is that in XSecController::setX509Data() the value read from
    the X509IssuerSerial element (a string generated by CryptoAPI) doesn't
    match the value generated by NSS from the certificate parsed from the
    X509Certificate element, so these are erroneously interpreted as 2
    distinct certificates.
    
    Try to make the EqualDistinguishedNames() more flexible so that it can
    try also a converted variant of the DN.
    
    (libxmlsec's NSS backend also complains that it cannot parse the DN:
     x509vfy.c:607: xmlSecNssX509NameRead() '' '' 12 'invalid data for 'char': 
actual=34 and expected comma ',''
     but it manages to validate the signature despite this.)
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124287
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit e63611fabd38c757809b510fbb71c077880b1081)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124196
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    (cherry picked from commit 3dfe381032fc61ea31106f103dee9db8277d4d25)
    
    Change-Id: I4f72900738d1f5313146bbda7320a8f44319ebc8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124420
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit ee48ce9886d884730a91c695b5d0668c6d90c740)

diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk 
b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
index 846bd9ba84e9..8255ad3256cf 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
@@ -27,6 +27,7 @@ $(eval $(call 
gb_CppunitTest_use_libraries,xmlsecurity_signing, \
        unotest \
        utl \
        xmlsecurity \
+       xsec_xmlsec \
 ))
 
 $(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\
diff --git a/xmlsecurity/inc/biginteger.hxx b/xmlsecurity/inc/biginteger.hxx
index 8b4d8a9143b5..1e6b3f4a876e 100644
--- a/xmlsecurity/inc/biginteger.hxx
+++ b/xmlsecurity/inc/biginteger.hxx
@@ -32,8 +32,17 @@ namespace xmlsecurity
 XSECXMLSEC_DLLPUBLIC OUString bigIntegerToNumericString( const 
css::uno::Sequence< sal_Int8 >& serial );
 XSECXMLSEC_DLLPUBLIC css::uno::Sequence< sal_Int8 > numericStringToBigInteger 
( const OUString& serialNumber );
 
+// DNs read as strings from XML files may need to be mangled for compatibility
+// as NSS and MS CryptoAPI have different string serialisations; if the DN is
+// from an XCertificate it's "native" already and doesn't need to be mangled.
+enum EqualMode
+{
+    NOCOMPAT,
+    COMPAT_2ND,
+    COMPAT_BOTH
+};
 XSECXMLSEC_DLLPUBLIC bool EqualDistinguishedNames(OUString const& rName1,
-                                                  OUString const& rName2);
+                                                  OUString const& rName2, 
EqualMode eMode);
 }
 
 #endif
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index 36f1de88b6d3..d2ff4e180493 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -50,6 +50,7 @@
 #include <documentsignaturehelper.hxx>
 #include <xmlsignaturehelper.hxx>
 #include <documentsignaturemanager.hxx>
+#include <biginteger.hxx>
 #include <certificate.hxx>
 #include <xsecctl.hxx>
 #include <sfx2/docfile.hxx>
@@ -802,6 +803,21 @@ CPPUNIT_TEST_FIXTURE(SigningTest, 
testODFDoubleX509Certificate)
     CPPUNIT_ASSERT(!infos[0].Signer.is());
 }
 
+CPPUNIT_TEST_FIXTURE(SigningTest, testDNCompatibility)
+{
+    OUString const msDN("CN=\"\"\"ABC\"\".\", O=\"Enterprise \"\"ABC\"\"\"");
+    OUString const nssDN("CN=\\\"ABC\\\".,O=Enterprise \\\"ABC\\\"");
+    // this is just the status quo, possibly either NSS or CryptoAPI might 
change
+    CPPUNIT_ASSERT(!xmlsecurity::EqualDistinguishedNames(msDN, nssDN, 
xmlsecurity::NOCOMPAT));
+    CPPUNIT_ASSERT(!xmlsecurity::EqualDistinguishedNames(nssDN, msDN, 
xmlsecurity::NOCOMPAT));
+    // with compat flag it should work, with the string one 2nd and the native 
one 1st
+#ifdef _WIN32
+    CPPUNIT_ASSERT(xmlsecurity::EqualDistinguishedNames(msDN, nssDN, 
xmlsecurity::COMPAT_2ND));
+#else
+    CPPUNIT_ASSERT(xmlsecurity::EqualDistinguishedNames(nssDN, msDN, 
xmlsecurity::COMPAT_2ND));
+#endif
+}
+
 /// Test a typical OOXML where a number of (but not all) streams are signed.
 void SigningTest::testOOXMLPartial()
 {
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx 
b/xmlsecurity/source/component/documentdigitalsignatures.cxx
index fd8648d26c8a..928b1d67aed8 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -647,7 +647,7 @@ sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
     for ( ; pAuthors != pAuthorsEnd; ++pAuthors )
     {
         SvtSecurityOptions::Certificate aAuthor = *pAuthors;
-        if (xmlsecurity::EqualDistinguishedNames(aAuthor[0], 
xAuthor->getIssuerName())
+        if (xmlsecurity::EqualDistinguishedNames(aAuthor[0], 
xAuthor->getIssuerName(), xmlsecurity::NOCOMPAT)
             && (aAuthor[1] == sSerialNum))
         {
             bFound = true;
diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx 
b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
index adb387d0879e..ad3b12ca3a32 100644
--- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
@@ -44,6 +44,7 @@
 #include <comphelper/ofopxmlhelper.hxx>
 #include <comphelper/sequence.hxx>
 #include <tools/diagnose_ex.h>
+#include <rtl/ustrbuf.hxx>
 #include <sal/log.hxx>
 
 #include <boost/optional.hpp>
@@ -610,7 +611,7 @@ static auto CheckX509Data(
                 start = i; // issuer isn't in the list
                 break;
             }
-            if 
(xmlsecurity::EqualDistinguishedNames(certs[i]->getIssuerName(), 
certs[j]->getSubjectName()))
+            if 
(xmlsecurity::EqualDistinguishedNames(certs[i]->getIssuerName(), 
certs[j]->getSubjectName(), xmlsecurity::NOCOMPAT))
             {
                 if (i == j) // self signed
                 {
@@ -643,7 +644,7 @@ static auto CheckX509Data(
             if (chain[i] != j)
             {
                 if (xmlsecurity::EqualDistinguishedNames(
-                        certs[chain[i]]->getSubjectName(), 
certs[j]->getIssuerName()))
+                        certs[chain[i]]->getSubjectName(), 
certs[j]->getIssuerName(), xmlsecurity::NOCOMPAT))
                 {
                     if (chain.size() != i + 1) // already found issuee?
                     {
diff --git a/xmlsecurity/source/helper/xsecverify.cxx 
b/xmlsecurity/source/helper/xsecverify.cxx
index edb12d641cb9..c5c253b86f66 100644
--- a/xmlsecurity/source/helper/xsecverify.cxx
+++ b/xmlsecurity/source/helper/xsecverify.cxx
@@ -272,7 +272,7 @@ void XSecController::setX509Data(
             auto iter = rX509IssuerSerials.begin();
             while (iter != rX509IssuerSerials.end())
             {
-                if (xmlsecurity::EqualDistinguishedNames(issuerName, 
iter->first)
+                if (xmlsecurity::EqualDistinguishedNames(issuerName, 
iter->first, xmlsecurity::COMPAT_2ND)
                         && serialNumber == iter->second)
                 {
                     data.back().X509IssuerName = iter->first;
@@ -420,7 +420,7 @@ void XSecController::setX509CertDigest(
     {
         for (auto & it : rData)
         {
-            if (xmlsecurity::EqualDistinguishedNames(it.X509IssuerName, 
rX509IssuerName)
+            if (xmlsecurity::EqualDistinguishedNames(it.X509IssuerName, 
rX509IssuerName, xmlsecurity::COMPAT_BOTH)
                 && it.X509SerialNumber == rX509SerialNumber)
             {
                 it.CertDigest = rCertDigest;
@@ -443,7 +443,7 @@ void XSecController::setX509CertDigest(
                     {
                         SAL_INFO("xmlsecurity.helper", "cannot parse 
X509Certificate");
                     }
-                    else if 
(xmlsecurity::EqualDistinguishedNames(xCert->getIssuerName(),rX509IssuerName)
+                    else if 
(xmlsecurity::EqualDistinguishedNames(xCert->getIssuerName(), rX509IssuerName, 
xmlsecurity::COMPAT_2ND)
                         && 
xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()) == 
rX509SerialNumber)
                     {
                         it.CertDigest = rCertDigest;
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx 
b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
index b5f779db3029..d3e2c5008258 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
@@ -32,6 +32,7 @@
 #include "oid.hxx"
 
 #include <rtl/locale.h>
+#include <rtl/ustrbuf.hxx>
 #include <osl/nlsupport.h>
 #include <osl/process.h>
 #include <o3tl/char16_t2wchar_t.hxx>
@@ -677,6 +678,67 @@ Sequence<OUString> SAL_CALL 
X509Certificate_MSCryptImpl::getSupportedServiceName
 
 namespace xmlsecurity {
 
+// based on some guesswork and:
+// https://datatracker.ietf.org/doc/html/rfc1485
+// 
https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR
+// the main problem appears to be that in values NSS uses \ escapes but 
CryptoAPI requires " quotes around value
+static OUString CompatDNNSS(OUString const& rDN)
+{
+    OUStringBuffer buf(rDN.getLength());
+    enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT);
+    for (sal_Int32 i = 0; i < rDN.getLength(); ++i)
+    {
+        if (state == DEFAULT)
+        {
+            buf.append(rDN[i]);
+            if (rDN[i] == '=')
+            {
+                if (rDN.getLength() == i+1)
+                {
+                    break; // invalid?
+                }
+                else
+                {
+                    buf.append('"');
+                    state = INVALUE;
+                }
+            }
+        }
+        else if (state == INVALUE)
+        {
+            if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';')
+            {
+                buf.append('"');
+                buf.append(rDN[i]);
+                state = DEFAULT;
+            }
+            else if (rDN[i] == '\\')
+            {
+                if (rDN.getLength() == i+1)
+                {
+                    break; // invalid?
+                }
+                if (rDN[i+1] == '"')
+                {
+                    buf.append('"');
+                }
+                buf.append(rDN[i+1]);
+                ++i;
+            }
+            else
+            {
+                buf.append(rDN[i]);
+            }
+            if (i+1 == rDN.getLength())
+            {
+                buf.append('"');
+                state = DEFAULT;
+            }
+        }
+    }
+    return buf.makeStringAndClear();
+}
+
 static bool EncodeDistinguishedName(OUString const& rName, CERT_NAME_BLOB & 
rBlob)
 {
     LPCWSTR pszError;
@@ -699,22 +761,38 @@ static bool EncodeDistinguishedName(OUString const& 
rName, CERT_NAME_BLOB & rBlo
 }
 
 bool EqualDistinguishedNames(
-        OUString const& rName1, OUString const& rName2)
+        OUString const& rName1, OUString const& rName2,
+        EqualMode const eMode)
 {
+    if (eMode == COMPAT_BOTH && !rName1.isEmpty() && rName1 == rName2)
+    {   // handle case where both need to be converted
+        return true;
+    }
     CERT_NAME_BLOB blob1;
     if (!EncodeDistinguishedName(rName1, blob1))
     {
         return false;
     }
     CERT_NAME_BLOB blob2;
-    if (!EncodeDistinguishedName(rName2, blob2))
+    bool ret(false);
+    if (!!EncodeDistinguishedName(rName2, blob2))
     {
-        delete[] blob1.pbData;
-        return false;
+        ret = CertCompareCertificateName(X509_ASN_ENCODING,
+            &blob1, &blob2) == TRUE;
+        delete[] blob2.pbData;
+    }
+    if (!ret && eMode == COMPAT_2ND)
+    {
+        CERT_NAME_BLOB blob2compat;
+        if (!EncodeDistinguishedName(CompatDNNSS(rName2), blob2compat))
+        {
+            delete[] blob1.pbData;
+            return false;
+        }
+        ret = CertCompareCertificateName(X509_ASN_ENCODING,
+            &blob1, &blob2compat) == TRUE;
+        delete[] blob2compat.pbData;
     }
-    bool const ret(CertCompareCertificateName(X509_ASN_ENCODING,
-            &blob1, &blob2) == TRUE);
-    delete[] blob2.pbData;
     delete[] blob1.pbData;
     return ret;
 }
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx 
b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
index db9ac25b2cbc..50caf51081f2 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
@@ -29,6 +29,8 @@
 #include <comphelper/servicehelper.hxx>
 #include <cppuhelper/supportsservice.hxx>
 #include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
 #include "x509certificate_nssimpl.hxx"
 
 #include <biginteger.hxx>
@@ -549,22 +551,103 @@ Sequence<OUString> SAL_CALL 
X509Certificate_NssImpl::getSupportedServiceNames()
 
 namespace xmlsecurity {
 
+// based on some guesswork and:
+// https://datatracker.ietf.org/doc/html/rfc1485
+// 
https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR
+// the main problem appears to be that in values " is escaped as "" vs. \"
+static OUString CompatDNCryptoAPI(OUString const& rDN)
+{
+    OUStringBuffer buf(rDN.getLength());
+    enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT);
+    for (sal_Int32 i = 0; i < rDN.getLength(); ++i)
+    {
+        if (state == DEFAULT)
+        {
+            buf.append(rDN[i]);
+            if (rDN[i] == '=')
+            {
+                if (rDN.getLength() == i+1)
+                {
+                    break; // invalid?
+                }
+                else if (rDN[i+1] == '"')
+                {
+                    buf.append(rDN[i+1]);
+                    ++i;
+                    state = INQUOTE;
+                }
+                else
+                {
+                    state = INVALUE;
+                }
+            }
+        }
+        else if (state == INVALUE)
+        {
+            if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';')
+            {
+                state = DEFAULT;
+            }
+            buf.append(rDN[i]);
+        }
+        else
+        {
+            assert(state == INQUOTE);
+            if (rDN[i] == '"')
+            {
+                if (rDN.getLength() != i+1 && rDN[i+1] == '"')
+                {
+                    buf.append('\\');
+                    buf.append(rDN[i+1]);
+                    ++i;
+                }
+                else
+                {
+                    buf.append(rDN[i]);
+                    state = DEFAULT;
+                }
+            }
+            else
+            {
+                buf.append(rDN[i]);
+            }
+        }
+    }
+    return buf.makeStringAndClear();
+}
+
 bool EqualDistinguishedNames(
-        OUString const& rName1, OUString const& rName2)
+        OUString const& rName1, OUString const& rName2,
+        EqualMode const eMode)
 {
+    if (eMode == COMPAT_BOTH && !rName1.isEmpty() && rName1 == rName2)
+    {   // handle case where both need to be converted
+        return true;
+    }
     CERTName *const pName1(CERT_AsciiToName(OUStringToOString(rName1, 
RTL_TEXTENCODING_UTF8).getStr()));
     if (pName1 == nullptr)
     {
         return false;
     }
     CERTName *const pName2(CERT_AsciiToName(OUStringToOString(rName2, 
RTL_TEXTENCODING_UTF8).getStr()));
-    if (pName2 == nullptr)
+    bool ret(false);
+    if (pName2)
     {
-        CERT_DestroyName(pName1);
-        return false;
+        ret = (CERT_CompareName(pName1, pName2) == SECEqual);
+        CERT_DestroyName(pName2);
+    }
+    if (!ret && eMode == COMPAT_2ND)
+    {
+        CERTName *const pName2Compat(CERT_AsciiToName(OUStringToOString(
+            CompatDNCryptoAPI(rName2), RTL_TEXTENCODING_UTF8).getStr()));
+        if (pName2Compat == nullptr)
+        {
+            CERT_DestroyName(pName1);
+            return false;
+        }
+        ret = CERT_CompareName(pName1, pName2Compat) == SECEqual;
+        CERT_DestroyName(pName2Compat);
     }
-    bool const ret(CERT_CompareName(pName1, pName2) == SECEqual);
-    CERT_DestroyName(pName2);
     CERT_DestroyName(pName1);
     return ret;
 }
commit a5ae1d94e6a457349acee19dfb963d70abf25fff
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Oct 15 20:52:47 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 20:29:49 2022 +0200

    xmlsecurity: fix test failing because NSS policy forbids SHA1
    
    With Fedora's nss-3.71.0-1.fc34.x86_64 there is the problem that
    8 tests including testODFGood in CppunitTest/xmlsecurity_signing
    fail because the crypto policy disallows SHA1 for signatures.
    
    Apparently this particular policy bit was added in NSS 3.59:
    https://bugzilla.mozilla.org/show_bug.cgi?id=1670835
    
    For signatures, maybe it's not a good idea to override system policy
    for product builds, so do it locally in the tests, at least for now.
    
    If similar problems turn up for encrypted documents in the future,
    that should be fixed in product builds too of course, as encrypted
    documents must always be decryptable.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123768
    Tested-by: Jenkins
    Tested-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 51e82016e8783a452fe5f7921d12c1bf20bfd6b5)
    
    xmlsecurity: fix --without-system-nss usage of NSS_SetAlgorithmPolicy
    
    The problem with commit ff572d9222ec16ffd679ae907a0bf4a8900265e1
    is that it's using the wrong library; NSS_SetAlgorithmPolicy is actually
    in libnssutil3.so.
    
    This causes a linking problem when upgrading the internal NSS to a
    version that has NSS_USE_ALG_IN_ANY_SIGNATURE.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123819
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 395c0c0bbaceadf909e0189af99c6358487c7978)
    
    Change-Id: I4f634cf5da1707fb628e63cd0cdafebdf4fc903f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123838
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 0f3431026dbff0251efeb0b92be335841a08cc5d)

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 1fefe339ec2f..da4aad2d956f 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -3432,6 +3432,11 @@ $(call gb_LinkTarget_add_libs,$(1),\
 
 endef
 
+define gb_LinkTarget__use_nssutil3
+$(call gb_LinkTarget__use_nss3,$(1))
+
+endef
+
 define gb_LinkTarget__use_plc4
 $(call gb_LinkTarget__use_nss3,$(1))
 
@@ -3501,6 +3506,27 @@ endif
 
 endef
 
+define gb_LinkTarget__use_nssutil3
+$(call gb_LinkTarget_use_package,$(1),nss)
+$(call gb_LinkTarget_set_include,$(1),\
+       $$(INCLUDE) \
+       -I$(call gb_UnpackedTarball_get_dir,nss)/dist/public/nss \
+       -I$(call gb_UnpackedTarball_get_dir,nss)/dist/out/include \
+)
+
+ifeq ($(COM),MSC)
+$(call gb_LinkTarget_add_libs,$(1),\
+       $(call gb_UnpackedTarball_get_dir,nss)/dist/out/lib/nssutil3.lib \
+)
+else
+$(call gb_LinkTarget_add_libs,$(1),\
+       -L$(call gb_UnpackedTarball_get_dir,nss)/dist/out/lib \
+       -lnssutil3 \
+)
+endif
+
+endef
+
 define gb_ExternalProject__use_nss3
 $(call gb_ExternalProject_use_package,$(1),nss)
 
diff --git a/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk 
b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk
index 021ab8dbe99f..083edf36dbe7 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk
@@ -34,6 +34,14 @@ $(eval $(call 
gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\
     boost_headers \
 ))
 
+ifneq ($(OS),WNT)
+ifneq (,$(ENABLE_NSS))
+$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\
+    nssutil3 \
+))
+endif
+endif
+
 $(eval $(call gb_CppunitTest_set_include,xmlsecurity_pdfsigning,\
        -I$(SRCDIR)/xmlsecurity/inc \
        $$(INCLUDE) \
diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk 
b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
index e9c80db4b8a9..846bd9ba84e9 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
@@ -34,6 +34,14 @@ $(eval $(call 
gb_CppunitTest_use_externals,xmlsecurity_signing,\
     libxml2 \
 ))
 
+ifneq ($(OS),WNT)
+ifneq (,$(ENABLE_NSS))
+$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\
+    nssutil3 \
+))
+endif
+endif
+
 $(eval $(call gb_CppunitTest_set_include,xmlsecurity_signing,\
        -I$(SRCDIR)/xmlsecurity/inc \
        $$(INCLUDE) \
diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx 
b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index 75cd771844a2..2341c315ee35 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -7,6 +7,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#ifndef _WIN32
+#include <secoid.h>
+#endif
+
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
 
@@ -137,6 +141,18 @@ void PDFSigningTest::setUp()
     osl::File::copy(aSourceDir + "key4.db", aTargetDir + "/key4.db");
     osl::File::copy(aSourceDir + "pkcs11.txt", aTargetDir + "/pkcs11.txt");
     setenv("MOZILLA_CERTIFICATE_FOLDER", aTargetPath.toUtf8().getStr(), 1);
+#endif
+
+    uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+        = xml::crypto::SEInitializer::create(mxComponentContext);
+    uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+        = xSEInitializer->createSecurityContext(OUString());
+#ifndef _WIN32
+#ifdef NSS_USE_ALG_IN_ANY_SIGNATURE
+    // policy may disallow using SHA1 for signatures but unit test documents
+    // have such existing signatures (call this after createSecurityContext!)
+    NSS_SetAlgorithmPolicy(SEC_OID_SHA1, NSS_USE_ALG_IN_ANY_SIGNATURE, 0);
+#endif
 #endif
 }
 
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index f63e8da729bd..36f1de88b6d3 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -14,6 +14,10 @@
 
 #include <cstdlib>
 
+#ifndef _WIN32
+#include <secoid.h>
+#endif
+
 #include <test/bootstrapfixture.hxx>
 #include <unotest/macros_test.hxx>
 #include <test/xmltesttools.hxx>
@@ -252,6 +256,13 @@ void SigningTest::setUp()
     mxDesktop.set(frame::Desktop::create(mxComponentContext));
     mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext);
     mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
+#ifndef _WIN32
+#ifdef NSS_USE_ALG_IN_ANY_SIGNATURE
+    // policy may disallow using SHA1 for signatures but unit test documents
+    // have such existing signatures (call this after createSecurityContext!)
+    NSS_SetAlgorithmPolicy(SEC_OID_SHA1, NSS_USE_ALG_IN_ANY_SIGNATURE, 0);
+#endif
+#endif
 }
 
 void SigningTest::tearDown()
commit 9905c0d0f062c291124c9aa3e190dea0913adb2f
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Oct 14 13:44:14 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 20:29:00 2022 +0200

    test: upgrade test NSS database from dbm: to sql:
    
    Fedora nss-3.69.0-1.fc34.x86_64 and Debian libnss3:amd64 2:3.70-1 no
    longer support the old BerekelyDB databases, so convert them to the new
    SQLite format for the benefit of --with-system-nss builds.
    
    This worked to do the upgrade:
    
    > certutil -N -d sql:test/new --empty-password
    > LD_LIBRARY_PATH=instdir/program 
workdir/UnpackedTarball/nss/dist/out/bin/certutil --merge -d sql:test/new 
--source-dir dbm:test/signing-keys
    
    Builds would fail running tests added in commit
    40d70d427edddb589eda64fafc2e56536953d274
    
      signing.cxx:551:Assertion
      Test name: testODFX509CertificateChain::TestBody
      equality assertion failed
      - Expected: 0
      - Actual  : 1
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123586
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 907784ccce7bd8b5121888cff7f5723a55d35358)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123643
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 7b4b03b9cf21ecd11bc82da5f29c4ff91ad242c9)
    
    Change-Id: I00aa20703e117ebf583c3331b84e966c2cfc78cd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123837
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 755155498b13c8724831276808c930adba891f5c)

diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx 
b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index 2dc0f7d59eb0..75cd771844a2 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -132,9 +132,10 @@ void PDFSigningTest::setUp()
     OUString caVar("LIBO_TEST_CRYPTOAPI_PKCS7");
     osl_setEnvironment(caVar.pData, aTargetPath.pData);
 #else
-    // Set up cert8.db and key3.db in workdir/CppunitTest/
-    osl::File::copy(aSourceDir + "cert8.db", aTargetDir + "cert8.db");
-    osl::File::copy(aSourceDir + "key3.db", aTargetDir + "key3.db");
+    // Set up NSS database in workdir/CppunitTest/
+    osl::File::copy(aSourceDir + "cert9.db", aTargetDir + "/cert9.db");
+    osl::File::copy(aSourceDir + "key4.db", aTargetDir + "/key4.db");
+    osl::File::copy(aSourceDir + "pkcs11.txt", aTargetDir + "/pkcs11.txt");
     setenv("MOZILLA_CERTIFICATE_FOLDER", aTargetPath.toUtf8().getStr(), 1);
 #endif
 }
diff --git a/xmlsecurity/qa/unit/signing/data/cert8.db 
b/xmlsecurity/qa/unit/signing/data/cert9.db
similarity index 50%
rename from xmlsecurity/qa/unit/signing/data/cert8.db
rename to xmlsecurity/qa/unit/signing/data/cert9.db
index 95e58ffe5b92..c4064e419f42 100644
Binary files a/xmlsecurity/qa/unit/signing/data/cert8.db and 
b/xmlsecurity/qa/unit/signing/data/cert9.db differ
diff --git a/xmlsecurity/qa/unit/signing/data/key3.db 
b/xmlsecurity/qa/unit/signing/data/key3.db
deleted file mode 100644
index f449e60a667f..000000000000
Binary files a/xmlsecurity/qa/unit/signing/data/key3.db and /dev/null differ
diff --git a/xmlsecurity/qa/unit/signing/data/key4.db 
b/xmlsecurity/qa/unit/signing/data/key4.db
new file mode 100644
index 000000000000..34a7fa28aa32
Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/key4.db differ
diff --git a/xmlsecurity/qa/unit/signing/data/pkcs11.txt 
b/xmlsecurity/qa/unit/signing/data/pkcs11.txt
new file mode 100644
index 000000000000..22c8f8519efd
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/pkcs11.txt
@@ -0,0 +1,5 @@
+library=
+name=NSS Internal PKCS #11 Module
+parameters=configdir='sql:test/new' certPrefix='' keyPrefix='' 
secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' 
updateid='' updateTokenDescription='' 
+NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 
slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512]
 askpw=any timeout=30})
+
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index 5330d45b46cc..f63e8da729bd 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -201,9 +201,10 @@ void SigningTest::setUp()
     OUString aTargetDir
         = 
m_directories.getURLFromWorkdir("CppunitTest/xmlsecurity_signing.test.user");
 
-    // Set up cert8.db in workdir/CppunitTest/
-    osl::File::copy(aSourceDir + "cert8.db", aTargetDir + "/cert8.db");
-    osl::File::copy(aSourceDir + "key3.db", aTargetDir + "/key3.db");
+    // Set up NSS database in workdir/CppunitTest/
+    osl::File::copy(aSourceDir + "cert9.db", aTargetDir + "/cert9.db");
+    osl::File::copy(aSourceDir + "key4.db", aTargetDir + "/key4.db");
+    osl::File::copy(aSourceDir + "pkcs11.txt", aTargetDir + "/pkcs11.txt");
 
     // Make gpg use our own defined setup & keys
     osl::File::copy(aSourceDir + "pubring.gpg", aTargetDir + "/pubring.gpg");
commit 3e55ecdda3fc7ecb9dec08a5b3260020d4f9a85f
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Oct 15 16:58:07 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 20:27:21 2022 +0200

    xmlsecurity: fix new tests on WNT
    
    Tests added in commit 40d70d427edddb589eda64fafc2e56536953d274 don't
    actually run on WNT but that wasn't obvious because commit
    149df1fec6472e30582162e17e04c75aee91d26a prevented running them in
    Jenkins on master, they failed only in the libreoffice-7-1 backport.
    
      xmlsecurity/qa/unit/signing/signing.cxx(631) : error : Assertion
      Test name: testODFDoubleX509Certificate::TestBody
      assertion failed
      - Expression: (nActual == SignatureState::NOTVALIDATED || nActual == 
SignatureState::OK)
      - 2
    
    This is an oddity where NSS claims the signature in the document is
    valid but CryptoAPI claims it is invalid; the hashes passed into the
    validation functions are the same.  Just allow BROKEN as an additional
    result value on WNT.
    
      xmlsecurity/qa/unit/signing/signing.cxx(550) : error : Assertion
      Test name: testODFX509CertificateChain::TestBody
      equality assertion failed
      - Expected: 0
      - Actual  : 1
    
    The problem here is that with NSS the tests use a custom NSS database
    in test/signing-keys so we need to make these certificates available for
    CryptoAPI too.
    
    The following one-liner converts the NSS database to a PKCS#7 that can
    be loaded by CrytpAPI:
    
    > openssl crl2pkcs7 -nocrl -certfile <(certutil -d sql:test/signing-keys -L 
| awk '/^[^ ].*,[^ ]*,/ { printf "%s", $1; for (i = 2; i < NF; i++) { printf " 
%s", $i; } printf "\n"; }' | while read name; do certutil -L -d 
sql:test/signing-keys -a -n "${name}" ; done) > test/signing-keys/test.p7b
    
    Then one might naively assume that something like this would allow these
    certificates to be added temporarily as trusted CAs:
    
    +                HCERTSTORE hRoot = CertOpenSystemStoreW( 0, L"Root" ) ;
    +                HCERTSTORE const hExtra = CertOpenStore(
    +                        CERT_STORE_PROV_FILENAME_A,
    +                        PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
    +                        NULL,
    +                        CERT_STORE_OPEN_EXISTING_FLAG | 
CERT_STORE_READONLY_FLAG,
    +                        path);
    +                if (hExtra != NULL && hRoot != NULL)
    +                {
    +                    BOOL ret = CertAddStoreToCollection(
    +                        hRoot,
    +                        hExtra,
    +                        CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
    +                        0);
    +                    SAL_DEBUG("XXX hExtra done " << ret);
    +                }
    
    There is no error from this, but it doesn't work.
    
    Instead, check if CertGetCertificateChain() sets the
    CERT_TRUST_IS_UNTRUSTED_ROOT flag and then look up the certificate
    manually in the extra PKCS#7 store.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123667
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit 7d664ec788acdc378506a7ff8b1120cea24a6770)
    
    Change-Id: Ic9865e0b5783211c2128ce0327c4583b7784ff62
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123836
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 7c622c58cda433964dd73544d56a81a7c88e3f5d)

diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx 
b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index 894aca99a26a..2dc0f7d59eb0 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -12,6 +12,7 @@
 
 #include <comphelper/processfactory.hxx>
 #include <osl/file.hxx>
+#include <osl/process.h>
 #include <sal/log.hxx>
 #include <test/bootstrapfixture.hxx>
 #include <tools/datetime.hxx>
@@ -119,15 +120,21 @@ void PDFSigningTest::setUp()
 
     
mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
 
-#ifndef _WIN32
-    // Set up cert8.db and key3.db in workdir/CppunitTest/
     OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
     OUString aTargetDir
         = 
m_directories.getURLFromWorkdir("/CppunitTest/xmlsecurity_pdfsigning.test.user/");
-    osl::File::copy(aSourceDir + "cert8.db", aTargetDir + "cert8.db");
-    osl::File::copy(aSourceDir + "key3.db", aTargetDir + "key3.db");
     OUString aTargetPath;
     osl::FileBase::getSystemPathFromFileURL(aTargetDir, aTargetPath);
+
+#ifdef _WIN32
+    // CryptoAPI test certificates
+    osl::File::copy(aSourceDir + "test.p7b", aTargetDir + "/test.p7b");
+    OUString caVar("LIBO_TEST_CRYPTOAPI_PKCS7");
+    osl_setEnvironment(caVar.pData, aTargetPath.pData);
+#else
+    // Set up cert8.db and key3.db in workdir/CppunitTest/
+    osl::File::copy(aSourceDir + "cert8.db", aTargetDir + "cert8.db");
+    osl::File::copy(aSourceDir + "key3.db", aTargetDir + "key3.db");
     setenv("MOZILLA_CERTIFICATE_FOLDER", aTargetPath.toUtf8().getStr(), 1);
 #endif
 }
diff --git a/xmlsecurity/qa/unit/signing/data/test.p7b 
b/xmlsecurity/qa/unit/signing/data/test.p7b
new file mode 100644
index 000000000000..44723697a2bf
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/test.p7b
@@ -0,0 +1,249 @@
+-----BEGIN PKCS7-----
+MIIuNgYJKoZIhvcNAQcCoIIuJzCCLiMCAQExADALBgkqhkiG9w0BBwGggi4LMIIF
+sjCCA5qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVUsxEDAO
+BgNVBAgMB0VuZ2xhbmQxHTAbBgNVBAoMFFhtbHNlY3VyaXR5IFJTQSBUZXN0MSUw
+IwYDVQQDDBxYbWxzZWN1cml0eSBSU0EgVGVzdCBSb290IENBMCAXDTE4MDYwNjE1
+MjAwNloYDzIxMTgwNTEzMTUyMDA2WjBpMQswCQYDVQQGEwJVSzEQMA4GA1UECAwH
+RW5nbGFuZDEdMBsGA1UECgwUWG1sc2VjdXJpdHkgUlNBIFRlc3QxKTAnBgNVBAMM
+IFhtbHNlY3VyaXR5IEludGVybWVkaWF0ZSBSb290IENBMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA+uBkXt39Yc0aOe2UkBWlVIqQcvlSwLheXlcGeDDI
+PSwSRaDcuGdGQXs+WFM65xDak8eZJwyyQSWtoDRV0lXEP63OJk/ktWLjFywLP69g
+Br2E4vsjOdr9DR94AAQY2WTW2/UXxcI92nB+sq6ZhVF5I9rfzDHPGYEiWTQqtnTM
+JDGpO5eo9JBjQtaB/sHG7ZnxF1FOl6V85F/dfGG3MBGp9glg5qE6QDjA11DsTuki
+V5OeP8vZsmoYkyNmViA7L+xuOM6iVUGY+b4XDCeI1Kgr5ZhF9xL7ByVTxtZrdMXz
+cPu+Dgcr9VF7QqhAYg/W/0s4WzoyXV/f1fjC5+uKXWSuttrRHNt16DMOh5T1lS4q
+HLfMoDYZ+AK8L0JrjQMXCzCp4WTmqplBg6bYWFpHvyzp0uccYJdUXv5o6PFhpIV6
+VpdVtT6fVfh9V5C5jDKBv+n14rZ9hPYzvIxVAnF6SYtXRTbrSzSDi5QqCiWwU56u
+SAWyyrwdED1zETgTDmGOFv5j2tIEcAbQ6TT8n/Mit5NuL98M5XxPnKduCQ39ssKD
+wO146lAe5kREJRv4Va/o47tards6tdkaV5267rXZA7ndvnov0TmZFNwDMQz9tRZJ
+ov07V7kriLS47xD/eDH7IyEOWYsgoU3N1J1GZKCYSRxZ3Wh6AiZy211PYwuJpP3x
+ugUCAwEAAaNmMGQwHQYDVR0OBBYEFDXB8g347TUPMvCNXTBSRQpVRvroMB8GA1Ud
+IwQYMBaAFOOqggO/I6PkIyJZqJ16mbDbtiXxMBIGA1UdEwEB/wQIMAYBAf8CAQAw
+DgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQAiyaCtGnPZRsfGD69y
+jkPptc6cwa8icyF9iiJwdngjvdMTCOJHhUAtzGTOuUITJEh0OJYzabB+EUgHmZWe
+6hwrWCzhJQysDktdsARQOB91Vi19VyDrcHPxnn43zObnbkLpFvZXg3Q3/S+eiTn/
+UWMg7f2tQjaCdj6xx1DGTiJmZBRI/CG24EWzYy+H7/MBNFuW3+1CdoDuPR3lkbWm
+YFJbvkOaWR8+faL6o5u7IagKCSmMaNDjRQA8/LKwJ8waD61Hw4S4H465I16UVCT4
+d226anZIfz7N3/NbVw0B8emJP1ZtVty1vDPEx/6A7+sXfgAYgjfMeiHhGHs17i2d
+7EvdwxlyvKq/iQkLMzkyAkA5kpUbZ/kpOQh8sR9JHxv3QEz0clRvRIwlJU5W+Pa1
+e3dNYTDR9x0fBaLwPUIc5RnnSZ5Aws2qxnp7yYrQzxTtLd3IoDU4BuuyBE+/Pauk
+bbfJUnr+e9Pwt+OXqrECnhxz+f0FDAMlX0CEe7Vlx8p37roBiT4sf3anXrNyrUZM
+QWQFLs9H3+yooEJJWTgs7QjFZ0l5LIQyTv1I4UmGBgEWlW8UNIJhvAeq1ykY+WZw
+At9JDlNwiAbFbFoMqGkVZDko1foTE8KUJfgth63ZmdWw1yzX8H9+zDlhpHCehJsJ
+68Rk7INjBNZr6IxpVViGLsW1qTCCBbgwggOgoAMCAQICAhAAMA0GCSqGSIb3DQEB
+CwUAMGkxCzAJBgNVBAYTAlVLMRAwDgYDVQQIDAdFbmdsYW5kMR8wHQYDVQQKDBZY
+bWxzZWN1cml0eSBFQ0RTQSBUZXN0MScwJQYDVQQDDB5YbWxzZWN1cml0eSBFQ0RT
+QSBUZXN0IFJvb3QgQ0EwIBcNMTgwNjA2MTUyMDIxWhgPMjExODA1MTMxNTIwMjFa
+MGsxCzAJBgNVBAYTAlVLMRAwDgYDVQQIDAdFbmdsYW5kMR8wHQYDVQQKDBZYbWxz
+ZWN1cml0eSBFQ0RTQSBUZXN0MSkwJwYDVQQDDCBYbWxzZWN1cml0eSBJbnRlcm1l
+ZGlhdGUgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKlB
+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
+BwMCMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln
+aWNlcnQuY29tMEsGA1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0
+LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5jcmwwPQYDVR0gBDYw
+NDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNv
+bS9DUFMwHQYDVR0OBBYEFD3TUKXWoK3u80pgCmXTIdT4+NYPMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBCwUAA4IBAQCdttCQhuGG
+Au3FoPA0HHTBjXbMhgqo8EqKQtY/yKlNrXwIrea2ULiiGk2IB7EpIdzn2sY8IeDj
+EUlwrHodAaTKETpXq31XKkB0/dMdhRhQ31dHdaF9VSAuRzdQcox/ghvSYo8tA1ra
+w8ihzixSogBj63O6cchJJyOXZIWeOA6tY2g8ulKBWHmjLAzf3m3rMfK6oHxs8SzU
+4b13hDcDzjK1yJqBGkqSTjtGmoX+g6L5noyjzA1esz3PBHiPFBR7MpzHAKZcxLWh
+VY1aVmikInCqPIFx2Z2oRTv05faiUd3He2Lobwx067ja+L+HDXlQkZCbGDuRWSfx
+NSgTqyZ+1fd6MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG
+9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw
+FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9i
+YWwgUm9vdCBDQTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaME0xCzAJ
+BgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lD
+ZXJ0IFNIQTIgU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANyuWJBNwcQwFZA1W248ghX1LFy949v/cUP6ZCWA1O4Yok3wZtAK
+c24RmDYXZK83nf36QYSvx6+M/hpzTc8zl5CilodTgyu5pnVILR1WN3vaMTIa16yr
+BvSqXUu3R0bdKpPDkC55gIDvEwRqFDu1m5K+wgdlTvza/P96rtxcflUxDOg5B6TX
+vi/TC2rSsd9f/ld0Uzs1gN2ujkSYs58O09rg1/RrKatEp0tYhG2SS4HD2nOLEpdI
+kARFdRrdNzGXkujNVA075ME/OV4uuPNcfhCOhkEAjUVmR7ChZc6gqikJTvOX6+gu
+qw9ypzAO+sf0/RR3w6RbKFfCs/mC/bdFWJsCAwEAAaOCAVowggFWMBIGA1UdEwEB
+/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggr
+BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1
+oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RD
+QS5jcmwwN6A1oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds
+b2JhbFJvb3RDQS5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEW
+HGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFA+AYRyCMWHV
+LyjnjUY4tCzhxtniMB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA0G
+CSqGSIb3DQEBCwUAA4IBAQAjPt9L0jFCpbZ+QlwaRMxp0Wi0XUvgBCFsS+JtzLHg
+l4+mUwnNqipl5TlPHoOlblyYoiQm5vuh7ZPHLgLGTUq/sELfeNqzqPlt/yGFUzZg
+THbO7Djc1lGA8MXW5dRNJ2Srm8c+cftIl7gzbckTB+6WohsYFfZcTEDts8Ls/3HB
+40f/1LkAtDdC2iDJ6m6K7hQGrn2iWZiIqBtvLfTyyRRfJs8sjX7tN8Cp1Tm5gr8Z
+DOo0rwAhaPitc+LJMto4JQtV05od8GiG7S5BNO98pVAdvzr508EIDObtHopYJeS4
+d60tbvVS3bR0j6tJLp07kzQoH3jOlOrHvdPJbRzeXDLzMIIEXDCCA0SgAwIBAgIN
+AeOpMBz8cgY4P5pTHTANBgkqhkiG9w0BAQsFADBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMK
+R2xvYmFsU2lnbjAeFw0xNzA2MTUwMDAwNDJaFw0yMTEyMTUwMDAwNDJaMFQxCzAJ
+BgNVBAYTAlVTMR4wHAYDVQQKExVHb29nbGUgVHJ1c3QgU2VydmljZXMxJTAjBgNV
+BAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzMwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDKUkvqHv/OJGuo2nIYaNVWXQ5IWi01CXZaz6TIHLGp
+/lOJ+600/4hbn7vn6AAB3DVzdQOts7G5pH0rJnnOFUAK71G4nzKMfHCGUksW/mon
+a+Y2emJQ2N+aicwJKetPKRSIgAuPOB6Aahh8Hb2XO3h9RUk2T0HNouB2VzxoMXlk
+yW7XUR5mw6JkLHnA52XDVoRTWkNty5oCINLvGmnRsJ1zouAqYGVQMc/7sy+/EYhA
+LrVJEA8KbtyX+r8snwU5C1hUrwaW6MWOARa8qBpNQcWTkaIeoYvy/sGIJEmjR0vF
+EwHdp1cSaWIr6/4g72n7OqXwfinu7ZYW97EfoOSQJeAzAgMBAAGjggEzMIIBLzAO
+BgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIG
+A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHfCuFCaZ3Z2sS3ChtCDoH6mfrpL
+MB8GA1UdIwQYMBaAFJviB1dnHB7AagbeWbSaLd/cGYYuMDUGCCsGAQUFBwEBBCkw
+JzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AucGtpLmdvb2cvZ3NyMjAyBgNVHR8E
+KzApMCegJaAjhiFodHRwOi8vY3JsLnBraS5nb29nL2dzcjIvZ3NyMi5jcmwwPwYD
+VR0gBDgwNjA0BgZngQwBAgIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly9wa2kuZ29v
+Zy9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAHLeJluRT7bvs26gyAZ8s
+o81trUISd7O45skDUmAge1cnxhG1P2cNmSxbWsoiCt2eux9LSD+PAj2LIYRFHW31
+/6xoic1k4tbWXkDCjir37xTTNqRAMPUyFRWSdvt+nlPqwnb8Oa2I/maSJukcxDjN
+SfpDh/Bd1lZNgdd/8cLdsE3+wypufJ9uXO1iQpnh9zbuFIwsIONGl1p3A8CgxkqI
+/UAih3JaGOqcpcdaCIzkBaR9uYQ1X4k2Vg5APRLouzVy7a8IVk6wuy6pm+T7HT4L
+Y8ibS5FEZlfAFLSW8NwsVz9SBK2Vqn1N0PIMn5xA6NZVc7o835DLAFshEWfC7TIe
+3jCCBFMwggI7oAMCAQICAhAAMA0GCSqGSIb3DQEBCwUAMGsxCzAJBgNVBAYTAlVL
+MRAwDgYDVQQIDAdFbmdsYW5kMR8wHQYDVQQKDBZYbWxzZWN1cml0eSBFQ0RTQSBU
+ZXN0MSkwJwYDVQQDDCBYbWxzZWN1cml0eSBJbnRlcm1lZGlhdGUgUm9vdCBDQTAg
+Fw0xODA2MDYxNTIwMjFaGA8yMTE4MDUxMzE1MjAyMVowbzELMAkGA1UEBhMCVUsx
+EDAOBgNVBAgMB0VuZ2xhbmQxHzAdBgNVBAoMFlhtbHNlY3VyaXR5IEVDRFNBIFRl
+c3QxLTArBgNVBAMMJFhtbHNlY3VyaXR5IEVDRFNBIFRlc3QgZXhhbXBsZSBBbGlj
+ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABARLFn7pnI5fqVyPKZsn+1aFSgoF
+NxwX30u97S9Ti3v0LkMhzCvJgCMRTRFE5Utzrg1tmNvAO1gl5Cn3VeRv/qWjgcUw
+gcIwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBaAwMwYJYIZIAYb4QgENBCYW
+JE9wZW5TU0wgR2VuZXJhdGVkIENsaWVudCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU
+6iBLx5qDOXkoKU2kRXYBsRuOKEQwHwYDVR0jBBgwFoAU0EyW4PhS5umRVdHSnb88
+88RIMkcwDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEF
+BQcDBDANBgkqhkiG9w0BAQsFAAOCAgEACu+ViKlFl5euwbhuysQro10mplQXhocM
+EpLyN4ZwSkplKbyfQIDahoCU1GSVUr6r5/3oOOjeqHNqeRYpd2hGQbmLaDydTbLO
+7Eb/i9u4VIYKrSKQCz4Q5Z7Hc/8hD+YFuwN8xQdzQRE5tMqHQ2PmEYwYkt0ABbqA
+El0Ae5nII98ejz5b1S7a4wPSr4CLVhSUDBTUSglJxaT5ZTa/rhmUjgOg4cFgE+Qm
+OQuaD2VEy65eCWcjUY7r7ZNP6+JbHVBW8DxiWvBd2YZwh4A4TwxUwRwcOgDMh8Z8
+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
+2kKXeAYV3wwAzKqplc7KW07VFFNNdjO3nQbVSYAR3ZIMfoAOqPxPTgjRSKumxDtv
+gZqwmiZZAG4K/2NjrmsA593uZYfhEOZWfY/hcJVnr76gKavYIwRF+hGxUi3fGDHk
+665Xgx0BxUHDosyRDPolGn3aQQY8wT3HXCcNFyeSznzOcK+ixlETAtj+y1arZ4ts
+4pnl0ImqILjEZxrmXTAkRO51TlYt0iA8NQVDa1Ne64Fy2N3OHz4XJzo3aoynf5Ta
+bakQCsh3/prFpCGMYkQMkxXonTdaJnyX/0aMiVfYdAZupG8cAvuRQSQ/i1k5SLAY
+ai1qQW8kmJVYPKdWmEvyBNqZHWVpNiG3SZka1nklMxzCkTfv7Z2Ix8DL+GqM5cNz
+I0DDfG0sOVfqLlcraumu7wZpY+KRGSBN9EF1ZZ9GOX7SwTn57U3yYd0xMIIFujCC
+A6KgAwIBAgIJAMtBg6xEFRDTMA0GCSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVL
+MRAwDgYDVQQIDAdFbmdsYW5kMR8wHQYDVQQKDBZYbWxzZWN1cml0eSBFQ0RTQSBU
+ZXN0MScwJQYDVQQDDB5YbWxzZWN1cml0eSBFQ0RTQSBUZXN0IFJvb3QgQ0EwIBcN
+MTgwNjA2MTUyMDIxWhgPMjExODA1MTMxNTIwMjFaMGkxCzAJBgNVBAYTAlVLMRAw
+DgYDVQQIDAdFbmdsYW5kMR8wHQYDVQQKDBZYbWxzZWN1cml0eSBFQ0RTQSBUZXN0
+MScwJQYDVQQDDB5YbWxzZWN1cml0eSBFQ0RTQSBUZXN0IFJvb3QgQ0EwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCjKXY/LOLDioXDCWBi3GLP29BMDoYx
+J0tkL9Pdir7mBACxRshI9K/eHfzzBURDWycUfW9jU9xPtt2NfJFB3TfUjet4uHkr
+f2K9oZW9QxloVvBSAMPR5393o/cSrcijJ1BA77hilZJQ75t8xOgqBu5uxLfR3yS2
+GHnZAqckavR9y7oQEbmf/b1b+Fa1WWz21RuT82E02M0Ew2/NpvrP7dpkgovyvLPz
+J/pDrdTWOzzYmvNxuKRnHsaDdBSPvgsGmokbZr5GevK5CUYhSumpcD+orZVelFxI
+Fv+KAMAZGlIyyW6Ipv5fs4fGORLJy0h1z2SYzNz41bqnWZsDCruZmEI4RCZkCfq2
+7gEoPQVRjP+RsgpZmnuI2Deyw33Uh/pLtUYf3bjOPnKRThRqzDl7JC27sRhgdUDM
+2KLOPC7IVMG+u94ejOvzSJ5zVdujNvki5OEscN4xPWUDYj/y3QOnDp8MarCd7al4
+P+Dk3niNnkFMLFSl+gbbLjDNcrabtVqCnd/dmgjwiU9k80oNa0jKx7pdKPqPvxKM
+e5xffmkDp9XFdKl7qeDprk5KQ9PtCO00JTVQGhyxapmMuUsJgezpGQSqF5wAKrNm
+dcdHWtFeZDq1IoLMQUS9uMCzzHV5tAfFDX/GnAz2xnPq88RW7nt9LFjzWA8ZsTYf
+/LPjaO+tYim8wQIDAQABo2MwYTAdBgNVHQ4EFgQUIDesPjHcCxXnc1U8kKP6BXGA
+WtUwHwYDVR0jBBgwFoAUIDesPjHcCxXnc1U8kKP6BXGAWtUwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAByhIRpqnRqr
+z/NrI2+LsQawI5PYFyyA8QDxHJveId8DX7OIJDqoXxdl0pqhPSli+2f1ZaLzfTfY
+av1BT2+ALcVY1DDz4RHSUg1YLk6n+1IPeq4hSAf7JVa13tA8tyK7ghjZMCIzX08Z
+Ux9Wz5FlnGSC/jFg2qRjjlZyHQB4N9mLtPp83OEuQBuFJ2LMd6dHcDDpERjrRGpH
+tLFxYnLKgT745h0A/k/HjZLKs46xJBO1y8ZruOoNKklsTkiysGImhRW4KnLJ5iSS
+/V6vzfaCGcDxSSYlbIT1twEN1lRcCuPlPmm7LgV/X12lACg+UR12/dcJnCe94x4E
+QaydT0wsAzT5WSNh69UOrRp0sDJrKtehhQ+7oGeIqTYQNpnmvA3L3MssRvcyw9wB
+ZUdAAw0Jr3jsgy0wZuYIFSbEUWzTlyhkL2Rhp9zzq4f0AW61m+yDb8QXkPnWJPln
+NrKqKYGTfzQNcMSIkcLiDnAmsBeZOze+iXpnuzZSWqlkPQfGhlFRkJ4jm63H15cX
+Hz2OE7zr/HoMJCxXXUbFVIyHDL2i9GbShHr+DVIM9OgBJ6UEPNEN2RZo4vncNCnQ
+zRZe4H1bvaGnh0SUKoLiE2Jy93LBUKrSygHLOtweerXL2dtHad2qi+SQjWXjYBUr
+Y3U3LDo+kQfo7hfVZ/HdrhK7ldhXbz7nMQA=
+-----END PKCS7-----
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index 91d1def56230..5330d45b46cc 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -214,8 +214,15 @@ void SigningTest::setUp()
     OUString aTargetPath;
     osl::FileBase::getSystemPathFromFileURL(aTargetDir, aTargetPath);
 
+#ifdef _WIN32
+    // CryptoAPI test certificates
+    osl::File::copy(aSourceDir + "test.p7b", aTargetDir + "/test.p7b");
+    OUString caVar("LIBO_TEST_CRYPTOAPI_PKCS7");
+    osl_setEnvironment(caVar.pData, aTargetPath.pData);
+#else
     OUString mozCertVar("MOZILLA_CERTIFICATE_FOLDER");
     osl_setEnvironment(mozCertVar.pData, aTargetPath.pData);
+#endif
     OUString gpgHomeVar("GNUPGHOME");
     osl_setEnvironment(gpgHomeVar.pData, aTargetPath.pData);
 
@@ -697,7 +704,8 @@ CPPUNIT_TEST_FIXTURE(SigningTest, 
testODFX509CertificateChain)
     CPPUNIT_ASSERT(infos[0].Signer.is());
     CPPUNIT_ASSERT_EQUAL(
         OUString("CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA 
Test,ST=England,C=UK"),
-        infos[0].Signer->getSubjectName());
+        // CryptoAPI puts a space after comma, NSS does not...
+        infos[0].Signer->getSubjectName().replaceAll(", ", ","));
 }
 
 CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Data)
@@ -766,9 +774,15 @@ CPPUNIT_TEST_FIXTURE(SigningTest, 
testODFDoubleX509Certificate)
     SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
     CPPUNIT_ASSERT(pObjectShell);
     SignatureState nActual = pObjectShell->GetDocumentSignatureState();
-    CPPUNIT_ASSERT_MESSAGE(
-        
(OString::number(/*o3tl::underlyingEnumValue(*/(int)nActual/*)*/).getStr()),
-        (nActual == SignatureState::NOTVALIDATED || nActual == 
SignatureState::OK));
+    bool const nTemp((nActual == SignatureState::NOTVALIDATED
+                      || nActual == SignatureState::OK
+#if defined(_WIN32)
+                      // oddly BCryptVerifySignature returns 
STATUS_INVALID_SIGNATURE
+                      // while the same succeeds with NSS 
_SGN_VerifyPKCS1DigestInfo
+                      || nActual == SignatureState::BROKEN
+#endif
+                      ));
+    
CPPUNIT_ASSERT_MESSAGE((OString::number(/*o3tl::underlyingEnumValue(*/(int)nActual/*)*/).getStr()),
 nTemp);
     uno::Sequence<security::DocumentSignatureInformation> const infos(
         pObjectShell->GetDocumentSignatureInformation(false));
     CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
diff --git 
a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx 
b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
index f339c1be480d..09ac700105b5 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
@@ -774,6 +774,61 @@ static HCERTSTORE getCertStoreForIntermediatCerts(
     return store;
 }
 
+static bool CheckUnitTestStore(PCCERT_CHAIN_CONTEXT const pChainContext, DWORD 
ignoreFlags)
+{
+    bool ret = false;
+    OUString const v("LIBO_TEST_CRYPTOAPI_PKCS7");
+    OUString var;
+    if (osl_Process_E_None != osl_getEnvironment(v.pData, &var.pData))
+    {
+        return ret;
+    }
+    if (pChainContext->cChain == 0)
+    {
+        return ret;
+    }
+    PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0];
+    // check if untrusted root is the only problem
+    if (pSimpleChain->TrustStatus.dwErrorStatus & 
~(CERT_TRUST_IS_UNTRUSTED_ROOT | ignoreFlags))
+    {
+        return ret;
+    }
+
+    // leak this store, re-opening is a waste of time in tests
+    static HCERTSTORE const hExtra = CertOpenStore(
+            CERT_STORE_PROV_FILENAME,
+            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+            NULL,
+            CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
+            OUString(var + "/test.p7b").getStr());
+    assert(hExtra != NULL);
+    if (pSimpleChain->cElement < 1)
+    {
+        SAL_WARN("xmlsecurity.xmlsec", "unexpected empty chain");
+        return ret;
+    }
+    PCCERT_CONTEXT const 
pRoot(pSimpleChain->rgpElement[pSimpleChain->cElement-1]->pCertContext);
+    PCCERT_CONTEXT const pIssuerCert = CertFindCertificateInStore(
+            hExtra,
+            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+            0,
+            CERT_FIND_SUBJECT_NAME,
+            &pRoot->pCertInfo->Subject,
+            NULL);
+    if (pIssuerCert)
+    {
+        // check that it signed itself
+        DWORD flags = CERT_STORE_SIGNATURE_FLAG;
+        BOOL result = CertVerifySubjectCertificateContext(pRoot, pIssuerCert, 
&flags);
+        if (result == TRUE && flags == 0)
+        {
+            ret = true;
+        }
+    }
+    CertFreeCertificateContext(pIssuerCert);
+    return ret;
+}
+
 //We return only valid or invalid, as long as the API documentation expresses
 //explicitly that all validation steps are carried out even if one or several
 //errors occur. See also
@@ -877,7 +932,8 @@ sal_Int32 
SecurityEnvironment_MSCryptImpl::verifyCertificate(
             DWORD revocationFlags = CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
                 CERT_TRUST_IS_OFFLINE_REVOCATION;
             DWORD otherErrorsMask = ~revocationFlags;
-            if( !(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask))
+            if (!(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask)
+                || CheckUnitTestStore(pChainContext, revocationFlags))
 
             {
                 //No errors except maybe those caused by missing revocation 
information
@@ -906,6 +962,11 @@ sal_Int32 
SecurityEnvironment_MSCryptImpl::verifyCertificate(
                         SAL_INFO("xmlsecurity.xmlsec", "Certificate is 
valid.");
                         validity = css::security::CertificateValidity::VALID;
                     }
+                    else if (CheckUnitTestStore(pChainContext, 0))
+                    {
+                        SAL_INFO("xmlsecurity.xmlsec", "root certificate found 
in extra test store");
+                        validity = css::security::CertificateValidity::VALID;
+                    }
                     else
                     {
                         SAL_INFO("xmlsecurity.xmlsec", "Certificate is 
invalid.");
commit 8004a416b6ebebadb26eed555de3398d181dec03
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Feb 26 17:29:37 2021 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 20:24:10 2022 +0200

    xmlsecurity: add tests for multiple X509Data/X509Certificate
    
    Change-Id: If50ae8156f81c1053aa8fbfc3148da64bb8e1442
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123438
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 956c638025e3c0bbe816f710da64769cf5874f4f)

diff --git 
a/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt
 
b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt
new file mode 100644
index 000000000000..d63e4b6b7b72
Binary files /dev/null and 
b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt
 differ
diff --git 
a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt 
b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt
new file mode 100644
index 000000000000..0190abb00f23
Binary files /dev/null and 
b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt 
differ
diff --git 
a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt 
b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt
new file mode 100644
index 000000000000..f4b4198f94a6
Binary files /dev/null and 
b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt 
differ
diff --git 
a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt
 
b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt
new file mode 100644
index 000000000000..558bdee47e59
Binary files /dev/null and 
b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt
 differ
diff --git 
a/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt 
b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt
new file mode 100644
index 000000000000..5e519dd8b7e7
Binary files /dev/null and 
b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index ff56ab953531..91d1def56230 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -24,6 +24,7 @@
 #include <com/sun/star/embed/XTransactedObject.hpp>
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
@@ -676,6 +677,105 @@ CPPUNIT_TEST_FIXTURE(SigningTest, 
testODFUnsignedTimestamp)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(18183742), infos[0].SignatureTime);
 }
 
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFX509CertificateChain)
+{
+    createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+              + "signed_with_x509certificate_chain.odt");
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+    CPPUNIT_ASSERT_MESSAGE(
+        
(OString::number(/*o3tl::underlyingEnumValue(*/(int)nActual/*)*/).getStr()),
+        (nActual == SignatureState::NOTVALIDATED || nActual == 
SignatureState::OK));
+    uno::Sequence<security::DocumentSignatureInformation> const infos(
+        pObjectShell->GetDocumentSignatureInformation(false));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+    // check that the signing certificate was picked, not one of the 2 CA ones
+    CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::VALID, 
infos[0].CertificateStatus);
+    CPPUNIT_ASSERT(infos[0].Signer.is());
+    CPPUNIT_ASSERT_EQUAL(
+        OUString("CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA 
Test,ST=England,C=UK"),
+        infos[0].Signer->getSubjectName());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Data)
+{
+    createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+              + "02_doc_signed_by_attacker_manipulated.odt");
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+    CPPUNIT_ASSERT_MESSAGE(
+        
(OString::number(/*o3tl::underlyingEnumValue(*/(int)nActual/*)*/).getStr()),
+        (nActual == SignatureState::NOTVALIDATED || nActual == 
SignatureState::OK));
+    uno::Sequence<security::DocumentSignatureInformation> const infos(
+        pObjectShell->GetDocumentSignatureInformation(false));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+    CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, 
infos[0].CertificateStatus);
+    CPPUNIT_ASSERT(!infos[0].Signer.is());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFTripleX509Data)
+{
+    createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+              + "02_doc_signed_by_attacker_manipulated_triple.odt");
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+    // here, libxmlsec will pick the 1st X509Data but signing key is the 2nd
+    
CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(/*o3tl::underlyingEnumValue(*/(int)nActual/*)*/).getStr()),
+                                 SignatureState::BROKEN, nActual);
+    uno::Sequence<security::DocumentSignatureInformation> const infos(
+        pObjectShell->GetDocumentSignatureInformation(false));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+    CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, 
infos[0].CertificateStatus);
+    CPPUNIT_ASSERT(!infos[0].Signer.is());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFMacroDoubleX509Data)
+{
+    createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+              + "02_doc_macros_signed_by_attacker_manipulated.odt");
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    SignatureState nActual = pObjectShell->GetScriptingSignatureState();
+    CPPUNIT_ASSERT_MESSAGE(
+        
(OString::number(/*o3tl::underlyingEnumValue(*/(int)nActual/*)*/).getStr()),
+        (nActual == SignatureState::NOTVALIDATED || nActual == 
SignatureState::OK));
+    uno::Sequence<security::DocumentSignatureInformation> const infos(
+        pObjectShell->GetDocumentSignatureInformation(true));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+    CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, 
infos[0].CertificateStatus);
+    CPPUNIT_ASSERT(!infos[0].Signer.is());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Certificate)
+{
+    createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+              + "02_doc_signed_by_attacker_manipulated2.odt");
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+    CPPUNIT_ASSERT_MESSAGE(
+        
(OString::number(/*o3tl::underlyingEnumValue(*/(int)nActual/*)*/).getStr()),
+        (nActual == SignatureState::NOTVALIDATED || nActual == 
SignatureState::OK));
+    uno::Sequence<security::DocumentSignatureInformation> const infos(
+        pObjectShell->GetDocumentSignatureInformation(false));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+    CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, 
infos[0].CertificateStatus);
+    CPPUNIT_ASSERT(!infos[0].Signer.is());
+}
+
 /// Test a typical OOXML where a number of (but not all) streams are signed.
 void SigningTest::testOOXMLPartial()
 {
commit 068bf3693ff57acdf87b480ceddbf17edfcddb0c
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Feb 26 17:24:10 2021 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 20:20:36 2022 +0200

    xmlsecurity: add test for timestamps
    
    Change-Id: I6ce64ca7c59639684779144ed0ed8d36c4aca32b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123437
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 3aabce61782c9561a0e1680fe1ecc58ac87be0ee)

diff --git 
a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt
 
b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt
new file mode 100644
index 000000000000..4136b32e5610
Binary files /dev/null and 
b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt
 differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index 1853b5eead8c..ff56ab953531 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -62,6 +62,7 @@ char const DATA_DIRECTORY[] = 
"/xmlsecurity/qa/unit/signing/data/";
 /// Testsuite for the document signing feature.
 class SigningTest : public test::BootstrapFixture, public unotest::MacrosTest, 
public XmlTestTools
 {
+protected:
     uno::Reference<uno::XComponentContext> mxComponentContext;
     uno::Reference<lang::XComponent> mxComponent;
     uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer;
@@ -178,7 +179,7 @@ public:
     CPPUNIT_TEST(testPreserveMacroTemplateSignature10);
     CPPUNIT_TEST_SUITE_END();
 
-private:
+protected:
     void createDoc(const OUString& rURL);
     void createCalc(const OUString& rURL);
     uno::Reference<security::XCertificate>
@@ -653,6 +654,29 @@ void SigningTest::testODFNo()
                          
static_cast<int>(pObjectShell->GetDocumentSignatureState()));
 }
 
+// document has one signed timestamp and one unsigned timestamp
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFUnsignedTimestamp)
+{
+    createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+              + "02_doc_signed_by_trusted_person_manipulated.odt");
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+    CPPUNIT_ASSERT_MESSAGE(
+        
(OString::number(/*o3tl::underlyingEnumValue(*/(int)nActual/*)*/).getStr()),
+        (nActual == SignatureState::NOTVALIDATED || nActual == 
SignatureState::OK));
+    uno::Sequence<security::DocumentSignatureInformation> const infos(
+        pObjectShell->GetDocumentSignatureInformation(false));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+    // was: 66666666
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(20210126), infos[0].SignatureDate);
+    // was: 0
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(18183742), infos[0].SignatureTime);
+}
+
+/// Test a typical OOXML where a number of (but not all) streams are signed.
 void SigningTest::testOOXMLPartial()
 {
     createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx");
commit 0537731048d79f77b5557a1829836fb2bd0031b5
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Mar 11 20:23:31 2021 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 19:50:20 2022 +0200

    do same set error state as ReadAndVerifySignature does
    
    this function is nearly exactly the same as ReadAndVerifySignature
    except it doesn't set error-state on exception during parse
    
    Change-Id: Ife881f639a11d3185920ca62cc2cd22812fae36d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112366
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112412
    (cherry picked from commit 52a23d595b820cab27d76d0e7c129f2757c762d6)
    (cherry picked from commit ed6db8f42484f135137939cf38dc40fc3f0913b1)

diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx 
b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
index 9f35130df47c..adb387d0879e 100644
--- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
@@ -408,6 +408,7 @@ bool 
XMLSignatureHelper::ReadAndVerifySignatureStorageStream(const css::uno::Ref
     catch(const uno::Exception&)
     {
         DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper");
+        mbError = true;
     }
 
     mpXSecController->releaseSignatureReader();
commit b3ae92e082c3821082a30545a46000841312a9a1
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Wed Jun 17 14:54:06 2020 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 19:05:16 2022 +0200

    allow building as root inside a container without complaint
    
    add a check for $container
    
    Change-Id: Ib6921c6d771622fb5f4acb82d10aa6fb34e1bbac
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96538
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit e19b67dcf5e987e58ce4252d8d1c8313d111df85)

diff --git a/Makefile.in b/Makefile.in
index c3724534e530..9fd266106cb3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -60,7 +60,7 @@ else # MAKE_RESTARTS
 all: build
 
 check-if-root:
-       @if test ! `uname` = 'Haiku' -a `id -u` = 0 && ! grep -q 'lxc\|docker' 
/proc/self/cgroup && ! grep -q 'libpod_parent' /proc/self/cgroup; then \
+       @if test ! `uname` = 'Haiku' -a `id -u` = 0 && test -z $$container && ! 
grep -q 'lxc\|docker' /proc/self/cgroup && ! grep -q 'libpod_parent' 
/proc/self/cgroup; then \
                echo; \
                echo 'Building LibreOffice as root is a very bad idea, use a 
regular user.'; \
                echo; \
commit ac7b16f82a9a48e90583eee5922de7368f743654
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Sat Jan 4 14:52:40 2020 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 19:04:15 2022 +0200

    allow root under podman
    
    Change-Id: I66dc674aab8dc86c95495754400c5e64b2583599
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86223
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    Tested-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 6fbfb54086c10f0107dc7026eaeffd177eda56c3)

diff --git a/Makefile.in b/Makefile.in
index 393e94fda331..c3724534e530 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -60,7 +60,7 @@ else # MAKE_RESTARTS
 all: build
 
 check-if-root:
-       @if test ! `uname` = 'Haiku' -a `id -u` = 0 && ! grep -q 'lxc\|docker' 
/proc/self/cgroup; then \
+       @if test ! `uname` = 'Haiku' -a `id -u` = 0 && ! grep -q 'lxc\|docker' 
/proc/self/cgroup && ! grep -q 'libpod_parent' /proc/self/cgroup; then \
                echo; \
                echo 'Building LibreOffice as root is a very bad idea, use a 
regular user.'; \
                echo; \
commit 35adbb0b38fb0a96e29e651cf5c701ddb2074c76
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Nov 12 17:23:48 2021 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 18:52:01 2022 +0200

    Revert "Comment out failing unit test"
    
    This reverts commit df1033d3e5692ea11dc2ac9ea08e8a245996dab1.

diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx 
b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index 2ee0f54e2832..894aca99a26a 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -454,9 +454,8 @@ void PDFSigningTest::testBadCertP1()
     // - Expected: 0 (SecurityOperationStatus_UNKNOWN)
     // - Actual  : 1 (SecurityOperationStatus_OPERATION_SUCCEEDED)
     // i.e. annotation after a P1 signature was not considered as a bad 
modification.
-    // FIXME This fails for some reason...
-    
//CPPUNIT_ASSERT_EQUAL(xml::crypto::SecurityOperationStatus::SecurityOperationStatus_UNKNOWN,
-    //                     rInformation.nStatus);
+    
CPPUNIT_ASSERT_EQUAL(xml::crypto::SecurityOperationStatus::SecurityOperationStatus_UNKNOWN,
+                         rInformation.nStatus);
 }
 
 /// Test writing a PAdES signature.
commit f9d8a81f7e93c816a55d5ab04c427f7f6a47c460
Author:     Stephan Bergmann <sberg...@redhat.com>
AuthorDate: Thu Oct 1 11:50:40 2020 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 18:52:01 2022 +0200

    exteranl/coinmp: Fix build with recent GCC 11 trunk
    
    It had started to fail for me now with
    
    >  ~/gcc/trunk/inst/bin/g++ -DHAVE_CONFIG_H -I. -I. -O -MT CoinFinite.lo 
-MD -MP -MF .deps/CoinFinite.Tpo -c CoinFinite.cpp  -fPIC -DPIC -o 
.libs/CoinFinite.o
    > CoinFinite.cpp: In function 'bool CoinFinite(double)':
    > CoinFinite.cpp:38:19: error: 'DBL_MAX' was not declared in this scope
    >    38 |     return val != DBL_MAX && val != -DBL_MAX;
    >       |                   ^~~~~~~
    > CoinFinite.cpp:8:1: note: 'DBL_MAX' is defined in header '<cfloat>'; did 
you forget to '#include <cfloat>'?
    >     7 | #include "CoinUtilsConfig.h"
    >   +++ |+#include <cfloat>
    >     8 |
    
    because of a missing -DCOINUTILS_BUILD.  Which in turn was caused by
    workdir/UnpackedTarball/coinmp/CoinUtils/configure (see
    workdir/UnpackedTarball/coinmp/CoinUtils/config.log), which first tries to
    determine an ac_declaration that would apparently be a suitable declaration 
of
    `exit` without actually including <stdlib.h> in a C++ file.  It settles on
    
    > configure:3551: ~/gcc/trunk/inst/bin/g++ -c -g -O2  conftest.cc >&5
    > conftest.cc:15:17: warning: 'void std::exit(int)' has not been declared 
within 'std'
    >    15 | extern "C" void std::exit (int) throw (); using std::exit;
    >       |                 ^~~
    > <built-in>: note: only here as a 'friend'
    > configure:3557: $? = 0
    
    (which generates a warning, but no error with the given g++ invocation).  
The
    determined ac_declaration value is then included in confdefs.h, causing the
    later
    
    > configure:4014: ~/gcc/trunk/inst/bin/g++ -o conftest -O3 -pipe -DNDEBUG 
-pedantic-errors -Wparentheses -Wreturn-type -Wcast-qual -Wall -Wpointer-arith 
-Wwrite-strings -Wconversion -Wno-unknown-pragmas -Wno-long-long   
-DCOINUTILS_BUILD  -Wl,-z,origin -Wl,-rpath,\$$ORIGIN conftest.cc  >&5
    > conftest.cc:15:17: error: 'void std::exit(int)' has not been declared 
within 'std'
    >    15 | extern "C" void std::exit (int) throw (); using std::exit;
    >       |                 ^~~
    > <built-in>: note: only here as a 'friend'
    > configure:4020: $? = 1
    > configure: failed program was:
    > | /* confdefs.h.  */
    > |
    > | #define PACKAGE_NAME "CoinUtils"
    > | #define PACKAGE_TARNAME "coinutils"
    > | #define PACKAGE_VERSION "2.9.11"
    > | #define PACKAGE_STRING "CoinUtils 2.9.11"
    > | #define PACKAGE_BUGREPORT "http://projects.coin-or.org/CoinUtils";
    > | #define COINUTILS_VERSION "2.9.11"
    > | #define COINUTILS_VERSION_MAJOR 2
    > | #define COINUTILS_VERSION_MINOR 9
    > | #define COINUTILS_VERSION_RELEASE 11
    > | #define COIN_COINUTILS_VERBOSITY 0
    > | #define COIN_COINUTILS_CHECKLEVEL 0
    > | #ifdef __cplusplus
    > | extern "C" void std::exit (int) throw (); using std::exit;
    > | #endif
    > | /* end confdefs.h.  */
    > |
    > | int
    > | main ()
    > | {
    > | int i=0; i++;
    > |   ;
    > |   return 0;
    > | }
    > configure:4045: WARNING: The flags CXXFLAGS="-O3 -pipe -DNDEBUG 
-pedantic-errors -Wparentheses -Wreturn-type -Wcast-qual -Wall -Wpointer-arith 
-Wwrite-strings -Wconversion -Wno-unknown-pragmas -Wno-long-long   
-DCOINUTILS_BUILD" do not work.  I will now just try '-O', but you might want 
to set CXXFLAGS manually.
    
    to fail, because its g++ invocation including -pedantic-errors turns that
    
    > 'void std::exit(int)' has not been declared within 'std'
    
    warning into an error.
    
    There were similar build failures in the Cgl,
    
    >  ~/gcc/trunk/inst/bin/g++ -DHAVE_CONFIG_H -I. -I. 
-I~/lo/core/workdir/UnpackedTarball/coinmp/CoinUtils/src -DCOIN_HAS_CLP -O -MT 
ClpCholeskyDense.lo -MD -MP -MF .deps/ClpCholeskyDense.Tpo -c 
ClpCholeskyDense.cpp  -fPIC -DPIC -o .libs/ClpCholeskyDense.o
    > In file included from ClpCholeskyDense.cpp:11:
    > ClpHelperFunctions.hpp:16:4: error: #error "don't have header file for 
math"
    >    16 | #  error "don't have header file for math"
    >       |    ^~~~~
    > In file included from ClpCholeskyDense.cpp:11:
    > ClpHelperFunctions.hpp: In function 'double CoinSqrt(double)':
    > ClpHelperFunctions.hpp:81:13: error: 'sqrt' was not declared in this scope
    >    81 |      return sqrt(x);
    >       |             ^~~~
    
    and Clp,
    
    >  ~/gcc/trunk/inst/bin/g++ -DHAVE_CONFIG_H -I. -I. -I.. -I./.. 
-I./../CglGomory -I~/lo/core/workdir/UnpackedTarball/coinmp/CoinUtils/src 
-I~/lo/core/workdir/UnpackedTarball/coinmp/Osi/src/Osi 
-I~/lo/core/workdir/UnpackedTarball/coinmp/CoinUtils/src 
-I~/lo/core/workdir/UnpackedTarball/coinmp/Clp/src/OsiClp 
-I~/lo/core/workdir/UnpackedTarball/coinmp/Clp/src 
-I~/lo/core/workdir/UnpackedTarball/coinmp/CoinUtils/src 
-I~/lo/core/workdir/UnpackedTarball/coinmp/Osi/src/Osi -O -MT 
CglLandPValidator.lo -MD -MP -MF .deps/CglLandPValidator.Tpo -c 
CglLandPValidator.cpp  -fPIC -DPIC -o .libs/CglLandPValidator.o
    > CglLandPValidator.cpp: In member function 'int 
LAP::Validator::cleanCut(OsiRowCut&, const double*, const OsiSolverInterface&, 
const CglParam&, const double*, const double*)':
    > CglLandPValidator.cpp:66:22: error: 'fabs' was not declared in this 
scope; did you mean 'labs'?
    >    66 |         double val = fabs(elems[i]);
    >       |                      ^~~~
    >       |                      labs
    > CglLandPValidator.cpp: In member function 'int 
LAP::Validator::cleanCut2(OsiRowCut&, const double*, const OsiSolverInterface&, 
const CglParam&, const double*, const double*)':
    > CglLandPValidator.cpp:189:23: error: 'fabs' was not declared in this 
scope; did you mean 'labs'?
    >   189 |     double smallest = fabs(rhs);
    >       |                       ^~~~
    >       |                       labs
    
    subdirectories, and which happened to get solved by the same approach of
    removing problematic ac_declaration values from configure.
    
    I am not sure what all that magic of determining that ac_declaration value 
is
    supposed to be good for.  There appears to be no trace of it in the
    corresponding configure.ac sources, so it likely was automatically added by 
some
    dated autotools (all three configure files mention "Generated by GNU
    Autoconf 2.59").  At least on a cursory look, the determined ac_declaration
    appears to only be used in configure itself, and not leak into the actual 
coinmp
    build stage, so dropping the problematic ac_declaration values is hopefully
    harmless.  These three subdirectories were all that failed for me, but there
    might still be silent issues in other subdirectories when a problematic
    ac_declaration value would negatively affect other configure checks.  (An
    alternative approach could be to regenerate all the configure files from 
their
    configure.ac sources with a recent autotools.  But at least some of the 
existing
    external/coinmp/*.patch* already change such configure files, which would 
need
    to be adapted.)
    
    Change-Id: I0a33b0f654800e8288d3ca28e26a64efc23a3f6b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103756
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    (cherry picked from commit 762aacc4e055fffbc605be81f66f2274dccb4be8)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114999
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 802b76340082e817efe67a5be4a021cb998a28a2)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115502
    Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    (cherry picked from commit 14b706520cc45a5b4b20da58deda5802384270f0)

diff --git a/external/coinmp/UnpackedTarball_coinmp.mk 
b/external/coinmp/UnpackedTarball_coinmp.mk
index c1f3df9866b1..a918effb1203 100644
--- a/external/coinmp/UnpackedTarball_coinmp.mk
+++ b/external/coinmp/UnpackedTarball_coinmp.mk
@@ -41,6 +41,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,coinmp,\
        external/coinmp/rpath.patch \
        external/coinmp/libtool.patch \
        external/coinmp/register.patch \
+       external/coinmp/configure-exit.patch \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/external/coinmp/configure-exit.patch 
b/external/coinmp/configure-exit.patch
new file mode 100644
index 000000000000..0a81b8073fd2
--- /dev/null
+++ b/external/coinmp/configure-exit.patch
@@ -0,0 +1,33 @@
+--- Cgl/configure
++++ Cgl/configure
+@@ -3501,8 +3501,6 @@
+ fi
+ for ac_declaration in \
+    '' \
+-   'extern "C" void std::exit (int) throw (); using std::exit;' \
+-   'extern "C" void std::exit (int); using std::exit;' \
+    'extern "C" void exit (int) throw ();' \
+    'extern "C" void exit (int);' \
+    'void exit (int);'
+--- Clp/configure
++++ Clp/configure
+@@ -3528,8 +3528,6 @@
+ fi
+ for ac_declaration in \
+    '' \
+-   'extern "C" void std::exit (int) throw (); using std::exit;' \
+-   'extern "C" void std::exit (int); using std::exit;' \
+    'extern "C" void exit (int) throw ();' \
+    'extern "C" void exit (int);' \
+    'void exit (int);'
+--- CoinUtils/configure
++++ CoinUtils/configure
+@@ -3527,8 +3527,6 @@
+ fi
+ for ac_declaration in \
+    '' \
+-   'extern "C" void std::exit (int) throw (); using std::exit;' \
+-   'extern "C" void std::exit (int); using std::exit;' \
+    'extern "C" void exit (int) throw ();' \
+    'extern "C" void exit (int);' \
+    'void exit (int);'
commit c967ff04fcb8001c194eea1157b247751238068d
Author:     Stephan Bergmann <sberg...@redhat.com>
AuthorDate: Mon Jul 20 16:23:18 2020 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Apr 6 18:52:01 2022 +0200

    external/coinmp: C++17 no longer supports "register"
    
    ...and GCC 11 trunk g++ now defaults to C++17, so compilation started to 
fail
    with that compiler
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99082
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    (cherry picked from commit ad607d898f9826c6fa144783c93541a10ad4740c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114998
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 656085bf2757437a088058871573385ff45f8ef5)
    
    Change-Id: I792e4c7ff59ad88e5571163d5b2362fdb349667d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115501
    Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    (cherry picked from commit 841534cb8404a379207165aa5dc4496d6cb98319)

diff --git a/external/coinmp/UnpackedTarball_coinmp.mk 
b/external/coinmp/UnpackedTarball_coinmp.mk
index 35cfbfcdbae8..c1f3df9866b1 100644
--- a/external/coinmp/UnpackedTarball_coinmp.mk
+++ b/external/coinmp/UnpackedTarball_coinmp.mk
@@ -40,6 +40,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,coinmp,\
        external/coinmp/ubsan.patch.0 \
        external/coinmp/rpath.patch \
        external/coinmp/libtool.patch \
+       external/coinmp/register.patch \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/external/coinmp/register.patch b/external/coinmp/register.patch
new file mode 100644
index 000000000000..cf4ca4d06c01
--- /dev/null
+++ b/external/coinmp/register.patch
@@ -0,0 +1,369 @@
+--- CoinUtils/src/CoinHelperFunctions.hpp
++++ CoinUtils/src/CoinHelperFunctions.hpp
+@@ -41,7 +41,7 @@
+     handled correctly. */
+ 
+ template <class T> inline void
+-CoinCopyN(register const T* from, const int size, register T* to)
++CoinCopyN(const T* from, const int size, T* to)
+ {
+     if (size == 0 || from == to)
+       return;
+@@ -52,10 +52,10 @@
+                       "CoinCopyN", "");
+ #endif
+ 
+-    register int n = (size + 7) / 8;
++    int n = (size + 7) / 8;
+     if (to > from) {
+-      register const T* downfrom = from + size;
+-      register T* downto = to + size;
++      const T* downfrom = from + size;
++      T* downto = to + size;
+       // Use Duff's device to copy
+       switch (size % 8) {
+       case 0: do{     *--downto = *--downfrom;
+@@ -99,7 +99,7 @@
+     the difference down to int.  -- lh, 100823 --
+ */
+ template <class T> inline void
+-CoinCopy(register const T* first, register const T* last, register T* to)
++CoinCopy(const T* first, const T* last, T* to)
+ {
+     CoinCopyN(first, static_cast<int>(last-first), to);
+ }
+@@ -114,7 +114,7 @@
+     Note JJF - the speed claim seems to be false on IA32 so I have added 
+     CoinMemcpyN which can be used for atomic data */
+ template <class T> inline void
+-CoinDisjointCopyN(register const T* from, const int size, register T* to)
++CoinDisjointCopyN(const T* from, const int size, T* to)
+ {
+ #ifndef _MSC_VER
+     if (size == 0 || from == to)
+@@ -135,7 +135,7 @@
+       throw CoinError("overlapping arrays", "CoinDisjointCopyN", "");
+ #endif
+ 
+-    for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
++    for (int n = size / 8; n > 0; --n, from += 8, to += 8) {
+       to[0] = from[0];
+       to[1] = from[1];
+       to[2] = from[2];
+@@ -167,8 +167,8 @@
+     are copied at a time. The source array is given by its first and "after
+     last" entry; the target array is given by its first entry. */
+ template <class T> inline void
+-CoinDisjointCopy(register const T* first, register const T* last,
+-               register T* to)
++CoinDisjointCopy(const T* first, const T* last,
++               T* to)
+ {
+     CoinDisjointCopyN(first, static_cast<int>(last - first), to);
+ }
+@@ -256,7 +256,7 @@
+     alternative coding if USE_MEMCPY defined*/
+ #ifndef COIN_USE_RESTRICT
+ template <class T> inline void
+-CoinMemcpyN(register const T* from, const int size, register T* to)
++CoinMemcpyN(const T* from, const int size, T* to)
+ {
+ #ifndef _MSC_VER
+ #ifdef USE_MEMCPY
+@@ -296,7 +296,7 @@
+       throw CoinError("overlapping arrays", "CoinMemcpyN", "");
+ #endif
+ 
+-    for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
++    for (int n = size / 8; n > 0; --n, from += 8, to += 8) {
+       to[0] = from[0];
+       to[1] = from[1];
+       to[2] = from[2];
+@@ -343,8 +343,8 @@
+     are copied at a time. The source array is given by its first and "after
+     last" entry; the target array is given by its first entry. */
+ template <class T> inline void
+-CoinMemcpy(register const T* first, register const T* last,
+-         register T* to)
++CoinMemcpy(const T* first, const T* last,
++         T* to)
+ {
+     CoinMemcpyN(first, static_cast<int>(last - first), to);
+ }
+@@ -358,7 +358,7 @@
+     Note JJF - the speed claim seems to be false on IA32 so I have added 
+     CoinZero to allow for memset. */
+ template <class T> inline void
+-CoinFillN(register T* to, const int size, register const T value)
++CoinFillN(T* to, const int size, const T value)
+ {
+     if (size == 0)
+       return;
+@@ -369,7 +369,7 @@
+                       "CoinFillN", "");
+ #endif
+ #if 1
+-    for (register int n = size / 8; n > 0; --n, to += 8) {
++    for (int n = size / 8; n > 0; --n, to += 8) {
+       to[0] = value;
+       to[1] = value;
+       to[2] = value;
+@@ -413,7 +413,7 @@
+     entries are filled at a time. The array is given by its first and "after
+     last" entry. */
+ template <class T> inline void
+-CoinFill(register T* first, register T* last, const T value)
++CoinFill(T* first, T* last, const T value)
+ {
+     CoinFillN(first, last - first, value);
+ }
+@@ -427,7 +427,7 @@
+     Note JJF - the speed claim seems to be false on IA32 so I have allowed 
+     for memset as an alternative */
+ template <class T> inline void
+-CoinZeroN(register T* to, const int size)
++CoinZeroN(T* to, const int size)
+ {
+ #ifdef USE_MEMCPY
+     // Use memset - seems faster on Intel with gcc
+@@ -448,7 +448,7 @@
+                       "CoinZeroN", "");
+ #endif
+ #if 1
+-    for (register int n = size / 8; n > 0; --n, to += 8) {
++    for (int n = size / 8; n > 0; --n, to += 8) {
+       to[0] = 0;
+       to[1] = 0;
+       to[2] = 0;
+@@ -519,7 +519,7 @@
+     entries are filled at a time. The array is given by its first and "after
+     last" entry. */
+ template <class T> inline void
+-CoinZero(register T* first, register T* last)
++CoinZero(T* first, T* last)
+ {
+     CoinZeroN(first, last - first);
+ }
+@@ -545,7 +545,7 @@
+     This function was introduced because for some reason compiler tend to
+     handle the <code>max()</code> function differently. */
+ template <class T> inline T
+-CoinMax(register const T x1, register const T x2)
++CoinMax(const T x1, const T x2)
+ {
+     return (x1 > x2) ? x1 : x2;
+ }
+@@ -556,7 +556,7 @@
+     This function was introduced because for some reason compiler tend to
+     handle the min() function differently. */
+ template <class T> inline T
+-CoinMin(register const T x1, register const T x2)
++CoinMin(const T x1, const T x2)
+ {
+     return (x1 < x2) ? x1 : x2;
+ }
+@@ -578,7 +578,7 @@
+     according to operator<. The array is given by a pointer to its first entry
+     and by its size. */
+ template <class T> inline bool
+-CoinIsSorted(register const T* first, const int size)
++CoinIsSorted(const T* first, const int size)
+ {
+     if (size == 0)
+       return true;
+@@ -590,7 +590,7 @@
+ #if 1
+     // size1 is the number of comparisons to be made
+     const int size1 = size  - 1;
+-    for (register int n = size1 / 8; n > 0; --n, first += 8) {
++    for (int n = size1 / 8; n > 0; --n, first += 8) {
+       if (first[8] < first[7]) return false;
+       if (first[7] < first[6]) return false;
+       if (first[6] < first[5]) return false;
+@@ -627,7 +627,7 @@
+     according to operator<. The array is given by its first and "after
+     last" entry. */
+ template <class T> inline bool
+-CoinIsSorted(register const T* first, register const T* last)
++CoinIsSorted(const T* first, const T* last)
+ {
+     return CoinIsSorted(first, static_cast<int>(last - first));
+ }
+@@ -638,7 +638,7 @@
+     etc. For speed 8 entries are filled at a time. The array is given by a
+     pointer to its first entry and its size. */
+ template <class T> inline void
+-CoinIotaN(register T* first, const int size, register T init)
++CoinIotaN(T* first, const int size, T init)
+ {
+     if (size == 0)
+       return;
+@@ -648,7 +648,7 @@
+       throw CoinError("negative number of entries", "CoinIotaN", "");
+ #endif
+ #if 1
+-    for (register int n = size / 8; n > 0; --n, first += 8, init += 8) {
++    for (int n = size / 8; n > 0; --n, first += 8, init += 8) {
+       first[0] = init;
+       first[1] = init + 1;
+       first[2] = init + 2;
+@@ -706,7 +706,7 @@
+     integer array specified by the last two arguments (again, first and "after
+     last" entry). */
+ template <class T> inline T *
+-CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast,
++CoinDeleteEntriesFromArray(T * arrayFirst, T * arrayLast,
+                          const int * firstDelPos, const int * lastDelPos)
+ {
+     int delNum = static_cast<int>(lastDelPos - firstDelPos);
+--- CoinUtils/src/CoinModelUseful2.cpp
++++ CoinUtils/src/CoinModelUseful2.cpp
+@@ -917,8 +917,8 @@
+   
+   int position=0;
+   int nEof=0; // Number of time send of string
+-  register int yystate;
+-  register int yyn;
++  int yystate;
++  int yyn;
+   int yyresult;
+   /* Number of tokens to shift before error messages enabled.  */
+   int yyerrstatus;

... etc. - the rest is truncated

Reply via email to