diff options
author | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2017-05-21 14:28:57 +0200 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2017-06-21 23:14:49 +0200 |
commit | 3e3b37ca4cbc881628a71715b67ac172018cf9f2 (patch) | |
tree | 5f16855d11f1a2910e2f4fbb08078c2aff4c5275 /xmlsecurity | |
parent | 814dbf3624b9e8608882b003d96dfb51fa3634fc (diff) |
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@cib.de>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'xmlsecurity')
44 files changed, 783 insertions, 360 deletions
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 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> |