-- |
-- Module      : Crypto.Cipher.DES
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : stable
-- Portability : good
--
module Crypto.Cipher.DES
    ( DES
    ) where

import           Data.Word
import           Crypto.Error
import           Crypto.Cipher.Types
import           Crypto.Cipher.DES.Primitive
import           Crypto.Internal.ByteArray (ByteArrayAccess)
import qualified Crypto.Internal.ByteArray as B
import           Data.Memory.Endian

-- | DES Context
data DES = DES Word64
    deriving (DES -> DES -> Bool
(DES -> DES -> Bool) -> (DES -> DES -> Bool) -> Eq DES
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DES -> DES -> Bool
$c/= :: DES -> DES -> Bool
== :: DES -> DES -> Bool
$c== :: DES -> DES -> Bool
Eq)

instance Cipher DES where
    cipherName :: DES -> String
cipherName    DES
_ = String
"DES"
    cipherKeySize :: DES -> KeySizeSpecifier
cipherKeySize DES
_ = Int -> KeySizeSpecifier
KeySizeFixed Int
8
    cipherInit :: key -> CryptoFailable DES
cipherInit key
k    = key -> CryptoFailable DES
forall key. ByteArrayAccess key => key -> CryptoFailable DES
initDES key
k

instance BlockCipher DES where
    blockSize :: DES -> Int
blockSize DES
_ = Int
8
    ecbEncrypt :: DES -> ba -> ba
ecbEncrypt (DES Word64
key) = (Word64 -> Word64) -> ba -> ba
forall bs. ByteArray bs => (Word64 -> Word64) -> bs -> bs
B.mapAsWord64 (Block -> Word64
unBlock (Block -> Word64) -> (Word64 -> Block) -> Word64 -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> Block -> Block
encrypt Word64
key (Block -> Block) -> (Word64 -> Block) -> Word64 -> Block
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> Block
Block)
    ecbDecrypt :: DES -> ba -> ba
ecbDecrypt (DES Word64
key) = (Word64 -> Word64) -> ba -> ba
forall bs. ByteArray bs => (Word64 -> Word64) -> bs -> bs
B.mapAsWord64 (Block -> Word64
unBlock (Block -> Word64) -> (Word64 -> Block) -> Word64 -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> Block -> Block
decrypt Word64
key (Block -> Block) -> (Word64 -> Block) -> Word64 -> Block
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> Block
Block)

initDES :: ByteArrayAccess key => key -> CryptoFailable DES
initDES :: key -> CryptoFailable DES
initDES key
k
    | Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
8  = DES -> CryptoFailable DES
forall a. a -> CryptoFailable a
CryptoPassed (DES -> CryptoFailable DES) -> DES -> CryptoFailable DES
forall a b. (a -> b) -> a -> b
$ Word64 -> DES
DES Word64
key
    | Bool
otherwise = CryptoError -> CryptoFailable DES
forall a. CryptoError -> CryptoFailable a
CryptoFailed (CryptoError -> CryptoFailable DES)
-> CryptoError -> CryptoFailable DES
forall a b. (a -> b) -> a -> b
$ CryptoError
CryptoError_KeySizeInvalid
  where len :: Int
len = key -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length key
k
        key :: Word64
key = BE Word64 -> Word64
forall a. ByteSwap a => BE a -> a
fromBE (BE Word64 -> Word64) -> BE Word64 -> Word64
forall a b. (a -> b) -> a -> b
$ key -> Int -> BE Word64
forall bs. ByteArrayAccess bs => bs -> Int -> BE Word64
B.toW64BE key
k Int
0