    {-# LANGUAGE DataKinds #-}
    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE ForeignFunctionInterface #-}
    {-# LANGUAGE KindSignatures #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE TypeOperators #-}
    {-# LANGUAGE UndecidableInstances #-}

    -- |
    -- Module      : Crypto.Hash.SHAKE
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- Module containing the binding functions to work with the
    -- SHA3 extendable output functions (SHAKE).
    module Crypto.Hash.SHAKE (
        SHAKE128 (..),
        SHAKE256 (..),
        HashSHAKE (..),
    ) where

    import Control.Monad (when)
    import Crypto.Hash.Types
    import Data.Bits
    import Data.Data
    import Data.Word (Word32, Word8)
    import Foreign.Ptr (Ptr, castPtr)
    import Foreign.Storable (Storable (..))

    import Crypto.Internal.Nat
    import GHC.TypeLits (KnownNat, Nat, type (+))

    -- | Type class of SHAKE algorithms.
    class HashAlgorithm a => HashSHAKE a where
        -- | Alternate finalization needed for cSHAKE
        cshakeInternalFinalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()

        -- | Get the digest bit length
        cshakeOutputLength :: a -> Int

    -- | SHAKE128 (128 bits) extendable output function.  Supports an arbitrary
    -- digest size, to be specified as a type parameter of kind 'Nat'.
    --
    -- Note: outputs from @'SHAKE128' n@ and @'SHAKE128' m@ for the same input are
    -- correlated (one being a prefix of the other).  Results are unrelated to
    -- 'SHAKE256' results.
    data SHAKE128 (bitlen :: Nat) = SHAKE128
        deriving (Int -> SHAKE128 bitlen -> ShowS
    [SHAKE128 bitlen] -> ShowS
    SHAKE128 bitlen -> String
    (Int -> SHAKE128 bitlen -> ShowS)
    -> (SHAKE128 bitlen -> String)
    -> ([SHAKE128 bitlen] -> ShowS)
    -> Show (SHAKE128 bitlen)
    forall (bitlen :: Nat). Int -> SHAKE128 bitlen -> ShowS
    forall (bitlen :: Nat). [SHAKE128 bitlen] -> ShowS
    forall (bitlen :: Nat). SHAKE128 bitlen -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall (bitlen :: Nat). Int -> SHAKE128 bitlen -> ShowS
    showsPrec :: Int -> SHAKE128 bitlen -> ShowS
    $cshow :: forall (bitlen :: Nat). SHAKE128 bitlen -> String
    show :: SHAKE128 bitlen -> String
    $cshowList :: forall (bitlen :: Nat). [SHAKE128 bitlen] -> ShowS
    showList :: [SHAKE128 bitlen] -> ShowS
    Show, Typeable (SHAKE128 bitlen)
    Typeable (SHAKE128 bitlen) =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> SHAKE128 bitlen -> c (SHAKE128 bitlen))
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c (SHAKE128 bitlen))
    -> (SHAKE128 bitlen -> Constr)
    -> (SHAKE128 bitlen -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c (SHAKE128 bitlen)))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e))
        -> Maybe (c (SHAKE128 bitlen)))
    -> ((forall b. Data b => b -> b)
        -> SHAKE128 bitlen -> SHAKE128 bitlen)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r)
    -> (forall u.
        (forall d. Data d => d -> u) -> SHAKE128 bitlen -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> SHAKE128 bitlen -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d)
        -> SHAKE128 bitlen -> m (SHAKE128 bitlen))
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d)
        -> SHAKE128 bitlen -> m (SHAKE128 bitlen))
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d)
        -> SHAKE128 bitlen -> m (SHAKE128 bitlen))
    -> Data (SHAKE128 bitlen)
    SHAKE128 bitlen -> Constr
    SHAKE128 bitlen -> DataType
    (forall b. Data b => b -> b) -> SHAKE128 bitlen -> SHAKE128 bitlen
    forall (bitlen :: Nat).
    KnownNat bitlen =>
    Typeable (SHAKE128 bitlen)
    forall (bitlen :: Nat).
    KnownNat bitlen =>
    SHAKE128 bitlen -> Constr
    forall (bitlen :: Nat).
    KnownNat bitlen =>
    SHAKE128 bitlen -> DataType
    forall (bitlen :: Nat).
    KnownNat bitlen =>
    (forall b. Data b => b -> b) -> SHAKE128 bitlen -> SHAKE128 bitlen
    forall (bitlen :: Nat) u.
    KnownNat bitlen =>
    Int -> (forall d. Data d => d -> u) -> SHAKE128 bitlen -> u
    forall (bitlen :: Nat) u.
    KnownNat bitlen =>
    (forall d. Data d => d -> u) -> SHAKE128 bitlen -> [u]
    forall (bitlen :: Nat) r r'.
    KnownNat bitlen =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
    forall (bitlen :: Nat) r r'.
    KnownNat bitlen =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
    forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, Monad m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, MonadPlus m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    forall (bitlen :: Nat) (c :: * -> *).
    KnownNat bitlen =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (SHAKE128 bitlen)
    forall (bitlen :: Nat) (c :: * -> *).
    KnownNat bitlen =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHAKE128 bitlen -> c (SHAKE128 bitlen)
    forall (bitlen :: Nat) (t :: * -> *) (c :: * -> *).
    (KnownNat bitlen, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (SHAKE128 bitlen))
    forall (bitlen :: Nat) (t :: * -> * -> *) (c :: * -> *).
    (KnownNat bitlen, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (SHAKE128 bitlen))
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u.
    Int -> (forall d. Data d => d -> u) -> SHAKE128 bitlen -> u
    forall u. (forall d. Data d => d -> u) -> SHAKE128 bitlen -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (SHAKE128 bitlen)
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHAKE128 bitlen -> c (SHAKE128 bitlen)
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (SHAKE128 bitlen))
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (SHAKE128 bitlen))
    $cgfoldl :: forall (bitlen :: Nat) (c :: * -> *).
    KnownNat bitlen =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHAKE128 bitlen -> c (SHAKE128 bitlen)
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHAKE128 bitlen -> c (SHAKE128 bitlen)
    $cgunfold :: forall (bitlen :: Nat) (c :: * -> *).
    KnownNat bitlen =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (SHAKE128 bitlen)
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (SHAKE128 bitlen)
    $ctoConstr :: forall (bitlen :: Nat).
    KnownNat bitlen =>
    SHAKE128 bitlen -> Constr
    toConstr :: SHAKE128 bitlen -> Constr
    $cdataTypeOf :: forall (bitlen :: Nat).
    KnownNat bitlen =>
    SHAKE128 bitlen -> DataType
    dataTypeOf :: SHAKE128 bitlen -> DataType
    $cdataCast1 :: forall (bitlen :: Nat) (t :: * -> *) (c :: * -> *).
    (KnownNat bitlen, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (SHAKE128 bitlen))
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (SHAKE128 bitlen))
    $cdataCast2 :: forall (bitlen :: Nat) (t :: * -> * -> *) (c :: * -> *).
    (KnownNat bitlen, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (SHAKE128 bitlen))
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (SHAKE128 bitlen))
    $cgmapT :: forall (bitlen :: Nat).
    KnownNat bitlen =>
    (forall b. Data b => b -> b) -> SHAKE128 bitlen -> SHAKE128 bitlen
    gmapT :: (forall b. Data b => b -> b) -> SHAKE128 bitlen -> SHAKE128 bitlen
    $cgmapQl :: forall (bitlen :: Nat) r r'.
    KnownNat bitlen =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
    $cgmapQr :: forall (bitlen :: Nat) r r'.
    KnownNat bitlen =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
    $cgmapQ :: forall (bitlen :: Nat) u.
    KnownNat bitlen =>
    (forall d. Data d => d -> u) -> SHAKE128 bitlen -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> SHAKE128 bitlen -> [u]
    $cgmapQi :: forall (bitlen :: Nat) u.
    KnownNat bitlen =>
    Int -> (forall d. Data d => d -> u) -> SHAKE128 bitlen -> u
    gmapQi :: forall u.
    Int -> (forall d. Data d => d -> u) -> SHAKE128 bitlen -> u
    $cgmapM :: forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, Monad m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    $cgmapMp :: forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, MonadPlus m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    $cgmapMo :: forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, MonadPlus m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> SHAKE128 bitlen -> m (SHAKE128 bitlen)
    Data)

    instance KnownNat bitlen => HashAlgorithm (SHAKE128 bitlen) where
        type HashBlockSize (SHAKE128 bitlen) = 168
        type HashDigestSize (SHAKE128 bitlen) = Div8 (bitlen + 7)
        type HashInternalContextSize (SHAKE128 bitlen) = 376
        hashBlockSize :: SHAKE128 bitlen -> Int
    hashBlockSize SHAKE128 bitlen
    _ = Int
    168
        hashDigestSize :: SHAKE128 bitlen -> Int
    hashDigestSize SHAKE128 bitlen
    _ = Proxy bitlen -> Int
    forall (bitlen :: Nat) a (proxy :: Nat -> *).
    (KnownNat bitlen, Num a) =>
    proxy bitlen -> a
    byteLen (Proxy bitlen
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy bitlen)
        hashInternalContextSize :: SHAKE128 bitlen -> Int
    hashInternalContextSize SHAKE128 bitlen
    _ = Int
    376
        hashInternalInit :: Ptr (Context (SHAKE128 bitlen)) -> IO ()
    hashInternalInit Ptr (Context (SHAKE128 bitlen))
    p = Ptr (Context (SHAKE128 bitlen)) -> Word32 -> IO ()
    forall a. Ptr (Context a) -> Word32 -> IO ()
    c_sha3_init Ptr (Context (SHAKE128 bitlen))
    p Word32
    128
        hashInternalUpdate :: Ptr (Context (SHAKE128 bitlen)) -> Ptr Word8 -> Word32 -> IO ()
    hashInternalUpdate = Ptr (Context (SHAKE128 bitlen)) -> Ptr Word8 -> Word32 -> IO ()
    forall a. Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()
    c_sha3_update
        hashInternalFinalize :: Ptr (Context (SHAKE128 bitlen))
    -> Ptr (Digest (SHAKE128 bitlen)) -> IO ()
    hashInternalFinalize = Proxy bitlen
    -> Ptr (Context (SHAKE128 bitlen))
    -> Ptr (Digest (SHAKE128 bitlen))
    -> IO ()
    forall (bitlen :: Nat) (proxy :: Nat -> *) a.
    KnownNat bitlen =>
    proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
    shakeFinalizeOutput (Proxy bitlen
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy bitlen)

    instance KnownNat bitlen => HashSHAKE (SHAKE128 bitlen) where
        cshakeInternalFinalize :: Ptr (Context (SHAKE128 bitlen))
    -> Ptr (Digest (SHAKE128 bitlen)) -> IO ()
    cshakeInternalFinalize = Proxy bitlen
    -> Ptr (Context (SHAKE128 bitlen))
    -> Ptr (Digest (SHAKE128 bitlen))
    -> IO ()
    forall (bitlen :: Nat) (proxy :: Nat -> *) a.
    KnownNat bitlen =>
    proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
    cshakeFinalizeOutput (Proxy bitlen
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy bitlen)
        cshakeOutputLength :: SHAKE128 bitlen -> Int
    cshakeOutputLength SHAKE128 bitlen
    _ = Proxy bitlen -> Int
    forall (bitlen :: Nat) a (proxy :: Nat -> *).
    (KnownNat bitlen, Num a) =>
    proxy bitlen -> a
    integralNatVal (Proxy bitlen
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy bitlen)

    -- | SHAKE256 (256 bits) extendable output function.  Supports an arbitrary
    -- digest size, to be specified as a type parameter of kind 'Nat'.
    --
    -- Note: outputs from @'SHAKE256' n@ and @'SHAKE256' m@ for the same input are
    -- correlated (one being a prefix of the other).  Results are unrelated to
    -- 'SHAKE128' results.
    data SHAKE256 (bitlen :: Nat) = SHAKE256
        deriving (Int -> SHAKE256 bitlen -> ShowS
    [SHAKE256 bitlen] -> ShowS
    SHAKE256 bitlen -> String
    (Int -> SHAKE256 bitlen -> ShowS)
    -> (SHAKE256 bitlen -> String)
    -> ([SHAKE256 bitlen] -> ShowS)
    -> Show (SHAKE256 bitlen)
    forall (bitlen :: Nat). Int -> SHAKE256 bitlen -> ShowS
    forall (bitlen :: Nat). [SHAKE256 bitlen] -> ShowS
    forall (bitlen :: Nat). SHAKE256 bitlen -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall (bitlen :: Nat). Int -> SHAKE256 bitlen -> ShowS
    showsPrec :: Int -> SHAKE256 bitlen -> ShowS
    $cshow :: forall (bitlen :: Nat). SHAKE256 bitlen -> String
    show :: SHAKE256 bitlen -> String
    $cshowList :: forall (bitlen :: Nat). [SHAKE256 bitlen] -> ShowS
    showList :: [SHAKE256 bitlen] -> ShowS
    Show, Typeable (SHAKE256 bitlen)
    Typeable (SHAKE256 bitlen) =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> SHAKE256 bitlen -> c (SHAKE256 bitlen))
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c (SHAKE256 bitlen))
    -> (SHAKE256 bitlen -> Constr)
    -> (SHAKE256 bitlen -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c (SHAKE256 bitlen)))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e))
        -> Maybe (c (SHAKE256 bitlen)))
    -> ((forall b. Data b => b -> b)
        -> SHAKE256 bitlen -> SHAKE256 bitlen)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r)
    -> (forall u.
        (forall d. Data d => d -> u) -> SHAKE256 bitlen -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> SHAKE256 bitlen -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d)
        -> SHAKE256 bitlen -> m (SHAKE256 bitlen))
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d)
        -> SHAKE256 bitlen -> m (SHAKE256 bitlen))
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d)
        -> SHAKE256 bitlen -> m (SHAKE256 bitlen))
    -> Data (SHAKE256 bitlen)
    SHAKE256 bitlen -> Constr
    SHAKE256 bitlen -> DataType
    (forall b. Data b => b -> b) -> SHAKE256 bitlen -> SHAKE256 bitlen
    forall (bitlen :: Nat).
    KnownNat bitlen =>
    Typeable (SHAKE256 bitlen)
    forall (bitlen :: Nat).
    KnownNat bitlen =>
    SHAKE256 bitlen -> Constr
    forall (bitlen :: Nat).
    KnownNat bitlen =>
    SHAKE256 bitlen -> DataType
    forall (bitlen :: Nat).
    KnownNat bitlen =>
    (forall b. Data b => b -> b) -> SHAKE256 bitlen -> SHAKE256 bitlen
    forall (bitlen :: Nat) u.
    KnownNat bitlen =>
    Int -> (forall d. Data d => d -> u) -> SHAKE256 bitlen -> u
    forall (bitlen :: Nat) u.
    KnownNat bitlen =>
    (forall d. Data d => d -> u) -> SHAKE256 bitlen -> [u]
    forall (bitlen :: Nat) r r'.
    KnownNat bitlen =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
    forall (bitlen :: Nat) r r'.
    KnownNat bitlen =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
    forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, Monad m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, MonadPlus m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    forall (bitlen :: Nat) (c :: * -> *).
    KnownNat bitlen =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (SHAKE256 bitlen)
    forall (bitlen :: Nat) (c :: * -> *).
    KnownNat bitlen =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHAKE256 bitlen -> c (SHAKE256 bitlen)
    forall (bitlen :: Nat) (t :: * -> *) (c :: * -> *).
    (KnownNat bitlen, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (SHAKE256 bitlen))
    forall (bitlen :: Nat) (t :: * -> * -> *) (c :: * -> *).
    (KnownNat bitlen, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (SHAKE256 bitlen))
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u.
    Int -> (forall d. Data d => d -> u) -> SHAKE256 bitlen -> u
    forall u. (forall d. Data d => d -> u) -> SHAKE256 bitlen -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (SHAKE256 bitlen)
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHAKE256 bitlen -> c (SHAKE256 bitlen)
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (SHAKE256 bitlen))
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (SHAKE256 bitlen))
    $cgfoldl :: forall (bitlen :: Nat) (c :: * -> *).
    KnownNat bitlen =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHAKE256 bitlen -> c (SHAKE256 bitlen)
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHAKE256 bitlen -> c (SHAKE256 bitlen)
    $cgunfold :: forall (bitlen :: Nat) (c :: * -> *).
    KnownNat bitlen =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (SHAKE256 bitlen)
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (SHAKE256 bitlen)
    $ctoConstr :: forall (bitlen :: Nat).
    KnownNat bitlen =>
    SHAKE256 bitlen -> Constr
    toConstr :: SHAKE256 bitlen -> Constr
    $cdataTypeOf :: forall (bitlen :: Nat).
    KnownNat bitlen =>
    SHAKE256 bitlen -> DataType
    dataTypeOf :: SHAKE256 bitlen -> DataType
    $cdataCast1 :: forall (bitlen :: Nat) (t :: * -> *) (c :: * -> *).
    (KnownNat bitlen, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (SHAKE256 bitlen))
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (SHAKE256 bitlen))
    $cdataCast2 :: forall (bitlen :: Nat) (t :: * -> * -> *) (c :: * -> *).
    (KnownNat bitlen, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (SHAKE256 bitlen))
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (SHAKE256 bitlen))
    $cgmapT :: forall (bitlen :: Nat).
    KnownNat bitlen =>
    (forall b. Data b => b -> b) -> SHAKE256 bitlen -> SHAKE256 bitlen
    gmapT :: (forall b. Data b => b -> b) -> SHAKE256 bitlen -> SHAKE256 bitlen
    $cgmapQl :: forall (bitlen :: Nat) r r'.
    KnownNat bitlen =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
    $cgmapQr :: forall (bitlen :: Nat) r r'.
    KnownNat bitlen =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
    $cgmapQ :: forall (bitlen :: Nat) u.
    KnownNat bitlen =>
    (forall d. Data d => d -> u) -> SHAKE256 bitlen -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> SHAKE256 bitlen -> [u]
    $cgmapQi :: forall (bitlen :: Nat) u.
    KnownNat bitlen =>
    Int -> (forall d. Data d => d -> u) -> SHAKE256 bitlen -> u
    gmapQi :: forall u.
    Int -> (forall d. Data d => d -> u) -> SHAKE256 bitlen -> u
    $cgmapM :: forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, Monad m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    $cgmapMp :: forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, MonadPlus m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    $cgmapMo :: forall (bitlen :: Nat) (m :: * -> *).
    (KnownNat bitlen, MonadPlus m) =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> SHAKE256 bitlen -> m (SHAKE256 bitlen)
    Data)

    instance KnownNat bitlen => HashAlgorithm (SHAKE256 bitlen) where
        type HashBlockSize (SHAKE256 bitlen) = 136
        type HashDigestSize (SHAKE256 bitlen) = Div8 (bitlen + 7)
        type HashInternalContextSize (SHAKE256 bitlen) = 344
        hashBlockSize :: SHAKE256 bitlen -> Int
    hashBlockSize SHAKE256 bitlen
    _ = Int
    136
        hashDigestSize :: SHAKE256 bitlen -> Int
    hashDigestSize SHAKE256 bitlen
    _ = Proxy bitlen -> Int
    forall (bitlen :: Nat) a (proxy :: Nat -> *).
    (KnownNat bitlen, Num a) =>
    proxy bitlen -> a
    byteLen (Proxy bitlen
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy bitlen)
        hashInternalContextSize :: SHAKE256 bitlen -> Int
    hashInternalContextSize SHAKE256 bitlen
    _ = Int
    344
        hashInternalInit :: Ptr (Context (SHAKE256 bitlen)) -> IO ()
    hashInternalInit Ptr (Context (SHAKE256 bitlen))
    p = Ptr (Context (SHAKE256 bitlen)) -> Word32 -> IO ()
    forall a. Ptr (Context a) -> Word32 -> IO ()
    c_sha3_init Ptr (Context (SHAKE256 bitlen))
    p Word32
    256
        hashInternalUpdate :: Ptr (Context (SHAKE256 bitlen)) -> Ptr Word8 -> Word32 -> IO ()
    hashInternalUpdate = Ptr (Context (SHAKE256 bitlen)) -> Ptr Word8 -> Word32 -> IO ()
    forall a. Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()
    c_sha3_update
        hashInternalFinalize :: Ptr (Context (SHAKE256 bitlen))
    -> Ptr (Digest (SHAKE256 bitlen)) -> IO ()
    hashInternalFinalize = Proxy bitlen
    -> Ptr (Context (SHAKE256 bitlen))
    -> Ptr (Digest (SHAKE256 bitlen))
    -> IO ()
    forall (bitlen :: Nat) (proxy :: Nat -> *) a.
    KnownNat bitlen =>
    proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
    shakeFinalizeOutput (Proxy bitlen
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy bitlen)

    instance KnownNat bitlen => HashSHAKE (SHAKE256 bitlen) where
        cshakeInternalFinalize :: Ptr (Context (SHAKE256 bitlen))
    -> Ptr (Digest (SHAKE256 bitlen)) -> IO ()
    cshakeInternalFinalize = Proxy bitlen
    -> Ptr (Context (SHAKE256 bitlen))
    -> Ptr (Digest (SHAKE256 bitlen))
    -> IO ()
    forall (bitlen :: Nat) (proxy :: Nat -> *) a.
    KnownNat bitlen =>
    proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
    cshakeFinalizeOutput (Proxy bitlen
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy bitlen)
        cshakeOutputLength :: SHAKE256 bitlen -> Int
    cshakeOutputLength SHAKE256 bitlen
    _ = Proxy bitlen -> Int
    forall (bitlen :: Nat) a (proxy :: Nat -> *).
    (KnownNat bitlen, Num a) =>
    proxy bitlen -> a
    integralNatVal (Proxy bitlen
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy bitlen)

    shakeFinalizeOutput
        :: KnownNat bitlen
        => proxy bitlen
        -> Ptr (Context a)
        -> Ptr (Digest a)
        -> IO ()
    shakeFinalizeOutput :: forall (bitlen :: Nat) (proxy :: Nat -> *) a.
    KnownNat bitlen =>
    proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
    shakeFinalizeOutput proxy bitlen
    d Ptr (Context a)
    ctx Ptr (Digest a)
    dig = do
        Ptr (Context a) -> IO ()
    forall a. Ptr (Context a) -> IO ()
    c_sha3_finalize_shake Ptr (Context a)
    ctx
        Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()
    forall a. Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()
    c_sha3_output Ptr (Context a)
    ctx Ptr (Digest a)
    dig (proxy bitlen -> Word32
    forall (bitlen :: Nat) a (proxy :: Nat -> *).
    (KnownNat bitlen, Num a) =>
    proxy bitlen -> a
    byteLen proxy bitlen
    d)
        proxy bitlen -> Ptr Word8 -> IO ()
    forall (bitlen :: Nat) (proxy :: Nat -> *).
    KnownNat bitlen =>
    proxy bitlen -> Ptr Word8 -> IO ()
    shakeTruncate proxy bitlen
    d (Ptr (Digest a) -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (Digest a)
    dig)

    cshakeFinalizeOutput
        :: KnownNat bitlen
        => proxy bitlen
        -> Ptr (Context a)
        -> Ptr (Digest a)
        -> IO ()
    cshakeFinalizeOutput :: forall (bitlen :: Nat) (proxy :: Nat -> *) a.
    KnownNat bitlen =>
    proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
    cshakeFinalizeOutput proxy bitlen
    d Ptr (Context a)
    ctx Ptr (Digest a)
    dig = do
        Ptr (Context a) -> IO ()
    forall a. Ptr (Context a) -> IO ()
    c_sha3_finalize_cshake Ptr (Context a)
    ctx
        Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()
    forall a. Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()
    c_sha3_output Ptr (Context a)
    ctx Ptr (Digest a)
    dig (proxy bitlen -> Word32
    forall (bitlen :: Nat) a (proxy :: Nat -> *).
    (KnownNat bitlen, Num a) =>
    proxy bitlen -> a
    byteLen proxy bitlen
    d)
        proxy bitlen -> Ptr Word8 -> IO ()
    forall (bitlen :: Nat) (proxy :: Nat -> *).
    KnownNat bitlen =>
    proxy bitlen -> Ptr Word8 -> IO ()
    shakeTruncate proxy bitlen
    d (Ptr (Digest a) -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (Digest a)
    dig)

    shakeTruncate :: KnownNat bitlen => proxy bitlen -> Ptr Word8 -> IO ()
    shakeTruncate :: forall (bitlen :: Nat) (proxy :: Nat -> *).
    KnownNat bitlen =>
    proxy bitlen -> Ptr Word8 -> IO ()
    shakeTruncate proxy bitlen
    d Ptr Word8
    ptr =
        Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Int
    bits Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    0) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
            byte <- Ptr Word8 -> Int -> IO Word8
    forall a. Storable a => Ptr a -> Int -> IO a
    peekElemOff Ptr Word8
    ptr Int
    index
            pokeElemOff ptr index (byte .&. mask)
      where
        mask :: Word8
    mask = (Word8
    1 Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    bits) Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    - Word8
    1
        (Int
    index, Int
    bits) = proxy bitlen -> Int
    forall (bitlen :: Nat) a (proxy :: Nat -> *).
    (KnownNat bitlen, Num a) =>
    proxy bitlen -> a
    integralNatVal proxy bitlen
    d Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `divMod` Int
    8

    foreign import ccall unsafe "crypton_sha3_init"
        c_sha3_init :: Ptr (Context a) -> Word32 -> IO ()

    foreign import ccall "crypton_sha3_update"
        c_sha3_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()

    foreign import ccall unsafe "crypton_sha3_finalize_shake"
        c_sha3_finalize_shake :: Ptr (Context a) -> IO ()

    foreign import ccall unsafe "crypton_sha3_finalize_cshake"
        c_sha3_finalize_cshake :: Ptr (Context a) -> IO ()

    foreign import ccall unsafe "crypton_sha3_output"
        c_sha3_output :: Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()