module Crypto.Random.Entropy.Unsafe
( replenish
, module Crypto.Random.Entropy.Backend
) where
import Data.Word (Word8)
import Foreign.Ptr (Ptr, plusPtr)
import Crypto.Random.Entropy.Backend
replenish :: Int -> [EntropyBackend] -> Ptr Word8 -> IO ()
replenish :: Int -> [EntropyBackend] -> Ptr Word8 -> IO ()
replenish _ [] _ = String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail "cryptonite: random: cannot get any source of entropy on this system"
replenish poolSize :: Int
poolSize backends :: [EntropyBackend]
backends ptr :: Ptr Word8
ptr = Int -> [EntropyBackend] -> Ptr Word8 -> Int -> IO ()
loop 0 [EntropyBackend]
backends Ptr Word8
ptr Int
poolSize
where loop :: Int -> [EntropyBackend] -> Ptr Word8 -> Int -> IO ()
loop :: Int -> [EntropyBackend] -> Ptr Word8 -> Int -> IO ()
loop retry :: Int
retry [] p :: Ptr Word8
p n :: Int
n | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 0 = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Int
retry Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 3 = String -> IO ()
forall a. HasCallStack => String -> a
error "cryptonite: random: cannot fully replenish"
| Bool
otherwise = Int -> [EntropyBackend] -> Ptr Word8 -> Int -> IO ()
loop (Int
retryInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) [EntropyBackend]
backends Ptr Word8
p Int
n
loop _ (_:_) _ 0 = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
loop retry :: Int
retry (b :: EntropyBackend
b:bs :: [EntropyBackend]
bs) p :: Ptr Word8
p n :: Int
n = do
Int
r <- EntropyBackend -> Ptr Word8 -> Int -> IO Int
gatherBackend EntropyBackend
b Ptr Word8
p Int
n
Int -> [EntropyBackend] -> Ptr Word8 -> Int -> IO ()
loop Int
retry [EntropyBackend]
bs (Ptr Word8
p Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
r) (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
r)