    -- |
    -- Module      : Crypto.Cipher.CAST5
    -- License     : BSD-style
    -- Maintainer  : Olivier Chéron <olivier.cheron@gmail.com>
    -- Stability   : stable
    -- Portability : good
    module Crypto.Cipher.CAST5 (
        CAST5,
    ) where

    import Crypto.Cipher.CAST5.Primitive
    import Crypto.Cipher.Types
    import Crypto.Error
    import Crypto.Internal.ByteArray (ByteArrayAccess)
    import qualified Crypto.Internal.ByteArray as B

    -- | CAST5 block cipher (also known as CAST-128).  Key is between
    -- 40 and 128 bits.
    newtype CAST5 = CAST5 Key

    instance Cipher CAST5 where
        cipherName :: CAST5 -> String
    cipherName CAST5
    _ = String
    "CAST5"
        cipherKeySize :: CAST5 -> KeySizeSpecifier
    cipherKeySize CAST5
    _ = Int -> Int -> KeySizeSpecifier
    KeySizeRange Int
    5 Int
    16
        cipherInit :: forall key. ByteArray key => key -> CryptoFailable CAST5
    cipherInit = key -> CryptoFailable CAST5
    forall key. ByteArrayAccess key => key -> CryptoFailable CAST5
    initCAST5

    instance BlockCipher CAST5 where
        blockSize :: CAST5 -> Int
    blockSize CAST5
    _ = Int
    8
        ecbEncrypt :: forall ba. ByteArray ba => CAST5 -> ba -> ba
    ecbEncrypt (CAST5 Key
    k) = (Word64 -> Word64) -> ba -> ba
    forall bs. ByteArray bs => (Word64 -> Word64) -> bs -> bs
    B.mapAsWord64 (Key -> Word64 -> Word64
    encrypt Key
    k)
        ecbDecrypt :: forall ba. ByteArray ba => CAST5 -> ba -> ba
    ecbDecrypt (CAST5 Key
    k) = (Word64 -> Word64) -> ba -> ba
    forall bs. ByteArray bs => (Word64 -> Word64) -> bs -> bs
    B.mapAsWord64 (Key -> Word64 -> Word64
    decrypt Key
    k)

    initCAST5 :: ByteArrayAccess key => key -> CryptoFailable CAST5
    initCAST5 :: forall key. ByteArrayAccess key => key -> CryptoFailable CAST5
    initCAST5 key
    bs
        | Int
    len Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    5 = CryptoError -> CryptoFailable CAST5
    forall a. CryptoError -> CryptoFailable a
    CryptoFailed CryptoError
    CryptoError_KeySizeInvalid
        | Int
    len Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    16 = CAST5 -> CryptoFailable CAST5
    forall a. a -> CryptoFailable a
    CryptoPassed (Key -> CAST5
    CAST5 (Key -> CAST5) -> Key -> CAST5
    forall a b. (a -> b) -> a -> b
    $ Bool -> Bytes -> Key
    forall key. ByteArrayAccess key => Bool -> key -> Key
    buildKey Bool
    short Bytes
    padded)
        | Int
    len Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    16 = CAST5 -> CryptoFailable CAST5
    forall a. a -> CryptoFailable a
    CryptoPassed (Key -> CAST5
    CAST5 (Key -> CAST5) -> Key -> CAST5
    forall a b. (a -> b) -> a -> b
    $ Bool -> key -> Key
    forall key. ByteArrayAccess key => Bool -> key -> Key
    buildKey Bool
    False key
    bs)
        | Bool
    otherwise = CryptoError -> CryptoFailable CAST5
    forall a. CryptoError -> CryptoFailable a
    CryptoFailed CryptoError
    CryptoError_KeySizeInvalid
      where
        len :: Int
    len = key -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length key
    bs
        short :: Bool
    short = Int
    len Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    10

        padded :: B.Bytes
        padded :: Bytes
    padded = key -> Bytes
    forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    bin -> bout
    B.convert key
    bs Bytes -> Bytes -> Bytes
    forall bs. ByteArray bs => bs -> bs -> bs
    `B.append` Int -> Word8 -> Bytes
    forall ba. ByteArray ba => Int -> Word8 -> ba
    B.replicate (Int
    16 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    len) Word8
    0