-- |
-- Module      : Crypto.Cipher.Types.Base
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : Stable
-- Portability : Excellent
--
-- Symmetric cipher basic types
--
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Crypto.Cipher.Types.Base
    ( KeySizeSpecifier(..)
    , Cipher(..)
    , AuthTag(..)
    , AEADMode(..)
    , CCM_M(..)
    , CCM_L(..)
    , DataUnitOffset
    ) where

import           Data.Word
import           Crypto.Internal.ByteArray (Bytes, ByteArrayAccess, ByteArray)
import qualified Crypto.Internal.ByteArray as B
import           Crypto.Internal.DeepSeq
import           Crypto.Error

-- | Different specifier for key size in bytes
data KeySizeSpecifier =
      KeySizeRange Int Int -- ^ in the range [min,max]
    | KeySizeEnum  [Int]   -- ^ one of the specified values
    | KeySizeFixed Int     -- ^ a specific size
    deriving (Int -> KeySizeSpecifier -> ShowS
[KeySizeSpecifier] -> ShowS
KeySizeSpecifier -> String
(Int -> KeySizeSpecifier -> ShowS)
-> (KeySizeSpecifier -> String)
-> ([KeySizeSpecifier] -> ShowS)
-> Show KeySizeSpecifier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> KeySizeSpecifier -> ShowS
showsPrec :: Int -> KeySizeSpecifier -> ShowS
$cshow :: KeySizeSpecifier -> String
show :: KeySizeSpecifier -> String
$cshowList :: [KeySizeSpecifier] -> ShowS
showList :: [KeySizeSpecifier] -> ShowS
Show,KeySizeSpecifier -> KeySizeSpecifier -> Bool
(KeySizeSpecifier -> KeySizeSpecifier -> Bool)
-> (KeySizeSpecifier -> KeySizeSpecifier -> Bool)
-> Eq KeySizeSpecifier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: KeySizeSpecifier -> KeySizeSpecifier -> Bool
== :: KeySizeSpecifier -> KeySizeSpecifier -> Bool
$c/= :: KeySizeSpecifier -> KeySizeSpecifier -> Bool
/= :: KeySizeSpecifier -> KeySizeSpecifier -> Bool
Eq)

-- | Offset inside an XTS data unit, measured in block size.
type DataUnitOffset = Word32

-- | Authentication Tag for AE cipher mode
newtype AuthTag = AuthTag { AuthTag -> Bytes
unAuthTag :: Bytes }
    deriving (Int -> AuthTag -> ShowS
[AuthTag] -> ShowS
AuthTag -> String
(Int -> AuthTag -> ShowS)
-> (AuthTag -> String) -> ([AuthTag] -> ShowS) -> Show AuthTag
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AuthTag -> ShowS
showsPrec :: Int -> AuthTag -> ShowS
$cshow :: AuthTag -> String
show :: AuthTag -> String
$cshowList :: [AuthTag] -> ShowS
showList :: [AuthTag] -> ShowS
Show, AuthTag -> Int
(AuthTag -> Int)
-> (forall p a. AuthTag -> (Ptr p -> IO a) -> IO a)
-> (forall p. AuthTag -> Ptr p -> IO ())
-> ByteArrayAccess AuthTag
forall p. AuthTag -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. AuthTag -> (Ptr p -> IO a) -> IO a
$clength :: AuthTag -> Int
length :: AuthTag -> Int
$cwithByteArray :: forall p a. AuthTag -> (Ptr p -> IO a) -> IO a
withByteArray :: forall p a. AuthTag -> (Ptr p -> IO a) -> IO a
$ccopyByteArrayToPtr :: forall p. AuthTag -> Ptr p -> IO ()
copyByteArrayToPtr :: forall p. AuthTag -> Ptr p -> IO ()
ByteArrayAccess, AuthTag -> ()
(AuthTag -> ()) -> NFData AuthTag
forall a. (a -> ()) -> NFData a
$crnf :: AuthTag -> ()
rnf :: AuthTag -> ()
NFData)

instance Eq AuthTag where
    (AuthTag Bytes
a) == :: AuthTag -> AuthTag -> Bool
== (AuthTag Bytes
b) = Bytes -> Bytes -> Bool
forall bs1 bs2.
(ByteArrayAccess bs1, ByteArrayAccess bs2) =>
bs1 -> bs2 -> Bool
B.constEq Bytes
a Bytes
b

data CCM_M = CCM_M4 | CCM_M6 | CCM_M8 | CCM_M10 | CCM_M12 | CCM_M14 | CCM_M16 deriving (Int -> CCM_M -> ShowS
[CCM_M] -> ShowS
CCM_M -> String
(Int -> CCM_M -> ShowS)
-> (CCM_M -> String) -> ([CCM_M] -> ShowS) -> Show CCM_M
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CCM_M -> ShowS
showsPrec :: Int -> CCM_M -> ShowS
$cshow :: CCM_M -> String
show :: CCM_M -> String
$cshowList :: [CCM_M] -> ShowS
showList :: [CCM_M] -> ShowS
Show, CCM_M -> CCM_M -> Bool
(CCM_M -> CCM_M -> Bool) -> (CCM_M -> CCM_M -> Bool) -> Eq CCM_M
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CCM_M -> CCM_M -> Bool
== :: CCM_M -> CCM_M -> Bool
$c/= :: CCM_M -> CCM_M -> Bool
/= :: CCM_M -> CCM_M -> Bool
Eq)
data CCM_L = CCM_L2 | CCM_L3 | CCM_L4 deriving (Int -> CCM_L -> ShowS
[CCM_L] -> ShowS
CCM_L -> String
(Int -> CCM_L -> ShowS)
-> (CCM_L -> String) -> ([CCM_L] -> ShowS) -> Show CCM_L
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CCM_L -> ShowS
showsPrec :: Int -> CCM_L -> ShowS
$cshow :: CCM_L -> String
show :: CCM_L -> String
$cshowList :: [CCM_L] -> ShowS
showList :: [CCM_L] -> ShowS
Show, CCM_L -> CCM_L -> Bool
(CCM_L -> CCM_L -> Bool) -> (CCM_L -> CCM_L -> Bool) -> Eq CCM_L
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CCM_L -> CCM_L -> Bool
== :: CCM_L -> CCM_L -> Bool
$c/= :: CCM_L -> CCM_L -> Bool
/= :: CCM_L -> CCM_L -> Bool
Eq)

-- | AEAD Mode
data AEADMode =
      AEAD_OCB -- OCB3
    | AEAD_CCM Int CCM_M CCM_L
    | AEAD_EAX
    | AEAD_CWC
    | AEAD_GCM
    deriving (Int -> AEADMode -> ShowS
[AEADMode] -> ShowS
AEADMode -> String
(Int -> AEADMode -> ShowS)
-> (AEADMode -> String) -> ([AEADMode] -> ShowS) -> Show AEADMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AEADMode -> ShowS
showsPrec :: Int -> AEADMode -> ShowS
$cshow :: AEADMode -> String
show :: AEADMode -> String
$cshowList :: [AEADMode] -> ShowS
showList :: [AEADMode] -> ShowS
Show,AEADMode -> AEADMode -> Bool
(AEADMode -> AEADMode -> Bool)
-> (AEADMode -> AEADMode -> Bool) -> Eq AEADMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AEADMode -> AEADMode -> Bool
== :: AEADMode -> AEADMode -> Bool
$c/= :: AEADMode -> AEADMode -> Bool
/= :: AEADMode -> AEADMode -> Bool
Eq)

-- | Symmetric cipher class.
class Cipher cipher where
    -- | Initialize a cipher context from a key
    cipherInit    :: ByteArray key => key -> CryptoFailable cipher
    -- | Cipher name
    cipherName    :: cipher -> String
    -- | return the size of the key required for this cipher.
    -- Some cipher accept any size for key
    cipherKeySize :: cipher -> KeySizeSpecifier