packages feed

entropy 0.3.8 → 0.4

raw patch · 6 files changed

+121/−64 lines, 6 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ System.Entropy: getHardwareEntropy :: Int -> IO (Maybe ByteString)

Files

README.md view
@@ -1,9 +1,25 @@ # Introduction -This package allows Haskell users to easily acquire entropy for use in-critical security applications by calling out to either windows crypto api,-unix/linux's `/dev/urandom`, or the RDRAND instruction.+This package allows Haskell users to easily acquire entropy for use in critical+security applications by calling out to either windows crypto api, unix/linux's+`/dev/urandom`. Hardware RNGs (currently RDRAND, patches welcome) are supported+via the `hardwareRNG` function. +If you wish to obtain an XOR of the hardware and system RNG consider:++```+import           Data.Bits (xor)+import qualified Data.ByteString as B+import qualified Control.Exception as X++xorRNG sz = do hw  <- hardwareRNG sz+               h   <- openHandle+               sys <- hGetEntropy h `X.finally` closeHandle h+               pure $ B.pack $ B.zipWith xor hw sys+```+ This package supports Windows, {li,u}nix, QNX, and has preliminary support for HaLVM.++Typically tested on Linux and OSX - testers are as welcome as patches.  [![Build Status](https://travis-ci.org/TomMD/entropy.svg?branch=master)](https://travis-ci.org/TomMD/entropy)
System/Entropy.hs view
@@ -16,18 +16,18 @@  module System.Entropy         ( getEntropy,-#if defined(isWindows)-         module System.EntropyWindows+          getHardwareEntropy,+          CryptHandle,+          openHandle,+          hGetEntropy,+          closeHandle         ) where+#if defined(isWindows) import System.EntropyWindows #else #ifdef XEN-         module System.EntropyXen-        ) where import System.EntropyXen #else-         module System.EntropyNix-        ) where import System.EntropyNix #endif #endif@@ -36,10 +36,42 @@ import Control.Exception (bracket)  -- |Get a specific number of bytes of cryptographically--- secure random data using the system-specific facilities.+-- secure random data using the *system-specific* sources. +-- (As of 0.4.  Verions <0.4 mixed system and hardware sources) ----- Use RDRAND if available and XOR with '/dev/urandom' on *nix and CryptAPI when on--- Windows.  In short, this entropy is considered cryptographically secure--- but not true entropy.-getEntropy :: Int -> IO B.ByteString+-- The returned random value is considered cryptographically secure but not true entropy.+--+-- On some platforms this requies a file handle which can lead to resource+-- exhaustion in some situations.+getEntropy :: Int               -- ^ Number of bytes+           -> IO B.ByteString getEntropy = bracket openHandle closeHandle . flip hGetEntropy++-- |Get a specific number of bytes of cryptographically+-- secure random data using a supported *hardware* random bit generator.+--+-- If there is no hardware random number generator then @Nothing@ is returned.+-- If any call returns non-Nothing then it should never be @Nothing@ unless+-- there has been a hardware failure.+--+-- If trust of the CPU allows it and no context switching is important,+-- a bias to the hardware rng with system rng as fall back is trivial:+--+-- @+-- let fastRandom nr = maybe (getEntropy nr) pure =<< getHardwareEntropy nr+-- @+--+-- The old, @<0.4@, behavior is possible using @xor@ from 'Data.Bits':+--+-- @+-- let oldRandom nr =+--      do hwRnd  <- maybe (replicate nr 0) BS.unpack <$> getHardwareEntropy nr+--         sysRnd <- BS.unpack <$> getEntropy nr+--         pure $ BS.pack $ zipWith xor sysRnd hwRnd+-- @+--+-- A less maliable mixing can be accomplished by replacing `xor` with a+-- composition of concat and cryptographic hash.+getHardwareEntropy :: Int                       -- ^ Number of bytes+                   -> IO (Maybe B.ByteString)+getHardwareEntropy = hardwareRandom
System/EntropyNix.hs view
@@ -13,6 +13,7 @@         , openHandle         , hGetEntropy         , closeHandle+        , hardwareRandom         ) where  import Control.Monad (liftM, when)@@ -38,20 +39,29 @@ -- |Handle for manual resource management data CryptHandle     = CH Fd++-- | Get random values from the hardward RNG or return Nothing if no+-- supported hardware RNG is available.+--+-- Supported hardware:+--      * RDRAND+--      * Patches welcome+hardwareRandom :: Int -> IO (Maybe B.ByteString) #ifdef HAVE_RDRAND-    | UseRdRand Fd+hardwareRandom n =+ do b <- cpuHasRdRand+    if b+     then Just <$> B.create n (\ptr ->+                      do r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)+                         when (r /= 0) (fail "RDRand failed to gather entropy"))+     else pure Nothing+#else+hardwareRandom _ = pure Nothing #endif  -- |Open a `CryptHandle` openHandle :: IO CryptHandle-openHandle = do-#ifdef HAVE_RDRAND-    b <- cpuHasRdRand-    if b then UseRdRand `fmap` nonRDRandHandle-         else CH `fmap` nonRDRandHandle-#else-              CH `fmap` nonRDRandHandle-#endif+openHandle = do CH `fmap` nonRDRandHandle  where   nonRDRandHandle :: IO Fd   nonRDRandHandle = openFd source ReadOnly Nothing defaultFileFlags@@ -59,22 +69,10 @@ -- |Close the `CryptHandle` closeHandle :: CryptHandle -> IO () closeHandle (CH h) = closeFd h-#ifdef HAVE_RDRAND-closeHandle (UseRdRand h) = closeFd h-#endif  -- |Read random data from a `CryptHandle` hGetEntropy :: CryptHandle -> Int -> IO B.ByteString hGetEntropy (CH h) = fdReadBS h-#ifdef HAVE_RDRAND-hGetEntropy (UseRdRand h) = \n ->- do bsURandom <- fdReadBS h n-    bsRDRAND  <- B.create n $ \ptr ->  do-                  r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)-                  when (r /= 0)-                       (fail "RDRand failed to gather entropy")-    return $ B.pack $ B.zipWith xor bsURandom bsRDRAND-#endif  fdReadBS :: Fd -> Int -> IO B.ByteString fdReadBS fd n =
System/EntropyWindows.hs view
@@ -4,7 +4,7 @@  Stability: beta  Portability: portable - Obtain entropy from system sources or x86 RDRAND when available.+ Obtain entropy from system sources. -}  module System.EntropyWindows@@ -12,6 +12,7 @@         , openHandle         , hGetEntropy         , closeHandle+        , hardwareRandom         ) where  import Control.Monad (liftM, when)@@ -64,8 +65,25 @@  data CryptHandle     = CH Word32+++-- | Get random values from the hardward RNG or return Nothing if no+-- supported hardware RNG is available.+--+-- Supported hardware:+--      * RDRAND+--      * Patches welcome+hardwareRandom :: Int -> IO (Maybe B.ByteString) #ifdef HAVE_RDRAND-    | UseRdRand Word32+hardwareRandom n =+  do b <- cpuHasRdRand+     if b+        then Just <$> BI.create n (\ptr ->+                        do r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)+                           when (r /= 0) (fail "RDRand failed to gather entropy"))+        else pure Nothing+#else+hardwareRandom _ = pure Nothing #endif  -- Define the constants we need from WinCrypt.h @@ -110,30 +128,12 @@  -- |Open a handle from which random data can be read openHandle :: IO CryptHandle-openHandle = do-#ifdef HAVE_RDRAND-    b <- cpuHasRdRand-    if b then UseRdRand `fmap` cryptAcquireCtx-         else do-#endif-                  CH `fmap` cryptAcquireCtx+openHandle = CH `fmap` cryptAcquireCtx  -- |Close the `CryptHandle` closeHandle :: CryptHandle -> IO () closeHandle (CH h)        = cryptReleaseCtx h-#ifdef HAVE_RDRAND-closeHandle (UseRdRand h) = cryptReleaseCtx h-#endif  -- |Read from `CryptHandle`-hGetEntropy :: CryptHandle -> Int -> IO B.ByteString +hGetEntropy :: CryptHandle -> Int -> IO B.ByteString hGetEntropy (CH h) n = cryptGenRandom h n-#ifdef HAVE_RDRAND-hGetEntropy (UseRdRand h) n =- do bsRDRAND <- BI.create n $ \ptr ->  do-                  r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)-                  when (r /= 0)-                       (fail "RDRand failed to gather entropy")-    bsWinCrypt <- cryptGenRandom h n-    return $ B.pack $ B.zipWith xor bsRDRAND bsWinCrypt-#endif
System/EntropyXen.hs view
@@ -4,7 +4,7 @@  Stability: beta  Portability: portable - Obtain entropy from system sources or x86 RDRAND when available.+ Obtain entropy from RDRAND when available.  -} @@ -13,6 +13,7 @@         , openHandle         , hGetEntropy         , closeHandle+        , hardwardRNG         ) where  import Control.Monad (liftM, when)@@ -48,7 +49,16 @@ closeHandle :: CryptHandle -> IO () closeHandle UseRdRand = return () --- |Read random data from a `CryptHandle`+-- | Get random values from the hardward RNG or return Nothing if no+-- supported hardware RNG is available.+--+-- Supported hardware:+--      * RDRAND+--      * Patches welcome+hardwareRandom :: Int -> IO (Maybe B.ByteString)+hardwareRandom sz = Just <$> hGetEntropy UseRdRand sz++-- |Read random data from a `CryptHandle`, which uses RDRAND (when on Xen) hGetEntropy :: CryptHandle -> Int -> IO B.ByteString hGetEntropy UseRdRand = \n -> do     B.create n $ \ptr ->  do
entropy.cabal view
@@ -1,7 +1,7 @@ name:           entropy-version:        0.3.8+version:        0.4 description:    A platform independent method to obtain cryptographically strong entropy-                (RDRAND when available anywhere, urandom on nix, CryptAPI on Windows, patches welcome)+                (RDRAND, urandom, CryptAPI, and patches welcome)                 Users looking for cryptographically strong (number-theoretically                 sound) PRNGs should see the 'DRBG' package too. synopsis:       A platform independent entropy source@@ -16,10 +16,10 @@ stability:      stable -- build-type:  Simple -- ^^ Used for HaLVM-build-type:        Custom+build-type:     Custom -- ^^ Test for RDRAND support using 'ghc' cabal-version:  >=1.10-tested-with:    GHC == 7.8.2+tested-with:    GHC == 8.2.2 -- data-files: extra-source-files:   ./cbits/rdrand.c, ./cbits/rdrand.h, README.md @@ -49,7 +49,8 @@        else          other-modules: System.EntropyNix   }-  other-extensions:    CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables+  other-extensions:    CPP, ForeignFunctionInterface, BangPatterns,+                       ScopedTypeVariables   build-depends:       base >= 4.3 && < 5, bytestring   default-language:    Haskell2010   if(os(halvm))