nss: upgrade to release 3.73
[LibreOffice.git] / xmlsecurity / source / helper / xsecsign.cxx
blobfd33a320d9bdcf5daf6ce9cc22d40225e4dcd66b
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;
37 /* protected: for signature generation */
38 OUString XSecController::createId()
40 sal_uInt8 aSeq[16];
41 rtl_createUuid( aSeq, nullptr, true );
43 char str[68]="ID_";
44 int length = 3;
45 for (sal_uInt8 i : aSeq)
47 length += sprintf(str+length, "%04x", i);
50 return OUString::createFromAscii(str);
53 css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite(
54 InternalSignatureInformation& internalSignatureInfor,
55 sal_Int32 nStorageFormat,
56 bool bXAdESCompliantIfODF)
58 sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId;
59 SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors;
61 sal_Int32 nIdOfSignatureElementCollector;
63 nIdOfSignatureElementCollector =
64 m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, true );
66 m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId);
68 rtl::Reference<SignatureCreatorImpl> xSignatureCreator(new SignatureCreatorImpl);
70 css::uno::Sequence<css::uno::Any> args(5);
71 args[0] <<= OUString::number(nSecurityId);
72 args[1] <<= uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), uno::UNO_QUERY);
73 args[2] <<= OUString::number(nIdOfSignatureElementCollector);
75 //for nss, the internal module is used for signing, which needs to be improved later
76 args[3] <<= m_xSecurityContext->getSecurityEnvironment();
78 args[4] <<= m_xXMLSignature;
79 xSignatureCreator->initialize(args);
81 sal_Int32 nBlockerId = m_xSAXEventKeeper->addBlocker();
82 m_xSAXEventKeeper->setSecurityId(nBlockerId, nSecurityId);
84 xSignatureCreator->setBlockerId(nBlockerId);
86 xSignatureCreator->addSignatureCreationResultListener(this);
88 m_xSAXEventKeeper->addReferenceResolvedListener(nIdOfSignatureElementCollector, xSignatureCreator.get());
90 int size = vReferenceInfors.size();
91 sal_Int32 nReferenceCount = 0;
93 for(int i=0; i<size; ++i)
95 sal_Int32 keeperId = internalSignatureInfor.vKeeperIds[i];
97 if ( keeperId != -1)
99 m_xSAXEventKeeper->setSecurityId(keeperId, nSecurityId);
100 m_xSAXEventKeeper->addReferenceResolvedListener( keeperId, xSignatureCreator.get());
101 xSignatureCreator->setReferenceId( keeperId );
102 nReferenceCount++;
106 xSignatureCreator->setReferenceCount( nReferenceCount );
109 * adds all URI binding
111 for(int i=0; i<size; ++i)
113 const SignatureReferenceInformation& refInfor = vReferenceInfors[i];
115 css::uno::Reference< css::io::XInputStream > xInputStream
116 = getObjectInputStream( refInfor.ouURI );
118 if (xInputStream.is())
119 xSignatureCreator->setUriBinding(refInfor.ouURI,xInputStream);
122 xSignatureCreator->setKeyId(0);
124 // use sha512 for gpg signing unconditionally
125 const sal_Int32 digestID = !internalSignatureInfor.signatureInfor.ouGpgCertificate.isEmpty()?
126 css::xml::crypto::DigestID::SHA512 : (bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1);
128 if (nStorageFormat != embed::StorageFormats::OFOPXML)
130 internalSignatureInfor.signatureInfor.ouSignatureId = createId();
131 internalSignatureInfor.signatureInfor.ouDateTimePropertyId = createId();
132 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDateTimePropertyId, -1, OUString() );
133 size++;
135 if (bXAdESCompliantIfODF)
137 // We write a new reference, so it's possible to use the correct type URI.
138 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -1, "http://uri.etsi.org/01903#SignedProperties");
139 size++;
142 if (!internalSignatureInfor.signatureInfor.ouDescription.isEmpty())
144 // Only mention the hash of the description in the signature if it's non-empty.
145 internalSignatureInfor.signatureInfor.ouDescriptionPropertyId = createId();
146 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDescriptionPropertyId, -1, OUString());
147 size++;
150 else
152 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject", -1, OUString());
153 size++;
154 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject", -1, OUString());
155 size++;
156 internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -1, OUString());
157 size++;
161 * replace both digestValues and signatureValue to " "
163 for(int i=0; i<size; ++i)
165 SignatureReferenceInformation& refInfor = vReferenceInfors[i];
166 refInfor.ouDigestValue = " ";
169 internalSignatureInfor.signatureInfor.ouSignatureValue = " ";
171 return xSignatureCreator.get();
174 void XSecController::signAStream( sal_Int32 securityId, const OUString& uri, bool isBinary, bool bXAdESCompliantIfODF)
176 const SignatureReferenceType type = isBinary ? SignatureReferenceType::BINARYSTREAM : SignatureReferenceType::XMLSTREAM;
177 sal_Int32 digestID = bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1;
179 int index = findSignatureInfor( securityId );
181 if (index == -1)
183 InternalSignatureInformation isi(securityId, nullptr);
184 isi.addReference(type, digestID, uri, -1, OUString());
185 m_vInternalSignatureInformations.push_back( isi );
187 else
189 // use sha512 for gpg signing unconditionally
190 if (!m_vInternalSignatureInformations[index].signatureInfor.ouGpgCertificate.isEmpty())
191 digestID = css::xml::crypto::DigestID::SHA512;
192 m_vInternalSignatureInformations[index].addReference(type, digestID, uri, -1, OUString());
196 // note: this is called when creating a new signature from scratch
197 void XSecController::setX509Certificate(
198 sal_Int32 nSecurityId,
199 const OUString& ouX509IssuerName,
200 const OUString& ouX509SerialNumber,
201 const OUString& ouX509Cert,
202 const OUString& ouX509CertDigest,
203 svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
205 int index = findSignatureInfor( nSecurityId );
207 if ( index == -1 )
209 InternalSignatureInformation isi(nSecurityId, nullptr);
210 isi.signatureInfor.X509Datas.clear();
211 isi.signatureInfor.X509Datas.emplace_back();
212 isi.signatureInfor.X509Datas.back().emplace_back();
213 isi.signatureInfor.X509Datas.back().back().X509IssuerName = ouX509IssuerName;
214 isi.signatureInfor.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber;
215 isi.signatureInfor.X509Datas.back().back().X509Certificate = ouX509Cert;
216 isi.signatureInfor.X509Datas.back().back().CertDigest = ouX509CertDigest;
217 isi.signatureInfor.eAlgorithmID = eAlgorithmID;
218 m_vInternalSignatureInformations.push_back( isi );
220 else
222 SignatureInformation &si
223 = m_vInternalSignatureInformations[index].signatureInfor;
224 si.X509Datas.clear();
225 si.X509Datas.emplace_back();
226 si.X509Datas.back().emplace_back();
227 si.X509Datas.back().back().X509IssuerName = ouX509IssuerName;
228 si.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber;
229 si.X509Datas.back().back().X509Certificate = ouX509Cert;
230 si.X509Datas.back().back().CertDigest = ouX509CertDigest;
234 void XSecController::setGpgCertificate(
235 sal_Int32 nSecurityId,
236 const OUString& ouKeyDigest,
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.ouGpgKeyID = ouKeyDigest;
248 m_vInternalSignatureInformations.push_back( isi );
250 else
252 SignatureInformation &si
253 = m_vInternalSignatureInformations[index].signatureInfor;
254 si.X509Datas.clear(); // it is a PGP signature now
255 si.ouGpgCertificate = ouCert;
256 si.ouGpgOwner = ouOwner;
257 si.ouGpgKeyID = ouKeyDigest;
261 void XSecController::setDate(
262 sal_Int32 nSecurityId,
263 const css::util::DateTime& rDateTime )
265 int index = findSignatureInfor( nSecurityId );
267 if ( index == -1 )
269 InternalSignatureInformation isi(nSecurityId, nullptr);
270 isi.signatureInfor.stDateTime = rDateTime;
271 m_vInternalSignatureInformations.push_back( isi );
273 else
275 SignatureInformation &si
276 = m_vInternalSignatureInformations[index].signatureInfor;
277 si.stDateTime = rDateTime;
281 void XSecController::setDescription(sal_Int32 nSecurityId, const OUString& rDescription)
283 int nIndex = findSignatureInfor(nSecurityId);
285 if (nIndex == -1)
287 InternalSignatureInformation aInformation(nSecurityId, nullptr);
288 aInformation.signatureInfor.ouDescription = rDescription;
289 m_vInternalSignatureInformations.push_back(aInformation);
291 else
293 SignatureInformation& rInformation = m_vInternalSignatureInformations[nIndex].signatureInfor;
294 rInformation.ouDescription = rDescription;
298 void XSecController::setSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId)
300 int nIndex = findSignatureInfor(nSecurityId);
302 if (nIndex == -1)
304 InternalSignatureInformation aInformation(nSecurityId, nullptr);
305 aInformation.signatureInfor.ouSignatureLineId = rSignatureLineId;
306 m_vInternalSignatureInformations.push_back(aInformation);
308 else
310 SignatureInformation& rInformation = m_vInternalSignatureInformations[nIndex].signatureInfor;
311 rInformation.ouSignatureLineId = rSignatureLineId;
315 void XSecController::setSignatureLineValidGraphic(sal_Int32 nSecurityId,
316 const Reference<XGraphic>& xValidGraphic)
318 int nIndex = findSignatureInfor(nSecurityId);
320 if (nIndex == -1)
322 InternalSignatureInformation aInformation(nSecurityId, nullptr);
323 aInformation.signatureInfor.aValidSignatureImage = xValidGraphic;
324 m_vInternalSignatureInformations.push_back(aInformation);
326 else
328 SignatureInformation& rInformation
329 = m_vInternalSignatureInformations[nIndex].signatureInfor;
330 rInformation.aValidSignatureImage = xValidGraphic;
334 void XSecController::setSignatureLineInvalidGraphic(
335 sal_Int32 nSecurityId, const Reference<XGraphic>& xInvalidGraphic)
337 int nIndex = findSignatureInfor(nSecurityId);
339 if (nIndex == -1)
341 InternalSignatureInformation aInformation(nSecurityId, nullptr);
342 aInformation.signatureInfor.aInvalidSignatureImage = xInvalidGraphic;
343 m_vInternalSignatureInformations.push_back(aInformation);
345 else
347 SignatureInformation& rInformation
348 = m_vInternalSignatureInformations[nIndex].signatureInfor;
349 rInformation.aInvalidSignatureImage = xInvalidGraphic;
353 bool XSecController::WriteSignature(
354 const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler,
355 bool bXAdESCompliantIfODF )
357 bool rc = false;
359 SAL_WARN_IF( !xDocumentHandler.is(), "xmlsecurity.helper", "I really need a document handler!" );
362 * chain the SAXEventKeeper to the SAX chain
364 chainOn();
366 if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
368 * if all security components are ready, add the signature
369 * stream.
372 m_bIsSAXEventKeeperSticky = true;
373 m_xSAXEventKeeper->setNextHandler(xDocumentHandler);
378 * export the signature template
380 css::uno::Reference<css::xml::sax::XDocumentHandler> xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()),css::uno::UNO_QUERY);
382 int i;
383 int sigNum = m_vInternalSignatureInformations.size();
385 for (i=0; i<sigNum; ++i)
387 InternalSignatureInformation &isi = m_vInternalSignatureInformations[i];
389 // Prepare the signature creator.
390 // 0 is not a documented value of embed::StorageFormats, ugh
391 isi.xReferenceResolvedListener = prepareSignatureToWrite( isi, 0, bXAdESCompliantIfODF );
393 exportSignature( xSEKHandler, isi.signatureInfor, bXAdESCompliantIfODF );
396 m_bIsSAXEventKeeperSticky = false;
397 chainOff();
399 rc = true;
401 catch( css::uno::Exception& )
405 m_xSAXEventKeeper->setNextHandler( nullptr );
406 m_bIsSAXEventKeeperSticky = false;
409 return rc;
412 bool XSecController::WriteOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler)
414 bool bRet = false;
416 SAL_WARN_IF(!xDocumentHandler.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
418 // Chain the SAXEventKeeper to the SAX chain.
419 chainOn();
421 if (m_eStatusOfSecurityComponents == InitializationState::INITIALIZED)
423 m_bIsSAXEventKeeperSticky = true;
424 m_xSAXEventKeeper->setNextHandler(xDocumentHandler);
428 // Export the signature template.
429 css::uno::Reference<xml::sax::XDocumentHandler> xSEKHandler(static_cast<cppu::OWeakObject*>(m_xSAXEventKeeper.get()), uno::UNO_QUERY);
431 for (InternalSignatureInformation & rInformation : m_vInternalSignatureInformations)
433 // Prepare the signature creator.
434 rInformation.xReferenceResolvedListener = prepareSignatureToWrite(rInformation, embed::StorageFormats::OFOPXML, false);
436 exportOOXMLSignature(xRootStorage, xSEKHandler, rInformation.signatureInfor);
439 m_bIsSAXEventKeeperSticky = false;
440 chainOff();
442 bRet = true;
444 catch(const uno::Exception&)
448 m_xSAXEventKeeper->setNextHandler(nullptr);
449 m_bIsSAXEventKeeperSticky = false;
452 return bRet;
455 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */