[Libreoffice-commits] core.git: vcl/source
Miklos Vajna
vmiklos at collabora.co.uk
Wed Nov 2 16:51:25 UTC 2016
vcl/source/gdi/pdfwriter_impl.cxx | 259 +++++++++++++++++++-------------------
1 file changed, 136 insertions(+), 123 deletions(-)
New commits:
commit 4f6028ad7610d36379aba36470e47e701f8a87d5
Author: Miklos Vajna <vmiklos at 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;
More information about the Libreoffice-commits
mailing list