git.iko.soy/typeable/entropy
on main help sign in
Merge pull request #4 from singpolyma/master
08931d0Thomas M. DuBuisson
System/Entropy.hs+21−16
@@ -16,9 +16,11 @@ module System.Entropy
16 , closeHandle
16 , closeHandle
17 ) where
17 ) where
18
18
19−import Control.Monad (liftM, when)
19+import Control.Monad (liftM)
20import Data.ByteString as B
20import Data.ByteString as B
21−import System.IO (openFile, hClose, IOMode(..), Handle, withBinaryFile)
21+import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString)
22+import System.Posix (openFd, closeFd, fdReadBuf, OpenMode(..), defaultFileFlags, Fd)
23+import Foreign (allocaBytes)
22
24
23#if defined(isWindows)
25#if defined(isWindows)
24{- C example for windows rng - taken from a blog, can't recall which one but thank you!
26{- C example for windows rng - taken from a blog, can't recall which one but thank you!
@@ -148,7 +150,6 @@ hGetEntropy UseRdRand =
148
150
149#else
151#else
150{- Not windows, assuming nix with a /dev/urandom -}
152{- Not windows, assuming nix with a /dev/urandom -}
151−import Foreign.C.Types
152import Foreign.Ptr
153import Foreign.Ptr
153
154
154source :: FilePath
155source :: FilePath
@@ -156,7 +157,7 @@ source = "/dev/urandom"
156
157
157-- |Handle for manual resource mangement
158-- |Handle for manual resource mangement
158data CryptHandle
159data CryptHandle
159− = CH Handle
160+ = CH Fd
160#ifdef HAVE_RDRAND
161#ifdef HAVE_RDRAND
161 | UseRdRand
162 | UseRdRand
162#endif
163#endif
@@ -169,18 +170,26 @@ openHandle = do
169 if b then return UseRdRand
170 if b then return UseRdRand
170 else do
171 else do
171#endif
172#endif
172− liftM CH (openFile source ReadMode)
173+ liftM CH (openFd source ReadOnly Nothing defaultFileFlags)
173
174
174-- |Close the `CryptHandle`
175-- |Close the `CryptHandle`
175closeHandle :: CryptHandle -> IO ()
176closeHandle :: CryptHandle -> IO ()
176−closeHandle (CH h) = hClose h
177+closeHandle (CH h) = closeFd h
177#ifdef HAVE_RDRAND
178#ifdef HAVE_RDRAND
178closeHandle UseRdRand = return ()
179closeHandle UseRdRand = return ()
179#endif
180#endif
180
181
182+fdReadBS :: Fd -> Int -> IO B.ByteString
183+fdReadBS fd n = do
184+ allocaBytes n $ \buf -> do
185+ rc <- fdReadBuf fd buf (fromIntegral n)
186+ case rc of
187+ 0 -> ioError (ioeSetErrorString (mkIOError eofErrorType "fdRead" Nothing Nothing) "EOF")
188+ n' -> B.packCStringLen (castPtr buf, fromIntegral n')
189+
181-- |Read random data from a `CryptHandle`
190-- |Read random data from a `CryptHandle`
182−hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
191+hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
183−hGetEntropy (CH h) = B.hGet h
192+hGetEntropy (CH h) = fdReadBS h
184#ifdef HAVE_RDRAND
193#ifdef HAVE_RDRAND
185hGetEntropy UseRdRand = \n -> do
194hGetEntropy UseRdRand = \n -> do
186 B.create n $ \ptr -> do
195 B.create n $ \ptr -> do
@@ -208,13 +217,9 @@ cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
208-- entropy.
217-- entropy.
209getEntropy :: Int -> IO B.ByteString
218getEntropy :: Int -> IO B.ByteString
210getEntropy n = do
219getEntropy n = do
211−#ifdef HAVE_RDRAND
220+ h <- openHandle
212− b <- cpuHasRdRand
213− if b then hGetEntropy UseRdRand n
221+ e <- hGetEntropy h n
214− else do
222+ closeHandle h
215−#endif
223+ return e
216−{- arch_x86 -}
217− withBinaryFile source ReadMode (`B.hGet` n)
218#endif
224#endif
219{- OS Test -}
225{- OS Test -}
220−
entropy.cabal+2
@@ -34,6 +34,8 @@ Library
34 if os(windows)
34 if os(windows)
35 cpp-options: -DisWindows
35 cpp-options: -DisWindows
36 extra-libraries: advapi32
36 extra-libraries: advapi32
37+ else
38+ Build-Depends: unix
37
39
38source-repository head
40source-repository head
39 type: git
41 type: git