git.iko.soy/typeable/entropy
on main help sign in
Add build-time configuration to check for RDRAND support.
7d267f3Thomas M. DuBuisson
Setup.hs+47−1
@@ -1,2 +1,48 @@
1import Distribution.Simple
1import Distribution.Simple
2−main = defaultMain
2+import Distribution.Simple.LocalBuildInfo
3+import Distribution.Simple.Setup
4+import Distribution.PackageDescription
5+import Distribution.Simple.Utils
6+import Distribution.Simple.Program
7+import Distribution.Verbosity
8+import System.Process
9+import System.Directory
10+import System.FilePath
11+import System.Exit
12+
13+main = defaultMainWithHooks hk
14+ where
15+ hk = simpleUserHooks { buildHook = \pd lbi uh bf -> do
16+ let ccProg = Program "gcc" undefined undefined undefined
17+ mConf = lookupProgram ccProg (withPrograms lbi)
18+ err = error "Could not determine C compiler"
19+ cc = locationPath . programLocation . maybe err id $ mConf
20+ b <- canUseRDRAND cc
21+ let newWithPrograms1 = userSpecifyArgs "gcc" cArgs (withPrograms lbi)
22+ newWithPrograms = userSpecifyArgs "ghc" cArgsHC newWithPrograms1
23+ lbiNew = if b then (lbi {withPrograms = newWithPrograms }) else lbi
24+ buildHook simpleUserHooks pd lbiNew uh bf
25+ }
26+
27+cArgs :: [String]
28+cArgs = ["-DHAVE_RDRAND"]
29+
30+cArgsHC :: [String]
31+cArgsHC = map ("-optc" ++) cArgs
32+
33+canUseRDRAND :: FilePath -> IO Bool
34+canUseRDRAND cc = do
35+ withTempDirectory normal "" "testRDRAND" $ \tmpDir -> do
36+ writeFile (tmpDir ++ "/testRDRAND.c")
37+ (unlines [ "#include <stdint.h>"
38+ , "int main() {"
39+ , " uint64_t therand;"
40+ , " unsigned char err;"
41+ , " asm volatile(\"rdrand %0 ; setc %1\""
42+ , " : \"=r\" (therand), \"=qm\" (err));"
43+ , " return (!err);"
44+ , "}"
45+ ])
46+ ec <- rawSystemExitCode normal cc [tmpDir </> "testRDRAND.c", "-o" ++ tmpDir ++ "/a.out"]
47+ notice normal $ "Result of RDRAND Test: " ++ show (ec == ExitSuccess)
48+ return (ec == ExitSuccess)
System/Entropy.hs+11−12
@@ -47,7 +47,7 @@ import Foreign.Marshal.Alloc (alloca)
47import Foreign.Marshal.Utils (toBool)
47import Foreign.Marshal.Utils (toBool)
48import Foreign.Storable (peek)
48import Foreign.Storable (peek)
49
49
50−#ifdef arch_x86_64
50+#ifdef HAVE_RDRAND
51foreign import ccall unsafe "cpu_has_rdrand"
51foreign import ccall unsafe "cpu_has_rdrand"
52 c_cpu_has_rdrand :: IO CInt
52 c_cpu_has_rdrand :: IO CInt
53
53
@@ -60,7 +60,7 @@ cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
60
60
61data CryptHandle
61data CryptHandle
62 = CH Word32
62 = CH Word32
63−#ifdef arch_x86_64
63+#ifdef HAVE_RDRAND
64 | UseRdRand
64 | UseRdRand
65#endif
65#endif
66
66
@@ -111,7 +111,7 @@ cryptReleaseCtx h = do
111-- on platforms without a secure RNG!
111-- on platforms without a secure RNG!
112getEntropy :: Int -> IO B.ByteString
112getEntropy :: Int -> IO B.ByteString
113getEntropy n = do
113getEntropy n = do
114−#ifdef arch_x86_64
114+#ifdef HAVE_RDRAND
115 b <- cpuHasRdRand
115 b <- cpuHasRdRand
116 if b then hGetEntropy UseRdRand n
116 if b then hGetEntropy UseRdRand n
117 else do
117 else do
@@ -125,7 +125,7 @@ getEntropy n = do
125-- |Open a handle from which random data can be read
125-- |Open a handle from which random data can be read
126openHandle :: IO CryptHandle
126openHandle :: IO CryptHandle
127openHandle = do
127openHandle = do
128−#ifdef arch_x86_64
128+#ifdef HAVE_RDRAND
129 b <- cpuHasRdRand
129 b <- cpuHasRdRand
130 if b then return UseRdRand
130 if b then return UseRdRand
131 else do
131 else do
@@ -138,7 +138,7 @@ closeHandle (CH h) = cryptReleaseCtx h
138-- |Read from `CryptHandle`
138-- |Read from `CryptHandle`
139hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
139hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
140hGetEntropy (CH h) = cryptGenRandom h
140hGetEntropy (CH h) = cryptGenRandom h
141−#ifdef arch_x86_64
141+#ifdef HAVE_RDRAND
142hGetEntropy UseRdRand =
142hGetEntropy UseRdRand =
143 B.create n $ \ptr -> do
143 B.create n $ \ptr -> do
144 r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
144 r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
@@ -150,7 +150,6 @@ hGetEntropy UseRdRand =
150{- Not windows, assuming nix with a /dev/urandom -}
150{- Not windows, assuming nix with a /dev/urandom -}
151import Foreign.C.Types
151import Foreign.C.Types
152import Foreign.Ptr
152import Foreign.Ptr
153−import Data.ByteString.Internal as B
154
153
155source :: FilePath
154source :: FilePath
156source = "/dev/urandom"
155source = "/dev/urandom"
@@ -158,14 +157,14 @@ source = "/dev/urandom"
158-- |Handle for manual resource mangement
157-- |Handle for manual resource mangement
159data CryptHandle
158data CryptHandle
160 = CH Handle
159 = CH Handle
161−#ifdef arch_x86_64
160+#ifdef HAVE_RDRAND
162 | UseRdRand
161 | UseRdRand
163#endif
162#endif
164
163
165-- |Open a `CryptHandle`
164-- |Open a `CryptHandle`
166openHandle :: IO CryptHandle
165openHandle :: IO CryptHandle
167openHandle = do
166openHandle = do
168−#ifdef arch_x86_64
167+#ifdef HAVE_RDRAND
169 b <- cpuHasRdRand
168 b <- cpuHasRdRand
170 if b then return UseRdRand
169 if b then return UseRdRand
171 else do
170 else do
@@ -175,14 +174,14 @@ openHandle = do
175-- |Close the `CryptHandle`
174-- |Close the `CryptHandle`
176closeHandle :: CryptHandle -> IO ()
175closeHandle :: CryptHandle -> IO ()
177closeHandle (CH h) = hClose h
176closeHandle (CH h) = hClose h
178−#ifdef arch_x86_64
177+#ifdef HAVE_RDRAND
179closeHandle UseRdRand = return ()
178closeHandle UseRdRand = return ()
180#endif
179#endif
181
180
182-- |Read random data from a `CryptHandle`
181-- |Read random data from a `CryptHandle`
183hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
182hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
184hGetEntropy (CH h) = B.hGet h
183hGetEntropy (CH h) = B.hGet h
185−#ifdef arch_x86_64
184+#ifdef HAVE_RDRAND
186hGetEntropy UseRdRand = \n -> do
185hGetEntropy UseRdRand = \n -> do
187 B.create n $ \ptr -> do
186 B.create n $ \ptr -> do
188 r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
187 r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
@@ -190,7 +189,7 @@ hGetEntropy UseRdRand = \n -> do
190 (fail "RDRand failed to gather entropy")
189 (fail "RDRand failed to gather entropy")
191#endif
190#endif
192
191
193−#ifdef arch_x86_64
192+#ifdef HAVE_RDRAND
194foreign import ccall unsafe "cpu_has_rdrand"
193foreign import ccall unsafe "cpu_has_rdrand"
195 c_cpu_has_rdrand :: IO CInt
194 c_cpu_has_rdrand :: IO CInt
196
195
@@ -209,7 +208,7 @@ cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
209-- entropy.
208-- entropy.
210getEntropy :: Int -> IO B.ByteString
209getEntropy :: Int -> IO B.ByteString
211getEntropy n = do
210getEntropy n = do
212−#if arch_x86_64
211+#ifdef HAVE_RDRAND
213 b <- cpuHasRdRand
212 b <- cpuHasRdRand
214 if b then hGetEntropy UseRdRand n
213 if b then hGetEntropy UseRdRand n
215 else do
214 else do
cbits/rdrand.c+4
@@ -1,3 +1,5 @@
1+#ifdef HAVE_RDRAND
2+
1#include <stdint.h>
3#include <stdint.h>
2#include <stdlib.h>
4#include <stdlib.h>
3
5
@@ -49,3 +51,5 @@ int get_rand_bytes(uint8_t *therand, size_t len)
49 }
51 }
50 return fail;
52 return fail;
51}
53}
54+
55+#endif // RDRAND
cbits/rdrand.h+2
@@ -1,4 +1,5 @@
1#ifndef rdrand_h
1#ifndef rdrand_h
2+#ifdef HAVE_RDRAND
2#include <stdint.h>
3#include <stdint.h>
3
4
4#ifdef arch_x86_64
5#ifdef arch_x86_64
@@ -7,4 +8,5 @@ int cpu_has_rdrand()
7// Returns 0 on success, non-zero on failure.
8// Returns 0 on success, non-zero on failure.
8int get_rand_bytes(uint8_t *therand, size_t len)
9int get_rand_bytes(uint8_t *therand, size_t len)
9#endif /* arch_x86_64 */
10#endif /* arch_x86_64 */
11+#endif // HAVE_RDRAND
10#endif // rdrand_h
12#endif // rdrand_h
entropy.cabal+1−1
@@ -14,7 +14,7 @@ category: Data, Cryptography
14homepage: https://github.com/TomMD/entropy
14homepage: https://github.com/TomMD/entropy
15bug-reports: https://github.com/TomMD/entropy/issues
15bug-reports: https://github.com/TomMD/entropy/issues
16stability: stable
16stability: stable
17−build-type: Simple
17+build-type: Custom
18cabal-version: >= 1.6
18cabal-version: >= 1.6
19tested-with: GHC == 6.12.1
19tested-with: GHC == 6.12.1
20data-files:
20data-files: