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 .
21 #include <xsecctl.hxx>
22 #include <certificate.hxx>
24 #include <com/sun/star/graphic/XGraphic.hpp>
25 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
26 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
27 #include <com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp>
28 #include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
29 #include <com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp>
30 #include <com/sun/star/io/XActiveDataSource.hpp>
31 #include <com/sun/star/embed/StorageFormats.hpp>
34 #include <framework/signaturecreatorimpl.hxx>
35 #include <framework/saxeventkeeperimpl.hxx>
38 using namespace css::uno
;
39 using namespace css::graphic
;
40 namespace cssu
= com::sun::star::uno
;
41 namespace cssl
= com::sun::star::lang
;
42 namespace cssxc
= com::sun::star::xml::crypto
;
43 namespace cssxs
= com::sun::star::xml::sax
;
45 /* protected: for signature generation */
46 OUString
XSecController::createId()
49 rtl_createUuid( aSeq
, nullptr, true );
53 for (sal_uInt8 i
: aSeq
)
55 length
+= sprintf(str
+length
, "%04x", i
);
58 return OUString::createFromAscii(str
);
61 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> XSecController::prepareSignatureToWrite(
62 InternalSignatureInformation
& internalSignatureInfor
,
63 sal_Int32 nStorageFormat
,
64 bool bXAdESCompliantIfODF
)
66 sal_Int32 nSecurityId
= internalSignatureInfor
.signatureInfor
.nSecurityId
;
67 SignatureReferenceInformations
& vReferenceInfors
= internalSignatureInfor
.signatureInfor
.vSignatureReferenceInfors
;
69 sal_Int32 nIdOfSignatureElementCollector
;
71 nIdOfSignatureElementCollector
=
72 m_xSAXEventKeeper
->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_AFTERMODIFY
, true );
74 m_xSAXEventKeeper
->setSecurityId(nIdOfSignatureElementCollector
, nSecurityId
);
76 rtl::Reference
<SignatureCreatorImpl
> xSignatureCreator(new SignatureCreatorImpl
);
78 cssu::Sequence
<cssu::Any
> args(5);
79 args
[0] <<= OUString::number(nSecurityId
);
80 args
[1] <<= uno::Reference
<xml::crypto::sax::XSecuritySAXEventKeeper
>(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), uno::UNO_QUERY
);
81 args
[2] <<= OUString::number(nIdOfSignatureElementCollector
);
83 //for nss, the internal module is used for signing, which needs to be improved later
84 args
[3] <<= m_xSecurityContext
->getSecurityEnvironment();
86 args
[4] <<= m_xXMLSignature
;
87 xSignatureCreator
->initialize(args
);
89 sal_Int32 nBlockerId
= m_xSAXEventKeeper
->addBlocker();
90 m_xSAXEventKeeper
->setSecurityId(nBlockerId
, nSecurityId
);
92 xSignatureCreator
->setBlockerId(nBlockerId
);
94 xSignatureCreator
->addSignatureCreationResultListener(this);
96 m_xSAXEventKeeper
->addReferenceResolvedListener(nIdOfSignatureElementCollector
, xSignatureCreator
.get());
98 int size
= vReferenceInfors
.size();
99 sal_Int32 nReferenceCount
= 0;
101 for(int i
=0; i
<size
; ++i
)
103 sal_Int32 keeperId
= internalSignatureInfor
.vKeeperIds
[i
];
107 m_xSAXEventKeeper
->setSecurityId(keeperId
, nSecurityId
);
108 m_xSAXEventKeeper
->addReferenceResolvedListener( keeperId
, xSignatureCreator
.get());
109 xSignatureCreator
->setReferenceId( keeperId
);
114 xSignatureCreator
->setReferenceCount( nReferenceCount
);
117 * adds all URI binding
119 for(int i
=0; i
<size
; ++i
)
121 const SignatureReferenceInformation
& refInfor
= vReferenceInfors
[i
];
123 cssu::Reference
< css::io::XInputStream
> xInputStream
124 = getObjectInputStream( refInfor
.ouURI
);
126 if (xInputStream
.is())
127 xSignatureCreator
->setUriBinding(refInfor
.ouURI
,xInputStream
);
130 xSignatureCreator
->setKeyId(0);
132 // use sha512 for gpg signing unconditionally
133 const sal_Int32 digestID
= !internalSignatureInfor
.signatureInfor
.ouGpgCertificate
.isEmpty()?
134 cssxc::DigestID::SHA512
: (bXAdESCompliantIfODF
? cssxc::DigestID::SHA256
: cssxc::DigestID::SHA1
);
136 if (nStorageFormat
!= embed::StorageFormats::OFOPXML
)
138 internalSignatureInfor
.signatureInfor
.ouSignatureId
= createId();
139 internalSignatureInfor
.signatureInfor
.ouPropertyId
= createId();
140 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, internalSignatureInfor
.signatureInfor
.ouPropertyId
, -1 );
143 if (bXAdESCompliantIfODF
)
145 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idSignedProperties", -1);
149 if (!internalSignatureInfor
.signatureInfor
.ouDescription
.isEmpty())
151 // Only mention the hash of the description in the signature if it's non-empty.
152 internalSignatureInfor
.signatureInfor
.ouDescriptionPropertyId
= createId();
153 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, internalSignatureInfor
.signatureInfor
.ouDescriptionPropertyId
, -1);
159 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idPackageObject", -1);
161 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idOfficeObject", -1);
163 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idSignedProperties", -1);
168 * replace both digestValues and signatureValue to " "
170 for(int i
=0; i
<size
; ++i
)
172 SignatureReferenceInformation
& refInfor
= vReferenceInfors
[i
];
173 refInfor
.ouDigestValue
= " ";
176 internalSignatureInfor
.signatureInfor
.ouSignatureValue
= " ";
178 return xSignatureCreator
.get();
181 void XSecController::signAStream( sal_Int32 securityId
, const OUString
& uri
, bool isBinary
, bool bXAdESCompliantIfODF
)
183 const SignatureReferenceType type
= isBinary
? SignatureReferenceType::BINARYSTREAM
: SignatureReferenceType::XMLSTREAM
;
184 sal_Int32 digestID
= bXAdESCompliantIfODF
? cssxc::DigestID::SHA256
: cssxc::DigestID::SHA1
;
186 int index
= findSignatureInfor( securityId
);
190 InternalSignatureInformation
isi(securityId
, nullptr);
191 isi
.addReference(type
, digestID
, uri
, -1);
192 m_vInternalSignatureInformations
.push_back( isi
);
196 // use sha512 for gpg signing unconditionally
197 if (!m_vInternalSignatureInformations
[index
].signatureInfor
.ouGpgCertificate
.isEmpty())
198 digestID
= cssxc::DigestID::SHA512
;
199 m_vInternalSignatureInformations
[index
].addReference(type
, digestID
, uri
, -1);
203 void XSecController::setX509Certificate(
204 sal_Int32 nSecurityId
,
205 const OUString
& ouX509IssuerName
,
206 const OUString
& ouX509SerialNumber
,
207 const OUString
& ouX509Cert
,
208 const OUString
& ouX509CertDigest
,
209 svl::crypto::SignatureMethodAlgorithm eAlgorithmID
)
211 int index
= findSignatureInfor( nSecurityId
);
215 InternalSignatureInformation
isi(nSecurityId
, nullptr);
216 isi
.signatureInfor
.ouX509IssuerName
= ouX509IssuerName
;
217 isi
.signatureInfor
.ouX509SerialNumber
= ouX509SerialNumber
;
218 isi
.signatureInfor
.ouX509Certificate
= ouX509Cert
;
219 isi
.signatureInfor
.ouCertDigest
= ouX509CertDigest
;
220 isi
.signatureInfor
.eAlgorithmID
= eAlgorithmID
;
221 m_vInternalSignatureInformations
.push_back( isi
);
225 SignatureInformation
&si
226 = m_vInternalSignatureInformations
[index
].signatureInfor
;
227 si
.ouX509IssuerName
= ouX509IssuerName
;
228 si
.ouX509SerialNumber
= ouX509SerialNumber
;
229 si
.ouX509Certificate
= ouX509Cert
;
230 si
.ouCertDigest
= ouX509CertDigest
;
234 void XSecController::setGpgCertificate(
235 sal_Int32 nSecurityId
,
236 const OUString
& ouCertDigest
,
237 const OUString
& ouCert
,
238 const OUString
& ouOwner
)
240 int index
= findSignatureInfor( nSecurityId
);
244 InternalSignatureInformation
isi(nSecurityId
, nullptr);
245 isi
.signatureInfor
.ouGpgCertificate
= ouCert
;
246 isi
.signatureInfor
.ouGpgOwner
= ouOwner
;
247 isi
.signatureInfor
.ouCertDigest
= ouCertDigest
;
248 m_vInternalSignatureInformations
.push_back( isi
);
252 SignatureInformation
&si
253 = m_vInternalSignatureInformations
[index
].signatureInfor
;
254 si
.ouGpgCertificate
= ouCert
;
255 si
.ouGpgOwner
= ouOwner
;
256 si
.ouCertDigest
= ouCertDigest
;
260 void XSecController::setDate(
261 sal_Int32 nSecurityId
,
262 const css::util::DateTime
& rDateTime
)
264 int index
= findSignatureInfor( nSecurityId
);
268 InternalSignatureInformation
isi(nSecurityId
, nullptr);
269 isi
.signatureInfor
.stDateTime
= rDateTime
;
270 m_vInternalSignatureInformations
.push_back( isi
);
274 SignatureInformation
&si
275 = m_vInternalSignatureInformations
[index
].signatureInfor
;
276 si
.stDateTime
= rDateTime
;
280 void XSecController::setDescription(sal_Int32 nSecurityId
, const OUString
& rDescription
)
282 int nIndex
= findSignatureInfor(nSecurityId
);
286 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
287 aInformation
.signatureInfor
.ouDescription
= rDescription
;
288 m_vInternalSignatureInformations
.push_back(aInformation
);
292 SignatureInformation
& rInformation
= m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
293 rInformation
.ouDescription
= rDescription
;
297 void XSecController::setSignatureLineId(sal_Int32 nSecurityId
, const OUString
& rSignatureLineId
)
299 int nIndex
= findSignatureInfor(nSecurityId
);
303 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
304 aInformation
.signatureInfor
.ouSignatureLineId
= rSignatureLineId
;
305 m_vInternalSignatureInformations
.push_back(aInformation
);
309 SignatureInformation
& rInformation
= m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
310 rInformation
.ouSignatureLineId
= rSignatureLineId
;
314 void XSecController::setSignatureLineValidGraphic(sal_Int32 nSecurityId
,
315 const Reference
<XGraphic
>& xValidGraphic
)
317 int nIndex
= findSignatureInfor(nSecurityId
);
321 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
322 aInformation
.signatureInfor
.aValidSignatureImage
= xValidGraphic
;
323 m_vInternalSignatureInformations
.push_back(aInformation
);
327 SignatureInformation
& rInformation
328 = m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
329 rInformation
.aValidSignatureImage
= xValidGraphic
;
333 void XSecController::setSignatureLineInvalidGraphic(
334 sal_Int32 nSecurityId
, const Reference
<XGraphic
>& xInvalidGraphic
)
336 int nIndex
= findSignatureInfor(nSecurityId
);
340 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
341 aInformation
.signatureInfor
.aInvalidSignatureImage
= xInvalidGraphic
;
342 m_vInternalSignatureInformations
.push_back(aInformation
);
346 SignatureInformation
& rInformation
347 = m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
348 rInformation
.aInvalidSignatureImage
= xInvalidGraphic
;
352 bool XSecController::WriteSignature(
353 const cssu::Reference
<cssxs::XDocumentHandler
>& xDocumentHandler
,
354 bool bXAdESCompliantIfODF
)
358 SAL_WARN_IF( !xDocumentHandler
.is(), "xmlsecurity.helper", "I really need a document handler!" );
361 * chain the SAXEventKeeper to the SAX chain
365 if ( m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
367 * if all security components are ready, add the signature
371 m_bIsSAXEventKeeperSticky
= true;
372 m_xSAXEventKeeper
->setNextHandler(xDocumentHandler
);
377 * export the signature template
379 cssu::Reference
<cssxs::XDocumentHandler
> xSEKHandler(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()),cssu::UNO_QUERY
);
382 int sigNum
= m_vInternalSignatureInformations
.size();
384 for (i
=0; i
<sigNum
; ++i
)
386 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
[i
];
388 // Prepare the signature creator.
389 // 0 is not a documented value of embed::StorageFormats, ugh
390 isi
.xReferenceResolvedListener
= prepareSignatureToWrite( isi
, 0, bXAdESCompliantIfODF
);
392 exportSignature( xSEKHandler
, isi
.signatureInfor
, bXAdESCompliantIfODF
);
395 m_bIsSAXEventKeeperSticky
= false;
400 catch( cssu::Exception
& )
404 m_xSAXEventKeeper
->setNextHandler( nullptr );
405 m_bIsSAXEventKeeperSticky
= false;
411 bool XSecController::WriteOOXMLSignature(const uno::Reference
<embed::XStorage
>& xRootStorage
, const uno::Reference
<xml::sax::XDocumentHandler
>& xDocumentHandler
)
415 SAL_WARN_IF(!xDocumentHandler
.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
417 // Chain the SAXEventKeeper to the SAX chain.
420 if (m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
422 m_bIsSAXEventKeeperSticky
= true;
423 m_xSAXEventKeeper
->setNextHandler(xDocumentHandler
);
427 // Export the signature template.
428 cssu::Reference
<xml::sax::XDocumentHandler
> xSEKHandler(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), uno::UNO_QUERY
);
430 for (InternalSignatureInformation
& rInformation
: m_vInternalSignatureInformations
)
432 // Prepare the signature creator.
433 rInformation
.xReferenceResolvedListener
= prepareSignatureToWrite(rInformation
, embed::StorageFormats::OFOPXML
, false);
435 exportOOXMLSignature(xRootStorage
, xSEKHandler
, rInformation
.signatureInfor
);
438 m_bIsSAXEventKeeperSticky
= false;
443 catch(const uno::Exception
&)
447 m_xSAXEventKeeper
->setNextHandler(nullptr);
448 m_bIsSAXEventKeeperSticky
= false;
454 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */