summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2015-02-26 21:14:38 +0200
committerTor Lillqvist <tml@collabora.com>2015-02-26 21:44:17 +0200
commit00646102569739e0bf8929c271963f129d747a5a (patch)
treee2000432ac920ed4e69e2206a84b4034872ff0c3
parentf07e93c2b75fb22c16d1002d10c813c0c61dcfbb (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
-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 b300bc6e2235..b435e84978f1 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6752,6 +6752,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)
@@ -7311,6 +7322,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);