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/embed/StorageFormats.hpp>
26 #include <sal/log.hxx>
28 #include <framework/signaturecreatorimpl.hxx>
29 #include <framework/saxeventkeeperimpl.hxx>
31 namespace com::sun::star::graphic
{ class XGraphic
; }
34 using namespace css::uno
;
35 using namespace css::graphic
;
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, OUString() );
139 if (bXAdESCompliantIfODF
)
141 // We write a new reference, so it's possible to use the correct type URI.
142 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idSignedProperties", -1, "http://uri.etsi.org/01903#SignedProperties");
146 if (!internalSignatureInfor
.signatureInfor
.ouDescription
.isEmpty())
148 // Only mention the hash of the description in the signature if it's non-empty.
149 internalSignatureInfor
.signatureInfor
.ouDescriptionPropertyId
= createId();
150 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, internalSignatureInfor
.signatureInfor
.ouDescriptionPropertyId
, -1, OUString());
156 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idPackageObject", -1, OUString());
158 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idOfficeObject", -1, OUString());
160 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idSignedProperties", -1, OUString());
165 * replace both digestValues and signatureValue to " "
167 for(int i
=0; i
<size
; ++i
)
169 SignatureReferenceInformation
& refInfor
= vReferenceInfors
[i
];
170 refInfor
.ouDigestValue
= " ";
173 internalSignatureInfor
.signatureInfor
.ouSignatureValue
= " ";
175 return xSignatureCreator
.get();
178 void XSecController::signAStream( sal_Int32 securityId
, const OUString
& uri
, bool isBinary
, bool bXAdESCompliantIfODF
)
180 const SignatureReferenceType type
= isBinary
? SignatureReferenceType::BINARYSTREAM
: SignatureReferenceType::XMLSTREAM
;
181 sal_Int32 digestID
= bXAdESCompliantIfODF
? cssxc::DigestID::SHA256
: cssxc::DigestID::SHA1
;
183 int index
= findSignatureInfor( securityId
);
187 InternalSignatureInformation
isi(securityId
, nullptr);
188 isi
.addReference(type
, digestID
, uri
, -1, OUString());
189 m_vInternalSignatureInformations
.push_back( isi
);
193 // use sha512 for gpg signing unconditionally
194 if (!m_vInternalSignatureInformations
[index
].signatureInfor
.ouGpgCertificate
.isEmpty())
195 digestID
= cssxc::DigestID::SHA512
;
196 m_vInternalSignatureInformations
[index
].addReference(type
, digestID
, uri
, -1, OUString());
200 void XSecController::setX509Certificate(
201 sal_Int32 nSecurityId
,
202 const OUString
& ouX509IssuerName
,
203 const OUString
& ouX509SerialNumber
,
204 const OUString
& ouX509Cert
,
205 const OUString
& ouX509CertDigest
,
206 svl::crypto::SignatureMethodAlgorithm eAlgorithmID
)
208 int index
= findSignatureInfor( nSecurityId
);
212 InternalSignatureInformation
isi(nSecurityId
, nullptr);
213 isi
.signatureInfor
.ouX509IssuerName
= ouX509IssuerName
;
214 isi
.signatureInfor
.ouX509SerialNumber
= ouX509SerialNumber
;
215 isi
.signatureInfor
.ouX509Certificate
= ouX509Cert
;
216 isi
.signatureInfor
.ouCertDigest
= ouX509CertDigest
;
217 isi
.signatureInfor
.eAlgorithmID
= eAlgorithmID
;
218 m_vInternalSignatureInformations
.push_back( isi
);
222 SignatureInformation
&si
223 = m_vInternalSignatureInformations
[index
].signatureInfor
;
224 si
.ouX509IssuerName
= ouX509IssuerName
;
225 si
.ouX509SerialNumber
= ouX509SerialNumber
;
226 si
.ouX509Certificate
= ouX509Cert
;
227 si
.ouCertDigest
= ouX509CertDigest
;
231 void XSecController::setGpgCertificate(
232 sal_Int32 nSecurityId
,
233 const OUString
& ouCertDigest
,
234 const OUString
& ouCert
,
235 const OUString
& ouOwner
)
237 int index
= findSignatureInfor( nSecurityId
);
241 InternalSignatureInformation
isi(nSecurityId
, nullptr);
242 isi
.signatureInfor
.ouGpgCertificate
= ouCert
;
243 isi
.signatureInfor
.ouGpgOwner
= ouOwner
;
244 isi
.signatureInfor
.ouCertDigest
= ouCertDigest
;
245 m_vInternalSignatureInformations
.push_back( isi
);
249 SignatureInformation
&si
250 = m_vInternalSignatureInformations
[index
].signatureInfor
;
251 si
.ouGpgCertificate
= ouCert
;
252 si
.ouGpgOwner
= ouOwner
;
253 si
.ouCertDigest
= ouCertDigest
;
257 void XSecController::setDate(
258 sal_Int32 nSecurityId
,
259 const css::util::DateTime
& rDateTime
)
261 int index
= findSignatureInfor( nSecurityId
);
265 InternalSignatureInformation
isi(nSecurityId
, nullptr);
266 isi
.signatureInfor
.stDateTime
= rDateTime
;
267 m_vInternalSignatureInformations
.push_back( isi
);
271 SignatureInformation
&si
272 = m_vInternalSignatureInformations
[index
].signatureInfor
;
273 si
.stDateTime
= rDateTime
;
277 void XSecController::setDescription(sal_Int32 nSecurityId
, const OUString
& rDescription
)
279 int nIndex
= findSignatureInfor(nSecurityId
);
283 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
284 aInformation
.signatureInfor
.ouDescription
= rDescription
;
285 m_vInternalSignatureInformations
.push_back(aInformation
);
289 SignatureInformation
& rInformation
= m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
290 rInformation
.ouDescription
= rDescription
;
294 void XSecController::setSignatureLineId(sal_Int32 nSecurityId
, const OUString
& rSignatureLineId
)
296 int nIndex
= findSignatureInfor(nSecurityId
);
300 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
301 aInformation
.signatureInfor
.ouSignatureLineId
= rSignatureLineId
;
302 m_vInternalSignatureInformations
.push_back(aInformation
);
306 SignatureInformation
& rInformation
= m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
307 rInformation
.ouSignatureLineId
= rSignatureLineId
;
311 void XSecController::setSignatureLineValidGraphic(sal_Int32 nSecurityId
,
312 const Reference
<XGraphic
>& xValidGraphic
)
314 int nIndex
= findSignatureInfor(nSecurityId
);
318 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
319 aInformation
.signatureInfor
.aValidSignatureImage
= xValidGraphic
;
320 m_vInternalSignatureInformations
.push_back(aInformation
);
324 SignatureInformation
& rInformation
325 = m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
326 rInformation
.aValidSignatureImage
= xValidGraphic
;
330 void XSecController::setSignatureLineInvalidGraphic(
331 sal_Int32 nSecurityId
, const Reference
<XGraphic
>& xInvalidGraphic
)
333 int nIndex
= findSignatureInfor(nSecurityId
);
337 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
338 aInformation
.signatureInfor
.aInvalidSignatureImage
= xInvalidGraphic
;
339 m_vInternalSignatureInformations
.push_back(aInformation
);
343 SignatureInformation
& rInformation
344 = m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
345 rInformation
.aInvalidSignatureImage
= xInvalidGraphic
;
349 bool XSecController::WriteSignature(
350 const cssu::Reference
<cssxs::XDocumentHandler
>& xDocumentHandler
,
351 bool bXAdESCompliantIfODF
)
355 SAL_WARN_IF( !xDocumentHandler
.is(), "xmlsecurity.helper", "I really need a document handler!" );
358 * chain the SAXEventKeeper to the SAX chain
362 if ( m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
364 * if all security components are ready, add the signature
368 m_bIsSAXEventKeeperSticky
= true;
369 m_xSAXEventKeeper
->setNextHandler(xDocumentHandler
);
374 * export the signature template
376 cssu::Reference
<cssxs::XDocumentHandler
> xSEKHandler(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()),cssu::UNO_QUERY
);
379 int sigNum
= m_vInternalSignatureInformations
.size();
381 for (i
=0; i
<sigNum
; ++i
)
383 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
[i
];
385 // Prepare the signature creator.
386 // 0 is not a documented value of embed::StorageFormats, ugh
387 isi
.xReferenceResolvedListener
= prepareSignatureToWrite( isi
, 0, bXAdESCompliantIfODF
);
389 exportSignature( xSEKHandler
, isi
.signatureInfor
, bXAdESCompliantIfODF
);
392 m_bIsSAXEventKeeperSticky
= false;
397 catch( cssu::Exception
& )
401 m_xSAXEventKeeper
->setNextHandler( nullptr );
402 m_bIsSAXEventKeeperSticky
= false;
408 bool XSecController::WriteOOXMLSignature(const uno::Reference
<embed::XStorage
>& xRootStorage
, const uno::Reference
<xml::sax::XDocumentHandler
>& xDocumentHandler
)
412 SAL_WARN_IF(!xDocumentHandler
.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
414 // Chain the SAXEventKeeper to the SAX chain.
417 if (m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
419 m_bIsSAXEventKeeperSticky
= true;
420 m_xSAXEventKeeper
->setNextHandler(xDocumentHandler
);
424 // Export the signature template.
425 cssu::Reference
<xml::sax::XDocumentHandler
> xSEKHandler(static_cast<cppu::OWeakObject
*>(m_xSAXEventKeeper
.get()), uno::UNO_QUERY
);
427 for (InternalSignatureInformation
& rInformation
: m_vInternalSignatureInformations
)
429 // Prepare the signature creator.
430 rInformation
.xReferenceResolvedListener
= prepareSignatureToWrite(rInformation
, embed::StorageFormats::OFOPXML
, false);
432 exportOOXMLSignature(xRootStorage
, xSEKHandler
, rInformation
.signatureInfor
);
435 m_bIsSAXEventKeeperSticky
= false;
440 catch(const uno::Exception
&)
444 m_xSAXEventKeeper
->setNextHandler(nullptr);
445 m_bIsSAXEventKeeperSticky
= false;
451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */