    {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Crypto.Nettle.CCM
    -- Copyright   :  (c) 2013 Stefan Bühler
    -- License     :  MIT-style (see the file COPYING)
    --
    -- Maintainer  :  stbuehler@web.de
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- (This is not a binding to nettle; it is implemented in pure haskell)
    --
    -- This module adds CCM support to all 128-bit block ciphers:
    --
    -- @aeadInit AEAD_CCM = ccmInitTLS@
    --
    -- CCM uses 2 parameters t and q: t is the tag length (2,4,6,8,10,12,14,16) and q (2..8) is the
    -- length in bytes that the length of the message is stored in (and the length of the
    -- counter variable).
    -- Maximum message length is @2^(8*q) - 1@.
    --
    -- CCM requires a nonce of length (15 - q). TLS uses CCM with @t = 16@ and @q = 3@,
    -- and a nonce length of 12 (the first 4 bytes are fixed from the handshake, the other 8
    -- usually represent the sequence counter).
    --
    -- CCM encrypts with a CTR mode, the start IV is based on the (t,q,nonce) parameters;
    -- the tag is encrypted with counter value = 0, then the message follows.
    --
    -- Calculating the tag needs the message length first - so this implementation needs
    -- to gather all data before calculating it.
    --
    -- In RFC 3610 @t@ is called @M@, and @q@ is called @L@.
    -----------------------------------------------------------------------------

    module Crypto.Nettle.CCM
    	( ccmInit
    	, ccmInitTLS
    	) where

    import Crypto.Cipher.Types
    import qualified Data.ByteString as B
    import Data.Byteable

    import Nettle.Utils

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

    -- ccm needs a 128-bit block cipher

    data CCM cipher
    	= CCM_Header (Int, Int, B.ByteString) B.ByteString
    	| CCM_Enc (Int, Int, B.ByteString) B.ByteString (IV cipher) B.ByteString
    	| CCM_Dec (Int, Int, B.ByteString) B.ByteString (IV cipher) B.ByteString

    {-|
    Start a CCM encryption with specified tag length @t@, length @q@ of the message length field and a @15-q@ bytes long @nonce@.
    Fails if any parameter is invalid or the block cipher doesn't use a 16-byte 'blockSize'.
    -}
    ccmInit
    	:: (BlockCipher cipher, Byteable iv)
    	=> Int    -- ^ tag length @t@
    	-> Int    -- ^ length @q@ of the message length field
    	-> cipher -- ^ cipher initialized with key
    	-> iv     -- ^ @nonce@ with length @15-q@
    	-> Maybe (AEAD cipher)
    ccmInit :: forall cipher iv.
    (BlockCipher cipher, Byteable iv) =>
    Int -> Int -> cipher -> iv -> Maybe (AEAD cipher)
    ccmInit Int
    t Int
    q cipher
    cipher iv
    nonce = Int -> Int -> cipher -> iv -> Maybe (CCM cipher)
    forall cipher iv.
    (BlockCipher cipher, Byteable iv) =>
    Int -> Int -> cipher -> iv -> Maybe (CCM cipher)
    ccm_init Int
    t Int
    q cipher
    cipher iv
    nonce Maybe (CCM cipher)
    -> (CCM cipher -> Maybe (AEAD cipher)) -> Maybe (AEAD cipher)
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= AEAD cipher -> Maybe (AEAD cipher)
    forall a. a -> Maybe a
    Just (AEAD cipher -> Maybe (AEAD cipher))
    -> (CCM cipher -> AEAD cipher) -> CCM cipher -> Maybe (AEAD cipher)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . cipher -> AEADState cipher -> AEAD cipher
    forall cipher. cipher -> AEADState cipher -> AEAD cipher
    AEAD cipher
    cipher (AEADState cipher -> AEAD cipher)
    -> (CCM cipher -> AEADState cipher) -> CCM cipher -> AEAD cipher
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CCM cipher -> AEADState cipher
    forall cipher st. AEADModeImpl cipher st => st -> AEADState cipher
    AEADState

    ccm_init :: (BlockCipher cipher, Byteable iv) => Int -> Int -> cipher -> iv -> Maybe (CCM cipher)
    ccm_init :: forall cipher iv.
    (BlockCipher cipher, Byteable iv) =>
    Int -> Int -> cipher -> iv -> Maybe (CCM cipher)
    ccm_init Int
    t Int
    q cipher
    cipher iv
    nonce = if Bool
    valid then CCM cipher -> Maybe (CCM cipher)
    forall a. a -> Maybe a
    Just (CCM cipher -> Maybe (CCM cipher))
    -> CCM cipher -> Maybe (CCM cipher)
    forall a b. (a -> b) -> a -> b
    $ (Int, Int, ByteString) -> ByteString -> CCM cipher
    forall cipher. (Int, Int, ByteString) -> ByteString -> CCM cipher
    CCM_Header (Int
    t, Int
    q, iv -> ByteString
    forall a. Byteable a => a -> ByteString
    toBytes iv
    nonce) ByteString
    B.empty else Maybe (CCM cipher)
    forall a. Maybe a
    Nothing
    	where
    	valid :: Bool
    valid = Bool
    valid_cipher Bool -> Bool -> Bool
    && Bool
    valid_t Bool -> Bool -> Bool
    && Bool
    valid_q Bool -> Bool -> Bool
    && Bool
    valid_nonce
    	valid_cipher :: Bool
    valid_cipher = cipher -> Int
    forall cipher. BlockCipher cipher => cipher -> Int
    blockSize cipher
    cipher Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    16
    	valid_t :: Bool
    valid_t = Int
    t Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    4 Bool -> Bool -> Bool
    && Int
    t Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    16 Bool -> Bool -> Bool
    && Int -> Bool
    forall a. Integral a => a -> Bool
    even Int
    t
    	valid_q :: Bool
    valid_q = Int
    q Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    2 Bool -> Bool -> Bool
    && Int
    q Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    8
    	nonce_len :: Int
    nonce_len = Int
    15 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    q
    	valid_nonce :: Bool
    valid_nonce = iv -> Int
    forall a. Byteable a => a -> Int
    byteableLength iv
    nonce Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    nonce_len

    {-|
    Start a CCM encryption with specified tag length @t = 16@, length @q = 3@ for the message length field and a @8@ bytes long @nonce@.
    Fails if any parameter is invalid or the block cipher doesn't use a 16-byte 'blockSize'.
    This are the parameters used for TLS.
    -}
    ccmInitTLS
    	:: (BlockCipher cipher, Byteable iv)
    	=> cipher -- ^ cipher initialized with key
    	-> iv     -- ^ 8 byte @nonce@
    	-> Maybe (AEAD cipher)
    ccmInitTLS :: forall cipher iv.
    (BlockCipher cipher, Byteable iv) =>
    cipher -> iv -> Maybe (AEAD cipher)
    ccmInitTLS = Int -> Int -> cipher -> iv -> Maybe (AEAD cipher)
    forall cipher iv.
    (BlockCipher cipher, Byteable iv) =>
    Int -> Int -> cipher -> iv -> Maybe (AEAD cipher)
    ccmInit Int
    16 Int
    3

    ccm_encodeAdditionalLength :: B.ByteString -> B.ByteString
    ccm_encodeAdditionalLength :: ByteString -> ByteString
    ccm_encodeAdditionalLength ByteString
    s = ByteString -> ByteString -> ByteString
    B.append (Int -> ByteString
    forall {n}. Integral n => n -> ByteString
    encLen (Int -> ByteString) -> Int -> ByteString
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Int
    B.length ByteString
    s) ByteString
    s where
    	encLen :: n -> ByteString
    encLen n
    n
    		| n
    n n -> n -> Bool
    forall a. Eq a => a -> a -> Bool
    == n
    0                       = ByteString
    B.empty
    		| n
    n n -> n -> Bool
    forall a. Ord a => a -> a -> Bool
    < (n
    2n -> Int -> n
    forall a b. (Num a, Integral b) => a -> b -> a
    ^(Int
    16::Int)n -> n -> n
    forall a. Num a => a -> a -> a
    -n
    2n -> Int -> n
    forall a b. (Num a, Integral b) => a -> b -> a
    ^(Int
    8::Int)) = [Word8] -> ByteString
    B.pack ([Word8] -> ByteString) -> [Word8] -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Int -> n -> [Word8]
    forall n. Integral n => Int -> n -> [Word8]
    netEncode Int
    2 n
    n
    		| n
    n n -> n -> Bool
    forall a. Ord a => a -> a -> Bool
    < (n
    2n -> Int -> n
    forall a b. (Num a, Integral b) => a -> b -> a
    ^(Int
    32::Int))            = [Word8] -> ByteString
    B.pack (Word8
    0xffWord8 -> [Word8] -> [Word8]
    forall a. a -> [a] -> [a]
    :Word8
    0xfeWord8 -> [Word8] -> [Word8]
    forall a. a -> [a] -> [a]
    :Int -> n -> [Word8]
    forall n. Integral n => Int -> n -> [Word8]
    netEncode Int
    4 n
    n)
    		| Bool
    otherwise                    = [Word8] -> ByteString
    B.pack (Word8
    0xffWord8 -> [Word8] -> [Word8]
    forall a. a -> [a] -> [a]
    :Word8
    0xffWord8 -> [Word8] -> [Word8]
    forall a. a -> [a] -> [a]
    :Int -> n -> [Word8]
    forall n. Integral n => Int -> n -> [Word8]
    netEncode Int
    8 n
    n)

    pad_zero :: Int -> B.ByteString -> B.ByteString
    pad_zero :: Int -> ByteString -> ByteString
    pad_zero Int
    l ByteString
    s = ByteString -> ByteString -> ByteString
    B.append ByteString
    s (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8 -> ByteString
    B.replicate (Int
    l Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - (ByteString -> Int
    B.length ByteString
    s Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `mod` Int
    l) Word8
    0

    _makeIV :: BlockCipher cipher => B.ByteString -> IV cipher
    _makeIV :: forall cipher. BlockCipher cipher => ByteString -> IV cipher
    _makeIV ByteString
    iv = let Just IV cipher
    iv' = ByteString -> Maybe (IV cipher)
    forall b c. (Byteable b, BlockCipher c) => b -> Maybe (IV c)
    makeIV ByteString
    iv in IV cipher
    iv'

    ccm_start_iv :: BlockCipher cipher => (Int, Int, B.ByteString) -> IV cipher
    ccm_start_iv :: forall cipher.
    BlockCipher cipher =>
    (Int, Int, ByteString) -> IV cipher
    ccm_start_iv (Int
    _, Int
    q, ByteString
    nonce) = ByteString -> IV cipher
    forall cipher. BlockCipher cipher => ByteString -> IV cipher
    _makeIV (ByteString -> IV cipher) -> ByteString -> IV cipher
    forall a b. (a -> b) -> a -> b
    $ [ByteString] -> ByteString
    B.concat [Word8 -> ByteString
    B.singleton (Word8 -> ByteString) -> Word8 -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> Word8) -> Int -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int
    q Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1, ByteString
    nonce, Int -> Word8 -> ByteString
    B.replicate (Int
    q Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1) Word8
    0, Word8 -> ByteString
    B.singleton Word8
    1]

    ccm_tag_iv :: BlockCipher cipher => (Int, Int, B.ByteString) -> IV cipher
    ccm_tag_iv :: forall cipher.
    BlockCipher cipher =>
    (Int, Int, ByteString) -> IV cipher
    ccm_tag_iv (Int
    _, Int
    q, ByteString
    nonce) = ByteString -> IV cipher
    forall cipher. BlockCipher cipher => ByteString -> IV cipher
    _makeIV (ByteString -> IV cipher) -> ByteString -> IV cipher
    forall a b. (a -> b) -> a -> b
    $ [ByteString] -> ByteString
    B.concat [Word8 -> ByteString
    B.singleton (Word8 -> ByteString) -> Word8 -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> Word8) -> Int -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int
    q Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1, ByteString
    nonce, Int -> Word8 -> ByteString
    B.replicate Int
    q Word8
    0]

    ccm_crypt :: BlockCipher cipher => cipher -> IV cipher -> B.ByteString -> (B.ByteString, IV cipher)
    ccm_crypt :: forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> (ByteString, IV cipher)
    ccm_crypt cipher
    key IV cipher
    iv ByteString
    src = let
    	blocks :: Int
    blocks = (ByteString -> Int
    B.length ByteString
    src Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    15) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    16
    	dst :: ByteString
    dst = cipher -> IV cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> ByteString
    ctrCombine cipher
    key IV cipher
    iv ByteString
    src
    	iv' :: IV cipher
    iv' = IV cipher -> Int -> IV cipher
    forall c. BlockCipher c => IV c -> Int -> IV c
    ivAdd IV cipher
    iv Int
    blocks
    	in (ByteString
    dst, IV cipher
    iv')

    ccm_tag :: BlockCipher cipher => cipher -> (Int, Int, B.ByteString) -> B.ByteString -> B.ByteString -> Int -> AuthTag
    ccm_tag :: forall cipher.
    BlockCipher cipher =>
    cipher
    -> (Int, Int, ByteString)
    -> ByteString
    -> ByteString
    -> Int
    -> AuthTag
    ccm_tag cipher
    key (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header ByteString
    msg Int
    taglen = let
    	-- 64*(header != "") + 8*M' + L'
    	auth_flags :: Word8
    auth_flags = (if ByteString -> Int
    B.length ByteString
    header Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    0 then Word8
    64 else Word8
    0) Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + Word8
    4Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    *(Int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    t Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    - Word8
    2) Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + (Int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    q Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    - Word8
    1)
    	b0 :: ByteString
    b0 = [ByteString] -> ByteString
    B.concat [Word8 -> ByteString
    B.singleton Word8
    auth_flags, ByteString
    nonce, [Word8] -> ByteString
    B.pack ([Word8] -> ByteString) -> [Word8] -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> [Word8]
    forall n. Integral n => Int -> n -> [Word8]
    netEncode Int
    q (Int -> [Word8]) -> Int -> [Word8]
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Int
    B.length ByteString
    msg]
    	blocks :: ByteString
    blocks = [ByteString] -> ByteString
    B.concat [ByteString
    b0, Int -> ByteString -> ByteString
    pad_zero Int
    16 (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ByteString
    ccm_encodeAdditionalLength ByteString
    header, Int -> ByteString -> ByteString
    pad_zero Int
    16 ByteString
    msg]
    	tag :: ByteString
    tag = (ByteString, IV cipher) -> ByteString
    forall a b. (a, b) -> a
    fst ((ByteString, IV cipher) -> ByteString)
    -> (ByteString, IV cipher) -> ByteString
    forall a b. (a -> b) -> a -> b
    $ cipher -> IV cipher -> ByteString -> (ByteString, IV cipher)
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> (ByteString, IV cipher)
    ccm_crypt cipher
    key ((Int, Int, ByteString) -> IV cipher
    forall cipher.
    BlockCipher cipher =>
    (Int, Int, ByteString) -> IV cipher
    ccm_tag_iv (Int
    t, Int
    q, ByteString
    nonce)) (ByteString -> (ByteString, IV cipher))
    -> ByteString -> (ByteString, IV cipher)
    forall a b. (a -> b) -> a -> b
    $ Int -> ByteString -> ByteString
    B.drop (ByteString -> Int
    B.length ByteString
    blocks Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    16) (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ cipher -> IV cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> ByteString
    cbcEncrypt cipher
    key IV cipher
    forall c. BlockCipher c => IV c
    nullIV ByteString
    blocks
    	in ByteString -> AuthTag
    AuthTag (ByteString -> AuthTag) -> ByteString -> AuthTag
    forall a b. (a -> b) -> a -> b
    $ Int -> ByteString -> ByteString
    B.take Int
    taglen ByteString
    tag

    instance BlockCipher cipher => AEADModeImpl cipher (CCM cipher) where
    	aeadStateAppendHeader :: cipher -> CCM cipher -> ByteString -> CCM cipher
    aeadStateAppendHeader cipher
    _ (CCM_Header (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header) ByteString
    src = (Int, Int, ByteString) -> ByteString -> CCM cipher
    forall cipher. (Int, Int, ByteString) -> ByteString -> CCM cipher
    CCM_Header (Int
    t, Int
    q, ByteString
    nonce) (ByteString -> CCM cipher) -> ByteString -> CCM cipher
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ByteString -> ByteString
    B.append ByteString
    header ByteString
    src
    	aeadStateAppendHeader cipher
    _ CCM cipher
    _ ByteString
    _ = [Char] -> CCM cipher
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "can't aeadStateAppendHeader anymore, already have real data"
    	aeadStateEncrypt :: cipher -> CCM cipher -> ByteString -> (ByteString, CCM cipher)
    aeadStateEncrypt cipher
    key (CCM_Header (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header) ByteString
    src = cipher -> CCM cipher -> ByteString -> (ByteString, CCM cipher)
    forall cipher state.
    AEADModeImpl cipher state =>
    cipher -> state -> ByteString -> (ByteString, state)
    aeadStateEncrypt cipher
    key ((Int, Int, ByteString)
    -> ByteString -> IV cipher -> ByteString -> CCM cipher
    forall cipher.
    (Int, Int, ByteString)
    -> ByteString -> IV cipher -> ByteString -> CCM cipher
    CCM_Enc (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header IV cipher
    iv ByteString
    B.empty) ByteString
    src
    		where iv :: IV cipher
    iv = (Int, Int, ByteString) -> IV cipher
    forall cipher.
    BlockCipher cipher =>
    (Int, Int, ByteString) -> IV cipher
    ccm_start_iv (Int
    t, Int
    q, ByteString
    nonce)
    	aeadStateEncrypt cipher
    key (CCM_Enc (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header IV cipher
    iv ByteString
    msg) ByteString
    src = let
    		(ByteString
    dst, IV cipher
    iv') = cipher -> IV cipher -> ByteString -> (ByteString, IV cipher)
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> (ByteString, IV cipher)
    ccm_crypt cipher
    key IV cipher
    iv ByteString
    src
    		in (ByteString
    dst, (Int, Int, ByteString)
    -> ByteString -> IV cipher -> ByteString -> CCM cipher
    forall cipher.
    (Int, Int, ByteString)
    -> ByteString -> IV cipher -> ByteString -> CCM cipher
    CCM_Enc (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header IV cipher
    iv' (ByteString -> CCM cipher) -> ByteString -> CCM cipher
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ByteString -> ByteString
    B.append ByteString
    msg ByteString
    src)
    	aeadStateEncrypt cipher
    _ CCM cipher
    _ ByteString
    _ = [Char] -> (ByteString, CCM cipher)
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "can't aeadStateEncrypt anymore, already is in decrypt mode"
    	aeadStateDecrypt :: cipher -> CCM cipher -> ByteString -> (ByteString, CCM cipher)
    aeadStateDecrypt cipher
    key (CCM_Header (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header) ByteString
    src = cipher -> CCM cipher -> ByteString -> (ByteString, CCM cipher)
    forall cipher state.
    AEADModeImpl cipher state =>
    cipher -> state -> ByteString -> (ByteString, state)
    aeadStateDecrypt cipher
    key ((Int, Int, ByteString)
    -> ByteString -> IV cipher -> ByteString -> CCM cipher
    forall cipher.
    (Int, Int, ByteString)
    -> ByteString -> IV cipher -> ByteString -> CCM cipher
    CCM_Dec (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header IV cipher
    iv ByteString
    B.empty) ByteString
    src
    		where iv :: IV cipher
    iv = (Int, Int, ByteString) -> IV cipher
    forall cipher.
    BlockCipher cipher =>
    (Int, Int, ByteString) -> IV cipher
    ccm_start_iv (Int
    t, Int
    q, ByteString
    nonce)
    	aeadStateDecrypt cipher
    key (CCM_Dec (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header IV cipher
    iv ByteString
    msg) ByteString
    src = let
    		(ByteString
    dst, IV cipher
    iv') = cipher -> IV cipher -> ByteString -> (ByteString, IV cipher)
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> (ByteString, IV cipher)
    ccm_crypt cipher
    key IV cipher
    iv ByteString
    src
    		in (ByteString
    dst, (Int, Int, ByteString)
    -> ByteString -> IV cipher -> ByteString -> CCM cipher
    forall cipher.
    (Int, Int, ByteString)
    -> ByteString -> IV cipher -> ByteString -> CCM cipher
    CCM_Enc (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header IV cipher
    iv' (ByteString -> CCM cipher) -> ByteString -> CCM cipher
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ByteString -> ByteString
    B.append ByteString
    msg ByteString
    dst)
    	aeadStateDecrypt cipher
    _ CCM cipher
    _ ByteString
    _ = [Char] -> (ByteString, CCM cipher)
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "can't aeadStateDecrypt anymore, already is in encrypt mode"
    	aeadStateFinalize :: cipher -> CCM cipher -> Int -> AuthTag
    aeadStateFinalize cipher
    key (CCM_Header (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header      ) Int
    taglen = cipher
    -> (Int, Int, ByteString)
    -> ByteString
    -> ByteString
    -> Int
    -> AuthTag
    forall cipher.
    BlockCipher cipher =>
    cipher
    -> (Int, Int, ByteString)
    -> ByteString
    -> ByteString
    -> Int
    -> AuthTag
    ccm_tag cipher
    key (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header ByteString
    B.empty Int
    taglen
    	aeadStateFinalize cipher
    key (CCM_Enc    (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header IV cipher
    _ ByteString
    msg) Int
    taglen = cipher
    -> (Int, Int, ByteString)
    -> ByteString
    -> ByteString
    -> Int
    -> AuthTag
    forall cipher.
    BlockCipher cipher =>
    cipher
    -> (Int, Int, ByteString)
    -> ByteString
    -> ByteString
    -> Int
    -> AuthTag
    ccm_tag cipher
    key (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header ByteString
    msg     Int
    taglen
    	aeadStateFinalize cipher
    key (CCM_Dec    (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header IV cipher
    _ ByteString
    msg) Int
    taglen = cipher
    -> (Int, Int, ByteString)
    -> ByteString
    -> ByteString
    -> Int
    -> AuthTag
    forall cipher.
    BlockCipher cipher =>
    cipher
    -> (Int, Int, ByteString)
    -> ByteString
    -> ByteString
    -> Int
    -> AuthTag
    ccm_tag cipher
    key (Int
    t, Int
    q, ByteString
    nonce) ByteString
    header ByteString
    msg     Int
    taglen