diff options
author | Tor Lillqvist <tml@collabora.com> | 2015-02-26 21:14:38 +0200 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2015-03-05 16:46:04 +0100 |
commit | c54a53d96d1280e86ef55c69bab7fa99f67b3314 (patch) | |
tree | 80625272b43bf817ffa940852a3d1300441f23da /vcl/source | |
parent | e3c43448136f7d422a25e37bf51aabda1913f643 (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.cxx | 122 |
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); |