diff --git a/ChangeLog b/ChangeLog index 522c80a0..8d93eaee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-01-14 Jay Berkenbilt + * Fix for Windows being unable to acquire crypt context with a new + keyset. Thanks to Cloudmersive for the fix. Fixes #387. + * Rewrite fix-qdf in C++. This means fix-qdf is a proper executable now, and there is no longer a runtime requirement on perl. diff --git a/libqpdf/SecureRandomDataProvider.cc b/libqpdf/SecureRandomDataProvider.cc index 86fb3752..fe2c93f9 100644 --- a/libqpdf/SecureRandomDataProvider.cc +++ b/libqpdf/SecureRandomDataProvider.cc @@ -46,7 +46,7 @@ class WindowsCryptProvider "Container", NULL, PROV_RSA_FULL, - 0)) + CRYPT_MACHINE_KEYSET)) { #if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \ defined(__clang__)) @@ -56,28 +56,46 @@ class WindowsCryptProvider # pragma GCC diagnostic ignored "-Wsign-conversion" #endif if (GetLastError() == NTE_BAD_KEYSET) -#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \ - defined(__clang__)) -# pragma GCC diagnostic pop -#endif { if (! CryptAcquireContext(&crypt_prov, "Container", NULL, PROV_RSA_FULL, - CRYPT_NEWKEYSET)) + CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET)) { throw std::runtime_error( "unable to acquire crypt context with new keyset: " + getErrorMessage()); } } + else if (GetLastError() == NTE_EXISTS) + { + throw std::runtime_error( + "unable to acquire crypt context; the key container" + " already exists, but you are attempting to create it." + " If a previous attempt to open the key failed with" + " NTE_BAD_KEYSET, it implies that access to the key" + " container is denied. Error: " + getErrorMessage()); + } + else if (GetLastError() == NTE_KEYSET_NOT_DEF) + { + throw std::runtime_error( + "unable to acquire crypt context; the Crypto Service" + " Provider (CSP) may not be set up correctly. Use of" + " Regsvr32.exe on CSP DLLs (Rsabase.dll or Rsaenh.dll)" + " may fix the problem, depending on the provider being" + " used. Error: " + getErrorMessage()); + } else { throw std::runtime_error( "unable to acquire crypt context: " + getErrorMessage()); } +#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \ + defined(__clang__)) +# pragma GCC diagnostic pop +#endif } } ~WindowsCryptProvider()