-- |
-- Module      : Crypto.Cipher.Types.AEAD
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : Stable
-- Portability : Excellent
--
-- AEAD cipher basic types
--
module Crypto.Cipher.Types.AEAD where

import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.Byteable
import Crypto.Cipher.Types.Base
import Crypto.Cipher.Types.Block

-- | Append associated data into the AEAD state
aeadAppendHeader :: BlockCipher a => AEAD a -> ByteString -> AEAD a
aeadAppendHeader :: forall a. BlockCipher a => AEAD a -> ByteString -> AEAD a
aeadAppendHeader (AEAD a
cipher (AEADState st
state)) ByteString
bs =
    forall cipher. cipher -> AEADState cipher -> AEAD cipher
AEAD a
cipher forall a b. (a -> b) -> a -> b
$ forall cipher st. AEADModeImpl cipher st => st -> AEADState cipher
AEADState (forall cipher state.
AEADModeImpl cipher state =>
cipher -> state -> ByteString -> state
aeadStateAppendHeader a
cipher st
state ByteString
bs)

-- | Encrypt input and append into the AEAD state
aeadEncrypt :: BlockCipher a => AEAD a -> ByteString -> (ByteString, AEAD a)
aeadEncrypt :: forall a.
BlockCipher a =>
AEAD a -> ByteString -> (ByteString, AEAD a)
aeadEncrypt (AEAD a
cipher (AEADState st
state)) ByteString
input = (ByteString
output, forall cipher. cipher -> AEADState cipher -> AEAD cipher
AEAD a
cipher (forall cipher st. AEADModeImpl cipher st => st -> AEADState cipher
AEADState st
nst))
  where (ByteString
output, st
nst) = forall cipher state.
AEADModeImpl cipher state =>
cipher -> state -> ByteString -> (ByteString, state)
aeadStateEncrypt a
cipher st
state ByteString
input

-- | Decrypt input and append into the AEAD state
aeadDecrypt :: BlockCipher a => AEAD a -> ByteString -> (ByteString, AEAD a)
aeadDecrypt :: forall a.
BlockCipher a =>
AEAD a -> ByteString -> (ByteString, AEAD a)
aeadDecrypt (AEAD a
cipher (AEADState st
state)) ByteString
input = (ByteString
output, forall cipher. cipher -> AEADState cipher -> AEAD cipher
AEAD a
cipher (forall cipher st. AEADModeImpl cipher st => st -> AEADState cipher
AEADState st
nst))
  where (ByteString
output, st
nst) = forall cipher state.
AEADModeImpl cipher state =>
cipher -> state -> ByteString -> (ByteString, state)
aeadStateDecrypt a
cipher st
state ByteString
input

-- | Finalize the AEAD state and create an authentification tag
aeadFinalize :: BlockCipher a => AEAD a -> Int -> AuthTag
aeadFinalize :: forall a. BlockCipher a => AEAD a -> Int -> AuthTag
aeadFinalize (AEAD a
cipher (AEADState st
state)) Int
len =
    forall cipher state.
AEADModeImpl cipher state =>
cipher -> state -> Int -> AuthTag
aeadStateFinalize a
cipher st
state Int
len

-- | Simple AEAD encryption
aeadSimpleEncrypt :: BlockCipher a
                  => AEAD a        -- ^ A new AEAD Context
                  -> B.ByteString  -- ^ Optional Authentified Header
                  -> B.ByteString  -- ^ Optional Plaintext
                  -> Int           -- ^ Tag length
                  -> (AuthTag, B.ByteString) -- ^ Authentification tag and ciphertext
aeadSimpleEncrypt :: forall a.
BlockCipher a =>
AEAD a -> ByteString -> ByteString -> Int -> (AuthTag, ByteString)
aeadSimpleEncrypt AEAD a
aeadIni ByteString
header ByteString
input Int
taglen = (AuthTag
tag, ByteString
output)
  where aead :: AEAD a
aead                = forall a. BlockCipher a => AEAD a -> ByteString -> AEAD a
aeadAppendHeader AEAD a
aeadIni ByteString
header
        (ByteString
output, AEAD a
aeadFinal) = forall a.
BlockCipher a =>
AEAD a -> ByteString -> (ByteString, AEAD a)
aeadEncrypt AEAD a
aead ByteString
input
        tag :: AuthTag
tag                 = forall a. BlockCipher a => AEAD a -> Int -> AuthTag
aeadFinalize AEAD a
aeadFinal Int
taglen

-- | Simple AEAD decryption
aeadSimpleDecrypt :: BlockCipher a
                  => AEAD a        -- ^ A new AEAD Context
                  -> B.ByteString  -- ^ Optional Authentified Header
                  -> B.ByteString  -- ^ Optional Plaintext
                  -> AuthTag       -- ^ Tag length
                  -> Maybe B.ByteString -- ^ Plaintext
aeadSimpleDecrypt :: forall a.
BlockCipher a =>
AEAD a -> ByteString -> ByteString -> AuthTag -> Maybe ByteString
aeadSimpleDecrypt AEAD a
aeadIni ByteString
header ByteString
input AuthTag
authTag
    | AuthTag
tag forall a. Eq a => a -> a -> Bool
== AuthTag
authTag = forall a. a -> Maybe a
Just ByteString
output
    | Bool
otherwise      = forall a. Maybe a
Nothing
  where aead :: AEAD a
aead                = forall a. BlockCipher a => AEAD a -> ByteString -> AEAD a
aeadAppendHeader AEAD a
aeadIni ByteString
header
        (ByteString
output, AEAD a
aeadFinal) = forall a.
BlockCipher a =>
AEAD a -> ByteString -> (ByteString, AEAD a)
aeadDecrypt AEAD a
aead ByteString
input
        tag :: AuthTag
tag                 = forall a. BlockCipher a => AEAD a -> Int -> AuthTag
aeadFinalize AEAD a
aeadFinal (forall a. Byteable a => a -> Int
byteableLength AuthTag
authTag)