1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <svl/sigstruct.hxx>
24 #include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp>
25 #include <com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp>
26 #include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp>
28 #include <rtl/ref.hxx>
29 #include <cppuhelper/implbase.hxx>
33 #include "UriBindingHelper.hxx"
35 namespace com::sun::star::embed
{ class XStorage
; }
36 namespace com::sun::star::graphic
{ class XGraphic
; }
37 namespace com::sun::star::io
{ class XInputStream
; }
38 namespace com::sun::star::lang
{ class XInitialization
; }
39 namespace com::sun::star::uno
{ class XComponentContext
; }
40 namespace com::sun::star::xml::crypto
{ class XXMLSecurityContext
; }
41 namespace com::sun::star::xml::crypto
{ class XXMLSignature
; }
42 namespace com::sun::star::xml::crypto:: sax
{ class XReferenceResolvedListener
; }
43 namespace com::sun::star::xml::sax
{ class XDocumentHandler
; }
45 inline constexpr OUStringLiteral NS_XMLDSIG
= u
"http://www.w3.org/2000/09/xmldsig#";
46 inline constexpr OUStringLiteral NS_DC
= u
"http://purl.org/dc/elements/1.1/";
47 inline constexpr OUStringLiteral NS_XD
= u
"http://uri.etsi.org/01903/v1.3.2#";
48 inline constexpr OUStringLiteral NS_MDSSI
= u
"http://schemas.openxmlformats.org/package/2006/digital-signature";
49 inline constexpr OUStringLiteral NS_LOEXT
= u
"urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0";
51 inline constexpr OUStringLiteral ALGO_C14N
= u
"http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
52 inline constexpr OUStringLiteral ALGO_RSASHA1
= u
"http://www.w3.org/2000/09/xmldsig#rsa-sha1";
53 inline constexpr OUStringLiteral ALGO_RSASHA256
= u
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
54 inline constexpr OUStringLiteral ALGO_RSASHA512
= u
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";
55 inline constexpr OUStringLiteral ALGO_ECDSASHA1
= u
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1";
56 inline constexpr OUStringLiteral ALGO_ECDSASHA256
= u
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256";
57 inline constexpr OUStringLiteral ALGO_ECDSASHA512
= u
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512";
58 inline constexpr OUStringLiteral ALGO_XMLDSIGSHA1
= u
"http://www.w3.org/2000/09/xmldsig#sha1";
59 inline constexpr OUStringLiteral ALGO_XMLDSIGSHA256
= u
"http://www.w3.org/2001/04/xmlenc#sha256";
60 inline constexpr OUStringLiteral ALGO_XMLDSIGSHA512
= u
"http://www.w3.org/2001/04/xmlenc#sha512";
61 inline constexpr OUStringLiteral ALGO_RELATIONSHIP
= u
"http://schemas.openxmlformats.org/package/2006/RelationshipTransform";
63 class XMLDocumentWrapper_XmlSecImpl
;
64 class SAXEventKeeperImpl
;
65 class XMLSignatureHelper
;
66 namespace svl::crypto
{ enum class SignatureMethodAlgorithm
; }
68 class InternalSignatureInformation
71 SignatureInformation signatureInfor
;
73 css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
> xReferenceResolvedListener
;
75 ::std::vector
< sal_Int32
> vKeeperIds
;
77 InternalSignatureInformation(
79 css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
> const & xListener
)
82 xReferenceResolvedListener
= xListener
;
85 void addReference( SignatureReferenceType type
, sal_Int32 digestID
, const OUString
& uri
, sal_Int32 keeperId
, const OUString
& rType
)
87 signatureInfor
.vSignatureReferenceInfors
.push_back(
88 SignatureReferenceInformation(type
, digestID
, uri
, rType
));
89 vKeeperIds
.push_back( keeperId
);
93 class XSecController final
: public cppu::WeakImplHelper
95 css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener
,
96 css::xml::crypto::sax::XSignatureCreationResultListener
,
97 css::xml::crypto::sax::XSignatureVerifyResultListener
99 /****** XSecController.hxx/CLASS XSecController *******************************
102 * XSecController -- the xml security framework controller
105 * Controls the whole xml security framework to create signatures or to
108 ******************************************************************************/
110 friend class XSecParser
;
111 friend class OOXMLSecParser
;
114 css::uno::Reference
< css::uno::XComponentContext
> mxCtx
;
117 * used to buffer SAX events
119 rtl::Reference
<XMLDocumentWrapper_XmlSecImpl
> m_xXMLDocumentWrapper
;
122 * the SAX events keeper
124 rtl::Reference
<SAXEventKeeperImpl
> m_xSAXEventKeeper
;
127 * the bridge component which creates/verifies signature
129 css::uno::Reference
< css::xml::crypto::XXMLSignature
> m_xXMLSignature
;
132 * the Security Context
134 css::uno::Reference
< css::xml::crypto::XXMLSecurityContext
> m_xSecurityContext
;
137 * the security id incrementer, in order to make any security id unique
138 * to the SAXEventKeeper.
139 * Because each XSecController has its own SAXEventKeeper, so this variable
140 * is not necessary to be static.
142 sal_Int32 m_nNextSecurityId
;
145 * Signature information
147 std::vector
< InternalSignatureInformation
> m_vInternalSignatureInformations
;
150 * the previous node on the SAX chain.
151 * The reason that use a Reference<XInterface> type variable
152 * is that the previous components are different when exporting
153 * and importing, and there is no other common interface they
156 css::uno::Reference
< css::uno::XInterface
> m_xPreviousNodeOnSAXChain
;
158 * whether the previous node can provide an XInitialize interface,
159 * use this variable in order to typecast the XInterface to the
160 * correct interface type.
162 bool m_bIsPreviousNodeInitializable
;
165 * a flag representing whether the SAXEventKeeper is now on the
168 bool m_bIsSAXEventKeeperConnected
;
171 * a flag representing whether it is collecting some element,
172 * which means that the SAXEventKeeper can't be chained off the
175 bool m_bIsCollectingElement
;
178 * a flag representing whether the SAX event stream is blocking,
179 * which also means that the SAXEventKeeper can't be chained off
185 * a flag representing the current status of security related
190 * status of security related components
192 enum class InitializationState
{ UNINITIALIZED
, INITIALIZED
, FAILTOINITIALIZED
} m_eStatusOfSecurityComponents
;
195 * a flag representing whether the SAXEventKeeper need to be
196 * on the SAX chain all the time.
197 * This flag is used to the situation when creating signature.
199 bool m_bIsSAXEventKeeperSticky
;
202 * the XSecParser which is used to parse the signature stream
204 css::uno::Reference
<css::xml::sax::XDocumentHandler
> m_xSecParser
;
207 * the caller assigned signature id for the next signature in the
210 sal_Int32 m_nReservedSignatureId
;
213 * representing whether to verify the current signature
215 bool m_bVerifyCurrentSignature
;
218 * An xUriBinding is provided to map Uris to XInputStream interfaces.
220 rtl::Reference
<UriBindingHelper
> m_xUriBinding
;
227 void createXSecComponent( );
228 int findSignatureInfor( sal_Int32 nSecurityId
) const;
231 void checkChainingStatus();
232 void initializeSAXChain();
234 css::uno::Reference
< css::io::XInputStream
> getObjectInputStream( const OUString
& objectURL
);
236 //sal_Int32 getFastPropertyIndex(sal_Int32 nHandle) const;
239 * For signature generation
241 static OUString
createId();
242 css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
> prepareSignatureToWrite(
243 InternalSignatureInformation
& signatureInfo
,
244 sal_Int32 nStorageFormat
,
245 bool bXAdESCompliantIfODF
);
248 * For signature verification
251 /// Sets algorithm from <SignatureMethod Algorithm="...">.
252 void setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID
);
253 void switchGpgSignature();
254 bool haveReferenceForId(std::u16string_view rId
) const;
256 const OUString
& ouUri
,
258 const OUString
& ouType
);
259 void addStreamReference(
260 const OUString
& ouUri
,
262 sal_Int32 nDigestID
);
263 void setReferenceCount() const;
266 std::vector
<std::pair
<OUString
, OUString
>> & rX509IssuerSerials
,
267 std::vector
<OUString
> const& rX509Certificates
);
268 void setX509CertDigest(
269 OUString
const& rCertDigest
, sal_Int32
const nReferenceDigestID
,
270 std::u16string_view
const& rX509IssuerName
, std::u16string_view
const& rX509SerialNumber
);
272 void setSignatureValue( OUString
const & ouSignatureValue
);
273 void setDigestValue( sal_Int32 nDigestID
, OUString
const & ouDigestValue
);
274 void setGpgKeyID( OUString
const & ouKeyID
);
275 void setGpgCertificate( OUString
const & ouGpgCert
);
276 void setGpgOwner( OUString
const & ouGpgOwner
);
278 void setDate(OUString
const& rId
, OUString
const& ouDate
);
279 void setDescription(OUString
const& rId
, OUString
const& rDescription
);
280 void setValidSignatureImage(std::u16string_view rValidSigImg
);
281 void setInvalidSignatureImage(std::u16string_view rInvalidSigImg
);
282 void setSignatureLineId(const OUString
& rSignatureLineId
);
285 void setSignatureBytes(const css::uno::Sequence
<sal_Int8
>& rBytes
);
288 void setId( OUString
const & ouId
);
290 css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
> prepareSignatureToRead(
291 sal_Int32 nSecurityId
);
294 explicit XSecController(css::uno::Reference
<css::uno::XComponentContext
> xCtx
);
295 virtual ~XSecController() override
;
297 sal_Int32
getNewSecurityId( );
299 void startMission(const rtl::Reference
<UriBindingHelper
>& xUriBinding
, const css::uno::Reference
<css::xml::crypto::XXMLSecurityContext
>& xSecurityContext
);
301 void setSAXChainConnector(const css::uno::Reference
< css::lang::XInitialization
>& xInitialization
);
303 void clearSAXChainConnector();
306 SignatureInformation
getSignatureInformation( sal_Int32 nSecurityId
) const;
307 SignatureInformations
getSignatureInformations() const;
308 /// only verify can figure out which X509Data is the signing certificate
309 void UpdateSignatureInformation(sal_Int32 nSecurityId
,
310 std::vector
<SignatureInformation::X509Data
> && rDatas
);
312 static void exportSignature(
313 const css::uno::Reference
< css::xml::sax::XDocumentHandler
>& xDocumentHandler
,
314 const SignatureInformation
& signatureInfo
,
315 bool bXAdESCompliantIfODF
);
319 * For signature generation
321 void signAStream( sal_Int32 securityId
, const OUString
& uri
, bool isBinary
, bool bXAdESCompliantIfODF
);
324 /** sets data that describes the certificate.
326 It is absolutely necessary that the parameter ouX509IssuerName is set. It contains
327 the base64 encoded certificate, which is DER encoded. The XMLSec needs it to find
328 the private key. Although issuer name and certificate should be sufficient to identify
329 the certificate the implementation in XMLSec is broken, both for Windows and mozilla.
330 The reason is that they use functions to find the certificate which take as parameter
331 the DER encoded ASN.1 issuer name. The issuer name is a DName, where most attributes
332 are of type DirectoryName, which is a choice of 5 string types. This information is
333 not contained in the issuer string and while it is converted to the ASN.1 name the
334 conversion function must assume a particular type, which is often wrong. For example,
335 the Windows function CertStrToName will use a T.61 string if the string does not contain
336 special characters. So if the certificate uses simple characters but encodes the
337 issuer attributes in Utf8, then CertStrToName will use T.61. The resulting DER encoded
338 ASN.1 name now contains different bytes which indicate the string type. The functions
339 for finding the certificate apparently use memcmp - hence they fail to find the
342 void setX509Certificate(
343 sal_Int32 nSecurityId
,
344 const OUString
& ouX509IssuerName
,
345 const OUString
& ouX509SerialNumber
,
346 const OUString
& ouX509Cert
,
347 const OUString
& ouX509CertDigest
,
348 svl::crypto::SignatureMethodAlgorithm eAlgorithmID
);
350 void addEncapsulatedX509Certificate(const OUString
& rEncapsulatedX509Certificate
);
352 void setGpgCertificate(
353 sal_Int32 nSecurityId
,
354 const OUString
& ouCertDigest
,
355 const OUString
& ouCert
,
356 const OUString
& ouOwner
);
359 sal_Int32 nSecurityId
,
360 const css::util::DateTime
& rDateTime
);
361 void setDescription(sal_Int32 nSecurityId
, const OUString
& rDescription
);
362 void setSignatureLineId(sal_Int32 nSecurityId
, const OUString
& rSignatureLineId
);
364 setSignatureLineValidGraphic(sal_Int32 nSecurityId
,
365 const css::uno::Reference
<css::graphic::XGraphic
>& xValidGraphic
);
366 void setSignatureLineInvalidGraphic(
367 sal_Int32 nSecurityId
, const css::uno::Reference
<css::graphic::XGraphic
>& xInvalidGraphic
);
370 const css::uno::Reference
< css::xml::sax::XDocumentHandler
>& xDocumentHandler
,
371 bool bXAdESCompliantIfODF
);
374 * For signature verification
376 void collectToVerify( std::u16string_view referenceId
);
377 void addSignature( sal_Int32 nSignatureId
);
378 css::uno::Reference
< css::xml::sax::XDocumentHandler
> const & createSignatureReader(XMLSignatureHelper
& rXMLSignatureHelper
, sal_Int32 nType
= 0);
379 void releaseSignatureReader();
382 /* Interface methods */
385 * XSAXEventKeeperStatusChangeListener
387 virtual void SAL_CALL
blockingStatusChanged( sal_Bool isBlocking
) override
;
388 virtual void SAL_CALL
collectionStatusChanged(
389 sal_Bool isInsideCollectedElement
) override
;
390 virtual void SAL_CALL
bufferStatusChanged( sal_Bool isBufferEmpty
) override
;
393 * XSignatureCreationResultListener
395 virtual void SAL_CALL
signatureCreated( sal_Int32 securityId
, css::xml::crypto::SecurityOperationStatus nResult
) override
;
398 * XSignatureVerifyResultListener
400 virtual void SAL_CALL
signatureVerified( sal_Int32 securityId
, css::xml::crypto::SecurityOperationStatus nResult
) override
;
402 /// Writes XML elements inside a single OOXML signature's <Signature> element.
403 bool WriteOOXMLSignature(const css::uno::Reference
<css::embed::XStorage
>& xRootStorage
, const css::uno::Reference
<css::xml::sax::XDocumentHandler
>& xDocumentHandler
);
404 /// Exports an OOXML signature, called by WriteOOXMLSignature().
405 void exportOOXMLSignature(const css::uno::Reference
<css::embed::XStorage
>& xRootStorage
, const css::uno::Reference
<css::xml::sax::XDocumentHandler
>& xDocumentHandler
, const SignatureInformation
& rInformation
);
408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */