    {-# OPTIONS_HADDOCK hide #-}
    {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}

    module Crypto.Nettle.Ciphers.Internal
    	( NettleCipher(..)
    	, NettleBlockCipher(..)
    	, NettleStreamCipher(..)
    	, NettleBlockedStreamCipher(..)
    	, NettleGCM
    	, nettle_cipherInit
    	, nettle_cipherInit'
    	, nettle_ecbEncrypt
    	, nettle_ecbDecrypt
    	, nettle_cbcEncrypt
    	, nettle_cbcDecrypt
    	, nettle_cfbEncrypt
    	, nettle_cfbDecrypt
    	, nettle_ctrCombine
    	, nettle_streamCombine
    	, nettle_streamSetNonce
    	, nettle_blockedStreamCombine
    	, nettle_blockedStreamSetNonce
    	, nettle_gcm_aeadInit
    	, nettle_gcm_aeadStateAppendHeader
    	, nettle_gcm_aeadStateEncrypt
    	, nettle_gcm_aeadStateDecrypt
    	, nettle_gcm_aeadStateFinalize
    	) where

    import Crypto.Cipher.Types as T

    import Data.Tagged
    import Data.Byteable (Byteable(..))
    import Data.SecureMem
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Internal as B
    import Data.Bits (xor)

    import Nettle.Utils
    import Crypto.Nettle.Ciphers.ForeignImports

    -- internal functions are not camelCase on purpose
    {-# ANN module "HLint: ignore Use camelCase" #-}

    class NettleCipher c where
    	-- | pointer to new context, key length, (const) key pointer
    	nc_cipherInit    :: Tagged c (Ptr Word8 -> Word -> Ptr Word8 -> IO())
    	nc_cipherName    :: Tagged c String
    	nc_cipherKeySize :: Tagged c T.KeySizeSpecifier
    	nc_ctx_size      :: Tagged c Int
    	nc_ctx           :: c -> SecureMem
    	nc_Ctx           :: SecureMem -> c
    class NettleCipher c => NettleBlockCipher c where
    	nbc_blockSize          :: Tagged c Int
    	nbc_encrypt_ctx_offset :: Tagged c (Ptr Word8 -> Ptr Word8)
    	nbc_encrypt_ctx_offset = (Ptr Word8 -> Ptr Word8) -> Tagged c (Ptr Word8 -> Ptr Word8)
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Ptr Word8 -> Ptr Word8
    forall a. a -> a
    id
    	nbc_decrypt_ctx_offset :: Tagged c (Ptr Word8 -> Ptr Word8)
    	nbc_decrypt_ctx_offset = (Ptr Word8 -> Ptr Word8) -> Tagged c (Ptr Word8 -> Ptr Word8)
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Ptr Word8 -> Ptr Word8
    forall a. a -> a
    id
    	nbc_ecb_encrypt        :: Tagged c NettleCryptFunc
    	nbc_ecb_decrypt        :: Tagged c NettleCryptFunc
    	nbc_fun_encrypt        :: Tagged c (FunPtr NettleCryptFunc)
    	nbc_fun_decrypt        :: Tagged c (FunPtr NettleCryptFunc)
    class NettleCipher c => NettleStreamCipher c where
    	nsc_streamCombine      :: Tagged c NettleCryptFunc
    	nsc_nonceSize          :: Tagged c T.KeySizeSpecifier
    	nsc_nonceSize          = KeySizeSpecifier -> Tagged c KeySizeSpecifier
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged (KeySizeSpecifier -> Tagged c KeySizeSpecifier)
    -> KeySizeSpecifier -> Tagged c KeySizeSpecifier
    forall a b. (a -> b) -> a -> b
    $ [Int] -> KeySizeSpecifier
    T.KeySizeEnum []
    	nsc_setNonce           :: Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    	nsc_setNonce           = Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    -> Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    forall a. Maybe a
    Nothing

    -- stream cipher based on generating (large) blocks to XOR with input,
    -- but don't keep incomplete blocks in the state, so we have to do that here
    class NettleCipher c => NettleBlockedStreamCipher c where
    	nbsc_blockSize          :: Tagged c Int
    	-- set new incomplete state
    	nbsc_IncompleteState    :: c -> B.ByteString -> c
    	nbsc_incompleteState    :: c -> B.ByteString
    	nbsc_streamCombine      :: Tagged c NettleCryptFunc
    	nbsc_nonceSize          :: Tagged c T.KeySizeSpecifier
    	nbsc_nonceSize          = KeySizeSpecifier -> Tagged c KeySizeSpecifier
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged (KeySizeSpecifier -> Tagged c KeySizeSpecifier)
    -> KeySizeSpecifier -> Tagged c KeySizeSpecifier
    forall a b. (a -> b) -> a -> b
    $ [Int] -> KeySizeSpecifier
    T.KeySizeEnum []
    	nbsc_setNonce           :: Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    	nbsc_setNonce           = Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    -> Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    forall a. Maybe a
    Nothing

    nettle_cipherInit :: NettleCipher c => Key c -> c
    nettle_cipherInit :: forall c. NettleCipher c => Key c -> c
    nettle_cipherInit Key c
    k = let ctx :: c
    ctx = (Ptr Word8 -> Word -> Ptr Word8 -> IO ()) -> Key c -> c
    forall c.
    NettleCipher c =>
    (Ptr Word8 -> Word -> Ptr Word8 -> IO ()) -> Key c -> c
    nettle_cipherInit' (Tagged c (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    forall c.
    NettleCipher c =>
    Tagged c (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    nc_cipherInit Tagged c (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    -> c -> Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    forall a b. Tagged a b -> a -> b
    `witness` c
    ctx) Key c
    k in c
    ctx

    nettle_cipherInit' :: NettleCipher c => (Ptr Word8 -> Word -> Ptr Word8 -> IO()) -> Key c -> c
    nettle_cipherInit' :: forall c.
    NettleCipher c =>
    (Ptr Word8 -> Word -> Ptr Word8 -> IO ()) -> Key c -> c
    nettle_cipherInit' Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    f Key c
    k = let ctx :: c
    ctx = SecureMem -> c
    forall c. NettleCipher c => SecureMem -> c
    nc_Ctx (SecureMem -> c) -> SecureMem -> c
    forall a b. (a -> b) -> a -> b
    $ (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    -> Int -> Key c -> SecureMem
    forall k.
    ToSecureMem k =>
    (Ptr Word8 -> Word -> Ptr Word8 -> IO ()) -> Int -> k -> SecureMem
    key_init Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    f (Tagged c Int
    forall c. NettleCipher c => Tagged c Int
    nc_ctx_size Tagged c Int -> c -> Int
    forall a b. Tagged a b -> a -> b
    `witness` c
    ctx) Key c
    k in c
    ctx

    assert_blockSize :: NettleBlockCipher c => c -> B.ByteString -> a -> a
    assert_blockSize :: forall c a. NettleBlockCipher c => c -> ByteString -> a -> a
    assert_blockSize c
    c ByteString
    src a
    result = if Int
    0 Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= ByteString -> Int
    B.length ByteString
    src Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `mod` (Tagged c Int
    forall c. NettleBlockCipher c => Tagged c Int
    nbc_blockSize Tagged c Int -> c -> Int
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) then [Char] -> a
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "input not a multiple of blockSize" else a
    result

    nettle_ecbEncrypt :: NettleBlockCipher c => c -> B.ByteString -> B.ByteString
    nettle_ecbEncrypt :: forall c. NettleBlockCipher c => c -> ByteString -> ByteString
    nettle_ecbEncrypt c
    c    ByteString
    src = c -> ByteString -> ByteString -> ByteString
    forall c a. NettleBlockCipher c => c -> ByteString -> a -> a
    assert_blockSize c
    c ByteString
    src (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (Ptr Word8 -> Ptr Word8)
    -> NettleCryptFunc -> SecureMem -> ByteString -> ByteString
    c_run_crypt   (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c)               (Tagged c NettleCryptFunc
    forall c. NettleBlockCipher c => Tagged c NettleCryptFunc
    nbc_ecb_encrypt Tagged c NettleCryptFunc -> c -> NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) ByteString
    src
    nettle_ecbDecrypt :: NettleBlockCipher c => c -> B.ByteString -> B.ByteString
    nettle_ecbDecrypt :: forall c. NettleBlockCipher c => c -> ByteString -> ByteString
    nettle_ecbDecrypt c
    c    ByteString
    src = c -> ByteString -> ByteString -> ByteString
    forall c a. NettleBlockCipher c => c -> ByteString -> a -> a
    assert_blockSize c
    c ByteString
    src (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (Ptr Word8 -> Ptr Word8)
    -> NettleCryptFunc -> SecureMem -> ByteString -> ByteString
    c_run_crypt   (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_decrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c)               (Tagged c NettleCryptFunc
    forall c. NettleBlockCipher c => Tagged c NettleCryptFunc
    nbc_ecb_decrypt Tagged c NettleCryptFunc -> c -> NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) ByteString
    src
    nettle_cbcEncrypt :: NettleBlockCipher c => c -> IV c -> B.ByteString -> B.ByteString
    nettle_cbcEncrypt :: forall c.
    NettleBlockCipher c =>
    c -> IV c -> ByteString -> ByteString
    nettle_cbcEncrypt c
    c IV c
    iv ByteString
    src = c -> ByteString -> ByteString -> ByteString
    forall c a. NettleBlockCipher c => c -> ByteString -> a -> a
    assert_blockSize c
    c ByteString
    src (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> IV c
    -> ByteString
    -> ByteString
    forall iv.
    Byteable iv =>
    (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> iv
    -> ByteString
    -> ByteString
    blockmode_run (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) NettleBlockMode
    c_cbc_encrypt (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_encrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) IV c
    iv ByteString
    src
    nettle_cbcDecrypt :: NettleBlockCipher c => c -> IV c -> B.ByteString -> B.ByteString
    nettle_cbcDecrypt :: forall c.
    NettleBlockCipher c =>
    c -> IV c -> ByteString -> ByteString
    nettle_cbcDecrypt c
    c IV c
    iv ByteString
    src = c -> ByteString -> ByteString -> ByteString
    forall c a. NettleBlockCipher c => c -> ByteString -> a -> a
    assert_blockSize c
    c ByteString
    src (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> IV c
    -> ByteString
    -> ByteString
    forall iv.
    Byteable iv =>
    (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> iv
    -> ByteString
    -> ByteString
    blockmode_run (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_decrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) NettleBlockMode
    c_cbc_decrypt (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_decrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) IV c
    iv ByteString
    src
    nettle_cfbEncrypt :: NettleBlockCipher c => c -> IV c -> B.ByteString -> B.ByteString
    nettle_cfbEncrypt :: forall c.
    NettleBlockCipher c =>
    c -> IV c -> ByteString -> ByteString
    nettle_cfbEncrypt c
    c IV c
    iv ByteString
    src = c -> ByteString -> ByteString -> ByteString
    forall c a. NettleBlockCipher c => c -> ByteString -> a -> a
    assert_blockSize c
    c ByteString
    src (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> IV c
    -> ByteString
    -> ByteString
    forall iv.
    Byteable iv =>
    (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> iv
    -> ByteString
    -> ByteString
    blockmode_run (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) NettleBlockMode
    c_cfb_encrypt (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_encrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) IV c
    iv ByteString
    src
    nettle_cfbDecrypt :: NettleBlockCipher c => c -> IV c -> B.ByteString -> B.ByteString
    nettle_cfbDecrypt :: forall c.
    NettleBlockCipher c =>
    c -> IV c -> ByteString -> ByteString
    nettle_cfbDecrypt c
    c IV c
    iv ByteString
    src = c -> ByteString -> ByteString -> ByteString
    forall c a. NettleBlockCipher c => c -> ByteString -> a -> a
    assert_blockSize c
    c ByteString
    src (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> IV c
    -> ByteString
    -> ByteString
    forall iv.
    Byteable iv =>
    (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> iv
    -> ByteString
    -> ByteString
    blockmode_run (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) NettleBlockMode
    c_cfb_decrypt (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_encrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) IV c
    iv ByteString
    src
    nettle_ctrCombine :: NettleBlockCipher c => c -> IV c -> B.ByteString -> B.ByteString
    nettle_ctrCombine :: forall c.
    NettleBlockCipher c =>
    c -> IV c -> ByteString -> ByteString
    nettle_ctrCombine c
    c        =                          (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> IV c
    -> ByteString
    -> ByteString
    forall iv.
    Byteable iv =>
    (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> iv
    -> ByteString
    -> ByteString
    blockmode_run (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) NettleBlockMode
    c_ctr_crypt   (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_encrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c)

    nettle_streamCombine :: NettleStreamCipher c => c -> B.ByteString -> (B.ByteString, c)
    nettle_streamCombine :: forall c.
    NettleStreamCipher c =>
    c -> ByteString -> (ByteString, c)
    nettle_streamCombine c
    c ByteString
    indata = let (ByteString
    r, SecureMem
    c') = NettleCryptFunc
    -> SecureMem -> ByteString -> (ByteString, SecureMem)
    stream_crypt (Tagged c NettleCryptFunc
    forall c. NettleStreamCipher c => Tagged c NettleCryptFunc
    nsc_streamCombine Tagged c NettleCryptFunc -> c -> NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) ByteString
    indata in (ByteString
    r, SecureMem -> c
    forall c. NettleCipher c => SecureMem -> c
    nc_Ctx SecureMem
    c')
    nettle_streamSetNonce :: NettleStreamCipher c => c -> B.ByteString -> Maybe c
    nettle_streamSetNonce :: forall c. NettleStreamCipher c => c -> ByteString -> Maybe c
    nettle_streamSetNonce c
    c ByteString
    nonce = case Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    forall c.
    NettleStreamCipher c =>
    Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    nsc_setNonce Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    -> c -> Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    forall a b. Tagged a b -> a -> b
    `witness` c
    c of
    	Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    Nothing -> Maybe c
    forall a. Maybe a
    Nothing
    	Just Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    setnonce -> IO (Maybe c) -> Maybe c
    forall a. IO a -> a
    unsafeDupablePerformIO (IO (Maybe c) -> Maybe c) -> IO (Maybe c) -> Maybe c
    forall a b. (a -> b) -> a -> b
    $
    		SecureMem -> IO SecureMem
    secureMemCopy (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) IO SecureMem -> (SecureMem -> IO (Maybe c)) -> IO (Maybe c)
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \SecureMem
    ctx' ->
    		SecureMem -> (Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c)
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    ctx' ((Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c))
    -> (Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    		ByteString -> (Word -> Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c)
    forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    nonce ((Word -> Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c))
    -> (Word -> Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c)
    forall a b. (a -> b) -> a -> b
    $ \Word
    noncelen Ptr Word8
    nonceptr ->
    		Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    setnonce Ptr Word8
    ctxptr Word
    noncelen Ptr Word8
    nonceptr IO () -> IO (Maybe c) -> IO (Maybe c)
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >>
    		Maybe c -> IO (Maybe c)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (c -> Maybe c
    forall a. a -> Maybe a
    Just (c -> Maybe c) -> c -> Maybe c
    forall a b. (a -> b) -> a -> b
    $ SecureMem -> c
    forall c. NettleCipher c => SecureMem -> c
    nc_Ctx SecureMem
    ctx')

    nettle_blockedStreamCombine :: NettleBlockedStreamCipher c => c -> B.ByteString -> (B.ByteString, c)
    nettle_blockedStreamCombine :: forall c.
    NettleBlockedStreamCipher c =>
    c -> ByteString -> (ByteString, c)
    nettle_blockedStreamCombine c
    c ByteString
    indata = if ByteString -> Int
    B.length ByteString
    indata Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0 then (ByteString
    indata, c
    c) else
    	let inc :: ByteString
    inc = c -> ByteString
    forall c. NettleBlockedStreamCipher c => c -> ByteString
    nbsc_incompleteState c
    c; blocksiz :: Int
    blocksiz = Tagged c Int
    forall c. NettleBlockedStreamCipher c => Tagged c Int
    nbsc_blockSize Tagged c Int -> c -> Int
    forall a b. Tagged a b -> a -> b
    `witness` c
    c in
    	if ByteString -> Int
    B.length ByteString
    inc Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    0
    		then let
    			-- first xor remaining block, then combine the rest
    			(ByteString
    i1, ByteString
    i2) = Int -> ByteString -> (ByteString, ByteString)
    B.splitAt (ByteString -> Int
    B.length ByteString
    inc) ByteString
    indata
    			(ByteString
    inc1, ByteString
    inc2) = Int -> ByteString -> (ByteString, ByteString)
    B.splitAt (ByteString -> Int
    B.length ByteString
    indata) ByteString
    inc
    			r1 :: ByteString
    r1 = [Word8] -> ByteString
    B.pack ([Word8] -> ByteString) -> [Word8] -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> [Word8]
    forall a. (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
    B.zipWith Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    xor ByteString
    i1 ByteString
    inc1
    			c' :: c
    c' = if ByteString -> Int
    B.length ByteString
    inc2 Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0 then SecureMem -> c
    forall c. NettleCipher c => SecureMem -> c
    nc_Ctx (SecureMem -> c) -> SecureMem -> c
    forall a b. (a -> b) -> a -> b
    $ c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c else c -> ByteString -> c
    forall c. NettleBlockedStreamCipher c => c -> ByteString -> c
    nbsc_IncompleteState c
    c ByteString
    inc2
    			(ByteString
    r, c
    c'') = c -> ByteString -> (ByteString, c)
    forall c.
    NettleBlockedStreamCipher c =>
    c -> ByteString -> (ByteString, c)
    nettle_blockedStreamCombine c
    c' ByteString
    i2
    			in (ByteString -> ByteString -> ByteString
    B.append ByteString
    r1 ByteString
    r, c
    c'')
    		else if ByteString -> Int
    B.length ByteString
    indata Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `mod` Int
    blocksiz Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    0
    			then let
    				padding :: ByteString
    padding = Int -> Word8 -> ByteString
    B.replicate (Int
    blocksiz Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - (ByteString -> Int
    B.length ByteString
    indata Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `mod` Int
    blocksiz)) Word8
    0
    				(ByteString
    r', SecureMem
    c') = NettleCryptFunc
    -> SecureMem -> ByteString -> (ByteString, SecureMem)
    stream_crypt (Tagged c NettleCryptFunc
    forall c. NettleBlockedStreamCipher c => Tagged c NettleCryptFunc
    nbsc_streamCombine Tagged c NettleCryptFunc -> c -> NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) (ByteString -> ByteString -> ByteString
    B.append ByteString
    indata ByteString
    padding)
    				(ByteString
    r, ByteString
    inc') = Int -> ByteString -> (ByteString, ByteString)
    B.splitAt (ByteString -> Int
    B.length ByteString
    indata) ByteString
    r'
    				in (ByteString
    r, c -> ByteString -> c
    forall c. NettleBlockedStreamCipher c => c -> ByteString -> c
    nbsc_IncompleteState (SecureMem -> c
    forall c. NettleCipher c => SecureMem -> c
    nc_Ctx SecureMem
    c') ByteString
    inc')
    			else
    				let (ByteString
    r, SecureMem
    c') = NettleCryptFunc
    -> SecureMem -> ByteString -> (ByteString, SecureMem)
    stream_crypt (Tagged c NettleCryptFunc
    forall c. NettleBlockedStreamCipher c => Tagged c NettleCryptFunc
    nbsc_streamCombine Tagged c NettleCryptFunc -> c -> NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) ByteString
    indata in (ByteString
    r, SecureMem -> c
    forall c. NettleCipher c => SecureMem -> c
    nc_Ctx SecureMem
    c')
    nettle_blockedStreamSetNonce :: NettleBlockedStreamCipher c => c -> B.ByteString -> Maybe c
    nettle_blockedStreamSetNonce :: forall c. NettleBlockedStreamCipher c => c -> ByteString -> Maybe c
    nettle_blockedStreamSetNonce c
    c ByteString
    nonce = case Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    forall c.
    NettleBlockedStreamCipher c =>
    Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    nbsc_setNonce Tagged c (Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ()))
    -> c -> Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    forall a b. Tagged a b -> a -> b
    `witness` c
    c of
    	Maybe (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    Nothing -> Maybe c
    forall a. Maybe a
    Nothing
    	Just Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    setnonce -> IO (Maybe c) -> Maybe c
    forall a. IO a -> a
    unsafeDupablePerformIO (IO (Maybe c) -> Maybe c) -> IO (Maybe c) -> Maybe c
    forall a b. (a -> b) -> a -> b
    $
    		SecureMem -> IO SecureMem
    secureMemCopy (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) IO SecureMem -> (SecureMem -> IO (Maybe c)) -> IO (Maybe c)
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \SecureMem
    ctx' ->
    		SecureMem -> (Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c)
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    ctx' ((Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c))
    -> (Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    		ByteString -> (Word -> Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c)
    forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    nonce ((Word -> Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c))
    -> (Word -> Ptr Word8 -> IO (Maybe c)) -> IO (Maybe c)
    forall a b. (a -> b) -> a -> b
    $ \Word
    noncelen Ptr Word8
    nonceptr ->
    		Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    setnonce Ptr Word8
    ctxptr Word
    noncelen Ptr Word8
    nonceptr IO () -> IO (Maybe c) -> IO (Maybe c)
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >>
    		Maybe c -> IO (Maybe c)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (c -> Maybe c
    forall a. a -> Maybe a
    Just (c -> Maybe c) -> c -> Maybe c
    forall a b. (a -> b) -> a -> b
    $ SecureMem -> c
    forall c. NettleCipher c => SecureMem -> c
    nc_Ctx SecureMem
    ctx')

    nettle_gcm_aeadInit              :: (NettleBlockCipher c, AEADModeImpl c NettleGCM, Byteable iv) => c -> iv -> Maybe (AEAD c)
    nettle_gcm_aeadInit :: forall c iv.
    (NettleBlockCipher c, AEADModeImpl c NettleGCM, Byteable iv) =>
    c -> iv -> Maybe (AEAD c)
    nettle_gcm_aeadInit          c
    c  iv
    iv = if Tagged c Int
    forall c. NettleBlockCipher c => Tagged c Int
    nbc_blockSize Tagged c Int -> c -> Int
    forall a b. Tagged a b -> a -> b
    `witness` c
    c Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    16 then AEAD c -> Maybe (AEAD c)
    forall a. a -> Maybe a
    Just (AEAD c -> Maybe (AEAD c)) -> AEAD c -> Maybe (AEAD c)
    forall a b. (a -> b) -> a -> b
    $ c -> AEADState c -> AEAD c
    forall cipher. cipher -> AEADState cipher -> AEAD cipher
    AEAD c
    c (AEADState c -> AEAD c) -> AEADState c -> AEAD c
    forall a b. (a -> b) -> a -> b
    $ NettleGCM -> AEADState c
    forall cipher st. AEADModeImpl cipher st => st -> AEADState cipher
    AEADState (NettleGCM -> AEADState c) -> NettleGCM -> AEADState c
    forall a b. (a -> b) -> a -> b
    $ (Ptr Word8 -> Ptr Word8)
    -> FunPtr NettleCryptFunc -> SecureMem -> iv -> NettleGCM
    forall iv.
    Byteable iv =>
    (Ptr Word8 -> Ptr Word8)
    -> FunPtr NettleCryptFunc -> SecureMem -> iv -> NettleGCM
    gcm_init (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_encrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c) iv
    iv else Maybe (AEAD c)
    forall a. Maybe a
    Nothing
    nettle_gcm_aeadStateAppendHeader :: t -> NettleGCM -> B.ByteString -> NettleGCM
    nettle_gcm_aeadStateAppendHeader :: forall t. t -> NettleGCM -> ByteString -> NettleGCM
    nettle_gcm_aeadStateAppendHeader t
    _ = NettleGCM -> ByteString -> NettleGCM
    gcm_update
    nettle_gcm_aeadStateEncrypt      :: NettleBlockCipher c => c -> NettleGCM -> B.ByteString -> (B.ByteString, NettleGCM)
    nettle_gcm_aeadStateEncrypt :: forall c.
    NettleBlockCipher c =>
    c -> NettleGCM -> ByteString -> (ByteString, NettleGCM)
    nettle_gcm_aeadStateEncrypt      c
    c = NettleGCMMode
    -> (Ptr Word8 -> Ptr Word8)
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> NettleGCM
    -> ByteString
    -> (ByteString, NettleGCM)
    gcm_crypt NettleGCMMode
    c_gcm_encrypt (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_encrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c)
    nettle_gcm_aeadStateDecrypt      :: NettleBlockCipher c => c -> NettleGCM -> B.ByteString -> (B.ByteString, NettleGCM)
    nettle_gcm_aeadStateDecrypt :: forall c.
    NettleBlockCipher c =>
    c -> NettleGCM -> ByteString -> (ByteString, NettleGCM)
    nettle_gcm_aeadStateDecrypt      c
    c = NettleGCMMode
    -> (Ptr Word8 -> Ptr Word8)
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> NettleGCM
    -> ByteString
    -> (ByteString, NettleGCM)
    gcm_crypt NettleGCMMode
    c_gcm_decrypt (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_encrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c)
    nettle_gcm_aeadStateFinalize     :: NettleBlockCipher c => c -> NettleGCM -> Int -> AuthTag
    nettle_gcm_aeadStateFinalize :: forall c. NettleBlockCipher c => c -> NettleGCM -> Int -> AuthTag
    nettle_gcm_aeadStateFinalize     c
    c = (Ptr Word8 -> Ptr Word8)
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> NettleGCM
    -> Int
    -> AuthTag
    gcm_digest              (Tagged c (Ptr Word8 -> Ptr Word8)
    forall c. NettleBlockCipher c => Tagged c (Ptr Word8 -> Ptr Word8)
    nbc_encrypt_ctx_offset Tagged c (Ptr Word8 -> Ptr Word8) -> c -> Ptr Word8 -> Ptr Word8
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (Tagged c (FunPtr NettleCryptFunc)
    forall c. NettleBlockCipher c => Tagged c (FunPtr NettleCryptFunc)
    nbc_fun_encrypt Tagged c (FunPtr NettleCryptFunc) -> c -> FunPtr NettleCryptFunc
    forall a b. Tagged a b -> a -> b
    `witness` c
    c) (c -> SecureMem
    forall c. NettleCipher c => c -> SecureMem
    nc_ctx c
    c)

    key_init
    	:: ToSecureMem k
    	=> (Ptr Word8 -> Word -> Ptr Word8 -> IO ())
    	-> Int -> k -> SecureMem
    key_init :: forall k.
    ToSecureMem k =>
    (Ptr Word8 -> Word -> Ptr Word8 -> IO ()) -> Int -> k -> SecureMem
    key_init Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    initfun Int
    size k
    k = Int -> (Ptr Word8 -> IO ()) -> SecureMem
    unsafeCreateSecureMem Int
    size ((Ptr Word8 -> IO ()) -> SecureMem)
    -> (Ptr Word8 -> IO ()) -> SecureMem
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    	SecureMem -> (Int -> Ptr Word8 -> IO ()) -> IO ()
    forall b. SecureMem -> (Int -> Ptr Word8 -> IO b) -> IO b
    withSecureMemPtrSz (k -> SecureMem
    forall a. ToSecureMem a => a -> SecureMem
    toSecureMem k
    k) ((Int -> Ptr Word8 -> IO ()) -> IO ())
    -> (Int -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Int
    ksize Ptr Word8
    kptr -> Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    initfun Ptr Word8
    ctxptr (Int -> Word
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    ksize) Ptr Word8
    kptr

    -- run encryption/decryption with same length for in and output
    c_run_crypt
    	:: (Ptr Word8 -> Ptr Word8)
    	-> NettleCryptFunc
    	-> SecureMem -> B.ByteString -> B.ByteString
    c_run_crypt :: (Ptr Word8 -> Ptr Word8)
    -> NettleCryptFunc -> SecureMem -> ByteString -> ByteString
    c_run_crypt Ptr Word8 -> Ptr Word8
    ctxoffset NettleCryptFunc
    cfun SecureMem
    ctx ByteString
    indata = IO ByteString -> ByteString
    forall a. IO a -> a
    unsafeDupablePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ SecureMem -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    ctx ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    	ByteString -> (Word -> Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    indata ((Word -> Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Word -> Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Word
    indatalen Ptr Word8
    indataptr ->
    	Int -> (Ptr Word8 -> IO ()) -> IO ByteString
    B.create (ByteString -> Int
    B.length ByteString
    indata) ((Ptr Word8 -> IO ()) -> IO ByteString)
    -> (Ptr Word8 -> IO ()) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    outptr ->
    	NettleCryptFunc
    cfun (Ptr Word8 -> Ptr Word8
    ctxoffset Ptr Word8
    ctxptr) Word
    indatalen Ptr Word8
    outptr Ptr Word8
    indataptr

    blockmode_run
    	:: (Byteable iv)
    	=> (Ptr Word8 -> Ptr Word8)
    	-> NettleBlockMode
    	-> FunPtr NettleCryptFunc
    	-> SecureMem -> iv -> B.ByteString -> B.ByteString
    blockmode_run :: forall iv.
    Byteable iv =>
    (Ptr Word8 -> Ptr Word8)
    -> NettleBlockMode
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> iv
    -> ByteString
    -> ByteString
    blockmode_run Ptr Word8 -> Ptr Word8
    ctxoffset NettleBlockMode
    mode FunPtr NettleCryptFunc
    crypt SecureMem
    ctx iv
    iv ByteString
    indata = IO ByteString -> ByteString
    forall a. IO a -> a
    unsafeDupablePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ SecureMem -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    ctx ((Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    	ByteString -> (Word -> Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    indata ((Word -> Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Word -> Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Word
    indatalen Ptr Word8
    indataptr ->
    	SecureMem -> (Int -> Ptr Word8 -> IO ByteString) -> IO ByteString
    forall b. SecureMem -> (Int -> Ptr Word8 -> IO b) -> IO b
    withSecureMemPtrSz (ByteString -> SecureMem
    forall a. ToSecureMem a => a -> SecureMem
    toSecureMem (ByteString -> SecureMem) -> ByteString -> SecureMem
    forall a b. (a -> b) -> a -> b
    $ iv -> ByteString
    forall a. Byteable a => a -> ByteString
    toBytes iv
    iv) ((Int -> Ptr Word8 -> IO ByteString) -> IO ByteString)
    -> (Int -> Ptr Word8 -> IO ByteString) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Int
    ivlen Ptr Word8
    ivptr -> -- copy IV, may get modified
    	Int -> (Ptr Word8 -> IO ()) -> IO ByteString
    B.create (ByteString -> Int
    B.length ByteString
    indata) ((Ptr Word8 -> IO ()) -> IO ByteString)
    -> (Ptr Word8 -> IO ()) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    outptr ->
    	NettleBlockMode
    mode (Ptr Word8 -> Ptr Word8
    ctxoffset Ptr Word8
    ctxptr) FunPtr NettleCryptFunc
    crypt (Int -> Word
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    ivlen) Ptr Word8
    ivptr Word
    indatalen Ptr Word8
    outptr Ptr Word8
    indataptr

    data NettleGCM = NettleGCM !SecureMem !SecureMem

    gcm_init
    	:: (Byteable iv)
    	=> (Ptr Word8 -> Ptr Word8)
    	-> FunPtr NettleCryptFunc
    	-> SecureMem -> iv -> NettleGCM
    gcm_init :: forall iv.
    Byteable iv =>
    (Ptr Word8 -> Ptr Word8)
    -> FunPtr NettleCryptFunc -> SecureMem -> iv -> NettleGCM
    gcm_init Ptr Word8 -> Ptr Word8
    encctxoffset FunPtr NettleCryptFunc
    encrypt SecureMem
    encctx iv
    iv = IO NettleGCM -> NettleGCM
    forall a. IO a -> a
    unsafeDupablePerformIO (IO NettleGCM -> NettleGCM) -> IO NettleGCM -> NettleGCM
    forall a b. (a -> b) -> a -> b
    $
    	iv -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall b. iv -> (Ptr Word8 -> IO b) -> IO b
    forall a b. Byteable a => a -> (Ptr Word8 -> IO b) -> IO b
    withBytePtr iv
    iv ((Ptr Word8 -> IO NettleGCM) -> IO NettleGCM)
    -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ivptr ->
    	SecureMem -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    encctx ((Ptr Word8 -> IO NettleGCM) -> IO NettleGCM)
    -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    encctxptr -> do
    	SecureMem
    h <- Int -> (Ptr Word8 -> IO ()) -> IO SecureMem
    createSecureMem Int
    c_gcm_key_size ((Ptr Word8 -> IO ()) -> IO SecureMem)
    -> (Ptr Word8 -> IO ()) -> IO SecureMem
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    hptr ->
    		Ptr Word8 -> Ptr Word8 -> FunPtr NettleCryptFunc -> IO ()
    c_gcm_set_key Ptr Word8
    hptr (Ptr Word8 -> Ptr Word8
    encctxoffset Ptr Word8
    encctxptr) FunPtr NettleCryptFunc
    encrypt
    	SecureMem -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    h ((Ptr Word8 -> IO NettleGCM) -> IO NettleGCM)
    -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    hptr -> do
    	    SecureMem
    ctx <- Int -> (Ptr Word8 -> IO ()) -> IO SecureMem
    createSecureMem Int
    c_gcm_ctx_size ((Ptr Word8 -> IO ()) -> IO SecureMem)
    -> (Ptr Word8 -> IO ()) -> IO SecureMem
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    		Ptr Word8 -> Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    c_gcm_set_iv Ptr Word8
    ctxptr Ptr Word8
    hptr (Int -> Word
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> Word) -> Int -> Word
    forall a b. (a -> b) -> a -> b
    $ iv -> Int
    forall a. Byteable a => a -> Int
    byteableLength iv
    iv) Ptr Word8
    ivptr
    	    NettleGCM -> IO NettleGCM
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (SecureMem -> SecureMem -> NettleGCM
    NettleGCM SecureMem
    ctx SecureMem
    h)

    -- independent of cipher
    gcm_update
    	:: NettleGCM -> B.ByteString -> NettleGCM
    gcm_update :: NettleGCM -> ByteString -> NettleGCM
    gcm_update (NettleGCM SecureMem
    ctx SecureMem
    h) ByteString
    indata = IO NettleGCM -> NettleGCM
    forall a. IO a -> a
    unsafeDupablePerformIO (IO NettleGCM -> NettleGCM) -> IO NettleGCM -> NettleGCM
    forall a b. (a -> b) -> a -> b
    $
    	SecureMem -> IO SecureMem
    secureMemCopy SecureMem
    ctx IO SecureMem -> (SecureMem -> IO NettleGCM) -> IO NettleGCM
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \SecureMem
    ctx' ->
    	SecureMem -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    ctx' ((Ptr Word8 -> IO NettleGCM) -> IO NettleGCM)
    -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    	SecureMem -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    h ((Ptr Word8 -> IO NettleGCM) -> IO NettleGCM)
    -> (Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    hptr ->
    	ByteString -> (Word -> Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    indata ((Word -> Ptr Word8 -> IO NettleGCM) -> IO NettleGCM)
    -> (Word -> Ptr Word8 -> IO NettleGCM) -> IO NettleGCM
    forall a b. (a -> b) -> a -> b
    $ \Word
    indatalen Ptr Word8
    indataptr ->
    	Ptr Word8 -> Ptr Word8 -> Word -> Ptr Word8 -> IO ()
    c_gcm_update Ptr Word8
    ctxptr Ptr Word8
    hptr Word
    indatalen Ptr Word8
    indataptr IO () -> IO NettleGCM -> IO NettleGCM
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >>
    	NettleGCM -> IO NettleGCM
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (SecureMem -> SecureMem -> NettleGCM
    NettleGCM SecureMem
    ctx' SecureMem
    h)

    gcm_crypt
    	:: NettleGCMMode
    	-> (Ptr Word8 -> Ptr Word8)
    	-> FunPtr NettleCryptFunc
    	-> SecureMem -> NettleGCM -> B.ByteString -> (B.ByteString, NettleGCM)
    gcm_crypt :: NettleGCMMode
    -> (Ptr Word8 -> Ptr Word8)
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> NettleGCM
    -> ByteString
    -> (ByteString, NettleGCM)
    gcm_crypt NettleGCMMode
    mode Ptr Word8 -> Ptr Word8
    encctxoffset FunPtr NettleCryptFunc
    encrypt SecureMem
    encctx (NettleGCM SecureMem
    ctx SecureMem
    h) ByteString
    indata = IO (ByteString, NettleGCM) -> (ByteString, NettleGCM)
    forall a. IO a -> a
    unsafeDupablePerformIO (IO (ByteString, NettleGCM) -> (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM) -> (ByteString, NettleGCM)
    forall a b. (a -> b) -> a -> b
    $
    	SecureMem -> IO SecureMem
    secureMemCopy SecureMem
    ctx IO SecureMem
    -> (SecureMem -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \SecureMem
    ctx' ->
    	SecureMem
    -> (Ptr Word8 -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    ctx' ((Ptr Word8 -> IO (ByteString, NettleGCM))
     -> IO (ByteString, NettleGCM))
    -> (Ptr Word8 -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    	SecureMem
    -> (Ptr Word8 -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    h ((Ptr Word8 -> IO (ByteString, NettleGCM))
     -> IO (ByteString, NettleGCM))
    -> (Ptr Word8 -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    hptr ->
    	SecureMem
    -> (Ptr Word8 -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    encctx ((Ptr Word8 -> IO (ByteString, NettleGCM))
     -> IO (ByteString, NettleGCM))
    -> (Ptr Word8 -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    encctxptr ->
    	ByteString
    -> (Word -> Ptr Word8 -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    indata ((Word -> Ptr Word8 -> IO (ByteString, NettleGCM))
     -> IO (ByteString, NettleGCM))
    -> (Word -> Ptr Word8 -> IO (ByteString, NettleGCM))
    -> IO (ByteString, NettleGCM)
    forall a b. (a -> b) -> a -> b
    $ \Word
    indatalen Ptr Word8
    indataptr -> do
    	ByteString
    outdata <- Int -> (Ptr Word8 -> IO ()) -> IO ByteString
    B.create (ByteString -> Int
    B.length ByteString
    indata) ((Ptr Word8 -> IO ()) -> IO ByteString)
    -> (Ptr Word8 -> IO ()) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    outptr ->
    		NettleGCMMode
    mode Ptr Word8
    ctxptr Ptr Word8
    hptr (Ptr Word8 -> Ptr Word8
    encctxoffset Ptr Word8
    encctxptr) FunPtr NettleCryptFunc
    encrypt Word
    indatalen Ptr Word8
    outptr Ptr Word8
    indataptr
    	(ByteString, NettleGCM) -> IO (ByteString, NettleGCM)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ByteString
    outdata, SecureMem -> SecureMem -> NettleGCM
    NettleGCM SecureMem
    ctx' SecureMem
    h)

    gcm_digest
    	:: (Ptr Word8 -> Ptr Word8)
    	-> FunPtr NettleCryptFunc
    	-> SecureMem -> NettleGCM -> Int -> AuthTag
    gcm_digest :: (Ptr Word8 -> Ptr Word8)
    -> FunPtr NettleCryptFunc
    -> SecureMem
    -> NettleGCM
    -> Int
    -> AuthTag
    gcm_digest Ptr Word8 -> Ptr Word8
    encctxoffset FunPtr NettleCryptFunc
    encrypt SecureMem
    encctx (NettleGCM SecureMem
    ctx SecureMem
    h) Int
    taglen = IO AuthTag -> AuthTag
    forall a. IO a -> a
    unsafeDupablePerformIO (IO AuthTag -> AuthTag) -> IO AuthTag -> AuthTag
    forall a b. (a -> b) -> a -> b
    $
    	SecureMem -> IO SecureMem
    secureMemCopy SecureMem
    ctx IO SecureMem -> (SecureMem -> IO AuthTag) -> IO AuthTag
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \SecureMem
    ctx' ->
    	SecureMem -> (Ptr Word8 -> IO AuthTag) -> IO AuthTag
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    ctx' ((Ptr Word8 -> IO AuthTag) -> IO AuthTag)
    -> (Ptr Word8 -> IO AuthTag) -> IO AuthTag
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    	SecureMem -> (Ptr Word8 -> IO AuthTag) -> IO AuthTag
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    h ((Ptr Word8 -> IO AuthTag) -> IO AuthTag)
    -> (Ptr Word8 -> IO AuthTag) -> IO AuthTag
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    hptr ->
    	SecureMem -> (Ptr Word8 -> IO AuthTag) -> IO AuthTag
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    encctx ((Ptr Word8 -> IO AuthTag) -> IO AuthTag)
    -> (Ptr Word8 -> IO AuthTag) -> IO AuthTag
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    encctxptr -> do
    	ByteString
    tag <- Int -> (Ptr Word8 -> IO ()) -> IO ByteString
    B.create (Int -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    taglen) ((Ptr Word8 -> IO ()) -> IO ByteString)
    -> (Ptr Word8 -> IO ()) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    tagptr ->
    		Ptr Word8
    -> Ptr Word8
    -> Ptr Word8
    -> FunPtr NettleCryptFunc
    -> Word
    -> Ptr Word8
    -> IO ()
    c_gcm_digest Ptr Word8
    ctxptr Ptr Word8
    hptr (Ptr Word8 -> Ptr Word8
    encctxoffset Ptr Word8
    encctxptr) FunPtr NettleCryptFunc
    encrypt (Int -> Word
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    taglen) Ptr Word8
    tagptr
    	AuthTag -> IO AuthTag
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (AuthTag -> IO AuthTag) -> AuthTag -> IO AuthTag
    forall a b. (a -> b) -> a -> b
    $ ByteString -> AuthTag
    AuthTag ByteString
    tag

    stream_crypt
    	:: NettleCryptFunc
    	-> SecureMem -> B.ByteString -> (B.ByteString, SecureMem)
    stream_crypt :: NettleCryptFunc
    -> SecureMem -> ByteString -> (ByteString, SecureMem)
    stream_crypt NettleCryptFunc
    crypt SecureMem
    ctx ByteString
    indata = IO (ByteString, SecureMem) -> (ByteString, SecureMem)
    forall a. IO a -> a
    unsafeDupablePerformIO (IO (ByteString, SecureMem) -> (ByteString, SecureMem))
    -> IO (ByteString, SecureMem) -> (ByteString, SecureMem)
    forall a b. (a -> b) -> a -> b
    $
    	SecureMem -> IO SecureMem
    secureMemCopy SecureMem
    ctx IO SecureMem
    -> (SecureMem -> IO (ByteString, SecureMem))
    -> IO (ByteString, SecureMem)
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \SecureMem
    ctx' ->
    	SecureMem
    -> (Ptr Word8 -> IO (ByteString, SecureMem))
    -> IO (ByteString, SecureMem)
    forall b. SecureMem -> (Ptr Word8 -> IO b) -> IO b
    withSecureMemPtr SecureMem
    ctx' ((Ptr Word8 -> IO (ByteString, SecureMem))
     -> IO (ByteString, SecureMem))
    -> (Ptr Word8 -> IO (ByteString, SecureMem))
    -> IO (ByteString, SecureMem)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ctxptr ->
    	ByteString
    -> (Word -> Ptr Word8 -> IO (ByteString, SecureMem))
    -> IO (ByteString, SecureMem)
    forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    indata ((Word -> Ptr Word8 -> IO (ByteString, SecureMem))
     -> IO (ByteString, SecureMem))
    -> (Word -> Ptr Word8 -> IO (ByteString, SecureMem))
    -> IO (ByteString, SecureMem)
    forall a b. (a -> b) -> a -> b
    $ \Word
    indatalen Ptr Word8
    indataptr -> do
    	ByteString
    outdata <- Int -> (Ptr Word8 -> IO ()) -> IO ByteString
    B.create (ByteString -> Int
    B.length ByteString
    indata) ((Ptr Word8 -> IO ()) -> IO ByteString)
    -> (Ptr Word8 -> IO ()) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    outptr ->
    		NettleCryptFunc
    crypt Ptr Word8
    ctxptr Word
    indatalen Ptr Word8
    outptr Ptr Word8
    indataptr
    	(ByteString, SecureMem) -> IO (ByteString, SecureMem)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ByteString
    outdata, SecureMem
    ctx')