Handle creating the default crypto context if it doesn't already exist
authorChristopher Dykes <cdykes@fb.com>
Fri, 5 Aug 2016 16:49:03 +0000 (09:49 -0700)
committerFacebook Github Bot 7 <facebook-github-bot-7-bot@fb.com>
Fri, 5 Aug 2016 16:53:29 +0000 (09:53 -0700)
Summary: It's perfectly possible that the default crypto context simply hasn't been created yet, so try to create it if the initial acquisition fails.

Reviewed By: yfeldblum

Differential Revision: D3673138

fbshipit-source-id: 122955df04055ff4f99513b182375d4388dd0305

folly/Random.cpp

index c6b611be181346d5b489851b710f5af22a24a5f2..8f5e3128d2036952f31ba8efcc73791a139e333b 100644 (file)
@@ -42,8 +42,16 @@ void readRandomDevice(void* data, size_t size) {
   static folly::once_flag flag;
   static HCRYPTPROV cryptoProv;
   folly::call_once(flag, [&] {
-    PCHECK(CryptAcquireContext(&cryptoProv, nullptr, nullptr,
-                               PROV_RSA_FULL, 0));
+    if (!CryptAcquireContext(&cryptoProv, nullptr, nullptr, PROV_RSA_FULL, 0)) {
+      if (GetLastError() == NTE_BAD_KEYSET) {
+        // Mostly likely cause of this is that no key container
+        // exists yet, so try to create one.
+        PCHECK(CryptAcquireContext(
+            &cryptoProv, nullptr, nullptr, PROV_RSA_FULL, CRYPT_NEWKEYSET));
+      } else {
+        LOG(FATAL) << "Failed to acquire the default crypto context.";
+      }
+    }
   });
   CHECK(size <= std::numeric_limits<DWORD>::max());
   PCHECK(CryptGenRandom(cryptoProv, (DWORD)size, (BYTE*)data));