[Libreoffice-commits] core.git: xmlsecurity/Library_xmlsecurity.mk xmlsecurity/source

Miklos Vajna vmiklos at collabora.co.uk
Thu Nov 3 08:10:06 UTC 2016


 xmlsecurity/Library_xmlsecurity.mk       |    3 
 xmlsecurity/source/pdfio/pdfdocument.cxx |  121 +++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+)

New commits:
commit 8d1fb35f5cd05fcbb2aae4d793b17ee4083c9b5e
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Nov 2 17:57:25 2016 +0100

    xmlsecurity PDF verify: initial Windows support
    
    The timestamp isn't extracted yet, but the digest match is already
    checked correctly and the certificate is exposed.
    
    Change-Id: Ieca002a5c4ca0b96f4dc397c460adb7f88f5ffc7
    Reviewed-on: https://gerrit.libreoffice.org/30499
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk
index c5e8d68..487011f 100644
--- a/xmlsecurity/Library_xmlsecurity.mk
+++ b/xmlsecurity/Library_xmlsecurity.mk
@@ -71,6 +71,9 @@ ifeq ($(OS)-$(COM),WNT-MSC)
 $(eval $(call gb_Library_add_defs,xmlsecurity,\
     -DXMLSEC_CRYPTO_MSCRYPTO \
 ))
+$(eval $(call gb_Library_use_system_win32_libs,xmlsecurity,\
+    crypt32 \
+))
 else
 ifneq (,$(filter DESKTOP,$(BUILD_TYPE)))
 $(eval $(call gb_Library_add_defs,xmlsecurity,\
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 894247f..ac75059 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -37,6 +37,13 @@
 #include <sechash.h>
 #endif
 
+#ifdef XMLSEC_CRYPTO_MSCRYPTO
+#include <prewin.h>
+#include <wincrypt.h>
+#include <postwin.h>
+#include <comphelper/windowserrorstring.hxx>
+#endif
+
 using namespace com::sun::star;
 
 namespace xmlsecurity
@@ -1864,6 +1871,120 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
         CERT_DestroyCertificate(pDocumentCertificate);
 
     return true;
+#elif defined XMLSEC_CRYPTO_MSCRYPTO
+    //  Open a message for decoding.
+    HCRYPTMSG hMsg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+                                          CMSG_DETACHED_FLAG,
+                                          0,
+                                          NULL,
+                                          nullptr,
+                                          nullptr);
+    if (!hMsg)
+    {
+        SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: CryptMsgOpenToDecode() failed");
+        return false;
+    }
+
+    //  Update the message with the encoded header blob.
+    if (!CryptMsgUpdate(hMsg, aSignature.data(), aSignature.size(), TRUE))
+    {
+        SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature, CryptMsgUpdate() for the header failed: " << WindowsErrorString(GetLastError()));
+        return false;
+    }
+
+    //  Update the message with the content blob.
+    for (const auto& rByteRange : aByteRanges)
+    {
+        rStream.Seek(rByteRange.first);
+
+        const int nChunkLen = 4096;
+        std::vector<unsigned char> aBuffer(nChunkLen);
+        for (size_t nByte = 0; nByte < rByteRange.second;)
+        {
+            size_t nRemainingSize = rByteRange.second - nByte;
+            if (nRemainingSize < nChunkLen)
+            {
+                rStream.ReadBytes(aBuffer.data(), nRemainingSize);
+                if (!CryptMsgUpdate(hMsg, aBuffer.data(), nRemainingSize, FALSE))
+                {
+                    SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature, CryptMsgUpdate() for the content failed: " << WindowsErrorString(GetLastError()));
+                    return false;
+                }
+                nByte = rByteRange.second;
+            }
+            else
+            {
+                rStream.ReadBytes(aBuffer.data(), nChunkLen);
+                if (!CryptMsgUpdate(hMsg, aBuffer.data(), nChunkLen, FALSE))
+                {
+                    SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature, CryptMsgUpdate() for the content failed: " << WindowsErrorString(GetLastError()));
+                    return false;
+                }
+                nByte += nChunkLen;
+            }
+        }
+    }
+    if (!CryptMsgUpdate(hMsg, nullptr, 0, TRUE))
+    {
+        SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature, CryptMsgUpdate() for the last content failed: " << WindowsErrorString(GetLastError()));
+        return false;
+    }
+
+    // Get the signer CERT_INFO from the message.
+    DWORD nSignerCertInfo = 0;
+    if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, 0, nullptr, &nSignerCertInfo))
+    {
+        SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: CryptMsgGetParam() failed");
+        return false;
+    }
+    std::unique_ptr<BYTE[]> pSignerCertInfoBuf(new BYTE[nSignerCertInfo]);
+    if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, 0, pSignerCertInfoBuf.get(), &nSignerCertInfo))
+    {
+        SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: CryptMsgGetParam() failed");
+        return false;
+    }
+    PCERT_INFO pSignerCertInfo = reinterpret_cast<PCERT_INFO>(pSignerCertInfoBuf.get());
+
+    // Open a certificate store in memory using CERT_STORE_PROV_MSG, which
+    // initializes it with the certificates from the message.
+    HCERTSTORE hStoreHandle = CertOpenStore(CERT_STORE_PROV_MSG,
+                                            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+                                            NULL,
+                                            0,
+                                            hMsg);
+    if (!hStoreHandle)
+    {
+        SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: CertOpenStore() failed");
+        return false;
+    }
+
+    // Find the signer's certificate in the store.
+    PCCERT_CONTEXT pSignerCertContext = CertGetSubjectCertificateFromStore(hStoreHandle,
+                                                                           PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+                                                                           pSignerCertInfo);
+    if (!pSignerCertContext)
+    {
+        SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: CertGetSubjectCertificateFromStore() failed");
+        return false;
+    }
+    else
+    {
+        // Write rInformation.ouX509Certificate.
+        uno::Sequence<sal_Int8> aDerCert(pSignerCertContext->cbCertEncoded);
+        for (size_t i = 0; i < pSignerCertContext->cbCertEncoded; ++i)
+            aDerCert[i] = pSignerCertContext->pbCertEncoded[i];
+        OUStringBuffer aBuffer;
+        sax::Converter::encodeBase64(aBuffer, aDerCert);
+        rInformation.ouX509Certificate = aBuffer.makeStringAndClear();
+    }
+
+    // Use the CERT_INFO from the signer certificate to verify the signature.
+    if (CryptMsgControl(hMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE, pSignerCertContext->pCertInfo))
+        rInformation.nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
+
+    CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
+    CryptMsgClose(hMsg);
+    return true;
 #else
     // Not implemented.
     (void)rStream;


More information about the Libreoffice-commits mailing list