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);
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 bXAdESCompliantIfODF);
bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant);
/// Remove signature at nPosition.
void remove(sal_uInt16 nPosition);
/// 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.
sal_uInt32 GetNextSignature();
/// 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.
sal_Int32 WriteAppearanceObject();
/// Write the annot object as part of signing.
@@ -162,7 +162,7 @@ public:
/// Read elements from the start of the stream till its end.
bool Read(SvStream& rStream);
/// 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.
bool Write(SvStream& rStream);
/// 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.
void SetDescription(const OUString& rDescription);
/// 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.
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.
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);
CPPUNIT_ASSERT(aDocument.Write(aOutStream));
}

View File

@@ -232,7 +232,7 @@ SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int3
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())
{
@@ -255,7 +255,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
getPDFSignatureHelper().SetX509Certificate(xCert);
getPDFSignatureHelper().SetDescription(rDescription);
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");
return false;
@@ -299,7 +299,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, bXAdESCompliantIfODF);
maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode, bAdESCompliant);
}
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);
std::size_t nInfos = maCurrentSignatureInformations.size();
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...
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bXAdESCompliantIfODF);
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bAdESCompliant);
// That's it...
XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);

View File

@@ -118,7 +118,7 @@ void PDFSignatureHelper::SetDescription(const OUString& 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));
xmlsecurity::pdfio::PDFDocument aDocument;
@@ -128,7 +128,7 @@ bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStre
return false;
}
if (!aDocument.Sign(m_xCertificate, m_aDescription))
if (!aDocument.Sign(m_xCertificate, m_aDescription, bAdES))
{
SAL_WARN("xmlsecurity.helper", "failed to sign");
return false;

View File

@@ -357,7 +357,7 @@ sal_uInt32 PDFDocument::GetNextSignature()
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.
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);
comphelper::string::padToLength(aContentFiller, MAX_SIGNATURE_CONTENT_LENGTH, '0');
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.
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.WriteCharPtr("\n");
sal_uInt64 nSignatureLastByteRangeOffset = 0;
sal_Int64 nSignatureContentOffset = 0;
sal_Int32 nSignatureId = WriteSignatureObject(rDescription, nSignatureLastByteRangeOffset, nSignatureContentOffset);
sal_Int32 nSignatureId = WriteSignatureObject(rDescription, bAdES, nSignatureLastByteRangeOffset, nSignatureContentOffset);
sal_Int32 nAppearanceId = WriteAppearanceObject();
@@ -2021,7 +2025,7 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
}
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");
return false;

View File

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