-- |
-- 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 :: AEAD a -> ByteString -> AEAD a
aeadAppendHeader (AEAD a
cipher (AEADState st
state)) ByteString
bs =
    a -> AEADState a -> AEAD a
forall cipher. cipher -> AEADState cipher -> AEAD cipher
AEAD a
cipher (AEADState a -> AEAD a) -> AEADState a -> AEAD a
forall a b. (a -> b) -> a -> b
$ st -> AEADState a
forall cipher st. AEADModeImpl cipher st => st -> AEADState cipher
AEADState (a -> st -> ByteString -> st
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 :: AEAD a -> ByteString -> (ByteString, AEAD a)
aeadEncrypt (AEAD a
cipher (AEADState st
state)) ByteString
input = (ByteString
output, a -> AEADState a -> AEAD a
forall cipher. cipher -> AEADState cipher -> AEAD cipher
AEAD a
cipher (st -> AEADState a
forall cipher st. AEADModeImpl cipher st => st -> AEADState cipher
AEADState st
nst))
  where (ByteString
output, st
nst) = a -> st -> ByteString -> (ByteString, st)
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 :: AEAD a -> ByteString -> (ByteString, AEAD a)
aeadDecrypt (AEAD a
cipher (AEADState st
state)) ByteString
input = (ByteString
output, a -> AEADState a -> AEAD a
forall cipher. cipher -> AEADState cipher -> AEAD cipher
AEAD a
cipher (st -> AEADState a
forall cipher st. AEADModeImpl cipher st => st -> AEADState cipher
AEADState st
nst))
  where (ByteString
output, st
nst) = a -> st -> ByteString -> (ByteString, st)
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 :: AEAD a -> Int -> AuthTag
aeadFinalize (AEAD a
cipher (AEADState st
state)) Int
len =
    a -> st -> Int -> AuthTag
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 :: 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                = AEAD a -> ByteString -> AEAD a
forall a. BlockCipher a => AEAD a -> ByteString -> AEAD a
aeadAppendHeader AEAD a
aeadIni ByteString
header
        (ByteString
output, AEAD a
aeadFinal) = AEAD a -> ByteString -> (ByteString, AEAD a)
forall a.
BlockCipher a =>
AEAD a -> ByteString -> (ByteString, AEAD a)
aeadEncrypt AEAD a
aead ByteString
input
        tag :: AuthTag
tag                 = AEAD a -> Int -> AuthTag
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 :: AEAD a -> ByteString -> ByteString -> AuthTag -> Maybe ByteString
aeadSimpleDecrypt AEAD a
aeadIni ByteString
header ByteString
input AuthTag
authTag
    | AuthTag
tag AuthTag -> AuthTag -> Bool
forall a. Eq a => a -> a -> Bool
== AuthTag
authTag = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
output
    | Bool
otherwise      = Maybe ByteString
forall a. Maybe a
Nothing
  where aead :: AEAD a
aead                = AEAD a -> ByteString -> AEAD a
forall a. BlockCipher a => AEAD a -> ByteString -> AEAD a
aeadAppendHeader AEAD a
aeadIni ByteString
header
        (ByteString
output, AEAD a
aeadFinal) = AEAD a -> ByteString -> (ByteString, AEAD a)
forall a.
BlockCipher a =>
AEAD a -> ByteString -> (ByteString, AEAD a)
aeadDecrypt AEAD a
aead ByteString
input
        tag :: AuthTag
tag                 = AEAD a -> Int -> AuthTag
forall a. BlockCipher a => AEAD a -> Int -> AuthTag
aeadFinalize AEAD a
aeadFinal (AuthTag -> Int
forall a. Byteable a => a -> Int
byteableLength AuthTag
authTag)