xmlsecurity PDF sign: handle AdES when writing SubFilter

Page 21 of "PAdES baseline signatures" specification from
<http://www.etsi.org/deliver/etsi_en/319100_319199/31914201/01.01.01_60/en_31914201v010101p.pdf>
says:

"The Signature Dictionary shall contain a value of ETSI.CAdES.detached
for the key SubFilter."

So in case the UI has the adescompliant checkbox enabled, write that
value instead of the Adobe default.

Change-Id: I69e606a32fb09bebd5e9b25b32150d1b8672f544
This commit is contained in:
Miklos Vajna
2016-11-17 12:40:06 +01:00
parent 07d4f5d9e3
commit 972c1e9e72
8 changed files with 22 additions and 18 deletions

View File

@@ -59,7 +59,7 @@ public:
bool isXML(const OUString& rURI); bool isXML(const OUString& rURI);
SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 eStreamMode, bool bTempStream); SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 eStreamMode, bool bTempStream);
/// Add a new signature, using xCert as a signing certificate, and rDescription as description. /// 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 bXAdESCompliantIfODF); bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant);
/// Remove signature at nPosition. /// Remove signature at nPosition.
void remove(sal_uInt16 nPosition); void remove(sal_uInt16 nPosition);
/// Read signatures from either a temp stream or the real storage. /// Read signatures from either a temp stream or the real storage.

View File

@@ -117,7 +117,7 @@ class XMLSECURITY_DLLPUBLIC PDFDocument
/// Suggest a minimal, yet free signature ID to use for the next signature. /// Suggest a minimal, yet free signature ID to use for the next signature.
sal_uInt32 GetNextSignature(); sal_uInt32 GetNextSignature();
/// Write the signature object as part of signing. /// Write the signature object as part of signing.
sal_Int32 WriteSignatureObject(const OUString& rDescription, sal_uInt64& rLastByteRangeOffset, sal_Int64& rSignatureContentOffset); sal_Int32 WriteSignatureObject(const OUString& rDescription, bool bAdES, sal_uInt64& rLastByteRangeOffset, sal_Int64& rSignatureContentOffset);
/// Write the appearance object as part of signing. /// Write the appearance object as part of signing.
sal_Int32 WriteAppearanceObject(); sal_Int32 WriteAppearanceObject();
/// Write the annot object as part of signing. /// Write the annot object as part of signing.
@@ -162,7 +162,7 @@ public:
/// Read elements from the start of the stream till its end. /// Read elements from the start of the stream till its end.
bool Read(SvStream& rStream); bool Read(SvStream& rStream);
/// Sign the read document with xCertificate in the edit buffer. /// Sign the read document with xCertificate in the edit buffer.
bool Sign(const css::uno::Reference<css::security::XCertificate>& xCertificate, const OUString& rDescription); bool Sign(const css::uno::Reference<css::security::XCertificate>& xCertificate, const OUString& rDescription, bool bAdES);
/// Serializes the contents of the edit buffer. /// Serializes the contents of the edit buffer.
bool Write(SvStream& rStream); bool Write(SvStream& rStream);
/// Get a list of signatures embedded into this document. /// Get a list of signatures embedded into this document.

View File

@@ -43,7 +43,7 @@ public:
/// Comment / reason to be used next time signing is performed. /// Comment / reason to be used next time signing is performed.
void SetDescription(const OUString& rDescription); void SetDescription(const OUString& rDescription);
/// Append a new signature at the end of xInputStream. /// Append a new signature at the end of xInputStream.
bool Sign(const css::uno::Reference<css::io::XInputStream>& xInputStream); bool Sign(const css::uno::Reference<css::io::XInputStream>& xInputStream, bool bAdES);
/// Remove the signature at nPosition (and all dependent signatures) from xInputStream. /// Remove the signature at nPosition (and all dependent signatures) from xInputStream.
static bool RemoveSignature(const css::uno::Reference<css::io::XInputStream>& xInputStream, sal_uInt16 nPosition); static bool RemoveSignature(const css::uno::Reference<css::io::XInputStream>& xInputStream, sal_uInt16 nPosition);
}; };

View File

@@ -142,7 +142,7 @@ bool PDFSigningTest::sign(const OUString& rInURL, const OUString& rOutURL, size_
// NSS failed to parse it's own profile or Windows has no certificates installed. // NSS failed to parse it's own profile or Windows has no certificates installed.
return false; return false;
} }
CPPUNIT_ASSERT(aDocument.Sign(aCertificates[0], "test")); CPPUNIT_ASSERT(aDocument.Sign(aCertificates[0], "test", /*bAdES=*/true));
SvFileStream aOutStream(rOutURL, StreamMode::WRITE | StreamMode::TRUNC); SvFileStream aOutStream(rOutURL, StreamMode::WRITE | StreamMode::TRUNC);
CPPUNIT_ASSERT(aDocument.Write(aOutStream)); CPPUNIT_ASSERT(aDocument.Write(aOutStream));
} }

View File

@@ -232,7 +232,7 @@ SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int3
return aHelper; return aHelper;
} }
bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bXAdESCompliantIfODF) bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant)
{ {
if (!xCert.is()) if (!xCert.is())
{ {
@@ -255,7 +255,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
getPDFSignatureHelper().SetX509Certificate(xCert); getPDFSignatureHelper().SetX509Certificate(xCert);
getPDFSignatureHelper().SetDescription(rDescription); getPDFSignatureHelper().SetDescription(rDescription);
uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY); uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
if (!getPDFSignatureHelper().Sign(xInputStream)) if (!getPDFSignatureHelper().Sign(xInputStream, bAdESCompliant))
{ {
SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed"); SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
return false; return false;
@@ -299,7 +299,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
for (sal_Int32 n = 0; n < nElements; n++) for (sal_Int32 n = 0; n < nElements; n++)
{ {
bool bBinaryMode = !isXML(aElements[n]); bool bBinaryMode = !isXML(aElements[n]);
maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode, bXAdESCompliantIfODF); maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode, bAdESCompliant);
} }
maSignatureHelper.SetDateTime(nSecurityId, Date(Date::SYSTEM), tools::Time(tools::Time::SYSTEM)); maSignatureHelper.SetDateTime(nSecurityId, Date(Date::SYSTEM), tools::Time(tools::Time::SYSTEM));
@@ -321,10 +321,10 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, uno::UNO_QUERY_THROW); uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, uno::UNO_QUERY_THROW);
std::size_t nInfos = maCurrentSignatureInformations.size(); std::size_t nInfos = maCurrentSignatureInformations.size();
for (std::size_t n = 0; n < nInfos; n++) for (std::size_t n = 0; n < nInfos; n++)
XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], bXAdESCompliantIfODF); XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], bAdESCompliant);
// Create a new one... // Create a new one...
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bXAdESCompliantIfODF); maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bAdESCompliant);
// That's it... // That's it...
XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler); XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);

View File

@@ -118,7 +118,7 @@ void PDFSignatureHelper::SetDescription(const OUString& rDescription)
m_aDescription = rDescription; m_aDescription = rDescription;
} }
bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStream) bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStream, bool bAdES)
{ {
std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
xmlsecurity::pdfio::PDFDocument aDocument; xmlsecurity::pdfio::PDFDocument aDocument;
@@ -128,7 +128,7 @@ bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStre
return false; return false;
} }
if (!aDocument.Sign(m_xCertificate, m_aDescription)) if (!aDocument.Sign(m_xCertificate, m_aDescription, bAdES))
{ {
SAL_WARN("xmlsecurity.helper", "failed to sign"); SAL_WARN("xmlsecurity.helper", "failed to sign");
return false; return false;

View File

@@ -357,7 +357,7 @@ sal_uInt32 PDFDocument::GetNextSignature()
return nRet + 1; return nRet + 1;
} }
sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, sal_uInt64& rLastByteRangeOffset, sal_Int64& rContentOffset) sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, bool bAdES, sal_uInt64& rLastByteRangeOffset, sal_Int64& rContentOffset)
{ {
// Write signature object. // Write signature object.
sal_Int32 nSignatureId = m_aXRef.size(); sal_Int32 nSignatureId = m_aXRef.size();
@@ -374,7 +374,11 @@ sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, sal_uI
OStringBuffer aContentFiller(MAX_SIGNATURE_CONTENT_LENGTH); OStringBuffer aContentFiller(MAX_SIGNATURE_CONTENT_LENGTH);
comphelper::string::padToLength(aContentFiller, MAX_SIGNATURE_CONTENT_LENGTH, '0'); comphelper::string::padToLength(aContentFiller, MAX_SIGNATURE_CONTENT_LENGTH, '0');
aSigBuffer.append(aContentFiller.makeStringAndClear()); aSigBuffer.append(aContentFiller.makeStringAndClear());
aSigBuffer.append(">\n/Type/Sig/SubFilter/adbe.pkcs7.detached"); aSigBuffer.append(">\n/Type/Sig/SubFilter");
if (bAdES)
aSigBuffer.append("/ETSI.CAdES.detached");
else
aSigBuffer.append("/adbe.pkcs7.detached");
// Time of signing. // Time of signing.
aSigBuffer.append(" /M ("); aSigBuffer.append(" /M (");
@@ -941,14 +945,14 @@ void PDFDocument::WriteXRef(sal_uInt64 nXRefOffset, PDFReferenceElement* pRoot)
} }
} }
bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificate, const OUString& rDescription) bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificate, const OUString& rDescription, bool bAdES)
{ {
m_aEditBuffer.Seek(STREAM_SEEK_TO_END); m_aEditBuffer.Seek(STREAM_SEEK_TO_END);
m_aEditBuffer.WriteCharPtr("\n"); m_aEditBuffer.WriteCharPtr("\n");
sal_uInt64 nSignatureLastByteRangeOffset = 0; sal_uInt64 nSignatureLastByteRangeOffset = 0;
sal_Int64 nSignatureContentOffset = 0; sal_Int64 nSignatureContentOffset = 0;
sal_Int32 nSignatureId = WriteSignatureObject(rDescription, nSignatureLastByteRangeOffset, nSignatureContentOffset); sal_Int32 nSignatureId = WriteSignatureObject(rDescription, bAdES, nSignatureLastByteRangeOffset, nSignatureContentOffset);
sal_Int32 nAppearanceId = WriteAppearanceObject(); sal_Int32 nAppearanceId = WriteAppearanceObject();
@@ -2021,7 +2025,7 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
} }
auto pSubFilter = dynamic_cast<PDFNameElement*>(pValue->Lookup("SubFilter")); auto pSubFilter = dynamic_cast<PDFNameElement*>(pValue->Lookup("SubFilter"));
if (!pSubFilter || pSubFilter->GetValue() != "adbe.pkcs7.detached") if (!pSubFilter || (pSubFilter->GetValue() != "adbe.pkcs7.detached" && pSubFilter->GetValue() != "ETSI.CAdES.detached"))
{ {
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: no or unsupported sub-filter"); SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: no or unsupported sub-filter");
return false; return false;

View File

@@ -136,7 +136,7 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc, pArgv)
SAL_WARN("xmlsecurity.pdfio", "no signing certificates found"); SAL_WARN("xmlsecurity.pdfio", "no signing certificates found");
return 1; return 1;
} }
if (!aDocument.Sign(aCertificates[0], "pdfverify")) if (!aDocument.Sign(aCertificates[0], "pdfverify", /*bAdES=*/true))
{ {
SAL_WARN("xmlsecurity.pdfio", "failed to sign"); SAL_WARN("xmlsecurity.pdfio", "failed to sign");
return 1; return 1;