summaryrefslogtreecommitdiff
path: root/vcl/source
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2015-02-26 21:14:38 +0200
committerAndras Timar <andras.timar@collabora.com>2015-03-05 16:46:04 +0100
commitc54a53d96d1280e86ef55c69bab7fa99f67b3314 (patch)
tree80625272b43bf817ffa940852a3d1300441f23da /vcl/source
parente3c43448136f7d422a25e37bf51aabda1913f643 (diff)
tdf#84881: Add Windows implementation of timestamping of signature
Luckily doable with much simpler code than the horrible NSS and curl mess used on Linux (and, sadly, OS X). Basically only one new API call needed: CryptRetrieveTimestamp(). A few hours of work, compared to about a week for the Linux case. However, amusingly, it causes the same message in Adobe Reader as when using the NSS code: "The signature includes an embedded timestamp but it could not be verified". Sigh. Change-Id: I98c973bd50b841d1ae3feb8a695bac29da538b6c (cherry picked from commit 00646102569739e0bf8929c271963f129d747a5a)
Diffstat (limited to 'vcl/source')
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx122
1 files changed, 122 insertions, 0 deletions
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 4b884bf8e5b6..b07859c69f58 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6719,6 +6719,17 @@ NSSCMSMessage *CreateCMSMessage(PRTime time,
#ifdef _WIN32
+typedef BOOL (WINAPI *PointerTo_CryptRetrieveTimeStamp)(LPCWSTR wszUrl,
+ DWORD dwRetrievalFlags,
+ DWORD dwTimeout,
+ LPCSTR pszHashId,
+ const CRYPT_TIMESTAMP_PARA *pPara,
+ const BYTE *pbData,
+ DWORD cbData,
+ PCRYPT_TIMESTAMP_CONTEXT *ppTsContext,
+ PCCERT_CONTEXT *ppTsSigner,
+ HCERTSTORE phStore);
+
namespace {
OUString WindowsError(DWORD nErrorCode)
@@ -7279,6 +7290,117 @@ bool PDFWriterImpl::finalizeSignature()
return false;
}
+#ifdef DBG_UTIL
+ {
+ FILE *out = fopen("PDFWRITER.signature.data", "wb");
+ fwrite(pSig.get(), nSigLen, 1, out);
+ fclose(out);
+ }
+#endif
+
+ if( !m_aContext.SignTSA.isEmpty() )
+ {
+ PointerTo_CryptRetrieveTimeStamp crts = (PointerTo_CryptRetrieveTimeStamp) GetProcAddress(LoadLibrary("crypt32.dll"), "CryptRetrieveTimeStamp");
+ if (!crts)
+ {
+ SAL_WARN("vcl.pdfwriter", "Could not find the CryptRetrieveTimeStamp function in crypt32.dll: " << WindowsError(GetLastError()));
+ CertFreeCertificateContext(pCertContext);
+ return false;
+ }
+ else
+ {
+ CRYPT_TIMESTAMP_PARA aTsPara;
+
+ unsigned int nNonce = comphelper::rng::uniform_uint_distribution(0, SAL_MAX_UINT32);
+
+ aTsPara.pszTSAPolicyId = NULL;
+ aTsPara.fRequestCerts = TRUE;
+ aTsPara.Nonce.cbData = sizeof(nNonce);
+ aTsPara.Nonce.pbData = (BYTE *)&nNonce;
+ aTsPara.cExtension = 0;
+ aTsPara.rgExtension = NULL;
+
+ PCRYPT_TIMESTAMP_CONTEXT pTsContext = NULL;
+
+ if (!(*crts)(m_aContext.SignTSA.getStr(),
+ 0,
+ 10000,
+ szOID_NIST_sha256,
+ &aTsPara,
+ pSig.get(),
+ nSigLen,
+ &pTsContext,
+ NULL,
+ NULL))
+ {
+ SAL_WARN("vcl.pdfwriter", "CryptRetrieveTimeStamp failed: " << WindowsError(GetLastError()));
+ CertFreeCertificateContext(pCertContext);
+ return false;
+ }
+
+ SAL_INFO("vcl.pdfwriter", "Time stamp size is " << pTsContext->cbEncoded << " bytes");
+
+#ifdef DBG_UTIL
+ {
+ FILE *out = fopen("PDFWRITER.tstoken.data", "wb");
+ fwrite(pTsContext->pbEncoded, pTsContext->cbEncoded, 1, out);
+ fclose(out);
+ }
+#endif
+
+ CRYPT_INTEGER_BLOB aTimestampBlob;
+ aTimestampBlob.cbData = pTsContext->cbEncoded;
+ aTimestampBlob.pbData = pTsContext->pbEncoded;
+
+ CRYPT_ATTRIBUTE aTimestampAttribute;
+ aTimestampAttribute.pszObjId = "1.2.840.113549.1.9.16.2.14";
+ aTimestampAttribute.cValue = 1;
+ aTimestampAttribute.rgValue = &aTimestampBlob;
+
+ aPara.cUnauthAttr = 1;
+ aPara.rgUnauthAttr = &aTimestampAttribute;
+
+ nSigLen = 0;
+ if (!CryptSignMessage(&aPara, TRUE, SAL_N_ELEMENTS(aBuffers), aBuffers, aBufferLens, NULL, &nSigLen))
+ {
+ SAL_WARN("vcl.pdfwriter", "CryptSignMessage failed: " << WindowsError(GetLastError()));
+ CryptMemFree(pTsContext);
+ CertFreeCertificateContext(pCertContext);
+ return false;
+ }
+
+ if (nSigLen*2 > MAX_SIGNATURE_CONTENT_LENGTH)
+ {
+ SAL_WARN("vcl.pdfwriter", "Signature requires more space (" << nSigLen*2 << ") than we reserved (" << MAX_SIGNATURE_CONTENT_LENGTH << ")");
+ CryptMemFree(pTsContext);
+ CertFreeCertificateContext(pCertContext);
+ return false;
+ }
+
+ SAL_INFO("vcl.pdfwriter", "Signature size including timestamp is " << nSigLen << " bytes");
+
+ pSig.reset(new BYTE[nSigLen]);
+
+ if (!CryptSignMessage(&aPara, TRUE, SAL_N_ELEMENTS(aBuffers), aBuffers, aBufferLens, pSig.get(), &nSigLen))
+ {
+ SAL_WARN("vcl.pdfwriter", "CryptSignMessage failed: " << WindowsError(GetLastError()));
+ CryptMemFree(pTsContext);
+ CertFreeCertificateContext(pCertContext);
+ return false;
+ }
+
+#ifdef DBG_UTIL
+ {
+ FILE *out = fopen("PDFWRITER.ts_signature.data", "wb");
+ fwrite(pSig.get(), nSigLen, 1, out);
+ fclose(out);
+ }
+#endif
+
+ CryptMemFree(pTsContext);
+ }
+ }
+
// Release resources
CertFreeCertificateContext(pCertContext);