git.iko.soy/typeable/entropy
on main help sign in
Fix (?) the windows build
commitb8a00eed12b37a2359c088ddc1ff5e0ac11cc8e2 authorThomas M. DuBuisson <tommd@galois.com> dateSun 12 May 2013, 20:18 (13 years ago) parent406e8ae
1 file changed+43−8
System/Entropy.hs+43−8
System/Entropy.hs+43−8
@@ -41,12 +41,28 @@ import Data.ByteString.Internal as BI
4141import Data.Int (Int32)
4242import Data.Word (Word32, Word8)
4343import Foreign.C.String (CString, withCString)
44−import Foreign.Ptr (Ptr, nullPtr)
44+import Foreign.C.Types
45+import Foreign.Ptr (Ptr, nullPtr, castPtr)
4546import Foreign.Marshal.Alloc (alloca)
4647import Foreign.Marshal.Utils (toBool)
4748import Foreign.Storable (peek)
4849
49−newtype CryptHandle = CH Word32
50+#ifdef arch_x86_64
51+foreign import ccall unsafe "cpu_has_rdrand"
52+ c_cpu_has_rdrand :: IO CInt
53+
54+foreign import ccall unsafe "get_rand_bytes"
55+ c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
56+
57+cpuHasRdRand :: IO Bool
58+cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
59+#endif
60+
61+newtype CryptHandle
62+ = CH Word32
63+#ifdef arch_x86_64
64+ | UseRdRand
65+#endif
5066
5167-- Define the constants we need from WinCrypt.h
5268msDefProv :: String
@@ -95,6 +111,11 @@ cryptReleaseCtx h = do
95111-- on platforms without a secure RNG!
96112getEntropy :: Int -> IO B.ByteString
97113getEntropy n = do
114+#ifdef arch_x86_64
115+ b <- cpuHasRdRand
116+ if b then hGetEntropy UseRdRand n
117+ else do
118+#endif
98119 h <- cryptAcquireCtx
99120 bs <- cryptGenRandom h n
100121 let !bs' = bs
@@ -103,7 +124,13 @@ getEntropy n = do
103124
104125-- |Open a handle from which random data can be read
105126openHandle :: IO CryptHandle
106−openHandle = liftM CH cryptAcquireCtx
127+openHandle = do
128+#ifdef arch_x86_64
129+ b <- cpuHasRdRand
130+ if b then return UseRdRand
131+ else do
132+#endif
133+ liftM CH cryptAcquireCtx
107134
108135-- |Close the `CryptHandle`
109136closeHandle (CH h) = cryptReleaseCtx h
@@ -111,6 +138,13 @@ closeHandle (CH h) = cryptReleaseCtx h
111138-- |Read from `CryptHandle`
112139hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
113140hGetEntropy (CH h) = cryptGenRandom h
141+#ifdef arch_x86_64
142+hGetEntropy UseRdRand =
143+ B.create n $ \ptr -> do
144+ r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
145+ when (r /= 0)
146+ (fail "RDRand failed to gather entropy")
147+#endif
114148
115149#else
116150{- Not windows, assuming nix with a /dev/urandom -}
@@ -122,7 +156,11 @@ source :: FilePath
122156source = "/dev/urandom"
123157
124158-- |Handle for manual resource mangement
125−data CryptHandle = CH Handle | UseRdRand
159+data CryptHandle
160+ = CH Handle
161+#ifdef arch_x86_64
162+ | UseRdRand
163+#endif
126164
127165-- |Open a `CryptHandle`
128166openHandle :: IO CryptHandle
@@ -173,10 +211,7 @@ getEntropy :: Int -> IO B.ByteString
173211getEntropy n = do
174212#if arch_x86_64
175213 b <- cpuHasRdRand
176− if b then B.create n $ \ptr -> do
177− r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
178− when (r /= 0)
179− (fail "RDRand failed to gather entropy")
214+ if b then hGetEntropy UseRdRand n
180215 else do
181216#endif
182217{- arch_x86 -}