[Libreoffice-commits] core.git: Branch 'libreoffice-5-4' - include/sal offapi/com offapi/UnoApi_offapi.mk postprocess/Rdb_services.mk xmlsecurity/inc xmlsecurity/Library_xmlsecurity.mk xmlsecurity/Library_xsec_gpg.mk xmlsecurity/Library_xsec_xmlsec.mk xmlsecurity/Module_xmlsecurity.mk xmlsecurity/qa xmlsecurity/source xmlsecurity/util

Thorsten Behrens Thorsten.Behrens at CIB.de
Wed Jun 21 21:15:11 UTC 2017


 include/sal/log-areas.dox                                         |    1 
 offapi/UnoApi_offapi.mk                                           |    1 
 offapi/com/sun/star/security/CertificateKind.idl                  |   33 +
 offapi/com/sun/star/security/XCertificate.idl                     |    8 
 postprocess/Rdb_services.mk                                       |    3 
 xmlsecurity/Library_xmlsecurity.mk                                |    6 
 xmlsecurity/Library_xsec_gpg.mk                                   |   75 ---
 xmlsecurity/Library_xsec_xmlsec.mk                                |   20 
 xmlsecurity/Module_xmlsecurity.mk                                 |    6 
 xmlsecurity/inc/certificatechooser.hxx                            |    8 
 xmlsecurity/inc/digitalsignaturesdialog.hxx                       |    4 
 xmlsecurity/inc/documentsignaturemanager.hxx                      |    6 
 xmlsecurity/inc/framework/signatureverifierimpl.hxx               |    3 
 xmlsecurity/inc/gpg/SEInitializer.hxx                             |    5 
 xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx                      |    1 
 xmlsecurity/inc/sigstruct.hxx                                     |    4 
 xmlsecurity/inc/xmlsec/xmlsec_init.hxx                            |   20 
 xmlsecurity/inc/xmlsec/xmlstreamio.hxx                            |    8 
 xmlsecurity/inc/xmlsignaturehelper.hxx                            |    3 
 xmlsecurity/inc/xsecctl.hxx                                       |    8 
 xmlsecurity/qa/unit/signing/signing.cxx                           |   12 
 xmlsecurity/source/component/documentdigitalsignatures.cxx        |   15 
 xmlsecurity/source/dialogs/certificatechooser.cxx                 |   19 
 xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx            |   96 ++--
 xmlsecurity/source/gpg/CertificateImpl.cxx                        |   57 ++
 xmlsecurity/source/gpg/CertificateImpl.hxx                        |    5 
 xmlsecurity/source/gpg/SEInitializer.cxx                          |    7 
 xmlsecurity/source/gpg/SecurityEnvironment.cxx                    |   49 +-
 xmlsecurity/source/gpg/SecurityEnvironment.hxx                    |    5 
 xmlsecurity/source/gpg/XMLSecurityContext.cxx                     |   20 
 xmlsecurity/source/gpg/XMLSecurityContext.hxx                     |   10 
 xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx                   |  203 ++++++----
 xmlsecurity/source/helper/documentsignaturehelper.cxx             |    3 
 xmlsecurity/source/helper/documentsignaturemanager.cxx            |  128 ++++--
 xmlsecurity/source/helper/xmlsignaturehelper.cxx                  |   10 
 xmlsecurity/source/helper/xsecctl.cxx                             |   91 +++-
 xmlsecurity/source/helper/xsecparser.cxx                          |   36 +
 xmlsecurity/source/helper/xsecparser.hxx                          |    4 
 xmlsecurity/source/helper/xsecsign.cxx                            |   23 +
 xmlsecurity/source/helper/xsecverify.cxx                          |   46 ++
 xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx |    5 
 xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx |    3 
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx         |    5 
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx         |    2 
 xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx      |   23 -
 xmlsecurity/source/xmlsec/xmlsec_init.cxx                         |   47 ++
 xmlsecurity/source/xmlsec/xmlstreamio.cxx                         |    4 
 xmlsecurity/source/xmlsec/xsec_xmlsec.cxx                         |   13 
 xmlsecurity/util/xsec_gpg.component                               |   25 -
 49 files changed, 825 insertions(+), 364 deletions(-)

New commits:
commit 3e3b37ca4cbc881628a71715b67ac172018cf9f2
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Sun May 21 14:28:57 2017 +0200

    gpg4libre: backport OpenPGP signing from master
    
    This squashes the following commits:
    
    - gpg4libre: share static xmlsec lib between nss and gpg
    - gpg4libre: fix gpg signature generation
    - gpg4libre: initial GPG signature validation
    - gpg4libre: Make signature dialog work with two signing services
    - gpg4libre: Having this dllpublic should be fine now since it's in inc/
    - gpg4libre: fix build, explicit ctor call
    - gpg4libre: now use the gpg security env
    - gpg4libre: [API-CHANGE] add certificate kind (X509 vs. OpenPGP)
    - gpg4libre: List both (x509 and gpg) existing signatures
    - gpg4libre: Init xmlsec in one place before creating the gpg/x509 services
    - gpg4libre: write PGPData info, get more metadata out for gpg key
    - gpg4libre: Fixup unit tests, now that SecurityContext is needed
    - gpg4libre: Make viewing signatures work for gpg signatures
    - gpg4libre: some code improvements, add metadata for OpenPGP keys
    - gpg4libre: make signature impl swappable in-situ during validation
    - gpg4libre: actually take key from user selection
    - gpg4libre: fix build for windows and mac
    
    Change-Id: I3e36b22cefba4c6195bcf8b85b3f7a2cc101b845
    Reviewed-on: https://gerrit.libreoffice.org/39076
    Reviewed-by: Katarina Behrens <Katarina.Behrens at cib.de>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index 8acbf3f62a0f..4da0c8b533fc 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -526,6 +526,7 @@ certain functionality.
 @li @c xmlsecurity.helper
 @li @c xmlsecurity.pdfio - signing of existing PDF
 @li @c xmlsecurity.xmlsec - xmlsec wrapper
+ at li @c xmlsecurity.xmlsec.gpg - gpg xmlsec component
 
 @section xmlscript
 
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 0e0a6cad8962..f0e03f2808e1 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -3316,6 +3316,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/security,\
 	CertificateCharacters \
 	CertificateContainerStatus \
 	CertificateException \
+	CertificateKind \
 	CertificateValidity \
 	CryptographyException \
 	DocumentSignatureInformation \
diff --git a/offapi/com/sun/star/security/CertificateKind.idl b/offapi/com/sun/star/security/CertificateKind.idl
new file mode 100644
index 000000000000..b1ae35e87ded
--- /dev/null
+++ b/offapi/com/sun/star/security/CertificateKind.idl
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __com_sun_star_security_CertificateKind_idl_
+#define __com_sun_star_security_CertificateKind_idl_
+
+module com { module sun { module star { module security {
+
+/**
+ * Enum definition of a certificate kind ( X509, OpenPGP )
+ */
+enum CertificateKind
+{
+    /** X.509 format of a certificate
+     */
+    X509,
+
+    /** OpenPGP format of a certificate
+     */
+    OPENPGP
+};
+
+} ; } ; } ; } ;
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/offapi/com/sun/star/security/XCertificate.idl b/offapi/com/sun/star/security/XCertificate.idl
index 22f7c6a4a1be..6feaa409ccf2 100644
--- a/offapi/com/sun/star/security/XCertificate.idl
+++ b/offapi/com/sun/star/security/XCertificate.idl
@@ -23,13 +23,14 @@
 #include <com/sun/star/uno/XInterface.idl>
 #include <com/sun/star/util/DateTime.idl>
 #include <com/sun/star/security/XCertificateExtension.idl>
+#include <com/sun/star/security/CertificateKind.idl>
 
 module com { module sun { module star { module security {
 
 /**
  * Interface of a PKI Certificate
  *
- * <p>This interface represents a x509 certificate.</p>
+ * <p>This interface represents a certificate (X.509 or OpenPGP) .</p>
  */
 interface XCertificate : com::sun::star::uno::XInterface
 {
@@ -109,6 +110,11 @@ interface XCertificate : com::sun::star::uno::XInterface
     [attribute, readonly] sequence< byte > MD5Thumbprint;
 
     /**
+     *  the kind of certificate, X.509 or OpenPGP
+     */
+    [attribute, readonly] com::sun::star::security::CertificateKind CertificateKind;
+
+    /**
      * Find a extension with a object identifier.
      */
     XCertificateExtension findCertificateExtension( [in]sequence< byte > oid ) ;
diff --git a/postprocess/Rdb_services.mk b/postprocess/Rdb_services.mk
index cd7a10cadd64..ce8649ed7f7e 100644
--- a/postprocess/Rdb_services.mk
+++ b/postprocess/Rdb_services.mk
@@ -109,9 +109,6 @@ $(eval $(call gb_Rdb_add_components,services,\
 	xmloff/util/xo \
 	xmlscript/util/xmlscript \
 	$(if $(ENABLE_NSS), \
-		$(if $(filter-out WNT MACOSX ANDROID IOS,$(OS)), \
-			xmlsecurity/util/xsec_gpg \
-		) \
 		xmlsecurity/util/xmlsecurity \
 		xmlsecurity/util/xsec_xmlsec$(if $(filter WNT,$(OS)),.windows)) \
 	$(if $(ENABLE_COINMP), \
diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk
index a0fe40a5a033..77d3bd81dc3b 100644
--- a/xmlsecurity/Library_xmlsecurity.mk
+++ b/xmlsecurity/Library_xmlsecurity.mk
@@ -45,12 +45,6 @@ $(eval $(call gb_Library_use_libraries,xmlsecurity,\
 	xsec_xmlsec \
 ))
 
-ifneq ($(filter-out WNT MACOSX ANDROID IOS,$(OS)),)
-$(eval $(call gb_Library_use_libraries,xmlsecurity,\
-	xsec_gpg \
-))
-endif
-
 $(eval $(call gb_Library_add_exception_objects,xmlsecurity,\
 	xmlsecurity/source/component/certificatecontainer \
 	xmlsecurity/source/component/documentdigitalsignatures \
diff --git a/xmlsecurity/Library_xsec_gpg.mk b/xmlsecurity/Library_xsec_gpg.mk
deleted file mode 100644
index 5c21173f94b8..000000000000
--- a/xmlsecurity/Library_xsec_gpg.mk
+++ /dev/null
@@ -1,75 +0,0 @@
-# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
-#
-# This file is part of the LibreOffice project.
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#
-
-$(eval $(call gb_Library_Library,xsec_gpg))
-
-$(eval $(call gb_Library_set_componentfile,xsec_gpg,xmlsecurity/util/xsec_gpg))
-
-$(eval $(call gb_Library_set_include,xsec_gpg,\
-	$$(INCLUDE) \
-	-I$(SRCDIR)/xmlsecurity/inc \
-	-I$(SRCDIR)/xmlsecurity/source/gpg \
-	-I$(call gb_UnpackedTarball_get_dir,xmlsec/include \
-)))
-
-$(eval $(call gb_Library_add_defs,xsec_gpg,\
-	-DXMLSEC_NO_XSLT \
-	-DXMLSEC_CRYPTO_NSS \
-	-DXSECGPG_DLLIMPLEMENTATION \
-))
-
-$(eval $(call gb_Library_use_custom_headers,xsec_gpg,\
-	officecfg/registry \
-))
-
-$(eval $(call gb_Library_use_sdk_api,xsec_gpg))
-
-$(eval $(call gb_Library_set_precompiled_header,xsec_gpg,$(SRCDIR)/xmlsecurity/inc/pch/precompiled_xsec_gpg))
-
-$(eval $(call gb_Library_use_packages,xsec_gpg,\
-	xmlsec \
-))
-$(eval $(call gb_Library_use_externals,xsec_gpg,\
-	boost_headers \
-	libxml2 \
-	nss3 \
-	gpgmepp))
-
-$(eval $(call gb_Library_use_libraries,xsec_gpg,\
-	comphelper \
-	cppu \
-	cppuhelper \
-	sal \
-	svl \
-	tl \
-	xo \
-	xsec_xmlsec \
-))
-
-$(eval $(call gb_Library_add_defs,xsec_gpg,\
-	-DXMLSEC_CRYPTO_NSS \
-))
-$(eval $(call gb_Library_add_libs,xsec_gpg,\
-	$(call gb_UnpackedTarball_get_dir,xmlsec)/src/nss/.libs/libxmlsec1-nss.a \
-	$(call gb_UnpackedTarball_get_dir,xmlsec)/src/.libs/libxmlsec1.a \
-))
-
-$(eval $(call gb_Library_add_exception_objects,xsec_gpg,\
-	xmlsecurity/source/gpg/CertificateImpl \
-	xmlsecurity/source/gpg/CipherContext \
-	xmlsecurity/source/gpg/DigestContext \
-	xmlsecurity/source/gpg/GpgComponentFactory \
-	xmlsecurity/source/gpg/SecurityEnvironment \
-	xmlsecurity/source/gpg/SEInitializer \
-	xmlsecurity/source/gpg/XMLEncryption \
-	xmlsecurity/source/gpg/XMLSecurityContext \
-	xmlsecurity/source/gpg/xmlsignature_gpgimpl \
-))
-
-# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/Library_xsec_xmlsec.mk b/xmlsecurity/Library_xsec_xmlsec.mk
index db161c13995f..639fe55f5add 100644
--- a/xmlsecurity/Library_xsec_xmlsec.mk
+++ b/xmlsecurity/Library_xsec_xmlsec.mk
@@ -18,6 +18,7 @@ endif
 $(eval $(call gb_Library_set_include,xsec_xmlsec,\
 	$$(INCLUDE) \
 	-I$(SRCDIR)/xmlsecurity/inc \
+	-I$(SRCDIR)/xmlsecurity/source/gpg \
 	-I$(SRCDIR)/xmlsecurity/source/xmlsec \
 	-I$(call gb_UnpackedTarball_get_dir,xmlsec/include) \
 ))
@@ -53,6 +54,11 @@ $(eval $(call gb_Library_use_externals,xsec_xmlsec,\
 	libxml2 \
 	nss3 \
 ))
+ifneq ($(filter-out WNT MACOSX ANDROID IOS,$(OS)),)
+$(eval $(call gb_Library_use_externals,xsec_xmlsec,\
+	gpgmepp \
+))
+endif
 
 $(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
 	xmlsecurity/source/xmlsec/biginteger \
@@ -62,6 +68,7 @@ $(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
 	xmlsecurity/source/xmlsec/serialnumberadapter \
 	xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl \
 	xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl \
+	xmlsecurity/source/xmlsec/xmlsec_init \
 	xmlsecurity/source/xmlsec/xmlstreamio \
 	xmlsecurity/source/xmlsec/xsec_xmlsec \
 	xmlsecurity/source/xmlsec/nss/ciphercontext \
@@ -70,6 +77,19 @@ $(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
 	xmlsecurity/source/xmlsec/nss/xsec_nss \
 ))
 
+ifneq ($(filter-out WNT MACOSX ANDROID IOS,$(OS)),)
+$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
+	xmlsecurity/source/gpg/CertificateImpl \
+	xmlsecurity/source/gpg/CipherContext \
+	xmlsecurity/source/gpg/DigestContext \
+	xmlsecurity/source/gpg/SecurityEnvironment \
+	xmlsecurity/source/gpg/SEInitializer \
+	xmlsecurity/source/gpg/XMLEncryption \
+	xmlsecurity/source/gpg/XMLSecurityContext \
+	xmlsecurity/source/gpg/xmlsignature_gpgimpl \
+))
+endif
+
 ifeq ($(OS),WNT)
 
 $(eval $(call gb_Library_add_defs,xsec_xmlsec,\
diff --git a/xmlsecurity/Module_xmlsecurity.mk b/xmlsecurity/Module_xmlsecurity.mk
index d3fafeb7e4ec..b14729ffc405 100644
--- a/xmlsecurity/Module_xmlsecurity.mk
+++ b/xmlsecurity/Module_xmlsecurity.mk
@@ -19,12 +19,6 @@ $(eval $(call gb_Module_add_targets,xmlsecurity,\
 	Library_xsec_xmlsec \
 ))
 
-ifneq ($(filter-out WNT MACOSX ANDROID IOS,$(OS)),)
-$(eval $(call gb_Module_add_targets,xmlsecurity,\
-	Library_xsec_gpg \
-))
-endif
-
 $(eval $(call gb_Module_add_slowcheck_targets,xmlsecurity,\
     CppunitTest_xmlsecurity_signing \
     CppunitTest_xmlsecurity_pdfsigning \
diff --git a/xmlsecurity/inc/certificatechooser.hxx b/xmlsecurity/inc/certificatechooser.hxx
index d5881eb5b837..264b740dd448 100644
--- a/xmlsecurity/inc/certificatechooser.hxx
+++ b/xmlsecurity/inc/certificatechooser.hxx
@@ -24,6 +24,8 @@
 #include <vcl/dialog.hxx>
 #include <vcl/fixed.hxx>
 #include <vcl/button.hxx>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <com/sun/star/uno/Sequence.hxx>
 #include <sigstruct.hxx>
@@ -43,6 +45,7 @@ class HeaderBar;
 struct UserData
 {
     css::uno::Reference<css::security::XCertificate> xCertificate;
+    css::uno::Reference<css::xml::crypto::XXMLSecurityContext> xSecurityContext;
     css::uno::Reference<css::xml::crypto::XSecurityEnvironment> xSecurityEnvironment;
 };
 
@@ -50,7 +53,7 @@ class CertificateChooser : public ModalDialog
 {
 private:
     css::uno::Reference< css::uno::XComponentContext > mxCtx;
-    std::vector< css::uno::Reference< css::xml::crypto::XSecurityEnvironment > > mxSecurityEnvironments;
+    std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > mxSecurityContexts;
     std::vector<std::shared_ptr<UserData>> mvUserData;
 
     VclPtr<SvSimpleTable>   m_pCertLB;
@@ -72,13 +75,14 @@ private:
 public:
     CertificateChooser(vcl::Window* pParent,
                        css::uno::Reference< css::uno::XComponentContext>& rxCtx,
-                       std::vector< css::uno::Reference< css::xml::crypto::XSecurityEnvironment > >& rxSecurityEnvironments);
+                       std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > >& rxSecurityContexts);
     virtual ~CertificateChooser() override;
     virtual void dispose() override;
 
     short Execute() override;
 
     css::uno::Reference< css::security::XCertificate > GetSelectedCertificate();
+    css::uno::Reference< css::xml::crypto::XXMLSecurityContext > GetSelectedSecurityContext();
     /// Gets the description string provided when selecting the certificate.
     OUString GetDescription();
 
diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx b/xmlsecurity/inc/digitalsignaturesdialog.hxx
index 44cf85da7d50..e49419e57a4a 100644
--- a/xmlsecurity/inc/digitalsignaturesdialog.hxx
+++ b/xmlsecurity/inc/digitalsignaturesdialog.hxx
@@ -101,6 +101,10 @@ private:
     void                ImplFillSignaturesBox();
     void                ImplShowSignaturesDetails();
 
+    css::uno::Reference<css::security::XCertificate> getCertificate(const SignatureInformation& rInfo);
+    css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getSecurityEnvironmentForCertificate(
+        css::uno::Reference<css::security::XCertificate> xCert);
+
     //Checks if adding is allowed.
     //See the spec at specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
     //(6.6.2)Behaviour with regard to ODF 1.2
diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx
index 2039b7fe778f..eed54a5a32c7 100644
--- a/xmlsecurity/inc/documentsignaturemanager.hxx
+++ b/xmlsecurity/inc/documentsignaturemanager.hxx
@@ -61,7 +61,9 @@ public:
     bool isXML(const OUString& rURI);
     SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 eStreamMode, bool bTempStream);
     /// Add a new signature, using xCert as a signing certificate, and rDescription as description.
-    bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant);
+    bool add(const css::uno::Reference<css::security::XCertificate>& xCert,
+             const css::uno::Reference<css::xml::crypto::XXMLSecurityContext> xSecurityContext,
+             const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant);
     /// Remove signature at nPosition.
     void remove(sal_uInt16 nPosition);
     /// Read signatures from either a temp stream or the real storage.
@@ -79,6 +81,8 @@ public:
     /// Get the security environment.
     css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getSecurityEnvironment();
     css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getGpgSecurityEnvironment();
+    css::uno::Reference<css::xml::crypto::XXMLSecurityContext> getSecurityContext();
+    css::uno::Reference<css::xml::crypto::XXMLSecurityContext> getGpgSecurityContext();
 };
 
 #endif // INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREMANAGER_HXX
diff --git a/xmlsecurity/inc/framework/signatureverifierimpl.hxx b/xmlsecurity/inc/framework/signatureverifierimpl.hxx
index 8c20c8385de9..592e4740c714 100644
--- a/xmlsecurity/inc/framework/signatureverifierimpl.hxx
+++ b/xmlsecurity/inc/framework/signatureverifierimpl.hxx
@@ -76,6 +76,9 @@ public:
     virtual OUString SAL_CALL getImplementationName(  ) override;
     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) override;
+
+    void updateSignature( const css::uno::Reference< css::xml::crypto::XXMLSignature >& xSignature,
+                          const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& xContext ) { m_xXMLSignature = xSignature; m_xXMLSecurityContext = xContext; }
 };
 
 /// @throws css::uno::RuntimeException
diff --git a/xmlsecurity/inc/gpg/SEInitializer.hxx b/xmlsecurity/inc/gpg/SEInitializer.hxx
index d4f375bfd41c..db73d621f7be 100644
--- a/xmlsecurity/inc/gpg/SEInitializer.hxx
+++ b/xmlsecurity/inc/gpg/SEInitializer.hxx
@@ -22,11 +22,8 @@
 
 class XSECGPG_DLLPUBLIC SEInitializerGpg : public cppu::WeakImplHelper< css::xml::crypto::XSEInitializer >
 {
-protected:
-    css::uno::Reference< css::uno::XComponentContext > m_xContext;
-
 public:
-    explicit SEInitializerGpg(const css::uno::Reference<css::uno::XComponentContext > &rxContext);
+    SEInitializerGpg();
     virtual ~SEInitializerGpg() override;
 
     /* XSEInitializer */
diff --git a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.hxx b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx
similarity index 98%
rename from xmlsecurity/source/gpg/xmlsignature_gpgimpl.hxx
rename to xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx
index 96dfa0c39f3e..913053b7a4f0 100644
--- a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.hxx
+++ b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx
@@ -36,7 +36,6 @@
 #include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp>
 #include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
 
-// TODO: hack, remove dllpublic again...
 class XSECGPG_DLLPUBLIC XMLSignature_GpgImpl : public ::cppu::WeakImplHelper<
     css::xml::crypto::XXMLSignature ,
     css::lang::XServiceInfo >
diff --git a/xmlsecurity/inc/sigstruct.hxx b/xmlsecurity/inc/sigstruct.hxx
index 479ba3d8f745..68e64176206b 100644
--- a/xmlsecurity/inc/sigstruct.hxx
+++ b/xmlsecurity/inc/sigstruct.hxx
@@ -74,6 +74,10 @@ struct SignatureInformation
     OUString ouX509IssuerName;
     OUString ouX509SerialNumber;
     OUString ouX509Certificate;
+
+    OUString ouGpgKeyID;
+    OUString ouGpgCertificate;
+
     OUString ouSignatureValue;
     css::util::DateTime stDateTime;
 
diff --git a/xmlsecurity/inc/xmlsec/xmlsec_init.hxx b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx
new file mode 100644
index 000000000000..6dc4de2a63cf
--- /dev/null
+++ b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLSEC_INIT_HXX
+#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLSEC_INIT_HXX
+
+#include <xsecxmlsecdllapi.h>
+
+XSECXMLSEC_DLLPUBLIC void initXmlSec();
+XSECXMLSEC_DLLPUBLIC void deInitXmlSec();
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsec/xmlstreamio.hxx b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx
index 55001cbd3ead..9483fdb25475 100644
--- a/xmlsecurity/inc/xmlsec/xmlstreamio.hxx
+++ b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx
@@ -25,13 +25,11 @@
 
 #include <xsecxmlsecdllapi.h>
 
-int xmlEnableStreamInputCallbacks() ;
-void xmlDisableStreamInputCallbacks() ;
-
+XSECXMLSEC_DLLPUBLIC int xmlEnableStreamInputCallbacks() ;
+XSECXMLSEC_DLLPUBLIC void xmlDisableStreamInputCallbacks() ;
 XSECXMLSEC_DLLPUBLIC int xmlRegisterStreamInputCallbacks(
     css::uno::Reference< css::xml::crypto::XUriBinding >& aUriBinding
-) ;
-
+);
 XSECXMLSEC_DLLPUBLIC int xmlUnregisterStreamInputCallbacks() ;
 
 #endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLSTREAMIO_HXX
diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx
index df77db92b7a8..261a4792cd61 100644
--- a/xmlsecurity/inc/xmlsignaturehelper.hxx
+++ b/xmlsecurity/inc/xmlsignaturehelper.hxx
@@ -154,6 +154,9 @@ public:
 
     void AddEncapsulatedX509Certificate(const OUString& ouEncapsulatedX509Certificate);
 
+    void SetGpgCertificate(sal_Int32 nSecurityId, const OUString& ouGpgCertDigest,
+        const OUString& ouGpgCert);
+
     void        SetDateTime( sal_Int32 nSecurityId, const Date& rDate, const tools::Time& rTime );
     void SetDescription(sal_Int32 nSecurityId, const OUString& rDescription);
 
diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx
index b7ee1f8310b9..a38c1cbf8e3d 100644
--- a/xmlsecurity/inc/xsecctl.hxx
+++ b/xmlsecurity/inc/xsecctl.hxx
@@ -292,6 +292,7 @@ private:
      * For signature verification
      */
     void addSignature();
+    void switchGpgSignature();
     void addReference(
         const OUString& ouUri,
         sal_Int32 nDigestID );
@@ -306,6 +307,8 @@ private:
     void setX509Certificate( OUString& ouX509Certificate );
     void setSignatureValue( OUString& ouSignatureValue );
     void setDigestValue( sal_Int32 nDigestID, OUString& ouDigestValue );
+    void setGpgKeyID( OUString& ouKeyID );
+    void setGpgCertificate( OUString& ouGpgCert );
 
     void setDate( OUString& ouDate );
     void setDescription(const OUString& rDescription);
@@ -382,6 +385,11 @@ public:
 
     void addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate);
 
+    void setGpgCertificate(
+        sal_Int32 nSecurityId,
+        const OUString& ouCertDigest,
+        const OUString& ouCert);
+
     void setDate(
         sal_Int32 nSecurityId,
         const css::util::DateTime& rDateTime );
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx
index f8fe7b55123d..2b6e60e7c0bd 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -56,6 +56,8 @@ class SigningTest : public test::BootstrapFixture, public unotest::MacrosTest, p
 {
     uno::Reference<uno::XComponentContext> mxComponentContext;
     uno::Reference<lang::XComponent> mxComponent;
+    uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer;
+    uno::Reference<xml::crypto::XXMLSecurityContext> mxSecurityContext;
 
 public:
     SigningTest();
@@ -135,6 +137,8 @@ void SigningTest::setUp()
 
     mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
     mxDesktop.set(frame::Desktop::create(mxComponentContext));
+    mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext);
+    mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
 
 #ifndef _WIN32
     // Set up cert8.db in workdir/CppunitTest/
@@ -214,7 +218,7 @@ void SigningTest::testDescription()
         return;
     OUString aDescription("SigningTest::testDescription");
     sal_Int32 nSecurityId;
-    aManager.add(xCertificate, aDescription, nSecurityId, false);
+    aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false);
 
     // Read back the signature and make sure that the description survives the roundtrip.
     aManager.read(/*bUseTempStream=*/true);
@@ -248,7 +252,7 @@ void SigningTest::testOOXMLDescription()
         return;
     OUString aDescription("SigningTest::testDescription");
     sal_Int32 nSecurityId;
-    aManager.add(xCertificate, aDescription, nSecurityId, false);
+    aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false);
 
     // Read back the signature and make sure that the description survives the roundtrip.
     aManager.read(/*bUseTempStream=*/true);
@@ -281,7 +285,7 @@ void SigningTest::testOOXMLAppend()
     if (!xCertificate.is())
         return;
     sal_Int32 nSecurityId;
-    aManager.add(xCertificate, OUString(), nSecurityId, false);
+    aManager.add(xCertificate, mxSecurityContext, OUString(), nSecurityId, false);
 
     // Read back the signatures and make sure that we have the expected amount.
     aManager.read(/*bUseTempStream=*/true);
@@ -586,7 +590,7 @@ void SigningTest::testXAdES()
     if (!xCertificate.is())
         return;
     sal_Int32 nSecurityId;
-    aManager.add(xCertificate, /*rDescription=*/OUString(), nSecurityId, /*bAdESCompliant=*/true);
+    aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, /*bAdESCompliant=*/true);
 
     // Write to storage.
     aManager.read(/*bUseTempStream=*/true);
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx
index 4dfa87edeeda..518b4acb1c93 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -307,6 +307,7 @@ DocumentDigitalSignatures::ImplVerifySignatures(
     rSignatureHelper.EndMission();
 
     uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = aSignatureManager.getSecurityEnvironment();
+    uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = aSignatureManager.getGpgSecurityEnvironment();
 
     SignatureInformations aSignInfos = rSignatureHelper.GetSignatureInformations();
     int nInfos = aSignInfos.size();
@@ -359,7 +360,11 @@ DocumentDigitalSignatures::ImplVerifySignatures(
             {
                 //We should always be able to get the certificates because it is contained in the document,
                 //unless the document is damaged so that signature xml file could not be parsed.
-                rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
+                rSigInfo.CertificateStatus =
+                    xGpgSecEnv->verifyCertificate(rSigInfo.Signer,
+                                                  Sequence<Reference<css::security::XCertificate> >());
+                // well - except for gpg signatures ...
+                //rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
             }
 
             rSigInfo.SignatureIsValid = ( rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );
@@ -447,16 +452,16 @@ sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
 
 Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificate(OUString& rDescription)
 {
-    std::vector< Reference< css::xml::crypto::XSecurityEnvironment > > xSecEnvs;
+    std::vector< Reference< css::xml::crypto::XXMLSecurityContext > > xSecContexts;
 
     DocumentSignatureMode eMode{};
     DocumentSignatureManager aSignatureManager(mxCtx, eMode);
     if (aSignatureManager.init()) {
-        xSecEnvs.push_back(aSignatureManager.getSecurityEnvironment());
-        xSecEnvs.push_back(aSignatureManager.getGpgSecurityEnvironment());
+        xSecContexts.push_back(aSignatureManager.getSecurityContext());
+        xSecContexts.push_back(aSignatureManager.getGpgSecurityContext());
     }
 
-    ScopedVclPtrInstance< CertificateChooser > aChooser(nullptr, mxCtx, xSecEnvs);
+    ScopedVclPtrInstance< CertificateChooser > aChooser(nullptr, mxCtx, xSecContexts);
 
     if (aChooser->Execute() != RET_OK)
         return Reference< css::security::XCertificate >(nullptr);
diff --git a/xmlsecurity/source/dialogs/certificatechooser.cxx b/xmlsecurity/source/dialogs/certificatechooser.cxx
index 3cf2b5e5af86..726b4038aa96 100644
--- a/xmlsecurity/source/dialogs/certificatechooser.cxx
+++ b/xmlsecurity/source/dialogs/certificatechooser.cxx
@@ -36,7 +36,7 @@ using namespace css;
 
 CertificateChooser::CertificateChooser(vcl::Window* _pParent,
                                        uno::Reference<uno::XComponentContext>& _rxCtx,
-                                       std::vector< css::uno::Reference< css::xml::crypto::XSecurityEnvironment > >& rxSecurityEnvironments)
+                                       std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > >& rxSecurityContexts)
     : ModalDialog(_pParent, "SelectCertificateDialog", "xmlsec/ui/selectcertificatedialog.ui"),
     mvUserData()
 {
@@ -61,7 +61,7 @@ CertificateChooser::CertificateChooser(vcl::Window* _pParent,
     m_pViewBtn->SetClickHdl( LINK( this, CertificateChooser, ViewButtonHdl ) );
 
     mxCtx = _rxCtx;
-    mxSecurityEnvironments = rxSecurityEnvironments;
+    mxSecurityContexts = rxSecurityContexts;
     mbInitialized = false;
 
     // disable buttons
@@ -150,8 +150,9 @@ void CertificateChooser::ImplInitialize()
     if ( mbInitialized )
         return;
 
-    for (auto &secEnvironment : mxSecurityEnvironments)
+    for (auto &secContext : mxSecurityContexts)
     {
+        auto secEnvironment = secContext->getSecurityEnvironment();
         if (!secEnvironment.is())
             continue;
 
@@ -183,6 +184,7 @@ void CertificateChooser::ImplInitialize()
         {
             std::shared_ptr<UserData> userData = std::make_shared<UserData>();
             userData->xCertificate = xCerts[ nC ];
+            userData->xSecurityContext = secContext;
             userData->xSecurityEnvironment = secEnvironment;
             mvUserData.push_back(userData);
             SvTreeListEntry* pEntry = m_pCertLB->InsertEntry( XmlSec::GetContentPart( xCerts[ nC ]->getSubjectName() )
@@ -210,6 +212,17 @@ uno::Reference< css::security::XCertificate > CertificateChooser::GetSelectedCer
     return xCert;
 }
 
+uno::Reference<xml::crypto::XXMLSecurityContext> CertificateChooser::GetSelectedSecurityContext()
+{
+    SvTreeListEntry* pSel = m_pCertLB->FirstSelected();
+    if( !pSel )
+        return uno::Reference<xml::crypto::XXMLSecurityContext>();
+
+    UserData* userData = static_cast<UserData*>(pSel->GetUserData());
+    uno::Reference<xml::crypto::XXMLSecurityContext> xCert = userData->xSecurityContext;
+    return xCert;
+}
+
 OUString CertificateChooser::GetDescription()
 {
     return m_pDescriptionED->GetText();
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index f691ab063157..a9fbe930b30d 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -32,6 +32,7 @@
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/security/CertificateValidity.hpp>
 #include <com/sun/star/packages/WrongPasswordException.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
 #include <com/sun/star/packages/manifest/ManifestReader.hpp>
@@ -386,15 +387,16 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, Button*, void)
         return;
     try
     {
-        std::vector<uno::Reference<xml::crypto::XSecurityEnvironment>> xSecEnvs;
-        xSecEnvs.push_back(maSignatureManager.getSecurityEnvironment());
-        xSecEnvs.push_back(maSignatureManager.getGpgSecurityEnvironment());
+        std::vector<uno::Reference<xml::crypto::XXMLSecurityContext>> xSecContexts;
+        xSecContexts.push_back(maSignatureManager.getSecurityContext());
+        xSecContexts.push_back(maSignatureManager.getGpgSecurityContext());
 
-        ScopedVclPtrInstance< CertificateChooser > aChooser( this, mxCtx, xSecEnvs );
+        ScopedVclPtrInstance< CertificateChooser > aChooser( this, mxCtx, xSecContexts );
         if ( aChooser->Execute() == RET_OK )
         {
             sal_Int32 nSecurityId;
-            if (!maSignatureManager.add(aChooser->GetSelectedCertificate(), aChooser->GetDescription(), nSecurityId, m_bAdESCompliant))
+            if (!maSignatureManager.add(aChooser->GetSelectedCertificate(), aChooser->GetSelectedSecurityContext(),
+                                        aChooser->GetDescription(), nSecurityId, m_bAdESCompliant))
                 return;
             mbSignaturesChanged = true;
 
@@ -499,10 +501,6 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
 {
     m_pSignaturesLB->Clear();
 
-    uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
-
-    uno::Reference< css::security::XCertificate > xCert;
-
     size_t nInfos = maSignatureManager.maCurrentSignatureInformations.size();
     size_t nValidSigs = 0, nValidCerts = 0;
     bool bAllNewSignatures = true;
@@ -518,26 +516,9 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
                 aElementsToBeVerified = DocumentSignatureHelper::CreateElementList(maSignatureManager.mxStore, maSignatureManager.meSignatureMode, mode);
 
             const SignatureInformation& rInfo = maSignatureManager.maCurrentSignatureInformations[n];
-            //First we try to get the certificate which is embedded in the XML Signature
-            if (!rInfo.ouX509Certificate.isEmpty())
-                xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
-            else {
-                //There must be an embedded certificate because we use it to get the
-                //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
-                //because it could be modified by an attacker. The issuer is displayed
-                //in the digital signature dialog.
-                //Comparing the X509IssuerName with the one from the X509Certificate in order
-                //to find out if the X509IssuerName was modified does not work. See #i62684
-                SAL_WARN( "xmlsecurity.dialogs", "Could not find embedded certificate!");
-            }
-
-            //In case there is no embedded certificate we try to get it from a local store
-            //Todo: This probably could be removed, see above.
-            if (!xCert.is())
-                xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) );
-
-            SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" );
+            uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo);
 
+            // TODO - should use pgpdata from info provider?
             OUString aSubject;
             OUString aIssuer;
             OUString aDateTimeStr;
@@ -550,8 +531,8 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
             {
                 //check the validity of the cert
                 try {
-                    sal_Int32 certResult = xSecEnv->verifyCertificate(xCert,
-                        Sequence<css::uno::Reference<css::security::XCertificate> >());
+                    sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert,
+                                                                                                          Sequence<uno::Reference<security::XCertificate> >());
 
                     bCertValid = certResult == css::security::CertificateValidity::VALID;
                     if ( bCertValid )
@@ -664,6 +645,46 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
     SignatureHighlightHdl( nullptr );
 }
 
+uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(const SignatureInformation& rInfo)
+{
+    uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
+    uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment();
+    uno::Reference<security::XCertificate> xCert;
+
+    //First we try to get the certificate which is embedded in the XML Signature
+    if (!rInfo.ouX509Certificate.isEmpty())
+        xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
+    else {
+        //There must be an embedded certificate because we use it to get the
+        //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
+        //because it could be modified by an attacker. The issuer is displayed
+        //in the digital signature dialog.
+        //Comparing the X509IssuerName with the one from the X509Certificate in order
+        //to find out if the X509IssuerName was modified does not work. See #i62684
+        SAL_WARN( "xmlsecurity.dialogs", "Could not find embedded certificate!");
+    }
+
+    //In case there is no embedded certificate we try to get it from a local store
+    if (!xCert.is())
+        xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) );
+    if (!xCert.is())
+        xCert = xGpgSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) );
+
+    SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" );
+
+    return xCert;
+}
+
+uno::Reference<xml::crypto::XSecurityEnvironment> DigitalSignaturesDialog::getSecurityEnvironmentForCertificate(uno::Reference<security::XCertificate> xCert)
+{
+    if (xCert->getCertificateKind() == CertificateKind_OPENPGP)
+        return maSignatureManager.getGpgSecurityEnvironment();
+    else if (xCert->getCertificateKind() == CertificateKind_X509)
+        return maSignatureManager.getSecurityEnvironment();
+
+    throw RuntimeException("Unknown certificate kind");
+}
+
 //If bUseTempStream is true then the temporary signature stream is used.
 //Otherwise the real signature stream is used.
 void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature)
@@ -678,19 +699,12 @@ void DigitalSignaturesDialog::ImplShowSignaturesDetails()
     {
         sal_uInt16 nSelected = (sal_uInt16) reinterpret_cast<sal_uIntPtr>( m_pSignaturesLB->FirstSelected()->GetUserData() );
         const SignatureInformation& rInfo = maSignatureManager.maCurrentSignatureInformations[ nSelected ];
-        uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
-        // Use Certificate from doc, not from key store
-        uno::Reference< css::security::XCertificate > xCert;
-        if (!rInfo.ouX509Certificate.isEmpty())
-            xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
-        //fallback if no certificate is embedded, get if from store
-        if (!xCert.is())
-            xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) );
-
-        SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Error getting Certificate!" );
+        uno::Reference<security::XCertificate> xCert = getCertificate(rInfo);
+        uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = getSecurityEnvironmentForCertificate(xCert);
+
         if ( xCert.is() )
         {
-            ScopedVclPtrInstance<CertificateViewer> aViewer(this, maSignatureManager.getSecurityEnvironment(), xCert, false);
+            ScopedVclPtrInstance<CertificateViewer> aViewer(this, xSecEnv, xCert, false);
             aViewer->Execute();
         }
     }
diff --git a/xmlsecurity/source/gpg/CertificateImpl.cxx b/xmlsecurity/source/gpg/CertificateImpl.cxx
index a00b0336fee1..e40f59323a04 100644
--- a/xmlsecurity/source/gpg/CertificateImpl.cxx
+++ b/xmlsecurity/source/gpg/CertificateImpl.cxx
@@ -10,16 +10,21 @@
 #include "CertificateImpl.hxx"
 
 #include <comphelper/servicehelper.hxx>
+#include <comphelper/sequence.hxx>
 
 #include <com/sun/star/security/KeyUsage.hpp>
 
+#include <gpgme.h>
+#include <context.h>
+#include <data.h>
+
 using namespace css;
 using namespace css::uno;
 using namespace css::security;
 using namespace css::util;
 
 CertificateImpl::CertificateImpl() :
-    m_pKey(nullptr)
+    m_pKey()
 {
 }
 
@@ -35,8 +40,10 @@ sal_Int16 SAL_CALL CertificateImpl::getVersion()
 
 Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSerialNumber()
 {
-    // Empty for gpg
-    return Sequence< sal_Int8 > ();
+    // This is mapped to the fingerprint for gpg
+    const char* keyId = m_pKey.primaryFingerprint();
+    return comphelper::arrayToSequence<sal_Int8>(
+        keyId, strlen(keyId));
 }
 
 OUString SAL_CALL CertificateImpl::getIssuerName()
@@ -113,8 +120,8 @@ Reference< XCertificateExtension > SAL_CALL CertificateImpl::findCertificateExte
 
 Sequence< sal_Int8 > SAL_CALL CertificateImpl::getEncoded()
 {
-    // Empty for gpg
-    return Sequence< sal_Int8 > ();
+    // Export key to base64Empty for gpg
+    return m_aBits;
 }
 
 OUString SAL_CALL CertificateImpl::getSubjectPublicKeyAlgorithm()
@@ -146,20 +153,31 @@ OUString SAL_CALL CertificateImpl::getSignatureAlgorithm()
 
 Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSHA1Thumbprint()
 {
-    // Empty for gpg
-    return Sequence< sal_Int8 > ();
+    // This is mapped to the short keyID for gpg
+    const char* keyId = m_pKey.shortKeyID();
+    return comphelper::arrayToSequence<sal_Int8>(
+        keyId, strlen(keyId));
 }
 
 uno::Sequence<sal_Int8> CertificateImpl::getSHA256Thumbprint()
 {
-    // Empty for gpg
-    return Sequence< sal_Int8 > ();
+    // This is mapped to the long keyID for gpg
+    const char* keyId = m_pKey.keyID();
+    return comphelper::arrayToSequence<sal_Int8>(
+        keyId, strlen(keyId));
 }
 
 Sequence< sal_Int8 > SAL_CALL CertificateImpl::getMD5Thumbprint()
 {
-    // Empty for gpg
-    return Sequence< sal_Int8 > ();
+    // This is mapped to the short keyID for gpg
+    const char* keyId = m_pKey.shortKeyID();
+    return comphelper::arrayToSequence<sal_Int8>(
+        keyId, strlen(keyId));
+}
+
+CertificateKind SAL_CALL CertificateImpl::getCertificateKind()
+{
+    return CertificateKind_OPENPGP;
 }
 
 sal_Int32 SAL_CALL CertificateImpl::getCertificateUsage()
@@ -187,9 +205,24 @@ const Sequence< sal_Int8>& CertificateImpl::getUnoTunnelId() {
     return CertificateImplUnoTunnelId::get().getSeq();
 }
 
-void CertificateImpl::setCertificate(GpgME::Key key)
+void CertificateImpl::setCertificate(GpgME::Context* ctx, const GpgME::Key& key)
 {
     m_pKey = key;
+
+    // extract key data, store into m_aBits
+    GpgME::Data data_out;
+    ctx->exportPublicKeys(key.keyID(), data_out);
+
+    assert(data_out.seek(0,SEEK_SET) == 0);
+    int len=0, curr=0; char buf;
+    while( (curr=data_out.read(&buf, 1)) )
+        len += curr;
+
+    // write bits to sequence of bytes
+    m_aBits.realloc(len);
+    assert(data_out.seek(0,SEEK_SET) == 0);
+    if( data_out.read(m_aBits.getArray(), len) != len )
+        throw RuntimeException("The GpgME library failed to read the key");
 }
 
 const GpgME::Key* CertificateImpl::getCertificate() const
diff --git a/xmlsecurity/source/gpg/CertificateImpl.hxx b/xmlsecurity/source/gpg/CertificateImpl.hxx
index cf9ab06c181f..9db3ab85de14 100644
--- a/xmlsecurity/source/gpg/CertificateImpl.hxx
+++ b/xmlsecurity/source/gpg/CertificateImpl.hxx
@@ -23,6 +23,7 @@
 #include <com/sun/star/uno/Sequence.hxx>
 #include <com/sun/star/lang/XUnoTunnel.hpp>
 #include <com/sun/star/uno/SecurityException.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
 #include <com/sun/star/security/XCertificate.hpp>
 
 #include <key.h>
@@ -33,6 +34,7 @@ class CertificateImpl : public cppu::WeakImplHelper< css::security::XCertificate
 {
 private:
     GpgME::Key m_pKey;
+    css::uno::Sequence< sal_Int8 > m_aBits;
 
 public:
     CertificateImpl();
@@ -77,9 +79,10 @@ public:
 
     /// @see xmlsecurity::Certificate::getSHA256Thumbprint().
     virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override;
+    virtual css::security::CertificateKind getCertificateKind() override;
 
     // Helper methods
-    void setCertificate(GpgME::Key key);
+    void setCertificate(GpgME::Context* ctx, const GpgME::Key& key);
     const GpgME::Key* getCertificate() const;
 } ;
 
diff --git a/xmlsecurity/source/gpg/SEInitializer.cxx b/xmlsecurity/source/gpg/SEInitializer.cxx
index af02de9d7ece..919161d86554 100644
--- a/xmlsecurity/source/gpg/SEInitializer.cxx
+++ b/xmlsecurity/source/gpg/SEInitializer.cxx
@@ -11,6 +11,8 @@
 #include "SecurityEnvironment.hxx"
 #include "XMLSecurityContext.hxx"
 
+#include <gpgme.h>
+#include <context.h>
 
 using namespace css;
 using namespace css::lang;
@@ -18,9 +20,10 @@ using namespace css::uno;
 using namespace css::xml::crypto;
 
 
-SEInitializerGpg::SEInitializerGpg( const css::uno::Reference< css::uno::XComponentContext > &rxContext )
+SEInitializerGpg::SEInitializerGpg()
 {
-    m_xContext = rxContext;
+    // Also init GpgME while we're at it
+    GpgME::initializeLibrary();
 }
 
 SEInitializerGpg::~SEInitializerGpg()
diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
index 323e267af6b0..2b8a2d567afd 100644
--- a/xmlsecurity/source/gpg/SecurityEnvironment.cxx
+++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
@@ -14,8 +14,6 @@
 #include <comphelper/servicehelper.hxx>
 #include <list>
 
-#include <gpgme.h>
-#include <context.h>
 #include <key.h>
 #include <keylistresult.h>
 
@@ -26,6 +24,13 @@ using namespace css::lang;
 
 SecurityEnvironmentGpg::SecurityEnvironmentGpg()
 {
+    GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
+    if (err)
+        throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+    m_ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+    if (m_ctx == nullptr)
+        throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
 }
 
 SecurityEnvironmentGpg::~SecurityEnvironmentGpg()
@@ -59,31 +64,22 @@ OUString SecurityEnvironmentGpg::getSecurityEnvironmentInformation()
 
 Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getPersonalCertificates()
 {
-    GpgME::initializeLibrary();
-    GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
-    if (err)
-        throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
-
-    GpgME::Context* ctx = GpgME::Context::createForProtocol(GpgME::OpenPGP);
-    if (ctx == nullptr)
-        throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
-
     CertificateImpl* xCert;
     std::list< CertificateImpl* > certsList;
 
-    ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
-    err = ctx->startKeyListing("", true);
+    m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+    GpgME::Error err = m_ctx->startKeyListing("", true);
     while (!err) {
-        GpgME::Key k = ctx->nextKey(err);
+        GpgME::Key k = m_ctx->nextKey(err);
         if (err)
             break;
         if (!k.isInvalid()) {
             xCert = new CertificateImpl();
-            xCert->setCertificate(k);
+            xCert->setCertificate(m_ctx.get(),k);
             certsList.push_back(xCert);
         }
     }
-    ctx->endKeyListing();
+    m_ctx->endKeyListing();
 
     Sequence< Reference< XCertificate > > xCertificateSequence(certsList.size());
     std::list< CertificateImpl* >::iterator xcertIt;
@@ -94,8 +90,27 @@ Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getPersonalCertif
     return xCertificateSequence;
 }
 
-Reference< XCertificate > SecurityEnvironmentGpg::getCertificate( const OUString& /*issuerName*/, const Sequence< sal_Int8 >& /*serialNumber*/ )
+Reference< XCertificate > SecurityEnvironmentGpg::getCertificate( const OUString& issuerName, const Sequence< sal_Int8 >& /*serialNumber*/ )
 {
+    CertificateImpl* xCert=nullptr;
+    std::list< CertificateImpl* > certsList;
+
+    m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+    OString ostr = OUStringToOString( issuerName , RTL_TEXTENCODING_UTF8 );
+    GpgME::Error err = m_ctx->startKeyListing(ostr.getStr(), true);
+    while (!err) {
+        GpgME::Key k = m_ctx->nextKey(err);
+        if (err)
+            break;
+        if (!k.isInvalid()) {
+            xCert = new CertificateImpl();
+            xCert->setCertificate(m_ctx.get(), k);
+            m_ctx->endKeyListing();
+            return xCert;
+        }
+    }
+    m_ctx->endKeyListing();
+
     return nullptr;
 }
 
diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.hxx b/xmlsecurity/source/gpg/SecurityEnvironment.hxx
index 51a263fa5e5d..66d79bb8643e 100644
--- a/xmlsecurity/source/gpg/SecurityEnvironment.hxx
+++ b/xmlsecurity/source/gpg/SecurityEnvironment.hxx
@@ -24,10 +24,14 @@
 #include <com/sun/star/security/CertificateValidity.hpp>
 #include <com/sun/star/lang/XUnoTunnel.hpp>
 
+#include <gpgme.h>
+#include <context.h>
 
 class SecurityEnvironmentGpg : public cppu::WeakImplHelper< css::xml::crypto::XSecurityEnvironment,
                                                             css::lang::XUnoTunnel >
 {
+    std::unique_ptr<GpgME::Context> m_ctx;
+
 public:
     SecurityEnvironmentGpg();
     virtual ~SecurityEnvironmentGpg() override;
@@ -61,6 +65,7 @@ public:
     virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii(
         const OUString& asciiCertificate ) override;
 
+    GpgME::Context& getGpgContext() { return *m_ctx.get(); }
 } ;
 
 #endif // INCLUDED_XMLSECURITY_SOURCE_GPG_SECURITYENVIRONMENT_HXX
diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.cxx b/xmlsecurity/source/gpg/XMLSecurityContext.cxx
index a05ea7e40c55..0919f4dbc2b6 100644
--- a/xmlsecurity/source/gpg/XMLSecurityContext.cxx
+++ b/xmlsecurity/source/gpg/XMLSecurityContext.cxx
@@ -10,6 +10,11 @@
 #include "XMLSecurityContext.hxx"
 #include "SecurityEnvironment.hxx"
 
+#include <cppuhelper/supportsservice.hxx>
+
+#include "xmlsec/xmlstreamio.hxx"
+#include "xmlsec-wrapper.h"
+
 using namespace css::uno;
 using namespace css::lang;
 using namespace css::xml::crypto;
@@ -65,4 +70,19 @@ void SAL_CALL XMLSecurityContextGpg::setDefaultSecurityEnvironmentIndex(sal_Int3
     m_nDefaultEnvIndex = nDefaultEnvIndex;
 }
 
+/* XServiceInfo */
+OUString SAL_CALL XMLSecurityContextGpg::getImplementationName() {
+    return OUString("com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl");
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSecurityContextGpg::supportsService( const OUString& serviceName) {
+    return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence< OUString > SAL_CALL XMLSecurityContextGpg::getSupportedServiceNames() {
+    return { OUString("com.sun.star.xml.crypto.XMLSecurityContext") };
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.hxx b/xmlsecurity/source/gpg/XMLSecurityContext.hxx
index 3402d33aa9cd..4355cc0ce67a 100644
--- a/xmlsecurity/source/gpg/XMLSecurityContext.hxx
+++ b/xmlsecurity/source/gpg/XMLSecurityContext.hxx
@@ -26,7 +26,8 @@
 
 #include <vector>
 
-class XMLSecurityContextGpg : public cppu::WeakImplHelper< css::xml::crypto::XXMLSecurityContext >
+class XMLSecurityContextGpg : public cppu::WeakImplHelper< css::xml::crypto::XXMLSecurityContext,
+                                                           css::lang::XServiceInfo>
 {
 private:
     std::vector< css::uno::Reference< css::xml::crypto::XSecurityEnvironment > > m_vSecurityEnvironments;
@@ -50,6 +51,13 @@ public:
     virtual sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex() override;
 
     virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override;
+
+    // XServiceInfo
+    virtual OUString SAL_CALL getImplementationName() override ;
+
+    virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override ;
+
+    virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ;
 } ;
 
 #endif // INCLUDED_XMLSECURITY_SOURCE_GPG_XMLSECURITYCONTEXT_HXX
diff --git a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx
index 4f4ff7956750..40248ee3a9e8 100644
--- a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx
+++ b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx
@@ -19,7 +19,7 @@
 
 #include <sal/config.h>
 #include <rtl/uuid.h>
-#include "xmlsignature_gpgimpl.hxx"
+#include "gpg/xmlsignature_gpgimpl.hxx"
 
 #include <gpgme.h>
 #include <context.h>
@@ -98,8 +98,6 @@ SAL_CALL XMLSignature_GpgImpl::generate(
     if( pSecEnv == nullptr )
         throw RuntimeException() ;
 
-    // TODO figure out key from pSecEnv!
-    // unclear how/where that is transported in nss impl...
     setErrorRecorder();
 
     //Create Signature context
@@ -110,6 +108,13 @@ SAL_CALL XMLSignature_GpgImpl::generate(
         return aTemplate;
     }
 
+    // set intended operation to sign - several asserts inside libxmlsec
+    // wanting that for digest / transforms
+    pDsigCtx->operation = xmlSecTransformOperationSign;
+
+    // we default to SHA512 for all digests - nss crypto does not have it...
+    //pDsigCtx->defDigestMethodId = xmlSecTransformSha512Id;
+
     // Calculate digest for all references
     xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children);
     if( cur != nullptr )
@@ -151,27 +156,42 @@ SAL_CALL XMLSignature_GpgImpl::generate(
     // get me a digestible buffer from the signature template!
     // -------------------------------------------------------
 
-    // run the transformations
+    // run the transformations over SignedInfo element (first child of
+    // pNode)
     xmlSecNodeSetPtr nodeset = nullptr;
-    nodeset = xmlSecNodeSetGetChildren(pNode->doc, pNode, 1, 0);
+    cur = xmlSecGetNextElementNode(pNode->children);
+    // TODO assert that...
+    nodeset = xmlSecNodeSetGetChildren(pNode->doc, cur, 1, 0);
     if(nodeset == nullptr)
         throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
 
     if( xmlSecTransformCtxXmlExecute(&(pDsigCtx->transformCtx), nodeset) < 0 )
         throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
 
-    //Sign the template via gpgme
-    GpgME::initializeLibrary();
-    if( GpgME::checkEngine(GpgME::OpenPGP) )
+    // now extract the keyid from PGPData
+    // walk xml tree to PGPData node - go to children, first is
+    // SignedInfo, 2nd is signaturevalue, 3rd is KeyInfo
+    // 1st child is PGPData, 1st grandchild is PGPKeyID
+    cur = xmlSecGetNextElementNode(pNode->children);
+    // TODO error handling
+    cur = xmlSecGetNextElementNode(cur->next);
+    cur = xmlSecGetNextElementNode(cur->next);
+    cur = xmlSecGetNextElementNode(cur->children);
+    // check that this is now PGPData
+    if(!xmlSecCheckNodeName(cur, xmlSecNamePGPData, xmlSecDSigNs))
         throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
-
-    GpgME::Context* ctx = GpgME::Context::createForProtocol(GpgME::OpenPGP);
-    if( ctx == nullptr )
+    // check that this is now PGPKeyID
+    cur = xmlSecGetNextElementNode(cur->children);
+    static const xmlChar xmlSecNodePGPKeyID[] = "PGPKeyID";
+    if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyID, xmlSecDSigNs))
         throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
 
-    ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+    GpgME::Context& rCtx=pSecEnv->getGpgContext();
+    rCtx.setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
     GpgME::Error err;
-    if( ctx->addSigningKey(ctx->key("0x909BE2575CEDBEA3", err, true)) )
+    if( rCtx.addSigningKey(
+            rCtx.key(
+                reinterpret_cast<char*>(xmlNodeGetContent(cur)), err, true)) )
         throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
 
     // good, ctx is setup now, let's sign the lot
@@ -180,17 +200,18 @@ SAL_CALL XMLSignature_GpgImpl::generate(
         xmlSecBufferGetSize(pDsigCtx->transformCtx.result), false);
     GpgME::Data data_out;
 
-    GpgME::SigningResult sign_res=ctx->sign(data_in, data_out,
-                                            GpgME::Clearsigned);
-    // TODO: needs some error handling
-    data_out.seek(0,SEEK_SET);
+    SAL_INFO("xmlsecurity.xmlsec.gpg", "Generating signature for: " << xmlSecBufferGetData(pDsigCtx->transformCtx.result));
+
+    GpgME::SigningResult sign_res=rCtx.sign(data_in, data_out,
+                                            GpgME::Detached);
+    assert(data_out.seek(0,SEEK_SET) == 0);
     int len=0, curr=0; char buf;
     while( (curr=data_out.read(&buf, 1)) )
         len += curr;
 
     // write signed data to xml
     std::vector<unsigned char> buf2(len);
-    data_out.seek(0,SEEK_SET);
+    assert(data_out.seek(0,SEEK_SET) == 0);
     if( data_out.read(&buf2[0], len) != len )
         throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
 
@@ -199,8 +220,11 @@ SAL_CALL XMLSignature_GpgImpl::generate(
     cur = xmlSecGetNextElementNode(pNode->children);
     cur = xmlSecGetNextElementNode(cur->next);
 
+    // TODO some assert would be good...
     xmlNodeSetContentLen(cur, &buf2[0], len);
 
+    aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+
     // done
     xmlSecDSigCtxDestroy( pDsigCtx ) ;
 
@@ -218,11 +242,8 @@ SAL_CALL XMLSignature_GpgImpl::validate(
     const Reference< XXMLSignatureTemplate >& aTemplate ,
     const Reference< XXMLSecurityContext >& aSecurityCtx
 ) {
-    xmlSecKeysMngrPtr pMngr = nullptr ;
     xmlSecDSigCtxPtr pDsigCtx = nullptr ;
     xmlNodePtr pNode = nullptr ;
-    //sal_Bool valid ;
-    (void)pMngr; (void)pDsigCtx; (void)pNode;
 
     if( !aTemplate.is() )
         throw RuntimeException() ;
@@ -259,72 +280,130 @@ SAL_CALL XMLSignature_GpgImpl::validate(
     {
         Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i);
 
-        //Get Keys Manager
-        Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
-#if 0
-        SecurityEnvironment_NssImpl* pSecEnv =
-            reinterpret_cast<SecurityEnvironment_NssImpl*>(
-                sal::static_int_cast<sal_uIntPtr>(
-                    xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() )));
+        SecurityEnvironmentGpg* pSecEnv =
+            dynamic_cast<SecurityEnvironmentGpg*>(aEnvironment.get());
         if( pSecEnv == nullptr )
             throw RuntimeException() ;
 
-        pMngr = pSecEnv->createKeysManager();
-        if( !pMngr ) {
-            throw RuntimeException() ;
-        }
+        // TODO figure out key from pSecEnv!
+        // unclear how/where that is transported in nss impl...
 
         //Create Signature context
-        pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
+        pDsigCtx = xmlSecDSigCtxCreate( nullptr ) ;
         if( pDsigCtx == nullptr )
         {
-            SecurityEnvironment_NssImpl::destroyKeysManager( pMngr );
-            //throw XMLSignatureException() ;
             clearErrorRecorder();
             return aTemplate;
         }
 
-        //Verify signature
-        int rs = xmlSecDSigCtxVerify( pDsigCtx , pNode );
+        // set intended operation to verify - several asserts inside libxmlsec
+        // wanting that for digest / transforms
+        pDsigCtx->operation = xmlSecTransformOperationVerify;
 
-        // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML.
-        xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences);
-        // Require that all manifest references are also good.
-        xmlSecSize nReferenceGood = 0;
-        for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference)
-        {
-            xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference));
-            if (pReference)
-            {
-                if (pReference->status == xmlSecDSigStatusSucceeded)
-                    ++nReferenceGood;
-            }
-        }
+        // reset status - to be set later
+        pDsigCtx->status = xmlSecDSigStatusUnknown;
+
+        // get me a digestible buffer from the SignatureInfo node!
+        // -------------------------------------------------------
+
+        // run the transformations - first child node is required to
+        // be SignatureInfo
+        xmlSecNodeSetPtr nodeset = nullptr;
+        xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children);
+        // TODO assert that...
+        nodeset = xmlSecNodeSetGetChildren(pNode->doc, cur, 1, 0);
+        if(nodeset == nullptr)
+            throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+        // TODO assert we really have the SignatureInfo here?
+        if( xmlSecTransformCtxXmlExecute(&(pDsigCtx->transformCtx), nodeset) < 0 )
+            throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
 
-        if (rs == 0 && pDsigCtx->status == xmlSecDSigStatusSucceeded && nReferenceCount == nReferenceGood)
+        // Validate the template via gpgme
+        GpgME::Context& rCtx=pSecEnv->getGpgContext();
+
+        GpgME::Data data_text(
+            reinterpret_cast<char*>(xmlSecBufferGetData(pDsigCtx->transformCtx.result)),
+            xmlSecBufferGetSize(pDsigCtx->transformCtx.result), false);
+
+        SAL_INFO("xmlsecurity.xmlsec.gpg", "Validating SignatureInfo: " << xmlSecBufferGetData(pDsigCtx->transformCtx.result));
+
+        // walk xml tree to sign value node - go to children, first is
+        // SignedInfo, 2nd is signaturevalue
+        cur = xmlSecGetNextElementNode(pNode->children);
+        cur = xmlSecGetNextElementNode(cur->next);
+
+        // TODO some assert would be good that cur is actually SignatureValue
+        xmlChar* pSignatureValue=xmlNodeGetContent(cur);
+        GpgME::Data data_signature(
+            reinterpret_cast<char*>(pSignatureValue),
+            xmlStrlen(pSignatureValue), false);
+
+        GpgME::VerificationResult verify_res=rCtx.verifyDetachedSignature(
+            data_signature, data_text);
+
+        xmlFree(pSignatureValue);
+
+        // TODO: needs some more error handling, needs checking _all_ signatures
+        if( verify_res.isNull() ||
+            verify_res.numSignatures() == 0 ||
+            verify_res.signature(0).validity() < GpgME::Signature::Full )
         {
-            aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
-            xmlSecDSigCtxDestroy( pDsigCtx ) ;
-            SecurityEnvironment_NssImpl::destroyKeysManager( pMngr );
-            break;
+            clearErrorRecorder();
+            return aTemplate;
         }
-        else
+
+        // now verify digest for all references
+        cur = xmlSecGetNextElementNode(pNode->children);
+        if( cur != nullptr )
+            cur = xmlSecGetNextElementNode(cur->children);
+        while( cur != nullptr )
         {
-            aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+            // some of those children I suppose should be reference elements
+            if( xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs) )
+            {
+                xmlSecDSigReferenceCtxPtr pDsigRefCtx =
+                    xmlSecDSigReferenceCtxCreate(pDsigCtx,
+                                                 xmlSecDSigReferenceOriginSignedInfo);
+                if(pDsigRefCtx == nullptr)
+                    throw RuntimeException();
+
+                // add this one to the list
+                if( xmlSecPtrListAdd(&(pDsigCtx->signedInfoReferences),
+                                     pDsigRefCtx) < 0 )
+                {
+                    // TODO resource handling
+                    xmlSecDSigReferenceCtxDestroy(pDsigRefCtx);
+                    throw RuntimeException();
+                }
+
+                if( xmlSecDSigReferenceCtxProcessNode(pDsigRefCtx, cur) < 0 )
+                    throw RuntimeException();
+
+                // final check - all good?
+                if(pDsigRefCtx->status != xmlSecDSigStatusSucceeded)
+                {
+                    pDsigCtx->status = xmlSecDSigStatusInvalid;
+                    return aTemplate; // TODO - harder error?
+                }
+            }
+
+            cur = xmlSecGetNextElementNode(cur->next);
         }
+
+        // TODO - also verify manifest (only relevant for ooxml)?
+        aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+
+        // done
         xmlSecDSigCtxDestroy( pDsigCtx ) ;
-        SecurityEnvironment_NssImpl::destroyKeysManager( pMngr );
-#endif
     }
 
-
     //Unregistered the stream/URI binding
     if( xUriBinding.is() )
         xmlUnregisterStreamInputCallbacks() ;
 
-    //return valid ;
     clearErrorRecorder();
-    return aTemplate;
+    return aTemplate ;
 }
 
 /* XServiceInfo */
diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx
index 96f78aaa6c80..1d8d1c0d72cb 100644
--- a/xmlsecurity/source/helper/documentsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx
@@ -554,7 +554,8 @@ void DocumentSignatureHelper::writeSignedProperties(
     writeDigestMethod(xDocumentHandler);
 
     xDocumentHandler->startElement("DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
-    assert(!signatureInfo.ouCertDigest.isEmpty());
+    // TODO: this is empty for gpg signatures currently
+    //assert(!signatureInfo.ouCertDigest.isEmpty());
     xDocumentHandler->characters(signatureInfo.ouCertDigest);
     xDocumentHandler->endElement("DigestValue");
 
diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx
index f2a155b4db8d..ded3de8d9960 100644
--- a/xmlsecurity/source/helper/documentsignaturemanager.cxx
+++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx
@@ -26,6 +26,7 @@
 #include <com/sun/star/io/XTruncate.hpp>
 #include <com/sun/star/embed/XTransactedObject.hpp>
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
 
 #include <comphelper/storagehelper.hxx>
 #include <rtl/ustrbuf.hxx>
@@ -37,7 +38,10 @@
 #include <certificate.hxx>
 #include <biginteger.hxx>
 
+#include <xmlsec/xmlsec_init.hxx>
+
 using namespace css;
+namespace cssu = com::sun::star::uno;
 
 DocumentSignatureManager::DocumentSignatureManager(const uno::Reference<uno::XComponentContext>& xContext, DocumentSignatureMode eMode)
     : mxContext(xContext),
@@ -46,7 +50,10 @@ DocumentSignatureManager::DocumentSignatureManager(const uno::Reference<uno::XCo
 {
 }
 
-DocumentSignatureManager::~DocumentSignatureManager() = default;
+DocumentSignatureManager::~DocumentSignatureManager()
+{
+    deInitXmlSec();
+}
 
 bool DocumentSignatureManager::init()
 {
@@ -54,9 +61,12 @@ bool DocumentSignatureManager::init()
     SAL_WARN_IF(mxSecurityContext.is(), "xmlsecurity.helper", "DocumentSignatureManager::Init - mxSecurityContext already set!");
     SAL_WARN_IF(mxGpgSEInitializer.is(), "xmlsecurity.helper", "DocumentSignatureManager::Init - mxGpgSEInitializer already set!");
 
+    // xmlsec is needed by both services, so init before those
+    initXmlSec();
+
     mxSEInitializer = xml::crypto::SEInitializer::create(mxContext);
 #if !defined(MACOSX) && !defined(WNT)
-    mxGpgSEInitializer.set(new SEInitializerGpg(mxContext));
+    mxGpgSEInitializer.set(new SEInitializerGpg());
 #endif
 
     if (mxSEInitializer.is())
@@ -243,7 +253,11 @@ SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int3
     return aHelper;
 }
 
-bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant)
+bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert,
+                                   const uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext,
+                                   const OUString& rDescription,
+                                   sal_Int32& nSecurityId,
+                                   bool bAdESCompliant)
 {
     if (!xCert.is())
     {
@@ -251,57 +265,94 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
         return false;
     }
 
-    OUString aCertSerial = xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber());
-    if (aCertSerial.isEmpty())
-    {
-        SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!");
-        return false;
-    }
-
-    if (!mxStore.is())
+    // GPG or X509 key?
+    uno::Reference< lang::XServiceInfo > xServiceInfo( xSecurityContext, cssu::UNO_QUERY );
+    if (xServiceInfo->getImplementationName() == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
     {
-        // Something not ZIP based, try PDF.
-        nSecurityId = getPDFSignatureHelper().GetNewSecurityId();
-        getPDFSignatureHelper().SetX509Certificate(xCert);
-        getPDFSignatureHelper().SetDescription(rDescription);
-        uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
-        if (!getPDFSignatureHelper().Sign(xInputStream, bAdESCompliant))
+        // GPG keys only really have PGPKeyId and PGPKeyPacket
+        // TODO: prevent selection of gpg keys for pdfs and ooxml early on!
+        if (!mxStore.is())
         {
-            SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
+            SAL_WARN("xmlsecurity.helper", "cannot sign pdfs with GPG keys");
             return false;
         }
-        return true;
-    }
 
-    maSignatureHelper.StartMission(mxSecurityContext);
+        maSignatureHelper.StartMission(xSecurityContext);
 
-    nSecurityId = maSignatureHelper.GetNewSecurityId();
+        nSecurityId = maSignatureHelper.GetNewSecurityId();
 
-    OUStringBuffer aStrBuffer;
-    sax::Converter::encodeBase64(aStrBuffer, xCert->getEncoded());
+        OUStringBuffer aStrBuffer;
+        sax::Converter::encodeBase64(aStrBuffer, xCert->getEncoded());
 
-    OUString aCertDigest;
-    if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
-    {
-        OUStringBuffer aBuffer;
-        sax::Converter::encodeBase64(aBuffer, pCertificate->getSHA256Thumbprint());
-        aCertDigest = aBuffer.makeStringAndClear();
+        OUString aKeyId;
+        if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
+        {
+            OUStringBuffer aBuffer;
+            sax::Converter::encodeBase64(aBuffer, pCertificate->getSHA256Thumbprint());
+            aKeyId = aBuffer.makeStringAndClear();
+        }
+        else
+            SAL_WARN("xmlsecurity.helper", "XCertificate implementation without an xmlsecurity::Certificate one");
+
+        maSignatureHelper.SetGpgCertificate(nSecurityId, aKeyId, aStrBuffer.makeStringAndClear());
     }
     else
-        SAL_WARN("xmlsecurity.helper", "XCertificate implementation without an xmlsecurity::Certificate one");
+    {
+        OUString aCertSerial = xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber());
+        if (aCertSerial.isEmpty())
+        {
+            SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!");
+            return false;
+        }
 
-    maSignatureHelper.SetX509Certificate(nSecurityId, xCert->getIssuerName(), aCertSerial, aStrBuffer.makeStringAndClear(), aCertDigest);
+        if (!mxStore.is())
+        {
+            // Something not ZIP based, try PDF.
+            nSecurityId = getPDFSignatureHelper().GetNewSecurityId();
+            getPDFSignatureHelper().SetX509Certificate(xCert);
+            getPDFSignatureHelper().SetDescription(rDescription);
+            uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
+            if (!getPDFSignatureHelper().Sign(xInputStream, bAdESCompliant))
+            {
+                SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
+                return false;
+            }
+            return true;
+        }
+
+        maSignatureHelper.StartMission(xSecurityContext);
+
+        nSecurityId = maSignatureHelper.GetNewSecurityId();
+
+        OUStringBuffer aStrBuffer;
+        sax::Converter::encodeBase64(aStrBuffer, xCert->getEncoded());
+
+        OUString aCertDigest;
+        if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
+        {
+            OUStringBuffer aBuffer;
+            sax::Converter::encodeBase64(aBuffer, pCertificate->getSHA256Thumbprint());
+            aCertDigest = aBuffer.makeStringAndClear();
+        }
+        else
+            SAL_WARN("xmlsecurity.helper", "XCertificate implementation without an xmlsecurity::Certificate one");
+
+        maSignatureHelper.SetX509Certificate(nSecurityId, xCert->getIssuerName(), aCertSerial, aStrBuffer.makeStringAndClear(), aCertDigest);
 
-    uno::Sequence< uno::Reference< security::XCertificate > > aCertPath = getSecurityEnvironment()->buildCertificatePath(xCert);
+    }
+
+    uno::Sequence< uno::Reference< security::XCertificate > > aCertPath = xSecurityContext->getSecurityEnvironment()->buildCertificatePath(xCert);
     const uno::Reference< security::XCertificate >* pCertPath = aCertPath.getConstArray();
     sal_Int32 nCnt = aCertPath.getLength();
 
+    OUStringBuffer aStrBuffer;
     for (int i = 0; i < nCnt; i++)
     {
         sax::Converter::encodeBase64(aStrBuffer, pCertPath[i]->getEncoded());
         maSignatureHelper.AddEncapsulatedX509Certificate(aStrBuffer.makeStringAndClear());
     }
 
+
     std::vector< OUString > aElements = DocumentSignatureHelper::CreateElementList(mxStore, meSignatureMode, DocumentSignatureAlgorithm::OOo3_2);
     DocumentSignatureHelper::AppendContentTypes(mxStore, aElements);
 
@@ -521,4 +572,15 @@ uno::Reference<xml::crypto::XSecurityEnvironment> DocumentSignatureManager::getG
     return mxGpgSecurityContext.is() ? mxGpgSecurityContext->getSecurityEnvironment() : uno::Reference<xml::crypto::XSecurityEnvironment>();
 }
 
+uno::Reference<xml::crypto::XXMLSecurityContext> DocumentSignatureManager::getSecurityContext()
+{
+    return mxSecurityContext;
+}
+
+uno::Reference<xml::crypto::XXMLSecurityContext> DocumentSignatureManager::getGpgSecurityContext()
+{
+    return mxGpgSecurityContext;
+}
+
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
index df8af13653b2..6242518ce4e1 100644
--- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
@@ -123,6 +123,16 @@ void XMLSignatureHelper::AddEncapsulatedX509Certificate(const OUString& ouEncaps
     mpXSecController->addEncapsulatedX509Certificate(ouEncapsulatedX509Certificate);
 }
 
+void XMLSignatureHelper::SetGpgCertificate(sal_Int32 nSecurityId,
+                                           const OUString& ouGpgCertDigest,
+                                           const OUString& ouGpgCert)
+{
+    mpXSecController->setGpgCertificate(
+        nSecurityId,
+        ouGpgCertDigest,
+        ouGpgCert);
+}
+
 void XMLSignatureHelper::SetDateTime( sal_Int32 nSecurityId, const ::Date& rDate, const tools::Time& rTime )
 {
     css::util::DateTime stDateTime = ::DateTime(rDate, rTime).GetUNODateTime();
diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx
index e28f8bd8f901..ffadd0584692 100644
--- a/xmlsecurity/source/helper/xsecctl.cxx
+++ b/xmlsecurity/source/helper/xsecctl.cxx
@@ -22,6 +22,9 @@
 #include "documentsignaturehelper.hxx"
 #include "framework/saxeventkeeperimpl.hxx"
 #include "xmlsec/xmldocumentwrapper_xmlsecimpl.hxx"
+#if !defined(MACOSX) && !defined(WNT)
+# include "gpg/xmlsignature_gpgimpl.hxx"
+#endif
 
 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
@@ -124,9 +127,13 @@ void XSecController::createXSecComponent( )
 
     cssu::Reference< cssl::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() );
 
-    m_xXMLSignature.set(
-        xMCF->createInstanceWithContext("com.sun.star.xml.crypto.XMLSignature", mxCtx ),
-        cssu::UNO_QUERY );
+#if !defined(MACOSX) && !defined(WNT)
+    uno::Reference< lang::XServiceInfo > xServiceInfo( m_xSecurityContext, cssu::UNO_QUERY );
+    if (xServiceInfo->getImplementationName() == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
+        m_xXMLSignature.set(new XMLSignature_GpgImpl());
+    else // xmlsec or mscrypt
+#endif
+        m_xXMLSignature.set(xMCF->createInstanceWithContext("com.sun.star.xml.crypto.XMLSignature", mxCtx), cssu::UNO_QUERY);
 
     bool bSuccess = m_xXMLSignature.is();
     if ( bSuccess )
@@ -716,43 +723,73 @@ void XSecController::exportSignature(
             "KeyInfo",
             cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
         {
-            /* Write X509Data element */
-            xDocumentHandler->startElement(
-                "X509Data",
-                cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
+            // GPG or X509 key?
+            if (!signatureInfo.ouGpgCertificate.isEmpty())
             {
-                /* Write X509IssuerSerial element */
+                /* Write PGPData element */
                 xDocumentHandler->startElement(
-                    "X509IssuerSerial",
+                    "PGPData",
                     cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
                 {
-                    /* Write X509IssuerName element */
+                    /* Write keyid element */
                     xDocumentHandler->startElement(
-                        "X509IssuerName",
+                        "PGPKeyID",
                         cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
-                    xDocumentHandler->characters( signatureInfo.ouX509IssuerName );
-                    xDocumentHandler->endElement( "X509IssuerName" );
+                    xDocumentHandler->characters( signatureInfo.ouCertDigest );
+                    xDocumentHandler->endElement( "PGPKeyID" );
 
-                    /* Write X509SerialNumber element */
-                    xDocumentHandler->startElement(
-                        "X509SerialNumber",
-                        cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
-                    xDocumentHandler->characters( signatureInfo.ouX509SerialNumber );
-                    xDocumentHandler->endElement( "X509SerialNumber" );
+                    /* Write PGPKeyPacket element */
+                    if (!signatureInfo.ouGpgCertificate.isEmpty())
+                    {
+                        xDocumentHandler->startElement(
+                            "PGPKeyPacket",
+                            cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
+                        xDocumentHandler->characters( signatureInfo.ouGpgCertificate );
+                        xDocumentHandler->endElement( "PGPKeyPacket" );
+                    }
                 }
-                xDocumentHandler->endElement( "X509IssuerSerial" );
-
-                /* Write X509Certificate element */
-                if (!signatureInfo.ouX509Certificate.isEmpty())
+                xDocumentHandler->endElement( "PGPData" );
+            }
+            else
+            {
+                /* Write X509Data element */
+                xDocumentHandler->startElement(
+                    "X509Data",
+                    cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
                 {
+                    /* Write X509IssuerSerial element */
                     xDocumentHandler->startElement(
-                        "X509Certificate",
+                        "X509IssuerSerial",
                         cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
-                    xDocumentHandler->characters( signatureInfo.ouX509Certificate );
-                    xDocumentHandler->endElement( "X509Certificate" );
+                    {
+                        /* Write X509IssuerName element */
+                        xDocumentHandler->startElement(
+                            "X509IssuerName",
+                            cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
+                        xDocumentHandler->characters( signatureInfo.ouX509IssuerName );
+                        xDocumentHandler->endElement( "X509IssuerName" );
+
+                        /* Write X509SerialNumber element */
+                        xDocumentHandler->startElement(
+                            "X509SerialNumber",
+                            cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
+                        xDocumentHandler->characters( signatureInfo.ouX509SerialNumber );
+                        xDocumentHandler->endElement( "X509SerialNumber" );
+                    }
+                    xDocumentHandler->endElement( "X509IssuerSerial" );
+
+                    /* Write X509Certificate element */
+                    if (!signatureInfo.ouX509Certificate.isEmpty())
+                    {
+                        xDocumentHandler->startElement(
+                            "X509Certificate",
+                            cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList()));
+                        xDocumentHandler->characters( signatureInfo.ouX509Certificate );
+                        xDocumentHandler->endElement( "X509Certificate" );
+                    }
                 }
+                xDocumentHandler->endElement( "X509Data" );
             }
-            xDocumentHandler->endElement( "X509Data" );
         }
         xDocumentHandler->endElement( "KeyInfo" );
 
diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx
index 6e6bfc45c426..6c402e73e0cb 100644
--- a/xmlsecurity/source/helper/xsecparser.cxx
+++ b/xmlsecurity/source/helper/xsecparser.cxx
@@ -35,6 +35,8 @@ XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper,
     : m_bInX509IssuerName(false)
     , m_bInX509SerialNumber(false)
     , m_bInX509Certificate(false)
+    , m_bInGpgCertificate(false)
+    , m_bInGpgKeyID(false)
     , m_bInCertDigest(false)
     , m_bInEncapsulatedX509Certificate(false)
     , m_bInSigningTime(false)
@@ -70,6 +72,8 @@ void SAL_CALL XSecParser::startDocument(  )
     m_bInX509IssuerName = false;
     m_bInX509SerialNumber = false;
     m_bInX509Certificate = false;
+    m_bInGpgCertificate = false;
+    m_bInGpgKeyID = false;
     m_bInSignatureValue = false;
     m_bInDigestValue = false;
     m_bInDate = false;
@@ -176,6 +180,20 @@ void SAL_CALL XSecParser::startElement(
             m_ouX509Certificate.clear();
             m_bInX509Certificate = true;
         }
+        else if (aName == "PGPData")
+        {
+            m_pXSecController->switchGpgSignature();
+        }
+        else if (aName == "PGPKeyID")
+        {
+            m_ouGpgKeyID.clear();
+            m_bInGpgKeyID = true;
+        }
+        else if (aName == "PGPKeyPacket")
+        {
+            m_ouGpgCertificate.clear();
+            m_bInGpgCertificate = true;
+        }
         else if (aName == "SignatureValue")
         {
             m_ouSignatureValue.clear();
@@ -289,6 +307,16 @@ void SAL_CALL XSecParser::endElement( const OUString& aName )
             m_pXSecController->setX509Certificate( m_ouX509Certificate );
             m_bInX509Certificate = false;
         }
+        else if (aName == "PGPKeyID")
+        {
+            m_pXSecController->setGpgKeyID( m_ouGpgKeyID );
+            m_bInGpgKeyID = false;
+        }
+        else if (aName == "PGPKeyPacket")
+        {
+            m_pXSecController->setGpgCertificate( m_ouGpgCertificate );
+            m_bInGpgCertificate = false;
+        }
         else if (aName == "xd:CertDigest")
         {
             m_pXSecController->setCertDigest( m_ouCertDigest );
@@ -352,6 +380,14 @@ void SAL_CALL XSecParser::characters( const OUString& aChars )
     {
         m_ouX509Certificate += aChars;
     }
+    else if (m_bInGpgCertificate)
+    {
+        m_ouGpgCertificate += aChars;
+    }
+    else if (m_bInGpgKeyID)
+    {
+        m_ouGpgKeyID += aChars;
+    }
     else if (m_bInSignatureValue)
     {
         m_ouSignatureValue += aChars;
diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx
index 1fc01b74123e..dd4d0c83c1e6 100644
--- a/xmlsecurity/source/helper/xsecparser.hxx
+++ b/xmlsecurity/source/helper/xsecparser.hxx
@@ -57,6 +57,8 @@ private:
     OUString m_ouX509IssuerName;
     OUString m_ouX509SerialNumber;
     OUString m_ouX509Certificate;
+    OUString m_ouGpgCertificate;
+    OUString m_ouGpgKeyID;
     OUString m_ouCertDigest;
     OUString m_ouEncapsulatedX509Certificate;
     OUString m_ouDigestValue;
@@ -71,6 +73,8 @@ private:
     bool m_bInX509IssuerName;
     bool m_bInX509SerialNumber;
     bool m_bInX509Certificate;
+    bool m_bInGpgCertificate;
+    bool m_bInGpgKeyID;
     bool m_bInCertDigest;
     bool m_bInEncapsulatedX509Certificate;
     bool m_bInSigningTime;
diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx
index 092b8fb001e6..452613b4d10b 100644
--- a/xmlsecurity/source/helper/xsecsign.cxx
+++ b/xmlsecurity/source/helper/xsecsign.cxx
@@ -239,6 +239,29 @@ void XSecController::setX509Certificate(
     }
 }
 
+void XSecController::setGpgCertificate(
+        sal_Int32 nSecurityId,
+        const OUString& ouCertDigest,
+        const OUString& ouCert)
+{
+    int index = findSignatureInfor( nSecurityId );
+
+    if ( index == -1 )
+    {
+        InternalSignatureInformation isi(nSecurityId, nullptr);
+        isi.signatureInfor.ouGpgCertificate = ouCert;
+        isi.signatureInfor.ouCertDigest = ouCertDigest;
+        m_vInternalSignatureInformations.push_back( isi );
+    }
+    else
+    {
+        SignatureInformation &si
+            = m_vInternalSignatureInformations[index].signatureInfor;
+        si.ouGpgCertificate = ouCert;
+        si.ouCertDigest = ouCertDigest;
+    }
+}
+
 void XSecController::setDate(
     sal_Int32 nSecurityId,
     const css::util::DateTime& rDateTime )
diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx
index 138a0026928a..ab2a8dec6100 100644
--- a/xmlsecurity/source/helper/xsecverify.cxx
+++ b/xmlsecurity/source/helper/xsecverify.cxx
@@ -23,12 +23,15 @@
 #include "ooxmlsecparser.hxx"
 #include "framework/signatureverifierimpl.hxx"
 #include "framework/saxeventkeeperimpl.hxx"
+#include "gpg/xmlsignature_gpgimpl.hxx"
+#include "gpg/SEInitializer.hxx"
 
 #include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp>
 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
 #include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
 #include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp>
+#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
 #include <com/sun/star/xml/sax/SAXParseException.hpp>
 #include <com/sun/star/embed/StorageFormats.hpp>
 #include <sal/log.hxx>
@@ -105,6 +108,27 @@ void XSecController::addSignature()
     m_vInternalSignatureInformations.push_back( isi );
 }
 
+void XSecController::switchGpgSignature()
+{
+#if !defined(MACOSX) && !defined(WNT)
+    // swap signature verifier for the Gpg one
+    m_xXMLSignature.set(new XMLSignature_GpgImpl());
+    if (!m_vInternalSignatureInformations.empty())
+    {
+        SignatureVerifierImpl* pImpl=
+            dynamic_cast<SignatureVerifierImpl*>(
+                m_vInternalSignatureInformations.back().xReferenceResolvedListener.get());
+        if (pImpl)
+        {
+            css::uno::Reference<css::xml::crypto::XSEInitializer> xGpgSEInitializer(
+                new SEInitializerGpg());
+            pImpl->updateSignature(new XMLSignature_GpgImpl(),
+                                   xGpgSEInitializer->createSecurityContext(OUString()));
+        }
+    }
+#endif
+}
+
 void XSecController::addReference( const OUString& ouUri, sal_Int32 nDigestID )
 {
     if (m_vInternalSignatureInformations.empty())
@@ -246,6 +270,28 @@ void XSecController::setDigestValue( sal_Int32 nDigestID, OUString& ouDigestValu
     reference.ouDigestValue = ouDigestValue;
 }
 
+void XSecController::setGpgKeyID( OUString& ouKeyID )
+{
+    if (m_vInternalSignatureInformations.empty())
+    {
+        SAL_INFO("xmlsecurity.helper","XSecController::setGpgKeyID: no signature");
+        return;
+    }
+    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+    isi.signatureInfor.ouGpgKeyID = ouKeyID;
+}
+
+void XSecController::setGpgCertificate( OUString& ouGpgCert )
+{
+    if (m_vInternalSignatureInformations.empty())
+    {
+        SAL_INFO("xmlsecurity.helper","XSecController::setGpgCertificate: no signature");
+        return;
+    }
+    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+    isi.signatureInfor.ouGpgCertificate = ouGpgCert;
+}
+
 void XSecController::setDate( OUString& ouDate )
 {
     if (m_vInternalSignatureInformations.empty())
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
index 8ae78b105403..35b3835a2afe 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
@@ -594,6 +594,11 @@ css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getMD5Thumb
     return getThumbprint(m_pCertContext, CERT_MD5_HASH_PROP_ID);
 }
 
+CertificateKind SAL_CALL X509Certificate_MSCryptImpl::getCertificateKind()
+{
+    return CertificateKind_X509;
+}
+
 sal_Int32 SAL_CALL X509Certificate_MSCryptImpl::getCertificateUsage(  )
 {
     sal_Int32 usage =
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
index f7ba8a21a3fc..ce63a8acc170 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
@@ -35,6 +35,7 @@
 #include <com/sun/star/uno/Exception.hpp>
 #include <com/sun/star/lang/XUnoTunnel.hpp>
 #include <com/sun/star/uno/SecurityException.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
 #include <com/sun/star/security/XCertificate.hpp>
 #include <certificate.hxx>
 
@@ -67,6 +68,8 @@ class X509Certificate_MSCryptImpl : public ::cppu::WeakImplHelper<
         virtual OUString SAL_CALL getSignatureAlgorithm() override;
         virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override;
         virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override;
+        virtual css::security::CertificateKind SAL_CALL getCertificateKind() override;
+
 
         virtual sal_Int32 SAL_CALL getCertificateUsage( ) override;
 
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
index cc93f1be46b7..079be582e02b 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
@@ -455,6 +455,11 @@ css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getMD5Thumbprin
     return getThumbprint(m_pCert, SEC_OID_MD5);
 }
 
+CertificateKind SAL_CALL X509Certificate_NssImpl::getCertificateKind()
+{
+    return CertificateKind_X509;
+}
+
 sal_Int32 SAL_CALL X509Certificate_NssImpl::getCertificateUsage(  )
 {
     SECStatus rv;
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
index 08e9cf1185e7..58759673935b 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
@@ -27,6 +27,7 @@
 #include <com/sun/star/uno/Exception.hpp>
 #include <com/sun/star/lang/XUnoTunnel.hpp>
 #include <com/sun/star/uno/SecurityException.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
 #include <com/sun/star/security/XCertificate.hpp>
 
 #include <certificate.hxx>
@@ -72,6 +73,7 @@ class X509Certificate_NssImpl : public ::cppu::WeakImplHelper<
         virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override ;
 
         virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override ;
+        virtual css::security::CertificateKind SAL_CALL getCertificateKind() override;
 
         virtual sal_Int32 SAL_CALL getCertificateUsage( ) override ;
 
diff --git a/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx
index 6b7a78b1e6a1..371a27f3d090 100644
--- a/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx
@@ -22,9 +22,6 @@
 #include "securityenvironment_nssimpl.hxx"
 
 #include "xmlsecuritycontext_nssimpl.hxx"
-#include "xmlsec/xmlstreamio.hxx"
-
-#include "xmlsec-wrapper.h"
 
 using namespace ::com::sun::star::uno ;
 using namespace ::com::sun::star::lang ;
@@ -37,30 +34,10 @@ using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
 XMLSecurityContext_NssImpl::XMLSecurityContext_NssImpl()
     : m_nDefaultEnvIndex(-1)
 {
-    //Init xmlsec library
-    if( xmlSecInit() < 0 ) {
-        throw RuntimeException() ;
-    }
-
-    //Init xmlsec crypto engine library
-    if( xmlSecCryptoInit() < 0 ) {
-        xmlSecShutdown() ;
-        throw RuntimeException() ;
-    }
-
-    //Enable external stream handlers
-    if( xmlEnableStreamInputCallbacks() < 0 ) {
-        xmlSecCryptoShutdown() ;
-        xmlSecShutdown() ;
-        throw RuntimeException() ;
-    }
 }
 
 XMLSecurityContext_NssImpl::~XMLSecurityContext_NssImpl()
 {
-    xmlDisableStreamInputCallbacks() ;
-    xmlSecCryptoShutdown() ;
-    xmlSecShutdown() ;
 }
 
 sal_Int32 SAL_CALL XMLSecurityContext_NssImpl::addSecurityEnvironment(
diff --git a/xmlsecurity/source/xmlsec/xmlsec_init.cxx b/xmlsecurity/source/xmlsec/xmlsec_init.cxx
new file mode 100644
index 000000000000..9b2fe90f87c2
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/xmlsec_init.cxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xmlsec/xmlsec_init.hxx"
+
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+#include "xmlsec/xmlstreamio.hxx"
+#include "xmlsec-wrapper.h"
+
+using namespace css::uno;
+
+XSECXMLSEC_DLLPUBLIC void initXmlSec()
+{
+    //Init xmlsec library
+    if( xmlSecInit() < 0 ) {
+        throw RuntimeException() ;
+    }
+
+    //Init xmlsec crypto engine library
+    if( xmlSecCryptoInit() < 0 ) {
+        xmlSecShutdown() ;
+        throw RuntimeException() ;
+    }
+
+    //Enable external stream handlers
+    if( xmlEnableStreamInputCallbacks() < 0 ) {
+        xmlSecCryptoShutdown() ;
+        xmlSecShutdown() ;
+        throw RuntimeException() ;
+    }
+}
+
+XSECXMLSEC_DLLPUBLIC void deInitXmlSec()
+{
+    xmlDisableStreamInputCallbacks();
+    xmlSecCryptoShutdown();
+    xmlSecShutdown();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/xmlstreamio.cxx b/xmlsecurity/source/xmlsec/xmlstreamio.cxx
index 6faf711c181b..32d86269cd7e 100644
--- a/xmlsecurity/source/xmlsec/xmlstreamio.cxx
+++ b/xmlsecurity/source/xmlsec/xmlstreamio.cxx
@@ -145,7 +145,7 @@ int xmlStreamClose( void * context )
     return 0 ;
 }
 
-int xmlEnableStreamInputCallbacks()
+XSECXMLSEC_DLLPUBLIC int xmlEnableStreamInputCallbacks()
 {
 
     if( !( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) ) {
@@ -210,7 +210,7 @@ XSECXMLSEC_DLLPUBLIC int xmlUnregisterStreamInputCallbacks()
     return 0 ;
 }
 
-void xmlDisableStreamInputCallbacks() {
+XSECXMLSEC_DLLPUBLIC void xmlDisableStreamInputCallbacks() {
     xmlUnregisterStreamInputCallbacks() ;
     enableXmlStreamIO &= ~XMLSTREAMIO_INITIALIZED ;
 }
diff --git a/xmlsecurity/source/xmlsec/xsec_xmlsec.cxx b/xmlsecurity/source/xmlsec/xsec_xmlsec.cxx
index 99738064c09f..b480b90a9235 100644
--- a/xmlsecurity/source/xmlsec/xsec_xmlsec.cxx
+++ b/xmlsecurity/source/xmlsec/xsec_xmlsec.cxx
@@ -27,6 +27,10 @@
 #include "xmlsec/xmldocumentwrapper_xmlsecimpl.hxx"
 #include "xsec_xmlsec.hxx"
 
+#if !defined(MACOSX) && !defined(WNT)
+# include "gpg/xmlsignature_gpgimpl.hxx"
+#endif
+
 using namespace ::cppu;
 using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::lang;
@@ -40,7 +44,14 @@ SAL_DLLPUBLIC_EXPORT void* SAL_CALL xsec_xmlsec_component_getFactory( const sal_
     Reference< XInterface > xFactory ;
 
     if( pImplName != nullptr ) {
-        if( XMLElementWrapper_XmlSecImpl_getImplementationName().equalsAscii( pImplName ) )
+#if !defined(MACOSX) && !defined(WNT)
+        if( XMLSignature_GpgImpl::impl_getImplementationName().equalsAscii( pImplName ) )
+        {
+            xFactory = XMLSignature_GpgImpl::impl_createFactory( static_cast< XMultiServiceFactory* >( pServiceManager ) ) ;
+        }
+        else
+#endif
+            if( XMLElementWrapper_XmlSecImpl_getImplementationName().equalsAscii( pImplName ) )
         {
             xFactory = cppu::createSingleComponentFactory(
                 XMLElementWrapper_XmlSecImpl_createInstance,
diff --git a/xmlsecurity/util/xsec_gpg.component b/xmlsecurity/util/xsec_gpg.component
deleted file mode 100644
index bf24f36953ca..000000000000
--- a/xmlsecurity/util/xsec_gpg.component
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- -->
-
-<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
-    prefix="xsec_gpg" xmlns="http://openoffice.org/2010/uno-components">
-  <implementation name="com.sun.star.xml.security.bridge.xmlsec.XMLSignature_GpgImpl">
-    <service name="com.sun.star.xml.crypto.XMLSignature2"/>
-  </implementation>
-</component>


More information about the Libreoffice-commits mailing list