@@ -122,19 +122,35 @@ source :: FilePath
122122source = "/dev/urandom"
123123
124124-- |Handle for manual resource mangement
125−newtype CryptHandle = CH Handle
125+data CryptHandle = CH Handle | UseRdRand
126126
127127-- |Open a `CryptHandle`
128128openHandle :: IO CryptHandle
129−openHandle = liftM CH (openFile source ReadMode)
129+openHandle = do
130+#ifdef arch_x86_64
131+ b <- cpuHasRdRand
132+ if b then return UseRdRand
133+ else do
134+#endif
135+ liftM CH (openFile source ReadMode)
130136
131137-- |Close the `CryptHandle`
132138closeHandle :: CryptHandle -> IO ()
133139closeHandle (CH h) = hClose h
140+#ifdef arch_x86_64
141+closeHandle UseRdRand = return ()
142+#endif
134143
135144-- |Read random data from a `CryptHandle`
136145hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
137146hGetEntropy (CH h) = B.hGet h
147+#ifdef arch_x86_64
148+hGetEntropy UseRdRand = \n -> do
149+ B.create n $ \ptr -> do
150+ r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
151+ when (r /= 0)
152+ (fail "RDRand failed to gather entropy")
153+#endif
138154
139155#ifdef arch_x86_64
140156foreign import ccall unsafe "cpu_has_rdrand"