git.iko.soy/typeable/entropy
on main help sign in
Separate system and HW entropy sources.
16309d3Thomas M. DuBuisson
README.md+19−3
@@ -1,9 +1,25 @@
1# Introduction
1# Introduction
2
2
3−This package allows Haskell users to easily acquire entropy for use in
3+This package allows Haskell users to easily acquire entropy for use in critical
4−critical security applications by calling out to either windows crypto api,
4+security applications by calling out to either windows crypto api, unix/linux's
5−unix/linux's `/dev/urandom`, or the RDRAND instruction.
5+`/dev/urandom`. Hardware RNGs (currently RDRAND, patches welcome) are supported
6+via the `hardwareRNG` function.
7+
8+If you wish to obtain an XOR of the hardware and system RNG consider:
9+
10+```
11+import Data.Bits (xor)
12+import qualified Data.ByteString as B
13+import qualified Control.Exception as X
14+
15+xorRNG sz = do hw <- hardwareRNG sz
16+ h <- openHandle
17+ sys <- hGetEntropy h `X.finally` closeHandle h
18+ pure $ B.pack $ B.zipWith xor hw sys
19+```
6
20
7This package supports Windows, {li,u}nix, QNX, and has preliminary support for HaLVM.
21This package supports Windows, {li,u}nix, QNX, and has preliminary support for HaLVM.
8
22
23+Typically tested on Linux and OSX - testers are as welcome as patches.
24+
9[![Build Status](https://travis-ci.org/TomMD/entropy.svg?branch=master)](https://travis-ci.org/TomMD/entropy)
25[![Build Status](https://travis-ci.org/TomMD/entropy.svg?branch=master)](https://travis-ci.org/TomMD/entropy)
System/EntropyNix.hs+19−21
@@ -13,6 +13,7 @@ module System.EntropyNix
13 , openHandle
13 , openHandle
14 , hGetEntropy
14 , hGetEntropy
15 , closeHandle
15 , closeHandle
16+ , hardwareRNG
16 ) where
17 ) where
17
18
18import Control.Monad (liftM, when)
19import Control.Monad (liftM, when)
@@ -38,20 +39,29 @@ source = "/dev/urandom"
38-- |Handle for manual resource management
39-- |Handle for manual resource management
39data CryptHandle
40data CryptHandle
40 = CH Fd
41 = CH Fd
42+
43+-- | Get random values from the hardward RNG or return Nothing if no
44+-- supported hardware RNG is available.
45+--
46+-- Supported hardware:
47+-- * RDRAND
48+-- * Patches welcome
49+hardwareRNG :: Int -> IO (Maybe B.ByteString)
41#ifdef HAVE_RDRAND
50#ifdef HAVE_RDRAND
42− | UseRdRand Fd
51+hardwareRNG n =
52+ do b <- cpuHasRdRand
53+ if b
54+ then Just <$> B.create n (\ptr ->
55+ do r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
56+ when (r /= 0) (fail "RDRand failed to gather entropy"))
57+ else pure Nothing
58+#else
59+hardwareRNG _ = pure Nothing
43#endif
60#endif
44
61
45-- |Open a `CryptHandle`
62-- |Open a `CryptHandle`
46openHandle :: IO CryptHandle
63openHandle :: IO CryptHandle
47−openHandle = do
48−#ifdef HAVE_RDRAND
49− b <- cpuHasRdRand
50− if b then UseRdRand `fmap` nonRDRandHandle
51− else CH `fmap` nonRDRandHandle
52−#else
53− CH `fmap` nonRDRandHandle
64+openHandle = do CH `fmap` nonRDRandHandle
54−#endif
55 where
65 where
56 nonRDRandHandle :: IO Fd
66 nonRDRandHandle :: IO Fd
57 nonRDRandHandle = openFd source ReadOnly Nothing defaultFileFlags
67 nonRDRandHandle = openFd source ReadOnly Nothing defaultFileFlags
@@ -59,22 +69,10 @@ openHandle = do
59-- |Close the `CryptHandle`
69-- |Close the `CryptHandle`
60closeHandle :: CryptHandle -> IO ()
70closeHandle :: CryptHandle -> IO ()
61closeHandle (CH h) = closeFd h
71closeHandle (CH h) = closeFd h
62−#ifdef HAVE_RDRAND
63−closeHandle (UseRdRand h) = closeFd h
64−#endif
65
72
66-- |Read random data from a `CryptHandle`
73-- |Read random data from a `CryptHandle`
67hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
74hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
68hGetEntropy (CH h) = fdReadBS h
75hGetEntropy (CH h) = fdReadBS h
69−#ifdef HAVE_RDRAND
70−hGetEntropy (UseRdRand h) = \n ->
71− do bsURandom <- fdReadBS h n
72− bsRDRAND <- B.create n $ \ptr -> do
73− r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
74− when (r /= 0)
75− (fail "RDRand failed to gather entropy")
76− return $ B.pack $ B.zipWith xor bsURandom bsRDRAND
77−#endif
78
76
79fdReadBS :: Fd -> Int -> IO B.ByteString
77fdReadBS :: Fd -> Int -> IO B.ByteString
80fdReadBS fd n =
78fdReadBS fd n =
System/EntropyWindows.hs+21−21
@@ -4,7 +4,7 @@
4 Stability: beta
4 Stability: beta
5 Portability: portable
5 Portability: portable
6
6
7− Obtain entropy from system sources or x86 RDRAND when available.
7+ Obtain entropy from system sources.
8-}
8-}
9
9
10module System.EntropyWindows
10module System.EntropyWindows
@@ -12,6 +12,7 @@ module System.EntropyWindows
12 , openHandle
12 , openHandle
13 , hGetEntropy
13 , hGetEntropy
14 , closeHandle
14 , closeHandle
15+ , hardwareRNG
15 ) where
16 ) where
16
17
17import Control.Monad (liftM, when)
18import Control.Monad (liftM, when)
@@ -64,8 +65,25 @@ cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
64
65
65data CryptHandle
66data CryptHandle
66 = CH Word32
67 = CH Word32
68+
69+
70+-- | Get random values from the hardward RNG or return Nothing if no
71+-- supported hardware RNG is available.
72+--
73+-- Supported hardware:
74+-- * RDRAND
75+-- * Patches welcome
76+hardwareRNG :: Int -> IO (Maybe B.ByteString)
67#ifdef HAVE_RDRAND
77#ifdef HAVE_RDRAND
68− | UseRdRand Word32
78+hardwareRNG n =
79+ do b <- cpuHasRdRand
80+ if b
81+ then Just <$> BI.create n (\ptr ->
82+ do r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
83+ when (r /= 0) (fail "RDRand failed to gather entropy"))
84+ else pure Nothing
85+#else
86+hardwareRNG _ = pure Nothing
69#endif
87#endif
70
88
71-- Define the constants we need from WinCrypt.h
89-- Define the constants we need from WinCrypt.h
@@ -110,30 +128,12 @@ cryptReleaseCtx h = do
110
128
111-- |Open a handle from which random data can be read
129-- |Open a handle from which random data can be read
112openHandle :: IO CryptHandle
130openHandle :: IO CryptHandle
113−openHandle = do
114−#ifdef HAVE_RDRAND
115− b <- cpuHasRdRand
116− if b then UseRdRand `fmap` cryptAcquireCtx
117− else do
118−#endif
119− CH `fmap` cryptAcquireCtx
131+openHandle = CH `fmap` cryptAcquireCtx
120
132
121-- |Close the `CryptHandle`
133-- |Close the `CryptHandle`
122closeHandle :: CryptHandle -> IO ()
134closeHandle :: CryptHandle -> IO ()
123closeHandle (CH h) = cryptReleaseCtx h
135closeHandle (CH h) = cryptReleaseCtx h
124−#ifdef HAVE_RDRAND
125−closeHandle (UseRdRand h) = cryptReleaseCtx h
126−#endif
127
136
128-- |Read from `CryptHandle`
137-- |Read from `CryptHandle`
129hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
138hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
130hGetEntropy (CH h) n = cryptGenRandom h n
139hGetEntropy (CH h) n = cryptGenRandom h n
131−#ifdef HAVE_RDRAND
132−hGetEntropy (UseRdRand h) n =
133− do bsRDRAND <- BI.create n $ \ptr -> do
134− r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
135− when (r /= 0)
136− (fail "RDRand failed to gather entropy")
137− bsWinCrypt <- cryptGenRandom h n
138− return $ B.pack $ B.zipWith xor bsRDRAND bsWinCrypt
139−#endif
System/EntropyXen.hs+12−2
@@ -4,7 +4,7 @@
4 Stability: beta
4 Stability: beta
5 Portability: portable
5 Portability: portable
6
6
7− Obtain entropy from system sources or x86 RDRAND when available.
7+ Obtain entropy from RDRAND when available.
8
8
9-}
9-}
10
10
@@ -13,6 +13,7 @@ module System.EntropyXen
13 , openHandle
13 , openHandle
14 , hGetEntropy
14 , hGetEntropy
15 , closeHandle
15 , closeHandle
16+ , hardwardRNG
16 ) where
17 ) where
17
18
18import Control.Monad (liftM, when)
19import Control.Monad (liftM, when)
@@ -48,7 +49,16 @@ openHandle = do
48closeHandle :: CryptHandle -> IO ()
49closeHandle :: CryptHandle -> IO ()
49closeHandle UseRdRand = return ()
50closeHandle UseRdRand = return ()
50
51
52+-- | Get random values from the hardward RNG or return Nothing if no
53+-- supported hardware RNG is available.
54+--
55+-- Supported hardware:
56+-- * RDRAND
57+-- * Patches welcome
58+hardwareRNG :: Int -> IO (Maybe B.ByteString)
59+hardwareRNG sz = Just <$> hGetEntropy UseRdRand sz
60+
51−-- |Read random data from a `CryptHandle`
61+-- |Read random data from a `CryptHandle`, which uses RDRAND (when on Xen)
52hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
62hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
53hGetEntropy UseRdRand = \n -> do
63hGetEntropy UseRdRand = \n -> do
54 B.create n $ \ptr -> do
64 B.create n $ \ptr -> do
entropy.cabal+3−3
@@ -1,5 +1,5 @@
1name: entropy
1name: entropy
2−version: 0.3.8
2+version: 0.4
3description: A platform independent method to obtain cryptographically strong entropy
3description: A platform independent method to obtain cryptographically strong entropy
4 (RDRAND when available anywhere, urandom on nix, CryptAPI on Windows, patches welcome)
4 (RDRAND when available anywhere, urandom on nix, CryptAPI on Windows, patches welcome)
5 Users looking for cryptographically strong (number-theoretically
5 Users looking for cryptographically strong (number-theoretically
@@ -16,10 +16,10 @@ bug-reports: https://github.com/TomMD/entropy/issues
16stability: stable
16stability: stable
17-- build-type: Simple
17-- build-type: Simple
18-- ^^ Used for HaLVM
18-- ^^ Used for HaLVM
19−build-type: Custom
19+build-type: Custom
20-- ^^ Test for RDRAND support using 'ghc'
20-- ^^ Test for RDRAND support using 'ghc'
21cabal-version: >=1.10
21cabal-version: >=1.10
22−tested-with: GHC == 7.8.2
22+tested-with: GHC == 8.2.1
23-- data-files:
23-- data-files:
24extra-source-files: ./cbits/rdrand.c, ./cbits/rdrand.h, README.md
24extra-source-files: ./cbits/rdrand.c, ./cbits/rdrand.h, README.md
25
25