Kaydet (Commit) b2318479 authored tarafından Tor Lillqvist's avatar Tor Lillqvist

Work in progress on supporting XAdES-compliant signatures for ODF

xmlsecurity is such a mess. Too many different classes that actually
have more or less identical life-time, with names that smell of
delusions of grandeur. "Manager", "security framework controller" etc
for stuff that actually exist only during the execution of a simple
dialog. And then a "helper" class that actually in on a higher level
than a "framework controller". But oh well.

Change-Id: I86e461b1bc91a0d8f5b7fb9f13a5be201729df1e
üst 29ddf52a
......@@ -70,6 +70,8 @@ private:
VclPtr<FixedImage> m_pSigsOldSignatureImg;
VclPtr<FixedText> m_pSigsOldSignatureFI;
VclPtr<CheckBox> m_pXAdESCompliantCB;
VclPtr<PushButton> m_pViewBtn;
VclPtr<PushButton> m_pAddBtn;
VclPtr<PushButton> m_pRemoveBtn;
......@@ -82,6 +84,9 @@ private:
bool m_bHasDocumentSignature;
bool m_bWarningShowSignMacro;
bool m_bXAdESCompliant;
DECL_LINK(XAdESCompliantCheckBoxHdl, CheckBox&, void);
DECL_LINK(ViewButtonHdl, Button*, void);
DECL_LINK(AddButtonHdl, Button*, void);
DECL_LINK(RemoveButtonHdl, Button*, void);
......@@ -90,7 +95,7 @@ private:
DECL_LINK(StartVerifySignatureHdl, LinkParamNone*, bool );
DECL_LINK(OKButtonHdl, Button*, void );
void ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature = true);
void ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature);
void ImplFillSignaturesBox();
void ImplShowSignaturesDetails();
......
......@@ -57,7 +57,7 @@ public:
bool isXML(const OUString& rURI);
SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 eStreamMode, bool bTempStream);
/// Add a new signature, using xCert as a signing certificate, and rDescription as description.
bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId);
bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bXAdESCompliantIfODF);
/// Remove signature at nPosition.
void remove(sal_uInt16 nPosition);
/// Read signatures from either a temp stream or the real storage.
......@@ -66,6 +66,10 @@ public:
void write();
/// Lazy creation of PDF helper.
PDFSignatureHelper& getPDFSignatureHelper();
#if 0
// Checks if the document is a kind where it is relevant to distinguish between using XAdES or not
bool IsXAdESRelevant();
#endif
};
#endif // INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREMANAGER_HXX
......
......@@ -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/xml/crypto/DigestID.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <vector>
......@@ -41,11 +42,23 @@ struct SignatureReferenceInformation
{
SignatureReferenceType nType;
OUString ouURI;
// For ODF: XAdES digests (SHA256) or the old SHA1, from css::xml::crypto::DigestID
sal_Int32 nDigestID;
OUString ouDigestValue;
SignatureReferenceInformation( SignatureReferenceType type, const OUString& uri )
SignatureReferenceInformation() :
nType(SignatureReferenceType::SAMEDOCUMENT),
ouURI(""),
nDigestID(css::xml::crypto::DigestID::SHA1),
ouDigestValue("")
{
}
SignatureReferenceInformation( SignatureReferenceType type, sal_Int32 digestID, const OUString& uri ) :
SignatureReferenceInformation()
{
nType = type;
nDigestID = digestID;
ouURI = uri;
}
};
......@@ -57,6 +70,8 @@ struct SignatureInformation
sal_Int32 nSecurityId;
sal_Int32 nSecurityEnvironmentIndex;
css::xml::crypto::SecurityOperationStatus nStatus;
// For ODF: XAdES digests (SHA256) or the old SHA1, from css::xml::crypto::DigestID
sal_Int32 nDigestID;
SignatureReferenceInformations vSignatureReferenceInfors;
OUString ouX509IssuerName;
OUString ouX509SerialNumber;
......
......@@ -172,8 +172,8 @@ public:
void SetDateTime( sal_Int32 nSecurityId, const Date& rDate, const tools::Time& rTime );
void SetDescription(sal_Int32 nSecurityId, const OUString& rDescription);
void AddForSigning( sal_Int32 securityId, const OUString& uri, const OUString& objectURL, bool bBinary );
bool CreateAndWriteSignature( const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler );
void AddForSigning( sal_Int32 securityId, const OUString& uri, const OUString& objectURL, bool bBinary, bool bXAdESCompliantIfODF );
bool CreateAndWriteSignature( const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, bool bXAdESCompliantIfODF );
bool ReadAndVerifySignature( const css::uno::Reference< css::io::XInputStream >& xInputStream );
// MT: ??? I think only for adding/removing, not for new signatures...
......
......@@ -202,7 +202,7 @@ void SigningTest::testDescription()
CPPUNIT_ASSERT(xCertificate.is());
OUString aDescription("SigningTest::testDescription");
sal_Int32 nSecurityId;
aManager.add(xCertificate, aDescription, nSecurityId);
aManager.add(xCertificate, aDescription, nSecurityId, false);
// Read back the signature and make sure that the description survives the roundtrip.
aManager.read(/*bUseTempStream=*/true);
......@@ -235,7 +235,7 @@ void SigningTest::testOOXMLDescription()
CPPUNIT_ASSERT(xCertificate.is());
OUString aDescription("SigningTest::testDescription");
sal_Int32 nSecurityId;
aManager.add(xCertificate, aDescription, nSecurityId);
aManager.add(xCertificate, aDescription, nSecurityId, false);
// Read back the signature and make sure that the description survives the roundtrip.
aManager.read(/*bUseTempStream=*/true);
......@@ -267,7 +267,7 @@ void SigningTest::testOOXMLAppend()
uno::Reference<security::XCertificate> xCertificate = getCertificate(aManager.maSignatureHelper);
CPPUNIT_ASSERT(xCertificate.is());
sal_Int32 nSecurityId;
aManager.add(xCertificate, OUString(), nSecurityId);
aManager.add(xCertificate, OUString(), nSecurityId, false);
// Read back the signatures and make sure that we have the expected amount.
aManager.read(/*bUseTempStream=*/true);
......
......@@ -57,6 +57,10 @@ DocumentDigitalSignatures::DocumentDigitalSignatures( const Reference< XComponen
{
}
DocumentDigitalSignatures::~DocumentDigitalSignatures()
{
}
void DocumentDigitalSignatures::initialize( const Sequence< Any >& aArguments)
throw (css::uno::Exception, css::uno::RuntimeException, std::exception)
{
......
......@@ -45,7 +45,9 @@ class DocumentDigitalSignatures : public cppu::WeakImplHelper
{
private:
css::uno::Reference< css::uno::XComponentContext > mxCtx;
// will be set by XInitialization. If not we assume true. false means an earlier version.
// will be set by XInitialization. If not we assume true. false means an earlier version (whatever that means,
// this is a string, not a boolean).
// Note that the code talks about "ODF version" even if this class is also used to sign OOXML.
OUString m_sODFVersion;
//The number of arguments which were passed in XInitialization::initialize
int m_nArgumentsCount;
......@@ -58,6 +60,7 @@ private:
public:
explicit DocumentDigitalSignatures( const css::uno::Reference< css::uno::XComponentContext>& rxCtx );
virtual ~DocumentDigitalSignatures() override;
// for service registration...
static OUString GetImplementationName() throw (css::uno::RuntimeException);
......
......@@ -116,6 +116,7 @@ DigitalSignaturesDialog::DigitalSignaturesDialog(
get(m_pHintDocFT, "dochint");
get(m_pHintBasicFT, "macrohint");
get(m_pHintPackageFT, "packagehint");
get(m_pXAdESCompliantCB, "xadescompliant");
get(m_pViewBtn, "view");
get(m_pAddBtn, "sign");
get(m_pRemoveBtn, "remove");
......@@ -129,6 +130,8 @@ DigitalSignaturesDialog::DigitalSignaturesDialog(
get(m_pSigsOldSignatureImg, "oldsignatureimg");
get(m_pSigsOldSignatureFI, "oldsignatureft");
m_bXAdESCompliant = !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
Size aControlSize(275, 109);
const long nControlWidth = aControlSize.Width();
aControlSize = LogicToPixel(aControlSize, MapUnit::MapAppFont);
......@@ -151,6 +154,9 @@ DigitalSignaturesDialog::DigitalSignaturesDialog(
m_pSignaturesLB->SetSelectHdl( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
m_pSignaturesLB->SetDoubleClickHdl( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
m_pXAdESCompliantCB->SetToggleHdl( LINK( this, DigitalSignaturesDialog, XAdESCompliantCheckBoxHdl ) );
m_pXAdESCompliantCB->Check(m_bXAdESCompliant);
m_pViewBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
m_pViewBtn->Disable();
......@@ -196,6 +202,7 @@ void DigitalSignaturesDialog::dispose()
m_pSigsNotvalidatedFI.clear();
m_pSigsOldSignatureImg.clear();
m_pSigsOldSignatureFI.clear();
m_pXAdESCompliantCB.clear();
m_pViewBtn.clear();
m_pAddBtn.clear();
m_pRemoveBtn.clear();
......@@ -315,9 +322,24 @@ short DigitalSignaturesDialog::Execute()
{
// Verify Signatures and add certificates to ListBox...
mbVerifySignatures = true;
ImplGetSignatureInformations(false);
ImplGetSignatureInformations(/*bUseTempStream=*/false, /*bCacheLastSignature=*/true);
ImplFillSignaturesBox();
// FIXME: Disable the "Use XAdES compliant signatures" checkbox if it is irrelevant. If it is
// enabled, set its initial state based on existing signatures, if any.
// If it is OOXML, the checkbox is irrelevant.
// How to find out here whether it is OOXML? I don't want to create a SignatureStreamHelper and
// check its nStorageFormat as that seems overly complicated and seems to have weird indirect
// consequences, as I noticed when I tried to use DocumentSignatureManager::IsXAdESRelevant()
// (which now is in #if 0).
if (maSignatureManager.maCurrentSignatureInformations.size() > 0)
{
// If the document has only SHA-1 signatures we probably want it to stay that way?
}
// Only verify once, content will not change.
// But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
mbVerifySignatures = false;
......@@ -346,6 +368,11 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl, SvTreeListBox*, boo
return false;
}
IMPL_LINK_NOARG(DigitalSignaturesDialog, XAdESCompliantCheckBoxHdl, CheckBox&, void)
{
m_bXAdESCompliant = m_pXAdESCompliantCB->IsChecked();
}
IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl, Button*, void)
{
ImplShowSignaturesDetails();
......@@ -363,7 +390,7 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, Button*, void)
if ( aChooser->Execute() == RET_OK )
{
sal_Int32 nSecurityId;
if (!maSignatureManager.add(aChooser->GetSelectedCertificate(), aChooser->GetDescription(), nSecurityId))
if (!maSignatureManager.add(aChooser->GetSelectedCertificate(), aChooser->GetDescription(), nSecurityId, m_bXAdESCompliant))
return;
mbSignaturesChanged = true;
......@@ -382,7 +409,7 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, Button*, void)
// will not contain
// SecurityOperationStatus_OPERATION_SUCCEEDED
mbVerifySignatures = true;
ImplGetSignatureInformations(true, /*bCacheLastSignature=*/false);
ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
ImplFillSignaturesBox();
}
}
......@@ -391,7 +418,7 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, Button*, void)
{
OSL_FAIL( "Exception while adding a signature!" );
// Don't keep invalid entries...
ImplGetSignatureInformations(true, /*bCacheLastSignature=*/false);
ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
ImplFillSignaturesBox();
}
}
......@@ -415,7 +442,7 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, Button*, void)
{
OSL_FAIL( "Exception while removing a signature!" );
// Don't keep invalid entries...
ImplGetSignatureInformations(true);
ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true);
ImplFillSignaturesBox();
}
}
......
......@@ -58,6 +58,28 @@ PDFSignatureHelper& DocumentSignatureManager::getPDFSignatureHelper()
return *mpPDFSignatureHelper;
}
#if 0 // For some reason does not work
bool DocumentSignatureManager::IsXAdESRelevant()
{
if (mxStore.is())
{
// ZIP-based: ODF or OOXML.
maSignatureHelper.StartMission();
SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(embed::ElementModes::READ, /*bUseTempStream=*/true);
if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
{
maSignatureHelper.EndMission();
return false;
}
// FIXME: How to figure out if it is ODF 1.2?
maSignatureHelper.EndMission();
return true;
}
return false;
}
#endif
/* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
We use the manifest to find out if a file is xml and if it is encrypted.
The parameter is an encoded uri. However, the manifest contains paths. Therefore
......@@ -193,7 +215,7 @@ SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int3
return aHelper;
}
bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId)
bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bXAdESCompliantIfODF)
{
if (!xCert.is())
{
......@@ -250,7 +272,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
for (sal_Int32 n = 0; n < nElements; n++)
{
bool bBinaryMode = !isXML(aElements[n]);
maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode);
maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode, bXAdESCompliantIfODF);
}
maSignatureHelper.SetDateTime(nSecurityId, Date(Date::SYSTEM), tools::Time(tools::Time::SYSTEM));
......@@ -275,7 +297,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n]);
// Create a new one...
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler);
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bXAdESCompliantIfODF);
// That's it...
XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
......
......@@ -59,7 +59,7 @@ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
{
OUString aURI = xAttribs->getValueByName("URI");
if (aURI.startsWith("#"))
m_pXSecController->addReference(aURI.copy(1));
m_pXSecController->addReference(aURI.copy(1), xml::crypto::DigestID::SHA1);
else
{
m_aReferenceURI = aURI;
......@@ -73,7 +73,7 @@ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
OUString aAlgorithm = xAttribs->getValueByName("Algorithm");
if (aAlgorithm == ALGO_RELATIONSHIP)
{
m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/false);
m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/false, /*nDigestID=*/xml::crypto::DigestID::SHA256);
m_bReferenceUnresolved = false;
}
}
......@@ -132,10 +132,10 @@ void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) throw (xml::sax:
if (m_bReferenceUnresolved)
{
// No transform algorithm found, assume binary.
m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/true);
m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/true, /*nDigestID=*/xml::crypto::DigestID::SHA256);
m_bReferenceUnresolved = false;
}
m_pXSecController->setDigestValue(m_aDigestValue);
m_pXSecController->setDigestValue(xml::crypto::DigestID::SHA256, m_aDigestValue);
}
else if (rName == "DigestValue" && !m_bInCertDigest)
m_bInDigestValue = false;
......
......@@ -145,9 +145,9 @@ void XMLSignatureHelper::SetDescription(sal_Int32 nSecurityId, const OUString& r
mpXSecController->setDescription(nSecurityId, rDescription);
}
void XMLSignatureHelper::AddForSigning( sal_Int32 nSecurityId, const OUString& uri, const OUString& objectURL, bool bBinary )
void XMLSignatureHelper::AddForSigning( sal_Int32 nSecurityId, const OUString& uri, const OUString& objectURL, bool bBinary, bool bXAdESCompliantIfODF )
{
mpXSecController->signAStream( nSecurityId, uri, objectURL, bBinary );
mpXSecController->signAStream( nSecurityId, uri, objectURL, bBinary, bXAdESCompliantIfODF );
}
......@@ -221,11 +221,11 @@ void XMLSignatureHelper::ExportOOXMLSignature(const uno::Reference<embed::XStora
}
}
bool XMLSignatureHelper::CreateAndWriteSignature( const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler )
bool XMLSignatureHelper::CreateAndWriteSignature( const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler, bool bXAdESCompliantIfODF )
{
mbError = false;
if ( !mpXSecController->WriteSignature( xDocumentHandler ) )
if ( !mpXSecController->WriteSignature( xDocumentHandler, bXAdESCompliantIfODF ) )
{
mbError = true;
}
......
......@@ -65,6 +65,7 @@ XSecController::XSecController( const cssu::Reference<cssu::XComponentContext>&
, m_bIsSAXEventKeeperSticky(false)
, m_nReservedSignatureId(0)
, m_bVerifyCurrentSignature(false)
, m_nDigestID(cssxc::DigestID::SHA1)
{
}
......@@ -614,9 +615,12 @@ void XSecController::exportSignature(
/* Write SignatureMethod element */
pAttributeList = new SvXMLAttributeList();
// Assume that all Reference elements use the same DigestMethod:Algorithm, and that the
// SignatureMethod:Algorithm should be the corresponding one.
pAttributeList->AddAttribute(
"Algorithm",
ALGO_RSASHA1);
(vReferenceInfors[0].nDigestID == cssxc::DigestID::SHA1 ? OUString(ALGO_RSASHA1) : OUString(ALGO_RSASHA256)));
xDocumentHandler->startElement( "SignatureMethod", cssu::Reference< cssxs::XAttributeList > (pAttributeList) );
xDocumentHandler->endElement( "SignatureMethod" );
......@@ -676,7 +680,7 @@ void XSecController::exportSignature(
pAttributeList = new SvXMLAttributeList();
pAttributeList->AddAttribute(
"Algorithm",
ALGO_XMLDSIGSHA1);
(refInfor.nDigestID == cssxc::DigestID::SHA1 ? OUString(ALGO_XMLDSIGSHA1) : OUString(ALGO_XMLDSIGSHA256)));
xDocumentHandler->startElement(
"DigestMethod",
cssu::Reference< cssxs::XAttributeList > (pAttributeList) );
......
......@@ -78,10 +78,10 @@ public:
xReferenceResolvedListener = xListener;
}
void addReference( SignatureReferenceType type, const OUString& uri, sal_Int32 keeperId )
void addReference( SignatureReferenceType type, sal_Int32 digestID, const OUString& uri, sal_Int32 keeperId )
{
signatureInfor.vSignatureReferenceInfors.push_back(
SignatureReferenceInformation(type, uri));
SignatureReferenceInformation(type, digestID, uri));
vKeeperIds.push_back( keeperId );
}
};
......@@ -254,6 +254,13 @@ private:
* representing whether to verify the current signature
*/
bool m_bVerifyCurrentSignature;
/*
* the type of signature to generate (from the css::xml::crypto::DigestID alternatives) when there is a choice,
* in practice currently SHA1 or SHA256 for ODF.
*/
sal_Int32 m_nDigestID;
public:
/*
* An xUriBinding is provided to map Uris to XInputStream interfaces.
......@@ -281,23 +288,28 @@ private:
*/
static OUString createId();
css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToWrite(
InternalSignatureInformation& signatureInfo, sal_Int32 nStorageFormat = 0 );
InternalSignatureInformation& signatureInfo,
sal_Int32 nStorageFormat,
bool bXAdESCompliantIfODF );
/*
* For signature verification
*/
void addSignature();
void addReference( const OUString& ouUri);
void addReference(
const OUString& ouUri,
sal_Int32 nDigestID );
void addStreamReference(
const OUString& ouUri,
bool isBinary );
bool isBinary,
sal_Int32 nDigestID );
void setReferenceCount() const;
void setX509IssuerName( OUString& ouX509IssuerName );
void setX509SerialNumber( OUString& ouX509SerialNumber );
void setX509Certificate( OUString& ouX509Certificate );
void setSignatureValue( OUString& ouSignatureValue );
void setDigestValue( OUString& ouDigestValue );
void setDigestValue( sal_Int32 nDigestID, OUString& ouDigestValue );
void setDate( OUString& ouDate );
void setDescription(const OUString& rDescription);
......@@ -342,7 +354,7 @@ public:
/*
* For signature generation
*/
void signAStream( sal_Int32 securityId, const OUString& uri, const OUString& objectURL, bool isBinary);
void signAStream( sal_Int32 securityId, const OUString& uri, const OUString& objectURL, bool isBinary, bool bXAdESCompliantIfODF);
/** sets data that describes the certificate.
......@@ -384,7 +396,8 @@ public:
void setDescription(sal_Int32 nSecurityId, const OUString& rDescription);
bool WriteSignature(
const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler );
const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler,
bool bXAdESCompliantIfODF);
/*
* For signature verification
......
......@@ -25,6 +25,7 @@
#include <string.h>
namespace cssu = com::sun::star::uno;
namespace cssxc = com::sun::star::xml::crypto;
namespace cssxs = com::sun::star::xml::sax;
XSecParser::XSecParser(XSecController* pXSecController,
......@@ -39,6 +40,7 @@ XSecParser::XSecParser(XSecController* pXSecController,
, m_pXSecController(pXSecController)
, m_xNextHandler(xNextHandler)
, m_bReferenceUnresolved(false)
, m_nReferenceDigestID(cssxc::DigestID::SHA1)
{
}
......@@ -113,7 +115,7 @@ void SAL_CALL XSecParser::startElement(
/*
* remove the first character '#' from the attribute value
*/
m_pXSecController->addReference( ouUri.copy(1) );
m_pXSecController->addReference( ouUri.copy(1), m_nReferenceDigestID );
}
else
{
......@@ -124,6 +126,21 @@ void SAL_CALL XSecParser::startElement(
m_bReferenceUnresolved = true;
}
}
else if (aName == "DigestMethod")
{
OUString ouAlgorithm = xAttribs->getValueByName("Algorithm");
SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" );
if (!ouAlgorithm.isEmpty())
{
SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1 && ouAlgorithm != ALGO_XMLDSIGSHA256,
"xmlsecurity.helper", "Algorithm neither SHA1 or SHA256");
if (ouAlgorithm == ALGO_XMLDSIGSHA1)
m_nReferenceDigestID = cssxc::DigestID::SHA1;
else if (ouAlgorithm == ALGO_XMLDSIGSHA256)
m_nReferenceDigestID = cssxc::DigestID::SHA256;
}
}
else if (aName == "Transform")
{
if ( m_bReferenceUnresolved )
......@@ -135,7 +152,7 @@ void SAL_CALL XSecParser::startElement(
* a xml stream
*/
{
m_pXSecController->addStreamReference( m_currentReferenceURI, false);
m_pXSecController->addStreamReference( m_currentReferenceURI, false, m_nReferenceDigestID );
m_bReferenceUnresolved = false;
}
}
......@@ -219,11 +236,11 @@ void SAL_CALL XSecParser::endElement( const OUString& aName )
* it must be a octet stream
*/
{
m_pXSecController->addStreamReference( m_currentReferenceURI, true);
m_pXSecController->addStreamReference( m_currentReferenceURI, true, m_nReferenceDigestID );
m_bReferenceUnresolved = false;
}
m_pXSecController->setDigestValue( m_ouDigestValue );
m_pXSecController->setDigestValue( m_nReferenceDigestID, m_ouDigestValue );
}
else if ( aName == "SignedInfo" )
{
......
......@@ -95,6 +95,10 @@ private:
OUString m_currentReferenceURI;
bool m_bReferenceUnresolved;
// Relevant for ODF. The digest algorithm selected by the current DigestMethod element's
// Algorithm attribute in the current Reference element. From css::xml::crypto::DigestID.
sal_Int32 m_nReferenceDigestID;
private:
static OUString getIdAttr(const css::uno::Reference<
css::xml::sax::XAttributeList >& xAttribs );
......
......@@ -59,7 +59,9 @@ OUString XSecController::createId()
}
cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite(
InternalSignatureInformation& internalSignatureInfor, sal_Int32 nStorageFormat )
InternalSignatureInformation& internalSignatureInfor,
sal_Int32 nStorageFormat,
bool bXAdESCompliantIfODF)
{
sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId;
SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors;
......@@ -165,28 +167,30 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar
cssu::Reference<cssxc::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, cssu::UNO_QUERY);
keyCollector->setKeyId(0);
const sal_Int32 digestID = bXAdESCompliantIfODF ? cssxc::DigestID::SHA256 : cssxc::DigestID::SHA1;
if (nStorageFormat != embed::StorageFormats::OFOPXML)
{
internalSignatureInfor.signatureInfor.ouSignatureId = createId();
internalSignatureInfor.signatureInfor.ouPropertyId = createId();
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, internalSignatureInfor.signatureInfor.ouPropertyId, -1 );
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouPropertyId, -1 );
size++;
if (!internalSignatureInfor.signatureInfor.ouDescription.isEmpty())
{
// Only mention the hash of the description in the signature if it's non-empty.
internalSignatureInfor.signatureInfor.ouDescriptionPropertyId = createId();
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, internalSignatureInfor.signatureInfor.ouDescriptionPropertyId, -1);
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDescriptionPropertyId, -1);
size++;
}
}
else
{
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, "idPackageObject", -1);
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject", -1);
size++;
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, "idOfficeObject", -1);
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject", -1);
size++;
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, "idSignedProperties", -1);
internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -1);
size++;
}
......@@ -204,21 +208,22 @@ cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepar
return xReferenceResolvedListener;
}
void XSecController::signAStream( sal_Int32 securityId, const OUString& uri, const OUString& /*objectURL*/, bool isBinary)
void XSecController::signAStream( sal_Int32 securityId, const OUString& uri, const OUString& /*objectURL*/, bool isBinary, bool bXAdESCompliantIfODF)
{
SignatureReferenceType type = isBinary ? SignatureReferenceType::BINARYSTREAM : SignatureReferenceType::XMLSTREAM;
const SignatureReferenceType type = isBinary ? SignatureReferenceType::BINARYSTREAM : SignatureReferenceType::XMLSTREAM;
const sal_Int32 digestID = bXAdESCompliantIfODF ? cssxc::DigestID::SHA256 : cssxc::DigestID::SHA1;
int index = findSignatureInfor( securityId );
if (index == -1)
{
InternalSignatureInformation isi(securityId, nullptr);
isi.addReference(type, uri, -1);
isi.addReference(type, digestID, uri, -1);
m_vInternalSignatureInformations.push_back( isi );
}
else
{
m_vInternalSignatureInformations[index].addReference(type, uri, -1);
m_vInternalSignatureInformations[index].addReference(type, digestID, uri, -1);
}
}
......@@ -302,8 +307,11 @@ void XSecController::setDescription(sal_Int32 nSecurityId, const OUString& rDesc
}
bool XSecController::WriteSignature(
const cssu::Reference<cssxs::XDocumentHandler>& xDocumentHandler )
const cssu::Reference<cssxs::XDocumentHandler>& xDocumentHandler,
bool bXAdESCompliantIfODF )
{
(void) bXAdESCompliantIfODF;
bool rc = false;
SAL_WARN_IF( !xDocumentHandler.is(), "xmlsecurity.helper", "I really need a document handler!" );
......@@ -336,11 +344,9 @@ bool XSecController::WriteSignature(
{
InternalSignatureInformation &isi = m_vInternalSignatureInformations[i];
/*
* prepare the signature creator
*/
isi.xReferenceResolvedListener
= prepareSignatureToWrite( isi );
// Prepare the signature creator.
// 0 is not a documented value of embed::StorageFormats, ugh
isi.xReferenceResolvedListener = prepareSignatureToWrite( isi, 0, bXAdESCompliantIfODF );
exportSignature( xSEKHandler, isi.signatureInfor );
}
......@@ -383,7 +389,7 @@ bool XSecController::WriteOOXMLSignature(const uno::Reference<embed::XStorage>&
for (InternalSignatureInformation & rInformation : m_vInternalSignatureInformations)
{
// Prepare the signature creator.
rInformation.xReferenceResolvedListener = prepareSignatureToWrite(rInformation, embed::StorageFormats::OFOPXML);
rInformation.xReferenceResolvedListener = prepareSignatureToWrite(rInformation, embed::StorageFormats::OFOPXML, false);
exportOOXMLSignature(xRootStorage, xSEKHandler, rInformation.signatureInfor);
}
......
......@@ -114,7 +114,7 @@ void XSecController::addSignature()
m_vInternalSignatureInformations.push_back( isi );
}
void XSecController::addReference( const OUString& ouUri)
void XSecController::addReference( const OUString& ouUri, sal_Int32 nDigestID )
{
if (m_vInternalSignatureInformations.empty())
{
......@@ -122,12 +122,13 @@ void XSecController::addReference( const OUString& ouUri)
return;
}
InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
isi.addReference(SignatureReferenceType::SAMEDOCUMENT,ouUri, -1 );
isi.addReference(SignatureReferenceType::SAMEDOCUMENT, nDigestID, ouUri, -1 );
}
void XSecController::addStreamReference(
const OUString& ouUri,
bool isBinary )
bool isBinary,
sal_Int32 nDigestID )
{
SignatureReferenceType type = (isBinary?SignatureReferenceType::BINARYSTREAM:SignatureReferenceType::XMLSTREAM);
......@@ -154,7 +155,7 @@ void XSecController::addStreamReference(
}
}
isi.addReference(type, ouUri, -1);
isi.addReference(type, nDigestID, ouUri, -1);
}
void XSecController::setReferenceCount() const
......@@ -235,7 +236,7 @@ void XSecController::setSignatureValue( OUString& ouSignatureValue )
isi.signatureInfor.ouSignatureValue = ouSignatureValue;
}
void XSecController::setDigestValue( OUString& ouDigestValue )
void XSecController::setDigestValue( sal_Int32 nDigestID, OUString& ouDigestValue )
{
if (m_vInternalSignatureInformations.empty())
{
......@@ -250,6 +251,7 @@ void XSecController::setDigestValue( OUString& ouDigestValue )
}
SignatureReferenceInformation &reference =
isi.signatureInfor.vSignatureReferenceInfors.back();
reference.nDigestID = nDigestID;
reference.ouDigestValue = ouDigestValue;
}
......
......@@ -139,7 +139,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
<property name="top_attach">7</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
......@@ -366,6 +366,19 @@
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="xadescompliant">
<property name="label" translatable="yes">Use XAdES-compliant signature when there is a choice</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment