Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / xmlsecurity / source / helper / xsecsign.cxx
blobb4c050e3b7a27fe105d4ed10bc4dd9afe66cb3c4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
32 #include <rtl/uuid.h>
34 #include <framework/signaturecreatorimpl.hxx>
35 #include <framework/saxeventkeeperimpl.hxx>
37 using namespace css;
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()
48 sal_uInt8 aSeq[16];
49 rtl_createUuid( aSeq, nullptr, true );
51 char str[68]="ID_";
52 int length = 3;
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];
105 if ( keeperId != -1)
107 m_xSAXEventKeeper->setSecurityId(keeperId, nSecurityId);
108 m_xSAXEventKeeper->addReferenceResolvedListener( keeperId, xSignatureCreator.get());
109 xSignatureCreator->setReferenceId( keeperId );
110 nReferenceCount++;
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 );
141 size++;
143 if (bXAdESCompliantIfODF)
145 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -1);
146 size++;
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);
154 size++;
157 else
159 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject", -1);
160 size++;
161 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject", -1);
162 size++;
163 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -1);
164 size++;
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 );
188 if (index == -1)
190 InternalSignatureInformation isi(securityId, nullptr);
191 isi.addReference(type, digestID, uri, -1);
192 m_vInternalSignatureInformations.push_back( isi );
194 else
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 );
213 if ( index == -1 )
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 );
223 else
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 );
242 if ( index == -1 )
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 );
250 else
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 );
266 if ( index == -1 )
268 InternalSignatureInformation isi(nSecurityId, nullptr);
269 isi.signatureInfor.stDateTime = rDateTime;
270 m_vInternalSignatureInformations.push_back( isi );
272 else
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);
284 if (nIndex == -1)
286 InternalSignatureInformation aInformation(nSecurityId, nullptr);
287 aInformation.signatureInfor.ouDescription = rDescription;
288 m_vInternalSignatureInformations.push_back(aInformation);
290 else
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);
301 if (nIndex == -1)
303 InternalSignatureInformation aInformation(nSecurityId, nullptr);
304 aInformation.signatureInfor.ouSignatureLineId = rSignatureLineId;
305 m_vInternalSignatureInformations.push_back(aInformation);
307 else
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);
319 if (nIndex == -1)
321 InternalSignatureInformation aInformation(nSecurityId, nullptr);
322 aInformation.signatureInfor.aValidSignatureImage = xValidGraphic;
323 m_vInternalSignatureInformations.push_back(aInformation);
325 else
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);
338 if (nIndex == -1)
340 InternalSignatureInformation aInformation(nSecurityId, nullptr);
341 aInformation.signatureInfor.aInvalidSignatureImage = xInvalidGraphic;
342 m_vInternalSignatureInformations.push_back(aInformation);
344 else
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 )
356 bool rc = false;
358 SAL_WARN_IF( !xDocumentHandler.is(), "xmlsecurity.helper", "I really need a document handler!" );
361 * chain the SAXEventKeeper to the SAX chain
363 chainOn();
365 if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
367 * if all security components are ready, add the signature
368 * stream.
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);
381 int i;
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;
396 chainOff();
398 rc = true;
400 catch( cssu::Exception& )
404 m_xSAXEventKeeper->setNextHandler( nullptr );
405 m_bIsSAXEventKeeperSticky = false;
408 return rc;
411 bool XSecController::WriteOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler)
413 bool bRet = false;
415 SAL_WARN_IF(!xDocumentHandler.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
417 // Chain the SAXEventKeeper to the SAX chain.
418 chainOn();
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;
439 chainOff();
441 bRet = true;
443 catch(const uno::Exception&)
447 m_xSAXEventKeeper->setNextHandler(nullptr);
448 m_bIsSAXEventKeeperSticky = false;
451 return bRet;
454 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */