{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE DefaultSignatures          #-}
{-# LANGUAGE RecordWildCards            #-}

-- |
--
-- Module      : Raaz.Random
-- Description : Cryptographically secure pseudo random generator.
-- Copyright   : (c) Piyush P Kurur, 2016
-- License     : Apache-2.0 OR BSD-3-Clause
-- Maintainer  : Piyush P Kurur <ppk@iitpkd.ac.in>
-- Stability   : experimental
--
module Raaz.Random
       ( -- * Cryptographically secure randomness.
         -- $randomness$
         RandomState
       , withRandomState
       , randomByteString
       , Random(..)
       -- ** Generating sensitive data
       -- $securerandom$
       , randomiseMemory
       , withRandomisedMemory
       , withSecureRandomisedMemory
       , withSecureRandomState
         -- ** Low level code
       , fillRandomBytes
       , RandomStorable(..)
       , fillRandom
       , unsafeFillRandomElements
       , reseed
       -- * Information
       , entropySource
       , csprgName, csprgDescription
       ) where

import Control.Applicative
import Control.Monad
import Data.ByteString             ( ByteString             )
import Data.Int
import Data.Vector.Unboxed         ( Unbox )
import Data.Word

import Foreign.Ptr      ( castPtr )
import Foreign.Storable ( Storable         )
import Prelude


import           Raaz.Core
import           Raaz.Core.Memory( Access(..) )
import           PRGenerator ( entropySource, csprgName, csprgDescription, RandomState
                             , fillRandomBytes
                             , reseed
                             )
import qualified Raaz.Primitive.ChaCha20.Internal as ChaCha20
import qualified Raaz.Primitive.Poly1305.Internal as Poly1305
import           Raaz.Primitive.Keyed.Internal ( Keyed )
import           Raaz.Verse.Poly1305.C.Portable   ( verse_poly1305_c_portable_clamp)

-- $randomness$
--
-- This module provides cryptographically secure pseudo-random
-- bytes. The state of the csprg is kept track in the memory element
-- `RandomState` and /should/ be run using `withRandomState`.
--

-- $securerandom$
--
-- Sensitive data like long term asymmetric keys need to be handled
-- with care as they may be inadvertently leaked into permanent
-- storage when memory is swapped out. Most of the time such keys are
-- generated using cryptographically pseudo-random bytes. However, a
-- direct approach, namely using `random`, to generate them hides a
-- subtle bug. For example the code below is unsafe.
--
-- >
-- > -- WARNING: Not safe from swapping
-- > main     :: withSecureRandomState myAction
-- > myAction ::  MySecretMem -> RandomState -> IO ()
-- > myAction mySecMem rstate = do secret <- random rstate
-- >                                 -- the pure value secret is in
-- >                                 -- the haskell heap and therefore
-- >                                 -- escapes locking
-- >                               initialise secret mysecmem
-- >                               doSomething
--
-- The `random` interface gives a pure Haskell value and is stored in
-- the Haskell heap. Although memory locking is often available on
-- modern operating systems, it is impossible to lock this value as
-- the garbage collector keeps moving values around.
--
-- How can we work around this problem ? The intention of the
-- programmer when using the above code was to randomise the contents
-- of the mySecMem memory element. We recommend converting the above
-- code to the following
--
-- >
-- > main = withSecureRandomisedMemory action
-- > myAction ::  MySecretMem -> RandomState -> IO ()
-- > myAction mySecMem rstate = do randomiseMemory mySecMem
-- >                               doSomething
--
-- The above code, though correct, is fragile as missing out on the
-- randomiseMemory call can jeopardise the safety of the code. Often
-- the randomisation is required only at the beginning of the task and
-- in this case it is better to use the safer alternative
-- `withSecureRandomisedMemory`

-- | Subclass of `Storable` which can be randomly generated. It might
-- appear that all instances of the class `Storable` should be
-- be instances of this class, after all we know the size of the
-- element, why not write that many random bytes. In fact, this module
-- provides an `unsafeFillRandomElements` which does that. However, we
-- do not give a blanket definition for all storables because for
-- certain refinements of a given type, like for example, Word8's
-- modulo 10, `unsafeFillRandomElements` introduces unacceptable
-- skews.
class Storable a => RandomStorable a where
  -- | Fill the buffer with so many random elements of type a.
  fillRandomElements :: Int       -- ^ number of elements to fill
                     -> Ptr a     -- ^ The buffer to fill
                     -> RandomState
                     -> IO ()

-- | Fill the given generalised pointer buffer with random elements.
fillRandom :: (RandomStorable a, Pointer ptr)
           => Int
           -> ptr a
           -> RandomState
           -> IO ()
fillRandom :: Int -> ptr a -> RandomState -> IO ()
fillRandom Int
n ptr a
ptr RandomState
rstate = (Ptr a -> IO ()) -> ptr a -> IO ()
forall (ptr :: * -> *) a b.
Pointer ptr =>
(Ptr a -> b) -> ptr a -> b
unsafeWithPointer (\ Ptr a
rawPtr -> Int -> Ptr a -> RandomState -> IO ()
forall a. RandomStorable a => Int -> Ptr a -> RandomState -> IO ()
fillRandomElements Int
n Ptr a
rawPtr RandomState
rstate) ptr a
ptr

{-

mem -> IO a

randomiseMemory -> (mem,RandomState) -> IO ()

withSecureMemory (randomiseMemory action)

-}


-- | Execute an action that takes the CSPRG state.
withRandomState :: (RandomState -> IO a) -- ^ The action that requires csprg state.
                -> IO a
withRandomState :: (RandomState -> IO a) -> IO a
withRandomState RandomState -> IO a
action = (RandomState -> IO a) -> IO a
forall mem a. Memory mem => (mem -> IO a) -> IO a
withMemory RandomState -> IO a
actionP
  where actionP :: RandomState -> IO a
actionP RandomState
rstate = do RandomState -> IO ()
reseed RandomState
rstate
                            RandomState -> IO a
action RandomState
rstate

-- | Execute an action that takes a memory element and random state
-- such that all the memory allocated for both of them is locked.
withSecureRandomState :: Memory mem
                      => (mem -> RandomState -> IO a) -- ^ The action that requires random state
                      -> IO a
withSecureRandomState :: (mem -> RandomState -> IO a) -> IO a
withSecureRandomState mem -> RandomState -> IO a
action = ((mem, RandomState) -> IO a) -> IO a
forall mem a. Memory mem => (mem -> IO a) -> IO a
withSecureMemory (mem, RandomState) -> IO a
actionP
  where actionP :: (mem, RandomState) -> IO a
actionP (mem
mem,RandomState
rstate) = do RandomState -> IO ()
reseed RandomState
rstate
                                  mem -> RandomState -> IO a
action mem
mem RandomState
rstate

-- | Randomise the contents of an accessible memory.
randomiseMemory :: WriteAccessible mem => mem -> RandomState -> IO ()
randomiseMemory :: mem -> RandomState -> IO ()
randomiseMemory mem
mem RandomState
rstate = (Access -> IO ()) -> [Access] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Access -> IO ()
randomise ([Access] -> IO ()) -> [Access] -> IO ()
forall a b. (a -> b) -> a -> b
$ mem -> [Access]
forall mem. WriteAccessible mem => mem -> [Access]
writeAccess mem
mem
  where randomise :: Access -> IO ()
randomise Access{Ptr Word8
BYTES Int
accessSize :: Access -> BYTES Int
accessPtr :: Access -> Ptr Word8
accessSize :: BYTES Int
accessPtr :: Ptr Word8
..} = BYTES Int -> Dest (Ptr Word8) -> RandomState -> IO ()
forall l (ptr :: * -> *) a.
(LengthUnit l, Pointer ptr) =>
l -> Dest (ptr a) -> RandomState -> IO ()
fillRandomBytes BYTES Int
accessSize (Ptr Word8 -> Dest (Ptr Word8)
forall a. a -> Dest a
destination Ptr Word8
accessPtr) RandomState
rstate

-- | Run a memory action which is passed a memory cell whose contents
-- are randomised with cryptographically secure pseudo-random bytes.
withRandomisedMemory :: WriteAccessible mem
                     => (mem -> IO a) -- ^ memory action
                     -> IO a
withRandomisedMemory :: (mem -> IO a) -> IO a
withRandomisedMemory mem -> IO a
action = ((mem, RandomState) -> IO a) -> IO a
forall mem a. Memory mem => (mem -> IO a) -> IO a
withMemory (mem, RandomState) -> IO a
actionP
  where actionP :: (mem, RandomState) -> IO a
actionP (mem
mem,RandomState
rstate) = do
          RandomState -> IO ()
reseed RandomState
rstate
          mem -> RandomState -> IO ()
forall mem. WriteAccessible mem => mem -> RandomState -> IO ()
randomiseMemory mem
mem RandomState
rstate
          mem -> IO a
action mem
mem

-- | Similar to `withRandomisedMemory` but all memory allocation is
-- locked. Use this when the randomised content is to be protected
-- from swapping.
withSecureRandomisedMemory :: WriteAccessible mem
                           => (mem -> IO a) -- ^ memory action
                           -> IO a
withSecureRandomisedMemory :: (mem -> IO a) -> IO a
withSecureRandomisedMemory mem -> IO a
action = (mem -> RandomState -> IO a) -> IO a
forall mem a. Memory mem => (mem -> RandomState -> IO a) -> IO a
withSecureRandomState mem -> RandomState -> IO a
actionP
  where actionP :: mem -> RandomState -> IO a
actionP mem
mem RandomState
rstate = do mem -> RandomState -> IO ()
forall mem. WriteAccessible mem => mem -> RandomState -> IO ()
randomiseMemory mem
mem RandomState
rstate
                                mem -> IO a
action mem
mem


-- TOTHINK:
-- -------
--
-- Do we want to give a default definition like
--
-- > fillRandomElements = unsafeFillRandomElements
--
-- This will make the instance definitions easier for the Storables
-- types that is spread over its entire range. However, it would lead
-- to a lazy definition which will compromise the quality of the
-- randomness.


-- | This is a helper function that has been exported to simplify the
-- definition of a `RandomStorable` instance for `Storable`
-- types. However, there is a reason why we do not give a blanket
-- instance for all instances of the `Storable` class and why this
-- function is unsafe. This function generates a random element of
-- type @a@ by generating @n@ random bytes where @n@ is the size of
-- the elements of @a@. For instances that range the entire @n@ byte
-- space this is fine. However, if the type is actually a refinement
-- of such a type, (consider a @`Word8`@ modulo @10@ for example) this
-- function might generate unacceptable skew in the
-- distribution. Hence this function is prefixed unsafe.
unsafeFillRandomElements :: Storable a  => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements :: Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements Int
n Ptr a
ptr = BYTES Int -> Dest (Ptr Any) -> RandomState -> IO ()
forall l (ptr :: * -> *) a.
(LengthUnit l, Pointer ptr) =>
l -> Dest (ptr a) -> RandomState -> IO ()
fillRandomBytes BYTES Int
totalSz (Dest (Ptr Any) -> RandomState -> IO ())
-> Dest (Ptr Any) -> RandomState -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr Any -> Dest (Ptr Any)
forall a. a -> Dest a
destination (Ptr Any -> Dest (Ptr Any)) -> Ptr Any -> Dest (Ptr Any)
forall a b. (a -> b) -> a -> b
$ Ptr a -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr a
ptr
  where totalSz :: BYTES Int
totalSz = Int -> BYTES Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n BYTES Int -> BYTES Int -> BYTES Int
forall a. Num a => a -> a -> a
* Proxy a -> BYTES Int
forall a. Storable a => Proxy a -> BYTES Int
sizeOf (Ptr a -> Proxy a
forall a. Ptr a -> Proxy a
getProxy Ptr a
ptr)
        getProxy :: Ptr a -> Proxy a
        getProxy :: Ptr a -> Proxy a
getProxy = Proxy a -> Ptr a -> Proxy a
forall a b. a -> b -> a
const Proxy a
forall k (t :: k). Proxy t
Proxy


-- | Generate a random byteString.

randomByteString ::LengthUnit l
                 => l
                 -> RandomState
                 -> IO ByteString
randomByteString :: l -> RandomState -> IO ByteString
randomByteString l
l RandomState
rstate = l -> (Ptr Any -> IO ()) -> IO ByteString
forall l a. LengthUnit l => l -> (Ptr a -> IO ()) -> IO ByteString
create l
l Ptr Any -> IO ()
forall (ptr :: * -> *) a. Pointer ptr => ptr a -> IO ()
genBS
  where genBS :: ptr a -> IO ()
genBS ptr a
ptr = l -> Dest (ptr a) -> RandomState -> IO ()
forall l (ptr :: * -> *) a.
(LengthUnit l, Pointer ptr) =>
l -> Dest (ptr a) -> RandomState -> IO ()
fillRandomBytes l
l (ptr a -> Dest (ptr a)
forall a. a -> Dest a
destination ptr a
ptr) RandomState
rstate

------------------------------- Some instances of Random ------------------------

instance RandomStorable Word8 where
  fillRandomElements :: Int -> Ptr Word8 -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Word8 -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Word16 where
  fillRandomElements :: Int -> Ptr Word16 -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Word16 -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Word32 where
  fillRandomElements :: Int -> Ptr Word32 -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Word32 -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Word64 where
  fillRandomElements :: Int -> Ptr Word64 -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Word64 -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Word where
  fillRandomElements :: Int -> Ptr Word -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Word -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Int8 where
  fillRandomElements :: Int -> Ptr Int8 -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Int8 -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Int16 where
  fillRandomElements :: Int -> Ptr Int16 -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Int16 -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Int32 where
  fillRandomElements :: Int -> Ptr Int32 -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Int32 -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Int64 where
  fillRandomElements :: Int -> Ptr Int64 -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Int64 -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable Int where
  fillRandomElements :: Int -> Ptr Int -> RandomState -> IO ()
fillRandomElements = Int -> Ptr Int -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable (Key ChaCha20.ChaCha20) where
  fillRandomElements :: Int -> Ptr (Key ChaCha20) -> RandomState -> IO ()
fillRandomElements = Int -> Ptr (Key ChaCha20) -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable (Nounce ChaCha20.ChaCha20) where
  fillRandomElements :: Int -> Ptr (Nounce ChaCha20) -> RandomState -> IO ()
fillRandomElements = Int -> Ptr (Nounce ChaCha20) -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements


instance RandomStorable (Key ChaCha20.XChaCha20) where
  fillRandomElements :: Int -> Ptr (Key XChaCha20) -> RandomState -> IO ()
fillRandomElements = Int -> Ptr (Key XChaCha20) -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements

instance RandomStorable (Nounce ChaCha20.XChaCha20) where
  fillRandomElements :: Int -> Ptr (Nounce XChaCha20) -> RandomState -> IO ()
fillRandomElements = Int -> Ptr (Nounce XChaCha20) -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements


instance RandomStorable Poly1305.R where
  fillRandomElements :: Int -> Ptr R -> RandomState -> IO ()
fillRandomElements Int
n Ptr R
ptr RandomState
state = Int -> Ptr R -> RandomState -> IO ()
forall a. Storable a => Int -> Ptr a -> RandomState -> IO ()
unsafeFillRandomElements Int
n Ptr R
ptr RandomState
state IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
clamp
    where clamp :: IO ()
clamp = Ptr (Tuple 2 Word64) -> Word64 -> IO ()
verse_poly1305_c_portable_clamp (Ptr R -> Ptr (Tuple 2 Word64)
forall a b. Ptr a -> Ptr b
castPtr Ptr R
ptr) (Int -> Word64
forall a. Enum a => Int -> a
toEnum Int
n)

instance RandomStorable w => RandomStorable (LE w) where
  fillRandomElements :: Int -> Ptr (LE w) -> RandomState -> IO ()
fillRandomElements Int
n = Int -> Ptr w -> RandomState -> IO ()
forall a. RandomStorable a => Int -> Ptr a -> RandomState -> IO ()
fillRandomElements Int
n (Ptr w -> RandomState -> IO ())
-> (Ptr (LE w) -> Ptr w) -> Ptr (LE w) -> RandomState -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr (LE w) -> Ptr w
forall w. Ptr (LE w) -> Ptr w
lePtrToPtr
    where lePtrToPtr :: Ptr (LE w) -> Ptr w
          lePtrToPtr :: Ptr (LE w) -> Ptr w
lePtrToPtr = Ptr (LE w) -> Ptr w
forall a b. Ptr a -> Ptr b
castPtr

instance RandomStorable w => RandomStorable (BE w) where
  fillRandomElements :: Int -> Ptr (BE w) -> RandomState -> IO ()
fillRandomElements Int
n = Int -> Ptr w -> RandomState -> IO ()
forall a. RandomStorable a => Int -> Ptr a -> RandomState -> IO ()
fillRandomElements Int
n (Ptr w -> RandomState -> IO ())
-> (Ptr (BE w) -> Ptr w) -> Ptr (BE w) -> RandomState -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr (BE w) -> Ptr w
forall w. Ptr (BE w) -> Ptr w
bePtrToPtr
    where bePtrToPtr :: Ptr (BE w) -> Ptr w
          bePtrToPtr :: Ptr (BE w) -> Ptr w
bePtrToPtr = Ptr (BE w) -> Ptr w
forall a b. Ptr a -> Ptr b
castPtr

instance (Dimension d, Unbox w, RandomStorable w) => RandomStorable (Tuple d w) where
  fillRandomElements :: Int -> Ptr (Tuple d w) -> RandomState -> IO ()
fillRandomElements Int
n Ptr (Tuple d w)
ptr = Int -> Ptr w -> RandomState -> IO ()
forall a. RandomStorable a => Int -> Ptr a -> RandomState -> IO ()
fillRandomElements (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Ptr (Tuple d w) -> Int
forall (d :: Nat) w. Dimension d => Ptr (Tuple d w) -> Int
sz Ptr (Tuple d w)
ptr) (Ptr w -> RandomState -> IO ()) -> Ptr w -> RandomState -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr (Tuple d w) -> Ptr w
forall (d :: Nat) w. Ptr (Tuple d w) -> Ptr w
tupPtrToPtr Ptr (Tuple d w)
ptr
    where sz   :: Dimension d => Ptr (Tuple d w) -> Int
          sz :: Ptr (Tuple d w) -> Int
sz   = Proxy (Tuple d w) -> Int
forall (dim :: Nat) a. Dimension dim => Proxy (Tuple dim a) -> Int
dimension' (Proxy (Tuple d w) -> Int)
-> (Ptr (Tuple d w) -> Proxy (Tuple d w)) -> Ptr (Tuple d w) -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr (Tuple d w) -> Proxy (Tuple d w)
forall (d :: Nat) w. Ptr (Tuple d w) -> Proxy (Tuple d w)
getProxy
          getProxy :: Ptr (Tuple d w) -> Proxy (Tuple d w)
          getProxy :: Ptr (Tuple d w) -> Proxy (Tuple d w)
getProxy = Proxy (Tuple d w) -> Ptr (Tuple d w) -> Proxy (Tuple d w)
forall a b. a -> b -> a
const Proxy (Tuple d w)
forall k (t :: k). Proxy t
Proxy
          tupPtrToPtr ::  Ptr (Tuple d w) -> Ptr w
          tupPtrToPtr :: Ptr (Tuple d w) -> Ptr w
tupPtrToPtr = Ptr (Tuple d w) -> Ptr w
forall a b. Ptr a -> Ptr b
castPtr


--------------------------------- Generating elements randomly ----------------------------

-- | Elements that can be randomly generated.
class Random a where
  random :: RandomState -> IO a

  default random :: RandomStorable a => RandomState -> IO a
  random RandomState
state = IO a
go
    where go :: IO a
go =   BYTES Int -> (Ptr a -> IO a) -> IO a
forall l (ptr :: * -> *) something b.
(LengthUnit l, Pointer ptr) =>
l -> (ptr something -> IO b) -> IO b
allocaBuffer (Proxy a -> BYTES Int
forall a. Storable a => Proxy a -> BYTES Int
alignedSizeOf (Proxy a -> BYTES Int) -> Proxy a -> BYTES Int
forall a b. (a -> b) -> a -> b
$ IO a -> Proxy a
forall a. IO a -> Proxy a
getProxy IO a
go) Ptr a -> IO a
forall b. RandomStorable b => Ptr b -> IO b
getIt
          getIt :: Ptr b -> IO b
getIt Ptr b
ptr  = Int -> Ptr b -> RandomState -> IO ()
forall a. RandomStorable a => Int -> Ptr a -> RandomState -> IO ()
fillRandomElements Int
1 (Ptr b -> Ptr b
forall a. Storable a => Ptr a -> Ptr a
nextLocation Ptr b
ptr) RandomState
state IO () -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr b -> IO b
forall a. Storable a => Ptr a -> IO a
peekAligned Ptr b
ptr
          getProxy   :: IO a -> Proxy a
          getProxy :: IO a -> Proxy a
getProxy   = Proxy a -> IO a -> Proxy a
forall a b. a -> b -> a
const Proxy a
forall k (t :: k). Proxy t
Proxy


instance (Random a, Random b) => Random (a,b) where
  random :: RandomState -> IO (a, b)
random RandomState
state = (,)
                 (a -> b -> (a, b)) -> IO a -> IO (b -> (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RandomState -> IO a
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (b -> (a, b)) -> IO b -> IO (a, b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO b
forall a. Random a => RandomState -> IO a
random RandomState
state
instance (Random a, Random b, Random c) => Random (a,b,c) where
  random :: RandomState -> IO (a, b, c)
random RandomState
state = (,,)
                 (a -> b -> c -> (a, b, c)) -> IO a -> IO (b -> c -> (a, b, c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RandomState -> IO a
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (b -> c -> (a, b, c)) -> IO b -> IO (c -> (a, b, c))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO b
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (c -> (a, b, c)) -> IO c -> IO (a, b, c)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO c
forall a. Random a => RandomState -> IO a
random RandomState
state


instance (Random a, Random b, Random c, Random d) => Random (a,b,c,d) where
  random :: RandomState -> IO (a, b, c, d)
random RandomState
state = (,,,)
                 (a -> b -> c -> d -> (a, b, c, d))
-> IO a -> IO (b -> c -> d -> (a, b, c, d))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RandomState -> IO a
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (b -> c -> d -> (a, b, c, d))
-> IO b -> IO (c -> d -> (a, b, c, d))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO b
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (c -> d -> (a, b, c, d)) -> IO c -> IO (d -> (a, b, c, d))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO c
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (d -> (a, b, c, d)) -> IO d -> IO (a, b, c, d)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO d
forall a. Random a => RandomState -> IO a
random RandomState
state


instance (Random a, Random b, Random c, Random d, Random e) => Random (a,b,c,d,e) where
  random :: RandomState -> IO (a, b, c, d, e)
random RandomState
state = (,,,,)
                 (a -> b -> c -> d -> e -> (a, b, c, d, e))
-> IO a -> IO (b -> c -> d -> e -> (a, b, c, d, e))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RandomState -> IO a
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (b -> c -> d -> e -> (a, b, c, d, e))
-> IO b -> IO (c -> d -> e -> (a, b, c, d, e))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO b
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (c -> d -> e -> (a, b, c, d, e))
-> IO c -> IO (d -> e -> (a, b, c, d, e))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO c
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (d -> e -> (a, b, c, d, e)) -> IO d -> IO (e -> (a, b, c, d, e))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO d
forall a. Random a => RandomState -> IO a
random RandomState
state
                 IO (e -> (a, b, c, d, e)) -> IO e -> IO (a, b, c, d, e)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RandomState -> IO e
forall a. Random a => RandomState -> IO a
random RandomState
state

instance Random Word8
instance Random Word16
instance Random Word32
instance Random Word64
instance Random Int8
instance Random Int16
instance Random Int32
instance Random Int64

instance Random (Key ChaCha20.ChaCha20) where
instance Random (Nounce ChaCha20.ChaCha20) where

instance Random (Key ChaCha20.XChaCha20) where
instance Random (Nounce ChaCha20.XChaCha20) where

instance Storable prim => Random (Key (Keyed prim))  where
  random :: RandomState -> IO (Key (Keyed prim))
random RandomState
state = IO (Key (Keyed prim))
randKY
    where randKY :: IO (Key (Keyed prim))
randKY   = ByteString -> Key (Keyed prim)
forall a. Encodable a => ByteString -> a
unsafeFromByteString (ByteString -> Key (Keyed prim))
-> IO ByteString -> IO (Key (Keyed prim))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BYTES Int -> RandomState -> IO ByteString
forall l. LengthUnit l => l -> RandomState -> IO ByteString
randomByteString BYTES Int
sz RandomState
state
          sz :: BYTES Int
sz         = Proxy prim -> BYTES Int
forall a. Storable a => Proxy a -> BYTES Int
sizeOf (Proxy prim -> BYTES Int) -> Proxy prim -> BYTES Int
forall a b. (a -> b) -> a -> b
$ IO (Key (Keyed prim)) -> Proxy prim
forall p. IO (Key (Keyed p)) -> Proxy p
getProxy IO (Key (Keyed prim))
randKY
          getProxy :: IO (Key (Keyed p)) -> Proxy p
          getProxy :: IO (Key (Keyed p)) -> Proxy p
getProxy IO (Key (Keyed p))
_ = Proxy p
forall k (t :: k). Proxy t
Proxy

instance Random Poly1305.R where

instance Random w => Random (LE w) where
  random :: RandomState -> IO (LE w)
random RandomState
state = w -> LE w
forall w. w -> LE w
littleEndian (w -> LE w) -> IO w -> IO (LE w)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RandomState -> IO w
forall a. Random a => RandomState -> IO a
random RandomState
state

instance Random w => Random (BE w) where
  random :: RandomState -> IO (BE w)
random RandomState
state = w -> BE w
forall w. w -> BE w
bigEndian (w -> BE w) -> IO w -> IO (BE w)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RandomState -> IO w
forall a. Random a => RandomState -> IO a
random RandomState
state


instance (Dimension d, Unbox w, Random w) => Random (Tuple d w) where
  random :: RandomState -> IO (Tuple d w)
random RandomState
state = IO w -> IO (Tuple d w)
forall (dim :: Nat) a.
(Dimension dim, Unbox a) =>
IO a -> IO (Tuple dim a)
generateIO (RandomState -> IO w
forall a. Random a => RandomState -> IO a
random RandomState
state)