Kaydet (Commit) d0edff60 authored tarafından Miklos Vajna's avatar Miklos Vajna

xmlsecurity PDF NSS verify: handle SHA1_WITH_RSA

SHA1_WITH_RSA is a signing algorithm, not a digest one, but let's
accept it, so LO on Linux can verify a signature generated by LO on
Windows.

It's annoying that equivalent mapping in NSS is not part of their public
API.

Change-Id: I97186fcc1d118f922e5ee3cb472aa5b52bc4b5ca
üst 8e38964c
...@@ -116,6 +116,8 @@ public: ...@@ -116,6 +116,8 @@ public:
PDFDocument(); PDFDocument();
PDFDocument& operator=(const PDFDocument&) = delete; PDFDocument& operator=(const PDFDocument&) = delete;
PDFDocument(const PDFDocument&) = delete; PDFDocument(const PDFDocument&) = delete;
/// @name Low-level functions, to be used by PDFElement subclasses.
//@{
static OString ReadKeyword(SvStream& rStream); static OString ReadKeyword(SvStream& rStream);
static size_t FindStartXRef(SvStream& rStream); static size_t FindStartXRef(SvStream& rStream);
void ReadXRef(SvStream& rStream); void ReadXRef(SvStream& rStream);
...@@ -136,13 +138,17 @@ public: ...@@ -136,13 +138,17 @@ public:
bool Tokenize(SvStream& rStream, TokenizeMode eMode, std::vector< std::unique_ptr<PDFElement> >& rElements, PDFObjectElement* pObject); bool Tokenize(SvStream& rStream, TokenizeMode eMode, std::vector< std::unique_ptr<PDFElement> >& rElements, PDFObjectElement* pObject);
/// Register an object (owned directly or indirectly by m_aElements) as a provder for a given ID. /// Register an object (owned directly or indirectly by m_aElements) as a provder for a given ID.
void SetIDObject(size_t nID, PDFObjectElement* pObject); void SetIDObject(size_t nID, PDFObjectElement* pObject);
//@}
/// @name High-level functions, to be used by others.
//@{
/// 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);
/// 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.
std::vector<PDFObjectElement*> GetSignatureWidgets(); std::vector<PDFObjectElement*> GetSignatureWidgets();
/** /**
* @param rInformation The actual result. * @param rInformation The actual result.
...@@ -152,6 +158,7 @@ public: ...@@ -152,6 +158,7 @@ public:
static bool ValidateSignature(SvStream& rStream, PDFObjectElement* pSignature, SignatureInformation& rInformation, bool bLast); static bool ValidateSignature(SvStream& rStream, PDFObjectElement* pSignature, SignatureInformation& rInformation, bool bLast);
/// Remove the nth signature from read document in the edit buffer. /// Remove the nth signature from read document in the edit buffer.
bool RemoveSignature(size_t nPosition); bool RemoveSignature(size_t nPosition);
//@}
}; };
} // namespace pdfio } // namespace pdfio
......
...@@ -58,6 +58,8 @@ public: ...@@ -58,6 +58,8 @@ public:
void testPDF14Adobe(); void testPDF14Adobe();
/// Test a PDF 1.6 document, signed by Adobe. /// Test a PDF 1.6 document, signed by Adobe.
void testPDF16Adobe(); void testPDF16Adobe();
/// Test a PDF 1.4 document, signed by LO on Windows.
void testPDF14LOWin();
CPPUNIT_TEST_SUITE(PDFSigningTest); CPPUNIT_TEST_SUITE(PDFSigningTest);
CPPUNIT_TEST(testPDFAdd); CPPUNIT_TEST(testPDFAdd);
...@@ -66,6 +68,7 @@ public: ...@@ -66,6 +68,7 @@ public:
CPPUNIT_TEST(testPDFRemoveAll); CPPUNIT_TEST(testPDFRemoveAll);
CPPUNIT_TEST(testPDF14Adobe); CPPUNIT_TEST(testPDF14Adobe);
CPPUNIT_TEST(testPDF16Adobe); CPPUNIT_TEST(testPDF16Adobe);
CPPUNIT_TEST(testPDF14LOWin);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
}; };
...@@ -267,6 +270,15 @@ void PDFSigningTest::testPDF16Adobe() ...@@ -267,6 +270,15 @@ void PDFSigningTest::testPDF16Adobe()
verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf16adobe.pdf", 1); verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf16adobe.pdf", 1);
} }
void PDFSigningTest::testPDF14LOWin()
{
// mscrypto used SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION as a digest
// algorithm when it meant SEC_OID_SHA1, make sure we tolerate that on all
// platforms.
// This failed, as NSS HASH_Create() didn't handle the sign algorithm.
verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf14lowin.pdf", 1);
}
CPPUNIT_TEST_SUITE_REGISTRATION(PDFSigningTest); CPPUNIT_TEST_SUITE_REGISTRATION(PDFSigningTest);
CPPUNIT_PLUGIN_IMPLEMENT(); CPPUNIT_PLUGIN_IMPLEMENT();
......
...@@ -1760,7 +1760,20 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat ...@@ -1760,7 +1760,20 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
} }
SECItem aAlgorithm = NSS_CMSSignedData_GetDigestAlgs(pCMSSignedData)[0]->algorithm; SECItem aAlgorithm = NSS_CMSSignedData_GetDigestAlgs(pCMSSignedData)[0]->algorithm;
HASH_HashType eHashType = HASH_GetHashTypeByOidTag(SECOID_FindOIDTag(&aAlgorithm)); SECOidTag eOidTag = SECOID_FindOIDTag(&aAlgorithm);
// Map a sign algorithm to a digest algorithm.
// See NSS_CMSUtil_MapSignAlgs(), which is private to us.
switch (eOidTag)
{
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
eOidTag = SEC_OID_SHA1;
break;
default:
break;
}
HASH_HashType eHashType = HASH_GetHashTypeByOidTag(eOidTag);
HASHContext* pHASHContext = HASH_Create(eHashType); HASHContext* pHASHContext = HASH_Create(eHashType);
if (!pHASHContext) if (!pHASHContext)
{ {
...@@ -1796,7 +1809,7 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat ...@@ -1796,7 +1809,7 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
// Find out what is the expected length of the hash. // Find out what is the expected length of the hash.
unsigned int nMaxResultLen = 0; unsigned int nMaxResultLen = 0;
switch (SECOID_FindOIDTag(&aAlgorithm)) switch (eOidTag)
{ {
case SEC_OID_SHA1: case SEC_OID_SHA1:
nMaxResultLen = msfilter::SHA1_HASH_LENGTH; nMaxResultLen = msfilter::SHA1_HASH_LENGTH;
......
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