From cf43882e9fb55b66776b9fc6c812487d772d37ca Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 24 May 2015 15:41:28 -0400 Subject: [PATCH] Handle Microsoft crypt provider without prior keys As reported in issue #40, a call to CryptAcquireContext in SecureRandomDataProvider fails in a fresh windows install prior to any user keys being created in AppData\Roaming\Microsoft\Crypto\RSA. Thanks michalrames. --- ChangeLog | 4 ++++ libqpdf/SecureRandomDataProvider.cc | 35 +++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99c1690f..8220c9b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-05-24 Jay Berkenbilt + * Handle Microsoft crypt provider initialization properly for case + where no keys have been previously created, such as in a fresh + Windows installation. + * Include time.h in QUtil.hh for time_t 2015-02-21 Jay Berkenbilt diff --git a/libqpdf/SecureRandomDataProvider.cc b/libqpdf/SecureRandomDataProvider.cc index 2870ab98..0b0b6c73 100644 --- a/libqpdf/SecureRandomDataProvider.cc +++ b/libqpdf/SecureRandomDataProvider.cc @@ -42,9 +42,40 @@ class WindowsCryptProvider public: WindowsCryptProvider() { - if (! CryptAcquireContext(&crypt_prov, NULL, NULL, PROV_RSA_FULL, 0)) + if (!CryptAcquireContext(&crypt_prov, + "Container", + NULL, + PROV_RSA_FULL, + 0)) { - throw std::runtime_error("unable to acquire crypt context"); +#ifdef __GNUC__ +# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wold-style-cast" +# pragma GCC diagnostic ignored "-Wsign-compare" +# endif +#endif + if (GetLastError() == NTE_BAD_KEYSET) +#ifdef __GNUC__ +# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406 +# pragma GCC diagnostic pop +# endif +#endif + { + if (! CryptAcquireContext(&crypt_prov, + "Container", + NULL, + PROV_RSA_FULL, + CRYPT_NEWKEYSET)) + { + throw std::runtime_error( + "unable to acquire crypt context with new keyset"); + } + } + else + { + throw std::runtime_error("unable to acquire crypt context"); + } } } ~WindowsCryptProvider()