Bump version to 6.0-36
[LibreOffice.git] / xmlsecurity / source / helper / xsecsign.cxx
blob701ce84d1989683b301b57d8a639035b82f4c6d0
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/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>
30 #include <rtl/uuid.h>
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()
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 );
137 size++;
139 if (bXAdESCompliantIfODF)
141 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -1);
142 size++;
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);
150 size++;
153 else
155 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject", -1);
156 size++;
157 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject", -1);
158 size++;
159 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -1);
160 size++;
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 );
184 if (index == -1)
186 InternalSignatureInformation isi(securityId, nullptr);
187 isi.addReference(type, digestID, uri, -1);
188 m_vInternalSignatureInformations.push_back( isi );
190 else
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 );
208 if ( index == -1 )
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 );
217 else
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 );
236 if ( index == -1 )
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 );
244 else
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 );
260 if ( index == -1 )
262 InternalSignatureInformation isi(nSecurityId, nullptr);
263 isi.signatureInfor.stDateTime = rDateTime;
264 m_vInternalSignatureInformations.push_back( isi );
266 else
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);
278 if (nIndex == -1)
280 InternalSignatureInformation aInformation(nSecurityId, nullptr);
281 aInformation.signatureInfor.ouDescription = rDescription;
282 m_vInternalSignatureInformations.push_back(aInformation);
284 else
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);
295 if (nIndex == -1)
297 InternalSignatureInformation aInformation(nSecurityId, nullptr);
298 aInformation.signatureInfor.ouSignatureLineId = rSignatureLineId;
299 m_vInternalSignatureInformations.push_back(aInformation);
301 else
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 )
312 bool rc = false;
314 SAL_WARN_IF( !xDocumentHandler.is(), "xmlsecurity.helper", "I really need a document handler!" );
317 * chain the SAXEventKeeper to the SAX chain
319 chainOn();
321 if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
323 * if all security components are ready, add the signature
324 * stream.
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);
337 int i;
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;
352 chainOff();
354 rc = true;
356 catch( cssu::Exception& )
360 m_xSAXEventKeeper->setNextHandler( nullptr );
361 m_bIsSAXEventKeeperSticky = false;
364 return rc;
367 bool XSecController::WriteOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler)
369 bool bRet = false;
371 SAL_WARN_IF(!xDocumentHandler.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
373 // Chain the SAXEventKeeper to the SAX chain.
374 chainOn();
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;
395 chainOff();
397 bRet = true;
399 catch(const uno::Exception&)
403 m_xSAXEventKeeper->setNextHandler(nullptr);
404 m_bIsSAXEventKeeperSticky = false;
407 return bRet;
410 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */