vcl/source/gdi/pdfwriter_impl.cxx | 259 +++++++++++++++++++------------------- 1 file changed, 136 insertions(+), 123 deletions(-)
New commits: commit 4f6028ad7610d36379aba36470e47e701f8a87d5 Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Wed Nov 2 15:03:41 2016 +0100 vcl: implement PDFWriter::Sign() on Windows Move Windows-specific code from PDFWriterImpl::finalizeSignature() to PDFWriter::Sign(), this way the pdfverify cmdline tool can sign a previously unsigned file. Change-Id: I1144e228bf8f12a284c3fc32fd3e74c355855ff3 diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index c20446f..94c730e 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -7058,121 +7058,8 @@ bool PDFWriter::Sign(PDFSignContext& rContext) return true; -#else - // Not implemented - (void)rContext; - - return false; -#endif -} - -bool PDFWriterImpl::finalizeSignature() -{ - - if (!m_aContext.SignCertificate.is()) - return false; - - // 1- calculate last ByteRange value - sal_uInt64 nOffset = ~0U; - CHECK_RETURN( (osl::File::E_None == m_aFile.getPos(nOffset) ) ); - - sal_Int64 nLastByteRangeNo = nOffset - (m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1); - - // 2- overwrite the value to the m_nSignatureLastByteRangeNoOffset position - sal_uInt64 nWritten = 0; - CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureLastByteRangeNoOffset) ) ); - OStringBuffer aByteRangeNo( 256 ); - aByteRangeNo.append( nLastByteRangeNo ); - aByteRangeNo.append( " ]" ); - - if (m_aFile.write(aByteRangeNo.getStr(), aByteRangeNo.getLength(), nWritten) != osl::File::E_None) - { - CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, nOffset)) ); - return false; - } - - // 3- create the PKCS#7 object using NSS - css::uno::Sequence< sal_Int8 > derEncoded = m_aContext.SignCertificate->getEncoded(); - - if (!derEncoded.hasElements()) - return false; - - sal_Int8* n_derArray = derEncoded.getArray(); - sal_Int32 n_derLength = derEncoded.getLength(); - -#ifndef _WIN32 - - // Prepare buffer and calculate PDF file digest - CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, 0)) ); - - std::unique_ptr<char[]> buffer1(new char[m_nSignatureContentOffset + 1]); - sal_uInt64 bytesRead1; - - //FIXME: Check if SHA1 is calculated from the correct byterange - CHECK_RETURN( (osl::File::E_None == m_aFile.read(buffer1.get(), m_nSignatureContentOffset - 1 , bytesRead1)) ); - if (bytesRead1 != (sal_uInt64)m_nSignatureContentOffset - 1) - SAL_WARN("vcl.pdfwriter", "First buffer read failed"); - - CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1)) ); - std::unique_ptr<char[]> buffer2(new char[nLastByteRangeNo + 1]); - sal_uInt64 bytesRead2; - CHECK_RETURN( (osl::File::E_None == m_aFile.read(buffer2.get(), nLastByteRangeNo, bytesRead2)) ); - if (bytesRead2 != (sal_uInt64) nLastByteRangeNo) - SAL_WARN("vcl.pdfwriter", "Second buffer read failed"); - - OStringBuffer cms_hexbuffer; - PDFWriter::PDFSignContext aSignContext(cms_hexbuffer); - aSignContext.m_pDerEncoded = n_derArray; - aSignContext.m_nDerEncoded = n_derLength; - aSignContext.m_pByteRange1 = buffer1.get(); - aSignContext.m_nByteRange1 = bytesRead1; - aSignContext.m_pByteRange2 = buffer2.get(); - aSignContext.m_nByteRange2 = bytesRead2; - aSignContext.m_aSignTSA = m_aContext.SignTSA; - aSignContext.m_aSignPassword = m_aContext.SignPassword; - if (!PDFWriter::Sign(aSignContext)) - { - SAL_WARN("vcl.pdfwriter", "PDFWriter::Sign() failed"); - return false; - } - - assert(cms_hexbuffer.getLength() <= MAX_SIGNATURE_CONTENT_LENGTH); - - // Set file pointer to the m_nSignatureContentOffset, we're ready to overwrite PKCS7 object - nWritten = 0; - CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset)) ); - m_aFile.write(cms_hexbuffer.getStr(), cms_hexbuffer.getLength(), nWritten); - - CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, nOffset)) ); - return true; - -#else - - // Prepare buffer and calculate PDF file digest - CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, 0)) ); - - std::unique_ptr<char[]> buffer1(new char[m_nSignatureContentOffset - 1]); - sal_uInt64 bytesRead1; - - if (osl::File::E_None != m_aFile.read(buffer1.get(), m_nSignatureContentOffset - 1 , bytesRead1) || - bytesRead1 != (sal_uInt64)m_nSignatureContentOffset - 1) - { - SAL_WARN("vcl.pdfwriter", "First buffer read failed"); - return false; - } - - std::unique_ptr<char[]> buffer2(new char[nLastByteRangeNo]); - sal_uInt64 bytesRead2; - - if (osl::File::E_None != m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1) || - osl::File::E_None != m_aFile.read(buffer2.get(), nLastByteRangeNo, bytesRead2) || - bytesRead2 != (sal_uInt64) nLastByteRangeNo) - { - SAL_WARN("vcl.pdfwriter", "Second buffer read failed"); - return false; - } - - PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, reinterpret_cast<const BYTE*>(n_derArray), n_derLength); +#else // _WIN32 + PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, reinterpret_cast<const BYTE*>(rContext.m_pDerEncoded), rContext.m_nDerEncoded); if (pCertContext == nullptr) { SAL_WARN("vcl.pdfwriter", "CertCreateCertificateContext failed: " << WindowsErrorString(GetLastError())); @@ -7244,8 +7131,8 @@ bool PDFWriterImpl::finalizeSignature() return false; } - if (!CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE *>(buffer1.get()), bytesRead1, FALSE) || - !CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE *>(buffer2.get()), bytesRead2, TRUE)) + if (!CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE *>(rContext.m_pByteRange1), rContext.m_nByteRange1, FALSE) || + !CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE *>(rContext.m_pByteRange2), rContext.m_nByteRange2, TRUE)) { SAL_WARN("vcl.pdfwriter", "CryptMsgUpdate failed: " << WindowsErrorString(GetLastError())); CryptMsgClose(hMsg); @@ -7255,7 +7142,7 @@ bool PDFWriterImpl::finalizeSignature() PCRYPT_TIMESTAMP_CONTEXT pTsContext = nullptr; - if( !m_aContext.SignTSA.isEmpty() ) + if( !rContext.m_aSignTSA.isEmpty() ) { PointerTo_CryptRetrieveTimeStamp crts = reinterpret_cast<PointerTo_CryptRetrieveTimeStamp>(GetProcAddress(LoadLibrary("crypt32.dll"), "CryptRetrieveTimeStamp")); if (!crts) @@ -7346,7 +7233,7 @@ bool PDFWriterImpl::finalizeSignature() aTsPara.cExtension = 0; aTsPara.rgExtension = nullptr; - if (!(*crts)(m_aContext.SignTSA.getStr(), + if (!(*crts)(rContext.m_aSignTSA.getStr(), 0, 10000, szOID_NIST_sha256, @@ -7401,8 +7288,8 @@ bool PDFWriterImpl::finalizeSignature() &aSignedInfo, nullptr, nullptr)) || - !CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE *>(buffer1.get()), bytesRead1, FALSE) || - !CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE *>(buffer2.get()), bytesRead2, TRUE)) + !CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE *>(rContext.m_pByteRange1), rContext.m_nByteRange1, FALSE) || + !CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE *>(rContext.m_pByteRange1), rContext.m_nByteRange2, TRUE)) { SAL_WARN("vcl.pdfwriter", "Re-creating the message failed: " << WindowsErrorString(GetLastError())); CryptMemFree(pTsContext); @@ -7464,10 +7351,136 @@ bool PDFWriterImpl::finalizeSignature() CryptMsgClose(hMsg); CertFreeCertificateContext(pCertContext); + for (unsigned int i = 0; i < nSigLen ; i++) + appendHex(pSig[i], rContext.m_rCMSHexBuffer); + + return true; +#endif +} + +bool PDFWriterImpl::finalizeSignature() +{ + + if (!m_aContext.SignCertificate.is()) + return false; + + // 1- calculate last ByteRange value + sal_uInt64 nOffset = ~0U; + CHECK_RETURN( (osl::File::E_None == m_aFile.getPos(nOffset) ) ); + + sal_Int64 nLastByteRangeNo = nOffset - (m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1); + + // 2- overwrite the value to the m_nSignatureLastByteRangeNoOffset position + sal_uInt64 nWritten = 0; + CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureLastByteRangeNoOffset) ) ); + OStringBuffer aByteRangeNo( 256 ); + aByteRangeNo.append( nLastByteRangeNo ); + aByteRangeNo.append( " ]" ); + + if (m_aFile.write(aByteRangeNo.getStr(), aByteRangeNo.getLength(), nWritten) != osl::File::E_None) + { + CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, nOffset)) ); + return false; + } + + // 3- create the PKCS#7 object using NSS + css::uno::Sequence< sal_Int8 > derEncoded = m_aContext.SignCertificate->getEncoded(); + + if (!derEncoded.hasElements()) + return false; + + sal_Int8* n_derArray = derEncoded.getArray(); + sal_Int32 n_derLength = derEncoded.getLength(); + +#ifndef _WIN32 + + // Prepare buffer and calculate PDF file digest + CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, 0)) ); + + std::unique_ptr<char[]> buffer1(new char[m_nSignatureContentOffset + 1]); + sal_uInt64 bytesRead1; + + //FIXME: Check if SHA1 is calculated from the correct byterange + CHECK_RETURN( (osl::File::E_None == m_aFile.read(buffer1.get(), m_nSignatureContentOffset - 1 , bytesRead1)) ); + if (bytesRead1 != (sal_uInt64)m_nSignatureContentOffset - 1) + SAL_WARN("vcl.pdfwriter", "First buffer read failed"); + + CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1)) ); + std::unique_ptr<char[]> buffer2(new char[nLastByteRangeNo + 1]); + sal_uInt64 bytesRead2; + CHECK_RETURN( (osl::File::E_None == m_aFile.read(buffer2.get(), nLastByteRangeNo, bytesRead2)) ); + if (bytesRead2 != (sal_uInt64) nLastByteRangeNo) + SAL_WARN("vcl.pdfwriter", "Second buffer read failed"); + + OStringBuffer cms_hexbuffer; + PDFWriter::PDFSignContext aSignContext(cms_hexbuffer); + aSignContext.m_pDerEncoded = n_derArray; + aSignContext.m_nDerEncoded = n_derLength; + aSignContext.m_pByteRange1 = buffer1.get(); + aSignContext.m_nByteRange1 = bytesRead1; + aSignContext.m_pByteRange2 = buffer2.get(); + aSignContext.m_nByteRange2 = bytesRead2; + aSignContext.m_aSignTSA = m_aContext.SignTSA; + aSignContext.m_aSignPassword = m_aContext.SignPassword; + if (!PDFWriter::Sign(aSignContext)) + { + SAL_WARN("vcl.pdfwriter", "PDFWriter::Sign() failed"); + return false; + } + + assert(cms_hexbuffer.getLength() <= MAX_SIGNATURE_CONTENT_LENGTH); + + // Set file pointer to the m_nSignatureContentOffset, we're ready to overwrite PKCS7 object + nWritten = 0; + CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset)) ); + m_aFile.write(cms_hexbuffer.getStr(), cms_hexbuffer.getLength(), nWritten); + + CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, nOffset)) ); + return true; + +#else + + // Prepare buffer and calculate PDF file digest + CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, 0)) ); + + std::unique_ptr<char[]> buffer1(new char[m_nSignatureContentOffset - 1]); + sal_uInt64 bytesRead1; + + if (osl::File::E_None != m_aFile.read(buffer1.get(), m_nSignatureContentOffset - 1 , bytesRead1) || + bytesRead1 != (sal_uInt64)m_nSignatureContentOffset - 1) + { + SAL_WARN("vcl.pdfwriter", "First buffer read failed"); + return false; + } + + std::unique_ptr<char[]> buffer2(new char[nLastByteRangeNo]); + sal_uInt64 bytesRead2; + + if (osl::File::E_None != m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1) || + osl::File::E_None != m_aFile.read(buffer2.get(), nLastByteRangeNo, bytesRead2) || + bytesRead2 != (sal_uInt64) nLastByteRangeNo) + { + SAL_WARN("vcl.pdfwriter", "Second buffer read failed"); + return false; + } + OStringBuffer cms_hexbuffer; + PDFWriter::PDFSignContext aSignContext(cms_hexbuffer); + aSignContext.m_pDerEncoded = n_derArray; + aSignContext.m_nDerEncoded = n_derLength; + aSignContext.m_pByteRange1 = buffer1.get(); + aSignContext.m_nByteRange1 = bytesRead1; + aSignContext.m_pByteRange2 = buffer2.get(); + aSignContext.m_nByteRange2 = bytesRead2; + aSignContext.m_aSignTSA = m_aContext.SignTSA; + aSignContext.m_aSignPassword = m_aContext.SignPassword; + if (!PDFWriter::Sign(aSignContext)) + { + SAL_WARN("vcl.pdfwriter", "PDFWriter::Sign() failed"); + return false; + } - for (unsigned int i = 0; i < nSigLen ; i++) - appendHex(pSig[i], cms_hexbuffer); + assert(cms_hexbuffer.getLength() <= MAX_SIGNATURE_CONTENT_LENGTH); // Set file pointer to the m_nSignatureContentOffset, we're ready to overwrite PKCS7 object nWritten = 0; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits