@@ -20,6 +20,7 @@ import Foreign (allocaBytes)
2020import Data.ByteString as B
2121import Data.ByteString.Internal as BI
2222import Data.Int (Int32)
23+import Data.Bits (xor)
2324import Data.Word (Word32, Word8)
2425import Foreign.C.String (CString, withCString)
2526import Foreign.C.Types
@@ -59,7 +60,7 @@ cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
5960data CryptHandle
6061 = CH Word32
6162#ifdef HAVE_RDRAND
62− | UseRdRand
63+ | UseRdRand Word32
6364#endif
6465
6566-- Define the constants we need from WinCrypt.h
@@ -107,22 +108,27 @@ openHandle :: IO CryptHandle
107108openHandle = do
108109#ifdef HAVE_RDRAND
109110 b <- cpuHasRdRand
110− if b then return UseRdRand
111+ if b then UseRdRand `fmap` cryptAcquireCtx
111112 else do
112113#endif
113− liftM CH cryptAcquireCtx
114+ CH `fmap` cryptAcquireCtx
114115
115116-- |Close the `CryptHandle`
116117closeHandle :: CryptHandle -> IO ()
117−closeHandle (CH h) = cryptReleaseCtx h
118+closeHandle (CH h) = cryptReleaseCtx h
119+#ifdef HAVE_RDRAND
120+closeHandle (UseRdRand h) = cryptReleaseCtx h
121+#endif
118122
119123-- |Read from `CryptHandle`
120124hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
121125hGetEntropy (CH h) n = cryptGenRandom h n
122126#ifdef HAVE_RDRAND
123−hGetEntropy UseRdRand n =
124− BI.create n $ \ptr -> do
125− r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
126− when (r /= 0)
127− (fail "RDRand failed to gather entropy")
127+hGetEntropy (UseRdRand h) n =
128+ do bsRDRAND <- BI.create n $ \ptr -> do
129+ r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
130+ when (r /= 0)
131+ (fail "RDRand failed to gather entropy")
132+ bsWinCrypt <- cryptGenRandom h n
133+ return $ B.pack $ B.zipWith xor bsRDRAND bsWinCrypt
128134#endif