RepositoryExternal.mk                                                          
   |   26 +
 comphelper/source/misc/storagehelper.cxx                                       
   |    2 
 sw/qa/extras/uiwriter/uiwriter.cxx                                             
   |   49 -
 sw/source/uibase/wrtsh/wrtsh1.cxx                                              
   |   21 
 test/signing-keys/test.p7b                                                     
   |  249 ++++++++++
 unotest/source/cpp/macros_test.cxx                                             
   |    7 
 xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk                              
   |    8 
 xmlsecurity/CppunitTest_xmlsecurity_signing.mk                                 
   |    8 
 xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx                                  
   |   16 
 
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/signed_with_x509certificate_chain.odt         
   |binary
 xmlsecurity/qa/unit/signing/signing.cxx                                        
   |  126 +++++
 xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx          
   |   62 ++
 16 files changed, 501 insertions(+), 73 deletions(-)

New commits:
commit 41befa02bb4dbaf4a39ac41cbaaf12d10242e12e
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Tue Oct 19 16:00:53 2021 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Oct 20 15:35:30 2021 +0200

    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.
    
    Change-Id: I954d88062c38881bc721bdf052db4f7b55888aae
    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)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123848
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index ea4fab6c87a7..e63b6fba6d0f 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -3427,6 +3427,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))
 
@@ -3496,6 +3501,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 dbedd1a1f7c9..667acc97e3e1 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk
@@ -37,7 +37,7 @@ $(eval $(call 
gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\
 ifneq ($(OS),WNT)
 ifneq (,$(ENABLE_NSS))
 $(eval $(call gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\
-    nss3 \
+    nssutil3 \
 ))
 endif
 endif
diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk 
b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
index 8ab2d3014657..ef9dce397a8c 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
@@ -41,7 +41,7 @@ $(eval $(call 
gb_CppunitTest_use_externals,xmlsecurity_signing,\
 ifneq ($(OS),WNT)
 ifneq (,$(ENABLE_NSS))
 $(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\
-    nss3 \
+    nssutil3 \
 ))
 endif
 endif
commit 4211f0eb60301bc18f82dea19f4e1cdf235efda6
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Oct 15 20:52:47 2021 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Oct 20 15:35:20 2021 +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.
    
    Change-Id: I4f634cf5da1707fb628e63cd0cdafebdf4fc903f
    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>

diff --git a/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk 
b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk
index 2441d47e046b..dbedd1a1f7c9 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,\
+    nss3 \
+))
+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 a3cdc25e6d7d..8ab2d3014657 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
@@ -38,6 +38,14 @@ $(eval $(call 
gb_CppunitTest_use_externals,xmlsecurity_signing,\
     $(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \
 ))
 
+ifneq ($(OS),WNT)
+ifneq (,$(ENABLE_NSS))
+$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\
+    nss3 \
+))
+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 f6bdfce9c050..a4b9a51bf034 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -10,6 +10,10 @@
 #include <sal/config.h>
 #include <config_features.h>
 
+#ifndef _WIN32
+#include <secoid.h>
+#endif
+
 #include <string_view>
 
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
@@ -67,6 +71,18 @@ void PDFSigningTest::setUp()
 {
     test::BootstrapFixture::setUp();
     MacrosTest::setUpNssGpg(m_directories, "xmlsecurity_pdfsigning");
+
+    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
 }
 
 void PDFSigningTest::tearDown()
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index b040f8861600..c5c323e246af 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -12,6 +12,10 @@
 
 #include <sal/config.h>
 
+#ifndef _WIN32
+#include <secoid.h>
+#endif
+
 #include <test/bootstrapfixture.hxx>
 #include <unotest/macros_test.hxx>
 #include <test/xmltesttools.hxx>
@@ -105,6 +109,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 a5b9a9774e9289f1216453f15636ae2300cfed8a
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Feb 26 17:29:37 2021 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Oct 20 15:35:14 2021 +0200

    xmlsecurity: add tests for multiple X509Data/X509Certificate
    
    Change-Id: If50ae8156f81c1053aa8fbfc3148da64bb8e1442
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111666
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Tested-by: Jenkins
    (cherry picked from commit 40d70d427edddb589eda64fafc2e56536953d274)
    
    This commit also contains:
    
    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.
    
    Change-Id: Ic9865e0b5783211c2128ce0327c4583b7784ff62
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123667
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit 7d664ec788acdc378506a7ff8b1120cea24a6770)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123646
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/test/signing-keys/test.p7b b/test/signing-keys/test.p7b
new file mode 100644
index 000000000000..44723697a2bf
--- /dev/null
+++ b/test/signing-keys/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/unotest/source/cpp/macros_test.cxx 
b/unotest/source/cpp/macros_test.cxx
index a6d690e0d2c1..0acf9db7edf5 100644
--- a/unotest/source/cpp/macros_test.cxx
+++ b/unotest/source/cpp/macros_test.cxx
@@ -103,7 +103,12 @@ void MacrosTest::setUpNssGpg(const test::Directories& 
rDirectories, const OUStri
     OUString aTargetPath;
     osl::FileBase::getSystemPathFromFileURL(aTargetDir, aTargetPath);
 
-#ifndef _WIN32
+#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
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 1ac88f9e731b..b040f8861600 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -21,6 +21,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>
@@ -530,6 +531,120 @@ 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(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"),
+        // CryptoAPI puts a space after comma, NSS does not...
+        infos[0].Signer->getSubjectName().replaceAll(", ", ","));
+}
+
+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(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());
+    // the signature in this manipulated document is technically valid but we 
can't tell who signed
+    // it, so make sure no misleading info is shown to the user
+    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(nActual)).getStr()),
+                                 SignatureState::BROKEN, nActual);
+    uno::Sequence<security::DocumentSignatureInformation> const infos(
+        pObjectShell->GetDocumentSignatureInformation(false));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+    // the signature in this manipulated document is technically valid but we 
can't tell who signed
+    // it, so make sure no misleading info is shown to the user
+    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(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());
+    // the signature in this manipulated document is technically valid but we 
can't tell who signed
+    // it, so make sure no misleading info is shown to the user
+    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();
+    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(nActual)).getStr()),
 nTemp);
+    uno::Sequence<security::DocumentSignatureInformation> const infos(
+        pObjectShell->GetDocumentSignatureInformation(false));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+    // the signature in this manipulated document is technically valid but we 
can't tell who signed
+    // it, so make sure no misleading info is shown to the user
+    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.
 CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLPartial)
 {
diff --git 
a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx 
b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
index 4f16dc5707ca..cd3d315efdd9 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
@@ -745,6 +745,60 @@ static HCERTSTORE getCertStoreForIntermediatCerts(
     return store;
 }
 
+static bool CheckUnitTestStore(PCCERT_CHAIN_CONTEXT const pChainContext, DWORD 
ignoreFlags)
+{
+    bool ret = false;
+    static char const*const pVar = getenv("LIBO_TEST_CRYPTOAPI_PKCS7");
+    if (!pVar)
+    {
+        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_A,
+            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+            NULL,
+            CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
+            OString(OString::Concat(pVar) + "/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
@@ -847,7 +901,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
@@ -876,6 +931,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 4deef62dbce49572be6a146898f760a558d932d7
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Oct 15 10:38:10 2021 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Oct 20 15:35:04 2021 +0200

    comphelper: fix bad error handling in CreatePackageEncryptionData()
    
    Not sure if rtl_digest_SHA1 can realistically return an error but avoid
    out-of-bounds write in this case.
    
    (regression from commit 9188ea83c346fdc2f668178ae7538665a1b09c02)
    
    Change-Id: If5f134cbcd9236338d1938242a469d7c79e87f06
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123649
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 62128c09237152d9e0585abe2fc88f0a13274b34)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123630
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/comphelper/source/misc/storagehelper.cxx 
b/comphelper/source/misc/storagehelper.cxx
index 8308e9138514..89c284e305fb 100644
--- a/comphelper/source/misc/storagehelper.cxx
+++ b/comphelper/source/misc/storagehelper.cxx
@@ -430,7 +430,7 @@ uno::Sequence< beans::NamedValue > 
OStorageHelper::CreatePackageEncryptionData(
             if ( nError != rtl_Digest_E_None )
             {
                 aEncryptionData.realloc( nSha1Ind );
-                break;
+                return aEncryptionData;
             }
 
             aEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 
>( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 );
commit 2138d2a7a3e0e2ed5b673d8e863f59253ef23df8
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Wed Oct 13 14:56:44 2021 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Oct 20 15:34:58 2021 +0200

    tdf#134426 tdf#138873 sw:  Revert "tdf#79717 ...
    
    ...save/restore character format on selection overwrite"
    which might also fix tdf#144638 as well.
    
    This reverts LO 6.3 commit 6abed0ea006f3616e40faf2ae782cf64f8ac2914.
    
    This 6.3 fix for bug 79717 has caused too many other problems
    that are not being looked at, so it should just be reverted.
    It is spamming documents with direct formatting which
    is a terrible thing to have happen by accident.
    It completely wrecks the proper use of styles.
    
    Also revert asscoiated follow-up commits:
    Revert "tdf#79717 save/restore character style on selection overwrite"
    This reverts commit 6.3 04bd1925706360414438b814046b543c5e317d0a.
    
    Revert "tdf#79717: sw_uiwriter: Add unittest"
    This reverts commit 7.1 b05955b480fe4d32852e7be8a118d46ca7e6dbfa.
    
    These effectively revert 7.0.4 12eac5bcbc9b71bf00cb88b918988826229cca35
    but its unit test is left intact.
    
    Change-Id: Ideced4d38bfdf4c82f1744534afbaad29689fded
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123566
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <justin_l...@sil.org>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123577
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx 
b/sw/qa/extras/uiwriter/uiwriter.cxx
index 702dc90636fd..8579f46b9b87 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -216,7 +216,6 @@ public:
     void testCaretPositionMovingUp();
     void testTdf93441();
     void testTdf81226();
-    void testTdf79717();
     void testTdf137532();
     void testFdo87448();
     void testTextCursorInvalidation();
@@ -451,7 +450,6 @@ public:
     CPPUNIT_TEST(testCaretPositionMovingUp);
     CPPUNIT_TEST(testTdf93441);
     CPPUNIT_TEST(testTdf81226);
-    CPPUNIT_TEST(testTdf79717);
     CPPUNIT_TEST(testTdf137532);
     CPPUNIT_TEST(testFdo87448);
     CPPUNIT_TEST(testTextCursorInvalidation);
@@ -2069,53 +2067,6 @@ void SwUiWriterTest::testTdf81226()
     CPPUNIT_ASSERT_EQUAL(OUString("beforeafter"), 
getParagraph(1)->getString());
 }
 
-void SwUiWriterTest::testTdf79717()
-{
-    SwDoc* const pDoc = createDoc();
-    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
-    pWrtShell->Insert("normal");
-    lcl_setWeight(pWrtShell, WEIGHT_BOLD);
-    pWrtShell->Insert("bold");
-    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
-    // Select 'bol' and replace it
-    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 3, 
/*bBasicCall=*/false);
-    pWrtShell->Insert("bol");
-
-    // Without the fix in place, 'bol' would have been replaced with normal 
font weight
-
-    auto xText = getParagraph(1)->getText();
-    CPPUNIT_ASSERT(xText.is());
-    {
-        auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 
1)));
-        CPPUNIT_ASSERT(xCursor.is());
-        CPPUNIT_ASSERT_EQUAL(OUString("normal"), xCursor->getString());
-        CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, 
getProperty<float>(xCursor, "CharWeight"));
-    }
-    {
-        auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 
2)));
-        CPPUNIT_ASSERT(xCursor.is());
-        CPPUNIT_ASSERT_EQUAL(OUString("bold"), xCursor->getString());
-        CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, 
getProperty<float>(xCursor, "CharWeight"));
-    }
-
-    // Now select characters from both runs and replace them
-    pWrtShell->EndPara();
-    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 5, 
/*bBasicCall=*/false);
-    pWrtShell->Insert("new");
-    {
-        auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 
1)));
-        CPPUNIT_ASSERT(xCursor.is());
-        CPPUNIT_ASSERT_EQUAL(OUString("norma"), xCursor->getString());
-        CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, 
getProperty<float>(xCursor, "CharWeight"));
-    }
-    {
-        auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 
2)));
-        CPPUNIT_ASSERT(xCursor.is());
-        CPPUNIT_ASSERT_EQUAL(OUString("new"), xCursor->getString());
-        CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, 
getProperty<float>(xCursor, "CharWeight"));
-    }
-}
-
 void SwUiWriterTest::testTdf137532()
 {
     SwDoc* const pDoc = createDoc();
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx 
b/sw/source/uibase/wrtsh/wrtsh1.cxx
index 08849e28a3f6..5e888e2c2ef6 100644
--- a/sw/source/uibase/wrtsh/wrtsh1.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -198,11 +198,6 @@ void SwWrtShell::Insert( const OUString &rStr )
          bCallIns = m_bIns /*|| bHasSel*/;
     bool bDeleted = false;
 
-    typedef svl::Items<RES_CHRATR_BEGIN, RES_CHRATR_RSID - 1,
-                       RES_CHRATR_RSID + 1, RES_CHRATR_END - 1,
-                       RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT> CharItems;
-    SfxItemSet aCharAttrSet(GetAttrPool(), CharItems{});
-
     if( bHasSel || ( !m_bIns && SelectHiddenRange() ) )
     {
             // Only here parenthesizing, because the normal
@@ -220,12 +215,6 @@ void SwWrtShell::Insert( const OUString &rStr )
             aRewriter.AddRule(UndoArg3, aTmpStr);
         }
 
-        // tdf#79717 Save character formatting of the start of the selection
-        const SwPosition *pStart = GetCursor()->Start();
-        SwPaM aPaM(pStart->nNode.GetNode(), pStart->nContent.GetIndex(),
-                   pStart->nNode.GetNode(), pStart->nContent.GetIndex() + 1);
-        GetPaMAttr(&aPaM, aCharAttrSet);
-
         StartUndo(SwUndoId::REPLACE, &aRewriter);
         bStarted = true;
         Push();
@@ -238,16 +227,6 @@ void SwWrtShell::Insert( const OUString &rStr )
     bCallIns ?
         SwEditShell::Insert2( rStr, bDeleted ) : SwEditShell::Overwrite( rStr 
);
 
-    if( bDeleted )
-    {
-        // tdf#79717 Restore formatting of the deleted selection
-        SwPosition* pEnd = GetCursor()->Start();
-        SwPaM aPaM(pEnd->nNode.GetNode(), pEnd->nContent.GetIndex() - 
rStr.getLength(),
-                   pEnd->nNode.GetNode(), pEnd->nContent.GetIndex());
-
-        SetAttrSet(aCharAttrSet, SetAttrMode::DEFAULT, &aPaM);
-    }
-
     if( bStarted )
     {
         EndUndo();

Reply via email to