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>
23 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
24 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
25 #include <com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp>
26 #include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
27 #include <com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp>
28 #include <com/sun/star/io/XActiveDataSource.hpp>
29 #include <com/sun/star/embed/StorageFormats.hpp>
32 #include <framework/signaturecreatorimpl.hxx>
33 #include <framework/saxeventkeeperimpl.hxx>
35 using namespace com::sun::star
;
36 namespace cssu
= com::sun::star::uno
;
37 namespace cssl
= com::sun::star::lang
;
38 namespace cssxc
= com::sun::star::xml::crypto
;
39 namespace cssxs
= com::sun::star::xml::sax
;
41 /* protected: for signature generation */
42 OUString
XSecController::createId()
45 rtl_createUuid( aSeq
, nullptr, true );
49 for (sal_uInt8 i
: aSeq
)
51 length
+= sprintf(str
+length
, "%04x", i
);
54 return OUString::createFromAscii(str
);
57 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> XSecController::prepareSignatureToWrite(
58 InternalSignatureInformation
& internalSignatureInfor
,
59 sal_Int32 nStorageFormat
,
60 bool bXAdESCompliantIfODF
)
62 sal_Int32 nSecurityId
= internalSignatureInfor
.signatureInfor
.nSecurityId
;
63 SignatureReferenceInformations
& vReferenceInfors
= internalSignatureInfor
.signatureInfor
.vSignatureReferenceInfors
;
65 sal_Int32 nIdOfSignatureElementCollector
;
67 nIdOfSignatureElementCollector
=
68 m_xSAXEventKeeper
->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_AFTERMODIFY
, true );
70 m_xSAXEventKeeper
->setSecurityId(nIdOfSignatureElementCollector
, nSecurityId
);
72 rtl::Reference
<SignatureCreatorImpl
> xSignatureCreator(new SignatureCreatorImpl
);
74 cssu::Sequence
<cssu::Any
> args(5);
75 args
[0] <<= OUString::number(nSecurityId
);
76 args
[1] <<= uno::Reference
<xml::crypto::sax::XSecuritySAXEventKeeper
>(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), uno::UNO_QUERY
);
77 args
[2] <<= OUString::number(nIdOfSignatureElementCollector
);
79 //for nss, the internal module is used for signing, which needs to be improved later
80 args
[3] <<= m_xSecurityContext
->getSecurityEnvironment();
82 args
[4] <<= m_xXMLSignature
;
83 xSignatureCreator
->initialize(args
);
85 sal_Int32 nBlockerId
= m_xSAXEventKeeper
->addBlocker();
86 m_xSAXEventKeeper
->setSecurityId(nBlockerId
, nSecurityId
);
88 xSignatureCreator
->setBlockerId(nBlockerId
);
90 xSignatureCreator
->addSignatureCreationResultListener(this);
92 m_xSAXEventKeeper
->addReferenceResolvedListener(nIdOfSignatureElementCollector
, xSignatureCreator
.get());
94 int size
= vReferenceInfors
.size();
95 sal_Int32 nReferenceCount
= 0;
97 for(int i
=0; i
<size
; ++i
)
99 sal_Int32 keeperId
= internalSignatureInfor
.vKeeperIds
[i
];
103 m_xSAXEventKeeper
->setSecurityId(keeperId
, nSecurityId
);
104 m_xSAXEventKeeper
->addReferenceResolvedListener( keeperId
, xSignatureCreator
.get());
105 xSignatureCreator
->setReferenceId( keeperId
);
110 xSignatureCreator
->setReferenceCount( nReferenceCount
);
113 * adds all URI binding
115 for(int i
=0; i
<size
; ++i
)
117 const SignatureReferenceInformation
& refInfor
= vReferenceInfors
[i
];
119 cssu::Reference
< css::io::XInputStream
> xInputStream
120 = getObjectInputStream( refInfor
.ouURI
);
122 if (xInputStream
.is())
123 xSignatureCreator
->setUriBinding(refInfor
.ouURI
,xInputStream
);
126 xSignatureCreator
->setKeyId(0);
128 // use sha512 for gpg signing unconditionally
129 const sal_Int32 digestID
= !internalSignatureInfor
.signatureInfor
.ouGpgCertificate
.isEmpty()?
130 cssxc::DigestID::SHA512
: (bXAdESCompliantIfODF
? cssxc::DigestID::SHA256
: cssxc::DigestID::SHA1
);
132 if (nStorageFormat
!= embed::StorageFormats::OFOPXML
)
134 internalSignatureInfor
.signatureInfor
.ouSignatureId
= createId();
135 internalSignatureInfor
.signatureInfor
.ouPropertyId
= createId();
136 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, internalSignatureInfor
.signatureInfor
.ouPropertyId
, -1 );
139 if (bXAdESCompliantIfODF
)
141 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idSignedProperties", -1);
145 if (!internalSignatureInfor
.signatureInfor
.ouDescription
.isEmpty())
147 // Only mention the hash of the description in the signature if it's non-empty.
148 internalSignatureInfor
.signatureInfor
.ouDescriptionPropertyId
= createId();
149 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, internalSignatureInfor
.signatureInfor
.ouDescriptionPropertyId
, -1);
155 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idPackageObject", -1);
157 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idOfficeObject", -1);
159 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idSignedProperties", -1);
164 * replace both digestValues and signatureValue to " "
166 for(int i
=0; i
<size
; ++i
)
168 SignatureReferenceInformation
& refInfor
= vReferenceInfors
[i
];
169 refInfor
.ouDigestValue
= " ";
172 internalSignatureInfor
.signatureInfor
.ouSignatureValue
= " ";
174 return xSignatureCreator
.get();
177 void XSecController::signAStream( sal_Int32 securityId
, const OUString
& uri
, bool isBinary
, bool bXAdESCompliantIfODF
)
179 const SignatureReferenceType type
= isBinary
? SignatureReferenceType::BINARYSTREAM
: SignatureReferenceType::XMLSTREAM
;
180 sal_Int32 digestID
= bXAdESCompliantIfODF
? cssxc::DigestID::SHA256
: cssxc::DigestID::SHA1
;
182 int index
= findSignatureInfor( securityId
);
186 InternalSignatureInformation
isi(securityId
, nullptr);
187 isi
.addReference(type
, digestID
, uri
, -1);
188 m_vInternalSignatureInformations
.push_back( isi
);
192 // use sha512 for gpg signing unconditionally
193 if (!m_vInternalSignatureInformations
[index
].signatureInfor
.ouGpgCertificate
.isEmpty())
194 digestID
= cssxc::DigestID::SHA512
;
195 m_vInternalSignatureInformations
[index
].addReference(type
, digestID
, uri
, -1);
199 void XSecController::setX509Certificate(
200 sal_Int32 nSecurityId
,
201 const OUString
& ouX509IssuerName
,
202 const OUString
& ouX509SerialNumber
,
203 const OUString
& ouX509Cert
,
204 const OUString
& ouX509CertDigest
)
206 int index
= findSignatureInfor( nSecurityId
);
210 InternalSignatureInformation
isi(nSecurityId
, nullptr);
211 isi
.signatureInfor
.ouX509IssuerName
= ouX509IssuerName
;
212 isi
.signatureInfor
.ouX509SerialNumber
= ouX509SerialNumber
;
213 isi
.signatureInfor
.ouX509Certificate
= ouX509Cert
;
214 isi
.signatureInfor
.ouCertDigest
= ouX509CertDigest
;
215 m_vInternalSignatureInformations
.push_back( isi
);
219 SignatureInformation
&si
220 = m_vInternalSignatureInformations
[index
].signatureInfor
;
221 si
.ouX509IssuerName
= ouX509IssuerName
;
222 si
.ouX509SerialNumber
= ouX509SerialNumber
;
223 si
.ouX509Certificate
= ouX509Cert
;
224 si
.ouCertDigest
= ouX509CertDigest
;
228 void XSecController::setGpgCertificate(
229 sal_Int32 nSecurityId
,
230 const OUString
& ouCertDigest
,
231 const OUString
& ouCert
,
232 const OUString
& ouOwner
)
234 int index
= findSignatureInfor( nSecurityId
);
238 InternalSignatureInformation
isi(nSecurityId
, nullptr);
239 isi
.signatureInfor
.ouGpgCertificate
= ouCert
;
240 isi
.signatureInfor
.ouGpgOwner
= ouOwner
;
241 isi
.signatureInfor
.ouCertDigest
= ouCertDigest
;
242 m_vInternalSignatureInformations
.push_back( isi
);
246 SignatureInformation
&si
247 = m_vInternalSignatureInformations
[index
].signatureInfor
;
248 si
.ouGpgCertificate
= ouCert
;
249 si
.ouGpgOwner
= ouOwner
;
250 si
.ouCertDigest
= ouCertDigest
;
254 void XSecController::setDate(
255 sal_Int32 nSecurityId
,
256 const css::util::DateTime
& rDateTime
)
258 int index
= findSignatureInfor( nSecurityId
);
262 InternalSignatureInformation
isi(nSecurityId
, nullptr);
263 isi
.signatureInfor
.stDateTime
= rDateTime
;
264 m_vInternalSignatureInformations
.push_back( isi
);
268 SignatureInformation
&si
269 = m_vInternalSignatureInformations
[index
].signatureInfor
;
270 si
.stDateTime
= rDateTime
;
274 void XSecController::setDescription(sal_Int32 nSecurityId
, const OUString
& rDescription
)
276 int nIndex
= findSignatureInfor(nSecurityId
);
280 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
281 aInformation
.signatureInfor
.ouDescription
= rDescription
;
282 m_vInternalSignatureInformations
.push_back(aInformation
);
286 SignatureInformation
& rInformation
= m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
287 rInformation
.ouDescription
= rDescription
;
291 void XSecController::setSignatureLineId(sal_Int32 nSecurityId
, const OUString
& rSignatureLineId
)
293 int nIndex
= findSignatureInfor(nSecurityId
);
297 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
298 aInformation
.signatureInfor
.ouSignatureLineId
= rSignatureLineId
;
299 m_vInternalSignatureInformations
.push_back(aInformation
);
303 SignatureInformation
& rInformation
= m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
304 rInformation
.ouSignatureLineId
= rSignatureLineId
;
308 bool XSecController::WriteSignature(
309 const cssu::Reference
<cssxs::XDocumentHandler
>& xDocumentHandler
,
310 bool bXAdESCompliantIfODF
)
314 SAL_WARN_IF( !xDocumentHandler
.is(), "xmlsecurity.helper", "I really need a document handler!" );
317 * chain the SAXEventKeeper to the SAX chain
321 if ( m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
323 * if all security components are ready, add the signature
327 m_bIsSAXEventKeeperSticky
= true;
328 m_xSAXEventKeeper
->setNextHandler(xDocumentHandler
);
333 * export the signature template
335 cssu::Reference
<cssxs::XDocumentHandler
> xSEKHandler(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()),cssu::UNO_QUERY
);
338 int sigNum
= m_vInternalSignatureInformations
.size();
340 for (i
=0; i
<sigNum
; ++i
)
342 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
[i
];
344 // Prepare the signature creator.
345 // 0 is not a documented value of embed::StorageFormats, ugh
346 isi
.xReferenceResolvedListener
= prepareSignatureToWrite( isi
, 0, bXAdESCompliantIfODF
);
348 exportSignature( xSEKHandler
, isi
.signatureInfor
, bXAdESCompliantIfODF
);
351 m_bIsSAXEventKeeperSticky
= false;
356 catch( cssu::Exception
& )
360 m_xSAXEventKeeper
->setNextHandler( nullptr );
361 m_bIsSAXEventKeeperSticky
= false;
367 bool XSecController::WriteOOXMLSignature(const uno::Reference
<embed::XStorage
>& xRootStorage
, const uno::Reference
<xml::sax::XDocumentHandler
>& xDocumentHandler
)
371 SAL_WARN_IF(!xDocumentHandler
.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
373 // Chain the SAXEventKeeper to the SAX chain.
376 if (m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
378 m_bIsSAXEventKeeperSticky
= true;
379 m_xSAXEventKeeper
->setNextHandler(xDocumentHandler
);
383 // Export the signature template.
384 cssu::Reference
<xml::sax::XDocumentHandler
> xSEKHandler(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), uno::UNO_QUERY
);
386 for (InternalSignatureInformation
& rInformation
: m_vInternalSignatureInformations
)
388 // Prepare the signature creator.
389 rInformation
.xReferenceResolvedListener
= prepareSignatureToWrite(rInformation
, embed::StorageFormats::OFOPXML
, false);
391 exportOOXMLSignature(xRootStorage
, xSEKHandler
, rInformation
.signatureInfor
);
394 m_bIsSAXEventKeeperSticky
= false;
399 catch(const uno::Exception
&)
403 m_xSAXEventKeeper
->setNextHandler(nullptr);
404 m_bIsSAXEventKeeperSticky
= false;
410 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */