Commit a8b6ff5763ea85f124e6d2be962d0ed34586b7f8

Authored by Cloudmersive
Committed by Jay Berkenbilt
1 parent 73a0e3a9

Fix for Windows unable to acquire crypt context with new keyset (fixes #387)

Fix is based on guidance
https://support.microsoft.com/en-us/help/238187/cryptacquirecontext-use-and-troubleshooting
and is the proper fix for #285/#286
ChangeLog
1 1 2020-01-14 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Fix for Windows being unable to acquire crypt context with a new
  4 + keyset. Thanks to Cloudmersive for the fix. Fixes #387.
  5 +
3 6 * Rewrite fix-qdf in C++. This means fix-qdf is a proper
4 7 executable now, and there is no longer a runtime requirement on
5 8 perl.
... ...
libqpdf/SecureRandomDataProvider.cc
... ... @@ -46,7 +46,7 @@ class WindowsCryptProvider
46 46 "Container",
47 47 NULL,
48 48 PROV_RSA_FULL,
49   - 0))
  49 + CRYPT_MACHINE_KEYSET))
50 50 {
51 51 #if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
52 52 defined(__clang__))
... ... @@ -56,28 +56,46 @@ class WindowsCryptProvider
56 56 # pragma GCC diagnostic ignored "-Wsign-conversion"
57 57 #endif
58 58 if (GetLastError() == NTE_BAD_KEYSET)
59   -#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
60   - defined(__clang__))
61   -# pragma GCC diagnostic pop
62   -#endif
63 59 {
64 60 if (! CryptAcquireContext(&crypt_prov,
65 61 "Container",
66 62 NULL,
67 63 PROV_RSA_FULL,
68   - CRYPT_NEWKEYSET))
  64 + CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET))
69 65 {
70 66 throw std::runtime_error(
71 67 "unable to acquire crypt context with new keyset: " +
72 68 getErrorMessage());
73 69 }
74 70 }
  71 + else if (GetLastError() == NTE_EXISTS)
  72 + {
  73 + throw std::runtime_error(
  74 + "unable to acquire crypt context; the key container"
  75 + " already exists, but you are attempting to create it."
  76 + " If a previous attempt to open the key failed with"
  77 + " NTE_BAD_KEYSET, it implies that access to the key"
  78 + " container is denied. Error: " + getErrorMessage());
  79 + }
  80 + else if (GetLastError() == NTE_KEYSET_NOT_DEF)
  81 + {
  82 + throw std::runtime_error(
  83 + "unable to acquire crypt context; the Crypto Service"
  84 + " Provider (CSP) may not be set up correctly. Use of"
  85 + " Regsvr32.exe on CSP DLLs (Rsabase.dll or Rsaenh.dll)"
  86 + " may fix the problem, depending on the provider being"
  87 + " used. Error: " + getErrorMessage());
  88 + }
75 89 else
76 90 {
77 91 throw std::runtime_error(
78 92 "unable to acquire crypt context: " +
79 93 getErrorMessage());
80 94 }
  95 +#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
  96 + defined(__clang__))
  97 +# pragma GCC diagnostic pop
  98 +#endif
81 99 }
82 100 }
83 101 ~WindowsCryptProvider()
... ...