-- |
-- Module      : Crypto.Cipher.Types.Base
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : Stable
-- Portability : Excellent
--
-- symmetric cipher basic types
--
module Crypto.Cipher.Types.Base
    ( KeyError(..)
    , KeySizeSpecifier(..)
    , Key(..)
    , IV(..)
    , Cipher(..)
    , AuthTag(..)
    , AEADMode(..)
    , DataUnitOffset
    ) where

import Data.Byteable
import Data.SecureMem
import Data.Word
import Data.ByteString (ByteString)

-- | Possible Error that can be reported when initializating a key
data KeyError =
      KeyErrorTooSmall
    | KeyErrorTooBig
    | KeyErrorInvalid String
    deriving (Int -> KeyError -> ShowS
[KeyError] -> ShowS
KeyError -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [KeyError] -> ShowS
$cshowList :: [KeyError] -> ShowS
show :: KeyError -> String
$cshow :: KeyError -> String
showsPrec :: Int -> KeyError -> ShowS
$cshowsPrec :: Int -> KeyError -> ShowS
Show,KeyError -> KeyError -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: KeyError -> KeyError -> Bool
$c/= :: KeyError -> KeyError -> Bool
== :: KeyError -> KeyError -> Bool
$c== :: KeyError -> KeyError -> Bool
Eq)

-- | 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
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [KeySizeSpecifier] -> ShowS
$cshowList :: [KeySizeSpecifier] -> ShowS
show :: KeySizeSpecifier -> String
$cshow :: KeySizeSpecifier -> String
showsPrec :: Int -> KeySizeSpecifier -> ShowS
$cshowsPrec :: Int -> KeySizeSpecifier -> ShowS
Show,KeySizeSpecifier -> KeySizeSpecifier -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: KeySizeSpecifier -> KeySizeSpecifier -> Bool
$c/= :: KeySizeSpecifier -> KeySizeSpecifier -> Bool
== :: KeySizeSpecifier -> KeySizeSpecifier -> Bool
$c== :: KeySizeSpecifier -> KeySizeSpecifier -> Bool
Eq)

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

-- | a Key parametrized by the cipher
newtype Key c = Key SecureMem deriving (Key c -> Key c -> Bool
forall c. Key c -> Key c -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Key c -> Key c -> Bool
$c/= :: forall c. Key c -> Key c -> Bool
== :: Key c -> Key c -> Bool
$c== :: forall c. Key c -> Key c -> Bool
Eq)

instance ToSecureMem (Key c) where
    toSecureMem :: Key c -> SecureMem
toSecureMem (Key SecureMem
sm) = SecureMem
sm
instance Byteable (Key c) where
    toBytes :: Key c -> ByteString
toBytes (Key SecureMem
sm) = forall a. Byteable a => a -> ByteString
toBytes SecureMem
sm

-- | an IV parametrized by the cipher
newtype IV c = IV ByteString deriving (IV c -> IV c -> Bool
forall c. IV c -> IV c -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IV c -> IV c -> Bool
$c/= :: forall c. IV c -> IV c -> Bool
== :: IV c -> IV c -> Bool
$c== :: forall c. IV c -> IV c -> Bool
Eq)

instance Byteable (IV c) where
    toBytes :: IV c -> ByteString
toBytes (IV ByteString
sm) = ByteString
sm

-- | Authentification Tag for AE cipher mode
newtype AuthTag = AuthTag ByteString
    deriving (Int -> AuthTag -> ShowS
[AuthTag] -> ShowS
AuthTag -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AuthTag] -> ShowS
$cshowList :: [AuthTag] -> ShowS
show :: AuthTag -> String
$cshow :: AuthTag -> String
showsPrec :: Int -> AuthTag -> ShowS
$cshowsPrec :: Int -> AuthTag -> ShowS
Show)

instance Eq AuthTag where
    (AuthTag ByteString
a) == :: AuthTag -> AuthTag -> Bool
== (AuthTag ByteString
b) = forall a. Byteable a => a -> a -> Bool
constEqBytes ByteString
a ByteString
b
instance Byteable AuthTag where
    toBytes :: AuthTag -> ByteString
toBytes (AuthTag ByteString
bs) = ByteString
bs

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

-- | Symmetric cipher class.
class Cipher cipher where
    -- | Initialize a cipher context from a key
    cipherInit    :: Key cipher -> 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