-- |
-- 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).
--
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Crypto.Hash.SHAKE
    (  SHAKE128 (..), SHAKE256 (..), HashSHAKE (..)
    ) where

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

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

-- | 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
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
showList :: [SHAKE128 bitlen] -> ShowS
$cshowList :: forall (bitlen :: Nat). [SHAKE128 bitlen] -> ShowS
show :: SHAKE128 bitlen -> String
$cshow :: forall (bitlen :: Nat). SHAKE128 bitlen -> String
showsPrec :: Int -> SHAKE128 bitlen -> ShowS
$cshowsPrec :: forall (bitlen :: Nat). Int -> SHAKE128 bitlen -> ShowS
Show, SHAKE128 bitlen -> DataType
SHAKE128 bitlen -> Constr
forall {bitlen :: Nat}.
KnownNat bitlen =>
Typeable (SHAKE128 bitlen)
forall (bitlen :: Nat).
KnownNat bitlen =>
SHAKE128 bitlen -> DataType
forall (bitlen :: Nat).
KnownNat bitlen =>
SHAKE128 bitlen -> Constr
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 (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)
gmapMo :: 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)
gmapMp :: forall (m :: * -> *).
MonadPlus 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)
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> SHAKE128 bitlen -> m (SHAKE128 bitlen)
$cgmapM :: forall (bitlen :: Nat) (m :: * -> *).
(KnownNat bitlen, Monad m) =>
(forall d. Data d => d -> m d)
-> SHAKE128 bitlen -> m (SHAKE128 bitlen)
gmapQi :: forall u.
Int -> (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
gmapQ :: forall u. (forall d. Data d => d -> u) -> SHAKE128 bitlen -> [u]
$cgmapQ :: forall (bitlen :: Nat) u.
KnownNat bitlen =>
(forall d. Data d => d -> u) -> SHAKE128 bitlen -> [u]
gmapQr :: 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
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
$cgmapQl :: forall (bitlen :: Nat) r r'.
KnownNat bitlen =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SHAKE128 bitlen -> r
gmapT :: (forall b. Data b => b -> b) -> SHAKE128 bitlen -> SHAKE128 bitlen
$cgmapT :: forall (bitlen :: Nat).
KnownNat bitlen =>
(forall b. Data b => b -> b) -> SHAKE128 bitlen -> SHAKE128 bitlen
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> 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))
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (SHAKE128 bitlen))
$cdataCast1 :: forall (bitlen :: Nat) (t :: * -> *) (c :: * -> *).
(KnownNat bitlen, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (SHAKE128 bitlen))
dataTypeOf :: SHAKE128 bitlen -> DataType
$cdataTypeOf :: forall (bitlen :: Nat).
KnownNat bitlen =>
SHAKE128 bitlen -> DataType
toConstr :: SHAKE128 bitlen -> Constr
$ctoConstr :: forall (bitlen :: Nat).
KnownNat bitlen =>
SHAKE128 bitlen -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> 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)
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SHAKE128 bitlen -> 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)
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
_          = forall (bitlen :: Nat) a (proxy :: Nat -> *).
(KnownNat bitlen, Num a) =>
proxy bitlen -> a
byteLen (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        = 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        = forall a. Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()
c_sha3_update
    hashInternalFinalize :: Ptr (Context (SHAKE128 bitlen))
-> Ptr (Digest (SHAKE128 bitlen)) -> IO ()
hashInternalFinalize      = forall (bitlen :: Nat) (proxy :: Nat -> *) a.
KnownNat bitlen =>
proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
shakeFinalizeOutput (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 = forall (bitlen :: Nat) (proxy :: Nat -> *) a.
KnownNat bitlen =>
proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
cshakeFinalizeOutput (forall {k} (t :: k). Proxy t
Proxy :: Proxy bitlen)
    cshakeOutputLength :: SHAKE128 bitlen -> Int
cshakeOutputLength SHAKE128 bitlen
_ = forall (bitlen :: Nat) a (proxy :: Nat -> *).
(KnownNat bitlen, Num a) =>
proxy bitlen -> a
integralNatVal (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
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
showList :: [SHAKE256 bitlen] -> ShowS
$cshowList :: forall (bitlen :: Nat). [SHAKE256 bitlen] -> ShowS
show :: SHAKE256 bitlen -> String
$cshow :: forall (bitlen :: Nat). SHAKE256 bitlen -> String
showsPrec :: Int -> SHAKE256 bitlen -> ShowS
$cshowsPrec :: forall (bitlen :: Nat). Int -> SHAKE256 bitlen -> ShowS
Show, SHAKE256 bitlen -> DataType
SHAKE256 bitlen -> Constr
forall {bitlen :: Nat}.
KnownNat bitlen =>
Typeable (SHAKE256 bitlen)
forall (bitlen :: Nat).
KnownNat bitlen =>
SHAKE256 bitlen -> DataType
forall (bitlen :: Nat).
KnownNat bitlen =>
SHAKE256 bitlen -> Constr
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 (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)
gmapMo :: 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)
gmapMp :: forall (m :: * -> *).
MonadPlus 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)
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> SHAKE256 bitlen -> m (SHAKE256 bitlen)
$cgmapM :: forall (bitlen :: Nat) (m :: * -> *).
(KnownNat bitlen, Monad m) =>
(forall d. Data d => d -> m d)
-> SHAKE256 bitlen -> m (SHAKE256 bitlen)
gmapQi :: forall u.
Int -> (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
gmapQ :: forall u. (forall d. Data d => d -> u) -> SHAKE256 bitlen -> [u]
$cgmapQ :: forall (bitlen :: Nat) u.
KnownNat bitlen =>
(forall d. Data d => d -> u) -> SHAKE256 bitlen -> [u]
gmapQr :: 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
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
$cgmapQl :: forall (bitlen :: Nat) r r'.
KnownNat bitlen =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SHAKE256 bitlen -> r
gmapT :: (forall b. Data b => b -> b) -> SHAKE256 bitlen -> SHAKE256 bitlen
$cgmapT :: forall (bitlen :: Nat).
KnownNat bitlen =>
(forall b. Data b => b -> b) -> SHAKE256 bitlen -> SHAKE256 bitlen
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> 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))
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (SHAKE256 bitlen))
$cdataCast1 :: forall (bitlen :: Nat) (t :: * -> *) (c :: * -> *).
(KnownNat bitlen, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (SHAKE256 bitlen))
dataTypeOf :: SHAKE256 bitlen -> DataType
$cdataTypeOf :: forall (bitlen :: Nat).
KnownNat bitlen =>
SHAKE256 bitlen -> DataType
toConstr :: SHAKE256 bitlen -> Constr
$ctoConstr :: forall (bitlen :: Nat).
KnownNat bitlen =>
SHAKE256 bitlen -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> 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)
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SHAKE256 bitlen -> 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)
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
_          = forall (bitlen :: Nat) a (proxy :: Nat -> *).
(KnownNat bitlen, Num a) =>
proxy bitlen -> a
byteLen (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        = 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        = forall a. Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()
c_sha3_update
    hashInternalFinalize :: Ptr (Context (SHAKE256 bitlen))
-> Ptr (Digest (SHAKE256 bitlen)) -> IO ()
hashInternalFinalize      = forall (bitlen :: Nat) (proxy :: Nat -> *) a.
KnownNat bitlen =>
proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
shakeFinalizeOutput (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 = forall (bitlen :: Nat) (proxy :: Nat -> *) a.
KnownNat bitlen =>
proxy bitlen -> Ptr (Context a) -> Ptr (Digest a) -> IO ()
cshakeFinalizeOutput (forall {k} (t :: k). Proxy t
Proxy :: Proxy bitlen)
    cshakeOutputLength :: SHAKE256 bitlen -> Int
cshakeOutputLength SHAKE256 bitlen
_ = forall (bitlen :: Nat) a (proxy :: Nat -> *).
(KnownNat bitlen, Num a) =>
proxy bitlen -> a
integralNatVal (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
    forall a. Ptr (Context a) -> IO ()
c_sha3_finalize_shake Ptr (Context a)
ctx
    forall a. Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()
c_sha3_output Ptr (Context a)
ctx Ptr (Digest a)
dig (forall (bitlen :: Nat) a (proxy :: Nat -> *).
(KnownNat bitlen, Num a) =>
proxy bitlen -> a
byteLen proxy bitlen
d)
    forall (bitlen :: Nat) (proxy :: Nat -> *).
KnownNat bitlen =>
proxy bitlen -> Ptr Word8 -> IO ()
shakeTruncate proxy bitlen
d (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
    forall a. Ptr (Context a) -> IO ()
c_sha3_finalize_cshake Ptr (Context a)
ctx
    forall a. Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()
c_sha3_output Ptr (Context a)
ctx Ptr (Digest a)
dig (forall (bitlen :: Nat) a (proxy :: Nat -> *).
(KnownNat bitlen, Num a) =>
proxy bitlen -> a
byteLen proxy bitlen
d)
    forall (bitlen :: Nat) (proxy :: Nat -> *).
KnownNat bitlen =>
proxy bitlen -> Ptr Word8 -> IO ()
shakeTruncate proxy bitlen
d (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 =
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
bits forall a. Ord a => a -> a -> Bool
> Int
0) forall a b. (a -> b) -> a -> b
$ do
        Word8
byte <- forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
ptr Int
index
        forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Word8
ptr Int
index (Word8
byte forall a. Bits a => a -> a -> a
.&. Word8
mask)
  where
    mask :: Word8
mask = (Word8
1 forall a. Bits a => a -> Int -> a
`shiftL` Int
bits) forall a. Num a => a -> a -> a
- Word8
1
    (Int
index, Int
bits) = forall (bitlen :: Nat) a (proxy :: Nat -> *).
(KnownNat bitlen, Num a) =>
proxy bitlen -> a
integralNatVal proxy bitlen
d forall a. Integral a => a -> a -> (a, a)
`divMod` Int
8

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

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

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

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

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