    {-# LANGUAGE ForeignFunctionInterface #-}
    {-# LANGUAGE ViewPatterns #-}
    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    -- |
    -- Module      : Crypto.Cipher.AES.Primitive
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : stable
    -- Portability : good
    --
    module Crypto.Cipher.AES.Primitive
        (
        -- * Block cipher data types
          AES

        -- * Authenticated encryption block cipher types
        , AESGCM
        , AESOCB

        -- * Creation
        , initAES

        -- * Miscellanea
        , genCTR
        , genCounter

        -- * Encryption
        , encryptECB
        , encryptCBC
        , encryptCTR
        , encryptXTS

        -- * Decryption
        , decryptECB
        , decryptCBC
        , decryptCTR
        , decryptXTS

        -- * CTR with 32-bit wrapping
        , combineC32

        -- * Incremental GCM
        , gcmMode
        , gcmInit

        -- * Incremental OCB
        , ocbMode
        , ocbInit

        -- * CCM
        , ccmMode
        , ccmInit
        ) where

    import           Data.Word
    import           Foreign.Ptr
    import           Foreign.C.Types
    import           Foreign.C.String

    import           Crypto.Error
    import           Crypto.Cipher.Types
    import           Crypto.Cipher.Types.Block (IV(..))
    import           Crypto.Internal.Compat
    import           Crypto.Internal.Imports
    import           Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes, withByteArray)
    import qualified Crypto.Internal.ByteArray as B

    instance Cipher AES where
        cipherName :: AES -> String
    cipherName    AES
    _ = String
    "AES"
        cipherKeySize :: AES -> KeySizeSpecifier
    cipherKeySize AES
    _ = [Int] -> KeySizeSpecifier
    KeySizeEnum [Int
    16,Int
    24,Int
    32]
        cipherInit :: forall key. ByteArray key => key -> CryptoFailable AES
    cipherInit key
    k    = key -> CryptoFailable AES
    forall key. ByteArrayAccess key => key -> CryptoFailable AES
    initAES key
    k

    instance BlockCipher AES where
        blockSize :: AES -> Int
    blockSize AES
    _ = Int
    16
        ecbEncrypt :: forall ba. ByteArray ba => AES -> ba -> ba
    ecbEncrypt = AES -> ba -> ba
    forall ba. ByteArray ba => AES -> ba -> ba
    encryptECB
        ecbDecrypt :: forall ba. ByteArray ba => AES -> ba -> ba
    ecbDecrypt = AES -> ba -> ba
    forall ba. ByteArray ba => AES -> ba -> ba
    decryptECB
        cbcEncrypt :: forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    cbcEncrypt = AES -> IV AES -> ba -> ba
    forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    encryptCBC
        cbcDecrypt :: forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    cbcDecrypt = AES -> IV AES -> ba -> ba
    forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    decryptCBC
        ctrCombine :: forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    ctrCombine = AES -> IV AES -> ba -> ba
    forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    encryptCTR
        aeadInit :: forall iv.
    ByteArrayAccess iv =>
    AEADMode -> AES -> iv -> CryptoFailable (AEAD AES)
    aeadInit AEADMode
    AEAD_GCM AES
    aes iv
    iv = AEAD AES -> CryptoFailable (AEAD AES)
    forall a. a -> CryptoFailable a
    CryptoPassed (AEAD AES -> CryptoFailable (AEAD AES))
    -> AEAD AES -> CryptoFailable (AEAD AES)
    forall a b. (a -> b) -> a -> b
    $ AEADModeImpl AESGCM -> AESGCM -> AEAD AES
    forall cipher st. AEADModeImpl st -> st -> AEAD cipher
    AEAD (AES -> AEADModeImpl AESGCM
    gcmMode AES
    aes) (AES -> iv -> AESGCM
    forall iv. ByteArrayAccess iv => AES -> iv -> AESGCM
    gcmInit AES
    aes iv
    iv)
        aeadInit AEADMode
    AEAD_OCB AES
    aes iv
    iv = AEAD AES -> CryptoFailable (AEAD AES)
    forall a. a -> CryptoFailable a
    CryptoPassed (AEAD AES -> CryptoFailable (AEAD AES))
    -> AEAD AES -> CryptoFailable (AEAD AES)
    forall a b. (a -> b) -> a -> b
    $ AEADModeImpl AESOCB -> AESOCB -> AEAD AES
    forall cipher st. AEADModeImpl st -> st -> AEAD cipher
    AEAD (AES -> AEADModeImpl AESOCB
    ocbMode AES
    aes) (AES -> iv -> AESOCB
    forall iv. ByteArrayAccess iv => AES -> iv -> AESOCB
    ocbInit AES
    aes iv
    iv)
        aeadInit (AEAD_CCM Int
    n CCM_M
    m CCM_L
    l) AES
    aes iv
    iv = AEADModeImpl AESCCM -> AESCCM -> AEAD AES
    forall cipher st. AEADModeImpl st -> st -> AEAD cipher
    AEAD (AES -> AEADModeImpl AESCCM
    ccmMode AES
    aes) (AESCCM -> AEAD AES)
    -> CryptoFailable AESCCM -> CryptoFailable (AEAD AES)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> AES -> iv -> Int -> CCM_M -> CCM_L -> CryptoFailable AESCCM
    forall iv.
    ByteArrayAccess iv =>
    AES -> iv -> Int -> CCM_M -> CCM_L -> CryptoFailable AESCCM
    ccmInit AES
    aes iv
    iv Int
    n CCM_M
    m CCM_L
    l
        aeadInit AEADMode
    _        AES
    _   iv
    _  = CryptoError -> CryptoFailable (AEAD AES)
    forall a. CryptoError -> CryptoFailable a
    CryptoFailed CryptoError
    CryptoError_AEADModeNotSupported
    instance BlockCipher128 AES where
        xtsEncrypt :: forall ba.
    ByteArray ba =>
    (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    xtsEncrypt = (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    forall ba.
    ByteArray ba =>
    (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    encryptXTS
        xtsDecrypt :: forall ba.
    ByteArray ba =>
    (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    xtsDecrypt = (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    forall ba.
    ByteArray ba =>
    (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    decryptXTS

    -- | Create an AES AEAD implementation for GCM
    gcmMode :: AES -> AEADModeImpl AESGCM
    gcmMode :: AES -> AEADModeImpl AESGCM
    gcmMode AES
    aes = AEADModeImpl
        { aeadImplAppendHeader :: forall ba. ByteArrayAccess ba => AESGCM -> ba -> AESGCM
    aeadImplAppendHeader = AESGCM -> ba -> AESGCM
    forall ba. ByteArrayAccess ba => AESGCM -> ba -> AESGCM
    gcmAppendAAD
        , aeadImplEncrypt :: forall ba. ByteArray ba => AESGCM -> ba -> (ba, AESGCM)
    aeadImplEncrypt      = AES -> AESGCM -> ba -> (ba, AESGCM)
    forall ba. ByteArray ba => AES -> AESGCM -> ba -> (ba, AESGCM)
    gcmAppendEncrypt AES
    aes
        , aeadImplDecrypt :: forall ba. ByteArray ba => AESGCM -> ba -> (ba, AESGCM)
    aeadImplDecrypt      = AES -> AESGCM -> ba -> (ba, AESGCM)
    forall ba. ByteArray ba => AES -> AESGCM -> ba -> (ba, AESGCM)
    gcmAppendDecrypt AES
    aes
        , aeadImplFinalize :: AESGCM -> Int -> AuthTag
    aeadImplFinalize     = AES -> AESGCM -> Int -> AuthTag
    gcmFinish AES
    aes
        }

    -- | Create an AES AEAD implementation for OCB
    ocbMode :: AES -> AEADModeImpl AESOCB
    ocbMode :: AES -> AEADModeImpl AESOCB
    ocbMode AES
    aes = AEADModeImpl
        { aeadImplAppendHeader :: forall ba. ByteArrayAccess ba => AESOCB -> ba -> AESOCB
    aeadImplAppendHeader = AES -> AESOCB -> ba -> AESOCB
    forall aad. ByteArrayAccess aad => AES -> AESOCB -> aad -> AESOCB
    ocbAppendAAD AES
    aes
        , aeadImplEncrypt :: forall ba. ByteArray ba => AESOCB -> ba -> (ba, AESOCB)
    aeadImplEncrypt      = AES -> AESOCB -> ba -> (ba, AESOCB)
    forall ba. ByteArray ba => AES -> AESOCB -> ba -> (ba, AESOCB)
    ocbAppendEncrypt AES
    aes
        , aeadImplDecrypt :: forall ba. ByteArray ba => AESOCB -> ba -> (ba, AESOCB)
    aeadImplDecrypt      = AES -> AESOCB -> ba -> (ba, AESOCB)
    forall ba. ByteArray ba => AES -> AESOCB -> ba -> (ba, AESOCB)
    ocbAppendDecrypt AES
    aes
        , aeadImplFinalize :: AESOCB -> Int -> AuthTag
    aeadImplFinalize     = AES -> AESOCB -> Int -> AuthTag
    ocbFinish AES
    aes
        }

    -- | Create an AES AEAD implementation for CCM
    ccmMode :: AES -> AEADModeImpl AESCCM
    ccmMode :: AES -> AEADModeImpl AESCCM
    ccmMode AES
    aes = AEADModeImpl
        { aeadImplAppendHeader :: forall ba. ByteArrayAccess ba => AESCCM -> ba -> AESCCM
    aeadImplAppendHeader = AES -> AESCCM -> ba -> AESCCM
    forall aad. ByteArrayAccess aad => AES -> AESCCM -> aad -> AESCCM
    ccmAppendAAD AES
    aes
        , aeadImplEncrypt :: forall ba. ByteArray ba => AESCCM -> ba -> (ba, AESCCM)
    aeadImplEncrypt      = AES -> AESCCM -> ba -> (ba, AESCCM)
    forall ba. ByteArray ba => AES -> AESCCM -> ba -> (ba, AESCCM)
    ccmEncrypt AES
    aes
        , aeadImplDecrypt :: forall ba. ByteArray ba => AESCCM -> ba -> (ba, AESCCM)
    aeadImplDecrypt      = AES -> AESCCM -> ba -> (ba, AESCCM)
    forall ba. ByteArray ba => AES -> AESCCM -> ba -> (ba, AESCCM)
    ccmDecrypt AES
    aes
        , aeadImplFinalize :: AESCCM -> Int -> AuthTag
    aeadImplFinalize     = AES -> AESCCM -> Int -> AuthTag
    ccmFinish AES
    aes
        }

    -- | AES Context (pre-processed key)
    newtype AES = AES ScrubbedBytes
        deriving (AES -> ()
    (AES -> ()) -> NFData AES
    forall a. (a -> ()) -> NFData a
    $crnf :: AES -> ()
    rnf :: AES -> ()
    NFData)

    -- | AESGCM State
    newtype AESGCM = AESGCM ScrubbedBytes
        deriving (AESGCM -> ()
    (AESGCM -> ()) -> NFData AESGCM
    forall a. (a -> ()) -> NFData a
    $crnf :: AESGCM -> ()
    rnf :: AESGCM -> ()
    NFData)

    -- | AESOCB State
    newtype AESOCB = AESOCB ScrubbedBytes
        deriving (AESOCB -> ()
    (AESOCB -> ()) -> NFData AESOCB
    forall a. (a -> ()) -> NFData a
    $crnf :: AESOCB -> ()
    rnf :: AESOCB -> ()
    NFData)

    -- | AESCCM State
    newtype AESCCM = AESCCM ScrubbedBytes
        deriving (AESCCM -> ()
    (AESCCM -> ()) -> NFData AESCCM
    forall a. (a -> ()) -> NFData a
    $crnf :: AESCCM -> ()
    rnf :: AESCCM -> ()
    NFData)

    sizeGCM :: Int
    sizeGCM :: Int
    sizeGCM = Int
    320

    sizeOCB :: Int
    sizeOCB :: Int
    sizeOCB = Int
    160

    sizeCCM :: Int
    sizeCCM :: Int
    sizeCCM = Int
    80

    keyToPtr :: AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr :: forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr (AES ScrubbedBytes
    b) Ptr AES -> IO a
    f = ScrubbedBytes -> (Ptr (ZonkAny 4) -> IO a) -> IO a
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ScrubbedBytes -> (Ptr p -> IO a) -> IO a
    withByteArray ScrubbedBytes
    b (Ptr AES -> IO a
    f (Ptr AES -> IO a)
    -> (Ptr (ZonkAny 4) -> Ptr AES) -> Ptr (ZonkAny 4) -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Ptr (ZonkAny 4) -> Ptr AES
    forall a b. Ptr a -> Ptr b
    castPtr)

    ivToPtr :: ByteArrayAccess iv => iv -> (Ptr Word8 -> IO a) -> IO a
    ivToPtr :: forall iv a.
    ByteArrayAccess iv =>
    iv -> (Ptr Word8 -> IO a) -> IO a
    ivToPtr iv
    iv Ptr Word8 -> IO a
    f = iv -> (Ptr (ZonkAny 3) -> IO a) -> IO a
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. iv -> (Ptr p -> IO a) -> IO a
    withByteArray iv
    iv (Ptr Word8 -> IO a
    f (Ptr Word8 -> IO a)
    -> (Ptr (ZonkAny 3) -> Ptr Word8) -> Ptr (ZonkAny 3) -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Ptr (ZonkAny 3) -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr)

    ivCopyPtr :: IV AES -> (Ptr Word8 -> IO a) -> IO (a, IV AES)
    ivCopyPtr :: forall a. IV AES -> (Ptr Word8 -> IO a) -> IO (a, IV AES)
    ivCopyPtr (IV byteArray
    iv) Ptr Word8 -> IO a
    f = (\(a
    x,byteArray
    y) -> (a
    x, byteArray -> IV AES
    forall c byteArray. ByteArray byteArray => byteArray -> IV c
    IV byteArray
    y)) ((a, byteArray) -> (a, IV AES))
    -> IO (a, byteArray) -> IO (a, IV AES)
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` byteArray -> (Ptr Word8 -> IO a) -> IO (a, byteArray)
    forall ba a.
    ByteArray ba =>
    ba -> (Ptr Word8 -> IO a) -> IO (a, ba)
    copyAndModify byteArray
    iv Ptr Word8 -> IO a
    f
      where
        copyAndModify :: ByteArray ba => ba -> (Ptr Word8 -> IO a) -> IO (a, ba)
        copyAndModify :: forall ba a.
    ByteArray ba =>
    ba -> (Ptr Word8 -> IO a) -> IO (a, ba)
    copyAndModify ba
    ba Ptr Word8 -> IO a
    f' = ba -> (Ptr Word8 -> IO a) -> IO (a, ba)
    forall bs1 bs2 p a.
    (ByteArrayAccess bs1, ByteArray bs2) =>
    bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
    B.copyRet ba
    ba Ptr Word8 -> IO a
    f'

    withKeyAndIV :: ByteArrayAccess iv => AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV :: forall iv a.
    ByteArrayAccess iv =>
    AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV AES
    ctx iv
    iv Ptr AES -> Ptr Word8 -> IO a
    f = AES -> (Ptr AES -> IO a) -> IO a
    forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr AES
    ctx ((Ptr AES -> IO a) -> IO a) -> (Ptr AES -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    kptr -> iv -> (Ptr Word8 -> IO a) -> IO a
    forall iv a.
    ByteArrayAccess iv =>
    iv -> (Ptr Word8 -> IO a) -> IO a
    ivToPtr iv
    iv ((Ptr Word8 -> IO a) -> IO a) -> (Ptr Word8 -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ivp -> Ptr AES -> Ptr Word8 -> IO a
    f Ptr AES
    kptr Ptr Word8
    ivp

    withKey2AndIV :: ByteArrayAccess iv => AES -> AES -> iv -> (Ptr AES -> Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKey2AndIV :: forall iv a.
    ByteArrayAccess iv =>
    AES
    -> AES -> iv -> (Ptr AES -> Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKey2AndIV AES
    key1 AES
    key2 iv
    iv Ptr AES -> Ptr AES -> Ptr Word8 -> IO a
    f =
        AES -> (Ptr AES -> IO a) -> IO a
    forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr AES
    key1 ((Ptr AES -> IO a) -> IO a) -> (Ptr AES -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    kptr1 -> AES -> (Ptr AES -> IO a) -> IO a
    forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr AES
    key2 ((Ptr AES -> IO a) -> IO a) -> (Ptr AES -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    kptr2 -> iv -> (Ptr Word8 -> IO a) -> IO a
    forall iv a.
    ByteArrayAccess iv =>
    iv -> (Ptr Word8 -> IO a) -> IO a
    ivToPtr iv
    iv ((Ptr Word8 -> IO a) -> IO a) -> (Ptr Word8 -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ivp -> Ptr AES -> Ptr AES -> Ptr Word8 -> IO a
    f Ptr AES
    kptr1 Ptr AES
    kptr2 Ptr Word8
    ivp

    withGCMKeyAndCopySt :: AES -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO a) -> IO (a, AESGCM)
    withGCMKeyAndCopySt :: forall a.
    AES -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO a) -> IO (a, AESGCM)
    withGCMKeyAndCopySt AES
    aes (AESGCM ScrubbedBytes
    gcmSt) Ptr AESGCM -> Ptr AES -> IO a
    f =
        AES -> (Ptr AES -> IO (a, AESGCM)) -> IO (a, AESGCM)
    forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr AES
    aes ((Ptr AES -> IO (a, AESGCM)) -> IO (a, AESGCM))
    -> (Ptr AES -> IO (a, AESGCM)) -> IO (a, AESGCM)
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    aesPtr -> do
            newSt <- ScrubbedBytes -> (Ptr (ZonkAny 10) -> IO ()) -> IO ScrubbedBytes
    forall bs1 bs2 p.
    (ByteArrayAccess bs1, ByteArray bs2) =>
    bs1 -> (Ptr p -> IO ()) -> IO bs2
    B.copy ScrubbedBytes
    gcmSt (\Ptr (ZonkAny 10)
    _ -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())
            a     <- withByteArray newSt $ \Ptr (ZonkAny 11)
    gcmStPtr -> Ptr AESGCM -> Ptr AES -> IO a
    f (Ptr (ZonkAny 11) -> Ptr AESGCM
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 11)
    gcmStPtr) Ptr AES
    aesPtr
            return (a, AESGCM newSt)

    withNewGCMSt :: AESGCM -> (Ptr AESGCM -> IO ()) -> IO AESGCM
    withNewGCMSt :: AESGCM -> (Ptr AESGCM -> IO ()) -> IO AESGCM
    withNewGCMSt (AESGCM ScrubbedBytes
    gcmSt) Ptr AESGCM -> IO ()
    f = ScrubbedBytes -> (Ptr (ZonkAny 2) -> IO ()) -> IO ScrubbedBytes
    forall bs1 bs2 p.
    (ByteArrayAccess bs1, ByteArray bs2) =>
    bs1 -> (Ptr p -> IO ()) -> IO bs2
    B.copy ScrubbedBytes
    gcmSt (Ptr AESGCM -> IO ()
    f (Ptr AESGCM -> IO ())
    -> (Ptr (ZonkAny 2) -> Ptr AESGCM) -> Ptr (ZonkAny 2) -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Ptr (ZonkAny 2) -> Ptr AESGCM
    forall a b. Ptr a -> Ptr b
    castPtr) IO ScrubbedBytes -> (ScrubbedBytes -> IO AESGCM) -> IO AESGCM
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \ScrubbedBytes
    sm2 -> AESGCM -> IO AESGCM
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ScrubbedBytes -> AESGCM
    AESGCM ScrubbedBytes
    sm2)

    withOCBKeyAndCopySt :: AES -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO a) -> IO (a, AESOCB)
    withOCBKeyAndCopySt :: forall a.
    AES -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO a) -> IO (a, AESOCB)
    withOCBKeyAndCopySt AES
    aes (AESOCB ScrubbedBytes
    gcmSt) Ptr AESOCB -> Ptr AES -> IO a
    f =
        AES -> (Ptr AES -> IO (a, AESOCB)) -> IO (a, AESOCB)
    forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr AES
    aes ((Ptr AES -> IO (a, AESOCB)) -> IO (a, AESOCB))
    -> (Ptr AES -> IO (a, AESOCB)) -> IO (a, AESOCB)
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    aesPtr -> do
            newSt <- ScrubbedBytes -> (Ptr (ZonkAny 15) -> IO ()) -> IO ScrubbedBytes
    forall bs1 bs2 p.
    (ByteArrayAccess bs1, ByteArray bs2) =>
    bs1 -> (Ptr p -> IO ()) -> IO bs2
    B.copy ScrubbedBytes
    gcmSt (\Ptr (ZonkAny 15)
    _ -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())
            a     <- withByteArray newSt $ \Ptr (ZonkAny 16)
    gcmStPtr -> Ptr AESOCB -> Ptr AES -> IO a
    f (Ptr (ZonkAny 16) -> Ptr AESOCB
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 16)
    gcmStPtr) Ptr AES
    aesPtr
            return (a, AESOCB newSt)

    withCCMKeyAndCopySt :: AES -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO a) -> IO (a, AESCCM)
    withCCMKeyAndCopySt :: forall a.
    AES -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO a) -> IO (a, AESCCM)
    withCCMKeyAndCopySt AES
    aes (AESCCM ScrubbedBytes
    ccmSt) Ptr AESCCM -> Ptr AES -> IO a
    f =
        AES -> (Ptr AES -> IO (a, AESCCM)) -> IO (a, AESCCM)
    forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr AES
    aes ((Ptr AES -> IO (a, AESCCM)) -> IO (a, AESCCM))
    -> (Ptr AES -> IO (a, AESCCM)) -> IO (a, AESCCM)
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    aesPtr -> do
            newSt <- ScrubbedBytes -> (Ptr (ZonkAny 20) -> IO ()) -> IO ScrubbedBytes
    forall bs1 bs2 p.
    (ByteArrayAccess bs1, ByteArray bs2) =>
    bs1 -> (Ptr p -> IO ()) -> IO bs2
    B.copy ScrubbedBytes
    ccmSt (\Ptr (ZonkAny 20)
    _ -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())
            a     <- withByteArray newSt $ \Ptr (ZonkAny 21)
    ccmStPtr -> Ptr AESCCM -> Ptr AES -> IO a
    f (Ptr (ZonkAny 21) -> Ptr AESCCM
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 21)
    ccmStPtr) Ptr AES
    aesPtr
            return (a, AESCCM newSt)

    -- | Initialize a new context with a key
    --
    -- Key needs to be of length 16, 24 or 32 bytes. Any other values will return failure
    initAES :: ByteArrayAccess key => key -> CryptoFailable AES
    initAES :: forall key. ByteArrayAccess key => key -> CryptoFailable AES
    initAES key
    k
        | Int
    len Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    16 = AES -> CryptoFailable AES
    forall a. a -> CryptoFailable a
    CryptoPassed (AES -> CryptoFailable AES) -> AES -> CryptoFailable AES
    forall a b. (a -> b) -> a -> b
    $ Int -> AES
    initWithRounds Int
    10
        | Int
    len Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    24 = AES -> CryptoFailable AES
    forall a. a -> CryptoFailable a
    CryptoPassed (AES -> CryptoFailable AES) -> AES -> CryptoFailable AES
    forall a b. (a -> b) -> a -> b
    $ Int -> AES
    initWithRounds Int
    12
        | Int
    len Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    32 = AES -> CryptoFailable AES
    forall a. a -> CryptoFailable a
    CryptoPassed (AES -> CryptoFailable AES) -> AES -> CryptoFailable AES
    forall a b. (a -> b) -> a -> b
    $ Int -> AES
    initWithRounds Int
    14
        | Bool
    otherwise = CryptoError -> CryptoFailable AES
    forall a. CryptoError -> CryptoFailable a
    CryptoFailed CryptoError
    CryptoError_KeySizeInvalid
      where len :: Int
    len = key -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length key
    k
            initWithRounds :: Int -> AES
    initWithRounds Int
    nbR = ScrubbedBytes -> AES
    AES (ScrubbedBytes -> AES) -> ScrubbedBytes -> AES
    forall a b. (a -> b) -> a -> b
    $ Int -> (Ptr (ZonkAny 1) -> IO ()) -> ScrubbedBytes
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze (Int
    16Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    16Int -> Int -> Int
    forall a. Num a => a -> a -> a
    *Int
    nbR) Ptr (ZonkAny 1) -> IO ()
    forall {a}. Ptr a -> IO ()
    aesInit
            aesInit :: Ptr a -> IO ()
    aesInit Ptr a
    ptr = key -> (Ptr (ZonkAny 0) -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. key -> (Ptr p -> IO a) -> IO a
    withByteArray key
    k ((Ptr (ZonkAny 0) -> IO ()) -> IO ())
    -> (Ptr (ZonkAny 0) -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 0)
    ikey ->
                Ptr AES -> CString -> CUInt -> IO ()
    c_aes_init (Ptr a -> Ptr AES
    forall a b. Ptr a -> Ptr b
    castPtr Ptr a
    ptr) (Ptr (ZonkAny 0) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 0)
    ikey) (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)

    -- | encrypt using Electronic Code Book (ECB)
    {-# NOINLINE encryptECB #-}
    encryptECB :: ByteArray ba => AES -> ba -> ba
    encryptECB :: forall ba. ByteArray ba => AES -> ba -> ba
    encryptECB = (CString -> Ptr AES -> CString -> CUInt -> IO ())
    -> AES -> ba -> ba
    forall ba b.
    ByteArray ba =>
    (Ptr b -> Ptr AES -> CString -> CUInt -> IO ()) -> AES -> ba -> ba
    doECB CString -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_encrypt_ecb

    -- | encrypt using Cipher Block Chaining (CBC)
    {-# NOINLINE encryptCBC #-}
    encryptCBC :: ByteArray ba
               => AES        -- ^ AES Context
               -> IV AES     -- ^ Initial vector of AES block size
               -> ba         -- ^ plaintext
               -> ba         -- ^ ciphertext
    encryptCBC :: forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    encryptCBC = (CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ())
    -> AES -> IV AES -> ba -> ba
    forall ba b.
    ByteArray ba =>
    (Ptr b -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ())
    -> AES -> IV AES -> ba -> ba
    doCBC CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
    c_aes_encrypt_cbc

    -- | generate a counter mode pad. this is generally xor-ed to an input
    -- to make the standard counter mode block operations.
    --
    -- if the length requested is not a multiple of the block cipher size,
    -- more data will be returned, so that the returned bytearray is
    -- a multiple of the block cipher size.
    {-# NOINLINE genCTR #-}
    genCTR :: ByteArray ba
           => AES    -- ^ Cipher Key.
           -> IV AES -- ^ usually a 128 bit integer.
           -> Int    -- ^ length of bytes required.
           -> ba
    genCTR :: forall ba. ByteArray ba => AES -> IV AES -> Int -> ba
    genCTR AES
    ctx (IV byteArray
    iv) Int
    len
        | Int
    len Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0  = ba
    forall a. ByteArray a => a
    B.empty
        | Bool
    otherwise = Int -> (Ptr (ZonkAny 5) -> IO ()) -> ba
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze (Int
    nbBlocks Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    16) Ptr (ZonkAny 5) -> IO ()
    forall {a}. Ptr a -> IO ()
    generate
      where generate :: Ptr a -> IO ()
    generate Ptr a
    o = AES -> byteArray -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall iv a.
    ByteArrayAccess iv =>
    AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV AES
    ctx byteArray
    iv ((Ptr AES -> Ptr Word8 -> IO ()) -> IO ())
    -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k Ptr Word8
    i -> CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
    c_aes_gen_ctr (Ptr a -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr a
    o) Ptr AES
    k Ptr Word8
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    nbBlocks)
            (Int
    nbBlocks',Int
    r) = Int
    len Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `quotRem` Int
    16
            nbBlocks :: Int
    nbBlocks = if Int
    r Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0 then Int
    nbBlocks' else Int
    nbBlocks' Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1

    -- | generate a counter mode pad. this is generally xor-ed to an input
    -- to make the standard counter mode block operations.
    --
    -- if the length requested is not a multiple of the block cipher size,
    -- more data will be returned, so that the returned bytearray is
    -- a multiple of the block cipher size.
    --
    -- Similiar to 'genCTR' but also return the next IV for continuation
    {-# NOINLINE genCounter #-}
    genCounter :: ByteArray ba
               => AES
               -> IV AES
               -> Int
               -> (ba, IV AES)
    genCounter :: forall ba. ByteArray ba => AES -> IV AES -> Int -> (ba, IV AES)
    genCounter AES
    ctx IV AES
    iv Int
    len
        | Int
    len Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0  = (ba
    forall a. ByteArray a => a
    B.empty, IV AES
    iv)
        | Bool
    otherwise = IO (ba, IV AES) -> (ba, IV AES)
    forall a. IO a -> a
    unsafeDoIO (IO (ba, IV AES) -> (ba, IV AES))
    -> IO (ba, IV AES) -> (ba, IV AES)
    forall a b. (a -> b) -> a -> b
    $
            AES -> (Ptr AES -> IO (ba, IV AES)) -> IO (ba, IV AES)
    forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr AES
    ctx ((Ptr AES -> IO (ba, IV AES)) -> IO (ba, IV AES))
    -> (Ptr AES -> IO (ba, IV AES)) -> IO (ba, IV AES)
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k ->
            IV AES -> (Ptr Word8 -> IO ba) -> IO (ba, IV AES)
    forall a. IV AES -> (Ptr Word8 -> IO a) -> IO (a, IV AES)
    ivCopyPtr IV AES
    iv ((Ptr Word8 -> IO ba) -> IO (ba, IV AES))
    -> (Ptr Word8 -> IO ba) -> IO (ba, IV AES)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    i ->
            Int -> (Ptr (ZonkAny 25) -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    outputLength ((Ptr (ZonkAny 25) -> IO ()) -> IO ba)
    -> (Ptr (ZonkAny 25) -> IO ()) -> IO ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 25)
    o -> do
                CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
    c_aes_gen_ctr_cont (Ptr (ZonkAny 25) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 25)
    o) Ptr AES
    k Ptr Word8
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    nbBlocks)
      where
            (Int
    nbBlocks',Int
    r) = Int
    len Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `quotRem` Int
    16
            nbBlocks :: Int
    nbBlocks = if Int
    r Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0 then Int
    nbBlocks' else Int
    nbBlocks' Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
            outputLength :: Int
    outputLength = Int
    nbBlocks Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    16

    {- TODO: when genCTR has same AESIV requirements for IV, add the following rules:
     - RULES "snd . genCounter" forall ctx iv len .  snd (genCounter ctx iv len) = genCTR ctx iv len
     -}

    -- | encrypt using Counter mode (CTR)
    --
    -- in CTR mode encryption and decryption is the same operation.
    {-# NOINLINE encryptCTR #-}
    encryptCTR :: ByteArray ba
               => AES        -- ^ AES Context
               -> IV AES     -- ^ initial vector of AES block size (usually representing a 128 bit integer)
               -> ba         -- ^ plaintext input
               -> ba         -- ^ ciphertext output
    encryptCTR :: forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    encryptCTR AES
    ctx IV AES
    iv ba
    input
        | Int
    len Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0          = ba
    forall a. ByteArray a => a
    B.empty
        | IV AES -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length IV AES
    iv Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    16 = String -> ba
    forall a. HasCallStack => String -> a
    error (String -> ba) -> String -> ba
    forall a b. (a -> b) -> a -> b
    $ String
    "AES error: IV length must be block size (16). Its length is: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ (Int -> String
    forall a. Show a => a -> String
    show (Int -> String) -> Int -> String
    forall a b. (a -> b) -> a -> b
    $ IV AES -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length IV AES
    iv)
        | Bool
    otherwise = Int -> (Ptr (ZonkAny 6) -> IO ()) -> ba
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze Int
    len Ptr (ZonkAny 6) -> IO ()
    forall {a}. Ptr a -> IO ()
    doEncrypt
      where doEncrypt :: Ptr a -> IO ()
    doEncrypt Ptr a
    o = AES -> IV AES -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall iv a.
    ByteArrayAccess iv =>
    AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV AES
    ctx IV AES
    iv ((Ptr AES -> Ptr Word8 -> IO ()) -> IO ())
    -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k Ptr Word8
    v -> ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                          CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
    c_aes_encrypt_ctr (Ptr a -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr a
    o) Ptr AES
    k Ptr Word8
    v CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)
            len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input

    -- | encrypt using XTS
    --
    -- the first key is the normal block encryption key
    -- the second key is used for the initial block tweak
    {-# NOINLINE encryptXTS #-}
    encryptXTS :: ByteArray ba
               => (AES,AES)  -- ^ AES cipher and tweak context
               -> IV AES     -- ^ a 128 bits IV, typically a sector or a block offset in XTS
               -> Word32     -- ^ number of rounds to skip, also seen a 16 byte offset in the sector or block.
               -> ba         -- ^ input to encrypt
               -> ba         -- ^ output encrypted
    encryptXTS :: forall ba.
    ByteArray ba =>
    (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    encryptXTS = (CString
     -> Ptr AES
     -> Ptr AES
     -> Ptr Word8
     -> CUInt
     -> CString
     -> CUInt
     -> IO ())
    -> (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    forall ba b.
    ByteArray ba =>
    (Ptr b
     -> Ptr AES
     -> Ptr AES
     -> Ptr Word8
     -> CUInt
     -> CString
     -> CUInt
     -> IO ())
    -> (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    doXTS CString
    -> Ptr AES
    -> Ptr AES
    -> Ptr Word8
    -> CUInt
    -> CString
    -> CUInt
    -> IO ()
    c_aes_encrypt_xts

    -- | decrypt using Electronic Code Book (ECB)
    {-# NOINLINE decryptECB #-}
    decryptECB :: ByteArray ba => AES -> ba -> ba
    decryptECB :: forall ba. ByteArray ba => AES -> ba -> ba
    decryptECB = (CString -> Ptr AES -> CString -> CUInt -> IO ())
    -> AES -> ba -> ba
    forall ba b.
    ByteArray ba =>
    (Ptr b -> Ptr AES -> CString -> CUInt -> IO ()) -> AES -> ba -> ba
    doECB CString -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_decrypt_ecb

    -- | decrypt using Cipher block chaining (CBC)
    {-# NOINLINE decryptCBC #-}
    decryptCBC :: ByteArray ba => AES -> IV AES -> ba -> ba
    decryptCBC :: forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    decryptCBC = (CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ())
    -> AES -> IV AES -> ba -> ba
    forall ba b.
    ByteArray ba =>
    (Ptr b -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ())
    -> AES -> IV AES -> ba -> ba
    doCBC CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
    c_aes_decrypt_cbc

    -- | decrypt using Counter mode (CTR).
    --
    -- in CTR mode encryption and decryption is the same operation.
    decryptCTR :: ByteArray ba
               => AES        -- ^ AES Context
               -> IV AES     -- ^ initial vector, usually representing a 128 bit integer
               -> ba         -- ^ ciphertext input
               -> ba         -- ^ plaintext output
    decryptCTR :: forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    decryptCTR = AES -> IV AES -> ba -> ba
    forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    encryptCTR

    -- | decrypt using XTS
    {-# NOINLINE decryptXTS #-}
    decryptXTS :: ByteArray ba
               => (AES,AES)  -- ^ AES cipher and tweak context
               -> IV AES     -- ^ a 128 bits IV, typically a sector or a block offset in XTS
               -> Word32     -- ^ number of rounds to skip, also seen a 16 byte offset in the sector or block.
               -> ba         -- ^ input to decrypt
               -> ba         -- ^ output decrypted
    decryptXTS :: forall ba.
    ByteArray ba =>
    (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    decryptXTS = (CString
     -> Ptr AES
     -> Ptr AES
     -> Ptr Word8
     -> CUInt
     -> CString
     -> CUInt
     -> IO ())
    -> (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    forall ba b.
    ByteArray ba =>
    (Ptr b
     -> Ptr AES
     -> Ptr AES
     -> Ptr Word8
     -> CUInt
     -> CString
     -> CUInt
     -> IO ())
    -> (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    doXTS CString
    -> Ptr AES
    -> Ptr AES
    -> Ptr Word8
    -> CUInt
    -> CString
    -> CUInt
    -> IO ()
    c_aes_decrypt_xts

    -- | encrypt/decrypt using Counter mode (32-bit wrapping used in AES-GCM-SIV)
    {-# NOINLINE combineC32 #-}
    combineC32 :: ByteArray ba
               => AES        -- ^ AES Context
               -> IV AES     -- ^ initial vector of AES block size (usually representing a 128 bit integer)
               -> ba         -- ^ plaintext input
               -> ba         -- ^ ciphertext output
    combineC32 :: forall ba. ByteArray ba => AES -> IV AES -> ba -> ba
    combineC32 AES
    ctx IV AES
    iv ba
    input
        | Int
    len Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0          = ba
    forall a. ByteArray a => a
    B.empty
        | IV AES -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length IV AES
    iv Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    16 = String -> ba
    forall a. HasCallStack => String -> a
    error (String -> ba) -> String -> ba
    forall a b. (a -> b) -> a -> b
    $ String
    "AES error: IV length must be block size (16). Its length is: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> String
    forall a. Show a => a -> String
    show (IV AES -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length IV AES
    iv)
        | Bool
    otherwise = Int -> (Ptr (ZonkAny 7) -> IO ()) -> ba
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze Int
    len Ptr (ZonkAny 7) -> IO ()
    forall {a}. Ptr a -> IO ()
    doEncrypt
      where doEncrypt :: Ptr a -> IO ()
    doEncrypt Ptr a
    o = AES -> IV AES -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall iv a.
    ByteArrayAccess iv =>
    AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV AES
    ctx IV AES
    iv ((Ptr AES -> Ptr Word8 -> IO ()) -> IO ())
    -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k Ptr Word8
    v -> ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                          CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
    c_aes_encrypt_c32 (Ptr a -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr a
    o) Ptr AES
    k Ptr Word8
    v CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)
            len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input

    {-# INLINE doECB #-}
    doECB :: ByteArray ba
          => (Ptr b -> Ptr AES -> CString -> CUInt -> IO ())
          -> AES -> ba -> ba
    doECB :: forall ba b.
    ByteArray ba =>
    (Ptr b -> Ptr AES -> CString -> CUInt -> IO ()) -> AES -> ba -> ba
    doECB Ptr b -> Ptr AES -> CString -> CUInt -> IO ()
    f AES
    ctx ba
    input
        | Int
    len Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0     = ba
    forall a. ByteArray a => a
    B.empty
        | Int
    r Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    0       = String -> ba
    forall a. HasCallStack => String -> a
    error (String -> ba) -> String -> ba
    forall a b. (a -> b) -> a -> b
    $ String
    "Encryption error: input length must be a multiple of block size (16). Its length is: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ (Int -> String
    forall a. Show a => a -> String
    show Int
    len)
        | Bool
    otherwise    =
            Int -> (Ptr (ZonkAny 26) -> IO ()) -> ba
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze Int
    len ((Ptr (ZonkAny 26) -> IO ()) -> ba)
    -> (Ptr (ZonkAny 26) -> IO ()) -> ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 26)
    o ->
            AES -> (Ptr AES -> IO ()) -> IO ()
    forall a. AES -> (Ptr AES -> IO a) -> IO a
    keyToPtr AES
    ctx         ((Ptr AES -> IO ()) -> IO ()) -> (Ptr AES -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k ->
            ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input  ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                Ptr b -> Ptr AES -> CString -> CUInt -> IO ()
    f (Ptr (ZonkAny 26) -> Ptr b
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 26)
    o) Ptr AES
    k CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    nbBlocks)
      where (Int
    nbBlocks, Int
    r) = Int
    len Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `quotRem` Int
    16
            len :: Int
    len           = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input

    {-# INLINE doCBC #-}
    doCBC :: ByteArray ba
          => (Ptr b -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ())
          -> AES -> IV AES -> ba -> ba
    doCBC :: forall ba b.
    ByteArray ba =>
    (Ptr b -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ())
    -> AES -> IV AES -> ba -> ba
    doCBC Ptr b -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
    f AES
    ctx (IV byteArray
    iv) ba
    input
        | Int
    len Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0  = ba
    forall a. ByteArray a => a
    B.empty
        | Int
    r Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    0    = String -> ba
    forall a. HasCallStack => String -> a
    error (String -> ba) -> String -> ba
    forall a b. (a -> b) -> a -> b
    $ String
    "Encryption error: input length must be a multiple of block size (16). Its length is: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ (Int -> String
    forall a. Show a => a -> String
    show Int
    len)
        | Bool
    otherwise = Int -> (Ptr (ZonkAny 8) -> IO ()) -> ba
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze Int
    len ((Ptr (ZonkAny 8) -> IO ()) -> ba)
    -> (Ptr (ZonkAny 8) -> IO ()) -> ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 8)
    o ->
                      AES -> byteArray -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall iv a.
    ByteArrayAccess iv =>
    AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV AES
    ctx byteArray
    iv ((Ptr AES -> Ptr Word8 -> IO ()) -> IO ())
    -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k Ptr Word8
    v ->
                      ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                      Ptr b -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
    f (Ptr (ZonkAny 8) -> Ptr b
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 8)
    o) Ptr AES
    k Ptr Word8
    v CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    nbBlocks)
      where (Int
    nbBlocks, Int
    r) = Int
    len Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `quotRem` Int
    16
            len :: Int
    len           = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input

    {-# INLINE doXTS #-}
    doXTS :: ByteArray ba
          => (Ptr b -> Ptr AES -> Ptr AES -> Ptr Word8 -> CUInt -> CString -> CUInt -> IO ())
          -> (AES, AES)
          -> IV AES
          -> Word32
          -> ba
          -> ba
    doXTS :: forall ba b.
    ByteArray ba =>
    (Ptr b
     -> Ptr AES
     -> Ptr AES
     -> Ptr Word8
     -> CUInt
     -> CString
     -> CUInt
     -> IO ())
    -> (AES, AES) -> IV AES -> DataUnitOffset -> ba -> ba
    doXTS Ptr b
    -> Ptr AES
    -> Ptr AES
    -> Ptr Word8
    -> CUInt
    -> CString
    -> CUInt
    -> IO ()
    f (AES
    key1,AES
    key2) IV AES
    iv DataUnitOffset
    spoint ba
    input
        | Int
    len Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0  = ba
    forall a. ByteArray a => a
    B.empty
        | Int
    r Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    0    = String -> ba
    forall a. HasCallStack => String -> a
    error (String -> ba) -> String -> ba
    forall a b. (a -> b) -> a -> b
    $ String
    "Encryption error: input length must be a multiple of block size (16) for now. Its length is: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ (Int -> String
    forall a. Show a => a -> String
    show Int
    len)
        | Bool
    otherwise = Int -> (Ptr (ZonkAny 9) -> IO ()) -> ba
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze Int
    len ((Ptr (ZonkAny 9) -> IO ()) -> ba)
    -> (Ptr (ZonkAny 9) -> IO ()) -> ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 9)
    o -> AES
    -> AES
    -> IV AES
    -> (Ptr AES -> Ptr AES -> Ptr Word8 -> IO ())
    -> IO ()
    forall iv a.
    ByteArrayAccess iv =>
    AES
    -> AES -> iv -> (Ptr AES -> Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKey2AndIV AES
    key1 AES
    key2 IV AES
    iv ((Ptr AES -> Ptr AES -> Ptr Word8 -> IO ()) -> IO ())
    -> (Ptr AES -> Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k1 Ptr AES
    k2 Ptr Word8
    v -> ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                Ptr b
    -> Ptr AES
    -> Ptr AES
    -> Ptr Word8
    -> CUInt
    -> CString
    -> CUInt
    -> IO ()
    f (Ptr (ZonkAny 9) -> Ptr b
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 9)
    o) Ptr AES
    k1 Ptr AES
    k2 Ptr Word8
    v (DataUnitOffset -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral DataUnitOffset
    spoint) CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    nbBlocks)
      where (Int
    nbBlocks, Int
    r) = Int
    len Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `quotRem` Int
    16
            len :: Int
    len           = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input

    ------------------------------------------------------------------------
    -- GCM
    ------------------------------------------------------------------------

    -- | initialize a gcm context
    {-# NOINLINE gcmInit #-}
    gcmInit :: ByteArrayAccess iv => AES -> iv -> AESGCM
    gcmInit :: forall iv. ByteArrayAccess iv => AES -> iv -> AESGCM
    gcmInit AES
    ctx iv
    iv = IO AESGCM -> AESGCM
    forall a. IO a -> a
    unsafeDoIO (IO AESGCM -> AESGCM) -> IO AESGCM -> AESGCM
    forall a b. (a -> b) -> a -> b
    $ do
        sm <- Int -> (Ptr (ZonkAny 29) -> IO ()) -> IO ScrubbedBytes
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    sizeGCM ((Ptr (ZonkAny 29) -> IO ()) -> IO ScrubbedBytes)
    -> (Ptr (ZonkAny 29) -> IO ()) -> IO ScrubbedBytes
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 29)
    gcmStPtr ->
                AES -> iv -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall iv a.
    ByteArrayAccess iv =>
    AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV AES
    ctx iv
    iv ((Ptr AES -> Ptr Word8 -> IO ()) -> IO ())
    -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k Ptr Word8
    v ->
                Ptr AESGCM -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
    c_aes_gcm_init (Ptr (ZonkAny 29) -> Ptr AESGCM
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 29)
    gcmStPtr) Ptr AES
    k Ptr Word8
    v (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> CUInt) -> Int -> CUInt
    forall a b. (a -> b) -> a -> b
    $ iv -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length iv
    iv)
        return $ AESGCM sm

    -- | append data which is only going to be authenticated to the GCM context.
    --
    -- needs to happen after initialization and before appending encryption/decryption data.
    {-# NOINLINE gcmAppendAAD #-}
    gcmAppendAAD :: ByteArrayAccess aad => AESGCM -> aad -> AESGCM
    gcmAppendAAD :: forall ba. ByteArrayAccess ba => AESGCM -> ba -> AESGCM
    gcmAppendAAD AESGCM
    gcmSt aad
    input = IO AESGCM -> AESGCM
    forall a. IO a -> a
    unsafeDoIO IO AESGCM
    doAppend
      where doAppend :: IO AESGCM
    doAppend =
                AESGCM -> (Ptr AESGCM -> IO ()) -> IO AESGCM
    withNewGCMSt AESGCM
    gcmSt ((Ptr AESGCM -> IO ()) -> IO AESGCM)
    -> (Ptr AESGCM -> IO ()) -> IO AESGCM
    forall a b. (a -> b) -> a -> b
    $ \Ptr AESGCM
    gcmStPtr ->
                aad -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. aad -> (Ptr p -> IO a) -> IO a
    withByteArray aad
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                Ptr AESGCM -> CString -> CUInt -> IO ()
    c_aes_gcm_aad Ptr AESGCM
    gcmStPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> CUInt) -> Int -> CUInt
    forall a b. (a -> b) -> a -> b
    $ aad -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length aad
    input)

    -- | append data to encrypt and append to the GCM context
    --
    -- the bytearray needs to be a multiple of AES block size, unless it's the last call to this function.
    -- needs to happen after AAD appending, or after initialization if no AAD data.
    {-# NOINLINE gcmAppendEncrypt #-}
    gcmAppendEncrypt :: ByteArray ba => AES -> AESGCM -> ba -> (ba, AESGCM)
    gcmAppendEncrypt :: forall ba. ByteArray ba => AES -> AESGCM -> ba -> (ba, AESGCM)
    gcmAppendEncrypt AES
    ctx AESGCM
    gcm ba
    input = IO (ba, AESGCM) -> (ba, AESGCM)
    forall a. IO a -> a
    unsafeDoIO (IO (ba, AESGCM) -> (ba, AESGCM))
    -> IO (ba, AESGCM) -> (ba, AESGCM)
    forall a b. (a -> b) -> a -> b
    $ AES
    -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO ba) -> IO (ba, AESGCM)
    forall a.
    AES -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO a) -> IO (a, AESGCM)
    withGCMKeyAndCopySt AES
    ctx AESGCM
    gcm Ptr AESGCM -> Ptr AES -> IO ba
    forall {ba}. ByteArray ba => Ptr AESGCM -> Ptr AES -> IO ba
    doEnc
      where len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input
            doEnc :: Ptr AESGCM -> Ptr AES -> IO ba
    doEnc Ptr AESGCM
    gcmStPtr Ptr AES
    aesPtr =
                Int -> (Ptr (ZonkAny 12) -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    len ((Ptr (ZonkAny 12) -> IO ()) -> IO ba)
    -> (Ptr (ZonkAny 12) -> IO ()) -> IO ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 12)
    o ->
                ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                CString -> Ptr AESGCM -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_gcm_encrypt (Ptr (ZonkAny 12) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 12)
    o) Ptr AESGCM
    gcmStPtr Ptr AES
    aesPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)

    -- | append data to decrypt and append to the GCM context
    --
    -- the bytearray needs to be a multiple of AES block size, unless it's the last call to this function.
    -- needs to happen after AAD appending, or after initialization if no AAD data.
    {-# NOINLINE gcmAppendDecrypt #-}
    gcmAppendDecrypt :: ByteArray ba => AES -> AESGCM -> ba -> (ba, AESGCM)
    gcmAppendDecrypt :: forall ba. ByteArray ba => AES -> AESGCM -> ba -> (ba, AESGCM)
    gcmAppendDecrypt AES
    ctx AESGCM
    gcm ba
    input = IO (ba, AESGCM) -> (ba, AESGCM)
    forall a. IO a -> a
    unsafeDoIO (IO (ba, AESGCM) -> (ba, AESGCM))
    -> IO (ba, AESGCM) -> (ba, AESGCM)
    forall a b. (a -> b) -> a -> b
    $ AES
    -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO ba) -> IO (ba, AESGCM)
    forall a.
    AES -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO a) -> IO (a, AESGCM)
    withGCMKeyAndCopySt AES
    ctx AESGCM
    gcm Ptr AESGCM -> Ptr AES -> IO ba
    forall {ba}. ByteArray ba => Ptr AESGCM -> Ptr AES -> IO ba
    doDec
      where len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input
            doDec :: Ptr AESGCM -> Ptr AES -> IO ba
    doDec Ptr AESGCM
    gcmStPtr Ptr AES
    aesPtr =
                Int -> (Ptr (ZonkAny 13) -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    len ((Ptr (ZonkAny 13) -> IO ()) -> IO ba)
    -> (Ptr (ZonkAny 13) -> IO ()) -> IO ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 13)
    o ->
                ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                CString -> Ptr AESGCM -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_gcm_decrypt (Ptr (ZonkAny 13) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 13)
    o) Ptr AESGCM
    gcmStPtr Ptr AES
    aesPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)

    -- | Generate the Tag from GCM context
    {-# NOINLINE gcmFinish #-}
    gcmFinish :: AES -> AESGCM -> Int -> AuthTag
    gcmFinish :: AES -> AESGCM -> Int -> AuthTag
    gcmFinish AES
    ctx AESGCM
    gcm Int
    taglen = Bytes -> AuthTag
    AuthTag (Bytes -> AuthTag) -> Bytes -> AuthTag
    forall a b. (a -> b) -> a -> b
    $ Int -> Bytes -> Bytes
    forall bs. ByteArray bs => Int -> bs -> bs
    B.take Int
    taglen Bytes
    computeTag
      where computeTag :: Bytes
    computeTag = Int -> (Ptr (ZonkAny 14) -> IO ()) -> Bytes
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze Int
    16 ((Ptr (ZonkAny 14) -> IO ()) -> Bytes)
    -> (Ptr (ZonkAny 14) -> IO ()) -> Bytes
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 14)
    t ->
                            AES
    -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO ()) -> IO ((), AESGCM)
    forall a.
    AES -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO a) -> IO (a, AESGCM)
    withGCMKeyAndCopySt AES
    ctx AESGCM
    gcm (CString -> Ptr AESGCM -> Ptr AES -> IO ()
    c_aes_gcm_finish (Ptr (ZonkAny 14) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 14)
    t)) IO ((), AESGCM) -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    ------------------------------------------------------------------------
    -- OCB v3
    ------------------------------------------------------------------------

    -- | initialize an ocb context
    {-# NOINLINE ocbInit #-}
    ocbInit :: ByteArrayAccess iv => AES -> iv -> AESOCB
    ocbInit :: forall iv. ByteArrayAccess iv => AES -> iv -> AESOCB
    ocbInit AES
    ctx iv
    iv = IO AESOCB -> AESOCB
    forall a. IO a -> a
    unsafeDoIO (IO AESOCB -> AESOCB) -> IO AESOCB -> AESOCB
    forall a b. (a -> b) -> a -> b
    $ do
        sm <- Int -> (Ptr (ZonkAny 28) -> IO ()) -> IO ScrubbedBytes
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    sizeOCB ((Ptr (ZonkAny 28) -> IO ()) -> IO ScrubbedBytes)
    -> (Ptr (ZonkAny 28) -> IO ()) -> IO ScrubbedBytes
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 28)
    ocbStPtr ->
                AES -> iv -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall iv a.
    ByteArrayAccess iv =>
    AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV AES
    ctx iv
    iv ((Ptr AES -> Ptr Word8 -> IO ()) -> IO ())
    -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k Ptr Word8
    v ->
                Ptr AESOCB -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
    c_aes_ocb_init (Ptr (ZonkAny 28) -> Ptr AESOCB
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 28)
    ocbStPtr) Ptr AES
    k Ptr Word8
    v (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> CUInt) -> Int -> CUInt
    forall a b. (a -> b) -> a -> b
    $ iv -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length iv
    iv)
        return $ AESOCB sm

    -- | append data which is going to just be authenticated to the OCB context.
    --
    -- need to happen after initialization and before appending encryption/decryption data.
    {-# NOINLINE ocbAppendAAD #-}
    ocbAppendAAD :: ByteArrayAccess aad => AES -> AESOCB -> aad -> AESOCB
    ocbAppendAAD :: forall aad. ByteArrayAccess aad => AES -> AESOCB -> aad -> AESOCB
    ocbAppendAAD AES
    ctx AESOCB
    ocb aad
    input = IO AESOCB -> AESOCB
    forall a. IO a -> a
    unsafeDoIO (((), AESOCB) -> AESOCB
    forall a b. (a, b) -> b
    snd (((), AESOCB) -> AESOCB) -> IO ((), AESOCB) -> IO AESOCB
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` AES
    -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO ()) -> IO ((), AESOCB)
    forall a.
    AES -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO a) -> IO (a, AESOCB)
    withOCBKeyAndCopySt AES
    ctx AESOCB
    ocb Ptr AESOCB -> Ptr AES -> IO ()
    doAppend)
      where doAppend :: Ptr AESOCB -> Ptr AES -> IO ()
    doAppend Ptr AESOCB
    ocbStPtr Ptr AES
    aesPtr =
                aad -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. aad -> (Ptr p -> IO a) -> IO a
    withByteArray aad
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_ocb_aad Ptr AESOCB
    ocbStPtr Ptr AES
    aesPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> CUInt) -> Int -> CUInt
    forall a b. (a -> b) -> a -> b
    $ aad -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length aad
    input)

    -- | append data to encrypt and append to the OCB context
    --
    -- the bytearray needs to be a multiple of the AES block size, unless it's the last call to this function.
    -- need to happen after AAD appending, or after initialization if no AAD data.
    {-# NOINLINE ocbAppendEncrypt #-}
    ocbAppendEncrypt :: ByteArray ba => AES -> AESOCB -> ba -> (ba, AESOCB)
    ocbAppendEncrypt :: forall ba. ByteArray ba => AES -> AESOCB -> ba -> (ba, AESOCB)
    ocbAppendEncrypt AES
    ctx AESOCB
    ocb ba
    input = IO (ba, AESOCB) -> (ba, AESOCB)
    forall a. IO a -> a
    unsafeDoIO (IO (ba, AESOCB) -> (ba, AESOCB))
    -> IO (ba, AESOCB) -> (ba, AESOCB)
    forall a b. (a -> b) -> a -> b
    $ AES
    -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO ba) -> IO (ba, AESOCB)
    forall a.
    AES -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO a) -> IO (a, AESOCB)
    withOCBKeyAndCopySt AES
    ctx AESOCB
    ocb Ptr AESOCB -> Ptr AES -> IO ba
    forall {ba}. ByteArray ba => Ptr AESOCB -> Ptr AES -> IO ba
    doEnc
      where len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input
            doEnc :: Ptr AESOCB -> Ptr AES -> IO ba
    doEnc Ptr AESOCB
    ocbStPtr Ptr AES
    aesPtr =
                Int -> (Ptr (ZonkAny 17) -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    len ((Ptr (ZonkAny 17) -> IO ()) -> IO ba)
    -> (Ptr (ZonkAny 17) -> IO ()) -> IO ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 17)
    o ->
                ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                CString -> Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_ocb_encrypt (Ptr (ZonkAny 17) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 17)
    o) Ptr AESOCB
    ocbStPtr Ptr AES
    aesPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)

    -- | append data to decrypt and append to the OCB context
    --
    -- the bytearray needs to be a multiple of the AES block size, unless it's the last call to this function.
    -- need to happen after AAD appending, or after initialization if no AAD data.
    {-# NOINLINE ocbAppendDecrypt #-}
    ocbAppendDecrypt :: ByteArray ba => AES -> AESOCB -> ba -> (ba, AESOCB)
    ocbAppendDecrypt :: forall ba. ByteArray ba => AES -> AESOCB -> ba -> (ba, AESOCB)
    ocbAppendDecrypt AES
    ctx AESOCB
    ocb ba
    input = IO (ba, AESOCB) -> (ba, AESOCB)
    forall a. IO a -> a
    unsafeDoIO (IO (ba, AESOCB) -> (ba, AESOCB))
    -> IO (ba, AESOCB) -> (ba, AESOCB)
    forall a b. (a -> b) -> a -> b
    $ AES
    -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO ba) -> IO (ba, AESOCB)
    forall a.
    AES -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO a) -> IO (a, AESOCB)
    withOCBKeyAndCopySt AES
    ctx AESOCB
    ocb Ptr AESOCB -> Ptr AES -> IO ba
    forall {ba}. ByteArray ba => Ptr AESOCB -> Ptr AES -> IO ba
    doDec
      where len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input
            doDec :: Ptr AESOCB -> Ptr AES -> IO ba
    doDec Ptr AESOCB
    ocbStPtr Ptr AES
    aesPtr =
                Int -> (Ptr (ZonkAny 18) -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    len ((Ptr (ZonkAny 18) -> IO ()) -> IO ba)
    -> (Ptr (ZonkAny 18) -> IO ()) -> IO ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 18)
    o ->
                ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                CString -> Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_ocb_decrypt (Ptr (ZonkAny 18) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 18)
    o) Ptr AESOCB
    ocbStPtr Ptr AES
    aesPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)

    -- | Generate the Tag from OCB context
    {-# NOINLINE ocbFinish #-}
    ocbFinish :: AES -> AESOCB -> Int -> AuthTag
    ocbFinish :: AES -> AESOCB -> Int -> AuthTag
    ocbFinish AES
    ctx AESOCB
    ocb Int
    taglen = Bytes -> AuthTag
    AuthTag (Bytes -> AuthTag) -> Bytes -> AuthTag
    forall a b. (a -> b) -> a -> b
    $ Int -> Bytes -> Bytes
    forall bs. ByteArray bs => Int -> bs -> bs
    B.take Int
    taglen Bytes
    computeTag
      where computeTag :: Bytes
    computeTag = Int -> (Ptr (ZonkAny 19) -> IO ()) -> Bytes
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze Int
    16 ((Ptr (ZonkAny 19) -> IO ()) -> Bytes)
    -> (Ptr (ZonkAny 19) -> IO ()) -> Bytes
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 19)
    t ->
                            AES
    -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO ()) -> IO ((), AESOCB)
    forall a.
    AES -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO a) -> IO (a, AESOCB)
    withOCBKeyAndCopySt AES
    ctx AESOCB
    ocb (CString -> Ptr AESOCB -> Ptr AES -> IO ()
    c_aes_ocb_finish (Ptr (ZonkAny 19) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 19)
    t)) IO ((), AESOCB) -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    ccmGetM :: CCM_M -> Int
    ccmGetL :: CCM_L -> Int
    ccmGetM :: CCM_M -> Int
    ccmGetM CCM_M
    m = case CCM_M
    m of
      CCM_M
    CCM_M4 -> Int
    4
      CCM_M
    CCM_M6 -> Int
    6
      CCM_M
    CCM_M8 -> Int
    8
      CCM_M
    CCM_M10 -> Int
    10
      CCM_M
    CCM_M12 -> Int
    12
      CCM_M
    CCM_M14 -> Int
    14
      CCM_M
    CCM_M16 -> Int
    16

    ccmGetL :: CCM_L -> Int
    ccmGetL CCM_L
    l = case CCM_L
    l of
      CCM_L
    CCM_L2 -> Int
    2
      CCM_L
    CCM_L3 -> Int
    3
      CCM_L
    CCM_L4 -> Int
    4

    -- | initialize a ccm context
    {-# NOINLINE ccmInit #-}
    ccmInit :: ByteArrayAccess iv => AES -> iv -> Int -> CCM_M -> CCM_L -> CryptoFailable AESCCM
    ccmInit :: forall iv.
    ByteArrayAccess iv =>
    AES -> iv -> Int -> CCM_M -> CCM_L -> CryptoFailable AESCCM
    ccmInit AES
    ctx iv
    iv Int
    n CCM_M
    m CCM_L
    l
        | Int
    15 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    li Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= iv -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length iv
    iv = CryptoError -> CryptoFailable AESCCM
    forall a. CryptoError -> CryptoFailable a
    CryptoFailed CryptoError
    CryptoError_IvSizeInvalid
        | Bool
    otherwise = IO (CryptoFailable AESCCM) -> CryptoFailable AESCCM
    forall a. IO a -> a
    unsafeDoIO (IO (CryptoFailable AESCCM) -> CryptoFailable AESCCM)
    -> IO (CryptoFailable AESCCM) -> CryptoFailable AESCCM
    forall a b. (a -> b) -> a -> b
    $ do
              sm <- Int -> (Ptr (ZonkAny 27) -> IO ()) -> IO ScrubbedBytes
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    sizeCCM ((Ptr (ZonkAny 27) -> IO ()) -> IO ScrubbedBytes)
    -> (Ptr (ZonkAny 27) -> IO ()) -> IO ScrubbedBytes
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 27)
    ccmStPtr ->
                AES -> iv -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall iv a.
    ByteArrayAccess iv =>
    AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
    withKeyAndIV AES
    ctx iv
    iv ((Ptr AES -> Ptr Word8 -> IO ()) -> IO ())
    -> (Ptr AES -> Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr AES
    k Ptr Word8
    v ->
                Ptr AESCCM
    -> Ptr AES -> Ptr Word8 -> CUInt -> CUInt -> CInt -> CInt -> IO ()
    c_aes_ccm_init (Ptr (ZonkAny 27) -> Ptr AESCCM
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 27)
    ccmStPtr) Ptr AES
    k Ptr Word8
    v (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> CUInt) -> Int -> CUInt
    forall a b. (a -> b) -> a -> b
    $ iv -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length iv
    iv) (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    n) (Int -> CInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    mi) (Int -> CInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    li)
              return $ CryptoPassed (AESCCM sm)
      where
        mi :: Int
    mi = CCM_M -> Int
    ccmGetM CCM_M
    m
        li :: Int
    li = CCM_L -> Int
    ccmGetL CCM_L
    l

    -- | append data which is only going to be authenticated to the CCM context.
    --
    -- needs to happen after initialization and before appending encryption/decryption data.
    {-# NOINLINE ccmAppendAAD #-}
    ccmAppendAAD :: ByteArrayAccess aad => AES -> AESCCM -> aad -> AESCCM
    ccmAppendAAD :: forall aad. ByteArrayAccess aad => AES -> AESCCM -> aad -> AESCCM
    ccmAppendAAD AES
    ctx AESCCM
    ccm aad
    input = IO AESCCM -> AESCCM
    forall a. IO a -> a
    unsafeDoIO (IO AESCCM -> AESCCM) -> IO AESCCM -> AESCCM
    forall a b. (a -> b) -> a -> b
    $ ((), AESCCM) -> AESCCM
    forall a b. (a, b) -> b
    snd (((), AESCCM) -> AESCCM) -> IO ((), AESCCM) -> IO AESCCM
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> AES
    -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO ()) -> IO ((), AESCCM)
    forall a.
    AES -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO a) -> IO (a, AESCCM)
    withCCMKeyAndCopySt AES
    ctx AESCCM
    ccm Ptr AESCCM -> Ptr AES -> IO ()
    doAppend
      where doAppend :: Ptr AESCCM -> Ptr AES -> IO ()
    doAppend Ptr AESCCM
    ccmStPtr Ptr AES
    aesPtr =
                aad -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. aad -> (Ptr p -> IO a) -> IO a
    withByteArray aad
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i -> Ptr AESCCM -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_ccm_aad Ptr AESCCM
    ccmStPtr Ptr AES
    aesPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> CUInt) -> Int -> CUInt
    forall a b. (a -> b) -> a -> b
    $ aad -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length aad
    input)

    -- | append data to encrypt and append to the CCM context
    --
    -- the bytearray needs to be a multiple of AES block size, unless it's the last call to this function.
    -- needs to happen after AAD appending, or after initialization if no AAD data.
    {-# NOINLINE ccmEncrypt #-}
    ccmEncrypt :: ByteArray ba => AES -> AESCCM -> ba -> (ba, AESCCM)
    ccmEncrypt :: forall ba. ByteArray ba => AES -> AESCCM -> ba -> (ba, AESCCM)
    ccmEncrypt AES
    ctx AESCCM
    ccm ba
    input = IO (ba, AESCCM) -> (ba, AESCCM)
    forall a. IO a -> a
    unsafeDoIO (IO (ba, AESCCM) -> (ba, AESCCM))
    -> IO (ba, AESCCM) -> (ba, AESCCM)
    forall a b. (a -> b) -> a -> b
    $ AES
    -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO ba) -> IO (ba, AESCCM)
    forall a.
    AES -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO a) -> IO (a, AESCCM)
    withCCMKeyAndCopySt AES
    ctx AESCCM
    ccm Ptr AESCCM -> Ptr AES -> IO ba
    forall {ba}. ByteArray ba => Ptr AESCCM -> Ptr AES -> IO ba
    cbcmacAndIv
      where len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input
            cbcmacAndIv :: Ptr AESCCM -> Ptr AES -> IO ba
    cbcmacAndIv Ptr AESCCM
    ccmStPtr Ptr AES
    aesPtr =
                Int -> (Ptr (ZonkAny 22) -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    len ((Ptr (ZonkAny 22) -> IO ()) -> IO ba)
    -> (Ptr (ZonkAny 22) -> IO ()) -> IO ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 22)
    o ->
                ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                CString -> Ptr AESCCM -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_ccm_encrypt (Ptr (ZonkAny 22) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 22)
    o) Ptr AESCCM
    ccmStPtr Ptr AES
    aesPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)

    -- | append data to decrypt and append to the CCM context
    --
    -- the bytearray needs to be a multiple of AES block size, unless it's the last call to this function.
    -- needs to happen after AAD appending, or after initialization if no AAD data.
    {-# NOINLINE ccmDecrypt #-}
    ccmDecrypt :: ByteArray ba => AES -> AESCCM -> ba -> (ba, AESCCM)
    ccmDecrypt :: forall ba. ByteArray ba => AES -> AESCCM -> ba -> (ba, AESCCM)
    ccmDecrypt AES
    ctx AESCCM
    ccm ba
    input = IO (ba, AESCCM) -> (ba, AESCCM)
    forall a. IO a -> a
    unsafeDoIO (IO (ba, AESCCM) -> (ba, AESCCM))
    -> IO (ba, AESCCM) -> (ba, AESCCM)
    forall a b. (a -> b) -> a -> b
    $ AES
    -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO ba) -> IO (ba, AESCCM)
    forall a.
    AES -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO a) -> IO (a, AESCCM)
    withCCMKeyAndCopySt AES
    ctx AESCCM
    ccm Ptr AESCCM -> Ptr AES -> IO ba
    forall {ba}. ByteArray ba => Ptr AESCCM -> Ptr AES -> IO ba
    cbcmacAndIv
      where len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    input
            cbcmacAndIv :: Ptr AESCCM -> Ptr AES -> IO ba
    cbcmacAndIv Ptr AESCCM
    ccmStPtr Ptr AES
    aesPtr =
                Int -> (Ptr (ZonkAny 23) -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    B.alloc Int
    len ((Ptr (ZonkAny 23) -> IO ()) -> IO ba)
    -> (Ptr (ZonkAny 23) -> IO ()) -> IO ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 23)
    o ->
                ba -> (CString -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    input ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \CString
    i ->
                CString -> Ptr AESCCM -> Ptr AES -> CString -> CUInt -> IO ()
    c_aes_ccm_decrypt (Ptr (ZonkAny 23) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 23)
    o) Ptr AESCCM
    ccmStPtr Ptr AES
    aesPtr CString
    i (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len)

    -- | Generate the Tag from CCM context
    {-# NOINLINE ccmFinish #-}
    ccmFinish :: AES -> AESCCM -> Int -> AuthTag
    ccmFinish :: AES -> AESCCM -> Int -> AuthTag
    ccmFinish AES
    ctx AESCCM
    ccm Int
    taglen = Bytes -> AuthTag
    AuthTag (Bytes -> AuthTag) -> Bytes -> AuthTag
    forall a b. (a -> b) -> a -> b
    $ Int -> Bytes -> Bytes
    forall bs. ByteArray bs => Int -> bs -> bs
    B.take Int
    taglen Bytes
    computeTag
      where computeTag :: Bytes
    computeTag = Int -> (Ptr (ZonkAny 24) -> IO ()) -> Bytes
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    B.allocAndFreeze Int
    16 ((Ptr (ZonkAny 24) -> IO ()) -> Bytes)
    -> (Ptr (ZonkAny 24) -> IO ()) -> Bytes
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 24)
    t ->
                            AES
    -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO ()) -> IO ((), AESCCM)
    forall a.
    AES -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO a) -> IO (a, AESCCM)
    withCCMKeyAndCopySt AES
    ctx AESCCM
    ccm (CString -> Ptr AESCCM -> Ptr AES -> IO ()
    c_aes_ccm_finish (Ptr (ZonkAny 24) -> CString
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 24)
    t)) IO ((), AESCCM) -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    ------------------------------------------------------------------------
    foreign import ccall "cryptonite_aes.h cryptonite_aes_initkey"
        c_aes_init :: Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_encrypt_ecb"
        c_aes_encrypt_ecb :: CString -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_decrypt_ecb"
        c_aes_decrypt_ecb :: CString -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_encrypt_cbc"
        c_aes_encrypt_cbc :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_decrypt_cbc"
        c_aes_decrypt_cbc :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_encrypt_xts"
        c_aes_encrypt_xts :: CString -> Ptr AES -> Ptr AES -> Ptr Word8 -> CUInt -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_decrypt_xts"
        c_aes_decrypt_xts :: CString -> Ptr AES -> Ptr AES -> Ptr Word8 -> CUInt -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_gen_ctr"
        c_aes_gen_ctr :: CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()

    foreign import ccall unsafe "cryptonite_aes.h cryptonite_aes_gen_ctr_cont"
        c_aes_gen_ctr_cont :: CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_encrypt_ctr"
        c_aes_encrypt_ctr :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_encrypt_c32"
        c_aes_encrypt_c32 :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_gcm_init"
        c_aes_gcm_init :: Ptr AESGCM -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_gcm_aad"
        c_aes_gcm_aad :: Ptr AESGCM -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_gcm_encrypt"
        c_aes_gcm_encrypt :: CString -> Ptr AESGCM -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_gcm_decrypt"
        c_aes_gcm_decrypt :: CString -> Ptr AESGCM -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_gcm_finish"
        c_aes_gcm_finish :: CString -> Ptr AESGCM -> Ptr AES -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ocb_init"
        c_aes_ocb_init :: Ptr AESOCB -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ocb_aad"
        c_aes_ocb_aad :: Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ocb_encrypt"
        c_aes_ocb_encrypt :: CString -> Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ocb_decrypt"
        c_aes_ocb_decrypt :: CString -> Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ocb_finish"
        c_aes_ocb_finish :: CString -> Ptr AESOCB -> Ptr AES -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_init"
        c_aes_ccm_init :: Ptr AESCCM -> Ptr AES -> Ptr Word8 -> CUInt -> CUInt -> CInt -> CInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_aad"
        c_aes_ccm_aad :: Ptr AESCCM -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_encrypt"
        c_aes_ccm_encrypt :: CString -> Ptr AESCCM -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_decrypt"
        c_aes_ccm_decrypt :: CString -> Ptr AESCCM -> Ptr AES -> CString -> CUInt -> IO ()

    foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_finish"
        c_aes_ccm_finish :: CString -> Ptr AESCCM -> Ptr AES -> IO ()