Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / xmlsecurity / source / helper / xsecsign.cxx
blob4d1b89949feb2d102f65e2b934169cbbd3254764
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>
23 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
24 #include <com/sun/star/embed/StorageFormats.hpp>
25 #include <rtl/uuid.h>
26 #include <sal/log.hxx>
28 #include <framework/signaturecreatorimpl.hxx>
29 #include <framework/saxeventkeeperimpl.hxx>
31 namespace com::sun::star::graphic { class XGraphic; }
33 using namespace css;
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()
44 sal_uInt8 aSeq[16];
45 rtl_createUuid( aSeq, nullptr, true );
47 char str[68]="ID_";
48 int length = 3;
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];
101 if ( keeperId != -1)
103 m_xSAXEventKeeper->setSecurityId(keeperId, nSecurityId);
104 m_xSAXEventKeeper->addReferenceResolvedListener( keeperId, xSignatureCreator.get());
105 xSignatureCreator->setReferenceId( keeperId );
106 nReferenceCount++;
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() );
137 size++;
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");
143 size++;
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());
151 size++;
154 else
156 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject", -1, OUString());
157 size++;
158 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject", -1, OUString());
159 size++;
160 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -1, OUString());
161 size++;
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 );
185 if (index == -1)
187 InternalSignatureInformation isi(securityId, nullptr);
188 isi.addReference(type, digestID, uri, -1, OUString());
189 m_vInternalSignatureInformations.push_back( isi );
191 else
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 );
210 if ( index == -1 )
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 );
220 else
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 );
239 if ( index == -1 )
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 );
247 else
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 );
263 if ( index == -1 )
265 InternalSignatureInformation isi(nSecurityId, nullptr);
266 isi.signatureInfor.stDateTime = rDateTime;
267 m_vInternalSignatureInformations.push_back( isi );
269 else
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);
281 if (nIndex == -1)
283 InternalSignatureInformation aInformation(nSecurityId, nullptr);
284 aInformation.signatureInfor.ouDescription = rDescription;
285 m_vInternalSignatureInformations.push_back(aInformation);
287 else
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);
298 if (nIndex == -1)
300 InternalSignatureInformation aInformation(nSecurityId, nullptr);
301 aInformation.signatureInfor.ouSignatureLineId = rSignatureLineId;
302 m_vInternalSignatureInformations.push_back(aInformation);
304 else
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);
316 if (nIndex == -1)
318 InternalSignatureInformation aInformation(nSecurityId, nullptr);
319 aInformation.signatureInfor.aValidSignatureImage = xValidGraphic;
320 m_vInternalSignatureInformations.push_back(aInformation);
322 else
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);
335 if (nIndex == -1)
337 InternalSignatureInformation aInformation(nSecurityId, nullptr);
338 aInformation.signatureInfor.aInvalidSignatureImage = xInvalidGraphic;
339 m_vInternalSignatureInformations.push_back(aInformation);
341 else
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 )
353 bool rc = false;
355 SAL_WARN_IF( !xDocumentHandler.is(), "xmlsecurity.helper", "I really need a document handler!" );
358 * chain the SAXEventKeeper to the SAX chain
360 chainOn();
362 if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
364 * if all security components are ready, add the signature
365 * stream.
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);
378 int i;
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;
393 chainOff();
395 rc = true;
397 catch( cssu::Exception& )
401 m_xSAXEventKeeper->setNextHandler( nullptr );
402 m_bIsSAXEventKeeperSticky = false;
405 return rc;
408 bool XSecController::WriteOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler)
410 bool bRet = false;
412 SAL_WARN_IF(!xDocumentHandler.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
414 // Chain the SAXEventKeeper to the SAX chain.
415 chainOn();
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;
436 chainOff();
438 bRet = true;
440 catch(const uno::Exception&)
444 m_xSAXEventKeeper->setNextHandler(nullptr);
445 m_bIsSAXEventKeeperSticky = false;
448 return bRet;
451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */