xmlsecurity OOXML export: fix appending new signatures next to existing ones

We append a new signature to a document by re-exporting the existing
ones, then writing the new signature. Given that existing signatures
aren't canonicalized before hashing, write them back as-is.

With this, our own signature verification is happy about the export
result, containing an existing and a newly created signature.

Change-Id: I0ff57a2266c6070a945f0c45ca5793406678be60
This commit is contained in:
Miklos Vajna
2016-03-04 09:40:17 +01:00
parent b9fb9062a9
commit 38c39dc49c
4 changed files with 42 additions and 6 deletions

View File

@@ -23,6 +23,7 @@
#include <rtl/ustring.hxx>
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp>
#include <com/sun/star/uno/Sequence.h>
#include <vector>
@@ -83,6 +84,8 @@ struct SignatureInformation
OUString ouDescriptionPropertyId;
/// OOXML certificate SHA-256 digest, empty for ODF.
OUString ouCertDigest;
/// A full OOXML signguature for unchanged roundtrip, empty for ODF.
css::uno::Sequence<sal_Int8> aSignatureBytes;
SignatureInformation( sal_Int32 nId )
{

View File

@@ -44,6 +44,7 @@
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/StorageFormats.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <tools/date.hxx>
#include <tools/time.hxx>
@@ -207,6 +208,12 @@ void XMLSignatureHelper::ExportOOXMLSignature(uno::Reference<embed::XStorage> xR
{
sal_Int32 nOpenMode = embed::ElementModes::READWRITE;
uno::Reference<io::XOutputStream> xOutputStream(xSignatureStorage->openStreamElement("sig" + OUString::number(nSignatureIndex) + ".xml", nOpenMode), uno::UNO_QUERY);
if (rInformation.aSignatureBytes.hasElements())
// This is a signature roundtrip, just write back the signature as-is.
xOutputStream->writeBytes(rInformation.aSignatureBytes);
else
{
uno::Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(mxCtx);
xSaxWriter->setOutputStream(xOutputStream);
xSaxWriter->startDocument();
@@ -215,6 +222,7 @@ void XMLSignatureHelper::ExportOOXMLSignature(uno::Reference<embed::XStorage> xR
mpXSecController->exportOOXMLSignature(xRootStorage, xDocumentHandler, rInformation);
xSaxWriter->endDocument();
}
}
bool XMLSignatureHelper::CreateAndWriteSignature( const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler )
@@ -403,6 +411,19 @@ bool XMLSignatureHelper::ReadAndVerifySignatureStorage(const uno::Reference<embe
uno::Reference<io::XInputStream> xInputStream(xStorage->openStreamElement(it->Second, nOpenMode), uno::UNO_QUERY);
if (!ReadAndVerifySignatureStorageStream(xInputStream))
return false;
// Store the contents of the stream as is, in case we need to write it back later.
xInputStream.clear();
xInputStream.set(xStorage->openStreamElement(it->Second, nOpenMode), uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xPropertySet(xInputStream, uno::UNO_QUERY);
if (xPropertySet.is())
{
sal_Int64 nSize = 0;
xPropertySet->getPropertyValue("Size") >>= nSize;
uno::Sequence<sal_Int8> aData;
xInputStream->readBytes(aData, nSize);
mpXSecController->setSignatureBytes(aData);
}
}
}
}

View File

@@ -390,7 +390,10 @@ private:
void setDate( OUString& ouDate );
void setDescription(const OUString& rDescription);
void setCertDigest(const OUString& rCertDigest);
public:
void setSignatureBytes(const css::uno::Sequence<sal_Int8>& rBytes);
private:
void setId( OUString& ouId );
void setPropertyId( OUString& ouPropertyId );

View File

@@ -274,6 +274,15 @@ void XSecController::setDescription(const OUString& rDescription)
rInformation.signatureInfor.ouDescription = rDescription;
}
void XSecController::setSignatureBytes(const uno::Sequence<sal_Int8>& rBytes)
{
if (m_vInternalSignatureInformations.empty())
return;
InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
rInformation.signatureInfor.aSignatureBytes = rBytes;
}
void XSecController::setCertDigest(const OUString& rCertDigest)
{
if (m_vInternalSignatureInformations.empty())